Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3778f0b
BIDS schema update
Remi-Gau Jan 15, 2021
a7ddab1
Merge pull request #110 from bids-standard/create-pull-request/patch
Remi-Gau Jan 15, 2021
dc1d4ed
BIDS schema update
Remi-Gau Feb 1, 2021
e616fa8
Merge pull request #119 from bids-standard/create-pull-request/patch
Remi-Gau Feb 1, 2021
7c76866
Merge branch 'master' into dev
Remi-Gau Feb 2, 2021
086acfd
BIDS schema update
Remi-Gau Feb 2, 2021
d3a8478
Merge pull request #120 from bids-standard/create-pull-request/patch
Remi-Gau Feb 2, 2021
456e851
create test for load_schema
Remi-Gau Jan 16, 2021
692f3df
add function to load schema
Remi-Gau Jan 16, 2021
2b599b3
-fix conflict
Remi-Gau Feb 4, 2021
a12798a
update load_schema test
Remi-Gau Jan 16, 2021
1cf5609
add functions to deal with schema extensions, suffixes and entities
Remi-Gau Jan 16, 2021
cd750fd
add function to return regular expression for a certain data type
Remi-Gau Jan 16, 2021
a49a4b3
update return_datatype_entities to new schema structure
Remi-Gau Feb 4, 2021
bdc7742
move schema functions
Remi-Gau Feb 4, 2021
1c3772a
update tests to moxunit format
Remi-Gau Feb 4, 2021
7c449eb
add test for parse_filename
Remi-Gau Feb 4, 2021
aea6e00
use schema to parse anat
Remi-Gau Feb 4, 2021
5829f81
linting, cleaning, use valid bids example for parse_filename
Remi-Gau Feb 4, 2021
b2980ec
use schema to parse behavioral and refactor
Remi-Gau Feb 4, 2021
a3b895d
parse ASL with schema
Remi-Gau Feb 4, 2021
39e51fb
parse dwi using schema
Remi-Gau Feb 4, 2021
4cd7599
linting
Remi-Gau Feb 4, 2021
6c4e932
parse func with schema
Remi-Gau Feb 4, 2021
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
62 changes: 62 additions & 0 deletions +bids/+internal/append_to_structure.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function subject = append_to_structure(file, subject, modality)
% Copyright (C) 2021--, BIDS-MATLAB developers

p = bids.internal.parse_filename(file);
idx = find_suffix_group(modality, p.type);
if isempty(idx)
warning('append_to_structure:noMatchingSuffix', ...
'Skipping file with no valid suffix in schema: %s', file);
return
end

schema = bids.schema.load_schema();
entities = bids.schema.return_datatype_entities(schema.datatypes.(modality)(idx));
p = bids.internal.parse_filename(file, entities);

if ~isempty(subject.(modality))

missing_fields = setxor(fieldnames(subject.(modality)), fieldnames(p));

if ~isempty(missing_fields)
for iField = 1:numel(missing_fields)
p = add_missing_field(p, ...
missing_fields{iField});
subject.(modality) = add_missing_field(subject.(modality), ...
missing_fields{iField});
end
end

end

subject.(modality) = [subject.(modality) p];

end

function structure = add_missing_field(structure, field)
if ~isfield(structure, field)
structure(1).(field) = '';
end
end

function idx = find_suffix_group(modality, suffix)

idx = [];

schema = bids.schema.load_schema();
suffix_groups = {schema.datatypes.(modality).suffixes}';

% the following loop could probably be improved with some cellfun magic
% cellfun(@(x, y) any(strcmp(x,y)), {p.type}, suffix_groups)
for i = 1:numel(suffix_groups)
if any(strcmp(suffix, suffix_groups{i}))
idx = i;
break
end
end

if isempty(idx)
warning('findSuffix:noMatchingSuffix', ...
'No corresponding suffix in schema for %s for datatype %s', suffix, modality);
end

end
11 changes: 6 additions & 5 deletions +bids/+internal/parse_filename.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
%
% Example:
%
% >> filename = '../sub-16/anat/sub-16_ses-mri_run-1_echo-2_FLASH.nii.gz';
% >> filename = '../sub-16/anat/sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz';
% >> bids.internal.parse_filename(filename)
%
% ans =
%
% struct with fields:
%
% filename: 'sub-16_ses-mri_run-1_echo-2_FLASH.nii.gz'
% type: 'FLASH'
% filename: 'sub-16_ses-mri_run-1_acq-hd_T1w.nii.gz'
% type: 'T1w'
% ext: '.nii.gz'
% sub: '16'
% ses: 'mri'
% run: '1'
% echo: '2'
% acq: 'hd'
% __________________________________________________________________________

% Copyright (C) 2016-2018, Guillaume Flandin, Wellcome Centre for Human Neuroimaging
Expand Down Expand Up @@ -50,7 +50,8 @@
try
p = orderfields(p, ['filename', 'ext', 'type', fields]);
catch
warning('Ignoring file ''%s'' not matching template.', filename);
warning('bidsMatlab:noMatchingTemplate', ...
'Ignoring file %s not matching template.', filename);
p = struct([]);
end
end
14 changes: 14 additions & 0 deletions +bids/+internal/return_datatype_extensions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function extensions = return_datatype_extensions(datatype)

extensions = '(';

for iExt = 1:numel(datatype.extensions)
if ~strcmp(datatype.extensions{iExt}, '.json')
extensions = [extensions, datatype.extensions{iExt}, '|']; %#ok<AGROW>
end
end

% Replace final "|" by a "){1}"
extensions(end:end + 3) = '){1}';

end
8 changes: 8 additions & 0 deletions +bids/+internal/return_datatype_regular_expression.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function regular_expression = return_datatype_regular_expression(datatype)

suffixes = bids.internal.return_datatype_suffixes(datatype);
extensions = bids.internal.return_datatype_extensions(datatype);

regular_expression = ['^%s.*' suffixes extensions '$'];

end
12 changes: 12 additions & 0 deletions +bids/+internal/return_datatype_suffixes.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function suffixes = return_datatype_suffixes(datatype)

suffixes = '_(';

for iExt = 1:numel(datatype.suffixes)
suffixes = [suffixes, datatype.suffixes{iExt}, '|']; %#ok<AGROW>
end

% Replace final "|" by a "){1}"
suffixes(end:end + 3) = '){1}';

end
64 changes: 64 additions & 0 deletions +bids/+schema/load_schema.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
function schema = load_schema(SCHEMA_DIR)
% Loads a json schema by recursively looking through a folder structure.
%
% The nesting of the output structure reflects a combination of the folder structure and
% any eventual nesting within each json.
%
%
% Copyright (C) 2021--, BIDS-MATLAB developers

% TODO:
% - folders that do not contain json files themselves but contain
% subfolders that do, are not reflected in the output structure (they are
% skipped). This can lead to "name conflicts". See "silenced" unit tests
% for more info.

if nargin < 1
SCHEMA_DIR = fullfile(fileparts(mfilename('fullpath')), '..', '..', 'schema');
end

schema = struct();

[json_file_list, dirs] = bids.internal.file_utils('FPList', SCHEMA_DIR, '^*.json$');

schema = append_json_content_to_structure(schema, json_file_list);

schema = inspect_subdir(schema, dirs);

end

function structure = append_json_content_to_structure(structure, json_file_list)

for iFile = 1:size(json_file_list, 1)

file = deblank(json_file_list(iFile, :));

field_name = bids.internal.file_utils(file, 'basename');

structure.(field_name) = bids.util.jsondecode(file);
end

end

function structure = inspect_subdir(structure, subdir_list)
% recursively inspects subdirectory for json files and reflects folder
% hierarchy in the output structure.

for iDir = 1:size(subdir_list, 1)

directory = deblank(subdir_list(iDir, :));

[json_file_list, dirs] = bids.internal.file_utils('FPList', directory, '^*.json$');

if ~isempty(json_file_list)
field_name = bids.internal.file_utils(directory, 'basename');
structure.(field_name) = struct();
structure.(field_name) = append_json_content_to_structure(structure.(field_name), ...
json_file_list);
end

structure = inspect_subdir(structure, dirs);

end

end
11 changes: 11 additions & 0 deletions +bids/+schema/return_datatype_entities.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function entities = return_datatype_entities(datatype)

schema = bids.schema.load_schema();

entity_names = fieldnames(datatype.entities);

for i = 1:size(entity_names, 1)
entities{1, i} = schema.entities.(entity_names{i}).entity; %#ok<*AGROW>
end

end
Loading