Skip to content

Commit

Permalink
Use CiftiCreateDenseFromTemplate for CIFTI ReHo (#1175)
Browse files Browse the repository at this point in the history
tsalo authored May 24, 2024
1 parent 4a50efc commit f61ac56
Showing 5 changed files with 103 additions and 51 deletions.
60 changes: 30 additions & 30 deletions .versions.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
{
"flagged": {
"0.0.1": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.2": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.3": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.4": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.5": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.6": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.7": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.8": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.0.9": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.1.0": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.1.1": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.1.2": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.1.3": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.2.0": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.2.1": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.2.2": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.3.0": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.3.1": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.3.2": "Denoised BOLD data contained interpolated volumes. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.4.0": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.5.0": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.5.1": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.5.2": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans. Temporal filtering may have reintroduced variance from nuisance regression.",
"0.6.0": "Temporal filtering may have reintroduced variance from nuisance regression.",
"0.6.1": "Temporal filtering may have reintroduced variance from nuisance regression.",
"0.6.2": "Temporal filtering may have reintroduced variance from nuisance regression.",
"0.6.3": "Temporal filtering may have reintroduced variance from nuisance regression.",
"0.7.1": "Band-pass filter parameters hardcoded to 0.01 - 0.1.",
"0.7.2": "Band-pass filter parameters hardcoded to 0.01 - 0.1.",
"0.7.3": "Band-pass filter parameters hardcoded to 0.01 - 0.1."
"0.0.1": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.2": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.3": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.4": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.5": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.6": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.7": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.8": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.0.9": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.1.0": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.1.1": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.1.2": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.1.3": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.2.0": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.2.1": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.2.2": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.3.0": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.3.1": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.3.2": "Denoised BOLD data contained interpolated volumes; Temporal filtering may have reintroduced variance from nuisance regression",
"0.4.0": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans; Temporal filtering may have reintroduced variance from nuisance regression",
"0.5.0": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans; Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.5.1": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans; Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.5.2": "Cubic spline interpolation + temporal filtering introduced extreme values at beginning and end of scans; Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.6.0": "Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.6.1": "Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.6.2": "Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.6.3": "Temporal filtering may have reintroduced variance from nuisance regression; Parcellated CIFTI ReHo TSVs were not accurate",
"0.7.1": "Band-pass filter parameters hardcoded to 0.01 - 0.1; Parcellated CIFTI ReHo TSVs were not accurate",
"0.7.2": "Band-pass filter parameters hardcoded to 0.01 - 0.1; Parcellated CIFTI ReHo TSVs were not accurate",
"0.7.3": "Band-pass filter parameters hardcoded to 0.01 - 0.1; Parcellated CIFTI ReHo TSVs were not accurate"
}
}
71 changes: 61 additions & 10 deletions xcp_d/interfaces/workbench.py
Original file line number Diff line number Diff line change
@@ -1115,27 +1115,54 @@ class _CiftiCreateDenseFromTemplateInputSpec(CommandLineInputSpec):
position=0,
desc="File to match brainordinates of.",
)
cifti_out = File(
name_source=["label"],
name_template="resampled_%s.dlabel.nii",
keep_extension=False,
out_file = File(
gen_file=True,
argstr="%s",
position=1,
desc="The output cifti file.",
)
volume_all = File(
exists=True,
mandatory=False,
argstr="-volume-all %s",
position=2,
desc="Use input data from volume files. Input volume file.",
)
from_cropped = traits.Bool(
False,
usedefault=True,
mandatory=False,
argstr="-from-cropped",
position=3,
desc="Use input data from cropped volume files.",
)
left_metric = File(
exists=True,
mandatory=False,
argstr="-metric CORTEX_LEFT %s",
position=4,
desc="Use input data from surface files. Input surface file.",
)
right_metric = File(
exists=True,
mandatory=False,
argstr="-metric CORTEX_RIGHT %s",
position=5,
desc="Use input data from surface files. Input surface file.",
)
label = File(
exists=True,
mandatory=True,
mandatory=False,
argstr="-cifti %s",
position=2,
position=6,
desc="Use input data from surface label files. Input label file.",
)


class _CiftiCreateDenseFromTemplateOutputSpec(TraitedSpec):
"""Output specification for the CiftiCreateDenseFromTemplate command."""

cifti_out = File(exists=True, desc="output CIFTI file")
out_file = File(exists=True, desc="output CIFTI file")


class CiftiCreateDenseFromTemplate(WBCommand):
@@ -1158,18 +1185,42 @@ class CiftiCreateDenseFromTemplate(WBCommand):
--------
>>> ccdft = CiftiCreateDenseFromTemplate()
>>> ccdft.inputs.template_cifti = "sub-01_task-rest_bold.dtseries.nii"
>>> ccdft.inputs.label = "parcellation.dlabel.nii"
>>> ccdft.inputs.volume_all = "parcellation.nii.gz"
>>> ccdft.inputs.from_cropped = True
>>> ccdft.inputs.left_metric = "lh.func.gii"
>>> ccdft.inputs.right_metric = "rh.func.gii"
>>> ccdft.cmdline
wb_command -cifti-create-dense-from-template \
sub-01_task-rest_bold.dtseries.nii \
resampled_parcellation.dlabel.nii \
-label parcellation.dlabel.nii
resampled_parcellation.dscalar.nii \
-volume-all parcellation.nii.gz \
-from-cropped \
-metric CORTEX_LEFT lh.func.gii \
-metric CORTEX_RIGHT rh.func.gii
"""

input_spec = _CiftiCreateDenseFromTemplateInputSpec
output_spec = _CiftiCreateDenseFromTemplateOutputSpec
_cmd = "wb_command -cifti-create-dense-from-template"

def _gen_filename(self, name):
if name != "out_file":
return None

if isdefined(self.inputs.out_file):
return self.inputs.out_file
elif isdefined(self.inputs.label):
_, fname, _ = split_filename(self.inputs.label)
else:
_, fname, _ = split_filename(self.inputs.template_cifti)

return f"{fname}_converted.dscalar.nii"

def _list_outputs(self):
outputs = self.output_spec().get()
outputs["out_file"] = os.path.abspath(self._gen_filename("out_file"))
return outputs


class _CiftiChangeMappingInputSpec(CommandLineInputSpec):
"""Input specification for the CiftiCreateDenseFromTemplate command."""
3 changes: 2 additions & 1 deletion xcp_d/tests/test_workflows_connectivity.py
Original file line number Diff line number Diff line change
@@ -271,6 +271,7 @@ def test_init_functional_connectivity_cifti_wf(ds001419_data, tmp_path_factory):
resample_atlas_to_data = CiftiCreateDenseFromTemplate(
template_cifti=bold_file,
label=atlas_file,
out_file="resampled_atlas_to_data.dscalar.nii",
)
resample_results = resample_atlas_to_data.run(cwd=tmpdir)

@@ -279,7 +280,7 @@ def test_init_functional_connectivity_cifti_wf(ds001419_data, tmp_path_factory):
only_numeric=True,
out_file=f"parcellated_atlas_{i_file}.pscalar.nii",
atlas_label=atlas_file,
in_file=resample_results.outputs.cifti_out,
in_file=resample_results.outputs.out_file,
)
parcellate_atlas_results = parcellate_atlas.run(cwd=tmpdir)

12 changes: 6 additions & 6 deletions xcp_d/workflows/connectivity.py
Original file line number Diff line number Diff line change
@@ -150,7 +150,7 @@ def init_load_atlases_wf(name="load_atlases_wf"):
# Add empty vertices to atlas for locations in data, but not in atlas
# (e.g., subcortical regions for cortex-only atlases)
resample_atlas_to_data = pe.MapNode(
CiftiCreateDenseFromTemplate(),
CiftiCreateDenseFromTemplate(out_file="resampled_atlas.dlabel.nii"),
name="resample_atlas_to_data",
n_procs=omp_nthreads,
iterfield=["label"],
@@ -159,7 +159,7 @@ def init_load_atlases_wf(name="load_atlases_wf"):
workflow.connect([
(inputnode, resample_atlas_to_data, [("bold_file", "template_cifti")]),
(atlas_file_grabber, resample_atlas_to_data, [("atlas_file", "label")]),
(resample_atlas_to_data, atlas_buffer, [("cifti_out", "atlas_file")]),
(resample_atlas_to_data, atlas_buffer, [("out_file", "atlas_file")]),
]) # fmt:skip

# Change the atlas to a scalar file.
@@ -175,7 +175,7 @@ def init_load_atlases_wf(name="load_atlases_wf"):
iterfield=["data_cifti"],
)
workflow.connect([
(resample_atlas_to_data, convert_to_dscalar, [("cifti_out", "data_cifti")]),
(resample_atlas_to_data, convert_to_dscalar, [("out_file", "data_cifti")]),
]) # fmt:skip

# Convert atlas from dlabel to pscalar format.
@@ -332,7 +332,7 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w

for file_to_parcellate in files_to_parcellate:
resample_atlas_to_surface = pe.MapNode(
CiftiCreateDenseFromTemplate(),
CiftiCreateDenseFromTemplate(out_file="resampled_atlas.dlabel.nii"),
name=f"resample_atlas_to_{file_to_parcellate}",
n_procs=omp_nthreads,
iterfield=["label"],
@@ -360,7 +360,7 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w
# fmt:off
workflow.connect([
(inputnode, parcellate_atlas, [(file_to_parcellate, "in_file")]),
(resample_atlas_to_surface, parcellate_atlas, [("cifti_out", "atlas_label")]),
(resample_atlas_to_surface, parcellate_atlas, [("out_file", "atlas_label")]),
])
# fmt:on

@@ -376,7 +376,7 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w
# fmt:off
workflow.connect([
(inputnode, parcellate_surface, [(file_to_parcellate, "data_file")]),
(resample_atlas_to_surface, parcellate_surface, [("cifti_out", "atlas")]),
(resample_atlas_to_surface, parcellate_surface, [("out_file", "atlas")]),
(atlas_file_grabber, parcellate_surface, [("atlas_labels_file", "atlas_labels")]),
(parcellate_atlas, parcellate_surface, [("out_file", "parcellated_atlas")]),
])
8 changes: 4 additions & 4 deletions xcp_d/workflows/restingstate.py
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
from xcp_d.interfaces.nilearn import Smooth
from xcp_d.interfaces.restingstate import ComputeALFF, ReHoNamePatch, SurfaceReHo
from xcp_d.interfaces.workbench import (
CiftiCreateDenseScalar,
CiftiCreateDenseFromTemplate,
CiftiSeparateMetric,
CiftiSeparateVolumeAll,
FixCiftiIntent,
@@ -345,7 +345,7 @@ def init_reho_cifti_wf(

# Merge the surfaces and subcortical structures back into a CIFTI
merge_cifti = pe.Node(
CiftiCreateDenseScalar(),
CiftiCreateDenseFromTemplate(from_cropped=True, out_file="reho.dscalar.nii"),
name="merge_cifti",
mem_gb=mem_gb["resampled"],
n_procs=omp_nthreads,
@@ -381,10 +381,10 @@ def init_reho_cifti_wf(
(lh_surf, lh_reho, [("out_file", "surf_bold")]),
(rh_surf, rh_reho, [("out_file", "surf_bold")]),
(subcortical_nifti, subcortical_reho, [("out_file", "in_file")]),
(subcortical_nifti, merge_cifti, [("label_file", "structure_label_volume")]),
(inputnode, merge_cifti, [("denoised_bold", "template_cifti")]),
(lh_reho, merge_cifti, [("surf_gii", "left_metric")]),
(rh_reho, merge_cifti, [("surf_gii", "right_metric")]),
(subcortical_reho, merge_cifti, [("out_file", "volume_data")]),
(subcortical_reho, merge_cifti, [("out_file", "volume_all")]),
(merge_cifti, outputnode, [("out_file", "reho")]),
(merge_cifti, reho_plot, [("out_file", "filename")]),
(reho_plot, ds_reho_plot, [("output_path", "in_file")]),

0 comments on commit f61ac56

Please sign in to comment.