diff --git a/Modules/Core/include/mitkTemporoSpatialStringProperty.h b/Modules/Core/include/mitkTemporoSpatialStringProperty.h
index 8f6f090f93..015a14320d 100644
--- a/Modules/Core/include/mitkTemporoSpatialStringProperty.h
+++ b/Modules/Core/include/mitkTemporoSpatialStringProperty.h
@@ -1,139 +1,148 @@
 /*============================================================================
 
 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 mitkTemporoSpatialStringProperty_h
 #define mitkTemporoSpatialStringProperty_h
 
 #include <itkConfigure.h>
 
 #include "mitkBaseProperty.h"
 #include <MitkCoreExports.h>
 
 #include "mitkTimeGeometry.h"
 
 #include <string>
 
 namespace mitk
 {
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable : 4522)
 #endif
 
   /**
    * @brief Property for time and space resolved string values
    * @ingroup DataManagement
    */
   class MITKCORE_EXPORT TemporoSpatialStringProperty : public BaseProperty
   {
   public:
     typedef ::itk::IndexValueType IndexValueType;
     typedef std::string ValueType;
 
     mitkClassMacro(TemporoSpatialStringProperty, BaseProperty);
 
     itkFactorylessNewMacro(Self);
 
     itkCloneMacro(Self);
     mitkNewMacro1Param(TemporoSpatialStringProperty, const char*);
     mitkNewMacro1Param(TemporoSpatialStringProperty, const std::string &);
 
     /**Returns the value of the first time point in the first slice.
      * If now value is set it returns an empty string.*/
     ValueType GetValue() const;
     /**Returns the value of the passed time step and slice. If it does not exist and allowedClosed is true
      * it will look for the closest value. If nothing could be found an empty string will be returned.*/
     ValueType GetValue(const TimeStepType &timeStep,
                        const IndexValueType &zSlice,
                        bool allowCloseTime = false,
                        bool allowCloseSlice = false) const;
     ValueType GetValueBySlice(const IndexValueType &zSlice, bool allowClose = false) const;
     ValueType GetValueByTimeStep(const TimeStepType &timeStep, bool allowClose = false) const;
 
     bool HasValue() const;
     bool HasValue(const TimeStepType &timeStep,
                   const IndexValueType &zSlice,
                   bool allowCloseTime = false,
                   bool allowCloseSlice = false) const;
     bool HasValueBySlice(const IndexValueType &zSlice, bool allowClose = false) const;
     bool HasValueByTimeStep(const TimeStepType &timeStep, bool allowClose = false) const;
 
     /** return all slices stored for the specified timestep.*/
     std::vector<IndexValueType> GetAvailableSlices(const TimeStepType& timeStep) const;
     /** return all time steps stored for the specified slice.*/
     std::vector<TimeStepType> GetAvailableTimeSteps(const IndexValueType& slice) const;
     /** return all time steps stored in the property.*/
     std::vector<TimeStepType> GetAvailableTimeSteps() const;
     /** return all slices stored in the property. @remark not all time steps may contain all slices.*/
     std::vector<IndexValueType> GetAvailableSlices() const;
 
     void SetValue(const TimeStepType &timeStep, const IndexValueType &zSlice, const ValueType &value);
 
     void SetValue(const ValueType &value);
 
     std::string GetValueAsString() const override;
 
     /** Indicates of all values (all time steps, all slices) are the same, or if at least one value stored
     in the property is different. If IsUniform==true one can i.a. use GetValueAsString() without the loss of
     information to retrieve the stored value.*/
     bool IsUniform() const;
 
     bool ToJSON(nlohmann::json& j) const override;
     bool FromJSON(const nlohmann::json& j) override;
 
     using BaseProperty::operator=;
 
   protected:
     typedef std::map<IndexValueType, std::string> SliceMapType;
     typedef std::map<TimeStepType, SliceMapType> TimeMapType;
 
     TimeMapType m_Values;
 
     TemporoSpatialStringProperty(const char *string = nullptr);
     TemporoSpatialStringProperty(const std::string &s);
 
     TemporoSpatialStringProperty(const TemporoSpatialStringProperty &);
 
     std::pair<bool, ValueType> CheckValue(const TimeStepType &timeStep,
                                           const IndexValueType &zSlice,
                                           bool allowCloseTime = false,
                                           bool allowCloseSlice = false) const;
 
   private:
     // purposely not implemented
     TemporoSpatialStringProperty &operator=(const TemporoSpatialStringProperty &);
 
     itk::LightObject::Pointer InternalClone() const override;
 
     bool IsEqual(const BaseProperty &property) const override;
     bool Assign(const BaseProperty &property) override;
   };
 
   namespace PropertyPersistenceSerialization
   {
     /** Serialization of a TemporoSpatialStringProperty into a JSON string.*/
     MITKCORE_EXPORT std::string serializeTemporoSpatialStringPropertyToJSON(const mitk::BaseProperty *prop);
   }
 
   namespace PropertyPersistenceDeserialization
   {
     /**Deserialize a passed JSON string into a TemporoSpatialStringProperty.*/
     MITKCORE_EXPORT mitk::BaseProperty::Pointer deserializeJSONToTemporoSpatialStringProperty(const std::string &value);
   }
 
+  /** Helper function that extracts the information of a time step out of a TemporoSpatialStringProperty
+  * and returns a TemporoSpatialStringProperty that only contains that time step.
+  * @param tsProperty The source property from which the values should be extracted.
+  * @param ts The time point that should be extracted.
+  * @pre tsProperty must point to a valid instance.
+  * @pre ts must indicate a time step that exists in tsProperty.
+  * @result Returns a TemporoSpatialStringProperty instance that only contains the values of the indicated time step. In the result the time step is always time step 0.*/
+  TemporoSpatialStringProperty::Pointer MITKCORE_EXPORT ExtractTimeStepFromTemporoSpatialStringProperty(const TemporoSpatialStringProperty* tsProperty, TimeStepType ts);
+
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
 } // namespace mitk
 
 #endif
diff --git a/Modules/Core/src/DataManagement/mitkTemporoSpatialStringProperty.cpp b/Modules/Core/src/DataManagement/mitkTemporoSpatialStringProperty.cpp
index ac53fc9dd6..1c4876cd48 100644
--- a/Modules/Core/src/DataManagement/mitkTemporoSpatialStringProperty.cpp
+++ b/Modules/Core/src/DataManagement/mitkTemporoSpatialStringProperty.cpp
@@ -1,425 +1,444 @@
 /*============================================================================
 
 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 <iterator>
 #include <set>
 #include <type_traits>
 
 #include "mitkTemporoSpatialStringProperty.h"
 
 #include <nlohmann/json.hpp>
 
 using CondensedTimeKeyType = std::pair<mitk::TimeStepType, mitk::TimeStepType>;
 using CondensedTimePointsType = std::map<CondensedTimeKeyType, std::string>;
 
 using CondensedSliceKeyType = std::pair<mitk::TemporoSpatialStringProperty::IndexValueType, mitk::TemporoSpatialStringProperty::IndexValueType>;
 using CondensedSlicesType = std::map<CondensedSliceKeyType, CondensedTimePointsType>;
 
 namespace
 {
   /** Helper function that checks if between an ID and a successive ID is no gap.*/
   template<typename TValue>
   bool isGap(const TValue& value, const TValue& successor)
   {
     return value<successor || value > successor + 1;
   }
 
 
   template<typename TNewKey, typename TNewValue, typename TMasterKey, typename TMasterValue, typename TCondensedContainer>
   void CheckAndCondenseElement(const TNewKey& newKeyMinID, const TNewValue& newValue, TMasterKey& masterKey, TMasterValue& masterValue, TCondensedContainer& condensedContainer)
   {
     if (newValue != masterValue
       || isGap(newKeyMinID, masterKey.second))
     {
       condensedContainer[masterKey] = masterValue;
       masterValue = newValue;
       masterKey.first = newKeyMinID;
     }
     masterKey.second = newKeyMinID;
   }
 
   /** Helper function that tries to condense the values of time points for a slice as much as possible and returns all slices with condensed timepoint values.*/
   CondensedSlicesType CondenseTimePointValuesOfProperty(const mitk::TemporoSpatialStringProperty* tsProp)
   {
     CondensedSlicesType uncondensedSlices;
 
     auto zs = tsProp->GetAvailableSlices();
     for (const auto z : zs)
     {
       CondensedTimePointsType condensedTimePoints;
       auto timePointIDs = tsProp->GetAvailableTimeSteps(z);
       CondensedTimeKeyType condensedKey = { timePointIDs.front(),timePointIDs.front() };
       auto refValue = tsProp->GetValue(timePointIDs.front(), z);
 
       for (const auto timePointID : timePointIDs)
       {
         const auto& newVal = tsProp->GetValue(timePointID, z);
         CheckAndCondenseElement(timePointID, newVal, condensedKey, refValue, condensedTimePoints);
       }
       condensedTimePoints[condensedKey] = refValue;
       uncondensedSlices[{ z, z }] = condensedTimePoints;
     }
     return uncondensedSlices;
   }
 }
 
 mitk::TemporoSpatialStringProperty::TemporoSpatialStringProperty(const char *s)
 {
   if (s)
   {
     SliceMapType slices{{0, s}};
 
     m_Values.insert(std::make_pair(0, slices));
   }
 }
 
 mitk::TemporoSpatialStringProperty::TemporoSpatialStringProperty(const std::string &s)
 {
   SliceMapType slices{{0, s}};
 
   m_Values.insert(std::make_pair(0, slices));
 }
 
 mitk::TemporoSpatialStringProperty::TemporoSpatialStringProperty(const TemporoSpatialStringProperty &other)
   : BaseProperty(other), m_Values(other.m_Values)
 {
 }
 
 bool mitk::TemporoSpatialStringProperty::IsEqual(const BaseProperty &property) const
 {
   return this->m_Values == static_cast<const Self &>(property).m_Values;
 }
 
 bool mitk::TemporoSpatialStringProperty::Assign(const BaseProperty &property)
 {
   this->m_Values = static_cast<const Self &>(property).m_Values;
   return true;
 }
 
 std::string mitk::TemporoSpatialStringProperty::GetValueAsString() const
 {
   return GetValue();
 }
 
 bool mitk::TemporoSpatialStringProperty::IsUniform() const
 {
   auto refValue = this->GetValue();
 
   for (const auto& timeStep : m_Values)
   {
     auto finding = std::find_if_not(timeStep.second.begin(), timeStep.second.end(), [&refValue](const mitk::TemporoSpatialStringProperty::SliceMapType::value_type& val) { return val.second == refValue; });
     if (finding != timeStep.second.end())
     {
       return false;
     }
   }
 
   return true;
 }
 
 itk::LightObject::Pointer mitk::TemporoSpatialStringProperty::InternalClone() const
 {
   itk::LightObject::Pointer result(new Self(*this));
   result->UnRegister();
   return result;
 }
 
 mitk::TemporoSpatialStringProperty::ValueType mitk::TemporoSpatialStringProperty::GetValue() const
 {
   std::string result = "";
 
   if (!m_Values.empty())
   {
     if (!m_Values.begin()->second.empty())
     {
       result = m_Values.begin()->second.begin()->second;
     }
   }
   return result;
 };
 
 std::pair<bool, mitk::TemporoSpatialStringProperty::ValueType> mitk::TemporoSpatialStringProperty::CheckValue(
   const TimeStepType &timeStep, const IndexValueType &zSlice, bool allowCloseTime, bool allowCloseSlice) const
 {
   std::string value = "";
   bool found = false;
 
   auto timeIter = m_Values.find(timeStep);
   auto timeEnd = m_Values.end();
   if (timeIter == timeEnd && allowCloseTime)
   { // search for closest time step (earlier preverd)
     timeIter = m_Values.upper_bound(timeStep);
     if (timeIter != m_Values.begin())
     { // there is a key lower than time step
       timeIter = std::prev(timeIter);
     }
   }
 
   if (timeIter != timeEnd)
   {
     const SliceMapType &slices = timeIter->second;
 
     auto sliceIter = slices.find(zSlice);
     auto sliceEnd = slices.end();
     if (sliceIter == sliceEnd && allowCloseSlice)
     { // search for closest slice (earlier preverd)
       sliceIter = slices.upper_bound(zSlice);
       if (sliceIter != slices.begin())
       { // there is a key lower than slice
         sliceIter = std::prev(sliceIter);
       }
     }
 
     if (sliceIter != sliceEnd)
     {
       value = sliceIter->second;
       found = true;
     }
   }
 
   return std::make_pair(found, value);
 };
 
 mitk::TemporoSpatialStringProperty::ValueType mitk::TemporoSpatialStringProperty::GetValue(const TimeStepType &timeStep,
                                                                                            const IndexValueType &zSlice,
                                                                                            bool allowCloseTime,
                                                                                            bool allowCloseSlice) const
 {
   return CheckValue(timeStep, zSlice, allowCloseTime, allowCloseSlice).second;
 };
 
 mitk::TemporoSpatialStringProperty::ValueType mitk::TemporoSpatialStringProperty::GetValueBySlice(
   const IndexValueType &zSlice, bool allowClose) const
 {
   return GetValue(0, zSlice, true, allowClose);
 };
 
 mitk::TemporoSpatialStringProperty::ValueType mitk::TemporoSpatialStringProperty::GetValueByTimeStep(
   const TimeStepType &timeStep, bool allowClose) const
 {
   return GetValue(timeStep, 0, allowClose, true);
 };
 
 bool mitk::TemporoSpatialStringProperty::HasValue() const
 {
   return !m_Values.empty();
 };
 
 bool mitk::TemporoSpatialStringProperty::HasValue(const TimeStepType &timeStep,
                                                   const IndexValueType &zSlice,
                                                   bool allowCloseTime,
                                                   bool allowCloseSlice) const
 {
   return CheckValue(timeStep, zSlice, allowCloseTime, allowCloseSlice).first;
 };
 
 bool mitk::TemporoSpatialStringProperty::HasValueBySlice(const IndexValueType &zSlice, bool allowClose) const
 {
   return HasValue(0, zSlice, true, allowClose);
 };
 
 bool mitk::TemporoSpatialStringProperty::HasValueByTimeStep(const TimeStepType &timeStep, bool allowClose) const
 {
   return HasValue(timeStep, 0, allowClose, true);
 };
 
 std::vector<mitk::TemporoSpatialStringProperty::IndexValueType> mitk::TemporoSpatialStringProperty::GetAvailableSlices() const
 {
   std::set<IndexValueType> uniqueSlices;
 
   for (const auto& timeStep : m_Values)
   {
     for (const auto& slice : timeStep.second)
     {
       uniqueSlices.insert(slice.first);
     }
   }
 
   return std::vector<IndexValueType>(std::begin(uniqueSlices), std::end(uniqueSlices));
 }
 
 std::vector<mitk::TemporoSpatialStringProperty::IndexValueType> mitk::TemporoSpatialStringProperty::GetAvailableSlices(
   const TimeStepType &timeStep) const
 {
   std::vector<IndexValueType> result;
 
   auto timeIter = m_Values.find(timeStep);
   auto timeEnd = m_Values.end();
 
   if (timeIter != timeEnd)
   {
     for (auto const &element : timeIter->second)
     {
       result.push_back(element.first);
     }
   }
 
   return result;
 };
 
 std::vector<mitk::TimeStepType> mitk::TemporoSpatialStringProperty::GetAvailableTimeSteps() const
 {
   std::vector<mitk::TimeStepType> result;
 
   for (auto const &element : m_Values)
   {
     result.push_back(element.first);
   }
 
   return result;
 };
 
 std::vector<mitk::TimeStepType> mitk::TemporoSpatialStringProperty::GetAvailableTimeSteps(const IndexValueType& slice) const
 {
   std::vector<mitk::TimeStepType> result;
 
   for (const auto& timeStep : m_Values)
   {
     if (timeStep.second.find(slice) != std::end(timeStep.second))
     {
       result.push_back(timeStep.first);
     }
   }
   return result;
 }
 
 
 void mitk::TemporoSpatialStringProperty::SetValue(const TimeStepType &timeStep,
                                                   const IndexValueType &zSlice,
                                                   const ValueType &value)
 {
   auto timeIter = m_Values.find(timeStep);
   auto timeEnd = m_Values.end();
 
   if (timeIter == timeEnd)
   {
     SliceMapType slices{{zSlice, value}};
     m_Values.insert(std::make_pair(timeStep, slices));
   }
   else
   {
     timeIter->second[zSlice] = value;
   }
   this->Modified();
 };
 
 void mitk::TemporoSpatialStringProperty::SetValue(const ValueType &value)
 {
   m_Values.clear();
   this->SetValue(0, 0, value);
 };
 
 bool mitk::TemporoSpatialStringProperty::ToJSON(nlohmann::json& j) const
 {
   // We condense the content of the property to have a compact serialization.
   // We start with condensing time points and then slices (in difference to the
   // internal layout). Reason: There is more entropy in slices (looking at DICOM)
   // than across time points for one slice, so we can "compress" at a higher rate.
   // We didn't want to change the internal structure of the property as it would
   // introduce API inconvenience and subtle changes in behavior.
   auto uncondensedSlices = CondenseTimePointValuesOfProperty(this);
   CondensedSlicesType condensedSlices;
 
   if(!uncondensedSlices.empty())
   {
     auto& masterSlice = uncondensedSlices.begin()->second;
     auto masterSliceKey = uncondensedSlices.begin()->first;
 
     for (const auto& uncondensedSlice : uncondensedSlices)
     {
       const auto& uncondensedSliceID = uncondensedSlice.first.first;
       CheckAndCondenseElement(uncondensedSliceID, uncondensedSlice.second, masterSliceKey, masterSlice, condensedSlices);
     }
 
     condensedSlices[masterSliceKey] = masterSlice;
   }
 
   auto values = nlohmann::json::array();
 
   for (const auto& z : condensedSlices)
   {
     for (const auto& t : z.second)
     {
       const auto& minSliceID = z.first.first;
       const auto& maxSliceID = z.first.second;
       const auto& minTimePointID = t.first.first;
       const auto& maxTimePointID = t.first.second;
 
       auto value = nlohmann::json::object();
       value["z"] = minSliceID;
 
       if (minSliceID != maxSliceID)
         value["zmax"] = maxSliceID;
 
       value["t"] = minTimePointID;
 
       if (minTimePointID != maxTimePointID)
         value["tmax"] = maxTimePointID;
 
       value["value"] = t.second;
 
       values.push_back(value);
     }
   }
 
   j = nlohmann::json{{"values", values}};
 
   return true;
 }
 
 bool mitk::TemporoSpatialStringProperty::FromJSON(const nlohmann::json& j)
 {
   for (const auto& element : j["values"])
   {
     auto value = element.value("value", "");
     auto z = element.value<TemporoSpatialStringProperty::IndexValueType>("z", 0);
     auto zmax = element.value<TemporoSpatialStringProperty::IndexValueType>("zmax", z);
     auto t = element.value<TimeStepType>("t", 0);
     auto tmax = element.value<TimeStepType>("tmax", t);
 
     for (auto currentT = t; currentT <= tmax; ++currentT)
     {
       for (auto currentZ = z; currentZ <= zmax; ++currentZ)
       {
         this->SetValue(currentT, currentZ, value);
       }
     }
   }
 
   return true;
 }
 
 std::string mitk::PropertyPersistenceSerialization::serializeTemporoSpatialStringPropertyToJSON(const mitk::BaseProperty *prop)
 {
   const auto *tsProp = dynamic_cast<const mitk::TemporoSpatialStringProperty *>(prop);
 
   if (!tsProp)
     mitkThrow() << "Cannot serialize properties of types other than TemporoSpatialStringProperty.";
 
   nlohmann::json j;
   tsProp->ToJSON(j);
 
   return j.dump();
 }
 
 mitk::BaseProperty::Pointer mitk::PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(const std::string &value)
 {
   if (value.empty())
     return nullptr;
 
   auto prop = mitk::TemporoSpatialStringProperty::New();
 
   auto root = nlohmann::json::parse(value);
   prop->FromJSON(root);
 
   return prop.GetPointer();
 }
+
+mitk::TemporoSpatialStringProperty::Pointer mitk::ExtractTimeStepFromTemporoSpatialStringProperty(const TemporoSpatialStringProperty* tsProperty, TimeStepType ts)
+{
+  if (nullptr == tsProperty)
+    mitkThrow() << "Cannot Extract time step. Passed TemporoSpatialStringProperty pointer is invalid.";
+
+  if (!tsProperty->HasValueByTimeStep(ts))
+    mitkThrow() << "Cannot Extract time step. TemporoSpatialStringProperty does not contain values for that passed time step. Invalid time step: " << ts;
+
+  auto slices = tsProperty->GetAvailableSlices(ts);
+
+  auto result = mitk::TemporoSpatialStringProperty::New();
+
+  for (const auto& slice : slices)
+  {
+    result->SetValue(0, slice, tsProperty->GetValue(ts, slice));
+  }
+  return result;
+}
diff --git a/Modules/Core/test/mitkTemporoSpatialStringPropertyTest.cpp b/Modules/Core/test/mitkTemporoSpatialStringPropertyTest.cpp
index 48db4613df..29c758999d 100644
--- a/Modules/Core/test/mitkTemporoSpatialStringPropertyTest.cpp
+++ b/Modules/Core/test/mitkTemporoSpatialStringPropertyTest.cpp
@@ -1,245 +1,273 @@
 /*============================================================================
 
 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 "mitkTemporoSpatialStringProperty.h"
 #include "mitkTestFixture.h"
 #include "mitkTestingMacros.h"
 
 #include <limits>
 
 class mitkTemporoSpatialStringPropertyTestSuite : public mitk::TestFixture
 {
   CPPUNIT_TEST_SUITE(mitkTemporoSpatialStringPropertyTestSuite);
 
   MITK_TEST(GetValue);
   MITK_TEST(HasValue);
   MITK_TEST(SetValue);
   MITK_TEST(IsUniform);
 
   MITK_TEST(serializeTemporoSpatialStringPropertyToJSON);
   MITK_TEST(deserializeJSONToTemporoSpatialStringProperty);
 
+  MITK_TEST(ExtractTimeStepFromTemporoSpatialStringProperty);
+
   CPPUNIT_TEST_SUITE_END();
 
 private:
   std::string refJSON;
   std::string refJSON_legacy;
   std::string refPartlyCondensibleJSON;
   std::string refCondensibleJSON;
   mitk::TemporoSpatialStringProperty::Pointer refProp;
   mitk::TemporoSpatialStringProperty::Pointer refPartlyCondensibleProp;
   mitk::TemporoSpatialStringProperty::Pointer refCondensibleProp;
 
 public:
   void setUp() override
   {
     refJSON_legacy = "{\"values\":[{\"t\":0, \"z\":0, \"value\":\"v_0_0\"}, {\"t\":3, \"z\":0, \"value\":\"v_3_0\"}, "
                      "{\"t\":3, \"z\":2, \"value\":\"v_3_2\"}, {\"t\":6, \"z\":1, \"value\":\"v_6_1\"}]}";
     refJSON = "{\"values\":[{\"z\":0, \"t\":0, \"value\":\"v_0_0\"}, {\"z\":0, \"t\":3, \"value\":\"v_3_0\"}, {\"z\":1, \"t\":6, \"value\":\"v_6_1\"}, {\"z\":2, \"t\":3, \"value\":\"v_3_2\"}]}";
     refPartlyCondensibleJSON = "{\"values\":[{\"z\":0, \"t\":0, \"value\":\"0\"}, {\"z\":1, \"t\":0, \"tmax\":1, \"value\":\"0\"}, {\"z\":1, \"t\":3, \"tmax\":5, \"value\":\"0\"}, {\"z\":1, \"t\":6, \"value\":\"otherValue\"}, {\"z\":2, \"t\":6, \"value\":\"0\"}]}";
     refCondensibleJSON = "{\"values\":[{\"z\":0, \"zmax\":2, \"t\":0, \"tmax\":1, \"value\":\"1\"}]}";
     refProp = mitk::TemporoSpatialStringProperty::New();
     refProp->SetValue(0, 0, "v_0_0");
     refProp->SetValue(3, 0, "v_3_0");
     refProp->SetValue(3, 2, "v_3_2");
     refProp->SetValue(6, 1, "v_6_1");
 
     refPartlyCondensibleProp = mitk::TemporoSpatialStringProperty::New();
     refPartlyCondensibleProp->SetValue(0, 0, "0");
     refPartlyCondensibleProp->SetValue(0, 1, "0");
     refPartlyCondensibleProp->SetValue(1, 1, "0");
     refPartlyCondensibleProp->SetValue(3, 1, "0");
     refPartlyCondensibleProp->SetValue(4, 1, "0");
     refPartlyCondensibleProp->SetValue(5, 1, "0");
     refPartlyCondensibleProp->SetValue(6, 1, "otherValue");
     refPartlyCondensibleProp->SetValue(6, 2, "0");
 
     refCondensibleProp = mitk::TemporoSpatialStringProperty::New();
     refCondensibleProp->SetValue(0, 0, "1");
     refCondensibleProp->SetValue(1, 0, "1");
     refCondensibleProp->SetValue(0, 1, "1");
     refCondensibleProp->SetValue(1, 1, "1");
     refCondensibleProp->SetValue(0, 2, "1");
     refCondensibleProp->SetValue(1, 2, "1");
   }
 
   void tearDown() override {}
 
   void GetValue()
   {
     CPPUNIT_ASSERT(refProp->GetValue() == "v_0_0");
 
     CPPUNIT_ASSERT(refProp->GetValue(3, 0) == "v_3_0");
     CPPUNIT_ASSERT(refProp->GetValue(3, 2) == "v_3_2");
     CPPUNIT_ASSERT(refProp->GetValue(3, 1, false, true) == "v_3_0");
     CPPUNIT_ASSERT(refProp->GetValue(3, 5, false, true) == "v_3_2");
 
     CPPUNIT_ASSERT(refProp->GetValueBySlice(0) == "v_0_0");
     CPPUNIT_ASSERT(refProp->GetValueBySlice(4, true) == "v_0_0");
 
     CPPUNIT_ASSERT(refProp->GetValueByTimeStep(3) == "v_3_0");
     CPPUNIT_ASSERT(refProp->GetValueByTimeStep(6) == "v_6_1");
     CPPUNIT_ASSERT(refProp->GetValueByTimeStep(5, true) == "v_3_0");
 
     CPPUNIT_ASSERT(refProp->GetValueAsString() == "v_0_0");
 
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps().size() == 3);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps()[0] == 0);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps()[1] == 3);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps()[2] == 6);
 
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(0).size() == 2);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(0)[0] == 0);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(0)[1] == 3);
 
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(1).size() == 1);
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(1)[0] == 6);
 
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps(5).size() == 0);
 
     CPPUNIT_ASSERT(refProp->GetAvailableSlices().size() == 3);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices()[0] == 0);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices()[1] == 1);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices()[2] == 2);
 
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(0).size() == 1);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(0)[0] == 0);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(3).size() == 2);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(3)[0] == 0);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(3)[1] == 2);
 
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(2).size() == 0);
   }
 
   void HasValue()
   {
     CPPUNIT_ASSERT(refProp->HasValue());
 
     CPPUNIT_ASSERT(refProp->HasValue(3, 0));
     CPPUNIT_ASSERT(refProp->HasValue(3, 2));
     CPPUNIT_ASSERT(refProp->HasValue(3, 1, false, true));
     CPPUNIT_ASSERT(refProp->HasValue(3, 5, false, true));
     CPPUNIT_ASSERT(!refProp->HasValue(3, 1));
     CPPUNIT_ASSERT(!refProp->HasValue(3, 5));
     CPPUNIT_ASSERT(refProp->HasValue(4, 2, true, true));
     CPPUNIT_ASSERT(refProp->HasValue(4, 2, true, false));
     CPPUNIT_ASSERT(!refProp->HasValue(4, 2, false, true));
 
     CPPUNIT_ASSERT(refProp->HasValueBySlice(0));
     CPPUNIT_ASSERT(refProp->HasValueBySlice(4, true));
     CPPUNIT_ASSERT(!refProp->HasValueBySlice(4));
 
     CPPUNIT_ASSERT(refProp->HasValueByTimeStep(3));
     CPPUNIT_ASSERT(refProp->HasValueByTimeStep(6));
     CPPUNIT_ASSERT(refProp->HasValueByTimeStep(5, true));
     CPPUNIT_ASSERT(!refProp->HasValueByTimeStep(5));
   }
 
   void SetValue()
   {
     CPPUNIT_ASSERT_NO_THROW(refProp->SetValue(8, 9, "v_8_9"));
     CPPUNIT_ASSERT(refProp->GetValue(8, 9) == "v_8_9");
 
     CPPUNIT_ASSERT_NO_THROW(refProp->SetValue("newValue"));
     CPPUNIT_ASSERT(refProp->GetValue(0, 0) == "newValue");
     CPPUNIT_ASSERT(refProp->GetAvailableTimeSteps().size() == 1);
     CPPUNIT_ASSERT(refProp->GetAvailableSlices(0).size() == 1);
   }
 
   void IsUniform()
   {
     CPPUNIT_ASSERT(!refProp->IsUniform());
     CPPUNIT_ASSERT(!refPartlyCondensibleProp->IsUniform());
     CPPUNIT_ASSERT(refCondensibleProp->IsUniform());
   }
 
   void serializeTemporoSpatialStringPropertyToJSON()
   {
     auto data = nlohmann::json::parse(mitk::PropertyPersistenceSerialization::serializeTemporoSpatialStringPropertyToJSON(refProp));
     auto ref = nlohmann::json::parse(refJSON);
 
     CPPUNIT_ASSERT(ref == data); //"Testing serializeTemporoSpatialStringPropertyToJSON() producing correct string.");
 
     data = nlohmann::json::parse(mitk::PropertyPersistenceSerialization::serializeTemporoSpatialStringPropertyToJSON(refPartlyCondensibleProp));
     ref = nlohmann::json::parse(refPartlyCondensibleJSON);
 
     CPPUNIT_ASSERT(ref == data);
 
     data = nlohmann::json::parse(mitk::PropertyPersistenceSerialization::serializeTemporoSpatialStringPropertyToJSON(refCondensibleProp));
     ref = nlohmann::json::parse(refCondensibleJSON);
 
     CPPUNIT_ASSERT(ref == data);
   }
 
   void deserializeJSONToTemporoSpatialStringProperty()
   {
     mitk::BaseProperty::Pointer prop =
       mitk::PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(refJSON);
 
     auto *tsProp = dynamic_cast<mitk::TemporoSpatialStringProperty *>(prop.GetPointer());
 
     CPPUNIT_ASSERT(
       tsProp->GetValue(0, 0) ==
       "v_0_0"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 1");
     CPPUNIT_ASSERT(
       tsProp->GetValue(3, 0) ==
       "v_3_0"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 2");
     CPPUNIT_ASSERT(
       tsProp->GetValue(3, 2) ==
       "v_3_2"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 3");
     CPPUNIT_ASSERT(
       tsProp->GetValue(6, 1) ==
       "v_6_1"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 4");
     CPPUNIT_ASSERT(*tsProp == *refProp); //"Testing deserializeJSONToTemporoSpatialStringProperty()");
 
     prop = mitk::PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(refJSON_legacy);
     tsProp = dynamic_cast<mitk::TemporoSpatialStringProperty*>(prop.GetPointer());
     CPPUNIT_ASSERT(
       tsProp->GetValue(0, 0) ==
       "v_0_0"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 1");
     CPPUNIT_ASSERT(
       tsProp->GetValue(3, 0) ==
       "v_3_0"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 2");
     CPPUNIT_ASSERT(
       tsProp->GetValue(3, 2) ==
       "v_3_2"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 3");
     CPPUNIT_ASSERT(
       tsProp->GetValue(6, 1) ==
       "v_6_1"); //"Testing deserializeJSONToTemporoSpatialStringProperty() producing property with correct value 4");
     CPPUNIT_ASSERT(*tsProp == *refProp); //"Testing deserializeJSONToTemporoSpatialStringProperty()");
 
 
     prop = mitk::PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(refPartlyCondensibleJSON);
     tsProp = dynamic_cast<mitk::TemporoSpatialStringProperty*>(prop.GetPointer());
     CPPUNIT_ASSERT(tsProp->GetValue(0, 0) =="0");
     CPPUNIT_ASSERT(tsProp->GetValue(0, 1) == "0");
     CPPUNIT_ASSERT(tsProp->GetValue(1, 1) == "0");
     CPPUNIT_ASSERT(tsProp->GetValue(3, 1) == "0");
     CPPUNIT_ASSERT(tsProp->GetValue(4, 1) == "0");
     CPPUNIT_ASSERT(tsProp->GetValue(5, 1) == "0");
     CPPUNIT_ASSERT(tsProp->GetValue(6, 1) == "otherValue");
     CPPUNIT_ASSERT(tsProp->GetValue(6, 2) == "0");
     CPPUNIT_ASSERT(*tsProp == *refPartlyCondensibleProp);
     
     prop = mitk::PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(refCondensibleJSON);
     tsProp = dynamic_cast<mitk::TemporoSpatialStringProperty*>(prop.GetPointer());
     CPPUNIT_ASSERT(tsProp->GetValue(0, 0) == "1");
     CPPUNIT_ASSERT(tsProp->GetValue(1, 0) == "1");
     CPPUNIT_ASSERT(tsProp->GetValue(0, 1) == "1");
     CPPUNIT_ASSERT(tsProp->GetValue(1, 1) == "1");
     CPPUNIT_ASSERT(tsProp->GetValue(0, 2) == "1");
     CPPUNIT_ASSERT(tsProp->GetValue(1, 2) == "1");
     CPPUNIT_ASSERT(*tsProp == *refCondensibleProp);
   }
+
+  void ExtractTimeStepFromTemporoSpatialStringProperty()
+  {
+    CPPUNIT_ASSERT_THROW(mitk::ExtractTimeStepFromTemporoSpatialStringProperty(nullptr, 0), mitk::Exception);
+    CPPUNIT_ASSERT_THROW_MESSAGE("Test for accessing invalid time step failed.", mitk::ExtractTimeStepFromTemporoSpatialStringProperty(refProp, 4), mitk::Exception);
+
+    auto result = mitk::ExtractTimeStepFromTemporoSpatialStringProperty(refProp, 0);
+
+    CPPUNIT_ASSERT(result->GetAvailableTimeSteps().size() == 1);
+    CPPUNIT_ASSERT(result->GetAvailableSlices(0).size() == 1);
+    CPPUNIT_ASSERT(result->GetValue(0, 0) == "v_0_0");
+
+    result = mitk::ExtractTimeStepFromTemporoSpatialStringProperty(refProp, 3);
+
+    CPPUNIT_ASSERT(result->GetAvailableTimeSteps().size() == 1);
+    CPPUNIT_ASSERT(result->GetAvailableSlices(0).size() == 2);
+    CPPUNIT_ASSERT(result->GetValue(0, 0) == "v_3_0");
+    CPPUNIT_ASSERT(result->GetValue(0, 2) == "v_3_2");
+
+    result = mitk::ExtractTimeStepFromTemporoSpatialStringProperty(refProp, 6);
+
+    CPPUNIT_ASSERT(result->GetAvailableTimeSteps().size() == 1);
+    CPPUNIT_ASSERT(result->GetAvailableSlices(0).size() == 1);
+    CPPUNIT_ASSERT(result->GetValue(0, 1) == "v_6_1");
+
+  }
 };
 
 MITK_TEST_SUITE_REGISTRATION(mitkTemporoSpatialStringProperty)