platipy
platipy copied to clipboard
Adding multiple DICOM structure files to a single CT visualisation
Good afternoon,
I am trying to add 2 different contours in same CT image. I have 2 different RTstructure files (.dcm) which were converted to nifti using convert_rtstruct. I can successfully load and visualise only 1 set of contours in a image while I was not able to add other set of contours.
This is the minimal reproducible example of code used (Python):
import platipy
import pydicom
import numpy as np
import SimpleITK as sitk
import matplotlib.pyplot as plt
import sys
import glob
import pathlib
from platipy.imaging import ImageVisualiser
from platipy.dicom.io.rtstruct_to_nifti import read_dicom_struct_file
from platipy.dicom.io.rtstruct_to_nifti import convert_rtstruct
from platipy.dicom.io.rtstruct_to_nifti import read_dicom_image
from pathlib import Path
import pathlib
import shutil
import urllib.request
zip_url = "https://github.com/RadiotherapyAI/test-data-public/releases/download/deepmind-dicom/0522c0768.zip"
zip_filepath = "data.zip"
data_directory = pathlib.Path("data")
if not data_directory.exists():
urllib.request.urlretrieve(zip_url, zip_filepath)
shutil.unpack_archive(zip_filepath, data_directory)
#Reading CT images
READctimages = read_dicom_image ("C:\\Python\\Practice files\\data\\0522c0768\\")
#Reading RT structure images
READcontour_filename= read_dicom_struct_file("C:\\Python\\Practice files\\data\\RS\\RS.dcm")
Contour_conversion = convert_rtstruct("C:\\Python\\Practice files\\data\\0522c0768\\"
,"C:\\Python\\Practice files\\data\\RS\\RS.dcm"
,prefix='Struct_'
, output_dir="C:\\Python\\Practice files\\data\\RS\\"
,spacing=None)
#First structure file set
Struct_list = list(glob.glob("C:\\Python\\Practice files\\data\\RS\\Structs_*.nii.gz"))
contours = {}
for Struct in Struct_list:
_name = Struct.split(".nii.gz")[0].split("Struct_")[-1]
contours[_name] = sitk.ReadImage(Struct)
#Visualisation
image_visualiser = ImageVisualiser(READctimages)
image_visualiser.add_contour(contours,color='red',linewidth=1)
fig = image_visualiser.show()
#Error message
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
c:\Python\Practice files\Simplified example.ipynb Cell 7' in <cell line: 4>()
2 image_visualiser = ImageVisualiser(READctimages)
3 image_visualiser.add_contour(contours,color='red',linewidth=1)
----> 4 fig = image_visualiser.show()
File C:\Python\Python3_9_10\lib\site-packages\platipy\imaging\visualisation\visualiser.py:451, in ImageVisualiser.show(self, interact)
448 # self.interact_adjust_slice()
450 self.__figure.canvas.draw()
--> 451 self._add_legend()
452 self.__figure.set_facecolor("white")
454 return self.__figure
File C:\Python\Python3_9_10\lib\site-packages\platipy\imaging\visualisation\visualiser.py:1613, in ImageVisualiser._add_legend(self)
1610 ax_ax_position = ax_ax.get_position()
1611 x_pos_legend = ax_ax_position.xmax + 0.05
-> 1613 approx_font_scaling = self.__figure_size / (
1614 len(self.__contours) + len(self.__bounding_boxes)
1615 )
1617 plt.figlegend(
1618 loc="center left",
1619 bbox_to_anchor=(x_pos_legend, y_pos_legend),
1620 fontsize=min([10, 16 * approx_font_scaling]),
1621 )
1622 else:
1623 # these is probably only one axis
ZeroDivisionError: division by zero
Can I ask for any advice on this error?
@SimonBiggs might you be able to help me out here?
Thank you very much in advance.
Lastly, I would like to thank Robert Finnegan (@rnfinnegan) and Phil Chlap (@pchlap) for their work in platipy. I am an recent graduate (master of medical physics) who has very limited programming background but platipy helped me a lot in medical image visualisation. It is very highly accessible and easy to use for an individual who has limited programming background. Thank you very much for your works again.
Kind regards
Young woo Kim
Hi @smallkev,
I tried to reproduce your error locally. There was quite a bit I needed to change within your code to make it work on my end. I adjusted your example to look like the following:
import pathlib
import shutil
import tempfile
import urllib.request
import SimpleITK as sitk
import matplotlib.pyplot as plt
from platipy.dicom.io.rtstruct_to_nifti import convert_rtstruct
from platipy.dicom.io.rtstruct_to_nifti import read_dicom_image
from platipy.imaging import ImageVisualiser
def test_font_scaling():
with tempfile.TemporaryDirectory() as temp_dir:
temp_dir = pathlib.Path(temp_dir)
zip_url = (
"https://github.com/RadiotherapyAI/test-data-public/"
"releases/download/deepmind-dicom/0522c0768.zip"
)
zip_filepath = temp_dir / "data.zip"
urllib.request.urlretrieve(zip_url, zip_filepath)
shutil.unpack_archive(zip_filepath, temp_dir)
patient_dir = temp_dir / "0522c0768"
structure_path = patient_dir / "RS.dcm"
ct_images = read_dicom_image(patient_dir)
prefix = "structure_masks_"
convert_rtstruct(
patient_dir,
structure_path,
prefix=prefix,
output_dir=patient_dir,
spacing=None,
)
structure_paths = patient_dir.glob(f"{prefix}*.nii.gz")
contours = {}
for path in structure_paths:
filename = _name_with_all_suffixes_removed(path)
contour_name = filename.removeprefix(prefix)
contours[contour_name] = sitk.ReadImage(str(path))
image_visualiser = ImageVisualiser(ct_images)
image_visualiser.add_contour(contours, color="red", linewidth=1)
fig = image_visualiser.show()
return fig
def _name_with_all_suffixes_removed(path: pathlib.Path):
while path.suffix:
path = path.with_suffix("")
return path.name
if __name__ == "__main__":
_fig = test_font_scaling()
plt.show()
And that above code worked without any issue, and produced a result that looked like the following:
Cheers :slightly_smiling_face:, Simon
Hello!
I am very happy that you find PlatiPy useful.
Thanks for providing a working example, @SimonBiggs!
For some context, it seems like your original code produced an error because there are no contours, i.e. contours
is empty.
When you save the DICOM RT-Structures you use the prefix Struct_
, but when you read them in you use the prefix Structs_
. This would make Struct_list
empty!
Could you check to see if this is the case, for example by adding print("contours is", contours)
?
Let me know if this helps.
Cheers, Rob
Thank you very much for your help, @SimonBiggs.
Kind regards.
Young woo Kim
Hello, Robert Finnegan(@rnfinnegan).
Firstly, thank you very much for your help.
I've checked my original codes by checking the structure list using print("contours is", contours)
.
And I found that one of structure list was empty.
So I've re-read all of my codes again, then I found that the prefix used for conversion and reading the structure files were different.
Now, I can successfully add contours.
Thank you very much for your help.
If it is okay, can I ask one more question?
I've tried to add 2 different sets of contours from 2 different structure files by adding these codes:
image_visualiser.add_contour(contours,color='red',linewidth=1)
image_visualiser.add_contour(contourss,color='green',linewidth=0.5)
fig = image_visualiser.show()
But it only shows 1 set of contour (contourss, green) in the image.
Can I add 2 different sets of contours in same image at once?
Thank you very much.
Kind regards.
Young woo Kim
Can I add 2 different sets of contours in same image at once?
Hi @smallkev,
I might be wrong about this, but without actually testing it myself I suspect the following approach might bring you some success.
At the end of the day, you want more contours by making this contours
dictionary have more items in it:
https://github.com/pyplati/platipy/blob/3f778df2ee825441933aa95a80f428e336157d48/platipy/imaging/visualisation/tests/test_use_case.py#L61-L66
This could be achieved by repeating the following section of code for each structure file, except, each time, use a different prefix:
https://github.com/pyplati/platipy/blob/3f778df2ee825441933aa95a80f428e336157d48/platipy/imaging/visualisation/tests/test_use_case.py#L49-L57
And then, when collecting the contour files allow for searching through all prefixes. Do this by changing this line: https://github.com/pyplati/platipy/blob/3f778df2ee825441933aa95a80f428e336157d48/platipy/imaging/visualisation/tests/test_use_case.py#L59
to say:
structure_paths = patient_dir.glob("*.nii.gz")
And removing the following line entirely:
https://github.com/pyplati/platipy/blob/3f778df2ee825441933aa95a80f428e336157d48/platipy/imaging/visualisation/tests/test_use_case.py#L64
This should then result in each contour displayed including the structure file prefix you have defined, and allowing for multiple files worth of structures to be included.
Thank you very much! @SimonBiggs.
I've just check with my codes and it worked.
Thank you very much again.
Kind regards
Young woo Kim
Thank you very much!
My pleasure :)
Also, as a last step, it might be worth changing the title of this issue to something that is more "Googlable". If you changed it to something like:
Adding multiple DICOM structure files to a single CT visulaisation
Then someone who is Google searching in that vein might land on this thread and also be helped :slightly_smiling_face: