diff --git a/Modules/Core/include/mitkITKEventObserverGuard.h b/Modules/Core/include/mitkITKEventObserverGuard.h
index fb8903f116..c2a509286d 100644
--- a/Modules/Core/include/mitkITKEventObserverGuard.h
+++ b/Modules/Core/include/mitkITKEventObserverGuard.h
@@ -1,93 +1,93 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef mitkITKEventObserverGuard_h
 #define mitkITKEventObserverGuard_h
 
 #include <functional>
 #include <memory>
 #include "MitkCoreExports.h"
 
 namespace itk
 {
   class Object;
   class Command;
   class EventObject;
 }
 
 namespace mitk
 {
   /**
     \brief Convenience class that helps to manage the lifetime of itk event observers.
     
     This helper class can be used to ensure itk event observers are removed form
     a sender object at the end of a certain scope.
     This class behaves similar to a std::unique_ptr but for event observers.
     Therefore the observer will be removed from the sender when one of the following
     conditions are met:
     - the guard is destroyed
-    - the guard is reseted (by Reset() or operator = )
+    - the guard is resetted (by Reset() or operator = )
 
     Sample usage:
      \code
        {
          auto &objRef = *o.GetPointer();
          auto guard = ITKEventObserverGuard(o, itk::AnyEvent(), [&objRef](const itk::EventObject &event)
          { std::cout << "Object: " << objRef.GetNameOfClass() << " Event: " << event << std::endl; });
          //some code
        }
        //now the guard is destroyed
      \endcode
     This will add an Observer to o executing the lambda for any event as long as the guard exists.
     @remark If the sender is already destroyed at the moment, when the guard wants to
     remove the observer, the removal will be skipped.
   */
 
   class MITKCORE_EXPORT ITKEventObserverGuard
   {
   public:
     ITKEventObserverGuard();
     ITKEventObserverGuard(const itk::Object* sender, unsigned long observerTag);
     ITKEventObserverGuard(const itk::Object* sender, const itk::EventObject& event, itk::Command* command);
     ITKEventObserverGuard(const itk::Object* sender, const itk::EventObject& event, std::function<void(const itk::EventObject&)> function);
     ITKEventObserverGuard(ITKEventObserverGuard&&);
     ITKEventObserverGuard& operator=(ITKEventObserverGuard&&);
 
     ~ITKEventObserverGuard();
 
     /** Resets the guard by removing the currently guarded observer. After the reset the guard is uninitialized.
      *@remark resetting an uninitialized guard has no effect.*/
     void Reset();
 
     /** Resets the guard by first removing the currently guarded observer. Then the passed observer tag for the
      * passed sender will be guarded.*/
     void Reset(const itk::Object* sender, unsigned long observerTag);
 
     /** Resets the guard by first removing the currently guarded observer. Then a observer will be added for
      * the passed sender with the passed event and command. The new observer is now guarded.*/
     void Reset(const itk::Object* sender, const itk::EventObject& event, itk::Command* command);
 
     /** Resets the guard by first removing the currently guarded observer. Then a observer will be added for
      * the passed sender with the passed event and lambda function. The new observer is now guarded.*/
     void Reset(const itk::Object* sender, const itk::EventObject& event, std::function<void(const itk::EventObject&)> function);
 
     bool IsInitialized() const;
 
   private:
     struct Impl;
     std::unique_ptr<Impl> m_ITKEventObserverGuardImpl;
   };
 
 
 }
 
 #endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
index 6a259e5039..58dc2c7acc 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
@@ -1,1472 +1,1499 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "QmitkSlicesInterpolator.h"
 #include "QmitkRenderWindow.h"
 #include "QmitkRenderWindowWidget.h"
 
 #include "mitkApplyDiffImageOperation.h"
 #include "mitkColorProperty.h"
 #include "mitkCoreObjectFactory.h"
 #include "mitkDiffImageApplier.h"
 #include "mitkInteractionConst.h"
 #include "mitkLevelWindowProperty.h"
 #include "mitkOperationEvent.h"
 #include "mitkProgressBar.h"
 #include "mitkProperties.h"
 #include "mitkRenderingManager.h"
 #include "mitkSegTool2D.h"
 #include "mitkSliceNavigationController.h"
 #include "mitkSurfaceToImageFilter.h"
 #include <mitkTimeNavigationController.h>
 #include "mitkToolManager.h"
 #include "mitkUndoController.h"
 
 #include <mitkExtractSliceFilter.h>
 #include <mitkPlanarCircle.h>
 #include <mitkImageReadAccessor.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkImageWriteAccessor.h>
 #include <mitkPlaneProposer.h>
 #include <mitkUnstructuredGridClusteringFilter.h>
 #include <mitkVtkImageOverwrite.h>
 #include <mitkShapeBasedInterpolationAlgorithm.h>
 #include <itkCommand.h>
 
 #include <mitkImageToContourFilter.h>
 #include <mitkImagePixelReadAccessor.h>
 
 //  Includes for the merge operation
 #include "mitkImageToContourFilter.h"
 #include <mitkLabelSetImage.h>
 
 #include <QCheckBox>
 #include <QCursor>
 #include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QVBoxLayout>
 
 #include <vtkDoubleArray.h>
 #include <vtkFieldData.h>
 #include <vtkPolyVertex.h>
 #include <vtkUnstructuredGrid.h>
 #include <vtkPolyData.h>
 
 #include <array>
 #include <atomic>
 #include <thread>
 #include <vector>
 
 namespace
 {
   template <typename T = mitk::BaseData>
   itk::SmartPointer<T> GetData(const mitk::DataNode* dataNode)
   {
     return nullptr != dataNode
       ? dynamic_cast<T*>(dataNode->GetData())
       : nullptr;
   }
 }
 
 float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f};
 
 const QmitkSlicesInterpolator::ActionToSliceDimensionMapType QmitkSlicesInterpolator::CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows)
 {
   std::map<QAction *, mitk::SliceNavigationController *> actionToSliceDimension;
   for (auto* window : windows)
   {
     std::string windowName;
     auto renderWindowWidget = dynamic_cast<QmitkRenderWindowWidget*>(window->parentWidget());
     if (renderWindowWidget)
     {
       windowName = renderWindowWidget->GetCornerAnnotationText();
     }
     else
     {
       windowName = window->GetRenderer()->GetName();
     }
     auto slicer = window->GetSliceNavigationController();
     actionToSliceDimension[new QAction(QString::fromStdString(windowName), nullptr)] = slicer;
   }
 
   return actionToSliceDimension;
 }
 
 mitk::Image::Pointer ExtractSliceFromImage(mitk::Image* image,
                                           const mitk::PlaneGeometry * contourPlane,
                                           unsigned int timeStep)
 {
   vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
   // set to false to extract a slice
   reslice->SetOverwriteMode(false);
   reslice->Modified();
 
   mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
   extractor->SetInput(image);
   extractor->SetTimeStep(timeStep);
   extractor->SetWorldGeometry(contourPlane);
   extractor->SetVtkOutputRequest(false);
   extractor->SetResliceTransformByGeometry(image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
   extractor->Update();
   mitk::Image::Pointer slice = extractor->GetOutput();
   return slice;
 }
 
 QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/)
   : QWidget(parent),
     m_Interpolator(mitk::SegmentationInterpolationController::New()),
     m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
     m_ToolManager(nullptr),
     m_Initialized(false),
     m_LastSNC(nullptr),
     m_LastSliceIndex(0),
     m_2DInterpolationEnabled(false),
     m_3DInterpolationEnabled(false),
     m_CurrentActiveLabelValue(0),
     m_FirstRun(true)
 {
   m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
 
   QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
 
   m_EdgeDetector = mitk::FeatureBasedEdgeDetectionFilter::New();
   m_PointScorer = mitk::PointCloudScoringFilter::New();
 
   m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode);
   m_CmbInterpolation->addItem("Disabled");
   m_CmbInterpolation->addItem("2-Dimensional");
   m_CmbInterpolation->addItem("3-Dimensional");
   vboxLayout->addWidget(m_CmbInterpolation);
 
   m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply2D);
 
   m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
 
   m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply3D);
 
   m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnReinit3DInterpolation);
 
   m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_ChkShowPositionNodes);
 
   this->HideAllInterpolationControls();
 
   connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int)));
   connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
   connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()));
   connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked()));
 
 
   connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation()));
   connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
   connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool)));
 
   QHBoxLayout *layout = new QHBoxLayout(this);
   layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode);
   this->setLayout(layout);
 
   itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged);
   InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command);
 
   itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged);
   SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2);
 
   auto command3 = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command3->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationAborted);
   InterpolationAbortedObserverTag = m_Interpolator->AddObserver(itk::AbortEvent(), command3);
 
   // feedback node and its visualization properties
   m_FeedbackNode = mitk::DataNode::New();
   mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(m_FeedbackNode);
 
   m_FeedbackNode->SetProperty("binary", mitk::BoolProperty::New(true));
   m_FeedbackNode->SetProperty("outline binary", mitk::BoolProperty::New(true));
   m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
   m_FeedbackNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false));
   m_FeedbackNode->SetProperty("layer", mitk::IntProperty::New(20));
   m_FeedbackNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(0, 1)));
   m_FeedbackNode->SetProperty("name", mitk::StringProperty::New("Interpolation feedback"));
   m_FeedbackNode->SetProperty("opacity", mitk::FloatProperty::New(0.8));
   m_FeedbackNode->SetProperty("helper object", mitk::BoolProperty::New(true));
 
   m_InterpolatedSurfaceNode = mitk::DataNode::New();
   m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback"));
   m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
   m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f));
   m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
   m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
   m_InterpolatedSurfaceNode->SetVisibility(false);
 
   QWidget::setContentsMargins(0, 0, 0, 0);
   if (QWidget::layout() != nullptr)
   {
     QWidget::layout()->setContentsMargins(0, 0, 0, 0);
   }
 
 
   // For running 3D Interpolation in background
   // create a QFuture and a QFutureWatcher
 
   connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
   connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
   connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
   m_Timer = new QTimer(this);
   connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
 }
 
 void QmitkSlicesInterpolator::SetDataStorage(mitk::DataStorage::Pointer storage)
 {
   if (m_DataStorage == storage)
   {
     return;
   }
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 
   m_DataStorage = storage;
   m_SurfaceInterpolator->SetDataStorage(storage);
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.AddListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 }
 
 void QmitkSlicesInterpolator::SetActiveLabelValue(mitk::LabelSetImage::LabelValueType labelValue)
 {
   bool changedValue = labelValue != this->m_CurrentActiveLabelValue;
 
   this->m_CurrentActiveLabelValue = labelValue;
 
   if (changedValue) this->OnActiveLabelChanged(labelValue);
 };
 
 
 mitk::DataStorage *QmitkSlicesInterpolator::GetDataStorage()
 {
   if (m_DataStorage.IsNotNull())
   {
     return m_DataStorage;
   }
   else
   {
     return nullptr;
   }
 }
 
 void QmitkSlicesInterpolator::InitializeWindow(QmitkRenderWindow* window)
 {
   auto slicer = window->GetSliceNavigationController();
 
   if (slicer == nullptr)
   {
     MITK_WARN << "Tried setting up interpolation for a render window that does not have a slice navigation controller set";
     return;
   }
 
   // Has to be initialized
   m_LastSNC = slicer;
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
   m_ControllerToDeleteObserverTag[slicer] = slicer->AddObserver(itk::DeleteEvent(), deleteCommand);
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged);
   m_ControllerToSliceObserverTag[slicer] = slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand);
 }
 
 void QmitkSlicesInterpolator::Initialize(mitk::ToolManager *toolManager,
                                          const QList<QmitkRenderWindow*>& windows)
 {
   Q_ASSERT(!windows.empty());
 
   if (m_Initialized)
   {
     // remove old observers
     this->Uninitialize();
   }
 
   m_ToolManager = toolManager;
 
   if (m_ToolManager)
   {
     // set enabled only if a segmentation is selected
     mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
     QWidget::setEnabled(node != nullptr);
 
     // react whenever the set of selected segmentation changes
     m_ToolManager->WorkingDataChanged +=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
 
     auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
     itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
       itk::MemberCommand<QmitkSlicesInterpolator>::New();
     timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
     m_ControllerToTimeObserverTag =
       timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), timeChangedCommand);
 
     m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
     // connect to the slice navigation controller. after each change, call the interpolator
     for (auto* window : windows)
     {
       this->InitializeWindow(window);
     }
 
     m_ActionToSlicerMap = CreateActionToSlicer(windows);
   }
 
   m_Initialized = true;
 }
 
 void QmitkSlicesInterpolator::Uninitialize()
 {
   if (m_ToolManager.IsNotNull())
   {
     m_ToolManager->WorkingDataChanged -=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
   }
 
   auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
   timeNavigationController->RemoveObserver(m_ControllerToTimeObserverTag);
 
 for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
     slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
   }
 
   m_ActionToSlicerMap.clear();
   m_ToolManager = nullptr;
 
   m_Initialized = false;
 }
 
 QmitkSlicesInterpolator::~QmitkSlicesInterpolator()
 {
   if (m_Initialized)
   {
     // remove old observers
     this->Uninitialize();
   }
 
   WaitForFutures();
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
 
     if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       m_DataStorage->Remove(m_InterpolatedSurfaceNode);
   }
 
   // remove observer
   m_Interpolator->RemoveObserver(InterpolationAbortedObserverTag);
   m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag);
   m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag);
 
   m_SurfaceInterpolator->SetCurrentInterpolationSession(nullptr);
 
   delete m_Timer;
 }
 
 /**
 External enableization...
 */
 void QmitkSlicesInterpolator::setEnabled(bool enable)
 {
   QWidget::setEnabled(enable);
 
   // Set the gui elements of the different interpolation modi enabled
   if (enable)
   {
     if (m_2DInterpolationEnabled)
     {
       this->Show2DInterpolationControls(true);
       m_Interpolator->Activate2DInterpolation(true);
     }
     else if (m_3DInterpolationEnabled)
     {
       this->Show3DInterpolationControls(true);
       this->Show3DInterpolationResult(true);
     }
   }
   // Set all gui elements of the interpolation disabled
   else
   {
     this->HideAllInterpolationControls();
     this->Show3DInterpolationResult(false);
   }
 }
 
 void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status)
 {
   OnInterpolationActivated(status);
   m_Interpolator->Activate2DInterpolation(status);
 }
 
 void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status)
 {
   On3DInterpolationActivated(status);
 }
 
 void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status)
 {
   if (status)
   {
     OnInterpolationActivated(!status);
     On3DInterpolationActivated(!status);
     this->Show3DInterpolationResult(false);
   }
 }
 
 void QmitkSlicesInterpolator::HideAllInterpolationControls()
 {
   this->Show2DInterpolationControls(false);
   this->Show3DInterpolationControls(false);
 }
 
 void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show)
 {
   m_BtnApply2D->setVisible(show);
   m_BtnApplyForAllSlices2D->setVisible(show);
 }
 
 void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show)
 {
   m_BtnApply3D->setVisible(show);
 
   m_ChkShowPositionNodes->setVisible(show);
   m_BtnReinit3DInterpolation->setVisible(show);
 }
 
 void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index)
 {
   switch (index)
   {
     case 0: // Disabled
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation");
       this->HideAllInterpolationControls();
       this->OnInterpolationActivated(false);
       this->On3DInterpolationActivated(false);
       this->Show3DInterpolationResult(false);
       m_Interpolator->Activate2DInterpolation(false);
       break;
 
     case 1: // 2D
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
       this->HideAllInterpolationControls();
       this->Show2DInterpolationControls(true);
       this->OnInterpolationActivated(true);
       this->On3DInterpolationActivated(false);
       this->Show3DInterpolationResult(false);
       m_Interpolator->Activate2DInterpolation(true);
       break;
 
     case 2: // 3D
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
       this->HideAllInterpolationControls();
       this->Show3DInterpolationControls(true);
       this->OnInterpolationActivated(false);
       this->On3DInterpolationActivated(true);
       m_Interpolator->Activate2DInterpolation(false);
       break;
 
     default:
       MITK_ERROR << "Unknown interpolation method!";
       m_CmbInterpolation->setCurrentIndex(0);
       break;
   }
 }
 
 void QmitkSlicesInterpolator::OnShowMarkers(bool state)
 {
   mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers =
     m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
 
   for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End();
        ++it)
   {
     it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
   }
 }
 
 void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified()
 {
   if (m_ToolManager->GetWorkingData(0) != nullptr)
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
     m_BtnReinit3DInterpolation->setEnabled(true);
   }
   else
   {
     // If no workingdata is set, remove the interpolation feedback
     this->GetDataStorage()->Remove(m_FeedbackNode);
     m_FeedbackNode->SetData(nullptr);
     this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
     m_InterpolatedSurfaceNode->SetData(nullptr);
     m_BtnReinit3DInterpolation->setEnabled(false);
     m_CmbInterpolation->setCurrentIndex(0);
     return;
   }
   // Updating the current selected segmentation for the 3D interpolation
   this->SetCurrentContourListID();
 
   if (m_2DInterpolationEnabled)
   {
     OnInterpolationActivated(true); // re-initialize if needed
   }
 }
 
 void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified()
 {
 }
 
 void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::TimeNavigationController::TimeEvent*>(&e))
   {
     return;
   }
 
   const auto* timeNavigationController = dynamic_cast<mitk::TimeNavigationController*>(sender);
   if (nullptr == timeNavigationController)
   {
     return;
   }
 
   bool timeChanged = m_TimePoint != timeNavigationController->GetSelectedTimePoint();
   m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (timeChanged)
   {
     if (m_3DInterpolationEnabled)
     {
       m_InterpolatedSurfaceNode->SetData(nullptr);
     }
     m_SurfaceInterpolator->Modified();
   }
 
   if (nullptr == m_LastSNC)
   {
     return;
   }
 
   if (TranslateAndInterpolateChangedSlice(m_LastSNC->GetCreatedWorldGeometry()))
   {
     m_LastSNC->GetRenderer()->RequestUpdate();
   }
 }
 
 void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e))
   {
     return;
   }
 
   auto sliceNavigationController = dynamic_cast<mitk::SliceNavigationController*>(sender);
   if (nullptr == sliceNavigationController)
   {
     return;
   }
 
   if(m_2DInterpolationEnabled)
   {
     this->On2DInterpolationEnabled(m_2DInterpolationEnabled);
   }  
 
   if (TranslateAndInterpolateChangedSlice(e, sliceNavigationController))
   {
     sliceNavigationController->GetRenderer()->RequestUpdate();
   }
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e,
   mitk::SliceNavigationController* sliceNavigationController)
 {
   const mitk::SliceNavigationController::GeometrySliceEvent* event =
     dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e);
 
   mitk::TimeGeometry* timeGeometry = event->GetTimeGeometry();
   m_LastSNC = sliceNavigationController;
 
   return this->TranslateAndInterpolateChangedSlice(timeGeometry);
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry)
 {
   if (!m_2DInterpolationEnabled)
   {
     return false;
   }
 
   if (nullptr == timeGeometry)
   {
     return false;
   }
 
   if (!timeGeometry->IsValidTimePoint(m_TimePoint))
   {
     return false;
   }
 
   mitk::SlicedGeometry3D* slicedGeometry =
     dynamic_cast<mitk::SlicedGeometry3D*>(timeGeometry->GetGeometryForTimePoint(m_TimePoint).GetPointer());
   if (nullptr == slicedGeometry)
   {
     return false;
   }
 
   mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetPlaneGeometry(m_LastSNC->GetStepper()->GetPos()));
   if (nullptr == plane)
   {
     return false;
   }
 
   this->Interpolate(plane);
   return true;
 }
 
 void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane)
 {
   if (nullptr == m_ToolManager)
   {
     return;
   }
 
   mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
   if (nullptr == node)
   {
     return;
   }
 
   m_Segmentation = dynamic_cast<mitk::Image*>(node->GetData());
   if (nullptr == m_Segmentation)
   {
     return;
   }
 
   if (!m_Segmentation->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot interpolate WorkingImage. Passed time point is not within the time bounds of WorkingImage. "
                  "Time point: "
               << m_TimePoint;
     return;
   }
 
   const auto timeStep = m_Segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   int clickedSliceDimension = -1;
   int clickedSliceIndex = -1;
 
   // calculate real slice position, i.e. slice of the image
   mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
 
   mitk::Image::Pointer interpolation =
     m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
   m_FeedbackNode->SetData(interpolation);
 
   //  maybe just have a variable that stores the active label color.
   if (m_ToolManager)
   {
     auto* workingNode = m_ToolManager->GetWorkingData(0);
     if (workingNode != nullptr)
     {
       auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel();
       if (nullptr != activeLabel)
       {
         auto activeColor = activeLabel->GetColor();
         m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
       }
     }
   }
 
   m_LastSliceIndex = clickedSliceIndex;
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished()
 {
   mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
 
   if (workingNode && workingNode->GetData())
   {
     const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
 
     if (segmentation == nullptr)
     {
       MITK_ERROR << "Run3DInterpolation triggered with no MultiLabelSegmentation as working data.";
       return;
     }
     mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(segmentation, m_CurrentActiveLabelValue, segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint));
 
     if (interpolatedSurface.IsNotNull())
     {
       m_BtnApply3D->setEnabled(true);;
 
       m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
       this->Show3DInterpolationResult(true);
 
       if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       {
         m_DataStorage->Add(m_InterpolatedSurfaceNode);
       }
     }
     else
     {
       m_BtnApply3D->setEnabled(false);
 
       if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       {
         this->Show3DInterpolationResult(false);
       }
     }
   }
 
   m_BtnReinit3DInterpolation->setEnabled(true);
 
   for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->GetRenderer()->RequestUpdate();
   }
 }
 
 void QmitkSlicesInterpolator::OnAcceptInterpolationClicked()
 {
   auto* workingNode = m_ToolManager->GetWorkingData(0);
   auto* planeGeometry = m_LastSNC->GetCurrentPlaneGeometry();
   auto* interpolatedPreview = dynamic_cast<mitk::Image*>(m_FeedbackNode->GetData());
   if (nullptr == workingNode || nullptr == interpolatedPreview)
     return;
 
   auto* segmentationImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
   if (nullptr == segmentationImage)
     return;
 
   if (!segmentationImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the "
       "time bounds of segmentation. Time point: "
       << m_TimePoint;
     return;
   }
 
   const auto timeStep = segmentationImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   auto interpolatedSlice = mitk::SegTool2D::GetAffectedImageSliceAs2DImage(planeGeometry, segmentationImage, timeStep)->Clone();
   auto activeValue = segmentationImage->GetActiveLabel()->GetValue();
   mitk::TransferLabelContentAtTimeStep(
     interpolatedPreview,
     interpolatedSlice,
     segmentationImage->GetConstLabelsByValue(segmentationImage->GetLabelValuesByGroup(segmentationImage->GetActiveLayer())),
     timeStep,
     0,
     mitk::LabelSetImage::UNLABELED_VALUE,
     false,
     { {0, mitk::LabelSetImage::UNLABELED_VALUE}, {1, activeValue} }
   );
 
   mitk::SegTool2D::WriteBackSegmentationResult(workingNode, planeGeometry, interpolatedSlice, timeStep);
   m_FeedbackNode->SetData(nullptr);
 }
 
 void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController *slicer)
 {
   /*
    * What exactly is done here:
    * 1. We create an empty diff image for the current segmentation
    * 2. All interpolated slices are written into the diff image
    * 3. Then the diffimage is applied to the original segmentation
    */
   if (m_Segmentation)
   {
     mitk::Image::Pointer segmentation3D = m_Segmentation;
     unsigned int timeStep = 0;
 
     if (4 == m_Segmentation->GetDimension())
     {
       const auto* geometry = m_Segmentation->GetTimeGeometry();
 
       if (!geometry->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept all interpolations. Time point selected by passed SliceNavigationController is not "
                      "within the time bounds of segmentation. Time point: "
                   << m_TimePoint;
         return;
       }
 
       mitk::Image::Pointer activeLabelImage;
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation);
         activeLabelImage = labelSetImage->CreateLabelMask(labelSetImage->GetActiveLabel()->GetValue());
       }
       catch (const std::exception& e)
       {
         MITK_ERROR << e.what() << " | NO LABELSETIMAGE IN WORKING NODE\n";
       }
 
       m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
       timeStep = geometry->TimePointToTimeStep(m_TimePoint);
 
       auto timeSelector = mitk::ImageTimeSelector::New();
       timeSelector->SetInput(m_Segmentation);
       timeSelector->SetTimeNr(timeStep);
       timeSelector->Update();
 
       segmentation3D = timeSelector->GetOutput();
     }
 
     // Create an empty diff image for the undo operation
     auto diffImage = mitk::Image::New();
     diffImage->Initialize(segmentation3D);
 
     // Create scope for ImageWriteAccessor so that the accessor is destroyed right after use
     {
       mitk::ImageWriteAccessor accessor(diffImage);
 
       // Set all pixels to zero
       auto pixelType = mitk::MakeScalarPixelType<mitk::Tool::DefaultSegmentationDataType>();
 
       // For legacy purpose support former pixel type of segmentations (before multilabel)
       if (itk::IOComponentEnum::UCHAR == m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType())
         pixelType = mitk::MakeScalarPixelType<unsigned char>();
 
       memset(accessor.GetData(), 0, pixelType.GetSize() * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2));
     }
 
     // Since we need to shift the plane it must be clone so that the original plane isn't altered
     auto slicedGeometry = m_Segmentation->GetSlicedGeometry();
     auto planeGeometry = slicer->GetCurrentPlaneGeometry()->Clone();
     int sliceDimension = -1;
     int sliceIndex = -1;
 
     mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, planeGeometry, sliceDimension, sliceIndex);
 
     const auto numSlices = m_Segmentation->GetDimension(sliceDimension);
     mitk::ProgressBar::GetInstance()->AddStepsToDo(numSlices);
 
     std::atomic_uint totalChangedSlices;
 
     // Reuse interpolation algorithm instance for each slice to cache boundary calculations
     auto algorithm = mitk::ShapeBasedInterpolationAlgorithm::New();
 
     // Distribute slice interpolations to multiple threads
     const auto numThreads = std::min(std::thread::hardware_concurrency(), numSlices);
     std::vector<std::vector<unsigned int>> sliceIndices(numThreads);
 
     for (std::remove_const_t<decltype(numSlices)> sliceIndex = 0; sliceIndex < numSlices; ++sliceIndex)
       sliceIndices[sliceIndex % numThreads].push_back(sliceIndex);
 
     std::vector<std::thread> threads;
     threads.reserve(numThreads);
 
     // This lambda will be executed by the threads
     auto interpolate = [=, &interpolator = m_Interpolator, &totalChangedSlices](unsigned int threadIndex)
     {
       auto clonedPlaneGeometry = planeGeometry->Clone();
       auto origin = clonedPlaneGeometry->GetOrigin();
 
       //  Go through the sliced indices
       for (auto sliceIndex : sliceIndices[threadIndex])
       {
         slicedGeometry->WorldToIndex(origin, origin);
         origin[sliceDimension] = sliceIndex;
         slicedGeometry->IndexToWorld(origin, origin);
         clonedPlaneGeometry->SetOrigin(origin);
 
         auto interpolation = interpolator->Interpolate(sliceDimension, sliceIndex, clonedPlaneGeometry, timeStep, algorithm);
 
         if (interpolation.IsNotNull())
         {
           // Setting up the reslicing pipeline which allows us to write the interpolation results back into the image volume
           auto reslicer = vtkSmartPointer<mitkVtkImageOverwrite>::New();
 
           // Set overwrite mode to true to write back to the image volume
           reslicer->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData());
           reslicer->SetOverwriteMode(true);
           reslicer->Modified();
 
           auto diffSliceWriter = mitk::ExtractSliceFilter::New(reslicer);
 
           diffSliceWriter->SetInput(diffImage);
           diffSliceWriter->SetTimeStep(0);
           diffSliceWriter->SetWorldGeometry(clonedPlaneGeometry);
           diffSliceWriter->SetVtkOutputRequest(true);
           diffSliceWriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0));
           diffSliceWriter->Modified();
           diffSliceWriter->Update();
 
           ++totalChangedSlices;
         }
 
         mitk::ProgressBar::GetInstance()->Progress();
       }
     };
     m_Interpolator->EnableSliceImageCache();
 
     //  Do the interpolation here.
     for (size_t threadIndex = 0; threadIndex < numThreads; ++threadIndex)
     {
       interpolate(threadIndex);
     }
 
     m_Interpolator->DisableSliceImageCache();
 
     const mitk::Label::PixelType newDestinationLabel = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation)->GetActiveLabel()->GetValue();
 
     //  Do and Undo Operations
     if (totalChangedSlices > 0)
     {
       // Create do/undo operations
       auto* doOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
 
       auto* undoOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
       undoOp->SetFactor(-1.0);
 
       auto comment = "Confirm all interpolations (" + std::to_string(totalChangedSlices) + ")";
       auto* undoStackItem = new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment);
 
       mitk::OperationEvent::IncCurrGroupEventId();
       mitk::OperationEvent::IncCurrObjectEventId();
       mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem);
       mitk::DiffImageApplier::GetInstanceForUndo()->SetDestinationLabel(newDestinationLabel);
       // Apply the changes to the original image
       mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation(doOp);
     }
     m_FeedbackNode->SetData(nullptr);
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController *slicer)
 {
   // this redirect is for calling from outside
   if (slicer == nullptr)
     OnAcceptAllInterpolationsClicked();
   else
     AcceptAllInterpolations(slicer);
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked()
 {
   QMenu orientationPopup(this);
   for (auto it = m_ActionToSlicerMap.begin(); it != m_ActionToSlicerMap.end(); ++it)
   {
     orientationPopup.addAction(it->first);
   }
 
   connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *)));
   orientationPopup.exec(QCursor::pos());
 }
 
 void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked()
 {
   auto referenceImage = GetData<mitk::Image>(m_ToolManager->GetReferenceData(0));
 
   auto* segmentationDataNode = m_ToolManager->GetWorkingData(0);
 
   auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(segmentationDataNode->GetData());
   auto activeLabelColor = labelSetImage->GetActiveLabel()->GetColor();
   std::string activeLabelName = labelSetImage->GetActiveLabel()->GetName();
 
   auto segmentation = GetData<mitk::Image>(segmentationDataNode);
 
   if (referenceImage.IsNull() || segmentation.IsNull())
     return;
 
   const auto* segmentationGeometry = segmentation->GetTimeGeometry();
 
   if (!referenceImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint) ||
       !segmentationGeometry->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Current time point is not within the time bounds of the patient image and segmentation.";
     return;
   }
 
   auto interpolatedSurface = GetData<mitk::Surface>(m_InterpolatedSurfaceNode);
 
   if (interpolatedSurface.IsNull())
     return;
 
   auto surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
 
   surfaceToImageFilter->SetImage(referenceImage);
   surfaceToImageFilter->SetMakeOutputBinary(true);
   surfaceToImageFilter->SetUShortBinaryPixelType(itk::IOComponentEnum::USHORT == segmentation->GetPixelType().GetComponentType());
   surfaceToImageFilter->SetInput(interpolatedSurface);
   surfaceToImageFilter->Update();
 
   mitk::Image::Pointer interpolatedSegmentation = surfaceToImageFilter->GetOutput();
   auto timeStep = segmentationGeometry->TimePointToTimeStep(m_TimePoint);
   const mitk::Label::PixelType newDestinationLabel = labelSetImage->GetActiveLabel()->GetValue();
 
   TransferLabelContentAtTimeStep(
     interpolatedSegmentation,
     labelSetImage,
     labelSetImage->GetConstLabelsByValue(labelSetImage->GetLabelValuesByGroup(labelSetImage->GetActiveLayer())),
     timeStep,
     0,
     0,
     false,
     {{1, newDestinationLabel}},
     mitk::MultiLabelSegmentation::MergeStyle::Merge,
     mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
   this->Show3DInterpolationResult(false);
 
   std::string name = segmentationDataNode->GetName() + " 3D-interpolation - " + activeLabelName;
   mitk::TimeBounds timeBounds;
 
   if (1 < interpolatedSurface->GetTimeSteps())
   {
     name += "_t" + std::to_string(timeStep);
 
     auto* polyData = vtkPolyData::New();
     polyData->DeepCopy(interpolatedSurface->GetVtkPolyData(timeStep));
 
     auto surface = mitk::Surface::New();
     surface->SetVtkPolyData(polyData);
 
     interpolatedSurface = surface;
     timeBounds = segmentationGeometry->GetTimeBounds(timeStep);
   }
   else
   {
     timeBounds = segmentationGeometry->GetTimeBounds(0);
   }
 
   auto* surfaceGeometry = static_cast<mitk::ProportionalTimeGeometry*>(interpolatedSurface->GetTimeGeometry());
   surfaceGeometry->SetFirstTimePoint(timeBounds[0]);
   surfaceGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
 
   // Typical file formats for surfaces do not save any time-related information. As a workaround at least for MITK scene files, we have the
   // possibility to seralize this information as properties.
 
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.FirstTimePoint", mitk::FloatProperty::New(surfaceGeometry->GetFirstTimePoint()));
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.StepDuration", mitk::FloatProperty::New(surfaceGeometry->GetStepDuration()));
 
   auto interpolatedSurfaceDataNode = mitk::DataNode::New();
 
   interpolatedSurfaceDataNode->SetData(interpolatedSurface);
   interpolatedSurfaceDataNode->SetName(name);
   interpolatedSurfaceDataNode->SetOpacity(0.7f);
 
   interpolatedSurfaceDataNode->SetColor(activeLabelColor);
   m_DataStorage->Add(interpolatedSurfaceDataNode, segmentationDataNode);
 }
 
 void QmitkSlicesInterpolator::OnReinit3DInterpolation()
 {
   //  Step 1. Load from the isContourPlaneGeometry nodes the contourNodes.
   mitk::NodePredicateProperty::Pointer pred =
     mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
   mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
     m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred);
 
   if (contourNodes->Size() != 0)
   {
     if (m_ToolManager->GetWorkingData(0) != nullptr)
     {
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
         if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
         {
           MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
           return;
         }
 
         mitk::SurfaceInterpolationController::CPIVector newCPIs;
         //  Adding label and timeStep information for the contourNodes.
         for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
         {
           auto contourNode = it->Value();
           auto labelID = dynamic_cast<mitk::UShortProperty *>(contourNode->GetProperty("labelID"))->GetValue();
           auto timeStep = dynamic_cast<mitk::IntProperty *>(contourNode->GetProperty("timeStep"))->GetValue();
 
           auto planeGeometry = dynamic_cast<mitk::PlanarFigure *>(contourNode->GetData())->GetPlaneGeometry();
           auto groupID = labelSetImage->GetGroupIndexOfLabel(labelID);
           auto sliceImage = ExtractSliceFromImage(labelSetImage->GetGroupImage(groupID), planeGeometry, timeStep);
           mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
           contourExtractor->SetInput(sliceImage);
           contourExtractor->SetContourValue(labelID);
           contourExtractor->Update();
           mitk::Surface::Pointer contour = contourExtractor->GetOutput();
 
           if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
             continue;
 
           contour->DisconnectPipeline();
           newCPIs.emplace_back(contour, planeGeometry->Clone(),labelID,timeStep);
         }
         m_SurfaceInterpolator->CompleteReinitialization(newCPIs);
       }
       catch(const std::exception& e)
       {
         MITK_ERROR << "Exception thrown casting toolmanager working data to labelsetImage";
       }
     }
   }
   else
   {
     m_BtnApply3D->setEnabled(false);
     QMessageBox errorInfo;
     errorInfo.setWindowTitle("Reinitialize surface interpolation");
     errorInfo.setIcon(QMessageBox::Information);
     errorInfo.setText("No contours available for the selected segmentation!");
     errorInfo.exec();
   }
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction *action)
 {
   try
   {
     auto iter = m_ActionToSlicerMap.find(action);
     if (iter != m_ActionToSlicerMap.end())
     {
       mitk::SliceNavigationController *slicer = iter->second;
       this->AcceptAllInterpolations(slicer);
     }
   }
   catch (...)
   {
     /* Showing message box with possible memory error */
     QMessageBox errorInfo;
     errorInfo.setWindowTitle("Interpolation Process");
     errorInfo.setIcon(QMessageBox::Critical);
     errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!");
     errorInfo.exec();
 
     std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl;
   }
 }
 
 void QmitkSlicesInterpolator::OnInterpolationActivated(bool on)
 {
   m_2DInterpolationEnabled = on;
 
   try
   {
     if (m_DataStorage.IsNotNull())
     {
       if (on && !m_DataStorage->Exists(m_FeedbackNode))
       {
         m_DataStorage->Add(m_FeedbackNode);
       }
     }
   }
   catch (...)
   {
     // don't care (double add/remove)
   }
 
   if (m_ToolManager)
   {
     mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
     mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0);
     QWidget::setEnabled(workingNode != nullptr);
 
     m_BtnApply2D->setEnabled(on);
     m_FeedbackNode->SetVisibility(on);
 
     if (!on)
     {
       mitk::RenderingManager::GetInstance()->RequestUpdateAll();
       return;
     }
 
     if (workingNode)
     {
       auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       if (nullptr == labelSetImage)
       {
         MITK_ERROR << "NO LABELSETIMAGE IN WORKING NODE\n";
         mitk::RenderingManager::GetInstance()->RequestUpdateAll();
         return;
       }
 
       const auto* activeLabel = labelSetImage->GetActiveLabel();
       const auto* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
       if (nullptr != activeLabel && nullptr != segmentation)
       {
         auto activeLabelImage = labelSetImage->CreateLabelMask(activeLabel->GetValue());
         m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
         if (referenceNode)
         {
           mitk::Image *referenceImage = dynamic_cast<mitk::Image *>(referenceNode->GetData());
           m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr
         }
       }
     }
   }
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::Run3DInterpolation()
 {
   auto workingNode = m_ToolManager->GetWorkingData(0);
 
   if (workingNode == nullptr)
   {
     MITK_ERROR << "Run3DInterpolation triggered with no working data set.";
     return;
   }
 
   const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
 
   if (segmentation == nullptr)
   {
     MITK_ERROR << "Run3DInterpolation triggered with no MultiLabelSegmentation as working data.";
     return;
   }
 
+  if (!segmentation->ExistLabel(m_CurrentActiveLabelValue))
+  {
+    MITK_ERROR << "Run3DInterpolation triggered with no valid label selected. Currently selected invalid label: "<<m_CurrentActiveLabelValue;
+    return;
+  }
+
   m_SurfaceInterpolator->Interpolate(segmentation,m_CurrentActiveLabelValue,segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint));
 }
 
 void QmitkSlicesInterpolator::StartUpdateInterpolationTimer()
 {
   m_Timer->start(500);
 }
 
 void QmitkSlicesInterpolator::StopUpdateInterpolationTimer()
 {
   if(m_ToolManager)
   {
     const auto* workingNode = m_ToolManager->GetWorkingData(0);
     const auto activeColor = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel()->GetColor();
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
   }
 
   m_Timer->stop();
 }
 
 void QmitkSlicesInterpolator::ChangeSurfaceColor()
 {
   float currentColor[3];
   m_InterpolatedSurfaceNode->GetColor(currentColor);
 
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->Update();
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS);
 }
 
 void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on)
 {
   m_3DInterpolationEnabled = on;
   try
   {
     // this->PrepareInputsFor3DInterpolation();
     m_SurfaceInterpolator->Modified();
   }
   catch (...)
   {
     MITK_ERROR << "Error with 3D surface interpolation!";
   }
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::EnableInterpolation(bool on)
 {
   // only to be called from the outside world
   // just a redirection to OnInterpolationActivated
   OnInterpolationActivated(on);
 }
 
 void QmitkSlicesInterpolator::Enable3DInterpolation(bool on)
 {
   // only to be called from the outside world
   // just a redirection to OnInterpolationActivated
   this->On3DInterpolationActivated(on);
 }
 
 void QmitkSlicesInterpolator::UpdateVisibleSuggestion()
 {
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
   // something (e.g. undo) changed the interpolation info, we should refresh our display
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationAborted(const itk::EventObject& /*e*/)
 {
   m_CmbInterpolation->setCurrentIndex(0);
   m_FeedbackNode->SetData(nullptr);
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
+  auto workingNode = m_ToolManager->GetWorkingData(0);
+
+  if (workingNode == nullptr)
+  {
+    MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no working data set.";
+    return;
+  }
+
+  const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
+
+  if (segmentation == nullptr)
+  {
+    MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no MultiLabelSegmentation as working data.";
+    return;
+  }
+
+  if (!segmentation->ExistLabel(m_CurrentActiveLabelValue))
+  {
+    MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no valid label selected. Currently selected invalid label: " << m_CurrentActiveLabelValue;
+    return;
+  }
+
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
-
     m_InterpolatedSurfaceNode->SetData(nullptr);
     m_Future = QtConcurrent::run(&QmitkSlicesInterpolator::Run3DInterpolation, this);
     m_Watcher.setFuture(m_Future);
   }
 }
 
 void QmitkSlicesInterpolator::SetCurrentContourListID()
 {
   // New ContourList = hide current interpolation
   Show3DInterpolationResult(false);
 
   if (m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC)
   {
     mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
 
     if (workingNode)
     {
       QWidget::setEnabled(true);
 
       if (!workingNode->GetData()->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << m_TimePoint;
         return;
       }
 
       m_SurfaceInterpolator->SetDistanceImageVolume(50000);
 
       auto segmentationImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage);
     }
     else
     {
       QWidget::setEnabled(false);
     }
   }
 }
 
 void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status)
 {
   if (m_InterpolatedSurfaceNode.IsNotNull())
     m_InterpolatedSurfaceNode->SetVisibility(status);
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnActiveLabelChanged(mitk::Label::PixelType)
 {
   m_FeedbackNode->SetData(nullptr);
   m_InterpolatedSurfaceNode->SetData(nullptr);
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
     m_SurfaceInterpolator->Modified();
   }
 
   if (m_2DInterpolationEnabled)
   {
     m_FeedbackNode->SetData(nullptr);
     this->OnInterpolationActivated(true);
 
     m_LastSNC->SendSlice();
   }
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::CheckSupportedImageDimension()
 {
   if (m_ToolManager->GetWorkingData(0))
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
 
     if (m_3DInterpolationEnabled && m_Segmentation && ((m_Segmentation->GetDimension() != 3) || (m_Segmentation->GetDimension() != 4)) )
     {
       QMessageBox info;
       info.setWindowTitle("3D Interpolation Process");
       info.setIcon(QMessageBox::Information);
       info.setText("3D Interpolation is only supported for 3D/4D images at the moment!");
       info.exec();
       m_CmbInterpolation->setCurrentIndex(0);
     }
   }
 }
 
 void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender,
                                                                  const itk::EventObject & /*e*/)
 {
   // Don't know how to avoid const_cast here?!
   mitk::SliceNavigationController *slicer =
     dynamic_cast<mitk::SliceNavigationController *>(const_cast<itk::Object *>(sender));
   if (slicer)
   {
     m_ControllerToSliceObserverTag.remove(slicer);
     m_ControllerToDeleteObserverTag.remove(slicer);
   }
 }
 
 void QmitkSlicesInterpolator::WaitForFutures()
 {
   if (m_Watcher.isRunning())
   {
     m_Watcher.waitForFinished();
   }
 
   if (m_PlaneWatcher.isRunning())
   {
     m_PlaneWatcher.waitForFinished();
   }
 }
 
 void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node)
 {
   if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) ||
       node == m_FeedbackNode ||
       node == m_InterpolatedSurfaceNode)
   {
     WaitForFutures();
   }
 }
diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
index d1f68616ec..a9011e69f7 100644
--- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
+++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
@@ -1,876 +1,876 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include <mitkSurfaceInterpolationController.h>
 
 #include <shared_mutex>
 
 #include <mitkCreateDistanceImageFromSurfaceFilter.h>
 #include <mitkComputeContourSetNormalsFilter.h>
 #include <mitkImageAccessByItk.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkImageToSurfaceFilter.h>
 #include <mitkNodePredicateDataUID.h>
 #include <mitkNodePredicateProperty.h>
 #include <mitkNodePredicateAnd.h>
 #include <mitkPlanarCircle.h>
 #include <mitkPlaneGeometry.h>
 #include <mitkReduceContourSetFilter.h>
 
 struct CPICache
 {
   mitk::SurfaceInterpolationController::CPIVector cpis;
   itk::TimeStamp cpiTimeStamp;
   mitk::Surface::Pointer cachedSurface;
 };
 
 typedef std::map<mitk::TimeStepType, CPICache> CPITimeStepMap;
 typedef std::map<mitk::LabelSetImage::LabelValueType, CPITimeStepMap> CPITimeStepLabelMap;
 
 typedef std::map<const mitk::LabelSetImage*, CPITimeStepLabelMap> CPITimeStepLabelSegMap;
 
 CPITimeStepLabelSegMap cpiMap;
 std::shared_mutex cpiMutex;
 
 std::map<mitk::LabelSetImage*, unsigned long> segmentationObserverTags;
 std::map<mitk::LabelSetImage*, unsigned long> labelRemovedObserverTags;
 
 mitk::SurfaceInterpolationController::SurfaceInterpolationController()
   : m_DistanceImageVolume(50000),
     m_SelectedSegmentation(nullptr)
 {
 }
 
 mitk::SurfaceInterpolationController::~SurfaceInterpolationController()
 {
   this->RemoveObservers();
 }
 
 void mitk::SurfaceInterpolationController::RemoveObservers()
 {
   // Removing all observers
   while (segmentationObserverTags.size())
   {
     this->RemoveObserversInternal(segmentationObserverTags.begin()->first);
   }
 }
 
 mitk::SurfaceInterpolationController *mitk::SurfaceInterpolationController::GetInstance()
 {
   static mitk::SurfaceInterpolationController::Pointer m_Instance;
 
   if (m_Instance.IsNull())
   {
     m_Instance = SurfaceInterpolationController::New();
   }
   return m_Instance;
 }
 
 void mitk::SurfaceInterpolationController::AddNewContours(const std::vector<ContourPositionInformation>& newCPIs,
   bool reinitializationAction, bool silent)
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
   if (selectedSegmentation.IsNull()) return;
 
   for (auto cpi : newCPIs)
   {
     if (cpi.Contour->GetVtkPolyData()->GetNumberOfPoints() > 0)
     {
       this->AddToCPIMap(cpi, reinitializationAction);
     }
   }
   if (!silent) this->Modified();
 }
 
 
 mitk::DataNode* GetSegmentationImageNodeInternal(mitk::DataStorage* ds, const mitk::LabelSetImage* seg)
 {
   if (nullptr == ds) return nullptr;
   if (nullptr == seg) return nullptr;
 
   mitk::DataNode* segmentationNode = nullptr;
   mitk::NodePredicateDataUID::Pointer dataUIDPredicate = mitk::NodePredicateDataUID::New(seg->GetUID());
   auto dataNodeObjects = ds->GetSubset(dataUIDPredicate);
 
   if (dataNodeObjects->Size() != 0)
   {
     for (auto it = dataNodeObjects->Begin(); it != dataNodeObjects->End(); ++it)
     {
       segmentationNode = it->Value();
     }
   }
   else
   {
     MITK_ERROR << "Unable to find the labelSetImage with the desired UID.";
   }
   return segmentationNode;
 }
 
 mitk::DataNode* mitk::SurfaceInterpolationController::GetSegmentationImageNode() const
 {
   if (m_DataStorage.IsNull()) return nullptr;
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
   if (selectedSegmentation.IsNull()) return nullptr;
   return GetSegmentationImageNodeInternal(this->m_DataStorage, selectedSegmentation);
 }
 
 mitk::DataStorage::SetOfObjects::ConstPointer mitk::SurfaceInterpolationController::GetPlaneGeometryNodeFromDataStorage(const DataNode* segNode, LabelSetImage::LabelValueType labelValue, TimeStepType timeStep) const
 {
   DataStorage::SetOfObjects::Pointer relevantNodes = DataStorage::SetOfObjects::New();
 
   if (m_DataStorage.IsNotNull())
   {
     //remove relevant plane nodes
     auto nodes = this->GetPlaneGeometryNodeFromDataStorage(segNode, labelValue);
 
     for (auto it = nodes->Begin(); it != nodes->End(); ++it)
     {
       auto aTS = static_cast<TimeStepType>(dynamic_cast<mitk::IntProperty*>(it->Value()->GetProperty("timeStep"))->GetValue());
       bool sameTS = (timeStep == aTS);
 
       if (sameTS)
       {
         relevantNodes->push_back(it->Value());
       }
     }
   }
   return relevantNodes;
 }
 
 mitk::DataStorage::SetOfObjects::ConstPointer mitk::SurfaceInterpolationController::GetPlaneGeometryNodeFromDataStorage(const DataNode* segNode, LabelSetImage::LabelValueType labelValue) const
 {
   auto isContourPlaneGeometry = NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
   auto isCorrectLabel = NodePredicateProperty::New("labelID", mitk::UShortProperty::New(labelValue));
   auto searchPredicate = NodePredicateAnd::New(isContourPlaneGeometry, isCorrectLabel);
 
   mitk::DataStorage::SetOfObjects::ConstPointer result;
   if (m_DataStorage.IsNotNull()) result = m_DataStorage->GetDerivations(segNode, searchPredicate);
   return result;
 }
 
 mitk::DataStorage::SetOfObjects::ConstPointer mitk::SurfaceInterpolationController::GetPlaneGeometryNodeFromDataStorage(const DataNode* segNode) const
 {
   auto isContourPlaneGeometry = NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
 
   mitk::DataStorage::SetOfObjects::ConstPointer result;
   if (m_DataStorage.IsNotNull()) result = m_DataStorage->GetDerivations(segNode, isContourPlaneGeometry);
   return result;
 }
 void mitk::SurfaceInterpolationController::AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo) const
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
   if (selectedSegmentation.IsNull())
   {
     mitkThrow()<< "Cannot add plane geometries. No valid segmentation selected.";
   }
 
   if (!selectedSegmentation->GetTimeGeometry()->IsValidTimeStep(contourInfo.TimeStep))
   {
     MITK_ERROR << "Invalid time point requested in AddPlaneGeometryNodeToDataStorage.";
     return;
   }
 
   if (m_DataStorage.IsNull())
   {
     MITK_DEBUG << "Cannot add plane geometry nodes. No data storage is set.";
     return;
   }
 
   auto planeGeometry = contourInfo.Plane;
   if (planeGeometry)
   {
     auto segmentationNode = this->GetSegmentationImageNode();
     mitk::DataStorage::SetOfObjects::ConstPointer contourNodes = this->GetPlaneGeometryNodeFromDataStorage(segmentationNode, contourInfo.LabelValue, contourInfo.TimeStep);
 
     mitk::DataNode::Pointer contourPlaneGeometryDataNode;
 
     //  Go through the pre-existing contours and check if the contour position matches them.
     for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
     {
       auto planeData = dynamic_cast<mitk::PlanarFigure*>(it->Value()->GetData());
       if (nullptr == planeData) mitkThrow() << "Invalid ContourPlaneGeometry data node. Does not contion a planar figure as data.";
 
       bool samePlane = contourInfo.Plane->IsOnPlane(planeData->GetPlaneGeometry());
 
       if (samePlane)
       {
         contourPlaneGeometryDataNode = it->Value();
         break;
       }
     }
 
     //  Go through the contourPlaneGeometry Data and add the segmentationNode to it.
     if (contourPlaneGeometryDataNode.IsNull())
     {
       auto planeGeometryData = mitk::PlanarCircle::New();
       planeGeometryData->SetPlaneGeometry(planeGeometry->Clone());
       mitk::Point2D p1;
       planeGeometry->Map(planeGeometry->GetCenter(), p1);
       planeGeometryData->PlaceFigure(p1);
       planeGeometryData->SetCurrentControlPoint(p1);
       planeGeometryData->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
 
       std::string contourName = "contourPlane L " + std::to_string(contourInfo.LabelValue) + " T " + std::to_string(contourInfo.TimeStep);
 
       contourPlaneGeometryDataNode = mitk::DataNode::New();
       contourPlaneGeometryDataNode->SetData(planeGeometryData);
 
       //  No need to change properties
       contourPlaneGeometryDataNode->SetProperty("helper object", mitk::BoolProperty::New(false));
       contourPlaneGeometryDataNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
       contourPlaneGeometryDataNode->SetProperty("isContourPlaneGeometry", mitk::BoolProperty::New(true));
       contourPlaneGeometryDataNode->SetVisibility(false);
 
       //  Need to change properties
       contourPlaneGeometryDataNode->SetProperty("name", mitk::StringProperty::New(contourName) );
       contourPlaneGeometryDataNode->SetProperty("labelID", mitk::UShortProperty::New(contourInfo.LabelValue));
       contourPlaneGeometryDataNode->SetProperty("timeStep", mitk::IntProperty::New(contourInfo.TimeStep));
 
       contourPlaneGeometryDataNode->SetData(planeGeometryData);
 
       m_DataStorage->Add(contourPlaneGeometryDataNode, segmentationNode);
     }
   }
 }
 
 void mitk::SurfaceInterpolationController::AddToCPIMap(ContourPositionInformation& contourInfo, bool reinitializationAction)
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
   if (selectedSegmentation.IsNull())
     return;
 
   if (!selectedSegmentation->GetTimeGeometry()->IsValidTimeStep(contourInfo.TimeStep))
   {
     MITK_ERROR << "Invalid time step requested for interpolation pipeline.";
     return;
   }
 
   if (contourInfo.Plane == nullptr)
   {
     MITK_ERROR << "contourInfo plane is null.";
     return;
   }
 
   if (contourInfo.Contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
   {
     this->RemoveContour(contourInfo);
     MITK_DEBUG << "contourInfo contour is empty.";
     return;
   }
 
   {
     std::lock_guard<std::shared_mutex> guard(cpiMutex);
     const auto& currentTimeStep = contourInfo.TimeStep;
     const auto& currentLabelValue = contourInfo.LabelValue;
 
     auto& currentImageContours = cpiMap[selectedSegmentation];
     auto& currentLabelContours = currentImageContours[currentLabelValue];
     auto& currentCPICache = currentLabelContours[currentTimeStep];
     auto& currentContourList = currentCPICache.cpis;
 
     auto finding = std::find_if(currentContourList.begin(), currentContourList.end(), [contourInfo](const ContourPositionInformation& element) {return contourInfo.Plane->IsOnPlane(element.Plane); });
 
     if (finding != currentContourList.end())
     {
       MITK_DEBUG << "CPI already exists. CPI is updated. Label: "<< currentLabelValue << "; Time Step: " << currentTimeStep;
       *finding = contourInfo;
     }
     else
     {
       currentContourList.push_back(contourInfo);
     }
     currentCPICache.cpiTimeStamp.Modified();
   }
 
   if (!reinitializationAction)
   {
     this->AddPlaneGeometryNodeToDataStorage(contourInfo);
   }
 }
 
 bool mitk::SurfaceInterpolationController::RemoveContour(ContourPositionInformation contourInfo, bool keepPlaceholderForUndo)
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
   if (selectedSegmentation.IsNull())
   {
     return false;
   }
 
   if (!selectedSegmentation->GetTimeGeometry()->IsValidTimeStep(contourInfo.TimeStep))
   {
     return false;
   }
 
   bool removedIt = false;
 
   {
     std::lock_guard<std::shared_mutex> cpiGuard(cpiMutex);
 
     const auto currentTimeStep = contourInfo.TimeStep;
     const auto currentLabel = contourInfo.LabelValue;
     auto& cpiCache = cpiMap.at(selectedSegmentation).at(currentLabel).at(currentTimeStep);
     auto it = cpiCache.cpis.begin();
 
 
     while (it != cpiCache.cpis.end())
     {
       const ContourPositionInformation& currentContour = (*it);
       if (currentContour.Plane->IsOnPlane(contourInfo.Plane))
       {
         if (keepPlaceholderForUndo)
         {
           it->Contour = nullptr;
         }
         else
         {
           cpiCache.cpis.erase(it);
         }
         cpiCache.cpiTimeStamp.Modified();
         removedIt = true;
 
         if (m_DataStorage.IsNotNull())
         {
           mitk::DataNode::Pointer contourPlaneGeometryDataNode;
 
           auto contourNodes = this->GetPlaneGeometryNodeFromDataStorage(GetSegmentationImageNodeInternal(m_DataStorage, selectedSegmentation), currentLabel, currentTimeStep);
 
           //  Go through the nodes and check if the contour position matches them.
           for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
           {
             auto planeData = dynamic_cast<mitk::PlanarFigure*>(it->Value()->GetData());
             if (nullptr == planeData) mitkThrow() << "Invalid ContourPlaneGeometry data node. Does not contion a planar figure as data.";
 
             bool samePlane = contourInfo.Plane->IsOnPlane(planeData->GetPlaneGeometry());
 
             if (samePlane)
             {
               m_DataStorage->Remove(it->Value());
               break;
             }
           }
         }
         break;
       }
       ++it;
     }
   }
 
   return removedIt;
 }
 
 void mitk::SurfaceInterpolationController::AddActiveLabelContoursForInterpolation(ReduceContourSetFilter* reduceFilter, const LabelSetImage* segmentationImage, LabelSetImage::LabelValueType labelValue, TimeStepType timeStep)
 {
   const auto& currentImageContours = cpiMap.at(segmentationImage);
 
   auto finding = currentImageContours.find(labelValue);
   if (finding == currentImageContours.end())
   {
     MITK_INFO << "Contours for label don't exist. Label value: " << labelValue;
     return;
   }
 
   const auto& currentLabelContoursMap = finding->second;
 
   auto tsfinding = currentLabelContoursMap.find(timeStep);
   if (tsfinding == currentLabelContoursMap.end())
   {
     MITK_INFO << "Contours for current time step don't exist.";
     return;
   }
 
   const auto& currentContours = tsfinding->second.cpis;
 
   unsigned int index = 0;
   for (const auto&  cpi : currentContours)
   {
     if (!cpi.IsPlaceHolder())
     {
       reduceFilter->SetInput(index, cpi.Contour);
       ++index;
     }
   }
 }
 
 bool CPICacheIsOutdated(const mitk::LabelSetImage* segmentationImage, mitk::LabelSetImage::LabelValueType labelValue, mitk::TimeStepType timeStep)
 {
   const auto& currentImageContours = cpiMap.at(segmentationImage);
 
   auto finding = currentImageContours.find(labelValue);
   if (finding == currentImageContours.end())
   {
     return false;
   }
 
   const auto& currentLabelContoursMap = finding->second;
 
   auto tsfinding = currentLabelContoursMap.find(timeStep);
   if (tsfinding == currentLabelContoursMap.end())
   {
     return false;
   }
 
   bool result = tsfinding->second.cachedSurface.IsNull() || tsfinding->second.cachedSurface->GetMTime() < tsfinding->second.cpiTimeStamp.GetMTime();
   return result;
 }
 
 void SetCPICacheSurface(mitk::Surface* surface, const mitk::LabelSetImage* segmentationImage, mitk::LabelSetImage::LabelValueType labelValue, mitk::TimeStepType timeStep)
 {
   const auto& currentImageContours = cpiMap.at(segmentationImage);
 
   auto finding = currentImageContours.find(labelValue);
   if (finding == currentImageContours.end())
   {
     return;
   }
 
   const auto& currentLabelContoursMap = finding->second;
 
   auto tsfinding = currentLabelContoursMap.find(timeStep);
   if (tsfinding == currentLabelContoursMap.end())
   {
     return;
   }
 
   cpiMap[segmentationImage][labelValue][timeStep].cachedSurface = surface;
 }
 
 void mitk::SurfaceInterpolationController::Interpolate(const LabelSetImage* segmentationImage, LabelSetImage::LabelValueType labelValue, TimeStepType timeStep)
 {
   if (nullptr == segmentationImage)
   {
     mitkThrow() << "Cannot interpolate contours. No valid segmentation passed.";
   }
 
   std::lock_guard<std::shared_mutex> guard(cpiMutex);
   auto it = cpiMap.find(segmentationImage);
   if (it == cpiMap.end())
   {
     mitkThrow() << "Cannot interpolate contours. Passed segmentation is not registered at controller.";
   }
 
   if (!segmentationImage->ExistLabel(labelValue))
   {
-    mitkThrow() << "Cannot interpolate contours. None existant label request. Invalid label:" << labelValue;
+    mitkThrow() << "Cannot interpolate contours. None existent label request. Invalid label:" << labelValue;
   }
 
   if (!segmentationImage->GetTimeGeometry()->IsValidTimeStep(timeStep))
   {
     mitkThrow() << "Cannot interpolate contours. No valid time step requested. Invalid time step:" << timeStep;
   }
 
   if (!CPICacheIsOutdated(segmentationImage, labelValue, timeStep)) return;
 
   mitk::Surface::Pointer interpolationResult = nullptr;
 
   auto reduceFilter = ReduceContourSetFilter::New();
   auto normalsFilter = ComputeContourSetNormalsFilter::New();
   auto interpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New();
 
   const auto spacing = segmentationImage->GetGeometry(timeStep)->GetSpacing();
   double minSpacing = 100;
   double maxSpacing = 0;
   for (int i = 0; i < 3; i++)
   {
     if (spacing[i] < minSpacing)
     {
       minSpacing = spacing[i];
     }
     if (spacing[i] > maxSpacing)
     {
       maxSpacing = spacing[i];
     }
   }
   reduceFilter->SetMinSpacing(minSpacing);
   reduceFilter->SetMaxSpacing(maxSpacing);
   normalsFilter->SetMaxSpacing(maxSpacing);
   interpolateSurfaceFilter->SetDistanceImageVolume(m_DistanceImageVolume);
 
   reduceFilter->SetUseProgressBar(false);
   normalsFilter->SetUseProgressBar(true);
   normalsFilter->SetProgressStepSize(1);
   interpolateSurfaceFilter->SetUseProgressBar(true);
   interpolateSurfaceFilter->SetProgressStepSize(7);
 
   //  Set reference image for interpolation surface filter
   itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New();
   mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
   timeSelector->SetInput(segmentationImage);
   timeSelector->SetTimeNr(timeStep);
   timeSelector->SetChannelNr(0);
   timeSelector->Update();
   mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
   AccessFixedDimensionByItk_1(refSegImage, GetImageBase, 3, itkImage);
   interpolateSurfaceFilter->SetReferenceImage(itkImage.GetPointer());
 
   try
   {
     this->AddActiveLabelContoursForInterpolation(reduceFilter, segmentationImage, labelValue, timeStep);
     reduceFilter->Update();
     auto currentNumberOfReducedContours = reduceFilter->GetNumberOfOutputs();
 
     if (currentNumberOfReducedContours < 2)
     {
       // If no interpolation is possible reset the interpolation result
       MITK_INFO << "Interpolation impossible: not enough contours.";
     }
     else
     {
       normalsFilter->SetSegmentationBinaryImage(refSegImage);
 
       for (size_t i = 0; i < currentNumberOfReducedContours; ++i)
       {
         mitk::Surface::Pointer reducedContour = reduceFilter->GetOutput(i);
         reducedContour->DisconnectPipeline();
         normalsFilter->SetInput(i, reducedContour);
         interpolateSurfaceFilter->SetInput(i, normalsFilter->GetOutput(i));
       }
 
       // Setting up progress bar
       mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
 
       // create a surface from the distance-image
       auto imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
       imageToSurfaceFilter->SetInput(interpolateSurfaceFilter->GetOutput());
       imageToSurfaceFilter->SetThreshold(0);
       imageToSurfaceFilter->SetSmooth(true);
       imageToSurfaceFilter->SetSmoothIteration(1);
       imageToSurfaceFilter->Update();
 
       interpolationResult = mitk::Surface::New();
       interpolationResult->Expand(segmentationImage->GetTimeSteps());
 
       auto geometry = segmentationImage->GetTimeGeometry()->Clone();
       geometry->ReplaceTimeStepGeometries(mitk::Geometry3D::New());
       interpolationResult->SetTimeGeometry(geometry);
 
       interpolationResult->SetVtkPolyData(imageToSurfaceFilter->GetOutput()->GetVtkPolyData(), timeStep);
       interpolationResult->DisconnectPipeline();
 
       // Last progress step
       mitk::ProgressBar::GetInstance()->Progress(20);
 
     }
   }
   catch (const Exception& e)
   {
     MITK_ERROR << "Interpolation failed: " << e.what();
     interpolationResult = nullptr;
   }
 
   SetCPICacheSurface(interpolationResult, segmentationImage, labelValue, timeStep);
 }
 
 mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult(const LabelSetImage* segmentationImage, LabelSetImage::LabelValueType labelValue, TimeStepType timeStep)
 {
   if (nullptr == segmentationImage)
   {
     mitkThrow() << "Cannot interpolate contours. No valid segmentation passed.";
   }
 
   std::shared_lock<std::shared_mutex> guard(cpiMutex);
 
   if (cpiMap.find(segmentationImage) == cpiMap.end())
   {
     mitkThrow() << "Cannot interpolate contours. Passed segmentation is not registered at controller.";
   }
 
   if (!segmentationImage->ExistLabel(labelValue))
   {
-    mitkThrow() << "Cannot interpolate contours. None existant label request. Invalid label:" << labelValue;
+    mitkThrow() << "Cannot interpolate contours. None existent label request. Invalid label:" << labelValue;
   }
 
   if (!segmentationImage->GetTimeGeometry()->IsValidTimeStep(timeStep))
   {
     mitkThrow() << "Cannot interpolate contours. No valid time step requested. Invalid time step:" << timeStep;
   }
 
   const auto& currentImageContours = cpiMap.at(segmentationImage);
 
   auto finding = currentImageContours.find(labelValue);
   if (finding == currentImageContours.end())
   {
     return nullptr;
   }
 
   const auto& currentLabelContoursMap = finding->second;
 
   auto tsfinding = currentLabelContoursMap.find(timeStep);
   if (tsfinding == currentLabelContoursMap.end())
   {
     return nullptr;
   }
 
   return tsfinding->second.cachedSurface;
 }
 
 void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage::Pointer ds)
 {
   m_DataStorage = ds;
 }
 
 void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume)
 {
   m_DistanceImageVolume = distImgVolume;
 }
 
 mitk::LabelSetImage* mitk::SurfaceInterpolationController::GetCurrentSegmentation()
 {
   return m_SelectedSegmentation.Lock();
 }
 
 unsigned int mitk::SurfaceInterpolationController::GetNumberOfInterpolationSessions()
 {
   return cpiMap.size();
 }
 
 template <typename TPixel, unsigned int VImageDimension>
 void mitk::SurfaceInterpolationController::GetImageBase(itk::Image<TPixel, VImageDimension> *input,
                                                         itk::ImageBase<3>::Pointer &result)
 {
   result->Graft(input);
 }
 
 void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::LabelSetImage* currentSegmentationImage)
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
 
   if (currentSegmentationImage == selectedSegmentation)
   {
     return;
   }
 
   m_SelectedSegmentation = currentSegmentationImage;
   selectedSegmentation = m_SelectedSegmentation.Lock();
 
   if (selectedSegmentation.IsNotNull())
   {
     std::lock_guard<std::shared_mutex> guard(cpiMutex);
 
     auto it = cpiMap.find(selectedSegmentation);
     if (it == cpiMap.end())
     {
       cpiMap[selectedSegmentation] = CPITimeStepLabelMap();
 
       auto command = itk::MemberCommand<SurfaceInterpolationController>::New();
       command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted);
       segmentationObserverTags[selectedSegmentation] = selectedSegmentation->AddObserver(itk::DeleteEvent(), command);
       auto& controller = *this;
       const auto sender = selectedSegmentation.GetPointer();
       labelRemovedObserverTags[selectedSegmentation] = selectedSegmentation->AddObserver(mitk::LabelRemovedEvent(), [&controller, sender](const itk::EventObject& event)
         {
           controller.OnRemoveLabel(sender, event);
         });
     }
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveInterpolationSession(const mitk::LabelSetImage* segmentationImage)
 {
   if (nullptr != segmentationImage)
   {
     auto selectedSegmentation = m_SelectedSegmentation.Lock();
     if (selectedSegmentation == segmentationImage)
     {
       this->SetCurrentInterpolationSession(nullptr);
     }
 
     {
       std::lock_guard<std::shared_mutex> guard(cpiMutex);
       this->RemoveObserversInternal(segmentationImage);
       cpiMap.erase(segmentationImage);
       if (m_DataStorage.IsNotNull())
       {
         auto nodes = this->GetPlaneGeometryNodeFromDataStorage(GetSegmentationImageNodeInternal(this->m_DataStorage, segmentationImage));
         this->m_DataStorage->Remove(nodes);
       }
     }
 
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveObserversInternal(const mitk::LabelSetImage* segmentationImage)
 {
   auto pos = segmentationObserverTags.find(const_cast<mitk::LabelSetImage*>(segmentationImage));
   if (pos != segmentationObserverTags.end())
   {
     pos->first->RemoveObserver((*pos).second);
     segmentationObserverTags.erase(const_cast<mitk::LabelSetImage*>(segmentationImage));
   }
 
   auto pos2 = labelRemovedObserverTags.find(const_cast<mitk::LabelSetImage*>(segmentationImage));
   if (pos2 != labelRemovedObserverTags.end())
   {
     pos2->first->RemoveObserver((*pos2).second);
     labelRemovedObserverTags.erase(const_cast<mitk::LabelSetImage*>(segmentationImage));
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveAllInterpolationSessions()
 {
   while (!cpiMap.empty())
   {
     this->RemoveInterpolationSession(cpiMap.begin()->first);
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveContours(const LabelSetImage* segmentationImage,
   mitk::Label::PixelType label,
   TimeStepType timeStep)
 {
   if (nullptr == segmentationImage)
   {
     mitkThrow() << "Cannot remove contours. No valid segmentation passed.";
   }
 
   std::lock_guard<std::shared_mutex> guard(cpiMutex);
 
   auto segfinding = cpiMap.find(segmentationImage);
 
   if (segfinding != cpiMap.end())
   {
     auto& cpiLabelMap = cpiMap[segmentationImage];
     auto finding = cpiLabelMap.find(label);
 
     if (finding != cpiLabelMap.end())
     {
       cpiLabelMap[label].erase(timeStep);
     }
 
     if (m_DataStorage.IsNotNull())
     {
       //remove relevant plane nodes
       auto nodes = this->GetPlaneGeometryNodeFromDataStorage(GetSegmentationImageNodeInternal(this->m_DataStorage, segmentationImage), label, timeStep);
 
       this->m_DataStorage->Remove(nodes);
     }
     this->Modified();
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveContours(const LabelSetImage* segmentationImage,
   mitk::Label::PixelType label)
 {
   if (nullptr == segmentationImage)
   {
     mitkThrow() << "Cannot remove contours. No valid segmentation passed.";
   }
 
   std::lock_guard<std::shared_mutex> guard(cpiMutex);
 
   auto finding = cpiMap.find(segmentationImage);
   if (finding != cpiMap.end())
   {
     cpiMap[segmentationImage].erase(label);
 
     if (m_DataStorage.IsNotNull())
     {
       //remove relevant plane nodes
       auto nodes = this->GetPlaneGeometryNodeFromDataStorage(GetSegmentationImageNodeInternal(this->m_DataStorage, segmentationImage), label);
       this->m_DataStorage->Remove(nodes);
     }
     this->Modified();
   }
 }
 
 
 void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller,
                                                                  const itk::EventObject & /*event*/)
 {
   auto tempImage = dynamic_cast<mitk::LabelSetImage *>(const_cast<itk::Object *>(caller));
   if (tempImage)
   {
     this->RemoveInterpolationSession(tempImage);
   }
 }
 
 void mitk::SurfaceInterpolationController::OnRemoveLabel(const itk::Object* caller, const itk::EventObject& event)
 {
   auto sendingSegmentation = dynamic_cast<const LabelSetImage*>(caller);
 
   auto removeEvent = dynamic_cast<const mitk::LabelRemovedEvent*>(&event);
 
   if (nullptr != sendingSegmentation && nullptr != removeEvent)
   {
     this->RemoveContours(sendingSegmentation, removeEvent->GetLabelValue());
   }
 }
 
 mitk::SurfaceInterpolationController::CPIVector* mitk::SurfaceInterpolationController::GetContours(LabelSetImage::LabelValueType labelValue, TimeStepType timeStep)
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
 
   if (selectedSegmentation == nullptr)
     return nullptr;
 
   std::shared_lock<std::shared_mutex> guard(cpiMutex);
 
   auto labelFinding = cpiMap[selectedSegmentation].find(labelValue);
 
   if (labelFinding != cpiMap[selectedSegmentation].end())
   {
     auto tsFinding = labelFinding->second.find(timeStep);
 
     if (tsFinding != labelFinding->second.end())
     {
       return &(tsFinding->second.cpis);
     }
   }
 
   return nullptr;
 }
 
 std::vector<mitk::LabelSetImage::LabelValueType> mitk::SurfaceInterpolationController::GetAffectedLabels(const LabelSetImage* seg, TimeStepType timeStep, const PlaneGeometry* plane) const
 {
   std::lock_guard<std::shared_mutex> guard(cpiMutex);
 
   std::vector<mitk::LabelSetImage::LabelValueType> result;
 
   auto finding = cpiMap.find(seg);
   if (finding == cpiMap.end()) return result;
   const auto& currentImageContours = cpiMap[seg];
 
   for (const auto& [label, contours] : currentImageContours)
   {
     auto tsFinding = contours.find(timeStep);
     if (tsFinding != contours.end())
     {
       const auto& cpis = contours.at(timeStep).cpis;
       auto finding = std::find_if(cpis.begin(), cpis.end(), [plane](const ContourPositionInformation& element) {return plane->IsOnPlane(element.Plane); });
 
       if (finding != cpis.end())
       {
         result.push_back(label);
       }
     }
   }
   return result;
 }
 
 
 void mitk::SurfaceInterpolationController::CompleteReinitialization(const std::vector<ContourPositionInformation>& newCPIs)
 {
   this->ClearInterpolationSession();
 
   //  Now the layers should be empty and the new layers can be added.
   this->AddNewContours(newCPIs, true);
 }
 
 void mitk::SurfaceInterpolationController::ClearInterpolationSession()
 {
   auto selectedSegmentation = m_SelectedSegmentation.Lock();
 
   if (selectedSegmentation != nullptr)
   {
     std::lock_guard<std::shared_mutex> guard(cpiMutex);
     cpiMap[selectedSegmentation].clear();
   }
 }