diff --git a/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.cpp b/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.cpp index 46264a8a2a..2f17becddb 100644 --- a/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.cpp +++ b/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.cpp @@ -1,388 +1,414 @@ /*=================================================================== 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 "mitkAlgorithmHelper.h" //itk #include // Mitk #include #include // MatchPoint #include #include #include #include #include namespace mitk { MITKAlgorithmHelper::MITKAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase *algorithm) : m_AlgorithmBase(algorithm), m_Error(CheckError::none) { m_AllowImageCasting = true; } + bool MITKAlgorithmHelper::HasImageAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm) + { + using InternalDefault2DImageType = itk::Image; + using InternalDefault3DImageType = itk::Image; + + using Alg2DType = const ::map::algorithm::facet::ImageRegistrationAlgorithmInterface; + if (dynamic_cast(algorithm) != nullptr) return true; + using Alg3DType = const ::map::algorithm::facet::ImageRegistrationAlgorithmInterface; + if (dynamic_cast(algorithm) != nullptr) return true; + using Alg2D3DType = const ::map::algorithm::facet::ImageRegistrationAlgorithmInterface; + if (dynamic_cast(algorithm) != nullptr) return true; + using Alg3D2DType = const ::map::algorithm::facet::ImageRegistrationAlgorithmInterface; + if (dynamic_cast(algorithm) != nullptr) return true; + + return false; + }; + + bool MITKAlgorithmHelper::HasPointSetAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm) + { + typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType; + typedef const ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface + PointSetRegInterface; + + return dynamic_cast(algorithm) != nullptr; + }; + map::core::RegistrationBase::Pointer MITKAlgorithmHelper:: GetRegistration() const { map::core::RegistrationBase::Pointer spResult; unsigned int movingDim = m_AlgorithmBase->getMovingDimensions(); unsigned int targetDim = m_AlgorithmBase->getTargetDimensions(); if (movingDim != targetDim) { mapDefaultExceptionStaticMacro( << "Error, algorithm instance has unequal dimensionality and is therefore not supported in the current version of MITKAlgorithmHelper."); } if (movingDim > 3) { mapDefaultExceptionStaticMacro( << "Error, algorithm instance has a dimensionality larger than 3 and is therefore not supported in the current version of MITKAlgorithmHelper."); } typedef ::map::algorithm::facet::RegistrationAlgorithmInterface<2, 2> RegistrationAlg2D2DInterface; typedef ::map::algorithm::facet::RegistrationAlgorithmInterface<3, 3> RegistrationAlg3D3DInterface; RegistrationAlg2D2DInterface* pRegAlgorithm2D2D = dynamic_cast (m_AlgorithmBase.GetPointer()); RegistrationAlg3D3DInterface* pRegAlgorithm3D3D = dynamic_cast (m_AlgorithmBase.GetPointer()); if (pRegAlgorithm2D2D) { spResult = pRegAlgorithm2D2D->getRegistration(); } if (pRegAlgorithm3D3D) { spResult = pRegAlgorithm3D3D->getRegistration(); } return spResult; } mitk::MAPRegistrationWrapper::Pointer MITKAlgorithmHelper:: GetMITKRegistrationWrapper() const { map::core::RegistrationBase::Pointer spInternalResult = GetRegistration(); mitk::MAPRegistrationWrapper::Pointer spResult = mitk::MAPRegistrationWrapper::New(); spResult->SetRegistration(spInternalResult); return spResult; }; static const mitk::Image* GetDataAsImage(const mitk::BaseData* data) { return dynamic_cast(data); }; static const mitk::PointSet* GetDataAsPointSet(const mitk::BaseData* data) { return dynamic_cast(data); }; bool MITKAlgorithmHelper:: CheckData(const mitk::BaseData* moving, const mitk::BaseData* target, CheckError::Type& error) const { if (! m_AlgorithmBase) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Helper has no algorithm defined."); } if (! moving) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Moving data pointer is nullptr."); } if (! target) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Target data pointer is nullptr."); } bool result = false; m_Error = CheckError::unsupportedDataType; unsigned int movingDim = m_AlgorithmBase->getMovingDimensions(); unsigned int targetDim = m_AlgorithmBase->getTargetDimensions(); if (movingDim != targetDim) { m_Error = CheckError::wrongDimension; } else { //First check if data are point sets or images if (GetDataAsPointSet(target) && GetDataAsPointSet(moving)) { typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType; typedef ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface PointSetRegInterface; PointSetRegInterface* pPointSetInterface = dynamic_cast (m_AlgorithmBase.GetPointer()); if (!pPointSetInterface) { result = false; m_Error = CheckError::unsupportedDataType; } } else if (GetDataAsImage(moving) && GetDataAsImage(target)) { if (movingDim == 2) { AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoCheckImages, 2); } else if (movingDim == 3) { AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoCheckImages, 3); } else { m_Error = CheckError::wrongDimension; } if (m_Error == CheckError::none || (m_AllowImageCasting && m_Error == CheckError::onlyByCasting)) { result = true; } } } error = m_Error; return result; }; void MITKAlgorithmHelper::SetAllowImageCasting(bool allowCasting) { this->m_AllowImageCasting = allowCasting; }; bool MITKAlgorithmHelper::GetAllowImageCasting() const { return this->m_AllowImageCasting; }; void MITKAlgorithmHelper::SetData(const mitk::BaseData* moving, const mitk::BaseData* target) { if (! m_AlgorithmBase) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Helper has no algorithm defined."); } if (! moving) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Moving data pointer is nullptr."); } if (! target) { mapDefaultExceptionStaticMacro( << "Error, cannot check data. Target data pointer is nullptr."); } unsigned int movingDim = m_AlgorithmBase->getMovingDimensions(); unsigned int targetDim = m_AlgorithmBase->getTargetDimensions(); if (movingDim != targetDim) { mapDefaultExceptionStaticMacro( << "Error, cannot set data. Current version of MITKAlgorithmHelper only supports images/point sets with same dimensionality."); } if (GetDataAsPointSet(target) && GetDataAsPointSet(moving)) { typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType; typedef ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface PointSetRegInterface; PointSetRegInterface* pPointSetInterface = dynamic_cast (m_AlgorithmBase.GetPointer()); pPointSetInterface->setMovingPointSet(mitk::PointSetMappingHelper::ConvertPointSetMITKtoMAP( GetDataAsPointSet(moving)->GetPointSet())); pPointSetInterface->setTargetPointSet(mitk::PointSetMappingHelper::ConvertPointSetMITKtoMAP( GetDataAsPointSet(target)->GetPointSet())); } else if (GetDataAsImage(moving) && GetDataAsImage(target)) { if (movingDim == 2) { AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoSetImages, 2); } else if (movingDim == 3) { AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoSetImages, 3); } } }; template typename TOutImageType::Pointer MITKAlgorithmHelper::CastImage(const TInImageType* input) const { typedef itk::CastImageFilter< TInImageType, TOutImageType > CastFilterType; typename CastFilterType::Pointer spImageCaster = CastFilterType::New(); spImageCaster->SetInput(input); typename TOutImageType::Pointer spImage = spImageCaster->GetOutput(); spImageCaster->Update(); return spImage; } template void MITKAlgorithmHelper::DoSetImages(const itk::Image* moving, const itk::Image* target) { typedef itk::Image MovingImageType; typedef itk::Image TargetImageType; typedef itk::Image InternalDefaultMovingImageType; typedef itk::Image InternalDefaultTargetImageType; typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface ImageRegInterface; typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface DefaultImageRegInterface; ImageRegInterface* pImageInterface = dynamic_cast(m_AlgorithmBase.GetPointer()); DefaultImageRegInterface* pDefaultImageInterface = dynamic_cast (m_AlgorithmBase.GetPointer()); if (pImageInterface) { //just set directly and you are done /**@todo the duplication work arround is needed due to a insufficuence in the AccessTwoImagesFixedDimensionByItk macro. The macro always cast the passed image into non const (even if tha image was passed as const). This behavior enforces the unnecessary use of an writeaccessor, which as a consequence will lead to redundant access exceptions as long as the algorithm exists; e.g. in the typical scenario with the MatchPoint Plugins*/ typedef itk::ImageDuplicator< MovingImageType > MovingDuplicatorType; typedef itk::ImageDuplicator< TargetImageType > TargetDuplicatorType; typename MovingDuplicatorType::Pointer mDuplicator = MovingDuplicatorType::New(); mDuplicator->SetInputImage(moving); mDuplicator->Update(); typename TargetDuplicatorType::Pointer tDuplicator = TargetDuplicatorType::New(); tDuplicator->SetInputImage(target); tDuplicator->Update(); typename MovingImageType::Pointer clonedMoving = mDuplicator->GetOutput(); typename TargetImageType::Pointer clonedTarget = tDuplicator->GetOutput(); pImageInterface->setTargetImage(clonedTarget); pImageInterface->setMovingImage(clonedMoving); } else if (pDefaultImageInterface) { //you may convert it to the default image type and use it then if (! m_AllowImageCasting) { mapDefaultExceptionStaticMacro( << "Error, cannot set images. MITKAlgorithmHelper has to convert them into MatchPoint default images, but is not allowed. Please reconfigure helper."); } typename InternalDefaultTargetImageType::Pointer spCastedTarget = CastImage(target); typename InternalDefaultMovingImageType::Pointer spCastedMoving = CastImage(moving); pDefaultImageInterface->setTargetImage(spCastedTarget); pDefaultImageInterface->setMovingImage(spCastedMoving); } else { mapDefaultExceptionStaticMacro( << "Error, algorithm is not able to use the based images."); } } template void MITKAlgorithmHelper::DoCheckImages(const itk::Image* /*moving*/, const itk::Image* /*target*/) const { typedef itk::Image MovingImageType; typedef itk::Image TargetImageType; typedef itk::Image InternalDefaultMovingImageType; typedef itk::Image InternalDefaultTargetImageType; typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface ImageRegInterface; typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface DefaultImageRegInterface; ImageRegInterface* pImageInterface = dynamic_cast(m_AlgorithmBase.GetPointer()); DefaultImageRegInterface* pDefaultImageInterface = dynamic_cast (m_AlgorithmBase.GetPointer()); if (pImageInterface) { //just set directly and you are done m_Error = CheckError::none; } else if (pDefaultImageInterface) { //you may convert it to the default image type and use it then m_Error = CheckError::onlyByCasting; } else { m_Error = CheckError::unsupportedDataType; } } mapGenerateAlgorithmUIDPolicyMacro(DummyRegIDPolicy, "de.dkfz.dipp", "Identity", "1.0.0", ""); mitk::MAPRegistrationWrapper::Pointer GenerateIdentityRegistration3D() { typedef map::algorithm::DummyImageRegistrationAlgorithm::InternalImageType, map::core::discrete::Elements<3>::InternalImageType, DummyRegIDPolicy> DummyRegType; DummyRegType::Pointer regAlg = DummyRegType::New(); mitk::MITKAlgorithmHelper helper(regAlg); map::core::discrete::Elements<3>::InternalImageType::Pointer dummyImg = map::core::discrete::Elements<3>::InternalImageType::New(); dummyImg->Allocate(); regAlg->setTargetImage(dummyImg); regAlg->setMovingImage(dummyImg); mitk::MAPRegistrationWrapper::Pointer dummyReg = mitk::MAPRegistrationWrapper::New(); dummyReg->SetRegistration(regAlg->getRegistration()); return dummyReg; } } diff --git a/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.h b/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.h index b1d1d51ecd..7cc70aeda4 100644 --- a/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.h +++ b/Modules/MatchPointRegistration/Helper/mitkAlgorithmHelper.h @@ -1,107 +1,111 @@ /*=================================================================== 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 mitkAlgorithmHelper_h #define mitkAlgorithmHelper_h //MatchPoint #include "mapRegistrationAlgorithmBase.h" #include "mapRegistrationBase.h" //MITK #include #include //MITK #include "MitkMatchPointRegistrationExports.h" #include "mitkMAPRegistrationWrapper.h" namespace mitk { /*! \brief MITKAlgorithmHelper \remark Current implementation is not thread-save. Just use one Helper class per registration task. \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. */ class MITKMATCHPOINTREGISTRATION_EXPORT MITKAlgorithmHelper { public: - MITKAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm = nullptr); + MITKAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm); void SetData(const mitk::BaseData* moving, const mitk::BaseData* target); void SetAllowImageCasting(bool allowCasting); bool GetAllowImageCasting() const; + static bool HasImageAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm); + static bool HasPointSetAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm); + + struct CheckError { enum Type { none = 0, onlyByCasting = 1, wrongDimension = 2, unsupportedDataType = 3 }; }; bool CheckData(const mitk::BaseData* moving, const mitk::BaseData* target, CheckError::Type& error) const; map::core::RegistrationBase::Pointer GetRegistration() const; mitk::MAPRegistrationWrapper::Pointer GetMITKRegistrationWrapper() const; ~MITKAlgorithmHelper() {} private: MITKAlgorithmHelper& operator = (const MITKAlgorithmHelper&); MITKAlgorithmHelper(const MITKAlgorithmHelper&); /**Internal helper that casts itk images from one pixel type into an other (used by DoSetImages if the images have the right dimension but wrong type and AllowImageCasting is activated)*/ template typename TOutImageType::Pointer CastImage(const TInImageType* input) const; /**Internal helper that is used by SetData if the data are images to set them properly.*/ template void DoSetImages(const itk::Image* moving, const itk::Image* target); /**Internal helper that is used by SetData if the data are images to check if the image types are supported by the algorithm.*/ template void DoCheckImages(const itk::Image* moving, const itk::Image* target) const; map::algorithm::RegistrationAlgorithmBase::Pointer m_AlgorithmBase; bool m_AllowImageCasting; mutable CheckError::Type m_Error; }; /**Small helper function that generates Identity transforms in 3D.*/ mitk::MAPRegistrationWrapper::Pointer MITKMATCHPOINTREGISTRATION_EXPORT GenerateIdentityRegistration3D(); } #endif diff --git a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp b/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp index a7217a76f0..a1fa06893d 100644 --- a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp +++ b/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.cpp @@ -1,171 +1,179 @@ /*=================================================================== 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 "mitkMaskedAlgorithmHelper.h" #include // Mitk #include // MatchPoint #include "mapMaskedRegistrationAlgorithmInterface.h" #include namespace mitk { MaskedAlgorithmHelper::MaskedAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm) : m_AlgorithmBase(algorithm) { } + bool MaskedAlgorithmHelper::HasMaskedRegistrationAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm) + { + using MaskedInterface2D = const ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<2, 2>; + using MaskedInterface3D = const ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<3, 3>; + + return dynamic_cast(algorithm) != nullptr && dynamic_cast(algorithm) != nullptr; + }; + bool MaskedAlgorithmHelper:: CheckSupport(const mitk::Image* movingMask, const mitk::Image* targetMask) const { if (! m_AlgorithmBase) mapDefaultExceptionStaticMacro(<< "Error, cannot check data. Helper has no algorithm defined."); unsigned int movingDim = m_AlgorithmBase->getMovingDimensions(); unsigned int targetDim = m_AlgorithmBase->getTargetDimensions(); bool result = movingDim == targetDim; if ( movingMask) { result = result && (movingMask->GetDimension() == movingDim); if (movingDim == 2) { typedef itk::Image MaskImageType; mitk::PixelType maskPixelType = mitk::MakePixelType(); result = result && (maskPixelType == movingMask->GetPixelType()); } else if (movingDim == 3) { typedef itk::Image MaskImageType; mitk::PixelType maskPixelType = mitk::MakePixelType(); result = result && (maskPixelType == movingMask->GetPixelType()); } } if ( targetMask) { result = result && (targetMask->GetDimension() == targetDim); if (movingDim == 2) { typedef itk::Image MaskImageType; mitk::PixelType maskPixelType = mitk::MakePixelType(); result = result && (maskPixelType == targetMask->GetPixelType()); } else if (movingDim == 3) { typedef itk::Image MaskImageType; mitk::PixelType maskPixelType = mitk::MakePixelType(); result = result && (maskPixelType == targetMask->GetPixelType()); } } if (movingDim == 2) { typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<2, 2> MaskedInterface; const MaskedInterface* pMaskedReg = dynamic_cast(m_AlgorithmBase.GetPointer()); result = result && pMaskedReg; } else if (movingDim == 3) { typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<3, 3> MaskedInterface; const MaskedInterface* pMaskedReg = dynamic_cast(m_AlgorithmBase.GetPointer()); result = result && pMaskedReg; } else { result = false; } return result; }; bool MaskedAlgorithmHelper::SetMasks(const mitk::Image* movingMask, const mitk::Image* targetMask) { if (! m_AlgorithmBase) mapDefaultExceptionStaticMacro(<< "Error, cannot set data. Helper has no algorithm defined."); if (! CheckSupport(movingMask, targetMask)) return false; unsigned int movingDim = m_AlgorithmBase->getMovingDimensions(); unsigned int targetDim = m_AlgorithmBase->getTargetDimensions(); if (movingDim!=targetDim) return false; if (movingDim == 2) { return DoSetMasks<2,2>(movingMask, targetMask); } else if (movingDim == 3) { return DoSetMasks<3,3>(movingMask, targetMask); } return false; }; template bool MaskedAlgorithmHelper::DoSetMasks(const mitk::Image* movingMask, const mitk::Image* targetMask) { typedef itk::SpatialObject MovingSpatialType; typedef itk::SpatialObject TargetSpatialType; typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface MaskedRegInterface; MaskedRegInterface* pAlg = dynamic_cast(m_AlgorithmBase.GetPointer()); if (!pAlg) return false; if (movingMask) { AccessFixedTypeByItk(movingMask, DoConvertMask, (MaskPixelType), (VImageDimension1)); typename MovingSpatialType::Pointer movingSpatial = dynamic_cast(m_convertResult.GetPointer()); if (! movingSpatial) mapDefaultExceptionStaticMacro(<< "Error, cannot convert moving mask."); pAlg->setMovingMask(movingSpatial); } if (targetMask) { AccessFixedTypeByItk(targetMask, DoConvertMask, (MaskPixelType), (VImageDimension2)); typename TargetSpatialType::Pointer targetSpatial = dynamic_cast(m_convertResult.GetPointer()); if (! targetSpatial) mapDefaultExceptionStaticMacro(<< "Error, cannot convert moving mask."); pAlg->setTargetMask(targetSpatial); } return true; } template void MaskedAlgorithmHelper::DoConvertMask(const itk::Image* mask) { typedef itk::ImageMaskSpatialObject SpatialType; typename SpatialType::Pointer spatial = SpatialType::New(); spatial->SetImage(mask); m_convertResult = spatial.GetPointer(); } } diff --git a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h b/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h index 34ccc9a56d..c878bfd0a3 100644 --- a/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h +++ b/Modules/MatchPointRegistration/Helper/mitkMaskedAlgorithmHelper.h @@ -1,80 +1,82 @@ /*=================================================================== 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 mitkMaskedAlgorithmHelper_h #define mitkMaskedAlgorithmHelper_h //MatchPoint #include "mapRegistrationAlgorithmBase.h" //MITK #include //MITK #include "MitkMatchPointRegistrationExports.h" namespace mitk { /*! \brief MaskedAlgorithmHelper Helper class as an easy bridge to set mitk images as masks for registration algorithms. It is assumed that the Image indicates the mask by pixel values != 0. \remark Currently only 2D-2D and 3D-3D algorithms are supported. \remark Currently only masks with pixel type unsigned char (default mitk segmentation images) are supported. \remark Current implementation is not thread-save. Just use one Helper class per registration task. */ class MITKMATCHPOINTREGISTRATION_EXPORT MaskedAlgorithmHelper { public: - MaskedAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm = nullptr); + MaskedAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm); /** Set one or both masks to an algorithm. * If the algorithm does not support masks it will be ignored. * @remark Set a mask to nullptr if you don't want to set it. * @return Indicates if the masks could be set/was supported by algorithm.*/ bool SetMasks(const mitk::Image* movingMask, const mitk::Image* targetMask); /** Checks if the algorithm supports masks of the passed type.*/ bool CheckSupport(const mitk::Image* movingMask, const mitk::Image* targetMask) const; + static bool HasMaskedRegistrationAlgorithmInterface(const map::algorithm::RegistrationAlgorithmBase* algorithm); + ~MaskedAlgorithmHelper() {} private: typedef unsigned char MaskPixelType; MaskedAlgorithmHelper& operator = (const MaskedAlgorithmHelper&); MaskedAlgorithmHelper(const MaskedAlgorithmHelper&); /**Internal helper that is used by SetMasks if the data are images to set them properly.*/ template bool DoSetMasks(const mitk::Image* movingMask, const mitk::Image* targetMask); /**Internal helper that is used by SetData if the data are images to set them properly.*/ template void DoConvertMask(const itk::Image* mask); /**Helper member that containes the result of the last call of DoConvertMask().*/ itk::DataObject::Pointer m_convertResult; map::algorithm::RegistrationAlgorithmBase::Pointer m_AlgorithmBase; }; } #endif diff --git a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.cpp b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.cpp index 50d70c2b46..97dcff7c31 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.cpp +++ b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.cpp @@ -1,978 +1,882 @@ /*=================================================================== 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 "org_mitk_gui_qt_matchpoint_algorithmcontrol_Activator.h" // Blueberry #include #include #include #include // Mitk #include #include #include #include #include +#include #include #include #include #include #include +#include // Qmitk #include "QmitkMatchPoint.h" #include #include // Qt #include #include #include #include #include // MatchPoint #include #include #include #include #include #include #include #include #include const std::string QmitkMatchPoint::VIEW_ID = "org.mitk.views.matchpoint.algorithm.control"; QmitkMatchPoint::QmitkMatchPoint() : m_Parent(nullptr), m_LoadedDLLHandle(nullptr), m_LoadedAlgorithm(nullptr) { m_CanLoadAlgorithm = false; m_ValidInputs = false; m_Working = false; m_spSelectedTargetData = nullptr; m_spSelectedMovingData = nullptr; m_spSelectedTargetMaskData = nullptr; m_spSelectedMovingMaskData = nullptr; } QmitkMatchPoint::~QmitkMatchPoint() { // remove selection service berry::ISelectionService* s = this->GetSite()->GetWorkbenchWindow()->GetSelectionService(); if (s) { s->RemoveSelectionListener(m_AlgorithmSelectionListener.data()); } } void QmitkMatchPoint::SetFocus() { } void QmitkMatchPoint::CreateConnections() { - - connect(m_Controls.checkMovingMask, SIGNAL(toggled(bool)), this, - SLOT(OnMaskCheckBoxToggeled(bool))); - connect(m_Controls.checkTargetMask, SIGNAL(toggled(bool)), this, - SLOT(OnMaskCheckBoxToggeled(bool))); + connect(m_Controls.targetNodeSelector, SIGNAL(CurrentSelectionChanged(QList)), this, SLOT(OnNodeSelectionChanged(QList))); + connect(m_Controls.movingNodeSelector, SIGNAL(CurrentSelectionChanged(QList)), this, SLOT(OnNodeSelectionChanged(QList))); + connect(m_Controls.targetMaskNodeSelector, SIGNAL(CurrentSelectionChanged(QList)), this, SLOT(OnNodeSelectionChanged(QList))); + connect(m_Controls.movingMaskNodeSelector, SIGNAL(CurrentSelectionChanged(QList)), this, SLOT(OnNodeSelectionChanged(QList))); // ------ // Tab 1 - Shared library loading interface // ------ connect(m_Controls.m_pbLoadSelected, SIGNAL(clicked()), this, SLOT(OnLoadAlgorithmButtonPushed())); // ----- // Tab 2 - Execution // ----- connect(m_Controls.m_pbStartReg, SIGNAL(clicked()), this, SLOT(OnStartRegBtnPushed())); connect(m_Controls.m_pbStopReg, SIGNAL(clicked()), this, SLOT(OnStopRegBtnPushed())); connect(m_Controls.m_pbSaveLog, SIGNAL(clicked()), this, SLOT(OnSaveLogBtnPushed())); } const map::deployment::DLLInfo* QmitkMatchPoint::GetSelectedAlgorithmDLL() const { return m_SelectedAlgorithmInfo; } -void QmitkMatchPoint::OnMaskCheckBoxToggeled(bool) -{ - if (!m_Working) - { - CheckInputs(); - ConfigureRegistrationControls(); - } -}; - void QmitkMatchPoint::OnSelectedAlgorithmChanged() { std::stringstream descriptionString; ::map::deployment::DLLInfo::ConstPointer currentItemInfo = GetSelectedAlgorithmDLL(); if (!currentItemInfo) { Error(QString("No valid algorithm is selected. ABORTING.")); return; } m_Controls.m_teAlgorithmDetails->updateInfo(currentItemInfo); m_Controls.m_lbSelectedAlgorithm->setText(QString::fromStdString( currentItemInfo->getAlgorithmUID().getName())); // enable loading m_CanLoadAlgorithm = true; this->AdaptFolderGUIElements(); } void QmitkMatchPoint::OnLoadAlgorithmButtonPushed() { map::deployment::DLLInfo::ConstPointer dllInfo = GetSelectedAlgorithmDLL(); if (!dllInfo) { Error(QString("No valid algorithm is selected. Cannot load algorithm. ABORTING.")); return; } ::map::deployment::DLLHandle::Pointer tempDLLHandle = ::map::deployment::openDeploymentDLL( dllInfo->getLibraryFilePath()); ::map::algorithm::RegistrationAlgorithmBase::Pointer tempAlgorithm = ::map::deployment::getRegistrationAlgorithm(tempDLLHandle); if (tempAlgorithm.IsNull()) { Error(QString("Error. Cannot load selected algorithm.")); return; } this->m_LoadedAlgorithm = tempAlgorithm; this->m_LoadedDLLHandle = tempDLLHandle; this->m_Controls.m_AlgoConfigurator->setAlgorithm(m_LoadedAlgorithm); - m_Controls.checkMovingMask->setChecked(false); - m_Controls.checkTargetMask->setChecked(false); + + typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<3, 3> MaskRegInterface; + const MaskRegInterface* pMaskReg = dynamic_cast + (m_LoadedAlgorithm.GetPointer()); + + if (!pMaskReg) + { + m_spSelectedTargetMaskData = nullptr; + m_spSelectedTargetMaskNode = nullptr; + m_spSelectedMovingMaskData = nullptr; + m_spSelectedMovingMaskNode = nullptr; + m_Controls.targetMaskNodeSelector->SetCurrentSelection(QmitkAbstractNodeSelectionWidget::NodeList()); + m_Controls.movingMaskNodeSelector->SetCurrentSelection(QmitkAbstractNodeSelectionWidget::NodeList()); + } + this->AdaptFolderGUIElements(); + this->ConfigureNodeSelectors(); this->CheckInputs(); this->ConfigureRegistrationControls(); this->ConfigureProgressInfos(); this->m_Controls.m_tabs->setCurrentIndex(1); this->m_Controls.m_teLog->clear(); } void QmitkMatchPoint::Error(QString msg) { mitk::StatusBar::GetInstance()->DisplayErrorText(msg.toLatin1()); MITK_ERROR << msg.toStdString().c_str(); m_Controls.m_teLog->append(QString("") + msg + QString("")); } void QmitkMatchPoint::AdaptFolderGUIElements() { m_Controls.m_pbLoadSelected->setEnabled(m_CanLoadAlgorithm); } void QmitkMatchPoint::CreateQtPartControl(QWidget* parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; - m_Controls.checkMovingMask->setChecked(false); - m_Controls.checkTargetMask->setChecked(false); m_Controls.m_tabs->setCurrentIndex(0); + m_Controls.movingNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.movingNodeSelector->SetSelectionIsOptional(false); + m_Controls.targetNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.targetNodeSelector->SetSelectionIsOptional(false); + m_Controls.movingMaskNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.movingMaskNodeSelector->SetSelectionIsOptional(true); + m_Controls.targetMaskNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.targetMaskNodeSelector->SetSelectionIsOptional(true); + m_AlgorithmSelectionListener.reset(new berry::SelectionChangedAdapter(this, &QmitkMatchPoint::OnAlgorithmSelectionChanged)); // register selection listener GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddSelectionListener( m_AlgorithmSelectionListener.data()); this->CreateConnections(); this->AdaptFolderGUIElements(); this->CheckInputs(); this->ConfigureProgressInfos(); this->ConfigureRegistrationControls(); + this->ConfigureNodeSelectors(); berry::ISelection::ConstPointer selection = GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.matchpoint.algorithm.browser"); this->UpdateAlgorithmSelection(selection); } -bool QmitkMatchPoint::CheckInputs() +mitk::Image::Pointer ExtractFirstFrame(const mitk::Image* dynamicImage) { - bool validMoving = false; - bool validTarget = false; - - bool validMovingMask = false; - bool validTargetMask = false; + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(dynamicImage); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); - mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); - mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); - mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); - mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); - - mitk::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); + return imageTimeSelector->GetOutput(); +}; +bool QmitkMatchPoint::CheckInputs() +{ if (m_LoadedAlgorithm.IsNull()) { - m_Controls.m_lbMovingName->setText(QString("No algorithm selected!")); m_spSelectedMovingNode = nullptr; m_spSelectedMovingData = nullptr; - m_Controls.m_lbTargetName->setText(QString("No algorithm selected!")); m_spSelectedTargetNode = nullptr; m_spSelectedTargetData = nullptr; m_spSelectedMovingMaskNode = nullptr; m_spSelectedMovingMaskData = nullptr; m_spSelectedTargetMaskNode = nullptr; m_spSelectedTargetMaskData = nullptr; } else { - QList nodes = this->GetDataManagerSelection(); - - mitk::Image* movingImage = nullptr; - mitk::PointSet* movingPointSet = nullptr; - mitk::Image* targetImage = nullptr; - mitk::PointSet* targetPointSet = nullptr; - - mitk::Image* movingMaskImage = nullptr; - mitk::Image* targetMaskImage = nullptr; - - typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType; - typedef ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface - PointSetRegInterface; - typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<3, 3> MaskRegInterface; - - PointSetRegInterface* pPointSetInterface = dynamic_cast - (m_LoadedAlgorithm.GetPointer()); - MaskRegInterface* pMaskInterface = dynamic_cast(m_LoadedAlgorithm.GetPointer()); - - if (nodes.count() < 1) + if (m_Controls.movingNodeSelector->GetSelectedNode().IsNull()) { - m_Controls.m_lbMovingName->setText(QString("no data selected!")); m_spSelectedMovingNode = nullptr; m_spSelectedMovingData = nullptr; } else { - m_spSelectedMovingNode = nodes.front(); + m_spSelectedMovingNode = m_Controls.movingNodeSelector->GetSelectedNode(); m_spSelectedMovingData = m_spSelectedMovingNode->GetData(); - movingImage = dynamic_cast(m_spSelectedMovingNode->GetData()); - movingPointSet = dynamic_cast(m_spSelectedMovingNode->GetData()); + auto movingImage = dynamic_cast(m_spSelectedMovingNode->GetData()); - if (movingPointSet && pPointSetInterface) - { - validMoving = true; - } - else if (movingImage && !pPointSetInterface) - { - if (movingImage->GetDimension() - 1 == m_LoadedAlgorithm->getMovingDimensions() + if (movingImage && movingImage->GetDimension() - 1 == m_LoadedAlgorithm->getMovingDimensions() && movingImage->GetTimeSteps() > 1) - { - //images has multiple time steps and a time step has the correct dimensionality - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - imageTimeSelector->SetInput(movingImage); - imageTimeSelector->SetTimeNr(0); - imageTimeSelector->UpdateLargestPossibleRegion(); - - m_spSelectedMovingData = imageTimeSelector->GetOutput(); - validMoving = true; - m_Controls.m_teLog->append( - QString("Selected moving image has multiple time steps. First time step is used as moving image.")); - } - else if (movingImage->GetDimension() != m_LoadedAlgorithm->getMovingDimensions()) - { - m_Controls.m_lbMovingName->setText(QString("wrong image dimension. ") + - QString::number(m_LoadedAlgorithm->getMovingDimensions()) + QString("D needed")); - } - else - { - validMoving = true; - } - } - else { - m_Controls.m_lbMovingName->setText(QString("no supported data selected!")); + m_spSelectedMovingData = ExtractFirstFrame(movingImage).GetPointer(); + m_Controls.m_teLog->append( + QString("Selected moving image has multiple time steps. First time step is used as moving image.")); } - - nodes.removeFirst(); } - if (nodes.count() < 1) + if (m_Controls.targetNodeSelector->GetSelectedNode().IsNull()) { - m_Controls.m_lbTargetName->setText(QString("no data selected!")); m_spSelectedTargetNode = nullptr; m_spSelectedTargetData = nullptr; } else { - m_spSelectedTargetNode = nodes.front(); + m_spSelectedTargetNode = m_Controls.targetNodeSelector->GetSelectedNode(); m_spSelectedTargetData = m_spSelectedTargetNode->GetData(); - targetImage = dynamic_cast(m_spSelectedTargetNode->GetData()); - targetPointSet = dynamic_cast(m_spSelectedTargetNode->GetData()); + auto targetImage = dynamic_cast(m_spSelectedTargetNode->GetData()); - if (targetPointSet && pPointSetInterface) + if (targetImage && targetImage->GetDimension() - 1 == m_LoadedAlgorithm->getTargetDimensions() + && targetImage->GetTimeSteps() > 1) { - validTarget = true; + m_spSelectedTargetData = ExtractFirstFrame(targetImage).GetPointer(); + m_Controls.m_teLog->append( + QString("Selected target image has multiple time steps. First time step is used as target image.")); } - else if (targetImage && !pPointSetInterface) - { - if (targetImage->GetDimension() - 1 == m_LoadedAlgorithm->getTargetDimensions() - && targetImage->GetTimeSteps() > 1) - { - //images has multiple time steps and a time step has the correct dimensionality - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - imageTimeSelector->SetInput(targetImage); - imageTimeSelector->SetTimeNr(0); - imageTimeSelector->UpdateLargestPossibleRegion(); - - m_spSelectedTargetData = imageTimeSelector->GetOutput(); - validTarget = true; - m_Controls.m_teLog->append( - QString("Selected target image has multiple time steps. First time step is used as target image.")); - } - else if (targetImage->GetDimension() != m_LoadedAlgorithm->getTargetDimensions()) - { - m_Controls.m_lbTargetName->setText(QString("wrong image dimension. ") + - QString::number(m_LoadedAlgorithm->getTargetDimensions()) + QString("D needed")); - } - else - { - validTarget = true; - } - } - else - { - m_Controls.m_lbTargetName->setText(QString("no supported data selected!")); - } - - nodes.removeFirst(); } - if (m_Controls.checkMovingMask->isChecked()) + if (m_Controls.movingMaskNodeSelector->GetSelectedNode().IsNull()) { - if (nodes.count() < 1) - { - m_Controls.m_lbMovingMaskName->setText(QString("no data selected!")); - m_spSelectedMovingMaskNode = nullptr; - m_spSelectedMovingMaskData = nullptr; - } - else - { - m_spSelectedMovingMaskNode = nodes.front(); - m_spSelectedMovingMaskData = nullptr; - - movingMaskImage = dynamic_cast(m_spSelectedMovingMaskNode->GetData()); - - bool isMask = maskPredicate->CheckNode(m_spSelectedMovingMaskNode); - - if (!isMask) - { - m_Controls.m_lbMovingMaskName->setText(QString("no mask selected!")); - } - else if (movingMaskImage && pMaskInterface) - { - if (movingMaskImage->GetDimension() - 1 == m_LoadedAlgorithm->getMovingDimensions() - && movingMaskImage->GetTimeSteps() > 1) - { - //images has multiple time steps and a time step has the correct dimensionality - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - imageTimeSelector->SetInput(movingMaskImage); - imageTimeSelector->SetTimeNr(0); - imageTimeSelector->UpdateLargestPossibleRegion(); - - m_spSelectedMovingMaskData = imageTimeSelector->GetOutput(); - validMovingMask = true; - m_Controls.m_teLog->append( - QString("Selected moving mask has multiple time steps. First time step is used as moving mask.")); - } - else if (movingMaskImage->GetDimension() != m_LoadedAlgorithm->getMovingDimensions()) - { - m_Controls.m_lbMovingMaskName->setText(QString("wrong image dimension. ") + - QString::number(m_LoadedAlgorithm->getMovingDimensions()) + QString("D needed")); - } - else - { - m_spSelectedMovingMaskData = movingMaskImage; - validMovingMask = true; - } - } - else - { - m_Controls.m_lbMovingMaskName->setText( - QString("no supported data selected!")); - } - - nodes.removeFirst(); - } + m_spSelectedMovingMaskNode = nullptr; + m_spSelectedMovingMaskData = nullptr; } else { - m_Controls.m_lbMovingMaskName->setText(QString("mask deactivated")); - validMovingMask = true; - m_spSelectedMovingMaskNode = nullptr; + m_spSelectedMovingMaskNode = m_Controls.movingMaskNodeSelector->GetSelectedNode(); m_spSelectedMovingMaskData = nullptr; - } - if (m_Controls.checkTargetMask->isChecked()) - { - if (nodes.count() < 1) - { - m_Controls.m_lbTargetMaskName->setText(QString("no data selected!")); - m_spSelectedTargetMaskNode = nullptr; - m_spSelectedTargetMaskData = nullptr; - } - else + auto movingMaskImage = dynamic_cast(m_spSelectedMovingMaskNode->GetData()); + + if (movingMaskImage->GetDimension() - 1 == m_LoadedAlgorithm->getMovingDimensions() + && movingMaskImage->GetTimeSteps() > 1) { - m_spSelectedTargetMaskNode = nodes.front(); - m_spSelectedTargetMaskData = nullptr; - targetMaskImage = dynamic_cast(m_spSelectedTargetMaskNode->GetData()); - - bool isMask = maskPredicate->CheckNode(m_spSelectedTargetMaskNode); - - if (!isMask) - { - m_Controls.m_lbTargetMaskName->setText(QString("no mask selected!")); - } - else if (targetMaskImage && pMaskInterface) - { - if (targetMaskImage->GetDimension() - 1 == m_LoadedAlgorithm->getTargetDimensions() - && targetMaskImage->GetTimeSteps() > 1) - { - //images has multiple time steps and a time step has the correct dimensionality - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - imageTimeSelector->SetInput(targetMaskImage); - imageTimeSelector->SetTimeNr(0); - imageTimeSelector->UpdateLargestPossibleRegion(); - - m_spSelectedTargetMaskData = imageTimeSelector->GetOutput(); - validTargetMask = true; - m_Controls.m_teLog->append( - QString("Selected target mask has multiple time steps. First time step is used as target mask.")); - } - else if (targetMaskImage->GetDimension() != m_LoadedAlgorithm->getTargetDimensions()) - { - m_Controls.m_lbTargetMaskName->setText(QString("wrong image dimension. ") + - QString::number(m_LoadedAlgorithm->getTargetDimensions()) + QString("D needed")); - } - else - { - m_spSelectedTargetMaskData = targetMaskImage; - validTargetMask = true; - } - } - else - { - m_Controls.m_lbTargetMaskName->setText( - QString("no supported data selected!")); - } + m_spSelectedMovingMaskData = ExtractFirstFrame(movingMaskImage).GetPointer(); + m_Controls.m_teLog->append( + QString("Selected moving mask has multiple time steps. First time step is used as moving mask.")); } - } - else + + if (m_Controls.targetMaskNodeSelector->GetSelectedNode().IsNull()) { - m_Controls.m_lbTargetMaskName->setText(QString("mask deactivated")); - validTargetMask = true; m_spSelectedTargetMaskNode = nullptr; m_spSelectedTargetMaskData = nullptr; } + else + { + m_spSelectedTargetMaskNode = m_Controls.targetMaskNodeSelector->GetSelectedNode(); + m_spSelectedTargetMaskData = nullptr; + auto targetMaskImage = dynamic_cast(m_spSelectedTargetMaskNode->GetData()); - } - - if (validMoving) - { - m_Controls.m_lbMovingName->setText(QString::fromStdString(GetInputNodeDisplayName( - m_spSelectedMovingNode))); - } - - if (validTarget) - { - m_Controls.m_lbTargetName->setText(QString::fromStdString(GetInputNodeDisplayName( - m_spSelectedTargetNode))); - } - - if (validMovingMask && m_Controls.checkMovingMask->isChecked()) - { - m_Controls.m_lbMovingMaskName->setText(QString::fromStdString(GetInputNodeDisplayName( - m_spSelectedMovingMaskNode))); - } + if (targetMaskImage->GetDimension() - 1 == m_LoadedAlgorithm->getTargetDimensions() + && targetMaskImage->GetTimeSteps() > 1) + { + m_spSelectedTargetMaskData = ExtractFirstFrame(targetMaskImage).GetPointer(); + m_Controls.m_teLog->append( + QString("Selected target mask has multiple time steps. First time step is used as target mask.")); + } + } - if (validTargetMask && m_Controls.checkTargetMask->isChecked()) - { - m_Controls.m_lbTargetMaskName->setText(QString::fromStdString(GetInputNodeDisplayName( - m_spSelectedTargetMaskNode))); } - m_ValidInputs = validMoving && validTarget && validMovingMask && validTargetMask; + m_ValidInputs = m_spSelectedMovingData.IsNotNull() && m_spSelectedTargetData.IsNotNull(); return m_ValidInputs; } std::string QmitkMatchPoint::GetInputNodeDisplayName(const mitk::DataNode* node) const { std::string result = "UNDEFINED/nullptr"; if (node) { result = node->GetName(); const mitk::PointSet* pointSet = dynamic_cast(node->GetData()); if (pointSet) { mitk::DataStorage::SetOfObjects::ConstPointer sources = this->GetDataStorage()->GetSources(node); if (sources.IsNotNull() && sources->Size() > 0) { result = result + " (" + sources->GetElement(0)->GetName() + ")"; } } } return result; } mitk::DataStorage::SetOfObjects::Pointer QmitkMatchPoint::GetRegNodes() const { mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetAll(); mitk::DataStorage::SetOfObjects::Pointer result = mitk::DataStorage::SetOfObjects::New(); for (mitk::DataStorage::SetOfObjects::const_iterator pos = nodes->begin(); pos != nodes->end(); ++pos) { if (mitk::MITKRegistrationHelper::IsRegNode(*pos)) { result->push_back(*pos); } } return result; } std::string QmitkMatchPoint::GetDefaultRegJobName() const { mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetRegNodes().GetPointer(); mitk::DataStorage::SetOfObjects::ElementIdentifier estimatedIndex = nodes->Size(); bool isUnique = false; std::string result = "Unnamed Reg"; while (!isUnique) { ++estimatedIndex; result = "Reg #" +::map::core::convert::toStr(estimatedIndex); isUnique = this->GetDataStorage()->GetNamedNode(result) == nullptr; } return result; } void QmitkMatchPoint::ConfigureRegistrationControls() { m_Controls.m_tabSelection->setEnabled(!m_Working); m_Controls.m_leRegJobName->setEnabled(!m_Working); m_Controls.groupMasks->setEnabled(!m_Working); m_Controls.m_pbStartReg->setEnabled(false); m_Controls.m_pbStopReg->setEnabled(false); m_Controls.m_pbStopReg->setVisible(false); - m_Controls.m_lbMovingMaskName->setVisible(m_Controls.checkMovingMask->isChecked()); - m_Controls.m_lbTargetMaskName->setVisible(m_Controls.checkTargetMask->isChecked()); - if (m_LoadedAlgorithm.IsNotNull()) { m_Controls.m_tabSettings->setEnabled(!m_Working); m_Controls.m_tabExecution->setEnabled(true); m_Controls.m_pbStartReg->setEnabled(m_ValidInputs && !m_Working); m_Controls.m_leRegJobName->setEnabled(!m_Working); m_Controls.m_checkMapEntity->setEnabled(!m_Working); - m_Controls.m_checkStoreReg->setEnabled(!m_Working); + m_Controls.targetNodeSelector->setEnabled(!m_Working); + m_Controls.movingNodeSelector->setEnabled(!m_Working); + m_Controls.targetMaskNodeSelector->setEnabled(!m_Working); + m_Controls.movingMaskNodeSelector->setEnabled(!m_Working); const IStoppableAlgorithm* pIterativ = dynamic_cast (m_LoadedAlgorithm.GetPointer()); if (pIterativ) { m_Controls.m_pbStopReg->setVisible(pIterativ->isStoppable()); } typedef ::map::algorithm::facet::MaskedRegistrationAlgorithmInterface<3, 3> MaskRegInterface; const MaskRegInterface* pMaskReg = dynamic_cast (m_LoadedAlgorithm.GetPointer()); m_Controls.groupMasks->setVisible(pMaskReg != nullptr); //if the stop button is set to visible and the algorithm is working -> //then the algorithm is stoppable, thus enable the button. m_Controls.m_pbStopReg->setEnabled(m_Controls.m_pbStopReg->isVisible() && m_Working); this->m_Controls.m_lbLoadedAlgorithmName->setText( QString::fromStdString(m_LoadedAlgorithm->getUID()->toStr())); } else { m_Controls.m_tabSettings->setEnabled(false); m_Controls.m_tabExecution->setEnabled(false); this->m_Controls.m_lbLoadedAlgorithmName->setText( QString("no algorithm loaded!")); m_Controls.groupMasks->setVisible(false); } if (!m_Working) { this->m_Controls.m_leRegJobName->setText(QString::fromStdString(this->GetDefaultRegJobName())); } } +void QmitkMatchPoint::ConfigureNodeSelectors() +{ + mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); + mitk::NodePredicateDataType::Pointer isPointSet = mitk::NodePredicateDataType::New("PointSet"); + mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); + mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); + mitk::NodePredicateBase::Pointer dimensionPredicate = mitk::NodePredicateOr::New(mitk::NodePredicateDimension::New(3), mitk::NodePredicateDimension::New(4)); + + mitk::NodePredicateAnd::Pointer maskPredicate = mitk::NodePredicateAnd::New(mitk::NodePredicateOr::New(isLegacyMask, isLabelSet), dimensionPredicate); + + m_Controls.movingNodeSelector->setEnabled(m_LoadedAlgorithm.IsNotNull()); + m_Controls.targetNodeSelector->setEnabled(m_LoadedAlgorithm.IsNotNull()); + m_Controls.movingMaskNodeSelector->setEnabled(m_LoadedAlgorithm.IsNotNull()); + m_Controls.targetMaskNodeSelector->setEnabled(m_LoadedAlgorithm.IsNotNull()); + + if (m_LoadedAlgorithm.IsNotNull()) + { + mitk::NodePredicateBase::Pointer dataPredicate; + + if (m_LoadedAlgorithm->getMovingDimensions() == 2) + { + dimensionPredicate = mitk::NodePredicateDimension::New(2); + } + + if (mitk::MITKAlgorithmHelper::HasImageAlgorithmInterface(m_LoadedAlgorithm)) + { + dataPredicate = mitk::NodePredicateAnd::New(isImage, dimensionPredicate); + + m_Controls.movingNodeSelector->SetInvalidInfo("Select valid moving image."); + m_Controls.movingNodeSelector->SetPopUpTitel("Select moving image."); + m_Controls.movingNodeSelector->SetPopUpHint("Select the moving image that should be registered onto the target image."); + m_Controls.targetNodeSelector->SetInvalidInfo("Select valid target image."); + m_Controls.targetNodeSelector->SetPopUpTitel("Select target image."); + m_Controls.targetNodeSelector->SetPopUpHint("Select the target image that should be used as reference for the registration."); + } + + if (mitk::MITKAlgorithmHelper::HasPointSetAlgorithmInterface(m_LoadedAlgorithm)) + { + if (dataPredicate.IsNull()) + { + dataPredicate = isPointSet; + m_Controls.movingNodeSelector->SetInvalidInfo("Select valid moving point set."); + m_Controls.movingNodeSelector->SetPopUpTitel("Select moving point set."); + m_Controls.movingNodeSelector->SetPopUpHint("Select the moving point set that should be registered onto the target point set."); + m_Controls.targetNodeSelector->SetInvalidInfo("Select valid target point set."); + m_Controls.targetNodeSelector->SetPopUpTitel("Select target point set."); + m_Controls.targetNodeSelector->SetPopUpHint("Select the target point set that should be used as reference for the registration."); + } + else + { + dataPredicate = mitk::NodePredicateOr::New(dataPredicate, isPointSet); + m_Controls.movingNodeSelector->SetInvalidInfo("Select valid moving data."); + m_Controls.movingNodeSelector->SetPopUpTitel("Select moving data."); + m_Controls.movingNodeSelector->SetPopUpHint("Select the moving data that should be registered onto the target data. The algorithm supports images as well as point sets."); + m_Controls.targetNodeSelector->SetInvalidInfo("Select valid target data."); + m_Controls.targetNodeSelector->SetPopUpTitel("Select target data."); + m_Controls.targetNodeSelector->SetPopUpHint("Select the target data that should be used as reference for the registration. The algorithm supports images as well as point sets."); + } + } + mitk::NodePredicateBase::Pointer nodePredicate = dataPredicate; + + m_Controls.movingNodeSelector->SetNodePredicate(nodePredicate); + m_Controls.targetNodeSelector->SetNodePredicate(nodePredicate); + + nodePredicate = mitk::NodePredicateAnd::New(maskPredicate, dimensionPredicate); + + m_Controls.movingMaskNodeSelector->SetEmptyInfo("Select moving mask. (optional)"); + m_Controls.movingMaskNodeSelector->SetPopUpTitel("Select moving mask"); + m_Controls.movingMaskNodeSelector->SetPopUpHint("Select a segmentation that serves as moving mask for the registration."); + m_Controls.targetMaskNodeSelector->SetEmptyInfo("Select target mask. (optional)"); + m_Controls.targetMaskNodeSelector->SetPopUpTitel("Select target mask"); + m_Controls.targetMaskNodeSelector->SetPopUpHint("Select a segmentation that serves as target mask for the registration."); + + m_Controls.movingMaskNodeSelector->SetNodePredicate(nodePredicate); + m_Controls.targetMaskNodeSelector->SetNodePredicate(nodePredicate); + } + +} + void QmitkMatchPoint::ConfigureProgressInfos() { const IIterativeAlgorithm* pIterative = dynamic_cast (m_LoadedAlgorithm.GetPointer()); const IMultiResAlgorithm* pMultiRes = dynamic_cast (m_LoadedAlgorithm.GetPointer()); m_Controls.m_progBarIteration->setVisible(pIterative); m_Controls.m_lbProgBarIteration->setVisible(pIterative); if (pIterative) { QString format = "%p% (%v/%m)"; if (!pIterative->hasMaxIterationCount()) { format = "%v"; m_Controls.m_progBarIteration->setMaximum(0); } else { m_Controls.m_progBarIteration->setMaximum(pIterative->getMaxIterations()); } m_Controls.m_progBarIteration->setFormat(format); } + m_Controls.m_progBarLevel->setVisible(pMultiRes); + m_Controls.m_lbProgBarLevel->setVisible(pMultiRes); + if (pMultiRes) { m_Controls.m_progBarLevel->setMaximum(pMultiRes->getResolutionLevels()); } else { m_Controls.m_progBarLevel->setMaximum(1); } m_Controls.m_progBarIteration->reset(); m_Controls.m_progBarLevel->reset(); } void QmitkMatchPoint::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList&) +{ +} + +void QmitkMatchPoint::OnNodeSelectionChanged(QList nodes) { if (!m_Working) { CheckInputs(); ConfigureRegistrationControls(); } } void QmitkMatchPoint::OnStartRegBtnPushed() { this->m_Working = true; //////////////////////////////// //configure GUI this->ConfigureProgressInfos(); m_Controls.m_progBarIteration->reset(); m_Controls.m_progBarLevel->reset(); this->ConfigureRegistrationControls(); if (m_Controls.m_checkClearLog->checkState() == Qt::Checked) { this->m_Controls.m_teLog->clear(); } ///////////////////////// //create job and put it into the thread pool QmitkRegistrationJob* pJob = new QmitkRegistrationJob(m_LoadedAlgorithm); pJob->setAutoDelete(true); pJob->m_spTargetData = m_spSelectedTargetData; pJob->m_spMovingData = m_spSelectedMovingData; pJob->m_TargetDataUID = mitk::EnsureUID(this->m_spSelectedTargetNode->GetData()); pJob->m_MovingDataUID = mitk::EnsureUID(this->m_spSelectedMovingNode->GetData()); if (m_spSelectedTargetMaskData.IsNotNull()) { pJob->m_spTargetMask = m_spSelectedTargetMaskData; pJob->m_TargetMaskDataUID = mitk::EnsureUID(this->m_spSelectedTargetMaskNode->GetData()); } if (m_spSelectedMovingMaskData.IsNotNull()) { pJob->m_spMovingMask = m_spSelectedMovingMaskData; pJob->m_MovingMaskDataUID = mitk::EnsureUID(this->m_spSelectedMovingMaskNode->GetData()); } pJob->m_JobName = m_Controls.m_leRegJobName->text().toStdString(); - pJob->m_StoreReg = m_Controls.m_checkStoreReg->checkState() == Qt::Checked; + pJob->m_StoreReg = true; connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnRegJobError(QString))); connect(pJob, SIGNAL(Finished()), this, SLOT(OnRegJobFinished())); connect(pJob, SIGNAL(RegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), this, SLOT(OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), Qt::BlockingQueuedConnection); connect(pJob, SIGNAL(AlgorithmInfo(QString)), this, SLOT(OnAlgorithmInfo(QString))); connect(pJob, SIGNAL(AlgorithmStatusChanged(QString)), this, SLOT(OnAlgorithmStatusChanged(QString))); connect(pJob, SIGNAL(AlgorithmIterated(QString, bool, unsigned long)), this, SLOT(OnAlgorithmIterated(QString, bool, unsigned long))); connect(pJob, SIGNAL(LevelChanged(QString, bool, unsigned long)), this, SLOT(OnLevelChanged(QString, bool, unsigned long))); QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pJob); } void QmitkMatchPoint::OnStopRegBtnPushed() { if (m_LoadedAlgorithm.IsNotNull()) { IStoppableAlgorithm* pIterativ = dynamic_cast(m_LoadedAlgorithm.GetPointer()); if (pIterativ && pIterativ->isStoppable()) { if (pIterativ->stopAlgorithm()) { } else { } m_Controls.m_pbStopReg->setEnabled(false); } else { } } } void QmitkMatchPoint::OnSaveLogBtnPushed() { QDateTime currentTime = QDateTime::currentDateTime(); QString fileName = tr("registration_log_") + currentTime.toString(tr("yyyy-MM-dd_hh-mm-ss")) + tr(".txt"); fileName = QFileDialog::getSaveFileName(nullptr, tr("Save registration log"), fileName, tr("Text files (*.txt)")); if (fileName.isEmpty()) { QMessageBox::critical(nullptr, tr("No file selected!"), tr("Cannot save registration log file. Please selected a file.")); } else { std::ofstream file; std::ios_base::openmode iOpenFlag = std::ios_base::out | std::ios_base::trunc; file.open(fileName.toStdString().c_str(), iOpenFlag); if (!file.is_open()) { mitkThrow() << "Cannot open or create specified file to save. File path: " << fileName.toStdString(); } file << this->m_Controls.m_teLog->toPlainText().toStdString() << std::endl; file.close(); } } void QmitkMatchPoint::OnRegJobError(QString err) { Error(err); }; void QmitkMatchPoint::OnRegJobFinished() { this->m_Working = false; this->GetRenderWindowPart()->RequestUpdate(); this->CheckInputs(); this->ConfigureRegistrationControls(); this->ConfigureProgressInfos(); }; void QmitkMatchPoint::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* pRegJob) { mitk::DataNode::Pointer spResultRegistrationNode = mitk::generateRegistrationResultNode( pRegJob->m_JobName, spResultRegistration, pRegJob->GetLoadedAlgorithm()->getUID()->toStr(), pRegJob->m_MovingDataUID, pRegJob->m_TargetDataUID); if (pRegJob->m_StoreReg) { m_Controls.m_teLog->append( QString(" Storing registration object in data manager ... ")); this->GetDataStorage()->Add(spResultRegistrationNode); this->GetRenderWindowPart()->RequestUpdate(); } if (m_Controls.m_checkMapEntity->checkState() == Qt::Checked) { QmitkMappingJob* pMapJob = new QmitkMappingJob(); pMapJob->setAutoDelete(true); pMapJob->m_spInputData = pRegJob->m_spMovingData; pMapJob->m_InputDataUID = pRegJob->m_MovingDataUID; pMapJob->m_spRegNode = spResultRegistrationNode; pMapJob->m_doGeometryRefinement = false; pMapJob->m_spRefGeometry = pRegJob->m_spTargetData->GetGeometry()->Clone().GetPointer(); pMapJob->m_MappedName = pRegJob->m_JobName + std::string(" mapped moving data"); pMapJob->m_allowUndefPixels = true; pMapJob->m_paddingValue = 100; pMapJob->m_allowUnregPixels = true; pMapJob->m_errorValue = 200; pMapJob->m_InterpolatorLabel = "Linear Interpolation"; pMapJob->m_InterpolatorType = mitk::ImageMappingInterpolator::Linear; connect(pMapJob, SIGNAL(Error(QString)), this, SLOT(OnMapJobError(QString))); connect(pMapJob, SIGNAL(MapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)), this, SLOT(OnMapResultIsAvailable(mitk::BaseData::Pointer, const QmitkMappingJob*)), Qt::BlockingQueuedConnection); connect(pMapJob, SIGNAL(AlgorithmInfo(QString)), this, SLOT(OnAlgorithmInfo(QString))); m_Controls.m_teLog->append( QString("Started mapping input data...")); QThreadPool* threadPool = QThreadPool::globalInstance(); threadPool->start(pMapJob); } }; void QmitkMatchPoint::OnMapJobError(QString err) { Error(err); }; void QmitkMatchPoint::OnMapResultIsAvailable(mitk::BaseData::Pointer spMappedData, const QmitkMappingJob* job) { m_Controls.m_teLog->append(QString("Mapped entity stored. Name: ") + QString::fromStdString(job->m_MappedName) + QString("")); mitk::DataNode::Pointer spMappedNode = mitk::generateMappedResultNode(job->m_MappedName, spMappedData, job->GetRegistration()->getRegistrationUID(), job->m_InputDataUID, job->m_doGeometryRefinement, job->m_InterpolatorLabel); this->GetDataStorage()->Add(spMappedNode); this->GetRenderWindowPart()->RequestUpdate(); }; void QmitkMatchPoint::OnAlgorithmIterated(QString info, bool hasIterationCount, unsigned long currentIteration) { if (hasIterationCount) { m_Controls.m_progBarIteration->setValue(currentIteration); } m_Controls.m_teLog->append(info); }; void QmitkMatchPoint::OnLevelChanged(QString info, bool hasLevelCount, unsigned long currentLevel) { if (hasLevelCount) { m_Controls.m_progBarLevel->setValue(currentLevel); } m_Controls.m_teLog->append(QString("") + info + QString("")); }; void QmitkMatchPoint::OnAlgorithmStatusChanged(QString info) { m_Controls.m_teLog->append(QString("") + info + QString(" ")); }; void QmitkMatchPoint::OnAlgorithmInfo(QString info) { m_Controls.m_teLog->append(QString("") + info + QString("")); }; void QmitkMatchPoint::OnAlgorithmSelectionChanged(const berry::IWorkbenchPart::Pointer& sourcepart, const berry::ISelection::ConstPointer& selection) { // check for null selection if (selection.IsNull()) { return; } if (sourcepart != this) { UpdateAlgorithmSelection(selection); } } void QmitkMatchPoint::UpdateAlgorithmSelection(berry::ISelection::ConstPointer selection) { mitk::MAPAlgorithmInfoSelection::ConstPointer currentSelection = selection.Cast(); if (currentSelection) { mitk::MAPAlgorithmInfoSelection::AlgorithmInfoVectorType infoVector = currentSelection->GetSelectedAlgorithmInfo(); if (!infoVector.empty()) { // only the first selection is of interest, the rest will be skipped. this->m_SelectedAlgorithmInfo = infoVector[0]; } } this->OnSelectedAlgorithmChanged(); }; diff --git a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.h b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.h index cf5b6226ae..52cc27c070 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.h +++ b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPoint.h @@ -1,209 +1,214 @@ /*=================================================================== 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 __Q_MITK_MATCHPOINT_H #define __Q_MITK_MATCHPOINT_H #include #include #include "ui_QmitkMatchPointControls.h" #include // MatchPoint #include #include #include #include #include #include #include class QmitkRegistrationJob; class QmitkMappingJob; /*! \brief MatchPoint \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class QmitkMatchPoint : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; /** * Creates smartpointer typedefs */ berryObjectMacro(QmitkMatchPoint) QmitkMatchPoint(); ~QmitkMatchPoint(); protected slots: /** * @brief Connect all GUI elements to its corresponding slots */ virtual void CreateConnections(); /// \brief Called when the user clicks the GUI button - void OnMaskCheckBoxToggeled(bool checked); void OnLoadAlgorithmButtonPushed(); void OnSelectedAlgorithmChanged(); + void OnNodeSelectionChanged(QList nodes); void OnStartRegBtnPushed(); void OnStopRegBtnPushed(); void OnSaveLogBtnPushed(); void OnRegJobError(QString err); void OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* pRegJob); void OnRegJobFinished(); void OnMapJobError(QString err); void OnMapResultIsAvailable(mitk::BaseData::Pointer spMappedData, const QmitkMappingJob* job); void OnAlgorithmIterated(QString info, bool hasIterationCount, unsigned long currentIteration); void OnLevelChanged(QString info, bool hasLevelCount, unsigned long currentLevel); void OnAlgorithmStatusChanged(QString info); void OnAlgorithmInfo(QString info); protected: virtual void CreateQtPartControl(QWidget* parent); virtual void SetFocus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes); private: /** * @brief Adapt the visibility of GUI elements depending on the current data loaded */ void AdaptFolderGUIElements(); void Error(QString msg); void UpdateAlgorithmList(); /** * checks if appropriated nodes are selected in the data manager. If nodes are selected, * they are stored m_MovingData and m_TargetData. It also sets the info lables accordingly. * @return True: All inputs are set and valid (images). False: At least one input is not set * or invalid */ bool CheckInputs(); /** * Updates the state of registration control buttons. Regarding to selected * inputs, loaded algorithm and its state.*/ void ConfigureRegistrationControls(); /** * Configures the progress bars according to the chosen algorithm. */ void ConfigureProgressInfos(); + /** + Configure the node selectors predicates and informations according to the selected algorithm. + */ + void ConfigureNodeSelectors(); + /** Methods returns a list of all nodes in the data manager containing a registration wrapper. * The list may be empty.*/ mitk::DataStorage::SetOfObjects::Pointer GetRegNodes() const; /** Returns a proposal for a (unique) default reg job name */ std::string GetDefaultRegJobName() const; /** Returns the display name of the passed node. Normally it is just node->GetName(). * if the node contains a point set it is additionally checked if the point set node * has a source node and its name will be added in parentheses.*/ std::string GetInputNodeDisplayName(const mitk::DataNode* node) const; /** Returns the Pointer to the DLL info of the algorithm currently selected by the system. The info is received via m_AlgorithmSelectionListener. @return If there is no item selected the returning pointer will be null. */ const map::deployment::DLLInfo* GetSelectedAlgorithmDLL() const; //! [Qt Selection Listener method and pointer] /** * @brief Method of berry::ISelectionListener that implements the selection listener functionality. * @param sourcepart The workbench part responsible for the selection change. * @param selection This parameter holds the current selection. * * @see ISelectionListener */ void OnAlgorithmSelectionChanged(const berry::IWorkbenchPart::Pointer& sourcepart, const berry::ISelection::ConstPointer& selection); void UpdateAlgorithmSelection(berry::ISelection::ConstPointer selection); friend struct berry::SelectionChangedAdapter; QWidget* m_Parent; /** @brief this pointer holds the algorithm selection listener */ QScopedPointer m_AlgorithmSelectionListener; ::map::deployment::DLLHandle::Pointer m_LoadedDLLHandle; ::map::algorithm::RegistrationAlgorithmBase::Pointer m_LoadedAlgorithm; ::map::deployment::DLLInfo::ConstPointer m_SelectedAlgorithmInfo; typedef map::algorithm::facet::IterativeAlgorithmInterface IIterativeAlgorithm; typedef map::algorithm::facet::MultiResRegistrationAlgorithmInterface IMultiResAlgorithm; typedef map::algorithm::facet::StoppableAlgorithmInterface IStoppableAlgorithm; mitk::DataNode::Pointer m_spSelectedTargetNode; mitk::DataNode::Pointer m_spSelectedMovingNode; /*Data of the selected target node that should be used for registration. Can be the direct return of node->GetData(), but can also be a sub set (like a special time frame).*/ mitk::BaseData::ConstPointer m_spSelectedTargetData; /*Data of the selected moving node that should be used for registration. Can be the direct return of node->GetData(), but can also be a sub set (like a special time frame).*/ mitk::BaseData::ConstPointer m_spSelectedMovingData; mitk::DataNode::Pointer m_spSelectedTargetMaskNode; mitk::DataNode::Pointer m_spSelectedMovingMaskNode; /*Data of the selected target mask node that should be used for registration. Can be the direct return of node->GetData(), but can also be a sub set (like a special time frame).*/ mitk::Image::ConstPointer m_spSelectedTargetMaskData; /*Data of the selected moving mask node that should be used for registration. Can be the direct return of node->GetData(), but can also be a sub set (like a special time frame).*/ mitk::Image::ConstPointer m_spSelectedMovingMaskData; // boolean variables to control visibility of GUI elements bool m_CanLoadAlgorithm; bool m_ValidInputs; bool m_Working; Ui::MatchPointAdvancedControls m_Controls; }; #endif // MatchPoint_h diff --git a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPointControls.ui b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPointControls.ui index fb263c8b38..c042cc629f 100644 --- a/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPointControls.ui +++ b/Plugins/org.mitk.gui.qt.matchpoint.algorithm.control/src/internal/QmitkMatchPointControls.ui @@ -1,761 +1,615 @@ MatchPointAdvancedControls 0 0 - 396 - 850 + 399 + 864 5 - + + 5 + + + 5 + + + 5 + + 5 Loaded algorithm: + + + 0 + 0 + + 400 16777215 0 170 0 0 170 0 159 158 158 75 true QFrame::StyledPanel 2 1 - Moving image/point set: + Moving data: - - - - - - - - 0 - 170 - 0 - - - - - - - - - 0 - 170 - 0 - - - - - - - - - 159 - 158 - 158 - - - - - - - - - 75 - true - - - - QFrame::StyledPanel - - - 2 - - - 1 - - - + + + + 0 + 40 + - Target image/point set: + Target data: - - - - - - - - 0 - 170 - 0 - - - - - - - - - 0 - 170 - 0 - - - - - - - - - 159 - 158 - 158 - - - - - - - - - 75 - true - - - - QFrame::StyledPanel - - - 2 - - - 1 - - - + + + + 0 + 40 + Masks + + false + 5 - + + 5 + + + 5 + + + 5 + + 5 - + - Moving Mask: + Moving mask: - - - - - - - - 0 - 170 - 0 - - - - - - - - - 0 - 170 - 0 - - - - - - - - - 159 - 158 - 158 - - - - - - - - - 75 - true - - - - QFrame::StyledPanel - - - 2 - - - 1 - - - + + + + 0 + 40 + - + - Target Mask: + Target mask: - - - - - - - - 0 - 170 - 0 - - - - - - - - - 0 - 170 - 0 - - - - - - - - - 159 - 158 - 158 - - - - - - - - - 75 - true - - - - QFrame::StyledPanel - - - 2 - - - 1 - - - + + + + 0 + 40 + true 200 0 1 false false false Selection - + + 5 + + + 5 + + + 5 + + 5 5 75 true Load an algorithm Algorithm browser selection: Load selected algorithm true false Selected algorithm information: true 0 -1 QFrame::StyledPanel 2 1 label_Heading1 m_teAlgorithmDetails label_algo label_algoInfo m_pbLoadSelected m_lbSelectedAlgorithm Execution 5 - + + 5 + + + 5 + + + 5 + + 5 0 0 75 true Perform Registration Registration job name: Name of the resulting mapped image Unnamed RegJob - - - - Store registration - - - true - - - Generate + store mapped result true Start Stop 0 0 Progress false Resolution level: 100 24 false %v/%m Iterations: 100 24 false %p% (%v/%m) Log: 0 0 9 Qt::ScrollBarAlwaysOn true QTextEdit::NoWrap true Clear log on algorithm start Save log to file Settings 5 - + + 5 + + + 5 + + + 5 + + 5 75 true Configure algorithm parameters 0 0 250 0 QmitkAlgorithmProfileViewer QWidget
QmitkAlgorithmProfileViewer.h
QmitkAlgorithmSettingsConfig QWidget
QmitkAlgorithmSettingsConfig.h
+ + QmitkSingleNodeSelectionWidget + QWidget +
QmitkSingleNodeSelectionWidget.h
+ 1 +
5 5 true true true