Coder Social home page Coder Social logo

qurit / rt-utils Goto Github PK

View Code? Open in Web Editor NEW
178.0 178.0 56.0 2.37 MB

A minimal Python library to facilitate the creation and manipulation of DICOM RTStructs.

License: MIT License

Python 100.00%
ai binary-masks dicom mask medical-image-processing medical-imaging nuclear-medicine pydicom roi rt-structs rt-utils rtstruct typed

rt-utils's People

Contributors

asim-shrestha avatar awtkns avatar carluri avatar igorhlx avatar joarroba avatar maxencelarose avatar pchlap avatar plesqui avatar qurit-frizi avatar rheg49 avatar smichi23 avatar thomasbudd avatar tomaroberts avatar w0nsh avatar zhack47 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rt-utils's Issues

image(s) that are not contained in input series

Hello, thank you very much for the great package. When running it, I got this error when loading an RT struct:

At line 400: <class 'Exception'>: Loaded RTStruct references image(s) that are not contained in input series data. Problematic image has SOP Instance Id: 1.2.752.37.5.626934496.20190830.24838.6.2067

I understand this is from a check, but what exactly is being checked?

Add DICOM attribute `RTROIInterpretedType` as optional parameter to `add_roi` and `ROIData`

RTROIInterpretedType stores information about the type of the contoured volume. Possible values can be found here: https://dicom.innolitics.com/ciods/rt-structure-set/rt-roi-observations/30060080/300600a4
One should be able to pass this parameter to add_roi so that the desired type of ROI can be passed to ds_helper.create_rtroi_observation(roi_data) within add_roi.

(follow-up issue to #70: after that, the RTStructMerger maybe could be changed to the usage of add_roi instead of just appending ROIContourSequence, StructureSetROISequence, RTROIObservationsSequence from one RTStructure to the other one)

Add ROIs from polygons

Is there a way of adding ROI using polygons rather than masks?

I'm currently converting our ROI annotations to dicomrt. Our annotations are polygon coordinates.

I think it would be straightforward to have a API that accepts polygon as input, although I can convert my polygons into mask and use the existing add_roi API.

I can raise a PR to do this if you are feeling comfortable with it.

'FileDataset' object has no attribute 'SeriesDate'

Hi,

We have come across this error on a few datasets we are using. Including the LCTSC dataset from TCIA: http://doi.org/10.7937/K9/TCIA.2017.3r3fvz08

/usr/local/lib/python3.6/dist-packages/rt_utils/rtstruct_builder.py:22: in create_new
    ds = ds_helper.create_rtstruct_dataset(series_data)
/usr/local/lib/python3.6/dist-packages/rt_utils/ds_helper.py:15: in create_rtstruct_dataset
    add_study_and_series_information(ds, series_data)
/usr/local/lib/python3.6/dist-packages/rt_utils/ds_helper.py:68: in add_study_and_series_information
    ds.SeriesDate = reference_ds.SeriesDate

AttributeError: 'FileDataset' object has no attribute 'SeriesDate'

The problem is our DICOMs don't have the SeriesDate attribute. Is this something any one else has come across? Could we consider adjusting the code only copy over that attribute if it is available? I'd be happy to look at submitting a pull request if this is something you are interested in.

Thanks!
Phil

RTReferencedStudySequence not present in RTSTRUCT dicom file?

Hi,

Because the attribute RTReferencedStudySequence is of type 3 (optional) it can be the case this is omitted in the RTSTRUCT dicom file. Because of this, an error message in validate_rtstruct_series_references.py occurs, when I try to convert the RTSTRUCT contour into a 3D mask in python.

Is this attribute really necessary and can you work around this issue?

Thank you!

How to create mask for tandem and ovoid?

We have tandem and ovoid in the brachytherapy. I have problem in creating a mask for tandem and ovoid using the rtutils. This package successfully load and create an existing RT structure contour as mask for OARs like Bladder, rectum, sigmoid and hrctv. But it gives and error for creating mask for tandem and ovoid. Could anyone help me in figuring out?

Thank you

File type for ML masks

What file type/ format are the masks expected to be in to create the RTStruct files? We're currently trialling a ML auto segmentation solution which outputs anatomical models as separate nii.gz (zipped nifti) files. Do you know if files of this type can be converted into the required format for them to be packaged into an RTStruct file? Thanks.

Not compatible with open-cv < 4.0.0

Hello there!

Great tool. Thank you for making it public :) . I noticed that the tool won't work with open-cv < 4.0.0. In particular, this line: https://github.com/qurit/rt-utils/blob/main/rt_utils/image_helper.py#L90 will return an error because cv.findContours returns a tuple of three elements in open-cv < 4.0.0 (e.g., see -> https://docs.opencv.org/3.4.17/d3/dc0/group__imgproc__shape.html#ga95f5b48d01abc7c2e0732db24689837b for 3.4.17). That behaviour changed in 4.0.0.

I am not sure if there are other backward compatibility issues.

I would suggests updating the requirements file to enforce a version of open-cv >= 4.0.0 (or whichever version the tests were run on) so that if the existing python environment already contains an old version of open-cv, this gets also updated.

My best regards,

P

the possibility of changing one of ROIs volumes.

Hi guys.
I am a medical researcher and working on DICOM files in my current project.
I wonder to know is it possible to be able to uniformly extend or shorten one of ROIs in rt-struct DICOM file?
Uniformly extending or shortening PTV(Planning Target Volume) in rt-struct DICOM file and obtaining the overlap volume between this PTV and surrounding Organ at risks (OAR) lead us to calculate OVH (Overlap Volume Histogram) which is a useful feature feeding machine learning models.

ImplementationClassUID invalid

The ImplementationClassUID (0002, 0012) tag is set to an invalid value.

In this line it is set to PYDICOM_ROOT_UID value defined in pydicom.
This value is just the root of the pydicom's implementation UID and not the full UID("1.2.826.0.1.3680043.8.498."). The full implementation class UID of pydicom is defined in PYDICOM_IMPLEMENTATION_UID ( "1.2.826.0.1.3680043.8.498.1")

Found out that it is invalid while running the DICOM validation tool dciovfy.

Apply limit to decimal places of ContourData DICOM item

Hi there,

Really nice package – great work.

I've been using rt-utils recently to create some RT Struct DICOM files which we would like to open in the Eclipse software platform. The RT Struct writer works and I get the DICOM files, however, when we import them into Eclipse, the logs state that the byte limit on the ContourData DICOM item has been exceeded.

According to the DICOM standard, there is a 16 byte maximum size for DS items (see here for screenshot from NEMA website).

Would it be possible to amend rt-utils so that it caps the number of decimal places on the item?

Edit – realised I was being silly: PR here.

Many thanks.

Make Certain Dataset Fields Optional

Opened from a comment on blog post.

PatientAge is optional information. It seems the utils requires PatientAge.

I have a CT dataset that has no PatientAge. The code would be crashed.

Traceback (most recent call last):
File “convert_nifti_segments_2_dicom.py”, line 6, in
rtstruct = RTStructBuilder.create_new(dicom_series_path=”./chest_CT”)
File “/home/gchen/anaconda3/lib/python3.8/site-packages/rt_utils/rtstruct_builder.py”, line 20, in create_new
ds = ds_helper.create_rtstruct_dataset(series_data)
File “/home/gchen/anaconda3/lib/python3.8/site-packages/rt_utils/ds_helper.py”, line 16, in create_rtstruct_dataset
add_patient_information(ds, series_data)
File “/home/gchen/anaconda3/lib/python3.8/site-packages/rt_utils/ds_helper.py”, line 84, in add_patient_information
ds.PatientAge = reference_ds.PatientAge
File “/home/gchen/anaconda3/lib/python3.8/site-packages/pydicom/dataset.py”, line 835, in __getattr__
return object.__getattribute__(self, name)
AttributeError: ‘FileDataset’ object has no attribute ‘PatientAge’

Is it possible to make PatientAge as an optional?

Sign error in z coordinates of ContourData

Dear Authors,
thanks a lot for making this great library public, it is highly appreciated!
We have encountered a small problem with it: we're using 3d CT images and due to the left-handed coordinate system the z coordinates in the image are negative. However the ROIs created by your library are missing the minus sign. By manually hacking I managed to get it working now, but it would be nice if this could be solved in your code.
Also it would be nice if one could change the ROIGenerationAlgorithm to AUTOMATIC possibly just as an additional argument to add_roi.
Many thanks!
Thomas

suggestion to avoid issue when multiple types of files are in the same folder

Hi rt_Utils authors,

Thanks for a great tool !

I've experienced some problems, when I am running the add_roi function.
I got the following error-message: Mask must have the same number of layers (In the 3rd dimension) as input series. Expected 130, got 129.

The problem arises, because my folder contains both RT structs, CT scans, RT dose and RT plan. The RT dose file do also have a 'pixel_array' attribute.

I changed a line in the function: load_dcm_images_from_path

from
if hasattr(ds, "pixel_array"):
series_data.append(ds)

to
if ds.Modality == 'CT':
series_data.append(ds)

It solved my problem. :)

Creating contour sequences with SOPInstanceUID instead of using the MediaStorageSOPInstanceUID

Hi,

First of all, you did an impressive work on this package!

I simply wanted to ask if there was a specific reason behind building the contour sequence around the MediaStorageSOPInstanceUID.

If not, adding an optional argument in order to switch between MediaStorageSOPInstanceUID and SOPInstanceUID could maybe be useful for users.

To give you additional context, here is small change I had to do in order to be able to add a new contour to an existing RTSTRUCT file with respect to the original structure.

In ds_helper.py

def create_contour_image_sequence(series_data) -> Sequence:
contour_image_sequence = Sequence()

# Add each referenced image
for series in series_data:
    contour_image = Dataset()
    contour_image.ReferencedSOPClassUID = series.file_meta.MediaStorageSOPClassUID
    contour_image.ReferencedSOPInstanceUID = series.file_meta.MediaStorageSOPInstanceUID
    contour_image_sequence.append(contour_image)
return contour_image_sequence

became

def create_contour_image_sequence(series_data) -> Sequence:
contour_image_sequence = Sequence()

# Add each referenced image
for series in series_data:
    contour_image = Dataset()
    contour_image.ReferencedSOPClassUID = series.SOPClassUID
    contour_image.ReferencedSOPInstanceUID = series.SOPInstanceUID
    contour_image_sequence.append(contour_image)
return contour_image_sequence

Thank you again for this amazing work!

AUTOMATIC ROIGenerationAlgorithm

Add another optional parameter to add_roi() in order to set the ROIGenerationAlgorithm. Update the comments and documentation for add_roi() to reflect this change.

path_length

Hi,
I was wondering if there is a potential limit to the length of the path directory used by the RTStrcuctBuilder.create_from() ?

I have created a script which was working well but as I lauched it on a new computer (and adapted the path) it did not work...I had no space or special caractere in my path.

The only solution I have found was to change the path by reducing it a little bit ?

Do you have an explanation ?

Best

Fabien

ROI_number

Hi,
thank you for this tool.

I have some difficulties when adding a new ROI into an existing RTstructure.

In fact, I looked at the code and when adding a new ROI, the ROI_number is set to ds.StructureSetROISequence +1. However, in the RT file I have downloaded from my PACS, ROI_number are not consecutive. For example they are foing from 2 to 17, then 19 and 63. So I have for example 17 initial ROIs, and if I add 2 more ROIs, numbers 18 and 19 are automatically attributed, and this generates a error message when I reimport the RT structure in my PACS because there are two "numbers 19".

I will try to get around the problem but one of my suggestion would be to propose to the user to add (or not) the ROI_number when calling the add_ROI function and at least to specify this problem in your readme file as it was very difficult to understand where was the problem.

Best

Fabien

RTSTRUCT save as

Two small things here:

  • We are opening but never closing the file.
  • Why are we using open? Why not Path.exsists() && Path.is_file()

def save(self, file_path):
try:
open(file_path, 'w')
# Opening worked, we should have a valid file_path
print("Writing file to", file_path)
self.ds.save_as(file_path)
except OSError:
raise Exception(f"Cannot write to file path '{file_path}'")

Not support old version DICOM

No DICOM magic number found, but the file appears to be DICOM without a preamble.
Proceeding without caution.No DICOM magic number found, but the file appears to be DICOM without a preamble.
Proceeding without caution.

solution:
use dcmread force=True, and
`def load_dcm_images_from_path(dicom_series_path: str) -> List[Dataset]:
series_data = []
for root, _, files in os.walk(dicom_series_path):
for file in files:
try:
ds = dcmread(os.path.join(root, file), force=True)
if hasattr(ds, 'PixelData'):
series_data.append(ds)

        except Exception:
            # Not a valid DICOM file
            continue

return series_data`

and delete the validation function
` def create_from(dicom_series_path: str, rt_struct_path: str) -> RTStruct:
"""
Method to load an existing rt struct, given related DICOM series and existing rt struct
"""

    series_data = image_helper.load_sorted_image_series(dicom_series_path)
    ds = dcmread(rt_struct_path)
    # RTStructBuilder.validate_rtstruct(ds)
    # RTStructBuilder.validate_rtstruct_series_references(ds, series_data)

    # TODO create new frame of reference? Right now we assume the last frame of reference created is suitable 
    return RTStruct(series_data, ds)`

add roi to existing structure set

Hi all,

I have two CTs and two structure sets (generated in TPS). I am trying to copy some rois from structutSet1 to structurSet2. The patient is the same, and most of the setting (same CT type, place where CT was taken, ...) just the acquisition date and time differs.

It seems that the append worked, so no error appear and a roi with "name" is added to structurSet2. But when I display the newly added roi, it is just a point and not the structure it should show. It does not matter, which roi I copy, it is always the same point at the same coordinates.

RoiInRTStruct1and2

When I copy the rois from structutSet1 to a new structure set, everything works fine.

Do you have any idea, why this is not working? I also tried to copy a roi from structurSet2 to structurSet2 with a new name. The name is added to structurSet2, but the roi is again a point at the same coordinates, as shown in the image above.

Thanks a lot for your help! Its a great tool by the way

Cheers,
Nadja

RTStruct FrameOfReferenceUID is not matching with the reference CT

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')

get_contour_fill_mask: truncating contour data

Hi there,

It seems perhaps that you're rounding the contour data too early in your code. The contour_data is changed to type 'int' here, before being converted to the pixel coordinates. I think you can just remove .astype(int) as it's converted to 'int32' further on.

This change can make a difference to the resulting mask, please see attached example where I forked the code and applied the change to the fork:

https://colab.research.google.com/drive/1anBcwIGgrGcPDbsyIDrNqgb0H9UZxJhC?usp=sharing

Change from Exception to warning when the rt's ReferencedSOPInstanceUID is different from the CT's SOPInstanceUID

Problem:

Sometimes the CT used by the radiologist for the manual segmentation of ROIs might not be the one put in the final database.
To give a concrete example, one might have an injection CT and one without injection, do the rtstruct on the injected one and put the non-injected one in the database.

Consequence

In this case the CT's SOPInstanceUID is different from thee RT's ReferencedSOPInstanceUID, even though the space is the same.

At lines 78-82, the check made raises an error if these are not identical.

Proposition

It would be great if the user could chose whether this should be a warning or an Exception, through a parameter passed to the RTStructBuilder (like strict_check_SOPInstanceUID=False)

If you think it's a good idea, I will submit a pull request for it.

RTSTRUCT slice interpolation

Dear RT-UTILS authors,

Firstly, thank you for this wonderful and helpful library. It is amazing to use.

I would like to make a feature suggestion. I am not aware of any existing tool for resampling the RTSTRUCT pointsets into a different 3D geometry, which is a nontrivial problem. Existing tools are capable of handling different pixel spacing using workarounds, but not different slice spacing. For example, I could prepare a dummy CT series with different pixel spacing, and pass it to RTStructBuilder.create_from. Similar hacking is possible in Plastimatch using a dummy reference series or image file e.g. Nifti format. However, to get to a different slice spacing, nearest-neighbor interpolation is still required. I believe that a more intelligent way to handle this, starting from the pointsets and not the voxel masks, would be a choice addition to RT-UTILS.

Best regards,
Dylan Hsu, Ph.D
Memorial Sloan-Kettering Cancer Center

issue with saggital MR scans

I have a 3D MR series with 160 dicom files. x, y, z dims for the series are (160, 256, 256). If I've followed the code properly, i think it assumes that image series files are acquired in z direction, is that a correct?

add ability to retrieve ROI names in a case insensitive way

HI,
i'm experiencing problem with low quality ROI labels (written like this: Heart, heart, HEART),
maybe an option to extract case insensitive ROIs could be useful to other also

I have a quick_fix in rtstruct.py:98
if structure_roi.ROIName.casefold() == name.casefold():

maybe a more general option while using ".get_roi__mask_by_name" could be better

'FileDataset' object has no attribute 'SliceLocation'

I have an rt-struct.dcm file by itself, I want to extract a 3D volumetric mask from this. From loading the Rt-struct using dicominfo on MATLAB I can see that it has no SliceLocation attribute. However, it does have ROI contour attributes. All I am trying to do is extract these ROI contours (which are currently stored in Cartesian coordinates) as a mask. Is it possible to do this with rt-utils?

Contour Sequence should be optional.

Hi,

Thank you for this awesome tool!

Contour Sequence is Type 3 (Optional), there's no guarantee it'll be present in a given item in the ROI Contour Sequence. I recently stumbled on AttributeError: 'Dataset' object has no attribute 'ContourSequence' while loading an existing RT Struct contour as a mask.

I think this error should not occur. I managed to fix it and will make a pull request to review my correction.

Best,

Maxence

AttributeError: 'Dataset' object has no attribute 'ContourImageSequence'

Hi,

Thanks for sharing the great package.

I'm using the following code to load RT annotations.

rtstruct = RTStructBuilder.create_from(
  dicom_series_path=r"path to \Export_Case\CT", 
  rt_struct_path=r"path to\lung.dcm"
)
print(rtstruct.get_roi_names())
for name in rtstruct.get_roi_names():
    mask_3d = rtstruct.get_roi_mask_by_name(name).astype(np.uint8)

It can output the roi_names, but encounter the following error

['Lungs 1000 intensity threshold', 'Heart']
Traceback (most recent call last):

  File ".\utils.py", line 40, in <module>
    mask_3d = rtstruct.get_roi_mask_by_name(name).astype(np.uint8)

  File "D:\ProgramData\Anaconda3\lib\site-packages\rt_utils\rtstruct.py", line 113, in get_roi_mask_by_name
    return image_helper.create_series_mask_from_contour_sequence(

  File "D:\ProgramData\Anaconda3\lib\site-packages\rt_utils\image_helper.py", line 246, in create_series_mask_from_contour_sequence
    slice_contour_data = get_slice_contour_data(series_slice, contour_sequence)

  File "D:\ProgramData\Anaconda3\lib\site-packages\rt_utils\image_helper.py", line 259, in get_slice_contour_data
    for contour_image in contour.ContourImageSequence:

  File "D:\ProgramData\Anaconda3\lib\site-packages\pydicom\dataset.py", line 835, in __getattr__
    return object.__getattribute__(self, name)

AttributeError: 'Dataset' object has no attribute 'ContourImageSequence'

How can I fix this problem?
Any comments would be highly appreciated:)

Best regards,
Jun

Support for Hex Colors

We should support hex and rgb colors. We should also maybe have a default list containing mims colors?

@carluri Do you have a list of colors you would like?

Setting value of "Contour Geometric Type".

Very nice RT toolbox you are making! Due to a lack of resources such as this a year ago, i actually ended up writing some RT tools for my hospital department, for transforming mask outputs from DL models, which are also based on cv2 and pydicom. I never found the time to turn them into a well made toolbox for github, so i would love to help you guys expand your toolbox a little instead.

Contour Geometric Type
contour.ContourGeometricType = 'CLOSED_PLANAR' # TODO figure out how to get this value
contour.NumberOfContourPoints = len(contour_data) / 3 # Each point has an x, y, and z value

Setting the geometric value as CLOSED_PLANAR will nearly always work, but i recently had to expand this part myself, as it resulted in a few errors when loading some RTstructs into our image software.
If part of the mask has a lone voxel in a slice, the voxel will be deleted when importing the RTstruct unless the geometric type is set to "POINT".
If only two voxels are connected, they must be set to "OPEN_PLANAR", as the CLOSED_PLANAR value only works for 3+ connected contour points. OPEN_PLANAR is not always supported by image software, so i have had to define cases with two connected voxels as two separate POINT contours.

Allow adding empty ROIs

Dear rt-utils devs,
Does the dicom format allow adding empty ROIs? This would be extremely useful to be able to:
When a template rtstruct is made, our deep learning segmentation model does not always predict something for all labels. Thus, we just need to remember to add them manually later. With the possibility to add empty ROIs this problem is solved and making rt-utils even more useful.

Mathis

Ability to load SPECT image masks

For modalities like PET, its image information spans across multiple files with a 2D image "slice" present in each file. With SPECT images on the other hand, only one file is given containing the entire 3D volume. This poses an issue when loading a 3D SPECT file mask as RT-Utils assumes that the series data is split as a file per slice.

Notes:

  • We can distinguish a SPECT image via its 'NM' modality
  • Instead of each slice containing its own image patient orientation, SPECT images will only have one orientation for the 3D volume. Some interpolation from this original value may be required as we iterate across each slice

@carluri Feel free to add anything you feel is missing.

Switch to using a logger

Rt-utils currently prints a few debug statements. We should instead log these via a logger so that we only need to display them if desired by the user.

tuple issue

Hi rt_Utils authors

Thanks for a great tool !

I had it working fine but made some updates and now I get som format issues ( tuples). I am adding the error message here - hope you can help :)

Skipping empty mask layer
Skipping empty mask layer
Skipping empty mask layer
Skipping empty mask layer
Skipping empty mask layer
Skipping empty mask layer
Traceback (most recent call last):

File "", line 1, in
rtstruct.add_roi(mask=mask_3d_bool, color=json.loads(strct_color1[strnum-1]), name=strct_names1[strnum-1])

File "C:\Users\jeskal\Anaconda3\lib\site-packages\rt_utils\rtstruct.py", line 59, in add_roi
self.ds.ROIContourSequence.append(ds_helper.create_roi_contour(roi_data, self.series_data))

File "C:\Users\jeskal\Anaconda3\lib\site-packages\rt_utils\ds_helper.py", line 144, in create_roi_contour
roi_contour.ContourSequence = create_contour_sequence(roi_data, series_data)

File "C:\Users\jeskal\Anaconda3\lib\site-packages\rt_utils\ds_helper.py", line 157, in create_contour_sequence
contours_coords = get_contours_coords(roi_data, series_data)

File "C:\Users\jeskal\Anaconda3\lib\site-packages\rt_utils\image_helper.py", line 64, in get_contours_coords
contours, _ = find_mask_contours(mask_slice, roi_data.approximate_contours)

File "C:\Users\jeskal\Anaconda3\lib\site-packages\rt_utils\image_helper.py", line 87, in find_mask_contours
contours[i] = [[pos[0][0], pos[0][1]] for pos in contour]

TypeError: 'tuple' object does not support item assignment

Rtstruct Referencing Multiple CT Image Series

Hi,

Thank you for this tool, it really helped me with my work.

Currently I have a single rtstruct file which references to multiple 3D CT Images of different Series.
I am using,
rtstruct.get_roi_mask_by_name(roiname)

By removing the validation check, it works for me, but in most of the sequence I am getting a 3d mask -> 0s.
Do you have any advice for me?

Delete ROI

Hi,

I know there is a function to add a roi to the RT struct (add_roi), but is there also something similar for deleting a roi?

Thanks!

Error accessing one ROI name

Code and error message are shown below. Other ROI name is fine so far. Any help? Thanks.

dicom_dir = f"./dicom/Renamed/Pediatric-CT-SEG-028C9198/"
rt_file = f"{dicom_dir}/Mask/1-1.dcm"
rtstruct = RTStructBuilder.create_from(
    dicom_series_path=dicom_dir+"Image/", 
    rt_struct_path=rt_file
    )
names = rtstruct.get_roi_names()
print(names)
mask_3d = rtstruct.get_roi_mask_by_name("Breast Left")
first_mask_slice = mask_3d[:, :, 1]
plt.imshow(first_mask_slice) # View one slice within the mask
plt.show()
['Adrenal Left', 'Adrenal Right', 'Bladder', 'Breast Left', 'Breast Right', 'Duodenum', 'Esophagus', 'Femoral Head Lef', 'Femoral Head Rig', 'Gall Bladder', 'Gonads', 'Heart', 'Kidney Left', 'Kidney Right', 'Large Intestine', 'Liver', 'Pancreas', 'Prostate', 'Rectum', 'Small Intestine', 'Spinal Canal', 'Spleen', 'Stomach', 'Thymus', 'UteroCervix', 'Lung_L', 'Lung_R', 'Skin', 'Bones']
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
d:\PythonProjects\AI_Segmention_Pediatric_Organ\step0_clean_names.ipynb Cell 9 in <cell line: 9>()
      [7](vscode-notebook-cell:/d%3A/PythonProjects/AI_Segmention_Pediatric_Organ/step0_clean_names.ipynb#X16sZmlsZQ%3D%3D?line=6) names = rtstruct.get_roi_names()
      [8](vscode-notebook-cell:/d%3A/PythonProjects/AI_Segmention_Pediatric_Organ/step0_clean_names.ipynb#X16sZmlsZQ%3D%3D?line=7) print(names)
----> [9](vscode-notebook-cell:/d%3A/PythonProjects/AI_Segmention_Pediatric_Organ/step0_clean_names.ipynb#X16sZmlsZQ%3D%3D?line=8) mask_3d = rtstruct.get_roi_mask_by_name("Breast Left")
     [10](vscode-notebook-cell:/d%3A/PythonProjects/AI_Segmention_Pediatric_Organ/step0_clean_names.ipynb#X16sZmlsZQ%3D%3D?line=9) first_mask_slice = mask_3d[:, :, 1]
     [11](vscode-notebook-cell:/d%3A/PythonProjects/AI_Segmention_Pediatric_Organ/step0_clean_names.ipynb#X16sZmlsZQ%3D%3D?line=10) plt.imshow(first_mask_slice) # View one slice within the mask

File d:\python38\lib\site-packages\rt_utils\rtstruct.py:110, in RTStruct.get_roi_mask_by_name(self, name)
    108 for structure_roi in self.ds.StructureSetROISequence:
    109     if structure_roi.ROIName == name:
--> 110         contour_sequence = ds_helper.get_contour_sequence_by_roi_number(
    111             self.ds, structure_roi.ROINumber
    112         )
    113         return image_helper.create_series_mask_from_contour_sequence(
    114             self.series_data, contour_sequence
    115         )
    117 raise RTStruct.ROIException(f"ROI of name `{name}` does not exist in RTStruct")

File d:\python38\lib\site-packages\rt_utils\ds_helper.py:221, in get_contour_sequence_by_roi_number(ds, roi_number)
    217 for roi_contour in ds.ROIContourSequence:
    218 
    219     # Ensure same type
    220     if str(roi_contour.ReferencedROINumber) == str(roi_number):
--> 221         return roi_contour.ContourSequence
    223 raise Exception(f"Referenced ROI number '{roi_number}' not found")

File d:\python38\lib\site-packages\pydicom\dataset.py:834, in Dataset.__getattr__(self, name)
    832     return {}
    833 # Try the base class attribute getter (fix for issue 332)
--> 834 return object.__getattribute__(self, name)

AttributeError: 'Dataset' object has no attribute 'ContourSequence'

pydicom 2.1.2 requirement

I've been running rt-utils with the latest pydicom for a few months now. I've had no issues. I've also run your tests with pydicom 2.3; no issues either. Maybe the requirement can be updated to allow later versions of pydicom?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.