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

Cannot open custom highdicom derived SC DICOM in ITK-Snap #247

Open
tomaroberts opened this issue Aug 7, 2023 · 8 comments
Open

Cannot open custom highdicom derived SC DICOM in ITK-Snap #247

tomaroberts opened this issue Aug 7, 2023 · 8 comments
Assignees
Labels
question Further information is requested

Comments

@tomaroberts
Copy link

Hi – I'm not super familiar with highdicom; this seems like a fairly straightforward problem but I've not managed to find solution to my issue in the docs or existing Issues, so apologies if I've missed it.

I'm basically trying to write a 3D singleframe .dcm dataset following the second code block in the tutorial here. I have no segmentation overlay, so I've removed those parts.

My adapted code snippet is below:

import highdicom as hd
import nibabel as nib
import numpy as np
import os

input_nii_path = r'/path/to/niifile.nii/gz.nii.gz'
output_dcm_path = r'/path/to/output_dcm_folder'
os.mkdir(output_dcm_path)

nii = nib.load(input_nii_path)

# get pixel data from NIfTI
nii_img = nii.get_fdata()
nii_img = nii_img.astype("uint16")  # match DICOM datatype

pixel_spacing = [1.0, 1.0]
sz = nii_img.shape[2]
print(f'nii_img sz: {sz}')

series_instance_uid = hd.UID()
study_instance_uid = hd.UID()

patient_orientation=['L', 'P']

for iz in range(sz):
    this_slice = nii_img[:, :, iz]

    pixel_array = this_slice

    # Create the secondary capture image
    sc_image = hd.sc.SCImage(
        pixel_array=pixel_array.astype(np.uint16),  #originally uint8 in tutorial
        photometric_interpretation=hd.PhotometricInterpretationValues.MONOCHROME2,
        bits_allocated=16,  # originally 8 in tutorial
        coordinate_system=hd.CoordinateSystemNames.PATIENT,
        study_instance_uid=study_instance_uid,
        series_instance_uid=series_instance_uid,
        sop_instance_uid=hd.UID(),
        series_number=100,
        instance_number=iz + 1,
        manufacturer='Manufacturer',
        pixel_spacing=pixel_spacing,
        patient_orientation=patient_orientation,
    )

    sc_image.save_as(os.path.join(output_dcm_path, 'sc_output_' + str(iz) + '.dcm'))

When I try to open this in ITK-Snap, it errors with the following:

image

My input NIFTI dataset is derived from MRI data, hence MONOCHROME2 and BitsAllocation = 16. When I opened the DICOMs in MITKWorkbench, it also failed and indicated an orientation problem, so I tried manually adding ImageOrientationPatient = (e.g.) ['1', '0', '0', '0', '1', '0'] but that has not helped.

Here's a dump of the DICOM metadata:

Dataset.file_meta -------------------------------
(0002, 0000) File Meta Information Group Length  UL: 210
(0002, 0001) File Meta Information Version       OB: b'\x00\x01'
(0002, 0002) Media Storage SOP Class UID         UI: Secondary Capture Image Storage
(0002, 0003) Media Storage SOP Instance UID      UI: 1.2.826.0.1.3680043.10.511.3.40792569118819711334400295680320982
(0002, 0010) Transfer Syntax UID                 UI: Explicit VR Little Endian
(0002, 0012) Implementation Class UID            UI: 1.2.826.0.1.3680043.9.7433.1.1
(0002, 0013) Implementation Version Name         SH: 'highdicom0.21.1'
-------------------------------------------------
(0008, 0008) Image Type                          CS: ['DERIVED', 'SECONDARY', 'OTHER']
(0008, 0016) SOP Class UID                       UI: Secondary Capture Image Storage
(0008, 0018) SOP Instance UID                    UI: 1.2.826.0.1.3680043.10.511.3.40792569118819711334400295680320982
(0008, 0020) Study Date                          DA: None
(0008, 0023) Content Date                        DA: "20230807"
(0008, 0030) Study Time                          TM: None
(0008, 0033) Content Time                        TM: "131553.080334"
(0008, 0050) Accession Number                    SH: None
(0008, 0060) Modality                            CS: 'OT'
(0008, 0064) Conversion Type                     CS: 'DI'
(0008, 0070) Manufacturer                        LO: 'Manufacturer'
(0008, 0090) Referring Physician's Name          PN: None
(0010, 0010) Patient's Name                      PN: None
(0010, 0020) Patient ID                          LO: None
(0010, 0030) Patient's Birth Date                DA: None
(0010, 0040) Patient's Sex                       CS: None
(0018, 1012) Date of Secondary Capture           DA: "20230807"
(0018, 1014) Time of Secondary Capture           TM: "131553.080376"
(0020, 000d) Study Instance UID                  UI: 1.2.826.0.1.3680043.10.511.3.47134193835689979621889364632875485
(0020, 000e) Series Instance UID                 UI: 1.2.826.0.1.3680043.10.511.3.30353553887687175567028695251528949
(0020, 0010) Study ID                            SH: None
(0020, 0011) Series Number                       IS: '100'
(0020, 0013) Instance Number                     IS: '129'
(0020, 0020) Patient Orientation                 CS: ['L', 'P']
(0020, 0035) Image Orientation                   DS: [1, 0, 0, 0, 1, 0]
(0028, 0002) Samples per Pixel                   US: 1
(0028, 0004) Photometric Interpretation          CS: 'MONOCHROME2'
(0028, 0010) Rows                                US: 146
(0028, 0011) Columns                             US: 146
(0028, 0030) Pixel Spacing                       DS: [1.0, 1.0]
(0028, 0100) Bits Allocated                      US: 16
(0028, 0101) Bits Stored                         US: 16
(0028, 0102) High Bit                            US: 15
(0028, 0103) Pixel Representation                US: 0
(7fe0, 0010) Pixel Data                          OW: Array of 42632 elements

Thanks in advance.

@tomaroberts tomaroberts changed the title Cannot open custom highdicom SC DICOM in ITK-Snap Cannot open custom highdicom derived SC DICOM in ITK-Snap Aug 7, 2023
@CPBridge
Copy link
Collaborator

CPBridge commented Aug 7, 2023

Hi @tomaroberts . There are no obvious problems with your code. I imagine that this is a problem with Itk-snap. Note that secondary captures are not really intended for recording 3D images in this way. Consequently they lack the spatial metadata expected by software to correctly create a 3D volume from a series of files. Specifically they do not have the ImageOrientationPatient (as you mentioned) and ImagePositionPatient attributes. You can just add these after creating the objects if you like (and make sure that the image position patient attributes varies between slices in the way implied by the image orientation patient). I suspect that this may allow ITK snap to display the volume correctly. But note that this is not compliant with the DICOM standard, it's a hack.

Other suggestions would be to run a validator such as dciodvfy on your files just to make sure that there are no issues with them.

@CPBridge CPBridge self-assigned this Aug 7, 2023
@CPBridge CPBridge added the question Further information is requested label Aug 7, 2023
@tomaroberts
Copy link
Author

@CPBridge – Thanks for the reply, much appreciated.

I've not seen dciodvfy before, I'll check it out, thanks.

Can I ask, are the SC DICOMs produced by highdicom compatible with commercial clinical information systems such as SECTRAPACS, scanner software, etc? Or do they need further coding on top of the tutorial examples? In my experience, it's one thing getting DICOMs to open in open-source software such as ITK-Snap, etc., but then there is another layer of complexity to surmount when it comes to full clinical systems.

Are there any example highdicom generated SC DICOMs which are known to open in PACS, etc? Or other imaging DICOM types – i.e., not just SC.

Cheers

@pieper
Copy link
Member

pieper commented Aug 7, 2023

Note that there's some disagreement about whether secondary captures with geometry information should be supported (see this issue and comments: InsightSoftwareConsortium/ITK#4109). In summary, two noted DICOM experts disagree, so GDCM, which is the default DICOM reader will not read the image position and orientation from SC but other systems (e.g. DCMTK and ultimately ITK and Slicer likely will; pydicom reads the tags but of course doesn't make direct use of them). I'll leave it to you @CPBridge, @hackermd and others how highdicom should behave.

@tomaroberts you may find this helpful: https://dicom4qi.readthedocs.io/en/latest/

Also note that clinical systems vary WIDELY in what they will or won't accept, so your only sure course is to experiment. Start with something they can read, then reverse engineer until your code works. Often the fallback is to pretend your SC is a CT or something.

@tomaroberts
Copy link
Author

Thanks @pieper – yep, reverse engineering is my approach to making DICOMs for clinical systems. Sigh. But good to know I'm not the only one.

When you say pretend the SC is a CT or something – do you mean create an SC and then set the Modality, etc. to CT, or... just use a CT DICOM and go from there to begin with? I'm not very familiar with SC, so tend to do the latter myself.

@pieper
Copy link
Member

pieper commented Aug 7, 2023

It's hard to say for sure what will work best for any given scenario, but for reference, two very experienced ITK developers (Jim Miller and Bill Lorensen from GE) created this module for Slicer (https://slicer.readthedocs.io/en/latest/user_guide/modules/createdicomseries.html) by adding all the tags they needed to make the results work with their Advantage Windows system at the time (early 2000s). By default it treated any ITK image data as a CT and it was enough to make it show up on the clinical system. I don't recall if they tried and rejected SC or just used CT because that's what data they were working with at the time. Setting the Modality of a derived image to match the input is more "correct" but maybe not strictly needed depending on your use case.

@CPBridge
Copy link
Collaborator

CPBridge commented Aug 7, 2023

While @pieper is definitely right that it can often be a bit of a guessing game getting things to work in clinical systems, I have to say my experience with secondary captures (including those produced by highdicom) is that they are generally very well supported by most "simple" radiology DICOM-first viewers (i.e. those focused on clinical radiology workflows rather than medical image computing and 3D imaging research workflows). I would bet you would be able to view your images in something like Osirix/Horos or weasis. This is because secondary captures are old, simple and widely used. Most "simple" DICOM viewers will simply try to order the images by instance number and not worry about the spatial metadata (unless of course you try to use some sort of MPR functionality).

By contrast things like Slicer, ITK-Snap etc tend to try and always make series into volumes (which cannot be done in this case) because they are fundamentally more advanced 3D viewers. Though of course @pieper knows much more about the specifics here.

@pieper
Copy link
Member

pieper commented Aug 7, 2023

I agree with @CPBridge that making an SC that shows up correctly in a simple dicom viewer as a 2D image is very robust and has been around for ages. It's the 3D part that is a bit controversial and may not work well and may require experimentation.

thewtex added a commit to thewtex/ITK that referenced this issue Mar 18, 2024
This enables support for reading image orientation patient and image
position patient from DICOM secondary capture images.

This addresses needs such as reading Visibla Human DICOM color images in
3D Slicer:

  NA-MIC/ProjectWeek#875

and reading highdicom derived secondary capture DICOM in ITK-Snap:

  ImagingDataCommons/highdicom#247

The required patch has not yet been merged upstream:

  malaterre/GDCM#167

but is available in ITK-vendored GDCM, so condition enablement on
NOT ITK_USE_SYSTEM_GDCM and provide a warning and pointer on where to
find the patches for package managers and other redistributors that also
the support.
thewtex added a commit to thewtex/ITK that referenced this issue Mar 25, 2024
This enables support for reading image orientation patient and image
position patient from DICOM secondary capture images.

This addresses needs such as reading Visible Human DICOM color images in
3D Slicer:

  NA-MIC/ProjectWeek#875

and reading highdicom derived secondary capture DICOM in ITK-Snap:

  ImagingDataCommons/highdicom#247

Update the RGB tests' baseline that were using a .png baseline because they now
output spatial metadata.
@thewtex
Copy link

thewtex commented Apr 22, 2024

This was addressed in ITK (see InsightSoftwareConsortium/ITK#4521 and related).

@jcfr @pieper may know when it will land in 3D Slicer.

@jilei-hao @pyushkevich may know when it will land in ITK-SNAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants