ENHANCE-PET / nifti2dicom

Welcome to Nifti2Dicom! Born from countless hours of yelling at screens, this software aims to swap NIfTI for DICOM without inviting any more hair-pulling or infernal uprisings. Because, honestly, who needs another software-induced existential crisis? 🔁💻😫🔥
Apache License 2.0
18 stars 3 forks source link

'LossyImageCompressionRatio' issue when using MOOSE segmentation CT as input #17

Open prabathbr opened 1 year ago

prabathbr commented 1 year ago

Hi,

Looks like pydicom is looking for LossyImageCompressionRatio attribute when using MOOSE segmentation as input. I am using nifti2dicom 1.1.3 with patched sms 3D

MOOSE Segmentation info from dataset.json:

{
    "name": "Dataset001_PUMA",
    "description": "",
    "reference": "",
    "licence": "hands off!",
    "release": "0.0",
    "labels": {
        "background": 0,
        "legs": 1,
        "body": 2,
        "head": 3,
        "arms": 4
    },
    "numTraining": 121,
    "file_ending": ".nii.gz",
    "channel_names": {
        "0": "CT"
    }
}

labels_region_body.json as per sample :

{
    "1": "legs",
    "2": "body",
    "3": "head",
    "4": "arms"
}

Error:

nifti2dicom -d J:\MTIC\moose\test\S1\AC-CT -n J:\MTIC\moose\test\S1\moosez-clin_ct_body-2023-08-21-12-50-22\segmentations\CT_Body_CT_2_mtic_fusion_ct_imar_0000.nii.gz -o J:\MTIC\moose\test\S1\seg_dicom_output -desc "test CT moose" -t seg -j J:\MTIC\moose\test\labels_region_body.json

          _ ______  _ ___       ___
   ____  (_) __/ /_(_)__ \ ____/ (_)________  ____ ___
  / __ \/ / /_/ __/ /__/ // __  / / ___/ __ \/ __ `__ \
 / / / / / __/ /_/ // __// /_/ / / /__/ /_/ / / / / / /
/_/ /_/_/_/  \__/_//____/\__,_/_/\___/\____/_/ /_/ /_/
A package to convert NIfTI images to DICOM format using a reference DICOM series. Nifti2dicom is a part of the ENHANCE.PET (https://enhance.pet) framework

 🔍 IDENTIFIED DATASETS:

 * Reference DICOM series directory: J:\MTIC\moose\test\S1\AC-CT
 * Loading NIfTI segmentation: J:\MTIC\moose\test\S1\moosez-clin_ct_body-2023-08-21-12-50-22\segmentations\CT_Body_CT_2_mtic_fusion_ct_imar_0000.nii.gz
 Processing segments... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Traceback (most recent call last):
  File "k:\Miniconda3\envs\moose\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "k:\Miniconda3\envs\moose\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "k:\Miniconda3\envs\moose\Scripts\nifti2dicom.exe\__main__.py", line 7, in <module>
  File "k:\Miniconda3\envs\moose\lib\site-packages\nifti2dicom\converter.py", line 293, in main
    save_dicom_from_nifti_seg(args.nifti_path, args.dicom_dir, args.output_dir, organ_index)
  File "k:\Miniconda3\envs\moose\lib\site-packages\nifti2dicom\converter.py", line 233, in save_dicom_from_nifti_seg
    seg = hd.seg.Segmentation(
  File "k:\Miniconda3\envs\moose\lib\site-packages\highdicom\seg\sop.py", line 1275, in __init__
    src_img.LossyImageCompressionRatio
  File "k:\Miniconda3\envs\moose\lib\site-packages\pydicom\dataset.py", line 908, in __getattr__
    return object.__getattribute__(self, name)
AttributeError: 'FileDataset' object has no attribute 'LossyImageCompressionRatio'
LalithShiyam commented 1 year ago

Hi @prabathbr thanks for the detailed report, much appreciated. Helps us a lot. @Keyn34 would you be kind enough to take a stab at this? I am occupied till 25th.

@prabathbr we will get back to you, on how to tackle this. But it's clear a tag is missing. But not sure why this is needed by highdicom/pydicom.

prabathbr commented 1 year ago

Hi @prabathbr thanks for the detailed report, much appreciated. Helps us a lot. @Keyn34 would you be kind enough to take a stab at this? I am occupied till 25th.

@prabathbr we will get back to you, on how to tackle this. But it's clear a tag is missing. But not sure why this is needed by highdicom/pydicom.

Thanks, I have added test environment version details for your reference as well.

pydicom = 2.4.3 highdicom = 0.21.1 nifti2dicom = 1.1.3 moosez = 2.2.23 dicom2nifti = 2.4.8

From my rough analysis, it seems that Lossy Image Compression Attribute (0028,2110) is an optional DICOM tag. https://dicom.innolitics.com/ciods/rt-dose/general-image/00282110

The source DICOM dataset contains LossyImageCompression: '01' and that triggers line 1273 of \highdicom\seg\sop.py shown below. The same source DICOM dataset works well with image conversion (i.e. with -t img -v sms after patch 4d flip )

        if self.LossyImageCompression == '01':
            self.LossyImageCompressionRatio = \
                src_img.LossyImageCompressionRatio
            self.LossyImageCompressionMethod = \
                src_img.LossyImageCompressionMethod
LalithShiyam commented 1 year ago

Yes, but do you want a segmentation object or a dicom series? Both of them are different. Right?

prabathbr commented 1 year ago

Yes, but do you want a segmentation object or a dicom series? Both of them are different. Right?

Sorry for the confusion. We are trying to get segmentation NIFTI as a dicom series.

nifti2dicom -d J:\MTIC\moose\test\S1\AC-CT -n J:\MTIC\moose\test\S1\moosez-clin_ct_body-2023-08-21-12-50-22\segmentations\CT_Body_CT_2_mtic_fusion_ct_imar_0000.nii.gz -o J:\MTIC\moose\test\S1\seg_dicom_output -desc "test CT moose" -t seg -j J:\MTIC\moose\test\labels_region_body.json

JasonMTIC commented 1 year ago

what we need is for the segmentation to be converted to a DICOM object that we can load into our DICOM image viewing platforms. Usually the DICOM object for a segmentation is a RTSS or RTSTRUCT. This is the standard that is used when defining regions of interest. We will contour a scan and then save the RTSS associated with that particular scan. so in this case the CT has been segmented so there needs to be a DICOM CT as well as a DICOM RTSS associated with that CT for the regions of interest. hope this makes sense.

LalithShiyam commented 1 year ago

@JasonMTIC yes it does - that's why I was confused when @ the image tag. That just creates another dicom series and the labels are not stored as intensities. We need to figure out why it fails as dicom segmentation object. May be send a sample to me, and I can see what's happening. It's hard to see without having the data. Cheers, Lalith

Keyn34 commented 1 year ago

@JasonMTIC & @prabathbr could you please send me some sample data so I can try to reproduce what you are experiencing here? I can set up a save data-sharing link as well. Just let us know.

JasonMTIC commented 1 year ago

DOE^JOHN_ANON72950_RTst_2023-03-07_105613_MTIC.PSR.Total.Body.Sn.(Adult)_Auto._n1__00000.zip

sure thing here is an RTSS file with multiple organs segmented on the CT. Can you send a data sharing link and i can send the CT as well

Keyn34 commented 1 year ago

Perfect, @JasonMTIC. That works just fine as well!

I will look into that.

Keyn34 commented 1 year ago

Hi @JasonMTIC, can you try this link to upload the rest of the data? Thanks!

LalithShiyam commented 1 year ago

Any updates on this guys??

JasonMTIC commented 1 year ago

I'm uploading an example now of a CT scan with an associated RTSS that has AI generated contours. This is what I'd like to be able to do with this converter. I want to run MOOSE and convert the CT and segmentation files back to a DICOM CT and DICOM RTSS.

JasonMTIC commented 1 year ago

I've just uploaded the same scan but run through MOOSE for comparison_

Keyn34 commented 1 year ago

Perfect @JasonMTIC. We will get back to you.

JasonMTIC commented 1 year ago

Perfect @JasonMTIC. We will get back to you.

how did it go with the example data?

Keyn34 commented 1 year ago

Hi @JasonMTIC, I could recreate the issue on my system, but conference preparations for EANM 2023 for the last two weeks made it hard to dive deeper into the problem and fix it. I am working on it right now, though!

Very sorry for the delay.

Keyn34 commented 1 year ago

Hi @JasonMTIC. It appears that I could circumvent the original issues concerning the LossyImageCompression tag. To my understanding, the tag LossyImageCompression is set to 01 in your dataset, which triggers the search for LossyImageCompressionRatio and LossyImageCompressionMethod in the pydicom/highdicom library that we use. These two tags do not exist in the dataset you provided.

Please correct me if I am wrong, but it appears this is a dataset-specific issue. It is possible that some tags went missing during exporting or were neglected when they were actually needed. I could circumvent it by manually setting the LossyImageCompression tag to 00 by a patch.

This does work but leads to a faulty DICOM segmentation because of the apparently existing compression, I think.

Do you have more insights into the compression and exporting procedures? Maybe we can follow up on that when we look deeper into the missing tags?

BTW, the segmentation nifti you gave me does not cover the extremities but the organs. The JSON looks like this:

"labels": {
        "background": 0,
        "spleen": 1,
        "kidney_right": 2,
        "kidney_left": 3,
        "gallbladder": 4,
        "liver": 5,
        "stomach": 6,
        "aorta": 7,
        "inferior_vena_cava": 8,
        "portal_vein_and_splenic_vein": 9,
        "pancreas": 10,
        "adrenal_gland_right": 11,
        "adrenal_gland_left": 12,
        "lung_upper_lobe_left": 13,
        "lung_lower_lobe_left": 14,
        "lung_upper_lobe_right": 15,
        "lung_middle_lobe_right": 16,
        "lung_lower_lobe_right": 17
    }

I used this one for testing.

JasonMTIC commented 1 year ago

Hi @Keyn34

sorry i was on a break for a couple of weeks. I've had a look into this and it look like maybe the modality is adding this compression tag when it is exported off the scanner. I'm just spoke with one of the engineers and this apparently makes the transfers significantly faster. He's going to look into it a bit more.

JasonMTIC commented 1 year ago

@Keyn34 @LalithShiyam @prabathbr

So i've found out what the lossy compression tag is about. we reconstruct the data with an extended filed of view. As a result siemens add the tag to say there is lossy compression applied however there is actually no compression. They add this tag to indicate that the eFOV was done. very confusing. Is there any way around this do you think?

Keyn34 commented 1 year ago

Hi @JasonMTIC,

Thank you for shedding light on this. That's an odd way to mark an extended field of view... I tried to set that tag to 0 manually, but that made the image unreadable for me. I will try to give it another go.

JasonMTIC commented 1 year ago

WE tried to run the converter again with a new dataset that did not have the compression tag and got the same result.

Warnings when running nifti2dicom :

C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int32' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int64' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int32' cannot be assigned to a tag with VR US.
  warnings.warn(msg)

Commands and output:

(moose-mtic) C:\QIMP_Data>nifti2dicom -d "C:\QIMP_Data\MOOSE\2023-10__Studies\name^^MR_121.1313_CT_2023-10-26_105547_PET^MTIC.PSR.Total.Body.Sn.CBM.(Adult)_MTIC.Fusion.CT_n601__00000" -n "C:\QIMP_Data\MOOSE\2023-10__Studies\moosez-clin_ct_organs-2023-10-26-11-23-15\segmentations\CT_Organs_CT_2_mtic_fusion_ct_0000.nii.gz" -o "C:\QIMP_Data\MOOSE\2023-10__Studies\seg_dicom_output" -desc "test CT moose" -t seg -j "C:\QIMP_Data\MOOSE\2023-10__Studies\moosez-clin_ct_organs-2023-10-26-11-23-15\segmentations\dataset_converted.json"

          _ ______  _ ___       ___
   ____  (_) __/ /_(_)__ \ ____/ (_)________  ____ ___
  / __ \/ / /_/ __/ /__/ // __  / / ___/ __ \/ __ `__ \
 / / / / / __/ /_/ // __// /_/ / 
/ /__/ /_/ / / / / / /
/_/ /_/_/_/  \__/_//____/\__,_/_/\___/\____/_/ /_/ /_/
A package to convert NIfTI images to DICOM format using a reference DICOM series. Nifti2dicom is a part of the ENHANCE.PET (https://enhance.pet) framework

 🔍 IDENTIFIED DATASETS:

 * Reference DICOM series directory: C:\QIMP_Data\MOOSE\2023-10__Studies\name^^MR_121.1313_CT_2023-10-26_105547_PET^MTIC.PSR.Total.Body.Sn.CBM.(Adult)_MTIC.Fusion.CT_n601__00000
 * Loading NIfTI segmentation: C:\QIMP_Data\MOOSE\2023-10__Studies\moosez-clin_ct_organs-2023-10-26-11-23-15\segmentations\CT_Organs_CT_2_mtic_fusion_ct_0000.nii.gz
 Processing segments... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int32' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int64' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
C:\QIMP_Data\moose-mtic\Lib\site-packages\pydicom\valuerep.py:443: UserWarning: A value of type 'int32' cannot be assigned to a tag with VR US.
  warnings.warn(msg)

(moose-mtic) C:\QIMP_Data>

This is the segmentation information JSON file:
dataset_converted.json

Error when trying to load output DICOM segmentation file as segmentation in ITK-SNAP: Screenshot 2023-10-26 114319

Keyn34 commented 1 year ago

Hi @JasonMTIC This is strange. After a quick review of the error messages, it seems like the problem stems from the header tags and pydicom itself. Can you transfer this dataset as well? If yes, I can send you a transfer link again. Thank you so much.

JasonMTIC commented 1 year ago

Yes can do. send me through the link

Keyn34 commented 1 year ago

There you go.

JasonMTIC commented 1 year ago

I've uploaded some sample data that I put through MOOSE and we havn't managed to convert back to DICOM

Keyn34 commented 1 year ago

Hello, @JasonMTIC! Thank you for your patience, and I am sorry again for the delay.


I used the latest version (1.1.4, which does not differ from the release version regarding conversion) of nifti2dicom and latest data that you transferred again, meaning the dataset ANON88347 with dataset_converted.json you uploaded. In a clean virtual environment, I used the following command:

nifti2dicom 
-d "~/nifti2dicom/MTIC_MOOSE/2023-10__Studies/DOE^JOHN_ANON88347_CT_2023-10-26_105547_PET^MTIC.PSR.Total.Body.Sn.CBM.(Adult)_MTIC.Fusion.CT_n601__00000" 
-n "~/nifti2dicom/MTIC_MOOSE/2023-10__Studies/moosez-clin_ct_organs-2023-10-30-09-58-29/segmentations/CT_Organs_CT_2_mtic_fusion_ct_0000.nii.gz" 
-o "~/nifti2dicom/MTIC_MOOSE/2023-10__Studies/dicom_output" 
-desc "test CT moose" 
-t seg 
-j "~/nifti2dicom/MTIC_MOOSE/2023-10__Studies/moosez-clin_ct_organs-2023-10-30-09-58-29/segmentations/dataset_converted.json"

The command was formatted for better readability.


After that, I received the following two warnings:

/home/horyzen/Projects/Python/nifti2dicom/venv/lib/python3.10/site-packages/pydicom/valuerep.py:443: UserWarning: A value of type 'int64' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
/home/horyzen/Projects/Python/nifti2dicom/venv/lib/python3.10/site-packages/pydicom/valuerep.py:443: UserWarning: A value of type 'int64' cannot be assigned to a tag with VR US.
  warnings.warn(msg)

They differ from your warnings!


Trying to read the image with ITK-SNAP as well gives me no error or warning now, but the following 3D image: image 3DSlicer was also able to read the image and display it in the same way.


This was the same output I got after manually removing those compression tags from your previous data. Did you use the same dataset that you sent me where you encountered the errors? I am not sure right now why we see differences suddenly. What Python version are you using for the virtual environment? Also, try updating nifti2dicom via pip install --upgrade nifti2dicom and give it another go.

Additionally, can you try a very different dataset, not from that scanner? That suggestion might sound odd, but I am curious if the warnings and errors are really device-dependent.

Please let me know, and thanks again!

prabathbr commented 1 year ago

Hello, @JasonMTIC! Thank you for your patience, and I am sorry again for the delay.

I used the latest version (1.1.4, which does not differ from the release version regarding conversion) of nifti2dicom and latest

Hello @Keyn34,

Thanks a lot for the detailed analysis. I think @JasonMTIC would be able share more information about the data itself.

Just a side note, would you be able to share pip list and python --version outputs of your environment. Probably there would be some difference in pydicom versions. We might be able to match the versions and give it a try.

Thanks.

Keyn34 commented 1 year ago

Hey @prabathbr, of course.

The Python version I am using is 3.10. To be specific, it is Python 3.10.12. Here is the list with all relevant packages and their version:

Package        Version
-------------- ------- 
emoji          2.8.0
highdicom      0.21.1
nibabel        5.1.0
numpy          1.26.1
pydicom        2.4.3
pyfiglet       1.0.2
rich           13.6.0

Hope this helps.

prabathbr commented 1 year ago

Hey @prabathbr, of course.

The Python version I am using is 3.10. To be specific, it is Python 3.10.12. Here is the list with all relevant packages and their version:

Package        Version
-------------- ------- 
emoji          2.8.0
highdicom      0.21.1
nibabel        5.1.0
numpy          1.26.1
pydicom        2.4.3
pyfiglet       1.0.2
rich           13.6.0

Hope this helps.

Hello @Keyn34,

Thanks a lot for the information and support. Finally, I was able to generate similar output as yours using below package versions in a fresh Python environment. There were no errors during the nifti2dicom conversion with these versions.

Python 3.10.13

Package        Version
-------------- ------
emoji          2.8.0
highdicom      0.22.0
markdown-it-py 3.0.0
mdurl          0.1.2
nibabel        5.1.0
nifti2dicom    1.1.4
numpy          1.26.1
packaging      23.2
Pillow         10.1.0
pillow-jpls    1.2.0
pip            23.3.1
pydicom        2.4.3
pyfiglet       1.0.2
Pygments       2.16.1
rich           13.6.0
setuptools     68.2.2
wheel          0.41.3

Also, I had to update ITK-SNAP from 3.8.0 to 4.0.2 to solve that issue showing in the ITK-SNAP and to open the resultant DICOM segmentation.

Looks like there is some kind of dimension mismatch in the resultant DICOM segmentation file, so that I can't open that as a segmentation file for the original CT image in either DICOM or NIFTI format wiht ITK-SNAP.

Original CT DICOM series is 512x512x601 (also MOOSE converted NITFI inputfile CT_2_mtic_fusion_ct.nii has the same 512x512x601 dimensions). But this DICOM segmentation file gets detected as 512x512x662 when opened as a segmentation overlay for the original CT image in ITK-SNAP,although NIFTI segmentation (MOOSE output file CT_Organs_CT_2_mtic_fusion_ct_0000.nii.gz in MOOSE output segmentation folder) has correct dimension of 512x512x601, same as the original CT DICOM series.

Could you please check with your results (i.e. load original CT image first, then load the segmentation DICOM as segmentation overlay in ITK-SNAP) as I am using the same dataset provided by @JasonMTIC, which you have used in here

Also, I have noticed in ITK-SNAP that all segmentation is fused together as 255 value for segmentations and 0 value for the background when I opened segmentation file in ITK-SNAP (as shown in your result image with ITK-SNAP). I am not sure this is an expected outcome as NIFTI segmentation files has different values for each organ segmentation.

Keyn34 commented 1 year ago

Hey @prabathbr,

Thank you a lot for the feedback and your provided information. It's good that we are at least on the same level regarding errors and output now! :D


I loaded the DICOM image, the CT image and the CT segmentation (generated by MOOSE) and the DICOM segmentation file (generated by nifti2dicom) and i can confirm that this

Original CT DICOM series is 512x512x601 (also MOOSE converted NITFI inputfile CT_2_mtic_fusion_ct.nii has the same 512x512x601 dimensions). But this DICOM segmentation file gets detected as 512x512x662 when opened as a segmentation overlay for the original CT image in ITK-SNAP,although NIFTI segmentation (MOOSE output file CT_Organs_CT_2_mtic_fusion_ct_0000.nii.gz in MOOSE output segmentation folder) has correct dimension of 512x512x601, same as the original CT DICOM series.

is the same for me as well. I also noticed that the spacing of the DICOM segmentation image is not the same. And I think this goes hand in hand with what you describe here,

Also, I have noticed in ITK-SNAP that all segmentation is fused together as 255 value for segmentations and 0 value for the background when I opened segmentation file in ITK-SNAP (as shown in your result image with ITK-SNAP). I am not sure this is an expected outcome as NIFTI segmentation files has different values for each organ segmentation.

because this is, unfortunately, not the expected outcome, the image itself should be the same. I noticed that, too, besides the false representation of the image.


I could not find any apparent error in the nifti2dicom implementation after browsing through the pydicom and highdicom documentation. However, I found some code samples on generating DICOM segmentations in the highdicom documentation. So, I decided to look at your DICOM CT data again and try to convert the data after simple thresholding to a DICOM segmentation. The outcome was similarly unusable: image

I also encountered the following warnings as before:

/home/horyzen/Projects/Python/nifti2dicom/venv/lib/python3.10/site-packages/pydicom/valuerep.py:443: UserWarning: A value of 
type 'int64' cannot be assigned to a tag with VR UL.
  warnings.warn(msg)
/home/horyzen/Projects/Python/nifti2dicom/venv/lib/python3.10/site-packages/pydicom/valuerep.py:443: UserWarning: A value of type 'int64' cannot be assigned to a tag with VR US.
  warnings.warn(msg)

What I suspect based on this observation are two things:

  1. highdicom apparently has trouble constructing a proper segmentation file. So, I would say we can pinpoint the error there: the construction of the DICOM segmentation file.
  2. I would even say the problem lies in the source_images attribute, where the original dicom data is passed. I assume that the data contains one or more DICOM tags that cause a major hiccup for highdicom. I also tried it with the PET image (just out of curiosity), and the outcome was similar. So, it is most likely a tag that both images share.

I will try to dig deeper later this or next week and update you if I find something. I hope this is alright for you! Sorry for the long reply as well.

JasonMTIC commented 1 year ago

Do you think it would be possible to convert the contours to a RTSTRUCT dicom object rather than a segmentation object? the RTSTRUCT object type is what we normally use clinically

Keyn34 commented 1 year ago

I'm not really sure. We made attempts regarding RTSTRUCT but did not come far, so unfortunately, this is out of our scope. Sorry about that.

rullator commented 11 months ago

Hi guys, I just tried nifti2dicom for the first time aiming to convert a MOOSE segmentation into a DICOM file/structure.

I ran into the same problem as initially described here.

Traceback (most recent call last):
  File "/.../nifti2dicom/bin/nifti2dicom", line 8, in <module>
    sys.exit(main())
  File "/.../nifti2dicom/lib/python3.9/site-packages/nifti2dicom/converter.py", line 290, in main
    save_dicom_from_nifti_seg(args.nifti_path, args.dicom_dir, args.output_dir, organ_index)
  File "/.../nifti2dicom/lib/python3.9/site-packages/nifti2dicom/converter.py", line 239, in save_dicom_from_nifti_seg
    seg = hd.seg.Segmentation(
  File "/.../nifti2dicom/lib/python3.9/site-packages/highdicom/seg/sop.py", line 1651, in __init__
    src_img.LossyImageCompressionRatio
  File "/.../nifti2dicom/lib/python3.9/site-packages/pydicom/dataset.py", line 908, in __getattr__
    return object.__getattribute__(self, name)
AttributeError: 'FileDataset' object has no attribute 'LossyImageCompressionRatio'

What is the current workaround for that issue? Removing the DICOM tag (0028,2110) LossyImageCompression from the referenced DICOM series (Siemens Quadra CT data in my case)?

Keyn34 commented 11 months ago

Hey @rullator,

Yes, you can try that. I noticed that the success here depends on what data is being used. So please let us know if that works for you! Thanks :)

rullator commented 11 months ago

I pretty much have similar data as @JasonMTIC

Only the (0028,2110) is set, but not (0028,2112) or (0028,2114). In the additionally required Tag Derivation Description (0008,2111), the information about extended field of view is stored: (0008,2111) ST [Reconstruction field larger than scan field].

I assume, that highdicom follows the DICOM recommendation and demands the tags (0028,2112) and (0028,2114), if (0028,2110) is set to "01", but both tags are not defined in the reference serie.

After removing (0028,2110) from the reference series, nifti2dicom runs smoothly. To remove the tag I used dcmtk: dcmodify -nb -e "(0028,2110)" *.dcm

I can open the converted segmentation successfully with Slicer. Actually, my main goal is to import/open the segmentation with the HERMES/HERMIA[1] suite, but that seems to be a tougher challenge.. Do you have any experience with it?

[1] https://www.hermesmedical.com/our-software/

LalithShiyam commented 11 months ago

@rullator ROFL! Ofcourse, HMS is our github sponsor for MOOSE. We work with them and we have a custom made solution that integrates seamlessly with Hermes. But for that we need to talk in private: lalith.shiyamsundar@meduniwien.ac.at

prabathbr commented 11 months ago

I pretty much have similar data as @JasonMTIC

Only the (0028,2110) is set, but not (0028,2112) or (0028,2114). In the additionally required Tag Derivation Description (0008,2111), the information about extended field of view is stored: (0008,2111) ST [Reconstruction field larger than scan field].

I assume, that highdicom follows the DICOM recommendation and demands the tags (0028,2112) and (0028,2114), if (0028,2110) is set to "01", but both tags are not defined in the reference serie.

After removing (0028,2110) from the reference series, nifti2dicom runs smoothly. To remove the tag I used dcmtk: dcmodify -nb -e "(0028,2110)" *.dcm

I can open the converted segmentation successfully with Slicer. Actually, my main goal is to import/open the segmentation with the HERMES/HERMIA[1] suite, but that seems to be a tougher challenge.. Do you have any experience with it?

[1] https://www.hermesmedical.com/our-software/

Hello @rullator,

I am wondering whether you were able to import original DICOM series to slicer and then import the segmentation DICOM output from nifti2dicom as a segmentation overlay. I tried to do the same with ITK-SNAP as mentioned in earlier reply, and ran into dimension mismatch issue.

Also, segmentation file had only 0 and 255 values and it was not showing different segments. Were you able to get everything correctly as expected with Slicer? Could you please share the procedure with Slicer?

Thanks a lot!

rullator commented 11 months ago

I think, the DICOM segmentation file has everything stored correctly and it's probably an visualization issue with the software (ITK-Snap). DICOM segmentations are stored differently then a multi-label 3D-NIfTI file, where each segmentation has its own label value. The disadvantage of multi-label 3D-NIfTI: it cannot handle two different labels for the same voxel. A 4D-NIfTI file could handle that and also the DICOM segmentation files provide that functionality.

The DICOM segmentation file is stored differently then the multi-label 3D-NIfTI file. It's not a 3D file with the same dimensions as the reference, where each label has its own gray value.

I'm no DICOM segmentation expert, but when looking into SegmentSequence (0062,0002), you will spot that each segmentation has its own item including its label (as provided by the JSON file). When looking into PerFrameFunctionalGroupsSequence (5200,9230) you will find a bunch of entries. Each entry is assigned to one of the defined labels (SegmentSequence (0062,0002)). The number of items probably correspond to the amount of planes where a segmentation could be find. So with 10 labels, each defined over 15 planes, you will probably have 150 items within that Tag. So each label is defined separatly and voxelwise probably simply defined as true (binary) or 255. It's then a feature of the DICOM visualization software to display each item with a different color (or whatever). But the labels per se still exist independent of each other in the DICOM segmentation file.

Loading within Slicer was done as following:

  1. I rarely use Slicer, so I have a pretty old version installed: v4.10.1, whereas v5.6.0 is already available.

  2. Slicer has several modules, which provide different functionalities. You will need the DICOM module first.

  3. On the Welcome Screen -> Load DICOM Data -> Import: Import your Reference and Segmentation series.

  4. Click on the Name in the first table. The second table shows all studies, the third all series to the chosen study. So choose your study and then both series.

  5. After I clicked on load, Slicer recommended to install the Extension "Quantitative Reporting", which I did (and also all required extensions).

  6. Then you have the reference and the corresponding segmentation loaded. The different segmentations are visualized with the same color. You can change that in the module "Segmentations". In my version, the loaded segmentation has the name "unkown". Choose the "unknown" as active segmenation. Then you can change the color for each segmentation. Just double click the label to change name/color. Please note that Slicer did not import the label names out of the DICOM file - at least in my old Slicer version. Screenshot_2

  7. Within the "Segmentations" module you can also create a surface for 3D rendering Screenshot

  8. If you want to get some statistics for the different labels, then please have look into the "Quantitative Reporting" module. Screenshot_3

In conclusion, I don't have dimension issues, each label is stored separately and is editable afterwards with Slicer.

prabathbr commented 11 months ago

I think, the DICOM segmentation file has everything stored correctly and it's probably an visualization issue with the software (ITK-Snap). DICOM segmentations are stored differently then a multi-label 3D-NIfTI file, where each segmentation has its own label value. The disadvantage of multi-label 3D-NIfTI: it cannot handle two different labels for the same voxel. A 4D-NIfTI file could handle that and also the DICOM segmentation files provide that functionality.

The DICOM segmentation file is stored differently then the multi-label 3D-NIfTI file. It's not a 3D file with the same dimensions as the reference, where each label has its own gray value.

I'm no DICOM segmentation expert, but when looking into SegmentSequence (0062,0002), you will spot that each segmentation has its own item including its label (as provided by the JSON file). When looking into PerFrameFunctionalGroupsSequence (5200,9230) you will find a bunch of entries. Each entry is assigned to one of the defined labels (SegmentSequence (0062,0002)). The number of items probably correspond to the amount of planes where a segmentation could be find. So with 10 labels, each defined over 15 planes, you will probably have 150 items within that Tag. So each label is defined separatly and voxelwise probably simply defined as true (binary) or 255. It's then a feature of the DICOM visualization software to display each item with a different color (or whatever). But the labels per se still exist independent of each other in the DICOM segmentation file.

Loading within Slicer was done as following:

1. I rarely use [Slicer](https://www.slicer.org), so I have a pretty old version installed: v4.10.1, whereas v5.6.0 is already available.

2. Slicer has several modules, which provide different functionalities. You will need the DICOM module first.

3. On the Welcome Screen -> Load DICOM Data -> Import: Import your Reference and Segmentation series.

4. Click on the Name in the first table. The second table shows all studies, the third all series to the chosen study. So choose your study and then both series.

5. After I clicked on load, Slicer recommended to install the Extension "Quantitative Reporting", which I did (and also all required extensions).

6. Then you have the reference and the corresponding segmentation loaded. The different segmentations are visualized with the same color. You can change that in the module "Segmentations". In my version, the loaded segmentation has the name "unkown". Choose the "unknown" as active segmenation. Then you can change the color for each segmentation. Just double click the label to change name/color.
   Please note that Slicer did not import the label names out of the DICOM file - at least in my old Slicer version.
   ![Screenshot_2](https://private-user-images.githubusercontent.com/7222167/288376085-1c76e73c-d59a-475a-9c31-eac4480fe1f0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDE5NDU3NDEsIm5iZiI6MTcwMTk0NTQ0MSwicGF0aCI6Ii83MjIyMTY3LzI4ODM3NjA4NS0xYzc2ZTczYy1kNTlhLTQ3NWEtOWMzMS1lYWM0NDgwZmUxZjAucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQUlXTkpZQVg0Q1NWRUg1M0ElMkYyMDIzMTIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyMzEyMDdUMTAzNzIxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OTFlNzBlMWE1NjA0NzAwMmJmNjg0NzQ3OTU1ODczNDIwNDYyOTk0MjFiMGVmYWQ4ZjAyNzBlOWYwMmJmNWRjMSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.QEfXO_sx9JyUgGEzD2S3paCQE21E-XGNt9GNWCH4Qws)

7. Within the "Segmentations" module you can also create a surface for 3D rendering
   ![Screenshot](https://private-user-images.githubusercontent.com/7222167/288373656-ded8369f-8cdf-45bc-91d8-d69768e7cea9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDE5NDU3NDEsIm5iZiI6MTcwMTk0NTQ0MSwicGF0aCI6Ii83MjIyMTY3LzI4ODM3MzY1Ni1kZWQ4MzY5Zi04Y2RmLTQ1YmMtOTFkOC1kNjk3NjhlN2NlYTkucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQUlXTkpZQVg0Q1NWRUg1M0ElMkYyMDIzMTIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyMzEyMDdUMTAzNzIxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDEyOGYwMTViMmVhOTQzYTkzNDUwZmY2NTM1MDNlMzJiNGQ4ODQ2ODk2OTBmMDBhMDBlYzNlZTMyYWI4NjA2OSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.YqfwP5L7wa0rySaK6aHsNU3l8OVzVdBszN9QCOonkhw)

8. If you want to get some statistics for the different labels, then please have look into the "Quantitative Reporting" module.
   ![Screenshot_3](https://private-user-images.githubusercontent.com/7222167/288377961-e4e4c1d6-72ff-4518-998a-c30cc3f4c380.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTEiLCJleHAiOjE3MDE5NDU3NDEsIm5iZiI6MTcwMTk0NTQ0MSwicGF0aCI6Ii83MjIyMTY3LzI4ODM3Nzk2MS1lNGU0YzFkNi03MmZmLTQ1MTgtOTk4YS1jMzBjYzNmNGMzODAucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQUlXTkpZQVg0Q1NWRUg1M0ElMkYyMDIzMTIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyMzEyMDdUMTAzNzIxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmQ2M2EyODZlMTIzZDllZjQxNzJmOTMyNmI0MTliNjlhM2FjMzg5Mzk3MDljY2FiZDk5YjE3MjVhMDZhMjMyZCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.CLJvdOcZ7gWiVRnuHV4InbeZKq051EDENk-yosaKh0s)

In conclusion, I don't have dimension issues, each label is stored separately and is editable afterwards with Slicer.

Thank you very much for the detailed tutorial. I was able to import both DICOM series and segmentation file as mentioned. I am using Slicer 5.2.2 and the segmentation labels were imported correctly with that.

I have an small issue that segmentations are not being registered properly. All of the segmentation including heart, spleen etc are positioned in the leg area. Is there any setting to be used for the proper registration ?