Code Monkey home page Code Monkey logo

dicom_rt_and_images_to_mask's Introduction

We're published! Please check out the Technical Note here: https://www.sciencedirect.com/science/article/abs/pii/S1879850021000485 and reference this work if you find it useful

This code provides functionality for turning dicom images and RT structures into nifti files as well as turning prediction masks back into RT structures

Installation guide

pip install DicomRTTool

Highly recommend to go through the jupyter notebook in the Examples folder and to read the Wiki

Quick use guide

from DicomRTTool.ReaderWriter import DicomReaderWriter, ROIAssociationClass
Dicom_path = r'.some_path_to_dicom'
Dicom_reader = DicomReaderWriter(description='Examples', arg_max=True)
Dicom_reader.walk_through_folders(Dicom_path) # This will parse through all DICOM present in the folder and subfolders
all_rois = Dicom_reader.return_rois(print_rois=True) # Return a list of all rois present

Contour_names = ['tumor'] # Define what rois you want
associations = [ROIAssociationClass('tumor', ['tumor_mr', 'tumor_ct'])] # Any list of roi associations
Dicom_reader.set_contour_names_and_assocations(contour_names=Contour_names, associations=associations)

Dicom_reader.get_images_and_mask()

image_numpy = Dicom_reader.ArrayDicom
mask_numpy = Dicom_reader.mask
image_sitk_handle = Dicom_reader.dicom_handle
mask_sitk_handle = Dicom_reader.annotation_handle

Other interesting additions

Adding information to the Dicom_reader.series_instances_dictionary

from DicomRTTool.ReaderWriter import Tag
plan_pydicom_string_keys = {"MyNamedRTPlan": Tag((0x300a, 0x002))}
image_sitk_string_keys = {"MyPatientName": "0010|0010"}
Dicom_reader = DicomReaderWriter(description='Examples', arg_max=True, plan_pydicom_string_keys=plan_pydicom_string_keys, image_sitk_string_keys=image_sitk_string_keys)
If you find this code useful, please provide a reference to my github page for others www.github.com/brianmanderson , thank you!
Ring update allows for multiple rings to be represented correctly

multiple_rings.png

Works on oblique images for masks and predictions*

dicom_rt_and_images_to_mask's People

Contributors

breber100 avatar brianmanderson avatar evan-porter avatar guatavita avatar kwahid avatar lcmoore 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

Watchers

 avatar  avatar  avatar  avatar

dicom_rt_and_images_to_mask's Issues

Skimage.draw.polygon yields incorrect polygons

The use of skimage.draw.polygon() in RTstruct reconstruction is not recommended because it is inconsistent in inclusion of surface coordinates (see plot below where blue is the RTStruct coordinates and yellow is the filled polygon coordinates). The function cv2.fillpoly() resolves this issue as well as running faster. I can submit the modification in a pull request if desired.

image

Problem with nifti2RTStructure conversion

Hi Brian,

Thank you so much for sharing Dicom-RT-tool
I want to convert my model's prediction mask to RTStructure.
I follow the example you wrote. But my prediction's shape is like the image's shape (e.g. (236, 512, 512)).

So I've got this error:

AssertionError: Your last dimension of prediction array should be equal to the number or ROI_names minus 1, channel 0 is background

What should I do?

I thank you for your consideration.
Best,
Parisa

the output

Hi, the ouput of "Dicom_reader.with_annotations(pred,output_path,ROI_Names=['test'])" is not nii???
there are two "path " in your offered samples....

dose handle issue from version 0.4.2 to version 1.0.0

Hi, thank you for your great work.

I have an issue with the dose data starting version 1.0.0.

code:
Dicom_reader = DicomReaderWriter(description='', arg_max=True, get_dose_output=True)
Dicom_reader.set_contour_names_and_associations(Contour_Names=Contour_Names, associations=associations)
Dicom_reader.walk_through_folders(patient_folder) # need to define in order to use all_roi method

        all_rois = Dicom_reader.return_rois(print_rois=False)  # Return a list of all rois p#esent, and print them
        series = Dicom_reader.series_instances_dictionary  
        indexes = Dicom_reader.which_indexes_have_all_rois() 

        Dicom_reader.set_index(x)  
        Dicom_reader.get_images_and_mask() 
        Dicom_reader.get_dose()  
        
        
        image_handle = Dicom_reader.dicom_handle 
        mask_handle = Dicom_reader.annotation_handle 
        dose_handle = Dicom_reader.dose_handle

I can get the dose data and handle with the version 0.4.2 but not with the versions starting at 1.0.0 (RDs list in the dictionnary is empty )

Cannot turn oblique mask predictions into RT Structures

The problems arises from the fact that I write RT structures on a 'slice by slice' basis, with the referenced slice being constant. When the images are oblique, the 'z' slice value varies across the entire prediction.

I'll need to get a distribution of the z-value for the entire image, not sure what the best way to do that now is..
Line 78 is what needs to be changed

Issue: Index is not present in the dictionary

Hello!

Nice script. I'm trying to use it to make some conversions from DICOM to Nifti, but I'm not able to convert some DICOMs due to the error you find here attached. However, I'm able to open these files even with other viewers (such as slicer).

Do you have any advice how to solve this issue?

Thanks

Compiling dictionaries together...
0 unique series IDs were found. Default is index 0, to change use set_index(index)
AssertionError                            Traceback (most recent call last)
Input In [35], in <cell line: 1>()
      1 for file in alldicomfolder:
      2     print(f"Processing {file}")
----> 3     d2nconvfold(file, output_dir)

Input In [32], in d2nconvfold(xinput, xoutput)
      2 reader = DicomReaderWriter()
      3 reader.walk_through_folders(xinput)
----> 4 reader.get_images()
      6 initial_file = os.path.basename(xinput)
      8 sitk.WriteImage(reader.dicom_handle, xoutput + "/" + initial_file + '_0000.nii.gz')

File ~/opt/anaconda3/envs/amd_gpu/lib/python3.8/site-packages/DicomRTTool/ReaderWriter.py:804, in DicomReaderWriter.get_images(self)
    803 def get_images(self) -> None:
--> 804     assert self.index in self.series_instances_dictionary, \
    805         'Index is not present in the dictionary! Set it using set_index(index)'
    806     index = self.index
    807     series_instance_uid = self.series_instances_dictionary[index]['SeriesInstanceUID']

AssertionError: Index is not present in the dictionary! Set it using set_index(index)

Mask matrix transposed

the mask displayed on the MRI slices flipped diagonally, seems like there is a transpose of the mask matrix.

how to get file with selected segmentations in struct file

hello, tahnk you for your script. I have a question, I need to create a single segmentation file containing single segmentations of the struct file.
For example my struct file has the following segmentations:
Body
CTV
Heart
PTV
lungdx
lungsx
Trachea
lung-PTV
GTV N
GTV T

Now I need to create three files .nrrd, one containing the segmentation GTV N and GTV T, one containing CTV and one PTV.

How can I do it? Thanks!!!

np.unique(mask)

I followed the example of Tutorial you shared.
In Part 1, after following code,

pt_indx = indexes[0]
dcm_reader.set_index(pt_indx) # This index has all the structures, corresponds to pre-RT T1-w image for patient 011
dcm_reader.get_images_and_mask() # Load up the images and mask for the␣ requested index

image = dcm_reader.ArrayDicom # image array
mask = dcm_reader.mask # mask array

I got [0,1,2] for np.unique(mask)

This makes problem when I calculate DSC score...
How can I get just 0 and 1 values for mask??

Indexes with ROIs

Hello,

I just wanted to clarify, does the reading in of the DICOM files (CT and RT) with Dicom_reader.walk_through_folders(DICOM_path) guarantee the order of the indexes ? Meaning are the returned indexes from command Dicom_reader.which_indexes_have_all_rois() correspond to the actual time positioning from the CT acquisition ? Are they basically ordered according to UID and timestamp ?

Why I'm asking is: I have 4DCTs with GTVs marked throughout multiple breathing phases (usually 10 or sometimes more). In our case, breathing phase corresponds to RT file. So we create an association class with gtvs and getting all the indexes with ROIs (our breathing phases). We later on extract for each breathing phase the 3D numpy arrays of the whole chest area (the full available image) and the 3D numpy arrays of the mask (where the GTV/tumor is marked) and we use those 3D numpy arrays for deep learning purposes. So for us it is important, that there is a spatio-temporal relationship between each of these 3D numpy arrays corresponding to a breathing phase. And that is why I'm asking if lets say 1st index returned is actually the first breathing phase (the patient just starts taking a deep breath) and the 2nd index is second breathing phase (patient takes a bit more air in).

Here is what I'm talking about (this gif is created from the arrays extracted and using the order of indexes as I mentioned):

movie

Possible race condition in the `walk_through_folders`

Hi Brian,

Thank you for implementing this useful package. I am reporting a possible race condition observed in the folder parsing method.
My use case is as follows:
I have directories of dicom files of the following structure:
|-patient_name|
|-original_ct_and_rtss
|-derived_ct_and_rtss1
|-derived_ct_and_rtss2
...
where I use your package to generate derived rtstruct files based on the original ct info. The derived ct images were transformed original ct images via ITK. I have found that repeating the folder parsing with the walk_through_folders does not give consistent results (i.e. different number of set of CT-RTss were found in different iterations). After digging deeper into the source code, I think the problem originates from this line, where the dicts (self.images_dictionary, self.rt_dictionary, self.rd_dictionary, self.rp_dictionary) were passed into multiple threads, and the modification on these dictionary were performed in-place.

Have you observed any similar phenomenon? Or My use case here is simply not well supported?
I will try to remove the multi-threading part in the walk_through_folders and give the feedback on the modification.
My Platform is a mac Ventura 13.4.1 with python 3.11.7.
Thank you for your time.

Update: Hi Brian, sorry about the raised issue, it turns out that the question was related to the ct image generation. As the creation time of the CT series was used for the series instance UID. It is possible to have two CT series sharing identical series instance UID. This is Unrelated to the Dicomrttool.

TLDR: This issue is not related to Dicomrttool and may be removed.

RT-Struct to Mask Array Issue

Dear Dr. Anderson,

My name is Elvis Duran, a research scientist in the MSK department at MDACC, and I am currently working with DICOM files in Python.
I have found your DicomRTTool extremely useful to load and process DICOM images and RTStructs exported from the MIM software. However, after loading RT-Struct files exported from the DynaCAD software, I noticed that all pixels had zero value across all slices in the mask generated. I guess there might be an issue with the code when transforming the DynaCAD raw contour file into a mask array, likely due to a different encoding of the metadata.

I would really appreciate if you can let me know what a possible solution could be.
Thank you.

Normalization of Pixel Spacing

Hi your library is super helpful, thank you for your wonderful work.
I hope to rather ask some details on the conversion from dicom files to a single array/tensor object.
Specifically, are the pixel spacing in the DCM file normalized or as is?
I have CT scan with thickness of 3mm but pixel spacing for both row and colum are [0.75mm,0.75mm], I hope to normalize each voxels to 1x1x3 mm.

Thank you.

Issue with some RTStruct data for converting to NumPy Masks

Dear Brianmanderson,
Thank you very for your work.

I am using your script for converting RTStruct data into Numpy Masks but some datasets its giving error "Dataset' object has no attribute 'ContourSequence".

Note: Its working fine with the "Example data" which I downloaded from your repo link.

Kindly let me know what I am missing here and please guide me to solve these issues.

Issue 1:
Dataset' object has no attribute 'ContourSequence' with below ROIs
("brai" , "spinal canal")

Issue 2: Below issue with different RTStruct data.

Dicom_reader.get_images_and_mask()
File "C:\Dicom_RT_and_Images_to_Mask\src\DicomRTTool\ReaderWriter.py", line 964, in get_images_and_mask
self.get_mask()
File "C:\Dicom_RT_and_Images_to_Mask\src\DicomRTTool\ReaderWriter.py", line 1113, in get_mask
mask = self.contours_to_mask(structure_index)
File "C:\Dicom_RT_and_Images_to_Mask\src\DicomRTTool\ReaderWriter.py", line 1206, in contours_to_mask
matrix_points = self.reshape_contour_data(Contour_data[i].ContourData[:])
File "C:\Dicom_RT_and_Images_to_Mask\src\DicomRTTool\ReaderWriter.py", line 1141, in reshape_contour_data
matrix_points = np.asarray([self.dicom_handle.TransformPhysicalPointToIndex(as_array[i])
File "C:\Dicom_RT_and_Images_to_Mask\src\DicomRTTool\ReaderWriter.py", line 1141, in
matrix_points = np.asarray([self.dicom_handle.TransformPhysicalPointToIndex(as_array[i])
File "C:\Python\Python38\lib\site-packages\SimpleITK\SimpleITK.py", line 3242, in TransformPhysicalPointToIndex
return _SimpleITK.Image_TransformPhysicalPointToIndex(self, point)
TypeError: in method 'Image_TransformPhysicalPointToIndex', argument 2 of type 'std::vector< double,std::allocator< double > > const &'

Thank you

AttributeError: 'DicomReaderWriter' object has no attribute 'dicom_names

Dicom slices and The RTStruct.dcm are in the Same folder, I get this error :

/usr/local/lib/python3.6/dist-packages/DicomRTTool.py in Contours_to_mask(self, index)
397
398 def Contours_to_mask(self, index):
--> 399 mask = np.zeros([len(self.dicom_names), self.image_size_rows, self.image_size_cols], dtype='int8')
400 Contour_data = self.RS_struct.ROIContourSequence[index].ContourSequence
401 for i in range(len(Contour_data)):

AttributeError: 'DicomReaderWriter' object has no attribute 'dicom_names

writing multiple predictions in the same RT struct file

Hi Brian, not a bug just a question. I didn't find an option to post questions in the wiki.

Is it possible to write the predictions of 2 models in the same RT struct file?

Something like :

Dicom_reader.prediction_array_to_RT(prediction_array=Mask1_save, output_dir=path
                                     ,ROI_Names=['PTV1', 'PTV2'])
Dicom_reader.prediction_array_to_RT(prediction_array=Mask2_save, output_dir=path
                                     ,ROI_Names=['GTV1', 'GTV2'])

Using the code i get 2 RT struct files.

Numpy deprecation causing issue

Hi Brian, I've run into an issue with your library. It was working fine for awhile, but numpy has recently updated and deprecated the np.bool type in favor of np.bool_. In the poly2mask method, it currently is using the np.bool which throws a combination of Attribute and Key errors at the return statement. I downloaded the source and made the modification locally. That seemed to do the trick and the masks are now available without errors.

If it helps, I'm using numpy 1.24.1. The requirements for this library don't specify a version number.

Reference to numpy docs

Does this only work on linux? Why do I get errors when I pip install DicomRTTool on Windows?

This is the wrong content.

E:\Desktop\pyDemo\pythonProject>pip install DicomRTTool
Defaulting to user installation because normal site-packages is not writeable
Collecting DicomRTTool
  Using cached DicomRTTool-2.1.3-py3-none-any.whl.metadata (3.5 kB)
Collecting numpy~=1.22.3 (from DicomRTTool)
  Using cached numpy-1.22.4.zip (11.5 MB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
ERROR: Exception:
Traceback (most recent call last):
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\cli\base_command.py", line 180, in exc_logging_wrapper
    status = run_func(*args)
             ^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\cli\req_command.py", line 245, in wrapper
    return func(self, options, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\commands\install.py", line 377, in run
    requirement_set = resolver.resolve(
                      ^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\resolver.py", line 95, in resolve
    result = self._result = resolver.resolve(
                            ^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\resolvers.py", line 546, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\resolvers.py", line 427, in resolve
    failure_causes = self._attempt_to_pin_criterion(name)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\resolvers.py", line 239, in _attempt_to_pin_criterion
    criteria = self._get_updated_criteria(candidate)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\resolvers.py", line 230, in _get_updated_criteria
    self._add_to_criteria(criteria, requirement, parent=candidate)
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\resolvers.py", line 173, in _add_to_criteria
    if not criterion.candidates:
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\resolvelib\structs.py", line 156, in __bool__
    return bool(self._sequence)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 155, in __bool__
    return any(self)
           ^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 143, in <genexpr>
    return (c for c in iterator if id(c) not in self._incompatible_ids)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 47, in _iter_built
    candidate = func()
                ^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\factory.py", line 182, in _make_candidate_from_link
    base: Optional[BaseCandidate] = self._make_base_candidate_from_link(
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\factory.py", line 228, in _make_base_candidate_from_link
    self._link_candidate_cache[link] = LinkCandidate(
                                       ^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 290, in __init__
    super().__init__(
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 156, in __init__
    self.dist = self._prepare()
                ^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 222, in _prepare
    dist = self._prepare_distribution()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 301, in _prepare_distribution
    return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\operations\prepare.py", line 525, in prepare_linked_requirement
    return self._prepare_linked_requirement(req, parallel_builds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\operations\prepare.py", line 640, in _prepare_linked_requirement
    dist = _get_prepared_distribution(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\operations\prepare.py", line 71, in _get_prepared_distribution
    abstract_dist.prepare_distribution_metadata(
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\distributions\sdist.py", line 54, in prepare_distribution_metadata
    self._install_build_reqs(finder)
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\distributions\sdist.py", line 124, in _install_build_reqs
    build_reqs = self._get_build_requires_wheel()
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\distributions\sdist.py", line 101, in _get_build_requires_wheel
    return backend.get_requires_for_build_wheel()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_internal\utils\misc.py", line 745, in get_requires_for_build_wheel
    return super().get_requires_for_build_wheel(config_settings=cs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\pyproject_hooks\_impl.py", line 166, in get_requires_for_build_wheel
    return self._call_hook('get_requires_for_build_wheel', {
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\pyproject_hooks\_impl.py", line 321, in _call_hook
    raise BackendUnavailable(data.get('traceback', ''))
pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
  File "C:\Users\kris\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 77, in _build_backend
    obj = import_module(mod_path)
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.12_3.12.752.0_x64__qbz5n2kfra8p0\Lib\importlib\__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "C:\Users\kris\AppData\Local\Temp\pip-build-env-pixxi3si\overlay\Lib\site-packages\setuptools\__init__.py", line 10, in <module>
    import distutils.core
ModuleNotFoundError: No module named 'distutils'

Image Orientations

I’m currently working with T2 MRI sequences, and I’ve noticed for multiple patients if the images were acquired in non-standard image orientations, i.e. DICOM tag (0020, 0037) != [1\0\0\0\1\0], the contour masks don’t really match up with the images. This isn’t a huge problem for most data from big centers, but for some outside imaging this can be an issue. I’ve checked this for multiple patients now and it seems to be a recurring problem.

Write output for multiple RS associated with single CT

Hi Brian! Thank you for sharing this fantastic tool.

When using the write_parallel function, Is it possible to write out multiple RS masks to .nii.gz files and corresponding excel file? My data folders contain the CT scan and 2 RS files (clinical_1, clinical_2) in the same folder as the CT scan.

Dicom_reader has no problem identifying and adding the different RS files to the dictionaries, but when writing out using the write_parallel function, it seems only to write out the masks for a single RS file. I tried to quickly implement a write_parallel_mult calling the get_images_and_mask_mult function, but I think I'm missing something.

Any help would be greatly appreciated.

Best Regards,
Rafe

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.