123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- %% LaBGAScore_prep_s1_write_events_tsv
- %
- % This script reads logfiles, extracts the onsets, durations, and ratings for
- % different conditions, and writes events.tsv files to the BIDS dir for
- % each subject
- % It also contains an option to write a single phenotype file with
- % trial-by-trial ratings for all subjects
- %
- % USAGE
- %
- % Script should be run from the root directory of the superdataset, e.g.
- % /data/proj_discoverie
- % The script is highly study-specific, as logfiles will vary with design,
- % stimulus presentation software used, etc
- % Hence, it is provided in LaBGAScore as an example and needs to be
- % downloaded and adapted to the code subdataset for your study/project
- % This example is from LaBGAS proj_erythritol_4a
- % (https://gin.g-node.org/labgas/proj_erythritol_4a)
- %
- %
- % DEPENDENCIES
- %
- % LaBGAScore Github repo on Matlab path, with subfolders
- % https://github.com/labgas/LaBGAScore
- %
- %
- % INPUTS
- %
- % Presentation .log files in sourcedata dir for each subject
- %
- %
- % OUTPUTS
- %
- % events.tsv files for each run in BIDS dir for each subject
- % phenotype.tsv file in BIDS/phenotype dir (optional)
- %
- %__________________________________________________________________________
- %
- % author: Lukas Van Oudenhove
- % date: December, 2021
- %
- %__________________________________________________________________________
- % @(#)% LaBGAScore_prep_s1_write_events_tsv.m v1.3
- % last modified: 2023/01/05
- %% DEFINE DIRECTORIES, SUBJECTS, RUNS, CONDITIONS, AND IMPORT OPTIONS
- %--------------------------------------------------------------------------
- emosex_prep_s0_define_directories; % lukasvo edited from original LaBGAScore script to enable standalone functioning of proj_ery_4a dataset
- subjs2write = {'sub-03518','sub-03618','sub-03719','sub-03819','sub-03920','sub-04020','sub-04121','sub-04221','sub-04322','sub-04422','sub-04523','sub-04623','sub-04724','sub-04824','sub-04925','sub-05025','sub-05528','sub-05628','sub-05729','sub-05829','sub-06332','sub-06432','sub-06533','sub-06633'}; % enter subjects separated by comma if you only want to write files for selected subjects e.g. {'sub-01','sub-02'}
- pheno_tsv = false; % turn to false if you do not wish to generate a phenotype.tsv file with trial-by-trial ratings; will only work if subjs2write is empty (i.e. when you loop over all your subjects)
- pheno_name = 'ratings_online.tsv';
- runnames = {'run-1'};
- logfilenames = {'*.log',};
- taskname = 'emosex_movies_';
- stimuli_labels = ["Neutral_clip: movie = 'Neu1.mov'"; "Neutral_clip: movie = 'Neu2.mov'"; "Neutral_clip: movie = 'Neu3.mov'"; "Affect_clip: movie = 'Sex.mov'"; "Affect_clip: movie = 'Pos.mov'"; "Affect_clip: movie = 'Neg.mov'"];% labels for sweet substance delivery in Code var of logfile
- stimuli_labels = cellstr(stimuli_labels)'; %Need these steps to deal with the quotation marks in the stimuli_labels
- rating_label_pre = {'Q_affect: autoDraw = True'};
- rating_labels_post = {'Q_post_neu_rating: autoDraw = True', 'Q_post_affect_rating: autoDraw = True'}; %labels for start of rating period in Code var of logfile
- rest_label = {'Rest: autoDraw = True'}; %label for start of resting period
- endmovie_labels = { 'Sound stopped'}%labels for fixation cross in Code var of logfile
- %keypress_label = {'Keypress: 5'}; %additional label to distinguish between different sound stops (endmovie_labels)
- keypress_label = {'Imported Questions_Retrospectief.xlsx as conditions, 15 conditions, 1 params'};
- blocks_interest = {'neutral', 'neutral', 'neutral', 'sex', 'positive', 'negative'} %names of events of interest to be written to event.tsv
- blocks_noninterest = {'pre_rating', 'post_rating', 'rest'};
- endmovie_type = {'endmovie'};
- score_types = {'score_post_neu', 'score_post_aff', 'score_pre_neu'};
- varNames = {'Time', 'Warning', 'Action'}; %varnames of logfile
- varTypes = {'double', 'categorical', 'categorical'}; %matlab vartypes to be used when importing log file as table
- delimiter = '\t';
- opts = delimitedTextImportOptions('VariableNames', varNames, ...
- 'VariableTypes', varTypes,...
- 'Delimiter', delimiter);
-
- %% LOOP OVER SUBJECTS TO READ LOGFILES, CREATE TABLE WITH ONSETS AND DURATIONS, AND SAVE AS EVENTS.TSV TO BIDSSUBJDIRS
- %-------------------------------------------------------------------------------------------------------------------
- if ~isempty(subjs2write)
- [C,ia,~] = intersect(sourcesubjs,subjs2write);
-
- if ~isequal(C',subjs2write)
- error('\nsubject %s present in subjs2write not present in %s, please check before proceeding',subjs2write{~ismember(subjs2write,C)},derivdir);
-
- else
-
- for sub = ia'
-
- % DEFINE SUBJECT LEVEL DIRS
- subjsourcedir = sourcesubjdirs{sub};
- subjBIDSdir = fullfile(BIDSsubjdirs{sub},'func');
- % LOOP OVER RUNS
- for run = 1:size(logfilenames,2)
-
- logfilename = dir(fullfile(subjsourcedir,'logfiles',logfilenames{run}));
- logfilename = char(logfilename(:).name);
- logfilepath = fullfile(subjsourcedir,'logfiles',logfilename);
-
- if ~isfile(logfilepath)
- warning('\nlogfile missing for run %d in %s, please check before proceeding',run,logfilepath);
- continue
-
- elseif size(logfilepath,1) > 1
- error('\nmore than one logfile with run index %s for %s, please check before proceeding',run,sourcesubjs{sub})
-
- else
- log = readtable(logfilepath,opts);
- %log = log(~isnan(log.Action),:);
- time_zero = log.Time(log.Action == "Intro_text: autoDraw = False"); % time for onsets and durations is counted from the first scanner pulse onwards
-
- % if size(time_zero,1) > 1
- % error('\nambiguity about time zero in %s%s, please check logfile',subjs{sub},logfilenames{run});
- % end
-
- log.TimeZero = log.Time - time_zero;
- log.onset = log.TimeZero;
- %log(log.EventType == 'Pulse',:) = [];
- log.trial_type = cell(height(log),1);
-
- for k = 1:height(log)
- if ismember(log.Action(k),rating_label_pre)
- log.trial_type{k} = blocks_noninterest{1};
-
- elseif ismember(log.Action(k),rating_labels_post)
- log.trial_type{k} = blocks_noninterest{2};
- log.onset(k) = log.onset(k)+4;
-
- elseif ismember(log.Action(k),rest_label)
- log.trial_type{k} = blocks_noninterest{3};
- log.onset(k) = log.onset(k)+4;
-
- elseif ismember(log.Action(k),stimuli_labels)
- idx = (log.Action(k) == stimuli_labels);
- log.trial_type{k} = blocks_interest{idx'};
-
- elseif ismember(log.Action(k),endmovie_labels) && k>2 && ismember(log.Action(k+1),keypress_label) %log.Action(k-1) when using keypresslabel Keypress: 5
- log.trial_type{k} = endmovie_type{1};
-
- else
- log.trial_type{k} = '';
-
- end
- end
-
- log.rating = zeros(height(log),1);
-
- for l = 1:height(log)
-
- if contains(char(log.Action(l)),'Q_post_neu_ratings: (key response) rating=','IgnoreCase',true)
- scorestring = char(log.Action(l));
- char_end = string(scorestring(end));
- log.rating(l) = str2double(char_end);
- log.trial_type{l} = score_types{1};
-
- elseif contains(char(log.Action(l)),'Q_post_neu_ratings: (mouse response) rating=','IgnoreCase',true)
- scorestring = char(log.Action(l));
- char_end = string(scorestring(end));
- log.rating(l) = str2double(char_end);
- log.trial_type{l} = score_types{1};
-
- elseif contains(char(log.Action(l)),'Q_post_affect_ratings: (key response) rating=','IgnoreCase',true)
- scorestring = char(log.Action(l));
- char_end = string(scorestring(end));
- log.rating(l) = str2double(char_end);
- log.trial_type{l} = score_types{2};
-
- elseif contains(char(log.Action(l)),'Q_affect_rating: (key response) rating=','IgnoreCase',true)
- scorestring = char(log.Action(l));
- char_end = string(scorestring(end));
- log.rating(l) = str2double(char_end);
- log.trial_type{l} = score_types{3};
-
- else
- log.rating(l) = NaN;
-
- end
- end
-
- log.trial_type = categorical(log.trial_type);
-
- log = log((~isundefined(log.trial_type) | ~isnan(log.rating)),:);
- copy_log = log;
-
- log.bedroefd = zeros(height(log),1);
- log.opgewekt = zeros(height(log),1);
- log.teneergeslagen = zeros(height(log),1);
- log.ontspannen = zeros(height(log),1);
- log.angstig = zeros(height(log),1);
- log.enthousiast = zeros(height(log),1);
- log.alert = zeros(height(log),1);
- log.vol_inspiratie = zeros(height(log),1);
- log.gespannen = zeros(height(log),1);
- log.tevreden = zeros(height(log),1);
- log.vastberaden = zeros(height(log),1);
- log.bang = zeros(height(log),1);
- log.seksueel_opgewonden = zeros(height(log),1);
- log.geil = zeros(height(log),1);
- log.seksueel_verlangen = zeros(height(log),1);
-
- for n = 31:height(log);
- for quest = 1:15; %number of questions is 15
- if quest == 1 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.bedroefd(n-1-2*quest,1) = log.rating(n);
- elseif quest == 2 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.opgewekt(n-1-2*quest,1) = log.rating(n);
- elseif quest == 3 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.teneergeslagen(n-1-2*quest,1) = log.rating(n);
- elseif quest == 4 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.ontspannen(n-1-2*quest,1) = log.rating(n);
- elseif quest == 5 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.angstig(n-1-2*quest,1) = log.rating(n);
- elseif quest == 6 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.enthousiast(n-1-2*quest,1) = log.rating(n);
- elseif quest == 7 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.alert(n-1-2*quest,1) = log.rating(n);
- elseif quest == 8 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.vol_inspiratie(n-1-2*quest,1) = log.rating(n);
- elseif quest == 9 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.gespannen(n-1-2*quest,1) = log.rating(n);
- elseif quest == 10 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.tevreden(n-1-2*quest,1) = log.rating(n);
- elseif quest == 11 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.vastberaden(n-1-2*quest,1) = log.rating(n);
- elseif quest == 12 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.bang(n-1-2*quest,1) = log.rating(n);
- elseif quest == 13 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.seksueel_opgewonden(n-1-2*quest,1) = log.rating(n);
- elseif quest == 14 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.geil(n-1-2*quest,1) = log.rating(n);
- elseif quest == 15 && ismember(log.trial_type(n-2*quest),endmovie_type) && (ismember(log.trial_type(n),score_types{1}) | ismember(log.trial_type(n),score_types{2}));
- log.seksueel_verlangen(n-1-2*quest,1) = log.rating(n);
- end
- end
- end
-
- copy_log.bedroefd = zeros(height(log),1);
- copy_log.opgewekt = zeros(height(log),1);
- copy_log.teneergeslagen = zeros(height(log),1);
- copy_log.ontspannen = zeros(height(log),1);
- copy_log.angstig = zeros(height(log),1);
- copy_log.enthousiast = zeros(height(log),1);
- copy_log.alert = zeros(height(log),1);
- copy_log.vol_inspiratie = zeros(height(log),1);
- copy_log.gespannen = zeros(height(log),1);
- copy_log.tevreden = zeros(height(log),1);
- copy_log.vastberaden = zeros(height(log),1);
- copy_log.bang = zeros(height(log),1);
- copy_log.seksueel_opgewonden = zeros(height(log),1);
- copy_log.geil = zeros(height(log),1);
- copy_log.seksueel_verlangen = zeros(height(log),1);
-
- for n = 1:height(log)-30;
- for quest = 1:15;
- if quest == 15 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.bedroefd(n-1+2*quest,1) = log.rating(n);
- elseif quest == 14 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.opgewekt(n-1+2*quest,1) = log.rating(n);
- elseif quest == 13 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.teneergeslagen(n-1+2*quest,1) = log.rating(n);
- elseif quest == 12 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.ontspannen(n-1+2*quest,1) = log.rating(n);
- elseif quest == 11 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.angstig(n-1+2*quest,1) = log.rating(n);
- elseif quest == 10 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.enthousiast(n-1+2*quest,1) = log.rating(n);
- elseif quest == 9 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.alert(n-1+2*quest,1) = log.rating(n);
- elseif quest == 8 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.vol_inspiratie(n-1+2*quest,1) = log.rating(n);
- elseif quest == 7 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.gespannen(n-1+2*quest,1) = log.rating(n);
- elseif quest == 6 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.tevreden(n-1+2*quest,1) = log.rating(n);
- elseif quest == 5 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.vastberaden(n-1+2*quest,1) = log.rating(n);
- elseif quest == 4 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.bang(n-1+2*quest,1) = log.rating(n);
- elseif quest == 3 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.seksueel_opgewonden(n-1+2*quest,1) = log.rating(n);
- elseif quest == 2 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.geil(n-1+2*quest,1) = log.rating(n);
- elseif quest == 1 && ismember(log.trial_type(n+2*quest),endmovie_type) && ismember(log.trial_type(n), score_types{3});
- copy_log.seksueel_verlangen(n-1+2*quest,1) = log.rating(n);
- end
- end
- end
-
-
-
-
- % for n = 1:height(log)
- %
- % if ismember(log.trial_type(n),events_interest)
- % log.rating(n) = log.rating(n+3);
- %
- % end
- %
- % end
-
- log = removevars(log,{'Time','Warning','Action','rating','TimeZero'}); % get rid of junk variables from logfile we don't need
- copy_log = removevars(copy_log,{'Time','Warning','Action','rating','TimeZero'});
- %log = log(~isundefined(log.trial_type),:);
-
- log.duration = zeros(height(log),1);
-
- for m = 1:height(log)-1;
-
- if ismember(log.trial_type(m+1),endmovie_type)
- log.duration(m) = log.onset(m+1) - log.onset(m);
-
- else
- log.duration(m) = NaN;
-
- end
- end
-
- copy_log.duration = zeros(height(log),1)
- for m2 = 1:height(copy_log)-1;
-
- if ismember(copy_log.trial_type(m2+1),endmovie_type)
- copy_log.duration(m2) = copy_log.onset(m2+1) - copy_log.onset(m2);
-
- else
- copy_log.duration(m2) = NaN;
-
- end
- end
-
- log = log(~ismember(log.trial_type, blocks_noninterest{3}),:); %remove rows which concern rest
- copy_log = copy_log(~ismember(copy_log.trial_type, blocks_noninterest{3}),:);
- log = log(~isnan(log.duration),:);
- copy_log = copy_log(~isnan(copy_log.duration),:);
- copy_log = copy_log(ismember(copy_log.trial_type, blocks_interest{1}),:);
-
- log = [log(:,2) log(:,1) log(:,18) log(:,3:17)];
- copy_log = [copy_log(:,2) copy_log(:,1) copy_log(:,18), copy_log(:,3:17)];
- filename = fullfile(subjBIDSdir,[sourcesubjs{sub},'_task-',taskname,runnames{run},'_events.tsv']);
- filename2 = fullfile(subjBIDSdir, [sourcesubjs{sub},'_task-', taskname,runnames{run},'_eventsnoninterest.tsv']);
- writetable(log,filename,'Filetype','text','Delimiter','\t');
- writetable(copy_log,filename2,'Filetype','text','Delimiter','\t');
- clear logfile log time_zero filename filename2
- end % if loop checking whether logfile exists
- end % for loop runs
-
- end % for loop subjects
-
- end % if loop checking subjs2write present in sourcesubjs
-
- else
-
- if ~isequal(sourcesubjs, BIDSsubjs)
- [D,~,~] = intersect(sourcesubjs,BIDSsubjs);
- error('\nsubject %s present in %s not present in %s, please check before proceeding',BIDSsubjs{~ismember(BIDSsubjs,D)},BIDSdir,derivdir);
-
- else
-
- if pheno_tsv
- pheno_file = table();
- pheno_dir = fullfile(BIDSdir,'phenotype');
- if ~isfolder(pheno_dir)
- mkdir(pheno_dir);
- end
- end
-
- for sub = 1:size(sourcesubjs,1)
-
- if pheno_tsv
- pheno_file_subj = table();
- end
- % DEFINE SUBJECT LEVEL DIRS
- subjsourcedir = sourcesubjdirs{sub};
- subjBIDSdir = fullfile(BIDSsubjdirs{sub},'func');
- % LOOP OVER RUNS
- for run = 1:size(logfilenames,2)
-
- logfilename = dir(fullfile(subjsourcedir,'logfiles',logfilenames{run}));
- logfilename = char(logfilename(:).name);
- logfilepath = fullfile(subjsourcedir,'logfiles',logfilename);
-
- if ~isfile(logfilepath)
- warning('\nlogfile missing for run %d in %s, please check before proceeding',run,logfilepath);
- continue
-
- elseif size(logfilepath,1) > 1
- error('\nmore than one logfile with run index %s for %s, please check before proceeding',run,sourcesubjs{sub})
-
- else
- log = readtable(logfilepath,opts);
- log = log(~isnan(log.Trial),:);
- time_zero = log.Time(log.Trial == 0 & log.EventType == 'Pulse'); % time for onsets and durations is counted from the first scanner pulse onwards
-
- if size(time_zero,1) > 1
- error('\nambiguity about time zero in %s%s, please check logfile',subjs{sub},logfilenames{run});
- end
-
- log.TimeZero = log.Time - time_zero;
- log.onset = log.TimeZero ./ 10000; % convert to seconds
- log(log.EventType == 'Pulse',:) = [];
- log.trial_type = cell(height(log),1);
-
- for k = 1:height(log)
-
- if ismember(log.Code(k),swallow_rinse_labels)
- log.trial_type{k} = events_nuisance{1};
-
- elseif ismember(log.Code(k),rating_labels)
- log.trial_type{k} = events_nuisance{2};
- log.onset(k) = log.onset(k)+4;
-
- elseif ismember(log.Code(k),sweet_labels)
- idx = (log.Code(k) == sweet_labels);
- log.trial_type{k} = events_interest{idx'};
-
- elseif ismember(log.Code(k),fixation_labels)
- log.trial_type{k} = 'fixation';
-
- else
- log.trial_type{k} = '';
-
- end
- end
-
- log.rating = zeros(height(log),1);
-
- for l = 1:height(log)
-
- if contains(char(log.Code(l)),'score','IgnoreCase',true)
- scorestring = char(log.Code(l));
-
- if strcmp(scorestring(1,end-3:end),'-100')
- log.rating(l) = str2double(scorestring(1,end-3:end));
-
- elseif ~contains(scorestring(1,end-2:end),':')
- log.rating(l) = str2double(strtrim(scorestring(1,end-2:end)));
-
- else
- log.rating(l) = str2double(scorestring(1,end));
-
- end
-
- else
- log.rating(l) = NaN;
-
- end
-
- end
-
- log.trial_type = categorical(log.trial_type);
-
- log = log((~isundefined(log.trial_type) | ~isnan(log.rating)),:);
-
- for n = 1:height(log)
-
- if ismember(log.trial_type(n),events_interest)
- log.rating(n) = log.rating(n+3);
-
- end
-
- end
-
- log = removevars(log,{'Trial','EventType','Code','Time','TTime','Duration','ReqTime','TimeZero'}); % get rid of junk variables from logfile we don't need
-
- log = log(~isundefined(log.trial_type),:);
-
- log.duration = zeros(height(log),1);
-
- for m = 1:height(log)
-
- if ~isequal(log.trial_type(m),'fixation')
- log.duration(m) = log.onset(m+1) - log.onset(m);
-
- else
- log.duration(m) = NaN;
-
- end
- end
-
- log = log(~isnan(log.duration),:);
-
- filename = fullfile(subjBIDSdir,[sourcesubjs{sub},'_task-',taskname,runnames{run},'_events.tsv']);
- writetable(log,filename,'Filetype','text','Delimiter','\t');
-
- if pheno_tsv
-
- log2 = log(~isnan(log.rating),:);
- log2 = removevars(log2,{'onset','duration'});
- for n = 1:height(log2)
- log2.participant_id(n,:) = BIDSsubjs{sub};
- log2.run_id(n) = run;
- log2.trial_id_run(n) = n; % generates consecutive trial numbers within each run
- log2.trial_id_concat(n) = height(pheno_file_subj) + n; % generates consecutive trial numbers over all conditions & runs
- end
-
- for o = 1:size(events_interest,2)
- idx_run = log2.trial_type == events_interest{o};
- log2.trial_id_cond_run(idx_run) = 1:sum(idx_run);
- if height(pheno_file_subj) > 0
- idx_sub = pheno_file_subj.trial_type == events_interest{o};
- log2.trial_id_cond_concat(idx_run) = sum(idx_sub)+1:(sum(idx_sub)+sum(idx_run));
- else
- log2.trial_id_cond_concat = log2.trial_id_cond_run;
- end
- clear idx_run idx_sub
- end
-
- pheno_file_subj = [pheno_file_subj;log2];
- end
-
- clear logfile log time_zero filename log2
- end % if loop checking whether logfile exists
- end % for loop runs
-
- pheno_file = [pheno_file;pheno_file_subj];
- clear pheno_file_subj;
- end % for loop subjects
-
- pheno_filename = fullfile(pheno_dir,pheno_name);
- writetable(pheno_file,pheno_filename,'Filetype','text','Delimiter','\t');
-
- end % if loop checking sourcesubjs == BIDSsubjs
-
- end % if loop checking writing option
|