Plugin for the d2b package to handle ASL data
Project description
d2b-asl
Plugin for the d2b package to handle ASL data
Installation
pip install d2b-asl
User Guide
This package adds support for the aslContext
field in the description objects located in the d2b
config files. This field should be an array of strings, where each string is a volume type (as defined in the BIDS specification here). Specifically, this array should have the same number of entries as the described ASL acquisition has volumes (if there are 109 volumes in the acquisition which this description is describing, then aslContext
should be an array of length 109).
For example, a config file describing an ASL acquisition might looks something like:
{
"descriptions": [
{
"dataType": "perf",
"modalityLabel": "asl",
"criteria": {
"ProtocolName": "ep2d_pasl",
"MagneticFieldStrength": 3,
"MRAcquisitionType": "2D",
"ImageType": [
"ORIGINAL",
"PRIMARY",
"ASL",
"NONE",
"ND",
"NORM",
"FILTERED",
"MOSAIC"
]
},
"sidecarChanges": {
"ArterialSpinLabelingType": "PASL",
"PostLabelingDelay": 1.8,
"BackgroundSuppression": false,
"M0Type": "Included",
"TotalAcquiredPairs": 54,
"AcquisitionVoxelSize": [3.5, 3.5, 4.5],
"BolusCutOffFlag": true,
"BolusCutOffDelayTime": 0.7,
"BolusCutOffTechnique": "Q2TIPS",
"PASLType": "PICORE"
},
"aslContext": [
"m0scan",
"control",
"label",
"control",
"label",
"control",
"label",
// full array omitted for readability ...
"control",
"label"
]
}
]
}
d2b-asl and array sidecar fields
There are two spots where you might be specifying arrays as field values in your d2b config files.
-
aslContext
- This array should ALWAYS have the same length as the number of volumes in your ASL data. -
fields in
SidecarChanges
- These are fields likeRepetitionTimePreparation
,PostLabelingDelay
etc. which may or may not need to be arrays. If they are arrays, then these arrays should have length equal to the number of volumes in the files output by d2b.
Why are the lengths of the fields in item 2 potentially different from the lengths of aslContext
in item 1? In the event that aslContext
has "discard" values in its array, the number of volumes in the output ASL data will be different than the number of volumes in the input data.
The lengths of any of the arrays in SidecarChanges
should take these discarded volumes into account. For example, suppose we have:
{
"aslContext": ["m0scan", "discard", "label", "control"]
}
then the PostLabelingDelay
field would look like:
{
"SidecarChanges": {
"PostLabelingDelay": [0, 1.8, 1.8]
},
"aslContext": ["m0scan", "discard", "label", "control"]
}
In general, the following relationship should hold:
len_sidecar_changes_field = len(config.SidecarChanges["<array-field>"])
len_aslcontext = len(config.aslContext)
len_aslcontext_discard = len(list(filter(lambda v: v == "discard", config.aslContext)))
len_sidecar_changes_field == len_aslcontext - len_aslcontext_discard
Understanding ASL-specific BIDS sidecar fields
So you a have ASL data and need to format it, great!
Here we try to unpack the most confusing parts of translating acquisition metadata into BIDS sidecar fields. We do this by considering 4 major classes of "acquisition configuration":
- PCASL + Separate M0
- PCASL + Included M0
- PASL + Separate M0
- PASL + Included M0
In each of the 4 scenarios we'll touch on:
- How to determine the following parameters:
RepetitionTimePreparation
PostLabelingDelay
LabelingDuration
InversionTime
- What the implications are with regard to array-like sidecar fields for ASL data.
As a historical/contextual note, it seems like the people who were/are involved in the creation of the ASL-specific portions of the BIDS specification have close ties (or are the same people) who work on the ASL tools included in FSL, and who created https://asl-docs.readthedocs.io. As such, we'll use the same language found there (FSL + asl-docs), because many of the concepts intentions in those locations seem to have made their way into the BIDS spec.
IMPORTANT: Any of the fields discussed here that can/should be of type
number[]
, should be arrays of length equal to the number of volumes in the associated acquisition, unless explicitly indicated otherwise.
PCASL + Separate M0
If this is how you acquired your ASL data then congratulations, because this is probably the least confusing of the 4 scenarios.
-
RepetitionTimePreparation
tl;dr: Probably
number
(same asRepetitionTime
)Unless you know that the TR varies (and how it varies) during the course of the ASL acquisition (in which case this field should be an array, see the note above) then this number can most likely be of type
number
(i.e. a single (scalar) value), and should probably match (be equal to) whatever is listed as theRepetitionTime
-
PostLabelingDelay
tl;dr:
number
(if single delay) ornumber[]
(if multi-delay)If you have single-delay data, then this field can simply be a scalar (single value), namely the single post-label delay with which your data was acquired. This will likely (or at least hopefully likely) be recorded in the MRI protocol sheet somewhere, worst case: someone in your lab (the lab that collected the data) will know what it is/was.
If you have multi-delay data, then this field should be of type
number[]
i.e. an array of numbers equal in length to the number of volumes in the ASL acquisition. Each number in the array should be the post-label delay used to acquire the volume at the corresponding index. (i.e.sidecar.PostLabelingDelay[0]
is the delay used for the first volume,sidecar.PostLabelingDelay[12]
is the delay used for the 13th volume, etc.) -
LabelingDuration
tl;dr: Probably
number
Similar to
RepetitionTimePreparation
, this is (very) probably a single number unless your know and/or have good reason to be believe that it should be an array (in which case this field should be an array, see the note above). This value will most likely be listed in the MRI protocol sheet as:label duration
orbolus duration
. -
InversionTime
tl;dr:
number
This should be whatever is listed in the DICOM header (or protocol sheet).
PCASL + Included M0
-
RepetitionTimePreparation
tl;dr: Probably
number
(but should benumber[]
- an array)First, we'll talk about what probably should be provided for this field, then we'll talk about you'll likely be able to provide.
Because of how the M0 images are acquired it's possible that the TR for the M0 volume(s) is(are) different (likely longer) than the TR for the rest of the "regular" ASL volumes. If this is the case and you actually know what the different TRs are, then this field should be an array (where length == num vols, yada yada ..., see the note above about arrays).
It's possible that either: A) the TR for the M0 volume(s) is(are) known to be the same as for the rest of the volumes, or B) that you suspect that the TRs are different, but you don't know what they are. In this case, either because it's right (A), or because it practical (B), this number will be of type
number
(i.e. a single scalar value) which equals (is the same as) theRepetitionTime
field listed for this acquisition. -
PostLabelingDelay
tl;dr:
number[]
(MUST be an array)In the previous section this field could have been a scalar or an array. In this case, it's no longer situation-dependent, this field must be an array of
number[]
.This is because, for the M0 volumes, (which are mixed in with the "regular" ASL volumes) the post-label delay is 0, so effectively we have a multi-delay timeseries with at least 2 delays:
- the M0 delay (0), and
- the delay(s) that you collected the "regular" ASL volumes (one (single-delay) or more (multi-delay) values > 0)
-
LabelingDuration
tl;dr:
number[]
(MUST be an array)The same argument that applied to
PostLabelingDelay
(in this section, above) applies here, the only difference is that, realisitically, this will (in most cases) be an array of exactly two values:0
and[actual-label-duration-from-protocol-sheet]
(<- which is probably a single value) -
InversionTime
tl;dr:
number
This should be whatever is listed in the DICOM header (or protocol sheet).
PASL + Separate M0
-
RepetitionTimePreparation
tl;dr: Probably
number
(but should benumber[]
- an array)See the discussion for
RepetitionTimePreparation
in the section PCASL + Separate M0 -
PostLabelingDelay
tl;dr:
number
(if single delay) ornumber[]
(if multi-delay)This is where things start to get more complicated. Already, there is a potentially confusing mixture of terms (described here), specifically, (only for PASL):
t_inversion (TI) = t_inflow (also, TI) = t_pld (as specified by BIDS)
In the context of a (P)CASL (continuous) ASL acquisition, we talk about
label duration
andpost-label delay
(the sum of the two asl-docs calls theinflow time
).t_inflow = t_label + t_pld
In the context of a PASL (pulsed) ASL acqusition, we talk about the
inversion time (TI)
, typically, for PASL, there aren't two "parts" to the inflow time, but instead we just have the inversion time:t_inflow = t_inversion
However, Since "inflow time" isn't an available BIDS sidecar field, the next best option might be
InversionTime
(an actual BIDS sidecar field), but there are two problems with using this field:- this field already has a different non-ASL meaning/role, and
- this field cannot be an array (
number[]
), which is a requirement of whatever field we use in order to accommodate multi-inversion time (multi-delay) PASL fields
Thus, to avoid adding yet another field the to the BIDS spec, the
PostLabelingDelay
field is used. As such, in the case of PASL:t_inflow = t_inversion = t_pld
So the "inversion time" (delay) used to collect your PASL data should be placed as the
PostLabelingDelay
field value, which anumber
(scalar) for single-inversion (single-delay) data, and anumber[]
(array) for "multi-inversion" (multi-delay) data. -
LabelingDuration
tl;dr: Should NOT be present ... or
number
Strictly speaking, the
LabelingDuration
field is an invalid field for data withArterialSpinLabelingType == "PASL"
, as such, this field should not appear in the associated sidecar.However, if you are hoping to make use of the ASLPrep BIDS app, this tool assumes the presence of a
LabelingDuration
field (until issue 167 is resolved). In this case one can get around this issue by setting:{ // other fields ... "LabelingDuration": 0 // ... }
in the sidecar and specifying
--skip-bids-validation
as a flag. -
InversionTime
tl;dr:
number
This should be whatever is listed in the DICOM header (or protocol sheet).
PASL + Included M0
-
RepetitionTimePreparation
tl;dr: Probably
number
(but should benumber[]
- an array)See the discussion for
RepetitionTimePreparation
in the section PCASL + Separate M0 -
PostLabelingDelay
tl;dr:
number[]
For the same reasons that
PostLabelingDelay
MUST be an array (outline in this section), this field must also be an arary.Regarding the interpretation/where to find these values see the discussion on
PostLabelingDelay
field in the previous section -
LabelingDuration
tl;dr: Should NOT be present ... or
number
Same reasoning as the previous section with the same caveat/remark/hack regarding ASLPrep.
-
InversionTime
tl;dr:
number
This should be whatever is listed in the DICOM header (or protocol sheet).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.