Skip to content
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

24 hour time #322

Open
neurolabusc opened this issue Oct 28, 2024 · 11 comments
Open

24 hour time #322

neurolabusc opened this issue Oct 28, 2024 · 11 comments
Labels
bug Something isn't working

Comments

@neurolabusc
Copy link
Contributor

The terrific validation dataset provides both the input DICOMs as well as the reference conversion to BIDS.

I notice there is an error for TimeZero in the file sub-GeneralElectricSignaAarhus_pet.json. The DICOM image suggests this is at 1pm using 24-hour time format:

(0008,0031) TM [134653]                                 #   6, 1 SeriesTime

but the JSON suggests 1am (12-hour format does not disambiguate morning or afternoon).

"TimeZero": "01:46:53",
@neurolabusc neurolabusc added the bug Something isn't working label Oct 28, 2024
@neurolabusc
Copy link
Contributor Author

I also think there is an error in this InjectedRadioactivity

  "InjectedRadioactivity": 21,
  "InjectedRadioactivityUnits": "MBq",

I believe this should match DICOM Radionuclide Total Dose (0018,1074) which is defined as MBq:

    (0018,1074) DS [      20924990]                         #  14, 1 RadionuclideTotalDose

The pet2bids source code is converting megabecquerels (MBq) to gigabecquerels (GBq). So the results should either be:

  "InjectedRadioactivity": 20924990,
  "InjectedRadioactivityUnits": "MBq",

or

  "InjectedRadioactivity": 21,
  "InjectedRadioactivityUnits": "GBq",

I suspect the source of this issue is the developer assumed that the DICOM RadionuclideTotalDose is defined in Becquerels, but it is actually megabecquerels.

@bendhouseart
Copy link
Contributor

Hmm, not getting that error with the latest version of pypet2bids, will have to check Matlab next. See
sub-GeneralElectricSignaPETMRAarhus_pet.json

Above was generated using the following arguments:

/Users/galassiae/Data/Aarhaus_timing_bug/GeneralElectricSignaPETMR-Aarhus
--destination-path
/Users/galassiae/Data/Aarhaus_timing_bug/sub-GeneralElectricSignaPETMRAarhus/pet
--kwargs
Manufacturer="General Electric"
ManufacturersModelName="Signa PETMR"
InstitutionName="Århus University Hospital, DK"
BodyPart="Phantom"
Units="Bq/mL"
TracerName="FDG"
TracerRadionuclide="F18"
InjectedRadioactivity=21
SpecificRadioactivity=3.7234e+03
ModeOfAdministration="infusion"
FrameDuration=[600]
FrameTimesStart=[0]
AcquisitionMode="list mode"
ImageDecayCorrected="true"
ImageDecayCorrectionTime=0
AttenuationCorrection="MR-corrected"
ReconFilterType='unknown'
ReconFilterSize=1
ReconMethodParameterLabels="[none, none]"
ReconMethodParameterUnits="[none, none]"
ReconMethodParameterValues="[0, 0]"

Could you attach the full JSON you're seeing that in? If you're referring to the sidecar json in the Computerome hosted dataset don't worry about it. I'll have access the output there shortly.

@bendhouseart
Copy link
Contributor

bendhouseart commented Dec 5, 2024

And good catch with the InjectedRadioactivity, but it's not wrong per say as the user ultimately decided that the dicom was wrong. Here is the snippet that was used to convert it:

try
    clear meta
    meta.TimeZero                   = 'ScanStart';
    meta.Manufacturer               = 'General Electric';
    meta.ManufacturersModelName     = 'Signa PET/MR';
    meta.InstitutionName            = 'Århus University Hospital, DK';
    meta.BodyPart                   = 'Phantom';
    meta.Units                      = 'Bq/mL';
    meta.TracerName                 = 'FDG';
    meta.TracerRadionuclide         = 'F18';
    meta.InjectedRadioactivity      = 21; % Mbq
    meta.SpecificRadioactivity      = 3.7234e+03; % ~ 21000000 Bq/ 5640 ml
    meta.ModeOfAdministration       = 'infusion';
    meta.FrameTimesStart            = 0;
    meta.AcquisitionMode            = 'list mode';
    meta.ImageDecayCorrected        = 'true';
    meta.ImageDecayCorrectionTime   = 0;
    meta.AttenuationCorrection      = 'MR-corrected';
    meta.FrameDuration              = 600;
    meta.FrameTimesStart            = 0;
    meta.ReconFilterType            = "none";
    meta.ReconFilterSize            = 0;
    meta.ReconMethodParameterLabels = ["none"];
    meta.ReconMethodParameterUnits  = ["none"];
    meta.ReconMethodParameterValues = [0];
    meta.InjectionEnd               = [10];

    dcm2niix4pet(fullfile(source,'GeneralElectricSignaPETMR-Aarhus'),meta,...
        'o',fullfile(destination,['sub-GeneralElectricSignaAarhus' filesep 'pet'])); % note we only need to use folders here

catch
    disp(message);
end

I've gone ahead and deleted the conversion script you referenced earlier as it's not been used in some time. Will double check the dataset on Computerome once I have access tomorrow and make any additional fixes.

Thanks again.

@neurolabusc
Copy link
Contributor Author

The errors I report are from the JSONs in the OpenNeuroPET Phantoms validation dataset.

@bendhouseart
Copy link
Contributor

Hmm, I wouldn't necessarily trust the information in the dicom header over the information applied manually via the meta input. It's typical to make a more accurate recording of the dosage outside of the scanner and reconcile it with the imaging after the fact. That said, even if it's inaccurate it might make sense to rerun the conversions on this dataset without manually adding the InjectedDose so that they align with the imaging data. I've started to update the InjectedDose where able in matlab_conversions.m in the meantime.

Alternatively, we could add the conversion script used to generate those files to the dataset so there's less confusion on how they arrived in their existing state.

@bendhouseart
Copy link
Contributor

@CPernet tagging you in as I'm having difficulty accessing the data on Computerome. Do you think we should:

  • update the conversion script to better reflect the dicom values
  • share the conversion script in the phantom dataset along with an explaination
  • or do all of the above

I was working on the first of those, but I'm slightly stuck until I have access to one of the phantoms.

@bendhouseart
Copy link
Contributor

Okay okay, not sure if it was a picnic issue or other with collecting the phantoms from Computerome.

But, getting back on point, in the Readme associated with this dataset it's not 100% clear that the dicoms won't match the BIDS output:

PN000001: OpenNeuroPETPhantoms
License: CCBY4.0

The PET Brain phantoms dataset is curated by OpenNeuroPET. This repository contains source data from PET scanners that need to be converted to nifti format, preferably following BIDS. An issue with ecat and DICOM data is that many tags are not mandatory and many values are not standardized making it difficult to harmonize the outputs of conversion, in particular side car json files. Here we collected many phantoms from different sites and scanners allowing to check the different header tags and values. This also allows validated conversion tools. Such test is performed via the code folder where one use the PET2BIDS library to do the conversion (which depends on dcm2niix for DICOM). Feel free to contact OpenNeuroPET to add your data from a scanner we have not tested.

So, do we want to make it more explicit that the scripts injected values that aren't in the dicoms? Or make the scripts "correct" to referect the dicom header info?

Thanks!

@neurolabusc
Copy link
Contributor Author

I do think it would be great if we could create a regression testing validation structure similar to the dcm_qa series. This would ensure changes do not break compatibility, and also provide a roadmap for extracting as much as possible from the DICOMs without human intervention. I would start with the basic dcm_qa that just uses dcm2niix to convert the DICOMs. You could apply a regression test that ignores tags we know can not currently be populated by dcm2niix, e.g. dcm_qa validation test ignore the key BidsGuess. Next, the json sidecar is injected with known details from pet2bids, with a second validation test that ignores fewer keys. I think the crucial thing about the dcm_qa series is that it has the raw DICOMs (In folder) and the reference correct solution (Ref folder). This provides a gold standard for improving our ability to populate the gold standard and detect if there are any unintended consequences of our changes.

@bendhouseart
Copy link
Contributor

Oh, that's pretty clever, the most we're doing now is comparing the outputs between the Matlab and Python versions of the conversions. I think we'd just need to add a run of dcm2niix over the same folders that pet2bids is targeting before we move onto a comparison between the two. I'll include that in the upcoming PR.

@CPernet
Copy link
Contributor

CPernet commented Dec 16, 2024

@bendhouseart can you point me to the code you use to retrieve the phamtom data (you do not need any login, there is a open access link)

@bendhouseart
Copy link
Contributor

@CPernet I mentioned this on Monday at our meeting; it turns out I'm just not very tech savvy and missed the download link here it's working fine for me now.

@neurolabusc a little history for you that might explain some things:

Initially we would warn users if the dicom header values didn't match the given user inputs either via arguments or from an input spreadsheet. But, at some point I got enough complaints about the verbosity of those warnings and I disabled that functionality. The same wasn't done in the Matlab version as those users didn't feel the same or are more used to being ignored. Of course some year(s) later I'm having trouble pinpointing exactly when/where those changes took place.

The discrepancy you've observed between the dicom headers and the BIDS sidecars, in most cases, exists because the dicom values are incorrect. I haven't had nearly enough time at the scanner, but Cyril will tell you that more often than not the manufacturer's have limited a users ability to enter the correct values into the console at scan time. If you speak to a PET imager they'll tell you that all "important" PET data being captured by some other means and recorded into a spreadsheet or text file later. It could be different at other locations, but in my encounters it's almost always the case that blood and radioactivity data accompany the imaging data in the form of a spreadsheet.

All that said, I still don't think it would hurt to update our documentation to better inform users of as much, nor adding in some mention of the differences between dcm2niix output and the extra metadata PET2BIDS tacks onto it. I think the documentation is more than due for a update with that and then some.

I do think it would be great if we could create a regression testing validation structure similar to the dcm_qa series. This would ensure changes do not break compatibility, and also provide a roadmap for extracting as much as possible from the DICOMs without human intervention. I would start with the basic dcm_qa that just uses dcm2niix to convert the DICOMs. You could apply a regression test that ignores tags we know can not currently be populated by dcm2niix, e.g. dcm_qa validation test ignore the key BidsGuess. Next, the json sidecar is injected with known details from pet2bids, with a second validation test that ignores fewer keys. I think the crucial thing about the dcm_qa series is that it has the raw DICOMs (In folder) and the reference correct solution (Ref folder). This provides a gold standard for improving our ability to populate the gold standard and detect if there are any unintended consequences of our changes.

I still think your suggestion is worthwhile and I'll be chipping away at it as soon as I get back from the holidays!

Cheers,

Anthony

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

When branches are created from issues, their pull requests are automatically linked.

3 participants