rordenlab / dcm2niix

dcm2nii DICOM to NIfTI converter: compiled versions available from NITRC
https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage
Other
827 stars 223 forks source link

Philips isotropic DWI b50 not recognized #827

Open JanOP1337 opened 3 weeks ago

JanOP1337 commented 3 weeks ago

Hi,

I have a dataset from Philips that includes a DWI b50 isotropic image, that by dcm2niix is only partially recognized as a DWI. "BidsGuess" is correctly catching its a DWI image, however because of line 2483 in nii_dicom_batch.cpp a bval-file is not being generated: if (minBval > 50.0)

I am guessing this line was added as it was found unreasonable to have b-values below 50, however I would argue there are multiple examples of using exactly b50 (e.g. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6011248/) in an attempt to mitigate IVIM while pertaining the use of the image as a surrogate for a b0 in handling of artefacts.

Values below b50 I would though agree would be an odd choise, and I would therefore argue for a simple fix of simply changing the line to : if (minBval >= 50.0)

Kind regards, Jan Ole

captainnova commented 3 weeks ago

I agree 50 s/mm^2 is too high, but note that b=2 s/mm^2 is often used in Philips diffusion protocols as a substitute for multiple b=0 volumes. Philips does not allow repeated volumes with the same b value and direction in the same scan, so small bs with scattered directions are often used to improve SNR.

However, I don't think that would necessarily affect dcm2niix; a series with multiple b vectors is still technically diffusion weighted even if all the diffusion weightings are tiny.

Maybe 10 s/mm^2 would be the best compromise?

JanOP1337 commented 3 weeks ago

I was unaware of the use of b=2s/mm^2 (I would personally have achieved what you describe in another way*), but this would also explain why the check for low b-values is even needed which I must admit I hadn't understood. With what you describe, then b=10s/mm^2 would indeed be fine.

(*Philips has to my knowledge an option to choose how many averages you want for each b-value - including b0 - though the exact name of the scan parameter eludes me. It is though likely an advanced parameter that may be locked behind some commercial option. Doing it "my" way would in my opinion be better as it would yield higher SNR to the data the scanner itself uses for artefact mitigation (NB: I am a former Philips employee, and I am liky biased by Philips' intended way of doing things which may not always completely align with all the user's actual needs).)

neurolabusc commented 3 weeks ago

Note this threshold is not only for Philips. For example with Siemens DWI images where the user specifies b=0, the DICOMs often report a small b-value. To quote Essa Yacoub these are more accurate representations of the actual b values... Regarding the b zero - there are always gradients so the weighting is never zero but the crusher gradients typically amount to around 5 and we did add an option in the gui to increase that if need be.

JanOP1337 commented 3 weeks ago

Interesting! I have never seen a Siemens scan not reporting only the diffusion-weighting caused by the diffusion-encoding gradients, so likely Siemens has changed their way of reporting the b-value at some point. From the link you provide @neurolabusc it seems like typical values are on the order of 5s/mm^2, meaning setting the limit to something lower than 50s/mm^2 shouldn't be a concern, though perhaps 10s/mm^2 is a bit on the low side. Could 25s/mm^2 be a reasonable compromise?

mharms commented 3 weeks ago

Maybe I'm not interpreting your comment correctly, but Siemens has incorporated the impact of the imaging gradients on the b-value embedded in the DICOM for a long time. In E11, it is reported with a granularity of 5 s/mm^2. In XA, it now appears to be reported with less granularity, although I don't know what the precision is now. (Either that, or in XA, Siemens is no longer including the impact of the imaging gradients into the calculation).

JanOP1337 commented 3 weeks ago

@mharms I believe you have interpreted what I meant correctly, but my limited knowledge of Siemens Dicoms show once again; I have not seen any examples of odd b-values (e.g. b=1001s/mm^2) which I took as evidence for imaging gradient's contributions not being included. However you here present another valid explanation, namely that its granularity is not in steps of 1s/mm^2 but in 5s/mm^2, and all my scans may have had limited b-value contribution from imaging gradients (its all clinical data so not a far-fetched idea). I did a quick googling though and found the following quote stating that imaging gradients are not included: https://dicomifier.readthedocs.io/en/latest/diffusion/siemens/index.html The b-value is always present and expressed in s/mm². It appears to be the ideal b-value, i.e. not modulated by the imaging gradients I do not know the tool where this is part of the documentation though so I can't vouch for its validity.

Even with this in mind, I still think that 25s/mm^2 is an appropriate compromise.

mharms commented 3 weeks ago

The statement at that link is not correct for VB and VE data -- the imaging gradients are included in the computation.

captainnova commented 2 weeks ago

Siemens XA also calculates the effect of imaging gradients, and reports the actual, not prescribed, b value in DICOM. However, they round b values to the nearest 50 s/mm^2, so the difference is rarely apparent in the .bval files written by dcm2niix.

I came across this when we prescribed a spherical shell at b = 2000 s/mm^2 and got some b = 1950s near the z axis. This is highly model dependent and possibly even scanner dependent. To their credit, Siemens also writes the b matrix, and the unrounded b value can be calculated from that. (It turned out to be around 1972 s/mm^2, so rounding to 50 was amplifying the apparent problem.)

captainnova commented 2 weeks ago

Note that tools like eddy default to expecting spherical shells (and so do most users!). I do not fault Siemens for rounding the simple b value, since they also provide the b matrix for those willing to delve deeper.

captainnova commented 2 weeks ago

I was unaware of the use of b=2s/mm^2 (I would personally have achieved what you describe in another way*), but this would also explain why the check for low b-values is even needed which I must admit I hadn't understood. With what you describe, then b=10s/mm^2 would indeed be fine.

(*Philips has to my knowledge an option to choose how many averages you want for each b-value - including b0 - though the exact name of the scan parameter eludes me. It is though likely an advanced parameter that may be locked behind some commercial option. Doing it "my" way would in my opinion be better as it would yield higher SNR to the data the scanner itself uses for artefact mitigation (NB: I am a former Philips employee, and I am liky biased by Philips' intended way of doing things which may not always completely align with all the user's actual needs).)

This is getting off-topic, but we were well aware of the Nex > 1 option for choosing averages. It is not suitable for protocols which require many (>~ 30 for b = 1000) directions for good angular coverage. Nex > 1 would still yield a #(b > 0)::#(b = 0) ratio >= 30, instead of the 8-12 range wanted for SNR, and it would not help angular coverage.

But getting back to dcm2niix (somewhat), I don't know if the threshold between b = "0" and b != 0 affects us much in "shelled" style dMRI. dcm2niix writes the 2s and 4s into the .bval and we carry on. This might only come up with "isotropic/trace" volumes where the b vector is [0 0 0] but b is > 0.

JanOP1337 commented 2 weeks ago

This is getting off-topic, but we were well aware of the Nex > 1 option for choosing averages. It is not suitable for protocols which require many (>~ 30 for b = 1000) directions for good angular coverage. Nex > 1 would still yield a #(b > 0)::#(b = 0) ratio >= 30, instead of the 8-12 range wanted for SNR, and it would not help angular coverage.

The parameter I was referring to is called "b-factor averages" and facilitates setting an extra factor for each b-value that is multiplied onto Nex's (NSA's in Philips lingo), i.e. setting it to 2 and 3 for b0 and b1000 and NSA=2 would yield 4 averages for b0 and 6 averages for b1000. Apologies if this was not clearly formulated. Indeed though, this is off-topic.

I came across this when we prescribed a spherical shell at b = 2000 s/mm^2 and got some b = 1950s near the z axis. This is highly model dependent and possibly even scanner dependent.

This sounds to me as another good argument for lowering the threshold for when dcm2niix does not generate a bval file; if you somehow got a sequence designed such that Siemens will report b=50s/mm^2 for the isotropic/trace-weighted images despite you intended it to be b=0s/mm^2, it would quite likely contribute significantly to the overall image contrast, thus something you would like to be aware of.

mharms commented 2 weeks ago

Note that tools like eddy default to expecting spherical shells (and so do most users!). I do not fault Siemens for rounding the simple b value, since they also provide the b matrix for those willing to delve deeper.

I don't know why Siemens changed from rounding to the nearest 5 s/mm^2 in VE to the nearest 50 s/mm^2 in XA. Users (and tools) were aware of the convention and had long since adapted to it (e.g., in terms of designating "shells"), so why change it ...