Skip to content

Commit 2dd83d7

Browse files
authored
Merge pull request #1343 from effigies/bids/derivatives_rc1
ENH: Conform confound regressor names to Derivatives RC2
2 parents ab686c9 + 5a0edd6 commit 2dd83d7

File tree

7 files changed

+75
-54
lines changed

7 files changed

+75
-54
lines changed

.circleci/config.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,10 @@ jobs:
354354
at: /tmp
355355
- restore_cache:
356356
keys:
357-
- ds005-anat-v9-{{ .Branch }}-{{ epoch }}
358-
- ds005-anat-v9-{{ .Branch }}
359-
- ds005-anat-v9-master
360-
- ds005-anat-v9-
357+
- ds005-anat-v10-{{ .Branch }}-{{ epoch }}
358+
- ds005-anat-v10-{{ .Branch }}
359+
- ds005-anat-v10-master
360+
- ds005-anat-v10-
361361
- run:
362362
name: Setting up test
363363
command: |
@@ -391,7 +391,7 @@ jobs:
391391
--sloppy --write-graph --mem_mb 4096 \
392392
--nthreads 2 --anat-only -vv
393393
- save_cache:
394-
key: ds005-anat-v9-{{ .Branch }}-{{ epoch }}
394+
key: ds005-anat-v10-{{ .Branch }}-{{ epoch }}
395395
paths:
396396
- /tmp/ds005/work
397397
- /tmp/ds005/derivatives/fmriprep

.circleci/ds005_outputs.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ fmriprep/logs/CITATION.md
66
fmriprep/logs/CITATION.tex
77
fmriprep/sub-01
88
fmriprep/sub-01/anat
9+
fmriprep/sub-01/anat/sub-01_desc-aparcaseg_dseg.nii.gz
10+
fmriprep/sub-01/anat/sub-01_desc-aseg_dseg.nii.gz
911
fmriprep/sub-01/anat/sub-01_desc-brain_mask.nii.gz
1012
fmriprep/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz
1113
fmriprep/sub-01/anat/sub-01_dseg.nii.gz
@@ -21,8 +23,6 @@ fmriprep/sub-01/anat/sub-01_hemi-R_inflated.surf.gii
2123
fmriprep/sub-01/anat/sub-01_hemi-R_midthickness.surf.gii
2224
fmriprep/sub-01/anat/sub-01_hemi-R_pial.surf.gii
2325
fmriprep/sub-01/anat/sub-01_hemi-R_smoothwm.surf.gii
24-
fmriprep/sub-01/anat/sub-01_label-aparcaseg_dseg.nii.gz
25-
fmriprep/sub-01/anat/sub-01_label-aseg_dseg.nii.gz
2626
fmriprep/sub-01/anat/sub-01_label-CSF_probseg.nii.gz
2727
fmriprep/sub-01/anat/sub-01_label-GM_probseg.nii.gz
2828
fmriprep/sub-01/anat/sub-01_label-WM_probseg.nii.gz
@@ -45,10 +45,10 @@ fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAs
4545
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
4646
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_desc-smoothAROMAnonaggr_bold.nii.gz
4747
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_boldref.nii.gz
48+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-aparcaseg_dseg.nii.gz
49+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-aseg_dseg.nii.gz
4850
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-brain_mask.nii.gz
4951
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-preproc_bold.nii.gz
50-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_label-aparcaseg_dseg.nii.gz
51-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_label-aseg_dseg.nii.gz
5252
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_AROMAnoiseICs.csv
5353
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_bold.dtseries.json
5454
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_bold.dtseries.nii
@@ -61,9 +61,9 @@ fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-MNI152NLin2009cAs
6161
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
6262
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-MNI152NLin2009cAsym_desc-smoothAROMAnonaggr_bold.nii.gz
6363
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_boldref.nii.gz
64+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_desc-aparcaseg_dseg.nii.gz
65+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_desc-aseg_dseg.nii.gz
6466
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_desc-brain_mask.nii.gz
6567
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_desc-preproc_bold.nii.gz
66-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_label-aparcaseg_dseg.nii.gz
67-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-02_space-T1w_label-aseg_dseg.nii.gz
6868
fmriprep/sub-01.html
6969
/tmp/ds005/derivatives

.circleci/ds005_partial_outputs.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ fmriprep/logs/CITATION.md
66
fmriprep/logs/CITATION.tex
77
fmriprep/sub-01
88
fmriprep/sub-01/anat
9+
fmriprep/sub-01/anat/sub-01_desc-aparcaseg_dseg.nii.gz
10+
fmriprep/sub-01/anat/sub-01_desc-aseg_dseg.nii.gz
911
fmriprep/sub-01/anat/sub-01_desc-brain_mask.nii.gz
1012
fmriprep/sub-01/anat/sub-01_desc-preproc_T1w.nii.gz
1113
fmriprep/sub-01/anat/sub-01_dseg.nii.gz
@@ -21,8 +23,6 @@ fmriprep/sub-01/anat/sub-01_hemi-R_inflated.surf.gii
2123
fmriprep/sub-01/anat/sub-01_hemi-R_midthickness.surf.gii
2224
fmriprep/sub-01/anat/sub-01_hemi-R_pial.surf.gii
2325
fmriprep/sub-01/anat/sub-01_hemi-R_smoothwm.surf.gii
24-
fmriprep/sub-01/anat/sub-01_label-aparcaseg_dseg.nii.gz
25-
fmriprep/sub-01/anat/sub-01_label-aseg_dseg.nii.gz
2626
fmriprep/sub-01/anat/sub-01_label-CSF_probseg.nii.gz
2727
fmriprep/sub-01/anat/sub-01_label-GM_probseg.nii.gz
2828
fmriprep/sub-01/anat/sub-01_label-WM_probseg.nii.gz
@@ -45,9 +45,9 @@ fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAs
4545
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz
4646
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-MNI152NLin2009cAsym_desc-smoothAROMAnonaggr_bold.nii.gz
4747
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_boldref.nii.gz
48+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-aparcaseg_dseg.nii.gz
49+
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-aseg_dseg.nii.gz
4850
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-brain_mask.nii.gz
4951
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_desc-preproc_bold.nii.gz
50-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_label-aparcaseg_dseg.nii.gz
51-
fmriprep/sub-01/func/sub-01_task-mixedgamblestask_run-01_space-T1w_label-aseg_dseg.nii.gz
5252
fmriprep/sub-01.html
5353
/tmp/ds005/derivatives_partial

fmriprep/interfaces/confounds.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
1111
"""
1212
import os
13+
import re
1314
import shutil
1415
import numpy as np
1516
import pandas as pd
@@ -27,6 +28,7 @@
2728
class GatherConfoundsInputSpec(BaseInterfaceInputSpec):
2829
signals = File(exists=True, desc='input signals')
2930
dvars = File(exists=True, desc='file containing DVARS')
31+
std_dvars = File(exists=True, desc='file containing standardized DVARS')
3032
fd = File(exists=True, desc='input framewise displacement')
3133
tcompcor = File(exists=True, desc='input tCompCorr')
3234
acompcor = File(exists=True, desc='input aCompCorr')
@@ -79,6 +81,7 @@ def _run_interface(self, runtime):
7981
combined_out, confounds_list = _gather_confounds(
8082
signals=self.inputs.signals,
8183
dvars=self.inputs.dvars,
84+
std_dvars=self.inputs.std_dvars,
8285
fdisp=self.inputs.fd,
8386
tcompcor=self.inputs.tcompcor,
8487
acompcor=self.inputs.acompcor,
@@ -124,7 +127,7 @@ def _run_interface(self, runtime):
124127
return runtime
125128

126129

127-
def _gather_confounds(signals=None, dvars=None, fdisp=None,
130+
def _gather_confounds(signals=None, dvars=None, std_dvars=None, fdisp=None,
128131
tcompcor=None, acompcor=None, cos_basis=None,
129132
motion=None, aroma=None, newpath=None):
130133
"""
@@ -134,16 +137,16 @@ def _gather_confounds(signals=None, dvars=None, fdisp=None,
134137
>>> from tempfile import TemporaryDirectory
135138
>>> tmpdir = TemporaryDirectory()
136139
>>> os.chdir(tmpdir.name)
137-
>>> pd.DataFrame({'a': [0.1]}).to_csv('signals.tsv', index=False, na_rep='n/a')
138-
>>> pd.DataFrame({'b': [0.2]}).to_csv('dvars.tsv', index=False, na_rep='n/a')
140+
>>> pd.DataFrame({'Global Signal': [0.1]}).to_csv('signals.tsv', index=False, na_rep='n/a')
141+
>>> pd.DataFrame({'stdDVARS': [0.2]}).to_csv('dvars.tsv', index=False, na_rep='n/a')
139142
>>> out_file, confound_list = _gather_confounds('signals.tsv', 'dvars.tsv')
140143
>>> confound_list
141144
['Global signals', 'DVARS']
142145
143146
>>> pd.read_csv(out_file, sep='\s+', index_col=None,
144147
... engine='python') # doctest: +NORMALIZE_WHITESPACE
145-
a b
146-
0 0.1 0.2
148+
global_signal std_dvars
149+
0 0.1 0.2
147150
>>> tmpdir.cleanup()
148151
149152
@@ -153,6 +156,12 @@ def less_breakable(a_string):
153156
''' hardens the string to different envs (i.e. case insensitive, no whitespace, '#' '''
154157
return ''.join(a_string.split()).strip('#')
155158

159+
# Taken from https://stackoverflow.com/questions/1175208/
160+
# If we end up using it more than just here, probably worth pulling in a well-tested package
161+
def camel_to_snake(name):
162+
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
163+
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
164+
156165
def _adjust_indices(left_df, right_df):
157166
# This forces missing values to appear at the beggining of the DataFrame
158167
# instead of the end
@@ -167,6 +176,7 @@ def _adjust_indices(left_df, right_df):
167176
all_files = []
168177
confounds_list = []
169178
for confound, name in ((signals, 'Global signals'),
179+
(std_dvars, 'Standardized DVARS'),
170180
(dvars, 'DVARS'),
171181
(fdisp, 'Framewise displacement'),
172182
(tcompcor, 'tCompCor'),
@@ -183,7 +193,7 @@ def _adjust_indices(left_df, right_df):
183193
for file_name in all_files: # assumes they all have headings already
184194
new = pd.read_csv(file_name, sep="\t")
185195
for column_name in new.columns:
186-
new.rename(columns={column_name: less_breakable(column_name)},
196+
new.rename(columns={column_name: camel_to_snake(less_breakable(column_name))},
187197
inplace=True)
188198

189199
_adjust_indices(confounds_data, new)
@@ -245,7 +255,7 @@ def _get_ica_confounds(ica_out_dir, skip_vols, newpath=None):
245255
# add one to motion_ic_indices to match melodic report.
246256
aroma_confounds = os.path.join(newpath, "AROMAAggrCompAROMAConfounds.tsv")
247257
pd.DataFrame(aggr_confounds.T,
248-
columns=['AROMAAggrComp%02d' % (x + 1) for x in motion_ic_indices]).to_csv(
258+
columns=['aroma_motion_%02d' % (x + 1) for x in motion_ic_indices]).to_csv(
249259
aroma_confounds, sep="\t", index=None)
250260

251261
return aroma_confounds, motion_ics_out, melodic_mix_out

fmriprep/workflows/anatomical.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,10 +1313,10 @@ def init_anat_derivatives_wf(output_dir, output_spaces, template, freesurfer,
13131313

13141314
if freesurfer:
13151315
ds_t1_fsaseg = pe.Node(
1316-
DerivativesDataSink(base_directory=output_dir, suffix='label-aseg_dseg'),
1316+
DerivativesDataSink(base_directory=output_dir, desc='aseg', suffix='dseg'),
13171317
name='ds_t1_fsaseg', run_without_submitting=True)
13181318
ds_t1_fsparc = pe.Node(
1319-
DerivativesDataSink(base_directory=output_dir, suffix='label-aparcaseg_dseg'),
1319+
DerivativesDataSink(base_directory=output_dir, desc='aparcaseg', suffix='dseg'),
13201320
name='ds_t1_fsparc', run_without_submitting=True)
13211321
workflow.connect([
13221322
(inputnode, lta_2_itk, [('t1_2_fsnative_forward_transform', 'in_lta')]),

fmriprep/workflows/bold/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -889,11 +889,11 @@ def init_func_derivatives_wf(output_dir, output_spaces, template, freesurfer,
889889

890890
if freesurfer:
891891
ds_bold_aseg_t1 = pe.Node(DerivativesDataSink(
892-
base_directory=output_dir, space='T1w', suffix='label-aseg_dseg'),
892+
base_directory=output_dir, space='T1w', desc='aseg', suffix='dseg'),
893893
name='ds_bold_aseg_t1', run_without_submitting=True,
894894
mem_gb=DEFAULT_MEMORY_MIN_GB)
895895
ds_bold_aparc_t1 = pe.Node(DerivativesDataSink(
896-
base_directory=output_dir, space='T1w', suffix='label-aparcaseg_dseg'),
896+
base_directory=output_dir, space='T1w', desc='aparcaseg', suffix='dseg'),
897897
name='ds_bold_aparc_t1', run_without_submitting=True,
898898
mem_gb=DEFAULT_MEMORY_MIN_GB)
899899
workflow.connect([

fmriprep/workflows/bold/confounds.py

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,17 @@ def init_bold_confs_wf(mem_gb, metadata, name="bold_confs_wf"):
4343
4444
The following confounds are calculated, with column headings in parentheses:
4545
46-
#. Region-wise average signal (``CSF``, ``WhiteMatter``, ``GlobalSignal``)
47-
#. DVARS - standard, nonstandard, and voxel-wise standard variants
48-
(``stdDVARS``, ``non-stdDVARS``, ``vx-wisestdDVARS``)
49-
#. Framewise displacement, based on MCFLIRT motion parameters
50-
(``FramewiseDisplacement``)
51-
#. Temporal CompCor (``tCompCorXX``)
52-
#. Anatomical CompCor (``aCompCorXX``)
46+
#. Region-wise average signal (``csf``, ``white_matter``, ``global_signal``)
47+
#. DVARS - original and standardized variants (``dvars``, ``std_dvars``)
48+
#. Framewise displacement, based on head-motion parameters
49+
(``framewise_displacement``)
50+
#. Temporal CompCor (``t_comp_cor_XX``)
51+
#. Anatomical CompCor (``a_comp_cor_XX``)
5352
#. Cosine basis set for high-pass filtering w/ 0.008 Hz cut-off
54-
(``CosineXX``)
55-
#. Non-steady-state volumes (``NonSteadyStateXX``)
53+
(``cosine_XX``)
54+
#. Non-steady-state volumes (``non_steady_state_XX``)
5655
#. Estimated head-motion parameters, in mm and rad
57-
(``X``, ``Y``, ``Z``, ``RotX``, ``RotY``, ``RotZ``)
56+
(``trans_x``, ``trans_y``, ``trans_z``, ``rot_x``, ``rot_y``, ``rot_z``)
5857
5958
6059
Prior to estimating aCompCor and tCompCor, non-steady-state volumes are
@@ -172,20 +171,22 @@ def init_bold_confs_wf(mem_gb, metadata, name="bold_confs_wf"):
172171
tcc_msk = pe.Node(niu.Function(function=_maskroi), name='tcc_msk')
173172

174173
# DVARS
175-
dvars = pe.Node(nac.ComputeDVARS(save_all=True, remove_zerovariance=True),
174+
dvars = pe.Node(nac.ComputeDVARS(save_nstd=True, save_std=True, remove_zerovariance=True),
176175
name="dvars", mem_gb=mem_gb)
177176

178177
# Frame displacement
179178
fdisp = pe.Node(nac.FramewiseDisplacement(parameter_source="SPM"),
180179
name="fdisp", mem_gb=mem_gb)
181180

182181
# a/t-CompCor
183-
tcompcor = pe.Node(TCompCor(
184-
components_file='tcompcor.tsv', pre_filter='cosine', save_pre_filter=True,
185-
percentile_threshold=.05), name="tcompcor", mem_gb=mem_gb)
186-
187-
acompcor = pe.Node(ACompCor(
188-
components_file='acompcor.tsv', pre_filter='cosine', save_pre_filter=True),
182+
tcompcor = pe.Node(
183+
TCompCor(components_file='tcompcor.tsv', header_prefix='t_comp_cor_', pre_filter='cosine',
184+
save_pre_filter=True, percentile_threshold=.05),
185+
name="tcompcor", mem_gb=mem_gb)
186+
187+
acompcor = pe.Node(
188+
ACompCor(components_file='acompcor.tsv', header_prefix='a_comp_cor_', pre_filter='cosine',
189+
save_pre_filter=True),
189190
name="acompcor", mem_gb=mem_gb)
190191

191192
# Set TR if present
@@ -195,12 +196,19 @@ def init_bold_confs_wf(mem_gb, metadata, name="bold_confs_wf"):
195196

196197
# Global and segment regressors
197198
mrg_lbl = pe.Node(niu.Merge(3), name='merge_rois', run_without_submitting=True)
198-
signals = pe.Node(SignalExtraction(class_labels=["CSF", "WhiteMatter", "GlobalSignal"]),
199+
signals = pe.Node(SignalExtraction(class_labels=["csf", "white_matter", "global_signal"]),
199200
name="signals", mem_gb=mem_gb)
200201

201202
# Arrange confounds
202-
add_header = pe.Node(AddTSVHeader(columns=["X", "Y", "Z", "RotX", "RotY", "RotZ"]),
203-
name="add_header", mem_gb=0.01, run_without_submitting=True)
203+
add_dvars_header = pe.Node(
204+
AddTSVHeader(columns=["dvars"]),
205+
name="add_dvars_header", mem_gb=0.01, run_without_submitting=True)
206+
add_std_dvars_header = pe.Node(
207+
AddTSVHeader(columns=["std_dvars"]),
208+
name="add_std_dvars_header", mem_gb=0.01, run_without_submitting=True)
209+
add_motion_headers = pe.Node(
210+
AddTSVHeader(columns=["trans_x", "trans_y", "trans_z", "rot_x", "rot_y", "rot_z"]),
211+
name="add_motion_headers", mem_gb=0.01, run_without_submitting=True)
204212
concat = pe.Node(GatherConfounds(), name="concat", mem_gb=0.01, run_without_submitting=True)
205213

206214
# Generate reportlet
@@ -273,14 +281,17 @@ def _pick_wm(files):
273281
(mrg_lbl, signals, [('out', 'label_files')]),
274282

275283
# Collate computed confounds together
276-
(inputnode, add_header, [('movpar_file', 'in_file')]),
284+
(inputnode, add_motion_headers, [('movpar_file', 'in_file')]),
285+
(dvars, add_dvars_header, [('out_nstd', 'in_file')]),
286+
(dvars, add_std_dvars_header, [('out_std', 'in_file')]),
277287
(signals, concat, [('out_file', 'signals')]),
278-
(dvars, concat, [('out_all', 'dvars')]),
279288
(fdisp, concat, [('out_file', 'fd')]),
280289
(tcompcor, concat, [('components_file', 'tcompcor'),
281290
('pre_filter_file', 'cos_basis')]),
282291
(acompcor, concat, [('components_file', 'acompcor')]),
283-
(add_header, concat, [('out_file', 'motion')]),
292+
(add_motion_headers, concat, [('out_file', 'motion')]),
293+
(add_dvars_header, concat, [('out_file', 'dvars')]),
294+
(add_std_dvars_header, concat, [('out_file', 'std_dvars')]),
284295

285296
# Set outputs
286297
(concat, outputnode, [('confounds_file', 'confounds_file')]),
@@ -356,11 +367,11 @@ def init_carpetplot_wf(mem_gb, metadata, name="bold_carpet_wf"):
356367
conf_plot = pe.Node(FMRISummary(
357368
tr=metadata['RepetitionTime'],
358369
confounds_list=[
359-
('GlobalSignal', None, 'GS'),
360-
('CSF', None, 'GSCSF'),
361-
('WhiteMatter', None, 'GSWM'),
362-
('stdDVARS', None, 'DVARS'),
363-
('FramewiseDisplacement', 'mm', 'FD')]),
370+
('global_signal', None, 'GS'),
371+
('csf', None, 'GSCSF'),
372+
('white_matter', None, 'GSWM'),
373+
('std_dvars', None, 'DVARS'),
374+
('framewise_displacement', 'mm', 'FD')]),
364375
name='conf_plot', mem_gb=mem_gb)
365376
ds_report_bold_conf = pe.Node(
366377
DerivativesDataSink(suffix='carpetplot'),

0 commit comments

Comments
 (0)