diff --git a/Modules/Core/include/mitkPropertyList.h b/Modules/Core/include/mitkPropertyList.h index b950ea5834..ce24b90ab3 100644 --- a/Modules/Core/include/mitkPropertyList.h +++ b/Modules/Core/include/mitkPropertyList.h @@ -1,253 +1,258 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #define PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #include "mitkBaseProperty.h" #include "mitkGenericProperty.h" #include "mitkUIDGenerator.h" #include #include #include #include namespace mitk { class XMLWriter; /** * @brief Key-value list holding instances of BaseProperty * * This list is meant to hold an arbitrary list of "properties", * which should describe the object associated with this list. * * Usually you will use PropertyList as part of a DataNode * object - in this context the properties describe the data object * held by the DataNode (e.g. whether the object is rendered at * all, which color is used for rendering, what name should be * displayed for the object, etc.) * * The values in the list are not fixed, you may introduce any kind * of property that seems useful - all you have to do is inherit * from BaseProperty. * * The list is organized as a key-value pairs, i.e. * * \li "name" : pointer to a StringProperty * \li "visible" : pointer to a BoolProperty * \li "color" : pointer to a ColorProperty * \li "volume" : pointer to a FloatProperty * * Please see the documentation of SetProperty and ReplaceProperty for two * quite different semantics. Normally SetProperty is what you want - this * method will try to change the value of an existing property and will * not allow you to replace e.g. a ColorProperty with an IntProperty. * * @ingroup DataManagement */ class MITKCORE_EXPORT PropertyList : public itk::Object { public: mitkClassMacroItkParent(PropertyList, itk::Object) /** * Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * Map structure to hold the properties: the map key is a string, * the value consists of the actual property object (BaseProperty). */ typedef std::map PropertyMap; typedef std::pair PropertyMapElementType; /** * @brief Get a property by its name. */ mitk::BaseProperty *GetProperty(const std::string &propertyKey) const; /** * @brief Set a property in the list/map by value. * * The actual OBJECT holding the value of the property is not replaced, but its value * is modified to match that of @a property. To really replace the object holding the * property - which would make sense if you want to change the type (bool, string) of the property * - call ReplaceProperty. */ void SetProperty(const std::string &propertyKey, BaseProperty *property); /** * @brief Set a property object in the list/map by reference. * * The actual OBJECT holding the value of the property is replaced by this function. * This is useful if you want to change the type of the property, like from BoolProperty to StringProperty. * Another use is to share one and the same property object among several ProperyList/DataNode objects, which * makes them appear synchronized. */ void ReplaceProperty(const std::string &propertyKey, BaseProperty *property); + /** + * @brief Remove a property object from the list/map by reference. + */ + void RemoveProperty(const std::string &propertyKey); + /** * @brief Set a property object in the list/map by reference. */ void ConcatenatePropertyList(PropertyList *pList, bool replace = false); //##Documentation //## @brief Convenience access method for GenericProperty properties //## (T being the type of the second parameter) //## @return @a true property was found template bool GetPropertyValue(const char *propertyKey, T &value) const { GenericProperty *gp = dynamic_cast *>(GetProperty(propertyKey)); if (gp != nullptr) { value = gp->GetValue(); return true; } return false; } /** * @brief Convenience method to access the value of a BoolProperty */ bool GetBoolProperty(const char *propertyKey, bool &boolValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, bool &boolValue) const; /** * @brief Convenience method to set the value of a BoolProperty */ void SetBoolProperty(const char *propertyKey, bool boolValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, bool boolValue); /** * @brief Convenience method to access the value of an IntProperty */ bool GetIntProperty(const char *propertyKey, int &intValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, int &intValue) const; /** * @brief Convenience method to set the value of an IntProperty */ void SetIntProperty(const char *propertyKey, int intValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, int intValue); /** * @brief Convenience method to access the value of a FloatProperty */ bool GetFloatProperty(const char *propertyKey, float &floatValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, float &floatValue) const; /** * @brief Convenience method to set the value of a FloatProperty */ void SetFloatProperty(const char *propertyKey, float floatValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, float floatValue); /** * @brief Convenience method to access the value of a DoubleProperty */ bool GetDoubleProperty(const char *propertyKey, double &doubleValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, double &doubleValue) const; /** * @brief Convenience method to set the value of a DoubleProperty */ void SetDoubleProperty(const char *propertyKey, double doubleValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, double doubleValue); /** * @brief Convenience method to access the value of a StringProperty */ bool GetStringProperty(const char *propertyKey, std::string &stringValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, std::string &stringValue) const; /** * @brief Convenience method to set the value of a StringProperty */ void SetStringProperty(const char *propertyKey, const char *stringValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, const char *stringValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, const std::string &stringValue); /** * @brief Get the timestamp of the last change of the map or the last change of one of * the properties store in the list (whichever is later). */ virtual unsigned long GetMTime() const override; /** * @brief Remove a property from the list/map. */ bool DeleteProperty(const std::string &propertyKey); const PropertyMap *GetMap() const { return &m_Properties; } bool IsEmpty() const { return m_Properties.empty(); } virtual void Clear(); protected: PropertyList(); PropertyList(const PropertyList &other); virtual ~PropertyList(); /** * @brief Map of properties. */ PropertyMap m_Properties; private: virtual itk::LightObject::Pointer InternalClone() const override; }; } // namespace mitk #endif /* PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D */ diff --git a/Modules/Core/src/DataManagement/mitkPropertyList.cpp b/Modules/Core/src/DataManagement/mitkPropertyList.cpp index 5f1e7a7b20..d2be580bcb 100644 --- a/Modules/Core/src/DataManagement/mitkPropertyList.cpp +++ b/Modules/Core/src/DataManagement/mitkPropertyList.cpp @@ -1,330 +1,343 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPropertyList.h" #include "mitkNumericTypes.h" #include "mitkProperties.h" #include "mitkStringProperty.h" mitk::BaseProperty *mitk::PropertyList::GetProperty(const std::string &propertyKey) const { PropertyMap::const_iterator it; it = m_Properties.find(propertyKey); if (it != m_Properties.cend()) return it->second; else return nullptr; } void mitk::PropertyList::SetProperty(const std::string &propertyKey, BaseProperty *property) { if (!property) return; // make sure that BaseProperty*, which may have just been created and never been // assigned to a SmartPointer, is registered/unregistered properly. If we do not // do that, it will a) not deleted in case it is identical to the old one or // b) possibly deleted when temporarily added to a smartpointer somewhere below. BaseProperty::Pointer tmpSmartPointerToProperty = property; auto it(m_Properties.find(propertyKey)); // Is a property with key @a propertyKey contained in the list? if (it != m_Properties.cend()) { // yes // is the property contained in the list identical to the new one? if (it->second->operator==(*property)) { // yes? do nothing and return. return; } if (it->second->AssignProperty(*property)) { // The assignment was successfull this->Modified(); } else { MITK_ERROR << "In " __FILE__ ", l." << __LINE__ << ": Trying to set existing property " << it->first << " of type " << it->second->GetNameOfClass() << " to a property with different type " << property->GetNameOfClass() << "." << " Use ReplaceProperty() instead." << std::endl; } return; } // no? add it. m_Properties.insert(PropertyMap::value_type(propertyKey, property)); this->Modified(); } void mitk::PropertyList::ReplaceProperty(const std::string &propertyKey, BaseProperty *property) { if (!property) return; auto it(m_Properties.find(propertyKey)); // Is a property with key @a propertyKey contained in the list? if (it != m_Properties.cend()) { it->second = nullptr; m_Properties.erase(it); } // no? add/replace it. m_Properties.insert(PropertyMap::value_type(propertyKey, property)); Modified(); } +void mitk::PropertyList::RemoveProperty(const std::string &propertyKey) +{ + auto it(m_Properties.find(propertyKey)); + + // Is a property with key @a propertyKey contained in the list? + if (it != m_Properties.cend()) + { + it->second = nullptr; + m_Properties.erase(it); + Modified(); + } +} + mitk::PropertyList::PropertyList() { } mitk::PropertyList::PropertyList(const mitk::PropertyList &other) : itk::Object() { for (auto i = other.m_Properties.cbegin(); i != other.m_Properties.cend(); ++i) { m_Properties.insert(std::make_pair(i->first, i->second->Clone())); } } mitk::PropertyList::~PropertyList() { Clear(); } /** * Consider the list as changed when any of the properties has changed recently. */ unsigned long mitk::PropertyList::GetMTime() const { for (auto it = m_Properties.cbegin(); it != m_Properties.cend(); ++it) { if (it->second.IsNull()) { itkWarningMacro(<< "Property '" << it->first << "' contains nothing (nullptr)."); continue; } if (Superclass::GetMTime() < it->second->GetMTime()) { Modified(); break; } } return Superclass::GetMTime(); } bool mitk::PropertyList::DeleteProperty(const std::string &propertyKey) { PropertyMap::iterator it = m_Properties.find(propertyKey); if (it != m_Properties.end()) { it->second = nullptr; m_Properties.erase(it); Modified(); return true; } return false; } void mitk::PropertyList::Clear() { auto it = m_Properties.begin(), end = m_Properties.end(); while (it != end) { it->second = nullptr; ++it; } m_Properties.clear(); } itk::LightObject::Pointer mitk::PropertyList::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); result->UnRegister(); return result; } void mitk::PropertyList::ConcatenatePropertyList(PropertyList *pList, bool replace) { if (pList) { const PropertyMap *propertyMap = pList->GetMap(); for (auto iter = propertyMap->cbegin(); // m_PropertyList is created in the constructor, so we don't check it here iter != propertyMap->cend(); ++iter) { const std::string key = iter->first; BaseProperty *value = iter->second; if (replace) { ReplaceProperty(key.c_str(), value); } else { SetProperty(key.c_str(), value); } } } } bool mitk::PropertyList::GetBoolProperty(const char *propertyKey, bool &boolValue) const { BoolProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { boolValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, boolValue); } bool mitk::PropertyList::GetIntProperty(const char *propertyKey, int &intValue) const { IntProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { intValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, intValue); } bool mitk::PropertyList::GetFloatProperty(const char *propertyKey, float &floatValue) const { FloatProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { floatValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, floatValue); } bool mitk::PropertyList::GetStringProperty(const char *propertyKey, std::string &stringValue) const { StringProperty *sp = dynamic_cast(GetProperty(propertyKey)); if (sp != nullptr) { stringValue = sp->GetValue(); return true; } return false; } void mitk::PropertyList::SetIntProperty(const char *propertyKey, int intValue) { SetProperty(propertyKey, mitk::IntProperty::New(intValue)); } void mitk::PropertyList::SetBoolProperty(const char *propertyKey, bool boolValue) { SetProperty(propertyKey, mitk::BoolProperty::New(boolValue)); } void mitk::PropertyList::SetFloatProperty(const char *propertyKey, float floatValue) { SetProperty(propertyKey, mitk::FloatProperty::New(floatValue)); } void mitk::PropertyList::SetStringProperty(const char *propertyKey, const char *stringValue) { SetProperty(propertyKey, mitk::StringProperty::New(stringValue)); } void mitk::PropertyList::Set(const char *propertyKey, bool boolValue) { this->SetBoolProperty(propertyKey, boolValue); } void mitk::PropertyList::Set(const char *propertyKey, int intValue) { this->SetIntProperty(propertyKey, intValue); } void mitk::PropertyList::Set(const char *propertyKey, float floatValue) { this->SetFloatProperty(propertyKey, floatValue); } void mitk::PropertyList::Set(const char *propertyKey, double doubleValue) { this->SetDoubleProperty(propertyKey, doubleValue); } void mitk::PropertyList::Set(const char *propertyKey, const char *stringValue) { this->SetStringProperty(propertyKey, stringValue); } void mitk::PropertyList::Set(const char *propertyKey, const std::string &stringValue) { this->SetStringProperty(propertyKey, stringValue.c_str()); } bool mitk::PropertyList::Get(const char *propertyKey, bool &boolValue) const { return this->GetBoolProperty(propertyKey, boolValue); } bool mitk::PropertyList::Get(const char *propertyKey, int &intValue) const { return this->GetIntProperty(propertyKey, intValue); } bool mitk::PropertyList::Get(const char *propertyKey, float &floatValue) const { return this->GetFloatProperty(propertyKey, floatValue); } bool mitk::PropertyList::Get(const char *propertyKey, double &doubleValue) const { return this->GetDoubleProperty(propertyKey, doubleValue); } bool mitk::PropertyList::Get(const char *propertyKey, std::string &stringValue) const { return this->GetStringProperty(propertyKey, stringValue); } bool mitk::PropertyList::GetDoubleProperty(const char *propertyKey, double &doubleValue) const { DoubleProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { doubleValue = gp->GetValue(); return true; } return false; } void mitk::PropertyList::SetDoubleProperty(const char *propertyKey, double doubleValue) { SetProperty(propertyKey, mitk::DoubleProperty::New(doubleValue)); } diff --git a/Modules/Core/test/mitkPropertyListTest.cpp b/Modules/Core/test/mitkPropertyListTest.cpp index d8562a1c2a..f4fb875fdf 100644 --- a/Modules/Core/test/mitkPropertyListTest.cpp +++ b/Modules/Core/test/mitkPropertyListTest.cpp @@ -1,251 +1,262 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkLookupTables.h" #include "mitkProperties.h" #include "mitkPropertyList.h" #include "mitkStringProperty.h" #include int mitkPropertyListTest(int /*argc*/, char * /*argv*/ []) { mitk::PropertyList::Pointer propList; std::cout << "Testing mitk::PropertyList::New(): "; propList = mitk::PropertyList::New(); if (propList.IsNull()) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } else { std::cout << "[PASSED]" << std::endl; } mitk::BoolProperty::Pointer boolProp = mitk::BoolProperty::New(false); mitk::BoolProperty::Pointer boolProp2 = mitk::BoolProperty::New(false); std::cout << "Testing BoolProperty ==: "; if (!(*boolProp2 == *boolProp)) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; unsigned long tBefore, tAfter; std::cout << "Testing SetProperty() with new key value: "; tBefore = propList->GetMTime(); propList->SetProperty("test", boolProp); tAfter = propList->GetMTime(); if (!(tAfter > tBefore)) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing SetProperty() with changed property value: "; tBefore = propList->GetMTime(); propList->SetProperty("test", mitk::BoolProperty::New(true)); tAfter = propList->GetMTime(); if (!(tAfter > tBefore)) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing SetProperty() with unchanged property value: "; tBefore = propList->GetMTime(); propList->SetProperty("test", mitk::BoolProperty::New(true)); tAfter = propList->GetMTime(); if (tBefore != tAfter) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing MTime correctness when changing property value: "; boolProp = mitk::BoolProperty::New(true); propList->ReplaceProperty("test", boolProp); tBefore = propList->GetMTime(); boolProp->SetValue(true); tAfter = propList->GetMTime(); boolProp->SetValue(false); unsigned long tAfterAll = propList->GetMTime(); if (tBefore != tAfter || tAfterAll <= tAfter) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing MTime correctness when calling SetProperty twice: "; boolProp = mitk::BoolProperty::New(true); propList->SetProperty("test", boolProp); tBefore = propList->GetMTime(); propList->SetProperty("test", boolProp); tAfter = propList->GetMTime(); if (tBefore != tAfter) { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing if existing properties survive SetProperty: "; propList->SetProperty("test", boolProp); mitk::BaseProperty *bpBefore = propList->GetProperty("test"); propList->SetProperty("test", boolProp2); mitk::BaseProperty *bpAfter = propList->GetProperty("test"); if (bpBefore != bpAfter || bpAfter == nullptr) { std::cout << std::endl; std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; std::cout << "Testing if existing properties survive ReplaceProperty: "; propList->SetProperty("test", boolProp); bpBefore = propList->GetProperty("test"); propList->ReplaceProperty("test", boolProp2); bpAfter = propList->GetProperty("test"); if (bpBefore == bpAfter || bpAfter == nullptr) { std::cout << std::endl; std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "[PASSED]" << std::endl; // std::cout << "Testing output of PropertyList to file: "; // if ( TestXMLWriter() ) // std::cout << "[PASSED]" << std::endl; // else // return EXIT_FAILURE; std::cout << "Testing GetPropertyValue(bool): "; mitk::BoolProperty::Pointer gpvTest = mitk::BoolProperty::New(true); propList->SetProperty("gpvBool", gpvTest); bool b = false; bool getPropertyValueReturnValue = propList->GetPropertyValue("gpvBool", b); if ((getPropertyValueReturnValue == true) && (b == gpvTest->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "Oh, not goot:" "\nWe called propList->GetPropertyValue('gpvBool', b) and it returned " << getPropertyValueReturnValue << "\nThen we compared b [" << b << "] and gpvTest->GetValue() [" << gpvTest->GetValue() << "]" << std::endl; std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "Testing GetPropertyValue(float): "; mitk::FloatProperty::Pointer gpvTest2 = mitk::FloatProperty::New(3.1337); propList->SetProperty("gpvfloat", gpvTest2); float v = -1.23; if ((propList->GetPropertyValue("gpvfloat", v) == true) && (v == gpvTest2->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } std::cout << "Testing GetPropertyValue(BoolLookupTable): "; mitk::BoolLookupTable blt; blt.SetTableValue(17, true); propList->SetProperty("blutprop", mitk::BoolLookupTableProperty::New(blt)); try { mitk::BoolLookupTable blut; if ((propList->GetPropertyValue("blutprop", blut) == true) && (blut.GetTableValue(17) == true)) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } } catch (...) { std::cout << "Exception thrown! [FAILED]" << std::endl; return EXIT_FAILURE; } { std::cout << "Testing GetBoolProperty(): "; mitk::BoolProperty::Pointer prop = mitk::BoolProperty::New(true); propList->ReplaceProperty("test", prop); bool v = false; if ((propList->GetBoolProperty("test", v) == true) && (v == prop->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } } { std::cout << "Testing GetIntProperty(): "; mitk::IntProperty::Pointer prop = mitk::IntProperty::New(31337); propList->ReplaceProperty("test", prop); int v = 1; if ((propList->GetIntProperty("test", v) == true) && (v == prop->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } } { std::cout << "Testing GetFloatProperty(): "; mitk::FloatProperty::Pointer prop = mitk::FloatProperty::New(31.337); propList->ReplaceProperty("test", prop); float v = 1.2; if ((propList->GetFloatProperty("test", v) == true) && (v == prop->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } } { std::cout << "Testing GetStringProperty(): "; mitk::StringProperty::Pointer prop = mitk::StringProperty::New("MITK"); propList->ReplaceProperty("test", prop); std::string v = ""; if ((propList->GetStringProperty("test", v) == true) && (v == prop->GetValue())) std::cout << "[PASSED]" << std::endl; else { std::cout << "[FAILED]" << std::endl; return EXIT_FAILURE; } } + { + + std::cout << "Testing RemoveProperty(): "; + propList->RemoveProperty("test"); + if (propList->GetProperty("test")!=nullptr) + { + std::cout << "[FAILED]" << std::endl; + return EXIT_FAILURE; + } + std::cout << "[PASSED]" << std::endl; + } std::cout << "[TEST DONE]" << std::endl; return EXIT_SUCCESS; } diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp index c3a5ddff61..ea86eec083 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp @@ -1,103 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include "mitkIOUtil.h" #include #include "mitkDWIHeadMotionCorrectionFilter.h" #include #include #include typedef short DiffusionPixelType; int mitkExtractSingleShellTest( int argc, char* argv[] ) { MITK_TEST_BEGIN("mitkExtractSingleShellTest"); MITK_TEST_CONDITION_REQUIRED( argc > 3, "Specify input and output and the shell to be extracted"); /* 1. Get input data */ mitk::Image::Pointer dwimage = dynamic_cast(mitk::IOUtil::Load( argv[1] )[0].GetPointer()); mitk::GradientDirectionsProperty::Pointer gradientsProperty = static_cast( dwimage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ); MITK_TEST_CONDITION_REQUIRED( gradientsProperty.IsNotNull(), "Input is a dw-image"); unsigned int extract_value = 0; std::istringstream input(argv[3]); input >> extract_value; typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMap; // GetShellSelection from GUI BValueMap shellSelectionMap; BValueMap originalShellMap = static_cast(dwimage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); std::vector newNumGradientDirections; shellSelectionMap[extract_value] = originalShellMap[extract_value]; newNumGradientDirections.push_back( originalShellMap[extract_value].size() ) ; itk::VectorImage< short, 3 >::Pointer itkVectorImagePointer = itk::VectorImage< short, 3 >::New(); mitk::CastToItkImage(dwimage, itkVectorImagePointer); itk::VectorImage< short, 3 > *vectorImage = itkVectorImagePointer.GetPointer(); mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainer = static_cast( dwimage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(newNumGradientDirections); filter->SetOriginalBValueMap(originalShellMap); filter->SetShellSelectionBValueMap(shellSelectionMap); try { filter->Update(); } catch( const itk::ExceptionObject& e) { MITK_TEST_FAILED_MSG( << "Failed due to ITK exception: " << e.what() ); } mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetGradientDirections() ) ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(dwimage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(dwimage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); + mitk::DiffusionPropertyHelper::CopyProperties(dwimage, outImage, true); + outImage->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetGradientDirections() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); /* * 3. Write output data **/ try { mitk::IOUtil::Save(outImage, argv[2]); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Catched exception: " << e.what(); mitkThrow() << "Failed with exception from subprocess!"; } MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionCoreIOActivator.cpp b/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionCoreIOActivator.cpp index b2a16e8b7b..5df159a551 100644 --- a/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionCoreIOActivator.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/autoload/IO/mitkDiffusionCoreIOActivator.cpp @@ -1,132 +1,132 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDiffusionCoreIOMimeTypes.h" namespace mitk { /** \brief Registers services for segmentation module. */ class DiffusionCoreIOActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context) override { us::ServiceProperties props; props[ us::ServiceConstants::SERVICE_RANKING() ] = 10; m_MimeTypes = mitk::DiffusionCoreIOMimeTypes::Get(); for (std::vector::const_iterator mimeTypeIter = m_MimeTypes.begin(), iterEnd = m_MimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { context->RegisterService(*mimeTypeIter, props); } m_DiffusionImageNrrdReaderService = new DiffusionImageNrrdReaderService(); m_DiffusionImageNiftiReaderService = new DiffusionImageNiftiReaderService( CustomMimeType( mitk::DiffusionCoreIOMimeTypes::DWI_NIFTI_MIMETYPE() ), mitk::DiffusionCoreIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION() ); m_DiffusionImageFslNiftiReaderService = new DiffusionImageNiftiReaderService( CustomMimeType( mitk::DiffusionCoreIOMimeTypes::DWI_FSL_MIMETYPE() ), mitk::DiffusionCoreIOMimeTypes::DWI_FSL_MIMETYPE_DESCRIPTION() ); m_NrrdTensorImageReader = new NrrdTensorImageReader(); m_NrrdQBallImageReader = new NrrdQBallImageReader(); m_DiffusionImageNrrdWriterService = new DiffusionImageNrrdWriterService(); m_DiffusionImageNiftiWriterService = new DiffusionImageNiftiWriterService(); m_NrrdTensorImageWriter = new NrrdTensorImageWriter(); m_NrrdQBallImageWriter = new NrrdQBallImageWriter(); //register relevant properties //non-persistent properties mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME, "This map stores which b values belong to which gradients."); mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME, "The original gradients used during acquisition. This property may be empty."); //persistent properties mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME, "The reference b value the gradients are normalized to."); mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME, "The measurment frame used during acquisition."); - mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME, "The gradients used during acquisition."); + mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME, "The gradients after applying measurement frame and image matrix."); mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::MODALITY, "Defines the modality used for acquisition. DWMRI signifies diffusion weighted images."); mitk::PropertyPersistenceInfo::Pointer PPI_referenceBValue = mitk::PropertyPersistenceInfo::New(); PPI_referenceBValue->SetNameAndKey(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME, "DWMRI_b-value"); mitk::PropertyPersistenceInfo::Pointer PPI_measurementFrame = mitk::PropertyPersistenceInfo::New(); PPI_measurementFrame->SetNameAndKey(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME, "measurement frame"); mitk::PropertyPersistenceInfo::Pointer PPI_gradientContainer = mitk::PropertyPersistenceInfo::New(); PPI_gradientContainer->SetNameAndKey(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME, "DWMRI_gradient"); mitk::PropertyPersistenceInfo::Pointer PPI_modality = mitk::PropertyPersistenceInfo::New(); PPI_modality->SetNameAndKey(mitk::DiffusionPropertyHelper::MODALITY, "modality"); mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_referenceBValue.GetPointer() , true); mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_measurementFrame.GetPointer(), true); mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_gradientContainer.GetPointer(), true); mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_modality.GetPointer(), true); } void Unload(us::ModuleContext*) override { for (unsigned int loop(0); loop < m_MimeTypes.size(); ++loop) { delete m_MimeTypes.at(loop); } delete m_DiffusionImageNrrdReaderService; delete m_DiffusionImageNiftiReaderService; delete m_DiffusionImageFslNiftiReaderService; delete m_NrrdTensorImageReader; delete m_NrrdQBallImageReader; delete m_DiffusionImageNrrdWriterService; delete m_DiffusionImageNiftiWriterService; delete m_NrrdTensorImageWriter; delete m_NrrdQBallImageWriter; } private: DiffusionImageNrrdReaderService * m_DiffusionImageNrrdReaderService; DiffusionImageNiftiReaderService * m_DiffusionImageNiftiReaderService; DiffusionImageNiftiReaderService * m_DiffusionImageFslNiftiReaderService; NrrdTensorImageReader * m_NrrdTensorImageReader; NrrdQBallImageReader * m_NrrdQBallImageReader; DiffusionImageNrrdWriterService * m_DiffusionImageNrrdWriterService; DiffusionImageNiftiWriterService * m_DiffusionImageNiftiWriterService; NrrdTensorImageWriter * m_NrrdTensorImageWriter; NrrdQBallImageWriter * m_NrrdQBallImageWriter; std::vector m_MimeTypes; }; } US_EXPORT_MODULE_ACTIVATOR(mitk::DiffusionCoreIOActivator) diff --git a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h index bed905a605..13dc914694 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h +++ b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h @@ -1,124 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_AbstractFitter_H #define _MITK_AbstractFitter_H #include #include #include namespace mitk { class AbstractFitter: public vnl_least_squares_function { public: typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType; typedef itk::VectorImage< unsigned short, 3 > DiffusionImageType; typedef itk::DiffusionTensor3D TensorType; AbstractFitter(unsigned int number_of_parameters, unsigned int number_of_measurements) : vnl_least_squares_function(number_of_parameters, number_of_measurements, no_gradient) { } GradientContainerType::Pointer gradientDirections; - typename DiffusionImageType::PixelType measurements; + DiffusionImageType::PixelType measurements; std::vector bValues; double S0; std::vector weightedIndices; void set_S0(double val) { S0 = val; } - void set_measurements(const typename DiffusionImageType::PixelType& m) + void set_measurements(const DiffusionImageType::PixelType& m) { measurements = m; } void set_bvalues(std::vector& x) { bValues = x; } void set_weightedIndices(std::vector& x) { weightedIndices = x; } void set_gradient_directions(const GradientContainerType::Pointer& directions) { gradientDirections = directions; } static void Sph2Cart(vnl_vector_fixed& dir, const double &theta, const double &phi) { dir[0] = std::sin(theta)*std::cos(phi); dir[1] = std::sin(theta)*std::sin(phi); dir[2] = std::cos(theta); } static void Cart2Sph(const vnl_vector_fixed& dir, double &theta, double &phi) { theta = std::acos( dir[2] ); // phi goes from 0.0 (+x axis) and wraps at 2 * PI // theta goes from 0.0 (+z axis) and wraps at PI // if x and y are 0.0 or very close, return phi == 0 if (fabs(dir[0]) + fabs(dir[1]) < 1E-9) { phi = 0.0; } else { // ie, if ( x == 0 && y == 0 ) == false if (dir[1] == 0.0) { if (dir[0] > 0.0) phi = 0.0; else phi = M_PI; } else if (dir[0] == 0.0) { // avoid div by zero if (dir[1] > 0) { phi = M_PI / 2.0; } else { phi = 1.5 * M_PI; } } else if (dir[0] > 0.0 && dir[1] > 0.0) // first quadrant phi = atan(dir[1] / dir[0]); else if (dir[0] < 0.0 && dir[1] > 0.0) // second quadrant phi = M_PI + atan(dir[1] / dir[0]); else if (dir[0] < 0.0 && dir[1] < 0.0) // third quadrant phi = M_PI + atan(dir[1] / dir[0]); else // fourth quadrant phi = 2.0 * M_PI + atan(dir[1] / dir[0]); } } }; } #endif diff --git a/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx b/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx index 7db96fb2e4..a04f4b6885 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx +++ b/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx @@ -1,267 +1,268 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX #define DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX #include "mitkDiffusionImageTransformedCreationFilter.h" #include "mitkDiffusionImageCorrectionFilter.h" #include "mitkImageCast.h" #include "mitkImageWriteAccessor.h" #include "mitkImageTimeSelector.h" #include "mitkProperties.h" #include "mitkIOUtil.h" #include #include #include #include #include template static void ResampleImage( typename ItkImageType::Pointer itk_reference, mitk::Image::Pointer mitk_input, typename TTransformType::Pointer transform, unsigned int interpolator, mitk::Image::Pointer output_target, unsigned int position ) { typedef itk::LinearInterpolateImageFunction< ItkImageType, double > InterpolatorType; typename InterpolatorType::Pointer linear_interpolator = InterpolatorType::New(); typedef itk::NearestNeighborInterpolateImageFunction< ItkImageType, double > NearestNeighborInterpolatorType; typename NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< ItkImageType, 7> WindowedSincInterpolatorType; typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::BSplineInterpolateImageFunction< ItkImageType, double, double> BSplineInterpolatorType; typename BSplineInterpolatorType::Pointer bicubic_interpolator = BSplineInterpolatorType::New(); bicubic_interpolator->SetSplineOrder(3); typedef typename itk::ResampleImageFilter< ItkImageType, ItkImageType, double> ResampleImageFilterType; typename ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New(); // Create interpolator pool typedef itk::InterpolateImageFunction< ItkImageType, double> InterpolateFunctionBaseType; std::vector< InterpolateFunctionBaseType* > InterpolateFunctionsPool; InterpolateFunctionsPool.push_back( nn_interpolator.GetPointer() ); InterpolateFunctionsPool.push_back( linear_interpolator.GetPointer() ); InterpolateFunctionsPool.push_back( bicubic_interpolator.GetPointer() ); InterpolateFunctionsPool.push_back( sinc_interpolator.GetPointer() ); // select interpolator by the selection flag resampler->SetInterpolator( InterpolateFunctionsPool.at( interpolator ) ); typename ItkImageType::Pointer itk_input; mitk::CastToItkImage< ItkImageType >( mitk_input, itk_input ); resampler->SetInput( itk_input ); resampler->SetTransform( transform ); resampler->SetReferenceImage( itk_reference ); resampler->UseReferenceImageOn(); resampler->Update(); mitk::Image::Pointer current_resampled = mitk::Image::New(); current_resampled->InitializeByItk( resampler->GetOutput() ); current_resampled->SetImportChannel( resampler->GetOutput()->GetBufferPointer(), mitk::Image::CopyMemory ); mitk::ImageWriteAccessor imac( current_resampled ); output_target->SetImportVolume( imac.GetData(), position, 0, mitk::Image::CopyMemory ); } /* template< typename TTransformType > static mitk::DiffusionPropertyHelper::GradientDirectionType TransformGradientDirection( mitk::DiffusionPropertyHelper::GradientDirectionType vec_in, typename TTransformType::Pointer transform ) { mitk::DiffusionPropertyHelper::GradientDirectionType vec_out; vec_out.fill(1.0); typedef typename TTransformType::MatrixType TMatrixType; return vec_out; } */ template< typename TTransformType> mitk::DiffusionImageTransformedCreationFilter ::DiffusionImageTransformedCreationFilter() { this->m_OutputPrefix = "/tmp/"; } template< typename TTransformType> mitk::DiffusionImageTransformedCreationFilter ::~DiffusionImageTransformedCreationFilter() { } template< typename TTransformType> mitk::DiffusionImageHeaderDescriptor mitk::DiffusionImageTransformedCreationFilter ::GetTransformedHeaderInformation() { typedef mitk::DiffusionPropertyHelper DPH; DiffusionImageHeaderDescriptor dwhdesc; dwhdesc.m_BValue = DPH::GetReferenceBValue( this->m_DiffusionReferenceImage ); // TODO : here comes transformation of the gradients dwhdesc.m_GradientDirections = DPH::GetGradientContainer( this->m_DiffusionReferenceImage ); dwhdesc.m_MeasurementFrame = DPH::GetMeasurementFrame( this->m_DiffusionReferenceImage ); dwhdesc.m_BValueMapType = DPH::GetBValueMap( this->m_DiffusionReferenceImage ); return dwhdesc; } template< typename TTransformType> void mitk::DiffusionImageTransformedCreationFilter< TTransformType > ::GenerateOutputInformation() { MITK_INFO << "Debug info"; } template< typename TTransformType> void mitk::DiffusionImageTransformedCreationFilter ::GenerateData() { mitk::Image::Pointer input = this->GetInput(); // validity checks if( m_InternalTransforms.size() != input->GetTimeSteps() ) { mitkThrow() << "Number of transforms" << m_InternalTransforms.size() << "differ from number of timesteps" << input->GetTimeSteps(); } typedef itk::Image< DiffusionPropertyHelper::DiffusionPixelType, 3> ImageType; // create intermediate output mitk::Image::Pointer resampled_output = mitk::Image::New(); resampled_output->Initialize( input ); ImageType::Pointer current_itk_reference = ImageType::New(); CastToItkImage( this->m_ResamplingReferenceImage, current_itk_reference ); unsigned int time_dim = input->GetDimension(3); for( unsigned int time_idx = 0; time_idx < time_dim; time_idx++ ) { mitk::ImageTimeSelector::Pointer t_sel = mitk::ImageTimeSelector::New(); t_sel->SetInput( input ); t_sel->SetTimeNr( time_idx ); t_sel->Update(); ResampleImage< TTransformType, ImageType>( current_itk_reference, t_sel->GetOutput(), this->m_InternalTransforms.at(time_idx), this->m_InterpolationLevel, resampled_output, time_idx); } // call here creation filter mitk::DiffusionImageCreationFilter::Pointer creator = mitk::DiffusionImageCreationFilter::New(); creator->SetInput( resampled_output ); creator->SetHeaderDescriptor( this->GetTransformedHeaderInformation() ); creator->Update(); mitk::Image::Pointer output = creator->GetOutput(); + mitk::DiffusionPropertyHelper::CopyProperties(resampled_output, output, true); typedef mitk::DiffusionPropertyHelper DPH; float BValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( creator->GetOutput() ); mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap( mitk::DiffusionPropertyHelper::GetGradientContainer( creator->GetOutput() ), BValue ); - output->SetProperty( DPH::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer( creator->GetOutput() )) ); - output->SetProperty( DPH::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mitk::DiffusionPropertyHelper::GetMeasurementFrame( creator->GetOutput() ) ) ); - output->SetProperty( DPH::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) ); - output->SetProperty( DPH::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) ); + output->GetPropertyList()->ReplaceProperty( DPH::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer( creator->GetOutput() )) ); + output->GetPropertyList()->ReplaceProperty( DPH::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mitk::DiffusionPropertyHelper::GetMeasurementFrame( creator->GetOutput() ) ) ); + output->GetPropertyList()->ReplaceProperty( DPH::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) ); + output->GetPropertyList()->ReplaceProperty( DPH::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) ); // correct gradients mitk::DiffusionImageCorrectionFilter::Pointer corrector = mitk::DiffusionImageCorrectionFilter::New(); corrector->SetImage( output) ; corrector->CorrectDirections( this->m_RotationMatrices ); DPH pHelper( output ); pHelper.InitializeImage(); m_OutputCache = output; this->SetPrimaryOutput( m_OutputCache ); m_OutputCache->Modified(); } template< typename TTransformType> void mitk::DiffusionImageTransformedCreationFilter ::SetTransformParameters(const TransformParametersContainerType ¶ms) { if( params.empty() ) { MITK_ERROR << "Empty parameter list given."; return; } TransformContainerType transforms; auto iter = std::begin( params ); while( iter != std::end( params ) ) { typename TTransformType::Pointer transform = TTransformType::New(); transform->SetParameters( (*iter) ); transforms.push_back( transform ); ++iter; } this->SetTransforms( transforms ); } template< typename TTransformType> void mitk::DiffusionImageTransformedCreationFilter ::SetTransforms(const TransformContainerType &transforms) { if( transforms.empty() ) { MITK_ERROR << "Empty transform list given."; return; } this->m_InternalTransforms.reserve( transforms.size() ); std::copy( transforms.begin(), transforms.end(), std::back_inserter(this->m_InternalTransforms ) ); MatrixType E; E.set_identity(); for( auto iter = std::begin(this->m_InternalTransforms); iter != std::end( this->m_InternalTransforms); ++iter) { MatrixType A = E * (*iter)->GetMatrix().GetVnlMatrix(); this->m_RotationMatrices.push_back( A ); } } #endif // DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX diff --git a/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/Properties/mitkDiffusionPropertyHelper.h b/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/Properties/mitkDiffusionPropertyHelper.h index 32c0c47033..e81abcb417 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/Properties/mitkDiffusionPropertyHelper.h +++ b/Modules/DiffusionImaging/DiffusionCore/include/IODataStructures/Properties/mitkDiffusionPropertyHelper.h @@ -1,145 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKDIFFUSIONPROPERTYHELPER_H #define MITKDIFFUSIONPROPERTYHELPER_H #include #include #include #include #include #include namespace mitk { /** \brief Helper class for mitk::Images containing diffusion weighted data * * This class takes a pointer to a mitk::Image containing diffusion weighted information and provides * functions to manipulate the diffusion meta-data. Will log an error if required information is * missing. */ class MITKDIFFUSIONCORE_EXPORT DiffusionPropertyHelper { public: typedef short DiffusionPixelType; typedef mitk::BValueMapProperty::BValueMap BValueMapType; typedef GradientDirectionsProperty::GradientDirectionType GradientDirectionType; typedef GradientDirectionsProperty::GradientDirectionsContainerType GradientDirectionsContainerType; typedef mitk::MeasurementFrameProperty::MeasurementFrameType MeasurementFrameType; typedef itk::VectorImage< DiffusionPixelType, 3> ImageType; static const std::string GRADIENTCONTAINERPROPERTYNAME; static const std::string ORIGINALGRADIENTCONTAINERPROPERTYNAME; static const std::string MEASUREMENTFRAMEPROPERTYNAME; static const std::string REFERENCEBVALUEPROPERTYNAME; static const std::string BVALUEMAPPROPERTYNAME; static const std::string MODALITY; + static const std::string KEEP_ORIGINAL_DIRECTIONS; /// Public constructor, takes a mitk::Image pointer as argument DiffusionPropertyHelper( mitk::Image* inputImage ); ~DiffusionPropertyHelper(); /** \brief Decide whether a provided image is a valid diffusion weighted image * * An image will be considered a valid diffusion weighted image if the following are true * - It has a reference b value * - It has a gradient directions property * - The number of gradients directions matches the number of components of the image * * This does not guarantee that the data is sensible or accurate, it just verfies that it * meets the formal requirements to possibly be a valid diffusion weighted image. */ static bool IsDiffusionWeightedImage(const mitk::Image *); static bool IsDiffusionWeightedImage(const mitk::DataNode* node); + static void ClearMeasurementFrameAndRotationMatrixFromGradients(mitk::Image* image); + static void CopyProperties(mitk::Image* source, mitk::Image* target, bool ignore_original_gradients=false); + static ImageType::Pointer GetItkVectorImage(Image *image); /// Convenience method to get the BValueMap static const BValueMapType & GetBValueMap(const mitk::Image *); /// Convenience method to get the BValue static float GetReferenceBValue(const mitk::Image *); /** \brief Convenience method to get the measurement frame * * This method will return the measurement frame of the image. * * \note If the image has no associated measurement frame the identity will be returned. */ static const MeasurementFrameType & GetMeasurementFrame(const mitk::Image *); /// Convenience method to get the original gradient directions static GradientDirectionsContainerType::Pointer GetOriginalGradientContainer(const mitk::Image *); /// Convenience method to get the gradient directions static GradientDirectionsContainerType::Pointer GetGradientContainer(const mitk::Image *); const BValueMapType & GetBValueMap() const; float GetReferenceBValue() const; const MeasurementFrameType & GetMeasurementFrame() const; GradientDirectionsContainerType::Pointer GetOriginalGradientContainer() const; GradientDirectionsContainerType::Pointer GetGradientContainer() const; bool IsDiffusionWeightedImage() const; void AverageRedundantGradients(double precision); /** \brief Make certain the owned image is up to date with all necessary properties * * This function will generate the B Value map and copy all properties to the owned image. */ void InitializeImage(); GradientDirectionsContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions); protected: DiffusionPropertyHelper(); /** * \brief Apply the previously set MeasurementFrame and the image rotation matrix to all gradients * * \warning first set the MeasurementFrame */ void ApplyMeasurementFrameAndRotationMatrix(); /** * \brief Apply the inverse of the previously set MeasurementFrame and the image rotation matrix to all gradients * * \warning first set the MeasurementFrame */ void UnApplyMeasurementFrameAndRotationMatrix(); /** * \brief Update the BValueMap (m_B_ValueMap) using the current gradient directions (m_Directions) * * \warning Have to be called after each manipulation on the GradientDirectionContainer * !especially after manipulation of the m_Directions (GetDirections()) container via pointer access! */ void UpdateBValueMap(); /// Determines whether gradients can be considered to be equal bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); /// Get the b value belonging to an index float GetB_Value(unsigned int i); mitk::Image* m_Image; }; } #endif diff --git a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp index 3f6fbc61a9..6bd55b4240 100644 --- a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp @@ -1,316 +1,317 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKDWIHEADMOTIONCORRECTIONFILTER_CPP #define MITKDWIHEADMOTIONCORRECTIONFILTER_CPP #include "mitkDWIHeadMotionCorrectionFilter.h" #include "itkSplitDWImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "mitkImageTimeSelector.h" #include "mitkPyramidImageRegistrationMethod.h" //#include "mitkRegistrationMethodITK4.h" #include #include "mitkDiffusionImageCorrectionFilter.h" #include #include #include #include "mitkIOUtil.h" #include mitk::DWIHeadMotionCorrectionFilter::DWIHeadMotionCorrectionFilter() : m_CurrentStep(0), m_Steps(100), m_IsInValidState(true), m_AbortRegistration(false), m_AverageUnweighted(true) { } void mitk::DWIHeadMotionCorrectionFilter::GenerateData() { typedef itk::SplitDWImageFilter< DiffusionPixelType, DiffusionPixelType> SplitFilterType; InputImageType* input = const_cast(this->GetInput(0)); ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(input, itkVectorImagePointer); typedef mitk::PyramidImageRegistrationMethod RegistrationMethod; // typedef mitk::RegistrationMethodITKV4 RegistrationMethod unsigned int numberOfSteps = itkVectorImagePointer->GetNumberOfComponentsPerPixel () ; m_Steps = numberOfSteps; // // (1) Extract the b-zero images to a 3d+t image, register them by NCorr metric and // rigid registration : they will then be used are reference image for registering // the gradient images // typedef itk::B0ImageExtractionToSeparateImageFilter< DiffusionPixelType, DiffusionPixelType> B0ExtractorType; B0ExtractorType::Pointer b0_extractor = B0ExtractorType::New(); b0_extractor->SetInput( itkVectorImagePointer ); b0_extractor->SetDirections( static_cast( input->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); b0_extractor->Update(); mitk::Image::Pointer b0Image = mitk::Image::New(); b0Image->InitializeByItk( b0_extractor->GetOutput() ); b0Image->SetImportChannel( b0_extractor->GetOutput()->GetBufferPointer(), mitk::Image::CopyMemory ); // (2.1) Use the extractor to access the extracted b0 volumes mitk::ImageTimeSelector::Pointer t_selector = mitk::ImageTimeSelector::New(); t_selector->SetInput( b0Image ); t_selector->SetTimeNr(0); t_selector->Update(); // first unweighted image as reference space for the registration mitk::Image::Pointer b0referenceImage = t_selector->GetOutput(); const unsigned int numberOfb0Images = b0Image->GetTimeSteps(); // register b-zeros only if the flag to average is set, use the first one otherwise if( m_AverageUnweighted && numberOfb0Images > 1) { RegistrationMethod::Pointer registrationMethod = RegistrationMethod::New(); registrationMethod->SetFixedImage( b0referenceImage ); registrationMethod->SetTransformToRigid(); // the unweighted images are of same modality registrationMethod->SetCrossModalityOff(); // use the advanced (windowed sinc) interpolation registrationMethod->SetUseAdvancedInterpolation(true); // Initialize the temporary output image mitk::Image::Pointer registeredB0Image = b0Image->Clone(); mitk::ImageTimeSelector::Pointer t_selector2 = mitk::ImageTimeSelector::New(); t_selector2->SetInput( b0Image ); for( unsigned int i=1; iSetTimeNr(i); t_selector2->Update(); registrationMethod->SetMovingImage( t_selector2->GetOutput() ); try { MITK_INFO << " === (" << i <<"/"<< numberOfb0Images-1 << ") :: Starting registration"; registrationMethod->Update(); } catch( const itk::ExceptionObject& e) { m_IsInValidState = false; mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what(); } // import volume to the inter-results mitk::ImageWriteAccessor imac(registrationMethod->GetResampledMovingImage()); registeredB0Image->SetImportVolume( imac.GetData(), i, 0, mitk::Image::ReferenceMemory ); } // use the accumulateImageFilter as provided by the ItkAccumulateFilter method in the header file AccessFixedDimensionByItk_1(registeredB0Image, ItkAccumulateFilter, (4), b0referenceImage ); } // // (2) Split the diffusion image into a 3d+t regular image, extract only the weighted images // SplitFilterType::Pointer split_filter = SplitFilterType::New(); split_filter->SetInput (itkVectorImagePointer ); split_filter->SetExtractAllAboveThreshold(8, static_cast(input->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap() ); try { split_filter->Update(); } catch( const itk::ExceptionObject &e) { m_IsInValidState = false; mitkThrow() << " Caught exception from SplitImageFilter : " << e.what(); } mitk::Image::Pointer splittedImage = mitk::Image::New(); splittedImage->InitializeByItk( split_filter->GetOutput() ); splittedImage->SetImportChannel( split_filter->GetOutput()->GetBufferPointer(), mitk::Image::CopyMemory ); // // (3) Use again the time-selector to access the components separately in order // to perform the registration of Image -> unweighted reference // RegistrationMethod::Pointer weightedRegistrationMethod = RegistrationMethod::New(); weightedRegistrationMethod->SetTransformToAffine(); weightedRegistrationMethod->SetCrossModalityOn(); // // - (3.1) Set the reference image // - a single b0 image // - average over the registered b0 images if multiple present // weightedRegistrationMethod->SetFixedImage( b0referenceImage ); // use the advanced (windowed sinc) interpolation weightedRegistrationMethod->SetUseAdvancedInterpolation(true); weightedRegistrationMethod->SetVerboseOn(); // // - (3.2) Register all timesteps in the splitted image onto the first reference // unsigned int maxImageIdx = splittedImage->GetTimeSteps(); mitk::TimeGeometry* tsg = splittedImage->GetTimeGeometry(); mitk::ProportionalTimeGeometry* ptg = dynamic_cast(tsg); ptg->Expand(maxImageIdx+1); ptg->SetTimeStepGeometry( ptg->GetGeometryForTimeStep(0), maxImageIdx ); mitk::Image::Pointer registeredWeighted = mitk::Image::New(); registeredWeighted->Initialize( splittedImage->GetPixelType(0), *tsg ); // insert the first unweighted reference as the first volume // in own scope to release the accessor asap after copy { mitk::ImageWriteAccessor imac(b0referenceImage); registeredWeighted->SetImportVolume( imac.GetData(), 0,0, mitk::Image::CopyMemory ); } // mitk::Image::Pointer registeredWeighted = splittedImage->Clone(); // this time start at 0, we have only gradient images in the 3d+t file // the reference image comes form an other image mitk::ImageTimeSelector::Pointer t_selector_w = mitk::ImageTimeSelector::New(); t_selector_w->SetInput( splittedImage ); // store the rotation parts of the transformations in a vector typedef RegistrationMethod::TransformMatrixType MatrixType; std::vector< MatrixType > estimated_transforms; for( unsigned int i=0; iSetTimeNr(i); t_selector_w->Update(); weightedRegistrationMethod->SetMovingImage( t_selector_w->GetOutput() ); try { MITK_INFO << " === (" << i+1 <<"/"<< maxImageIdx << ") :: Starting registration"; weightedRegistrationMethod->Update(); } catch( const itk::ExceptionObject& e) { m_IsInValidState = false; mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what(); } // allow expansion mitk::ImageWriteAccessor imac(weightedRegistrationMethod->GetResampledMovingImage()); registeredWeighted->SetImportVolume( imac.GetData(), i+1, 0, mitk::Image::CopyMemory); estimated_transforms.push_back( weightedRegistrationMethod->GetLastRotationMatrix() ); } // // (4) Cast the resulting image back to an diffusion weighted image // mitk::DiffusionPropertyHelper::GradientDirectionsContainerType *gradients = static_cast( input->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradients_new = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New(); mitk::DiffusionPropertyHelper::GradientDirectionType bzero_vector; bzero_vector.fill(0); // compose the direction vector // - no direction for the first image // - correct ordering of the directions based on the index list gradients_new->push_back( bzero_vector ); SplitFilterType::IndexListType index_list = split_filter->GetIndexList(); SplitFilterType::IndexListType::const_iterator lIter = index_list.begin(); while( lIter != index_list.end() ) { gradients_new->push_back( gradients->at( *lIter ) ); ++lIter; } registeredWeighted->SetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradients_new.GetPointer() )); registeredWeighted->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(input->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); // // (5) Adapt the gradient directions according to the estimated transforms // typedef mitk::DiffusionImageCorrectionFilter CorrectionFilterType; CorrectionFilterType::Pointer corrector = CorrectionFilterType::New(); mitk::Image::Pointer output = registeredWeighted; corrector->SetImage( output ); corrector->CorrectDirections( estimated_transforms ); // // (6) Pass the corrected image to the filters output port // m_CurrentStep += 1; this->GetOutput()->Initialize( output ); - this->GetOutput()->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( output->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); - this->GetOutput()->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast( output->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - this->GetOutput()->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(output->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); + mitk::DiffusionPropertyHelper::CopyProperties(output, this->GetOutput(), true); + this->GetOutput()->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( output->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); + this->GetOutput()->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast( output->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); + this->GetOutput()->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(output->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); mitk::DiffusionPropertyHelper propertyHelper( this->GetOutput() ); propertyHelper.InitializeImage(); this->GetOutput()->Modified(); } #endif // MITKDWIHEADMOTIONCORRECTIONFILTER_CPP diff --git a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkRegistrationWrapper.cpp b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkRegistrationWrapper.cpp index 1a787ea098..b9957edc05 100644 --- a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkRegistrationWrapper.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/Registration/mitkRegistrationWrapper.cpp @@ -1,257 +1,255 @@ #include "mitkRegistrationWrapper.h" #include "mitkPyramidImageRegistrationMethod.h" #include "mitkImage.h" #include #include "itkB0ImageExtractionImageFilter.h" #include #include #include #include #include #include #include #include #include #include void mitk::RegistrationWrapper::ApplyTransformationToImage(mitk::Image::Pointer img, const mitk::RegistrationWrapper::RidgidTransformType &transformation,double* offset, mitk::Image* resampleReference, bool binary) { if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( img ) ) { ItkImageType::Pointer itkImage = ItkImageType::New(); CastToItkImage(img, itkImage); typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension); for (int i = 0; i<6;++i) parameters[i] = transformation[i]; rtransform->SetParameters( parameters ); mitk::Point3D origin = img->GetGeometry()->GetOrigin(); // overwrite origin only if an offset was supplied if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0) { origin[0]=offset[0]; origin[1]=offset[1]; origin[2]=offset[2]; } mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(origin); itk::Matrix dir = itkImage->GetDirection(); itk::Matrix transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix())); itk::Matrix newDirection = transM * dir; itkImage->SetOrigin(newOrigin); itkImage->SetDirection(newDirection); // Perform Resampling if reference image is provided if (resampleReference != nullptr) { typedef itk::ResampleImageFilter ResampleFilterType; ItkImageType::Pointer itkReference = ItkImageType::New(); CastToItkImage(resampleReference,itkReference); typedef itk::Function::WelchWindowFunction<4> WelchWindowFunction; typedef itk::WindowedSincInterpolateImageFunction< ItkImageType, 4,WelchWindowFunction> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::LinearInterpolateImageFunction< ItkImageType> LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::NearestNeighborInterpolateImageFunction< ItkImageType, double > NearestNeighborInterpolatorType; NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New(); typedef itk::BSplineInterpolateImageFunction< ItkImageType, double > BSplineInterpolatorType; BSplineInterpolatorType::Pointer bSpline_interpolator = BSplineInterpolatorType::New(); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkImage); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); if (binary) resampler->SetInterpolator(nn_interpolator); else resampler->SetInterpolator(lin_interpolator); resampler->Update(); GrabItkImageMemory(resampler->GetOutput(), img); } else { // !! CastToItk behaves very differently depending on the original data type // if the target type is the same as the original, only a pointer to the data is set // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed // GrabItkImageMemory - is not necessary in this case since we worked on the original data // See Bug 17538 - this is why we duplicate the itkImage first and then create a new mitk::Image from it. itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImage); duplicator->Update(); GrabItkImageMemory(duplicator->GetOutput(), img); } } else { mitk::Image::Pointer diffImages = dynamic_cast(img.GetPointer()); // mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientDirections = // static_cast( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension); for (int i = 0; i<6;++i) { parameters[i] = transformation[i]; } rtransform->SetParameters( parameters ); typedef itk::VectorImage ITKDiffusionImageType; ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(diffImages, itkVectorImagePointer); mitk::Point3D b0origin = itkVectorImagePointer->GetOrigin(); // overwrite origin only if an offset was supplied if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0) { b0origin[0]=offset[0]; b0origin[1]=offset[1]; b0origin[2]=offset[2]; } mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(b0origin); itk::Matrix dir = itkVectorImagePointer->GetDirection(); itk::Matrix transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix())); itk::Matrix newDirection = transM * dir; itkVectorImagePointer->SetOrigin(newOrigin); itkVectorImagePointer->SetDirection(newDirection); // !! CastToItk behaves very differently depending on the original data type // if the target type is the same as the original, only a pointer to the data is set // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed // GrabItkImageMemory - is not necessary in this case since we worked on the original data // See Bug 17538 - this is why we duplicate the itkImage first and then create a new mitk::Image from it. itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkVectorImagePointer); duplicator->Update(); GrabItkImageMemory(duplicator->GetOutput(), img); - img->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( diffImages->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); - img->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast( diffImages->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - img->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(diffImages->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); + mitk::DiffusionPropertyHelper::CopyProperties(diffImages, img, false); mitk::DiffusionPropertyHelper propertyHelper( img ); propertyHelper.InitializeImage(); mitk::DiffusionImageCorrectionFilter::Pointer correctionFilter = mitk::DiffusionImageCorrectionFilter::New(); // For Diff. Images: Need to rotate the gradients (works in-place) correctionFilter->SetImage(img); correctionFilter->CorrectDirections(transM.GetVnlMatrix()); } } void mitk::RegistrationWrapper::GetTransformation(mitk::Image::Pointer fixedImage, mitk::Image::Pointer movingImage, RidgidTransformType transformation,double* offset, bool useSameOrigin, mitk::Image* mask) { // Handle the case that fixed/moving image is a DWI image mitk::Image* fixedDwi = dynamic_cast (fixedImage.GetPointer()); mitk::Image* movingDwi = dynamic_cast (movingImage.GetPointer()); itk::B0ImageExtractionImageFilter::Pointer b0Extraction = itk::B0ImageExtractionImageFilter::New(); offset[0]=offset[1]=offset[2]=0; typedef itk::VectorImage ITKDiffusionImageType; if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( fixedDwi ) ) { // Set b0 extraction as fixed image mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer fixedGradientDirections = static_cast( fixedDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); ITKDiffusionImageType::Pointer itkFixedDwiPointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(fixedDwi, itkFixedDwiPointer); b0Extraction->SetInput( itkFixedDwiPointer ); b0Extraction->SetDirections(fixedGradientDirections); b0Extraction->Update(); mitk::Image::Pointer tmp = mitk::Image::New(); tmp->InitializeByItk(b0Extraction->GetOutput()); tmp->SetVolume(b0Extraction->GetOutput()->GetBufferPointer()); fixedImage = tmp; } if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( movingDwi )) { // Set b0 extraction as moving image mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer movingGradientDirections = static_cast( movingDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); ITKDiffusionImageType::Pointer itkMovingDwiPointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(movingDwi, itkMovingDwiPointer); b0Extraction->SetInput( itkMovingDwiPointer ); b0Extraction->SetDirections(movingGradientDirections); b0Extraction->Update(); mitk::Image::Pointer tmp = mitk::Image::New(); tmp->InitializeByItk(b0Extraction->GetOutput()); tmp->SetVolume(b0Extraction->GetOutput()->GetBufferPointer()); movingImage = tmp; } // align the offsets of the two images. this is done to avoid non-overlapping initialization // Point3D origin = fixedImage->GetGeometry()->GetOrigin(); Point3D center = fixedImage->GetGeometry()->GetCenter(); Point3D centerMoving = movingImage->GetGeometry()->GetCenter(); Point3D originMoving = movingImage->GetGeometry()->GetOrigin(); mitk::Image::Pointer tmpImage = movingImage->Clone(); if (useSameOrigin) { offset[0] = (originMoving[0]-centerMoving[0])+center[0]; offset[1] = (originMoving[1]-centerMoving[1])+center[1]; offset[2] = (originMoving[2]-centerMoving[2])+center[2]; Point3D translatedOrigin; translatedOrigin[0]= offset[0]; translatedOrigin[1]= offset[1]; translatedOrigin[2]= offset[2]; tmpImage->GetGeometry()->SetOrigin(translatedOrigin); } // Start registration mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New(); registrationMethod->SetFixedImage( fixedImage ); if (mask != nullptr) { registrationMethod->SetFixedImageMask(mask); registrationMethod->SetUseFixedImageMask(true); } else { registrationMethod->SetUseFixedImageMask(false); } registrationMethod->SetTransformToRigid(); registrationMethod->SetCrossModalityOn(); registrationMethod->SetVerboseOn(); registrationMethod->SetMovingImage(tmpImage); registrationMethod->Update(); registrationMethod->GetParameters(transformation); // first three: euler angles, last three translation } diff --git a/Modules/DiffusionImaging/DiffusionCore/src/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp b/Modules/DiffusionImaging/DiffusionCore/src/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp index 9672394102..20f45ad109 100644 --- a/Modules/DiffusionImaging/DiffusionCore/src/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/src/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp @@ -1,505 +1,568 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDiffusionPropertyHelper.h" #include #include #include #include #include const std::string mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME = "DWMRI.GradientDirections"; const std::string mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME = "DWMRI.OriginalGradientDirections"; const std::string mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME = "DWMRI.MeasurementFrame"; const std::string mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME = "DWMRI.ReferenceBValue"; const std::string mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME = "DWMRI.BValueMap"; const std::string mitk::DiffusionPropertyHelper::MODALITY = "DWMRI.Modality"; +const std::string mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS = "DWMRI.KeepOriginalDirections"; mitk::DiffusionPropertyHelper::DiffusionPropertyHelper() { } mitk::DiffusionPropertyHelper::DiffusionPropertyHelper( mitk::Image* inputImage) : m_Image( inputImage ) { // Update props } mitk::DiffusionPropertyHelper::~DiffusionPropertyHelper() { } mitk::DiffusionPropertyHelper::ImageType::Pointer mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk::Image* image) { - ImageType::Pointer vectorImage = ImageType::New(); - mitk::CastToItkImage(image, vectorImage); - return vectorImage; + ImageType::Pointer vectorImage = ImageType::New(); + mitk::CastToItkImage(image, vectorImage); + return vectorImage; } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer - mitk::DiffusionPropertyHelper::CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions) +mitk::DiffusionPropertyHelper::CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionsContainerType::Pointer newDirections = GradientDirectionsContainerType::New(); // fill new direction container for(GradientDirectionsContainerType::ConstIterator gdcitOld = directions->Begin(); - gdcitOld != directions->End(); ++gdcitOld) + gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirections->Begin(); - gdcitNew != newDirections->End(); ++gdcitNew) + gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } void mitk::DiffusionPropertyHelper::AverageRedundantGradients(double precision) { mitk::GradientDirectionsProperty* DirectionsProperty = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ); GradientDirectionsContainerType::Pointer oldDirs = DirectionsProperty->GetGradientDirectionsContainer(); GradientDirectionsContainerType::Pointer newDirs = - CalcAveragedDirectionSet(precision, oldDirs); + CalcAveragedDirectionSet(precision, oldDirs); // if sizes equal, we do not need to do anything in this function if(oldDirs->size() == newDirs->size()) return; // new image ImageType::Pointer oldImage = ImageType::New(); mitk::CastToItkImage( m_Image, oldImage); ImageType::Pointer newITKImage = ImageType::New(); newITKImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing newITKImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin newITKImage->SetDirection( oldImage->GetDirection() ); // Set the image direction newITKImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->SetVectorLength( newDirs->size() ); newITKImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); newITKImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(newITKImage, newITKImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel ImageType::PixelType newVec; newVec.SetSize(newDirs->size()); newVec.AllocateElements(newDirs->size()); // find which gradients should be averaged GradientDirectionsContainerType::Pointer oldDirections = oldDirs; std::vector > dirIndices; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirs->Begin(); - gdcitNew != newDirs->End(); ++gdcitNew) + gdcitNew != newDirs->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin(); - gdcitOld != oldDirections->End(); ++gdcitOld) + gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { //MITK_INFO << gdcitNew.Value() << " " << gdcitOld.Value(); dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress //typename ImageType::IndexType ind = newIt.GetIndex(); //ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; iSetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); m_Image->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( newDirs ) ); ApplyMeasurementFrameAndRotationMatrix(); UpdateBValueMap(); std::cout << std::endl; } void mitk::DiffusionPropertyHelper::ApplyMeasurementFrameAndRotationMatrix() { if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) { return; } GradientDirectionsContainerType::Pointer originalDirections = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); MeasurementFrameType measurementFrame = GetMeasurementFrame(m_Image); mitk::Vector3D s = m_Image->GetGeometry()->GetSpacing(); mitk::VnlVector c0 = m_Image->GetGeometry()->GetMatrixColumn(0)/s[0]; mitk::VnlVector c1 = m_Image->GetGeometry()->GetMatrixColumn(1)/s[1]; mitk::VnlVector c2 = m_Image->GetGeometry()->GetMatrixColumn(2)/s[2]; MeasurementFrameType imageRotationMatrix; imageRotationMatrix[0][0] = c0[0]; imageRotationMatrix[1][0] = c0[1]; imageRotationMatrix[2][0] = c0[2]; imageRotationMatrix[0][1] = c1[0]; imageRotationMatrix[1][1] = c1[1]; imageRotationMatrix[2][1] = c1[2]; imageRotationMatrix[0][2] = c2[0]; imageRotationMatrix[1][2] = c2[1]; imageRotationMatrix[2][2] = c2[2]; GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New(); if( originalDirections.IsNull() || ( originalDirections->size() == 0 ) ) { // original direction container was not set return; } - MITK_INFO << "Applying measurement frame to diffusion-gradient directions:"; - std::cout << measurementFrame << std::endl; - MITK_INFO << "Applying image totation to diffusion-gradient directions:"; - std::cout << imageRotationMatrix << std::endl; + bool keep_originals = false; + m_Image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS.c_str(), keep_originals); + + if (!keep_originals) + { + MITK_INFO << "Applying measurement frame to diffusion-gradient directions:"; + std::cout << measurementFrame << std::endl; + MITK_INFO << "Applying image totation to diffusion-gradient directions:"; + std::cout << imageRotationMatrix << std::endl; + } int c = 0; for(GradientDirectionsContainerType::ConstIterator gdcit = originalDirections->Begin(); gdcit != originalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); - vec = vec.pre_multiply(measurementFrame); - vec = vec.pre_multiply(imageRotationMatrix); + if (!keep_originals) + { + vec = vec.pre_multiply(measurementFrame); + vec = vec.pre_multiply(imageRotationMatrix); + } directions->InsertElement(c, vec); c++; } m_Image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( directions ) ); } void mitk::DiffusionPropertyHelper::UnApplyMeasurementFrameAndRotationMatrix() { if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) { return; } GradientDirectionsContainerType::Pointer modifiedDirections = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); MeasurementFrameType measurementFrame = GetMeasurementFrame(m_Image); measurementFrame = vnl_matrix_inverse(measurementFrame).pinverse(); mitk::Vector3D s = m_Image->GetGeometry()->GetSpacing(); mitk::VnlVector c0 = m_Image->GetGeometry()->GetMatrixColumn(0)/s[0]; mitk::VnlVector c1 = m_Image->GetGeometry()->GetMatrixColumn(1)/s[1]; mitk::VnlVector c2 = m_Image->GetGeometry()->GetMatrixColumn(2)/s[2]; MeasurementFrameType imageRotationMatrix; imageRotationMatrix[0][0] = c0[0]; imageRotationMatrix[1][0] = c0[1]; imageRotationMatrix[2][0] = c0[2]; imageRotationMatrix[0][1] = c1[0]; imageRotationMatrix[1][1] = c1[1]; imageRotationMatrix[2][1] = c1[2]; imageRotationMatrix[0][2] = c2[0]; imageRotationMatrix[1][2] = c2[1]; imageRotationMatrix[2][2] = c2[2]; imageRotationMatrix = vnl_matrix_inverse(imageRotationMatrix).pinverse(); GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New(); if( modifiedDirections.IsNull() || ( modifiedDirections->size() == 0 ) ) { // original direction container was not set return; } - MITK_INFO << "Reverting image totation to diffusion-gradient directions:"; - std::cout << imageRotationMatrix << std::endl; - MITK_INFO << "Reverting measurement frame to diffusion-gradient directions:"; - std::cout << measurementFrame << std::endl; + bool keep_originals = false; + m_Image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS.c_str(), keep_originals); + + if (!keep_originals) + { + MITK_INFO << "Reverting image totation to diffusion-gradient directions:"; + std::cout << imageRotationMatrix << std::endl; + MITK_INFO << "Reverting measurement frame to diffusion-gradient directions:"; + std::cout << measurementFrame << std::endl; + } int c = 0; for(GradientDirectionsContainerType::ConstIterator gdcit = modifiedDirections->Begin(); gdcit != modifiedDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); - vec = vec.pre_multiply(imageRotationMatrix); - vec = vec.pre_multiply(measurementFrame); + if (!keep_originals) + { + vec = vec.pre_multiply(imageRotationMatrix); + vec = vec.pre_multiply(measurementFrame); + } directions->InsertElement(c, vec); c++; } m_Image->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( directions ) ); } + +void mitk::DiffusionPropertyHelper::ClearMeasurementFrameAndRotationMatrixFromGradients(mitk::Image* image) +{ + + if( image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) + { + return; + } + + GradientDirectionsContainerType::Pointer originalDirections = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); + + GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New(); + + if( originalDirections.IsNull() || ( originalDirections->size() == 0 ) ) + { + // original direction container was not set + return; + } + + int c = 0; + for(GradientDirectionsContainerType::ConstIterator gdcit = originalDirections->Begin(); + gdcit != originalDirections->End(); ++gdcit) + { + vnl_vector vec = gdcit.Value(); + directions->InsertElement(c, vec); + c++; + } + + image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS.c_str(), mitk::BoolProperty::New(true) ); + image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( directions ) ); +} + + void mitk::DiffusionPropertyHelper::UpdateBValueMap() { BValueMapType b_ValueMap; if(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).IsNull()) { } else { b_ValueMap = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); } if(!b_ValueMap.empty()) { b_ValueMap.clear(); } if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).IsNotNull() ) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); GradientDirectionsContainerType::ConstIterator gdcit; for( gdcit = directions->Begin(); gdcit != directions->End(); ++gdcit) { b_ValueMap[GetB_Value(gdcit.Index())].push_back(gdcit.Index()); } } m_Image->SetProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( b_ValueMap ) ); } bool mitk::DiffusionPropertyHelper::AreAlike(GradientDirectionType g1, - GradientDirectionType g2, - double precision) + GradientDirectionType g2, + double precision) { GradientDirectionType diff = g1 - g2; GradientDirectionType diff2 = g1 + g2; return diff.two_norm() < precision || diff2.two_norm() < precision; } float mitk::DiffusionPropertyHelper::GetB_Value(unsigned int i) { GradientDirectionsContainerType::Pointer directions = static_cast( m_Image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); float b_value = static_cast(m_Image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); if(i > directions->Size()-1) return -1; if(directions->ElementAt(i).one_norm() <= 0.0) { return 0; } else { double twonorm = directions->ElementAt(i).two_norm(); double bval = b_value*twonorm*twonorm; if (bval<0) bval = ceil(bval - 0.5); else bval = floor(bval + 0.5); return bval; } } +void mitk::DiffusionPropertyHelper::CopyProperties(mitk::Image* source, mitk::Image* target, bool ignore_original_gradients) +{ + mitk::PropertyList::Pointer props = source->GetPropertyList()->Clone(); + if (ignore_original_gradients) + props->RemoveProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME); + target->SetPropertyList(props); +} + void mitk::DiffusionPropertyHelper::InitializeImage() { + if ( m_Image->GetProperty(mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS.c_str()).IsNull() ) + m_Image->SetProperty( mitk::DiffusionPropertyHelper::KEEP_ORIGINAL_DIRECTIONS.c_str(), mitk::BoolProperty::New(false) ); + if( m_Image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() ) { // we don't have the original gradient directions. Therefore use the modified directions and roatate them back. this->UnApplyMeasurementFrameAndRotationMatrix(); } else this->ApplyMeasurementFrameAndRotationMatrix(); this->UpdateBValueMap(); // initialize missing properties mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( m_Image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); m_Image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( identity )); } } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::DataNode* node) { - if ( node==nullptr ) - return false; - if ( node->GetData()==nullptr ) - return false; - return IsDiffusionWeightedImage(dynamic_cast(node->GetData())); + if ( node==nullptr ) + return false; + if ( node->GetData()==nullptr ) + return false; + return IsDiffusionWeightedImage(dynamic_cast(node->GetData())); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::Image * image) { bool isDiffusionWeightedImage( true ); if( image == nullptr ) { isDiffusionWeightedImage = false; } if( isDiffusionWeightedImage ) { mitk::FloatProperty::Pointer referenceBValue = dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer()); if( referenceBValue.IsNull() ) { isDiffusionWeightedImage = false; } } unsigned int gradientDirections( 0 ); if( isDiffusionWeightedImage ) { mitk::GradientDirectionsProperty::Pointer gradientDirectionsProperty = dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer()); if( gradientDirectionsProperty.IsNull() ) { isDiffusionWeightedImage = false; } else { gradientDirections = gradientDirectionsProperty->GetGradientDirectionsContainer()->size(); } } if( isDiffusionWeightedImage ) { unsigned int components = image->GetPixelType().GetNumberOfComponents(); if( components != gradientDirections ) { isDiffusionWeightedImage = false; } } return isDiffusionWeightedImage; } const mitk::DiffusionPropertyHelper::BValueMapType & mitk::DiffusionPropertyHelper::GetBValueMap(const mitk::Image *image) { return dynamic_cast(image->GetProperty(BVALUEMAPPROPERTYNAME.c_str()).GetPointer())->GetBValueMap(); } float mitk::DiffusionPropertyHelper::GetReferenceBValue(const mitk::Image *image) { - return dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer())->GetValue(); + return dynamic_cast(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer())->GetValue(); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame(const mitk::Image *image) { mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast( image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer()); if( mf.IsNull() ) { //no measurement frame present, identity is assumed MeasurementFrameType identity; identity.set_identity(); mf = mitk::MeasurementFrameProperty::New( identity ); } return mf->GetMeasurementFrame(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer(const mitk::Image *image) { return dynamic_cast(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer(); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage() const { return IsDiffusionWeightedImage(m_Image); } const mitk::DiffusionPropertyHelper::BValueMapType &mitk::DiffusionPropertyHelper::GetBValueMap() const { return GetBValueMap(m_Image); } float mitk::DiffusionPropertyHelper::GetReferenceBValue() const { return GetReferenceBValue(m_Image); } const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame() const { return GetMeasurementFrame(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer() const { return GetOriginalGradientContainer(m_Image); } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer() const { return GetGradientContainer(m_Image); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp index cc212bd699..b921e98c4a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp @@ -1,2301 +1,2203 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include #include #include #include #include #include // Multishell includes #include // Multishell Functors #include #include #include #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkPreprocessingView::VIEW_ID = "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; QmitkPreprocessingView::QmitkPreprocessingView() : QmitkAbstractView(), m_Controls(nullptr) { } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); } } void QmitkPreprocessingView::SetFocus() { m_Controls->m_MirrorGradientToHalfSphereButton->setFocus(); } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { m_Controls->m_NormalizationMaskBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_SelctedImageComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MergeDwiBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isQbi, isDti); mitk::NodePredicateAnd::Pointer noDiffusionImage = mitk::NodePredicateAnd::New(isMitkImage, mitk::NodePredicateNot::New(isDiffusionImage)); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer binaryNoDiffusionImage = mitk::NodePredicateAnd::New(noDiffusionImage, isBinaryPredicate); m_Controls->m_NormalizationMaskBox->SetPredicate(binaryNoDiffusionImage); m_Controls->m_SelctedImageComboBox->SetPredicate(noDiffusionImage); m_Controls->m_MergeDwiBox->SetPredicate(isMitkImage); m_Controls->m_ExtractBrainMask->setVisible(false); m_Controls->m_BrainMaskIterationsBox->setVisible(false); m_Controls->m_ResampleIntFrame->setVisible(false); connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) ); connect( (QObject*)(m_Controls->m_ProjectSignalButton), SIGNAL(clicked()), this, SLOT(DoProjectSignal()) ); connect( (QObject*)(m_Controls->m_B_ValueMap_Rounder_SpinBox), SIGNAL(valueChanged(int)), this, SLOT(UpdateDwiBValueMapRounder(int))); connect( (QObject*)(m_Controls->m_CreateLengthCorrectedDwi), SIGNAL(clicked()), this, SLOT(DoLengthCorrection()) ); connect( (QObject*)(m_Controls->m_NormalizeImageValuesButton), SIGNAL(clicked()), this, SLOT(DoDwiNormalization()) ); connect( (QObject*)(m_Controls->m_ModifyDirection), SIGNAL(clicked()), this, SLOT(DoApplyDirectionMatrix()) ); connect( (QObject*)(m_Controls->m_ModifySpacingButton), SIGNAL(clicked()), this, SLOT(DoApplySpacing()) ); connect( (QObject*)(m_Controls->m_ModifyOriginButton), SIGNAL(clicked()), this, SLOT(DoApplyOrigin()) ); connect( (QObject*)(m_Controls->m_ResampleImageButton), SIGNAL(clicked()), this, SLOT(DoResampleImage()) ); connect( (QObject*)(m_Controls->m_ResampleTypeBox), SIGNAL(currentIndexChanged(int)), this, SLOT(DoUpdateInterpolationGui(int)) ); connect( (QObject*)(m_Controls->m_CropImageButton), SIGNAL(clicked()), this, SLOT(DoCropImage()) ); connect( (QObject*)(m_Controls->m_RemoveGradientButton), SIGNAL(clicked()), this, SLOT(DoRemoveGradient()) ); connect( (QObject*)(m_Controls->m_ExtractGradientButton), SIGNAL(clicked()), this, SLOT(DoExtractGradient()) ); connect( (QObject*)(m_Controls->m_FlipAxis), SIGNAL(clicked()), this, SLOT(DoFlipAxis()) ); connect( (QObject*)(m_Controls->m_FlipGradientsButton), SIGNAL(clicked()), this, SLOT(DoFlipGradientDirections()) ); + connect( (QObject*)(m_Controls->m_ClearRotationButton), SIGNAL(clicked()), this, SLOT(DoClearRotationOfGradients()) ); + connect( (QObject*)(m_Controls->m_SelctedImageComboBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnImageSelectionChanged()) ); m_Controls->m_NormalizationMaskBox->SetZeroEntryText("--"); } } void QmitkPreprocessingView::DoFlipAxis() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(node) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) ); if (isDiffusionImage) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); itk::FixedArray flipAxes; flipAxes[0] = m_Controls->m_FlipX->isChecked(); flipAxes[1] = m_Controls->m_FlipY->isChecked(); flipAxes[2] = m_Controls->m_FlipZ->isChecked(); itk::FlipImageFilter< ItkDwiType >::Pointer flipper = itk::FlipImageFilter< ItkDwiType >::New(); flipper->SetInput(itkVectorImagePointer); flipper->SetFlipAxes(flipAxes); flipper->Update(); - mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer oldGradients - = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + GradProp::GradientDirectionsContainerType::Pointer oldGradients + = static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); - mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer newGradients - = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New(); + GradProp::GradientDirectionsContainerType::Pointer newGradients + = GradProp::GradientDirectionsContainerType::New(); for (unsigned int i=0; iSize(); i++) { - mitk::GradientDirectionsProperty::GradientDirectionType g = oldGradients->GetElement(i); - mitk::GradientDirectionsProperty::GradientDirectionType newG = g; + GradProp::GradientDirectionType g = oldGradients->GetElement(i); + GradProp::GradientDirectionType newG = g; if (flipAxes[0]) { newG[0] *= -1; } if (flipAxes[1]) { newG[1] *= -1; } if (flipAxes[2]) { newG[2] *= -1; } newGradients->InsertElement(i, newG); } mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( newGradients ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, true); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( newGradients ) ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin()); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_flipped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() == 1 ) { AccessFixedDimensionByItk(image, TemplatedFlipAxis,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedFlipAxis(itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } itk::FixedArray flipAxes; flipAxes[0] = m_Controls->m_FlipX->isChecked(); flipAxes[1] = m_Controls->m_FlipY->isChecked(); flipAxes[2] = m_Controls->m_FlipZ->isChecked(); typename itk::FlipImageFilter< itk::Image >::Pointer flipper = itk::FlipImageFilter< itk::Image >::New(); flipper->SetInput(itkImage); flipper->SetFlipAxes(flipAxes); flipper->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() ); newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin()); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_flipped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoRemoveGradient() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } std::vector< unsigned int > channelsToRemove; channelsToRemove.push_back(m_Controls->m_RemoveGradientBox->value()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); itk::RemoveDwiChannelFilter< short >::Pointer filter = itk::RemoveDwiChannelFilter< short >::New(); filter->SetInput(itkVectorImagePointer); filter->SetChannelIndices(channelsToRemove); - filter->SetDirections( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + filter->SetDirections( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( filter->GetNewDirections() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, true); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetNewDirections() ) ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_removedgradients").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoExtractGradient() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); unsigned int channel = m_Controls->m_ExtractGradientBox->value(); itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New(); filter->SetInput( itkVectorImagePointer); filter->SetChannelIndex(channel); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_direction-"+QString::number(channel)).toStdString().c_str() ); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::DoCropImage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); ItkDwiType::SizeType lower; ItkDwiType::SizeType upper; lower[0] = m_Controls->m_XstartBox->value(); lower[1] = m_Controls->m_YstartBox->value(); lower[2] = m_Controls->m_ZstartBox->value(); upper[0] = m_Controls->m_XendBox->value(); upper[1] = m_Controls->m_YendBox->value(); upper[2] = m_Controls->m_ZendBox->value(); itk::CropImageFilter< ItkDwiType, ItkDwiType >::Pointer cropper = itk::CropImageFilter< ItkDwiType, ItkDwiType >::New(); cropper->SetLowerBoundaryCropSize(lower); cropper->SetUpperBoundaryCropSize(upper); cropper->SetInput( itkVectorImagePointer ); cropper->Update(); ItkDwiType::Pointer itkOutImage = cropper->GetOutput(); ItkDwiType::DirectionType dir = itkOutImage->GetDirection(); itk::Point origin = itkOutImage->GetOrigin(); itk::Point t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2]; t= dir*t; origin[0] += t[0]; origin[1] += t[1]; origin[2] += t[2]; itkOutImage->SetOrigin(origin); mitk::Image::Pointer newimage = mitk::GrabItkImageMemory( itkOutImage ); - - newimage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) - ->GetGradientDirectionsContainer() ) ); - - newimage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newimage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newimage ); + PropHelper::CopyProperties(image, newimage, false); + PropHelper propertyHelper( newimage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newimage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedCropImage,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedCropImage( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } ItkDwiType::SizeType lower; ItkDwiType::SizeType upper; lower[0] = m_Controls->m_XstartBox->value(); lower[1] = m_Controls->m_YstartBox->value(); lower[2] = m_Controls->m_ZstartBox->value(); upper[0] = m_Controls->m_XendBox->value(); upper[1] = m_Controls->m_YendBox->value(); upper[2] = m_Controls->m_ZendBox->value(); typedef itk::Image ImageType; typename itk::CropImageFilter< ImageType, ImageType >::Pointer cropper = itk::CropImageFilter< ImageType, ImageType >::New(); cropper->SetLowerBoundaryCropSize(lower); cropper->SetUpperBoundaryCropSize(upper); cropper->SetInput(itkImage); cropper->Update(); typename ImageType::Pointer itkOutImage = cropper->GetOutput(); typename ImageType::DirectionType dir = itkOutImage->GetDirection(); itk::Point origin = itkOutImage->GetOrigin(); itk::Point t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2]; t= dir*t; origin[0] += t[0]; origin[1] += t[1]; origin[2] += t[2]; itkOutImage->SetOrigin(origin); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( itkOutImage.GetPointer() ); image->SetVolume( itkOutImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoApplySpacing() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { mitk::Vector3D spacing; spacing[0] = m_Controls->m_HeaderSpacingX->value(); spacing[1] = m_Controls->m_HeaderSpacingY->value(); spacing[2] = m_Controls->m_HeaderSpacingZ->value(); mitk::Image::Pointer newImage = image->Clone(); newImage->GetGeometry()->SetSpacing( spacing ); - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_newspacing").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedSetImageSpacing,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedSetImageSpacing( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) return; mitk::Vector3D spacing; spacing[0] = m_Controls->m_HeaderSpacingX->value(); spacing[1] = m_Controls->m_HeaderSpacingY->value(); spacing[2] = m_Controls->m_HeaderSpacingZ->value(); typedef itk::ImageDuplicator< itk::Image > DuplicateFilterType; typename DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); duplicator->SetInputImage( itkImage ); duplicator->Update(); typename itk::Image::Pointer newImage = duplicator->GetOutput(); newImage->SetSpacing(spacing); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( newImage.GetPointer() ); image->SetVolume( newImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_newspacing").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoApplyOrigin() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image)); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image)); if ( isDiffusionImage ) { mitk::Vector3D origin; origin[0] = m_Controls->m_HeaderOriginX->value(); origin[1] = m_Controls->m_HeaderOriginY->value(); origin[2] = m_Controls->m_HeaderOriginZ->value(); mitk::Image::Pointer newImage = image->Clone(); - newImage->GetGeometry()->SetOrigin( origin ); - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_neworigin").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedSetImageOrigin,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedSetImageOrigin( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Vector3D origin; origin[0] = m_Controls->m_HeaderOriginX->value(); origin[1] = m_Controls->m_HeaderOriginY->value(); origin[2] = m_Controls->m_HeaderOriginZ->value(); typedef itk::ImageDuplicator< itk::Image > DuplicateFilterType; typename DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); duplicator->SetInputImage( itkImage ); duplicator->Update(); typename itk::Image::Pointer newImage = duplicator->GetOutput(); newImage->SetOrigin(origin); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( newImage.GetPointer() ); image->SetVolume( newImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_neworigin").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoUpdateInterpolationGui(int i) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } switch (i) { case 0: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); break; } case 1: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); mitk::BaseGeometry* geom = image->GetGeometry(); m_Controls->m_ResampleDoubleX->setValue(geom->GetSpacing()[0]); m_Controls->m_ResampleDoubleY->setValue(geom->GetSpacing()[1]); m_Controls->m_ResampleDoubleZ->setValue(geom->GetSpacing()[2]); break; } case 2: { m_Controls->m_ResampleIntFrame->setVisible(true); m_Controls->m_ResampleDoubleFrame->setVisible(false); mitk::BaseGeometry* geom = image->GetGeometry(); m_Controls->m_ResampleIntX->setValue(geom->GetExtent(0)); m_Controls->m_ResampleIntY->setValue(geom->GetExtent(1)); m_Controls->m_ResampleIntZ->setValue(geom->GetExtent(2)); break; } default: { m_Controls->m_ResampleIntFrame->setVisible(false); m_Controls->m_ResampleDoubleFrame->setVisible(true); } } } void QmitkPreprocessingView::DoExtractBrainMask() { } void QmitkPreprocessingView::DoResampleImage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); typedef itk::ResampleDwiImageFilter< short > ResampleFilter; ResampleFilter::Pointer resampler = ResampleFilter::New(); resampler->SetInput( itkVectorImagePointer ); switch (m_Controls->m_ResampleTypeBox->currentIndex()) { case 0: { itk::Vector< double, 3 > samplingFactor; samplingFactor[0] = m_Controls->m_ResampleDoubleX->value(); samplingFactor[1] = m_Controls->m_ResampleDoubleY->value(); samplingFactor[2] = m_Controls->m_ResampleDoubleZ->value(); resampler->SetSamplingFactor(samplingFactor); break; } case 1: { itk::Vector< double, 3 > newSpacing; newSpacing[0] = m_Controls->m_ResampleDoubleX->value(); newSpacing[1] = m_Controls->m_ResampleDoubleY->value(); newSpacing[2] = m_Controls->m_ResampleDoubleZ->value(); resampler->SetNewSpacing(newSpacing); break; } case 2: { itk::ImageRegion<3> newRegion; newRegion.SetSize(0, m_Controls->m_ResampleIntX->value()); newRegion.SetSize(1, m_Controls->m_ResampleIntY->value()); newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value()); resampler->SetNewImageSize(newRegion); break; } default: { MITK_WARN << "Unknown resampling parameters!"; return; } } QString outAdd; switch (m_Controls->m_InterpolatorBox->currentIndex()) { case 0: { resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour); outAdd = "NearestNeighbour"; break; } case 1: { resampler->SetInterpolation(ResampleFilter::Interpolate_Linear); outAdd = "Linear"; break; } case 2: { resampler->SetInterpolation(ResampleFilter::Interpolate_BSpline); outAdd = "BSpline"; break; } case 3: { resampler->SetInterpolation(ResampleFilter::Interpolate_WindowedSinc); outAdd = "WindowedSinc"; break; } default: { resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour); outAdd = "NearestNeighbour"; } } resampler->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( resampler->GetOutput() ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) - ->GetGradientDirectionsContainer() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, false); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); imageNode->SetVisibility(false); GetDataStorage()->Add(imageNode, node); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedResampleImage,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedResampleImage( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } itk::Vector< double, 3 > newSpacing; itk::ImageRegion<3> newRegion; switch (m_Controls->m_ResampleTypeBox->currentIndex()) { case 0: { itk::Vector< double, 3 > sampling; sampling[0] = m_Controls->m_ResampleDoubleX->value(); sampling[1] = m_Controls->m_ResampleDoubleY->value(); sampling[2] = m_Controls->m_ResampleDoubleZ->value(); newSpacing = itkImage->GetSpacing(); newSpacing[0] /= sampling[0]; newSpacing[1] /= sampling[1]; newSpacing[2] /= sampling[2]; newRegion = itkImage->GetLargestPossibleRegion(); newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]); newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]); newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]); break; } case 1: { newSpacing[0] = m_Controls->m_ResampleDoubleX->value(); newSpacing[1] = m_Controls->m_ResampleDoubleY->value(); newSpacing[2] = m_Controls->m_ResampleDoubleZ->value(); itk::Vector< double, 3 > oldSpacing = itkImage->GetSpacing(); itk::Vector< double, 3 > sampling; sampling[0] = oldSpacing[0]/newSpacing[0]; sampling[1] = oldSpacing[1]/newSpacing[1]; sampling[2] = oldSpacing[2]/newSpacing[2]; newRegion = itkImage->GetLargestPossibleRegion(); newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]); newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]); newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]); break; } case 2: { newRegion.SetSize(0, m_Controls->m_ResampleIntX->value()); newRegion.SetSize(1, m_Controls->m_ResampleIntY->value()); newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value()); itk::ImageRegion<3> oldRegion = itkImage->GetLargestPossibleRegion(); itk::Vector< double, 3 > sampling; sampling[0] = (double)newRegion.GetSize(0)/oldRegion.GetSize(0); sampling[1] = (double)newRegion.GetSize(1)/oldRegion.GetSize(1); sampling[2] = (double)newRegion.GetSize(2)/oldRegion.GetSize(2); newSpacing = itkImage->GetSpacing(); newSpacing[0] /= sampling[0]; newSpacing[1] /= sampling[1]; newSpacing[2] /= sampling[2]; break; } default: { MITK_WARN << "Unknown resampling parameters!"; return; } } itk::Point origin = itkImage->GetOrigin(); origin[0] -= itkImage->GetSpacing()[0]/2; origin[1] -= itkImage->GetSpacing()[1]/2; origin[2] -= itkImage->GetSpacing()[2]/2; origin[0] += newSpacing[0]/2; origin[1] += newSpacing[1]/2; origin[2] += newSpacing[2]/2; typedef itk::Image ImageType; typename ImageType::Pointer outImage = ImageType::New(); outImage->SetSpacing( newSpacing ); outImage->SetOrigin( origin ); outImage->SetDirection( itkImage->GetDirection() ); outImage->SetLargestPossibleRegion( newRegion ); outImage->SetBufferedRegion( newRegion ); outImage->SetRequestedRegion( newRegion ); outImage->Allocate(); typedef itk::ResampleImageFilter ResampleFilter; typename ResampleFilter::Pointer resampler = ResampleFilter::New(); resampler->SetInput(itkImage); resampler->SetOutputParametersFromImage(outImage); QString outAdd; switch (m_Controls->m_InterpolatorBox->currentIndex()) { case 0: { typename itk::NearestNeighborInterpolateImageFunction::Pointer interp = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "NearestNeighbour"; break; } case 1: { typename itk::LinearInterpolateImageFunction::Pointer interp = itk::LinearInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "Linear"; break; } case 2: { typename itk::BSplineInterpolateImageFunction::Pointer interp = itk::BSplineInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "BSpline"; break; } case 3: { typename itk::WindowedSincInterpolateImageFunction::Pointer interp = itk::WindowedSincInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "WindowedSinc"; break; } default: { typename itk::NearestNeighborInterpolateImageFunction::Pointer interp = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "NearestNeighbour"; } } resampler->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( resampler->GetOutput() ); image->SetVolume( resampler->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoApplyDirectionMatrix() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::DirectionType newDirection; for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c); if (!item) return; newDirection[r][c] = item->text().toDouble(); } } ItkDwiType::Pointer itkDwi = ItkDwiType::New(); mitk::CastToItkImage(image, itkDwi); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkDwi); duplicator->Update(); itkDwi = duplicator->GetOutput(); - - //vnl_matrix_fixed< double,3,3 > oldInverseDirection = itkDwi->GetDirection().GetInverse(); - - mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer oldGradients - = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) - ->GetGradientDirectionsContainer(); - - mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer newGradients - = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New(); - - for (unsigned int i=0; iSize(); i++) - { - mitk::GradientDirectionsProperty::GradientDirectionType g = oldGradients->GetElement(i); -// double mag = g.magnitude(); -// g.normalize(); -// mitk::GradientDirectionsProperty::GradientDirectionType newG = oldInverseDirection*g; -// newG = newDirection.GetVnlMatrix()*newG; -// newG.normalize(); - newGradients->InsertElement(i, g); - } - itkDwi->SetDirection(newDirection); - mitk::Image::Pointer newDwi2 = mitk::GrabItkImageMemory( itkDwi.GetPointer() ); - - newDwi2->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( newGradients ) ); - - newDwi2->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newDwi2->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( newDwi2 ); + mitk::Image::Pointer newDwi2 = mitk::GrabItkImageMemory( itkDwi.GetPointer() ); + PropHelper::CopyProperties(image, newDwi2, false); + PropHelper propertyHelper( newDwi2 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi2 ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_newdirection").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance() ->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if( image->GetPixelType().GetNumberOfComponents() ) { AccessFixedDimensionByItk(image, TemplatedApplyRotation,3); } else { QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedApplyRotation( itk::Image* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } ItkDwiType::DirectionType newDirection; for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c); if (!item) return; newDirection[r][c] = item->text().toDouble(); } } typedef itk::Image ImageType; typename ImageType::Pointer newImage = ImageType::New(); newImage->SetSpacing( itkImage->GetSpacing() ); newImage->SetOrigin( itkImage->GetOrigin() ); newImage->SetDirection( newDirection ); newImage->SetLargestPossibleRegion( itkImage->GetLargestPossibleRegion() ); newImage->SetBufferedRegion( itkImage->GetLargestPossibleRegion() ); newImage->SetRequestedRegion( itkImage->GetLargestPossibleRegion() ); newImage->Allocate(); newImage->FillBuffer(0); itk::ImageRegionIterator< itk::Image > it(itkImage, itkImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { newImage->SetPixel(it.GetIndex(), it.Get()); ++it; } mitk::Image::Pointer newMitkImage = mitk::Image::New(); newMitkImage->InitializeByItk(newImage.GetPointer()); newMitkImage->SetVolume(newImage->GetBufferPointer()); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newMitkImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_newdirection").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoProjectSignal() { switch(m_Controls->m_ProjectionMethodBox->currentIndex()) { case 0: DoADCAverage(); break; case 1: DoAKCFit(); break; case 2: DoBiExpFit(); break; default: DoADCAverage(); } } void QmitkPreprocessingView::DoDwiNormalization() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } GradientDirectionContainerType::Pointer gradientContainer - = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + = static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); int b0Index = -1; for (unsigned int i=0; isize(); i++) { GradientDirectionType g = gradientContainer->GetElement(i); if (g.magnitude()<0.001) { b0Index = i; break; } } if (b0Index==-1) { return; } typedef itk::DwiNormilzationFilter FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); - filter->SetGradientDirections( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + filter->SetGradientDirections( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->SetNewMean(m_Controls->m_NewMean->value()); filter->SetNewStdev(m_Controls->m_NewStdev->value()); UcharImageType::Pointer itkImage = nullptr; if (m_Controls->m_NormalizationMaskBox->GetSelectedNode().IsNotNull()) { itkImage = UcharImageType::New(); if ( dynamic_cast(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()) != nullptr ) { mitk::CastToItkImage( dynamic_cast(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()), itkImage ); } filter->SetMaskImage(itkImage); } filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) - ->GetGradientDirectionsContainer() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, false); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_normalized").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoLengthCorrection() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } typedef itk::DwiGradientLengthCorrectionFilter FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); filter->SetReferenceBValue( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); - filter->SetReferenceGradientDirectionContainer( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + filter->SetReferenceGradientDirectionContainer( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); - mitk::Image::Pointer newImage = mitk::Image::New();//mitk::ImportItkImage( itkVectorImagePointer ); + mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( itkVectorImagePointer.GetPointer() ); newImage->SetImportVolume( itkVectorImagePointer->GetBufferPointer(), 0, 0, mitk::Image::CopyMemory); itkVectorImagePointer->GetPixelContainer()->ContainerManageMemoryOff(); - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradientDirectionContainer() ) ); - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetNewBValue() ) ); - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, true); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetOutputGradientDirectionContainer() ) ); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetNewBValue() ) ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_rounded").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(node) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) ); if ( ! isDiffusionImage ) { return; } UpdateBValueTableWidget(i); } void QmitkPreprocessingView:: CallMultishellToSingleShellFilter( itk::DWIVoxelFunctor * functor, mitk::Image::Pointer image, QString imageName, mitk::DataNode* parent ) { typedef itk::RadialMultishellToSingleshellImageFilter FilterType; // filter input parameter const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); ItkDwiType* vectorImage = itkVectorImagePointer.GetPointer(); - const mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer gradientContainer - = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + const GradProp::GradientDirectionsContainerType::Pointer gradientContainer + = static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); const unsigned int& bValue = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue(); mitk::DataNode::Pointer imageNode = 0; // filter call FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( filter->GetTargetGradientDirections() ) ); + PropHelper::CopyProperties(image, outImage, true); - outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( m_Controls->m_targetBValueSpinBox->value() ) ); + outImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), + GradProp::New( filter->GetTargetGradientDirections() ) ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); + outImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), + mitk::FloatProperty::New( m_Controls->m_targetBValueSpinBox->value() ) ); - mitk::DiffusionPropertyHelper propertyHelper( outImage ); + PropHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); imageNode = mitk::DataNode::New(); imageNode->SetData( outImage ); imageNode->SetName(imageName.toStdString().c_str()); GetDataStorage()->Add(imageNode, parent); // if(m_Controls->m_OutputRMSErrorImage->isChecked()){ // // create new Error image // FilterType::ErrorImageType::Pointer errImage = filter->GetErrorImage(); // mitk::Image::Pointer mitkErrImage = mitk::Image::New(); // mitkErrImage->InitializeByItk(errImage); // mitkErrImage->SetVolume(errImage->GetBufferPointer()); // imageNode = mitk::DataNode::New(); // imageNode->SetData( mitkErrImage ); // imageNode->SetName((imageName+"_Error").toStdString().c_str()); // GetDataStorage()->Add(imageNode); // } } void QmitkPreprocessingView::DoBiExpFit() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while( it != originalShellMap.end() ) { bValueList.put(s++,(it++)->first); } const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_BiExp", node); } void QmitkPreprocessingView::DoAKCFit() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) { return; } itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap& originalShellMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_AKC", node); } void QmitkPreprocessingView::DoADCFit() { // later } void QmitkPreprocessingView::DoADCAverage() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) return; itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); QString name(node->GetName().c_str()); const mitk::BValueMapProperty::BValueMap - &originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + &originalShellMap = static_cast(image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,image,name + "_ADC", node); } void QmitkPreprocessingView::CleanBValueTableWidget() { m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(1); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); m_Controls->m_B_ValueMap_TableWidget->setItem(0,0,new QTableWidgetItem("-")); m_Controls->m_B_ValueMap_TableWidget->setItem(0,1,new QTableWidgetItem("-")); } void QmitkPreprocessingView::UpdateBValueTableWidget(int) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { CleanBValueTableWidget(); return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage(false); - isDiffusionImage = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); + isDiffusionImage = PropHelper::IsDiffusionWeightedImage(image); if ( ! isDiffusionImage ) { CleanBValueTableWidget(); } else { typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator; BValueMapIterator it; BValueMap roundedBValueMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(roundedBValueMap.size() ); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); int i = 0 ; for(it = roundedBValueMap.begin() ;it != roundedBValueMap.end(); it++) { m_Controls->m_B_ValueMap_TableWidget->setItem(i,0,new QTableWidgetItem(QString::number(it->first))); QTableWidgetItem* item = m_Controls->m_B_ValueMap_TableWidget->item(i,0); item->setFlags(item->flags() & ~Qt::ItemIsEditable); m_Controls->m_B_ValueMap_TableWidget->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size()))); i++; } } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedUpdateGui( itk::Image* itkImage) { for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(itkImage->GetDirection()[r][c])); m_Controls->m_DirectionMatrixTable->setItem(r,c,item); } } } template < typename TPixel, unsigned int VImageDimension > void QmitkPreprocessingView::TemplatedUpdateGui( itk::VectorImage* itkImage) { for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(itkImage->GetDirection()[r][c])); m_Controls->m_DirectionMatrixTable->setItem(r,c,item); } } } void QmitkPreprocessingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer , const QList& nodes) { (void) nodes; this->OnImageSelectionChanged(); } void QmitkPreprocessingView::OnImageSelectionChanged() { bool foundImageVolume = true; mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } - bool foundDwiVolume( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( node ) ); + bool foundDwiVolume( PropHelper::IsDiffusionWeightedImage( node ) ); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } bool multiComponentVolume = (image->GetPixelType().GetNumberOfComponents() > 1); bool threeDplusTVolume = (image->GetTimeSteps() > 1); // we do not support multi-component and 3D+t images in the widget, check early to avoid access exception bool foundSingleImageVolume = foundDwiVolume || (foundImageVolume && (!multiComponentVolume) && (!threeDplusTVolume) ); m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume); m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume); m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume); m_Controls->m_B_ValueMap_Rounder_SpinBox->setEnabled(foundDwiVolume); m_Controls->m_ProjectSignalButton->setEnabled(foundDwiVolume); m_Controls->m_CreateLengthCorrectedDwi->setEnabled(foundDwiVolume); m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume); m_Controls->m_NormalizeImageValuesButton->setEnabled(foundDwiVolume); m_Controls->m_DirectionMatrixTable->setEnabled(foundSingleImageVolume); m_Controls->m_ModifyDirection->setEnabled(foundSingleImageVolume); m_Controls->m_ExtractBrainMask->setEnabled(foundSingleImageVolume); m_Controls->m_ResampleImageButton->setEnabled(foundSingleImageVolume); m_Controls->m_ModifySpacingButton->setEnabled(foundSingleImageVolume); m_Controls->m_ModifyOriginButton->setEnabled(foundSingleImageVolume); m_Controls->m_CropImageButton->setEnabled(foundSingleImageVolume); m_Controls->m_RemoveGradientButton->setEnabled(foundDwiVolume); m_Controls->m_ExtractGradientButton->setEnabled(foundDwiVolume); m_Controls->m_FlipAxis->setEnabled(foundSingleImageVolume); m_Controls->m_FlipGradientsButton->setEnabled(foundDwiVolume); + m_Controls->m_ClearRotationButton->setEnabled(foundDwiVolume); // reset sampling frame to 1 and update all ealted components m_Controls->m_B_ValueMap_Rounder_SpinBox->setValue(1); UpdateBValueTableWidget(m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); DoUpdateInterpolationGui(m_Controls->m_ResampleTypeBox->currentIndex()); if (foundDwiVolume) { m_Controls->m_InputData->setTitle("Input Data"); vnl_matrix_fixed< double, 3, 3 > mf = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) ->GetMeasurementFrame(); for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { // Measurement frame { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c ); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_Controls->m_MeasurementFrameTable->setItem( r, c, item ); } // Direction matrix { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c ); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(itkVectorImagePointer->GetDirection()[r][c])); m_Controls->m_DirectionMatrixTable->setItem( r, c, item ); } } } //calculate target bValue for MultishellToSingleShellfilter const mitk::BValueMapProperty::BValueMap & bValMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); mitk::BValueMapProperty::BValueMap::const_iterator it = bValMap.begin(); unsigned int targetBVal = 0; while(it != bValMap.end()) { targetBVal += (it++)->first; } targetBVal /= (float)bValMap.size()-1; m_Controls->m_targetBValueSpinBox->setValue(targetBVal); m_Controls->m_HeaderSpacingX->setValue(image->GetGeometry()->GetSpacing()[0]); m_Controls->m_HeaderSpacingY->setValue(image->GetGeometry()->GetSpacing()[1]); m_Controls->m_HeaderSpacingZ->setValue(image->GetGeometry()->GetSpacing()[2]); m_Controls->m_HeaderOriginX->setValue(image->GetGeometry()->GetOrigin()[0]); m_Controls->m_HeaderOriginY->setValue(image->GetGeometry()->GetOrigin()[1]); m_Controls->m_HeaderOriginZ->setValue(image->GetGeometry()->GetOrigin()[2]); m_Controls->m_XstartBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YstartBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZstartBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); m_Controls->m_XendBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YendBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZendBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); - m_Controls->m_RemoveGradientBox->setMaximum(static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + m_Controls->m_RemoveGradientBox->setMaximum(static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer()->Size()-1); - m_Controls->m_ExtractGradientBox->setMaximum(static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + m_Controls->m_ExtractGradientBox->setMaximum(static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer()->Size()-1); } else if (foundSingleImageVolume) { for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } } m_Controls->m_HeaderSpacingX->setValue(image->GetGeometry()->GetSpacing()[0]); m_Controls->m_HeaderSpacingY->setValue(image->GetGeometry()->GetSpacing()[1]); m_Controls->m_HeaderSpacingZ->setValue(image->GetGeometry()->GetSpacing()[2]); m_Controls->m_HeaderOriginX->setValue(image->GetGeometry()->GetOrigin()[0]); m_Controls->m_HeaderOriginY->setValue(image->GetGeometry()->GetOrigin()[1]); m_Controls->m_HeaderOriginZ->setValue(image->GetGeometry()->GetOrigin()[2]); m_Controls->m_XstartBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YstartBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZstartBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); m_Controls->m_XendBox->setMaximum(image->GetGeometry()->GetExtent(0)-1); m_Controls->m_YendBox->setMaximum(image->GetGeometry()->GetExtent(1)-1); m_Controls->m_ZendBox->setMaximum(image->GetGeometry()->GetExtent(2)-1); AccessFixedDimensionByItk(image, TemplatedUpdateGui,3); } else { for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c ); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem( r, c, item ); } { QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c ); delete item; item = new QTableWidgetItem(); m_Controls->m_DirectionMatrixTable->setItem( r, c, item ); } } } } } void QmitkPreprocessingView::Activated() { } void QmitkPreprocessingView::Deactivated() { OnImageSelectionChanged(); } void QmitkPreprocessingView::Visible() { OnImageSelectionChanged(); } void QmitkPreprocessingView::Hidden() { } +void QmitkPreprocessingView::DoClearRotationOfGradients() +{ + + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + if (image == nullptr) + return; + + if(!PropHelper::IsDiffusionWeightedImage(image)) + return; + + mitk::Image::Pointer newDwi = image->Clone(); + + PropHelper propertyHelper( newDwi ); + propertyHelper.InitializeImage(); + PropHelper::ClearMeasurementFrameAndRotationMatrixFromGradients(newDwi); + + mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); + imageNode->SetData( newDwi ); + + QString name = node->GetName().c_str(); + imageNode->SetName( (name+"_OriginalGradients").toStdString().c_str() ); + GetDataStorage()->Add( imageNode, node ); + +} void QmitkPreprocessingView::DoFlipGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); GradientDirectionContainerType::Pointer gradientContainer = - static_cast - ( newDwi->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + static_cast + ( newDwi->GetProperty(PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); for (unsigned int j=0; jSize(); j++) { if (m_Controls->m_FlipGradBoxX->isChecked()) { gradientContainer->at(j)[0] *= -1; } if (m_Controls->m_FlipGradBoxY->isChecked()) { gradientContainer->at(j)[1] *= -1; } if (m_Controls->m_FlipGradBoxZ->isChecked()) { gradientContainer->at(j)[2] *= -1; } } - newDwi->GetPropertyList()->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( gradientContainer ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newDwi ); + PropHelper::CopyProperties(image, newDwi, true); + newDwi->GetPropertyList()->ReplaceProperty( PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( gradientContainer ) ); + PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_GradientFlip").toStdString().c_str() ); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); GradientDirectionContainerType::Pointer gradientContainer = - static_cast - ( newDwi->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + static_cast + ( newDwi->GetProperty(PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); for (unsigned int j=0; jSize(); j++) { if (gradientContainer->at(j)[0]<0) { gradientContainer->at(j) = -gradientContainer->at(j); } } - newDwi->SetProperty( mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( gradientContainer ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newDwi ); + PropHelper::CopyProperties(image, newDwi, true); + newDwi->GetPropertyList()->ReplaceProperty( PropHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( gradientContainer ) ); + PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_halfsphere").toStdString().c_str() ); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoApplyMesurementFrame() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) return; vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) { for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) return; mf[r][c] = item->text().toDouble(); } } mitk::Image::Pointer newDwi = image->Clone(); - newDwi->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( mf ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newDwi ); + newDwi->GetPropertyList()->ReplaceProperty( PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); + PropHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_new-MF").toStdString().c_str()); GetDataStorage()->Add( imageNode, node ); } void QmitkPreprocessingView::DoShowGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } int maxIndex = 0; unsigned int maxSize = image->GetDimension(0); if (maxSizeGetDimension(1)) { maxSize = image->GetDimension(1); maxIndex = 1; } if (maxSizeGetDimension(2)) { maxSize = image->GetDimension(2); maxIndex = 2; } mitk::Point3D origin = image->GetGeometry()->GetOrigin(); mitk::PointSet::Pointer originSet = mitk::PointSet::New(); typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator; BValueMap bValMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); - GradientDirectionContainerType::Pointer gradientContainer = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + GradientDirectionContainerType::Pointer gradientContainer = static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); mitk::BaseGeometry::Pointer geometry = image->GetGeometry(); int shellCount = 1; for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it) { mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (unsigned int j=0; jsecond.size(); j++) { mitk::Point3D ip; vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]); if (v.magnitude()>mitk::eps) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*image->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*image->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*image->GetDimension(2)/2; pointset->InsertPoint(j, ip); } else if (originSet->IsEmpty()) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*image->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*image->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*image->GetDimension(2)/2; originSet->InsertPoint(j, ip); } } if ( it->first < mitk::eps ) { continue; } // add shell to datastorage mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pointset); QString name = node->GetName().c_str(); name += "_Shell_"; name += QString::number( it->first ); newNode->SetName( name.toStdString().c_str() ); newNode->SetProperty( "pointsize", mitk::FloatProperty::New((float)maxSize / 50) ); int b0 = shellCount % 2; int b1 = 0; int b2 = 0; if (shellCount>4) { b2 = 1; } if (shellCount%4 >= 2) { b1 = 1; } newNode->SetProperty("color", mitk::ColorProperty::New( b2, b1, b0 )); GetDataStorage()->Add( newNode, node ); shellCount++; } // add origin to datastorage mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(originSet); QString name = node->GetName().c_str(); name += "_Origin"; newNode->SetName(name.toStdString().c_str()); newNode->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); newNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); GetDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoReduceGradientDirections() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef mitk::BValueMapProperty::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; BValueMap originalShellMap = static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ) ->GetBValueMap(); std::vector newNumGradientDirections; int shellCounter = 0; QString name = node->GetName().c_str(); for (int i=0; im_B_ValueMap_TableWidget->rowCount(); i++) { double BValue = m_Controls->m_B_ValueMap_TableWidget->item(i,0)->text().toDouble(); shellSlectionMap[BValue] = originalShellMap[BValue]; unsigned int num = m_Controls->m_B_ValueMap_TableWidget->item(i,1)->text().toUInt(); newNumGradientDirections.push_back(num); name += "_"; name += QString::number(num); shellCounter++; } if (newNumGradientDirections.empty()) { return; } GradientDirectionContainerType::Pointer gradientContainer - = static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + = static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(newNumGradientDirections); filter->SetOriginalBValueMap(originalShellMap); filter->SetShellSelectionBValueMap(shellSlectionMap); filter->Update(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( filter->GetGradientDirections() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() ) - ->GetMeasurementFrame() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) - ->GetValue() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper::CopyProperties(image, newImage, true); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetGradientDirections() ) ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); GetDataStorage()->Add(imageNode, node); // update the b-value widget to remove the modified number of gradients used for extraction this->CleanBValueTableWidget(); this->UpdateBValueTableWidget(0); } void QmitkPreprocessingView::MergeDwis() { - typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; + typedef GradProp::GradientDirectionsContainerType GradientContainerType; mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } mitk::DataNode::Pointer node2 = m_Controls->m_MergeDwiBox->GetSelectedNode(); if (node2.IsNull()) { return; } mitk::Image::Pointer image2 = dynamic_cast(node2->GetData()); if ( image2 == nullptr ) { return; } typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; QString name = ""; { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); imageContainer.push_back( itkVectorImagePointer ); - gradientListContainer.push_back( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + gradientListContainer.push_back( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); bValueContainer.push_back( static_cast - (image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) + (image->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); name += node->GetName().c_str(); } { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image2, itkVectorImagePointer); imageContainer.push_back( itkVectorImagePointer ); - gradientListContainer.push_back( static_cast - ( image2->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + gradientListContainer.push_back( static_cast + ( image2->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); bValueContainer.push_back( static_cast - (image2->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) + (image2->GetProperty(PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() ) ->GetValue() ); name += "+"; name += node2->GetName().c_str(); } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), - mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); - - newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), - mitk::MeasurementFrameProperty::New( mf ) ); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), GradProp::New( filter->GetOutputGradients() ) ); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); + newImage->GetPropertyList()->ReplaceProperty( PropHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); - newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), - mitk::FloatProperty::New( filter->GetB_Value() ) ); - - mitk::DiffusionPropertyHelper propertyHelper( newImage ); + PropHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); GetDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } - typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; + typedef GradProp::GradientDirectionsContainerType GradientContainerType; // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); - filter->SetDirections( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + filter->SetDirections( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer newNode=mitk::DataNode::New(); newNode->SetData( mitkImage ); newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0")); GetDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } // typedefs - typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; + typedef GradProp::GradientDirectionsContainerType GradientContainerType; typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); // Extract image using found index FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); - filter->SetDirections( static_cast - ( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) + filter->SetDirections( static_cast + ( image->GetProperty(PropHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() ) ->GetGradientDirectionsContainer() ); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer newNode=mitk::DataNode::New(); newNode->SetData( mitkImage ); newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0_ALL")); GetDataStorage()->Add(newNode, node); /*A reinitialization is needed to access the time channels via the ImageNavigationController The Global-Geometry can not recognize the time channel without a re-init. (for a new selection in datamanger a automatically updated of the Global-Geometry should be done - if it contains the time channel)*/ mitk::RenderingManager::GetInstance()->InitializeViews( newNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::AverageGradients() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) return; mitk::Image::Pointer newDwi = image->Clone(); - newDwi->SetPropertyList( image->GetPropertyList()->Clone() ); - - mitk::DiffusionPropertyHelper propertyHelper(newDwi); + PropHelper propertyHelper(newDwi); propertyHelper.AverageRedundantGradients(m_Controls->m_Blur->value()); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_averaged").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h index 7b6338f261..bfc68a103a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h @@ -1,168 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QMITKPREPROCESSINGVIEW_H_INCLUDED #define _QMITKPREPROCESSINGVIEW_H_INCLUDED #include #include #include "ui_QmitkPreprocessingViewControls.h" // st includes #include // itk includes #include #include // mitk includes #include #include "itkDWIVoxelFunctor.h" #include typedef short DiffusionPixelType; struct PrpSelListener; /*! * \ingroup org_mitk_gui_qt_preprocessing_internal * * \brief Viewing and modifying diffusion weighted images (gradient reduction, resampling, b-value projection, ...) * */ class QmitkPreprocessingView : public QmitkAbstractView, public mitk::ILifecycleAwarePart { friend struct PrpSelListener; // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image< unsigned char, 3 > UcharImageType; typedef itk::Image< double, 3 > ItkDoubleImageType; + typedef mitk::DiffusionPropertyHelper PropHelper; + typedef mitk::GradientDirectionsProperty GradProp; QmitkPreprocessingView(); virtual ~QmitkPreprocessingView(); virtual void CreateQtPartControl(QWidget *parent) override; /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); virtual void Activated() override; virtual void Deactivated() override; virtual void Visible() override; virtual void Hidden() override; /// /// Sets the focus to an internal widget. /// virtual void SetFocus() override; static const int nrconvkernels; protected slots: void AverageGradients(); void ExtractB0(); void MergeDwis(); void DoApplySpacing(); void DoApplyOrigin(); void DoApplyDirectionMatrix(); void DoApplyMesurementFrame(); void DoReduceGradientDirections(); void DoShowGradientDirections(); void DoHalfSphereGradientDirections(); void UpdateDwiBValueMapRounder(int i); void DoLengthCorrection(); void DoDwiNormalization(); void DoProjectSignal(); void DoExtractBrainMask(); void DoResampleImage(); void DoCropImage(); void DoUpdateInterpolationGui(int i); void DoRemoveGradient(); void DoExtractGradient(); void DoFlipAxis(); void OnImageSelectionChanged(); void DoFlipGradientDirections(); + void DoClearRotationOfGradients(); protected: void DoADCFit(); void DoAKCFit(); void DoBiExpFit(); void DoADCAverage(); template < typename TPixel, unsigned int VImageDimension > void TemplatedFlipAxis( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedCropImage( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedApplyRotation( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedUpdateGui( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedUpdateGui( itk::VectorImage* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedResampleImage( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedSetImageSpacing( itk::Image* itkImage); template < typename TPixel, unsigned int VImageDimension > void TemplatedSetImageOrigin( itk::Image* itkImage); /** Called by ExtractB0 if check-box activated, extracts all b0 images without averaging */ void DoExtractBOWithoutAveraging(); void UpdateBValueTableWidget(int); /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; Ui::QmitkPreprocessingViewControls* m_Controls; void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name); void CallMultishellToSingleShellFilter( itk::DWIVoxelFunctor * functor, mitk::Image::Pointer ImPtr, QString imageName, mitk::DataNode* parent ); void CleanBValueTableWidget(); }; #endif // _QMITKPREPROCESSINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui index c04eaa3fd2..37263c6949 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingViewControls.ui @@ -1,1710 +1,1729 @@ QmitkPreprocessingViewControls 0 0 523 - 1158 + 1192 0 0 false QmitkPreprocessingViewControls true Please Select Input Data Image: QComboBox::AdjustToMinimumContentsLength 0 Gradients 0 0 Qt::ScrollBarAsNeeded Qt::ScrollBarAlwaysOff true 100 true false true b-Value Number of gradients - + + + + Qt::Vertical + + + + 20 + 40 + + + + + QFrame::NoFrame QFrame::Raised 0 0 0 0 6 - - - - false - - - Generate pointset displaying the gradient vectors (applied measurement frame). - - - - - - - - - Show gradients - - - <html><head/><body><p>Define the sampling frame the b-Values are rounded with.</p></body></html> Sampling frame: false <html><head/><body><p>Round b-values to nearest multiple of this value (click &quot;Round b-value&quot; to create new image with these values).</p></body></html> QAbstractSpinBox::CorrectToNearestValue 1 10000 10 - - + + false - Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere using an iterative energy repulsion strategy. + Sometimes the gradient directions are not located on one half sphere. - Reduce number of gradients + Mirror gradients to half sphere - - + + false - Sometimes the gradient directions are not located on one half sphere. + Generate pointset displaying the gradient vectors (applied measurement frame). - Mirror gradients to half sphere + Show gradients - - + + false + + Generate pointset displaying the gradient vectors (applied measurement frame). + + + + + + + - Round b-values + Flip gradients - - + + false - Generate pointset displaying the gradient vectors (applied measurement frame). + Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere using an iterative energy repulsion strategy. - Flip gradients + Reduce number of gradients QFrame::NoFrame QFrame::Plain 0 0 0 0 0 x y z + + + + false + + + Round b-values + + + + + + + false + + + By default, the image matrix is applied to the image gradients. This button removes this additional rotation. + + + + + + + + + Clear rotation of gradients + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - Image Values Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. 6 2.000000000000000 0.000100000000000 0.001000000000000 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Merge radius false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Merge selected DWIs false Normalizes the diffusion-weighted image values across all weighted volumes to the given mean and standard deviation. Normalize image values QFrame::NoFrame QFrame::Raised 0 0 0 0 0 false Target b-value 100000 500 Select projection method. QComboBox::AdjustToMinimumContentsLength ADC Average AKC Bi-Exponential false Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them by taking all directions within a certain radius into account. Average repetitions false Project image values onto one b-shell. Project onto shell QFrame::NoFrame QFrame::Raised 0 0 0 0 0 true New stdev 100000 100 500 Select binary mask image. The mask is used to calculate the old mean and standard deviation. QComboBox::AdjustToMinimumContentsLength true New mean value 100000 100 1000 false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Flip axis QFrame::NoFrame QFrame::Raised 0 0 0 0 Y Qt::Horizontal 40 20 X Z Axis: QComboBox::AdjustToMinimumContentsLength Resample image QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0.010000000000000 2.000000000000000 0.010000000000000 2.000000000000000 0.010000000000000 2.000000000000000 Sampling factor New image spacing New image size QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Interpolator: Nearest neighbour Linear B-spline Windowed sinc false Resample image QFrame::NoFrame QFrame::Raised 0 0 0 0 0 1 10000 1 10000 1 10000 Header Image size 0 0 0 y: Number of pixels to remove on lower image bound. 999999999 Number of pixels to remove on upper image bound. 999999999 Number of pixels to remove on upper image bound. 999999999 Number of pixels to remove on lower image bound. 999999999 x: Number of pixels to remove on lower image bound. 999999999 Number of pixels to remove on upper image bound. 999999999 z: false Crop image Remove or extract gradient volumes false Generate pointset displaying the gradient vectors (applied measurement frame). Remove false Generate pointset displaying the gradient vectors (applied measurement frame). Extract Voxel size 0 0 0 4 4 4 0.000000000000000 99.989999999999995 false Set new voxel size Qt::Vertical 20 40 0 0 Measurment frame 0 0 0 Qt::Horizontal 40 20 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column false Diffusion encoding gradient directions are rotated accordingly. Apply new measurement frame Direction matrix 0 9 0 0 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column false Diffusion encoding gradient directions are rotated accordingly. Apply new direction Qt::Horizontal 40 20 Origin 0 0 0 4 -999999999.000000000000000 999999999.000000000000000 4 -999999999.000000000000000 999999999.000000000000000 4 -99999999.000000000000000 999999999.000000000000000 false Set new origin Other false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Estimate binary brain mask Maximum number of iterations. 10000 10000 Qt::Vertical 20 40 false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Extract baseline image Create a 3D+t data set containing all b0 images as timesteps Disable averaging - QmitkDataStorageComboBoxWithSelectNone + QmitkDataStorageComboBox QComboBox -
QmitkDataStorageComboBoxWithSelectNone.h
+
QmitkDataStorageComboBox.h
- QmitkDataStorageComboBox + QmitkDataStorageComboBoxWithSelectNone QComboBox -
QmitkDataStorageComboBox.h
+
QmitkDataStorageComboBoxWithSelectNone.h
m_B_ValueMap_Rounder_SpinBox m_Blur m_targetBValueSpinBox m_ProjectionMethodBox m_ResampleTypeBox m_ResampleDoubleX m_ResampleDoubleY m_ResampleDoubleZ m_ResampleIntX m_ResampleIntY m_ResampleIntZ m_InterpolatorBox m_HeaderSpacingX m_HeaderSpacingY m_HeaderSpacingZ m_HeaderOriginX m_HeaderOriginY m_HeaderOriginZ m_DirectionMatrixTable m_MeasurementFrameTable m_CheckExtractAll m_BrainMaskIterationsBox tabWidget m_B_ValueMap_TableWidget m_CreateLengthCorrectedDwi m_ShowGradientsButton m_MirrorGradientToHalfSphereButton m_ReduceGradientsButton m_ButtonAverageGradients m_ProjectSignalButton m_NormalizeImageValuesButton m_MergeDwisButton m_ResampleImageButton m_ModifySpacingButton m_ModifyOriginButton m_ModifyDirection m_ModifyMeasurementFrame m_ButtonExtractB0 m_ExtractBrainMask
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp index d8ef803c11..9579acd42f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp @@ -1,1064 +1,1063 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTensorReconstructionView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include #include #include #include #include // itk includes #include "itkTimeProbe.h" //#include "itkTensor.h" // mitk includes #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "QmitkDataStorageComboBox.h" #include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h" #include "itkDiffusionTensor3DReconstructionImageFilter.h" #include "itkTensorImageToDiffusionImageFilter.h" #include "itkPointShell.h" #include "itkVector.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkTensorReconstructionWithEigenvalueCorrectionFilter.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include #include #include "mitkProperties.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkLookupTableProperty.h" #include "mitkLookupTable.h" #include "mitkImageStatisticsHolder.h" #include #include #include #include #include #include const std::string QmitkTensorReconstructionView::VIEW_ID = "org.mitk.views.tensorreconstruction"; typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; using namespace berry; QmitkTensorReconstructionView::QmitkTensorReconstructionView() : QmitkAbstractView(), m_Controls(nullptr) { m_DiffusionImages = mitk::DataStorage::SetOfObjects::New(); m_TensorImages = mitk::DataStorage::SetOfObjects::New(); } QmitkTensorReconstructionView::~QmitkTensorReconstructionView() { } void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTensorReconstructionViewControls; m_Controls->setupUi(parent); this->CreateConnections(); Advanced1CheckboxClicked(); } } void QmitkTensorReconstructionView::SetFocus() { m_Controls->m_Advanced1->setFocus(); } void QmitkTensorReconstructionView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_StartReconstruction), SIGNAL(clicked()), this, SLOT(Reconstruct()) ); connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) ); connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) ); connect( (QObject*)(m_Controls->m_TensorsToQbiButton), SIGNAL(clicked()), this, SLOT(TensorsToQbi()) ); connect( (QObject*)(m_Controls->m_ResidualButton), SIGNAL(clicked()), this, SLOT(ResidualCalculation()) ); connect( (QObject*)(m_Controls->m_PerSliceView), SIGNAL(pointSelected(int, int)), this, SLOT(ResidualClicked(int, int)) ); connect( (QObject*)(m_Controls->m_TensorReconstructionThreshold), SIGNAL(valueChanged(int)), this, SLOT(PreviewThreshold(int)) ); } } void QmitkTensorReconstructionView::ResidualClicked(int slice, int volume) { // Use image coord to reset crosshair // Find currently selected diffusion image // Update Label // to do: This position should be modified in order to skip B0 volumes that are not taken into account // when calculating residuals // Find the diffusion image mitk::Image* diffImage; mitk::DataNode::Pointer correctNode; mitk::BaseGeometry* geometry; bool isDiffusionImage(false); if (m_DiffusionImage.IsNotNull()) { isDiffusionImage = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_DiffusionImage->GetData())) ; diffImage = static_cast(m_DiffusionImage->GetData()); geometry = m_DiffusionImage->GetData()->GetGeometry(); // Remember the node whose display index must be updated correctNode = mitk::DataNode::New(); correctNode = m_DiffusionImage; } if( isDiffusionImage ) { GradientDirectionContainerType::Pointer dirs = static_cast( diffImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); for(itk::SizeValueType i=0; iSize() && i<=(itk::SizeValueType)volume; i++) { GradientDirectionType grad = dirs->ElementAt(i); // check if image is b0 weighted if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001) { volume++; } } QString pos = "Volume: "; pos.append(QString::number(volume)); pos.append(", Slice: "); pos.append(QString::number(slice)); m_Controls->m_PositionLabel->setText(pos); if(correctNode) { int oldDisplayVal; correctNode->GetIntProperty("DisplayChannel", oldDisplayVal); QString oldVal = QString::number(oldDisplayVal); QString newVal = QString::number(volume); correctNode->SetIntProperty("DisplayChannel",volume); correctNode->SetSelected(true); this->FirePropertyChanged("DisplayChannel", oldVal, newVal); correctNode->UpdateOutputInformation(); mitk::Point3D p3 = this->GetRenderWindowPart()->GetSelectedPosition(); itk::Index<3> ix; geometry->WorldToIndex(p3, ix); // ix[2] = slice; mitk::Vector3D vec; vec[0] = ix[0]; vec[1] = ix[1]; vec[2] = slice; mitk::Vector3D v3New; geometry->IndexToWorld(vec, v3New); mitk::Point3D origin = geometry->GetOrigin(); mitk::Point3D p3New; p3New[0] = v3New[0] + origin[0]; p3New[1] = v3New[1] + origin[1]; p3New[2] = v3New[2] + origin[2]; this->GetRenderWindowPart()->SetSelectedPosition(p3New); this->GetRenderWindowPart()->RequestUpdate(); } } } void QmitkTensorReconstructionView::Advanced1CheckboxClicked() { bool check = m_Controls-> m_Advanced1->isChecked(); m_Controls->frame->setVisible(check); } void QmitkTensorReconstructionView::Activated() { } void QmitkTensorReconstructionView::Deactivated() { // Get all current nodes mitk::DataStorage::SetOfObjects::ConstPointer objects = this->GetDataStorage()->GetAll(); mitk::DataStorage::SetOfObjects::const_iterator itemiter( objects->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( objects->end() ); while ( itemiter != itemiterend ) // for all items { mitk::DataNode::Pointer node = *itemiter; if (node.IsNull()) continue; // only look at interesting types if( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(dynamic_cast(node->GetData()))) { if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter)) { node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter); this->GetDataStorage()->Remove(node); } } itemiter++; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkTensorReconstructionView::Visible() { } void QmitkTensorReconstructionView::Hidden() { } void QmitkTensorReconstructionView::ResidualCalculation() { // Extract dwi and dti from current selection // In case of multiple selections, take the first one, since taking all combinations is not meaningful mitk::DataStorage::SetOfObjects::Pointer set = mitk::DataStorage::SetOfObjects::New(); mitk::Image::Pointer diffImage = mitk::Image::New(); TensorImageType::Pointer tensorImage; std::string nodename; if(m_DiffusionImage.IsNotNull()) { diffImage = static_cast(m_DiffusionImage->GetData()); } else return; if(m_TensorImage.IsNotNull()) { mitk::TensorImage* mitkVol; mitkVol = static_cast(m_TensorImage->GetData()); mitk::CastToItkImage(mitkVol, tensorImage); m_TensorImage->GetStringProperty("name", nodename); } else return; typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; GradientDirectionContainerType* gradients = static_cast( diffImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); // Find the min and the max values from a baseline image mitk::ImageStatisticsHolder *stats = diffImage->GetStatistics(); //Initialize filter that calculates the modeled diffusion weighted signals FilterType::Pointer filter = FilterType::New(); filter->SetInput( tensorImage ); filter->SetBValue( static_cast(diffImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue()); filter->SetGradientList(gradients); filter->SetMin(stats->GetScalarValueMin()); filter->SetMax(stats->GetScalarValueMax()); filter->Update(); // TENSORS TO DATATREE mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradients ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(diffImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(diffImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); + mitk::DiffusionPropertyHelper::CopyProperties(diffImage, image, true); + image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradients ) ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); mitk::ImageVtkMapper2D::SetDefaultProperties(node); QString newname; newname = newname.append(nodename.c_str()); newname = newname.append("_Estimated DWI"); node->SetName(newname.toLatin1()); GetDataStorage()->Add(node, m_TensorImage); BValueMapType map = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap();; std::vector< unsigned int > b0Indices = map[0]; typedef itk::ResidualImageFilter ResidualImageFilterType; ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(diffImage, itkVectorImagePointer); ITKDiffusionImageType::Pointer itkSecondVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(image, itkSecondVectorImagePointer); ResidualImageFilterType::Pointer residualFilter = ResidualImageFilterType::New(); residualFilter->SetInput( itkVectorImagePointer ); residualFilter->SetSecondDiffusionImage( itkSecondVectorImagePointer ); residualFilter->SetGradients(gradients); residualFilter->SetB0Index(b0Indices[0]); residualFilter->SetB0Threshold(30); residualFilter->Update(); itk::Image::Pointer residualImage = itk::Image::New(); residualImage = residualFilter->GetOutput(); mitk::Image::Pointer mitkResImg = mitk::Image::New(); mitk::CastToMitkImage(residualImage, mitkResImg); stats = mitkResImg->GetStatistics(); float min = stats->GetScalarValueMin(); float max = stats->GetScalarValueMax(); mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(min, max); // If you don't want to use the whole color range, you can use // SetValueRange, SetHueRange, and SetSaturationRange lookupTable->Build(); vtkSmartPointer reversedlookupTable = vtkSmartPointer::New(); reversedlookupTable->SetTableRange(min+1, max); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookupTable->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } lut->SetVtkLookupTable(lookupTable); lutProp->SetLookupTable(lut); // Create lookuptable mitk::DataNode::Pointer resNode=mitk::DataNode::New(); resNode->SetData( mitkResImg ); resNode->SetName("Residuals"); resNode->SetProperty("LookupTable", lutProp); bool b; resNode->GetBoolProperty("use color", b); resNode->SetBoolProperty("use color", false); GetDataStorage()->Add(resNode, m_TensorImage); this->GetRenderWindowPart()->RequestUpdate(); // Draw Graph std::vector means = residualFilter->GetMeans(); std::vector q1s = residualFilter->GetQ1(); std::vector q3s = residualFilter->GetQ3(); std::vector percentagesOfOUtliers = residualFilter->GetPercentagesOfOutliers(); m_Controls->m_ResidualAnalysis->SetMeans(means); m_Controls->m_ResidualAnalysis->SetQ1(q1s); m_Controls->m_ResidualAnalysis->SetQ3(q3s); m_Controls->m_ResidualAnalysis->SetPercentagesOfOutliers(percentagesOfOUtliers); if(m_Controls->m_PercentagesOfOutliers->isChecked()) { m_Controls->m_ResidualAnalysis->DrawPercentagesOfOutliers(); } else { m_Controls->m_ResidualAnalysis->DrawMeans(); } // Draw Graph for volumes per slice in the QGraphicsView std::vector< std::vector > outliersPerSlice = residualFilter->GetOutliersPerSlice(); int xSize = outliersPerSlice.size(); if(xSize == 0) { return; } int ySize = outliersPerSlice[0].size(); // Find maximum in outliersPerSlice double maxOutlier= 0.0; for(int i=0; imaxOutlier) { maxOutlier = outliersPerSlice[i][j]; } } } // Create some QImage QImage qImage(xSize, ySize, QImage::Format_RGB32); QImage legend(1, 256, QImage::Format_RGB32); QRgb value; vtkSmartPointer lookup = vtkSmartPointer::New(); lookup->SetTableRange(0.0, maxOutlier); lookup->Build(); reversedlookupTable->SetTableRange(0, maxOutlier); reversedlookupTable->Build(); for(int i=0; i<256; i++) { double* rgba = reversedlookupTable->GetTableValue(255-i); lookup->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); } // Fill qImage for(int i=0; iMapValue(out); int r, g, b; r = _rgba[0]; g = _rgba[1]; b = _rgba[2]; value = qRgb(r, g, b); qImage.setPixel(i,j,value); } } for(int i=0; i<256; i++) { double* rgba = lookup->GetTableValue(i); int r, g, b; r = rgba[0]*255; g = rgba[1]*255; b = rgba[2]*255; value = qRgb(r, g, b); legend.setPixel(0,255-i,value); } QString upper = QString::number(maxOutlier, 'g', 3); upper.append(" %"); QString lower = QString::number(0.0); lower.append(" %"); m_Controls->m_UpperLabel->setText(upper); m_Controls->m_LowerLabel->setText(lower); QPixmap pixmap(QPixmap::fromImage(qImage)); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); item->setTransform(QTransform::fromScale(10.0, 3.0), true); QPixmap pixmap2(QPixmap::fromImage(legend)); QGraphicsPixmapItem *item2 = new QGraphicsPixmapItem(pixmap2); item2->setTransform(QTransform::fromScale(20.0, 1.0), true); m_Controls->m_PerSliceView->SetResidualPixmapItem(item); QGraphicsScene* scene = new QGraphicsScene; QGraphicsScene* scene2 = new QGraphicsScene; scene->addItem(item); scene2->addItem(item2); m_Controls->m_PerSliceView->setScene(scene); m_Controls->m_LegendView->setScene(scene2); m_Controls->m_PerSliceView->show(); m_Controls->m_PerSliceView->repaint(); m_Controls->m_LegendView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); m_Controls->m_LegendView->show(); m_Controls->m_LegendView->repaint(); } void QmitkTensorReconstructionView::Reconstruct() { int method = m_Controls->m_ReconctructionMethodBox->currentIndex(); switch (method) { case 0: ItkTensorReconstruction(m_DiffusionImages); break; case 1: TensorReconstructionWithCorr(m_DiffusionImages); break; default: ItkTensorReconstruction(m_DiffusionImages); } } void QmitkTensorReconstructionView::TensorReconstructionWithCorr (mitk::DataStorage::SetOfObjects::Pointer inImages) { try { int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); while ( itemiter != itemiterend ) // for all items { mitk::Image* vols = static_cast((*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // TENSOR RECONSTRUCTION MITK_INFO << "Tensor reconstruction with correction for negative eigenvalues"; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Tensor reconstruction for %s", nodename.c_str()).toLatin1()); typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< DiffusionPixelType, TTensorPixelType > ReconstructionFilter; float b0Threshold = m_Controls->m_TensorReconstructionThreshold->value(); GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New(); for(GradientDirectionContainerType::ConstIterator it = static_cast( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->Begin(); it != static_cast( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->End(); it++) { gradientContainerCopy->push_back(it.Value()); } ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); ReconstructionFilter::Pointer reconFilter = ReconstructionFilter::New(); reconFilter->SetBValue( static_cast(vols->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); reconFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer); reconFilter->SetB0Threshold(b0Threshold); reconFilter->Update(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer outputTensorImg = reconFilter->GetOutput(); typedef itk::ImageRegionIterator TensorImageIteratorType; TensorImageIteratorType tensorIt(outputTensorImg, outputTensorImg->GetRequestedRegion()); tensorIt.GoToBegin(); int negatives = 0; while(!tensorIt.IsAtEnd()) { typedef itk::DiffusionTensor3D TensorType; TensorType tensor = tensorIt.Get(); TensorType::EigenValuesArrayType ev; tensor.ComputeEigenValues(ev); for(unsigned int i=0; iInitializeByItk( outputTensorImg.GetPointer() ); image->SetVolume( outputTensorImg->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); SetDefaultNodeProperties(node, nodename+"_EigenvalueCorrected_DT"); GetDataStorage()->Add(node, *itemiter); mitk::ProgressBar::GetInstance()->Progress(); ++itemiter; } mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toLatin1()); this->GetRenderWindowPart()->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MITK_INFO << ex ; QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription()); } } void QmitkTensorReconstructionView::ItkTensorReconstruction(mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); while ( itemiter != itemiterend ) // for all items { mitk::Image* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // TENSOR RECONSTRUCTION clock.Start(); MITK_DEBUG << "Tensor reconstruction "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Tensor reconstruction for %s", nodename.c_str()).toLatin1()); typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New(); for(GradientDirectionContainerType::ConstIterator it = static_cast( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->Begin(); it != static_cast( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->End(); it++) { gradientContainerCopy->push_back(it.Value()); } ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); tensorReconstructionFilter->SetBValue( static_cast(vols->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer ); tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreshold->value() ); tensorReconstructionFilter->Update(); clock.Stop(); MITK_DEBUG << "took " << clock.GetMean() << "s."; // TENSORS TO DATATREE mitk::TensorImage::Pointer image = mitk::TensorImage::New(); typedef itk::Image, 3> TensorImageType; TensorImageType::Pointer tensorImage; tensorImage = tensorReconstructionFilter->GetOutput(); // Check the tensor for negative eigenvalues if(m_Controls->m_CheckNegativeEigenvalues->isChecked()) { typedef itk::ImageRegionIterator TensorImageIteratorType; TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion()); tensorIt.GoToBegin(); while(!tensorIt.IsAtEnd()) { typedef itk::DiffusionTensor3D TensorType; //typedef itk::Tensor TensorType2; TensorType tensor = tensorIt.Get(); TensorType::EigenValuesArrayType ev; tensor.ComputeEigenValues(ev); for(unsigned int i=0; iSetDirection( itkVectorImagePointer->GetDirection() ); image->InitializeByItk( tensorImage.GetPointer() ); image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); SetDefaultNodeProperties(node, nodename+"_LinearLeastSquares_DT"); GetDataStorage()->Add(node, *itemiter); mitk::ProgressBar::GetInstance()->Progress(); ++itemiter; } mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toLatin1()); this->GetRenderWindowPart()->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MITK_INFO << ex ; QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription()); return; } } void QmitkTensorReconstructionView::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); node->SetProperty( "name", mitk::StringProperty::New(name) ); } void QmitkTensorReconstructionView::TensorsToDWI() { DoTensorsToDWI(m_TensorImages); } void QmitkTensorReconstructionView::TensorsToQbi() { for (unsigned int i=0; isize(); i++) { mitk::DataNode::Pointer tensorImageNode = m_TensorImages->at(i); MITK_INFO << "starting Q-Ball estimation"; typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(dynamic_cast(tensorImageNode->GetData()), itkvol); typedef itk::TensorImageToQBallImageFilter< TTensorPixelType, TTensorPixelType > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->Update(); typedef itk::Vector OutputPixelType; typedef itk::Image OutputImageType; mitk::QBallImage::Pointer image = mitk::QBallImage::New(); OutputImageType::Pointer outimg = filter->GetOutput(); image->InitializeByItk( outimg.GetPointer() ); image->SetVolume( outimg->GetBufferPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(tensorImageNode->GetName()+"_Qball"); GetDataStorage()->Add(node, tensorImageNode); } } void QmitkTensorReconstructionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { m_DiffusionImages = mitk::DataStorage::SetOfObjects::New(); m_TensorImages = mitk::DataStorage::SetOfObjects::New(); bool foundDwiVolume = false; bool foundTensorVolume = false; m_Controls->m_DiffusionImageLabel->setText("mandatory"); m_DiffusionImage = nullptr; m_TensorImage = nullptr; m_Controls->m_InputData->setTitle("Please Select Input Data"); // iterate selection for (mitk::DataNode::Pointer node: nodes) { if (node.IsNull()) continue; // only look at interesting types bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); if ( isDiffusionImage ) { foundDwiVolume = true; m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_DiffusionImages->push_back(node); m_DiffusionImage = node; } else if(dynamic_cast(node->GetData())) { foundTensorVolume = true; m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_TensorImages->push_back(node); m_TensorImage = node; } } m_Controls->m_StartReconstruction->setEnabled(foundDwiVolume); m_Controls->m_TensorsToDWIButton->setEnabled(foundTensorVolume); m_Controls->m_TensorsToQbiButton->setEnabled(foundTensorVolume); if (foundDwiVolume || foundTensorVolume) m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_ResidualButton->setEnabled(foundDwiVolume && foundTensorVolume); m_Controls->m_PercentagesOfOutliers->setEnabled(foundDwiVolume && foundTensorVolume); m_Controls->m_PerSliceView->setEnabled(foundDwiVolume && foundTensorVolume); } template itk::VectorContainer >::Pointer QmitkTensorReconstructionView::MakeGradientList() { itk::VectorContainer >::Pointer retval = itk::VectorContainer >::New(); vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); for(int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval->push_back(v); } // Add 0 vector for B0 vnl_vector_fixed v; v.fill(0.0); retval->push_back(v); return retval; } void QmitkTensorReconstructionView::DoTensorsToDWI(mitk::DataStorage::SetOfObjects::Pointer inImages) { try { itk::TimeProbe clock; int nrFiles = inImages->size(); if (!nrFiles) return; QString status; mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles); mitk::DataStorage::SetOfObjects::const_iterator itemiter( inImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( inImages->end() ); while ( itemiter != itemiterend ) // for all items { std::string nodename; (*itemiter)->GetStringProperty("name", nodename); mitk::TensorImage* vol = static_cast((*itemiter)->GetData()); typedef float TTensorPixelType; typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef itk::Image< TensorPixelType, 3 > TensorImageType; TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(vol, itkvol); typedef itk::TensorImageToDiffusionImageFilter< TTensorPixelType, DiffusionPixelType > FilterType; FilterType::GradientListPointerType gradientList = FilterType::GradientListType::New(); switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex()) { case 0: gradientList = MakeGradientList<12>(); break; case 1: gradientList = MakeGradientList<42>(); break; case 2: gradientList = MakeGradientList<92>(); break; case 3: gradientList = MakeGradientList<162>(); break; case 4: gradientList = MakeGradientList<252>(); break; case 5: gradientList = MakeGradientList<362>(); break; case 6: gradientList = MakeGradientList<492>(); break; case 7: gradientList = MakeGradientList<642>(); break; case 8: gradientList = MakeGradientList<812>(); break; case 9: gradientList = MakeGradientList<1002>(); break; default: gradientList = MakeGradientList<92>(); } double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble(); // DWI ESTIMATION clock.Start(); MBI_INFO << "DWI Estimation "; mitk::StatusBar::GetInstance()->DisplayText(status.sprintf( "DWI Estimation for %s", nodename.c_str()).toLatin1()); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkvol ); filter->SetBValue(bVal); filter->SetGradientList(gradientList); //filter->SetNumberOfThreads(1); filter->Update(); clock.Stop(); MBI_DEBUG << "took " << clock.GetMean() << "s."; // TENSORS TO DATATREE mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() ); image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradientList ) ); image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( bVal ) ); image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New() ); mitk::DiffusionPropertyHelper propertyHelper( image ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( image ); mitk::ImageVtkMapper2D::SetDefaultProperties(node); node->SetName(nodename+"_DWI"); GetDataStorage()->Add(node, *itemiter); mitk::ProgressBar::GetInstance()->Progress(); ++itemiter; } mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles).toLatin1()); this->GetRenderWindowPart()->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MITK_INFO << ex ; QMessageBox::information(0, "DWI estimation failed:", ex.GetDescription()); return ; } } void QmitkTensorReconstructionView::PreviewThreshold(int threshold) { mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_DiffusionImages->begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_DiffusionImages->end() ); while ( itemiter != itemiterend ) // for all items { mitk::Image* vols = static_cast( (*itemiter)->GetData()); ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); // Extract b0 image typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filterB0 = FilterType::New(); filterB0->SetInput(itkVectorImagePointer); filterB0->SetDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(vols)); filterB0->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); typedef itk::Image ImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; // apply threshold ThresholdFilterType::Pointer filterThreshold = ThresholdFilterType::New(); filterThreshold->SetInput(filterB0->GetOutput()); filterThreshold->SetLowerThreshold(threshold); filterThreshold->SetInsideValue(0); filterThreshold->SetOutsideValue(1); // mark cut off values red filterThreshold->Update(); mitkImage->InitializeByItk( filterThreshold->GetOutput() ); mitkImage->SetVolume( filterThreshold->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node; if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter)) { node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter); } else { // create a new node, to show thresholded values node = mitk::DataNode::New(); GetDataStorage()->Add( node, *itemiter ); node->SetProperty( "name", mitk::StringProperty::New("ThresholdOverlay")); node->SetBoolProperty("helper object", true); } node->SetData( mitkImage ); itemiter++; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } }