qurit / rt-utils Goto Github PK
View Code? Open in Web Editor NEWA minimal Python library to facilitate the creation and manipulation of DICOM RTStructs.
License: MIT License
A minimal Python library to facilitate the creation and manipulation of DICOM RTStructs.
License: MIT License
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.
... or at least make it with logging, so it can be filtered out.
Thanks for a wonderful library!
Mathis
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
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)`
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
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:
@carluri Feel free to add anything you feel is missing.
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
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
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?
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
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!
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?
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
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.
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
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
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
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
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!
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?
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.
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.
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
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. :)
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
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.
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)
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.
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
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?
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
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.
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'
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')
Sometime we have not-so-standard DICOM files....
Suggestion...
ds = dcmread(os.path.join(root, file),force=True)
if hasattr(ds, 'ImageOrientationPatient'):
series_data.append(ds)
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.
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.
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.
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.
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!
Two small things here:
Path.exsists() && Path.is_file()
Lines 54 to 61 in 26447ff
Hello, everyone.
I want to create a mask with more contour sequences than CT slices, just like the contour sequences of couch. How should I implement it?
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?
RT-Utils should inform the user when the ROI uses a dicom series that has not been referenced in a RT-struct when loading a previously generated rt-struct.
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?
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?
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.