diff --git a/Modules/DicomRT/CMakeLists.txt b/Modules/DicomRT/CMakeLists.txt index 770c6c7415..56e50c2ab7 100644 --- a/Modules/DicomRT/CMakeLists.txt +++ b/Modules/DicomRT/CMakeLists.txt @@ -1,10 +1,12 @@ # CREATE MODULE HERE IF (NOT DEFINED DCMTK_dcmrt_LIBRARY OR DCMTK_dcmrt_LIBRARY) MITK_CREATE_MODULE( + INCLUDE_DIRS DataStructures DEPENDS MitkSegmentation MitkSceneSerializationBase PACKAGE_DEPENDS DCMTK + QT_MODULE ) ADD_SUBDIRECTORY(Testing) ELSE() MESSAGE("MITK DicomRT Support disabled because the DCMTK dcmrt library not found") ENDIF() diff --git a/Modules/DicomRT/DataStructures/mitkDoseValueType.h b/Modules/DicomRT/DataStructures/mitkDoseValueType.h new file mode 100644 index 0000000000..ed3ba8680a --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkDoseValueType.h @@ -0,0 +1,37 @@ +/*=================================================================== + +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 _MITK_DOSE_VALUE_TYPE_H_ +#define _MITK_DOSE_VALUE_TYPE_H_ + +namespace mitk +{ + +/** + \brief Represents absolute dose values (in Gy). +*/ +typedef double DoseValueAbs; + +/** +\brief Represents relative dose values (in %). +*/ +typedef double DoseValueRel; + + +} // namespace mitk + +#endif //_MITK_DOSE_VALUE_TYPE_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp new file mode 100644 index 0000000000..fa4feb2218 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp @@ -0,0 +1,79 @@ +/*=================================================================== + +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 "mitkIsoDoseLevel.h" + +mitk::IsoDoseLevel::IsoDoseLevel() : +m_DoseValue (0.0), + m_VisibleIsoLine ( true ), + m_VisibleColorWash (true) +{ + m_Color.Fill(0); +} + +mitk::IsoDoseLevel::IsoDoseLevel( const IsoDoseLevel & other ) +{ + if (&other != this) + { + this->m_Color = other.m_Color; + this->m_DoseValue = other.m_DoseValue; + this->m_VisibleColorWash = other.m_VisibleColorWash; + this->m_VisibleIsoLine = other.m_VisibleIsoLine; + } +} + +mitk::IsoDoseLevel::IsoDoseLevel(const DoseValueType & value, const ColorType& color, bool visibleIsoLine, bool visibleColorWash): + m_DoseValue (value), + m_Color (color), + m_VisibleIsoLine ( visibleIsoLine ), + m_VisibleColorWash ( visibleColorWash ) +{ +}; + +mitk::IsoDoseLevel::~IsoDoseLevel() +{ +} + +bool mitk::IsoDoseLevel::operator == ( const IsoDoseLevel& right) const +{ + bool result = this->m_DoseValue == right.m_DoseValue; + + result = result && (this->m_Color == right.m_Color); + result = result && (this->m_VisibleColorWash == right.m_VisibleColorWash); + result = result && (this->m_VisibleIsoLine == right.m_VisibleIsoLine); + + return result; +} + +bool mitk::IsoDoseLevel::operator <( const IsoDoseLevel& right) const +{ + return this->m_DoseValue < right.m_DoseValue; +} + +bool mitk::IsoDoseLevel::operator > ( const IsoDoseLevel& right) const +{ + return this->m_DoseValue > right.m_DoseValue; +} + +void mitk::IsoDoseLevel::PrintSelf(std::ostream &os, itk::Indent indent) const +{ + Superclass::PrintSelf(os,indent); + os< +#include +#include + +#include "mitkCommon.h" +#include "mitkDoseValueType.h" +#include "MitkDicomRTExports.h" + +namespace mitk +{ + + /** + \brief Stores values needed for the representation/visualization of dose iso levels. + * + * The dose iso level is defined in the topology of a dose distribution by the dose value + * that indicates the lower boundary of the iso level. The upper boundary is implicitly defined + * by the next IsoDoseLevel greater (higher dose value) than the current iso level. + * Color and the visibility options are used to indicate the visualization style. + */ + class MitkDicomRT_EXPORT IsoDoseLevel: public itk::Object + { + public: + typedef ::itk::RGBPixel ColorType; + typedef DoseValueRel DoseValueType; + + mitkClassMacro(IsoDoseLevel, itk::Object); + itkNewMacro(Self); + mitkNewMacro4Param(Self,DoseValueType, ColorType, bool, bool); + + /** Checks if current dose iso level instances is greater + according to the dose values.*/ + bool operator> ( const IsoDoseLevel& right ) const; + /** Checks if current dose iso level instances is lesser + according to the dose values.*/ + bool operator< ( const IsoDoseLevel& right ) const; + + bool operator == ( const IsoDoseLevel& right) const; + + itkSetMacro(DoseValue,DoseValueType); + itkGetConstMacro(DoseValue,DoseValueType); + + itkSetMacro(Color,ColorType); + itkGetConstMacro(Color,ColorType); + + itkSetMacro(VisibleIsoLine,bool); + itkGetConstMacro(VisibleIsoLine,bool); + itkBooleanMacro(VisibleIsoLine); + + itkSetMacro(VisibleColorWash,bool); + itkGetConstMacro(VisibleColorWash,bool); + itkBooleanMacro(VisibleColorWash); + + protected: + IsoDoseLevel(); + IsoDoseLevel(const IsoDoseLevel & other); + IsoDoseLevel(const DoseValueType & value, const ColorType& color, bool visibleIsoLine = true, bool visibleColorWash = true ); + virtual ~IsoDoseLevel(); + + mitkCloneMacro(IsoDoseLevel); + + void PrintSelf(std::ostream &os, itk::Indent indent) const; + + private: + /** Relative dose value and lower boundary of the iso level instance + */ + DoseValueType m_DoseValue; + + /** RGB color code that should be used for the iso level.*/ + ColorType m_Color; + + /** indicates if an iso line should be shown for the iso level + (the lower boundary indicated by m_DoseValue)*/ + bool m_VisibleIsoLine; + + /** indicates if a color wash should be shown for the iso level.*/ + bool m_VisibleColorWash; + + /** Not implemented on purpose*/ + IsoDoseLevel& operator = (const IsoDoseLevel& source); + }; + +} // namespace mitk + +#endif //_MITK_DOSE_ISO_LEVEL_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp new file mode 100644 index 0000000000..0d0f8b2764 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp @@ -0,0 +1,145 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelCollections.h" +#include "mitkExceptionMacro.h" + +namespace mitk +{ +/** "Private" functor used in std::find_if to find IsoDoseLevels with a given reference value */ +class EqualDoseFunctor +{ +public: + typedef IsoDoseLevel::DoseValueType DoseValueType; + + EqualDoseFunctor(const DoseValueType& refValue) : m_refValue(refValue) + {}; + + bool operator () (const IsoDoseLevel* level) + { + return level->GetDoseValue() == m_refValue; + } + +protected: + DoseValueType m_refValue; +}; + +/** "Private" binary function used in std::sort to check the order of IsoDoseLeveles */ +bool lesserIsoDoseLevel(const IsoDoseLevel* first, const IsoDoseLevel* second) +{ + return first->GetDoseValue() < second->GetDoseValue(); +} +} + +mitk::IsoDoseLevelSet::IsoDoseLevelSet(const IsoDoseLevelSet & other) +{ + if (&other != this) + { + this->m_IsoLevels = other.m_IsoLevels; + } +}; + +const mitk::IsoDoseLevel& mitk::IsoDoseLevelSet::GetIsoDoseLevel(IsoLevelIndexType index) const +{ + if (index < this->m_IsoLevels.size()) + { + return *(this->m_IsoLevels[index].GetPointer()); + } + else + { + mitkThrow() << "Try to access non existing dose iso level."; + } +}; + +const mitk::IsoDoseLevel& mitk::IsoDoseLevelSet::GetIsoDoseLevel(DoseValueType value) const +{ + InternalVectorType::const_iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), EqualDoseFunctor(value)); + + if (pos != this->m_IsoLevels.end()) + { + return *(pos->GetPointer()); + } + else + { + mitkThrow() << "Try to access non existing dose iso level."; + } +}; + +void mitk::IsoDoseLevelSet::SetIsoDoseLevel(const IsoDoseLevel* level) +{ + if (!level) + { + mitkThrow() << "Cannot set iso level. Passed null pointer."; + } + + this->DeleteIsoDoseLevel(level->GetDoseValue()); + + this->m_IsoLevels.push_back(level->Clone()); + + std::sort(this->m_IsoLevels.begin(), this->m_IsoLevels.end(),lesserIsoDoseLevel); +}; + +bool mitk::IsoDoseLevelSet::DoseLevelExists(IsoLevelIndexType index) const +{ + return index < this->m_IsoLevels.size(); +}; + + +bool mitk::IsoDoseLevelSet::DoseLevelExists(DoseValueType value) const +{ + InternalVectorType::const_iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), EqualDoseFunctor(value)); + return pos != this->m_IsoLevels.end(); +}; + +void mitk::IsoDoseLevelSet::DeleteIsoDoseLevel(DoseValueType value) +{ + InternalVectorType::iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), EqualDoseFunctor(value)); + + if (pos != this->m_IsoLevels.end()) + { + this->m_IsoLevels.erase(pos); + } +}; + +void mitk::IsoDoseLevelSet::DeleteIsoDoseLevel(IsoLevelIndexType index) +{ + if (DoseLevelExists(index)) + { + this->m_IsoLevels.erase(this->m_IsoLevels.begin()+index); + } +}; + +mitk::IsoDoseLevelSet::ConstIterator mitk::IsoDoseLevelSet::Begin(void) const +{ + return ConstIterator(this->m_IsoLevels.begin()); +}; + +mitk::IsoDoseLevelSet::ConstIterator mitk::IsoDoseLevelSet::End(void) const +{ + return ConstIterator(this->m_IsoLevels.end()); +}; + +mitk::IsoDoseLevelSet::IsoLevelIndexType mitk::IsoDoseLevelSet::Size(void) const +{ + return this->m_IsoLevels.size(); +}; + +void mitk::IsoDoseLevelSet::Reset(void) +{ + this->m_IsoLevels.clear(); +}; diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h new file mode 100644 index 0000000000..dc98dd1b9b --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h @@ -0,0 +1,158 @@ +/*=================================================================== + +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 _MITK_DOSE_ISO_LEVEL_COLLECTIONS_H_ +#define _MITK_DOSE_ISO_LEVEL_COLLECTIONS_H_ + +#include +#include + +#include "mitkIsoDoseLevel.h" + +namespace mitk +{ + /** + \class IsoDoseLevelVector + \brief Simple vector that stores dose iso levels. + * + * This class is for example used to store the user defined free iso values. + */ + typedef ::itk::VectorContainer IsoDoseLevelVector; + + + /** + \class IsoDoseLevelSet + \brief Stores values needed for the representation/visualization of dose iso levels. + * + * Set of dose iso levels sorted by the dose values of the iso levels (low to high values). + * This data structure is used to represent the dose iso level setup used for the + * visualization of a dose distribution. + */ +class MitkDicomRT_EXPORT IsoDoseLevelSet: + public itk::Object +{ +public: + mitkClassMacro(IsoDoseLevelSet, itk::Object); + itkNewMacro(Self); + +private: + /** Quick access to the STL vector type that was inherited. */ + typedef std::vector< IsoDoseLevel::Pointer > InternalVectorType; + typedef InternalVectorType::size_type size_type; + typedef InternalVectorType::iterator VectorIterator; + typedef InternalVectorType::const_iterator VectorConstIterator; + + InternalVectorType m_IsoLevels; + +protected: + IsoDoseLevelSet() {}; + IsoDoseLevelSet(const IsoDoseLevelSet & other); + + virtual ~IsoDoseLevelSet() {}; + + mitkCloneMacro(IsoDoseLevelSet); + +public: + typedef size_type IsoLevelIndexType; + typedef IsoDoseLevel::DoseValueType DoseValueType; + + /** Convenient typedefs for the iterator and const iterator. */ + class ConstIterator; + + /** Friends to this class. */ + friend class ConstIterator; + + /** \class ConstIterator + * Simulate STL-vector style const iteration where dereferencing the iterator + * gives read access to the value. + */ + class ConstIterator + { +public: + ConstIterator() {} + ConstIterator(const VectorConstIterator & i): m_Iter(i) {} + ConstIterator(const ConstIterator & r) { m_Iter = r.m_Iter; } + const IsoDoseLevel & operator*() { return *(m_Iter->GetPointer()); } + const IsoDoseLevel * operator->() { return m_Iter->GetPointer(); } + ConstIterator & operator++() {++m_Iter; return *this; } + ConstIterator operator++(int) { ConstIterator temp(*this); ++m_Iter; return temp; } + ConstIterator & operator--() {--m_Iter; return *this; } + ConstIterator operator--(int) { ConstIterator temp(*this); --m_Iter; return temp; } + ConstIterator & operator=(const ConstIterator & r) {m_Iter = r.m_Iter; return *this; } + bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; } + bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; } + + const IsoDoseLevel & Value(void) const { return *(m_Iter->GetPointer()); } + +private: + VectorConstIterator m_Iter; + }; + + /* Declare the public interface routines. */ + + /** + * Read the element from the given index. + * It is assumed that the index exists. + */ + const IsoDoseLevel& GetIsoDoseLevel(IsoLevelIndexType) const; + const IsoDoseLevel& GetIsoDoseLevel(DoseValueType) const; + + /** + * Set the element value at the given index. + * It is assumed that the index exists. + */ + void SetIsoDoseLevel(const IsoDoseLevel*); + + /** + * Check if the index range of the vector is large enough to allow the + * given index without expansion. + */ + bool DoseLevelExists(IsoLevelIndexType) const; + bool DoseLevelExists(DoseValueType) const; + + /** + * Delete the element defined by the index identifier. In practice, it + * doesn't make sense to delete a vector index. Instead, this method just + * overwrites the index with the default element. + */ + void DeleteIsoDoseLevel(DoseValueType); + void DeleteIsoDoseLevel(IsoLevelIndexType); + + /** + * Get a begin const iterator for the vector. + */ + ConstIterator Begin(void) const; + + /** + * Get an end const iterator for the vector. + */ + ConstIterator End(void) const; + + /** + * Get the number of elements currently stored in the vector. + */ + IsoLevelIndexType Size(void) const; + + /** + * Clear the elements. The final size will be zero. + */ + void Reset(void); +}; + +} + +#endif //_MITK_DOSE_ISO_LEVEL_COLLECTIONS_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp new file mode 100644 index 0000000000..8d15835b82 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp @@ -0,0 +1,107 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelSetProperty.h" + + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty() +{ +} + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty(const mitk::IsoDoseLevelSetProperty& other) + : BaseProperty(other) + , m_IsoLevelSet(other.m_IsoLevelSet) +{ +} + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty(IsoDoseLevelSet* levelSet) : m_IsoLevelSet(levelSet) +{ +} + +mitk::IsoDoseLevelSetProperty::~IsoDoseLevelSetProperty() +{ +} + +bool mitk::IsoDoseLevelSetProperty::IsEqual(const BaseProperty& property) const +{ + return this->m_IsoLevelSet == static_cast(property).m_IsoLevelSet; +} + +bool mitk::IsoDoseLevelSetProperty::Assign(const BaseProperty& property) +{ + this->m_IsoLevelSet = static_cast(property).m_IsoLevelSet; + return true; +} + +const mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetIsoDoseLevelSet() const +{ + return m_IsoLevelSet; +} + +const mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetValue() const +{ + return GetIsoDoseLevelSet(); +} + +mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetIsoDoseLevelSet() +{ + return m_IsoLevelSet; +} + +mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetValue() +{ + return GetIsoDoseLevelSet(); +} + + +void mitk::IsoDoseLevelSetProperty::SetIsoDoseLevelSet(IsoDoseLevelSet* levelSet) +{ + if(m_IsoLevelSet != levelSet) + { + m_IsoLevelSet = levelSet; + Modified(); + } +} + +void mitk::IsoDoseLevelSetProperty::SetValue(IsoDoseLevelSet* levelSet) +{ + SetIsoDoseLevelSet(levelSet); +} + +std::string mitk::IsoDoseLevelSetProperty::GetValueAsString() const +{ + std::stringstream myStr; + + myStr << "IsoDoseLevels: "; + + if (m_IsoLevelSet.IsNotNull()) + { + myStr << m_IsoLevelSet->Size() << std::endl; + + for (IsoDoseLevelSet::ConstIterator pos = m_IsoLevelSet->Begin(); pos != m_IsoLevelSet->End(); ++pos) + { + myStr << " " << 100*(pos->GetDoseValue()) << "% : ("<GetColor()<< "); iso line: " << pos->GetVisibleIsoLine() << "; color wash: "<GetVisibleColorWash() << std::endl; + } + } + return myStr.str(); +} + +itk::LightObject::Pointer mitk::IsoDoseLevelSetProperty::InternalClone() const +{ + itk::LightObject::Pointer result(new Self(*this)); + return result; +} diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.h new file mode 100644 index 0000000000..a6f7c5357a --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.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 _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ +#define _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ + +#include "mitkBaseProperty.h" +#include "mitkIsoDoseLevelCollections.h" +#include "MitkDicomRTExports.h" + +namespace mitk { + +/** +\brief Property class for dose iso level sets. +*/ +class MitkDicomRT_EXPORT IsoDoseLevelSetProperty : public BaseProperty +{ + +protected: + IsoDoseLevelSet::Pointer m_IsoLevelSet; + + IsoDoseLevelSetProperty(); + + IsoDoseLevelSetProperty(const IsoDoseLevelSetProperty& other); + + IsoDoseLevelSetProperty(IsoDoseLevelSet* levelSet); + +public: + mitkClassMacro(IsoDoseLevelSetProperty, BaseProperty); + + itkNewMacro(IsoDoseLevelSetProperty); + mitkNewMacro1Param(IsoDoseLevelSetProperty, IsoDoseLevelSet*); + + typedef IsoDoseLevelSet ValueType; + + virtual ~IsoDoseLevelSetProperty(); + + const IsoDoseLevelSet * GetIsoDoseLevelSet() const; + const IsoDoseLevelSet * GetValue() const; + IsoDoseLevelSet * GetIsoDoseLevelSet(); + IsoDoseLevelSet * GetValue(); + + + void SetIsoDoseLevelSet(IsoDoseLevelSet* levelSet); + void SetValue(IsoDoseLevelSet* levelSet); + + virtual std::string GetValueAsString() const; + + using BaseProperty::operator=; + +private: + + // purposely not implemented + IsoDoseLevelSetProperty& operator=(const IsoDoseLevelSetProperty&); + + itk::LightObject::Pointer InternalClone() const; + + virtual bool IsEqual(const BaseProperty& property) const; + virtual bool Assign(const BaseProperty& property); + +}; + +} // namespace mitk + + +#endif /* _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ */ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp new file mode 100644 index 0000000000..cc4b577bc7 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp @@ -0,0 +1,107 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelVectorProperty.h" + + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty() +{ +} + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty(const mitk::IsoDoseLevelVectorProperty& other) + : BaseProperty(other) + , m_IsoLevelVector(other.m_IsoLevelVector) +{ +} + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty(IsoDoseLevelVector* levelVector) : m_IsoLevelVector(levelVector) +{ +} + +mitk::IsoDoseLevelVectorProperty::~IsoDoseLevelVectorProperty() +{ +} + +bool mitk::IsoDoseLevelVectorProperty::IsEqual(const BaseProperty& property) const +{ + return this->m_IsoLevelVector == static_cast(property).m_IsoLevelVector; +} + +bool mitk::IsoDoseLevelVectorProperty::Assign(const BaseProperty& property) +{ + this->m_IsoLevelVector = static_cast(property).m_IsoLevelVector; + return true; +} + +const mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetIsoDoseLevelVector() const +{ + return m_IsoLevelVector; +} + +const mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetValue() const +{ + return GetIsoDoseLevelVector(); +} + +mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetIsoDoseLevelVector() +{ + return m_IsoLevelVector; +} + +mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetValue() +{ + return GetIsoDoseLevelVector(); +} + + +void mitk::IsoDoseLevelVectorProperty::SetIsoDoseLevelVector(IsoDoseLevelVector* levelVector) +{ + if(m_IsoLevelVector != levelVector) + { + m_IsoLevelVector = levelVector; + Modified(); + } +} + +void mitk::IsoDoseLevelVectorProperty::SetValue(IsoDoseLevelVector* levelVector) +{ + SetIsoDoseLevelVector(levelVector); +} + +std::string mitk::IsoDoseLevelVectorProperty::GetValueAsString() const +{ + std::stringstream myStr; + + myStr << "IsoDoseLevels: "; + + if (m_IsoLevelVector.IsNotNull()) + { + myStr << m_IsoLevelVector->Size() << std::endl; + + for (IsoDoseLevelVector::ConstIterator pos = m_IsoLevelVector->Begin(); pos != m_IsoLevelVector->End(); ++pos) + { + myStr << " " << 100*(pos->Value()->GetDoseValue()) << "% : ("<Value()->GetColor()<< "); iso line: " << pos->Value()->GetVisibleIsoLine() << std::endl; + } + } + return myStr.str(); +} + +itk::LightObject::Pointer mitk::IsoDoseLevelVectorProperty::InternalClone() const +{ + itk::LightObject::Pointer result(new Self(*this)); + return result; +} diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h new file mode 100644 index 0000000000..3a680bcf7a --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h @@ -0,0 +1,81 @@ +/*=================================================================== + +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 _MITK_DOSE_ISO_LEVEL_VECTOR_PROPERTY_H_ +#define _MITK_DOSE_ISO_LEVEL_VECTOR_PROPERTY_H_ + +#include "mitkBaseProperty.h" +#include "mitkIsoDoseLevelCollections.h" +#include "MitkDicomRTExports.h" + +namespace mitk { + +/** +\brief Property class for dose iso level vector. +*/ +class MitkDicomRT_EXPORT IsoDoseLevelVectorProperty : public BaseProperty +{ + +protected: + IsoDoseLevelVector::Pointer m_IsoLevelVector; + + IsoDoseLevelVectorProperty(); + + IsoDoseLevelVectorProperty(const IsoDoseLevelVectorProperty& other); + + IsoDoseLevelVectorProperty(IsoDoseLevelVector* levelVector); + +public: + mitkClassMacro(IsoDoseLevelVectorProperty, BaseProperty); + + itkNewMacro(IsoDoseLevelVectorProperty); + mitkNewMacro1Param(IsoDoseLevelVectorProperty, IsoDoseLevelVector*); + + typedef IsoDoseLevelVector ValueType; + + virtual ~IsoDoseLevelVectorProperty(); + + const IsoDoseLevelVector * GetIsoDoseLevelVector() const; + const IsoDoseLevelVector * GetValue() const; + IsoDoseLevelVector * GetIsoDoseLevelVector(); + IsoDoseLevelVector * GetValue(); + + + void SetIsoDoseLevelVector(IsoDoseLevelVector* levelVector); + void SetValue(IsoDoseLevelVector* levelVector); + + virtual std::string GetValueAsString() const; + + using BaseProperty::operator=; + +private: + + // purposely not implemented + IsoDoseLevelVectorProperty& operator=(const IsoDoseLevelVectorProperty&); + + itk::LightObject::Pointer InternalClone() const; + + virtual bool IsEqual(const BaseProperty& property) const; + virtual bool Assign(const BaseProperty& property); + +}; + +} // namespace mitk + + + +#endif /* _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ */ diff --git a/Modules/DicomRT/DataStructures/mitkRTConstants.cpp b/Modules/DicomRT/DataStructures/mitkRTConstants.cpp new file mode 100644 index 0000000000..1dfd7b57d0 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkRTConstants.cpp @@ -0,0 +1,28 @@ +/*=================================================================== + +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 "mitkRTConstants.h" + +const std::string mitk::Constants::DOSE_PROPERTY_NAME = "dose"; +const std::string mitk::Constants::PRESCRIBED_DOSE_PROPERTY_NAME = "dose.PrescribedDose"; +const std::string mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME = "dose.ReferenceDose"; +const std::string mitk::Constants::DOSE_TYPE_PROPERTY_NAME = "dose.type"; +const std::string mitk::Constants::DOSE_SUMMATION_TYPE_PROPERTY_NAME = "dose.summationType"; +const std::string mitk::Constants::DOSE_FRACTION_COUNT_PROPERTY_NAME = "dose.fractionCount"; +const std::string mitk::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME = "dose.showIsoLines"; +const std::string mitk::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME = "dose.showColorWash"; +const std::string mitk::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME = "dose.isoLevels"; +const std::string mitk::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME = "dose.freeIsoValues"; diff --git a/Modules/DicomRT/DataStructures/mitkRTConstants.h b/Modules/DicomRT/DataStructures/mitkRTConstants.h new file mode 100644 index 0000000000..72dde62f8f --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkRTConstants.h @@ -0,0 +1,87 @@ +/*=================================================================== + +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 _MITK_RT_CONSTANTS_H_ +#define _MITK_RT_CONSTANTS_H_ + +#include + +#include "MitkDicomRTExports.h" + +namespace mitk +{ +struct MitkDicomRT_EXPORT Constants +{ + /** + * Name of the property that indicates if a data/node is a dose. + */ + static const std::string DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the prescribed dose associated with the data node + * If a RTPLAN file exists the value can be extracted from the tag (300A,0026) - Target Prescription Dose in the plan file. + */ + static const std::string PRESCRIBED_DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the reference dose that should be used for relative dose vizualization/evaluation purpose. + * It is often the prescribed dose but may differ e.g. when to dose distributions sould be compared using the same reference. + */ + static const std::string REFERENCE_DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the optional string property holding the information from the tag (3004,0004) - Dose Type. + * This contains useful information for medical doctors + */ + static const std::string DOSE_TYPE_PROPERTY_NAME; + + /** + * Name of the property that encodes the optional string property holding the information from the tag (3004,000A) - Dose Summation Type. + * This contains useful information for medical doctors + */ + static const std::string DOSE_SUMMATION_TYPE_PROPERTY_NAME; + + /** + * Name of the property that encodes the number of fractions. + * It is for example in DICOM stored in tag (300A,0078) - Number of Fractions Prescribed (from the RTPLAN file if this file exists). + * This value could be used to further scale the dose according to dose summation type. + * For example a given plan consists of 8 fractions. Scaling the fraction dose by 8 gives the complete planned dose. + */ + static const std::string DOSE_FRACTION_COUNT_PROPERTY_NAME; + + /** + * Name of the property that encodes if the iso line rendering should be activated for the node. + */ + static const std::string DOSE_SHOW_ISOLINES_PROPERTY_NAME; + + /** + * Name of the property that encodes if the color wash rendering should be activated for the node. + */ + static const std::string DOSE_SHOW_COLORWASH_PROPERTY_NAME; + + /** + * Name of the property that encodes if the set of iso levels should be used to visualize the dose distribution. + */ + static const std::string DOSE_ISO_LEVELS_PROPERTY_NAME; + + /** + * Name of the property that encodes user defined iso values that mark special dose values in the distribution. + */ + static const std::string DOSE_FREE_ISO_VALUES_PROPERTY_NAME; +}; +} + +#endif diff --git a/Modules/DicomRT/Testing/files.cmake b/Modules/DicomRT/Testing/files.cmake index 0c2dfa33a6..f9c7fa5d99 100644 --- a/Modules/DicomRT/Testing/files.cmake +++ b/Modules/DicomRT/Testing/files.cmake @@ -1,3 +1,4 @@ SET(MODULE_TESTS mitkRTStructureSetReaderTest.cpp + mitkRTDoseReaderTest.cpp ) diff --git a/Modules/DicomRT/Testing/mitkRTDoseReaderTest.cpp b/Modules/DicomRT/Testing/mitkRTDoseReaderTest.cpp new file mode 100644 index 0000000000..9ada1d9033 --- /dev/null +++ b/Modules/DicomRT/Testing/mitkRTDoseReaderTest.cpp @@ -0,0 +1,54 @@ +/*=================================================================== + +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 + +class mitkRTDoseReaderTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRTDoseReaderTestSuite); + MITK_TEST(TestDoseImage); + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::RTDoseReader::Pointer m_rtDoseReader; + +public: + + void setUp() + { + m_rtDoseReader = mitk::RTDoseReader::New(); + CPPUNIT_ASSERT_MESSAGE("Failed to initialize RTDoseReader", m_rtDoseReader.IsNotNull()); + } + + void TestDoseImage() + { + mitk::Image::Pointer refImage = mitk::IOUtil::LoadImage(GetTestDataFilePath("RT/Dose/RT_Dose.nrrd")); + + mitk::DataNode::Pointer node = m_rtDoseReader->LoadRTDose(GetTestDataFilePath("RT/Dose/RD.dcm").c_str()); + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + MITK_ASSERT_EQUAL(refImage, image, "referece-Image and image should be equal"); + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRTDoseReader) diff --git a/Modules/DicomRT/files.cmake b/Modules/DicomRT/files.cmake index e9c78095e7..f638320b1f 100644 --- a/Modules/DicomRT/files.cmake +++ b/Modules/DicomRT/files.cmake @@ -1,13 +1,26 @@ SET(CPP_FILES + mitkRTDoseReader.cpp mitkRTStructureSetReader.cpp + DataStructures/mitkRTConstants.cpp + DataStructures/mitkIsoDoseLevel.cpp + DataStructures/mitkIsoDoseLevelCollections.cpp + DataStructures/mitkIsoDoseLevelSetProperty.cpp + DataStructures/mitkIsoDoseLevelVectorProperty.cpp ) set(H_FILES + mitkRTDoseReader.h mitkRTStructureSetReader.h + DataStructures/mitkIsoDoseLevel.h + DataStructures/mitkIsoDoseLevelCollections.h + DataStructures/mitkIsoDoseLevelSetProperty.h + DataStructures/mitkIsoDoseLevelVectorProperty.h + DataStructures/mitkDoseValueType.h + DataStructures/mitkRTConstants.h ) set(TPP_FILES ) set(MOC_H_FILES ) diff --git a/Modules/DicomRT/mitkRTDoseReader.cpp b/Modules/DicomRT/mitkRTDoseReader.cpp new file mode 100644 index 0000000000..68f41e8efd --- /dev/null +++ b/Modules/DicomRT/mitkRTDoseReader.cpp @@ -0,0 +1,145 @@ +/*=================================================================== + +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 + +namespace mitk +{ + + RTDoseReader::RTDoseReader(){} + + RTDoseReader::~RTDoseReader(){} + + mitk::DataNode::Pointer RTDoseReader:: + LoadRTDose(const char* filename) + { + DcmFileFormat fileformat; + OFCondition outp = fileformat.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + MITK_ERROR << "Cant read the file" << endl; + } + DcmDataset *dataset = fileformat.getDataset(); + + std::string name = filename; + itk::FilenamesContainer file; + file.push_back(name); + + mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader; + + mitk::DataNode::Pointer originalNode = reader->LoadDicomSeries(file,false); + + if(originalNode.IsNull()) + { + MITK_ERROR << "Error reading the dcm file" << endl; + return 0; + } + + mitk::Image::Pointer originalImage + = dynamic_cast(originalNode->GetData()); + + DRTDoseIOD doseObject; + OFCondition result = doseObject.read(*dataset); + + if(result.bad()) + { + MITK_ERROR << "Error reading the Dataset" << endl; + return 0; + } + + OFString gridScaling; + Float32 gridscale; + + doseObject.getDoseGridScaling(gridScaling); + gridscale = OFStandard::atof(gridScaling.c_str()); + + AccessByItk_1(originalImage, MultiplayGridScaling, gridscale); + + double prescripeDose = this->GetMaxDoseValue(dataset); + + originalNode->SetName("RT Dose"); + originalNode->SetFloatProperty(mitk::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescripeDose); + originalNode->SetFloatProperty(mitk::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40); + originalNode->SetBoolProperty(mitk::Constants::DOSE_PROPERTY_NAME.c_str(),true); + return originalNode; + } + + template + void RTDoseReader::MultiplayGridScaling(itk::Image* image, + Float32 gridscale) + { + typedef itk::Image InputImageType; + itk::ImageRegionIterator it(image, + image->GetRequestedRegion()); + for(it=it.Begin(); !it.IsAtEnd(); ++it) + { + it.Set(it.Get()*gridscale); + } + } + + double RTDoseReader::GetMaxDoseValue(DcmDataset* dataSet) + { + DRTDoseIOD doseObject; + OFCondition result = doseObject.read(*dataSet); + if(result.bad()) + { + MITK_ERROR << "Error reading the RT Dose dataset" << endl; + return 0; + } + + Uint16 rows, columns, frames; + OFString nrframes, gridScaling; + const Uint16 *pixelData = NULL; + Float32 gridscale; + + Uint16 &rows_ref = rows; + Uint16 &columns_ref = columns; + + doseObject.getRows(rows_ref); + doseObject.getColumns(columns_ref); + doseObject.getNumberOfFrames(nrframes); + doseObject.getDoseGridScaling(gridScaling); + + frames = atoi(nrframes.c_str()); + gridscale = OFStandard::atof(gridScaling.c_str()); + dataSet->findAndGetUint16Array(DCM_PixelData, pixelData, 0); + + int size = columns*rows*frames; + double highest = 0; + + for(int i=0; ihighest) + { + highest = pixelData[i] * gridscale; + } + } + + return highest; + } + +} diff --git a/Modules/DicomRT/mitkRTDoseReader.h b/Modules/DicomRT/mitkRTDoseReader.h new file mode 100644 index 0000000000..af90d0d14d --- /dev/null +++ b/Modules/DicomRT/mitkRTDoseReader.h @@ -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. + +===================================================================*/ + + +#ifndef mitkDicomRTReader_h +#define mitkDicomRTReader_h + +#include +#include +#include +#include + +#include "dcmtk/dcmrt/drtdose.h" + +#include +#include +#include + +namespace mitk +{ + + class MitkDicomRT_EXPORT RTDoseReader: public itk::Object + { + + public: + + mitkClassMacro( RTDoseReader, itk::Object ); + itkNewMacro( Self ); + + template + void MultiplayGridScaling( itk::Image< TPixel, VImageDimension>* image, Float32 gridscale); + + /** + * @brief Get the maximum dose value from the dose file + * @param dataSet The DcmDataset of the DicomRTDose file + * @return The dose value + * + * Checks all pixel values for the maximum value + */ + double GetMaxDoseValue(DcmDataset* dataSet); + + /** + * @brief Reads a DcmDataset from a DicomRT dose file + * @param dataset DcmDataset-object from DCMTK + * @param filename The path with the dose file used for getting the geometry + * @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 definied 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 destructor. + */ + virtual ~RTDoseReader(); + + protected: + + /** + * Constructor. + */ + RTDoseReader(); + + }; + +} + +#endif