diff --git a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp index 8f2e233..f0b68c4 100644 --- a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp +++ b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp @@ -1,1141 +1,1140 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_TPP #define __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_TPP -#include #include #include "itkExtractImageFilter.h" #include "mapAlgorithmException.h" #include "mapPreCachedRegistrationKernel.h" #include "mapInverseRegistrationKernelGenerator.h" #include "mapRegistrationManipulator.h" #include "mapAlgorithmWrapperEvent.h" #include "mapITKMVNLOptimizerControlInterface.h" #include "mapITKSVNLOptimizerControlInterface.h" #include "mapMaskBoundingBoxHelper.h" namespace map { namespace algorithm { namespace itk { template typename ITKImageRegistrationAlgorithm::FieldRepRequirement::Type ITKImageRegistrationAlgorithm:: isMovingRepresentationRequired() const { return FieldRepRequirement::No; }; template typename ITKImageRegistrationAlgorithm::FieldRepRequirement::Type ITKImageRegistrationAlgorithm:: isTargetRepresentationRequired() const { return FieldRepRequirement::No; }; template bool ITKImageRegistrationAlgorithm:: isStoppable() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->isStoppable(); } return result; }; template typename ITKImageRegistrationAlgorithm::IterationCountType ITKImageRegistrationAlgorithm:: doGetCurrentIteration() const { return this->_currentIterationCount; }; template typename ITKImageRegistrationAlgorithm::IterationCountType ITKImageRegistrationAlgorithm:: doGetMaxIterations() const { IterationCountType result = 0; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->getMaxIterations(); } return result; }; template bool ITKImageRegistrationAlgorithm:: hasIterationCount() const { return true; }; template bool ITKImageRegistrationAlgorithm:: hasMaxIterationCount() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->hasMaxIterationCount(); } return result; }; template bool ITKImageRegistrationAlgorithm:: hasCurrentOptimizerValue() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->hasCurrentValue(); } return result; }; template bool ITKImageRegistrationAlgorithm:: isReusable() const { return true; } template ITKImageRegistrationAlgorithm:: ITKImageRegistrationAlgorithm() { _finalizedTransformParameters.clear(); _currentTransformParameters.clear(); _currentIterationCount = 0; _spInternalMovingImage = NULL; _spInternalTargetImage = NULL; _CropInputImagesByMask = true; _ComputeFinalMetricValue = false; //now set the policy event slots typedef ::itk::ReceptorMemberCommand AlgorithmCommandType; typename AlgorithmCommandType::Pointer spInterpolatorCmd = AlgorithmCommandType::New(); spInterpolatorCmd->SetCallbackFunction(this, &Self::onInterpolatorChange); InterpolatorPolicyType::_spOnChange = spInterpolatorCmd; typename AlgorithmCommandType::Pointer spOptimizerCmd = AlgorithmCommandType::New(); spOptimizerCmd->SetCallbackFunction(this, &Self::onOptimizerChange); OptimizerPolicyType::_spOnChange = spOptimizerCmd; typename AlgorithmCommandType::Pointer spMetricCmd = AlgorithmCommandType::New(); spMetricCmd->SetCallbackFunction(this, &Self::onMetricChange); MetricPolicyType::_spOnChange = spMetricCmd; typename AlgorithmCommandType::Pointer spTransformCmd = AlgorithmCommandType::New(); spTransformCmd->SetCallbackFunction(this, &Self::onTransformChange); TransformPolicyType::_spOnChange = spTransformCmd; }; template ITKImageRegistrationAlgorithm:: ~ITKImageRegistrationAlgorithm() { }; template void ITKImageRegistrationAlgorithm:: configureAlgorithm() { //default implementation does nothing; } template typename ITKImageRegistrationAlgorithm::TransformParametersType ITKImageRegistrationAlgorithm:: getCurrentTransformParameters() const { typedef std::lock_guard LockHolderType; LockHolderType holder(this->_currentIterationLock); return this->_currentTransformParameters; }; template void ITKImageRegistrationAlgorithm:: setCurrentTransformParameters(const TransformParametersType& param) { typedef std::lock_guard LockHolderType; LockHolderType holder(this->_currentIterationLock); this->_currentTransformParameters = param; }; template typename ITKImageRegistrationAlgorithm::InterimRegistrationPointer ITKImageRegistrationAlgorithm:: determineInterimRegistration(const MovingRepresentationDescriptorType* pMovingRepresentation, const TargetRepresentationDescriptorType* pTargetRepresentation) const { InterimRegistrationPointer spResult; if (this->_currentIterationCount > 0) { //the algorithm has iterated at least once so we can determin an interim registration const TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. No transform model present on internal level (getTransformInternal(). Pleas ensure proper setup of algorithm."); } //clone the transform model typename TransformBaseType::Pointer spInterimTransformModel = pTransformModel->Clone(); if (spInterimTransformModel.IsNull()) { std::ostringstream modelStrm; pTransformModel->Print(modelStrm); mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. Unable to clone transform model. Current model: "); //<< modelStrm); } //set the parameter of the interim transform model to the current transform parameters of the algorithm //We set the parameter by Value and not by using SetParameter() because otherwise //it could cause errors with itk transforms that only keep a pointer to their parameters (e.g. itk::BSplineDeformableTransform). //This transforms would be invalid as soon as we leave this method. spInterimTransformModel->SetParametersByValue( this->getCurrentTransformParameters()); //now build the inverse kernel (main kernel of a image based registration algorithm) typedef core::PreCachedRegistrationKernel InverseKernelType; typename InverseKernelType::Pointer spIKernel = InverseKernelType::New(); spIKernel->setTransformModel(spInterimTransformModel); //now build the direct kernel via inversion of the inverse kernel typedef core::InverseRegistrationKernelGenerator GeneratorType; typename GeneratorType::Pointer spGenerator = GeneratorType::New(); typedef typename GeneratorType::InverseKernelBaseType DirectKernelType; typename DirectKernelType::Pointer spDKernel = spGenerator->generateInverse(* (spIKernel.GetPointer()), pMovingRepresentation); if (spDKernel.IsNull()) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine direct mapping kernel of interim registration. Current inverse kernel: " << spIKernel); } //now create the registration an set the kernels spResult = InterimRegistrationType::New(); ::map::core::RegistrationManipulator manipulator(spResult); manipulator.setDirectMapping(spDKernel); manipulator.setInverseMapping(spIKernel); manipulator.getTagValues()[tags::AlgorithmUID] = this->getUID()->toStr(); } return spResult; }; template bool ITKImageRegistrationAlgorithm:: doStopAlgorithm() { bool result = false; OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->stop(); } return result; }; template void ITKImageRegistrationAlgorithm:: prepCheckValidity() { if (!this->getTransformInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no transformation model available."); } if (!this->getInterpolatorInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no interpolator available."); } if (!this->getOptimizerInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no optimizer available."); } if (!this->getMetricInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no metric available."); } if (!this->getMovingImage()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no moving image."); } if (!this->getTargetImage()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no target image."); } } template void ITKImageRegistrationAlgorithm:: prepPrepareSubComponents() { this->prepareTransform(); this->prepareInterpolator(); this->prepareMetric(); this->prepareOptimizer(); } template void ITKImageRegistrationAlgorithm:: prepAssembleSubComponents() { this->_internalRegistrationMethod->SetMetric(this->getMetricInternal()->getImageToImageMetric()); this->_internalRegistrationMethod->SetOptimizer(this->getOptimizerInternal()->getSVNLOptimizer()); this->_internalRegistrationMethod->SetTransform(this->getTransformInternal()); this->_internalRegistrationMethod->SetInterpolator(this->getInterpolatorInternal()); } template void ITKImageRegistrationAlgorithm:: prepPerpareInternalInputData() { typedef ::itk::ExtractImageFilter MovingExtractFilterType; typedef ::itk::ExtractImageFilter TargetExtractFilterType; typename MovingExtractFilterType::Pointer movingFilter = MovingExtractFilterType::New(); ::map::core::OStringStream os; ::map::core::OStringStream os2; if (this->getCropInputImagesByMask()) { if (this->getInternalTargetMask().IsNotNull()) { //we have a mask -> so construct the image region typename TargetImageType::RegionType boundedRegion; if (::map::algorithm::MaskBoundingBoxHelper::computeBoundingImageRegion( this->getInternalTargetMask(), this->getInternalTargetImage(), boundedRegion)) { if (boundedRegion.Crop(this->getInternalTargetImage()->GetLargestPossibleRegion())) { os << "Target mask: set -> target image space region is set to: " << ::std::endl << boundedRegion; typename TargetExtractFilterType::Pointer targetFilter = TargetExtractFilterType::New(); targetFilter->SetExtractionRegion(boundedRegion); targetFilter->SetInput(this->getInternalTargetImage()); targetFilter->Update(); typename TargetImageType::Pointer newTarget = targetFilter->GetOutput(); newTarget->DisconnectPipeline(); this->setInternalTargetImage(newTarget); } else { os << "Target mask: set, but invalid (not within the bufferd target image) -> use complete target image."; } } else { os << "Target mask: set, but invalid (cannot compute bounding box) -> use complete target image."; } } else { os << "Target mask: none -> use complete target image."; } this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); if (this->getInternalMovingMask().IsNotNull()) { //we have a mask -> so construct the image region typename MovingImageType::RegionType boundedRegion; if (::map::algorithm::MaskBoundingBoxHelper::computeBoundingImageRegion( this->getInternalMovingMask(), this->getInternalMovingImage(), boundedRegion)) { if (boundedRegion.Crop(this->getInternalMovingImage()->GetLargestPossibleRegion())) { os2 << "Moving mask: set -> moving image space region is set to: " << ::std::endl << boundedRegion; typename MovingExtractFilterType::Pointer movingFilter = MovingExtractFilterType::New(); movingFilter->SetExtractionRegion(boundedRegion); movingFilter->SetInput(this->getInternalMovingImage()); movingFilter->Update(); typename MovingImageType::Pointer newMoving = movingFilter->GetOutput(); newMoving->DisconnectPipeline(); this->setInternalMovingImage(newMoving); } else { os2 << "Moving mask: set, but invalid (not within the bufferd moving image) -> use complete moving image."; } } else { os2 << "Moving mask: set, but invalid (cannot compute bounding box) -> use complete moving image."; } } else { os2 << "Moving mask: none -> use complete moving image."; } this->InvokeEvent(::map::events::AlgorithmEvent(this, os2.str())); } } template void ITKImageRegistrationAlgorithm:: prepSetInternalInputData() { //Connect images this->InvokeEvent(::map::events::AlgorithmEvent(this, "Connect images to itk registration method.")); this->_internalRegistrationMethod->SetFixedImage(this->getInternalTargetImage()); this->_internalRegistrationMethod->SetMovingImage(this->getInternalMovingImage()); //Connect masks if present this->InvokeEvent(::map::events::AlgorithmEvent(this, "Connect masks to registration metric.")); if (this->getInternalMovingMask().IsNotNull()) { //add moving mask this->getMetricInternal()->getImageToImageMetric()->SetMovingImageMask(this->getInternalMovingMask()); } if (this->getInternalTargetMask().IsNotNull()) { //add target mask this->getMetricInternal()->getImageToImageMetric()->SetFixedImageMask(this->getInternalTargetMask()); } this->_internalRegistrationMethod->SetFixedImageRegion( this->getInternalTargetImage()->GetLargestPossibleRegion()); } template void ITKImageRegistrationAlgorithm:: prepInitializeTransformation() { const TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. No transform model present on internal level (getTransformInternal(). Pleas ensure proper setup of algorithm."); } ::map::core::OStringStream os; os << "Set start transformation parameters to: " << pTransformModel->GetParameters(); //set the parameter of the transform model to the current transform parameters of the algorithm this->setCurrentTransformParameters(pTransformModel->GetParameters()); this->_internalRegistrationMethod->SetInitialTransformParameters( pTransformModel->GetParameters()); this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); }; template void ITKImageRegistrationAlgorithm:: prepFinalizePreparation() { //initialize registration components after assembly this->prepareTransformAfterAssembly(); this->prepareInterpolatorAfterAssembly(); this->prepareMetricAfterAssembly(); this->prepareOptimizerAfterAssembly(this->getMetricInternal()->getMinimizeToOptimize()); }; template void ITKImageRegistrationAlgorithm:: prepareAlgorithm() { this->prepCheckValidity(); this->_currentIterationCount = 0; this->_spFinalizedRegistration = NULL; this->_spInternalMovingImage = NULL; this->_spInternalTargetImage = NULL; this->_finalizedTransformParameters.Fill(0); //create method this->_internalRegistrationMethod = InternalRegistrationMethodType::New(); //initialize registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Transfer cached MetaProperties.")); this->configureAlgorithmByMetaProperties(); //initialize registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing registration components.")); this->prepPrepareSubComponents(); //assemble registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing itk multi resolution registration method.")); this->prepAssembleSubComponents(); this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing/Preparing input data.")); this->prepPerpareInternalInputData(); this->InvokeEvent(::map::events::AlgorithmEvent(this, "Passing input data to internal algorithm.")); this->prepSetInternalInputData(); //possibility to initialize internal registration method after assembly this->prepInitializeTransformation(); //initialize registration components after assembly this->InvokeEvent(::map::events::AlgorithmEvent(this, "Finalizing initialization...")); this->prepFinalizePreparation(); //Register observers if (_onIterationObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onIterationEvent); _onIterationObserver = core::ObserverSentinel::New(this->getOptimizerInternal()->getSVNLOptimizer(), ::itk::IterationEvent(), spCommand); } if (_onGeneralOptimizerObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralOptimizerEvent); _onGeneralOptimizerObserver = core::ObserverSentinel::New( this->getOptimizerInternal()->getSVNLOptimizer(), ::itk::AnyEvent(), spCommand); } if (_onGeneralMetricObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralMetricEvent); _onGeneralMetricObserver = core::ObserverSentinel::New( this->getMetricInternal()->getImageToImageMetric(), ::itk::AnyEvent(), spCommand); } if (_onGeneralInterpolatorObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralInterpolatorEvent); _onGeneralInterpolatorObserver = core::ObserverSentinel::New(this->getInterpolatorInternal(), ::itk::AnyEvent(), spCommand); } if (_onGeneralTransformObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralTransformEvent); _onGeneralTransformObserver = core::ObserverSentinel::New( this->getTransformInternal(), ::itk::AnyEvent(), spCommand); } typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralRegistrationMethodEvent); this->_internalRegistrationMethod->AddObserver(::itk::AnyEvent(), spCommand); }; template bool ITKImageRegistrationAlgorithm:: runAlgorithm() { this->_internalRegistrationMethod->Update(); this->_stopConditionDescription = this->getOptimizerInternal()->getStopConditionDescription(); return true; }; template void ITKImageRegistrationAlgorithm:: finalizeAlgorithm() { RegistrationPointer spResult; //touch the sub component to ensure an actualzed modification time, //this is needed because in case of arbitrary policies and dll deployment //the components could come out of another context. So a //ModificationTimeValidator is needed in it could produce //false positives in this constellation. OptimizerPolicyType::GetMTime(); MetricPolicyType::GetMTime(); TransformPolicyType::GetMTime(); TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine final registration. No transform model present on internal level (getTransformInternal()). Please ensure proper setup of algorithm."); } //clone the transform model typename TransformBaseType::Pointer spFinalTransformModel = pTransformModel->Clone(); if (spFinalTransformModel.IsNull()) { std::ostringstream modelStrm; pTransformModel->Print(modelStrm); mapExceptionMacro(AlgorithmException, << "Error. Cannot determine final registration. Unable to clone transform model. Current model: " << modelStrm.str()); } TransformParametersType lastTransformParameters = this->_internalRegistrationMethod->GetLastTransformParameters(); //set the parameter of the final transform model to the final transform parameters of the algorithm spFinalTransformModel->SetParametersByValue( lastTransformParameters); //this line is need to ensure correct cloning for //itk transforms that only keep a pointer to their parameters (e.g. itk::BSplineDeformableTransform). //Thoose transforms can cause problems with optimizers that only keep the parameters localy (e.g. itk::LBFGSOptimizer). //Excplicit resetting the parameters is a work arround to this problem. //now build the inverse kernel (main kernel of a image based registration algorithm) typedef core::PreCachedRegistrationKernel InverseKernelType; typename InverseKernelType::Pointer spIKernel = InverseKernelType::New(); spIKernel->setTransformModel(spFinalTransformModel); //now build the direct kernel via inversion of the inverse kernel typedef core::InverseRegistrationKernelGenerator GeneratorType; typename GeneratorType::Pointer spGenerator = GeneratorType::New(); typedef typename GeneratorType::InverseKernelBaseType DirectKernelType; typename DirectKernelType::Pointer spDKernel = spGenerator->generateInverse(* (spIKernel.GetPointer()), this->getMovingRepresentation()); if (spDKernel.IsNull()) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine direct mapping kernel of final registration. Current inverse kernel: " << spIKernel); } if (this->_ComputeFinalMetricValue) { auto metricController = this->getMetricInternal(); auto finalMetricValue = metricController->getSVMetric()->GetValue(lastTransformParameters); ::map::core::OStringStream os; os << "Final transform parameters: " << lastTransformParameters; this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); this->InvokeEvent(::map::events::AlgorithmEvent(this, "Final metric value: " + map::core::convert::toStr(finalMetricValue))); } //ensure that settings changed to the registration determination process are reseted to default this->configureAlgorithm(); //now create the registration an set the kernels spResult = RegistrationType::New(); ::map::core::RegistrationManipulator manipulator(spResult); manipulator.setDirectMapping(spDKernel); manipulator.setInverseMapping(spIKernel); manipulator.getTagValues()[tags::AlgorithmUID] = this->getUID()->toStr(); //store the final results _spFinalizedRegistration = spResult; _finalizedTransformParameters = lastTransformParameters; }; template typename ITKImageRegistrationAlgorithm::RegistrationPointer ITKImageRegistrationAlgorithm:: doGetRegistration() const { return _spFinalizedRegistration; }; template void ITKImageRegistrationAlgorithm:: onIterationEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::core::OStringStream os; TransformParametersType currentParams = this->getTransformInternal()->GetParameters(); bool hasCurrentPosition = this->getOptimizerInternal()->hasCurrentPosition(); typename OptimizerBaseType::OptimizerPositionType currentPosition = this->getOptimizerInternal()->getCurrentPosition(); bool hasCurrentValue = this->getOptimizerInternal()->hasCurrentValue(); typename OptimizerBaseType::SVNLMeasureType currentValue = this->getOptimizerInternal()->getCurrentMeasure(); this->_currentIterationLock.lock(); ++_currentIterationCount; _currentTransformParameters = currentParams; os << "Iteration #" << _currentIterationCount << "; params: "; os << currentParams << "; optimizer position: "; if (hasCurrentPosition) { os << currentPosition; } else { os << "unkown"; } os << "; metric value: "; if (hasCurrentValue) { os << currentValue; } else { os << "unkown"; } this->_currentIterationLock.unlock(); this->InvokeEvent(::map::events::AlgorithmIterationEvent(this, os.str())); }; template void ITKImageRegistrationAlgorithm:: onGeneralOptimizerEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal optimizer event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralMetricEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal metric event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralInterpolatorEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal interpolator event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralTransformEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal transform event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralRegistrationMethodEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal registration method event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onOptimizerChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { // we can directly reset the observer sentinel befor the optimizer will be unregistered this->_onGeneralOptimizerObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onMetricChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the metric will be unregistered this->_onGeneralMetricObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onInterpolatorChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the interpolator will be unregistered this->_onGeneralInterpolatorObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onTransformChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the transform will be unregistered this->_onGeneralTransformObserver = NULL; } }; template bool ITKImageRegistrationAlgorithm:: registrationIsOutdated() const { bool outdated = _spFinalizedRegistration.IsNull(); if (_spFinalizedRegistration.IsNotNull()) { if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < MetaPropertyAlgorithmBase::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < InterpolatorPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < OptimizerPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < MetricPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < TransformPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < this->getMovingImageMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < this->getTargetImageMTime(); } if (!outdated) { //check if the target mask has been changed outdated = _spFinalizedRegistration->GetMTime() < this->getTargetMaskMTime(); } if (!outdated) { //check if the moving mask has been changed outdated = _spFinalizedRegistration->GetMTime() < this->getMovingMaskMTime(); } } return outdated; }; template typename ITKImageRegistrationAlgorithm::OptimizerMeasureType ITKImageRegistrationAlgorithm:: doGetCurrentOptimizerValue() const { OptimizerMeasureType result; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { if (pOptimizer->hasCurrentValue()) { result = pOptimizer->getCurrentValue(); } } return result; }; template typename ITKImageRegistrationAlgorithm::InternalRegistrationMethodType& ITKImageRegistrationAlgorithm:: getInternalRegistrationMethod() { return *(this->_internalRegistrationMethod.GetPointer()); }; template void ITKImageRegistrationAlgorithm:: PrintSelf(std::ostream& os, ::itk::Indent indent) const { Superclass::PrintSelf(os, indent); ImageRegistrationAlgorithmBase::PrintSelf(os, indent); MaskedRegistrationAlgorithmBase::PrintSelf( os, indent); os << indent << "Current itertation count: " << _currentIterationCount << std::endl; os << indent << "Current transform parameters: " << _currentTransformParameters << std::endl; os << indent << "Finalized transform parameters: " << _finalizedTransformParameters << std::endl; os << indent << "Finalized registration: " << _spFinalizedRegistration << std::endl; }; template void ITKImageRegistrationAlgorithm:: compileInfos(MetaPropertyVectorType& infos) const { #ifndef MAP_SEAL_ALGORITHMS infos.push_back(::map::algorithm::MetaPropertyInfo::New("CropInputImagesByMasks", typeid(bool), true, true)); infos.push_back(::map::algorithm::MetaPropertyInfo::New("ComputeFinalMetricValue", typeid(bool), true, true)); #endif }; template typename ITKImageRegistrationAlgorithm::MetaPropertyPointer ITKImageRegistrationAlgorithm:: doGetProperty(const MetaPropertyNameType& name) const { MetaPropertyPointer spResult; if (name == "CropInputImagesByMasks") { spResult = ::map::core::MetaProperty::New(this->_CropInputImagesByMask); } else if (name == "ComputeFinalMetricValue") { spResult = ::map::core::MetaProperty::New(this->_ComputeFinalMetricValue); } return spResult; }; template void ITKImageRegistrationAlgorithm:: doSetProperty(const MetaPropertyNameType& name, const MetaPropertyType* pProperty) { if (name == "CropInputImagesByMasks") { bool crop = this->_CropInputImagesByMask; ::map::core::unwrapMetaProperty(pProperty, crop); this->_CropInputImagesByMask = crop; } else if (name == "ComputeFinalMetricValue") { bool compute = this->_ComputeFinalMetricValue; ::map::core::unwrapMetaProperty(pProperty, compute); this->_ComputeFinalMetricValue = compute; } else { assert(false); //any other property name should have been excluded or allready handled by the calling function. } }; template typename ITKImageRegistrationAlgorithm::MovingImageConstPointer ITKImageRegistrationAlgorithm:: getInternalMovingImage() const { MovingImageConstPointer result = this->getMovingImage(); if (this->_spInternalMovingImage.IsNotNull()) { result = _spInternalMovingImage; } return result; }; template typename ITKImageRegistrationAlgorithm::TargetImageConstPointer ITKImageRegistrationAlgorithm:: getInternalTargetImage() const { TargetImageConstPointer result = this->getTargetImage(); if (this->_spInternalTargetImage.IsNotNull()) { result = _spInternalTargetImage; } return result; }; template void ITKImageRegistrationAlgorithm:: setInternalMovingImage(MovingImageType* image) { _spInternalMovingImage = image; }; template void ITKImageRegistrationAlgorithm:: setInternalTargetImage(TargetImageType* image) { _spInternalTargetImage = image; }; template typename ITKImageRegistrationAlgorithm::MovingMaskBaseConstPointer ITKImageRegistrationAlgorithm:: getInternalMovingMask() const { MovingMaskBaseConstPointer result = this->getMovingMask(); if (this->_spInternalMovingMask.IsNotNull()) { result = _spInternalMovingMask; } return result; } template typename ITKImageRegistrationAlgorithm::TargetMaskBaseConstPointer ITKImageRegistrationAlgorithm:: getInternalTargetMask() const { TargetMaskBaseConstPointer result = this->getTargetMask(); if (this->_spInternalTargetMask.IsNotNull()) { result = _spInternalTargetMask; } return result; } template void ITKImageRegistrationAlgorithm:: setInternalMovingMask(MovingMaskBaseType* mask) { _spInternalMovingMask = mask; } template void ITKImageRegistrationAlgorithm:: setInternalTargetMask(TargetMaskBaseType* mask) { _spInternalTargetMask = mask; } } // end namespace itk } // end namespace algorithm } // end namespace map #endif