From 53d9be1a51c982bf5b98b33234869782a954d095 Mon Sep 17 00:00:00 2001 From: Gauthier Bouilhol Date: Wed, 8 Feb 2012 14:59:50 +0100 Subject: [PATCH] clitkDicomRTPlan2Gate tool added --- tools/CMakeLists.txt | 7 + tools/clitkDicomRTPlan2Gate.cxx | 283 ++++++++++++++++++++++++++++++++ tools/clitkDicomRTPlan2Gate.ggo | 8 + 3 files changed, 298 insertions(+) create mode 100644 tools/clitkDicomRTPlan2Gate.cxx create mode 100644 tools/clitkDicomRTPlan2Gate.ggo diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8ab0488..f7d426d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -252,6 +252,13 @@ IF (CLITK_BUILD_TOOLS) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkMeshViewer) ENDIF(CLITK_EXPERIMENTAL) + IF(ITK_VERSION_MAJOR VERSION_LESS 4) + MESSAGE(WARNING "clitkDicomRTPlan2Gate is not compatible with GDCM<2 (ITK<4). It will not be build.") + ELSE(ITK_VERSION_MAJOR VERSION_LESS 4) + ADD_EXECUTABLE(clitkDicomRTPlan2Gate clitkDicomRTPlan2Gate.cxx clitkDicomRTPlan2Gate_ggo.c) + TARGET_LINK_LIBRARIES(clitkDicomRTPlan2Gate clitkCommon ${ITK_LIBRARIES}) + ENDIF(ITK_VERSION_MAJOR VERSION_LESS 4) + SET_TARGET_PROPERTIES(${TOOLS_INSTALL} PROPERTIES INSTALL_RPATH "${VTK_DIR}:${ITK_DIR}" ) INSTALL (TARGETS ${TOOLS_INSTALL} DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/tools/clitkDicomRTPlan2Gate.cxx b/tools/clitkDicomRTPlan2Gate.cxx new file mode 100644 index 0000000..2026861 --- /dev/null +++ b/tools/clitkDicomRTPlan2Gate.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ +#ifndef CLITKDICOMRTPLAN2GATE_CXX +#define CLITKDICOMRTPLAN2GATE_CXX + +#include "clitkDicomRTPlan2Gate_ggo.h" + +#include "clitkIO.h" +#include "clitkCommon.h" + +#include "gdcmFile.h" +#include "gdcmReader.h" +#include "gdcmAttribute.h" + +int main(int argc, char * argv[]) +{ + + // init command line + GGO(clitkDicomRTPlan2Gate, args_info); + CLITK_INIT; + char* input_file = args_info.input_arg; + char* output_file = args_info.output_arg; + + gdcm::Reader reader; + reader.SetFileName(input_file); + if( !reader.Read() ) + { + std::cerr << "Failed to read: " << input_file << std::endl; + return 1; + } + + const gdcm::DataSet & ds = reader.GetFile().GetDataSet(); + + //Check file type + gdcm::MediaStorage ms; + ms.SetFromFile(reader.GetFile()); + if( ms != gdcm::MediaStorage::RTIonPlanStorage ) + { + std::cerr << "The file <" << input_file << "> is not a RT Ion Plan." << std::endl; + exit(0); + } + + std::ofstream output; + output.open(output_file); + output << "#TREATMENT-PLAN-DESCRIPTION" << "\n"; + + gdcm::Attribute<0x300a,0x2> label; + label.SetFromDataSet(ds); + gdcm::Attribute<0x300a,0x3> planName; + planName.SetFromDataSet(ds); + + output << "#PlanName\n"<< planName.GetValue() << "\n"; + + gdcm::Tag tFractionGroupSQ(0x300a,0x70); + gdcm::Attribute<0x300a,0x71> fractionID; + gdcm::Attribute<0x300a,0x78> numberOfFractions; + gdcm::Attribute<0x300a,0x80> numberOfBeams; + + gdcm::Tag tReferencedBeamSQ(0x300c,0x4); + gdcm::Attribute<0x300a,0x86> meterSet; + gdcm::Attribute<0x300c,0x6> beamID; + + const gdcm::DataElement &FractionGroupSQ = ds.GetDataElement( tFractionGroupSQ ); + gdcm::SmartPointer sqf = FractionGroupSQ.GetValueAsSQ(); + gdcm::Item &ReferencedBeamItem = sqf->GetItem(1); + gdcm::DataSet &ReferencedBeamData = ReferencedBeamItem.GetNestedDataSet(); + numberOfFractions.SetFromDataSet(ReferencedBeamData); + + output << "#NumberOfFractions\n"<< numberOfFractions.GetValue() << "\n"; + + for( unsigned int fidx = 1; fidx <= sqf->GetNumberOfItems(); ++fidx ) + { + gdcm::Item &ReferencedBeamItem = sqf->GetItem(fidx); + gdcm::DataSet &ReferencedBeamData = ReferencedBeamItem.GetNestedDataSet(); + + fractionID.SetFromDataSet(ReferencedBeamData); + numberOfFractions.SetFromDataSet(ReferencedBeamData); + numberOfBeams.SetFromDataSet(ReferencedBeamData); + output << "##FractionID\n"<< fractionID.GetValue() << "\n"; + output << "##NumberOfFields\n"<< numberOfBeams.GetValue() << "\n"; + + const gdcm::DataElement &ReferencedBeamSQ = ReferencedBeamData.GetDataElement(tReferencedBeamSQ); + gdcm::SmartPointer sqb = ReferencedBeamSQ.GetValueAsSQ(); + for( unsigned int bidx = 1; bidx <= sqb->GetNumberOfItems(); ++bidx ) + { + gdcm::Item &ReferencedBeamGroupItem = sqb->GetItem(bidx); + gdcm::DataSet &ReferencedBeamGroupData = ReferencedBeamGroupItem.GetNestedDataSet(); + + meterSet.SetFromDataSet(ReferencedBeamGroupData); + beamID.SetFromDataSet(ReferencedBeamGroupData); + output << "###FieldsID\n"<< beamID.GetValue() << "\n"; + } + } + + gdcm::Tag tPatientSetupSQ(0x300a,0x180); + gdcm::Attribute<0x0018,0x5100> position; + gdcm::Attribute<0x300a,0x1b0> setupTechnique; + gdcm::Attribute<0x300a,0x182> setupID; + + const gdcm::DataElement &PatientSetupSQ = ds.GetDataElement( tPatientSetupSQ ); + gdcm::SmartPointer sqs = PatientSetupSQ.GetValueAsSQ(); + for( unsigned int sidx = 1; sidx <= sqs->GetNumberOfItems(); ++sidx ) + { + gdcm::Item &PatientSetupItem = sqs->GetItem(sidx); + gdcm::DataSet &PatientSetupData = PatientSetupItem.GetNestedDataSet(); + + position.SetFromDataSet(PatientSetupData); + setupTechnique.SetFromDataSet(PatientSetupData); + setupID.SetFromDataSet(PatientSetupData); + } + + gdcm::Tag tIonBeamSQ(0x300a,0x3a2); + gdcm::Attribute<0x300a,0xb2> machine; + gdcm::Attribute<0x300a,0xc6> radiationType; + gdcm::Attribute<0x300a,0xce> treatmentType; + gdcm::Attribute<0x300a,0xc0> ionBeamID; + gdcm::Attribute<0x300a,0x10e> finalCumulativeMeterSetWeight; + gdcm::Attribute<0x300a,0x110> numberOfControlPoints; + gdcm::Attribute<0x300c,0x6a> patientSetupID; + gdcm::Attribute<0x300a,0xd0> numberOfWedges; + gdcm::Attribute<0x300a,0xe0> numberOfCompensators; + gdcm::Attribute<0x300a,0xed> numberOfBoli; + gdcm::Attribute<0x300a,0xf0> numberOfBlocks; + gdcm::Attribute<0x300a,0x312> numberOfRangeShifters; + gdcm::Attribute<0x300a,0x330> numberOfLateralSpreadingDevices; + gdcm::Attribute<0x300a,0x340> numberOfRangeModulators; + + gdcm::Tag tSnoutSQ(0x300a,0x30c); + gdcm::Attribute<0x300a,0x30f> snoutID; + + gdcm::Tag tControlPointSQ(0x300a,0x3a8); + gdcm::Attribute<0x300a,0x15> energyUnit; + gdcm::Attribute<0x300a,0x114> energyValue; + gdcm::Attribute<0x300a,0x112> controlPointIndex; + gdcm::Attribute<0x300a,0x134> cumulativeMetersetWeight; + gdcm::Attribute<0x300a,0x392> numberOfScannedSpots; + gdcm::Attribute<0x300a,0x390> spotTunnedID; + + gdcm::Tag tSpotPositionsData(0x300a,0x394); + gdcm::Attribute<0x300a,0x394> spotPositions; + gdcm::Tag tSpotWeightsData(0x300a,0x396); + gdcm::Attribute<0x300a,0x396> spotWeights; + + gdcm::Attribute<0x300a,0x11e> gantryAngle; + gdcm::Attribute<0x300a,0x122> patientSupportAngle; + gdcm::Attribute<0x300a,0x12c> isocenterPosition; + + int totalCumMeterSet = 0; + + const gdcm::DataElement &IonBeamSQ = ds.GetDataElement( tIonBeamSQ ); + gdcm::SmartPointer sqi = IonBeamSQ.GetValueAsSQ(); + + for( unsigned int iidx = 1; iidx <= sqi->GetNumberOfItems(); ++iidx ) + { + gdcm::Item &IonBeamItem = sqi->GetItem(iidx); + gdcm::DataSet &IonBeamData = IonBeamItem.GetNestedDataSet(); + finalCumulativeMeterSetWeight.SetFromDataSet(IonBeamData); + totalCumMeterSet += finalCumulativeMeterSetWeight.GetValue(); + } + + output << "#TotalMetersetWeightOfAllFields\n" << totalCumMeterSet << "\n"; + + for( unsigned int iidx = 1; iidx <= sqi->GetNumberOfItems(); ++iidx ) + { + gdcm::Item &IonBeamItem = sqi->GetItem(iidx); + gdcm::DataSet &IonBeamData = IonBeamItem.GetNestedDataSet(); + + machine.SetFromDataSet(IonBeamData); + radiationType.SetFromDataSet(IonBeamData); + treatmentType.SetFromDataSet(IonBeamData); + ionBeamID.SetFromDataSet(IonBeamData); + finalCumulativeMeterSetWeight.SetFromDataSet(IonBeamData); + numberOfControlPoints.SetFromDataSet(IonBeamData); + patientSetupID.SetFromDataSet(IonBeamData); + numberOfWedges.SetFromDataSet(IonBeamData); + numberOfCompensators.SetFromDataSet(IonBeamData); + numberOfBoli.SetFromDataSet(IonBeamData); + numberOfBlocks.SetFromDataSet(IonBeamData); + numberOfRangeShifters.SetFromDataSet(IonBeamData); + numberOfLateralSpreadingDevices.SetFromDataSet(IonBeamData); + numberOfRangeModulators.SetFromDataSet(IonBeamData); + + const gdcm::DataElement &SnoutSQ = IonBeamData.GetDataElement(tSnoutSQ); + gdcm::SmartPointer sqsn = SnoutSQ.GetValueAsSQ(); + for( unsigned int snidx = 1; snidx <= sqsn->GetNumberOfItems(); ++snidx ) + { + gdcm::Item &SnoutItem = sqsn->GetItem(snidx); + gdcm::DataSet &SnoutData = SnoutItem.GetNestedDataSet(); + + snoutID.SetFromDataSet(SnoutData); + } + + const gdcm::DataElement &ControlPointSQ = IonBeamData.GetDataElement(tControlPointSQ); + gdcm::SmartPointer sqcp = ControlPointSQ.GetValueAsSQ(); + gdcm::Item &ControlPointItem = sqcp->GetItem(1); + gdcm::DataSet &ControlPointData = ControlPointItem.GetNestedDataSet(); + + gantryAngle.SetFromDataSet(ControlPointData); + patientSupportAngle.SetFromDataSet(ControlPointData); + isocenterPosition.SetFromDataSet(ControlPointData); + + output << "\n#FIELD-DESCRIPTION" << "\n"; + output << "###FieldID\n"<< ionBeamID.GetValue() << "\n"; + output << "###FinalCumulativeMeterSetWeight\n"<< finalCumulativeMeterSetWeight.GetValue() << "\n"; + output << "###GantryAngle\n" << gantryAngle.GetValue() << "\n"; + output << "###PatientSupportAngle\n" << patientSupportAngle.GetValue() << "\n"; + output << "###IsocenterPosition\n" << isocenterPosition.GetValue(0); + output << " " << isocenterPosition.GetValue(1); + output << " " << isocenterPosition.GetValue(2) << "\n"; + output << "###NumberOfControlPoints\n" << numberOfControlPoints.GetValue() << "\n\n"; + output << "#SPOTS-DESCRIPTION" << "\n"; + + for( unsigned int cpidx = 1; cpidx <= sqcp->GetNumberOfItems(); ++cpidx ) + { + gdcm::Item &ControlPointItem = sqcp->GetItem(cpidx); + gdcm::DataSet &ControlPointData = ControlPointItem.GetNestedDataSet(); + + if ( cpidx == 1 ) + { + gantryAngle.SetFromDataSet(ControlPointData); + patientSupportAngle.SetFromDataSet(ControlPointData); + isocenterPosition.SetFromDataSet(ControlPointData); + } + + if ( cpidx < sqcp->GetNumberOfItems() ) + { + energyUnit.SetFromDataSet(ControlPointData); + energyValue.SetFromDataSet(ControlPointData); + controlPointIndex.SetFromDataSet(ControlPointData); + cumulativeMetersetWeight.SetFromDataSet(ControlPointData); + numberOfScannedSpots.SetFromDataSet(ControlPointData); + spotTunnedID.SetFromDataSet(ControlPointData); + + const gdcm::DataElement &spotPositionsData = ControlPointData.GetDataElement(tSpotPositionsData); + spotPositions.SetFromDataElement(spotPositionsData); + const gdcm::DataElement &spotWeightsData = ControlPointData.GetDataElement(tSpotWeightsData); + spotWeights.SetFromDataElement(spotWeightsData); + } + + if ( cpidx == sqcp->GetNumberOfItems() ) + { + energyUnit.SetValue( "0" ); + energyValue.SetValue( 0 ); + controlPointIndex.SetFromDataSet(ControlPointData); + cumulativeMetersetWeight.SetFromDataSet(ControlPointData); + numberOfScannedSpots.SetValue( 0 ); + spotTunnedID.SetValue( "0" ); + } + + output << "####ControlPointIndex\n" << controlPointIndex.GetValue() << "\n"; + output << "####SpotTunnedID\n" << spotTunnedID.GetValue() << "\n"; + output << "####CumulativeMetersetWeight\n" << cumulativeMetersetWeight.GetValue() << "\n"; + output << "####Energy (MeV)\n"<< energyValue.GetValue() << "\n"; + output << "####NbOfScannedSpots\n" << numberOfScannedSpots.GetValue() << "\n"; + output << "####X Y Weight\n"; + for ( unsigned int sp=0; sp < numberOfScannedSpots.GetValue(); ++sp) + { + output << spotPositions.GetValue(2*sp) << " " << spotPositions.GetValue(2*sp+1) << " " << spotWeights.GetValue(sp) << "\n"; + } + + } + + } + + return 0; +} + +#endif diff --git a/tools/clitkDicomRTPlan2Gate.ggo b/tools/clitkDicomRTPlan2Gate.ggo new file mode 100644 index 0000000..21b23eb --- /dev/null +++ b/tools/clitkDicomRTPlan2Gate.ggo @@ -0,0 +1,8 @@ +# file DicomRTPlan2Gate +package "clitk" +version "1.0" +purpose "Convert DicomRTPlan to Gate compatible file" +option "config" - "config file" string no +option "input" i "Input dicom file name" string yes +option "output" o "Output text file name" string yes +option "verbose" v "verbose" flag off -- 2.45.2