diff --git a/niworkflows/data/nipreps.json b/niworkflows/data/nipreps.json deleted file mode 100644 index 56b86770e5a..00000000000 --- a/niworkflows/data/nipreps.json +++ /dev/null @@ -1,211 +0,0 @@ -{ - "name": "nipreps", - "entities": [ - { - "name": "subject", - "pattern": "[/\\\\]+sub-([a-zA-Z0-9+]+)", - "directory": "{subject}" - }, - { - "name": "session", - "pattern": "[_/\\\\]+ses-([a-zA-Z0-9+]+)", - "mandatory": false, - "directory": "{subject}{session}" - }, - { - "name": "task", - "pattern": "[_/\\\\]+task-([a-zA-Z0-9+]+)" - }, - { - "name": "acquisition", - "pattern": "[_/\\\\]+acq-([a-zA-Z0-9+]+)" - }, - { - "name": "ceagent", - "pattern": "[_/\\\\]+ce-([a-zA-Z0-9+]+)" - }, - { - "name": "reconstruction", - "pattern": "[_/\\\\]+rec-([a-zA-Z0-9+]+)" - }, - { - "name": "tracer", - "pattern": "[_/\\\\]+trc-([a-zA-Z0-9+]+)" - }, - { - "name": "direction", - "pattern": "[_/\\\\]+dir-([a-zA-Z0-9+]+)" - }, - { - "name": "run", - "pattern": "[_/\\\\]+run-(\\d+)", - "dtype": "int" - }, - { - "name": "proc", - "pattern": "[_/\\\\]+proc-([a-zA-Z0-9+]+)" - }, - { - "name": "pvc", - "pattern": "[_/\\\\]+pvc-([a-zA-Z0-9+]+)" - }, - { - "name": "modality", - "pattern": "[_/\\\\]+mod-([a-zA-Z0-9+]+)" - }, - { - "name": "echo", - "pattern": "[_/\\\\]+echo-([0-9]+)" - }, - { - "name": "flip", - "pattern": "[_/\\\\]+flip-([0-9]+)" - }, - { - "name": "inv", - "pattern": "[_/\\\\]+inv-([0-9]+)" - }, - { - "name": "mt", - "pattern": "[_/\\\\]+mt-(on|off)" - }, - { - "name": "part", - "pattern": "[_/\\\\]+part-(mag|phase|real|imag)" - }, - { - "name": "recording", - "pattern": "[_/\\\\]+recording-([a-zA-Z0-9+]+)" - }, - { - "name": "space", - "pattern": "[_/\\\\]+space-([a-zA-Z0-9+]+)" - }, - { - "name": "suffix", - "pattern": "[._]*([a-zA-Z0-9]*?)\\.[^/\\\\]+$" - }, - { - "name": "scans", - "pattern": "(.*\\_scans.tsv)$" - }, - { - "name": "fmap", - "pattern": "(phasediff|magnitude[1-2]|phase[1-2]|fieldmap|epi)\\.nii" - }, - { - "name": "datatype", - "pattern": "[/\\\\]+(func|anat|pet|fmap|dwi|perf|meg|eeg|figures)[/\\\\]+" - }, - { - "name": "extension", - "pattern": "[._]*[a-zA-Z0-9]*?(\\.[^/\\\\]+)$" - }, - { - "name": "atlas", - "pattern": "[_/\\\\]+atlas-([a-zA-Z0-9+]+)" - }, - { - "name": "roi", - "pattern": "[_/\\\\]+roi-([a-zA-Z0-9+]+)" - }, - { - "name": "label", - "pattern": "[_/\\\\]+label-([a-zA-Z0-9+]+)" - }, - { - "name": "fmapid", - "pattern": "[_/\\\\]+fmapid-([a-zA-Z0-9+]+)" - }, - { - "name": "desc", - "pattern": "[_/\\\\]+desc-([a-zA-Z0-9+]+)" - }, - { - "name": "from", - "pattern": "(?:^|_)from-([a-zA-Z0-9+]+).*xfm" - }, - { - "name": "to", - "pattern": "(?:^|_)to-([a-zA-Z0-9+]+).*xfm" - }, - { - "name": "mode", - "pattern": "(?:^|_)mode-(image|points).*xfm" - }, - { - "name": "hemi", - "pattern": "hemi-(L|R)" - }, - { - "name": "model", - "pattern": "model-([a-zA-Z0-9+]+)" - }, - { - "name": "subset", - "pattern": "subset-([a-zA-Z0-9+]+)" - }, - { - "name": "resolution", - "pattern": "res-([a-zA-Z0-9+]+)" - }, - { - "name": "density", - "pattern": "res-([a-zA-Z0-9+]+)" - }, - { - "name": "cohort", - "pattern": "[_/\\\\]+cohort-0*(\\d+)", - "dtype": "int" - }, - { - "name": "hash", - "pattern": "hash-([a-zA-Z0-9+]+)" - } - ], - "default_path_patterns": [ - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}][_hemi-{hemi}]_from-{from}_to-{to}_mode-{mode|image}_{suffix|xfm}{extension<.txt|.h5>}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}]_hemi-{hemi}[_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.surf.gii|.shape.gii>}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.dscalar.nii|.json>}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_label-{label}]_desc-{desc}_{suffix|mask}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}]_label-{label}[_desc-{desc}]_{suffix|probseg}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_desc-{desc}]_{suffix}{extension<.tsv|.json>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_label-{label}][_desc-{desc}]_{suffix}{extension<.tsv|.json>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|anat}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_run-{run}]_hemi-{hemi}[_space-{space}][_cohort-{cohort}][_den-{density}]_desc-{desc}_{suffix|mask}{extension<.label.gii|.json>|.label.gii}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_hemi-{hemi}]_from-{from}_to-{to}_mode-{mode|image}[_desc-{desc}]_{suffix|xfm}{extension<.txt|.h5>}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_res-{resolution}]_desc-{desc}_{suffix|mask}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix|AROMAnoiseICs}{extension<.csv|.tsv>|.csv}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix|timeseries}{extension<.json|.tsv>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix|components}{extension<.json|.tsv|.nii|.nii.gz>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix|decomposition}{extension<.json>|.json}", - "sub-{subject}[/ses-{session}]/{datatype|func}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_hemi-{hemi}][_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.dtseries.nii|.dtseries.json|.func.gii|.func.json>}", - "sub-{subject}[/ses-{session}]/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|dwi}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.json|.nii.gz|.nii>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|dwi}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}]_desc-{desc}_{suffix}{extension<.json|.nii.gz|.nii>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|dwi}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_desc-{desc}]_{suffix}{extension<.tsv|.bval|.bvec|.b>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|dwi}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_rec-{reconstruction}][_dir-{direction}][_run-{run}]_from-{from}_to-{to}_mode-{mode|image}[_desc-{desc}]_{suffix|xfm}{extension<.txt|.h5>}", - "sub-{subject}[/ses-{session}]/{datatype|perf}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_rec-{reconstruction}][_dir-{direction}][_run-{run}]_{suffix}{extension<.tsv|.json>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|perf}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}]_from-{from}_to-{to}_mode-{mode|image}_{suffix|xfm}{extension<.txt|.h5>}", - "sub-{subject}[/ses-{session}]/{datatype|perf}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_atlas-{atlas}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.json|.tsv>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|perf}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_space-{space}][_atlas-{atlas}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json|.tsv>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|fmap}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_dir-{direction}][_run-{run}][_part-{part}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_fmapid-{fmapid}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|fmap}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_dir-{direction}][_run-{run}][_part-{part}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_fmapid-{fmapid}][_label-{label}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}][_pvc-{pvc}][_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_hemi-{hemi}]_from-{from}_to-{to}_mode-{mode|image}_{suffix|xfm}{extension<.txt|.h5>}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}]_hemi-{hemi}[_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.surf.gii|.shape.gii>}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.dscalar.nii|.json>}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}]_desc-{desc}_{suffix|mask}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_res-{resolution}]_label-{label}[_desc-{desc}]_{suffix|probseg}{extension<.nii|.nii.gz|.json>|.nii.gz}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_part-{part}][_space-{space}][_cohort-{cohort}][_label-{label}][_pvc-{pvc}][_desc-{desc}]_{suffix|timeseries}{extension<.json|.tsv>|.tsv}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_hemi-{hemi}][_pvc-{pvc}][_space-{space}][_cohort-{cohort}][_den-{density}][_desc-{desc}]_{suffix}{extension<.dtseries.nii|.dtseries.json|.func.gii|.func.json>}", - "sub-{subject}[/ses-{session}]/{datatype|pet}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_label-{label}][_res-{resolution}]_desc-{desc}_{suffix}{extension<.tsv|.json>|.tsv}", - "sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}", - "sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_fmapid-{fmapid}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}", - "sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}", - "sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}", - "sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_label-{label}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}" - ] -} diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py index b01841fe823..685acb2ee80 100644 --- a/niworkflows/interfaces/bids.py +++ b/niworkflows/interfaces/bids.py @@ -27,7 +27,7 @@ import shutil from collections import defaultdict from contextlib import suppress -from json import dumps, loads +from json import dumps from pathlib import Path import nibabel as nb @@ -51,13 +51,270 @@ from nipype.interfaces.io import add_traits from nipype.utils.filemanip import hash_infile -from .. import data from ..utils.bids import _init_layout, relative_to_root from ..utils.images import set_consumables, unsafe_write_nifti_header_and_data from ..utils.misc import _copy_any, unlink regz = re.compile(r'\.gz$') -_pybids_spec = loads(data.load.readable('nipreps.json').read_text()) + +# Generate the pybids config from the BIDS schema with NiPreps extensions. +# Standard derivative patterns come from the schema (with hash entity injected); +# only patterns with non-schema suffixes or NiPreps-specific entities are listed +# explicitly below. +from bids.layout.config_gen import ConfigExtension, generate_extended_config + +# NiPreps-specific extra rules for path pattern generation. Each rule dict +# specifies datatypes, suffixes, and extensions; entities are inherited from the +# schema's derivative rules for the given datatypes and only *additions* (like +# the non-schema entities fmapid, pvc, from/to/mode) or *overrides* (like +# hemisphere=required for surface files) need to be listed explicitly. +# +# Schema-covered patterns (mask, probseg, dseg, phase, fieldmap, T2starmap, dwi +# sidecars) come from rule_groups=["deriv"] with hash injection. +# Shared entity sets +_XFM_ENTITIES = { + 'from': 'required', + 'to': 'required', + 'mode': {'level': 'required', 'enum': ['image', 'points'], 'default': 'image'}, +} +_PET_ENTITIES = { + 'acquisition': 'optional', + 'ceagent': 'optional', + 'cohort': 'optional', + 'density': 'optional', + 'direction': 'optional', + 'hemisphere': 'optional', + 'label': 'optional', + 'part': 'optional', +} +_PERF_ENTITIES = { + 'task': 'optional', + 'ceagent': 'optional', + 'atlas': 'optional', + 'label': 'optional', +} + +# Shared suffix/extension lists +_SURFACE_SUFFIXES = [ + 'white', + 'smoothwm', + 'pial', + 'midthickness', + 'inflated', + 'vinflated', + 'sphere', + 'flat', + 'sulc', + 'curv', + 'thickness', +] +_SCALAR_SUFFIXES = ['sulc', 'curv', 'thickness'] +_CIFTI_EXTENSIONS = ['.dtseries.nii', '.dtseries.json', '.func.gii', '.func.json'] + +_NIPREPS_EXTRA_RULES = [ + # --- Transforms (all datatypes) --- + { + 'datatypes': ['anat', 'func', 'dwi'], + 'suffixes': ['xfm'], + 'extensions': ['.txt', '.h5'], + 'entities': _XFM_ENTITIES, + }, + { + 'datatypes': ['perf'], + 'suffixes': ['xfm'], + 'extensions': ['.txt', '.h5'], + 'entities': {**_PERF_ENTITIES, **_XFM_ENTITIES}, + }, + { + 'datatypes': ['pet'], + 'suffixes': ['xfm'], + 'extensions': ['.txt', '.h5'], + 'entities': {**_PET_ENTITIES, **_XFM_ENTITIES}, + }, + # --- Surface anatomy (anat + pet) --- + { + 'datatypes': ['anat'], + 'suffixes': _SURFACE_SUFFIXES, + 'extensions': ['.surf.gii', '.shape.gii'], + 'entities': {'hemisphere': 'required'}, + }, + {'datatypes': ['anat'], 'suffixes': _SCALAR_SUFFIXES, 'extensions': ['.dscalar.nii', '.json']}, + {'datatypes': ['anat'], 'suffixes': ['morph'], 'extensions': ['.tsv', '.json']}, + { + 'datatypes': ['anat'], + 'suffixes': ['mask'], + 'extensions': ['.label.gii', '.json'], + 'entities': {'hemisphere': 'required', 'description': 'required'}, + }, + { + 'datatypes': ['pet'], + 'suffixes': _SURFACE_SUFFIXES, + 'extensions': ['.surf.gii', '.shape.gii'], + 'entities': {**_PET_ENTITIES, 'hemisphere': 'required'}, + }, + { + 'datatypes': ['pet'], + 'suffixes': _SCALAR_SUFFIXES, + 'extensions': ['.dscalar.nii', '.json'], + 'entities': _PET_ENTITIES, + }, + { + 'datatypes': ['pet'], + 'suffixes': ['morph'], + 'extensions': ['.tsv', '.json'], + 'entities': {**_PET_ENTITIES, 'description': 'required'}, + }, + # --- CIFTI/surface extensions for schema suffixes --- + { + 'datatypes': ['func'], + 'suffixes': ['bold', 'boldmap'], + 'extensions': _CIFTI_EXTENSIONS, + 'entities': {'hemisphere': 'optional', 'density': 'optional'}, + }, + { + 'datatypes': ['pet'], + 'suffixes': ['pet'], + 'extensions': _CIFTI_EXTENSIONS, + 'entities': {**_PET_ENTITIES, 'pvc': 'optional'}, + }, + # --- anat --- + { + 'datatypes': ['anat'], + 'suffixes': ['MTw', 'TSE'], + 'extensions': ['.nii', '.nii.gz', '.json'], + }, + # --- func --- + { + 'datatypes': ['func'], + 'suffixes': ['boldref', 'boldmap'], + 'extensions': ['.nii', '.nii.gz', '.json'], + }, + {'datatypes': ['func'], 'suffixes': ['AROMAnoiseICs'], 'extensions': ['.csv', '.tsv']}, + { + 'datatypes': ['func'], + 'suffixes': ['timeseries', 'regressors'], + 'extensions': ['.json', '.tsv'], + }, + { + 'datatypes': ['func'], + 'suffixes': ['components', 'mixing'], + 'extensions': ['.json', '.tsv', '.nii', '.nii.gz'], + }, + {'datatypes': ['func'], 'suffixes': ['decomposition'], 'extensions': ['.json']}, + # --- dwi --- + { + 'datatypes': ['dwi'], + 'suffixes': ['dwiref', 'epiref', 'lowb'], + 'extensions': ['.nii', '.nii.gz', '.json'], + }, + # --- perf --- + { + 'datatypes': ['perf'], + 'suffixes': ['aslcontext'], + 'extensions': ['.tsv', '.json'], + 'entities': {'task': 'optional'}, + }, + { + 'datatypes': ['perf'], + 'suffixes': ['timeseries'], + 'extensions': ['.json', '.tsv'], + 'entities': _PERF_ENTITIES, + }, + { + 'datatypes': ['perf'], + 'suffixes': ['asl', 'aslref', 'att', 'cbf', 'coverage', 'mask'], + 'extensions': ['.nii', '.nii.gz', '.json', '.tsv'], + 'entities': _PERF_ENTITIES, + }, + # --- fmap --- + { + 'datatypes': ['fmap'], + 'suffixes': ['fieldmap', 'mask'], + 'extensions': ['.nii', '.nii.gz', '.json'], + 'entities': {'fmapid': 'optional'}, + }, + # --- pet --- + { + 'datatypes': ['pet'], + 'suffixes': ['pet', 'petref'], + 'extensions': ['.nii', '.nii.gz', '.json'], + 'entities': {**_PET_ENTITIES, 'pvc': 'optional'}, + }, + { + 'datatypes': ['pet'], + 'suffixes': ['timeseries', 'regressors', 'tacs'], + 'extensions': ['.json', '.tsv'], + 'entities': {**_PET_ENTITIES, 'pvc': 'optional'}, + }, +] + +# Figure patterns use a non-standard directory layout (no session directory), +# so they cannot be generated from rules and are kept as literal patterns. +_NIPREPS_FIGURE_PATTERNS = [ + 'sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}', + 'sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_fmapid-{fmapid}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}', + 'sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}', + 'sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_dir-{direction}][_run-{run}][_echo-{echo}][_part-{part}][_space-{space}][_cohort-{cohort}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}', + 'sub-{subject}/{datatype}/sub-{subject}[_ses-{session}][_hash-{hash}][_task-{task}][_acq-{acquisition}][_ce-{ceagent}][_trc-{tracer}][_rec-{reconstruction}][_run-{run}][_space-{space}][_cohort-{cohort}][_label-{label}][_desc-{desc}]_{suffix}{extension<.html|.svg>|.svg}', +] + +_nipreps_extension = ConfigExtension( + name='nipreps', + extra_entities=[ + { + 'name': 'hash', + 'pattern': 'hash-([a-zA-Z0-9+]+)', + 'position': 'after:session', + }, + { + 'name': 'fmapid', + 'pattern': '[_/\\\\]+fmapid-([a-zA-Z0-9+]+)', + 'position': 'after:label', + }, + { + 'name': 'pvc', + 'pattern': '[_/\\\\]+pvc-([a-zA-Z0-9+]+)', + 'position': 'after:tracer', + }, + { + 'name': 'from', + 'pattern': '(?:^|_)from-([a-zA-Z0-9+]+).*xfm', + 'position': 'after:hemi', + }, + { + 'name': 'to', + 'pattern': '(?:^|_)to-([a-zA-Z0-9+]+).*xfm', + 'position': 'after:from', + }, + { + 'name': 'mode', + 'pattern': '(?:^|_)mode-(image|points).*xfm', + 'position': 'after:to', + }, + ], + # Rename schema-key entity names to match the short names used in + # pybids conventions and the old nipreps.json config. + entity_overrides={ + 'description': {'name': 'desc'}, + 'hemisphere': {'name': 'hemi'}, + 'processing': {'name': 'proc'}, + 'inversion': {'name': 'inv'}, + 'mtransfer': {'name': 'mt'}, + }, + extra_datatypes=['figures'], + extra_rules=_NIPREPS_EXTRA_RULES, + extra_path_patterns=_NIPREPS_FIGURE_PATTERNS, + inject_entity_segments=[ + {'segment': '[_hash-{hash}]', 'after': '[_ses-{session}]'}, + ], +) +_pybids_spec = generate_extended_config( + name='nipreps', + extensions=[_nipreps_extension], + rule_groups=['deriv'], + sidecar_split=False, +) + BIDS_DERIV_ENTITIES = _pybids_spec['entities'] BIDS_DERIV_PATTERNS = tuple(_pybids_spec['default_path_patterns']) diff --git a/niworkflows/reports/core.py b/niworkflows/reports/core.py index 698fd67ddcd..831f0796c6a 100644 --- a/niworkflows/reports/core.py +++ b/niworkflows/reports/core.py @@ -40,7 +40,9 @@ # Add a new figures spec try: - add_config_paths(figures=data.load('nipreps.json')) + from niworkflows.interfaces.bids import _pybids_spec + + add_config_paths(figures=_pybids_spec) except ValueError as e: if "Configuration 'figures' already exists" != str(e): raise