% MATLAB SCRIPT FOR THE AUTOMATICITY/NON-AUTOMATICITY EXPERIMENT
% An experiment in which automatic and non-automatic movements are tested.
% For the automatic movements, participants need to perform a pre-learned
% 12 digit sequence (sequenceauto) during a finger tapping and a foot stomping task. Also
% a non-automatic newly learned 12 digit sequence (sequencenonauto) will be tested including both
% tasks. Note that for the non-automatic tasks the participant is also tested on
% automaticity for the movement during a short dual task, this holds for
% each limb.

%Before starting the experiment, clear the workspace.
clear all

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% START ZMQ & LSL
% raspberry names
zmq_proxy='lsldert00.local';
lsl_hosts={'lsldert00', 'lsldert04', 'lsldert05'};

%add lsl streams
trigstr=cell(1);
nstr=0;
for ii=1:numel(lsl_hosts)
    host=lsl_hosts{ii};
    info_type=sprintf('type=''Digital Triggers @ %s''',host);
    info=lsl_resolver(info_type);
    desc=info.list();
    if isempty(desc)
        warning('lsl stream on host ''%s'' not found', host);
    else
        nstr=nstr+1;
        fprintf('%d: name: ''%s'' type: ''%s''\n',nstr,desc(1).name,desc(1).type);
        trigstr{nstr}=lsl_istream(info{1});
    end
    delete(info);
end
trig = lsldert_pubclient(zmq_proxy);
cleanupObj=onCleanup(@()cleanupFun);

% create session
ses=lsl_session();
for ii=1:nstr
    ses.add_stream(trigstr{ii});
end

% add listener
for ii=1:nstr
    addlistener(trigstr{ii}, 'DataAvailable', @triglistener);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%INITIALISATION
% start lsl session
ses.start();
trig.digitalout(0, 'TTL_init'); % ensures that the output is set to 0
trig.pulseIR(3, 0.2); % start trigger for the nirs recording

%Open Phsychtoolbox.
PsychDefaultSetup(2);
KbName('UnifyKeyNames'); %Links the key presses to the key board names
KbQueueCreate;
KbQueueStart;

%Skip screen synchronization to prevent Pyshtoolbox for freezing
Screen('Preference', 'SkipSyncTests', 1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%SETUP PARAMETERS

t1 = 20; %Resting period in seconds
t2 = 5;  %Random interval around the resting period time
t3 = 9.5; %Duration of a trial (tapping/stomping the sequence 1 time)
N_letters = 8; % Number of letters presented during a trial for the automaticity test
N_trials = 11; % Number of trials for the automaticity test

%The sequences used for this study (automatic and non-automatic sequences
%randomized between participants)
sequenceA = '4 3 4 1 4 1 2 4 3 2 1 2';
sequenceB = '2 1 2 3 2 1 3 2 4 2 4 1';
%Sequences used in order to be able to print in the command window if
%sequences performed by the participant were right (see also end of script)
sequenceprintA = {'BackSpace','6','BackSpace','4','BackSpace','4','5','BackSpace','6','5','4','5'};
sequenceprintB = {'5','4','5','6','5','4','6','5','BackSpace','5','BackSpace','4'};

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%LOAD METRONOME SOUNDS (PsychToolbox)
audio_dir='C:\Users\Helena\Documents\Experiment_ME\metronomesounds';
cd(audio_dir)
[WAVMetronome8.wave,WAVMetronome8.fs]       = audioread('Metronome8.wav');
[WAVMetronome600.wave,WAVMetronome600.fs]       = audioread('Metronome600.wav');
[WAVMetronome180.wave,WAVMetronome180.fs]       = audioread('Metronome180.wav');

% change rows<>columns
WAVMetronome8.wave = WAVMetronome8.wave';         WAVMetronome8.nrChan=2;
WAVMetronome600.wave = WAVMetronome600.wave';         WAVMetronome600.nrChan=2;
WAVMetronome180.wave = WAVMetronome180.wave';         WAVMetronome180.nrChan=2;

% CREATE AND FILL AUDIO BUFFER
% Initialize Sounddriver
% This routine loads the PsychPortAudio sound driver for high precision, low latency,
% multichannel sound playback and recording
% Call it at the beginning of your experiment script, optionally providing the
% 'reallyneedlowlatency'-flag set to 1 to push really hard for low latency
InitializePsychSound(1);

priority = 0;                       % 0 = better quality, increased latency; 1 = minimum latency
duration = 1;                       % number of repetitions of the wav-file
PsychPortAudio('Verbosity',1);      % verbosity = "wordiness" -> 1= print errors

% Get audio device
h_device = PsychPortAudio ('GetDevices');

% Open handle
h_Metronome8   = PsychPortAudio('Open', [], [], priority, WAVMetronome8.fs, WAVMetronome8.nrChan);
h_Metronome600   = PsychPortAudio('Open', [], [], priority, WAVMetronome600.fs, WAVMetronome600.nrChan);
h_Metronome180   = PsychPortAudio('Open', [], [], priority, WAVMetronome180.fs, WAVMetronome180.nrChan);

% Fill buffer
PsychPortAudio('FillBuffer', h_Metronome8, WAVMetronome8.wave);
PsychPortAudio('FillBuffer', h_Metronome600, WAVMetronome600.wave);
PsychPortAudio('FillBuffer', h_Metronome180, WAVMetronome180.wave);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%SAVE FILES IN FOLDER

fprintf('Select the project directory \n')
root_dir=uigetdir('C:\Users\Helena\Documents\Data_ME\', 'Select the project directory');

complete=0;
while complete==0
    sub_ID=input('What is the subject ID (2 digit number) \n', 's');
    sub=sprintf('sub-%s', sub_ID);
        rec_n=input('What is the number of the recording? \n');
        rec=sprintf('rec-%.3d', rec_n);

    inf=fprintf('\n root_dir = %s \n sub = %s \n rec = %s \n', root_dir, sub, rec);
    correct=input('Is the above information correct? (y/n) \n', 's');
    if strcmp(correct, 'y')
        complete=1;
    else
        continue
    end
end

% go to subject folder
sub_dir=fullfile(root_dir, sub);
if ~exist(sub_dir)
    mkdir(sub_dir)
end
cd(sub_dir)

logname=sprintf('%s_%s_triggers.log', sub, rec); diary(logname);
% % save current script in subject directory
script=mfilename('fullpath');
script_name=mfilename;
copyfile(sprintf('%s.m', script), fullfile(sub_dir, sprintf('%s_%s.m', sub, script_name)))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%RANDOMIZATION

%Set the right sequence that is automatic (studied at home) and
%non-automatic (new). Randomized between participants.
sequenceauto = sequenceB;
sequencenonauto = sequenceA;
sequenceautoprint = sequenceprintB;
sequencenonautoprint = sequenceprintA;

%The order of the experiment is randomized for each participant
%Create a vector to represent the two different options (1=non-automatic
%test, 2=automatic test).
order_experiment=[1,2];
%Save the order of the experiment
%save('order_experiment.mat', 'order_experiment');

%Create a vector to represent the two different options for non-automatic
%tasks (3 = finger tapping, 4 = foot stomping).
order_nonauto=[4,3];
%Save the order of the non-automatic experiment
%save('order_nonauto.mat', 'order_nonauto');

%Create a vector to represent the two different options for automatic tasks
%(5 = finger tapping, 6 = foot stomping).
order_auto=[5,6];
%Save the order of the automatic experiment
%save('order_auto.mat', 'order_auto');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SCREEN PREPARATION

% Get the screen numbers.
screens = Screen('Screens');

% Select the external screen if it is present, else revert to the native
% screen
screenNumber = max(screens);

% Define black, white and grey
black = BlackIndex(screenNumber);
white = WhiteIndex(screenNumber);

% Open an on screen window and color it grey
[window, windowRect] = PsychImaging('OpenWindow', screenNumber, black);

% Get the size of the on screen window in pixels
% For help see: Screen WindowSize?
[screenXpixels, screenYpixels] = Screen('WindowSize', window);

% Get the centre coordinate of the window in pixels
% For help see: help RectCenter
[xCenter, yCenter] = RectCenter(windowRect);

% Query the frame duration
ifi = Screen('GetFlipInterval', window)

% Set up alpha-blending for smooth (anti-aliased) lines
Screen('BlendFunction', window, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');

% Preparations for the fixation cross so we only need to do this once
fixCrossDimPix = 40; % Here we set the size of the arms of our fixation cross
xCoords = [-fixCrossDimPix fixCrossDimPix 0 0]; % Set the coordinates (these are all relative to zero we will let the drawing routine center the cross in the center of our monitor for us)
yCoords = [0 0 -fixCrossDimPix fixCrossDimPix];
allCoords = [xCoords; yCoords];
lineWidthPix = 4;% Set the line width for the fixation cross

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% START OF THE EXPERIMENT

%Empty structure for key presses -> use later again so it saves the key
%presses within this structure -> save at the end
events_handauto=struct([]);
events_footauto=struct([]);
events_handnonauto=struct([]);
events_footnonauto=struct([]);
events_handnonautodual=struct([]);
events_footnonautodual=struct([]);

%Instruction experiment
trig.beep(440, 0.2, 'instructions');
Screen('TextSize',window,25);
DrawFormattedText(window,'You will now start with the experiment. \n You will either start with the automatic tasks, performing the at home studied sequence, \n or with the non-automatic tasks, for which you will be presented with a new sequence, \n which you can study for 5 minutes for each limb. \n Note that for the non-automatic tasks you will also perform an automaticity test (dual task). \n This is the same test as you just did for the automatic (at home studied) sequence. \n\n Detailed instructions will appear at the start of each new task. \n You can take a break in between tasks. \n This will be indicated in the on-screen instructions. \n\n Press any key to continue and see with which test you start.','center', 'center', white);
vbl = Screen('Flip', window);
KbStrokeWait; %wait for response to terminate instructions

%Start the randomization loop between non-automatic (=1) and automatic (=2)
for i=order_experiment; %Either [1,2] or [2,1] -> determines the order of the tasks

    % NON-AUTOMATICITY TASKS
    if i==1; %Start with the non-automatic tasks
        %Show instructions
        Screen('TextSize', window, 25);
        DrawFormattedText(window, 'NON-AUTOMATICITY TASK \n\n You will perform the finger tapping and foot stomping task for a new sequence. \n You will either start with the finger tapping or the foot stomping task. \n You will get 5 minutes practice time before each task starts. \n Press any key to continue.', 'center', 'center', white);
        vbl= Screen('Flip', window);
        KbStrokeWait; %wait for response to terminate instructions

        %Determine to start with either hand or foot task.
        for j=order_nonauto; %Either [3,4] or [4,3] -> determines the order of the limbs
            trig.beep(440, 0.2, 'instructions');

            % NON-AUTOMATIC FINGER TAPPING TASK
            if j==3;

                %Non automatic finger tapping task instructions
                %Practice new sequence
                trig.beep(440, 0.2, 'practice_finger_nonauto');
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'You will now perform the non-automaticity FINGER tapping task. \n For the next 5 minutes you can practice a new sequence for the finger tapping task, \n the same way you practiced at home. \n The first 2 minutes are without a metronome sound and the last 3 minutes with the metronome sound. \n If you would like the metronome sound during the full practice session (5 min) please tell us.\n After that we will start with the finger tapping task. \n Press any key to see the new sequence and start practicing.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                %Presenting the new (non-automatic) sequence on the screen
                %2 minutes without metronome sound
                Screen('TextSize', window, 50);
                DrawFormattedText(window, sprintf('%s', sequencenonauto), 'center', 'center', white); % is this the same for each participant?
                vbl= Screen('Flip', window);
                WaitSecs(120);%120

                %Presenting the new (non-automatic) sequence on the screen
                %3 minutes with metronome sound
                Screen('TextSize', window, 50);
                DrawFormattedText(window, sprintf('%s', sequencenonauto), 'center', 'center', white); % is this the same for each participant?
                vbl= Screen('Flip', window);
                PsychPortAudio('Start', h_Metronome180, 1, [], []); %Play metronome sound file (3 minutes)
                WaitSecs(180); %180

                %Practice time is over
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'The time to practice the new sequence is over. \n Press any key to continue to the finger tapping experiment.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                WaitSecs(5)
                KbStrokeWait; %wait for response to terminate instructions

                %Instructions non-automatic finger tapping task
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the finger tapping task for the sequence you just practiced (non-automatic). \n There is a total of 11 trials, so performing the sequence 11 times (once per trial). \n  In between each trial there is a rest period of 20 seconds. \n During this rest you will hear a metronome sound, tap the sequence according to this interval sound. \n Trials and rest periods are indicated with red(= trial) and white(= rest) fixation crosses showing on the screen. \n\n When the experiment starts you cannot talk anymore. \n Furthermore, it is important to stay still except for your right hand. \n Keep your eyes open (also during the rest periods). \n\n Before the start of each new trial the sequence will be shown on the screen. \n If you press any key, the experiment starts. \n It will start with a rest period. \n Whenever a RED fixation cross appears on the screen, you should start tapping the sequence: \n %s \n When ready: press any key to start the finger tapping experiment.', sequencenonauto),'center','center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                %Stimulus for finger tapping non-automatic sequence
                for l = 1:N_trials; %Will perform 11 trials
                    keypresses=table('Size', [12, 3], 'VariableNames', {'onset', 'duration', 'value'}, 'VariableTypes', {'double', 'double', 'cell'});

                    %Rest period between each sequence 20-25 seconds
                    %fixation cross
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file (8 seconds)
                    WaitSecs(t1+randi(t2));

                    %Red fixation cross during finger tapping trial
                    trig.beep(440, 0.2, 'finger_nonauto');
                    onset=GetSecs;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                    Screen('Flip', window)
                    m=1;

                    % Meanwhile record key presses
                    start_timer=GetSecs;
                    while GetSecs-start_timer < t3
                        if m<13 %do not record more than 12 key presses
                            [secs, keyCode, deltaSecs] = KbWait([],2);
                            if any(keyCode)
                                key={KbName(find(keyCode))};
                                keypresses.onset(m)=secs;
                                keypresses.value(m)=key;
                                m=m+1;
                            elseif KbName('ESCAPE')
                            elseif GetSecs-start_timer >= t3
                                break
                            end
                        end
                    end

                    % Show short white fix cross after trial
                    duration=GetSecs-onset;
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window)
                    WaitSecs(5); % 5 seconds, so the nirs signal has time to go back to baseline

                    % Show the sequence before a new trial starts
                    Screen('TextSize', window, 25);
                    DrawFormattedText(window, sprintf('%s \n Press any key to continue with the next trial.', sequencenonauto), 'center', 'center', white);
                    vbl= Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instructions

                    %Save the response and the key presses
                    value={'red X'};
                    events_handnonauto(l).stimuli=table(onset,duration, value);
                    events_handnonauto(l).responses=keypresses;

                end

                % End of the non-automatic finger tapping task is reached.
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'This is the end of the non-automatic finger tapping task. \n Take a rest if needed. \n When ready: press any key to continue with the automaticity test for this task.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                save('events_handnonauto.mat', 'events_handnonauto'); % save the events
                KbStrokeWait; %wait for response to terminate instructions

                %DUAL TASK NONAUTOMATIC FINGER TAPPING
                %Instruction automaticity task finger tapping
                trig.beep(440, 0.2, 'instructions');
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the sequence you just learned during an automaticity test for the FINGER tapping task. \n %s \n\n  While you perform the task, letters will be shown on the screen (C,G,O,Q). \n In between each letter a red fixation cross will appear shortly. \n The goal is to perform the sequence tapping while counting how many times G is presented. \n After each time you tapped the full sequence, you should tell us how many times G was presented. \n For answering this question, keep in mind that \n you press the right key on your keyboard according to your answer (not the number of the sequence!). \n\n We will perform 11 trails. \n For each trial you perform the sequence once. \n Note that during the tapping task you cannot talk. \n Try to keep your body movements as still as possible exept for the right hand. \n Keep your eyes open (also during the rest periods). \n\n In between the trials you will see a white fixation cross for 20 seconds. \n During the first few seconds you will hear a metronome sound. \n Tap the sequence on this rhythm, which is the same as you practiced before. \n \n We will start with a fixation cross on the screen for 20 seconds. \n After that the first trial will start automatically. \n So start tapping the sequence as soon as a RED fixation cross on the screen appears. \n When ready: press any key to continue and start the test.', sequencenonauto),'center','center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                for r=1:N_trials;
                    %Presentation of the letters on the screen (dual task). -> is random.
                    %Participant has to count the amount that G was presented.
                    Letterlist='CGOQ';
                    letter_order=randi(length(Letterlist), 1, N_letters);
                    value={Letterlist(letter_order)};

                    % Always start with a 20-25 seconds fixation cross with 8 seconds of metronome
                    % sound
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file (8 seconds)
                    WaitSecs(t1+randi(t2));

                    %Presentation of random letters on the screen during the finger
                    %tapping test + recording of the key presses
                    trig.beep(440, 0.2, 'finger_nonauto_dual');
                    onset=GetSecs;
                    % preallocate table with key presses
                    keypresses=table('Size', [12, 3], 'VariableNames', {'onset', 'duration', 'value'}, 'VariableTypes', {'double', 'double', 'cell'});
                    v=1; % first key press
                    KbQueueFlush;
                    %Present red fixation cross in between the letters
                    for w=1:N_letters;
                        Screen('DrawLines', window, allCoords,...
                            lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                        Screen('Flip', window);
                        time_cross=rand(1)+0.5; %Speed with which the letters are presented

                        % Meanwhile record key presses
                        start_timer=GetSecs;
                        while GetSecs-start_timer<time_cross
                            [ pressed, firstPress, ~, lastPress, ~]=KbQueueCheck;
                            if v<13 && GetSecs-start_timer<time_cross && pressed %not more than 12 keys can be saved
                                if isempty(find(firstPress~=lastPress)) % no key was pressed twice
                                    keys=KbName(find(firstPress)); % find the pressed keys
                                    [timing, idx]=sort(firstPress(find(firstPress))); % get timing of key presses in ascending order
                                    if length(idx)>1
                                        keys=keys(idx); % sort the pressed keys in ascending order
                                    else
                                        keys={keys};
                                        key_n=length(keys); % number of pressed keys
                                    end
                                    for q=1:key_n
                                        keypresses.onset(v)=timing(q); %store and record the timing
                                        keypresses.value(v)=keys(q);  %store and record the presses
                                        v=v+1;
                                        if v>12
                                            break
                                        end
                                    end
                                else
                                    error('key was pressed twice')
                                end
                            end
                        end

                        % Present random letter on the screen
                        Screen('TextSize', window, 100);
                        DrawFormattedText(window, value{1}(w),'center','center', white);
                        vbl = Screen('Flip', window);
                        WaitSecs (0.2);
                    end

                    % Present white fixation cross for some seconds to show that
                    % trial is over
                    trig.beep(440, 0.2, 'rest');
                    duration=GetSecs-onset;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    WaitSecs(5); % 5 seconds, so the nirs signal has time to go back to baseline

                    % Ask how many G's were presented
                    Screen('TextSize',window,30);
                    DrawFormattedText(window, 'How many times was G presented? ','center','center', white);
                    vbl = Screen('Flip', window);
                    [secs, keyCode, deltaSecs]=KbWait;
                    % save the response and the key presses
                    response={KbName(find(keyCode))};
                    events_handnonautodual(r).stimuli=table(onset,duration, value, response);
                    events_handnonautodual(r).responses=keypresses;
                    DrawFormattedText(window, ['Your answer: ' response{1} '\n Press any key to continue.'],'center','center', white);
                    vbl = Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instruction
                    DrawFormattedText(window, 'Press any key to continue with the next trail. \n Note that you will first start with a fixation cross again. \n Start tapping the sequence as soon as a RED fixation cross appears on the screen.' ,'center','center', white);
                    vbl = Screen('Flip', window);
                    KbStrokeWait;
                end

                % After all trials completed, the end of the finger tapping task is
                % reached.
                Screen('TextSize',window,30);
                DrawFormattedText(window, 'This is the end of the automaticity test for the non-automatic finger tapping task. \n You can take a rest if needed. \n Whenever you feel ready, \n press any key to continue with the experiment.' ,'center','center', white);
                vbl = Screen('Flip', window);
                save('events_handnonautodual.mat', 'events_handnonautodual'); % save the events
                KbStrokeWait; %wait for response to terminate instructions

            end

            %NON-AUTOMATIC FOOT STOMPING TASK
            if j==4;;

                %Non automatic foot stomping task instructions
                %Practice new sequence
                trig.beep(440, 0.2, 'practice_foot_nonauto');
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'You will now perform the non-automaticity FOOT stomping task. \n For the next 5 minutes you can practice a new sequence for the foot stomping task, \n the same way you practiced at home. \n The first 2 minutes are without a metronome sound and the last 3 minutes with the metronome sound. \n If you would like the metronome sound during the full practice session (5 min) please tell us.\n After that we will start with the foot stomping task. \n Press any key to see the new sequence and start practicing.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                % Presenting the new (non-automatic) sequence on the screen
                % for 2 minutes without the metronome sound
                Screen('TextSize', window, 50);
                DrawFormattedText(window, sprintf('%s', sequencenonauto), 'center', 'center', white); % is this the same for each participant?
                vbl= Screen('Flip', window);
                %PsychPortAudio('Start', h_Metronome180, 1, [], []); % Play metronome sound file
                WaitSecs(120);

                % Presenting the new (non-automatic) sequence on the screen
                % for 3 minutes with the metronome sound
                Screen('TextSize', window, 50);
                DrawFormattedText(window, sprintf('%s', sequencenonauto), 'center', 'center', white); % is this the same for each participant?
                vbl= Screen('Flip', window);
                PsychPortAudio('Start', h_Metronome180, 1, [], []); % Play metronome sound file
                WaitSecs(180);

                %Practice time is over
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'The time to practice the new sequence is over. \n Press any key to continue to the foot stomping experiment.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                %Instructions non-automatic foot stomping task
                trig.beep(440, 0.2, 'instructions');
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the foot stomping experiment for the sequence you just practiced (non-automatic). \n There is a total of 11 trials, so performing the sequence 11 times (once per trial). \n In between each trial there is a rest period of 20 seconds. \n During this rest you will hear a metronome sound, stomp the sequence according to this interval sound. \n Trials and rest periods are indicated with red(= trial) and white(=rest) fixation crosses presented on the screen. \n\n When the experiment starts you cannot talk anymore. \n Furthermore, it is important to stay still except for your right leg. \n Keep your eyes open (also during the rest periods). \n\n Before the start of each new trial the sequence will be shown on the screen. \n If you press any key, the experiment starts right away. \n It will start with a rest period. \n Whenever a RED fixation cross appears on the screen, you should start stomping the sequence: \n %s \n When ready: press any key to start the foot stomping experiment.', sequencenonauto),'center', 'center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                trig.digitalout(1, 'start_rec'); % starts the recording of xsens
                %Stimulus for foot stomping non-automatic sequence
                for n = 1:N_trials; %Will perform 11 trials

                    % Rest period 20-25 seconds, show white fixation cross
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file (8 seconds)
                    WaitSecs(t1+randi(t2));

                    % Red fixation cross during trial
                    trig.beep(880, 0.2, 'foot_nonauto');
                    onset=GetSecs;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                    Screen('Flip', window);
                    WaitSecs(t3);

                    % Short white fix cross after trial
                    trig.beep(440, 0.2, 'rest');
                    duration=GetSecs-onset;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    WaitSecs (5);  %5 seconds, so the nirs signal has time to go back to baseline

                    % Show sequence before new trial starts
                    Screen('TextSize', window, 25);
                    DrawFormattedText(window, sprintf('%s \n Press any key to continue with the next trial.', sequencenonauto), 'center', 'center', white);
                    vbl= Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instructions

                    %Store info in the created event
                    value={'red X'};
                    events_footnonauto(n).stimuli=table(onset,duration, value);

                end

                % End of the non-automatic foot stomping task
                trig.beep(440, 0.2, 'rest');
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'This is the end of the non-automatic foot stomping task. \n Take a rest if needed. \n When ready: press any key to continue with the automaticity test.', 'center', 'center', white);
                vbl= Screen('Flip', window);
                save('events_footnonauto.mat', 'events_footnonauto'); % save the events
                KbStrokeWait; %wait for response to terminate instructions
                trig.digitalout(0, 'stop_rec'); % stops the recording of xsens

                % DUAL TASK NON AUTOMATIC FOOT STOMPING TASK
                % Instruction automaticity task foot stomping
                trig.beep(440, 0.2, 'instructions');
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the sequence you just learned for an automaticity test for the FOOT stomping task. \n %s \n\n While you perform the task, letters will be shown on the screen (C,G,O,Q). \n In between each letter a red fixation cross will appear shortly. \n The goal is to perform the sequence stomping while counting how many times G is presented. \n After each time you stomped the full sequence, you should tell us how many times G was presented. \n For answering this question, keep in mind that \n you press the right key on your keyboard according to your answer (not the number of the sequence!). \n\n We will perform 11 trials. \n For each trial you perform the sequence once. \n Note that during the stomping task you cannot talk. \n Try to keep your body movements as still as possible exept for your right leg. \n Keep your eyes open (also during the rest periods). \n\n In between the trials you will see a fixation cross for 20 seconds. \n During the first few seconds you will hear a metronome sound. \n Stomp the sequence on this rhythm, which is the same as you studied at home. \n\n We will start with a fixation cross on the screen for 20 seconds. \n After that the first trial will start automatically. \n So start stomping the sequence as soon as a RED fixation cross on the screen appears. \n When ready: press any key to continue and start the test.', sequencenonauto),'center','center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

                %Trials for the footstomping test
                trig.digitalout(1, 'start_rec'); % starts the recording of xsens
                for r=1:N_trials;
                    %Presentation of the letters on the screen (dual task). -> is random.
                    %Participant has to count the amount that G was presented.
                    Letterlist= 'CGOQ';
                    letter_order=randi(length(Letterlist), 1, N_letters);
                    value={Letterlist(letter_order)};

                    % Always start with a fixation cross and 8 seconds of metronome
                    % sound
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file (8 seconds)
                    WaitSecs(t1+randi(t2));

                    %Presentation of random letters on the screen during the foot
                    %stomping test
                    trig.beep(880, 0.2, 'foot_nonauto_dual');
                    onset=GetSecs;
                    for w=1:N_letters;
                        Screen('DrawLines', window, allCoords,...
                            lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                        Screen('Flip', window);
                        time_cross=rand(1)+0.5; %Speed with which the letters are presented = A randomized value between 0 and 1, + 0.5 sec
                        WaitSecs(time_cross);

                        % Between each letter show a red fixation cross
                        Screen('TextSize', window, 100);
                        DrawFormattedText(window, value{1}(w),'center','center', white);
                        vbl = Screen('Flip', window);
                        WaitSecs (0.2);
                    end

                    % Present white fixation cross for some seconds to show that
                    % trial is over
                    duration=GetSecs-onset;
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    WaitSecs(5);  %5 seconds, so the nirs signal has time to go back to baseline

                    % Ask how many G's were presented
                    Screen('TextSize',window,30);
                    DrawFormattedText(window, 'How many times was G presented? ','center','center', white);
                    vbl = Screen('Flip', window);
                    [secs, keyCode, deltaSecs]=KbWait;
                    % save the response and the key presses
                    response={KbName(find(keyCode))};
                    events_footnonautodual(r).stimuli=table(onset,duration, value, response);
                    DrawFormattedText(window, ['Your answer: ' response{1} '\n Press any key to continue.'],'center','center', white);
                    vbl = Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instruction
                    DrawFormattedText(window, 'Press any key to continue with the next trail. \n Note that you will first start with a fixation cross again. \n Start tapping the sequence as soon as a RED fixation cross appears on the screen.' ,'center','center', white);
                    vbl = Screen('Flip', window);
                    KbStrokeWait;

                end

                % After all trials completed, the end of the foot stomping task is reached.
                trig.digitalout(0, 'stop_rec'); % stops the recording of xsens
                Screen('TextSize',window,25);
                DrawFormattedText(window, 'End of the automaticity test for the non-automatic foot stomping task. \n You can take a rest if needed. \n Whenever you feel ready, \n press any key to continue with the experiment.','center','center', white);
                vbl = Screen('Flip', window);
                save('events_footnonautodual.mat', 'events_footnonautodual'); % save the letters that were presented and the reported number of g's
                KbStrokeWait; %wait for response to terminate instructions
            end
        end
    end

    % AUTOMATICITY TASKS
    if i==2; %Start with the automatic tasks

        % Show instructions
        trig.beep(440, 0.2, 'instructions');
        Screen('TextSize', window, 25);
        DrawFormattedText(window, 'AUTOMATICITY TASK \n\n You will perform the finger tapping and foot stomping task for the sequence you studied at home. \n You will either start with the finger tapping or foot stomping task. \n Press any key to continue.', 'center', 'center', white);
        vbl= Screen('Flip', window);
        KbStrokeWait; %wait for response to terminate instructions

        %Determine to start with either hand or foot task.
        for k=order_auto; %Either [5,6] or [6,5] -> determines the order of the limbs

            %AUTOMATIC FINGER TAPPING TASK
            if k==5;
                %Automatic finger tapping task instructions
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the FINGER tapping task for the sequence you studied at home (automatic). \n %s \n\n There is a total of 11 trials, so performing the sequence 11 times (once per trial). \n  In between each trial there is a rest period of 20 seconds. \n During this rest you will hear a metronome sound, tap the sequence according to this interval sound. \n Trials and rest periods are indicated with red(= trial) and white(= rest) fixation crosses presented on the screen. \n\n When the experiment starts you cannot talk anymore. \n Furthermore, it is important to stay still except for your right hand. \n Keep your eyes open (also during the rest periods). \n\n Before the start of each new trial the sequence will be shown on the screen. \n If you press any key, the experiment starts right away. \n It will start with a rest period. \n Whenever a RED fixation cross appears on the screen, you should start tapping the sequence. \n When ready: press any key to start the finger tapping experiment.', sequenceauto),'center','center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait;

                %Stimulus for finger tapping automatic sequence
                for o = 1:N_trials; % Will perform 11 trials
                    keypresses=table('Size', [12, 3], 'VariableNames', {'onset', 'duration', 'value'}, 'VariableTypes', {'double', 'double', 'cell'});

                    %Rest period 20-25 seconds of white fixation cross and
                    %8 seconds of metronome sound
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file
                    WaitSecs(t1+randi(t2));

                    % Show a red fixation cross during trial
                    trig.beep(440, 0.2, 'finger_auto');
                    onset=GetSecs;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                    Screen('Flip', window)
                    p=1;

                    % Meanwhile record key presses
                    start_timer=GetSecs;
                    while GetSecs-start_timer < t3
                        if p<13
                            [secs, keyCode, deltaSecs] = KbWait([],2);
                            if any(keyCode)
                                key={KbName(find(keyCode))};
                                keypresses.onset(p)=secs;
                                keypresses.value(p)=key;
                                p=p+1;
                            elseif KbName('ESCAPE')
                            elseif GetSecs-start_timer >= t3
                                break
                            end
                        end
                    end

                    % Show short white fix cross after trial
                    trig.beep(440, 0.2, 'rest');
                    duration=GetSecs-onset;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window)
                    WaitSecs(5);  %5 seconds, so the nirs signal has time to go back to baseline

                    % Show sequence before new trial starts
                    Screen('TextSize', window, 25);
                    DrawFormattedText(window, sprintf('%s \n Press any key to continue with the next trial.', sequenceauto), 'center', 'center', white);
                    vbl= Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instructions

                    % Store the response and the key presses in the create
                    % events
                    value={'red X'};
                    events_handauto(o).stimuli=table(onset,duration, value);
                    events_handauto(o).responses=keypresses;

                end

                %End of the automatic finger tapping task
                trig.beep(440, 0.2, 'rest');
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'This is the end of the automatic finger tapping task. \n You can take a rest if needed. \n Whenever you feel ready, \n press any key to continue with the rest of the experiment.', 'center', 'center', white);
                save('events_handauto.mat', 'events_handauto'); % save the events
                vbl= Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions

            end

            %AUTOMATIC FOOT STOMPING TASK
            if k==6;
                %Automatic foot stomping instructions
                trig.beep(440, 0.2, 'instructions');
                Screen('TextSize',window,25);
                DrawFormattedText(window, sprintf('You will now perform the FOOT stomping experiment for the sequence you studied at home (automatic). \n %s \n\n There is a total of 11 trials, so performing the sequence 11 times (once per trial). \n In between each trial there is a rest period of 20 seconds. \n During this rest you will hear a metronome sound, stomp the sequence according to this interval sound. \n Trials and rest periods are indicated with red(= trial) and white(= rest)fixation crosses presented on the screen. \n\n When the experiment starts you cannot talk anymore. \n Furthermore, it is important to stay still except for your right leg. \n Keep your eyes open (also during the rest periods). \n\n Before the start of each new trial the sequence will be shown on the screen. \n If you press any key, the experiment starts right away. \n It will start with a rest period. \n Whenever a RED fixation cross appears on the screen, you should start stomping the sequence. \n When ready: press any key to start the foot stomping experiment.', sequenceauto), 'center', 'center', white);
                vbl = Screen('Flip', window);
                KbStrokeWait;

                trig.digitalout(1, 'start_rec'); % starts the recording of xsens
                %Stimulus for foot stomping automatic sequence
                for q = 1:N_trials; % Will perform 11 trials

                    %Rest period 20-25 seconds white fixation cross with 8
                    %seconds of metronome sound
                    trig.beep(440, 0.2, 'rest');
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    PsychPortAudio('Start', h_Metronome8, 1, [], []); % Play metronome sound file
                    WaitSecs(t1+randi(t2));

                    %Show a red fixation cross during trial
                    trig.beep(880, 0.2, 'foot_auto');
                    onset=GetSecs;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, [1 0 0], [xCenter yCenter], 2);
                    Screen('Flip', window)
                    WaitSecs (t3);

                    % Show short white fix cross after trial
                    trig.beep(440, 0.2, 'rest');
                    duration=GetSecs-onset;
                    Screen('TextSize', window, 36);
                    Screen('DrawLines', window, allCoords,...
                        lineWidthPix, white, [xCenter yCenter], 2);
                    Screen('Flip', window);
                    WaitSecs(5); % 5 seconds, so the nirs signal has time to go back to baseline

                    % Show sequence before new trial starts
                    Screen('TextSize', window, 25);
                    DrawFormattedText(window, sprintf('%s \n Press any key to continue with the next trial.', sequenceauto), 'center', 'center', white);
                    vbl= Screen('Flip', window);
                    KbStrokeWait; %wait for response to terminate instructions

                    % Store information in created event
                    value={'red X'};
                    events_footauto(q).stimuli=table(onset,duration, value);

                end

                % End of the automatic foot stomping task.
                trig.beep(440, 0.2, 'rest');
                Screen('TextSize', window, 25);
                DrawFormattedText(window, 'This is the end of the automatic foot stomping task. \n You can take a rest if needed. \n Whenever you are ready, \n press any key to continue with the rest of the experiment.', 'center', 'center', white);
                save('events_footauto.mat', 'events_footauto'); % save the events
                vbl= Screen('Flip', window);
                KbStrokeWait; %wait for response to terminate instructions
                trig.digitalout(0, 'stop_rec'); % stops the recording of xsens
            end
        end
    end

end

%Show dual task performance (non-automatic sequence) of finger tapping task in command window
fprintf('Finger NonAutoDual \n')
for h = 1:N_trials
    fprintf('Trial %d: \n', h)
    % Show if the answers for the number of G's presented were correct
    if str2num(events_handnonautodual(h).stimuli.response{1})==length(strfind(events_handnonautodual(h).stimuli.value{1}, 'G'))
        fprintf('G correct \n')
    else
        fprintf('G incorrect \n')
    end
    %Show if the tempo was correct.
    margin=0.25; % margin of error: think about what is most convenient
    delay=mean(diff(events_handnonautodual(h).responses.onset)-1/1.50);
    fprintf('the tempo was off with on average %f seconds \n', delay);
    %Show if the tapped sequence was correct
    if all(strcmp(events_handnonautodual(h).responses.value,sequencenonautoprint'))
        fprintf('Seq correct \n')
    else
        fprintf('Seq incorrect \n')
    end
end

%Show dual task performance (non-automatic sequence) for foot stomping task
%in command window
fprintf('Foot NonAutoDual \n')
for g = 1:N_trials
    fprintf('Trial %d: \n', g)
    %Show if the answers for the number of G's presented were correct
    if str2num(events_footnonautodual(g).stimuli.response{1})==length(strfind(events_footnonautodual(g).stimuli.value{1}, 'G'))
        fprintf('G correct \n')
    else
        fprintf('G incorrect \n')
    end
end

%Show tempo performance of finger tapping task of non-automaticity experiment
fprintf('Finger NonAuto \n')
for e = 1:N_trials
    fprintf('Trial %d: \n', e)
    % Show if the tempo was correct
    margin=0.25; % margin of error: think about what is most convenient
    delay=mean(diff((events_handnonauto(e).responses.onset))-1/1.50);
    fprintf('the tempo was off with on average %f seconds \n', delay);
    %Show if the tapped sequence was correct
    if all(strcmp(events_handnonauto(e).responses.value,sequencenonautoprint'))
        fprintf('Seq correct \n')
    else
        fprintf('Seq incorrect \n')
    end
end

%Show tempo performance of finger tapping task of automaticity experiment
fprintf('Finger Auto \n')
for f = 1:N_trials
    fprintf('Trial %d: \n', f)
    %Show if the tempo was correct
    margin=0.25; % margin of error: think about what is most convenient
    delay=mean(diff((events_handauto(f).responses.onset))-1/1.50);
    fprintf('the tempo was off with on average %f seconds \n', delay);
    %Show if the tapped sequence was correct
    if all(strcmp(events_handauto(f).responses.value,sequenceautoprint'))
        fprintf('Seq correct \n')
    else
        fprintf('Seq incorrect \n')
    end
end

% End of the experiment, thank the participant
Screen('TextSize',window,30);
DrawFormattedText(window,'This is the end of the experiment, thank you for participating!', 'center', 'center', white);
vbl = Screen('Flip', window);

KbStrokeWait;
sca

%% end the lsl session
trig.pulseIR(3, 0.2); % stop trigger for the nirs recording
delete(trig);
ses.stop();
diary off;
%% HELPER FUNCTIONS
function triglistener(src, event)
for ii=1:numel(event.Data)
  info=src.info;
  fprintf('   lsl event (%s) received @ %s with (uncorrected) timestamp %.3f \n',  event.Data{ii}, info.type, event.Timestamps(ii));
end
end

function cleanupFun()
delete(ses);
delete(trigstr{1});
delete(trigstr{2});
delete(info);
end


function [collect] = ft_channelcombination(channelcmb, datachannel, includeauto, dirflag)

% FT_CHANNELCOMBINATION creates a cell-array with combinations of EEG/MEG channels
% for subsequent cross-spectral-density, coherence and/or connectivity ananalysis
%
% You should specify channel combinations as a two-column cell-array,
%   cfg.channelcmb = {  'EMG' 'MLF31'
%                       'EMG' 'MLF32'
%                       'EMG' 'MLF33' };
% to compare EMG with these three sensors, or
%   cfg.channelcmb = { 'MEG' 'MEG' };
% to make all MEG combinations, or
%   cfg.channelcmb = { 'EMG' 'MEG' };
% to make all combinations between the EMG and all MEG channels.
%
% For each column, you can specify a mixture of real channel labels
% and of special strings that will be replaced by the corresponding
% channel labels. Channels that are not present in the raw datafile
% are automatically removed from the channel list.
%
% When directional connectivity measures will subsequently be computed, the
% interpretation of each channel-combination is that the direction of the
% interaction is from the first column to the second column.
%
% Note that the default behavior is to exclude symmetric pairs and
% auto-combinations.
%
% See also FT_CHANNELSELECTION

% Undocumented options:
%   includeauto = 0 (or 1), include auto-combinations
%   dirflag     = 0 (or 1, or 2) specifies the treatment of the order in
%                   the columns of the output. If dirflag = 0, the order is
%                   preserved, if dirflag = 1, the order is reversed,
%                   second input column is put first. If dirflag = 2, both
%                   directions are added to the list of combinations.

% Copyright (C) 2003-2015, Jan-Mathijs Schoffelen & Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

if nargin<3 || isempty(includeauto), includeauto = 0; end
if nargin<4 || isempty(dirflag),     dirflag     = 0; end

% ensure that datachannel is a column vector
datachannel = datachannel(:);

if ischar(channelcmb) && strcmp(channelcmb, 'all')
  % make all possible combinations of all channels
  channelcmb = {'all' 'all'};
end

% it should have a selection of two channels or channelgroups in each row
if size(channelcmb,1)==2 && size(channelcmb,2)~=2
  ft_warning('transposing channelcombination matrix');
  channelcmb = channelcmb';
end

if ~(numel(channelcmb)==2 && iscell(channelcmb{1}) && iscell(channelcmb{2})) &&...
    isempty(setdiff(channelcmb(:), datachannel))
  % there is not much to do, since there are no channelgroups with special names
  % each element of the input therefore already contains a proper channel name

  switch dirflag
    case 0
      % nothing to do
    case 1
      % switch the order
      channelcmb = channelcmb(:,[2 1]);
    case 2
      channelcmb = [channelcmb; channelcmb(:,[2 1])];
    otherwise
      ft_error('unknown value for input argument ''dirflag''');
  end
  collect = channelcmb;

  if includeauto
    autochannel = unique(channelcmb(:));
    for ch=1:numel(autochannel)
      collect = cat(1, collect, [autochannel(ch) autochannel(ch)]);
    end
  end

else
  % a combination is made for each row of the input selection after
  % translating the channel group (such as 'all') to the proper channel names
  % and within each set, double occurences and autocombinations are removed

  selmat = false(numel(datachannel));
  for sel=1:size(channelcmb,1)
    % translate both columns and subsequently make all combinations
    if iscell(channelcmb(sel,1)) && iscell(channelcmb(sel,2))
    % - channelcmb is a 1x2 cell-array containing cells
      channelcmb1 = ft_channelselection(channelcmb{sel,1}, datachannel);
      channelcmb2 = ft_channelselection(channelcmb{sel,2}, datachannel);
    else
    % - channelgroups with special names
      channelcmb1 = ft_channelselection(channelcmb(sel,1), datachannel);
      channelcmb2 = ft_channelselection(channelcmb(sel,2), datachannel);
    end
    % translate both columns and subsequently make all combinations
    list1 = match_str(datachannel, channelcmb1);
    list2 = match_str(datachannel, channelcmb2);

    selmat(list1,list2) = true;
    if dirflag==2
      % also fill the other 'direction'
      selmat(list2,list1) = true;
    end

    if ~includeauto
      % exclude the auto-combinations
      selmat = selmat & ~eye(size(selmat));
    else
      % ensure that the appropriate diagonal entries are filled
      autovec = false(numel(datachannel),1);
      autovec([list1(:);list2(:)]) = true;
      selmat = selmat | diag(autovec);
    end

  end

  if dirflag<2
    % remove double occurrences
    selmat   = selmat & ~tril(selmat, -1)';
  end
  [i1, i2] = find(selmat);

  switch dirflag
    case 0
      % original behavior,
      % row-to-column, i.e. outflow according to FT's convention
      indx = [i1 i2];
    case 1
      % column-to-row, i.e. inflow according to FT's convention
      indx = [i2 i1];
    case 2
      % both
      indx = [i1 i2];

    otherwise
      ft_error('unknown value for input argument ''dirflag''');
  end

  if isempty(indx)
    collect = cell(0,2);
  else
    collect = [datachannel(indx(:,1)) datachannel(indx(:,2))];
  end
end


%
% my_append(file, lines)
%
% Similate the function of "double right arrow file writing" function in Unix
% The inputs are
%       file: the destination
%       lines: the text that will be written
%
% Author: Xiong Xiao,
%         School of Computer Engineering, Nanyang Technological University
% Date Created: 02 Feb, 2009
% Last Modified: 02 Feb, 2009
%
function my_append(file, lines, start, stop)

FID = fopen(file, 'a');
if nargin < 3
    start = 1;
    stop = length(lines);
end

if iscell(lines)
    for i=start:min(stop,length(lines))
        if length(lines{i})==0
            continue;
        elseif strcmp(lines{i}(end), '\n') == 1
            fprintf(FID, '%s', lines{i});
        else
            fprintf(FID, '%s\n', lines{i});
        end
    end
else
    fprintf(FID, '%s\n', lines);
end

fclose(FID);


% For each layer, determine whether we need to pass gradient back
function layer = DetermineGradientPass(layer)

% find the parent of every layer
parent = DetermineLayerParent(layer);

skipBP = zeros(length(layer),1);
for i=1:length(layer)
    if isfield(layer{i}, 'skipBP')
        skipBP(i) = layer{i}.skipBP;
    end
end

update = zeros(length(layer),1);
for i=1:length(layer)
    if isfield(layer{i}, 'update')
        update(i) = layer{i}.update;
    end
end

for i=1:length(layer)
    if IsUpdatableNode(layer{i}.name)==0; continue; end
    if skipBP(i); continue; end

    layer{i}.passGradBack = sum(update(parent{i}))>0;
end

end


%kxvortho 'Visualize and navigate by orthogonal planes in a volume'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros xvortho.pane file
%
% Parameters:
% InputFile: i ' Input Image ', optional: 'Input image filename'
% InputFile: cmap 'Colormap Image', optional: 'input alternate colormap file'
% Integer: x 'X Placement', default: -1: 'x location for GUI autoplacement'
% Integer: y 'Y Placement', default: -1: 'y location for GUI autoplacement'
% Double: update 'Update Time', default: 0: 'initial update time'
%
% Example: kxvortho({i, cmap}, {'i','';'cmap','';'x',-1;'y',-1;'update',0})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% xvortho - Interactively navigate by orthogonal planes in a volume
%
%  DESCRIPTION
% "xvortho" is an interactive tool which allows navigation by any input
% object.
% The features provided by "xvortho" include:
% - An input file history list
% - Normalization of colormaps
% - Control over which columns of the map data are displayed as red, green, and blue
% - Application of functions to the map data values to produce new colormaps
% - Pre-defined colormap installation
%
% The master form of "xvortho" displays the input object in a workspace.
% The object is displayed as three orthogonal planes, named planes X, Y
% and Z, as the input object was a 3D volume.
% Plane X corresponds to a constant dimention w and it is a function of d and h.
% Plane Y corresponds to a constant dimention h and it is a function of w and d.
% Plane Z corresponds to a constant dimention d and it is a function of w and h.
%
% The initial configuration shows plane X with w=0, plane Y with h=0 and
% plane Z with d=0. Initial time and element dimentions are also zero. Clicking
% in one of the three displayed planes is equivalent to changing the choosen
% positions w, h or d, depending on which plane the cursor was pointing on
% during the clicking. For instance, if we are in the position w=10, h=20 and
% d=30, and the cursor is in the plane Z, on the
% position (50,100) when the button is pressed, then the new positions in w and
% h will be 50 and 100 respectively, which will cause the planes X and Y to be
% updated. Changing of time and element dimentions are also possible using
% scroll bars on the bottom of the workspace.
%
% Above the workspace are "License", "Help", and "Quit" buttons, from which one
% may access the license agreement, display online help pages, and quit the
% program, respectively.  To the left of the image workspace are two subform
% buttons labeled "Files" and "Options".
%
% Use the "Files" subform button to display the "Input and Output Files" subform.
% From this subform, you may input a new image. You may also output any of the
% three displayed
% images, either as they currently appears, or as they really are in the input
% image.
%
% A number of features are available from the "Options" subform, which
% contains three panes: "Image List", "Display" and "Colormaps". Those were
% adapted from editimage.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% editimage
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993, 1994, 1995 UNICAMP, R A Lotufo,  All rights reserved.
%

function varargout = kxvortho(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kxvortho(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'cmap', '__input';'x', -1;'y', -1;'update', 0};
maxval={1,1,1000,1000,1};
minval={1,1,-1,-1,1};
istoggle=[1,1,1,1,1];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','Integer','Integer','Double'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=0; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(0);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
callKhoros([w 'xvortho"  '],Inputs,narglist);


classdef ElasticMaterial < Material

    properties (Access = public)
        C
    end

end


function volROIfiles2mrGray(roiFilename, writeDir)
%
% volROIfiles2mrGray(roiFilename, [writeDir])
%
% PURPOSE:  Read ROI.mat files (mrLoadRet format) and write
% out the ROIs in a format that mrGray can read. The new files
% will have the same file name as the ROI files and will be
% written to writeDir (defaults to pwd).
%
% roiFilename can either be a single filename string, a cell
% array of file names, or a single directory name (in which
% case all .mat files in the dir will be converted).
%
%
% HISTORY:
%   2002.01.11 RFD (bob@white.stanford.edu) wrote it.
%

if(~iscell(roiFilename))
		 d = dir(roiFilename);
		 if(length(d)==1 & d.isdir==0)
		     roiFilename = {roiFilename};
		 else
		     % It's a directory- get all .mat files
         p = roiFilename;
         roiFilename = {};
         for(ii=1:length(d))
             if(~d(ii).isdir & length(d(ii).name)>3 ...
                   & strcmpi(d(ii).name(end-3:end), '.mat'))
               roiFilename{end+1} = fullfile(p,d(ii).name);
             end
         end
     end
end

for(ii=1:length(roiFilename))
    roi = load(roiFilename{ii});
    [p, n, e] = fileparts(roiFilename{ii});
    if(exist('writeDir', 'var'))
        p = writeDir;
    end
    outName = [n,'.roi'];
    disp(['Writing ',outName,' to ',p,'.']);
    volROI2mrGray(outName, roi.ROI, p);
end

return;


function f = comp(varargin)
% FUNC = COMP(FUNCTIONS+)
%   Form the composition of FUNCTIONS, resulting in FUNC.
%

  functions = varargin;
  function varargout = func(varargin)
    in = varargin;
    for i = 1:numel(functions)
      func = functions{i};
      if iscell(func)
        [func, nout] = deal(func{:});
      else
        nout = max(nargout(func), 1);
      end
      out = cell(1, nout);
      [out{:}] = func(in{:});
      in = out;
    end

    [varargout{1:max(nargout, 1)}] = deal(in{:});
  end

  f = @func;
end


function fixedtrx2ann(trx,oldannname,newannname)

% open the annotation file for reading and writing
fin = fopen(oldannname,'rb');
if exist(newannname,'file'),
  b = questdlg(sprintf('File %s exists. Overwrite?',newannname));
  if ~strcmpi(b,'yes'),
    return;
  end
end
fout = fopen(newannname,'wb');

% find the end of the header
while true,
  [s,param,value] = read_ann_line(fin);
  if ~ischar(s) && s == -1,
    error('End of file encountered before end of header found');
  end
  if ~ischar(value) && length(value) > 1,
    fprintf(fout,'%s\n',s);
    fwrite(fout,value,'uint8');
  else
    fprintf(fout,'%s\n',s);
  end
  if strcmp(s,'end header'),
    break;
  end
end

if ftell(fin) ~= ftell(fout),
  error('input and output file do not match');
end

fclose(fin);

nframes = max([trx.endframe]);
nflies = length(trx);

for i = 1:nframes,
  if mod(i,100) == 0,
    fprintf('Writing frame %d\n',i);
  end
  for j = 1:nflies,
    if trx(j).firstframe > i || trx(j).endframe < i,
      continue;
    end
    k = i - trx(j).firstframe + 1;
    fprintf(fout,'%f\t%f\t%f\t%f\t%f\t%d\t',...
      trx(j).x(k)-1,trx(j).y(k)-1,trx(j).b(k),trx(j).a(k),trx(j).theta(k),j-1);
  end
  fprintf(fout,'\n');
end

fclose(fout);

if 0,
  fclose('all');
  fin = fopen(oldannname,'rb');
  fout = fopen(newannname,'rb');
  while true,
[sin,paramin,valuein] = read_ann_line(fin);
[sout,paramout,valueout] = read_ann_line(fout);
if ~strcmp(sin,sout),
fprintf('sin does not match sout\n');
keyboard;
else
fprintf([sin,'\n']);
end
if strcmp(sin,'end header'),
   if ~strcmp(sout,'end header'),
     fprintf('end of headerin but not headerout\n');
     keyboard;
   end
   break;
elseif strcmp(sout,'end header'),
  fprintf('end of headerout but not headerin\n');
  keyboard;
  break;
end
if isempty(paramin) && isempty(paramout),
  fprintf('both empty\n');
  continue;
end
if ~strcmp(paramin,paramout),
fprintf('paramin does not match paramout\n');
keyboard;
else
fprintf([paramin,'\n']);
end
if ischar(valuein),
if ~ischar(valueout),
fprintf('ischar(valuein) but not valueout\n');
keyboard;
end
if ~strcmp(valuein,valueout),
fprintf('valuein does not match valueout\n');
end
elseif length(valuein) == 1,
if ischar(valueout),
fprintf('ischar(valueout) but not valuein\n');
keyboard;
end
if length(valueout) ~= 1,
fprintf('length(valuein) == 1, but not valueout\n');
keyboard;
end
if valuein ~= valueout,
fprintf('valuein and valueout do not match\n');
keyboard;
else
fprintf([num2str(value),'\n']);
end
else
if ischar(valueout),
fprintf('ischar(valueout) but not valuein\n');
keyboard;
end

if length(valueout) == 1,
fprintf('length(valueout) == 1 but not valuein\n');
keyboard;
end
if length(valuein) ~= length(valueout),
fprintf('lengths do not match\n');
keyboard;
end
if ~all(valuein == valueout),
fprintf('not all values match\n');
keyboard;
else
fprintf('value vectors of length %d match\n',length(valuein));
end
end
end
end


% LTFAT - Block processing
%
%  Zdenek Prusa, 2013 - 2018.
%
%  Basic methods
%    BLOCK          - Setup a new block-stream
%    BLOCKDEVICES   - List available audio I/O devices
%    BLOCKREAD      - Read samples from file/device
%    BLOCKPLAY      - Play block (sound output)
%    BLOCKPANEL     - Block-stream control GUI
%    BLOCKPANELGET  - Obtain parameter(s) from GUI
%    BLOCKDONE      - Closes block-stream and frees resources
%    BLOCKWRITE     - Appends data to a wav file
%
%  Block-adapted transforms
%    BLOCKFRAMEACCEL     - Prepare a frame for a block-stream processing
%    BLOCKFRAMEPAIRACCEL - Prepare a pair of frames for a block-stream processing
%    BLOCKANA            - Block analysis
%    BLOCKSYN            - Block synthesis
%
%  Running visualisation
%    BLOCKFIGURE   - Initialize figure for redrawing
%    BLOCKPLOT     - Append coefficients to the running plot
%
%  Other
%    LTFATPLAY     - Replacement for the sound command allowing selecting an output device
%
%  For help, bug reports, suggestions etc. please visit
%  http://github.com/ltfat/ltfat/issues


%Disk logger test
%
% Author: Jonathan Karr, jkarr@stanford.edu
% Affiliation: Covert Lab, Department of Bioengineering, Stanford University
% Last updaetd 2/3/2011
classdef DiskLogger_Test < TestCase
    properties
        simulation
    end

    methods
        function this = DiskLogger_Test(name)
            this = this@TestCase(name);
        end

        function setUp(this)
            sim = edu.stanford.covert.cell.sim.SimulationFixture.load([], true);
            sim.applyOptions('lengthSec', 10);
            this.simulation = sim;
        end
    end

    methods
        function testLogging(this)
            import edu.stanford.covert.cell.sim.util.DiskLogger;

            sim = this.simulation;
            pm = sim.state('ProteinMonomer');

            metadata = edu.stanford.covert.cell.sim.util.ConditionSet.parseConditionSet(...
                sim, 'src_test/+edu/+stanford/+covert/+cell/+sim/+util/fixtures/runSimulations.xml').metadata;
            metadata.knowledgeBaseWID = 145;
            metadata.revision = edu.stanford.covert.util.revision;

            outputDirectory = 'output/runSmallTests/DiskLogger';
            delete([outputDirectory '/*']);
            segmentSizeSec = 2;
            logger = DiskLogger(outputDirectory, segmentSizeSec, metadata);
            logger.addMetadata(metadata);
            sim.run(logger);

            DiskLogger.reindexTimeCourses(outputDirectory);

            metadatafields = {'shortDescription'; 'longDescription';
                'email'; 'lastName'; 'firstName'; 'affiliation'; 'knowledgeBaseWID';
                'startTime'; 'endTime'; 'lengthSec'; 'revision'; 'differencesFromRevision';
                'userName'; 'hostName'; 'ipAddress';
                'outputDirectory'; 'segmentSizeStep'; 'downsampleStepSec';
                'stateNames'; 'dependentStateNames'};
            assertEqual(sort(metadatafields), sort(fieldnames(logger.metadata)));

            %% assert created files
            files = dir(outputDirectory);
            fileNames = {'.'; '..'; 'fittedConstants.mat'; 'metadata.mat'; 'options.mat'; 'parameters.mat';
                'state-0.mat'; 'state-1.mat'; 'state-2.mat'; 'state-3.mat'; 'state-4.mat'; 'state-5.mat';
                'randStreamStates.mat'};
            assertTrue(all(ismember(fileNames, {files.name}')));

            %% assert loading back from disk
            downsampleStepSec = 2;
            nTimepoints = sim.lengthSec / downsampleStepSec;

            %extraction downsampling
            [states, metadata, options, parameters, fittedConstants, randStreamStates] = ...
                DiskLogger.load(outputDirectory, '-all', [], [], downsampleStepSec, 'extract');
            metadata.downsampleStepSec = logger.metadata.downsampleStepSec;
            metadata.segmentSizeStep = logger.metadata.segmentSizeStep;

            assertEqual(sort(cellfun(@(x) x(7:end), sim.stateWholeCellModelIDs, 'UniformOutput', false)), sort(fieldnames(states)));
            assertEqual([1 1 nTimepoints], size(states.Time.values));
            assertEqual(permute([1:downsampleStepSec:sim.lengthSec-3 sim.lengthSec], [1 3 2]), states.Time.values);
            assertEqual([numel(sim.getRandStreamStates().simulation) sim.lengthSec+1], size(randStreamStates.simulation));

            assertEqual(logger.metadata, metadata);
            assertEqual(sim.getOptions, options);
            assertEqual(sim.getParameters, parameters);
            assertEqual(sim.getFittedConstants, fittedConstants);

            pmCounts = states.ProteinMonomer.counts;

            states = DiskLogger.load(outputDirectory, {'ProteinMonomer' 'counts' '-sum' ':'}, [], [], downsampleStepSec, 'extract');
            assertEqual(sum(pmCounts, 1), states.ProteinMonomer.counts);

            states = DiskLogger.load(outputDirectory, {'ProteinMonomer' 'counts' '-sum' '-sum'}, [], [], downsampleStepSec, 'extract');
            assertEqual(sum(sum(pmCounts, 1), 2), states.ProteinMonomer.counts);

            states = DiskLogger.load(outputDirectory, {'ProteinMonomer' 'counts' ':' [3 4]}, [], [], downsampleStepSec, 'extract');
            assertEqual(sum(pmCounts(:, [3 4], :), 2), states.ProteinMonomer.counts);

            states = DiskLogger.load(outputDirectory, {'ProteinMonomer' 'counts' [pm.matureIndexs pm.boundIndexs] [1 4]}, [], [], downsampleStepSec, 'extract');
            assertEqual(sum(pmCounts(pm.matureIndexs, [1 4], :) + pmCounts(pm.boundIndexs, [1 4], :), 2), states.ProteinMonomer.counts);

            %mean downsampling
            [states, metadata, options, parameters, fittedConstants] = ...
                DiskLogger.load(outputDirectory, '-all', [], [], downsampleStepSec, 'mean');
            metadata.downsampleStepSec = logger.metadata.downsampleStepSec;

            assertEqual(sort(cellfun(@(x) x(7:end), sim.stateWholeCellModelIDs, 'UniformOutput', false)), sort(fieldnames(states)));
            assertEqual([1 1 nTimepoints], size(states.Time.values));
            assertEqual(permute(0.5+(1:downsampleStepSec:sim.lengthSec), [1 3 2]), states.Time.values);

            assertEqual(logger.metadata, metadata);
            assertEqual(sim.getOptions, options);
            assertEqual(sim.getParameters, parameters);
            assertEqual(sim.getFittedConstants, fittedConstants);

            states = DiskLogger.load(outputDirectory, '-independent', [], [], downsampleStepSec, 'extract'); %#ok<NASGU>
            states = DiskLogger.load(outputDirectory, '-dependent', [], [], downsampleStepSec, 'extract'); %#ok<NASGU>

            %test loadSimulation
            [sim2, states, ~, ~, ~, metadata] = loadSimulation([pwd filesep outputDirectory]);
            metadata.downsampleStepSec = logger.metadata.downsampleStepSec;

            assertEqual(options, sim2.getOptions());
            assertEqual(parameters, sim2.getParameters());
            assertEqual(fittedConstants, sim2.getFittedConstants());
            assertEqual(metadata, logger.metadata);

            states2 = struct;
            for i = 1:numel(sim2.states)
                state = sim2.states{i};
                stateID = state.wholeCellModelID(7:end);
                states2.(stateID) = struct;
                for j = 1:numel(state.stateNames)
                    name = state.stateNames{j};
                    states2.(stateID).(name) = state.(name);
                end
            end
            assertEqual(states, states2);
        end

        function testEarlyTermination(this)
            import edu.stanford.covert.cell.sim.util.DiskLogger;

            %setup
            sim = this.simulation;

            metadata = edu.stanford.covert.cell.sim.util.ConditionSet.parseConditionSet(sim, 'src_test/+edu/+stanford/+covert/+cell/+sim/+util/fixtures/runSimulations.xml').metadata;
            metadata.knowledgeBaseWID = 145;

            outputDirectory = 'output/runSmallTests/DiskLogger';
            delete([outputDirectory '/*']);
            segmentSizeSec = 2;
            logger = DiskLogger(outputDirectory, segmentSizeSec, metadata);
            logger.addMetadata(metadata);

            %run simulation
            logger.initialize(sim);

            for i = 1:sim.getNumSteps / 2
                sim.evolveState();
                logger.append(sim);
            end

            logger.finalize(sim);

            %test
            files = dir(outputDirectory);
            fileNames = {'.'; '..'; 'fittedConstants.mat'; 'metadata.mat'; 'options.mat'; 'parameters.mat';
                'state-0.mat'; 'state-1.mat'; 'state-2.mat'; 'state-3.mat'};
            assertTrue(all(ismember(fileNames, {files.name}')));

            [states, metadata] = logger.load(outputDirectory, {'Time' 'values'}, [], [], 2, 'extract');
            assertEqual(sim.getNumSteps / 2, metadata.lengthSec);
            assertEqual(permute([1 3 5], [1 3 2]), states.Time.values);

            [states, metadata] = logger.load(outputDirectory, {'Time' 'values'}, [], [], 2, 'mean');
            assertEqual(sim.getNumSteps / 2, metadata.lengthSec);
            assertEqual(permute([1.5 3.5 5], [1 3 2]), states.Time.values);
        end
    end
end


function texturedVRML2(outputFname,vertex, face, textureUV, textureImageFile)
%{
  outputFname is the file name for VRML2 file. usualy it is *.wrl
      when it is done, open the file in meshlab
  vertex is 3xN points
  face is KxM faces (index for faces with K vertices and M face in total.
        K=3 for triangulated mesh. K=4 for rectangular mesh.)
  textureUV is KxMx2 uv coordinates for each vertice of the faces
        (all values should be from 0 to 1)
  texture coordinate system

  V (0,1)      (1,1)
  ^
  |
  |
  |
  +--------> U (1,0)
 (0,0)

  more document: http://www.c3.hu/cryptogram/vrmltut/part6.html
%}

fp = fopen(outputFname,'w');
fprintf(fp,'#VRML V2.0 utf8\n');
fprintf(fp,'Shape{ geometry IndexedFaceSet{\n');
fprintf(fp,'coord Coordinate{point[\n');
for i=1:size(vertex,2)
    fprintf(fp,'%f %f %f,\n',vertex(1,i),vertex(2,i),vertex(3,i));
end
fprintf(fp,']}\n');
fprintf(fp,'coordIndex[\n');
for i=1:size(face,2)
    for j=1:size(face,1)
        fprintf(fp,'%d,',face(j,i));
    end
    fprintf(fp,'-1,\n');
end
fprintf(fp,']\n');
fprintf(fp,'texCoord TextureCoordinate{point[\n');
for i=1:size(textureUV,2)
    for j=1:size(textureUV,1)
        fprintf(fp,'%f %f\n',textureUV(j,i,1),textureUV(j,i,2));
    end
end
fprintf(fp,']}\n');
fprintf(fp,'texCoordIndex[\n');
cnt =0;
for i=1:size(textureUV,2)
    for j=1:size(textureUV,1)
        fprintf(fp,'%d ',cnt);
        cnt=cnt+1;
    end
    fprintf(fp,'-1\n');
end
fprintf(fp,']\n');
fprintf(fp,'}\n');
fprintf(fp,'appearance Appearance{material Material{diffuseColor 1 1 1 }  texture ImageTexture { url "%s" } }\n',textureImageFile);
fprintf(fp,'}\n');
fclose(fp);
end


function [plotMins,plotMaxs] = prtPlotUtilGetPlotLims(PrtClassifier,PrtDataSet)
% Internal function,
% xxx Need Help xxx

% Here we get the limits for plotting:
if nargin == 1 || isempty(PrtDataSet)
    testY = [];
    testX = [];
else
    testX = getObservations(PrtDataSet);
end

trainX = getObservations(PrtClassifier.PrtDataSet);
plotMins = min(cat(1,trainX,testX));
plotMaxs = max(cat(1,trainX,testX));


% PRIORTOOLBOXES Load in the relevant toolboxes for kern.

importLatest('optimi');
importLatest('ndlutil');


function [results] = test_all_complements(models,final,grid,friend_classes,savegtids,saverecs)
VOCinit;

keep_thresh = 0.1;
max_os = 1.0;

for exid = 1:length(models)
  fprintf(1,'!');
  Iex = im2double(imread(sprintf(VOCopts.imgpath, ...
                                 models{exid}.curid)));
  models{exid}.sizeI = size(Iex);
end

%compute all friends

% classes = VOCopts.classes;

% countvec = zeros(1,20);
% for i = 1:length(models)
%   fprintf(1,'.');
%   recs = PASreadrecord(sprintf(VOCopts.annopath,models{i}.curid));
%   bbs = cat(1,recs.objects.bbox);
%   osmat = getosmatrix_bb(bbs(models{i}.objectid,:), bbs);
%   c = {recs.objects.class};
%   goodname = ismember(c,friend_classes);
%   targets = find(osmat>keep_thresh & osmat <=max_os & goodname);

%   if length(targets) > 1
%     fprintf(1,'got multiple d, keeping best\n',length(targets));
%     [aa,bb] = sort(osmat(targets),'descend');
%     targets = targets(bb);
%     targets = targets(bb(1));
%   end

%   targetc = c(targets);

%   models{i}.friendbb = bbs(targets,:);
%   models{i}.friendc = targetc;

%   [aa,bb] = ismember(targetc,classes);
%   countvec(bb) = countvec(bb)+1;
% end

% frac_covered = countvec ./ length(models)*100;
%models_with_friends = models;

%friend_classes = find(countvec > 10);
%friend_classes = classes(friend_classes);

for z = 1:length(friend_classes)
  targetcls = friend_classes{z};

  models = cellfun2(@(x)initialize_with_friends(x,targetcls), ...
                    models);

  % for aaa = 1:length(models_with_friends)
  %   oks = find(ismember(models_with_friends{z}.friendc,targetcls));
  %   models{z}.friendbb = models_with_friends{z}.friendbb(oks,:);
  %   models{z}.friendc = models_with_friends{z}.friendc(oks);
  % end

bboxes = final.unclipped_boxes;

minoverlap = .5;
if 1 %~exist('minoverlap','var')
  fprintf(1,'transferring friends\n');
  %oldbboxes = bboxes;
  bboxes = transfer_friends(models, bboxes);
end

if 0
maxdet = cellfun2(@(x)max(x(:,end)),bboxes);
lens = cellfun(@(x)length(x),maxdet);
goods = find(lens>0);
[alpha,beta] = sort([maxdet{goods}],'descend');
for i = 1:length(beta)
  curid = grid{goods(beta(i))}.curid;
  Ibase = imread(sprintf(VOCopts.imgpath,curid));
  figure(1)
  clf
  imagesc(Ibase)
  plot_bbox(bboxes{goods(beta(i))});
  pause
end
end

for i = 1:length(bboxes)
  bboxes{i} = clip_to_image(bboxes{i},grid{i}.imbb);
end

filer=sprintf(VOCopts.detrespath,'comp3',targetcls);
fprintf(1,'Writing File %s\n',filer);
fid = fopen(filer,'w');

for i = 1:length(bboxes)
  curid = grid{i}.curid;
  for q = 1:size(bboxes{i},1)
    fprintf(fid,'%s %f %f %f %f %f\n',curid,...
            bboxes{i}(q,end), bboxes{i}(q,1:4));
  end
end
fclose(fid);

if exist('minoverlap','var')
  VOCopts.minoverlap = minoverlap;
end

[recall,prec,ap,apold] = VOCevaldet(VOCopts,'comp3',targetcls, ...
                                    true,savegtids,saverecs);
results{z}.recall = recall;
results{z}.prc = prec;
results{z}.ap = ap;
results{z}.apold = apold;
results{z}.targetcls = targetcls;

figure;
plot(recall,prec)
title(sprintf('%s to predict %s: apold=%.3f',models{1}.cls,targetcls,apold));
targetcls
drawnow
end


function [fname] = check_file_extension(fname, extension)
% See also CLEAR_FILE_EXTENSION, ISFILEXTENSION.
%
% File:      check_file_extension.m
% Author:    Ioannis Filippidis, jfilippidis@gmail.com
% Date:      2012.06.22
% Language:  MATLAB R2012a
% Purpose:   append desired file extension if absent
% Copyright: Ioannis Filippidis, 2012-

% extension ok ?
if isfilextension(fname, extension)
    return
end

% dot in extension ?
if ~strcmp(extension(1), '.')
    extension = ['.', extension];
end

fname = [fname, extension];


function tagS = content_identification_macro_tags
%"content_identification_macro_tags"
%   Return the tags used to represent content as specified by C.10.9 in
%   PS3.3 of 2006 DICOM specification. Tags are returned in a struct array
%   with 3 fields:
%
%   Tag: String containing hex DICOM tag of a field.
%  Type: String describing type of field, with 5 options:
%         '1' Field must exist, data must exist and be valid.
%         '2' Field must exist, data can exist and be valid, or be NULL.
%         '3' Field is optional, if the field exists data can exist and be
%             valid or be NULL.
%         '1C' Field must exist under certain conditions and contain valid
%             data.
%         '2C' Field must exist under certain conditions and can contain
%             valid data or be NULL.
%Children: For sequences, a tagS with the same format as this struct array.
%
%JRA 06/06/06
%YWU Modified 03/01/08
%
%Usage:
%   tagS = patient_module_tags
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

tagC = {'00200013','00700080','00700081','00700084'};

tagDecC = {2097171, 7340160, 7340161, 7340164};

tagTypeC = {'1','1','2','2'};

childC = {[],[],[],[]};

tagS = struct('tag', tagC, 'tagdec', tagDecC, 'type', tagTypeC, 'children', childC);

%
% %Initialize the tagS structure.
% tagS = struct('tag', {}, 'type', {}, 'children', {});
%
% %Create an empty tagS template for sequence creation.
% template = tagS;
%
% %Add tags based on PS3.3 attribute lists.
%
% %Instance Number
% tagS(end+1) = struct('tag', ['00200013'], 'type', ['1'], 'children', []);
%
% %Content Label
% tagS(end+1) = struct('tag', ['00700080'], 'type', ['1'], 'children', []);
%
% %Content Description
% tagS(end+1) = struct('tag', ['00700081'], 'type', ['2'], 'children', []);
%
% %Content Creator's Name
% tagS(end+1) = struct('tag', ['00700084'], 'type', ['2'], 'children', []);
%


function [inplane, isEmpty] = vol2ipCurROI(volume,inplane)
%
% [inplane, isEmpty] = vol2ipCurROI(volume,inplane)
%
% Calls vol2ipROI with the currently selected ROI.  Called from
% callback in xformInplaneMenu.
%
% Also returns isEmpty, a logical flag indicating whether the xformed
% ROI has coordinates within the inplanes or not.
%
% djh, 8/98
% djh, 2/2001, replaced globals with local variables
if ~volume.selectedROI
    myErrorDlg('Must have a selected ROI in the Volume window before it can be transformed to the Inplane window.');
end

volROI = volume.ROIs(volume.selectedROI);
ipROI = vol2ipROI(volROI,volume,inplane);

% if no coords exist in the inplanes, offer user the option of not xforming
% this ROI
if isempty(ipROI.coords)
    isEmpty = true;
    q = 'This ROI lies outside the inplane range. Xform empty ROI?';
    resp = questdlg(q, ipROI.name);
    if ~isequal(resp, 'Yes'); % cancel or close dialog
        fprintf('%s: user aborted. \n', mfilename);
        return
    end
else
    isEmpty = false;
end

inplane = addROI(inplane, ipROI, 1);

return


% params
totalNum = 1502861;
bValue = 2000;
lamda = 0.1;
qFile = '/home/yinhuan/Data/mapModel/park/weightVector.txt';
visFilesDir = '/home/yinhuan/Data/mapModel/park/visMatrix/';
maxQ = 110;
minQ = 1;

splitLength_0 = 100;
saveResultsDir_0 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/0/';
saveReIndexFile_0 = '/hozcme/yinhuan/Data/mapModel/park/iter_b_2000/index/0.txt';
saveNewQFile_0 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/weight/0.txt';

splitLength_1 = 200;
saveResultsDir_1 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/1/';
saveReIndexFile_1 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/index/1.txt';
saveNewQFile_1 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/weight/1.txt';

splitLength_2 = 400;
saveResultsDir_2 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/2/';
saveReIndexFile_2 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/index/2.txt';
saveNewQFile_2 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/weight/2.txt';

splitLength_3 = 800;
saveResultsDir_3 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/3/';
saveReIndexFile_3 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/index/3.txt';
saveNewQFile_3 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/weight/3.txt';

splitLength_4 = 800;
saveResultsDir_4 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/4/';
saveReIndexFile_4 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/index/4.txt';
saveNewQFile_4 = '/home/yinhuan/Data/mapModel/park/iter_b_2000/weight/4.txt';

%% iteration of optimization

visCells_origin = fromVisDirToCells(visFilesDir);

[ epsilon_soft_0, time_sum_0  ] = Uniform_loopCompress_Cells( lamda, qFile, visCells_origin, splitLength_0, totalNum, bValue, saveResultsDir_0 );
min_cost_0 = get_min_cost(minQ, maxQ, saveResultsDir_0, qFile, lamda, epsilon_soft_0);
[totalNum_0, visCells_0] = deleteZeroPoints_Cells( qFile, visCells_origin, saveResultsDir_0, saveReIndexFile_0, saveNewQFile_0 );

[ epsilon_soft_1, time_sum_1  ] = Uniform_loopCompress_Cells( lamda, saveNewQFile_0, visCells_0, splitLength_1, totalNum_0, bValue, saveResultsDir_1 );
min_cost_1 = get_min_cost(minQ, maxQ, saveResultsDir_1, saveNewQFile_0, lamda, epsilon_soft_1);
[totalNum_1, visCells_1] = deleteZeroPoints_Cells( saveNewQFile_0, visCells_0, saveResultsDir_1, saveReIndexFile_1, saveNewQFile_1 );

[ epsilon_soft_2, time_sum_2  ] = Uniform_loopCompress_Cells( lamda, saveNewQFile_1, visCells_1, splitLength_2, totalNum_1, bValue, saveResultsDir_2 );
min_cost_2 = get_min_cost(minQ, maxQ, saveResultsDir_2, saveNewQFile_1, lamda, epsilon_soft_2);
[totalNum_2, visCells_2] = deleteZeroPoints_Cells( saveNewQFile_1, visCells_1, saveResultsDir_2, saveReIndexFile_2, saveNewQFile_2 );

[ epsilon_soft_3, time_sum_3  ] = Uniform_loopCompress_Cells( lamda, saveNewQFile_2, visCells_2, splitLength_3, totalNum_2, bValue, saveResultsDir_3 );
min_cost_3 = get_min_cost(minQ, maxQ, saveResultsDir_3, saveNewQFile_2, lamda, epsilon_soft_3);
[totalNum_3, visCells_3] = deleteZeroPoints_Cells( saveNewQFile_2, visCells_2, saveResultsDir_3, saveReIndexFile_3, saveNewQFile_3 );

[ epsilon_soft_4, time_sum_4  ] = Uniform_loopCompress_Cells( lamda, saveNewQFile_3, visCells_3, splitLength_4, totalNum_3, bValue, saveResultsDir_4 );
min_cost_4 = get_min_cost(minQ, maxQ, saveResultsDir_4, saveNewQFile_3, lamda, epsilon_soft_4);
[totalNum_4, visCells_4] = deleteZeroPoints_Cells( saveNewQFile_3, visCells_3, saveResultsDir_4, saveReIndexFile_4, saveNewQFile_4 );

%% save the results

compressIndex_3 = anal_reindex_last(saveResultsDir_4, saveReIndexFile_3);
compressIndex_2 = anal_reindex_middle(compressIndex_3, saveReIndexFile_2);
compressIndex_1 = anal_reindex_middle(compressIndex_2, saveReIndexFile_1);
compressIndex_0 = anal_reindex_middle(compressIndex_1, saveReIndexFile_0);

dlmwrite('/home/yinhuan/Data/mapModel/park/iter_b_2000/compressIndex_final.txt', compressIndex_0, 'precision', '%d');


function entry = findindict(c,dcode)
% Look up an entry in the dictionary
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id$

entry = [];
d = getdict;
d = d.(dcode);
if ischar(c)
    for i=1:length(d),
        if strcmpi(d(i).label,c),
            entry = d(i);
            break;
        end;
    end;
elseif isnumeric(c) && numel(c)==1
    for i=1:length(d),
        if d(i).code==c,
            entry = d(i);
            break;
        end;
    end;
else
    error(['Inappropriate code for ' dcode '.']);
end;
if isempty(entry)
    fprintf('\nThis is not an option.  Try one of these:\n');
    for i=1:length(d)
        fprintf('%5d) %s\n', d(i).code, d(i).label);
    end;
    %fprintf('\nNO CHANGES MADE\n');
end;


function svgLuminanceToAlpha(s, source, result)
% Adds a feColorMatrix SVG filter that maps luminance to alpha values
% PRELIMINARY IMPLEMENTATION (Parameters may change)
%
% svgLuminanceToAlpha(s, source, result)
% Parameters:
%   s : Array of plot object handles
%   source : Any previous defined filter result string, 'SourceGraphic',
%            or 'SourceAlpha'.
%   result : String that identifies the filter result for following filter
%            stages.
for i = 1:length(s)
    userdata = get(s(i),'UserData');
    if isfield(userdata, 'svg') && isfield(userdata.svg, 'Filter')
        next = length(userdata.svg.Filter) + 1;
    else
        next = 1;
    end
    userdata.svg.Filter(next).Subfilter.Type = 'feColorMatrix';
    userdata.svg.Filter(next).Subfilter.Source = source;
    userdata.svg.Filter(next).Subfilter.Result = result;
    userdata.svg.Filter(next).Subfilter.ColorType = 'luminanceToAlpha';
    set(s(i),'UserData', userdata);
end