RT Structure Set conversions to binary label maps - SlicerRT vs plastimatch
Closed this issue · 29 comments
Hi,
I am trying to batch convert many RT Structure Sets to binary label maps (NRRD format). Using the Slicer
GUI and the SlicerRT
extension, I seem to be able to load in the RTSS and then using the Segmentations module in Slicer
I can export to a label map and also specify a reference volume (DICOM series) so that the label map has the same geometry as the original CT image.
After saving the mask, when I clear the scene in Slicer
and then load the NRRD mask back in, I can verify in the Volumes module that the dimensions (512 512 275), spacing (0.78 0.78 1.00), and origin line up with the reference volume. This is great.
However, doing this interactively is not very efficient for how many conversions I need to perform. I tried to use plastimatch
from the command-line so that I could eventually wrap it into a shell script for batch conversions. Here is how I have been using plastimatch
...
plastimatch convert --input structure.dcm --output-labelmap mask.nrrd --referenced-ct /path/to/dicom/series
However, the resulting binary mask does NOT seem to have the geometry of the reference volume. Here is the plastimatch
output to the shell...
Loading RDD
Loading RDD complete
Found RTSTUCT, UID=1.3.12.2.1107.5.8.15.130095.30000019050309482349500000100
Found DCM_ReferencedFrameOfReferenceSequence!
Found DCM_RTReferencedStudySequence!
Trying to load rt structure set.
Adding structure (1), L1GTV1
Structure 1 has color 245\60\25
PIH is:
Origin = -65.9414 121.3711 -528.8000
Size = 512 512 18
Spacing = 0.0401 0.0401 1.0000
Direction = 1.0000 0.0000 0.0000 0.0000 1.0000 0.0000 0.0000 0.0000 1.0000
Rt_study_warp: Convert ss_img to cxt.
Rt_study_warp: Apply dicom_dir.
Rt_study_warp: Set geometry from PIH.
Rt_study_warp: Set rasterization geometry.
rast_dim = 512 512 18
rast_offset = -65.9414 121.371 -528.8
rast_spacing = 0.0400543 0.0400543 1
Rt_study_warp: warp and save ss.
Warp_and_save_ss: seg->rasterize
Rasterizing...
Converting...
Finished rasterization.
Warp_and_save_ss: save_ss_img
save_ss_img: save_labelmap
Trying to write image to mask.nrrd
Finished!
As with before, when I load this NRRD mask (mask.nrrd) into Slicer, the Volumes module shows that the dimensions (512 512 18) and spacing (0.04 0.04 1.00) are not the same as the reference image. Any idea why there is this discrepancy between the Slicer
conversion and the plastimatch
conversion? Am I doing something wrong?
Thanks for your help.
Have you tried this?
https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing
We developed this just for this purpose.
@cpinter Thanks for sharing. I will give this a shot and report back.
Still interested in why plastimatch
isn't doing what I was hoping. I was under the impression plastimatch
was part of the SlicerRT extension, so I expected to achieve equivalent results.
SlicerRT relies on Plastimatch but it is its own library:
http://plastimatch.org/
https://gitlab.com/plastimatch/plastimatch/issues
@gregsharp
@cpinter Thanks. I did post this issue over on gitlab, but it didn't appear to be too active, so I decided to cross-post it over here as I thought the issue overlapped both libraries.
I am going to try your batch conversion script shortly and I can report back with my experiences.
@cpinter The _readme.txt file indicates that the CT image needs to located in the input folder alongside the RTSS. What format can the reference volume be in? Will a directory containing a DICOM series be a valid reference volume?
Yes, I believe that it actually expects DICOM
@cpinter So I am not sure if I have been able to get the batch conversion script working entirely. Slicer seems to error-out without any informative errors so it isn't obvious what the issue is, if there is one.
I have a directory called input which contains the RTSS file and also a directory which recursively leads to a DICOM series. I have another empty directory called output for returning the NRRD mask.
The code looks as follows:
C:/'Program Files'/'Slicer 4.10.1'/Slicer.exe --no-main-window --python-script path/to/BatchStructureSetConversion.py --input-folder /path/to/inputs --output-folder /path/to/outputs
A few of the Slicer progress bars pop up and disappear before Slicer produces this error:
error: [C:/Program Files/Slicer 4.10.1/bin/SlicerApp-real.exe] exit abnormally - Report the problem.
A .nrrd file is in the output folder and I can load it into Slicer GUI and it actually looks mostly correct. The Volumes module has the expected spacing, however, the dimensions of the mask [27 27 21] are not the same as the reference volume supplied [512 512 275]. Is this expected? Should the dimensions be the same as the reference DICOM series?
EDIT: Using Slicer, I was also able to properly superimpose the label map (.nrrd) output from the batch conversion python script onto the DICOM series. It looks fine.
It is possible that the CT is not used as reference volume. Such an option wouldn't be hard to add. I'll look into it when I have time.
Can you check the log file for some clue about the crash? If you start Slicer and go to About / Report an error, then you can find the 10 last logs.
@cpinter Sorry for taking so long to return to this issue. Here is a print-out of the error log from Slicer:
Same as before, the label map has the expected spacing, but the dimensions are not the same as the input. I'm not sure if the dimensions should be the same or not. I guess it depends on if the script uses the CT as a reference volume in that way.
What should be contained in the input directory? Right now I have the RTSS file, and a directory containing the CT series. Seems like the CT series is being ignored.
The screenshot shows a fresh Slicer log just after starting. I'd need the one from the time it crashed. If you start Slicer and go to About / Report an error, then you can find the 10 last logs. Thanks!
@cpinter Matt and I figured out the problem with plastimatch, which is that it does not search recursive subdirectories for the reference CT. But SlicerRT should not have that problem, since the CT is loaded by Slicer.
Regarding the labelmap size. isn't the issue that the created labelmap is minimally sized to contain the structure, and padding zeros are not included?
Regarding the labelmap size. isn't the issue that the created labelmap is minimally sized to contain the structure, and padding zeros are not included?
@gregsharp I agree, this seems like the most logical reason for the difference in dimensions. If it is expected that the RTSS is converted to a labelmap with its size as a minimal bounding box containing the ROI, then perhaps the script is working as anticipated.
Notes:
* The CT (or other anatomical) volume of the study needs to be present in the input folder so that the converter can use it as a reference.
However, it is this note (shown above) that was contained in the _readme.txt
file for the BatchStructureSetConversion.py
that led me to believe the CT volume was used as a reference for the output geometry. Perhaps the CT image is used as a reference for a different reason.
SlicerRT should not have that problem, since the CT is loaded by Slicer
Yes, but I believe the reference image is simply not considered in SlicerRT and 1x1x1mm^3 resolution is used. However I don't have time to work on this right now.
Regarding the labelmap size. isn't the issue that the created labelmap is minimally sized to contain the structure, and padding zeros are not included?
Same thing, would need to use the reference.
Sorry guys I don't even have time to check the code now. I have an emergency task for today and PhD defense on Monday. Please remind me about this a bit later.
@cpinter Do not worry about this issue. There is no rush. I am in the process of moving from Toronto to Boston, so I can't spend much time on this at the moment either. Lets come back to this at a later date.
We can circle back after your defense. Good luck.
Hi @cpinter. I hope your PhD defense went well, I'm sure it did. In case you do decide to circle back to this issue, here is a brief summary of our conversation:
- I used your
BatchStructureSetConversion.py
script to convert aRTSS
(containing only a single structure) to aNRRD
label-map. The outputNRRD
file did NOT have the same dimensions as the referenceDICOM
series provided (it seems like theNRRD
mask is cropped to the bounding box of the mask)
So potential updates/features might be:
- Option to apply/force the reference CT geometry to the output label map
- Allow the reference CT and the RTSS to be in different directories and specified as separate arguments to the script (e.g.
--input-folder
,--ref-dicom-dir
,--output-folder
)
It went fine, thanks for asking :)
Since we have the same option in Slicer, I'd lean towards the first option, i.e. adding an argument to use the found anatomical image as the reference for the nrrd conversion. Would it be satisfactory?
I think that sounds like a great idea. Though, I think combining both suggested features could be useful for those who might want to use a common reference CT for many RTSS conversions (probably less common), or simply in situations where the reference CT and the RTSS are located in separate directories (probably more common).
Selfishly, I prefer to avoid moving files into a common directory to use a script. But I haven't looked into the guts of the script, so I don't really have a sense for the amount of extra work this would take.
I'm imaging something like...
Slicer --no-main-window --python-script path/to/BatchStructureSetConversion.py \
--input-folder /path/to/rtss \
--ref-dicom-dir path/to/dicom \
--output-folder /path/to/output \
--force-geom-match
I added these two arguments, see 2078c7a
The argument names are slightly different from what you suggested, please see readme file.
Let me know how it works for you.
Also can you please briefly describe what do you use SlicerRT for, and which institution you are from? We just entered in the maintenance period of the CANARIE SlicerRT grant, which is just about helping new groups adopt the software, and for reporting purposes if would help a lot. Thanks :)
@mattwarkentin Could you please aknowledge that you received notification about the improvement I implemented for you last week?
@cpinter Sorry for the slow response time. I have been travelling with very limited internet access. I confirm that I have received this notification. Thank you very much for this enhancement; it is very much appreciated. I will formally test it out when I am back in the office and will report back here with my experiences. Here is a write-up about my usage of the SlicerRT
extension and also the BatchStructureSetConversion.py
script that I hope is helpful for your grant reporting:
I am a PhD candidate in Molecular Epidemiology at University of Toronto and a Doctoral Fellow/Trainee at the Lunenfeld-Tanenbaum Research Institute at Mount Sinai Hospital. My PhD supervisor is a co-PI for a grant whereby the goal of one of the sub-projects is to integrate the lung screening data for several large international lung screening trials. In my role, I am working to develop the pipeline and tools needed for each site to independently extract and compile engineered features (i.e. radiomics) for all of the nodules identified in their lung screening CTs. This will be perhaps the largest and most diverse set of lung nodule data/features ever assembled, to date. Since we are collaborating with several international sites, some sites export their nodule contours from their CT vendor software as DICOM RTSS format. For our purposes, we convert the structures (contoured nodules) contained therein into binary label maps (NRRD format), so that we may then perform batch feature extraction. For the RTSS>NRRD conversion, I have tested your original script on a small subset of images/nodules, and will additionally test your newly updated script for this purpose.
I have also used the SlicerRT
extension functionality many times from within the Slicer
GUI to import/view RTSS files, and to convert RTSS to NRRD interactively (i.e. one at-a-time); but primarily I use the script/extension for en masse file conversions.
I hope this is helpful. Please let me know if I can provide any other useful information. Thanks again for all of your help.
Thank you very much for taking the time to describe your work!
Looking forward to hear about how the new options work for you.
Hi ,I had a experiment that I convert the RTstructure(2.dcm) into mask_ROIs(.nii.gz) respectively with the result as following figure on April 6 by using Platimatch convert commandline accidently,now I want to do it again,but I can't ,and I can't remember how I did ,I am being lost in it for some days,I ask for help on it.
the name of files of all *.nii.gz is automatically finished
Is this a supposed issue with plastimatch
or SlicerRT
? If the former, you may wish to file an issue over at its repository here: https://gitlab.com/plastimatch/plastimatch/issues
From the plastimatch manual page (https://plastimatch.org/plastimatch.html), this may be helpful:
This next example shows how to convert a DICOM RT structure set file into an image using the –output-ss-img option. Because structures in DICOM RT are polylines, they are rasterized to create the image. The voxels of the output image are 32-bit integers, where the i^th bit of each integer has value one if the voxel lies with in the corresponding structure, and value zero if the voxel lies outside the structure. The structure names are stored in separate file using the –output-ss-list option.
plastimatch convert \
--input structures.dcm \
--output-ss-img outfile.nrrd \
--output-ss-list outfile.txt
@mattwarkentin ,thanks,I filed an issue over at [https://gitlab.com/plastimatch/plastimatch/issues] as your suggest. I still is waiting for help
@liyongwu-github You're more likely to get a quick and helpful response if you are able to provide a minimal sample of data and code that reproduces your issue - especially code that can be copy and pasted. Generally, screenshots are of little help in most troubleshooting cases.
If you can't share the data for someone to try to reproduce your issue, then providing at least the code that produces the error is the next best thing.
@mattwarkentin,thanks,images is in a directory with 88 DICOM files now zipped into 3 files(*.zip, available for uploading) as attached and The RTstructrue file zipped as 2.zip is attached too .
but I can't remember the code(a commandline in plastimatch) that I did,it a pity that only I can recall it with having 3 parameters in commandline.sorry
img1.zip
img2.zip
img3.zip
2.zip
This command gets you most of the way there. This should serve as a good starting point.
plastimatch convert \
--input 2.dcm \
--output-prefix "masks" \
--prefix-format "nii.gz" \
--output-ss-img "image.nii.gz"
In general, you should try to include the code you have tried, even if it does not work. It is much easier to offer help with a starting point.
@mattwarkentin ,you are a kind person, thanks.