rordenlab / dcm2niix

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

RepetitionTime is sometimes incorrectly calculated #825

Closed lsaca05 closed 5 months ago

lsaca05 commented 5 months ago

Describe the bug A little background: I'm working with DCE-MRI data and I'm trying to read time resolution (time between volumes) from jsons generated from dcm2niix (which is run as a result of dcm2bids). I found that with my dataset, most cases I am only able to get time resolution when the RepetitionTimeExcitation (TR) field exists, in which case the RepetitionTime field becomes the time resolution. If it doesn't exist, then RepetitionTime is TR, and sometimes I can get time resolution from AcquisitionDuration. I'm wondering if there's a better, more consistent way to get time resolution beyond going to the DICOMs.

Onto the actual bug, for several cases I found that RepetitionTime (as time resolution) is incorrectly calculated. For one particular case, the AcquisitionTime difference between the first slice and first volume and the first slice and last volume divided by number of volumes was the correct value of 15.35 sec or so, instead of the reported "estimated" (according to a dcm2niix warning) RepetitionTime (json time res) of ~5.19556 sec. It seems likely that the divisor was some arbitrary whole number, in this case 189 (63*3? Frankly, no idea where this number could've come from). I can provide this case if you'd like.

To reproduce

Steps to reproduce the behavior:

  1. Run the command 'dcm2niix ...' on dynamic series DICOMs for particular cases...
  2. See Warning: Discrepancy between reported (0.00518s) and estimated (5.19556s) repetition time (issue 560) [issue unrelated?]
  3. Observe incorrect RepetitionTime in generated json, expecting a higher value Time Resolution.

Expected behavior

DICOMs converted to NIFTI should result in a json with a correct time resolution corresponding to the RepetitionTime field, if RepetitionTimeExcitation exists. This bug happens with ~5-10% of my data but there cases with the same scanner that have correct values.

Output log

Problematic data available upon request.

Version

Please report the complete version string:

Chris Rorden's dcm2niiX version v1.0.20240202 (JP2:OpenJPEG) (JP-LS:CharLS) GCC8.4.0 x86-64 (64-bit Linux)

Troubleshooting

Please try the following steps to resolve your issue:

git clone --branch development https://github.com/rordenlab/dcm2niix.git
cd dcm2niix/console
make
./dcm2niix ....

Have not done yet. I took a quick look at the dev branch commits and they do not seem related.

neurolabusc commented 5 months ago

Hello, it is worth noting that a single sequence can have several types of repetition time, with different manufacturers providing different types for the public tag. In contrast, BIDS requires the field RepetitionTime to refer to the time between 3D volumes. Therefore, it is hard to answer this question without more details. Feel free to share a sample dataset with my institutional email. My best hunch would be that this data comes from a manufacturer that uses a different form of TR in the public tag and has scrambled the time values in an attempt to preserve privacy. In these cases, you will have to specify values manually.

lsaca05 commented 5 months ago

Thanks for the speedy reply. I sent a sample, let me know if it didn't work.

neurolabusc commented 5 months ago

I believe this is the expected behavior. The value of created by dcm2niix is unintuitive for the DSC sample you sent me because the data has been averaged. While 64 volumes are generated, each with a timestamp separated by 15.5875 seconds, each is based on the average of three images. Therefore, the RepetitionTime between volumes (e.g. T1 recovery) is 5.19583 sec, while the RepetitionTimeExcitation is 0.00518. The crucial tag here is NumberOfAverages (DICOM public tag 0018,0083), which dcm2niix preserves in the BIDS header. If you do want to use traditional time series analyses, you will probably want to turn off the averaging and save more (but noisier) volumes.

Instance 1 (start of 1st volume)
(0020,1041) DS [-53.878510043911]   #  16, 1 SliceLocation
(0018,0080) DS [5.18]               #   4, 1 RepetitionTime
(0008,0032) TM [111414.792500]      #  14, 1 AcquisitionTime
(0018,0083) DS [3]                  #   2, 1 NumberOfAverages

Instance 17 (start of 2nd volume)
(0020,1041) DS [-53.878510043911]   #  16, 1 SliceLocation
(0018,0080) DS [5.18]               #   4, 1 RepetitionTime
(0008,0032) TM [111430.380000]      #  14, 1 AcquisitionTime
(0018,0083) DS [3]                  #   2, 1 NumberOfAverages
ironictoo commented 5 months ago

If BIDS defines RepetitionTime as the time between 3D volumes that is easy enough to interpret along with the averages value. However, this moves the problem to some other datasets we have. In most datasets we process the BIDS RepetitionTime field is filled in with the time between excitation pulses (these are spoiled 3D gradient echo data, so this is ~0.005 sec) and RepetitionTimeExcitation is not filled in at all. In these cases, the time between 3D volumes (which is ~15sec) is usually recorded in one of two places in the JSON: AcquisitionDuration, or TriggerTime

It sounds like the expected behavior for these other datasets is the 0.005sec value should be recorded in RepetitionTimeExcitation, and RepetitionTime should be calculated from the values found in AcquistionDuration or Trigger time as appropriate, so it is always time between 3D volumes. Does that sound correct?

For context this is all spoiled 3D gradient echo data, collected over ~10 years across 5 or so imaging sites, so we have some variation in the imaging protocol, scanner manufacturers, and scanner software versions.

neurolabusc commented 5 months ago

The BIDS standard defines RepetitionTime, RepetitionTimeExcitation, and RepetitionTimePreparation. It is not always clear how to distinguish these between manufacturers as well as different sequences or software from a single manufacturer. Therefore, dcm2niix tends to be pretty conservative about filling these fields, as it I would prefer to err on the side of not reporting a value than reporting it incorrectly for some situations. I am open to suggestion regarding how to identify these, but it is challenging. While it is an important modality, Dynamic Contrast-Enhanced is outside my expertise and we probably need some community input and public validation datasets so we can all agree we have specified the variables correctly.

ironictoo commented 5 months ago

Ok, I'll see if I can find some people from OSIPI that want to help with this. This seems to fall into what they are trying to accomplish.

neurolabusc commented 5 months ago

@ironictoo I am closing this issue, as we need more details to move forward. You may also want to see if ExploreASL does a better job than dcm2niix. ExploreASL does include some advanced logic that can resolve some perfusion parameters. Unfortunately, while it is free for non-commercial it uses a license that is incompatible with permissive open source licenses like the one used by dcm2niix. Therefore, I am unable to duplicate its behavior.

ironictoo commented 5 months ago

If I can get details, test datasets, and specific DICOM fields with help from OSIPI, are you willing to make updates to dcm2niix? I can give exact details and datasets for the three different ways "time between 3D volumes" is reported that I have found, but it sounded like you wanted input from a broader group.

I have this working for my pipeline, I just have a bunch of if statements and use different json fields depending on the data, so I don't need an immediate fix. But it would be nice if this worked more consistently for DCE applications.

neurolabusc commented 5 months ago

Happy to make improvements or merge pull requests from other teams, as long as this can be done without jeopardizing our permissive open source license. I agree it would be nice if it worked for DCE applications, but we also have to be careful about unintended consequences as we do not want to break support for a lot of other supported use cases like multi-echo fMRI.