diff --git a/Modules/Core/src/IO/mitkIOMimeTypes.cpp b/Modules/Core/src/IO/mitkIOMimeTypes.cpp index 2bccbae700..2e11f44817 100644 --- a/Modules/Core/src/IO/mitkIOMimeTypes.cpp +++ b/Modules/Core/src/IO/mitkIOMimeTypes.cpp @@ -1,312 +1,333 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOMimeTypes.h" #include "mitkCustomMimeType.h" +#include "mitkLogMacros.h" #include "itkGDCMImageIO.h" +#include "itkMetaDataObject.h" namespace mitk { IOMimeTypes::DicomMimeType::DicomMimeType() : CustomMimeType(DICOM_MIMETYPE_NAME()) { this->AddExtension("gdcm"); this->AddExtension("dcm"); this->AddExtension("DCM"); this->AddExtension("dc3"); this->AddExtension("DC3"); this->AddExtension("ima"); this->AddExtension("img"); this->SetCategory(CATEGORY_IMAGES()); this->SetComment("DICOM"); } bool IOMimeTypes::DicomMimeType::AppliesTo(const std::string &path) const { - if (CustomMimeType::AppliesTo(path)) - return true; + if (!CustomMimeType::AppliesTo(path)) + return false; // Ask the GDCM ImageIO class directly itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New(); - return gdcmIO->CanReadFile(path.c_str()); + gdcmIO->SetFileName(path); + try { + gdcmIO->ReadImageInformation(); + } + catch (const itk::ExceptionObject & err) { + MITK_ERROR << "ExceptionObject caught in IOMimeTypes::DicomMimeType::AppliesTo! " << err.GetDescription(); + return false; + } + + //DICOMRT modalities have specific reader, don't read with normal DICOM readers + std::string modality; + itk::MetaDataDictionary& dict = gdcmIO->GetMetaDataDictionary(); + itk::ExposeMetaData(dict, "0008|0060", modality); + MITK_INFO << "DICOM Modality is " << modality; + if (modality == "RTSTRUCT" || modality == "RTDOSE" || modality == "RTPLAN") { + return false; + } + else { + return gdcmIO->CanReadFile(path.c_str()); + } } IOMimeTypes::DicomMimeType *IOMimeTypes::DicomMimeType::Clone() const { return new DicomMimeType(*this); } std::vector IOMimeTypes::Get() { std::vector mimeTypes; // order matters here (descending rank for mime types) mimeTypes.push_back(NRRD_MIMETYPE().Clone()); mimeTypes.push_back(NIFTI_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE().Clone()); mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(DICOM_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE().Clone()); mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE().Clone()); mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE().Clone()); mimeTypes.push_back(WAVEFRONT_OBJ_MIMETYPE().Clone()); mimeTypes.push_back(STANFORD_PLY_MIMETYPE().Clone()); mimeTypes.push_back(RAW_MIMETYPE().Clone()); mimeTypes.push_back(POINTSET_MIMETYPE().Clone()); return mimeTypes; } CustomMimeType IOMimeTypes::VTK_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_NAME()); mimeType.AddExtension("vti"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_IMAGE_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_LEGACY_NAME()); mimeType.AddExtension("vtk"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Legacy Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_IMAGE_NAME()); mimeType.AddExtension("pvti"); mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Parallel Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_NAME()); mimeType.AddExtension("vtp"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_LEGACY_NAME()); mimeType.AddExtension("vtk"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Legacy PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_POLYDATA_NAME()); mimeType.AddExtension("pvtp"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Parallel PolyData"); return mimeType; } CustomMimeType IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE() { CustomMimeType mimeType(STEREOLITHOGRAPHY_NAME()); mimeType.AddExtension("stl"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("Stereolithography"); return mimeType; } CustomMimeType IOMimeTypes::WAVEFRONT_OBJ_MIMETYPE() { CustomMimeType mimeType(WAVEFRONT_OBJ_NAME()); mimeType.AddExtension("obj"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("Wavefront OBJ"); return mimeType; } CustomMimeType IOMimeTypes::STANFORD_PLY_MIMETYPE() { CustomMimeType mimeType(STANFORD_PLY_NAME()); mimeType.AddExtension("ply"); mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("Stanford PLY"); return mimeType; } std::string IOMimeTypes::STEREOLITHOGRAPHY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".stl"; return name; } std::string IOMimeTypes::WAVEFRONT_OBJ_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".obj"; return name; } std::string IOMimeTypes::STANFORD_PLY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".ply"; return name; } std::string IOMimeTypes::DEFAULT_BASE_NAME() { static std::string name = "application/vnd.mitk"; return name; } std::string IOMimeTypes::CATEGORY_IMAGES() { static std::string cat = "Images"; return cat; } std::string IOMimeTypes::CATEGORY_SURFACES() { static std::string cat = "Surfaces"; return cat; } std::string IOMimeTypes::VTK_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image"; return name; } std::string IOMimeTypes::VTK_IMAGE_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.image"; return name; } std::string IOMimeTypes::VTK_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata"; return name; } std::string IOMimeTypes::VTK_POLYDATA_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.polydata"; return name; } CustomMimeType IOMimeTypes::NRRD_MIMETYPE() { CustomMimeType mimeType(NRRD_MIMETYPE_NAME()); mimeType.AddExtension("nrrd"); mimeType.AddExtension("nhdr"); mimeType.SetCategory("Images"); mimeType.SetComment("NRRD"); return mimeType; } CustomMimeType IOMimeTypes::NIFTI_MIMETYPE() { CustomMimeType mimeType(NIFTI_MIMETYPE_NAME()); mimeType.AddExtension("nii"); mimeType.AddExtension("nii.gz"); mimeType.AddExtension("hdr"); mimeType.AddExtension("hdr.gz"); mimeType.AddExtension("img"); mimeType.AddExtension("img.gz"); mimeType.AddExtension("nia"); mimeType.SetCategory("Images"); mimeType.SetComment("Nifti"); return mimeType; } CustomMimeType IOMimeTypes::RAW_MIMETYPE() { CustomMimeType mimeType(RAW_MIMETYPE_NAME()); mimeType.AddExtension("raw"); mimeType.SetCategory("Images"); mimeType.SetComment("Raw data"); return mimeType; } IOMimeTypes::DicomMimeType IOMimeTypes::DICOM_MIMETYPE() { return DicomMimeType(); } std::string IOMimeTypes::NRRD_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nrrd"; return name; } std::string IOMimeTypes::NIFTI_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nifti"; return name; } std::string IOMimeTypes::RAW_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.raw"; return name; } std::string IOMimeTypes::DICOM_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.dicom"; return name; } CustomMimeType IOMimeTypes::POINTSET_MIMETYPE() { CustomMimeType mimeType(POINTSET_MIMETYPE_NAME()); mimeType.AddExtension("mps"); mimeType.SetCategory("Point Sets"); mimeType.SetComment("MITK Point Set"); return mimeType; } std::string IOMimeTypes::POINTSET_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".pointset"; return name; } CustomMimeType IOMimeTypes::GEOMETRY_DATA_MIMETYPE() { mitk::CustomMimeType mimeType(DEFAULT_BASE_NAME() + ".geometrydata"); mimeType.AddExtension("mitkgeometry"); mimeType.SetCategory("Geometries"); mimeType.SetComment("GeometryData object"); return mimeType; } } diff --git a/Modules/DICOMReader/src/mitkDICOMTagsOfInterestHelper.cpp b/Modules/DICOMReader/src/mitkDICOMTagsOfInterestHelper.cpp index 79859938a1..44a93f9bd7 100644 --- a/Modules/DICOMReader/src/mitkDICOMTagsOfInterestHelper.cpp +++ b/Modules/DICOMReader/src/mitkDICOMTagsOfInterestHelper.cpp @@ -1,194 +1,206 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY { } without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDICOMTagsOfInterestHelper.h" #include #include "usModuleContext.h" #include "usGetModuleContext.h" mitk::DICOMTagPathMapType::value_type MakeLegacyEntry(const std::string& propName, const mitk::DICOMTag& tag) { return std::make_pair(tag, propName); } mitk::DICOMTagPathMapType::value_type MakeEntry(const mitk::DICOMTagPath& tagPath) { return std::make_pair(tagPath, ""); } mitk::DICOMTagPathMapType mitk::GetCurrentDICOMTagsOfInterest() { mitk::DICOMTagPathMapType result; std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); if (toiRegisters.empty()) { // bad, no service found, cannot get tags of interest MITK_ERROR << "DICOM tag error: no service for DICOM tags of interest"; return result; } else if (toiRegisters.size() > 1) { MITK_WARN << "DICOM tag error: multiple service for DICOM tags of interest found. Using just one."; } IDICOMTagsOfInterest* toiRegister = us::GetModuleContext()->GetService(toiRegisters.front()); if (!toiRegister) { MITK_ERROR << "Service lookup error, cannot get DICOM tag of interest service "; } return toiRegister->GetTagsOfInterest(); } mitk::DICOMTagPathMapType mitk::GetDefaultDICOMTagsOfInterest() { DICOMTagPathMapType result; //These tags are copied from DICOMSeriesReader. The old naming style (deprecated) //is kept for backwards compatibility until it is removed. //Below we have also already added the properties with the new naming style // Patient module /*dicom.patient.PatientsName*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x0010))); /*dicom.patient.PatientID*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x0020))); /*dicom.patient.PatientsBirthDate*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x0030))); /*dicom.patient.PatientsSex*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x0040))); /*dicom.patient.PatientsBirthTime*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x0032))); /*dicom.patient.OtherPatientIDs*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x1000))); /*dicom.patient.OtherPatientNames*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x1001))); /*dicom.patient.EthnicGroup*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x2160))); /*dicom.patient.PatientComments*/ result.insert(MakeEntry(DICOMTag(0x0010, 0x4000))); /*dicom.patient.PatientIdentityRemoved*/ result.insert(MakeEntry(DICOMTag(0x0012, 0x0062))); /*dicom.patient.DeIdentificationMethod*/ result.insert(MakeEntry(DICOMTag(0x0012, 0x0063))); // General Study module /*dicom.study.StudyInstanceUID*/ result.insert(MakeEntry(DICOMTag(0x0020, 0x000d))); /*dicom.study.StudyDate*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0020))); /*dicom.study.StudyTime*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0030))); /*dicom.study.ReferringPhysiciansName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0090))); /*dicom.study.StudyID*/ result.insert(MakeEntry(DICOMTag(0x0020, 0x0010))); /*dicom.study.AccessionNumber*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0050))); /*dicom.study.StudyDescription*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1030))); /*dicom.study.PhysiciansOfRecord*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1048))); /*dicom.study.NameOfPhysicianReadingStudy*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1060))); // General Series module /*dicom.series.Modality*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0060))); /*dicom.series.SeriesInstanceUID*/ result.insert(MakeEntry(DICOMTag(0x0020, 0x000e))); /*dicom.series.SeriesNumber*/ result.insert(MakeEntry(DICOMTag(0x0020, 0x0011))); /*dicom.series.Laterality*/ result.insert(MakeEntry(DICOMTag(0x0020, 0x0060))); /*dicom.series.SeriesDate*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0021))); /*dicom.series.SeriesTime*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0031))); /*dicom.series.PerformingPhysiciansName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1050))); /*dicom.series.ProtocolName*/ result.insert(MakeEntry(DICOMTag(0x0018, 0x1030))); /*dicom.series.SeriesDescription*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x103e))); /*dicom.series.OperatorsName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1070))); /*dicom.series.BodyPartExamined*/ result.insert(MakeEntry(DICOMTag(0x0018, 0x0015))); /*dicom.series.PatientPosition*/ result.insert(MakeEntry(DICOMTag(0x0018, 0x5100))); /*dicom.series.SmallestPixelValueInSeries*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0108))); /*dicom.series.LargestPixelValueInSeries*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0109))); // VOI LUT module /*dicom.voilut.WindowCenter*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x1050))); /*dicom.voilut.WindowWidth*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x1051))); /*dicom.voilut.WindowCenterAndWidthExplanation*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x1055))); // Image Pixel module /*dicom.pixel.PhotometricInterpretation*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0004))); /*dicom.pixel.Rows*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0010))); /*dicom.pixel.Columns*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0011))); // Image Plane module /*dicom.PixelSpacing*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x0030))); /*dicom.ImagerPixelSpacing*/ result.insert(MakeEntry(DICOMTag(0x0018, 0x1164))); //additional for RT /*dicom.RescaleIntercept*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x1052))); /*dicom.RescaleSlope*/ result.insert(MakeEntry(DICOMTag(0x0028, 0x1053))); /*dicom.ManufacturerModelName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1090))); /*dicom.ManufacturerName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0070))); /*dicom.InstitutionName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x0080))); /*dicom.StationName*/ result.insert(MakeEntry(DICOMTag(0x0008, 0x1010))); /*dicom.DoseGridScaling*/ result.insert(MakeEntry(DICOMTag(0x3004, 0x000e))); //Additions for RTPLAN DICOMTagPath doseReferenceSequence; doseReferenceSequence.AddAnySelection(0x300A, 0x0010); DICOMTagPath fractionGroupSequence; fractionGroupSequence.AddAnySelection(0x300A, 0x0070); DICOMTagPath beamSequence; beamSequence.AddAnySelection(0x300A, 0x00B0); DICOMTagPath referencedStructureSetSequence; referencedStructureSetSequence.AddAnySelection(0x300C, 0x0060); result.insert(MakeEntry(DICOMTagPath(doseReferenceSequence).AddElement(0x300A, 0x0013))); //dicom.DoseReferenceSequence.DoseReferenceUID result.insert(MakeEntry(DICOMTagPath(doseReferenceSequence).AddElement(0x300A, 0x0016))); //dicom.DoseReferenceSequence.DoseReferenceDescription result.insert(MakeEntry(DICOMTagPath(doseReferenceSequence).AddElement(0x300A, 0x0026))); //dicom.DoseReferenceSequence.TargetPrescriptionDose result.insert(MakeEntry(DICOMTagPath(fractionGroupSequence).AddElement(0x300A, 0x0078))); //dicom.FractionGroupSequence.NumberOfFractionsPlanned result.insert(MakeEntry(DICOMTagPath(fractionGroupSequence).AddElement(0x300A, 0x0080))); //dicom.FractionGroupSequence.NumberOfBeams result.insert(MakeEntry(DICOMTagPath(beamSequence).AddElement(0x300A, 0x00C6))); //dicom.BeamSequence.RadiationType result.insert(MakeEntry(DICOMTagPath(referencedStructureSetSequence).AddElement(0x0008, 0x1155))); //dicom.ReferencedStructureSetSequence.ReferencedSOPInstanceUID + //Additions for RTSTRUCT + DICOMTagPath structureSetROISequence; + structureSetROISequence.AddAnySelection(0x3006, 0x0020); + result.insert(MakeEntry(DICOMTagPath(structureSetROISequence).AddElement(0x3006, 0x0022))); //dicom.StructureSetROISequence.ROINumber + result.insert(MakeEntry(DICOMTagPath(structureSetROISequence).AddElement(0x3006, 0x0026))); //dicom.StructureSetROISequence.ROIName + result.insert(MakeEntry(DICOMTagPath(structureSetROISequence).AddElement(0x3006, 0x0024))); //dicom.StructureSetROISequence.ReferencedFrameOfReferenceUID + + //Additions for RTDOSE + DICOMTagPath planReferenceSequence; + planReferenceSequence.AddAnySelection(0x300C, 0x0002); + result.insert(MakeEntry(DICOMTagPath(planReferenceSequence).AddElement(0x0008, 0x1155))); //dicom.PlanReferenceSequence.ReferencedSOPInstanceUID + //Additions for PET DICOMTagPath radioPharmaRootTag; radioPharmaRootTag.AddAnySelection(0x0054, 0x0016); DICOMTagPath radioNuclideRootTag(radioPharmaRootTag); radioNuclideRootTag.AddAnySelection(0x0054, 0x0300); result.insert(MakeEntry(DICOMTagPath(radioPharmaRootTag).AddElement(0x0018, 0x0031))); //dicom.pet.Radiopharmaceutical result.insert(MakeEntry(DICOMTagPath(radioPharmaRootTag).AddElement(0x0018, 0x1072))); //dicom.pet.RadiopharmaceuticalStartTime result.insert(MakeEntry(DICOMTagPath(radioPharmaRootTag).AddElement(0x0018, 0x1074))); //dicom.pet.RadionuclideTotalDose result.insert(MakeEntry(DICOMTagPath(radioPharmaRootTag).AddElement(0x0018, 0x1075))); //dicom.pet.RadionuclideHalfLife result.insert(MakeEntry(DICOMTagPath(radioPharmaRootTag).AddElement(0x0018, 0x1076))); //dicom.pet.RadionuclidePositronFraction result.insert(MakeEntry(DICOMTagPath(radioNuclideRootTag).AddElement(0x0008, 0x0100))); //dicom.pet.Radionuclide.CodeValue result.insert(MakeEntry(DICOMTagPath(radioNuclideRootTag).AddElement(0x0008, 0x0102))); //dicom.pet.Radionuclide.CodingSchemeDesignator result.insert(MakeEntry(DICOMTagPath(radioNuclideRootTag).AddElement(0x0008, 0x0104))); //dicom.pet.Radionuclide.CodemManing result.insert(MakeEntry(DICOMTag(0x0054, 0x1001))); //dicom.pet.RadioactivityUnits result.insert(MakeEntry(DICOMTag(0x0054, 0x1102))); //dicom.pet.DecayCorrection result.insert(MakeEntry(DICOMTag(0x0054, 0x1321))); //dicom.pet.DecayFactor result.insert(MakeEntry(DICOMTag(0x0054, 0x1300))); //dicom.pet.FrameReferenceTime result.insert(MakeEntry(DICOMTag(0x0010, 0x1030))); //dicom.patient.PatientWeight result.insert(MakeEntry(DICOMTag(0x0010, 0x1020))); //dicom.patient.PatientSize //Other interesting acquisition correlated information result.insert(MakeEntry(DICOMTag(0x0008, 0x0022))); //dicom.acquisition date result.insert(MakeEntry(DICOMTag(0x0008, 0x0032))); //dicom.acquisition time result.insert(MakeEntry(DICOMTag(0x0008, 0x002a))); //dicom.acquisition datetime result.insert(MakeEntry(DICOMTag(0x0008, 0x0080))); //dicom.Modality result.insert(MakeEntry(DICOMTag(0x0018, 0x002a))); //dicom.Sequence Name result.insert(MakeEntry(DICOMTag(0x0018, 0x0020))); //dicom.Scanning Sequence result.insert(MakeEntry(DICOMTag(0x0018, 0x0021))); //dicom.Sequence Variant result.insert(MakeEntry(DICOMTag(0x0018, 0x0080))); //dicom.TR result.insert(MakeEntry(DICOMTag(0x0018, 0x0081))); //dicom.TE result.insert(MakeEntry(DICOMTag(0x0018, 0x1310))); //dicom.Acquisition Matrix result.insert(MakeEntry(DICOMTag(0x0018, 0x0087))); //dicom.Magnetic Field Strength //SOP result.insert(MakeEntry(DICOMTag(0x0008, 0x0018))); //SOP Instance UID result.insert(MakeEntry(DICOMTag(0x0020, 0x0013))); //Instance number result.insert(MakeEntry(DICOMTag(0x0020, 0x1041))); //Slice location return result; }; diff --git a/Modules/DicomRT/CMakeLists.txt b/Modules/DicomRT/CMakeLists.txt index 592e612cf2..4b74df9614 100644 --- a/Modules/DicomRT/CMakeLists.txt +++ b/Modules/DicomRT/CMakeLists.txt @@ -1,9 +1,10 @@ if(NOT DEFINED DCMTK_dcmrt_LIBRARY OR DCMTK_dcmrt_LIBRARY) mitk_create_module( DEPENDS MitkSegmentation MitkSceneSerializationBase MitkLegacyIO MitkDICOMReader MitkDICOMReaderServices PACKAGE_DEPENDS PUBLIC Qt5|Core DCMTK ) + add_subdirectory(autoload/IO) add_subdirectory(test) else() message("MITK DicomRT Support disabled because the DCMTK dcmrt library not found") endif() diff --git a/Modules/DicomRT/autoload/IO/CMakeLists.txt b/Modules/DicomRT/autoload/IO/CMakeLists.txt new file mode 100644 index 0000000000..e4f46be87f --- /dev/null +++ b/Modules/DicomRT/autoload/IO/CMakeLists.txt @@ -0,0 +1,7 @@ +MITK_CREATE_MODULE( DicomRTIO + INCLUDE_DIRS + PRIVATE src/IO + DEPENDS PUBLIC MitkDicomRT + PACKAGE_DEPENDS PUBLIC DCMTK + AUTOLOAD_WITH MitkCore +) \ No newline at end of file diff --git a/Modules/DicomRT/autoload/IO/files.cmake b/Modules/DicomRT/autoload/IO/files.cmake new file mode 100644 index 0000000000..5bcdb2f9d9 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/files.cmake @@ -0,0 +1,8 @@ +set(CPP_FILES + mitkDicomRTIOActivator.cpp + mitkDicomRTIOMimeTypes.cpp + mitkRTDoseReaderService.cpp + mitkRTPlanReaderService.cpp + mitkRTStructureSetReaderService.cpp + mitkDicomRTIOHelper.cpp +) diff --git a/Modules/DicomRT/autoload/IO/mitkDicomRTIOActivator.cpp b/Modules/DicomRT/autoload/IO/mitkDicomRTIOActivator.cpp new file mode 100644 index 0000000000..c9017c5070 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkDicomRTIOActivator.cpp @@ -0,0 +1,78 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "mitkDicomRTIOMimeTypes.h" + +namespace mitk +{ + /** + \brief Registers services for segmentation module. + */ + class DicomRTIOActivator : public us::ModuleActivator + { + public: + + void Load(us::ModuleContext* context) override + { + us::ServiceProperties props; + props[ us::ServiceConstants::SERVICE_RANKING() ] = 100; + + m_MimeTypes = mitk::DicomRTIOMimeTypes::Get(); + for (std::vector::const_iterator mimeTypeIter = m_MimeTypes.begin(), + iterEnd = m_MimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) + { + context->RegisterService(*mimeTypeIter, props); + } + + m_RTDoseReader = new RTDoseReaderService(); + m_RTPlanReader = new RTPlanReaderService(); + m_RTStructureSetReader = new RTStructureSetReaderService(); + } + + void Unload(us::ModuleContext*) override + { + for (auto& aMimeType : m_MimeTypes) + { + delete aMimeType; + } + + delete m_RTDoseReader; + delete m_RTPlanReader; + delete m_RTStructureSetReader; + } + + private: + + RTDoseReaderService * m_RTDoseReader; + RTPlanReaderService * m_RTPlanReader; + RTStructureSetReaderService * m_RTStructureSetReader; + + std::vector m_MimeTypes; + + }; +} + +US_EXPORT_MODULE_ACTIVATOR(mitk::DicomRTIOActivator) diff --git a/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.cpp b/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.cpp new file mode 100644 index 0000000000..7a93419db9 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.cpp @@ -0,0 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkDicomRTIOHelper.h" + +#include +#include +#include "mitkTemporoSpatialStringProperty.h" +#include "mitkImage.h" + +namespace mitk +{ + mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService() + { + mitk::IDICOMTagsOfInterest* result = nullptr; + + std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); + if (!toiRegisters.empty()) + { + if (toiRegisters.size() > 1) + { + MITK_WARN << "Multiple DICOM tags of interest services found. Using just one."; + } + result = us::GetModuleContext()->GetService(toiRegisters.front()); + } + + return result; + } + + FindingsListVectorType ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const DICOMDatasetAccessingImageFrameList& frames) + { + std::vector findings; + for (const auto& entry : pathsOfInterest) { + findings.push_back(frames.front()->GetTagValueAsString(entry)); + } + return findings; + } + + void SetProperties(BaseDataPointer image, const FindingsListVectorType& findings) + { + for (const auto& finding : findings) { + for (const auto& entry : finding) { + const std::string propertyName = mitk::DICOMTagPathToPropertyName(entry.path); + auto property = mitk::TemporoSpatialStringProperty::New(); + property->SetValue(entry.value); + image->SetProperty(propertyName.c_str(), property); + } + } + } + +} diff --git a/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.h b/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.h new file mode 100644 index 0000000000..aa07d095cb --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkDicomRTIOHelper.h @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKDicomRTIOHelper_H +#define MITKDicomRTIOHelper_H + +#include +#include "mitkDICOMDatasetAccessingImageFrameInfo.h" + +#include + +namespace mitk { + class BaseData; + + typedef std::vector FindingsListVectorType; + typedef BaseData* BaseDataPointer; + + mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService(); + + FindingsListVectorType ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const DICOMDatasetAccessingImageFrameList& frames); + + void SetProperties(BaseDataPointer image, const FindingsListVectorType& findings); +} + +#endif diff --git a/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.cpp b/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.cpp new file mode 100644 index 0000000000..06bda58c5b --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.cpp @@ -0,0 +1,263 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkDicomRTIOMimeTypes.h" + +#include "mitkIOMimeTypes.h" + +#include "mitkDICOMDCMTKTagScanner.h" +#include "mitkDICOMTagPath.h" +#include "mitkDICOMTagsOfInterestService.h" +#include +#include + +#include + +#include +#include +#include +#include + +namespace mitk +{ + +std::vector DicomRTIOMimeTypes::Get() +{ + std::vector mimeTypes; + + // order matters here (descending rank for mime types) + mimeTypes.push_back(DICOMRT_DOSE_MIMETYPE().Clone()); + mimeTypes.push_back(DICOMRT_PLAN_MIMETYPE().Clone()); + mimeTypes.push_back(DICOMRT_STRUCT_MIMETYPE().Clone()); + + return mimeTypes; +} + +// Mime Types + +DicomRTIOMimeTypes::RTDoseMimeType::RTDoseMimeType() + : CustomMimeType(DICOMRT_DOSE_MIMETYPE_NAME()) +{ + std::string category = "DICOMRT"; + this->SetCategory(category); + this->SetComment("RTDose"); + + this->AddExtension("dcm"); +} + +bool DicomRTIOMimeTypes::RTDoseMimeType::AppliesTo(const std::string &path) const +{ + bool canRead( CustomMimeType::AppliesTo(path) ); + + if (!canRead) { + return false; + } + + if (!canReadByDicomFileReader(path)) { + return false; + } + + auto modality = GetModality(path); + + if (modality == "RTDOSE") { + return true; + } + else { + return false; + } +} + +std::string DicomRTIOMimeTypes::GetModality(const std::string & path) +{ + mitk::IDICOMTagsOfInterest* toiSrv = GetDicomTagsOfInterestService(); + + auto tagsOfInterest = toiSrv->GetTagsOfInterest(); + + DICOMTagPathList tagsOfInterestList; + for (const auto& tag : tagsOfInterest) { + tagsOfInterestList.push_back(tag.first); + } + + mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); + scanner->SetInputFiles({ path }); + scanner->AddTagPaths(tagsOfInterestList); + scanner->Scan(); + + mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); + auto findings = frames.front()->GetTagValueAsString(DICOMTagPath(0x0008, 0x0060)); + + std::string modality = findings.front().value; + return modality; +} + +bool DicomRTIOMimeTypes::canReadByDicomFileReader(const std::string & filename) +{ + mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New(); + selector->LoadBuiltIn3DConfigs(); + selector->SetInputFiles({ filename }); + + mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages(); + + if (reader.IsNull()) { + return false; + } + else { + return true; + } +} + +DicomRTIOMimeTypes::RTDoseMimeType* DicomRTIOMimeTypes::RTDoseMimeType::Clone() const +{ + return new RTDoseMimeType(*this); +} + +DicomRTIOMimeTypes::RTStructMimeType::RTStructMimeType() + : CustomMimeType(DICOMRT_STRUCT_MIMETYPE_NAME()) +{ + std::string category = "DICOMRT"; + this->SetCategory(category); + this->SetComment("RTStruct"); + + this->AddExtension("dcm"); +} + +bool DicomRTIOMimeTypes::RTStructMimeType::AppliesTo(const std::string &path) const +{ + bool canRead(CustomMimeType::AppliesTo(path)); + + if (!canRead) { + return false; + } + + auto modality = GetModality(path); + if (modality == "RTSTRUCT") { + return true; + } + else { + return false; + } +} + +DicomRTIOMimeTypes::RTStructMimeType* DicomRTIOMimeTypes::RTStructMimeType::Clone() const +{ + return new RTStructMimeType(*this); +} + +DicomRTIOMimeTypes::RTPlanMimeType::RTPlanMimeType() + : CustomMimeType(DICOMRT_PLAN_MIMETYPE_NAME()) +{ + std::string category = "DICOMRT"; + this->SetCategory(category); + this->SetComment("RTPLAN"); + + this->AddExtension("dcm"); +} + +bool DicomRTIOMimeTypes::RTPlanMimeType::AppliesTo(const std::string &path) const +{ + bool canRead(CustomMimeType::AppliesTo(path)); + + if (!canRead) { + return false; + } + + auto modality = GetModality(path); + if (modality == "RTPLAN") { + return true; + } + else { + return false; + } +} + +DicomRTIOMimeTypes::RTPlanMimeType* DicomRTIOMimeTypes::RTPlanMimeType::Clone() const +{ + return new RTPlanMimeType(*this); +} + + +DicomRTIOMimeTypes::RTDoseMimeType DicomRTIOMimeTypes::DICOMRT_DOSE_MIMETYPE() +{ + return RTDoseMimeType(); +} + +DicomRTIOMimeTypes::RTStructMimeType DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE() +{ + return RTStructMimeType(); +} + +DicomRTIOMimeTypes::RTPlanMimeType DicomRTIOMimeTypes::DICOMRT_PLAN_MIMETYPE() +{ + return RTPlanMimeType(); +} + +// Names +std::string DicomRTIOMimeTypes::DICOMRT_DOSE_MIMETYPE_NAME() +{ + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".dicomrt.dose"; + return name; +} + +std::string DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_NAME() +{ + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".dicomrt.struct"; + return name; +} + +std::string DicomRTIOMimeTypes::DICOMRT_PLAN_MIMETYPE_NAME() +{ + static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".dicomrt.plan"; + return name; +} + +// Descriptions + +std::string DicomRTIOMimeTypes::DICOMRT_DOSE_MIMETYPE_DESCRIPTION() +{ + static std::string description = "RTDOSE reader"; + return description; +} + +std::string DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_DESCRIPTION() +{ + static std::string description = "RTSTRUCT reader"; + return description; +} + +std::string DicomRTIOMimeTypes::DICOMRT_PLAN_MIMETYPE_DESCRIPTION() +{ + static std::string description = "RTPLAN reader"; + return description; +} + +mitk::IDICOMTagsOfInterest* DicomRTIOMimeTypes::GetDicomTagsOfInterestService() +{ + mitk::IDICOMTagsOfInterest* result = nullptr; + + std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); + if (!toiRegisters.empty()) + { + if (toiRegisters.size() > 1) + { + MITK_WARN << "Multiple DICOM tags of interest services found. Using just one."; + } + result = us::GetModuleContext()->GetService(toiRegisters.front()); + } + + return result; +} + +} diff --git a/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.h b/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.h new file mode 100644 index 0000000000..43f835ee4d --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkDicomRTIOMimeTypes.h @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKDicomRTIOMimeTypes_H +#define MITKDicomRTIOMimeTypes_H + +#include "mitkCustomMimeType.h" +#include + +#include + +namespace mitk { + +class DicomRTIOMimeTypes +{ +public: + + class RTDoseMimeType : public CustomMimeType + { + public: + RTDoseMimeType(); + virtual bool AppliesTo(const std::string &path) const override; + + virtual RTDoseMimeType* Clone() const override; + }; + + class RTStructMimeType : public CustomMimeType + { + public: + RTStructMimeType(); + virtual bool AppliesTo(const std::string &path) const override; + virtual RTStructMimeType* Clone() const override; + }; + + class RTPlanMimeType : public CustomMimeType + { + public: + RTPlanMimeType(); + virtual bool AppliesTo(const std::string &path) const override; + virtual RTPlanMimeType* Clone() const override; + }; + // Get all DicomRT Mime Types + static std::vector Get(); + + static RTDoseMimeType DICOMRT_DOSE_MIMETYPE(); + static RTStructMimeType DICOMRT_STRUCT_MIMETYPE(); + static RTPlanMimeType DICOMRT_PLAN_MIMETYPE(); + + static std::string DICOMRT_DOSE_MIMETYPE_NAME(); + static std::string DICOMRT_STRUCT_MIMETYPE_NAME(); + static std::string DICOMRT_PLAN_MIMETYPE_NAME(); + + static std::string DICOMRT_DOSE_MIMETYPE_DESCRIPTION(); + static std::string DICOMRT_STRUCT_MIMETYPE_DESCRIPTION(); + static std::string DICOMRT_PLAN_MIMETYPE_DESCRIPTION(); + + DicomRTIOMimeTypes() = delete; + DicomRTIOMimeTypes(const DicomRTIOMimeTypes&) = delete; + + static mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService(); + static bool canReadByDicomFileReader(const std::string & path); + static std::string GetModality(const std::string & path); +}; + +} + +#endif // MITKDicomRTIOMimeTypes_H diff --git a/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.cpp b/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.cpp new file mode 100644 index 0000000000..08ba6abb55 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.cpp @@ -0,0 +1,172 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkRTDoseReaderService.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "mitkDICOMDCMTKTagScanner.h" +#include "mitkDicomRTIOMimeTypes.h" +#include "mitkDicomRTIOHelper.h" + +#include "dcmtk/dcmrt/drtdose.h" + +#include +#include + +namespace mitk +{ + + RTDoseReaderService::RTDoseReaderService() : AbstractFileReader(CustomMimeType(mitk::DicomRTIOMimeTypes::DICOMRT_DOSE_MIMETYPE_NAME()), mitk::DicomRTIOMimeTypes::DICOMRT_DOSE_MIMETYPE_DESCRIPTION()) { + m_FileReaderServiceReg = RegisterService(); + } + + RTDoseReaderService::RTDoseReaderService(const RTDoseReaderService& other) : mitk::AbstractFileReader(other) + { + + } + + RTDoseReaderService::~RTDoseReaderService() {} + + template + void RTDoseReaderService::MultiplyGridScaling(itk::Image* image, float gridscale) + { + typedef itk::Image OutputImageType; + typedef itk::Image InputImageType; + + typedef itk::CastImageFilter CastFilterType; + typedef itk::ShiftScaleImageFilter ScaleFilterType; + typename CastFilterType::Pointer castFilter = CastFilterType::New(); + typename ScaleFilterType::Pointer scaleFilter = ScaleFilterType::New(); + + castFilter->SetInput(image); + scaleFilter->SetInput(castFilter->GetOutput()); + scaleFilter->SetScale(gridscale); + scaleFilter->Update(); + typename OutputImageType::Pointer scaledOutput = scaleFilter->GetOutput(); + this->scaledDoseImage = mitk::Image::New(); + + mitk::CastToMitkImage(scaledOutput, this->scaledDoseImage); + } + + std::vector > RTDoseReaderService::Read() + { + std::vector > result; + + + mitk::IDICOMTagsOfInterest* toiSrv = GetDicomTagsOfInterestService(); + + auto tagsOfInterest = toiSrv->GetTagsOfInterest(); + + DICOMTagPathList tagsOfInterestList; + for (const auto& tag : tagsOfInterest) { + tagsOfInterestList.push_back(tag.first); + } + + std::string location = GetInputLocation(); + mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New(); + selector->LoadBuiltIn3DConfigs(); + selector->SetInputFiles({ location }); + + mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages(); + reader->SetAdditionalTagsOfInterest(toiSrv->GetTagsOfInterest()); + + reader->SetInputFiles({ location }); + reader->AnalyzeInputFiles(); + reader->LoadImages(); + + if (reader->GetNumberOfOutputs() == 0) { + MITK_ERROR << "Could not determine a DICOM reader for this file" << std::endl; + return result; + } + + mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); + scanner->SetInputFiles({ location }); + scanner->AddTagPaths(tagsOfInterestList); + scanner->Scan(); + + mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); + if (frames.empty()) { + MITK_ERROR << "Error reading the RTDOSE file" << std::endl; + return result; + } + + const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(0); + + mitk::Image::Pointer originalImage = desc.GetMitkImage(); + + if (originalImage.IsNull()) + { + MITK_ERROR << "Error reading the RTDOSE file in mitk::DicomFileReader" << std::endl; + return result; + } + + DcmFileFormat fileformat; + OFCondition outp = fileformat.loadFile(location.c_str(), EXS_Unknown); + if (outp.bad()) + { + MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl; + return result; + } + DcmDataset *dataset = fileformat.getDataset(); + + DRTDoseIOD doseObject; + OFCondition DCMTKresult = doseObject.read(*dataset); + + if (DCMTKresult.bad()) + { + MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl; + return result; + } + + auto findingsGridScaling = frames.front()->GetTagValueAsString(DICOMTagPath(0x3004, 0x000e)); //(0x3004, 0x000e) is grid scaling + + double gridScaling; + if (findingsGridScaling.empty()) { + MITK_ERROR << "Could not find DoseGridScaling tag" << std::endl; + return result; + } + else { + gridScaling = boost::lexical_cast(findingsGridScaling.front().value); + } + + AccessByItk_1(originalImage, MultiplyGridScaling, gridScaling); + + auto statistics = this->scaledDoseImage->GetStatistics(); + double maxDose = statistics->GetScalarValueMax(); + + this->scaledDoseImage->SetPropertyList(originalImage->GetPropertyList()); + this->scaledDoseImage->SetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), mitk::GenericProperty::New(0.8*maxDose)); + auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames); + SetProperties(this->scaledDoseImage, findings); + + result.push_back(this->scaledDoseImage.GetPointer()); + return result; + } + + RTDoseReaderService* RTDoseReaderService::Clone() const + { + return new RTDoseReaderService(*this); + } +} diff --git a/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.h b/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.h new file mode 100644 index 0000000000..c07b62abdb --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTDoseReaderService.h @@ -0,0 +1,68 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef mitkRTDoseReaderService_h +#define mitkRTDoseReaderService_h + +#include + +#include +#include +#include + +namespace mitk +{ + /** + * \brief RTDoseReaderService reads DICOM files of modality RTDOSE. + */ + class MITKDICOMRTIO_EXPORT RTDoseReaderService : public mitk::AbstractFileReader + { + public: + RTDoseReaderService(const RTDoseReaderService& other); + RTDoseReaderService(); + + virtual ~RTDoseReaderService(); + + using AbstractFileReader::Read; + /** + * @brief Reads a dicom dataset from a RTDOSE file + * The method reads the PixelData from the DicomRT dose file and scales + * them with a factor for getting Gray-values instead of pixel-values. + * The Gray-values are stored in a mitkImage with a vtkColorTransferFunc. + * Relative values are used for coloring the image. The relative values are + * relative to a PrescriptionDose defined in the RT-Plan. If there is no + * RT-Plan file PrescriptionDose is set to 80% of the maximum dose. + */ + virtual std::vector > Read() override; + + private: + RTDoseReaderService* Clone() const override; + /** + * \brief Scales an image with a factor + * + * \param gridscale the factor to scale with + */ + template + void MultiplyGridScaling(itk::Image< TPixel, VImageDimension>* image, float gridscale); + + mitk::Image::Pointer scaledDoseImage; + us::ServiceRegistration m_FileReaderServiceReg; + }; + +} + +#endif diff --git a/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.cpp b/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.cpp new file mode 100644 index 0000000000..b59594787d --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.cpp @@ -0,0 +1,86 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkRTPlanReaderService.h" + +#include "mitkImage.h" +#include "mitkDICOMDCMTKTagScanner.h" +#include "mitkIOMimeTypes.h" +#include "mitkDicomRTIOHelper.h" +#include "mitkDICOMTagPath.h" +#include "mitkDICOMTagsOfInterestService.h" +#include "mitkDICOMDatasetAccessingImageFrameInfo.h" +#include "mitkDicomRTIOMimeTypes.h" + + +namespace mitk +{ + + RTPlanReaderService::RTPlanReaderService() : AbstractFileReader(CustomMimeType(mitk::DicomRTIOMimeTypes::DICOMRT_PLAN_MIMETYPE_NAME()), mitk::DicomRTIOMimeTypes::DICOMRT_PLAN_MIMETYPE_DESCRIPTION()) { + m_FileReaderServiceReg = RegisterService(); + + } + + RTPlanReaderService::RTPlanReaderService(const RTPlanReaderService& other) : mitk::AbstractFileReader(other) + { + } + + RTPlanReaderService::~RTPlanReaderService() {} + + std::vector > RTPlanReaderService::Read() + { + std::vector > result; + auto DICOMTagsOfInterestService = GetDicomTagsOfInterestService(); + auto tagsOfInterest = DICOMTagsOfInterestService->GetTagsOfInterest(); + DICOMTagPathList tagsOfInterestList; + for (const auto& tag : tagsOfInterest) { + tagsOfInterestList.push_back(tag.first); + } + + std::string location = GetInputLocation(); + mitk::StringList files = { location }; + mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); + scanner->SetInputFiles(files); + scanner->AddTagPaths(tagsOfInterestList); + scanner->Scan(); + + mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); + if (frames.empty()) { + MITK_ERROR << "Error reading the RTPLAN file" << std::endl; + return result; + } + + auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames); + + //just create empty image. No image information available in RTPLAN. But properties will be attached. + Image::Pointer dummyImage = Image::New(); + mitk::PixelType pt = mitk::MakeScalarPixelType(); + unsigned int dim[] = { 1,1}; + dummyImage->Initialize(pt, 2, dim); + SetProperties(dummyImage, findings); + + result.push_back(dummyImage.GetPointer()); + + return result; + } + + RTPlanReaderService* RTPlanReaderService::Clone() const + { + return new RTPlanReaderService(*this); + } + +} diff --git a/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.h b/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.h new file mode 100644 index 0000000000..11cff9e6e4 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTPlanReaderService.h @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef mitkRTPlanReaderService_h +#define mitkRTPlanReaderService_h + +#include "mitkAbstractFileReader.h" + +#include + +#include "mitkIDICOMTagsOfInterest.h" +#include "mitkDICOMDatasetAccessingImageFrameInfo.h" + +#include + +#include "MitkDicomRTIOExports.h" + +namespace mitk +{ + /** + * \brief RTPlanReaderService reads DICOM files of modality RTPLAN. + \details The tags are defined in mitk::GetDefaultDICOMTagsOfInterest() in Module MitkDicomReader. They are stored as TemporoSpatialStringProperty. + with the key as their respective DICOM tags. + \note No image information is in RTPLAN. + */ + class MITKDICOMRTIO_EXPORT RTPlanReaderService : public mitk::AbstractFileReader + { + + public: + RTPlanReaderService(); + RTPlanReaderService(const RTPlanReaderService& other); + + using AbstractFileReader::Read; + /** + * \brief Reads the file (only tags). + @details DICOMDCMTKTagScanner is used to read the tags + \note No image information is in RTPLAN. + \sa mitk::GetDefaultDICOMTagsOfInterest() for tags that are read + */ + virtual std::vector > Read() override; + + virtual ~RTPlanReaderService(); + + private: + RTPlanReaderService* Clone() const override; + + us::ServiceRegistration m_FileReaderServiceReg; + }; +} + +#endif diff --git a/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.cpp b/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.cpp new file mode 100644 index 0000000000..85b895af2d --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.cpp @@ -0,0 +1,292 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkRTStructureSetReaderService.h" + +#include "mitkDicomRTIOMimeTypes.h" +#include "mitkDicomRTIOHelper.h" +#include +#include + +#include "dcmtk/dcmrt/drtstrct.h" + +namespace mitk +{ + RTStructureSetReaderService::RTStructureSetReaderService() : AbstractFileReader(CustomMimeType(mitk::DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_NAME()), mitk::DicomRTIOMimeTypes::DICOMRT_STRUCT_MIMETYPE_DESCRIPTION()) { + m_FileReaderServiceReg = RegisterService(); + } + + RTStructureSetReaderService::RTStructureSetReaderService(const RTStructureSetReaderService& other) : mitk::AbstractFileReader(other) + { + } + + RTStructureSetReaderService::~RTStructureSetReaderService() {} + + RTStructureSetReaderService::RoiEntry::RoiEntry() + { + Number = 0; + DisplayColor[0] = 1.0; + DisplayColor[1] = 0.0; + DisplayColor[2] = 0.0; + ContourModelSet = mitk::ContourModelSet::New(); + } + + RTStructureSetReaderService::RoiEntry::RoiEntry(const RoiEntry& src) + { + Number = src.Number; + Name = src.Name; + Description = src.Description; + DisplayColor[0] = src.DisplayColor[0]; + DisplayColor[1] = src.DisplayColor[1]; + DisplayColor[2] = src.DisplayColor[2]; + ContourModelSet = mitk::ContourModelSet::New(); + SetPolyData(src.ContourModelSet); + } + + RTStructureSetReaderService::RoiEntry::~RoiEntry() {} + + RTStructureSetReaderService::RoiEntry& RTStructureSetReaderService:: + RoiEntry::operator =(const RoiEntry& src) + { + Number = src.Number; + Name = src.Name; + Description = src.Description; + DisplayColor[0] = src.DisplayColor[0]; + DisplayColor[1] = src.DisplayColor[1]; + DisplayColor[2] = src.DisplayColor[2]; + SetPolyData(src.ContourModelSet); + return (*this); + } + + void RTStructureSetReaderService::RoiEntry:: + SetPolyData(mitk::ContourModelSet::Pointer roiPolyData) + { + if (roiPolyData == this->ContourModelSet) + { + return; + } + + this->ContourModelSet = roiPolyData; + } + + size_t RTStructureSetReaderService::GetNumberOfROIs() const + { + return this->ROISequenceVector.size(); + } + + RTStructureSetReaderService::RoiEntry* RTStructureSetReaderService:: + FindRoiByNumber(unsigned int roiNum) + { + for (unsigned int i = 0; i < this->ROISequenceVector.size(); ++i) + { + if (this->ROISequenceVector[i].Number == roiNum) + { + return &this->ROISequenceVector[i]; + } + } + + return nullptr; + } + + std::vector > RTStructureSetReaderService::Read() + { + std::vector > result; + + std::string location = GetInputLocation(); + + auto DICOMTagsOfInterestService = GetDicomTagsOfInterestService(); + auto tagsOfInterest = DICOMTagsOfInterestService->GetTagsOfInterest(); + DICOMTagPathList tagsOfInterestList; + for (const auto& tag : tagsOfInterest) { + tagsOfInterestList.push_back(tag.first); + } + + mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); + scanner->SetInputFiles({ location }); + scanner->AddTagPaths(tagsOfInterestList); + scanner->Scan(); + + mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); + if (frames.empty()) { + MITK_ERROR << "Error reading the RTSTRUCT file" << std::endl; + return result; + } + + auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames); + + DcmFileFormat file; + OFCondition output = file.loadFile(location.c_str(), EXS_Unknown); + + if (output.bad()) + { + MITK_ERROR << "Can't read the file" << std::endl; + return result; + } + + DcmDataset* dataset = file.getDataset(); + + DRTStructureSetIOD structureSetObject; + OFCondition outp = structureSetObject.read(*dataset); + + if (!outp.good()) + { + MITK_ERROR << "Error reading the file" << std::endl; + return result; + } + + DRTStructureSetROISequence& roiSequence = + structureSetObject.getStructureSetROISequence(); + + if (!roiSequence.gotoFirstItem().good()) + { + MITK_ERROR << "Error reading the structure sequence" << std::endl; + return result; + } + + do + { + DRTStructureSetROISequence::Item& currentSequence = + roiSequence.getCurrentItem(); + + if (!currentSequence.isValid()) + { + continue; + } + + OFString roiName; + OFString roiDescription; + Sint32 roiNumber; + RoiEntry roi; + + currentSequence.getROIName(roiName); + currentSequence.getROIDescription(roiDescription); + currentSequence.getROINumber(roiNumber); + + roi.Name = roiName.c_str(); + roi.Description = roiDescription.c_str(); + roi.Number = roiNumber; + + this->ROISequenceVector.push_back(roi); + } while (roiSequence.gotoNextItem().good()); + + Sint32 refRoiNumber; + DRTROIContourSequence& roiContourSeqObject = + structureSetObject.getROIContourSequence(); + + if (!roiContourSeqObject.gotoFirstItem().good()) + { + MITK_ERROR << "Error reading the contour sequence" << std::endl; + return result; + } + + do + { + mitk::ContourModelSet::Pointer contourSet = mitk::ContourModelSet::New(); + DRTROIContourSequence::Item& currentRoiObject = + roiContourSeqObject.getCurrentItem(); + + if (!currentRoiObject.isValid()) + { + continue; + } + + currentRoiObject.getReferencedROINumber(refRoiNumber); + DRTContourSequence& contourSeqObject = + currentRoiObject.getContourSequence(); + + if (contourSeqObject.getNumberOfItems() > 0 && contourSeqObject.gotoFirstItem().good()) + { + do + { + DRTContourSequence::Item& contourItem = + contourSeqObject.getCurrentItem(); + + if (!contourItem.isValid()) + { + continue; + } + + OFString contourNumber; + OFString numberOfPoints; + OFVector contourData_LPS; + mitk::ContourModel::Pointer contourSequence = + mitk::ContourModel::New(); + + contourItem.getContourNumber(contourNumber); + contourItem.getNumberOfContourPoints(numberOfPoints); + contourItem.getContourData(contourData_LPS); + + for (unsigned int i = 0; i < contourData_LPS.size() / 3; i++) + { + mitk::Point3D point; + point[0] = contourData_LPS.at(3 * i); + point[1] = contourData_LPS.at(3 * i + 1); + point[2] = contourData_LPS.at(3 * i + 2); + contourSequence->AddVertex(point); + } + + contourSequence->Close(); + contourSet->AddContourModel(contourSequence); + } while (contourSeqObject.gotoNextItem().good()); + } + else + { + MITK_WARN << "contourSeqObject has no items in sequence. Object is neglected and not read. Struct name: " << this->FindRoiByNumber(refRoiNumber)->Name << std::endl; + } + + RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); + + if (refROI == NULL) + { + MITK_ERROR << "Can not find references ROI" << std::endl; + continue; + } + + Sint32 roiColor; + + for (unsigned int j = 0; j < 3; j++) + { + currentRoiObject.getROIDisplayColor(roiColor, j); + refROI->DisplayColor[j] = roiColor / 255.0; + } + + refROI->ContourModelSet = contourSet; + contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); + contourSet->SetProperty("contour.color", mitk::ColorProperty::New( + refROI->DisplayColor[0], + refROI->DisplayColor[1], + refROI->DisplayColor[2])); + + } while (roiContourSeqObject.gotoNextItem().good()); + + for (auto const& aROI : ROISequenceVector) + { + result.push_back(aROI.ContourModelSet.GetPointer()); + result.at(result.size() - 1)->SetProperty("name", aROI.ContourModelSet->GetProperty("name")); + result.at(result.size() - 1)->SetProperty("color", aROI.ContourModelSet->GetProperty("contour.color")); + result.at(result.size() - 1)->SetProperty("contour.color", aROI.ContourModelSet->GetProperty("contour.color")); + SetProperties(result.at(result.size() - 1).GetPointer(), findings); + } + + return result; + } + + RTStructureSetReaderService* RTStructureSetReaderService::Clone() const + { + return new RTStructureSetReaderService(*this); + } + +} diff --git a/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.h b/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.h new file mode 100644 index 0000000000..105559dcf1 --- /dev/null +++ b/Modules/DicomRT/autoload/IO/mitkRTStructureSetReaderService.h @@ -0,0 +1,89 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRTSTRUCTURESETREADER_H +#define MITKRTSTRUCTURESETREADER_H + +#include + +#include "MitkDicomRTIOExports.h" +#include + +#include + +namespace mitk +{ + class MITKDICOMRTIO_EXPORT RTStructureSetReaderService : public mitk::AbstractFileReader + { + + /** + * Represent a region of interest (ROI) + */ + class RoiEntry + { + public: + RoiEntry(); + RoiEntry(const RoiEntry& src); + virtual ~RoiEntry(); + RoiEntry& operator=(const RoiEntry& src); + + void SetPolyData(ContourModelSet::Pointer roiPolyData); + + unsigned int Number; + std::string Name; + std::string Description; + double DisplayColor[3]; + mitk::ContourModelSet::Pointer ContourModelSet; + }; + + public: + RTStructureSetReaderService(); + RTStructureSetReaderService(const RTStructureSetReaderService& other); + + virtual ~RTStructureSetReaderService(); + + /** + * @brief Reading a RT StructureSet from the DICOM file and returns the ROIs + * (region of interest) as a ContourModelSet. One ContourModelSet represent + * one ROI. A ContourModelSet contains ContourModels which represent the + * single structures. + */ + using AbstractFileReader::Read; + virtual std::vector > Read() override; + + private: + RTStructureSetReaderService* Clone() const override; + + /** + * containing the ROIs meta information like name number and description + */ + std::vector ROISequenceVector; + + /** + * Returns the number of ROIs from the ROISequenceVector + */ + size_t GetNumberOfROIs() const; + + /** + * Returns the relevant ROI from the ROISequenceVector by its number + */ + RoiEntry* FindRoiByNumber(unsigned int roiNum); + + us::ServiceRegistration m_FileReaderServiceReg; + }; +} + +#endif // MITKRTSTRUCTURESETREADER_H diff --git a/Modules/DicomRT/files.cmake b/Modules/DicomRT/files.cmake index bbb35f627c..64210e3cf4 100644 --- a/Modules/DicomRT/files.cmake +++ b/Modules/DicomRT/files.cmake @@ -1,21 +1,18 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") SET(CPP_FILES - mitkRTDoseReader.cpp - mitkRTPlanReader.cpp mitkRTConstants.cpp mitkIsoDoseLevel.cpp mitkIsoDoseLevelCollections.cpp mitkIsoDoseLevelSetProperty.cpp mitkIsoDoseLevelVectorProperty.cpp - mitkRTStructureSetReader.cpp mitkDoseImageVtkMapper2D.cpp mitkIsoLevelsGenerator.cpp mitkDoseNodeHelper.cpp ) set(TPP_FILES ) set(MOC_H_FILES ) diff --git a/Modules/DicomRT/include/mitkRTDoseReader.h b/Modules/DicomRT/include/mitkRTDoseReader.h deleted file mode 100644 index a170bb6226..0000000000 --- a/Modules/DicomRT/include/mitkRTDoseReader.h +++ /dev/null @@ -1,76 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#ifndef mitkDicomRTReader_h -#define mitkDicomRTReader_h - -#include - -#include -#include -#include - -namespace mitk -{ - /** - * \brief RTDoseReader reads DICOM files of modality RTDOSE. - */ - class MITKDICOMRT_EXPORT RTDoseReader : public mitk::AbstractFileReader - { - - public: - RTDoseReader(const RTDoseReader& other); - RTDoseReader(); - - /** - * @brief Reads a dicom dataset from a RTDOSE file - * @param filename The path with the dose file - * @return Returns a mitkDataNode::Pointer in which a mitk::Image is stored - * - * The method reads the PixelData from the DicomRT dose file and scales - * them with a factor for getting Gray-values instead of pixel-values. - * The Gray-values are stored in a mitkImage with a vtkColorTransferFunc. - * Relative values are used for coloring the image. The relative values are - * relative to a PrescriptionDose defined in the RT-Plan. If there is no - * RT-Plan file PrescriptionDose is set to 80% of the maximum dose. - */ - //mitk::DataNode::Pointer LoadRTDose(const char* filename); - - virtual ~RTDoseReader(); - - using AbstractFileReader::Read; - virtual std::vector > Read() override; - - private: - RTDoseReader* Clone() const override; - /** - * \brief Scales an image with a factor - * - * \param gridscale the factor to scale with - */ - template - void MultiplyGridScaling(itk::Image< TPixel, VImageDimension>* image, float gridscale); - - mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService(); - - mitk::Image::Pointer scaledDoseImage; - us::ServiceRegistration m_ServiceReg; - }; - -} - -#endif diff --git a/Modules/DicomRT/include/mitkRTStructureSetReader.h b/Modules/DicomRT/include/mitkRTStructureSetReader.h deleted file mode 100644 index e73892adcb..0000000000 --- a/Modules/DicomRT/include/mitkRTStructureSetReader.h +++ /dev/null @@ -1,98 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#ifndef MITKRTSTRUCTURESETREADER_H -#define MITKRTSTRUCTURESETREADER_H - -#include - -#include -#include -#include -#include -#include - -#include - -namespace mitk -{ - class MITKDICOMRT_EXPORT RTStructureSetReader : public mitk::AbstractFileReader - { - typedef std::vector FindingsListVectorType; - - /** - * Represent a region of interest (ROI) - */ - class RoiEntry - { - public: - RoiEntry(); - RoiEntry(const RoiEntry& src); - virtual ~RoiEntry(); - RoiEntry& operator=(const RoiEntry& src); - - void SetPolyData(ContourModelSet::Pointer roiPolyData); - - unsigned int Number; - std::string Name; - std::string Description; - double DisplayColor[3]; - mitk::ContourModelSet::Pointer ContourModelSet; - }; - - public: - RTStructureSetReader(); - RTStructureSetReader(const RTStructureSetReader& other); - - virtual ~RTStructureSetReader(); - - /** - * @brief Reading a RT StructureSet from the DICOM file and returns the ROIs - * (region of interest) as a ContourModelSet. One ContourModelSet represent - * one ROI. A ContourModelSet contains ContourModels which represent the - * single structures. - */ - using AbstractFileReader::Read; - virtual std::vector > Read() override; - - private: - RTStructureSetReader* Clone() const override; - - FindingsListVectorType ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const DICOMDatasetAccessingImageFrameList& frames) const; - void SetProperties(BaseData::Pointer data, const FindingsListVectorType& findings) const; - mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService() const; - - /** - * containing the ROIs meta information like name number and description - */ - std::vector ROISequenceVector; - - /** - * Returns the number of ROIs from the ROISequenceVector - */ - size_t GetNumberOfROIs(); - - /** - * Returns the relevant ROI from the ROISequenceVector by its number - */ - RoiEntry* FindRoiByNumber(unsigned int roiNum); - - us::ServiceRegistration m_ServiceReg; - IDICOMTagsOfInterest* m_DICOMTagsOfInterestService; - }; -} - -#endif // MITKRTSTRUCTURESETREADER_H diff --git a/Modules/DicomRT/mitkDICOMRTIOActivator.cpp b/Modules/DicomRT/mitkDICOMRTIOActivator.cpp deleted file mode 100644 index 504c808afe..0000000000 --- a/Modules/DicomRT/mitkDICOMRTIOActivator.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include "mitkRTDoseReader.h" - -#include -#include - - -namespace mitk { - -/* - * This is the module activator for the "VirtuosIO" module. - */ -class DICOMRTIOActivator : public us::ModuleActivator -{ -public: - - void Load(us::ModuleContext* context) - { - m_RTDoseReader = new RTDoseReader(); - } - - void Unload(us::ModuleContext* ) - { - delete m_RTDoseReader; - } - -private: - mitk::RTDoseReader* m_RTDoseReader; -}; -} - -US_EXPORT_MODULE_ACTIVATOR(mitk::DICOMRTIOActivator) \ No newline at end of file diff --git a/Modules/DicomRT/src/mitkRTDoseReader.cpp b/Modules/DicomRT/src/mitkRTDoseReader.cpp deleted file mode 100644 index d61b9a5c77..0000000000 --- a/Modules/DicomRT/src/mitkRTDoseReader.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "mitkRTDoseReader.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usModuleContext.h" -#include "usGetModuleContext.h" - -#include "dcmtk/dcmrt/drtdose.h" - -#include -#include - -namespace mitk -{ - - RTDoseReader::RTDoseReader() : AbstractFileReader(IOMimeTypes::DICOM_MIMETYPE_NAME(), "DICOM RTDose File Reader") { - m_ServiceReg = RegisterService(); - } - - RTDoseReader::RTDoseReader(const RTDoseReader& other) : mitk::AbstractFileReader(other) - { - - } - - RTDoseReader::~RTDoseReader(){} - - template - void RTDoseReader::MultiplyGridScaling(itk::Image* image, float gridscale) - { - typedef itk::Image OutputImageType; - typedef itk::Image InputImageType; - - typedef itk::CastImageFilter CastFilterType; - typedef itk::ShiftScaleImageFilter ScaleFilterType; - typename CastFilterType::Pointer castFilter = CastFilterType::New(); - typename ScaleFilterType::Pointer scaleFilter = ScaleFilterType::New(); - - castFilter->SetInput(image); - scaleFilter->SetInput(castFilter->GetOutput()); - scaleFilter->SetScale(gridscale); - scaleFilter->Update(); - typename OutputImageType::Pointer scaledOutput = scaleFilter->GetOutput(); - this->scaledDoseImage = mitk::Image::New(); - - mitk::CastToMitkImage(scaledOutput, this->scaledDoseImage); - } - - mitk::IDICOMTagsOfInterest* RTDoseReader::GetDicomTagsOfInterestService() - { - mitk::IDICOMTagsOfInterest* result = nullptr; - - std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); - if (!toiRegisters.empty()) - { - if (toiRegisters.size() > 1) - { - MITK_WARN << "Multiple DICOM tags of interest services found. Using just one."; - } - result = us::GetModuleContext()->GetService(toiRegisters.front()); - } - - return result; - } - - std::vector > RTDoseReader::Read() - { - std::vector > result; - - DICOMTag referencedRTPlan(0x300c, 0x0002); - mitk::IDICOMTagsOfInterest* toiSrv = GetDicomTagsOfInterestService(); - if (toiSrv) - { - toiSrv->AddTagOfInterest(referencedRTPlan); - } - - std::string location = GetInputLocation(); - mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New(); - selector->LoadBuiltIn3DConfigs(); - selector->SetInputFiles({ location }); - - mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages(); - reader->SetAdditionalTagsOfInterest(toiSrv->GetTagsOfInterest()); - - reader->SetInputFiles({ location }); - reader->AnalyzeInputFiles(); - reader->LoadImages(); - - if (reader->GetNumberOfOutputs() == 0){ - MITK_ERROR << "Could not determine a DICOM reader for this file" << std::endl; - return result; - } - - const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(0); - - mitk::Image::Pointer originalImage = desc.GetMitkImage(); - - if (originalImage.IsNull()) - { - MITK_ERROR << "Error reading the RTDOSE file in mitk::DicomFileReader" << std::endl; - return result; - } - - DcmFileFormat fileformat; - OFCondition outp = fileformat.loadFile(location.c_str(), EXS_Unknown); - if (outp.bad()) - { - MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl; - return result; - } - DcmDataset *dataset = fileformat.getDataset(); - - DRTDoseIOD doseObject; - OFCondition DCMTKresult = doseObject.read(*dataset); - - if (DCMTKresult.bad()) - { - MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl; - return result; - } - - OFString gridScaling; - Float32 gridscale; - - doseObject.getDoseGridScaling(gridScaling); - gridscale = OFStandard::atof(gridScaling.c_str()); - - AccessByItk_1(originalImage, MultiplyGridScaling, gridscale); - - auto statistics = this->scaledDoseImage->GetStatistics(); - double maxDose = statistics->GetScalarValueMax(); - - this->scaledDoseImage->SetPropertyList(originalImage->GetPropertyList()); - this->scaledDoseImage->SetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), mitk::GenericProperty::New(0.8*maxDose)); - - result.push_back(this->scaledDoseImage.GetPointer()); - return result; - } - - RTDoseReader* RTDoseReader::Clone() const - { - return new RTDoseReader(*this); - } - -} diff --git a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp b/Modules/DicomRT/src/mitkRTStructureSetReader.cpp deleted file mode 100644 index 714324efc4..0000000000 --- a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include "mitkRTStructureSetReader.h" - -#include -#include -#include -#include - -#include "dcmtk/dcmrt/drtstrct.h" - -namespace mitk -{ - RTStructureSetReader::RTStructureSetReader() : AbstractFileReader(IOMimeTypes::DICOM_MIMETYPE_NAME(), "DICOM RTSTRUCT File Reader") { - m_ServiceReg = RegisterService(); - m_DICOMTagsOfInterestService = GetDicomTagsOfInterestService(); - } - - RTStructureSetReader::RTStructureSetReader(const RTStructureSetReader& other) : mitk::AbstractFileReader(other) - { - - } - - RTStructureSetReader::~RTStructureSetReader() {} - - RTStructureSetReader::RoiEntry::RoiEntry() - { - Number = 0; - DisplayColor[0] = 1.0; - DisplayColor[1] = 0.0; - DisplayColor[2] = 0.0; - ContourModelSet = mitk::ContourModelSet::New(); - } - - RTStructureSetReader::RoiEntry::RoiEntry(const RoiEntry& src) - { - Number = src.Number; - Name = src.Name; - Description = src.Description; - DisplayColor[0] = src.DisplayColor[0]; - DisplayColor[1] = src.DisplayColor[1]; - DisplayColor[2] = src.DisplayColor[2]; - ContourModelSet = mitk::ContourModelSet::New(); - SetPolyData(src.ContourModelSet); - } - - RTStructureSetReader::RoiEntry::~RoiEntry() {} - - RTStructureSetReader::RoiEntry& RTStructureSetReader:: - RoiEntry::operator =(const RoiEntry& src) - { - Number = src.Number; - Name = src.Name; - Description = src.Description; - DisplayColor[0] = src.DisplayColor[0]; - DisplayColor[1] = src.DisplayColor[1]; - DisplayColor[2] = src.DisplayColor[2]; - SetPolyData(src.ContourModelSet); - return (*this); - } - - void RTStructureSetReader::RoiEntry:: - SetPolyData(mitk::ContourModelSet::Pointer roiPolyData) - { - if (roiPolyData == this->ContourModelSet) - { - return; - } - - this->ContourModelSet = roiPolyData; - } - - size_t RTStructureSetReader::GetNumberOfROIs() - { - return this->ROISequenceVector.size(); - } - - RTStructureSetReader::RoiEntry* RTStructureSetReader:: - FindRoiByNumber(unsigned int roiNum) - { - for (unsigned int i = 0; i < this->ROISequenceVector.size(); ++i) - { - if (this->ROISequenceVector[i].Number == roiNum) - { - return &this->ROISequenceVector[i]; - } - } - - return nullptr; - } - - std::vector > RTStructureSetReader::Read() - { - std::vector > result; - - std::string location = GetInputLocation(); - - auto tagsOfInterest = m_DICOMTagsOfInterestService->GetTagsOfInterest(); - DICOMTagPathList tagsOfInterestList; - for (const auto& tag : tagsOfInterest){ - tagsOfInterestList.push_back(tag.first); - } - - - mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); - scanner->SetInputFiles({ location }); - scanner->AddTagPaths(tagsOfInterestList); - scanner->Scan(); - - mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); - if (frames.empty()){ - MITK_ERROR << "Error reading the RTSTRUCT file" << std::endl; - return result; - } - - auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames); - - DcmFileFormat file; - OFCondition output = file.loadFile(location.c_str(), EXS_Unknown); - - if (output.bad()) - { - MITK_ERROR << "Can't read the file" << std::endl; - return result; - } - - DcmDataset* dataset = file.getDataset(); - - DRTStructureSetIOD structureSetObject; - OFCondition outp = structureSetObject.read(*dataset); - - if (!outp.good()) - { - MITK_ERROR << "Error reading the file" << std::endl; - return result; - } - - DRTStructureSetROISequence& roiSequence = - structureSetObject.getStructureSetROISequence(); - - if (!roiSequence.gotoFirstItem().good()) - { - MITK_ERROR << "Error reading the structure sequence" << std::endl; - return result; - } - - do - { - DRTStructureSetROISequence::Item& currentSequence = - roiSequence.getCurrentItem(); - - if (!currentSequence.isValid()) - { - continue; - } - - OFString roiName; - OFString roiDescription; - Sint32 roiNumber; - RoiEntry roi; - - currentSequence.getROIName(roiName); - currentSequence.getROIDescription(roiDescription); - currentSequence.getROINumber(roiNumber); - - roi.Name = roiName.c_str(); - roi.Description = roiDescription.c_str(); - roi.Number = roiNumber; - - this->ROISequenceVector.push_back(roi); - } while (roiSequence.gotoNextItem().good()); - - Sint32 refRoiNumber; - DRTROIContourSequence& roiContourSeqObject = - structureSetObject.getROIContourSequence(); - - if (!roiContourSeqObject.gotoFirstItem().good()) - { - MITK_ERROR << "Error reading the contour sequence" << std::endl; - return result; - } - - do - { - mitk::ContourModelSet::Pointer contourSet = mitk::ContourModelSet::New(); - DRTROIContourSequence::Item& currentRoiObject = - roiContourSeqObject.getCurrentItem(); - - if (!currentRoiObject.isValid()) - { - continue; - } - - currentRoiObject.getReferencedROINumber(refRoiNumber); - DRTContourSequence& contourSeqObject = - currentRoiObject.getContourSequence(); - - if (contourSeqObject.getNumberOfItems()>0 && contourSeqObject.gotoFirstItem().good()) - { - do - { - DRTContourSequence::Item& contourItem = - contourSeqObject.getCurrentItem(); - - if (!contourItem.isValid()) - { - continue; - } - - OFString contourNumber; - OFString numberOfPoints; - OFVector contourData_LPS; - mitk::ContourModel::Pointer contourSequence = - mitk::ContourModel::New(); - - contourItem.getContourNumber(contourNumber); - contourItem.getNumberOfContourPoints(numberOfPoints); - contourItem.getContourData(contourData_LPS); - - for (unsigned int i = 0; i < contourData_LPS.size() / 3; i++) - { - mitk::Point3D point; - point[0] = contourData_LPS.at(3 * i); - point[1] = contourData_LPS.at(3 * i + 1); - point[2] = contourData_LPS.at(3 * i + 2); - contourSequence->AddVertex(point); - } - - contourSequence->Close(); - contourSet->AddContourModel(contourSequence); - } while (contourSeqObject.gotoNextItem().good()); - } - else - { - MITK_WARN << "contourSeqObject has no items in sequence. Object is neglected and not read. Struct name: " << this->FindRoiByNumber(refRoiNumber)->Name << std::endl; - } - - RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); - - if (refROI == nullptr) - { - MITK_ERROR << "Can not find references ROI" << std::endl; - continue; - } - - Sint32 roiColor; - - for (unsigned int j = 0; j < 3; j++) - { - currentRoiObject.getROIDisplayColor(roiColor, j); - refROI->DisplayColor[j] = roiColor / 255.0; - } - - refROI->ContourModelSet = contourSet; - contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); - contourSet->SetProperty("contour.color", mitk::ColorProperty::New( - refROI->DisplayColor[0], - refROI->DisplayColor[1], - refROI->DisplayColor[2])); - - } while (roiContourSeqObject.gotoNextItem().good()); - - for (auto const& aROI : ROISequenceVector) - { - result.push_back(aROI.ContourModelSet.GetPointer()); - result.at(result.size() - 1)->SetProperty("name", aROI.ContourModelSet->GetProperty("name")); - result.at(result.size() - 1)->SetProperty("color", aROI.ContourModelSet->GetProperty("contour.color")); - result.at(result.size() - 1)->SetProperty("contour.color", aROI.ContourModelSet->GetProperty("contour.color")); - SetProperties(result.at(result.size() - 1).GetPointer(), findings); - } - - return result; - } - - RTStructureSetReader* RTStructureSetReader::Clone() const - { - return new RTStructureSetReader(*this); - } - - RTStructureSetReader::FindingsListVectorType RTStructureSetReader::ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const mitk::DICOMDatasetAccessingImageFrameList& frames) const - { - std::vector findings; - for (const auto& entry : pathsOfInterest){ - findings.push_back(frames.front()->GetTagValueAsString(entry)); - } - return findings; - } - - void RTStructureSetReader::SetProperties(BaseData::Pointer data, const FindingsListVectorType& findings) const - { - for (const auto& finding : findings){ - for (const auto& entry : finding){ - const std::string propertyName = mitk::DICOMTagPathToPropertyName(entry.path); - auto property = mitk::TemporoSpatialStringProperty::New(); - property->SetValue(entry.value); - data->SetProperty(propertyName.c_str(), property); - } - } - } - - mitk::IDICOMTagsOfInterest* RTStructureSetReader::GetDicomTagsOfInterestService() const - { - mitk::IDICOMTagsOfInterest* result = nullptr; - - std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); - if (!toiRegisters.empty()) - { - if (toiRegisters.size() > 1) - { - MITK_WARN << "Multiple DICOM tags of interest services found. Using just one."; - } - result = us::GetModuleContext()->GetService(toiRegisters.front()); - } - - return result; - } - -} diff --git a/Modules/DicomRT/test/files.cmake b/Modules/DicomRT/test/files.cmake index e589e7598e..104a1aa047 100644 --- a/Modules/DicomRT/test/files.cmake +++ b/Modules/DicomRT/test/files.cmake @@ -1,5 +1,5 @@ SET(MODULE_TESTS - mitkRTStructureSetReaderTest.cpp - mitkRTDoseReaderTest.cpp - mitkRTPlanReaderTest.cpp + mitkRTStructureSetReaderServiceTest.cpp + mitkRTDoseReaderServiceTest.cpp + mitkRTPlanReaderServiceTest.cpp ) diff --git a/Modules/DicomRT/test/mitkRTDoseReaderServiceTest.cpp b/Modules/DicomRT/test/mitkRTDoseReaderServiceTest.cpp new file mode 100644 index 0000000000..39a9241b8f --- /dev/null +++ b/Modules/DicomRT/test/mitkRTDoseReaderServiceTest.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include +#include +#include "mitkTemporoSpatialStringProperty.h" +#include + +class mitkRTDoseReaderServiceTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRTDoseReaderServiceTestSuite); + MITK_TEST(TestDoseImage); + MITK_TEST(TestProperties); + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::Image::ConstPointer m_doseImage; + mitk::Image::ConstPointer m_referenceImage; + +public: + + void setUp() override + { + m_referenceImage = mitk::IOUtil::LoadImage(GetTestDataFilePath("RT/Dose/RT_Dose.nrrd")); + m_doseImage = mitk::IOUtil::LoadImage(GetTestDataFilePath("RT/Dose/RD.dcm")); + } + + void TestDoseImage() + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("image should not be null", m_doseImage.IsNotNull(), true); + CPPUNIT_ASSERT_EQUAL_MESSAGE("reference image and image should be equal", true, mitk::Equal(*m_doseImage, *m_referenceImage, mitk::eps, true)); + } + + void TestProperties() { + CheckStringProperty("DICOM.0008.0060", "RTDOSE"); //Modality + auto prescibedDoseProperty = m_doseImage->GetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str()); + auto prescribedDoseGenericProperty = dynamic_cast*>(prescibedDoseProperty.GetPointer()); + double actualPrescribedDose = prescribedDoseGenericProperty->GetValue(); + double expectedPrescribedDose = 65535 * 0.0010494648*0.8; + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("prescribed dose property is not as expected", expectedPrescribedDose, actualPrescribedDose, 1e-5); + CheckStringProperty("DICOM.0020.000D", "1.2.826.0.1.3680043.8.176.2013826104517910.408.3433258507"); //StudyInstanceUID + CheckStringProperty("DICOM.3004.000E", "0.0010494648"); //DoseGridScaling + CheckStringProperty("DICOM.300C.0002.[0].0008.1155", "1.2.826.0.1.3680043.8.176.2013826104526987.672.1228523524"); //ReferencedRTPlanSequence.ReferencedSOPInstanceUID + } + + void CheckStringProperty(const std::string& propertyName, const std::string& expectedPropertyValue) + { + auto actualProperty = m_doseImage->GetProperty(propertyName.c_str()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Property not found: " + propertyName, actualProperty.IsNotNull(), true); + auto actualTemporoSpatialStringProperty = dynamic_cast(actualProperty.GetPointer()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Property has not type string: " + propertyName, actualTemporoSpatialStringProperty != nullptr, true); + std::string actualStringProperty = actualTemporoSpatialStringProperty->GetValue(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(propertyName + " is not as expected", actualStringProperty, expectedPropertyValue); + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRTDoseReaderService) diff --git a/Modules/DicomRT/test/mitkRTDoseReaderTest.cpp b/Modules/DicomRT/test/mitkRTDoseReaderTest.cpp deleted file mode 100644 index 12bb0f5b0f..0000000000 --- a/Modules/DicomRT/test/mitkRTDoseReaderTest.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include -#include - -#include - -#include -#include -#include -#include "mitkRTDoseReader.h" - -class mitkRTDoseReaderTestSuite : public mitk::TestFixture -{ - CPPUNIT_TEST_SUITE(mitkRTDoseReaderTestSuite); - MITK_TEST(TestDoseImage); - CPPUNIT_TEST_SUITE_END(); - -public: - - void setUp() override - { - } - - void TestDoseImage() - { - mitk::Image::Pointer refImage = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("RT/Dose/RT_Dose.nrrd"))[0].GetPointer()); - - auto doseReader = mitk::RTDoseReader(); - doseReader.SetInput(GetTestDataFilePath("RT/Dose/RD.dcm")); - std::vector > readerOutput = doseReader.Read(); - CPPUNIT_ASSERT_EQUAL_MESSAGE("reader output should have one entry.", static_cast(1), static_cast(readerOutput.size())); - - mitk::Image::Pointer image = dynamic_cast(readerOutput.at(0).GetPointer()); - - CPPUNIT_ASSERT_EQUAL_MESSAGE("read image should not be null", image.IsNotNull(), true); - CPPUNIT_ASSERT_EQUAL_MESSAGE("reference image and image should be equal", true, mitk::Equal(*image, *refImage, mitk::eps, true)); - - auto prescibedDoseProperty = image->GetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str()); - auto prescribedDoseGenericProperty = dynamic_cast*>(prescibedDoseProperty.GetPointer()); - double actualPrescribedDose = prescribedDoseGenericProperty->GetValue(); - double expectedPrescribedDose = 65535 * 0.0010494648*0.8; - CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("prescribed dose property is not as expected", expectedPrescribedDose, actualPrescribedDose, 1e-5); - - } - -}; - -MITK_TEST_SUITE_REGISTRATION(mitkRTDoseReader) diff --git a/Modules/DicomRT/test/mitkRTPlanReaderServiceTest.cpp b/Modules/DicomRT/test/mitkRTPlanReaderServiceTest.cpp new file mode 100644 index 0000000000..5ed22e12fb --- /dev/null +++ b/Modules/DicomRT/test/mitkRTPlanReaderServiceTest.cpp @@ -0,0 +1,75 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include "mitkTestFixture.h" + +#include "mitkImage.h" +#include "mitkTemporoSpatialStringProperty.h" +#include "mitkBaseProperty.h" +#include + +class mitkRTPlanReaderServiceTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRTPlanReaderServiceTestSuite); + MITK_TEST(TestProperties); + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::Image::ConstPointer m_image; + +public: + + void setUp() override + { + m_image = mitk::IOUtil::LoadImage(GetTestDataFilePath("RT/Plan/rtplan.dcm")); + CPPUNIT_ASSERT_EQUAL(m_image.IsNotNull(), true); + } + + void TestProperties() + { + CheckStringProperty("DICOM.300A.0010.[0].300A.0013", "1.2.246.352.72.11.320687012.17740.20090508173031"); + CheckStringProperty("DICOM.300A.0010.[1].300A.0013", "1.2.246.352.72.11.320687012.17741.20090508173031"); + CheckStringProperty("DICOM.300A.0010.[0].300A.0016", "Breast"); + CheckStringProperty("DICOM.300A.0010.[1].300A.0016", "CALC POINT"); + CheckStringProperty("DICOM.300A.0010.[0].300A.0026", "14"); + CheckStringProperty("DICOM.300A.0010.[1].300A.0026", "11.3113869239676"); + + CheckStringProperty("DICOM.300A.0070.[0].300A.0078", "7"); + CheckStringProperty("DICOM.300A.0070.[0].300A.0080", "4"); + + CheckStringProperty("DICOM.300A.00B0.[0].300A.00C6", "PHOTON"); + CheckStringProperty("DICOM.300A.00B0.[1].300A.00C6", "PHOTON"); + CheckStringProperty("DICOM.300A.00B0.[2].300A.00C6", "PHOTON"); + CheckStringProperty("DICOM.300A.00B0.[3].300A.00C6", "PHOTON"); + + CheckStringProperty("DICOM.300C.0060.[0].0008.1155", "1.2.246.352.71.4.320687012.3190.20090511122144"); + } + + void CheckStringProperty(const std::string& propertyName, const std::string& expectedPropertyValue) + { + auto actualProperty = m_image->GetProperty(propertyName.c_str()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Property not found: " + propertyName, actualProperty.IsNotNull(), true); + auto actualTemporoSpatialStringProperty = dynamic_cast(actualProperty.GetPointer()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Property has not type string: " + propertyName, actualTemporoSpatialStringProperty != nullptr, true); + std::string actualStringProperty = actualTemporoSpatialStringProperty->GetValue(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(propertyName + " is not as expected", actualStringProperty, expectedPropertyValue); + } + + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRTPlanReaderService) diff --git a/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp b/Modules/DicomRT/test/mitkRTStructureSetReaderServiceTest.cpp similarity index 52% rename from Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp rename to Modules/DicomRT/test/mitkRTStructureSetReaderServiceTest.cpp index c7ca1d3048..a03a8f93dd 100644 --- a/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp +++ b/Modules/DicomRT/test/mitkRTStructureSetReaderServiceTest.cpp @@ -1,129 +1,135 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include -#include "mitkRTStructureSetReader.h" #include +#include -class mitkRTStructureSetReaderTestSuite : public mitk::TestFixture +class mitkRTStructureSetReaderServiceTestSuite : public mitk::TestFixture { - CPPUNIT_TEST_SUITE(mitkRTStructureSetReaderTestSuite); + CPPUNIT_TEST_SUITE(mitkRTStructureSetReaderServiceTestSuite); MITK_TEST(TestStructureSets); CPPUNIT_TEST_SUITE_END(); +private: + std::vector structureSets; + public: void setUp() override { + auto baseDataVector = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/RS.dcm")); + //16 structures are in the data set + CPPUNIT_ASSERT_EQUAL(baseDataVector.size(), size_t(16)); + for (auto& baseData : baseDataVector) { + auto contour = dynamic_cast(baseData.GetPointer()); + CPPUNIT_ASSERT_EQUAL(contour != nullptr, true); + //only compare structs with content + if (contour->GetSize() > 0) { + structureSets.push_back(contour); + } + } } void TestStructureSets() { - auto structureSetReader = mitk::RTStructureSetReader(); - structureSetReader.SetInput(GetTestDataFilePath("RT/StructureSet/RS.dcm")); - auto readerOutput = structureSetReader.Read(); - CPPUNIT_ASSERT_EQUAL_MESSAGE("reader output should have one entry.", static_cast(16), static_cast(readerOutput.size())); - auto contourModelVectorCorrect = LoadGroundTruthData(); - std::vector contourModelVectorTest; - for (const auto& aStruct : readerOutput){ - mitk::ContourModelSet::Pointer contourModelSet = dynamic_cast(aStruct.GetPointer()); - //only compare structs with content - if (contourModelSet->GetSize() > 0){ - contourModelVectorTest.push_back(contourModelSet); - } - } - bool equal = true; - for (const auto& aStructTest : contourModelVectorTest) + unsigned int comparedStructs = 0; + for (const auto& aStructTest : structureSets) { - const std::string nameTest = aStructTest->GetProperty("name")->GetValueAsString(); - for (const auto& aStructCorrect : contourModelVectorCorrect) - { - const std::string nameCorrect = aStructCorrect->GetProperty("name")->GetValueAsString(); - if (nameTest == nameCorrect){ - if (!Compare(aStructTest, aStructCorrect)){ - equal = false; - } - } + const std::string nameTest = aStructTest->GetProperty("name")->GetValueAsString(); + for (const auto& aStructCorrect : contourModelVectorCorrect) + { + const std::string nameCorrect = aStructCorrect->GetProperty("name")->GetValueAsString(); + if (nameTest == nameCorrect) { + if (!Compare(aStructTest, aStructCorrect)) { + equal = false; + } + else { + comparedStructs++; + } } + } } CPPUNIT_ASSERT(equal); + //only 6 structure sets have content + CPPUNIT_ASSERT_EQUAL(comparedStructs, unsigned int(6)); } - bool Compare(mitk::ContourModelSet::Pointer c1, mitk::ContourModelSet::Pointer c2){ - if(c1->GetSize()!=c2->GetSize()) + bool Compare(mitk::ContourModelSet::Pointer c1, mitk::ContourModelSet::Pointer c2) { + if (c1->GetSize() != c2->GetSize()) { MITK_INFO << "Number of ContourModelSets different" << std::endl; return false; } else { - for(int i=0;iGetSize();++i) + for (int i = 0; i < c1->GetSize(); ++i) { mitk::ContourModel::Pointer cm1 = c1->GetContourModelAt(i); mitk::ContourModel::Pointer cm2 = c2->GetContourModelAt(i); - if(cm1->GetNumberOfVertices()!=cm2->GetNumberOfVertices()) + if (cm1->GetNumberOfVertices() != cm2->GetNumberOfVertices()) { MITK_INFO << "Number of Vertices different" << std::endl; return false; } else { - for(int j=0;jGetNumberOfVertices();++j) + for (int j = 0; j < cm1->GetNumberOfVertices(); ++j) { mitk::Point3D p1 = cm1->GetVertexAt(i)->Coordinates; mitk::Point3D p2 = cm2->GetVertexAt(i)->Coordinates; - if (!Equal(p1, p2, 0.001)){ - return false; + if (!Equal(p1, p2, 0.001)) { + return false; } } } } } return true; } - mitk::ContourModelSet::Pointer LoadFileWithNameProperty(const std::string& filename, const std::string& propertyName){ - auto readerOutput = mitk::IOUtil::Load(GetTestDataFilePath(filename)); - mitk::ContourModelSet::Pointer contourSet = dynamic_cast(readerOutput.at(0).GetPointer()); - contourSet->SetProperty("name", mitk::StringProperty::New(propertyName)); - return contourSet; + mitk::ContourModelSet::Pointer LoadFileWithNameProperty(const std::string& filename, const std::string& propertyName) { + auto readerOutput = mitk::IOUtil::Load(GetTestDataFilePath(filename)); + mitk::ContourModelSet::Pointer contourSet = dynamic_cast(readerOutput.at(0).GetPointer()); + contourSet->SetProperty("name", mitk::StringProperty::New(propertyName)); + return contourSet; } std::vector LoadGroundTruthData() { std::vector allStructs; allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/BODY.cnt_set", "BODY")); allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Bladder.cnt_set", "Bladder")); allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Femoral Head Lt.cnt_set", "Femoral Head Lt")); allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Femoral Head RT.cnt_set", "Femoral Head RT")); allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/PTV.cnt_set", "PTV")); allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Rectum.cnt_set", "Rectum")); return allStructs; } }; -MITK_TEST_SUITE_REGISTRATION(mitkRTStructureSetReader) +MITK_TEST_SUITE_REGISTRATION(mitkRTStructureSetReaderService) diff --git a/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt b/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt index da36994ac9..2a2055a1ff 100644 --- a/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.dicom/CMakeLists.txt @@ -1,30 +1,30 @@ project(org_mitk_gui_qt_dicom) # Note: # If we use an installed version of DCMTK then DCMTK_DIR points to the subdirectory # of the installation directory (share/dcmtk) that contains DCMTKConfig.cmake. # Therefore we look for the the storescp command in the '../../bin' directory, too. find_program(DCMTK_STORESCP NAMES storescp storescp${DCMTK_CMAKE_DEBUG_POSTFIX} storescp${CMAKE_DEBUG_POSTFIX} PATHS "${DCMTK_DIR}/bin" "${DCMTK_DIR}/../bin" "${DCMTK_DIR}/../../bin" PATH_SUFFIXES Release Debug DOC "Dcmtk storage provider which is used to store dicom files which are transfered over network." NO_DEFAULT_PATH ) mark_as_advanced(DCMTK_STORESCP) if(NOT EXISTS ${DCMTK_STORESCP}) message(WARNING "Couldn't find program storescp: Query/retrieve of the DICOM plugin won't work!") else(NOT EXISTS ${DCMTK_STORESCP}) configure_file( org_mitk_gui_qt_dicom_config.h.in org_mitk_gui_qt_dicom_config.h @ONLY) MITK_INSTALL_HELPER_APP( EXECUTABLES ${DCMTK_STORESCP}) mitk_create_plugin( EXPORT_DIRECTIVE DICOM_EXPORT EXPORTED_INCLUDE_SUFFIXES src - MODULE_DEPENDS MitkQtWidgetsExt MitkDicomUI MitkDicomRT MitkRTUI MitkDICOMReader + MODULE_DEPENDS MitkQtWidgetsExt MitkDicomUI MitkDicomRT MitkDicomRTIO MitkRTUI MitkDICOMReader ) endif() diff --git a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp index f228b79a90..7ff707f79f 100644 --- a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp +++ b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp @@ -1,434 +1,434 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPluginActivator.h" #include "DicomEventHandler.h" #include #include #include #include #include #include #include #include #include #include "mitkImage.h" #include #include #include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DicomEventHandler::DicomEventHandler() { } DicomEventHandler::~DicomEventHandler() { } void DicomEventHandler::OnSignalAddSeriesToDataManager(const ctkEvent& ctkEvent) { QStringList listOfFilesForSeries; listOfFilesForSeries = ctkEvent.getProperty("FilesForSeries").toStringList(); if (!listOfFilesForSeries.isEmpty()) { //for rt data, if the modality tag isn't defined or is "CT" the image is handled like before if(ctkEvent.containsProperty("Modality") && (ctkEvent.getProperty("Modality").toString().compare("RTDOSE",Qt::CaseInsensitive) == 0 || ctkEvent.getProperty("Modality").toString().compare("RTSTRUCT",Qt::CaseInsensitive) == 0 || ctkEvent.getProperty("Modality").toString().compare("RTPLAN", Qt::CaseInsensitive) == 0)) { QString modality = ctkEvent.getProperty("Modality").toString(); if(modality.compare("RTDOSE",Qt::CaseInsensitive) == 0) { - auto doseReader = mitk::RTDoseReader(); + auto doseReader = mitk::RTDoseReaderService(); doseReader.SetInput(listOfFilesForSeries.front().toStdString()); std::vector > readerOutput = doseReader.Read(); if (!readerOutput.empty()){ mitk::Image::Pointer doseImage = dynamic_cast(readerOutput.at(0).GetPointer()); mitk::DataNode::Pointer doseImageNode = mitk::DataNode::New(); doseImageNode->SetData(doseImage); doseImageNode->SetName("RTDose"); mitk::DataNode::Pointer doseOutlineNode = mitk::DataNode::New(); doseOutlineNode->SetData(doseImage); if (doseImage != nullptr) { auto sopUIDProperty = doseImage->GetProperty("dicomseriesreader.SOPClassUID"); if (sopUIDProperty.IsNotNull()){ auto sopUIDStringProperty = dynamic_cast(sopUIDProperty.GetPointer()); if (sopUIDStringProperty != nullptr){ std::string sopUID = sopUIDStringProperty->GetValue(); doseImageNode->SetName(sopUID); } } berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID.c_str()); typedef QStringList NamesType; NamesType names = prefNode->ChildrenNames(); std::map presetMap; for (NamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) { berry::IPreferences::Pointer aPresetNode = prefNode->Node(*pos); if (aPresetNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << (*pos).toStdString(); } mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); NamesType levelNames = aPresetNode->ChildrenNames(); for (NamesType::const_iterator levelName = levelNames.begin(); levelName != levelNames.end(); ++levelName) { berry::IPreferences::Pointer levelNode = aPresetNode->Node(*levelName); if (aPresetNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find level node under given preset name. Name: " << (*pos).toStdString() << "; Level id: " << (*levelName).toStdString(); } mitk::IsoDoseLevel::Pointer isoLevel = mitk::IsoDoseLevel::New(); isoLevel->SetDoseValue(levelNode->GetDouble(mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID.c_str(), 0.0)); mitk::IsoDoseLevel::ColorType color; color.SetRed(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID.c_str(), 1.0)); color.SetGreen(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID.c_str(), 1.0)); color.SetBlue(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID.c_str(), 1.0)); isoLevel->SetColor(color); isoLevel->SetVisibleIsoLine(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID.c_str(), true)); isoLevel->SetVisibleColorWash(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID.c_str(), true)); levelSet->SetIsoDoseLevel(isoLevel); } presetMap.insert(std::make_pair((*pos).toStdString(), levelSet)); } if (presetMap.size() == 0) { presetMap.insert(std::make_pair(std::string("Virtuos"), mitk::GeneratIsoLevels_Virtuos())); } prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID.c_str()); if (prefNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << prefNode->ToString().toStdString(); } //set some specific colorwash and isoline properties bool showColorWashGlobal = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID.c_str(), true); doseImageNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), showColorWashGlobal); bool showIsolinesGlobal = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_ISOLINES_ID.c_str(), true); doseOutlineNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), showIsolinesGlobal); //Set reference dose property double referenceDose = prefNode->GetDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID.c_str(), mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE); doseImageNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); doseOutlineNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); QString presetName = prefNode->Get(mitk::RTUIConstants::SELECTED_ISO_PRESET_ID.c_str(), "Virtuos"); mitk::IsoDoseLevelSet::Pointer isoDoseLevelPreset = presetMap[presetName.toStdString()]; mitk::IsoDoseLevelSetProperty::Pointer levelSetProp = mitk::IsoDoseLevelSetProperty::New(isoDoseLevelPreset); doseImageNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), levelSetProp); doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), levelSetProp); mitk::IsoDoseLevelVector::Pointer levelVector = mitk::IsoDoseLevelVector::New(); mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(levelVector); doseImageNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(), levelVecProp); doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(), levelVecProp); mitk::RenderingModeProperty::Pointer renderingModeProp = mitk::RenderingModeProperty::New(); if (showColorWashGlobal) { //Generating the Colorwash vtkSmartPointer transferFunction = vtkSmartPointer::New(); for (mitk::IsoDoseLevelSet::ConstIterator itIsoDoseLevel = isoDoseLevelPreset->Begin(); itIsoDoseLevel != isoDoseLevelPreset->End(); ++itIsoDoseLevel) { float *hsv = new float[3]; //used for transfer rgb to hsv vtkSmartPointer cCalc = vtkSmartPointer::New(); if (itIsoDoseLevel->GetVisibleColorWash()){ cCalc->RGBToHSV(itIsoDoseLevel->GetColor()[0], itIsoDoseLevel->GetColor()[1], itIsoDoseLevel->GetColor()[2], &hsv[0], &hsv[1], &hsv[2]); transferFunction->AddHSVPoint(itIsoDoseLevel->GetDoseValue()*referenceDose, hsv[0], hsv[1], hsv[2], 1.0, 1.0); } } mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); mitkTransFunc->SetColorTransferFunction(transferFunction); mitkTransFuncProp->SetValue(mitkTransFunc); doseImageNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); renderingModeProp->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); } else { //Set rendering mode to levelwindow color mode renderingModeProp->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); } doseImageNode->SetProperty("Image Rendering.Mode", renderingModeProp); doseImageNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); //set the outline properties doseOutlineNode->SetBoolProperty("outline binary", true); doseOutlineNode->SetProperty("helper object", mitk::BoolProperty::New(true)); doseOutlineNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); dataStorage->Add(doseImageNode); dataStorage->Add(doseOutlineNode, doseImageNode); //set the dose mapper for outline drawing; the colorwash is realized by the imagevtkmapper2D mitk::DoseImageVtkMapper2D::Pointer contourMapper = mitk::DoseImageVtkMapper2D::New(); doseOutlineNode->SetMapper(1, contourMapper); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); } }//END DOSE } else if(modality.compare("RTSTRUCT",Qt::CaseInsensitive) == 0) { - auto structReader = mitk::RTStructureSetReader(); + auto structReader = mitk::RTStructureSetReaderService(); structReader.SetInput(listOfFilesForSeries.front().toStdString()); std::vector > readerOutput = structReader.Read(); if (readerOutput.empty()){ MITK_ERROR << "No structure sets were created" << endl; } else { std::vector modelVector; ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); for (const auto& aStruct : readerOutput){ mitk::ContourModelSet::Pointer countourModelSet = dynamic_cast(aStruct.GetPointer()); mitk::DataNode::Pointer structNode = mitk::DataNode::New(); structNode->SetData(countourModelSet); structNode->SetProperty("name", aStruct->GetProperty("name")); structNode->SetProperty("color", aStruct->GetProperty("contour.color")); structNode->SetProperty("contour.color", aStruct->GetProperty("contour.color")); structNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); structNode->SetVisibility(true, mitk::BaseRenderer::GetInstance( - mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); + mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); structNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); structNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); structNode->SetVisibility(true, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); dataStorage->Add(structNode); } mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); } } else if (modality.compare("RTPLAN", Qt::CaseInsensitive) == 0) { - auto planReader = mitk::RTPlanReader(); + auto planReader = mitk::RTPlanReaderService(); planReader.SetInput(listOfFilesForSeries.front().toStdString()); std::vector > readerOutput = planReader.Read(); if (!readerOutput.empty()){ //there is no image, only the properties are interesting mitk::Image::Pointer planDummyImage = dynamic_cast(readerOutput.at(0).GetPointer()); mitk::DataNode::Pointer planImageNode = mitk::DataNode::New(); planImageNode->SetData(planDummyImage); planImageNode->SetName("RTPlan"); ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); dataStorage->Add(planImageNode); } } } else { mitk::StringList seriesToLoad; QStringListIterator it(listOfFilesForSeries); while (it.hasNext()) { seriesToLoad.push_back(it.next().toStdString()); } //Get Reference for default data storage. ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); //special handling of Philips 3D US DICOM. //Copied from DICOMSeriesReaderService if (!seriesToLoad.empty() && mitk::DicomSeriesReader::IsPhilips3DDicom(seriesToLoad.front())) { MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; mitk::LocaleSwitch localeSwitch("C"); std::locale previousCppLocale(std::cin.getloc()); std::locale l("C"); std::cin.imbue(l); mitk::DataNode::Pointer node = mitk::DataNode::New(); mitk::DicomSeriesReader::StringContainer stringvec; stringvec.push_back(seriesToLoad.front()); if (mitk::DicomSeriesReader::LoadDicomSeries(stringvec, *node)) { mitk::BaseData::Pointer data = node->GetData(); mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameName(seriesToLoad.front())); data->GetPropertyList()->SetProperty("name", nameProp); node->SetProperty("name", nameProp); dataStorage->Add(node); } std::cin.imbue(previousCppLocale); return; } //Normal DICOM handling (It wasn't a Philips 3D US) mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New(); selector->LoadBuiltIn3DConfigs(); selector->LoadBuiltIn3DnTConfigs(); selector->SetInputFiles(seriesToLoad); mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages(); reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest()); reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor); reader->SetInputFiles(seriesToLoad); mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); scanner->AddTagPaths(reader->GetTagsOfInterest()); scanner->SetInputFiles(seriesToLoad); scanner->Scan(); reader->SetTagCache(scanner->GetScanCache()); reader->AnalyzeInputFiles(); reader->LoadImages(); for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i) { const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i); mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer(); std::string nodeName = "Unnamed_DICOM"; std::string studyDescription = desc.GetPropertyAsString("studyDescription"); std::string seriesDescription = desc.GetPropertyAsString("seriesDescription"); if (!studyDescription.empty()) { nodeName = studyDescription; } if (!seriesDescription.empty()) { if (!studyDescription.empty()) { nodeName += "/"; } nodeName += seriesDescription; } mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New(nodeName); data->SetProperty("name", nameProp); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(data); nameProp = mitk::StringProperty::New(nodeName); node->SetProperty("name", nameProp); dataStorage->Add(node); } if (reader->GetNumberOfOutputs() < 1) { MITK_ERROR << "Error loading series: " << ctkEvent.getProperty("SeriesName").toString().toStdString() << " id: " << ctkEvent.getProperty("SeriesUID").toString().toStdString(); } } } else { MITK_INFO << "There are no files for the current series"; } } void DicomEventHandler::OnSignalRemoveSeriesFromStorage(const ctkEvent& /*ctkEvent*/) { } void DicomEventHandler::SubscribeSlots() { ctkServiceReference ref = mitk::PluginActivator::getContext()->getServiceReference(); if (ref) { ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService(ref); ctkDictionary properties; properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/ADD"; eventAdmin->subscribeSlot(this, SLOT(OnSignalAddSeriesToDataManager(ctkEvent)), properties); properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/DELETED"; eventAdmin->subscribeSlot(this, SLOT(OnSignalRemoveSeriesFromStorage(ctkEvent)), properties); } }