From 74eda56cc7c4483e6516963659c192389f09a825 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Jul 2024 12:52:11 -0400 Subject: [PATCH 01/17] feat(metaschema): Allow column definition object as an alternative to JSON Schema --- src/metaschema.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/metaschema.json b/src/metaschema.json index ce500d6418..c0462edcaf 100644 --- a/src/metaschema.json +++ b/src/metaschema.json @@ -82,7 +82,18 @@ "patternProperties": { "^[a-zA-Z0-9_]+$": { "allOf": [ - { "$ref": "#/definitions/termTypes/JSONSchema" }, + { + "anyOf": [ + { "$ref": "#/definitions/termTypes/JSONSchema" }, + { + "type": "object", + "properties": { + "definition": { "type": "object" } + }, + "required": ["definition"] + } + ] + }, { "$ref": "#/definitions/termTypes/general" }, { "$ref": "#/definitions/termTypes/nameValue" }, { From 8fdfdb98745194215964811bc554f4fb3260b4f4 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Jul 2024 12:53:14 -0400 Subject: [PATCH 02/17] feat(schema): Provide default JSON column definitions --- src/schema/objects/columns.yaml | 115 +++++++++++++++++++------------- 1 file changed, 69 insertions(+), 46 deletions(-) diff --git a/src/schema/objects/columns.yaml b/src/schema/objects/columns.yaml index 9128a235ba..d93145430e 100644 --- a/src/schema/objects/columns.yaml +++ b/src/schema/objects/columns.yaml @@ -40,14 +40,20 @@ age: It is recommended to tag participant ages that are 89 or higher as 89+, for privacy purposes. - type: number - unit: year + definition: { + "LongName": "Subject age", + "Description": "Subject age in postnatal years", + "Units": "year", + } cardiac: name: cardiac display_name: Cardiac measurement description: | continuous pulse measurement - type: number + definition: { + "Description": "continuous pulse measurement", + "Units": "mV" + } channel: name: channel display_name: Channel @@ -185,6 +191,27 @@ group__channel: handedness: name: handedness display_name: Subject handedness + definition: { + "LongName": "Subject handedness", + "Description": "String value indicating one of \"left\", \"right\", or \"ambidextrous\".", + "Levels": { + "left": "Left-handed", + "l": "Left-handed", + "L": "Left-handed", + "LEFT": "Left-handed", + "Left": "Left-handed", + "right": "Right-handed", + "r": "Right-handed", + "R": "Right-handed", + "RIGHT": "Right-handed", + "Right": "Right-handed", + "ambidextrous": "Ambidextrous", + "a": "Ambidextrous", + "A": "Ambidextrous", + "AMBIDEXTROUS": "Ambidextrous", + "Ambidextrous": "Ambidextrous", + } + } description: | String value indicating one of "left", "right", "ambidextrous". @@ -194,25 +221,6 @@ handedness: For "ambidextrous", use one of these values: `ambidextrous`, `a`, `A`, `AMBIDEXTROUS`, `Ambidextrous`. - type: string - # TODO: Add definitions for these values. (perhaps don't specify) - enum: - - left - - l - - L - - LEFT - - Left - - right - - r - - R - - RIGHT - - Right - - ambidextrous - - a - - A - - AMBIDEXTROUS - - Ambidextrous - - n/a hemisphere: name: hemisphere display_name: Electrode hemisphere @@ -368,7 +376,9 @@ pathology: When different from `healthy`, pathology SHOULD be specified. The pathology may be specified in either `samples.tsv` or `sessions.tsv`, depending on whether the pathology changes over time. - type: string + definition: { + "Description": "Description of the pathology of the sample or type of control." + } participant_id: name: participant_id display_name: Participant ID @@ -429,7 +439,10 @@ respiratory: display_name: Respiratory measurement description: | continuous breathing measurement - type: number + definition: { + "Description": "continuous measurements by respiration belt", + "Units": "mV" + } response_time: name: response_time display_name: Response time @@ -494,25 +507,27 @@ sex: For "female", use one of these values: `female`, `f`, `F`, `FEMALE`, `Female`. For "other", use one of these values: `other`, `o`, `O`, `OTHER`, `Other`. - type: string - # TODO: Add definitions for these values. (perhaps don't specify) - enum: - - male - - m - - M - - MALE - - Male - - female - - f - - F - - FEMALE - - Female - - other - - o - - O - - OTHER - - Other - - n/a + definition: { + "LongName": "sex", + "Description": "String value indicating phenotypical sex.", + "Levels": { + "F": "Female", + "FEMALE": "Female", + "Female": "Female", + "f": "Female", + "female": "Female", + "M": "Male", + "MALE": "Male", + "Male": "Male", + "m": "Male", + "male": "Male", + "O": "Other", + "OTHER": "Other", + "Other": "Other", + "o": "Other", + "other": "Other", + } + } short_channel: name: short_channel display_name: Short Channel @@ -568,7 +583,10 @@ species: (for example, `homo sapiens`, `mus musculus`, `rattus norvegicus`). For backwards compatibility, if `species` is absent, the participant is assumed to be `homo sapiens`. - type: string + definition: { + "Description": + "binomial species name from the NCBI Taxonomy (https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi)" + } status: name: status display_name: Channel status @@ -609,7 +627,9 @@ strain: description: | For species different from `homo sapiens`, string value indicating the strain of the species, for example: `C57BL/6J`. - type: string + definition: { + "Description": "name of the strain of the species" + } strain_rrid: name: strain_rrid display_name: Strain RRID @@ -649,7 +669,10 @@ trigger: display_name: Trigger description: | continuous measurement of the scanner trigger signal - type: number + definition: { + "Description": "continuous measurement of the scanner trigger signal", + "Units": "arbitrary" + } # type column in channels.tsv files type__channels: name: type From 40ca7bbd2f9bd2d981df29707d8ff9f3e9ab78de Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 25 Jul 2024 12:54:32 -0400 Subject: [PATCH 03/17] feat(spec): Render definition and enum columns alike --- .../bidsschematools/render/tables.py | 16 ++++++------ .../schemacode/bidsschematools/render/text.py | 24 ++++++++++-------- .../bidsschematools/render/utils.py | 25 ++++++++++++++++++- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/tools/schemacode/bidsschematools/render/tables.py b/tools/schemacode/bidsschematools/render/tables.py index 9366ae5725..31b6e13fd0 100644 --- a/tools/schemacode/bidsschematools/render/tables.py +++ b/tools/schemacode/bidsschematools/render/tables.py @@ -74,8 +74,8 @@ def _make_object_table( "columns": "column", }.get(table_type) - for element in subschema.keys(): - field_name = subschema[element]["name"] + for element, field in subschema.items(): + field_name = field["name"] # NOTE: Link to the glossary entry, # except for subobjects (if table_type) and # "additional columns" (field_name.startswith("**")) @@ -90,19 +90,19 @@ def _make_object_table( "[DEPRECATED](SPEC_ROOT/common-principles.md#definitions)", ) - type_string = utils.resolve_metadata_type(subschema[element]) + type_string = utils.resolve_metadata_type(field) description = utils.normalize_requirements( - subschema[element]["description"] + " " + description_addendum + f"{field['description']} {description_addendum}".strip() ) # Append a list of valid values, if provided, to the description. # If there are a lot of valid values, this will add a link to the description linking to # the associated glossary entry. - if ( - "enum" in subschema[element].keys() - and len(subschema[element]["enum"]) >= n_values_to_combine - ): + levels = subschema[element].get("enum", []) or subschema[element].get( + "definition", {} + ).get("Levels", []) + if len(levels) >= n_values_to_combine: glossary_entry = f"{GLOSSARY_PATH}.md#objects.{table_type}.{element}" valid_values_str = ( f"For a list of valid values for this {element_type}, see the " diff --git a/tools/schemacode/bidsschematools/render/text.py b/tools/schemacode/bidsschematools/render/text.py index f26ba73204..ce70ae0ded 100644 --- a/tools/schemacode/bidsschematools/render/text.py +++ b/tools/schemacode/bidsschematools/render/text.py @@ -175,17 +175,19 @@ def make_glossary(schema, src_path=None): elif obj["type"] == "format": text += f"**Regular expression**: `{obj_def['pattern']}`\n\n" - keys_to_drop = ["description", "display_name", "name", "value", "pattern"] - if "enum" in obj_def.keys(): - allowed_values = [] - keys_to_drop.append("enum") - for value in obj_def["enum"]: - if isinstance(value, str): - allowed_values.append(value) - else: - allowed_values.append(value["name"]) - - text += f"**Allowed values**: `{'`, `'.join(allowed_values)}`\n\n" + keys_to_drop = [ + "description", + "display_name", + "name", + "value", + "pattern", + "enum", + "definition", + ] + levels = list(obj_def.get("enum", []) or obj_def.get("definition", {}).get("Levels", {})) + if levels: + levels = [level["name"] if isinstance(level, dict) else level for level in levels] + text += f"**Allowed values**: `{'`, `'.join(levels)}`\n\n" text += f"**Description**:\n{obj_desc}\n\n" diff --git a/tools/schemacode/bidsschematools/render/utils.py b/tools/schemacode/bidsschematools/render/utils.py index 873699058e..97b3eefa0f 100644 --- a/tools/schemacode/bidsschematools/render/utils.py +++ b/tools/schemacode/bidsschematools/render/utils.py @@ -222,6 +222,21 @@ def resolve_metadata_type(definition): string = " or ".join(substrings) + elif "definition" in definition: + json_def = definition["definition"] + + if "Delimiter" in json_def: + # Delimiter indicates the value must be parsed. For BIDS purposes, + # this is a string, even if the parsed array is of numbers. + string = "string" + elif "Levels" in json_def: + # JSON keys are always strings. + string = "string" + elif "Units" in json_def: + # Values with units are always (any exceptions?) numbers. + string = "number" + else: + string = "string or number" else: # This clause should only catch $refs. # The schema should be deferenced by this point, so $refs should not exist. @@ -246,7 +261,15 @@ def describe_valid_values(definition): str : A sentence describing valid values for the object. """ description = "" - if "anyOf" in definition.keys(): + if "anyOf" in definition: + return description + + if "definition" in definition: + levels = definition["definition"].get("Levels") + if levels: + description = ( + f"Unless redefined in a sidecar file, must be one of: {', '.join(levels)}." + ) return description if definition["type"] == "boolean": From 439736145afb70ea8c59b92a2aa70140b4bfd71a Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 25 Jul 2024 20:29:21 +0200 Subject: [PATCH 04/17] [ENH] Add admonitions to task and beh pages (#1735) * update task and beh pages * update doc * apply suggestions from review * Update CONTRIBUTING.md Co-authored-by: Stefan Appelhoff * typo * semantic line break --------- Co-authored-by: Stefan Appelhoff --- CONTRIBUTING.md | 3 + .../behavioral-experiments.md | 25 ++++-- src/modality-specific-files/task-events.md | 84 ++++++++++--------- 3 files changed, 64 insertions(+), 48 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d16d54cdc5..adae5e2cba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -257,6 +257,9 @@ The keyword for the heading must be one of the following: - example - quote +Do not put [macros](#using-macros) in admonitions, +as this will likely not give the output you expect. + ## Using macros We use [mkdocs-macros](https://mkdocs-macros-plugin.readthedocs.io/en/latest/) diff --git a/src/modality-specific-files/behavioral-experiments.md b/src/modality-specific-files/behavioral-experiments.md index aa17cc3757..b27592cad4 100644 --- a/src/modality-specific-files/behavioral-experiments.md +++ b/src/modality-specific-files/behavioral-experiments.md @@ -1,5 +1,11 @@ # Behavioral experiments (with no neural recordings) +!!! example "Example datasets" + + Datasets containing behavioral data can be found + in the [BIDS examples repository](https://bids-standard.github.io/bids-examples/#behavioral) + and can be used as helpful guidance when curating new datasets. + {{ MACROS___make_filename_template("raw", datatypes=["beh"]) }} -In addition to logs from behavioral experiments performed alongside imaging data -acquisitions, one can also include data from experiments performed with no neural -recordings. -The results of those experiments can be stored in the `beh` directory using the same -formats for event timing (`_events.tsv`), metadata (`_events.json`), +In addition to logs from behavioral experiments +performed alongside imaging data acquisitions, +one MAY also include data from experiments +performed with no neural recordings. +The results of those experiments MAY be stored in the `beh` directory +using the same formats for event timing (`_events.tsv`), +metadata (`_events.json`), physiological (`_physio.tsv.gz`, `_physio.json`) and other continuous recordings (`_stim.tsv.gz`, `_stim.json`) as for tasks performed during MRI, electrophysiological or other neural recordings. -Additionally, events files that do not include the mandatory `onset` and -`duration` columns can still be included, but should be labeled `_beh.tsv` -rather than `_events.tsv`. +Additionally, events files +that do not include the mandatory `onset` and `duration` columns +MAY be included, +but MUST be labeled `_beh.tsv` rather than `_events.tsv`. ## Sidecar JSON (`*_beh.json`) diff --git a/src/modality-specific-files/task-events.md b/src/modality-specific-files/task-events.md index ca5925909d..7dd53428a6 100644 --- a/src/modality-specific-files/task-events.md +++ b/src/modality-specific-files/task-events.md @@ -27,9 +27,9 @@ Each task events file REQUIRES a corresponding task data file. It is also possible to have a single `events.tsv` file describing events for all participants and runs (see [Inheritance Principle](../common-principles.md#the-inheritance-principle)). -As with all other tabular data, `events.tsv` files MAY be accompanied by a JSON -file describing the columns in detail (see -[Tabular Files](../common-principles.md#tabular-files)). +As with all other tabular data, `events.tsv` files MAY be accompanied +by a JSON file describing the columns in detail +(see [Tabular Files](../common-principles.md#tabular-files)). The tabular files consists of one row per event and a set of REQUIRED and OPTIONAL columns: @@ -44,26 +44,30 @@ and a guide for using macros can be found at The content of `events.tsv` files SHOULD be sorted by values in the `onset` column. -Note for MRI data: -If any acquired scans have been discarded before forming the imaging data file, -ensure that an `onset` of 0 corresponds to the time the first image was stored. -For example in case there is an in scanner training phase that -begins before the scanning sequence has started events from this sequence should -have negative onset time counting down to the beginning of the acquisition of -the first volume. - -Note regarding the precision of numeric metadata: -It is RECOMMENDENDED that dataset curators specify numeric metadata like `onset` and -`duration` with as much decimal precision as is reasonable in the context of the experiment. -For example in an EEG experiment with devices operating at 1000 Hz sampling frequency, -dataset curators SHOULD specify **at least** 3 figures after the decimal point. - -An arbitrary number of additional columns can be added. Those allow describing -other properties of events that could be later referenced in modeling and +An arbitrary number of additional columns can be added. +Those allow describing other properties of events that could be later referenced in modeling and hypothesis extensions of BIDS. Note that the `trial_type` and any additional columns in a TSV file SHOULD be documented in an accompanying JSON sidecar file. +!!! note "Regarding the precision of numeric metadata" + + For the precision of numeric metadata, + it is RECOMMENDENDED that dataset curators specify numeric metadata like `onset` and + `duration` with as much decimal precision as is reasonable in the context of the experiment. + For example in an EEG experiment with devices operating at 1000 Hz sampling frequency, + dataset curators SHOULD specify **at least** 3 figures after the decimal point. + +!!! note "For fMRI data" + + For fMRI data + if any acquired scans have been discarded before forming the imaging data file, + ensure that an `onset` of 0 corresponds to the time the first image was stored. + For example in case there is an in scanner training phase that + begins before the scanning sequence has started events from this sequence should + have negative onset time counting down to the beginning of the acquisition of + the first volume. + Example: -{{ MACROS___make_sidecar_table("mri.MRIEchoPlanarImagingAndB0Mapping") }} +{{ MACROS___make_sidecar_table([ + "mri.MRIB0FieldIdentifier", + "mri.MRIEchoPlanarImagingAndB0FieldSource", + ]) +}} #### Tissue description diff --git a/src/schema/rules/checks/events.yaml b/src/schema/rules/checks/events.yaml index 1f0f57a123..a5fa9ac5fd 100644 --- a/src/schema/rules/checks/events.yaml +++ b/src/schema/rules/checks/events.yaml @@ -13,6 +13,7 @@ EventsMissing: - '"task" in entities' - '!match(entities.task, "rest")' - suffix != "events" + - extension != ".json" checks: - '"events" in associations' diff --git a/src/schema/rules/checks/fmap.yaml b/src/schema/rules/checks/fmap.yaml index b6e8e621cc..199b6e44b3 100644 --- a/src/schema/rules/checks/fmap.yaml +++ b/src/schema/rules/checks/fmap.yaml @@ -9,6 +9,7 @@ EchoTime12DifferenceUnreasonable: level: error selectors: - suffix == "phasediff" + - match(extension, '\.nii(\.gz)?$') checks: - sidecar.EchoTime2 - sidecar.EchoTime1 >= 0.0001 - sidecar.EchoTime2 - sidecar.EchoTime1 <= 0.01 @@ -22,6 +23,7 @@ FmapFieldmapWithoutMagnitude: level: error selectors: - suffix == "fieldmap" + - match(extension, '\.nii(\.gz)?$') checks: - '"magnitude" in associations' @@ -34,6 +36,7 @@ FmapPhasediffWithoutMagnitude: level: warning selectors: - suffix == "phasediff" + - match(extension, '\.nii(\.gz)?$') checks: - '"magnitude1" in associations' diff --git a/src/schema/rules/checks/func.yaml b/src/schema/rules/checks/func.yaml index cce740a1ec..a908bfa345 100644 --- a/src/schema/rules/checks/func.yaml +++ b/src/schema/rules/checks/func.yaml @@ -127,3 +127,14 @@ SliceTimingAcquisitionDurationMutex: checks: - type(sidecar.AcquisitionDuration) == "null" - type(sidecar.DelayTime) == "null" + +VolumeTimingMissingAcquisitionDuration: + issue: + code: VOLUME_TIMING_MISSING_ACQUISITION_DURATION + message: | + The field 'VolumeTiming' requires 'AcquisitionDuration' or 'SliceTiming' to be defined. + level: error + selectors: + - type(sidecar.VolumeTiming) != "null" + checks: + - '"SliceTiming" in sidecar || "AcquisitionDuration" in sidecar' diff --git a/src/schema/rules/checks/nirs.yaml b/src/schema/rules/checks/nirs.yaml index 3ec07ce1d2..e4cabe3291 100644 --- a/src/schema/rules/checks/nirs.yaml +++ b/src/schema/rules/checks/nirs.yaml @@ -2,7 +2,7 @@ NASamplingFreq: selectors: - suffix == "nirs" - - samplingFrequency == "n/a" + - sidecar.SamplingFrequency == "n/a" checks: - associations.channels.sampling_frequency != null @@ -10,6 +10,7 @@ NIRSChannelCount: selectors: - datatype == "nirs" - suffix == "nirs" + - match(extension, '\.nii(\.gz)?$') checks: - | sidecar.NIRSChannelCount diff --git a/src/schema/rules/sidecars/func.yaml b/src/schema/rules/sidecars/func.yaml index dbb4d714e0..7192886407 100644 --- a/src/schema/rules/sidecars/func.yaml +++ b/src/schema/rules/sidecars/func.yaml @@ -57,10 +57,6 @@ MRIFuncTimingParameters: required for sequences that are described with the `VolumeTiming` field and that do not have the `SliceTiming` field set to allow for accurate calculation of "acquisition time" - issue: - code: VOLUME_TIMING_MISSING_ACQUISITION_DURATION - message: | - The field 'VolumeTiming' requires 'AcquisitionDuration' or 'SliceTiming' to be defined. DelayAfterTrigger: recommended # fMRI task information diff --git a/src/schema/rules/sidecars/mri.yaml b/src/schema/rules/sidecars/mri.yaml index c9b94ec83b..1dce5f67af 100644 --- a/src/schema/rules/sidecars/mri.yaml +++ b/src/schema/rules/sidecars/mri.yaml @@ -296,15 +296,23 @@ MRISliceAcceleration: MRIAnatomicalLandmarks: selectors: - - modality == "mri" + - datatype == "anat" + - intersects(dataset.datatypes, ["meg"]) fields: AnatomicalLandmarkCoordinates__mri: recommended -MRIEchoPlanarImagingAndB0Mapping: +MRIB0FieldIdentifier: selectors: - - modality == "mri" + - datatype == 'fmap' + - match(extension, '\.nii(\.gz)?$') fields: B0FieldIdentifier: recommended + +MRIEchoPlanarImagingAndB0FieldSource: + selectors: + - intersects(datatype, ['dwi', 'func', 'perf']) + - intersects(dataset.datatypes, ['fmap']) + fields: B0FieldSource: recommended MRIInstitutionInformation: From fdca7ec3885045319e32dbd04e14389f49544948 Mon Sep 17 00:00:00 2001 From: Ross Blair Date: Thu, 1 Aug 2024 09:14:34 -0500 Subject: [PATCH 08/17] fix(schema): Add hint to see if dataset name contains a visible character (#1879) * add check to see if dataset name contains a visible character * Update src/schema/rules/checks/hints.yaml Co-authored-by: Chris Markiewicz * js regex expects double slash for character classes in strings * Revert "js regex expects double slash for character classes in strings" This reverts commit 156960770ffc4a65bbff37315f202c3fa0c03f0e. --------- Co-authored-by: Chris Markiewicz --- src/schema/rules/checks/hints.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/schema/rules/checks/hints.yaml b/src/schema/rules/checks/hints.yaml index 50cc0f05dc..6efaf4ecdc 100644 --- a/src/schema/rules/checks/hints.yaml +++ b/src/schema/rules/checks/hints.yaml @@ -34,6 +34,19 @@ TooFewAuthors: checks: - length(json.Authors) > 1 +# 115 +EmptyDatasetName: + issue: + code: EMPTY_DATASET_NAME + message: | + The Name field of dataset_description.json is present but empty of visible characters. + level: warning + selectors: + - path == '/dataset_description.json' + - type(json.Name) != 'null' + checks: + - match(json.Name, '\S') + ### Functional files # 85 From d2557e3c28f20515d3ac0520bb521818fee63c45 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Mon, 5 Aug 2024 12:02:34 -0400 Subject: [PATCH 09/17] [FIX] Replace defunct awaresystems.be and fslwiki links (#1874) * [FIX] Replace defunct awaresystems.be link with Wayback machine link * [FIX] fslwiki is redirecting to fsl/docs --- src/modality-specific-files/magnetic-resonance-imaging-data.md | 2 +- src/modality-specific-files/microscopy.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modality-specific-files/magnetic-resonance-imaging-data.md b/src/modality-specific-files/magnetic-resonance-imaging-data.md index a4e6c1fc7a..5e4528aca5 100644 --- a/src/modality-specific-files/magnetic-resonance-imaging-data.md +++ b/src/modality-specific-files/magnetic-resonance-imaging-data.md @@ -721,7 +721,7 @@ within the `[*_]dwi.bval` and `[*_]dwi.bvec` files) MAY change across DWI runs. **Gradient orientation file formats**. The `[*_]dwi.bval` and `[*_]dwi.bvec` files MUST follow the -[FSL format](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FDT/UserGuide#DTIFIT): +[FSL format](https://fsl.fmrib.ox.ac.uk/fsl/docs/#/diffusion/index?id=diffusion-data-in-fsl): The `[*_]dwi.bvec` file contains 3 rows with *N* space-delimited floating-point numbers (corresponding to the *N* volumes in the corresponding NIfTI file.) The first row contains the *x* elements, the second row contains the *y* elements and diff --git a/src/modality-specific-files/microscopy.md b/src/modality-specific-files/microscopy.md index d095a7bb4d..569e6a5245 100644 --- a/src/modality-specific-files/microscopy.md +++ b/src/modality-specific-files/microscopy.md @@ -55,7 +55,7 @@ Microscopy raw data MUST be stored in one of the following formats: - [OME-TIFF](https://docs.openmicroscopy.org/ome-model/6.1.2/ome-tiff/specification.html#) (`.ome.tif` for standard TIFF files or `.ome.btf` for - [BigTIFF](https://www.awaresystems.be/imaging/tiff/bigtiff.html) files) + [BigTIFF](https://web.archive.org/web/20240706160214/https://www.awaresystems.be/imaging/tiff/bigtiff.html) files) - [OME-ZARR/NGFF](https://ngff.openmicroscopy.org/latest/) (`.ome.zarr` directories) From 7f63953f6b9b84aeb811352d1d1b03eb514ff3e7 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 1 Aug 2024 23:25:11 -0400 Subject: [PATCH 10/17] fix(metaschema): Require issues for checks --- src/metaschema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metaschema.json b/src/metaschema.json index c0462edcaf..f6e5a62d25 100644 --- a/src/metaschema.json +++ b/src/metaschema.json @@ -315,7 +315,7 @@ "$ref": "#/definitions/ruleTypes/expressionList" } }, - "required": ["checks", "selectors"], + "required": ["checks", "selectors", "issue"], "additionalProperties": false } } From e23714770c88590fffdb699eca599e3dd84d127d Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 1 Aug 2024 23:26:07 -0400 Subject: [PATCH 11/17] fix(schema): Add issues for file reference checks --- src/schema/rules/checks/references.yaml | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/schema/rules/checks/references.yaml b/src/schema/rules/checks/references.yaml index b0f1dd6e9d..191dcb6d4f 100644 --- a/src/schema/rules/checks/references.yaml +++ b/src/schema/rules/checks/references.yaml @@ -1,5 +1,11 @@ --- SubjectRelativeIntendedForString: + issue: + code: INTENDED_FOR + message: | + 'IntendedFor' field needs to point to an existing file. + Files must be subject-relative paths or BIDS URIs. + level: error selectors: - datatype != "ieeg" - type(sidecar.IntendedFor) == "string" @@ -7,6 +13,12 @@ SubjectRelativeIntendedForString: - exists(sidecar.IntendedFor, "bids-uri") + exists(sidecar.IntendedFor, "subject") == 1 SubjectRelativeIntendedForArray: + issue: + code: INTENDED_FOR + message: | + 'IntendedFor' field needs to point to an existing file. + Files must be subject-relative paths or BIDS URIs. + level: error selectors: - datatype != "ieeg" - type(sidecar.IntendedFor) == "array" @@ -14,6 +26,12 @@ SubjectRelativeIntendedForArray: - exists(sidecar.IntendedFor, "bids-uri") + exists(sidecar.IntendedFor, "subject") == length(sidecar.IntendedFor) DatasetRelativeIntendedForString: + issue: + code: INTENDED_FOR + message: | + 'IntendedFor' field needs to point to an existing file. + Files must be dataset-relative paths or BIDS URIs. + level: error selectors: - datatype == "ieeg" - type(sidecar.IntendedFor) == "string" @@ -21,6 +39,12 @@ DatasetRelativeIntendedForString: - exists(sidecar.IntendedFor, "bids-uri") + exists(sidecar.IntendedFor, "dataset") == 1 DatasetRelativeIntendedForArray: + issue: + code: INTENDED_FOR + message: | + 'IntendedFor' field needs to point to an existing file. + Files must be dataset-relative paths or BIDS URIs. + level: error selectors: - datatype == "ieeg" - type(sidecar.IntendedFor) == "array" @@ -28,6 +52,12 @@ DatasetRelativeIntendedForArray: - exists(sidecar.IntendedFor, "bids-uri") + exists(sidecar.IntendedFor, "dataset") == length(sidecar.IntendedFor) AssociatedEmptyRoomString: + issue: + code: ASSOCIATED_EMPTY_ROOM + message: | + 'AssociatedEmptyRoom' field needs to point to an existing file. + Files must be dataset-relative paths or BIDS URIs. + level: error selectors: - datatype == "meg" - type(sidecar.AssociatedEmptyRoom) == "string" @@ -35,6 +65,12 @@ AssociatedEmptyRoomString: - exists(sidecar.AssociatedEmptyRoom, "bids-uri") + exists(sidecar.AssociatedEmptyRoom, "dataset") == 1 AssociatedEmptyRoomArray: + issue: + code: ASSOCIATED_EMPTY_ROOM + message: | + 'AssociatedEmptyRoom' field needs to point to an existing file. + Files must be dataset-relative paths or BIDS URIs. + level: error selectors: - datatype == "meg" - type(sidecar.AssociatedEmptyRoom) == "array" @@ -44,6 +80,12 @@ AssociatedEmptyRoomArray: == length(sidecar.AssociatedEmptyRoom) Sources: + issue: + code: SOURCE_FILE_EXIST + message: | + 'Sources' field needs to point to existing files. + Files must be dataset-relative paths or BIDS URIs. + level: error selectors: - dataset.dataset_description.DatasetType == "derivatives" - type(sidecar.Sources) != "null" From c5cb8eed6ef6179cc239a960d0fdf20f5c0d02f1 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 1 Aug 2024 23:47:19 -0400 Subject: [PATCH 12/17] fix(schema): Add issues for resolution/density object checks --- src/schema/rules/checks/common_derivatives.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/schema/rules/checks/common_derivatives.yaml b/src/schema/rules/checks/common_derivatives.yaml index 723ddf0e59..6d9cd2eda7 100644 --- a/src/schema/rules/checks/common_derivatives.yaml +++ b/src/schema/rules/checks/common_derivatives.yaml @@ -1,18 +1,32 @@ --- ResInSidecar: + issue: + code: MISSING_RESOLUTION_DESCRIPTION + message: | + The Resolution metadata object does not contain an entry for the file's + res-