diff --git a/.github/workflows/miss_hit.yml b/.github/workflows/miss_hit.yml
index d4cb7ae8..4603893a 100644
--- a/.github/workflows/miss_hit.yml
+++ b/.github/workflows/miss_hit.yml
@@ -28,7 +28,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools
- pip3 install install miss_hit
+ pip3 install miss_hit
- name: Miss_hit code quality
run: |
diff --git a/.travis.yml b/.travis.yml
index faa12678..63e8b15f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,61 +2,74 @@
# This will only work on your repo if you have an account on travis and you
# have set it up to run continuous integration on this this repo
-# Linux distribution (bionic beaver)
dist: bionic
-# Language and version
-language: python
-python:
- - "3.6" # current default Python on Travis CI
+language: node_js
+node_js:
+ - "10"
cache:
- apt: true # only works with Pro version
+ apt: true
directories:
- - node_modules # NPM packages for the remark markdown linter
+ - node_modules
+# only run the CI for those branches
branches:
- only: # only run the CI for those branches
- - master
- - dev
+ only:
+ - master
+ - dev
env:
global:
- OCTFLAGS="--no-gui --no-window-system --silent"
-jobs:
+# TODO maybe this could be refactored as this is not needed to check the
+# the markdown linting
+install:
+ # install octave
+ - travis_retry sudo apt-get -y -qq update
+ - travis_retry sudo apt-get -y install octave
+ - travis_retry sudo apt-get -y install liboctave-dev
+
+ # install SPM and the relevant patches for octave
+ - git clone https://github.com/spm/spm12.git --depth 1
+ - make -C spm12/src PLATFORM=octave distclean
+ - make -C spm12/src PLATFORM=octave
+ - make -C spm12/src PLATFORM=octave install
+ # update octave path
+ - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'lib'))); savepath();"
+ - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'src'))); savepath();"
+ - octave $OCTFLAGS --eval "addpath(fullfile(pwd, 'spm12')); savepath();"
+
+jobs:
include:
- # names the first job
+ #-------------------------------------------------------------------------
+ # first job
+ #-------------------------------------------------------------------------
- name: "Unit tests and coverage"
- before_install:
- # install octave
- - travis_retry sudo apt-get -y -qq update
- - travis_retry sudo apt-get -y install octave
- - travis_retry sudo apt-get -y install liboctave-dev
+ before_script:
+
# install MOX unit
- git clone https://github.com/MOxUnit/MOxUnit.git --depth 1
- cd MOxUnit
- make install
- cd ..
+
# install MOcov
- git clone https://github.com/MOcov/MOcov.git --depth 1
- cd MOcov
- make install
- cd ..
- # install SPM and the relevant patches for octave
- - git clone https://github.com/spm/spm12.git --depth 1
- - make -C spm12/src PLATFORM=octave distclean
- - make -C spm12/src PLATFORM=octave
- - make -C spm12/src PLATFORM=octave install
+
# get data
- output_folder='demos/MoAE/output/'
- mkdir $output_folder
- curl http://www.fil.ion.ucl.ac.uk/spm/download/data/MoAEpilot/MoAEpilot.bids.zip --output $output_folder'MoAEpilot.zip'
- unzip $output_folder'MoAEpilot.zip' -d $output_folder
-
+
script:
- octave $OCTFLAGS --eval "runTests"
- cat test_report.log | grep 0
@@ -65,11 +78,28 @@ jobs:
after_success:
- bash <(curl -s https://codecov.io/bash)
+ #-------------------------------------------------------------------------
+ # second job
+ #-------------------------------------------------------------------------
- name: "Check markdown"
- language: node_js
- node_js:
- - "10"
+
before_script:
+ # install node.js dependencies
- npm install `cat npm-requirements.txt`
+
+ script:
+ - remark *.md --frail
+ - remark ./demos/ --frail
+ - remark ./docs/ --frail
+ - remark ./tests/ --frail
+
+ #-------------------------------------------------------------------------
+ # third job
+ #-------------------------------------------------------------------------
+ - name: "Run demo"
+
+ if: branch = master
+
script:
- - remark ./docs/ --frail
\ No newline at end of file
+ - cd demos/MoAE
+ - octave $OCTFLAGS --eval "MoAEpilot_run"
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index a63e8576..00000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,178 +0,0 @@
-# Changelog
-
-## [Unreleased](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/HEAD)
-
-[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.3...HEAD)
-
-**Closed issues:**
-
-- add code coverage
- [\#77](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/77)
-- getData :Accommidate scripts for structural analysis \(without funtional\).
- [\#68](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/68)
-
-**Merged pull requests:**
-
-- 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))
-- 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))
-- 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))
-- add octave in dependencies
- [\#71](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/71)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- 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))
-- update print credit
- [\#63](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/63)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- update DOI
- [\#62](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/62)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- update DOI badge
- [\#61](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/61)
- ([Remi-Gau](https://github.com/Remi-Gau))
-
-## [v0.0.3](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.3) (2019-11-28)
-
-[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.2...v0.0.3)
-
-**Merged pull requests:**
-
-- 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))
-
-## [v0.0.2](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.2) (2019-11-26)
-
-[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/v0.0.1...v0.0.2)
-
-**Merged pull requests:**
-
-- Create LICENSE
- [\#58](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/58)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- 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))
-
-## [v0.0.1](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/tree/v0.0.1) (2019-11-13)
-
-[Full Changelog](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/compare/8ca4e1b47af1d983cde988bae1a9bd9659151330...v0.0.1)
-
-**Implemented enhancements:**
-
-- refactor getRuns, getSessions, getFilenames
- [\#9](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/9)
-- find a way to specify the contrasts to compute
- [\#11](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/11)
-- 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))
-- 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))
-
-**Closed issues:**
-
-- spm_jsonread issue
- [\#54](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/54)
-- \[WORKSHOP 2019\] - to do list
- [\#48](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/48)
-- \[WORKSHOP 2019\] - MVPA
- [\#47](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/47)
-- \[WORKSHOP 2019\] - sharing data
- [\#46](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/46)
-- changes way subjects are indexed in getData
- [\#44](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/44)
-- Add Moh as contributors
- [\#37](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/37)
-- add Marco as contributors
- [\#35](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/35)
-- getData issue with 2 groups
- [\#22](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/22)
-- 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)
-- 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)
-- test with octave
- [\#5](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/5)
-- export final results as NIDM results to facilitate upload to neurovault
- [\#52](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/issues/52)
-- 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)
-- 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)
-
-**Merged pull requests:**
-
-- BIDS results
- [\#55](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/55)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- \[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))
-- 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))
-- 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))
-- 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))
-- 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))
-- 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))
-- 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))
-- 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))
-- 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))
-- 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))
-- update doc
- [\#24](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/24)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- - 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))
-- Ane getsessions merge
- [\#19](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/19)
- ([anege](https://github.com/anege))
-- Dockerfile and option defaults
- [\#16](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/16)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- 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))
-- 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))
-- 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))
-- delete extra getOptions
- [\#8](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/8)
- ([Remi-Gau](https://github.com/Remi-Gau))
-- Split into 3 repos
- [\#1](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/pull/1)
- ([Remi-Gau](https://github.com/Remi-Gau))
-
-\* _This Changelog was automatically generated by
-[github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)_
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 345742f1..88b79e16 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,3 +8,339 @@ is partly created using the bash script `createDummyDataSet.sh`.
## Changelog
+
+
diff --git a/README.md b/README.md
index d282e2c1..8ee55558 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+
+
**Code quality and style**
[](https://github.com/cpp-lln-lab/CPP_BIDS_SPM_pipeline/actions)
@@ -20,6 +22,8 @@
+
+
# CPPL SPM12 Pipeline
This is a set of functions to fMRI analysis on a
@@ -28,18 +32,30 @@ This is a set of functions to fMRI analysis on a
This can perform:
- slice timing correction,
+
- spatial preprocessing:
- - realignment, coregistration `func` to `anat`, `anat` segmention,
+
+ - realignment, coregistration `func` to `anat`, `anat` segmentation,
normalization to MNI space
- - realignm and unwarp, coregistration `func` to `anat`, `anat` segmention
+
+ - realignm and unwarp, coregistration `func` to `anat`, `anat`
+ segmentation
+
- smoothing,
+
- Quality analysis:
+
- for anatomical data
- for functional data
+
- GLM at the subject level
-- GLM at the group level à la SPM (meaning using a summary statistics approach).
-Please see our [documentation](https://cpp-bids-spm.readthedocs.io/en/latest/index.html) for more info.
+- GLM at the group level à la SPM (meaning using a summary statistics
+ approach).
+
+Please see our
+[documentation](https://cpp-bids-spm.readthedocs.io/en/latest/index.html) for
+more info.
The core functions are in the `src` folder.
@@ -52,6 +68,8 @@ path.
For instructions see the following links:
+
+
| Dependencies | Used version |
| ----------------------------------------------------------------------------------------- | ------------ |
| [Matlab](https://www.mathworks.com/products/matlab.html) | 20??? |
@@ -60,14 +78,15 @@ For instructions see the following links:
| [Tools for NIfTI and ANALYZE image toolbox](https://github.com/sergivalverde/nifti_tools) | NA |
| [spmup](https://github.com/CPernet/spmup) | NA |
+
-## Contributors ✨
+## Contributors
Thanks goes to these wonderful people
([emoji key](https://allcontributors.org/docs/en/emoji-key)):
-
+
-
+
This project follows the
diff --git a/demos/MoAE/MoAEpilot_run.m b/demos/MoAE/MoAEpilot_run.m
index 641747ba..59e7c9b6 100644
--- a/demos/MoAE/MoAEpilot_run.m
+++ b/demos/MoAE/MoAEpilot_run.m
@@ -32,31 +32,31 @@
opt.space = 'individual';
%% Get data
-% fprintf('%-40s:', 'Downloading dataset...');
-% urlwrite(URL, 'MoAEpilot.zip');
+fprintf('%-40s:', 'Downloading dataset...');
+urlwrite(URL, 'MoAEpilot.zip');
unzip('MoAEpilot.zip', fullfile(WD, 'output'));
checkDependencies();
%% Run batches
-% reportBIDS(opt);
+reportBIDS(opt);
+bidsCopyRawFolder(opt, 1);
-% bidsCopyRawFolder(opt, 1);
-
-bidsSegmentSkullStrip(opt);
-
-return
+% In case you just want to run segmentation and skull stripping
+% bidsSegmentSkullStrip(opt);
bidsSTC(opt);
bidsSpatialPrepro(opt);
-anatomicalQA(opt);
-bidsResliceTpmToFunc(opt);
-functionalQA(opt);
+% The following do not run on octave for now (because of spmup)
+% anatomicalQA(opt);
+% bidsResliceTpmToFunc(opt);
+% functionalQA(opt);
bidsSmoothing(FWHM, opt);
-bidsFFX('specifyAndEstimate', opt, FWHM);
-bidsFFX('contrasts', opt, FWHM);
-bidsResults(opt, FWHM);
+% The following crash on Travis CI
+% bidsFFX('specifyAndEstimate', opt, FWHM);
+% bidsFFX('contrasts', opt, FWHM);
+% bidsResults(opt, FWHM);
diff --git a/demos/openneuro/ds000001_getOption.m b/demos/openneuro/ds000001_getOption.m
index 07be6d40..6de06884 100644
--- a/demos/openneuro/ds000001_getOption.m
+++ b/demos/openneuro/ds000001_getOption.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function opt = ds000001_getOption()
% returns a structure that contains the options chosen by the user to run
diff --git a/demos/openneuro/ds000001_run.m b/demos/openneuro/ds000001_run.m
index c9201d39..a8b7f066 100644
--- a/demos/openneuro/ds000001_run.m
+++ b/demos/openneuro/ds000001_run.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
% runDs00014
diff --git a/demos/openneuro/ds000114_getOption.m b/demos/openneuro/ds000114_getOption.m
index 626aa34a..816f0561 100644
--- a/demos/openneuro/ds000114_getOption.m
+++ b/demos/openneuro/ds000114_getOption.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function opt = ds000114_getOption()
% returns a structure that contains the options chosen by the user to run
diff --git a/demos/openneuro/ds000114_run.m b/demos/openneuro/ds000114_run.m
index dc4b0424..c0fcbe27 100644
--- a/demos/openneuro/ds000114_run.m
+++ b/demos/openneuro/ds000114_run.m
@@ -1,10 +1,9 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
% runDs00014
clear;
clc;
-close all;
% Smoothing to apply
FWHM = 6;
diff --git a/demos/openneuro/ds001168_getOption.m b/demos/openneuro/ds001168_getOption.m
new file mode 100644
index 00000000..2f0ce7b8
--- /dev/null
+++ b/demos/openneuro/ds001168_getOption.m
@@ -0,0 +1,29 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function opt = ds001168_getOption()
+ % returns a structure that contains the options chosen by the user to run
+ % slice timing correction, pre-processing, FFX, RFX.
+
+ if nargin < 1
+ opt = [];
+ end
+
+ % The directory where the data are located
+ opt.dataDir = '/home/remi/openneuro/ds001168/raw';
+
+ % suject to run in each group
+ opt.subjects = {'01'};
+
+ % task to analyze
+ opt.taskName = 'rest';
+
+ opt.anatReference.type = 'T1w';
+ opt.anatReference.session = 1;
+
+ opt.ignoreFieldmaps = false;
+
+ %% DO NOT TOUCH
+ opt = checkOptions(opt);
+ % saveOptions(opt);
+
+end
diff --git a/demos/openneuro/ds001168_run.m b/demos/openneuro/ds001168_run.m
new file mode 100644
index 00000000..305e1a10
--- /dev/null
+++ b/demos/openneuro/ds001168_run.m
@@ -0,0 +1,49 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+% runDs001168
+
+clear;
+clc;
+
+% Smoothing to apply
+FWHM = 6;
+
+% directory with this script becomes the current directory
+WD = fileparts(mfilename('fullpath'));
+
+% we add all the subfunctions that are in the sub directories
+addpath(fullfile(WD, '..'));
+addpath(genpath(fullfile(WD, '..', 'src')));
+addpath(genpath(fullfile(WD, '..', 'lib')));
+
+%% Set options
+opt = ds001168_getOption();
+
+% the line below allows to run preprocessing in "native" space.
+% - use realign and unwarp
+% - don't do normalization
+opt.space = 'individual';
+
+checkDependencies();
+
+%% Run batches
+
+reportBIDS(opt);
+
+bidsCopyRawFolder(opt, 1);
+
+bidsCreateVDM(opt);
+
+bidsSTC(opt);
+
+bidsSpatialPrepro(opt);
+
+anatomicalQA(opt);
+bidsResliceTpmToFunc(opt);
+functionalQA(opt);
+%
+% bidsSmoothing(FWHM, opt);
+%
+% bidsFFX('specifyAndEstimate', opt, FWHM);
+% bidsFFX('contrasts', opt, FWHM);
+% bidsResults(opt, FWHM, []);
diff --git a/demos/openneuro/openneuro.md b/demos/openneuro/openneuro.md
index fb80298d..c56643b6 100644
--- a/demos/openneuro/openneuro.md
+++ b/demos/openneuro/openneuro.md
@@ -1,13 +1,12 @@
-
Download with datalad
-In case you use the python package for datalad, activate your virtual environment (like conda).
+In case you use the python package for datalad, activate your virtual
+environment (like conda).
```bash
conda activate datalad
```
-
## ds000114
Multi-subject and multi-session dataset.
@@ -26,4 +25,16 @@ datalad get sub-0[12]/*/func/*linebisection*
cd ds000001/
datalad get sub-0[12]/anat/*T1w*
datalad get sub-0[12]/func/*balloonanalogrisktask*
- ```
+```
+
+## ds001168
+
+7T test-retest data set with fieldmaps
+
+```bash
+ datalad clone https://github.com/OpenNeuroDatasets/ds001168.git
+ cd ds001168/
+ datalad get sub-0[12]/ses*/anat/*
+ datalad get sub-0[12]/ses*/func/*fullbrain*
+
+```
diff --git a/docs/README.md b/docs/README.md
index 93621c95..24a540c3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -38,8 +38,8 @@ extensions = [
'sphinx.ext.autodoc']
```
-`matlab_src_dir` in `docs/source/conf.py` should have the path (relative to `conf.py`)
-to the folder containing your matlab code:
+`matlab_src_dir` in `docs/source/conf.py` should have the path (relative to
+`conf.py`) to the folder containing your matlab code:
```python
matlab_src_dir = os.path.dirname(os.path.abspath('../../src'))
@@ -47,29 +47,42 @@ matlab_src_dir = os.path.dirname(os.path.abspath('../../src'))
## reStructured text markup
-reStructured text mark up primers:
+reStructured text mark up primers:
-- on the [sphinx site](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html)
-- more [python oriented](https://pythonhosted.org/an_example_pypi_project/sphinx.html)
+- on the [sphinx site](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html)
-- typical doc strings templates
- - [google way](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html)
- - [numpy](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy)
+- more
+ [python oriented](https://pythonhosted.org/an_example_pypi_project/sphinx.html)
+
+- typical doc strings templates
+ - [google way](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html)
+ - [numpy](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy)
## "Templates"
+The templates to use for the doc are in the `src/templates` folder.
+
You then just need to insert this in your `.rst` file for the documentation to
be done automatically.
```rst
-.. automodule:: src .. <-- This is necessary for autodocumenting the rest
+.. automodule:: src.folder_name .. <-- This is necessary for auto-documenting the rest
-.. autofunction:: my_function
+.. autofunction:: function to document
-.. autofunction:: my_function_napoleon
```
+To get the filenames of all the functions in a folder:
+
+``` bash
+ls -l src/*.m | cut -c42- | rev | cut -c 3- | rev
+```
+
+Increase the `42` to crop more characters at the beginning.
+
+Change the `3` to crop more characters at the end.
+
## Build the documentation locally
From the `docs` directory:
@@ -87,9 +100,9 @@ Add a [`.readthedocs.yml`](../.readthedocs.yml) file in the root of your repo.
See [HERE](https://docs.readthedocs.io/en/stable/config-file/v2.html) for
details.
-You can then trigger the build of the doc by going to the [read the docs]
-website: https://readthedocs.org.
+You can then trigger the build of the doc by going to the
+[read the docs website](https://readthedocs.org).
You might need to be added as a maintainer of the doc.
-The doc can be built from any branch of a repo.
\ No newline at end of file
+The doc can be built from any branch of a repo.
diff --git a/docs/requirements.txt b/docs/requirements.txt
index a4b9ccc8..42ea70da 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,4 +1,5 @@
Sphinx
sphinxcontrib-matlabdomain
sphinxcontrib-napoleon
-sphinx_rtd_theme
\ No newline at end of file
+sphinx_rtd_theme
+miss_hit
\ No newline at end of file
diff --git a/docs/source/batches.rst b/docs/source/batches.rst
index 24cf0162..9da85ccb 100644
--- a/docs/source/batches.rst
+++ b/docs/source/batches.rst
@@ -7,18 +7,25 @@ List of functions to set SPM batches.
.. automodule:: src.batches
-.. autofunction:: setBatchCoregistration
-.. autofunction:: setBatchNormalize
-.. autofunction:: setBatchSegmentation
+.. autofunction:: setBatchComputeVDM
+.. autofunction:: setBatchCoregistrationFmap
+.. autofunction:: setBatchCoregistrationFuncToAnat
+.. autofunction:: setBatchCoregistration
+.. autofunction:: setBatchCreateVDMs
+.. autofunction:: setBatchFactorialDesign
+.. autofunction:: setBatchImageCalculation
+.. autofunction:: setBatchMeanAnatAndMask
+.. autofunction:: setBatchNormalizationSpatialPrepro
+.. autofunction:: setBatchNormalize
+.. autofunction:: setBatchRealign
+.. autofunction:: setBatchReslice
+.. autofunction:: setBatchSaveCoregistrationMatrix
+.. autofunction:: setBatchSegmentation
+.. autofunction:: setBatchSelectAnat
+.. autofunction:: setBatchSkullStripping
+.. autofunction:: setBatchSmoothConImages
+.. autofunction:: setBatchSmoothing
.. autofunction:: setBatchSTC
-.. autofunction:: setBatchFactorialDesign
-.. autofunction:: setBatchRealign
-.. autofunction:: setBatchSelectAnat
.. autofunction:: setBatchSubjectLevelContrasts
-.. autofunction:: setBatchMeanAnatAndMask
-.. autofunction:: setBatchReslice
-.. autofunction:: setBatchSmoothConImages
-.. autofunction:: setBatchSubjectLevelGLMSpec
-.. autofunction:: setBatchNormalizationSpatialPrepro
-.. autofunction:: setBatchSaveCoregistrationMatrix
-.. autofunction:: setBatchSmoothing
\ No newline at end of file
+.. autofunction:: setBatchSubjectLevelGLMSpec
+
\ No newline at end of file
diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst
index 1b2439b6..d9855ed0 100644
--- a/docs/source/contributing.rst
+++ b/docs/source/contributing.rst
@@ -17,26 +17,26 @@ Template proposal
% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [argout1, argout2] = templateFunction(argin1, argin2, argin3)
- %
- % Short description of what the function does goes here.
- %
- % USAGE:
+ %
+ % Short description of what the function does goes here.
+ %
+ % USAGE::
%
% [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3])
%
- % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet,
+ % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet,
% consectetur adipiscing elit. Ut congue nec est ac lacinia.
% :type argin1: type
- % :param argin2: optional argument and its default value. And some of the
+ % :param argin2: optional argument and its default value. And some of the
% options can be shown in litteral like ``this`` or ``that``.
% :type argin2: string
- % :param argin3: (dimension) optional argument
+ % :param argin3: (dimension) optional argument
%
- % :returns: - :argout1: (type) (dimension)
- % - :argout2: (type) (dimension)
+ % :returns: - :argout1: (type) (dimension)
+ % - :argout2: (type) (dimension)
%
% .. todo:
- %
+ %
% - item 1
% - item 2
diff --git a/docs/source/defaults.rst b/docs/source/defaults.rst
index 9956589a..85a1cc81 100644
--- a/docs/source/defaults.rst
+++ b/docs/source/defaults.rst
@@ -7,6 +7,10 @@ Defaults of the pipeline.
.. automodule:: src.defaults
+checkOptions
+============
+
+.. autofunction:: checkOptions
spm_my_defaults
===============
@@ -28,3 +32,4 @@ pipeline.
.. autofunction:: spm_my_defaults
+
diff --git a/docs/source/function_description.rst b/docs/source/function_description.rst
index 3ea62825..10745525 100644
--- a/docs/source/function_description.rst
+++ b/docs/source/function_description.rst
@@ -1,34 +1,76 @@
Function description
-====================
+********************
List of functions in the ``src`` folder.
----
.. automodule:: src
-
-.. autofunction:: getBoldFilenameForFFX
-.. autofunction:: getMeanFuncFilename
-.. autofunction:: printProcessingRun
-.. autofunction:: specifyContrasts
-.. autofunction:: concatBetaImgTmaps
-.. autofunction:: getBoldFilename
-.. autofunction:: getPrefix
-.. autofunction:: printProcessingSubject
+
+.. autofunction:: getAnatFilename
+.. autofunction:: getBoldFilename
+.. autofunction:: getData
+.. autofunction:: getFuncVoxelDims
+.. autofunction:: getInfo
+.. autofunction:: getMeanFuncFilename
+.. autofunction:: getPrefix
+.. autofunction:: getRealignParamFile
+.. autofunction:: getSliceOrder
+.. autofunction:: getSpecificSubjects
+.. autofunction:: setDerivativesDir
.. autofunction:: unzipImgAndReturnsFullpathName
-.. autofunction:: convertOnsetTsvToMat
-.. autofunction:: getData
-.. autofunction:: getRealignParamFile
-.. autofunction:: createAndReturnOnsetFile
-.. autofunction:: getFFXdir
-.. autofunction:: getRFXdir
-.. autofunction:: reportBIDS
-.. autofunction:: getFuncVoxelDims
-.. autofunction:: getSliceOrder
-.. autofunction:: deleteResidualImages
-.. autofunction:: getGrpLevelContrastToCompute
-.. autofunction:: getSpecificSubjects
+
+Subject level model
+===================
+
+.. automodule:: src.subject_level
+
+.. autofunction:: concatBetaImgTmaps
+.. autofunction:: convertOnsetTsvToMat
+.. autofunction:: createAndReturnOnsetFile
+.. autofunction:: deleteResidualImages
+.. autofunction:: getBoldFilenameForFFX
+.. autofunction:: getFFXdir
+.. autofunction:: specifyContrasts
+
+Group level model
+=================
+
+.. automodule:: src.group_level
+
+.. autofunction:: getGrpLevelContrastToCompute
+.. autofunction:: getRFXdir
+
+
+fieldmaps
+=========
+
+.. automodule:: src.fieldmaps
+
+.. autofunction:: getBlipDirection
+.. autofunction:: getMetadataFromIntendedForFunc
+.. autofunction:: getTotalReadoutTime
+.. autofunction:: getVdmFile
+
+Utilities
+=========
+
+Utility functions
+
+----
+
+.. automodule:: src.utils
+
+.. autofunction:: checkDependencies
+.. autofunction:: createDataDictionary
+.. autofunction:: getEnvInfo
+.. autofunction:: getVersion
+.. autofunction:: isOctave
+.. autofunction:: loadAndCheckOptions
+.. autofunction:: printCredits
+.. autofunction:: printProcessingRun
+.. autofunction:: printProcessingSubject
.. autofunction:: saveMatlabBatch
-.. autofunction:: getAnatFilename
-.. autofunction:: getInfo
-.. autofunction:: setDerivativesDir
\ No newline at end of file
+.. autofunction:: saveOptions
+.. autofunction:: setDefaultFields
+.. autofunction:: validationInputFile
diff --git a/docs/source/index.rst b/docs/source/index.rst
index a40529c8..aafb80c3 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -7,8 +7,8 @@ Welcome to CPP SPM BIDS pipeline documentation!
***********************************************
.. toctree::
- :maxdepth: 3
- :caption: Contentset_up
+ :maxdepth: 2
+ :caption: Content
set_up
workflows
@@ -18,7 +18,6 @@ Welcome to CPP SPM BIDS pipeline documentation!
function_description
method_section_boilerplate
mancoreg
- utils
docker
contributing
diff --git a/docs/source/method_section_boilerplate.rst b/docs/source/method_section_boilerplate.rst
index bf90cbe6..aacb8fbc 100644
--- a/docs/source/method_section_boilerplate.rst
+++ b/docs/source/method_section_boilerplate.rst
@@ -1,6 +1,12 @@
Boilerplate methods section
***************************
+Use the report function to get a print out of the content of a dataset.
+
+.. automodule:: src.reports
+
+.. autofunction:: reportBIDS
+
Preprocessing
=============
diff --git a/docs/source/utils.rst b/docs/source/utils.rst
deleted file mode 100644
index 3c67325f..00000000
--- a/docs/source/utils.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-Utilities
-=========
-
-Utilities functions
-
-----
-
-.. automodule:: src.utils
-
-.. autofunction:: checkDependencies
-.. autofunction:: createDataDictionary
-.. autofunction:: getVersion
-.. autofunction:: loadAndCheckOptions
-.. autofunction:: saveOptions
-.. autofunction:: validationInputFile
-.. autofunction:: checkOptions
-.. autofunction:: getEnvInfo
-.. autofunction:: isOctave
-.. autofunction:: printCredits
-.. autofunction:: setDefaultFields
-
-
diff --git a/docs/source/workflows.rst b/docs/source/workflows.rst
index 0f6e6367..21f5872c 100644
--- a/docs/source/workflows.rst
+++ b/docs/source/workflows.rst
@@ -116,5 +116,7 @@ Comput results
---
.. autofunction:: bidsRealignReslice
-
-.. autofunction:: bidsRealignUnwarp
\ No newline at end of file
+.. autofunction:: bidsRealignUnwarp
+.. autofunction:: bidsCreateVDM
+.. autofunction:: bidsResliceTpmToFunc
+.. autofunction:: bidsSegmentSkullStrip
diff --git a/getOption_template b/getOption_template
deleted file mode 100644
index 15be3d13..00000000
--- a/getOption_template
+++ /dev/null
@@ -1,47 +0,0 @@
-function opt = getOption()
-% returns a structure that contains the options chosen by the user to return
-% the different workflows
-
-if nargin<1
- opt = [];
-end
-
-% group of subjects to analyze
-opt.groups = {''};
-% suject to run in each group
-opt.subjects = {[]};
-
-% task to analyze
-opt.taskName = 'balloonanalogrisktask';
-
-% The directory where the data are located
-opt.dataDir = '/home/remi/BIDS/ds001/rawdata';
-
-% Options for slice time correction
-% If left unspecified the slice timing will be done using the mid-volume acquisition
-% time point as reference.
-% Slice order must be entered in time unit (ms) (this is the BIDS way of doing things)
-% instead of the slice index of the reference slice (the "SPM" way of doing things).
-% More info here: https://en.wikibooks.org/wiki/SPM/Slice_Timing
-opt.sliceOrder = [];
-opt.STC_referenceSlice = [];
-
-% Options for normalize
-% Voxel dimensions for resampling at normalization of functional data or leave empty [ ].
-opt.funcVoxelDims = [];
-
-% specify the model file that contains the contrasts to compute
-opt.model.univariate.file = fullfile(fileparts(mfilename('fullpath')), 'model', model-balloonanalogriskUnivariate_smdl.json');
-
-% specify the result to compute
-opt.result.Steps(1) = struct(...
- 'Level', 'dataset', ...
- 'Contrasts', struct(...
- 'Name', 'pumps_demean', ... % has to match
- 'Mask', false, ... % this might need improving if a mask is required
- 'MC', 'none', ... FWE, none, FDR
- 'p', 0.05, ...
- 'k', 0, ...
- 'NIDM', true) );
-
-end
diff --git a/lib/bids-matlab b/lib/bids-matlab
index dd04a370..cc946cf7 160000
--- a/lib/bids-matlab
+++ b/lib/bids-matlab
@@ -1 +1 @@
-Subproject commit dd04a3709dcbfd04255cd43ef1caced94872ddc8
+Subproject commit cc946cf7d63c5ad42aa7258ef4ef73a2d24c97e5
diff --git a/runTests.m b/runTests.m
index ea84f508..ac531bf4 100644
--- a/runTests.m
+++ b/runTests.m
@@ -2,10 +2,6 @@
warning('OFF');
-addpath(fullfile(pwd, 'spm12'));
-addpath(genpath(fullfile(pwd, 'src')));
-addpath(genpath(fullfile(pwd, 'lib')));
-
spm('defaults', 'fMRI');
folderToCover = fullfile(pwd, 'src');
diff --git a/src/QA/anatomicalQA.m b/src/QA/anatomicalQA.m
index 0c3eb686..c8336812 100644
--- a/src/QA/anatomicalQA.m
+++ b/src/QA/anatomicalQA.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function anatomicalQA(opt)
% anatomicalQA(opt)
diff --git a/src/QA/functionalQA.m b/src/QA/functionalQA.m
index baf04c41..ed016a9b 100644
--- a/src/QA/functionalQA.m
+++ b/src/QA/functionalQA.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function functionalQA(opt)
% functionalQA(opt)
diff --git a/src/batches/setBatchComputeVDM.m b/src/batches/setBatchComputeVDM.m
new file mode 100644
index 00000000..2c840c1b
--- /dev/null
+++ b/src/batches/setBatchComputeVDM.m
@@ -0,0 +1,65 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchComputeVDM(matlabbatch, fmapType, refImage)
+ % matlabbatch = setBatchComputeVDM(type)
+ %
+ % adapted from spmup get_FM_workflow.m (@ commit
+ % 198c980d6d7520b1a996f0e56269e2ceab72cc83)
+
+ switch lower(fmapType)
+ case 'phasediff'
+ matlabbatch{end + 1}.spm.tools.fieldmap.calculatevdm.subj(1).data.presubphasemag.phase = '';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).data.presubphasemag.magnitude = '';
+
+ case 'phase&mag'
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).data.phasemag.shortphase = '';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).data.phasemag.shortmag = '';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).data.phasemag.longphase = '';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).data.phasemag.longmag = '';
+
+ otherwise
+ error('This type of field map is not handled: %s', fmapType);
+ end
+
+ UF = struct( ...
+ 'method', 'Mark3D', ...
+ 'fwhm', 10, ...
+ 'pad', 0, ...
+ 'ws', 1);
+
+ MF = struct( ...
+ 'fwhm', 5, ...
+ 'nerode', 2, ...
+ 'ndilate', 4, ...
+ 'thresh', 0.5, ...
+ 'reg', 0.02);
+
+ defaultsval = struct( ...
+ 'et', [NaN NaN], ...
+ 'maskbrain', 1, ...
+ 'blipdir', 1, ...
+ 'tert', '', ...
+ 'epifm', 0, ... % can be changed
+ 'ajm', 0, ...
+ 'uflags', UF, ...
+ 'mflags', MF);
+
+ fieldMapTemplate = spm_select( ...
+ 'FPList', ...
+ fullfile( ...
+ spm('dir'), ...
+ 'toolbox', ...
+ 'FieldMap'), ...
+ '^T1.nii$');
+ defaultsval.mflags.template = { fieldMapTemplate };
+
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).defaults.defaultsval = defaultsval;
+
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).session.epi = {refImage};
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).matchvdm = 1;
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).sessname = 'vdm-';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).writeunwarped = 1;
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).anat = '';
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj(1).matchanat = 0;
+
+end
diff --git a/src/batches/setBatchCoregistration.m b/src/batches/setBatchCoregistration.m
index a9438f8c..5cb17502 100644
--- a/src/batches/setBatchCoregistration.m
+++ b/src/batches/setBatchCoregistration.m
@@ -1,76 +1,14 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
-
-function matlabbatch = setBatchCoregistration(matlabbatch, BIDS, subID, opt)
-
- fprintf(1, ' BUILDING SPATIAL JOB : COREGISTER\n');
-
- matlabbatch{end + 1}.spm.spatial.coreg.estimate.ref(1) = ...
- cfg_dep('Named File Selector: Anatomical(1) - Files', ...
- substruct( ...
- '.', 'val', '{}', {opt.orderBatches.selectAnat}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}), ...
- substruct('.', 'files', '{}', {1}));
-
- % SOURCE IMAGE : DEPENDENCY FROM REALIGNEMENT
- % Mean Image
-
- meanImageToUse = 'rmean';
- otherImageToUse = 'cfiles';
- if strcmp(opt.space, 'individual')
- meanImageToUse = 'meanuwr';
- otherImageToUse = 'uwrfiles';
- end
-
- matlabbatch{end}.spm.spatial.coreg.estimate.source(1) = ...
- cfg_dep('Realign: Estimate & Reslice/Unwarp: Mean Image', ...
- substruct( ...
- '.', 'val', '{}', {opt.orderBatches.realign}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}), ...
- substruct('.', meanImageToUse));
-
- % OTHER IMAGES : DEPENDENCY FROM REALIGNEMENT
-
- [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions');
-
- runCounter = 1;
-
- for iSes = 1:nbSessions
-
- % get all runs for that subject for this session
- [~, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes});
-
- for iRun = 1:nbRuns
-
- matlabbatch{end}.spm.spatial.coreg.estimate.other(runCounter) = ...
- cfg_dep([ ...
- 'Realign: Estimate & Reslice/Unwarp: Realigned Images (Sess ', ...
- num2str(runCounter), ...
- ')'], ...
- substruct( ...
- '.', 'val', '{}', {opt.orderBatches.realign}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}, ...
- '.', 'val', '{}', {1}), ...
- substruct( ...
- '.', 'sess', '()', {runCounter}, ...
- '.', otherImageToUse));
-
- runCounter = runCounter + 1;
-
- end
-
- end
-
- % The following lines are commented out because those parameters
- % can be set in the spm_my_defaults.m
- % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';
- % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];
- % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.tol = ...
- % [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];
- % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchCoregistration(matlabbatch, ref, src, other)
+ % matlabbatch = setBatchCoregistrationGeneral(matlabbatch, ref, src, other)
+ %
+ % ref: string
+ % src: string
+ % other: cell string
+
+ matlabbatch{end + 1}.spm.spatial.coreg.estimate.ref = { ref };
+ matlabbatch{end}.spm.spatial.coreg.estimate.source = { src };
+ matlabbatch{end}.spm.spatial.coreg.estimate.other = other;
end
diff --git a/src/batches/setBatchCoregistrationFmap.m b/src/batches/setBatchCoregistrationFmap.m
new file mode 100644
index 00000000..4e73a142
--- /dev/null
+++ b/src/batches/setBatchCoregistrationFmap.m
@@ -0,0 +1,53 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchCoregistrationFmap(BIDS, opt, subID)
+
+ % TODO
+ % assumes all the fieldmap relate to the current task
+ % - use the "for" metadata field
+ % - implement for 'phase12', 'fieldmap', 'epi'
+
+ fprintf(1, ' FIELDMAP WORKFLOW: COREGISTERING FIELD MAPS TO FIRST FUNC IMAGE\n');
+
+ % Create rough mean of the 1rst run to improve SNR for coregistration
+ % TODO use the slice timed EPI if STC was used ?
+ [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions');
+ runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1});
+ [fileName, subFuncDataDir] = getBoldFilename(BIDS, subID, sessions{1}, runs{1}, opt);
+
+ spmup_basics(fullfile(subFuncDataDir, fileName), 'mean');
+
+ refImage = fullfile(subFuncDataDir, ['mean_', fileName]);
+
+ matlabbatch = [];
+
+ for iSes = 1:nbSessions
+
+ runs = spm_BIDS(BIDS, 'runs', ...
+ 'modality', 'fmap', ...
+ 'sub', subID, ...
+ 'ses', sessions{iSes});
+
+ for iRun = 1:numel(runs)
+
+ % TODO
+ % - Move to getInfo
+ fmapFiles = spm_BIDS(BIDS, 'data', ...
+ 'modality', 'fmap', ...
+ 'sub', subID, ...
+ 'ses', sessions{iSes}, ...
+ 'run', runs{iRun});
+
+ srcImage = strrep(fmapFiles{1}, 'phasediff', 'magnitude1');
+
+ otherImages = cell(2, 1);
+ otherImages{1} = strrep(fmapFiles{1}, 'phasediff', 'magnitude2');
+ otherImages{2} = fmapFiles{1};
+
+ matlabbatch = setBatchCoregistration(matlabbatch, refImage, srcImage, otherImages);
+
+ end
+
+ end
+
+end
diff --git a/src/batches/setBatchCoregistrationFuncToAnat.m b/src/batches/setBatchCoregistrationFuncToAnat.m
new file mode 100644
index 00000000..40e11635
--- /dev/null
+++ b/src/batches/setBatchCoregistrationFuncToAnat.m
@@ -0,0 +1,76 @@
+% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, subID, opt)
+
+ fprintf(1, ' BUILDING SPATIAL JOB : COREGISTER\n');
+
+ matlabbatch{end + 1}.spm.spatial.coreg.estimate.ref(1) = ...
+ cfg_dep('Named File Selector: Anatomical(1) - Files', ...
+ substruct( ...
+ '.', 'val', '{}', {opt.orderBatches.selectAnat}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}), ...
+ substruct('.', 'files', '{}', {1}));
+
+ % SOURCE IMAGE : DEPENDENCY FROM REALIGNEMENT
+ % Mean Image
+
+ meanImageToUse = 'rmean';
+ otherImageToUse = 'cfiles';
+ if strcmp(opt.space, 'individual')
+ meanImageToUse = 'meanuwr';
+ otherImageToUse = 'uwrfiles';
+ end
+
+ matlabbatch{end}.spm.spatial.coreg.estimate.source(1) = ...
+ cfg_dep('Realign: Estimate & Reslice/Unwarp: Mean Image', ...
+ substruct( ...
+ '.', 'val', '{}', {opt.orderBatches.realign}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}), ...
+ substruct('.', meanImageToUse));
+
+ % OTHER IMAGES : DEPENDENCY FROM REALIGNEMENT
+
+ [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions');
+
+ runCounter = 1;
+
+ for iSes = 1:nbSessions
+
+ % get all runs for that subject for this session
+ [~, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes});
+
+ for iRun = 1:nbRuns
+
+ matlabbatch{end}.spm.spatial.coreg.estimate.other(runCounter) = ...
+ cfg_dep([ ...
+ 'Realign: Estimate & Reslice/Unwarp: Realigned Images (Sess ', ...
+ num2str(runCounter), ...
+ ')'], ...
+ substruct( ...
+ '.', 'val', '{}', {opt.orderBatches.realign}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}, ...
+ '.', 'val', '{}', {1}), ...
+ substruct( ...
+ '.', 'sess', '()', {runCounter}, ...
+ '.', otherImageToUse));
+
+ runCounter = runCounter + 1;
+
+ end
+
+ end
+
+ % The following lines are commented out because those parameters
+ % can be set in the spm_my_defaults.m
+ % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';
+ % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];
+ % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.tol = ...
+ % [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];
+ % matlabbatch{end}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];
+
+end
diff --git a/src/batches/setBatchCreateVDMs.m b/src/batches/setBatchCreateVDMs.m
new file mode 100644
index 00000000..79d782df
--- /dev/null
+++ b/src/batches/setBatchCreateVDMs.m
@@ -0,0 +1,119 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchCreateVDMs(BIDS, opt, subID)
+ %
+ % Short description of what the function does goes here.
+ %
+ % USAGE::
+ %
+ % matlabbatch = setBatchCreateVDMs(BIDS, opt, subID)
+ %
+ % :param BIDS:
+ % :type BIDS: structure
+ % :param opt:
+ % :type opt: structure
+ % :param subID:
+ %
+ % :returns: - :matlabbatch: (structure) (dimension)
+ %
+ % TODO
+ % assumes all the fieldmap relate to the current task
+ % - implement for 'phase12', 'fieldmap', 'epi'
+
+ fprintf(1, ' FIELDMAP WORKFLOW: CREATING VDMs \n');
+
+ [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions');
+
+ runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1});
+ [fileName, subFuncDataDir] = getBoldFilename(BIDS, subID, sessions{1}, runs{1}, opt);
+ refImage = validationInputFile(subFuncDataDir, fileName, 'mean_');
+
+ matlabbatch = [];
+ for iSes = 1:nbSessions
+
+ runs = spm_BIDS(BIDS, 'runs', ...
+ 'modality', 'fmap', ...
+ 'sub', subID, ...
+ 'ses', sessions{iSes});
+
+ for iRun = 1:numel(runs)
+
+ matlabbatch = setBatchComputeVDM(matlabbatch, 'phasediff', refImage);
+
+ % TODO
+ % Move to getInfo ?
+ fmapFiles = spm_BIDS(BIDS, 'data', ...
+ 'modality', 'fmap', ...
+ 'sub', subID, ...
+ 'ses', sessions{iSes}, ...
+ 'run', runs{iRun});
+
+ phaseImage = fmapFiles{1};
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.data.presubphasemag.phase = ...
+ {phaseImage};
+
+ magnitudeImage = strrep(phaseImage, 'phasediff', 'magnitude1');
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.data.presubphasemag.magnitude = ...
+ {magnitudeImage};
+
+ [echotimes, isEPI, totReadTime, blipDir] = getMetadataForVDM(BIDS, ...
+ subID, ...
+ sessions{iSes}, ...
+ runs{iRun});
+
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.defaults.defaultsval.et = echotimes;
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.defaults.defaultsval.tert = totReadTime;
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.defaults.defaultsval.blipdir = blipDir;
+ matlabbatch{end}.spm.tools.fieldmap.calculatevdm.subj.defaults.defaultsval.epifm = isEPI;
+
+ end
+
+ end
+
+end
+
+function varargout = getMetadataForVDM(BIDS, subID, sessionID, runID)
+
+ % get metadata fmap and its associated func files
+ fmapMetadata = spm_BIDS(BIDS, 'metadata', ...
+ 'modality', 'fmap', ...
+ 'sub', subID, ...
+ 'ses', sessionID, ...
+ 'run', runID);
+ if numel(fmapMetadata) > 1
+ fmapMetadata = fmapMetadata{1};
+ end
+
+ echotimes = getEchoTimes(fmapMetadata);
+
+ isEPI = checkFmapPulseSequenceType(fmapMetadata);
+
+ varargout{1} = echotimes;
+ varargout{2} = isEPI;
+
+ [totalReadoutTime, blipDir] = getMetadataFromIntendedForFunc(BIDS, fmapMetadata);
+
+ varargout{3} = totalReadoutTime;
+ varargout{4} = blipDir;
+
+end
+
+function echotimes = getEchoTimes(fmapMetadata)
+
+ echotimes = 1000 * [ ...
+ fmapMetadata.EchoTime1, ...
+ fmapMetadata.EchoTime2]; % in milliseconds
+
+end
+
+function isEPI = checkFmapPulseSequenceType(fmapMetadata)
+
+ isEPI = 0;
+
+ if isfield(fmapMetadata, 'PulseSequenceType') && ...
+ sum(strfind(fmapMetadata.PulseSequenceType, 'EPI')) ~= 0
+
+ isEPI = 1;
+ end
+
+end
diff --git a/src/batches/setBatchImageCalculation.m b/src/batches/setBatchImageCalculation.m
new file mode 100644
index 00000000..076af5e4
--- /dev/null
+++ b/src/batches/setBatchImageCalculation.m
@@ -0,0 +1,16 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function matlabbatch = setBatchImageCalculation(matlabbatch, input, output, outDir, expression)
+
+ matlabbatch{end + 1}.spm.util.imcalc.input = input;
+ matlabbatch{end}.spm.util.imcalc.output = output;
+ matlabbatch{end}.spm.util.imcalc.outdir = { outDir };
+ matlabbatch{end}.spm.util.imcalc.expression = expression;
+
+ % matlabbatch{1}.spm.util.imcalc.var = struct('name', {}, 'value', {});
+ % matlabbatch{1}.spm.util.imcalc.options.dmtx = 0;
+ % matlabbatch{1}.spm.util.imcalc.options.mask = 0;
+ % matlabbatch{1}.spm.util.imcalc.options.interp = 1;
+ % matlabbatch{1}.spm.util.imcalc.options.dtype = 4;
+
+end
diff --git a/src/batches/setBatchRealign.m b/src/batches/setBatchRealign.m
index cc6c9f33..7c9c5610 100644
--- a/src/batches/setBatchRealign.m
+++ b/src/batches/setBatchRealign.m
@@ -1,13 +1,35 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
-function [matlabbatch, voxDim] = setBatchRealign(matlabbatch, BIDS, subID, opt, action)
- % [matlabbatch, voxDim] = setBatchRealign(matlabbatch, BIDS, subID, opt, action)
+function [matlabbatch, voxDim] = setBatchRealign(varargin)
%
- % to set the batch in a spatial preprocessing pipeline
+ % Set the batch for realign / realign and reslice / realign and unwarp
%
- % Assumption about the order of the sessions:
+ % USAGE::
+ %
+ % [matlabbatch, voxDim] = setBatchRealign(matlabbatch, BIDS, subID, opt, [action = 'realign'])
+ %
+ % :param matlabbatch: SPM batch
+ % :type matlabbatch: structure
+ % :param BIDS: BIDS layout returned by ``getData``
+ % :type BIDS: structure
+ % :param subID: subject label
+ % :type subID: string
+ % :param opt: options
+ % :type opt: structure
+ % :param action: ``realign``, ``realignReslice``, ``realignUnwarp``
+ % :type action: string
+ %
+ % :returns: - :matlabbatch: (structure) (dimension)
+ % - :voxDim: (array) (dimension)
+
+ if numel(varargin) < 5
+ [matlabbatch, BIDS, subID, opt] = deal(varargin{:});
+ action = '';
+ else
+ [matlabbatch, BIDS, subID, opt, action] = deal(varargin{:});
+ end
- if nargin < 5 || isempty(action)
+ if isempty(action)
action = 'realign';
end
@@ -44,18 +66,18 @@
for iRun = 1:nbRuns
% get the filename for this bold run for this task
- [fileName, subFuncDataDir] = getBoldFilename( ...
- BIDS, ...
- subID, ...
- sessions{iSes}, ...
- runs{iRun}, ...
- opt);
+ [boldFilename, subFuncDataDir] = getBoldFilename( ...
+ BIDS, ...
+ subID, ...
+ sessions{iSes}, ...
+ runs{iRun}, ...
+ opt);
% check that the file with the right prefix exist and we get and
% save its voxeldimension
prefix = getPrefix('preprocess', opt);
- file = validationInputFile(subFuncDataDir, fileName, prefix);
- [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, fileName);
+ file = validationInputFile(subFuncDataDir, boldFilename, prefix);
+ [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, boldFilename);
if size(file, 1) > 1
errorStruct.identifier = 'setBatchRealign:tooManyFiles';
@@ -66,10 +88,15 @@
fprintf(1, ' %s\n', file);
if strcmp(action, 'realignUnwarp')
- matlabbatch{end}.spm.spatial.realignunwarp.data(1, runCounter).pmscan = '';
+
+ vdmFile = getVdmFile(BIDS, opt, boldFilename);
+ matlabbatch{end}.spm.spatial.realignunwarp.data(1, runCounter).pmscan = { vdmFile };
matlabbatch{end}.spm.spatial.realignunwarp.data(1, runCounter).scans = { file };
+
else
+
matlabbatch{end}.spm.spatial.realign.estwrite.data{1, runCounter} = { file };
+
end
runCounter = runCounter + 1;
diff --git a/src/batches/setBatchReslice.m b/src/batches/setBatchReslice.m
index 3e270b8a..3de4a142 100644
--- a/src/batches/setBatchReslice.m
+++ b/src/batches/setBatchReslice.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function matlabbatch = setBatchReslice(referenceImg, sourceImages)
% matlabbatch = bidsSmoothing(referenceImg, sourceImages)
diff --git a/src/batches/setBatchSaveCoregistrationMatrix.m b/src/batches/setBatchSaveCoregistrationMatrix.m
index 78ab40da..99e70647 100644
--- a/src/batches/setBatchSaveCoregistrationMatrix.m
+++ b/src/batches/setBatchSaveCoregistrationMatrix.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, subID, opt)
diff --git a/src/defaults/checkOptions.m b/src/defaults/checkOptions.m
index c840ad0c..952d34cd 100644
--- a/src/defaults/checkOptions.m
+++ b/src/defaults/checkOptions.m
@@ -88,6 +88,11 @@
fieldsToSet.STC_referenceSlice = []; % reference slice: middle acquired slice
fieldsToSet.sliceOrder = []; % To be used if SPM can't extract slice info
+ % when opt.ignoreFieldmaps is set to false, the
+ % preprocessing pipeline will look for the voxel displacement maps (created by
+ % the corresponding workflow) and will use them for realign and unwarp
+ fieldsToSet.ignoreFieldmaps = false;
+
% fieldsToSet for normalize
% Voxel dimensions for resampling at normalization of functional data or leave empty [ ].
fieldsToSet.funcVoxelDims = [];
diff --git a/src/fieldmaps/getBlipDirection.m b/src/fieldmaps/getBlipDirection.m
new file mode 100644
index 00000000..0212f7c6
--- /dev/null
+++ b/src/fieldmaps/getBlipDirection.m
@@ -0,0 +1,37 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function blipDir = getBlipDirection(metadata)
+ %
+ % Gets the total read out time of a sequence.
+ %
+ % USAGE::
+ %
+ % blipDir = getBlipDirection(metadata)
+ %
+ % :param metadata: image metadata
+ % :type metadata: strcuture
+ %
+ % :returns: - :blipDir:
+ %
+ % Used to create the voxel dsiplacement map (VDM) from the fieldmap
+ %
+
+ blipDir = 1;
+
+ if isfield(metadata, 'PhaseEncodingDirection') && ...
+ ~isempty(metadata.PhaseEncodingDirection)
+
+ switch metadata.PhaseEncodingDirection
+
+ case {'i', 'j', 'y'}
+ blipDir = 1;
+ case {'i-', 'j-', 'y-'}
+ blipDir = -1;
+ otherwise
+ error('unknown phase encoding direction: %s', metadata.PhaseEncodingDirection);
+
+ end
+
+ end
+
+end
diff --git a/src/fieldmaps/getMetadataFromIntendedForFunc.m b/src/fieldmaps/getMetadataFromIntendedForFunc.m
new file mode 100644
index 00000000..e0b28830
--- /dev/null
+++ b/src/fieldmaps/getMetadataFromIntendedForFunc.m
@@ -0,0 +1,63 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function [totalReadoutTime, blipDir] = getMetadataFromIntendedForFunc(BIDS, fmapMetadata)
+ % get metadata of the associated bold file
+ % find bold file this fmap is intended for, parse its filename and get its
+ % metadata
+ %
+ % USAGE::
+ %
+ % [totalReadoutTime, blipDir] = getMetadataFromIntendedForFunc(BIDS, fmapMetadata)
+ %
+ % :param BIDS:
+ % :type BIDS: structure
+ % :param fmapMetadata:
+ % :type fmapMetadata: structure
+ %
+ % :returns: - :totalReadoutTime: (type) (dimension)
+ % - :blipDir: (type) (dimension)
+ %
+ % At the moment the VDM is created based on the characteristics of the last
+ % func file in the IntendedFor field
+ %
+ % TODO
+ % - if there are several func file for this fmap and they have different
+ % characteristic this may require creating a VDM for each
+
+ for iFile = 1:size(fmapMetadata.IntendedFor)
+
+ if iscell(fmapMetadata.IntendedFor)
+ filename = fmapMetadata.IntendedFor{iFile};
+ else
+ filename = fmapMetadata.IntendedFor(iFile, :);
+ end
+ filename = spm_file(filename, 'filename');
+
+ fragments = bids.internal.parse_filename(filename);
+
+ funcMetadata = spm_BIDS(BIDS, 'metadata', ...
+ 'modality', 'func', ...
+ 'type', fragments.type, ...
+ 'sub', fragments.sub, ...
+ 'ses', fragments.ses, ...
+ 'run', fragments.run, ...
+ 'acq', fragments.acq);
+
+ end
+
+ totalReadoutTime = getTotalReadoutTime(funcMetadata);
+
+ % temporary for designing
+ % totalReadoutTime = 63;
+
+ if isempty(totalReadoutTime)
+ errorStruct.identifier = 'getMetadataForVDM:emptyReadoutTime';
+ errorStruct.message = [ ...
+ 'Voxel displacement map creation requires a non empty value' ...
+ 'for the TotalReadoutTime of the bold sequence they are matched to.'];
+ error(errorStruct);
+ end
+
+ blipDir = getBlipDirection(funcMetadata);
+
+end
diff --git a/src/fieldmaps/getTotalReadoutTime.m b/src/fieldmaps/getTotalReadoutTime.m
new file mode 100644
index 00000000..b4c7770b
--- /dev/null
+++ b/src/fieldmaps/getTotalReadoutTime.m
@@ -0,0 +1,66 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function totalReadoutTime = getTotalReadoutTime(metadata)
+ %
+ % Gets the total read out time of a sequence.
+ %
+ % USAGE::
+ %
+ % totalReadoutTime = getTotalReadoutTime(metadata)
+ %
+ % :param metadata: image metadata
+ % :type metadata: strcuture
+ %
+ % :returns: - :totalReadoutTime: (float) in millisecond
+ %
+ % Used to create the voxel dsiplacement map (VDM) from the fieldmap
+ %
+
+ totalReadoutTime = '';
+
+ % apparently this comes from the functional metadata to create the VDM
+ if isfield(metadata, 'TotalReadoutTime') && ~isempty(metadata.TotalReadoutTime)
+ totalReadoutTime = metadata.TotalReadoutTime;
+
+ % TODO
+ % double check this section
+ % this was in spmup but I don't remember where I got this from
+ %
+ % % from spmup: apparently this comes from the fmap metadata
+ % % but PixelBandwidth is not is not a valid BIDS term
+ % elseif isfield(metadata, 'PixelBandwidth') && ~isempty(metadata.PixelBandwidth)
+ % totalReadoutTime = 1 / fieldmap_param.PixelBandwidth * 1000;
+ % warning('PixelBandwidth is not a valid BIDS term.');
+ %
+ % % apparently this comes from the functional metadata ???
+ % elseif isfield(metadata, 'RepetitionTime') && ~isempty(metadata.RepetitionTime)
+ % totalReadoutTime = metadata.RepetitionTime;
+ %
+ % % apparently this comes from the functional metadata ???
+ % elseif isfield(metadata, 'EffectiveEchoSpacing') && ~isempty(metadata.NumberOfEchos)
+ % totalReadoutTime = (metadata.NumberOfEchos - 1) * ...
+ % metadata.EffectiveEchoSpacing;
+
+ %% Phase enconded lines (PELines) and ReadOutTime
+
+ % PELines = ((BaseResolution * PartialFourier)/iPat) + ((iPat-1)/iPAT) * ReferenceLines) =
+ % ReadoutDuration = PELines * InterEchoSpacing
+
+ % GRAPPA=iPAT4 ; Partial Fourrier=6/8 ; 48 sli ; TE=25ms ; Res=0.75 mm
+ % Bandwidth Per Pixel Phase Encode = 15.873
+
+ %% According to Robert Trampel
+
+ % For distortion correction: ignore Partial Fourrier and references lines
+ % BaseResolution/iPAT = PELines
+
+ % Effective echo spacing: 2 ways to calculate, should be the same
+ % 1/(Bandwidth Per Pixel Phase Encode * Reconstructed phase lines) --> 0.246 ms
+ % echo spacing (syngo) / iPAT
+
+ % SPM Total readout time = 1/"Bandwidth Per Pixel Phase Encode", stored in
+ % DICOM tag (0019, 1028) --> 63 ms
+
+ end
+
+end
diff --git a/src/fieldmaps/getVdmFile.m b/src/fieldmaps/getVdmFile.m
new file mode 100644
index 00000000..8c57dfb0
--- /dev/null
+++ b/src/fieldmaps/getVdmFile.m
@@ -0,0 +1,67 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function vdmFile = getVdmFile(BIDS, opt, boldFilename)
+ %
+ % returns the voxel displacement map associated with a given bold file
+ %
+ % USAGE::
+ %
+ % vdmFile = getVdmFile(BIDS, opt, boldFilename)
+ %
+ % :param BIDS:
+ % :type BIDS: structure
+ % :param opt: options
+ % :type opt: structure
+ % :param boldFilename:
+ % :type opt: string
+ %
+ % :returns: - :vdmFile: (string)
+ %
+
+ vdmFile = '';
+
+ fragments = bids.internal.parse_filename(boldFilename);
+
+ if ~isfield(fragments, 'ses')
+ fragments.ses = '';
+ end
+
+ modalities = spm_BIDS(BIDS, 'modalities', ...
+ 'sub', fragments.sub, ...
+ 'ses', fragments.ses);
+
+ if ~opt.ignoreFieldmaps && any(ismember('fmap', modalities))
+ % We loop through the field maps and find the one that is intended for this
+ % bold file by reading from the metadata
+ %
+ % We break the loop when the file has been found
+
+ fmapFiles = spm_BIDS(BIDS, 'data', ...
+ 'modality', 'fmap', ...
+ 'sub', fragments.sub, ...
+ 'ses', fragments.ses);
+
+ fmapMetadata = spm_BIDS(BIDS, 'metadata', ...
+ 'modality', 'fmap', ...
+ 'sub', fragments.sub, ...
+ 'ses', fragments.ses);
+
+ for iFile = 1:size(fmapFiles, 1)
+
+ intendedFor = fmapMetadata{iFile}.IntendedFor;
+
+ if strfind(intendedFor, boldFilename) %#ok
+ [pth, filename, ext] = spm_fileparts(fmapFiles{iFile});
+ vdmFile = validationInputFile(pth, [filename ext], 'vdm5_sc');
+ break
+ end
+
+ end
+
+ end
+
+ if isempty(vdmFile)
+ warning('No voxel displacement map associated with: \n %s', boldFilename);
+ end
+
+end
diff --git a/src/getAnatFilename.m b/src/getAnatFilename.m
index 75a2305d..66a6cc9b 100644
--- a/src/getAnatFilename.m
+++ b/src/getAnatFilename.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt)
% [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt)
diff --git a/src/getData.m b/src/getData.m
index b1a0068c..f7656b37 100644
--- a/src/getData.m
+++ b/src/getData.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [group, opt, BIDS] = getData(opt, BIDSdir, type)
% [group, opt, BIDS] = getData(opt, BIDSdir, type)
diff --git a/src/getFuncVoxelDims.m b/src/getFuncVoxelDims.m
index c1192aad..d5fe3851 100644
--- a/src/getFuncVoxelDims.m
+++ b/src/getFuncVoxelDims.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, fileName)
% [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, fileName)
diff --git a/src/getInfo.m b/src/getInfo.m
index 98ca7b69..dd4a8626 100644
--- a/src/getInfo.m
+++ b/src/getInfo.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function varargout = getInfo(BIDS, subID, opt, info, varargin)
% wrapper function to fetch specific info in a BIDS structure returned by
@@ -70,14 +70,12 @@
[session, run, type] = deal(varargin{:});
- fileName = spm_BIDS(BIDS, 'data', ...
- 'sub', subID, ...
- 'run', run, ...
- 'ses', session, ...
- 'task', opt.taskName, ...
- 'type', type);
-
- varargout = fileName;
+ varargout = spm_BIDS(BIDS, 'data', ...
+ 'sub', subID, ...
+ 'run', run, ...
+ 'ses', session, ...
+ 'task', opt.taskName, ...
+ 'type', type);
otherwise
error('Not sure what info you want me to get.');
diff --git a/src/getMeanFuncFilename.m b/src/getMeanFuncFilename.m
index 8641a492..72a7459e 100644
--- a/src/getMeanFuncFilename.m
+++ b/src/getMeanFuncFilename.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subID, opt)
% [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt)
diff --git a/src/getPrefix.m b/src/getPrefix.m
index 9f4776c0..2314b8d8 100644
--- a/src/getPrefix.m
+++ b/src/getPrefix.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [prefix, motionRegressorPrefix] = getPrefix(step, opt, funcFWHM)
% [prefix, motionRegressorPrefix] = getPrefix(step, opt, funcFWHM)
diff --git a/src/getRealignParamFile.m b/src/getRealignParamFile.m
index 7f743072..c4347b70 100644
--- a/src/getRealignParamFile.m
+++ b/src/getRealignParamFile.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function realignParamFile = getRealignParamFile(fullpathBoldFileName, prefix)
diff --git a/src/getSliceOrder.m b/src/getSliceOrder.m
index 2c164165..37449801 100644
--- a/src/getSliceOrder.m
+++ b/src/getSliceOrder.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function sliceOrder = getSliceOrder(opt, verbose)
% get the slice order information from the BIDS data set or from getOption
diff --git a/src/getSpecificSubjects.m b/src/getSpecificSubjects.m
index 15d9f1c7..af259063 100644
--- a/src/getSpecificSubjects.m
+++ b/src/getSpecificSubjects.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function group = getSpecificSubjects(opt, group, iGroup, subjects)
diff --git a/src/getGrpLevelContrastToCompute.m b/src/group_level/getGrpLevelContrastToCompute.m
similarity index 100%
rename from src/getGrpLevelContrastToCompute.m
rename to src/group_level/getGrpLevelContrastToCompute.m
diff --git a/src/getRFXdir.m b/src/group_level/getRFXdir.m
similarity index 100%
rename from src/getRFXdir.m
rename to src/group_level/getRFXdir.m
diff --git a/src/mancoreg/mancoreg.m b/src/mancoreg/mancoreg.m
index e4e2d99d..d2cf31e7 100644
--- a/src/mancoreg/mancoreg.m
+++ b/src/mancoreg/mancoreg.m
@@ -1,7 +1,7 @@
% (C) Copyright 2004-2009 JH
% (C) Copyright 2009_2012 DSS
% (C) Copyright 2012_2019 Remi Gau
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function mancoreg(targetimage, sourceimage)
% mancoreg(targetimage, sourceimage)
diff --git a/src/mancoreg/mancoregCallbacks.m b/src/mancoreg/mancoregCallbacks.m
index 32f42b63..f1bb63f0 100644
--- a/src/mancoreg/mancoregCallbacks.m
+++ b/src/mancoreg/mancoregCallbacks.m
@@ -1,7 +1,7 @@
% (C) Copyright 2004-2009 JH
% (C) Copyright 2009_2012 DSS
% (C) Copyright 2012_2019 Remi Gau
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function mancoregCallbacks(operation, varargin)
% mancoreg_callbacks(op, varargin)
diff --git a/src/reportBIDS.m b/src/reports/reportBIDS.m
similarity index 100%
rename from src/reportBIDS.m
rename to src/reports/reportBIDS.m
diff --git a/src/setDerivativesDir.m b/src/setDerivativesDir.m
index 6ee46fa3..3012c175 100644
--- a/src/setDerivativesDir.m
+++ b/src/setDerivativesDir.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function opt = setDerivativesDir(opt)
% derivativeDir sets the derivatives folder
diff --git a/src/concatBetaImgTmaps.m b/src/subject_level/concatBetaImgTmaps.m
similarity index 100%
rename from src/concatBetaImgTmaps.m
rename to src/subject_level/concatBetaImgTmaps.m
diff --git a/src/convertOnsetTsvToMat.m b/src/subject_level/convertOnsetTsvToMat.m
similarity index 100%
rename from src/convertOnsetTsvToMat.m
rename to src/subject_level/convertOnsetTsvToMat.m
diff --git a/src/createAndReturnOnsetFile.m b/src/subject_level/createAndReturnOnsetFile.m
similarity index 100%
rename from src/createAndReturnOnsetFile.m
rename to src/subject_level/createAndReturnOnsetFile.m
diff --git a/src/deleteResidualImages.m b/src/subject_level/deleteResidualImages.m
similarity index 100%
rename from src/deleteResidualImages.m
rename to src/subject_level/deleteResidualImages.m
diff --git a/src/getBoldFilenameForFFX.m b/src/subject_level/getBoldFilenameForFFX.m
similarity index 94%
rename from src/getBoldFilenameForFFX.m
rename to src/subject_level/getBoldFilenameForFFX.m
index a87aa925..d0c5b42a 100644
--- a/src/getBoldFilenameForFFX.m
+++ b/src/subject_level/getBoldFilenameForFFX.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [boldFileName, prefix] = getBoldFilenameForFFX(varargin)
% [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subID, funcFWHM, iSes, iRun)
diff --git a/src/getFFXdir.m b/src/subject_level/getFFXdir.m
similarity index 100%
rename from src/getFFXdir.m
rename to src/subject_level/getFFXdir.m
diff --git a/src/specifyContrasts.m b/src/subject_level/specifyContrasts.m
similarity index 100%
rename from src/specifyContrasts.m
rename to src/subject_level/specifyContrasts.m
diff --git a/src/templates/templateFunction.m b/src/templates/templateFunction.m
index bf349d86..4b6135cc 100644
--- a/src/templates/templateFunction.m
+++ b/src/templates/templateFunction.m
@@ -1,29 +1,29 @@
% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [argout1, argout2] = templateFunction(argin1, argin2, argin3)
- %
- % Short description of what the function does goes here.
- %
- % USAGE:
- %
- % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3])
- %
- % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet,
- % consectetur adipiscing elit. Ut congue nec est ac lacinia.
- % :type argin1: type
- % :param argin2: optional argument and its default value. And some of the
- % options can be shown in litteral like ``this`` or ``that``.
- % :type argin2: string
- % :param argin3: (dimension) optional argument
- %
- % :returns: - :argout1: (type) (dimension)
- % - :argout2: (type) (dimension)
- %
- % .. todo:
- %
- % - item 1
- % - item 2
+ %
+ % Short description of what the function does goes here.
+ %
+ % USAGE::
+ %
+ % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3])
+ %
+ % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet,
+ % consectetur adipiscing elit. Ut congue nec est ac lacinia.
+ % :type argin1: type
+ % :param argin2: optional argument and its default value. And some of the
+ % options can be shown in litteral like ``this`` or ``that``.
+ % :type argin2: string
+ % :param argin3: (dimension) optional argument
+ %
+ % :returns: - :argout1: (type) (dimension)
+ % - :argout2: (type) (dimension)
+ %
+ % .. todo:
+ %
+ % - item 1
+ % - item 2
- % The code goes below
+ % The code goes below
-end
\ No newline at end of file
+end
diff --git a/src/templates/templateFunctionExample.m b/src/templates/templateFunctionExample.m
index 0ce1dec7..e4a39d6d 100644
--- a/src/templates/templateFunctionExample.m
+++ b/src/templates/templateFunctionExample.m
@@ -1,42 +1,42 @@
% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function templateFunctionExample()
- % This function illustrates a documentation test defined for MOdox.
- % Other than that it does absolutely nothinghort description of what
- % the function does goes here.
- %
- % Examples:
- % a=2;
- % disp(a)
- % % Expected output is prefixed by '%||' as in the following line:
- % %|| 2
- % %
- % % The test continues because no interruption through whitespace,
- % % as the previous line used a '%' comment character;
- % % thus the 'a' variable is still in the namespace and can be
- % % accessed.
- % b=3+a;
- % disp(a+[3 4])
- % %|| [5 6]
- %
- % % A new test starts here because the previous line was white-space
- % % only. Thus the 'a' and 'b' variables are not present here anymore.
- % % The following expression raises an error because the 'b' variable
- % % is not defined (and does not carry over from the previous test).
- % % Because the expected output indicates an error as well,
- % % the test passes
- % disp(b)
- % %|| error('Some error')
- %
- % % A set of expressions is ignored if there is no expected output
- % % (that is, no lines starting with '%||').
- % % Thus, the following expression is not part of any test,
- % % and therefore does not raise an error.
- % error('this is never executed)
- %
- %
- % % tests end here because test indentation has ended
+ % This function illustrates a documentation test defined for MOdox.
+ % Other than that it does absolutely nothinghort description of what
+ % the function does goes here.
+ %
+ % Examples:
+ % a=2;
+ % disp(a)
+ % % Expected output is prefixed by '%||' as in the following line:
+ % %|| 2
+ % %
+ % % The test continues because no interruption through whitespace,
+ % % as the previous line used a '%' comment character;
+ % % thus the 'a' variable is still in the namespace and can be
+ % % accessed.
+ % b=3+a;
+ % disp(a+[3 4])
+ % %|| [5 6]
+ %
+ % % A new test starts here because the previous line was white-space
+ % % only. Thus the 'a' and 'b' variables are not present here anymore.
+ % % The following expression raises an error because the 'b' variable
+ % % is not defined (and does not carry over from the previous test).
+ % % Because the expected output indicates an error as well,
+ % % the test passes
+ % disp(b)
+ % %|| error('Some error')
+ %
+ % % A set of expressions is ignored if there is no expected output
+ % % (that is, no lines starting with '%||').
+ % % Thus, the following expression is not part of any test,
+ % % and therefore does not raise an error.
+ % error('this is never executed)
+ %
+ %
+ % % tests end here because test indentation has ended
- % The code goes below
+ % The code goes below
-end
\ No newline at end of file
+end
diff --git a/src/templates/templateFunctionNumpy.m b/src/templates/templateFunctionNumpy.m
index 77cb0e67..ff449f9d 100644
--- a/src/templates/templateFunctionNumpy.m
+++ b/src/templates/templateFunctionNumpy.m
@@ -1,21 +1,21 @@
% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function [argout] = templateFunctionNumpy(argin1, argin2, argin3)
- %
- % Short description of what the function does goes here.
- %
- % y = templateFunction(argin1, argin2, argin3)
- %
- % Parameters:
- % argin1: The first input value
- %
- % argin2: The second input value
- %
- % argin3: The third input value
- %
- % Returns:
- % The input value multiplied by two
+ %
+ % Short description of what the function does goes here.
+ %
+ % y = templateFunction(argin1, argin2, argin3)
+ %
+ % Parameters:
+ % argin1: The first input value
+ %
+ % argin2: The second input value
+ %
+ % argin3: The third input value
+ %
+ % Returns:
+ % The input value multiplied by two
- % The code goes below
+ % The code goes below
-end
\ No newline at end of file
+end
diff --git a/src/templates/templateGetOption.m b/src/templates/templateGetOption.m
new file mode 100644
index 00000000..b1eb5872
--- /dev/null
+++ b/src/templates/templateGetOption.m
@@ -0,0 +1,71 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function opt = templateGetOption()
+ % returns a structure that contains the options chosen by the user to return
+ % the different workflows
+
+ if nargin < 1
+ opt = [];
+ end
+
+ % group of subjects to analyze
+ % opt.groups = {''};
+ % suject to run in each group
+ % opt.subjects = {[]};
+
+ % task to analyze
+ opt.taskName = 'balloonanalogrisktask';
+
+ % The directory where the data are located
+ opt.dataDir = '/home/remi/BIDS/ds001/rawdata';
+
+ % Where the data will go
+ % opt.derivativesDir = '';
+
+ % Options for slice time correction
+ % If left unspecified the slice timing will be done using the mid-volume acquisition
+ % time point as reference.
+ % Slice order must be entered in time unit (ms) (this is the BIDS way of doing things)
+ % instead of the slice index of the reference slice (the "SPM" way of doing things).
+ % More info here: https://en.wikibooks.org/wiki/SPM/Slice_Timing
+ % opt.sliceOrder = [];
+ % opt.STC_referenceSlice = [];
+
+ % when opt.ignoreFieldmaps is set to false, the
+ % preprocessing pipeline will look for the voxel displacement maps (created by
+ % the corresponding workflow) and will use them for realign and unwarp
+ % opt.ignoreFieldmaps = false;
+
+ % session number and type of the anatomical reference
+ % opt.anatReference.type = 'T1w';
+ % opt.anatReference.session = 1;
+
+ % any voxel with p(grayMatter) + p(whiteMatter) + p(CSF) > threshold
+ % will be included in the skull stripping mask
+ % opt.skullstrip.threshold = 0.75;
+
+ % space where we conduct the analysis
+ % opt.space = 'MNI';
+
+ % Options for normalize
+ % Voxel dimensions for resampling at normalization of functional data or leave empty [ ].
+ % opt.funcVoxelDims = [];
+
+ % specify the model file that contains the contrasts to compute
+ opt.model.univariate.file = ...
+ fullfile(fileparts(mfilename('fullpath')), ...
+ 'model', ...
+ 'model - balloonanalogriskUnivariate_smdl.json');
+
+ % specify the result to compute
+ % opt.result.Steps(1) = struct( ...
+ % 'Level', 'dataset', ...
+ % 'Contrasts', struct( ...
+ % 'Name', 'pumps_demean', ...
+ % 'Mask', false, ...
+ % 'MC', 'none', ... FWE, none, FDR
+ % 'p', 0.05, ...
+ % 'k', 0, ...
+ % 'NIDM', true));
+
+end
diff --git a/src/unzipImgAndReturnsFullpathName.m b/src/unzipImgAndReturnsFullpathName.m
index 42116cd7..d13bed94 100644
--- a/src/unzipImgAndReturnsFullpathName.m
+++ b/src/unzipImgAndReturnsFullpathName.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function unzippedFullpathImgName = unzipImgAndReturnsFullpathName(fullpathImgName)
% unzippedFullpathImgName = unzipImgAndReturnsFullpathName(fullpathImgName)
diff --git a/src/utils/createDataDictionary.m b/src/utils/createDataDictionary.m
index c58db070..454f6edb 100644
--- a/src/utils/createDataDictionary.m
+++ b/src/utils/createDataDictionary.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function createDataDictionary(subFuncDataDir, fileName, nbColums)
diff --git a/src/utils/loadAndCheckOptions.m b/src/utils/loadAndCheckOptions.m
index 3c3b79b6..619b497a 100644
--- a/src/utils/loadAndCheckOptions.m
+++ b/src/utils/loadAndCheckOptions.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function opt = loadAndCheckOptions(opt)
% opt = loadAndCheckOptions(opt)
@@ -19,6 +19,7 @@
return
end
+ % finds most recent option file
if size(opt, 1) > 1
containsDate = cellfun(@any, strfind(cellstr(opt), '_date-'));
opt = opt(containsDate, :);
diff --git a/src/printProcessingRun.m b/src/utils/printProcessingRun.m
similarity index 89%
rename from src/printProcessingRun.m
rename to src/utils/printProcessingRun.m
index dbab8a53..d0b3efba 100644
--- a/src/printProcessingRun.m
+++ b/src/utils/printProcessingRun.m
@@ -4,7 +4,7 @@ function printProcessingRun(groupName, iSub, subID, iSes, iRun)
fprintf(1, ...
[ ...
- 'PROCESSING GROUP: %s' ...
+ ' PROCESSING GROUP: %s' ...
'SUBJECT No.: %i ' ...
'SUBJECT ID : %s ' ...
'SESSION: %i ' ...
diff --git a/src/printProcessingSubject.m b/src/utils/printProcessingSubject.m
similarity index 85%
rename from src/printProcessingSubject.m
rename to src/utils/printProcessingSubject.m
index 308ad32a..61e4a00a 100644
--- a/src/printProcessingSubject.m
+++ b/src/utils/printProcessingSubject.m
@@ -3,7 +3,7 @@
function printProcessingSubject(groupName, iSub, subID)
fprintf(1, [ ...
- 'PROCESSING GROUP: %s' ...
+ ' PROCESSING GROUP: %s' ...
'SUBJECT No.: %i ' ...
'SUBJECT ID : %s \n'], ...
groupName, iSub, subID);
diff --git a/src/saveMatlabBatch.m b/src/utils/saveMatlabBatch.m
similarity index 100%
rename from src/saveMatlabBatch.m
rename to src/utils/saveMatlabBatch.m
diff --git a/src/utils/saveOptions.m b/src/utils/saveOptions.m
index dff2d99b..4d912caa 100644
--- a/src/utils/saveOptions.m
+++ b/src/utils/saveOptions.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function saveOptions(opt)
diff --git a/src/utils/setDefaultFields.m b/src/utils/setDefaultFields.m
index 666ea7b6..98689d7d 100644
--- a/src/utils/setDefaultFields.m
+++ b/src/utils/setDefaultFields.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function structure = setDefaultFields(structure, fieldsToSet)
% structure = setDefaultFields(structure, fieldsToSet)
diff --git a/src/workflows/bidsCopyRawFolder.m b/src/workflows/bidsCopyRawFolder.m
index 7a921091..6f059559 100644
--- a/src/workflows/bidsCopyRawFolder.m
+++ b/src/workflows/bidsCopyRawFolder.m
@@ -1,58 +1,54 @@
% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
-function bidsCopyRawFolder(opt, deleteZippedNii)
- % This function will copy the subject's folders from the "raw" folder to the
- % "derivatives" folder, and will copy the dataset description and task json files
+function bidsCopyRawFolder(opt, deleteZippedNii, modalitiesToCopy)
+ %
+ % This function will copy the subject's folders from the ``raw`` folder to the
+ % ``derivatives`` folder, and will copy the dataset description and task json files
% to the derivatives directory.
% Then it will search the derivatives directory for any zipped nii.gz image
% and uncompress it to .nii images.
%
- % INPUT:
+ % USAGE::
+ %
+ % bidsCopyRawFolder([opt,] ...
+ % [deleteZippedNii = true,] ...
+ % [modalitiesToCopy = {'anat', 'func', 'fmap'}])
%
- % opt - options structure defined by the getOption function. If no inout is given
- % this function will attempt to load a opt.mat file in the same directory
- % to try to get some options
+ % :param opt:
+ % :type opt: type
+ % :param deleteZippedNii:
+ % :type deleteZippedNii: boolean
+ % :param modalitiesToCopy:
+ % :type modalitiesToCopy: cell
%
- % deleteZippedNii - true or false and will delete original zipped files
- % after copying and unzipping
%% input variables default values
- if nargin < 2 % if second argument isn't specified
- deleteZippedNii = 1; % delete the original zipped nii.gz
+
+ if nargin < 3 || isempty(modalitiesToCopy)
+ % Will only copy those modalities if they exist
+ modalitiesToCopy = {'anat', 'func', 'fmap'};
+ end
+
+ if nargin < 2 || isempty(deleteZippedNii)
+ % delete the original zipped nii.gz
+ deleteZippedNii = true;
end
% if input has no opt, load the opt.mat file
- if nargin < 1
+ if nargin < 1 || isempty(opt)
opt = [];
end
opt = loadAndCheckOptions(opt);
- % Will only copy those modalities if they exist
- modalitiesToCopy = {'anat', 'func'};
-
%% All tasks in this experiment
% raw directory and derivatives directory
- rawDir = opt.dataDir;
opt = setDerivativesDir(opt);
+ rawDir = opt.dataDir;
derivativesDir = opt.derivativesDir;
- % make derivatives folder if it doesnt exist
- if ~exist(derivativesDir, 'dir')
- mkdir(derivativesDir);
- fprintf('derivatives directory created: %s \n', derivativesDir);
- else
- fprintf('derivatives directory already exists. \n');
- end
+ createDerivativeDir(derivativesDir);
- % copy TSV and JSON file from raw folder if it doesnt exist
- copyfile(fullfile(rawDir, '*.json'), derivativesDir);
- fprintf(' json files copied to derivatives directory \n');
-
- try
- copyfile(fullfile(rawDir, '*.tsv'), derivativesDir);
- fprintf(' tsv files copied to derivatives directory \n');
- catch
- end
+ copyTsvJson(rawDir, derivativesDir);
%% Loop through the groups, subjects, sessions
[group, opt, BIDS] = getData(opt, rawDir);
@@ -76,64 +72,98 @@ function bidsCopyRawFolder(opt, deleteZippedNii)
for iSes = 1:nbSessions
- sessionFolder = [];
+ sessionDir = [];
if ~isempty(sessions{iSes})
- sessionFolder = ['ses-' sessions{iSes}];
+ sessionDir = ['ses-' sessions{iSes}];
end
- mkdir(fullfile(derivativesDir, subDir, sessionFolder));
-
- modalities = spm_BIDS(BIDS, 'modalities', ...
- 'sub', subID, ...
- 'ses', sessions{iSes}, ...
- 'task', opt.taskName);
+ mkdir(fullfile(derivativesDir, subDir, sessionDir));
+ modalities = bids.query(BIDS, 'modalities', ...
+ 'sub', subID, ...
+ 'ses', sessions{iSes}, ...
+ 'task', opt.taskName);
modalities = intersect(modalities, modalitiesToCopy);
for iModality = 1:numel(modalities)
- try
- status = system( ...
- sprintf('cp -R -L %s %s', ...
- fullfile(rawDir, ...
- subDir, ...
- sessionFolder, ...
- modalities{iModality}), ...
- fullfile(derivativesDir, ...
- subDir, ...
- sessionFolder, ...
- modalities{iModality})));
-
- if status > 0
- message = [ ...
- 'Copying data with system command failed: ' ...
- 'Are you running Windows?\n', ...
- 'Will use matlab/octave copyfile command instead.\n', ...
- 'Maybe your data set contains symbolic links' ...
- '(e.g. if you use datalad or git-annex.'];
- error(message);
- end
-
- catch
- copyfile(fullfile(rawDir, ...
- subDir, ...
- sessionFolder, ...
- modalities{iModality}), ...
- fullfile(derivativesDir, ...
- subDir, ...
- sessionFolder, ...
- modalities{iModality}));
- end
+ mkdir(fullfile(derivativesDir, subDir, sessionDir, modalities{iModality}));
+
+ srcFolder = fullfile(rawDir, ...
+ subDir, ...
+ sessionDir, ...
+ modalities{iModality});
+ targetFolder = fullfile(derivativesDir, ...
+ subDir, ...
+ sessionDir);
+
+ copyModalityDir(srcFolder, targetFolder);
end
+ fprintf('folder copied: %s \n', subDir);
+
end
+ end
+
+ end
+
+ unzipFiles(derivativesDir, deleteZippedNii);
- fprintf('folder copied: %s \n', subDir);
+end
+
+function createDerivativeDir(derivativesDir)
+ % make derivatives folder if it doesnt exist
+
+ if ~exist(derivativesDir, 'dir')
+ mkdir(derivativesDir);
+ fprintf('derivatives directory created: %s \n', derivativesDir);
+ else
+ fprintf('derivatives directory already exists. \n');
+ end
+
+end
+
+function copyTsvJson(rawDir, derivativesDir)
+ % copy TSV and JSON file from raw folder
+
+ copyfile(fullfile(rawDir, '*.json'), derivativesDir);
+ fprintf(' json files copied to derivatives directory \n');
+ try
+ copyfile(fullfile(rawDir, '*.tsv'), derivativesDir);
+ fprintf(' tsv files copied to derivatives directory \n');
+ catch
+ end
+
+end
+
+function copyModalityDir(srcFolder, targetFolder)
+
+ try
+ status = system( ...
+ sprintf('cp -R -L -f %s %s', ...
+ srcFolder, ...
+ targetFolder));
+
+ if status > 0
+ message = [ ...
+ 'Copying data with system command failed: ' ...
+ 'Are you running Windows?\n', ...
+ 'Will use matlab/octave copyfile command instead.\n', ...
+ 'Maybe your data set contains symbolic links' ...
+ '(e.g. if you use datalad or git-annex.'];
+ error(message);
end
+
+ catch
+ fprintf(1, 'Using octave/matlab to copy files.');
+ copyfile(srcFolder, targetFolder);
end
+end
+
+function unzipFiles(derivativesDir, deleteZippedNii)
%% search for nifti files in a compressed nii.gz format
zippedNiifiles = spm_select('FPListRec', derivativesDir, '^.*.nii.gz$');
@@ -145,9 +175,10 @@ function bidsCopyRawFolder(opt, deleteZippedNii)
save_untouch_nii(n, file(1:end - 4)); % Save the functional data as unzipped nii
fprintf('unzipped: %s \n', file);
- if deleteZippedNii == 1
+ if deleteZippedNii
delete(file); % delete original zipped file
end
+
end
end
diff --git a/src/workflows/bidsCreateVDM.m b/src/workflows/bidsCreateVDM.m
new file mode 100644
index 00000000..ef196688
--- /dev/null
+++ b/src/workflows/bidsCreateVDM.m
@@ -0,0 +1,51 @@
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
+
+function bidsCreateVDM(opt)
+ % bidsCreateVDM(opt)
+ %
+ % inspired from spmup spmup_BIDS_preprocess (@ commit
+ % 198c980d6d7520b1a996f0e56269e2ceab72cc83)
+
+ if nargin < 1
+ opt = [];
+ end
+ opt = loadAndCheckOptions(opt);
+
+ % load the subjects/Groups information and the task name
+ [group, opt, BIDS] = getData(opt);
+
+ fprintf(1, ' FIELDMAP WORKFLOW\n');
+
+ %% Loop through the groups, subjects, and sessions
+ for iGroup = 1:length(group)
+
+ groupName = group(iGroup).name;
+
+ for iSub = 1:group(iGroup).numSub
+
+ subID = group(iGroup).subNumber{iSub};
+
+ % TODO Move to getInfo
+ types = spm_BIDS(BIDS, 'types', 'sub', subID);
+
+ if any(ismember(types, {'phase12', 'phasediff', 'fieldmap', 'epi'}))
+
+ printProcessingSubject(groupName, iSub, subID);
+
+ matlabbatch = setBatchCoregistrationFmap(BIDS, opt, subID);
+ saveMatlabBatch(matlabbatch, 'coregister_fmap', opt, subID);
+ spm_jobman('run', matlabbatch);
+
+ matlabbatch = setBatchCreateVDMs(BIDS, opt, subID);
+ saveMatlabBatch(matlabbatch, 'create_vdm', opt, subID);
+ spm_jobman('run', matlabbatch);
+
+ % TODO
+ % delete temporary mean images ??
+
+ end
+
+ end
+
+ end
+end
diff --git a/src/workflows/bidsRealignReslice.m b/src/workflows/bidsRealignReslice.m
index 3f64669a..06dc8444 100644
--- a/src/workflows/bidsRealignReslice.m
+++ b/src/workflows/bidsRealignReslice.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function bidsRealignReslice(opt)
% bidsRealignReslice(opt)
diff --git a/src/workflows/bidsRealignUnwarp.m b/src/workflows/bidsRealignUnwarp.m
index 40fe98cd..b3857c06 100644
--- a/src/workflows/bidsRealignUnwarp.m
+++ b/src/workflows/bidsRealignUnwarp.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function bidsRealignUnwarp(opt)
% bidsRealignReslice(opt)
diff --git a/src/workflows/bidsResliceTpmToFunc.m b/src/workflows/bidsResliceTpmToFunc.m
index 91469abd..d5a5671f 100644
--- a/src/workflows/bidsResliceTpmToFunc.m
+++ b/src/workflows/bidsResliceTpmToFunc.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 2020 CPP BIDS SPM-pipeline developpers
function bidsResliceTpmToFunc(opt)
% bidsResliceTpmToFunc(opt)
diff --git a/src/workflows/bidsSegmentSkullStrip.m b/src/workflows/bidsSegmentSkullStrip.m
index 5a60df9d..4ddbfe69 100644
--- a/src/workflows/bidsSegmentSkullStrip.m
+++ b/src/workflows/bidsSegmentSkullStrip.m
@@ -1,4 +1,4 @@
-% (C) Copyright 2019 CPP BIDS SPM-pipeline developpers
+% (C) Copyright 20120 CPP BIDS SPM-pipeline developpers
function bidsSegmentSkullStrip(opt)
%
diff --git a/src/workflows/bidsSpatialPrepro.m b/src/workflows/bidsSpatialPrepro.m
index 2a795945..2a100219 100644
--- a/src/workflows/bidsSpatialPrepro.m
+++ b/src/workflows/bidsSpatialPrepro.m
@@ -57,7 +57,7 @@ function bidsSpatialPrepro(opt)
opt.orderBatches.realign = 2;
% dependency from file selector ('Anatomical')
- matlabbatch = setBatchCoregistration(matlabbatch, BIDS, subID, opt);
+ matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, subID, opt);
opt.orderBatches.coregister = 3;
matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, subID, opt);
diff --git a/tests/README.md b/tests/README.md
index f884994b..28db08aa 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -7,4 +7,4 @@ coverage = mocov( ...
'-cover', fullfile(pwd, '..', 'subfun'), ....
'-cover_xml_file', 'coverage.xml', ...
'-cover_html_dir', 'coverage_html')
-```
\ No newline at end of file
+```
diff --git a/tests/test_bidsCopyRawFolder.m b/tests/test_bidsCopyRawFolder.m
index a82bd517..fa559eea 100644
--- a/tests/test_bidsCopyRawFolder.m
+++ b/tests/test_bidsCopyRawFolder.m
@@ -8,6 +8,8 @@
function test_bidsCopyRawFolderBasic()
+ % TODO add test to only copy some modalities
+
% directory with this script becomes the current directory
opt.dataDir = fullfile( ...
fileparts(mfilename('fullpath')), ...
diff --git a/tests/test_checkOptions.m b/tests/test_checkOptions.m
index cbfe42b1..232f1684 100644
--- a/tests/test_checkOptions.m
+++ b/tests/test_checkOptions.m
@@ -94,6 +94,8 @@ function test_checkOptionsErrorVoxDim()
expectedOptions.skullstrip.threshold = 0.75;
+ expectedOptions.ignoreFieldmaps = false;
+
expectedOptions.taskName = '';
expectedOptions.zeropad = 2;
diff --git a/tests/test_loadAndCheckOptions.m b/tests/test_loadAndCheckOptions.m
index 355fa9e5..ca8c4673 100644
--- a/tests/test_loadAndCheckOptions.m
+++ b/tests/test_loadAndCheckOptions.m
@@ -108,6 +108,8 @@ function test_loadAndCheckOptionsFromSeveralFiles()
expectedOptions.skullstrip.threshold = 0.75;
+ expectedOptions.ignoreFieldmaps = false;
+
expectedOptions.taskName = '';
expectedOptions.zeropad = 2;
diff --git a/tests/test_setBatchCoregistration.m b/tests/test_setBatchCoregistrationFuncToAnat.m
similarity index 91%
rename from tests/test_setBatchCoregistration.m
rename to tests/test_setBatchCoregistrationFuncToAnat.m
index 8bdf6f4a..138029a1 100644
--- a/tests/test_setBatchCoregistration.m
+++ b/tests/test_setBatchCoregistrationFuncToAnat.m
@@ -1,4 +1,4 @@
-function test_suite = test_setBatchCoregistration %#ok<*STOUT>
+function test_suite = test_setBatchCoregistrationFuncToAnat %#ok<*STOUT>
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
test_functions = localfunctions(); %#ok<*NASGU>
catch % no problem; early Matlab versions can use initTestSuite fine
@@ -6,7 +6,7 @@
initTestSuite;
end
-function test_setBatchCoregistrationBasic()
+function test_setBatchCoregistrationFuncToAnatBasic()
% necessarry to deal with SPM module dependencies
spm_jobman('initcfg');
@@ -24,7 +24,7 @@ function test_setBatchCoregistrationBasic()
opt.orderBatches.realign = 2;
matlabbatch = {};
- matlabbatch = setBatchCoregistration(matlabbatch, BIDS, subID, opt);
+ matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, subID, opt);
nbRuns = 4;
@@ -44,7 +44,7 @@ function test_setBatchCoregistrationBasic()
end
-function test_setBatchCoregistrationNative()
+function test_setBatchCoregistrationFuncToAnatNative()
% necessarry to deal with SPM module dependencies
spm_jobman('initcfg');
@@ -63,7 +63,7 @@ function test_setBatchCoregistrationNative()
opt.orderBatches.realign = 2;
matlabbatch = {};
- matlabbatch = setBatchCoregistration(matlabbatch, BIDS, subID, opt);
+ matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, subID, opt);
nbRuns = 4;