Skip to content

Commit 3804278

Browse files
committed
initial commit
0 parents  commit 3804278

File tree

6 files changed

+435
-0
lines changed

6 files changed

+435
-0
lines changed

checkCFG.m

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
function expParameters = checkCFG(expParameters)
2+
% check that we have all the fields that we need in the experiment
3+
% parameters
4+
5+
if ~isfield(expParameters, 'outputDir')
6+
expParameters.outputDir = fullfile(...
7+
fileparts(mfilename('fullpath')), ...
8+
'..', ...
9+
'output');
10+
end
11+
12+
% set empty values for a series of field if they have not been specified
13+
fields2Check = { ...
14+
'ce', ...
15+
'dir', ... % For BIDS file naming: phase encoding direction of acquisition for fMRI
16+
'rec', ... % For BIDS file naming: reconstruction of fMRI images
17+
'echo', ... % For BIDS file naming: echo fMRI images
18+
'acq' % For BIDS file naming: acquisition of fMRI images
19+
};
20+
21+
for iField = 1:numel(fields2Check)
22+
if ~isfield(expParameters, fields2Check{iField})
23+
expParameters = setfield(expParameters, fields2Check{iField}, []); %#ok<SFLD>
24+
end
25+
end
26+
27+
28+
end

createFilename.m

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
function expParameters = createFilename(expParameters, cfg)
2+
% create the BIDS compliant directories and filenames for the behavioral output for this subject /
3+
% session / run.
4+
% Will also create the right filename for the eyetracking data file.
5+
%
6+
% For the moment the date of acquisition is appreneded to the filename
7+
%
8+
% can work for behavioral experiment if cfg.device is set to 'PC'
9+
% can work for fMRI experiment if cfg.device is set to 'scanner'
10+
% can work for simple eyetracking data if cfg.eyeTracker is set to 1
11+
%
12+
% BOLD
13+
% sub-<label>[_ses-<label>]_task-<label>[_acq-<label>][_ce-<label>][_dir-<label>][_rec-<label>][_run-<index>][_echo-<index>]_<contrast_label>.nii[.gz]
14+
%
15+
% iEEG
16+
% sub-<label>[_ses-<label>]_task-<task_label>[_run-<index>]_ieeg.json
17+
%
18+
% EEG
19+
% sub-<label>[_ses-<label>]_task-<label>[_run-<index>]_eeg.<manufacturer_specific_extension>
20+
%
21+
% EYETRACKER
22+
% sub-<participant_label>[_ses-<label>][_acq-<label>]_task-<task_label>_eyetrack.<manufacturer_specific_extension>
23+
24+
zeroPadding = 3;
25+
pattern = ['%0' num2str(zeroPadding) '.0f'];
26+
27+
dateFormat = 'yyyymmdd_HHMM';
28+
29+
30+
31+
% extract input
32+
subjectGrp = expParameters.subjectGrp;
33+
subjectNb = expParameters.subjectNb;
34+
sessionNb = expParameters.sessionNb;
35+
runNb = expParameters.runNb;
36+
37+
expParameters.date = datestr(now, dateFormat);
38+
39+
% output dir
40+
expParameters.outputDir = fullfile (...
41+
expParameters.outputDir, ...
42+
'source', ...
43+
['sub-' subjectGrp, sprintf(pattern, subjectNb)], ...
44+
['ses-', sprintf(pattern, sessionNb)]);
45+
46+
% create base filename
47+
expParameters.fileName.base = ...
48+
['sub-', subjectGrp, sprintf(pattern, subjectNb), ...
49+
'_ses-', sprintf(pattern, sessionNb) , ...
50+
'_task-', expParameters.task];
51+
52+
runSuffix = ['_run-' sprintf(pattern, runNb)];
53+
54+
55+
switch lower(cfg.device)
56+
case 'pc'
57+
modality = 'beh';
58+
case 'scanner'
59+
modality = 'func';
60+
otherwise
61+
modality = 'beh';
62+
end
63+
64+
expParameters.modality = modality;
65+
66+
67+
% set values for the suffixes for the different fields in the BIDS name
68+
fields2Check = { ...
69+
'ce', ...
70+
'dir', ... % For BIDS file naming: phase encoding direction of acquisition for fMRI
71+
'rec', ... % For BIDS file naming: reconstruction of fMRI images
72+
'echo', ... % For BIDS file naming: echo fMRI images
73+
'acq' % For BIDS file naming: acquisition of fMRI images
74+
};
75+
76+
for iField = 1:numel(fields2Check)
77+
if isempty (getfield(expParameters, fields2Check{iField}) ) %#ok<*GFLD>
78+
expParameters = setfield(expParameters, [fields2Check{iField} 'Suffix'], ...
79+
''); %#ok<*SFLD>
80+
else
81+
expParameters = setfield(expParameters, [fields2Check{iField} 'Suffix'], ...
82+
['_' fields2Check{iField} '-' getfield(expParameters, fields2Check{iField})]);
83+
end
84+
end
85+
86+
87+
%% create directories
88+
[~, ~, ~] = mkdir(expParameters.outputDir);
89+
[~, ~, ~] = mkdir(fullfile(expParameters.outputDir, modality));
90+
91+
if cfg.eyeTracker
92+
[~, ~, ~] = mkdir(fullfile(expParameters.outputDir, 'eyetracker'));
93+
end
94+
95+
96+
%% create filenames
97+
98+
switch modality
99+
100+
case 'beh'
101+
102+
expParameters.fileName.events = ...
103+
[expParameters.fileName.base, runSuffix, '_events_date-' expParameters.date '.tsv'];
104+
105+
case 'func'
106+
107+
expParameters.fileName.events = ...
108+
[expParameters.fileName.base, ...
109+
expParameters.acqSuffix, expParameters.ceSuffix, ...
110+
expParameters.dirSuffix, expParameters.recSuffix, ...
111+
runSuffix, expParameters.echoSuffix, ...
112+
'_events_date-' expParameters.date '.tsv'];
113+
114+
end
115+
116+
if cfg.eyeTracker
117+
118+
expParameters.fileName.eyetracker = ...
119+
[expParameters.fileName.base, expParameters.acqSuffix, ...
120+
runSuffix, '_eyetrack_date-' expParameters.date '.edf'];
121+
122+
end
123+
124+
125+
end

saveEventsFile.m

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
function [ logFile ] = saveEventsFile(input, expParameters, logFile, varargin)
2+
3+
if nargin<3 || isempty(logFile)
4+
logFile = struct();
5+
end
6+
7+
switch input
8+
9+
case 'open'
10+
11+
logFile = struct();
12+
13+
% Initialize txt logfiles and empty fields for the standard BIDS
14+
% event file
15+
logFile.eventLogFile = fopen(...
16+
fullfile(expParameters.outputDir, expParameters.modality, expParameters.fileName.events), ...
17+
'w');
18+
19+
% print the basic BIDS columns
20+
fprintf(logFile.eventLogFile, '%s\t%s\t%s\t', 'onset', 'trial_type', 'duration');
21+
22+
% print any extra column specified by the user
23+
% also prepare an empty field in the structure to collect data
24+
% for those
25+
for iExtraColumn = 1:numel(varargin)
26+
fprintf(logFile.eventLogFile,'%s\t', lower(varargin{iExtraColumn}));
27+
end
28+
29+
% next line so we start printing at the right place
30+
fprintf(logFile.eventLogFile, '\n');
31+
32+
33+
case 'save'
34+
35+
% appends to the logfile all the data stored in the structure
36+
% first with the standard BIDS data and then any extra things
37+
for iEvent = 1:size(logFile,1)
38+
39+
fprintf(logFile(1).eventLogFile,'%f\t%s\t%f\t',...
40+
logFile(iEvent).onset, ...
41+
logFile(iEvent).trial_type, ...
42+
logFile(iEvent).duration);
43+
44+
for iExtraColumn = 1:numel(varargin)
45+
46+
% if the field we are looking for does not exist or is empty in the
47+
% input logFile structure we will write a NaN otherwise we
48+
% write its content
49+
50+
if ~isfield(logFile, varargin{iExtraColumn})
51+
data = [];
52+
else
53+
data = getfield(logFile(iEvent), varargin{iExtraColumn});
54+
end
55+
56+
if isempty(data)
57+
data = NaN;
58+
end
59+
60+
if ischar(data)
61+
fprintf(logFile(1).eventLogFile, '%s\t', data);
62+
else
63+
fprintf(logFile(1).eventLogFile, '%f\t', data);
64+
end
65+
66+
end
67+
68+
fprintf(logFile(1).eventLogFile, '\n');
69+
end
70+
71+
case 'close'
72+
73+
% close txt log file
74+
fclose(logFile(1).eventLogFile);
75+
76+
end

test/test_createFilename.m

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
% test for filename creation and their directories
2+
3+
% add parent folder to the parth
4+
addpath(genpath(fullfile(fileparts(mfilename), '..')))
5+
6+
7+
%% check directory and filename creation (PC and eyetracker)
8+
9+
clear
10+
11+
expParameters.subjectGrp = '';
12+
expParameters.subjectNb = 1;
13+
expParameters.sessionNb = 1;
14+
expParameters.runNb = 1;
15+
expParameters.task = 'testtask';
16+
17+
cfg.eyeTracker = true;
18+
cfg.device = 'PC';
19+
20+
expParameters = checkCFG(expParameters);
21+
expParameters = createFilename(expParameters, cfg);
22+
23+
outputDir = fullfile(pwd, ...
24+
'..', '..', ...
25+
'output', 'source', 'sub-001', 'ses-001', 'beh');
26+
27+
eyetrackerDir = fullfile(pwd, ...
28+
'..', '..', ...
29+
'output', 'source', 'sub-001', 'ses-001', 'eyetracker');
30+
31+
32+
assert(exist(outputDir, 'dir')==7)
33+
assert(exist(eyetrackerDir, 'dir')==7)
34+
assert(strcmp(...
35+
expParameters.fileName.events, ...
36+
['sub-001_ses-001_task-testtask_run-001_events_date-' expParameters.date '.tsv']));
37+
assert(strcmp(...
38+
expParameters.fileName.eyetracker, ...
39+
['sub-001_ses-001_task-testtask_run-001_eyetrack_date-' expParameters.date '.edf']));
40+
41+
42+
%% check directory and filename creation (fMRI)
43+
44+
clear
45+
46+
expParameters.subjectGrp = 'ctrl';
47+
expParameters.subjectNb = 2;
48+
expParameters.sessionNb = 2;
49+
expParameters.runNb = 2;
50+
expParameters.task = 'testtask';
51+
52+
cfg.eyeTracker = false;
53+
cfg.device = 'scanner';
54+
55+
expParameters = checkCFG(expParameters);
56+
expParameters = createFilename(expParameters, cfg);
57+
58+
outputDir = fullfile(pwd, ...
59+
'..', '..', ...
60+
'output', 'source', 'sub-ctrl002', 'ses-002', 'func');
61+
62+
eyetrackerDir = fullfile(pwd, ...
63+
'..', '..', ...
64+
'output', 'source', 'sub-ctrl002', 'ses-002', 'eyetracker');
65+
66+
67+
assert(exist(outputDir, 'dir')==7)
68+
assert(strcmp(expParameters.fileName.base, 'sub-ctrl002_ses-002_task-testtask'))
69+
assert(strcmp(...
70+
expParameters.fileName.events, ...
71+
['sub-ctrl002_ses-002_task-testtask_run-002_events_date-' expParameters.date '.tsv']));
72+

test/test_saveEventsFile.m

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
% test for events.tsv file creation
2+
3+
% add parent folder to the parth
4+
addpath(genpath(fullfile(fileparts(mfilename), '..')))
5+
6+
7+
%% set up
8+
9+
clear
10+
11+
expParameters.subjectGrp = '';
12+
expParameters.subjectNb = 1;
13+
expParameters.sessionNb = 1;
14+
expParameters.runNb = 1;
15+
expParameters.task = 'testtask';
16+
17+
cfg.eyeTracker = false;
18+
cfg.device = 'scanner';
19+
20+
expParameters = checkCFG(expParameters);
21+
expParameters = createFilename(expParameters, cfg);
22+
23+
24+
25+
%% create the file
26+
27+
logFile = saveEventsFile('open', expParameters, [], 'Speed', 'is_Fixation');
28+
29+
30+
% ---- test section
31+
32+
fileName = fullfile(expParameters.outputDir, expParameters.modality, expParameters.fileName.events);
33+
34+
% check that the file has the right path and name
35+
assert(exist(fileName, 'file')==2)
36+
37+
38+
39+
%% write things in it
40+
41+
logFile(1).onset = 1;
42+
logFile(1).trial_type = 'motion_up';
43+
logFile(1).duration = 1;
44+
logFile(1).speed = [];
45+
logFile(1).is_fixation = 'true';
46+
47+
saveEventsFile('save', expParameters, logFile, 'speed', 'is_fixation');
48+
49+
50+
logFile(1,1).onset = 2;
51+
logFile(1,1).trial_type = 'motion_up';
52+
logFile(1,1).duration = 1;
53+
logFile(1,1).speed = 2;
54+
logFile(1,1).is_fixation = true;
55+
56+
logFile(2,1).onset = 3;
57+
logFile(2,1).trial_type = 'static';
58+
logFile(2,1).duration = 4;
59+
logFile(2,1).is_fixation = 3;
60+
61+
saveEventsFile('save', expParameters, logFile, 'speed', 'is_fixation');
62+
63+
64+
% close the file
65+
saveEventsFile('close', expParameters, logFile);
66+
67+
68+
% ---- test section
69+
70+
% check the extra columns of the header and some of the content
71+
72+
FID = fopen(fileName, 'r');
73+
C = textscan(FID,'%s%s%s%s%s','Delimiter', '\t', 'EndOfLine', '\n');
74+
75+
assert(isequal(C{4}{1}, 'speed')); % check header
76+
77+
assert(isequal(C{4}{2}, 'NaN')); % check that empty values are entered as NaN
78+
assert(isequal(C{4}{4}, 'NaN')); % check that missing fields are entered as NaN
79+
80+
assert(isequal(str2num(C{5}{4}), 3)); % check values entered properly

0 commit comments

Comments
 (0)