diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp index b6bea643ef..45958b3029 100644 --- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp @@ -1,50 +1,48 @@ /*============================================================================ 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 "mitkAreaUnderFirstMomentDescriptionParameter.h" const std::string mitk::AreaUnderFirstMomentDescriptionParameter::PARAMETER_NAME = "AreaUnderFirstMoment"; mitk::AreaUnderFirstMomentDescriptionParameter::AreaUnderFirstMomentDescriptionParameter() { } mitk::AreaUnderFirstMomentDescriptionParameter::~AreaUnderFirstMomentDescriptionParameter() { } mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderFirstMomentDescriptionParameter::GetDescriptionParameterName() const { DescriptionParameterNamesType result = { PARAMETER_NAME }; return result; } mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderFirstMomentDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const { DescriptionParameterResultsType results; CurveDescriptionParameterResultType aumc = 0; auto steps = grid.GetSize(); for (CurveGridType::size_type i = 0; i < steps - 1; ++i) { double deltaX = grid(i + 1) - grid(i); double deltaY = curve(i + 1)*grid(i + 1) - curve(i)*grid(i); double Yi = curve(i)*grid(i); - double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX; - + double intI = 0.5 * deltaX * deltaY + Yi * deltaX; aumc += std::abs(intI); - } results.push_back(aumc); return results; } diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp index e7e1a40351..556b67ce7f 100644 --- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp @@ -1,51 +1,48 @@ /*============================================================================ 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 "mitkAreaUnderTheCurveDescriptionParameter.h" const std::string mitk::AreaUnderTheCurveDescriptionParameter::PARAMETER_NAME = "AreaUnderCurve"; mitk::AreaUnderTheCurveDescriptionParameter::AreaUnderTheCurveDescriptionParameter() { } mitk::AreaUnderTheCurveDescriptionParameter::~AreaUnderTheCurveDescriptionParameter() { } mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderTheCurveDescriptionParameter::GetDescriptionParameterName() const { DescriptionParameterNamesType result = { PARAMETER_NAME }; return result; } mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderTheCurveDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const { DescriptionParameterResultsType results; CurveDescriptionParameterResultType auc = 0; auto steps = grid.GetSize(); for (CurveGridType::size_type i = 0; i < steps - 1; ++i) { double deltaX = grid(i + 1) - grid(i); double deltaY = curve(i + 1) - curve(i); double Yi = curve(i); - - double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX; - + double intI = 0.5 * deltaX * deltaY + Yi * deltaX; auc += std::abs(intI); - } results.push_back(auc); return results; } diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp index d1edcc2092..4d29bc8b0b 100644 --- a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp @@ -1,63 +1,63 @@ /*============================================================================ 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 "mitkMeanResidenceTimeDescriptionParameter.h" const std::string mitk::MeanResidenceTimeDescriptionParameter::PARAMETER_NAME = "MeanResidenceTime"; mitk::MeanResidenceTimeDescriptionParameter::MeanResidenceTimeDescriptionParameter() { } mitk::MeanResidenceTimeDescriptionParameter::~MeanResidenceTimeDescriptionParameter() { } mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::MeanResidenceTimeDescriptionParameter::GetDescriptionParameterName() const { DescriptionParameterNamesType result = { PARAMETER_NAME }; return result; } mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::MeanResidenceTimeDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const { DescriptionParameterResultsType results; CurveDescriptionParameterResultType aumc = 0; CurveDescriptionParameterResultType auc = 0; CurveDescriptionParameterResultType mrt = 0; auto steps = grid.GetSize(); for (CurveGridType::size_type i = 0; i < steps - 1; ++i) { double deltaX = grid(i + 1) - grid(i); double deltaY1 = curve(i + 1)*grid(i + 1) - curve(i)*grid(i); double Y1 = curve(i)*grid(i); - double intI1 = 1 / 2 * deltaX * deltaY1 + Y1 * deltaX; + double intI1 = 0.5 * deltaX * deltaY1 + Y1 * deltaX; aumc += std::abs(intI1); double deltaY2 = curve(i + 1) - curve(i); double Y2 = curve(i); - double intI2 = 1 / 2 * deltaX * deltaY2 + Y2 * deltaX; + double intI2 = 0.5 * deltaX * deltaY2 + Y2 * deltaX; auc += std::abs(intI2); } if(auc != 0) { mrt = aumc/auc; } results.push_back(mrt); return results; } diff --git a/Modules/Pharmacokinetics/test/files.cmake b/Modules/Pharmacokinetics/test/files.cmake index ae3fb37d4a..798cd13404 100644 --- a/Modules/Pharmacokinetics/test/files.cmake +++ b/Modules/Pharmacokinetics/test/files.cmake @@ -1,7 +1,8 @@ SET(MODULE_TESTS mitkDescriptivePharmacokineticBrixModelTest.cpp mitkStandardToftsModelTest.cpp mitkTwoCompartmentExchangeModelTest.cpp mitkExtendedToftsModelTest.cpp mitkConvertSignalToConcentrationTest.cpp + mitkCurveDescriptiveParametersTest.cpp ) diff --git a/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp b/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp new file mode 100644 index 0000000000..a6167bdaff --- /dev/null +++ b/Modules/Pharmacokinetics/test/mitkCurveDescriptiveParametersTest.cpp @@ -0,0 +1,124 @@ +/*============================================================================ + +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. + +============================================================================*/ + +// Testing +#include "mitkTestingMacros.h" +#include "mitkTestFixture.h" + +//MITK includes +#include "mitkVector.h" +#include "mitkMaximumCurveDescriptionParameter.h" +#include "mitkMeanResidenceTimeDescriptionParameter.h" +#include "mitkAreaUnderTheCurveDescriptionParameter.h" +#include "mitkAreaUnderFirstMomentDescriptionParameter.h" +#include "mitkTimeToPeakCurveDescriptionParameter.h" + +class mitkCurveDescriptiveParametersTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkCurveDescriptiveParametersTestSuite); + MITK_TEST(MaximumCurveDescriptionParameterTest); + MITK_TEST(AreaUnderTheCurveDescriptionParameterTest); + MITK_TEST(AreaUnderFirstMomentDescriptionParameterTest); + MITK_TEST(MeanResidenceTimeDescriptionParameterTest); + MITK_TEST(TimeToPeakDescriptionParameterTest); + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_maxParameter; + mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_aucParameter; + mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_aumcParameter; + mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_mrtParameter; + mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType m_ttpParameter; + +public: + void setUp() override + { + mitk::ModelBase::TimeGridType m_grid(22); + for (int i = 0; i < 22; ++i) + { + // time grid in seconds, 14s between frames + m_grid[i] = (double)14 * i; + } + + static const double t = 100.0; + static const double b1 = 0.0; + static const double a1 = 5.0; + static const double a2 = -3.0; + const auto b2 = (a1-a2) * t + b1; + + + mitk::ModelBase::ModelResultType signal(m_grid.GetSize()); + mitk::ModelBase::TimeGridType::const_iterator timeGridEnd = m_grid.end(); + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + + for (mitk::ModelBase::ModelResultType::const_iterator gridPos = m_grid.begin(); gridPos != timeGridEnd; ++gridPos, ++signalPos) + { + if ((*gridPos) < t) + { + *signalPos = a1 * (*gridPos) + b1; + } + else + { + *signalPos = a2 * (*gridPos) + b2; + } + } + + mitk::CurveDescriptionParameterBase::Pointer maxParameterFunction = mitk::MaximumCurveDescriptionParameter::New().GetPointer(); + m_maxParameter = maxParameterFunction->GetCurveDescriptionParameter(signal, m_grid); + + mitk::CurveDescriptionParameterBase::Pointer aucParameterFunction = mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer(); + m_aucParameter = aucParameterFunction->GetCurveDescriptionParameter(signal, m_grid); + + mitk::CurveDescriptionParameterBase::Pointer aumcParameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer(); + m_aumcParameter = aumcParameterFunction->GetCurveDescriptionParameter(signal, m_grid); + + mitk::CurveDescriptionParameterBase::Pointer mrtParameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer(); + m_mrtParameter = mrtParameterFunction->GetCurveDescriptionParameter(signal, m_grid); + + mitk::CurveDescriptionParameterBase::Pointer ttpParameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer(); + m_ttpParameter = ttpParameterFunction->GetCurveDescriptionParameter(signal, m_grid); + } + + + void tearDown() override + { + + } + + void MaximumCurveDescriptionParameterTest() + { + CPPUNIT_ASSERT_MESSAGE("Checking maximum value.", mitk::Equal(490.0, m_maxParameter[0], 1e-6, true) == true); + } + + void AreaUnderTheCurveDescriptionParameterTest() + { + CPPUNIT_ASSERT_MESSAGE("Checking auc value.", mitk::Equal(67690.0, m_aucParameter[0], 1e-6, true) == true); + } + + void AreaUnderFirstMomentDescriptionParameterTest() + { + CPPUNIT_ASSERT_MESSAGE("Checking aumc value.", mitk::Equal(8459948.0, m_aumcParameter[0], 1e-6, true) == true); + } + + void MeanResidenceTimeDescriptionParameterTest() + { + CPPUNIT_ASSERT_MESSAGE("Checking mrt value.", mitk::Equal(124.980765253, m_mrtParameter[0], 1e-6, true) == true); + } + + void TimeToPeakDescriptionParameterTest() + { + CPPUNIT_ASSERT_MESSAGE("Checking ttp value.", mitk::Equal(98.0, m_ttpParameter[0], 1e-6, true) == true); + } +}; +MITK_TEST_SUITE_REGISTRATION(mitkCurveDescriptiveParameters) + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox index 1814f00b35..ab9068b411 100644 --- a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox @@ -1,27 +1,27 @@ /** \page org_mitk_views_pharmacokinetics_curvedescriptor The Perfusion Curve Description Parameters View \imageMacro{pharmacokinetics_curve_desc_doc.svg,"Icon of the Perfusion Curve Description Parameters View",3.0} \tableofcontents \section org_mitk_views_pharmacokinetics_curvedescriptor_overview Overview In cases where data quality is not sufficient for dedicated pharmacokinetic analysis, or if global scouting of the overall image is performed to identify regions of interest, it is often advisable to use semi-quantitative measures that describe the general shape and type of the curve. The Perfusion Curve Description Parameters View can be used to voxelwise calculate these parameters. Currently the following parameters are offered by the tool (visualized in figure 1): \imageMacro{pharmacokinetics_curve_desc_parameter_description.png,"Figure 1: Calculation of currently available descriptive parameters",3.0} -- area-under-the-curve (AUC): The area under the signal time curve is calculated by step-wise integration with linear interpolation between sampling points. -- area-under the first moment curve (AUMC): The area under the first moment signal time curve is calculated by step-wise integration with linear interpolation between sampling points. +- area-under-the-curve (AUC): The absolute area under the signal time curve is calculated by step-wise integration with linear interpolation between sampling points. +- area-under the first moment curve (AUMC): The absolute area under the first moment signal time curve is calculated by step-wise integration with linear interpolation between sampling points. - mean-residence-time (MRT): The mean residence time is calculated as MRT = AUMC/AUC. - time-to-peak: The duration between the onset time and the time of the maximum signal of the curve. - maximum signal: The overall maximum of all data points of the curve. These parameters are usually calculated directly from the raw data signal intensities of the acquired MR image. Alternatively, if semi-quantitative parameters should be calculated from concentration time curves, use the \ref org_mitk_views_pharmacokinetics_concentration_mri prior to the parameter calculation. Parameters of interest can be selected from the list. Selecting a 4D image enables the Calculate Parameters button. Resulting parameter maps will afterwards be added to the data manager as subnodes to the analyzed 4D image. */