Skip to content

Commit 2979cdc

Browse files
authored
Merge pull request #467 from cpp-lln-lab/rmi-anat_only
[ENH] create an anat only spatial preprocessing
2 parents 826a0f3 + 76ca3e1 commit 2979cdc

20 files changed

+230
-81
lines changed

.github/workflows/miss_hit_quality.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ jobs:
2929
run: |
3030
python -m pip install --upgrade pip setuptools
3131
pip3 install -r requirements.txt
32-
cd tests
33-
make data
3432
3533
- name: MISS_HIT Metrics
3634
run: |

.github/workflows/miss_hit_style.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ jobs:
2929
run: |
3030
python -m pip install --upgrade pip setuptools
3131
pip3 install -r requirements.txt
32-
cd tests
33-
make data
3432
3533
- name: MISS_HIT Code style
3634
run: |

demos/face_repetition/face_rep_anat.m

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
clear;
77
clc;
88

9-
downloadData = true;
9+
downloadData = false;
1010

1111
try
1212
run ../../initCppSpm.m;
@@ -20,6 +20,7 @@
2020
opt.pipeline.type = 'preproc';
2121
opt.pipeline.name = 'cpp_spm-anat';
2222
opt.query.modality = 'anat';
23+
opt.anatOnly = true;
2324

2425
opt = checkOptions(opt);
2526

@@ -32,10 +33,8 @@
3233

3334
end
3435

35-
%% Run batches
3636
reportBIDS(opt);
37-
bidsCopyInputFolder(opt);
3837

39-
bidsSegmentSkullStrip(opt);
38+
bidsCopyInputFolder(opt);
4039

41-
anatomicalQA(opt);
40+
bidsSpatialPrepro(opt);

src/QA/functionalQA.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ function functionalQA(opt)
4848
% TODO: - the tissue probability maps are in the "native" space of each subject
4949
% and are resliced to the dimension of the functional
5050

51+
if opt.anatOnly
52+
return
53+
end
54+
5155
if isOctave()
5256
warning('\nfunctionalQA is not yet supported on Octave. This step will be skipped.');
5357
return

src/batches/preproc/setBatchCoregistrationFuncToAnat.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
%
2222
% (C) Copyright 2020 CPP_SPM developers
2323

24+
if opt.anatOnly
25+
return
26+
end
27+
2428
printBatchName('coregister functional data to anatomical', opt);
2529

2630
matlabbatch{end + 1}.spm.spatial.coreg.estimate.ref(1) = ...

src/batches/preproc/setBatchNormalizationSpatialPrepro.m

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,54 +19,60 @@
1919

2020
jobsToAdd = numel(matlabbatch) + 1;
2121

22+
if opt.anatOnly
23+
maxJobsToAdd = 4;
24+
else
25+
maxJobsToAdd = 5;
26+
end
27+
2228
% set the deformation field for all the images we are about to normalize
2329
% we reuse a previously created deformation field if it is there
2430
% otherwise we link to a segmentation module by using a dependency
2531
deformationField = getDeformationField(matlabbatch, BIDS, opt);
2632

27-
for iJob = jobsToAdd:(jobsToAdd + 5)
28-
33+
for iJob = jobsToAdd:(jobsToAdd + maxJobsToAdd)
2934
% we set images to be resampled at the voxel size we had at acquisition
3035
matlabbatch = setBatchNormalize(matlabbatch, deformationField, voxDim);
31-
3236
end
3337

34-
printBatchName('normalise functional images', opt);
35-
36-
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = ...
37-
cfg_dep('Coregister: Estimate: Coregistered Images', ...
38-
returnDependency(opt, 'coregister'), ...
39-
substruct('.', 'cfiles'));
38+
if ~opt.anatOnly
39+
printBatchName('normalise functional images', opt);
40+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = ...
41+
cfg_dep('Coregister: Estimate: Coregistered Images', ...
42+
returnDependency(opt, 'coregister'), ...
43+
substruct('.', 'cfiles'));
44+
jobsToAdd = jobsToAdd + 1;
45+
end
4046

4147
% NORMALIZE STRUCTURAL
4248
biasCorrectedImage = getBiasCorrectedImage(matlabbatch, BIDS, opt);
43-
4449
printBatchName('normalise anatomical images', opt);
45-
matlabbatch{jobsToAdd + 1}.spm.spatial.normalise.write.subj.resample(1) = biasCorrectedImage;
46-
47-
% size 3 allow to run RunQA / original voxel size at acquisition
48-
matlabbatch{jobsToAdd + 1}.spm.spatial.normalise.write.woptions.vox = [1 1 1];
50+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = biasCorrectedImage;
51+
% TODO why do we choose this resolution for this normalization?
52+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.woptions.vox = [1 1 1];
53+
jobsToAdd = jobsToAdd + 1;
4954

5055
% NORMALIZE TISSUE PROBABILITY MAPS
5156
[gmTpm, wmTpm, csfTpm] = getTpms(matlabbatch, BIDS, opt);
5257

5358
printBatchName('normalise grey matter tissue probability map', opt);
54-
matlabbatch{jobsToAdd + 2}.spm.spatial.normalise.write.subj.resample(1) = gmTpm;
59+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = gmTpm;
60+
jobsToAdd = jobsToAdd + 1;
5561

5662
printBatchName('normalise white matter tissue probability map', opt);
57-
matlabbatch{jobsToAdd + 3}.spm.spatial.normalise.write.subj.resample(1) = wmTpm;
63+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = wmTpm;
64+
jobsToAdd = jobsToAdd + 1;
5865

5966
printBatchName('normalise csf tissue probability map', opt);
60-
matlabbatch{jobsToAdd + 4}.spm.spatial.normalise.write.subj.resample(1) = csfTpm;
67+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = csfTpm;
68+
jobsToAdd = jobsToAdd + 1;
6169

6270
% NORMALIZE SKULSTRIPPED STRUCTURAL
6371
skullstrippedImage = getSkullstrippedImage(matlabbatch, BIDS, opt);
64-
6572
printBatchName('normalise skullstripped anatomical images', opt);
66-
matlabbatch{jobsToAdd + 5}.spm.spatial.normalise.write.subj.resample(1) = skullstrippedImage;
67-
68-
% size 3 allow to run RunQA / original voxel size at acquisition
69-
matlabbatch{jobsToAdd + 5}.spm.spatial.normalise.write.woptions.vox = [1 1 1];
73+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.subj.resample(1) = skullstrippedImage;
74+
% TODO why do we choose this resolution for this normalization?
75+
matlabbatch{jobsToAdd}.spm.spatial.normalise.write.woptions.vox = [1 1 1];
7076

7177
end
7278

src/batches/preproc/setBatchRealign.m

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
% USAGE::
66
%
77
% [matlabbatch, voxDim] = setBatchRealign(matlabbatch, ...
8-
% [action = 'realign'], ...
98
% BIDS, ...
109
% opt, ...
11-
% subLabel)
10+
% subLabel, ...
11+
% [action = 'realign'])
1212
%
1313
% :param matlabbatch: SPM batch
14-
% :type matlabbatch: structure
14+
% :type matlabbatch: cell
1515
% :param BIDS: BIDS layout returned by ``getData``.
1616
% :type BIDS: structure
17-
% :param action: ``realign``, ``realignReslice``, ``realignUnwarp``
18-
% :type action: string
1917
% :param opt: Options chosen for the analysis. See ``checkOptions()``.
2018
% :type opt: structure
21-
% :type subLabel: string
2219
% :param subLabel: subject label
20+
% :type subLabel: string
21+
% :param action: ``realign``, ``realignReslice``, ``realignUnwarp``, ``'reslice'``
22+
% :type action: string
2323
%
2424
% :returns: - :matlabbatch: (structure) (dimension)
2525
% - :voxDim: (array) (dimension)
@@ -29,15 +29,33 @@
2929

3030
% TODO make which image is resliced more consistent 'which = []'
3131

32-
if numel(varargin) < 5
33-
[matlabbatch, BIDS, opt, subLabel] = deal(varargin{:});
34-
action = '';
35-
else
36-
[matlabbatch, BIDS, opt, subLabel, action] = deal(varargin{:});
37-
end
38-
39-
if isempty(action)
40-
action = 'realignUnwarp';
32+
p = inputParser;
33+
34+
default_action = 'realignUnwarp';
35+
allowedActions = @(x) ischar(x) && ...
36+
ismember(lower(x), ...
37+
{'realignunwarp', ...
38+
'realignreslice', ...
39+
'realign', ...
40+
'reslice'});
41+
42+
addRequired(p, 'matlabbatch', @iscell);
43+
addRequired(p, 'BIDS', @isstruct);
44+
addRequired(p, 'opt', @isstruct);
45+
addRequired(p, 'subLabel', @ischar);
46+
addOptional(p, 'action', default_action, allowedActions);
47+
48+
parse(p, varargin{:});
49+
50+
matlabbatch = p.Results.matlabbatch;
51+
BIDS = p.Results.BIDS;
52+
opt = p.Results.opt;
53+
subLabel = p.Results.subLabel;
54+
action = p.Results.action;
55+
56+
if opt.anatOnly
57+
voxDim = [];
58+
return
4159
end
4260

4361
msg = '';

src/batches/preproc/setBatchSaveCoregistrationMatrix.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
%
2020
% (C) Copyright 2020 CPP_SPM developers
2121

22+
if opt.anatOnly
23+
return
24+
end
25+
2226
printBatchName('saving coregistration matrix', opt);
2327

2428
% create name of the output file based on the name

src/defaults/checkOptions.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@
176176
fieldsToSet.pipeline.type = '';
177177
fieldsToSet.pipeline.name = 'cpp_spm';
178178

179+
fieldsToSet.anatOnly = false;
180+
179181
fieldsToSet.useBidsSchema = false;
180182

181183
fieldsToSet.fwhm.func = 6;

src/reports/copyFigures.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function copyFigures(BIDS, opt, subLabel)
1919
imgNb = copyGraphWindownOutput(opt, subLabel, 'realign');
2020

2121
% loop through the figures outputed for unwarp: one per run
22-
if opt.realign.useUnwarp
22+
if opt.realign.useUnwarp && ~opt.anatOnly
2323

2424
runs = bids.query(BIDS, 'runs', ...
2525
'sub', subLabel, ...

0 commit comments

Comments
 (0)