Skip to content

Commit 26cd875

Browse files
authored
Merge pull request #104 from marcobarilari/marco_add-update-filter-func
add option to save a tsv filtered event file
2 parents faf45ad + b0db59c commit 26cd875

File tree

7 files changed

+187
-25
lines changed

7 files changed

+187
-25
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
# exclude content of logfiles folders
99
*output*
10-
*.tsv
1110
*.mat
1211

1312
# exclude temp files from tests and coverage
1413
*test_code_report.txt
1514
*coverage*
1615

16+
*filteredBy*
17+
1718
tests/*.nii*
1819
tests/*.json*
1920
tests/*.tsv*

src/readAndFilterLogfile.m

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
% (C) Copyright 2020 CPP_BIDS developers
2+
3+
function outputFiltered = readAndFilterLogfile(columnName, filterBy, saveOutputTsv, varargin)
4+
% outputFiltered = readAndFilterLogfile(columnName, filterBy, saveOutputTsv, varargin)
5+
%
6+
% It will display in the command window the content of the `output.tsv' filtered by one element
7+
% of a target column.
8+
%
9+
% INPUT:
10+
%
11+
% - columnName: string, the header of the column where the content of insterest is stored
12+
% (e.g., for 'trigger' will be 'trial type')
13+
% - filterBy: string, the content of the column you want to filter out. It can take just
14+
% part of the content name (e.g., you want to display the triggers and you have
15+
% 'trigger_motion' and 'trigger_static', 'trigger' as input will do)
16+
% - saveOutputTsv: boolean to save the filtered ouput
17+
% - varargin: either cfg (to display the last run output) or the file path as string
18+
%
19+
% OUTPUT:
20+
%
21+
% - outputFiltered: dataset with only the specified content, to see it in the command window
22+
% use display(outputFiltered)
23+
24+
% Create tag to add to output file in case you want to save it
25+
outputFilterTag = ['_filteredBy-' columnName '_' filterBy '.tsv'];
26+
27+
% Checke if input is cfg or the file path and assign the output filename for later saving
28+
if ischar(varargin{1})
29+
30+
tsvFile = varargin{1};
31+
32+
elseif isstruct(varargin{1})
33+
34+
tsvFile = fullfile(varargin{1}.dir.outputSubject, ...
35+
varargin{1}.fileName.modality, ...
36+
varargin{1}.fileName.events);
37+
38+
end
39+
40+
% Create output file name
41+
outputFileName = strrep(tsvFile, '.tsv', outputFilterTag);
42+
43+
% Check if the file exists
44+
if ~exist(tsvFile, 'file')
45+
error([newline 'Input file does not exist: %s'], tsvFile);
46+
end
47+
48+
try
49+
% Read the the tsv file and store each column in a field of `output` structure
50+
output = bids.util.tsvread(tsvFile);
51+
catch
52+
% Add the 'bids-matlab' in case is not in the path
53+
addpath(genpath(fullfile(pwd, '..', 'lib')));
54+
% Read the the tsv file and store each column in a field of `output` structure
55+
output = bids.util.tsvread(tsvFile);
56+
end
57+
58+
% Get the index of the target contentent to filter and display
59+
filterIdx = strncmp(output.(columnName), filterBy, length(filterBy));
60+
61+
% apply the filter
62+
listFields = fieldnames(output);
63+
for iField = 1:numel(listFields)
64+
output.(listFields{iField})(~filterIdx) = [];
65+
end
66+
67+
% Convert the structure to dataset
68+
try
69+
outputFiltered = struct2dataset(output);
70+
catch
71+
% dataset not yet supported by octave
72+
outputFiltered = output;
73+
end
74+
75+
if saveOutputTsv
76+
77+
bids.util.tsvwrite(outputFileName, output);
78+
79+
end
80+
81+
end

src/subfun/utilsForTests/setUp.m

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
% (C) Copyright 2020 CPP_BIDS developers
2+
3+
function [cfg, logFile] = setUp()
4+
5+
outputDir = fullfile(fileparts(mfilename('fullpath')), 'output');
6+
7+
cfg.verbose = true;
8+
9+
cfg.subject.subjectNb = 1;
10+
cfg.subject.runNb = 1;
11+
12+
cfg.task.name = 'testtask';
13+
14+
cfg.dir.output = outputDir;
15+
16+
cfg.testingDevice = 'mri';
17+
18+
cfg = createFilename(cfg);
19+
20+
logFile.extraColumns.Speed.length = 1;
21+
logFile.extraColumns.LHL24.length = 12;
22+
logFile.extraColumns.is_Fixation.length = 1;
23+
24+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
onset duration trial_type
2+
2 15 VisMot
3+
25 15 VisStat

tests/test_readAndFilterLogfile.m

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
function test_suite = test_readAndFilterLogfile %#ok<*STOUT>
2+
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
3+
test_functions = localfunctions(); %#ok<*NASGU>
4+
catch % no problem; early Matlab versions can use initTestSuite fine
5+
end
6+
initTestSuite;
7+
end
8+
9+
function test_readAndFilterLogfileBasic()
10+
11+
%% set up
12+
13+
[cfg, logFile] = setUp();
14+
15+
% create the events file and header
16+
logFile = saveEventsFile('open', cfg, logFile);
17+
18+
% ROW 2: normal events : all info is there
19+
logFile(1, 1).onset = 2;
20+
logFile(end, 1).trial_type = 'motion_up';
21+
logFile(end, 1).duration = 3;
22+
logFile(end, 1).Speed = 2;
23+
logFile(end, 1).is_Fixation = true;
24+
logFile(end, 1).LHL24 = 1:12;
25+
26+
logFile(2, 1).onset = 2;
27+
logFile(end, 1).trial_type = 'motion_down';
28+
logFile(end, 1).duration = 3;
29+
logFile(end, 1).Speed = 2;
30+
logFile(end, 1).is_Fixation = true;
31+
logFile(end, 1).LHL24 = 2:13;
32+
33+
logFile = saveEventsFile('save', cfg, logFile);
34+
35+
% close the file
36+
saveEventsFile('close', cfg, logFile);
37+
38+
% filter file
39+
outputFiltered = readAndFilterLogfile('trial_type', 'motion_down', true, cfg);
40+
41+
%% test
42+
expectedFilename = strrep(cfg.fileName.events, '.tsv', ...
43+
['_filteredBy-' 'trial_type' '_' 'motion_down' '.tsv']);
44+
expectedFile = fullfile(cfg.dir.outputSubject, ...
45+
cfg.fileName.modality, ...
46+
expectedFilename);
47+
48+
assertEqual(exist(expectedFile, 'file'), 2);
49+
50+
content = bids.util.tsvread(expectedFile);
51+
52+
assertEqual(content.trial_type{1}, 'motion_down');
53+
54+
end
55+
56+
function test_readAndFilterLogfileFromFile()
57+
58+
%% set up
59+
60+
inputFile = fullfile(fileparts(mfilename('fullpath')), 'dummyData', ...
61+
'sub-blind01_ses-01_task-vislocalizer_events.tsv');
62+
63+
% filter file
64+
outputFiltered = readAndFilterLogfile('trial_type', 'VisStat', true, inputFile);
65+
66+
%% test
67+
expectedFile = strrep(inputFile, '.tsv', ...
68+
['_filteredBy-' 'trial_type' '_' 'VisStat' '.tsv']);
69+
70+
assertEqual(exist(expectedFile, 'file'), 2);
71+
72+
content = bids.util.tsvread(expectedFile);
73+
74+
assertEqual(content.trial_type{1}, 'VisStat');
75+
76+
end

tests/test_saveEventsFileSave.m

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -207,29 +207,6 @@ function test_saveEventsFileSaveErrors()
207207

208208
end
209209

210-
function [cfg, logFile] = setUp()
211-
212-
outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output');
213-
214-
cfg.verbose = true;
215-
216-
cfg.subject.subjectNb = 1;
217-
cfg.subject.runNb = 1;
218-
219-
cfg.task.name = 'testtask';
220-
221-
cfg.dir.output = outputDir;
222-
223-
cfg.testingDevice = 'mri';
224-
225-
cfg = createFilename(cfg);
226-
227-
logFile.extraColumns.Speed.length = 1;
228-
logFile.extraColumns.LHL24.length = 12;
229-
logFile.extraColumns.is_Fixation.length = 1;
230-
231-
end
232-
233210
function content = getFileContent(cfg, logFile)
234211

235212
% check the extra columns of the header and some of the content

0 commit comments

Comments
 (0)