-
Notifications
You must be signed in to change notification settings - Fork 169
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1060 from tsalo/schema-sprint-taylor
Start drafting validation rules for ASL data
- Loading branch information
Showing
4 changed files
with
360 additions
and
0 deletions.
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" |