diff --git a/Modules/DICOM/files.cmake b/Modules/DICOM/files.cmake index 05d6cd2f66..c0ba702991 100644 --- a/Modules/DICOM/files.cmake +++ b/Modules/DICOM/files.cmake @@ -1,64 +1,65 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkBaseDICOMReaderService.cpp mitkDICOMFileReader.cpp mitkDICOMTagScanner.cpp mitkDICOMGDCMTagScanner.cpp mitkDICOMDCMTKTagScanner.cpp mitkDICOMImageBlockDescriptor.cpp mitkDICOMITKSeriesGDCMReader.cpp mitkDICOMDatasetSorter.cpp mitkDICOMTagBasedSorter.cpp mitkDICOMGDCMImageFrameInfo.cpp mitkDICOMImageFrameInfo.cpp mitkDICOMIOHelper.cpp mitkDICOMGenericImageFrameInfo.cpp mitkDICOMDatasetAccessingImageFrameInfo.cpp + mitkDICOMSplitReason.cpp mitkDICOMSortCriterion.cpp mitkDICOMSortByTag.cpp mitkITKDICOMSeriesReaderHelper.cpp mitkEquiDistantBlocksSorter.cpp mitkNormalDirectionConsistencySorter.cpp mitkSortByImagePositionPatient.cpp mitkGantryTiltInformation.cpp mitkClassicDICOMSeriesReader.cpp mitkThreeDnTDICOMSeriesReader.cpp mitkDICOMTag.cpp mitkDICOMTagsOfInterestHelper.cpp mitkDICOMTagCache.cpp mitkDICOMGDCMTagCache.cpp mitkDICOMGenericTagCache.cpp mitkDICOMEnums.cpp mitkDICOMReaderConfigurator.cpp mitkDICOMFileReaderSelector.cpp mitkIDICOMTagsOfInterest.cpp mitkDICOMTagsOfInterestAddHelper.cpp mitkDICOMTagPath.cpp mitkDICOMProperty.cpp mitkDICOMFilesHelper.cpp mitkDICOMIOMetaInformationPropertyConstants.cpp legacy/mitkDicomSeriesReader.cpp legacy/mitkDicomSR_GantryTiltInformation.cpp legacy/mitkDicomSR_ImageBlockDescriptor.cpp legacy/mitkDicomSR_LoadDICOMRGBPixel.cpp legacy/mitkDicomSR_LoadDICOMRGBPixel4D.cpp legacy/mitkDicomSR_LoadDICOMScalar.cpp legacy/mitkDicomSR_LoadDICOMScalar4D.cpp legacy/mitkDicomSR_SliceGroupingResult.cpp ) set(RESOURCE_FILES configurations/3D/classicreader.xml configurations/3D/imageposition.xml configurations/3D/imageposition_byacquisition.xml configurations/3D/instancenumber.xml configurations/3D/instancenumber_soft.xml configurations/3D/slicelocation.xml configurations/3D/simpleinstancenumber_soft.xml configurations/3DnT/classicreader.xml configurations/3DnT/imageposition.xml configurations/3DnT/imageposition_byacquisition.xml configurations/3DnT/imageposition_bytriggertime.xml ) diff --git a/Modules/DICOM/include/mitkDICOMSplitReason.h b/Modules/DICOM/include/mitkDICOMSplitReason.h new file mode 100644 index 0000000000..6db9ec46d5 --- /dev/null +++ b/Modules/DICOM/include/mitkDICOMSplitReason.h @@ -0,0 +1,71 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef mitkDICOMSplitReason_h +#define mitkDICOMSplitReason_h + +#include "itkLightObject.h" +#include "mitkCommon.h" + +#include "MitkDICOMExports.h" + +namespace mitk +{ + + class MITKDICOM_EXPORT DICOMSplitReason : public itk::LightObject + { + public: + mitkClassMacroItkParent(DICOMSplitReason, itk::LightObject); + itkFactorylessNewMacro(DICOMSplitReason); + itkCloneMacro(DICOMSplitReason); + + enum class ReasonType + { + Unkown = 0, + ValueSplitDifference = 2, //*< split due to different values in splitting relevant dicom tags + ValueSortDistance = 3, //*< split due value distance of sort criterion to large for relevant dicom tag(s) + ImagePostionMissing = 4, //*< split because image position tag was missing in one of the compared files + OverlappingSlices = 8, //*< split because at least two input files are overlapping in world coordinate space + GantryTiltDifference = 16, //*< split because the gantry tilts of at least two input files were different + SliceDistanceInconsistency = 32 //*< split because the distance between slices were inconsistent. + // This can either be evoked by volumes with heterogeneous z spacing or by missing slices. + }; + + void AddReason(ReasonType type, std::string_view detail = ""); + void RemoveReason(ReasonType type); + + bool ReasonExists() const; + bool ReasonExists(ReasonType type) const; + std::string GetReasonDetails(ReasonType type) const; + + Pointer ExtendReason(const Self* otherReason) const; + + static std::string SerializeToJSON(const DICOMSplitReason*); + static std::string TypeToString(const DICOMSplitReason::ReasonType& reasonType); + + protected: + mitkCloneMacro(DICOMSplitReason); + + DICOMSplitReason(); + ~DICOMSplitReason() override; + DICOMSplitReason(const DICOMSplitReason& other); + + private: + DICOMSplitReason& operator=(const DICOMSplitReason& other); + + using ReasonMapType = std::map; + ReasonMapType m_ReasonMap; + }; + +} + +#endif diff --git a/Modules/DICOM/src/mitkDICOMSplitReason.cpp b/Modules/DICOM/src/mitkDICOMSplitReason.cpp new file mode 100644 index 0000000000..16e12ca410 --- /dev/null +++ b/Modules/DICOM/src/mitkDICOMSplitReason.cpp @@ -0,0 +1,108 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "mitkDICOMSplitReason.h" + +#include + +void mitk::DICOMSplitReason::AddReason(ReasonType type, std::string_view detail) +{ + m_ReasonMap.insert(std::make_pair(type, detail)); +} + +void mitk::DICOMSplitReason::RemoveReason(ReasonType type) +{ + m_ReasonMap.erase(type); +} + +bool mitk::DICOMSplitReason::ReasonExists() const +{ + return !m_ReasonMap.empty(); +} + +bool mitk::DICOMSplitReason::ReasonExists(ReasonType type) const +{ + return m_ReasonMap.cend() != m_ReasonMap.find(type); +} + +std::string mitk::DICOMSplitReason::GetReasonDetails(ReasonType type) const +{ + auto finding = m_ReasonMap.find(type); + if (m_ReasonMap.cend() == finding) + mitkThrow() << "Cannot get details for inexistent type."; + + return finding->second; +}; + +mitk::DICOMSplitReason::Pointer mitk::DICOMSplitReason::ExtendReason(const Self* otherReason) const +{ + if (nullptr == otherReason) + mitkThrow() << "Cannot extend reason. Pass other reason is in valid."; + + Pointer result = this->Clone(); + + result->m_ReasonMap.insert(otherReason->m_ReasonMap.cbegin(), otherReason->m_ReasonMap.cend()); + + return result; +} + +mitk::DICOMSplitReason::DICOMSplitReason(): itk::LightObject() +{ +} + +mitk::DICOMSplitReason::~DICOMSplitReason() +{ +} + +mitk::DICOMSplitReason::DICOMSplitReason(const DICOMSplitReason& other) +{ + m_ReasonMap = other.m_ReasonMap; +} + +std::string mitk::DICOMSplitReason::TypeToString(const DICOMSplitReason::ReasonType& reasonType) +{ + switch (reasonType) + { + case DICOMSplitReason::ReasonType::GantryTiltDifference: + return "gantry_tilt_difference"; + case DICOMSplitReason::ReasonType::ImagePostionMissing: + return "gantry_tilt_difference"; + case DICOMSplitReason::ReasonType::OverlappingSlices: + return "overlapping_slices"; + case DICOMSplitReason::ReasonType::SliceDistanceInconsistency: + return "slice_distance_inconsistency"; + case DICOMSplitReason::ReasonType::ValueSortDistance: + return "value_sort_distance"; + case DICOMSplitReason::ReasonType::ValueSplitDifference: + return "value_split_difference"; + } + return "unknown"; +} + +std::string mitk::DICOMSplitReason::SerializeToJSON(const DICOMSplitReason* reason) +{ + if (nullptr == reason) + mitkThrow() << "Cannot extend reason. Pass other reason is in valid."; + + auto data = nlohmann::json::array(); + + for (const auto& [type, detail] : reason->m_ReasonMap) + { + auto details = nlohmann::json::array(); + + details.push_back(TypeToString(type)); + details.push_back(detail); + data.push_back(details); + } + + return data.dump(); +}