Skip to content

Commit 6266f69

Browse files
authored
Merge pull request #31 from cpp-lln-lab/special_prefix
[ENH] deal with special prefixes in identify sources
2 parents b9c0218 + 0afade2 commit 6266f69

File tree

6 files changed

+120
-71
lines changed

6 files changed

+120
-71
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.vscode
44

55
*.json
6+
mapping.md
67

78
env/
89

miss_hit.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ copyright_entity: "spm_2_bids developers"
1717
# metric for code quality
1818
metric "cnest": limit 5
1919
metric "file_length": limit 500
20-
metric "cyc": limit 16
20+
metric "cyc": limit 15
2121
metric "parameters": limit 6

src/Mapping.m

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,26 +104,26 @@
104104
% filter.ext
105105
%
106106

107-
p = inputParser;
107+
args = inputParser;
108108

109-
addParameter(p, 'prefix', obj.default_value);
110-
addParameter(p, 'suffix', obj.default_value);
111-
addParameter(p, 'entities', obj.default_value);
112-
addParameter(p, 'ext', obj.default_value);
113-
addParameter(p, 'name_spec', obj.default_value);
109+
addParameter(args, 'prefix', obj.default_value);
110+
addParameter(args, 'suffix', obj.default_value);
111+
addParameter(args, 'entities', obj.default_value);
112+
addParameter(args, 'ext', obj.default_value);
113+
addParameter(args, 'name_spec', obj.default_value);
114114

115-
parse(p, varargin{:});
115+
parse(args, varargin{:});
116116

117-
prefix = p.Results.prefix;
117+
prefix = args.Results.prefix;
118118
if ~iscell(prefix)
119119
prefix = {prefix};
120120
end
121121

122122
obj.mapping(end + 1, 1).prefix = prefix;
123-
obj.mapping(end, 1).suffix = p.Results.suffix;
124-
obj.mapping(end, 1).entities = p.Results.entities;
125-
obj.mapping(end, 1).ext = p.Results.ext;
126-
obj.mapping(end, 1).name_spec = p.Results.name_spec;
123+
obj.mapping(end, 1).suffix = args.Results.suffix;
124+
obj.mapping(end, 1).entities = args.Results.entities;
125+
obj.mapping(end, 1).ext = args.Results.ext;
126+
obj.mapping(end, 1).name_spec = args.Results.name_spec;
127127

128128
end
129129

@@ -317,6 +317,8 @@ function print_mapping(obj, filename)
317317
[obj.smooth, obj.norm, obj.unwarp], ...
318318
[obj.smooth, obj.norm, obj.realign] }, obj.cfg.smooth_norm};
319319

320+
spec_preproc = {{[obj.realign, obj.stc]}, obj.cfg.preproc};
321+
320322
spec_preproc_norm = {{obj.norm, ...
321323
[obj.norm, obj.bias_cor], ...
322324
[obj.norm, obj.stc, obj.unwarp], ...
@@ -329,6 +331,7 @@ function print_mapping(obj, filename)
329331
spec_smooth, ...
330332
spec_smooth_norm, ...
331333
spec_preproc_norm, ...
334+
spec_preproc, ...
332335
spec_mean, ...
333336
spec_norm_mean);
334337

@@ -348,15 +351,15 @@ function print_mapping(obj, filename)
348351
% idx = obj.find_mapping('prefix', str)
349352
%
350353

351-
p = inputParser;
354+
args = inputParser;
352355

353-
addParameter(p, 'prefix', @ischar);
356+
addParameter(args, 'prefix', @ischar);
354357

355-
parse(p, varargin{:});
358+
parse(args, varargin{:});
356359

357360
available_mapped_prefixes = {obj.mapping.prefix}';
358361

359-
idx = strcmp(p.Results.prefix, available_mapped_prefixes);
362+
idx = strcmp(args.Results.prefix, available_mapped_prefixes);
360363

361364
end
362365

src/spm_2_bids.m

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
function [new_filename, pth, json] = spm_2_bids(file, map, verbose)
1+
function [new_filename, pth, json] = spm_2_bids(varargin)
22
%
33
% Provides a bids derivatives name for a file preprocessed with SPM
44
%
55
% USAGE::
66
%
7-
% [new_filename, pth, json] = spm_2_bids(file)
8-
% [new_filename, pth, json] = spm_2_bids(file, map)
7+
% [new_filename, pth, json] = spm_2_bids(file [, map][, verbose])
98
%
109
% :param file: SPM preprocessed filename (can be fullpath);
1110
% for example ``wmsub-01_ses-01_T1w.nii``
1211
% :type file: string
12+
%
1313
% :param map: optional spm_2_bids map to overwrite the default
1414
% map (see Mapping)
1515
% :param map: Mapping object
1616
%
17+
% :param verbose:
18+
% :param verbose: boolean
19+
%
1720
% :returns: - :new_filename: (string) BIDS compatible filename
1821
% for example ``sub-01_ses-01_space-IXI549Space_desc-preproc_T1w.nii``;
1922
% - :pth: (string) relative BIDS path
@@ -26,15 +29,23 @@
2629
%
2730
% (C) Copyright 2021 spm_2_bids developers
2831

29-
if nargin < 2 || isempty(map)
32+
args = inputParser;
33+
34+
addRequired(args, 'file', @ischar);
35+
addOptional(args, 'map', []);
36+
addOptional(args, 'verbose', true, @islogical);
37+
38+
parse(args, varargin{:});
39+
40+
file = args.Results.file;
41+
map = args.Results.map;
42+
verbose = args.Results.verbose;
43+
44+
if isempty(map)
3045
map = Mapping();
3146
map = map.default();
3247
end
3348

34-
if nargin < 3
35-
verbose = true;
36-
end
37-
3849
mapping = map.mapping;
3950
cfg = map.cfg;
4051

@@ -82,22 +93,7 @@
8293
strcmp({mapping.ext}', '*')], 2);
8394
end
8495

85-
% we compare the entities-label pairs present in the file
86-
% to those required in the mapping (if any)
87-
% if no entity requirement anywhere in the mapping then anything goes
88-
entitiy_match = true(size(mapping));
89-
90-
needs_entity_check = ~cellfun('isempty', {mapping.entities}');
91-
if any(needs_entity_check)
92-
93-
entitiy_match = false(size(mapping));
94-
95-
idx = find(needs_entity_check);
96-
for i = 1:numel(idx)
97-
status = check_field_content(bf.entities, mapping(idx(i)).entities);
98-
entitiy_match(idx(i)) = status;
99-
end
100-
end
96+
entitiy_match = get_entity_match(mapping, bf);
10197

10298
this_mapping = [prefix_match, suffix_match, entitiy_match, ext_match];
10399

@@ -116,9 +112,15 @@
116112
end
117113

118114
if isempty(spec) && verbose
119-
% TODO this warning should probably go in the find_mapping methods
120-
msg = sprintf('Unknown prefix: %s', bf.prefix);
121-
warning('spm_2_bids:unknownPrefix', msg); %#ok<SPWRN>
115+
if isnan(str2double(bf.prefix(1))) && ...
116+
~bids.internal.starts_with(bf.prefix, 'c4') && ... % ALI toolbox prefixes
117+
~bids.internal.starts_with(bf.prefix, 'td_') % spmup toolbox truncated prefixes
118+
119+
% TODO this warning should probably go in the find_mapping methods
120+
msg = sprintf('Unknown prefix: %s', bf.prefix);
121+
warning('spm_2_bids:unknownPrefix', msg); %#ok<SPWRN>
122+
123+
end
122124
return
123125
end
124126

@@ -144,6 +146,25 @@
144146

145147
end
146148

149+
function entitiy_match = get_entity_match(mapping, bf)
150+
% we compare the entities-label pairs present in the file
151+
% to those required in the mapping (if any)
152+
% if no entity requirement anywhere in the mapping then anything goes
153+
entitiy_match = true(size(mapping));
154+
155+
needs_entity_check = ~cellfun('isempty', {mapping.entities}');
156+
if any(needs_entity_check)
157+
158+
entitiy_match = false(size(mapping));
159+
160+
idx = find(needs_entity_check);
161+
for i = 1:numel(idx)
162+
status = check_field_content(bf.entities, mapping(idx(i)).entities);
163+
entitiy_match(idx(i)) = status;
164+
end
165+
end
166+
end
167+
147168
function json = set_metadata(file, map, verbose, bf)
148169

149170
json = bids.derivatives_json(bf.filename);

src/utils/identify_sources.m

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,7 @@
3232

3333
prefix_based = true;
3434

35-
add_deformation_field = false;
36-
deformation_field = 'TODO: add deformation field';
37-
38-
% TODO? grab all the anat suffixes from BIDS schema?
39-
covered_suffixes = {'T1w', ...
40-
'T2w', ...
41-
'PDw', ...
42-
'T2starw', ...
43-
'inplaneT1', ...
44-
'inplaneT2', ...
45-
'PD', ...
46-
'PDT2', ...
47-
'T2star', ...
48-
'FLASH', ...
49-
'T1map', ...
50-
'T2map', ...
51-
'T2starmap', ...
52-
'R1map', ...
53-
'R2map', ...
54-
'R2starmap', ...
55-
'PDmap', ...
56-
'UNIT1'};
35+
deformation_field_needed = false;
5736

5837
args = inputParser;
5938

@@ -102,15 +81,31 @@
10281
else
10382
% remove the prefix of the last step
10483

105-
if bids.internal.starts_with(bf.prefix, 's') || ...
106-
bids.internal.starts_with(bf.prefix, 'u')
84+
if bids.internal.starts_with(bf.prefix, 's') && ...
85+
~bids.internal.starts_with(bf.prefix, 'std_') && ...
86+
~bids.internal.starts_with(bf.prefix, 'segparam_')
87+
88+
% in case we have "s6" for the fwhm
89+
if isnan(str2double(bf.prefix(2)))
90+
bf.prefix = bf.prefix(2:end);
91+
else
92+
bf.prefix = bf.prefix(3:end);
93+
end
94+
95+
elseif bids.internal.starts_with(bf.prefix, 'u') && ...
96+
~bids.internal.starts_with(bf.prefix, 'unwarpparam_')
97+
10798
bf.prefix = bf.prefix(2:end);
10899

100+
deformation_field_needed = true;
101+
109102
elseif bids.internal.starts_with(bf.prefix, 'w')
103+
110104
bf.prefix = bf.prefix(2:end);
111-
add_deformation_field = true;
105+
deformation_field_needed = true;
112106

113107
elseif bids.internal.starts_with(bf.prefix, 'rp_a')
108+
114109
bf.prefix = bf.prefix(4:end);
115110

116111
elseif bids.internal.starts_with(bf.prefix, 'mean')
@@ -137,7 +132,35 @@
137132

138133
sources{1, 1} = fullfile(bf.bids_path, new_filename);
139134

140-
if add_deformation_field
135+
sources = add_deformation_field(sources, bf, map, verbose, deformation_field_needed);
136+
137+
end
138+
139+
function sources = add_deformation_field(sources, bf, map, verbose, deformation_field_needed)
140+
141+
deformation_field = 'TODO: add deformation field';
142+
143+
% TODO? grab all the anat suffixes from BIDS schema?
144+
covered_suffixes = {'T1w', ...
145+
'T2w', ...
146+
'PDw', ...
147+
'T2starw', ...
148+
'inplaneT1', ...
149+
'inplaneT2', ...
150+
'PD', ...
151+
'PDT2', ...
152+
'T2star', ...
153+
'FLASH', ...
154+
'T1map', ...
155+
'T2map', ...
156+
'T2starmap', ...
157+
'R1map', ...
158+
'R2map', ...
159+
'R2starmap', ...
160+
'PDmap', ...
161+
'UNIT1'};
162+
163+
if deformation_field_needed
141164

142165
% for anatomical data we assume that
143166
% the deformation field comes from the anatomical file itself
@@ -157,5 +180,4 @@
157180
sources{2, 1} = deformation_field;
158181

159182
end
160-
161183
end

tests/test_spm_2_bids.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ function test_spm_2_bids_func()
239239
'sub-01_task-auditory_motion.tsv'; ...
240240
{'mean', 'meanu', 'meanua', 'meanau'}, ...
241241
'sub-01_task-auditory_space-individual_desc-mean_bold.nii'; ...
242+
{'ra'}, ...
243+
'sub-01_task-auditory_space-individual_desc-preproc_bold.nii'; ...
242244
{'w', 'wua', 'wu', 'wr', 'wra'}, ...
243245
'sub-01_task-auditory_space-IXI549Space_desc-preproc_bold.nii'; ...
244246
{'wmean', 'wmeanu', 'wmeanua', 'wmeanau'}, ...

0 commit comments

Comments
 (0)