-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SCHEMA] Start drafting validation rules for ASL data #1060
Merged
effigies
merged 17 commits into
bids-standard:schema-sprint
from
tsalo:schema-sprint-taylor
Apr 15, 2022
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
341a73b
Draft ASL validation file.
tsalo c571358
Fix level.
tsalo a6b22c4
Reorder based on code.
tsalo 60d1572
Add 196 and reorder selectors.
tsalo f8214ba
Add a few DWI and events rules.
tsalo a295fc2
Fix linter issues.
tsalo 5d6f7cd
Add a few more rules.
tsalo 3bec3f8
Add a few more rules.
tsalo 8f4eec7
Update src/schema/rules/sidecars/asl_validation.yaml
tsalo c040e09
Switch to new context terms.
tsalo 3b40559
More.
tsalo 6530002
Use YAML schema types.
tsalo 9820ae7
Apply suggestions from code review
tsalo ebf3c23
associated --> associations
tsalo fd046c4
seq --> array
tsalo a2852a9
Merge branch 'schema-sprint-taylor' of https://github.com/tsalo/bids-…
tsalo 4e9b980
Revert extra change.
tsalo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
# Rules for ASL data that are not defined in tables. | ||
--- | ||
|
||
# 157 | ||
ASLLabelingDurationNiftiLength: | ||
code: LABELING_DURATION_LENGTH_NOT_MATCHING_NIFTI | ||
description: | | ||
The number of values for 'LabelingDuration' for this file does not match the 4th dimension of the NIfTI header. | ||
'LabelingDuration' is the total duration of the labeling pulse train, in seconds, | ||
corresponding to the temporal width of the labeling bolus for `(P)CASL`. | ||
In case all control-label volumes (or deltam or CBF) have the same `LabelingDuration`, a scalar must be | ||
specified. | ||
In case the control-label volumes (or deltam or cbf) have a different `LabelingDuration`, | ||
an array of numbers must be specified, for which any `m0scan` in the timeseries has a `LabelingDuration` of | ||
zero. | ||
In case an array of numbers is provided, its length should be equal to the number of volumes specified in | ||
`*_aslcontext.tsv`. Corresponds to DICOM Tag 0018,9258 `ASL Pulse Train Duration`. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- sidecar contains "LabelingDuration" | ||
- type(sidecar.LabelingDuration) == "array" | ||
checks: | ||
- nifti_header.dim[4] == len(sidecar.LabelingDuration) | ||
|
||
# 165 | ||
ASLContextConsistent: | ||
code: ASLCONTEXT_TSV_NOT_CONSISTENT | ||
description: | | ||
The number of volumes in the '*_aslcontext.tsv' for this file does not match the number of | ||
values in the NIfTI header. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
checks: | ||
- nifti_header.dim[4] == associations.aslcontext.n_rows | ||
|
||
# 168 | ||
ASLFlipAngleNiftiLength: | ||
code: FLIP_ANGLE_NOT_MATCHING_NIFTI | ||
description: | | ||
The number of values for 'FlipAngle' for this file does not match the 4th dimension of the NIfTI header. | ||
'FlipAngle' is the flip angle (FA) for the acquisition, specified in degrees. | ||
Corresponds to: DICOM Tag 0018, 1314 `Flip Angle`. | ||
The data type number may apply to files from any MRI modality concerned with a single value for this field, | ||
or to the files in a file collection where the value of this field is iterated using the flip entity. | ||
The data type array provides a value for each volume in a 4D dataset and should only be used when the | ||
volume timing is critical for interpretation of the data, such as in ASL or variable flip angle fMRI sequences. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- sidecar contains "FlipAngle" | ||
- type(sidecar.FlipAngle) == "array" | ||
checks: | ||
- nifti_header.dim[4] == len(sidecar.FlipAngle) | ||
|
||
# 172 | ||
ASLFlipAngleASLContextLength: | ||
code: FLIP_ANGLE_NOT_MATCHING_ASLCONTEXT_TSV | ||
description: | | ||
The number of values for 'FlipAngle' for this file does not match the number of volumes in the | ||
'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'FlipAngle' is the flip angle (FA) for the acquisition, specified in degrees. | ||
Corresponds to: DICOM Tag 0018, 1314 `Flip Angle`. | ||
The data type number may apply to files from any MRI modality concerned with a single value for this field, | ||
or to the files in a file collection where the value of this field is iterated using the flip entity. | ||
The data type array provides a value for each volume in a 4D dataset and should only be used when the volume | ||
timing is critical for interpretation of the data, such as in ASL or variable flip angle fMRI sequences. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "FlipAngle" | ||
- type(sidecar.FlipAngle) == "array" | ||
checks: | ||
- aslcontext.n_rows == sidecar.FlipAngle.size | ||
|
||
# 173 | ||
ASLPostLabelingDelayNiftiLength: | ||
code: POST_LABELING_DELAY_NOT_MATCHING_NIFTI | ||
description: | | ||
The number of values for 'PostLabelingDelay' for this file does not match the 4th dimension of the NIfTI | ||
header. | ||
'PostLabelingDelay' is the time, in seconds, after the end of the labeling (for (P)CASL) or middle of the | ||
labeling pulse (for PASL) until the middle of the excitation pulse applied to the imaging slab | ||
(for 3D acquisition) or first slice (for 2D acquisition). | ||
Can be a number (for a single-PLD time series) or an array of numbers (for multi-PLD and Look-Locker). | ||
In the latter case, the array of numbers contains the PLD of each volume (i.e. each 'control' and 'label') | ||
in the acquisition order. Any image within the time-series without a PLD (e.g. an 'm0scan') is indicated by a | ||
zero. | ||
Based on DICOM Tags 0018,9079 Inversion Times and 0018,0082 InversionTime. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- sidecar contains "PostLabelingDelay" | ||
- type(sidecar.PostLabelingDelay) == "array" | ||
checks: | ||
- nifti_header.pixdim[4] == sidecar.PostLabelingDelay.size | ||
|
||
# 174 | ||
ASLPostLabelingDelayASLContextLength: | ||
code: POST_LABELING_DELAY_NOT_MATCHING_ASLCONTEXT_TSV | ||
description: | | ||
The number of values for 'PostLabelingDelay' for this file does not match the number of volumes | ||
in the 'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'PostLabelingDelay' is the time, in seconds, after the end of the labeling (for (P)CASL) or | ||
middle of the labeling pulse (for PASL) until the middle of the excitation pulse applied to | ||
the imaging slab (for 3D acquisition) or first slice (for 2D acquisition). | ||
Can be a number (for a single-PLD time series) or an array of numbers (for multi-PLD and Look-Locker). | ||
In the latter case, the array of numbers contains the PLD of each volume (i.e. each 'control' and 'label') | ||
in the acquisition order. | ||
Any image within the time-series without a PLD (e.g. an 'm0scan') is indicated by a zero. | ||
Based on DICOM Tags 0018,9079 Inversion Times and 0018,0082 InversionTime. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "PostLabelingDelay" | ||
- type(sidecar.PostLabelingDelay) == "array" | ||
checks: | ||
- aslcontext.n_rows == sidecar.PostLabelingDelay.size | ||
|
||
# 175 | ||
ASLLabelingDurationASLContextLength: | ||
code: LABELLING_DURATION_NOT_MATCHING_ASLCONTEXT_TSV | ||
description: | | ||
The number of values for 'LabelingDuration' for this file does not match the number of volumes | ||
in the 'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'LabelingDuration' is the total duration of the labeling pulse train, in seconds, | ||
corresponding to the temporal width of the labeling bolus for `(P)CASL`. | ||
In case all control-label volumes (or deltam or CBF) have the same `LabelingDuration`, | ||
a scalar must be specified. | ||
In case the control-label volumes (or deltam or cbf) have a different `LabelingDuration`, | ||
an array of numbers must be specified, for which any `m0scan` in the timeseries has a | ||
`LabelingDuration` of zero. | ||
In case an array of numbers is provided, its length should be equal to the number of volumes | ||
specified in `*_aslcontext.tsv`. | ||
Corresponds to DICOM Tag 0018,9258 `ASL Pulse Train Duration`. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "LabelingDuration" | ||
- type(sidecar.LabelingDuration) == "array" | ||
checks: | ||
- aslcontext.n_rows == sidecar.LabelingDuration.size | ||
|
||
# 177 | ||
ASLRepetitionTimePreparationASLContextLength: | ||
code: REPETITIONTIMEPREPARATION_NOT_MATCHING_ASLCONTEXT_TSV | ||
description: | | ||
The number of values of 'RepetitionTimePreparation' for this file does not match the number of | ||
volumes in the 'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'RepetitionTimePreparation' is the interval, in seconds, that it takes a preparation pulse block to | ||
re-appear at the beginning of the succeeding (essentially identical) pulse sequence block. | ||
The data type number may apply to files from any MRI modality concerned with a single value for this field. | ||
The data type array provides a value for each volume in a 4D dataset and should only be used when the | ||
volume timing is critical for interpretation of the data, such as in ASL. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "RepetitionTimePreparation" | ||
- type(sidecar.RepetitionTimePreparation) == "array" | ||
checks: | ||
- aslcontext.n_rows == sidecar.RepetitionTimePreparation.size | ||
|
||
# 180 | ||
ASLBackgroundSuppressionNumberPulses: | ||
code: BACKGROUND_SUPPRESSION_PULSE_NUMBER_NOT_CONSISTENT | ||
description: | | ||
The 'BackgroundSuppressionNumberPulses' field is not consistent with the length of | ||
'BackgroundSuppressionPulseTime'. | ||
'BackgroundSuppressionNumberPulses' is the number of background suppression pulses used. | ||
Note that this excludes any effect of background suppression pulses applied before the labeling. | ||
level: warning | ||
selectors: | ||
- suffix == "asl" | ||
- sidecar contains "BackgroundSuppressionNumberPulses" | ||
- sidecar contains "BackgroundSuppressionPulseTime" | ||
- type(sidecar.BackgroundSuppressionPulseTime) == "array" | ||
checks: | ||
- sidecar.BackgroundSuppressionPulseTime.size == sidecar.BackgroundSuppressionNumberPulses | ||
|
||
# 181 | ||
ASLTotalAcquiredVolumesASLContextLength: | ||
code: TOTAL_ACQUIRED_VOLUMES_NOT_CONSISTENT | ||
description: | | ||
The number of values for 'TotalAcquiredVolumes' for this file does not match number of | ||
volumes in the 'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'TotalAcquiredVolumes' is the original number of 3D volumes acquired for each volume defined in the | ||
'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
level: warning | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "TotalAcquiredVolumes" | ||
checks: | ||
- aslcontext.n_rows == sidecar.TotalAcquiredVolumes | ||
|
||
# 196 | ||
ASLEchoTimeASLContextLength: | ||
code: ECHO_TIME_NOT_CONSISTENT | ||
description: | | ||
The number of values for 'EchoTime' for this file does not match number of volumes in the | ||
'sub-<label>[_ses-<label>][_acq-<label>][_rec-<label>][_run-<index>]_aslcontext.tsv'. | ||
'EchoTime' is the echo time (TE) for the acquisition, specified in seconds. | ||
level: warning | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar contains "EchoTime" | ||
- type(sidecar.EchoTime) == "array" | ||
checks: | ||
- aslcontext.n_rows == sidecar.EchoTime.size | ||
|
||
# 198 | ||
ASLM0TypeAbsentScan: | ||
code: M0Type_SET_INCORRECTLY_TO_ABSENT | ||
description: | | ||
You defined M0Type as 'absent' while including a separate '*_m0scan.nii[.gz]' and | ||
'*_m0scan.json', or defining the 'M0Estimate' field. | ||
This is not allowed, please check that this field are filled correctly. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- associations contains "m0scan" | ||
checks: | ||
- sidecar.M0Type != "absent" | ||
|
||
# 199 | ||
ASLM0TypeAbsentASLContext: | ||
code: M0Type_SET_INCORRECTLY_TO_ABSENT_IN_ASLCONTEXT | ||
description: | | ||
You defined M0Type as 'absent' while including an m0scan volume within the '*_aslcontext.tsv'. | ||
This is not allowed, please check that this field are filled correctly. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- aslcontext.volume_type contains "m0scan" | ||
checks: | ||
- sidecar.M0Type != "absent" | ||
|
||
# 202 | ||
ASLM0TypeIncorrect: | ||
code: M0Type_SET_INCORRECTLY | ||
description: | | ||
M0Type was not defined correctly. | ||
If 'M0Type' is equal to 'separate', the dataset should include a *_m0scan.nii[.gz] and *_m0scan.json file. | ||
level: error | ||
selectors: | ||
- suffix == "asl" | ||
- associations contains "aslcontext" | ||
- sidecar.M0Type == "separate" | ||
checks: | ||
- associations contains "m0scan" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Rules for DWI data that are not defined in tables. | ||
--- | ||
|
||
# 29 | ||
DWIVolumeCount: | ||
code: VOLUME_COUNT_MISMATCH | ||
description: | | ||
The number of volumes in this scan does not match the number of volumes in the | ||
corresponding .bvec and .bval files. | ||
level: error | ||
selectors: | ||
- suffix == "dwi" | ||
- associations contains "bval" | ||
- associations contains "bvec" | ||
checks: | ||
- associations.bval.n_cols == nifti_header.dim[4] | ||
- associations.bvec.n_cols == nifti_header.dim[4] | ||
|
||
# 30 | ||
DWIBvalRows: | ||
code: BVAL_MULTIPLE_ROWS | ||
description: | | ||
'.bval' files should contain exactly one row of volumes. | ||
level: error | ||
selectors: | ||
- extension == "bval" | ||
checks: | ||
- data.n_rows == 1 | ||
|
||
# 31 | ||
DWIBvecRows: | ||
code: BVEC_NUMBER_ROWS | ||
description: | | ||
'.bvec' files should contain exactly three rows of volumes. | ||
level: error | ||
selectors: | ||
- extension == "bvec" | ||
checks: | ||
- data.n_rows == 3 | ||
|
||
# 32 | ||
DWIMissingBvec: | ||
code: DWI_MISSING_BVEC | ||
description: | | ||
DWI scans must have a corresponding .bvec file. | ||
level: error | ||
selectors: | ||
- suffix == "dwi" | ||
checks: | ||
- associations contains "bvec" | ||
|
||
# 33 | ||
DWIMissingBval: | ||
code: DWI_MISSING_BVAL | ||
description: | | ||
DWI scans must have a corresponding .bval file. | ||
level: error | ||
selectors: | ||
- suffix == "dwi" | ||
checks: | ||
- associations contains "bval" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Rules for events data that are not defined in tables. | ||
--- | ||
|
||
# 25 | ||
EventsMissing: | ||
code: EVENTS_TSV_MISSING | ||
description: | | ||
Task scans should have a corresponding events.tsv file. | ||
If this is a resting state scan you can ignore this warning or rename the task to include the word "rest". | ||
level: warning # could be an error with the proper selectors, I think | ||
selectors: | ||
- entities contains "task" | ||
- entities.task != "rest" | ||
- entities.task not contains "rest" # Alternative for including the word "rest" | ||
checks: | ||
- associations contains "events" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Rules for fieldmap data that are not defined in tables. | ||
--- | ||
|
||
# 91 | ||
FmapFieldmapWithoutMagnitude: | ||
code: _FIELDMAP_WITHOUT_MAGNITUDE_FILE | ||
description: | | ||
'_fieldmap.nii[.gz]' file does not have accompanying '_magnitude.nii[.gz]' file. | ||
level: error | ||
selectors: | ||
- suffix == "fieldmap" | ||
checks: | ||
- associations contains "magnitude" | ||
|
||
# 92 | ||
FmapPhasediffWithoutMagnitude: | ||
code: MISSING_MAGNITUDE1_FILE | ||
description: | | ||
Each '_phasediff.nii[.gz]' file should be associations with a '_magnitude1.nii[.gz]' file. | ||
level: warning | ||
selectors: | ||
- suffix == "phasediff" | ||
checks: | ||
- associations contains "magnitude1" |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for my sparse appearance at the meetings. So do we have a grammar and interpreter already? (Since in general looks like python but this absent
contains
operand throws me off, not sure why not to use availablein
with swap of the arguments)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In YAML:
raises an error because of YAML parsing rules. But we also don't insist that people always use
<
instead of>
so it seemed reasonable to have both directions.