Skip to content

Commit c5392fd

Browse files
authored
Merge pull request #80 from cpp-lln-lab/remi-highres_analysis
mostly creating unit tests to increase our coverage
2 parents 86ebdd1 + 4afe4a9 commit c5392fd

File tree

194 files changed

+2176
-1148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

194 files changed

+2176
-1148
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*.asv
44
*.m~
55
*.mat
6-
*.nii
76
*.xml
87
*.log
98
*.html

CHANGELOG.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Changelog
2+
3+
## [Unreleased](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/HEAD)
4+
5+
[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.3...HEAD)
6+
7+
**Closed issues:**
8+
9+
- add code coverage [\#77](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/77)
10+
- getData :Accommidate scripts for structural analysis \(without funtional\). [\#68](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/68)
11+
12+
**Merged pull requests:**
13+
14+
- major refactoring reporting for duty [\#79](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/79) ([Remi-Gau](https://github.com/Remi-Gau))
15+
- fix linter and use Mox unit for testing [\#76](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/76) ([Remi-Gau](https://github.com/Remi-Gau))
16+
- reorganize and set up MH linter [\#75](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/75) ([Remi-Gau](https://github.com/Remi-Gau))
17+
- add octave in dependencies [\#71](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/71) ([Remi-Gau](https://github.com/Remi-Gau))
18+
- allow getData to query only anatomical data [\#69](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/69) ([Remi-Gau](https://github.com/Remi-Gau))
19+
- update print credit [\#63](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/63) ([Remi-Gau](https://github.com/Remi-Gau))
20+
- update DOI [\#62](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/62) ([Remi-Gau](https://github.com/Remi-Gau))
21+
- update DOI badge [\#61](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/61) ([Remi-Gau](https://github.com/Remi-Gau))
22+
23+
## [v0.0.3](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.3) (2019-11-28)
24+
25+
[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.2...v0.0.3)
26+
27+
**Merged pull requests:**
28+
29+
- fix RFX issues and add credits [\#60](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/60) ([Remi-Gau](https://github.com/Remi-Gau))
30+
31+
## [v0.0.2](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.2) (2019-11-26)
32+
33+
[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.1...v0.0.2)
34+
35+
**Merged pull requests:**
36+
37+
- Create LICENSE [\#58](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/58) ([Remi-Gau](https://github.com/Remi-Gau))
38+
- fix problem when task JSON file is missing from root folder [\#56](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/56) ([Remi-Gau](https://github.com/Remi-Gau))
39+
40+
## [v0.0.1](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.1) (2019-11-13)
41+
42+
[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/8ca4e1b47af1d983cde988bae1a9bd9659151330...v0.0.1)
43+
44+
**Implemented enhancements:**
45+
46+
- refactor getRuns, getSessions, getFilenames [\#9](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/9)
47+
- find a way to specify the contrasts to compute [\#11](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/11)
48+
- Complete boiler plate methods section of the README [\#17](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/17) ([Remi-Gau](https://github.com/Remi-Gau))
49+
- Big PR to fix previous PR, update FFX and RFX [\#2](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/2) ([Remi-Gau](https://github.com/Remi-Gau))
50+
51+
**Closed issues:**
52+
53+
- spm\_jsonread issue [\#54](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/54)
54+
- \[WORKSHOP 2019\] - to do list [\#48](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/48)
55+
- \[WORKSHOP 2019\] - MVPA [\#47](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/47)
56+
- \[WORKSHOP 2019\] - sharing data [\#46](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/46)
57+
- changes way subjects are indexed in getData [\#44](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/44)
58+
- Add Moh as contributors [\#37](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/37)
59+
- add Marco as contributors [\#35](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/35)
60+
- getData issue with 2 groups [\#22](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/22)
61+
- create a function to checks options and set some defaults if none are specified [\#15](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/15)
62+
- use SPM BIDS data set from SPM tuto to test and make a simple demo [\#7](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/7)
63+
- test with octave [\#5](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/5)
64+
- export final results as NIDM results to facilitate upload to neurovault [\#52](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/52)
65+
- Consider to unzip the bold files in a separate function from BIDS\_rmDumies.m [\#26](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/26)
66+
- create a function that copies the raw data into a derivatives/SPM12-CPP directory [\#25](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/25)
67+
68+
**Merged pull requests:**
69+
70+
- BIDS results [\#55](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/55) ([Remi-Gau](https://github.com/Remi-Gau))
71+
- \[WIP\] constrast specification + uni and multivaraite issues + remove dummies [\#51](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/51) ([Remi-Gau](https://github.com/Remi-Gau))
72+
- fix some details in getData to pass tests and make octave compatible [\#45](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/45) ([Remi-Gau](https://github.com/Remi-Gau))
73+
- fix indexing issue in getData [\#43](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/43) ([Remi-Gau](https://github.com/Remi-Gau))
74+
- docs: add OliColli as a contributor [\#40](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/40) ([allcontributors[bot]](https://github.com/apps/allcontributors))
75+
- docs: add anege as a contributor [\#39](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/39) ([allcontributors[bot]](https://github.com/apps/allcontributors))
76+
- docs: add mohmdrezk as a contributor [\#38](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/38) ([allcontributors[bot]](https://github.com/apps/allcontributors))
77+
- docs: add marcobarilari as a contributor [\#36](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/36) ([allcontributors[bot]](https://github.com/apps/allcontributors))
78+
- docs: add Remi-Gau as a contributor [\#30](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/30) ([allcontributors[bot]](https://github.com/apps/allcontributors))
79+
- Add another test to getData and improve README [\#28](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/28) ([Remi-Gau](https://github.com/Remi-Gau))
80+
- edit info about step1: 'Remove Dummy Scans' [\#27](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/27) ([marcobarilari](https://github.com/marcobarilari))
81+
- update doc [\#24](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/24) ([Remi-Gau](https://github.com/Remi-Gau))
82+
- - fix getData issue when there are multiple groups [\#23](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/23) ([mohmdrezk](https://github.com/mohmdrezk))
83+
- Ane getsessions merge [\#19](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/19) ([anege](https://github.com/anege))
84+
- Dockerfile and option defaults [\#16](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/16) ([Remi-Gau](https://github.com/Remi-Gau))
85+
- Containerization of the pipeline with docker and octave [\#13](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/13) ([Remi-Gau](https://github.com/Remi-Gau))
86+
- fix crash on batch\_download\_run [\#12](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/12) ([Remi-Gau](https://github.com/Remi-Gau))
87+
- Initial preparartion for Workshop scripts for Motion dataset [\#10](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/10) ([mohmdrezk](https://github.com/mohmdrezk))
88+
- delete extra getOptions [\#8](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/8) ([Remi-Gau](https://github.com/Remi-Gau))
89+
- Split into 3 repos [\#1](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/1) ([Remi-Gau](https://github.com/Remi-Gau))
90+
91+
92+
93+
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
- [fMRI data analysis](#fmri-data-analysis)
4141
- [References](#references)
4242
- [Unit testing](#unit-testing)
43+
- [Changelog](#changelog)
4344
- [Contributors ✨](#contributors-)
4445

4546
<!-- /TOC -->
@@ -326,6 +327,9 @@ Corbin, N., Todd, N., Friston, K. J. & Callaghan, M. F. Accurate modeling of tem
326327

327328
All tests are in the test folder. There is also an empty dummy BIDS dataset that is partly created using the bash script `createDummyDataSet.sh`.
328329

330+
## Changelog
331+
332+
<!-- github_changelog_generator -u cpp-lln-lab -p CPP_BIDS_SPM_pipeline --token 93b4c584bf22883a3c4f8b9031b70e381deef272 -->
329333

330334
## Contributors ✨
331335

demo/batch_download_run.m

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
WD = fileparts(mfilename('fullpath'));
1919

2020
% we add all the subfunctions that are in the sub directories
21+
addpath(fullfile(WD, '..'));
2122
addpath(genpath(fullfile(WD, '..', 'src')));
2223
addpath(genpath(fullfile(WD, '..', 'lib')));
2324

@@ -66,7 +67,7 @@
6667
%% Get data
6768
% fprintf('%-40s:', 'Downloading dataset...');
6869
% urlwrite(URL, 'MoAEpilot.zip');
69-
% unzip('MoAEpilot.zip', fullfile(WD, 'output'));
70+
unzip('MoAEpilot.zip', fullfile(WD, 'output'));
7071

7172
%% Check dependencies
7273
% If toolboxes are not in the MATLAB Directory and needed to be added to
@@ -81,10 +82,12 @@
8182
checkDependencies();
8283

8384
%% Run batches
85+
isMVPA = 0;
86+
8487
bidsCopyRawFolder(opt, 1);
8588
bidsSTC(opt);
8689
bidsSpatialPrepro(opt);
8790
bidsSmoothing(FWHM, opt);
88-
bidsFFX(1, FWHM, opt, 0);
89-
bidsFFX(2, FWHM, opt, 0);
90-
bidsResults(FWHM, [], opt, 0);
91+
bidsFFX('specifyAndEstimate', opt, FWHM, isMVPA);
92+
bidsFFX('contrasts', opt, FWHM, isMVPA);
93+
bidsResults(opt, FWHM, [], isMVPA);

demo/model-MoAE_smdl.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@
2222
"type": "t"
2323
}
2424
]
25+
},
26+
{
27+
"Level": "run",
28+
"Model": {
29+
"X": [
30+
"trial_type.listening",
31+
"trans_x", "trans_y", "trans_z", "rot_x", "rot_y", "rot_z"
32+
]
33+
},
34+
"AutoContrasts": ["trial_type.listening"]
2535
}
2636
]
2737
}

miss_hit.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ exclude_dir: "lib"
66

77
# metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html)
88
metric "cnest": limit 4
9-
metric "file_length": limit 500
9+
metric "file_length": limit 300
1010
metric "cyc": limit 15
11-
metric "parameters": limit 6
11+
metric "parameters": limit 4

src/concatBetaImgTmaps.m

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
function concatBetaImgTmaps(funcFWHM, opt, deleteIndBeta, deleteIndTmaps)
2+
% concatBetaImgTmaps(funcFWHM, opt, deleteIndBeta, deleteIndTmaps)
3+
%
4+
% Make 4D images of beta and t-maps for the MVPA
5+
%
6+
% Inputs
7+
% funcFWHM - smoothing (FWHM) applied to the the normalized EPI
8+
% opt - options structure defined by the getOption function. If no inout is given
9+
% this function will attempt to load a opt.mat file in the same directory
10+
% to try to get some options
11+
%
12+
% deleteIndBeta, deleteIndTmaps: boolean to decide to delete
13+
% original t-maps, beta-maps or ResMaps (default = true)
14+
15+
% if input has no opt, load the opt.mat file
16+
if nargin < 2
17+
load('opt.mat');
18+
fprintf('opt.mat file loaded \n\n');
19+
end
20+
21+
% delete individual Beta and tmaps
22+
if nargin < 3
23+
deleteIndBeta = 1;
24+
deleteIndTmaps = 1;
25+
end
26+
27+
% assign isMVPA to true
28+
isMVPA = 1;
29+
30+
% load the subjects/Groups information and the task name
31+
[group, opt, ~] = getData(opt);
32+
33+
%% Loop through the groups, subjects
34+
for iGroup = 1:length(group)
35+
36+
for iSub = 1:group(iGroup).numSub
37+
38+
subID = group(iGroup).subNumber{iSub};
39+
40+
fprintf(1, 'PREPARING: 4D maps: %s \n', subID);
41+
42+
ffxDir = getFFXdir(subID, funcFWHM, opt, isMVPA);
43+
44+
load(fullfile(ffxDir, 'SPM.mat'));
45+
46+
contrasts = specifyContrasts(ffxDir, opt.taskName, opt, isMVPA);
47+
48+
beta_maps = cell(length(contrasts), 1);
49+
t_maps = cell(length(contrasts), 1);
50+
51+
% path to beta and t-map files.
52+
for iContrast = 1:length(beta_maps)
53+
% Note that the betas are created from the idx (Beta_idx(iBeta))
54+
fileName = sprintf('beta_%04d.nii', find(contrasts(iContrast).C));
55+
fileName = inputFileValidation(ffxDir, '', fileName);
56+
beta_maps{iContrast, 1} = [fileName{1}, ',1'];
57+
58+
% while the contrastes (t-maps) are not from the index. They were created
59+
fileName = sprintf('spmT_%04d.nii', iContrast);
60+
fileName = inputFileValidation(ffxDir, '', fileName);
61+
t_maps{iContrast, 1} = [fileName{1}, ',1'];
62+
end
63+
64+
% clear previous matlabbatch and files
65+
matlabbatch = [];
66+
67+
% 4D beta maps
68+
matlabbatch{1}.spm.util.cat.vols = beta_maps;
69+
matlabbatch{1}.spm.util.cat.name = ['4D_beta_', num2str(funcFWHM), '.nii'];
70+
matlabbatch{1}.spm.util.cat.dtype = 4;
71+
72+
% 4D t-maps
73+
matlabbatch{2}.spm.util.cat.vols = t_maps;
74+
matlabbatch{2}.spm.util.cat.name = ['4D_t_maps_', num2str(funcFWHM), '.nii'];
75+
matlabbatch{2}.spm.util.cat.dtype = 4;
76+
77+
saveMatlabBatch(matlabbatch, 'concatBetaImgTmaps', opt, subID);
78+
79+
spm_jobman('run', matlabbatch);
80+
81+
removeBetaImgTmaps(beta_maps, t_maps, deleteIndBeta, deleteIndTmaps);
82+
83+
end
84+
end
85+
86+
end
87+
88+
function removeBetaImgTmaps(beta_maps, t_maps, deleteIndBeta, deleteIndTmaps)
89+
90+
% delete maps
91+
if deleteIndBeta
92+
93+
% delete all individual beta maps
94+
fprintf('Deleting individual beta-maps ... ');
95+
for iBeta = 1:length(beta_maps)
96+
delete(beta_maps{iBeta}(1:end - 2));
97+
end
98+
fprintf('Done. \n\n\n ');
99+
100+
end
101+
102+
if deleteIndTmaps
103+
104+
% delete all individual con maps
105+
fprintf('Deleting individual con maps ... ');
106+
for iCon = 1:length(t_maps)
107+
delete(fullfile(ffxDir, ['con_', sprintf('%04d', iCon), '.nii']));
108+
end
109+
fprintf('Done. \n\n\n ');
110+
111+
% delete all individual t-maps
112+
fprintf('Deleting individual t-maps ... ');
113+
for iTmap = 1:length(t_maps)
114+
delete(t_maps{iTmap}(1:end - 2));
115+
end
116+
fprintf('Done. \n\n\n ');
117+
end
118+
119+
% delete mat files
120+
121+
% This is refactorable
122+
% ex: delete(fullfile(ffxDir, ['4D_*', num2str(funcFWHM), '.mat']));
123+
124+
if exist(fullfile(ffxDir, ['4D_beta_', num2str(funcFWHM), '.mat']), 'file')
125+
delete(fullfile(ffxDir, ['4D_beta_', num2str(funcFWHM), '.mat']));
126+
end
127+
if exist(fullfile(ffxDir, ['4D_t_maps_', num2str(funcFWHM), '.mat']), 'file')
128+
delete(fullfile(ffxDir, ['4D_t_maps_', num2str(funcFWHM), '.mat']));
129+
end
130+
end

src/convertOnsetTsvToMat.m

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
function fullpathOnsetFileName = convertOnsetTsvToMat(opt, tsvFile, isMVPA)
2+
%% Converts a tsv file to an onset file suitable for SPM ffx analysis
3+
% The scripts extracts the conditions' names, onsets, and durations, and
4+
% converts them to TRs (time unit) and saves the onset file to be used for
5+
% SPM
6+
%%
7+
8+
if ~exist(tsvFile, 'file')
9+
10+
errorStruct.identifier = 'convertOnsetTsvToMat:nonExistentFile';
11+
errorStruct.message = sprintf('%s\n%s', ...
12+
'This onset tsv file deos not exist:', ...
13+
tsvFile);
14+
error(errorStruct);
15+
end
16+
17+
% Read the tsv file
18+
fprintf('reading the tsv file : %s \n', tsvFile);
19+
t = spm_load(tsvFile);
20+
21+
if ~isfield(t, 'trial_type')
22+
23+
errorStruct.identifier = 'convertOnsetTsvToMat:noTrialType';
24+
errorStruct.message = sprintf('%s\n%s', ...
25+
'There was no trial_type field in this file:', ...
26+
tsvFile);
27+
error(errorStruct);
28+
29+
end
30+
31+
conds = t.trial_type; % assign all the tsv information to a variable called conds.
32+
33+
% identify where the conditions to include that are specificed in the 'un' step of the
34+
% model file
35+
if isMVPA
36+
model = spm_jsonread(opt.model.multivariate.file);
37+
else
38+
model = spm_jsonread(opt.model.univariate.file);
39+
end
40+
41+
for runIdx = 1:numel(model.Steps)
42+
if strcmp(model.Steps{1}.Level, 'run')
43+
break
44+
end
45+
end
46+
47+
isTrialType = strfind(model.Steps{runIdx}.Model.X, 'trial_type.');
48+
49+
% for each condition
50+
for iCond = 1:numel(isTrialType)
51+
52+
if isTrialType{iCond}
53+
54+
conditionName = strrep(model.Steps{runIdx}.Model.X{iCond}, ...
55+
'trial_type.', ...
56+
'');
57+
58+
% Get the index of each condition by comparing the unique names and
59+
% each line in the tsv files
60+
idx = find(strcmp(conditionName, conds));
61+
62+
% Get the onset and duration of each condition
63+
names{1, iCond} = conditionName;
64+
onsets{1, iCond} = t.onset(idx)'; %#ok<*AGROW,*NASGU>
65+
durations{1, iCond} = t.duration(idx)';
66+
67+
end
68+
end
69+
70+
% save the onsets as a matfile
71+
[path, file] = spm_fileparts(tsvFile);
72+
73+
fullpathOnsetFileName = fullfile(path, ['onsets_' file '.mat']);
74+
75+
save(fullpathOnsetFileName, ...
76+
'names', 'onsets', 'durations');
77+
78+
end

0 commit comments

Comments
 (0)