diff --git a/src/metaschema.json b/src/metaschema.json index e5d4c7b400..49d0f8cab7 100644 --- a/src/metaschema.json +++ b/src/metaschema.json @@ -71,6 +71,9 @@ "additionalProperties": false } }, + "templates": { + "type": "object" + }, "versions": { "type": "array", "items": { diff --git a/src/schema/README.md b/src/schema/README.md index 3505ea1b04..075151f476 100644 --- a/src/schema/README.md +++ b/src/schema/README.md @@ -167,21 +167,43 @@ references (the cases in which they are used will be presented later): (which are in turn references to individual values), and the references inside `GeneticLevel.anyOf` indicate that there may be a single such value or a list of values. -1. In [`rules.files.deriv.preprocessed_data`][preprocessed_data]: +1. In [`rules.files.deriv.imaging`](./rules/files/deriv/imaging.yaml): ```YAML - anat_nonparametric_common: - $ref: rules.files.raw.anat.nonparametric + anat_parametric_volumetric: + $ref: rules.files.raw.anat.parametric entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.parametric.entities ``` Here, the derivative datatype rule starts by copying the raw datatype rule `rules.files.raw.anat.nonparametric`. It then *overrides* the `entities` portion of that rule with a new object. - To *extend* the original `entities`, it again begins - by referencing `rules.files.raw.anat.nonparametric.entities`, - and adding the new entities `space` and `description`. + To *extend* the original `entities`, it composes + `meta.templates.deriv.volumetric.entities` + and `rules.files.raw.anat.nonparametric.entities`. + When multiple references are aggregated, the first reference takes + precedence. + + Note also that `value: null` can be used to "delete" a key from a template. + For example, in `rules.files.raw.events`: + + ```YAML + events__pet: + $ref: rules.files.raw.events.events + datatypes: + - pet + entities: + $ref: meta.templates.raw.task.entities + tracer: optional + reconstruction: optional + # Most events allow acquisition, PET doesn't + acquisition: null + ``` + + This technique should be used judiciously, preferring semantic clarity to brevity. + Templates should be expected to grow as BIDS evolves, + and should thus be used only where those changes should propagate. ### Expressions @@ -1071,5 +1093,4 @@ ensuring consistency across the entire schema directory. Validation of the schem incorporated into the CI, so any changes that are inconsistent will be flagged before inclusion. -[preprocessed_data]: https://github.com/bids-standard/bids-specification/tree/master/src/schema/rules/files/deriv/preprocessed_data.yaml [tabular files]: https://bids-specification.readthedocs.io/en/stable/common-principles.html#tabular-files diff --git a/src/schema/meta/templates.yaml b/src/schema/meta/templates.yaml new file mode 100644 index 0000000000..f9db50d33d --- /dev/null +++ b/src/schema/meta/templates.yaml @@ -0,0 +1,148 @@ +--- +# This section is unstructured, for inclusion in rules by reference + +# Entities that apply to most raw files +# Include thus: +# +# filerule: +# entities: +# $ref: meta.templates.raw.base.entities +# task: optional +# ... +# datatypes: +# ... +raw: + base: + entities: + subject: required + session: optional + + recording: + entities: + $ref: meta.templates.raw.base.entities + acquisition: optional + run: optional + + task: + entities: + $ref: meta.templates.raw.recording.entities + task: required + + mri: + entities: + $ref: meta.templates.raw.recording.entities + ceagent: optional + reconstruction: optional + chunk: optional + + epi: + entities: + $ref: meta.templates.raw.mri.entities + direction: optional + part: optional + + pet: + entities: + $ref: meta.templates.raw.base.entities + task: optional + tracer: optional + reconstruction: optional + run: optional + + mrs: + entities: + $ref: meta.templates.raw.recording.entities + task: optional + nucleus: optional + volume: optional + reconstruction: optional + +# Entities that apply to most derivative files +# Include thus: +# +# filerule: +# entities: +# $ref: meta.templates.deriv.base.entities +# task: optional +# ... +# datatypes: +# ... +deriv: + base: + selectors: + - dataset.dataset_description.DatasetType == 'derivative' + entities: + subject: optional + session: optional + description: optional + + spatial: + $ref: meta.templates.deriv.base + entities: + $ref: meta.templates.deriv.base.entities + space: optional + + # Imaging derivatives + volumetric: + $ref: meta.templates.deriv.spatial + extensions: + - .nii.gz + - .nii + - .json + entities: + $ref: meta.templates.deriv.spatial.entities + resolution: optional + + surface: + $ref: meta.templates.deriv.spatial + entities: + $ref: meta.templates.deriv.spatial.entities + hemisphere: optional + density: optional + + mask: + $ref: meta.templates.deriv.volumetric + suffixes: + - mask + entities: + $ref: meta.templates.deriv.volumetric.entities + label: optional + + dseg: + $ref: meta.templates.deriv.volumetric + extensions: + - .nii.gz + - .nii + - .tsv + - .json + suffixes: + - dseg + entities: + $ref: meta.templates.deriv.volumetric.entities + segmentation: optional + + probseg: + $ref: meta.templates.deriv.volumetric + extensions: + - .nii.gz + - .nii + - .json + suffixes: + - probseg + entities: + $ref: meta.templates.deriv.volumetric.entities + segmentation: optional + label: optional + + dseg_surface: + $ref: meta.templates.deriv.surface + extensions: + - .label.gii + - .dlabel.nii + - .tsv + - .json + suffixes: + - dseg + entities: + $ref: meta.templates.deriv.surface.entities + segmentation: optional diff --git a/src/schema/rules/files/deriv/imaging.yaml b/src/schema/rules/files/deriv/imaging.yaml index 819654b4e5..d2ce8a451d 100644 --- a/src/schema/rules/files/deriv/imaging.yaml +++ b/src/schema/rules/files/deriv/imaging.yaml @@ -1,280 +1,327 @@ +# This document implements general imaging derivatives. +# +# The _volumetric rules cover supersets of files that would be covered by the +# common derivatives spec, namely, the space and description entities. --- +# Preprocessed and/or resampled volumes anat_parametric_volumetric: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.parametric entities: - $ref: rules.files.raw.anat.parametric.entities - space: optional - resolution: optional - density: optional - description: optional + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.parametric.entities anat_nonparametric_volumetric: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - resolution: optional - density: optional - description: optional - -dwi_volumetric: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.dwi - entities: - $ref: rules.files.raw.dwi.dwi.entities - space: optional - resolution: optional - density: optional - description: optional + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.nonparametric + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.nonparametric.entities + +anat_defacemask_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.defacemask + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.defacemask.entities + +anat_mese_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.mese + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.mese.entities + +anat_megre_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.megre + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.megre.entities + +anat_multiflip_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.multiflip + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.multiflip.entities + +anat_multiinversion_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.multiinversion + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.multiinversion.entities + +anat_mp2rage_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.mp2rage + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.mp2rage.entities + +anat_vfamt_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.vfamt + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.vfamt.entities + +anat_mtr_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.anat.mtr + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.anat.mtr.entities + +dwi_dwi_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.dwi.dwi + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.dwi.dwi.entities + +dwi_sbref_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.dwi.sbref + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.dwi.sbref.entities dwi_scannerderivatives: - $ref: rules.files.raw.dwi.ScannerDerivatives + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.dwi.ScannerDerivatives entities: - $ref: rules.files.raw.dwi.ScannerDerivatives.entities - space: optional - resolution: optional - density: optional - description: optional + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.dwi.ScannerDerivatives.entities func_volumetric: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.func - entities: - $ref: rules.files.raw.func.func.entities - space: optional - resolution: optional - density: optional - description: optional - -anat_parametric_mask: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric - suffixes: - - mask - entities: - $ref: rules.files.raw.anat.parametric.entities - space: optional - resolution: optional - label: optional - description: optional - -anat_nonparametric_mask: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - suffixes: - - mask - entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - resolution: optional - label: optional - description: optional + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.func.func + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.func.func.entities + +func_phase_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.func.phase + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.func.phase.entities + +fmap_fieldmaps_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.fieldmaps + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.fieldmaps.entities + +fmap_pepolar_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.pepolar + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.pepolar.entities + +fmap_pepolar_m0scan: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.pepolar_m0scan + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.pepolar.entities + +fmap_TB1DAM_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.TB1DAM + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.TB1DAM.entities + +fmap_TB1EPI_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.TB1EPI + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.TB1EPI.entities + +fmap_RFFieldMaps_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.RFFieldMaps + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.RFFieldMaps.entities + +fmap_TB1SRGE_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.TB1SRGE + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.TB1SRGE.entities + +fmap_parametric_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.fmap.parametric + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.fmap.parametric.entities + +perf_asl_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.perf.asl + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.perf.asl.entities + +pet_pet_volumetric: + $ref: + - meta.templates.deriv.volumetric + - rules.files.raw.pet.pet + entities: + $ref: + - meta.templates.deriv.volumetric.entities + - rules.files.raw.pet.pet.entities + +# Masks +anat_mask: + $ref: + - meta.templates.deriv.mask + - rules.files.raw.anat.nonparametric + entities: + # The nonparametric entities are a superset of parametric entities, + # so no need to duplicate. + $ref: + - meta.templates.deriv.mask.entities + - rules.files.raw.anat.nonparametric.entities dwi_mask: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.dwi - suffixes: - - mask - extensions: - - .nii.gz - - .nii - - .json - entities: - $ref: rules.files.raw.dwi.dwi.entities - space: optional - resolution: optional - label: optional - description: optional + $ref: + - meta.templates.deriv.mask + - rules.files.raw.dwi.dwi + entities: + $ref: + - meta.templates.deriv.mask.entities + - rules.files.raw.dwi.dwi.entities func_mask: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.func - suffixes: - - mask - entities: - $ref: rules.files.raw.func.func.entities - space: optional - resolution: optional - label: optional - description: optional - -anat_parametric_discrete_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric - suffixes: - - dseg - entities: - $ref: rules.files.raw.anat.parametric.entities - space: optional - segmentation: optional - resolution: optional - description: optional - extensions: - - .nii.gz - - .nii - - .json - - .tsv - -anat_nonparametric_discrete_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - suffixes: - - dseg - entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - segmentation: optional - resolution: optional - description: optional - extensions: - - .nii.gz - - .nii - - .json - - .tsv + $ref: + - meta.templates.deriv.mask + - rules.files.raw.func.func + entities: + $ref: + - meta.templates.deriv.mask.entities + - rules.files.raw.func.func.entities + +# Discrete and probabilistic segmentations +anat_discrete_segmentation: + $ref: + - meta.templates.deriv.dseg + - rules.files.raw.anat.nonparametric + entities: + # ibid + $ref: + - meta.templates.deriv.dseg.entities + - rules.files.raw.anat.nonparametric.entities func_discrete_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.func - suffixes: - - dseg - entities: - $ref: rules.files.raw.func.func.entities - space: optional - segmentation: optional - resolution: optional - description: optional - extensions: - - .nii.gz - - .nii - - .json - - .tsv + $ref: + - meta.templates.deriv.dseg + - rules.files.raw.func.func + entities: + $ref: + - meta.templates.deriv.dseg.entities + - rules.files.raw.func.func.entities dwi_discrete_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.dwi - suffixes: - - dseg - entities: - $ref: rules.files.raw.dwi.dwi.entities - space: optional - resolution: optional - description: optional - extensions: - - .nii.gz - - .nii - - .json - - .tsv - -anat_parametric_probabilistic_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric - suffixes: - - probseg - entities: - $ref: rules.files.raw.anat.parametric.entities - space: optional - segmentation: optional - resolution: optional - label: optional - description: optional - -anat_nonparametric_probabilistic_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - suffixes: - - probseg - entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - segmentation: optional - resolution: optional - label: optional - description: optional + $ref: + - meta.templates.deriv.dseg + - rules.files.raw.dwi.dwi + entities: + $ref: + - meta.templates.deriv.dseg.entities + - rules.files.raw.dwi.dwi.entities + +anat_probabilistic_segmentation: + $ref: + - meta.templates.deriv.probseg + - rules.files.raw.anat.nonparametric + entities: + # ibid + $ref: + - meta.templates.deriv.probseg.entities + - rules.files.raw.anat.nonparametric.entities func_probabilistic_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.func - suffixes: - - probseg - entities: - $ref: rules.files.raw.func.func.entities - space: optional - segmentation: optional - resolution: optional - label: optional - description: optional + $ref: + - meta.templates.deriv.probseg + - rules.files.raw.func.func + entities: + $ref: + - meta.templates.deriv.probseg.entities + - rules.files.raw.func.func.entities dwi_probabilistic_segmentation: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.dwi - suffixes: - - probseg - entities: - $ref: rules.files.raw.dwi.dwi.entities - space: optional - segmentation: optional - resolution: optional - label: optional - description: optional - extensions: - - .nii.gz - - .nii - - .json - -anat_parametric_discrete_surface: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric - suffixes: - - dseg - extensions: - - .label.gii - - .dlabel.nii - - .json - - .tsv - entities: - $ref: rules.files.raw.anat.parametric.entities - hemisphere: optional - space: optional - segmentation: optional - resolution: optional - density: optional - description: optional - -anat_nonparametric_discrete_surface: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - suffixes: - - dseg - extensions: - - .label.gii - - .dlabel.nii - - .json - - .tsv - entities: - $ref: rules.files.raw.anat.nonparametric.entities - hemisphere: optional - space: optional - segmentation: optional - resolution: optional - density: optional - description: optional + $ref: + - meta.templates.deriv.probseg + - rules.files.raw.dwi.dwi + entities: + $ref: + - meta.templates.deriv.probseg.entities + - rules.files.raw.dwi.dwi.entities + +anat_discrete_surface: + $ref: + - meta.templates.deriv.dseg_surface + - rules.files.raw.anat.nonparametric + entities: + # ibid + $ref: + - meta.templates.deriv.dseg_surface.entities + - rules.files.raw.anat.nonparametric.entities diff --git a/src/schema/rules/files/deriv/preprocessed_data.yaml b/src/schema/rules/files/deriv/preprocessed_data.yaml index 48ca1bccc6..0a1029b348 100644 --- a/src/schema/rules/files/deriv/preprocessed_data.yaml +++ b/src/schema/rules/files/deriv/preprocessed_data.yaml @@ -1,378 +1,175 @@ +# This document implements the common derivatives specification, +# generally adding space and description entities to most raw data. +# +# Imaging files are generally omitted, due to redundancy with imaging.yaml --- -anat_nonparametric_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.nonparametric - entities: - $ref: rules.files.raw.anat.nonparametric.entities - space: optional - description: optional - -anat_parametric_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.parametric - entities: - $ref: rules.files.raw.anat.parametric.entities - space: optional - description: optional - -anat_defacemask_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.defacemask - entities: - $ref: rules.files.raw.anat.defacemask.entities - space: optional - description: optional - -anat_megre_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.megre - entities: - $ref: rules.files.raw.anat.megre.entities - space: optional - description: optional - -anat_mese_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.mese - entities: - $ref: rules.files.raw.anat.mese.entities - space: optional - description: optional - -anat_multiflip_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.multiflip - entities: - $ref: rules.files.raw.anat.multiflip.entities - space: optional - description: optional - -anat_multiinversion_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.multiinversion - entities: - $ref: rules.files.raw.anat.multiinversion.entities - space: optional - description: optional - -anat_mp2rage_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.mp2rage - entities: - $ref: rules.files.raw.anat.mp2rage.entities - space: optional - description: optional - -anat_vfamt_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.vfamt - entities: - $ref: rules.files.raw.anat.vfamt.entities - space: optional - description: optional - -anat_mtr_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.anat.mtr - entities: - $ref: rules.files.raw.anat.mtr.entities - space: optional - description: optional - beh_noncontinuous_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.beh.noncontinuous + $ref: + - meta.templates.deriv.base + - rules.files.raw.beh.noncontinuous entities: - $ref: rules.files.raw.beh.noncontinuous.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.beh.noncontinuous.entities channels_channels_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.channels + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.channels entities: - $ref: rules.files.raw.channels.channels.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.channels.entities channels_channels__meg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.channels__meg + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.channels__meg entities: - $ref: rules.files.raw.channels.channels__meg.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.channels__meg.entities channels_channels__motion_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.channels__motion + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.channels__motion entities: - $ref: rules.files.raw.channels.channels__motion.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.channels__motion.entities channels_coordsystem_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.coordsystem + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.coordsystem entities: - $ref: rules.files.raw.channels.coordsystem.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.coordsystem.entities channels_coordsystem__eeg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.coordsystem__eeg + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.coordsystem__eeg entities: - $ref: rules.files.raw.channels.coordsystem__eeg.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.coordsystem__eeg.entities channels_electrodes_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.electrodes + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.electrodes entities: - $ref: rules.files.raw.channels.electrodes.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.electrodes.entities channels_electrodes__meg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.electrodes__meg - entities: - $ref: rules.files.raw.channels.electrodes__meg.entities - description: optional - -channels_electrodes_optodes_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.channels.optodes - entities: - $ref: rules.files.raw.channels.optodes.entities - description: optional - -dwi_dwi_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.dwi + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.electrodes__meg entities: - $ref: rules.files.raw.dwi.dwi.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.electrodes__meg.entities -dwi_sbref_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.dwi.sbref +channels_optodes_common: + $ref: + - meta.templates.deriv.base + - rules.files.raw.channels.optodes entities: - $ref: rules.files.raw.dwi.sbref.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.channels.optodes.entities eeg_eeg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.eeg.eeg + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.eeg.eeg entities: - $ref: rules.files.raw.eeg.eeg.entities - space: optional - description: optional - -fmap_fieldmaps_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.fieldmaps - entities: - $ref: rules.files.raw.fmap.fieldmaps.entities - space: optional - description: optional - -fmap_pepolar_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.pepolar - entities: - $ref: rules.files.raw.fmap.pepolar.entities - space: optional - description: optional - -fmap_pepolar_m0scan: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.pepolar_m0scan - entities: - $ref: rules.files.raw.fmap.pepolar.entities - space: optional - description: optional - -fmap_TB1DAM_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.TB1DAM - entities: - $ref: rules.files.raw.fmap.TB1DAM.entities - space: optional - description: optional - -fmap_TB1EPI_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.TB1EPI - entities: - $ref: rules.files.raw.fmap.TB1EPI.entities - space: optional - description: optional - -fmap_RFFieldMaps_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.RFFieldMaps - entities: - $ref: rules.files.raw.fmap.RFFieldMaps.entities - space: optional - description: optional - -fmap_TB1SRGE_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.TB1SRGE - entities: - $ref: rules.files.raw.fmap.TB1SRGE.entities - space: optional - description: optional - -fmap_parametric_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.fmap.parametric - entities: - $ref: rules.files.raw.fmap.parametric.entities - space: optional - description: optional - -func_func_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.func - entities: - $ref: rules.files.raw.func.func.entities - space: optional - description: optional - -func_phase_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.func.phase - entities: - $ref: rules.files.raw.func.phase.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.eeg.eeg.entities ieeg_ieeg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.ieeg.ieeg + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.ieeg.ieeg entities: - $ref: rules.files.raw.ieeg.ieeg.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.ieeg.ieeg.entities meg_meg_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.meg.meg + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.meg.meg entities: - $ref: rules.files.raw.meg.meg.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.meg.meg.entities meg_calibration_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.meg.calibration + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.meg.calibration entities: - $ref: rules.files.raw.meg.calibration.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.meg.calibration.entities meg_crosstalk_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.meg.crosstalk + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.meg.crosstalk entities: - $ref: rules.files.raw.meg.crosstalk.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.meg.crosstalk.entities meg_headshape_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.meg.headshape + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.meg.headshape entities: - $ref: rules.files.raw.meg.headshape.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.meg.headshape.entities meg_markers_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.meg.markers + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.meg.markers entities: - $ref: rules.files.raw.meg.markers.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.meg.markers.entities micr_microscopy_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.micr.microscopy - entities: - $ref: rules.files.raw.micr.microscopy.entities - space: optional - description: optional - -perf_asl_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.perf.asl - entities: - $ref: rules.files.raw.perf.asl.entities - space: optional - description: optional - -pet_pet_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.pet.pet + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.micr.microscopy entities: - $ref: rules.files.raw.pet.pet.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.micr.microscopy.entities pet_blood_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.pet.blood + $ref: + - meta.templates.deriv.spatial + - rules.files.raw.pet.blood entities: - $ref: rules.files.raw.pet.blood.entities - space: optional - description: optional + $ref: + - meta.templates.deriv.spatial.entities + - rules.files.raw.pet.blood.entities task_events_common: - selectors: - - dataset.dataset_description.DatasetType == 'derivative' - $ref: rules.files.raw.events.events + $ref: + - meta.templates.deriv.base + - rules.files.raw.events.events entities: - $ref: rules.files.raw.events.events.entities - description: optional + $ref: + - meta.templates.deriv.base.entities + - rules.files.raw.events.events.entities diff --git a/src/schema/rules/files/raw/anat.yaml b/src/schema/rules/files/raw/anat.yaml index d1b83f17d9..ba751c0253 100644 --- a/src/schema/rules/files/raw/anat.yaml +++ b/src/schema/rules/files/raw/anat.yaml @@ -20,16 +20,10 @@ nonparametric: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional echo: optional part: optional - chunk: optional parametric: suffixes: @@ -56,14 +50,8 @@ parametric: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional - chunk: optional defacemask: suffixes: @@ -75,15 +63,9 @@ defacemask: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional modality: optional - chunk: optional megre: suffixes: @@ -95,16 +77,10 @@ megre: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional echo: required part: optional - chunk: optional mese: suffixes: @@ -116,17 +92,11 @@ mese: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional direction: optional - run: optional echo: required part: optional - chunk: optional multiflip: suffixes: @@ -138,17 +108,11 @@ multiflip: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional echo: optional flip: required part: optional - chunk: optional multiinversion: suffixes: @@ -160,16 +124,10 @@ multiinversion: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional inversion: required part: optional - chunk: optional mp2rage: suffixes: @@ -181,18 +139,12 @@ mp2rage: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional echo: optional flip: optional inversion: required part: optional - chunk: optional vfamt: suffixes: @@ -205,18 +157,12 @@ vfamt: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional echo: optional flip: required mtransfer: required part: optional - chunk: optional mtr: suffixes: @@ -228,13 +174,7 @@ mtr: datatypes: - anat entities: - subject: required - session: optional + $ref: meta.templates.raw.mri.entities task: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional mtransfer: required part: optional - chunk: optional diff --git a/src/schema/rules/files/raw/beh.yaml b/src/schema/rules/files/raw/beh.yaml index 6193015295..df6f9dac06 100644 --- a/src/schema/rules/files/raw/beh.yaml +++ b/src/schema/rules/files/raw/beh.yaml @@ -1,6 +1,7 @@ --- # Non-continuous data noncontinuous: + $ref: meta.templates.raw.task suffixes: - beh extensions: @@ -8,9 +9,3 @@ noncontinuous: - .json datatypes: - beh - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional diff --git a/src/schema/rules/files/raw/channels.yaml b/src/schema/rules/files/raw/channels.yaml index 6a4358c689..4f2c9e774b 100644 --- a/src/schema/rules/files/raw/channels.yaml +++ b/src/schema/rules/files/raw/channels.yaml @@ -1,5 +1,6 @@ --- channels: + $ref: meta.templates.raw.task suffixes: - channels extensions: @@ -9,12 +10,6 @@ channels: - eeg - ieeg - nirs - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional # MEG has an additional entity available channels__meg: @@ -43,8 +38,7 @@ coordsystem: - meg - nirs entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities task: optional acquisition: optional @@ -68,11 +62,8 @@ electrodes: - eeg - ieeg entities: - subject: required - session: optional + $ref: meta.templates.raw.recording.entities task: optional - acquisition: optional - run: optional space: optional # MEG has an additional entity available @@ -93,6 +84,5 @@ optodes: datatypes: - nirs entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities acquisition: optional diff --git a/src/schema/rules/files/raw/dwi.yaml b/src/schema/rules/files/raw/dwi.yaml index 91319046dc..cc211150a0 100644 --- a/src/schema/rules/files/raw/dwi.yaml +++ b/src/schema/rules/files/raw/dwi.yaml @@ -11,14 +11,10 @@ dwi: datatypes: - dwi entities: - subject: required - session: optional - acquisition: optional - reconstruction: optional - direction: optional - run: optional - part: optional - chunk: optional + $ref: meta.templates.raw.epi.entities + # Historically BIDS has not permitted ceagent for DWI + # This could be relaxed without backwards incompatibility + ceagent: null sbref: suffixes: @@ -30,14 +26,8 @@ sbref: datatypes: - dwi entities: - subject: required - session: optional - acquisition: optional - reconstruction: optional - direction: optional - run: optional - part: optional - chunk: optional + $ref: meta.templates.raw.epi.entities + ceagent: null # Common scanner-generated derivatives need raw names ScannerDerivatives: @@ -55,10 +45,7 @@ ScannerDerivatives: datatypes: - dwi entities: - subject: required - session: optional - acquisition: optional - reconstruction: optional - direction: optional - run: optional - chunk: optional + $ref: meta.templates.raw.epi.entities + # part is also not defined for derivative maps + ceagent: null + part: null diff --git a/src/schema/rules/files/raw/eeg.yaml b/src/schema/rules/files/raw/eeg.yaml index 676d66dc1b..0fa2e21feb 100644 --- a/src/schema/rules/files/raw/eeg.yaml +++ b/src/schema/rules/files/raw/eeg.yaml @@ -1,5 +1,6 @@ --- eeg: + $ref: meta.templates.raw.task suffixes: - eeg extensions: @@ -13,9 +14,3 @@ eeg: - .bdf datatypes: - eeg - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional diff --git a/src/schema/rules/files/raw/events.yaml b/src/schema/rules/files/raw/events.yaml index 7800b946df..bbd1ff9b84 100644 --- a/src/schema/rules/files/raw/events.yaml +++ b/src/schema/rules/files/raw/events.yaml @@ -1,5 +1,6 @@ --- events: + $ref: meta.templates.raw.task suffixes: - events extensions: @@ -11,12 +12,6 @@ events: - ieeg - meg - nirs - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional # Specializations # In these rules, we use $ref to retrieve most of an object, and then override @@ -44,20 +39,11 @@ events__pet: datatypes: - pet entities: - # Most events allow acquisition, PET doesn't - subject: required - session: optional - task: required - tracer: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.pet.entities events__mrs: $ref: rules.files.raw.events.events datatypes: - mrs entities: - $ref: rules.files.raw.events.events.entities - reconstruction: optional - nucleus: optional - volume: optional + $ref: meta.templates.raw.mrs.entities diff --git a/src/schema/rules/files/raw/fmap.yaml b/src/schema/rules/files/raw/fmap.yaml index 79d5944feb..7d04c547a4 100644 --- a/src/schema/rules/files/raw/fmap.yaml +++ b/src/schema/rules/files/raw/fmap.yaml @@ -15,13 +15,11 @@ fieldmaps: datatypes: - fmap entities: - subject: required - session: optional - acquisition: optional - run: optional + $ref: meta.templates.raw.recording.entities chunk: optional pepolar: + $ref: meta.templates.raw.epi suffixes: - epi extensions: @@ -32,17 +30,9 @@ pepolar: - .bvec datatypes: - fmap - entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - direction: required - run: optional - part: optional - chunk: optional pepolar_m0scan: + $ref: meta.templates.raw.epi suffixes: - m0scan extensions: @@ -51,15 +41,6 @@ pepolar_m0scan: - .json datatypes: - fmap - entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - direction: required - run: optional - part: optional - chunk: optional TB1DAM: suffixes: @@ -71,16 +52,10 @@ TB1DAM: datatypes: - fmap entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.mri.entities flip: required inversion: optional part: optional - chunk: optional TB1EPI: suffixes: @@ -92,17 +67,11 @@ TB1EPI: datatypes: - fmap entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.mri.entities echo: required flip: required inversion: optional part: optional - chunk: optional RFFieldMaps: suffixes: @@ -117,17 +86,11 @@ RFFieldMaps: datatypes: - fmap entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.mri.entities echo: optional flip: optional inversion: optional part: optional - chunk: optional TB1SRGE: suffixes: @@ -139,19 +102,14 @@ TB1SRGE: datatypes: - fmap entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.mri.entities echo: optional flip: required inversion: required part: optional - chunk: optional parametric: + $ref: meta.templates.raw.mri suffixes: - TB1map - RB1map @@ -161,11 +119,3 @@ parametric: - .json datatypes: - fmap - entities: - subject: required - session: optional - acquisition: optional - ceagent: optional - reconstruction: optional - run: optional - chunk: optional diff --git a/src/schema/rules/files/raw/func.yaml b/src/schema/rules/files/raw/func.yaml index 61a614bead..4072d04437 100644 --- a/src/schema/rules/files/raw/func.yaml +++ b/src/schema/rules/files/raw/func.yaml @@ -11,17 +11,10 @@ func: datatypes: - func entities: - subject: required - session: optional - task: required - acquisition: optional - ceagent: optional - reconstruction: optional - direction: optional - run: optional + $ref: + - meta.templates.raw.epi.entities + - meta.templates.raw.task.entities echo: optional - part: optional - chunk: optional norf: $ref: rules.files.raw.func.func @@ -32,22 +25,9 @@ norf: modality: optional phase: + $ref: rules.files.raw.func.func suffixes: - phase # deprecated - extensions: - - .nii.gz - - .nii - - .json - datatypes: - - func entities: - subject: required - session: optional - task: required - acquisition: optional - ceagent: optional - reconstruction: optional - direction: optional - run: optional - echo: optional - chunk: optional + $ref: rules.files.raw.func.func.entities + part: null diff --git a/src/schema/rules/files/raw/ieeg.yaml b/src/schema/rules/files/raw/ieeg.yaml index 587f9bcbb8..9197aa9676 100644 --- a/src/schema/rules/files/raw/ieeg.yaml +++ b/src/schema/rules/files/raw/ieeg.yaml @@ -1,5 +1,6 @@ --- ieeg: + $ref: meta.templates.raw.task suffixes: - ieeg extensions: @@ -14,9 +15,3 @@ ieeg: - .nwb datatypes: - ieeg - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional diff --git a/src/schema/rules/files/raw/meg.yaml b/src/schema/rules/files/raw/meg.yaml index a25ed56646..48de894cdd 100644 --- a/src/schema/rules/files/raw/meg.yaml +++ b/src/schema/rules/files/raw/meg.yaml @@ -19,11 +19,7 @@ meg: datatypes: - meg entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional + $ref: meta.templates.raw.task.entities processing: optional split: optional @@ -35,8 +31,7 @@ calibration: datatypes: - meg entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities acquisition: level: required enum: @@ -50,8 +45,7 @@ crosstalk: datatypes: - meg entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities acquisition: level: required enum: @@ -66,8 +60,7 @@ headshape: datatypes: - meg entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities acquisition: optional markers: @@ -79,8 +72,7 @@ markers: datatypes: - meg entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities task: optional acquisition: optional space: optional diff --git a/src/schema/rules/files/raw/micr.yaml b/src/schema/rules/files/raw/micr.yaml index b256033ce9..ba88843472 100644 --- a/src/schema/rules/files/raw/micr.yaml +++ b/src/schema/rules/files/raw/micr.yaml @@ -29,10 +29,7 @@ microscopy: datatypes: - micr entities: - subject: required - session: optional + $ref: meta.templates.raw.recording.entities sample: required - acquisition: optional stain: optional - run: optional chunk: optional diff --git a/src/schema/rules/files/raw/motion.yaml b/src/schema/rules/files/raw/motion.yaml index 5ac18a4e92..818a979792 100644 --- a/src/schema/rules/files/raw/motion.yaml +++ b/src/schema/rules/files/raw/motion.yaml @@ -8,9 +8,5 @@ motion: datatypes: - motion entities: - subject: required - session: optional - task: required + $ref: meta.templates.raw.task.entities tracksys: required - acquisition: optional - run: optional diff --git a/src/schema/rules/files/raw/mrs.yaml b/src/schema/rules/files/raw/mrs.yaml index fe95f08f3a..1190bebbf1 100644 --- a/src/schema/rules/files/raw/mrs.yaml +++ b/src/schema/rules/files/raw/mrs.yaml @@ -12,13 +12,6 @@ mrs: datatypes: - mrs entities: - subject: required - session: optional - task: optional - acquisition: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.mrs.entities echo: optional inversion: optional - nucleus: optional - volume: optional diff --git a/src/schema/rules/files/raw/nirs.yaml b/src/schema/rules/files/raw/nirs.yaml index 8dfc41e861..aafce13fa9 100644 --- a/src/schema/rules/files/raw/nirs.yaml +++ b/src/schema/rules/files/raw/nirs.yaml @@ -1,5 +1,6 @@ --- nirs: + $ref: meta.templates.raw.task suffixes: - nirs extensions: @@ -7,9 +8,3 @@ nirs: - .json datatypes: - nirs - entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional diff --git a/src/schema/rules/files/raw/perf.yaml b/src/schema/rules/files/raw/perf.yaml index c725bef442..330bdc087a 100644 --- a/src/schema/rules/files/raw/perf.yaml +++ b/src/schema/rules/files/raw/perf.yaml @@ -10,14 +10,10 @@ asl: datatypes: - perf entities: - subject: required - session: optional - acquisition: optional - reconstruction: optional - direction: optional - run: optional + $ref: meta.templates.raw.epi.entities echo: optional - part: optional + ceagent: null + chunk: null aslcontext: suffixes: @@ -27,12 +23,10 @@ aslcontext: datatypes: - perf entities: - subject: required - session: optional - acquisition: optional - reconstruction: optional - direction: optional - run: optional + $ref: meta.templates.raw.epi.entities + ceagent: null + part: null + chunk: null asllabeling: suffixes: @@ -44,11 +38,8 @@ asllabeling: datatypes: - perf entities: - subject: required - session: optional - acquisition: optional + $ref: meta.templates.raw.recording.entities reconstruction: optional - run: optional norf: $ref: rules.files.raw.perf.asl diff --git a/src/schema/rules/files/raw/pet.yaml b/src/schema/rules/files/raw/pet.yaml index a94cb9addd..2f543efac1 100644 --- a/src/schema/rules/files/raw/pet.yaml +++ b/src/schema/rules/files/raw/pet.yaml @@ -9,12 +9,7 @@ pet: datatypes: - pet entities: - subject: required - session: optional - task: optional - tracer: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.pet.entities blood: suffixes: @@ -25,10 +20,5 @@ blood: datatypes: - pet entities: - subject: required - session: optional - task: optional - tracer: optional - reconstruction: optional - run: optional + $ref: meta.templates.raw.pet.entities recording: required diff --git a/src/schema/rules/files/raw/photo.yaml b/src/schema/rules/files/raw/photo.yaml index f5969e2d0c..65706b02d8 100644 --- a/src/schema/rules/files/raw/photo.yaml +++ b/src/schema/rules/files/raw/photo.yaml @@ -12,8 +12,7 @@ photo: - meg - nirs entities: - subject: required - session: optional + $ref: meta.templates.raw.base.entities acquisition: optional photo__micr: diff --git a/src/schema/rules/files/raw/task.yaml b/src/schema/rules/files/raw/task.yaml index 8a207a7384..15fab309de 100644 --- a/src/schema/rules/files/raw/task.yaml +++ b/src/schema/rules/files/raw/task.yaml @@ -12,11 +12,7 @@ timeseries: - ieeg - nirs entities: - subject: required - session: optional - task: required - acquisition: optional - run: optional + $ref: meta.templates.raw.task.entities recording: optional timeseries__mri_no_task: @@ -30,10 +26,7 @@ timeseries__mri_no_task: - dwi - perf entities: - subject: required - session: optional - acquisition: optional - run: optional + $ref: meta.templates.raw.recording.entities reconstruction: optional direction: optional recording: optional @@ -46,12 +39,11 @@ timeseries__anat: datatypes: - anat entities: - $ref: rules.files.raw.task.timeseries.entities - ceagent: optional - reconstruction: optional + $ref: + - rules.files.raw.task.timeseries.entities + - meta.templates.raw.mri.entities echo: optional part: optional - chunk: optional modality: optional timeseries__func: @@ -85,11 +77,8 @@ timeseries__pet: datatypes: - pet entities: - # Most timeseries allow acquisition, PET doesn't - subject: required - session: optional - task: required + $ref: rules.files.raw.task.timeseries.entities tracer: optional reconstruction: optional - run: optional - recording: optional + # Most timeseries allow acquisition, PET doesn't + acquisition: null diff --git a/tools/schemacode/src/bidsschematools/schema.py b/tools/schemacode/src/bidsschematools/schema.py index ca36e2668b..0208d51e00 100644 --- a/tools/schemacode/src/bidsschematools/schema.py +++ b/tools/schemacode/src/bidsschematools/schema.py @@ -5,6 +5,7 @@ import json import os import re +from collections import ChainMap from collections.abc import Iterable, Mapping from copy import deepcopy from functools import cache, lru_cache @@ -90,17 +91,32 @@ def _find(obj, predicate): def _dereference(namespace, base_schema): # In-place, recursively dereference objects - # This allows a referenced object to itself contain a reference - # A dependency graph could be constructed, but would likely be slower - # to build than to duplicate a couple dereferences + # This allows for referencing objects that contain references, + # as well as objects that do not exist until a parent is dereferenced. for struct in _find(namespace, lambda obj: "$ref" in obj): - target = base_schema.get(struct["$ref"]) - if target is None: - raise ValueError(f"Reference {struct['$ref']} not found in schema.") - if isinstance(target, Mapping): + refs = struct["$ref"] + if isinstance(refs, str): + refs = [refs] + targets = [] + for ref in refs: + target = base_schema + for part in ref.split("."): + target = target.get(part) + if target is None: + raise ValueError(f"Reference {ref} not found in schema.") + if "$ref" in target: + _dereference(target, base_schema) + targets.append(target) + + if all(isinstance(target, Mapping) for target in targets): struct.pop("$ref") - _dereference(target, base_schema) - struct.update({**target, **struct}) + + struct.update({**ChainMap(*targets), **struct}) + + # Use `key: null` to delete fields + for key, value in list(struct.items()): + if value is None: + del struct[key] @cache diff --git a/tools/schemacode/src/bidsschematools/tests/test_schema.py b/tools/schemacode/src/bidsschematools/tests/test_schema.py index 3ee2430fe4..0663cec898 100644 --- a/tools/schemacode/src/bidsschematools/tests/test_schema.py +++ b/tools/schemacode/src/bidsschematools/tests/test_schema.py @@ -412,18 +412,18 @@ def test_valid_schema_with_check_jsonschema(tmp_path, regex_variant): def test_add_legal_field(): """Test that adding a legal field does not raise an error.""" namespace = schema.load_schema() - namespace["rules"]["files"]["deriv"]["preprocessed_data"]["anat_nonparametric_common"][ - "entities" - ]["density"] = "optional" + namespace["rules"]["files"]["deriv"]["imaging"]["anat_nonparametric_volumetric"]["entities"][ + "density" + ] = "optional" schema.validate_schema(namespace) def test_invalid_value(): """Test that an invalid value raises an error.""" namespace = schema.load_schema() - namespace["rules"]["files"]["deriv"]["preprocessed_data"]["anat_nonparametric_common"][ - "entities" - ]["density"] = "invalid" + namespace["rules"]["files"]["deriv"]["imaging"]["anat_nonparametric_volumetric"]["entities"][ + "density" + ] = "invalid" with pytest.raises(ValidationError) as e: schema.validate_schema(namespace) print(e.value)