qurit / rt-utils

A minimal Python library to facilitate the creation and manipulation of DICOM RTStructs.
MIT License
191 stars 56 forks source link

RTStruct FrameOfReferenceUID is not matching with the reference CT #29

Closed jinkoo2 closed 1 year ago

jinkoo2 commented 3 years ago

Hi my code is simple, like below. It runs fine, but I see the FrameOfRefernceUID in the output file (RS.new.dcm) is difference from the FrameOfRefceUID of the reference CT dicom series. So, I cannot import the RS file to my application. Is this a bug?... any suggestion would be greatly appreciated. Thanks! Jay.

from rt_utils import RTStructBuilder
import numpy as np
import SimpleITK as sitk
from os.path import join

ct_path = 'U:\\temp\\New folder\\ct_dicom'
mask_mhd = '.\\data1\\00001500\Rectum.mhd'
out_rs_path = 'U:\\temp\\New folder\\RS.new.dcm'

# read segmentation image
mask_img = sitk.ReadImage(mask_mhd)

# convert to np array
mask_np = sitk.GetArrayFromImage(mask_img)

# reorder from z,y,x->y,x,z (donno why... but this worked ok for my application)
new_shape = (mask_np.shape[2], mask_np.shape[1], mask_np.shape[0])
mask_np_trans = np.empty(new_shape, dtype=bool)
for k in range(mask_np.shape[0]):
    for j in range(mask_np.shape[1]):
        for i in range(mask_np.shape[2]):
            mask_np_trans[i,j,k] = bool(mask_np[k,j,i])

# create new RT Struct. 
rtstruct = RTStructBuilder.create_new(dicom_series_path=ct_path)

# add mask
rtstruct.add_roi(
  mask=mask_np_trans, 
  color=[255, 0, 255], 
  name="Rectum"
)

#save
rtstruct.save(out_rs_path)
print('done')
jinkoo2 commented 3 years ago

Changing the first code block to the following made my code start working... code repo not updated at github... donno how...

From

def add_refd_frame_of_ref_sequence(ds: FileDataset, series_data):
    refd_frame_of_ref = Dataset()
    refd_frame_of_ref.FrameOfReferenceUID = generate_uid() # TODO Find out if random generation is ok
    refd_frame_of_ref.RTReferencedStudySequence = create_frame_of_ref_study_sequence(series_data)
    ...

To

def add_refd_frame_of_ref_sequence(ds: FileDataset, series_data):
    refd_frame_of_ref = Dataset()
    refd_frame_of_ref.FrameOfReferenceUID =  getattr(series_data[0], 'FrameOfReferenceUID', generate_uid())
    refd_frame_of_ref.RTReferencedStudySequence = create_frame_of_ref_study_sequence(series_data)
    ...
asim-shrestha commented 3 years ago

Hi Jinkoo, when we first created this library, we made the assumption that any ROI's added would be contained within a new FrameOfReferenceUID, not an existing one. I'm thinking as a fix, we could add another parameter to the RTStruct builder in order for users to input a their own frame of reference uid. Otherwise, it would just create a new one. What do you think?

jinkoo2 commented 3 years ago

An ROI created based on an image would normally share the same FOR of the base image. I modified the code already for my application, so I am good. I am not quite familiar with Git, so I didn't publish it, but I believe I made a post re: what & where I modified. Thank you.

On Wed, Aug 25, 2021 at 11:03 PM Asim Shrestha @.***> wrote:

Hi Jinkoo, when we first created this library, we made the assumption that any ROI's added would be contained within a new FrameOfReferenceUID, not an existing one. I'm thinking as a fix, we could add another parameter to the RTStruct builder in order for users to input a their own frame of reference uid. Otherwise, it would just create a new one. What do you think?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/qurit/rt-utils/issues/29#issuecomment-906054646, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACJP72GKZBBUP2QETBOJOSDT6WVHXANCNFSM5COQCGIQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

locastre commented 2 years ago

I'm writing to second the opinion of the OP. In our experience, when an RTSTRUCT is created it needs to be associated with a "parent" DICOM image set. It is customary, and multiple image viewing platforms rely on the convention, that the RTSTRUCT will have the same FrameOfReferenceUID as the parent DICOM series the contours are to be displayed over.

xfuren commented 2 years ago

This commit solved my problem, too. Please merge it into main. Is there any reason to use a random FrameOfReferenceUID instead of the real referenced one?

jforthomme commented 1 year ago

I agree with @locastre and @jinkoo2 , this is how CTs and structure sets are usually linked in DICOM. Most treatment planning systems will complain if those 2 tags don't match.

asim-shrestha commented 1 year ago

Thanks for the input folks! Will ensure this gets pushed in later today

jinkoo2 commented 1 year ago

It sounds like a good alternative... Or, by default use the FOR of the base image for the new ROI unless provided. Either way should be okay. Thank you!

On Wed, Aug 25, 2021 at 11:03 PM Asim Shrestha @.***> wrote:

Hi Jinkoo, when we first created this library, we made the assumption that any ROI's added would be contained within a new FrameOfReferenceUID, not an existing one. I'm thinking as a fix, we could add another parameter to the RTStruct builder in order for users to input a their own frame of reference uid. Otherwise, it would just create a new one. What do you think?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/qurit/rt-utils/issues/29#issuecomment-906054646, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACJP72GKZBBUP2QETBOJOSDT6WVHXANCNFSM5COQCGIQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .