Skip to content

[ENH] use bids matlab transformer to filter TSV #204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ repos:
additional_dependencies: [miss_hit]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
Expand Down
2 changes: 1 addition & 1 deletion lib/bids-matlab
Submodule bids-matlab updated 231 files
65 changes: 46 additions & 19 deletions src/readAndFilterLogfile.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@
% outputFiltered = readAndFilterLogfile(columnName, filterBy, saveOutputTsv, cfg)
%
% :param columnName: the header of the column where the content of interest is stored
% (for example for ``trigger`` will be ``trial type``)
% :type columnName: string
% :param filterBy: the content of the column you want to filter out. It can take just
% part of the content name (for example, if you want to display the triggers
% and you have ``trigger_motion`` and ``trigger_static``,
% ``trigger`` as input will do)
% :type filterBy: string
% (for example for ``trigger`` will be ``trial_type``)
% :type columnName: char
%
% :param filterBy: The content of the column you want to filter out.
% Relies on the ``filter`` transformer of bids.matlab
% Supports:
%
% - ``>``, ``<``, ``>=``, ``<=``, ``==`` for numeric values
% - ``==`` for string operation (case sensitive)
%
% For example, ``trial_type==trigger`` or `onset > 1`.
% :type filterBy: char
%
% :param saveOutputTsv: flag to save the filtered output in a tsv file
% :type saveOutputTsv: boolean
%
% :param tsvFile: TSV file to filter
% :type tsvFile: string
%
% :param cfg: Configuration. See ``checkCFG()``. If ``cfg`` is given as input the name
% of the TSV file to read will be infered from there.
% :type cfg: structure
Expand All @@ -30,12 +38,13 @@
% :outputFiltered: dataset with only the specified content, to see it
% in the command window use ``display(outputFiltered)``.
%
%
% See also: bids.transformers.filter
%
%
% (C) Copyright 2020 CPP_BIDS developers

% Create tag to add to output file in case you want to save it
outputFilterTag = ['_filteredBy-' columnName '_' filterBy '.tsv'];

% Checke if input is cfg or the file path and assign the output filename for later saving
% Check if input is cfg or the file path and assign the output filename for later saving
if ischar(varargin{1})

tsvFile = varargin{1};
Expand All @@ -48,9 +57,6 @@

end

% Create output file name
outputFileName = strrep(tsvFile, '.tsv', outputFilterTag);

% Check if the file exists
if ~exist(tsvFile, 'file')
error([newline 'Input file does not exist: %s'], tsvFile);
Expand All @@ -66,19 +72,40 @@
output = bids.util.tsvread(tsvFile);
end

% Get the index of the target contentent to filter and display
filterIdx = strncmp(output.(columnName), filterBy, length(filterBy));
transformers{1} = struct('Name', 'Filter', ...
'Input', columnName, ...
'Query', filterBy);

output = bids.transformers(transformers, output);

% apply the filter
% remove nans
if isnumeric(output.(columnName))
rowsToRemove = isnan(output.(columnName));
elseif iscell(output.(columnName))
rowsToRemove = cellfun(@(x) numel(x) == 1 && isnan(x), ...
output.(columnName));
end
listFields = fieldnames(output);
for iField = 1:numel(listFields)
output.(listFields{iField})(~filterIdx) = [];
output.(listFields{iField})(rowsToRemove) = [];
end

outputFiltered = output;
% Convert the structure to dataset
try
outputFiltered = struct2dataset(output);
catch
% dataset not yet supported by octave
outputFiltered = output;
end

if saveOutputTsv

% Create tag to add to output file in case you want to save it
outputFilterTag = ['_filteredOn-' columnName '.tsv'];

% Create output file name
outputFileName = strrep(tsvFile, '.tsv', outputFilterTag);

bids.util.tsvwrite(outputFileName, output);

end
Expand Down
16 changes: 10 additions & 6 deletions tests/test_readAndFilterLogfile.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
initTestSuite;
end

function test_readAndFilterLogfileBasic()
function test_readAndFilterLogfile_basic()

%% set up
[cfg, logFile] = setUp();
Expand Down Expand Up @@ -52,11 +52,11 @@ function test_readAndFilterLogfileBasic()
saveEventsFile('close', cfg, logFile);

% filter file
outputFiltered = readAndFilterLogfile('trial_type', 'motion_down', true, cfg);
readAndFilterLogfile('trial_type', 'trial_type==motion_down', true, cfg);

%% test
expectedFilename = strrep(cfg.fileName.events, '.tsv', ...
['_filteredBy-' 'trial_type' '_' 'motion_down' '.tsv']);
'_filteredOn-trial_type.tsv');
expectedFile = fullfile(cfg.dir.outputSubject, ...
cfg.fileName.modality, ...
expectedFilename);
Expand All @@ -70,26 +70,30 @@ function test_readAndFilterLogfileBasic()
assertEqual(content.trial_type{1}, 'motion_down');
assertEqual(content.trial_type{2}, 'motion_down');

delete(expectedFile);

end

function test_readAndFilterLogfileFromFile()
function test_readAndFilterLogfile_from_file()

%% set up

inputFile = fullfile(fileparts(mfilename('fullpath')), 'testData', ...
'sub-blind01_ses-01_task-vislocalizer_events.tsv');

% filter file
outputFiltered = readAndFilterLogfile('trial_type', 'VisStat', true, inputFile);
readAndFilterLogfile('trial_type', 'trial_type==VisStat', true, inputFile);

%% test
expectedFile = strrep(inputFile, '.tsv', ...
['_filteredBy-' 'trial_type' '_' 'VisStat' '.tsv']);
'_filteredOn-trial_type.tsv');

assertEqual(exist(expectedFile, 'file'), 2);

content = bids.util.tsvread(expectedFile);

assertEqual(content.trial_type{1}, 'VisStat');

delete(expectedFile);

end
20 changes: 20 additions & 0 deletions tests/utils/isOctave.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function retval = isOctave()
%
% Returns true if the environment is Octave.
%
% USAGE::
%
% retval = isOctave()
%
% :returns: :retval: (boolean)
%
% (C) Copyright 2022 CPP_BIDS developers

persistent cacheval % speeds up repeated calls

if isempty (cacheval)
cacheval = (exist ('OCTAVE_VERSION', 'builtin') > 0);
end

retval = cacheval;
end