I load RTPLAN, RTDOSE, RTSTRUCT, and RT image into Slicer and would like to export them as dicom files.
I can have RTDOSE, RTSTRUCT, and RT image exported, not RTPLAN. I look at the code RTPLAN node does not get checked in SlicerRT/DicomRtImportExport/Logic/vtkSlicerDicomRtImportExportModuleLogic.cxx. It only check:
// Get nodes for the different roles from the exportable list
vtkMRMLScalarVolumeNode* doseNode = nullptr;
vtkMRMLSegmentationNode* segmentationNode = nullptr;
vtkMRMLScalarVolumeNode* imageNode = nullptr;
Correspondingly, only anatomical image, dose distribution image and structure can be set in SlicerRT/DicomRtImportExport/Logic/vtkSlicerDicomRtWriter.h:
/// Set anatomical image to Plastimatch RT study for export
void SetImage(const Plm_image::Pointer&);
/// Set dose distribution image to Plastimatch RT study for export
void SetDose(const Plm_image::Pointer&);
/// Add structure as image data to Plastimatch RT study for export
void AddStructure(UCharImageType::Pointer, const char* name, double* color);
If anyone has exported RTPLAN, could you share your code with me?
RT Plan export in SlicerRT has not been implemented unfortunately. We are currently writing a grant that will allow that, but it will be at least a year or two before it happens. If you or your lab has the capacity to start adding this feature I will be happy to help.
I would like to start working on it. Currently, I am thinking how to convert vtkMRMLRTPlanNode object to Rtplan object. Then I can set it in the writer. If you have any information on it, please let me know.
My current goal is still vague. My idea is that if I create a RTPLAN in SlicerRT, I should be able to export out from Slicer and then reload it back into Slicer.
Thanks for pointing out the code needed to be changed.
// Convert input RTPlan to the format Plastimatch can use
if (planNode) {
std::cout << "chengs++: export RT study find RTPlanVolume node " << std::endl;
Rtplan::Pointer plan = Rtplan::New();
plan->rt_plan_label = "T ORL 1C";
plan->rt_plan_name = "T ORL 1C";
plan->rt_plan_date = "18850827";
plan->rt_plan_time = "111111";
plan->patient_position = "hfs"; //patient position metadata: one of {hfs,hfp,ffs,ffp}
rtWriter->SetPlan(plan);
}
Basically, it is just dummy Rtplan object.
However, the problem I face now is that I could not load the RTPLAN dicom file back with Slicer. Because Slicer think this file is scalar volume. Here is the error:
"
Warning in DICOM plugin Scalar Volume when examining loadable 114120633: Unnamed Series: Reference image in series does not contain geometry information. Please use caution.
vtkITKArchetypeImageSeriesReader::ExecuteInformation: Cannot open /tmp/IRS-gchen/DICOMExportTemp_20191011_135248/RTPLAN/rtplan_1.2.826.0.1.3680043.8.274.1.1.8323329.21835.1570819971.548083.dcm. ITK exception info: error in unknown: Could not create IO object for reading file /tmp/IRS-gchen/DICOMExportTemp_20191011_135248/RTPLAN/rtplan_1.2.826.0.1.3680043.8.274.1.1.8323329.21835.1570819971.548083.dcm
Tried to create one of the following:
BMPImageIO
BioRadImageIO
DCMTKImageIO
GDCMImageIO
GiplImageIO
JPEGImageIO
LSMImageIO
MGHImageIO
MINCImageIO
MRCImageIO
MetaImageIO
NiftiImageIO
NrrdImageIO
PNGImageIO
StimulateImageIO
TIFFImageIO
VTKImageIO
MRMLIDImageIO
Bruker2dseqImageIO
GE4ImageIO
GE5ImageIO
HDF5ImageIO
JPEG2000ImageIO
You probably failed to set a file suffix, or
set the suffix to an unsupported type.
"
I have not figure out the reason. If you have any suggestion, please let me know.
Thanks.
The plan is not completely imported. Only the first control point is loaded, also things like beam energy, MU, etc. are not loaded. That’s why I feel it might not be useful to export such a plan.
Thanks for response. I found the reason. The RTplan exported is RTIonPlan. So it is not recognized as RT loadable. Here is the comments in DicomRtImportExport/Logic/vtkSlicerDicomRtImportExportModuleLogic.cxx:
“”"
/* Not yet supported
else if (sopClass == UID_RTTreatmentSummaryRecordStorage)
else if (sopClass == UID_RTIonPlanStorage)
else if (sopClass == UID_RTIonBeamsTreatmentRecordStorage)
*/
“”"
By tacking down, I found a new read function is needed to read RTIonPlan in DCMTK/dcmrt/libsrc/drtplan.cc.
It would probably not take too much time to finish it, but it is not high on the priority list. If you’d like to give it a shot, I am happy to prepare you a branch and give you pointers.
If your goal is to have a complete import/export ion plan wofkflow with Slicer, however, it could take significant effort due to the things @gcsharp mentions. Also see my comment above.