Skip to content

Enable doctests #1410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ inline-quotes = "single"
quote-style = "single"

[tool.pytest.ini_options]
addopts = '-m "not integration"'
addopts = '--doctest-modules -m "not integration"'
markers = [
"integration: mark test as an integration test",
"ds001419_nifti: mark NIfTI integration test for fMRIPrep derivatives from ds001419",
Expand Down
29 changes: 9 additions & 20 deletions xcp_d/interfaces/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,25 +231,7 @@ class _QCPlotsOutputSpec(TraitedSpec):


class QCPlots(SimpleInterface):
"""Generate pre- and post-processing quality control (QC) figures.

Examples
--------
.. testsetup::
>>> from tempfile import TemporaryDirectory
>>> tmpdir = TemporaryDirectory()
>>> os.chdir(tmpdir.name)
.. doctest::
qcplots = QCPlots()
qcplots.inputs.cleaned_file = datafile
qcplots.inputs.bold_file = rawbold
qcplots.inputs.TR = TR
qcplots.inputs.temporal_mask = temporalmask
qcplots.inputs.mask_file = mask
qcplots.run()
.. testcleanup::
>>> tmpdir.cleanup()
"""
"""Generate pre- and post-processing quality control (QC) figures."""

input_spec = _QCPlotsInputSpec
output_spec = _QCPlotsOutputSpec
Expand Down Expand Up @@ -1109,13 +1091,20 @@ class PlotNifti(SimpleInterface):
def _run_interface(self, runtime):
from bids.layout import parse_file_entities

from xcp_d.data import load as load_data

xcp_d_config = str(load_data('xcp_d_bids_config2.json'))

ENTITIES_TO_USE = ['cohort', 'den', 'res']

# templateflow uses the full entity names in its BIDSLayout config,
# so we need to map the abbreviated names used by xcpd and pybids to the full ones.
ENTITY_NAMES_MAPPER = {'den': 'density', 'res': 'resolution'}
space = parse_file_entities(self.inputs.name_source)['space']
file_entities = parse_file_entities(self.inputs.name_source)
file_entities = parse_file_entities(
self.inputs.name_source,
config=['bids', 'derivatives', xcp_d_config],
)
entities_to_use = {f: file_entities[f] for f in file_entities if f in ENTITIES_TO_USE}
entities_to_use = {ENTITY_NAMES_MAPPER.get(k, k): v for k, v in entities_to_use.items()}

Expand Down
41 changes: 3 additions & 38 deletions xcp_d/interfaces/restingstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,7 @@ class _SurfaceReHoOutputSpec(TraitedSpec):


class SurfaceReHo(SimpleInterface):
"""Calculate regional homogeneity (ReHo) on a surface file.

Examples
--------
.. testsetup::
>>> from tempfile import TemporaryDirectory
>>> tmpdir = TemporaryDirectory()
>>> os.chdir(tmpdir.name)
.. doctest::
>>> surfacereho_wf = SurfaceReHo()
>>> surfacereho_wf.inputs.surf_bold = 'rhhemi.func.gii'
>>> surfacereho_wf.inputs.surf_hemi = 'R'
>>> surfacereho_wf.run()
.. testcleanup::
>>> tmpdir.cleanup()
"""
"""Calculate regional homogeneity (ReHo) on a surface file."""

input_spec = _SurfaceReHoInputSpec
output_spec = _SurfaceReHoOutputSpec
Expand Down Expand Up @@ -212,18 +197,7 @@ class ReHoNamePatch(SimpleInterface):
"""Compute ReHo for a given neighbourhood, based on a local neighborhood of that voxel.

For complete details, see the `3dReHo Documentation.
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dReHo.html>`_

Examples
--------
>>> from nipype.interfaces import afni
>>> reho = afni.ReHo()
>>> reho.inputs.in_file = 'functional.nii'
>>> reho.inputs.out_file = 'reho.nii.gz'
>>> reho.inputs.neighborhood = 'vertices'
>>> reho.cmdline
'3dReHo -prefix reho.nii.gz -inset functional.nii -nneigh 27'
>>> res = reho.run() # doctest: +SKIP
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dReHo.html>`_.
"""

_cmd = '3dReHo'
Expand Down Expand Up @@ -260,16 +234,7 @@ class DespikePatch(Despike):
"""Remove 'spikes' from the 3D+time input dataset.

For complete details, see the `3dDespike Documentation.
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dDespike.html>`_

Examples
--------
>>> from nipype.interfaces import afni
>>> despike = afni.Despike()
>>> despike.inputs.in_file = 'functional.nii'
>>> despike.cmdline
'3dDespike -prefix functional_despike functional.nii'
>>> res = despike.run() # doctest: +SKIP
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dDespike.html>`_.
"""

input_spec = _DespikePatchInputSpec
Expand Down
116 changes: 3 additions & 113 deletions xcp_d/interfaces/workbench.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,18 +447,6 @@ class CiftiParcellateWorkbench(WBCommand):

The input cifti file must have a brain models mapping on the chosen
dimension, columns for .dtseries.

Examples
--------
>>> ciftiparcel = CiftiParcellateWorkbench()
>>> ciftiparcel.inputs.in_file = 'sub-01XX_task-rest.dtseries.nii'
>>> ciftiparcel.inputs.out_file = 'sub_01XX_task-rest.ptseries.nii'
>>> ciftiparcel.inputs.atlas_label = 'schaefer_space-fsLR_den-32k_desc-400_atlas.dlabel.nii'
>>> ciftiparcel.inputs.direction = 'COLUMN'
>>> ciftiparcel.cmdline
wb_command -cifti-parcellate sub-01XX_task-rest.dtseries.nii \
schaefer_space-fsLR_den-32k_desc-400_atlas.dlabel.nii COLUMN \
sub_01XX_task-rest.ptseries.nii
"""

input_spec = _CiftiParcellateWorkbenchInputSpec
Expand Down Expand Up @@ -589,17 +577,6 @@ class CiftiSeparateMetric(WBCommand):
Other structures can also be extracted.
The input cifti file must have a brain models mapping on the chosen
dimension, columns for .dtseries,

Examples
--------
>>> ciftiseparate = CiftiSeparateMetric()
>>> ciftiseparate.inputs.in_file = 'sub-01XX_task-rest.dtseries.nii'
>>> ciftiseparate.inputs.metric = "CORTEX_LEFT" # extract left hemisphere
>>> ciftiseparate.inputs.out_file = 'sub_01XX_task-rest_hemi-L.func.gii'
>>> ciftiseparate.inputs.direction = 'COLUMN'
>>> ciftiseparate.cmdline
wb_command -cifti-separate 'sub-01XX_task-rest.dtseries.nii' COLUMN \
-metric CORTEX_LEFT 'sub_01XX_task-rest_hemi-L.func.gii'
"""

input_spec = _CiftiSeparateMetricInputSpec
Expand Down Expand Up @@ -655,19 +632,7 @@ class CiftiSeparateVolumeAll(WBCommand):

Other structures can also be extracted.
The input cifti file must have a brain models mapping on the chosen
dimension, columns for .dtseries,

Examples
--------
>>> ciftiseparate = CiftiSeparateVolumeAll()
>>> ciftiseparate.inputs.in_file = 'sub-01_task-rest.dtseries.nii'
>>> ciftiseparate.inputs.out_file = 'sub_01_task-rest_volumetric_data.nii.gz'
>>> ciftiseparate.inputs.label_file = 'sub_01_task-rest_labels.nii.gz'
>>> ciftiseparate.inputs.direction = 'COLUMN'
>>> ciftiseparate.cmdline
wb_command -cifti-separate 'sub-01XX_task-rest.dtseries.nii' COLUMN \
-volume-all 'sub_01_task-rest_volumetric_data.nii.gz' \
-label 'sub_01_task-rest_labels.nii.gz'
dimension, columns for .dtseries.
"""

input_spec = _CiftiSeparateVolumeAllInputSpec
Expand Down Expand Up @@ -727,21 +692,7 @@ class CiftiCreateDenseScalar(WBCommand):

Other structures can also be extracted.
The input cifti file must have a brain models mapping on the chosen
dimension, columns for .dtseries,

Examples
--------
>>> cifticreatedensescalar = CiftiCreateDenseScalar()
>>> cifticreatedensescalar.inputs.out_file = 'sub_01_task-rest.dscalar.nii'
>>> cifticreatedensescalar.inputs.left_metric = 'sub_01_task-rest_hemi-L.func.gii'
>>> cifticreatedensescalar.inputs.left_metric = 'sub_01_task-rest_hemi-R.func.gii'
>>> cifticreatedensescalar.inputs.volume_data = 'sub_01_task-rest_subcortical.nii.gz'
>>> cifticreatedensescalar.inputs.structure_label_volume = 'sub_01_task-rest_labels.nii.gz'
>>> cifticreatedensescalar.cmdline
wb_command -cifti-create-dense-scalar 'sub_01_task-rest.dscalar.nii' \
-left-metric 'sub_01_task-rest_hemi-L.func.gii' \
-right-metric 'sub_01_task-rest_hemi-R.func.gii' \
-volume-data 'sub_01_task-rest_subcortical.nii.gz' 'sub_01_task-rest_labels.nii.gz'
dimension, columns for .dtseries.
"""

input_spec = _CiftiCreateDenseScalarInputSpec
Expand Down Expand Up @@ -942,17 +893,7 @@ class _CiftiConvertOutputSpec(TraitedSpec):


class CiftiConvert(WBCommand):
"""Convert between CIFTI and NIFTI file formats.

Examples
--------
>>> cifticonvert = CiftiConvert()
>>> cifticonvert.inputs.in_file = 'sub-01_task-rest_bold.dscalar.nii'
>>> cifticonvert.target = "to"
>>> cifticonvert.cmdline
wb_command -cifti-convert -to-nifti 'sub-01_task-rest_bold.dscalar.nii' \
'sub-01_task-rest_bold_converted.nii.gz'
"""
"""Convert between CIFTI and NIFTI file formats."""

input_spec = _CiftiConvertInputSpec
output_spec = _CiftiConvertOutputSpec
Expand Down Expand Up @@ -1050,23 +991,6 @@ class CiftiCreateDenseFromTemplate(WBCommand):

Any structure that isn't covered by an input is filled with zeros or the
unlabeled key.

Examples
--------
>>> ccdft = CiftiCreateDenseFromTemplate()
>>> ccdft.inputs.template_cifti = "sub-01_task-rest_bold.dtseries.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.dscalar.nii \
-volume-all parcellation.nii.gz \
-from-cropped \
-metric CORTEX_LEFT lh.func.gii \
-metric CORTEX_RIGHT rh.func.gii
"""

input_spec = _CiftiCreateDenseFromTemplateInputSpec
Expand Down Expand Up @@ -1136,16 +1060,6 @@ class CiftiMath(WBCommand):

I should use a dynamic trait for the variables going into the math expression,
but I hardcoded data and mask because those are the only ones I'm currently using.

Examples
--------
>>> ciftimath = CiftiMath()
>>> ciftimath.inputs.data = 'sub-01XX_task-rest.dtseries.nii'
>>> ciftimath.inputs.out_file = 'mathed_sub_01XX_task-rest.dtseries.nii'
>>> ciftimath.inputs.expression = 'data * 2'
>>> ciftimath.cmdline
wb_command -cifti-math "data * 2" mathed_sub_01XX_task-rest.dtseries.nii \
-var data sub-01XX_task-rest.dtseries.nii
"""

input_spec = _CiftiMathInputSpec
Expand Down Expand Up @@ -1183,16 +1097,6 @@ class CiftiCorrelation(WBCommand):
"""Generate correlation of rows in CIFTI file.

This interface only supports parcellated time series files for now.

Examples
--------
>>> cifticorrelation = CiftiCorrelation()
>>> cifticorrelation.inputs.in_file = 'sub-01XX_task-rest_bold.ptseries.nii'
>>> cifticorrelation.inputs.out_file = 'sub-01XX_task-rest_bold.pconn.nii'
>>> cifticorrelation.cmdline
wb_command -cifti-correlation \
sub-01XX_task-rest_bold.ptseries.nii \
sub-01XX_task-rest_bold.pconn.nii
"""

input_spec = _CiftiCorrelationInputSpec
Expand Down Expand Up @@ -1323,20 +1227,6 @@ class CiftiSmooth(WBCommand):
zeros with extrapolated values. The ROI should have a brain models
mapping along columns, exactly matching the mapping of the chosen
direction in the input file. Data outside the ROI is ignored.

>>> from xcp_d.interfaces.workbench import CiftiSmooth
>>> smooth = CiftiSmooth()
>>> smooth.inputs.in_file = 'sub-01_task-rest.dtseries.nii'
>>> smooth.inputs.sigma_surf = 4
>>> smooth.inputs.sigma_vol = 4
>>> smooth.inputs.direction = 'COLUMN'
>>> smooth.inputs.right_surf = 'sub-01.R.midthickness.32k_fs_LR.surf.gii'
>>> smooth.inputs.left_surf = 'sub-01.L.midthickness.32k_fs_LR.surf.gii'
>>> smooth.cmdline
'wb_command -cifti-smoothing sub-01_task-rest.dtseries.nii 4.0 4.0 COLUMN \
smoothed_sub-01_task-rest.dtseries.nii \
-left-surface sub-01.L.midthickness.32k_fs_LR.surf.gii \
-right-surface sub-01.R.midthickness.32k_fs_LR.surf.gii'
"""

input_spec = _CiftiSmoothInputSpec
Expand Down