diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp index 6421f65a8b..1d95621cc2 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp @@ -1,418 +1,420 @@ /*=================================================================== 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 const std::string mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME = "meta.GradientDirections"; const std::string mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME = "meta.OriginalGradientDirections"; const std::string mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME = "meta.MeasurementFrame"; const std::string mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME = "meta.ReferenceBValue"; const std::string mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME = "BValueMap"; 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; } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer 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) { // already exists? bool found = false; for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirections->Begin(); 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); // 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) { dirIndices.push_back(std::vector(0)); for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin(); 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 ) ); ApplyMeasurementFrame(); UpdateBValueMap(); std::cout << std::endl; } void mitk::DiffusionPropertyHelper::ApplyMeasurementFrame() { 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); 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(); vec = vec.pre_multiply(measurementFrame); - MITK_INFO << gdcit.Value(); directions->InsertElement(c, vec); c++; } m_Image->SetProperty( 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) { - MITK_INFO << gdcit.Value(); 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 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::InitializeImage() { this->ApplyMeasurementFrame(); 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())); } bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::Image * image) { bool isDiffusionWeightedImage( true ); if( image == NULL ) { 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(); } 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/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx index 91bb189c78..7565957134 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx @@ -1,882 +1,882 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkTimeGeometry.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" #define _USE_MATH_DEFINES #include template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI M_PI template mitk::OdfVtkMapper2D::LocalStorage::LocalStorage() { m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInputData(vtkPolyData::New()); m_OdfsPlanes[1]->AddInputData(vtkPolyData::New()); m_OdfsPlanes[2]->AddInputData(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); } template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); m_ShowMaxNumber = 500; } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D ::GetVtkProp(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); return localStorage->m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } switch(m_ScaleBy) { case ODFSB_NONE: m_OdfSource->SetScale(m_Scaling); break; case ODFSB_GFA: m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } m_OdfSource->SetNormalization(m_Normalization); m_OdfSource->SetOdf(odf); m_OdfSource->Modified(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry(); // set up the cutter orientation according to the current geometry of // the renderers plane double vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.GetVnlVector(), vp ); vnl2vtk( normal.GetVnlVector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; point1[0] = M[0]; point1[1] = M[1]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); point1[0] = L[0]; point1[1] = L[1]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); point1[0] = O[0]; point1[1] = O[1]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry retval; retval.vp[0] = vp[0]; retval.vp[1] = vp[1]; retval.vp[2] = vp[2]; retval.vnormal[0] = vnormal[0]; retval.vnormal[1] = vnormal[1]; retval.vnormal[2] = vnormal[2]; retval.normal[0] = normal[0]; retval.normal[1] = normal[1]; retval.normal[2] = normal[2]; retval.d = d; retval.d1 = d1; retval.d2 = d2; retval.M3D[0] = M3D[0]; retval.M3D[1] = M3D[1]; retval.M3D[2] = M3D[2]; retval.L3D[0] = L3D[0]; retval.L3D[1] = L3D[1]; retval.L3D[2] = L3D[2]; retval.O3D[0] = O3D[0]; retval.O3D[1] = O3D[1]; retval.O3D[2] = O3D[2]; retval.vp_original[0] = vp[0]; retval.vp_original[1] = vp[1]; retval.vp_original[2] = vp[2]; retval.vnormal_original[0] = vnormal[0]; retval.vnormal_original[1] = vnormal[1]; retval.vnormal_original[2] = vnormal[2]; retval.size[0] = size[0]; retval.size[1] = size[1]; retval.origin[0] = origin[0]; retval.origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[0]/spac[0]) < 0.4) dispGeo.vp[0] = 0.4*spac[0]; if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo.vnormal[1] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[1]/spac[1]) < 0.4) dispGeo.vp[1] = 0.4*spac[1]; if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) ) { if(fabs(dispGeo.vp[2]/spac[2]) < 0.4) dispGeo.vp[2] = 0.4*spac[2]; if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo.vp ); m_Planes[index]->SetNormal( dispGeo.vnormal ); vtkSmartPointer points; vtkSmartPointer tmppoints; vtkSmartPointer polydata; vtkSmartPointer pointdata; vtkSmartPointer delaunay; vtkSmartPointer cuttedPlane; // the cutter only works if we do not have a 2D-image // or if we have a 2D-image and want to see the whole image. // // for side views of 2D-images, we need some special treatment if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) || (dims[1] == 1 && dispGeo.vnormal[1] != 0) || (dims[2] == 1 && dispGeo.vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInputData( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInputData( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes1[index]->SetThickness(dispGeo.d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInputData( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes2[index]->SetThickness(dispGeo.d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInputData( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { localStorage->m_OdfsPlanes[index]->RemoveAllInputs(); vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkSmartPointer trans = vtkSmartPointer::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkSmartPointer glyphGenerator = vtkSmartPointer::New(); glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints())); - glyphGenerator->SetRandomMode(0); + glyphGenerator->SetRandomMode(1); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSourceConnection(trans->GetOutputPort() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } localStorage->m_OdfsPlanes[index]->AddInputConnection(glyphGenerator->GetOutputPort()); localStorage->m_OdfsPlanes[index]->Update(); } } localStorage->m_PropAssemblies[index]->VisibilityOn(); if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index])) localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]); localStorage->m_OdfsMappers[index]->SetInputData(localStorage->m_OdfsPlanes[index]->GetOutput()); localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); if(inputTimeGeometry==NULL || inputTimeGeometry->CountTimeSteps()==0 || !inputTimeGeometry->IsValidTimeStep(this->GetTimestep())) return false; if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T"); break; case 1: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S"); break; case 2: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } GenerateDataForRenderer(renderer); } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); if ( (localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime()) && dispGeo.Equals(m_LastDisplayGeometry)) return; localStorage->m_LastUpdateTime.Modified(); if(!IsVisibleOdfs(renderer)) { localStorage->m_OdfsActors[0]->VisibilityOff(); localStorage->m_OdfsActors[1]->VisibilityOff(); localStorage->m_OdfsActors[2]->VisibilityOff(); } else { localStorage->m_OdfsActors[0]->VisibilityOn(); localStorage->m_OdfsActors[1]->VisibilityOn(); localStorage->m_OdfsActors[2]->VisibilityOn(); m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer))); ApplyPropertySettings(); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } } template double mitk::OdfVtkMapper2D::GetMinImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min = spacing[0]; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } return min; } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast(this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) m_Normalization = nmp->GetNormalization(); OdfScaleByProperty* sbp = dynamic_cast(this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) m_ScaleBy = sbp->GetScaleBy(); this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry(); double vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.GetVnlVector(), vnormal ); mitk::Image* currentImage = dynamic_cast( this->GetDataNode()->GetData() ); if( currentImage == NULL ) return false; mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0); mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1); mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2); imageNormal0.Normalize(); imageNormal1.Normalize(); imageNormal2.Normalize(); double eps = 0.000001; int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; return false; } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); 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_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp index 77448fc7c4..cfcbf0e488 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp @@ -1,220 +1,225 @@ /*=================================================================== 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 __itkKspaceImageFilter_txx #define __itkKspaceImageFilter_txx #include #include #include #include "itkKspaceImageFilter.h" #include #include #include #include #define _USE_MATH_DEFINES #include namespace itk { template< class TPixelType > KspaceImageFilter< TPixelType > ::KspaceImageFilter() : m_FrequencyMapSlice(NULL) , m_Z(0) , m_UseConstantRandSeed(false) , m_SpikesPerSlice(0) , m_IsBaseline(true) { m_DiffusionGradientDirection.Fill(0.0); m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); } template< class TPixelType > void KspaceImageFilter< TPixelType > ::BeforeThreadedGenerateData() { if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); typename OutputImageType::Pointer outputImage = OutputImageType::New(); itk::ImageRegion<2> region; region.SetSize(0, m_OutSize[0]); region.SetSize(1, m_OutSize[1]); outputImage->SetLargestPossibleRegion( region ); outputImage->SetBufferedRegion( region ); outputImage->SetRequestedRegion( region ); outputImage->Allocate(); double gamma = 42576000; // Gyromagnetic ratio in Hz/T if ( m_Parameters.m_SignalGen.m_EddyStrength>0 && m_DiffusionGradientDirection.GetNorm()>0.001) { m_DiffusionGradientDirection.Normalize(); m_DiffusionGradientDirection = m_DiffusionGradientDirection * m_Parameters.m_SignalGen.m_EddyStrength/1000 * gamma; m_IsBaseline = false; } this->SetNthOutput(0, outputImage); m_Spike = vcl_complex(0,0); m_Transform = m_Parameters.m_SignalGen.m_ImageDirection; for (int i=0; i<3; i++) for (int j=0; j<3; j++) m_Transform[i][j] *= m_Parameters.m_SignalGen.m_ImageSpacing[j]; } template< class TPixelType > void KspaceImageFilter< TPixelType > ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType) { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); typedef ImageRegionConstIterator< InputImageType > InputIteratorType; double kxMax = outputImage->GetLargestPossibleRegion().GetSize(0); // k-space size in x-direction double kyMax = outputImage->GetLargestPossibleRegion().GetSize(1); // k-space size in y-direction double xMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(0); // scanner coverage in x-direction double yMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(1); // scanner coverage in y-direction double numPix = kxMax*kyMax; double dt = m_Parameters.m_SignalGen.m_tLine/kxMax; double fromMaxEcho = - m_Parameters.m_SignalGen.m_tLine*kyMax/2; double upsampling = xMax/kxMax; // discrepany between k-space resolution and image resolution double yMaxFov = kyMax*upsampling; // actual FOV in y-direction (in x-direction xMax==FOV) int xRingingOffset = xMax-kxMax; int yRingingOffset = yMaxFov-kyMax; while( !oit.IsAtEnd() ) { itk::Index< 2 > kIdx; kIdx[0] = oit.GetIndex()[0]; kIdx[1] = oit.GetIndex()[1]; - double t = fromMaxEcho + ((double)kIdx[1]*kxMax+(double)kIdx[0])*dt; // dephasing time + // dephasing time + double t = 0; + if (!m_Parameters.m_SignalGen.m_ReversePhase) + t = fromMaxEcho + ((double)kIdx[1]*kxMax+(double)kIdx[0])*dt; + else + t = fromMaxEcho + ((double)(kyMax-1-kIdx[1])*kxMax+(double)kIdx[0])*dt; // rearrange slice if( kIdx[0] < kxMax/2 ) kIdx[0] = kIdx[0] + kxMax/2; else kIdx[0] = kIdx[0] - kxMax/2; if( kIdx[1] < kyMax/2 ) kIdx[1] = kIdx[1] + kyMax/2; else kIdx[1] = kIdx[1] - kyMax/2; // calculate eddy current decay factors double eddyDecay = 0; if ( m_Parameters.m_SignalGen.m_EddyStrength>0) eddyDecay = exp(-( m_Parameters.m_SignalGen.m_tEcho/2 + t)/ m_Parameters.m_SignalGen.m_Tau) * t/1000; // calcualte signal relaxation factors std::vector< double > relaxFactor; if ( m_Parameters.m_SignalGen.m_DoSimulateRelaxation) for (unsigned int i=0; i=kxMax/2) kx += xRingingOffset; if (ky>=kyMax/2) ky += yRingingOffset; vcl_complex s(0,0); InputIteratorType it(m_CompartmentImages.at(0), m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); while( !it.IsAtEnd() ) { double x = it.GetIndex()[0]-xMax/2; double y = it.GetIndex()[1]-yMax/2; vcl_complex f(0, 0); // sum compartment signals and simulate relaxation for (unsigned int i=0; i( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * relaxFactor.at(i) * m_Parameters.m_SignalGen.m_SignalScale, 0); else f += std::complex( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * m_Parameters.m_SignalGen.m_SignalScale ); // simulate eddy currents and other distortions double omega_t = 0; if ( m_Parameters.m_SignalGen.m_EddyStrength>0 && !m_IsBaseline) { itk::Vector< double, 3 > pos; pos[0] = x; pos[1] = y; pos[2] = m_Z; pos = m_Transform*pos/1000; // vector from image center to current position (in meter) omega_t += (m_DiffusionGradientDirection[0]*pos[0]+m_DiffusionGradientDirection[1]*pos[1]+m_DiffusionGradientDirection[2]*pos[2])*eddyDecay; } if (m_FrequencyMapSlice.IsNotNull()) // simulate distortions omega_t += m_FrequencyMapSlice->GetPixel(it.GetIndex())*t/1000; if (y<-yMaxFov/2) y += yMaxFov; else if (y>=yMaxFov/2) y -= yMaxFov; // actual DFT term s += f * exp( std::complex(0, 2 * M_PI * (kx*x/xMax + ky*y/yMaxFov + omega_t )) ); ++it; } s /= numPix; if (m_SpikesPerSlice>0 && sqrt(s.imag()*s.imag()+s.real()*s.real()) > sqrt(m_Spike.imag()*m_Spike.imag()+m_Spike.real()*m_Spike.real()) ) m_Spike = s; outputImage->SetPixel(kIdx, s); ++oit; } } template< class TPixelType > void KspaceImageFilter< TPixelType > ::AfterThreadedGenerateData() { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); double kxMax = outputImage->GetLargestPossibleRegion().GetSize(0); // k-space size in x-direction double kyMax = outputImage->GetLargestPossibleRegion().GetSize(1); // k-space size in y-direction m_Spike *= m_Parameters.m_SignalGen.m_SpikeAmplitude; itk::Index< 2 > spikeIdx; for (unsigned int i=0; iGetIntegerVariate()%(int)kxMax; spikeIdx[1] = m_RandGen->GetIntegerVariate()%(int)kyMax; outputImage->SetPixel(spikeIdx, m_Spike); } } } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h index 78565e23d4..1e2ad4c9ff 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h @@ -1,122 +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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkKspaceImageFilter_h_ #define __itkKspaceImageFilter_h_ #include #include #include #include #include #include using namespace std; namespace itk{ /** * \brief Simulates k-space acquisition of one slice with a single shot EPI sequence. Enables the simulation of various effects occuring during real MR acquisitions: * - T2 signal relaxation * - Spikes * - N/2 Ghosts * - Aliasing (wrap around) * - Image distortions (off-frequency effects) * - Gibbs ringing * - Eddy current effects * Based on a discrete fourier transformation. * See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ template< class TPixelType > class KspaceImageFilter : public ImageSource< Image< vcl_complex< TPixelType >, 2 > > { public: typedef KspaceImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< vcl_complex< TPixelType >, 2 > > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(KspaceImageFilter, ImageToImageFilter) typedef typename itk::Image< double, 2 > InputImageType; typedef typename InputImageType::Pointer InputImagePointerType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::Matrix MatrixType; typedef itk::Point Point2D; itkSetMacro( SpikesPerSlice, unsigned int ) ///< Number of spikes per slice. Corresponding parameter in fiberfox parameter object specifies the number of spikes for the whole image and can thus not be used here. itkSetMacro( FrequencyMapSlice, typename InputImageType::Pointer ) ///< Used to simulate distortions. Specifies additional frequency component per voxel. itkSetMacro( Z, double ) ///< Slice position, necessary for eddy current simulation. itkSetMacro( OutSize, itk::Size<2> ) ///< Output slice size. Can be different from input size, e.g. if Gibbs ringing is enabled. itkSetMacro( UseConstantRandSeed, bool ) ///< Use constant seed for random generator for reproducible results. void SetParameters( FiberfoxParameters param ){ m_Parameters = param; } FiberfoxParameters GetParameters(){ return m_Parameters; } void SetCompartmentImages( std::vector< InputImagePointerType > cImgs ) { m_CompartmentImages=cImgs; } ///< One signal image per compartment. void SetT2( std::vector< double > t2Vector ) { m_T2=t2Vector; } ///< One T2 relaxation constant per compartment image. + void SetT1( std::vector< double > t1Vector ) { m_T1=t1Vector; } ///< One T1 relaxation constant per compartment image. void SetDiffusionGradientDirection(itk::Vector g) { m_DiffusionGradientDirection=g; } ///< Gradient direction is needed for eddy current simulation. protected: KspaceImageFilter(); ~KspaceImageFilter() {} void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType); void AfterThreadedGenerateData(); FiberfoxParameters m_Parameters; typename InputImageType::Pointer m_FrequencyMapSlice; vector< double > m_T2; + vector< double > m_T1; vector< InputImagePointerType > m_CompartmentImages; itk::Vector m_DiffusionGradientDirection; double m_Z; bool m_UseConstantRandSeed; unsigned int m_SpikesPerSlice; itk::Size<2> m_OutSize; bool m_IsBaseline; vcl_complex m_Spike; MatrixType m_Transform; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkKspaceImageFilter.cpp" #endif #endif //__itkKspaceImageFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 86093896aa..7906df9dcb 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,1302 +1,1325 @@ /*=================================================================== 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 "itkTractsToDWIImageFilter.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 #include #include #include #include namespace itk { template< class PixelType > TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() : m_FiberBundle(NULL) , m_StatusText("") , m_UseConstantRandSeed(false) , m_RandGen(itk::Statistics::MersenneTwisterRandomVariateGenerator::New()) { m_RandGen->SetSeed(); } template< class PixelType > TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } template< class PixelType > TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >::DoKspaceStuff( std::vector< DoubleDwiType::Pointer >& images ) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); // create slice object ImageRegion<2> sliceRegion; - sliceRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); - sliceRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); + sliceRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]); + sliceRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]); Vector< double, 2 > sliceSpacing; - sliceSpacing[0] = m_UpsampledSpacing[0]; - sliceSpacing[1] = m_UpsampledSpacing[1]; + sliceSpacing[0] = m_WorkingSpacing[0]; + sliceSpacing[1] = m_WorkingSpacing[1]; // frequency map slice SliceType::Pointer fMapSlice = NULL; if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) { fMapSlice = SliceType::New(); ImageRegion<2> region; - region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); - region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); + region.SetSize(0, m_WorkingImageRegion.GetSize()[0]); + region.SetSize(1, m_WorkingImageRegion.GetSize()[1]); fMapSlice->SetLargestPossibleRegion( region ); fMapSlice->SetBufferedRegion( region ); fMapSlice->SetRequestedRegion( region ); fMapSlice->Allocate(); fMapSlice->FillBuffer(0.0); } DoubleDwiType::Pointer newImage = DoubleDwiType::New(); newImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); newImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); newImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - newImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_ImageRegion ); - newImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_ImageRegion ); - newImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_ImageRegion ); + newImage->SetLargestPossibleRegion( m_CroppedRegion ); + newImage->SetBufferedRegion( m_CroppedRegion ); + newImage->SetRequestedRegion( m_CroppedRegion ); newImage->SetVectorLength( images.at(0)->GetVectorLength() ); newImage->Allocate(); std::vector< unsigned int > spikeVolume; for (unsigned int i=0; iGetIntegerVariate()%images.at(0)->GetVectorLength()); + spikeVolume.push_back(m_RandGen->GetIntegerVariate()%(images.at(0)->GetVectorLength())); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned long lastTick = 0; boost::progress_display disp(2*images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2)); for (unsigned int g=0; gGetVectorLength(); g++) { std::vector< unsigned int > spikeSlice; while (!spikeVolume.empty() && spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%images.at(0)->GetLargestPossibleRegion().GetSize(2)); spikeVolume.pop_back(); } std::sort (spikeSlice.begin(), spikeSlice.end()); std::reverse (spikeSlice.begin(), spikeSlice.end()); for (unsigned int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { std::vector< SliceType::Pointer > compartmentSlices; std::vector< double > t2Vector; + std::vector< double > t1Vector; for (unsigned int i=0; i* signalModel; if (iSetLargestPossibleRegion( sliceRegion ); slice->SetBufferedRegion( sliceRegion ); slice->SetRequestedRegion( sliceRegion ); slice->SetSpacing(sliceSpacing); slice->Allocate(); slice->FillBuffer(0.0); // extract slice from channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; slice->SetPixel(index2D, images.at(i)->GetPixel(index3D)[g]); if (fMapSlice.IsNotNull() && i==0) fMapSlice->SetPixel(index2D, m_Parameters.m_SignalGen.m_FrequencyMap->GetPixel(index3D)); } compartmentSlices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); + t1Vector.push_back(signalModel->GetT1()); } if (this->GetAbortGenerateData()) return NULL; // create k-sapce (inverse fourier transform slices) - itk::Size<2> outSize; outSize.SetElement(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)); outSize.SetElement(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)); + itk::Size<2> outSize; outSize.SetElement(0, m_CroppedRegion.GetSize(0)); outSize.SetElement(1, m_CroppedRegion.GetSize(1)); itk::KspaceImageFilter< SliceType::PixelType >::Pointer idft = itk::KspaceImageFilter< SliceType::PixelType >::New(); idft->SetCompartmentImages(compartmentSlices); idft->SetT2(t2Vector); + idft->SetT1(t1Vector); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); idft->SetParameters(m_Parameters); idft->SetZ((double)z-(double)images.at(0)->GetLargestPossibleRegion().GetSize(2)/2.0); idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g)); idft->SetFrequencyMapSlice(fMapSlice); idft->SetOutSize(outSize); int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } idft->SetSpikesPerSlice(numSpikes); idft->Update(); ComplexSliceType::Pointer fSlice; fSlice = idft->GetOutput(); ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; // fourier transform slice SliceType::Pointer newSlice; itk::DftImageFilter< SliceType::PixelType >::Pointer dft = itk::DftImageFilter< SliceType::PixelType >::New(); dft->SetInput(fSlice); dft->Update(); newSlice = dft->GetOutput(); // put slice back into channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::PixelType pix3D = newImage->GetPixel(index3D); pix3D[g] = newSlice->GetPixel(index2D); newImage->SetPixel(index3D, pix3D); } ++disp; newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } } m_StatusText += "\n\n"; return newImage; } template< class PixelType > -void TractsToDWIImageFilter< PixelType >::GenerateData() +void TractsToDWIImageFilter< PixelType >::CheckVolumeFractionImages() { - m_TimeProbe.Start(); - m_StatusText = "Starting simulation\n"; - - // check input data - if (m_FiberBundle.IsNull()) - itkExceptionMacro("Input fiber bundle is NULL!"); + // check for fiber volume fraction maps + for (int i=0; iGetVolumeFractionImage().IsNotNull()) + m_StatusText += "Using volume fraction map for fiber compartment " + boost::lexical_cast(i+1) + "\n"; - if (m_Parameters.m_FiberModelList.empty()) - itkExceptionMacro("No diffusion model for fiber compartments defined!"); + // check for non-fiber volume fraction maps + for (int i=0; iGetVolumeFractionImage().IsNotNull()) + m_StatusText += "Using volume fraction map for non-fiber compartment " + boost::lexical_cast(i+1) + "\n"; - if (m_Parameters.m_NonFiberModelList.empty()) - itkExceptionMacro("No diffusion model for non-fiber compartments defined!"); + // check volume fraction images + if (m_Parameters.m_FiberModelList.size()>2) + for (int i=0; iGetVolumeFractionImage().IsNull()) + itkExceptionMacro("More than two fiber compartment selected but no volume fraction maps set!"); - int baselineIndex = m_Parameters.m_SignalGen.GetFirstBaselineIndex(); - if (baselineIndex<0) - itkExceptionMacro("No baseline index found!"); + if (m_Parameters.m_NonFiberModelList.size()>1) + for (int i=0; iGetVolumeFractionImage().IsNull()) + itkExceptionMacro("More than one non-fiber compartment selected but no volume fraction maps set!"); - if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) - m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false; - if (m_UseConstantRandSeed) // always generate the same random numbers? - m_RandGen->SetSeed(0); - else - m_RandGen->SetSeed(); + // initialize the images that store the output volume fraction of each compartment + m_VolumeFractions.clear(); + for (int i=0; iSetSpacing( m_WorkingSpacing ); + doubleImg->SetOrigin( m_WorkingOrigin ); + doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); + doubleImg->SetLargestPossibleRegion( m_WorkingImageRegion ); + doubleImg->SetBufferedRegion( m_WorkingImageRegion ); + doubleImg->SetRequestedRegion( m_WorkingImageRegion ); + doubleImg->Allocate(); + doubleImg->FillBuffer(0); + m_VolumeFractions.push_back(doubleImg); + } +} +template< class PixelType > +void TractsToDWIImageFilter< PixelType >::InitializeData() +{ // initialize output dwi image - ImageRegion<3> croppedRegion = m_Parameters.m_SignalGen.m_ImageRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Parameters.m_SignalGen.m_CroppingFactor); - itk::Point shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)-croppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; - typename OutputImageType::Pointer outImage = OutputImageType::New(); - outImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); - outImage->SetOrigin( shiftedOrigin ); - outImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - outImage->SetLargestPossibleRegion( croppedRegion ); - outImage->SetBufferedRegion( croppedRegion ); - outImage->SetRequestedRegion( croppedRegion ); - outImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); - outImage->Allocate(); + m_CroppedRegion = m_Parameters.m_SignalGen.m_ImageRegion; m_CroppedRegion.SetSize(1, m_CroppedRegion.GetSize(1)*m_Parameters.m_SignalGen.m_CroppingFactor); + itk::Point shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)-m_CroppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; + m_OutputImage = OutputImageType::New(); + m_OutputImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); + m_OutputImage->SetOrigin( shiftedOrigin ); + m_OutputImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); + m_OutputImage->SetLargestPossibleRegion( m_CroppedRegion ); + m_OutputImage->SetBufferedRegion( m_CroppedRegion ); + m_OutputImage->SetRequestedRegion( m_CroppedRegion ); + m_OutputImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); + m_OutputImage->Allocate(); typename OutputImageType::PixelType temp; temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); temp.Fill(0.0); - outImage->FillBuffer(temp); + m_OutputImage->FillBuffer(temp); + + if ( m_CroppedRegion.GetSize(0)%2 == 1 ) + m_CroppedRegion.SetSize(0, m_CroppedRegion.GetSize(0)+1); + if ( m_CroppedRegion.GetSize(1)%2 == 1 ) + m_CroppedRegion.SetSize(1, m_CroppedRegion.GetSize(1)+1); // ADJUST GEOMETRY FOR FURTHER PROCESSING // is input slize size a power of two? unsigned int x=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0); unsigned int y=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1); ItkDoubleImgType::SizeType pad; pad[0]=x%2; pad[1]=y%2; pad[2]=0; m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, x+pad[0]); m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, y+pad[1]); if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); zeroPadder->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = zeroPadder->GetOutput(); } if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); zeroPadder->SetInput(m_Parameters.m_SignalGen.m_MaskImage); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); m_Parameters.m_SignalGen.m_MaskImage = zeroPadder->GetOutput(); } // Apply in-plane upsampling for Gibbs ringing artifact double upsampling = 1; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) upsampling = 2; - m_UpsampledSpacing = m_Parameters.m_SignalGen.m_ImageSpacing; - m_UpsampledSpacing[0] /= upsampling; - m_UpsampledSpacing[1] /= upsampling; - m_UpsampledImageRegion = m_Parameters.m_SignalGen.m_ImageRegion; - m_UpsampledImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling); - m_UpsampledImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling); - m_UpsampledOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; - m_UpsampledOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; m_UpsampledOrigin[0] += m_UpsampledSpacing[0]/2; - m_UpsampledOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_UpsampledOrigin[1] += m_UpsampledSpacing[1]/2; - m_UpsampledOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; m_UpsampledOrigin[2] += m_UpsampledSpacing[2]/2; + m_WorkingSpacing = m_Parameters.m_SignalGen.m_ImageSpacing; + m_WorkingSpacing[0] /= upsampling; + m_WorkingSpacing[1] /= upsampling; + m_WorkingImageRegion = m_Parameters.m_SignalGen.m_ImageRegion; + m_WorkingImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling); + m_WorkingImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling); + m_WorkingOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; + m_WorkingOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; m_WorkingOrigin[0] += m_WorkingSpacing[0]/2; + m_WorkingOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_WorkingOrigin[1] += m_WorkingSpacing[1]/2; + m_WorkingOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; m_WorkingOrigin[2] += m_WorkingSpacing[2]/2; + m_VoxelVolume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2]; // generate double images to store the individual compartment signals m_CompartmentImages.clear(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); - for (int i=0; iSetSpacing( m_UpsampledSpacing ); - doubleDwi->SetOrigin( m_UpsampledOrigin ); + doubleDwi->SetSpacing( m_WorkingSpacing ); + doubleDwi->SetOrigin( m_WorkingOrigin ); doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - doubleDwi->SetLargestPossibleRegion( m_UpsampledImageRegion ); - doubleDwi->SetBufferedRegion( m_UpsampledImageRegion ); - doubleDwi->SetRequestedRegion( m_UpsampledImageRegion ); + doubleDwi->SetLargestPossibleRegion( m_WorkingImageRegion ); + doubleDwi->SetBufferedRegion( m_WorkingImageRegion ); + doubleDwi->SetRequestedRegion( m_WorkingImageRegion ); doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); m_CompartmentImages.push_back(doubleDwi); } - // initialize output volume fraction images - m_VolumeFractions.clear(); - for (int i=0; iSetSpacing( m_UpsampledSpacing ); - doubleImg->SetOrigin( m_UpsampledOrigin ); - doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - doubleImg->SetLargestPossibleRegion( m_UpsampledImageRegion ); - doubleImg->SetBufferedRegion( m_UpsampledImageRegion ); - doubleImg->SetRequestedRegion( m_UpsampledImageRegion ); - doubleImg->Allocate(); - doubleImg->FillBuffer(0); - m_VolumeFractions.push_back(doubleImg); - } - - // get volume fraction images - ItkDoubleImgType::Pointer sumImage = ItkDoubleImgType::New(); - bool foundVolumeFractionImage = false; - - for (int i=0; iGetVolumeFractionImage().IsNotNull()) - { - foundVolumeFractionImage = true; - - itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); - zeroPadder->SetInput(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); - zeroPadder->SetConstant(0); - zeroPadder->SetPadUpperBound(pad); - zeroPadder->Update(); - m_Parameters.m_NonFiberModelList[i]->SetVolumeFractionImage(zeroPadder->GetOutput()); - - sumImage->SetSpacing( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetSpacing() ); - sumImage->SetOrigin( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetOrigin() ); - sumImage->SetDirection( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetDirection() ); - sumImage->SetLargestPossibleRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); - sumImage->SetBufferedRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); - sumImage->SetRequestedRegion( m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion() ); - sumImage->Allocate(); - sumImage->FillBuffer(0); - break; - } - } - if (!foundVolumeFractionImage) - { - sumImage->SetSpacing( m_UpsampledSpacing ); - sumImage->SetOrigin( m_UpsampledOrigin ); - sumImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - sumImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); - sumImage->SetBufferedRegion( m_UpsampledImageRegion ); - sumImage->SetRequestedRegion( m_UpsampledImageRegion ); - sumImage->Allocate(); - sumImage->FillBuffer(0.0); - } - for (int i=0; iGetVolumeFractionImage().IsNull()) - { - ItkDoubleImgType::Pointer doubleImg = ItkDoubleImgType::New(); - doubleImg->SetSpacing( sumImage->GetSpacing() ); - doubleImg->SetOrigin( sumImage->GetOrigin() ); - doubleImg->SetDirection( sumImage->GetDirection() ); - doubleImg->SetLargestPossibleRegion( sumImage->GetLargestPossibleRegion() ); - doubleImg->SetBufferedRegion( sumImage->GetLargestPossibleRegion() ); - doubleImg->SetRequestedRegion( sumImage->GetLargestPossibleRegion() ); - doubleImg->Allocate(); - doubleImg->FillBuffer(1.0/numNonFiberCompartments); - m_Parameters.m_NonFiberModelList[i]->SetVolumeFractionImage(doubleImg); - } - ImageRegionIterator it(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage(), m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion()); - while(!it.IsAtEnd()) - { - sumImage->SetPixel(it.GetIndex(), sumImage->GetPixel(it.GetIndex())+it.Get()); - ++it; - } - } - for (int i=0; i it(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage(), m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion()); - while(!it.IsAtEnd()) - { - if (sumImage->GetPixel(it.GetIndex())>0) - it.Set(it.Get()/sumImage->GetPixel(it.GetIndex())); - ++it; - } - } - // resample mask image and frequency map to fit upsampled geometry if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) { if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull()) { // rescale mask image (otherwise there are problems with the resampling) itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); // resample mask image itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); - resampler->SetSize(m_UpsampledImageRegion.GetSize()); - resampler->SetOutputSpacing(m_UpsampledSpacing); - resampler->SetOutputOrigin(m_UpsampledOrigin); + resampler->SetSize(m_WorkingImageRegion.GetSize()); + resampler->SetOutputSpacing(m_WorkingSpacing); + resampler->SetOutputOrigin(m_WorkingOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput(); - - itk::ImageFileWriter::Pointer w = itk::ImageFileWriter::New(); - w->SetFileName("/local/mask_ups.nrrd"); - w->SetInput(m_Parameters.m_SignalGen.m_MaskImage); - w->Update(); } // resample frequency map if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_FrequencyMap); - resampler->SetSize(m_UpsampledImageRegion.GetSize()); - resampler->SetOutputSpacing(m_UpsampledSpacing); - resampler->SetOutputOrigin(m_UpsampledOrigin); + resampler->SetSize(m_WorkingImageRegion.GetSize()); + resampler->SetOutputSpacing(m_WorkingSpacing); + resampler->SetOutputOrigin(m_WorkingOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput(); } } - // no input tissue mask is set -> create default m_MaskImageSet = true; if (m_Parameters.m_SignalGen.m_MaskImage.IsNull()) { + // no input tissue mask is set -> create default m_StatusText += "No tissue mask set\n"; MITK_INFO << "No tissue mask set"; m_Parameters.m_SignalGen.m_MaskImage = ItkUcharImgType::New(); - m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_UpsampledSpacing ); - m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_UpsampledOrigin ); + m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_WorkingSpacing ); + m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_WorkingOrigin ); m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); - m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_UpsampledImageRegion ); - m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_UpsampledImageRegion ); + m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_WorkingImageRegion ); + m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_WorkingImageRegion ); + m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->Allocate(); - m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(1); + m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(100); m_MaskImageSet = false; } else { + if (m_Parameters.m_SignalGen.m_MaskImage->GetLargestPossibleRegion()!=m_Parameters.m_SignalGen.m_ImageRegion) + itkExceptionMacro("Mask image and specified DWI geometry are not matching!"); + m_StatusText += "Using tissue mask\n"; MITK_INFO << "Using tissue mask"; } - m_Parameters.m_SignalGen.m_ImageRegion = croppedRegion; - x=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0); y=m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1); - if ( x%2 == 1 ) - m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, x+1); - if ( y%2 == 1 ) - m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, y+1); - - // resample fiber bundle for sufficient voxel coverage - m_StatusText += "\n"+this->GetTime()+" > Resampling fibers ...\n"; - double segmentVolume = 0.0001; - float minSpacing = 1; - if(m_UpsampledSpacing[0]GetDeepCopy(); - double volumeAccuracy = 10; - m_FiberBundleWorkingCopy->ResampleSpline(minSpacing/volumeAccuracy); - double mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000; - if (mmRadius>0) - segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/volumeAccuracy; - - double maxVolume = 0; - m_VoxelVolume = m_UpsampledSpacing[0]*m_UpsampledSpacing[1]*m_UpsampledSpacing[2]; - if (m_Parameters.m_SignalGen.m_DoAddMotion) { std::string fileName = "fiberfox_motion_0.log"; std::string filePath = mitk::IOUtil::GetTempPath(); if (m_Parameters.m_Misc.m_OutputPath.size()>0) filePath = m_Parameters.m_Misc.m_OutputPath; int c = 1; while (itksys::SystemTools::FileExists((filePath+fileName).c_str())) { fileName = "fiberfox_motion_"; fileName += boost::lexical_cast(c); fileName += ".log"; c++; } m_Logfile.open((filePath+fileName).c_str()); m_Logfile << "0 rotation: 0,0,0; translation: 0,0,0\n"; if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { m_StatusText += "Adding random motion artifacts:\n"; m_StatusText += "Maximum rotation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°\n"; m_StatusText += "Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm\n"; } else { m_StatusText += "Adding linear motion artifacts:\n"; m_StatusText += "Maximum rotation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°\n"; m_StatusText += "Maximum translation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm\n"; } m_StatusText += "Motion logfile: " + (filePath+fileName) + "\n"; MITK_INFO << "Adding motion artifacts"; MITK_INFO << "Maximum rotation: " << m_Parameters.m_SignalGen.m_Rotation; MITK_INFO << "Maxmimum translation: " << m_Parameters.m_SignalGen.m_Translation; } - maxVolume = 0; - - m_StatusText += "\n"+this->GetTime()+" > Generating " + boost::lexical_cast(numFiberCompartments+numNonFiberCompartments) + "-compartment diffusion-weighted signal.\n"; - MITK_INFO << "Generating " << numFiberCompartments+numNonFiberCompartments << "-compartment diffusion-weighted signal."; - int numFibers = m_FiberBundle->GetNumFibers(); - boost::progress_display disp(numFibers*m_Parameters.m_SignalGen.GetNumVolumes()); - // get transform for motion artifacts - m_FiberBundleTransformed = m_FiberBundleWorkingCopy; m_Rotation = m_Parameters.m_SignalGen.m_Rotation/m_Parameters.m_SignalGen.GetNumVolumes(); m_Translation = m_Parameters.m_SignalGen.m_Translation/m_Parameters.m_SignalGen.GetNumVolumes(); // creat image to hold transformed mask (motion artifact) - m_MaskImage = ItkUcharImgType::New(); + m_TransformedMaskImage = ItkUcharImgType::New(); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage); duplicator->Update(); - m_MaskImage = duplicator->GetOutput(); + m_TransformedMaskImage = duplicator->GetOutput(); // second upsampling needed for motion artifacts - ImageRegion<3> upsampledImageRegion = m_UpsampledImageRegion; - DoubleVectorType upsampledSpacing = m_UpsampledSpacing; + ImageRegion<3> upsampledImageRegion = m_WorkingImageRegion; + DoubleVectorType upsampledSpacing = m_WorkingSpacing; upsampledSpacing[0] /= 4; upsampledSpacing[1] /= 4; upsampledSpacing[2] /= 4; - upsampledImageRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]*4); - upsampledImageRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]*4); - upsampledImageRegion.SetSize(2, m_UpsampledImageRegion.GetSize()[2]*4); - itk::Point upsampledOrigin = m_UpsampledOrigin; - upsampledOrigin[0] -= m_UpsampledSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; - upsampledOrigin[1] -= m_UpsampledSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; - upsampledOrigin[2] -= m_UpsampledSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; + upsampledImageRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]*4); + upsampledImageRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]*4); + upsampledImageRegion.SetSize(2, m_WorkingImageRegion.GetSize()[2]*4); + itk::Point upsampledOrigin = m_WorkingOrigin; + upsampledOrigin[0] -= m_WorkingSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; + upsampledOrigin[1] -= m_WorkingSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; + upsampledOrigin[2] -= m_WorkingSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; m_UpsampledMaskImage = ItkUcharImgType::New(); itk::ResampleImageFilter::Pointer upsampler = itk::ResampleImageFilter::New(); upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetSize(upsampledImageRegion.GetSize()); upsampler->SetOutputSpacing(upsampledSpacing); upsampler->SetOutputOrigin(upsampledOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); upsampler->SetInterpolator(nn_interpolator); upsampler->Update(); m_UpsampledMaskImage = upsampler->GetOutput(); +} + +template< class PixelType > +void TractsToDWIImageFilter< PixelType >::InitializeFiberData() +{ + // resample fiber bundle for sufficient voxel coverage + m_StatusText += "\n"+this->GetTime()+" > Resampling fibers ...\n"; + segmentVolume = 0.0001; + float minSpacing = 1; + if(m_WorkingSpacing[0]GetDeepCopy(); // working copy is needed because we need to resample the fibers but do not want to change the original bundle + double volumeAccuracy = 10; + m_FiberBundleWorkingCopy->ResampleSpline(minSpacing/volumeAccuracy); + mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000; + if (mmRadius>0) + segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/volumeAccuracy; + m_FiberBundleTransformed = m_FiberBundleWorkingCopy; // a secon fiber bundle is needed to store the transformed version of the m_FiberBundleWorkingCopy +} +template< class PixelType > +void TractsToDWIImageFilter< PixelType >::GenerateData() +{ + m_TimeProbe.Start(); + m_StatusText = "Starting simulation\n"; + + // check input data + if (m_FiberBundle.IsNull()) + itkExceptionMacro("Input fiber bundle is NULL!"); + + if (m_Parameters.m_FiberModelList.empty()) + itkExceptionMacro("No diffusion model for fiber compartments defined! At least one fiber compartment is necessary."); + + if (m_Parameters.m_NonFiberModelList.empty()) + itkExceptionMacro("No diffusion model for non-fiber compartments defined! At least one non-fiber compartment is necessary."); + + int baselineIndex = m_Parameters.m_SignalGen.GetFirstBaselineIndex(); + if (baselineIndex<0) + itkExceptionMacro("No baseline index found!"); + + if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) // No upsampling of input image needed if no k-space simulation is performed + m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false; + + if (m_UseConstantRandSeed) // always generate the same random numbers? + m_RandGen->SetSeed(0); + else + m_RandGen->SetSeed(); + + InitializeData(); + CheckVolumeFractionImages(); + InitializeFiberData(); + + int numFiberCompartments = m_Parameters.m_FiberModelList.size(); + int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); + + double maxVolume = 0; unsigned long lastTick = 0; int signalModelSeed = m_RandGen->GetIntegerVariate(); + + m_StatusText += "\n"+this->GetTime()+" > Generating " + boost::lexical_cast(numFiberCompartments+numNonFiberCompartments) + "-compartment diffusion-weighted signal.\n"; + MITK_INFO << "Generating " << numFiberCompartments+numNonFiberCompartments << "-compartment diffusion-weighted signal."; + int numFibers = m_FiberBundleWorkingCopy->GetNumFibers(); + boost::progress_display disp(numFibers*m_Parameters.m_SignalGen.GetNumVolumes()); + switch (m_Parameters.m_SignalGen.m_DiffusionDirectionMode) { case(SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS): // use fiber tangent directions to determine diffusion direction { m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; for (unsigned int g=0; gSetSeed(signalModelSeed); for (int i=0; iSetSeed(signalModelSeed); + // storing voxel-wise intra-axonal volume in mm³ ItkDoubleImgType::Pointer intraAxonalVolumeImage = ItkDoubleImgType::New(); - intraAxonalVolumeImage->SetSpacing( m_UpsampledSpacing ); - intraAxonalVolumeImage->SetOrigin( m_UpsampledOrigin ); + intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing ); + intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - intraAxonalVolumeImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); - intraAxonalVolumeImage->SetBufferedRegion( m_UpsampledImageRegion ); - intraAxonalVolumeImage->SetRequestedRegion( m_UpsampledImageRegion ); + intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion ); + intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion ); + intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); + maxVolume = 0; vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData(); - // generate fiber signal (if there are any fiber models present) if (!m_Parameters.m_FiberModelList.empty()) for( int i=0; iGetFiberWeight(i); vtkCell* cell = fiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; for( int j=0; jGetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } double* temp = points->GetPoint(j); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(j+1))-v; else dir = v-GetItkVector(points->GetPoint(j-1)); if (dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) continue; itk::Index<3> idx; itk::ContinuousIndex contIndex; - m_MaskImage->TransformPhysicalPointToIndex(vertex, idx); - m_MaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); + m_TransformedMaskImage->TransformPhysicalPointToIndex(vertex, idx); + m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex); - if (!m_MaskImage->GetLargestPossibleRegion().IsInside(idx) || m_MaskImage->GetPixel(idx)<=0) + if (!m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(idx) || m_TransformedMaskImage->GetPixel(idx)<=0) continue; // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); DoubleDwiType::PixelType pix = m_CompartmentImages.at(k)->GetPixel(idx); pix[g] += fiberWeight*segmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g); m_CompartmentImages.at(k)->SetPixel(idx, pix); } // update fiber volume image double vol = intraAxonalVolumeImage->GetPixel(idx) + segmentVolume*fiberWeight; intraAxonalVolumeImage->SetPixel(idx, vol); - if (g==0 && vol>maxVolume) + if (vol>maxVolume) // we assume that the first volume is always unweighted! maxVolume = vol; } // progress report ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } // generate non-fiber signal - ImageRegionIterator it3(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); - double fact = 1; - if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001 || maxVolume>m_VoxelVolume) + ImageRegionIterator it3(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion()); + double fact = 1; // density correction factor in mm³ + if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001 || maxVolume>m_VoxelVolume) // the fullest voxel is always completely full fact = m_VoxelVolume/maxVolume; while(!it3.IsAtEnd()) { if (it3.Get()>0) { DoubleDwiType::IndexType index = it3.GetIndex(); + itk::Point point; + m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point); + if (m_Parameters.m_SignalGen.m_DoAddMotion) + { + if (m_Parameters.m_SignalGen.m_DoRandomizeMotion && g>0) + point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0],-m_Rotation[1],-m_Rotation[2],-m_Translation[0],-m_Translation[1],-m_Translation[2]); + else if (g>=0) + point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0]*g,-m_Rotation[1]*g,-m_Rotation[2]*g,-m_Translation[0]*g,-m_Translation[1]*g,-m_Translation[2]*g); + } - // adjust intra-axonal signal to abtain an only-fiber voxel - if (fabs(fact-1.0)>0.0001) - for (int i=0; iGetPixel(index); - pix[g] *= fact; - m_CompartmentImages.at(i)->SetPixel(index, pix); - } + double iAxVolume = intraAxonalVolumeImage->GetPixel(index); + + // if volume fraction image is set use it, otherwise use scaling factor to obtain one full fiber voxel + double fact2 = fact; + if (m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr && iAxVolume>0.0001) + { + DoubleDwiType::IndexType newIndex; + m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); + if (m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) + fact2 = m_VoxelVolume*m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()->GetPixel(newIndex)/iAxVolume; + } + + // adjust intra-axonal image value + for (int i=0; iGetPixel(index); + pix[g] *= fact2; + m_CompartmentImages.at(i)->SetPixel(index, pix); + } // simulate other compartments - SimulateNonFiberSignal(index, intraAxonalVolumeImage->GetPixel(index)*fact, g); + SimulateExtraAxonalSignal(index, iAxVolume*fact2, g); } ++it3; } // move fibers SimulateMotion(g); } break; } case (SignalGenerationParameters::MAIN_FIBER_DIRECTIONS): // use main fiber directions to determine voxel-wise diffusion directions { typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< unsigned int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; // calculate main fiber directions itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(m_FiberBundleTransformed); - fOdfFilter->SetMaskImage(m_MaskImage); + fOdfFilter->SetMaskImage(m_TransformedMaskImage); fOdfFilter->SetAngularThreshold(cos(m_Parameters.m_SignalGen.m_FiberSeparationThreshold*M_PI/180.0)); fOdfFilter->SetNormalizeVectors(false); fOdfFilter->SetUseWorkingCopy(true); fOdfFilter->SetSizeThreshold(0); fOdfFilter->SetMaxNumDirections(3); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); // allocate image storing intra-axonal volume fraction information ItkDoubleImgType::Pointer intraAxonalVolumeImage = ItkDoubleImgType::New(); - intraAxonalVolumeImage->SetSpacing( m_UpsampledSpacing ); - intraAxonalVolumeImage->SetOrigin( m_UpsampledOrigin ); + intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing ); + intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - intraAxonalVolumeImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); - intraAxonalVolumeImage->SetBufferedRegion( m_UpsampledImageRegion ); - intraAxonalVolumeImage->SetRequestedRegion( m_UpsampledImageRegion ); + intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion ); + intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion ); + intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); // determine intra-axonal volume fraction using the tract density itk::TractDensityImageFilter< ItkDoubleImgType >::Pointer tdiFilter = itk::TractDensityImageFilter< ItkDoubleImgType >::New(); tdiFilter->SetFiberBundle(m_FiberBundleTransformed); tdiFilter->SetBinaryOutput(false); tdiFilter->SetOutputAbsoluteValues(false); tdiFilter->SetInputImage(intraAxonalVolumeImage); tdiFilter->SetUseImageGeometry(true); tdiFilter->Update(); intraAxonalVolumeImage = tdiFilter->GetOutput(); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; - boost::progress_display disp(m_MaskImage->GetLargestPossibleRegion().GetNumberOfPixels()*m_Parameters.m_SignalGen.GetNumVolumes()); + boost::progress_display disp(m_TransformedMaskImage->GetLargestPossibleRegion().GetNumberOfPixels()*m_Parameters.m_SignalGen.GetNumVolumes()); for (unsigned int g=0; gSetSeed(signalModelSeed); for (int i=0; iSetSeed(signalModelSeed); if (m_Parameters.m_SignalGen.m_DoAddMotion && g>0) // if fibers have moved we need a new TDI and new directions { fOdfFilter->SetFiberBundle(m_FiberBundleTransformed); - fOdfFilter->SetMaskImage(m_MaskImage); + fOdfFilter->SetMaskImage(m_TransformedMaskImage); fOdfFilter->Update(); directionImageContainer = fOdfFilter->GetDirectionImageContainer(); tdiFilter->SetFiberBundle(m_FiberBundleTransformed); tdiFilter->Update(); intraAxonalVolumeImage = tdiFilter->GetOutput(); } - ImageRegionIterator< ItkUcharImgType > it(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); + ImageRegionIterator< ItkUcharImgType > it(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } if (it.Get()>0) { // generate fiber signal for (int c=0; cGetPixel(it.GetIndex()); for (unsigned int i=0; iSize(); i++) { itk::Vector< double, 3> dir; dir.CastFrom(directionImageContainer->GetElement(i)->GetPixel(it.GetIndex())); double norm = dir.GetNorm(); if (norm>0.0001) { m_Parameters.m_FiberModelList.at(c)->SetFiberDirection(dir); pix[g] += m_Parameters.m_FiberModelList.at(c)->SimulateMeasurement(g)*norm; count++; } } if (count>0) pix[g] /= count; pix[g] *= intraAxonalVolumeImage->GetPixel(it.GetIndex())*m_VoxelVolume; m_CompartmentImages.at(c)->SetPixel(it.GetIndex(), pix); } // simulate other compartments - SimulateNonFiberSignal(it.GetIndex(), intraAxonalVolumeImage->GetPixel(it.GetIndex())*m_VoxelVolume, g); + SimulateExtraAxonalSignal(it.GetIndex(), intraAxonalVolumeImage->GetPixel(it.GetIndex())*m_VoxelVolume, g); } ++it; } SimulateMotion(g); } itk::ImageFileWriter< ItkUcharImgType >::Pointer wr = itk::ImageFileWriter< ItkUcharImgType >::New(); wr->SetInput(fOdfFilter->GetNumDirectionsImage()); wr->SetFileName(mitk::IOUtil::GetTempPath()+"/NumDirections_MainFiberDirections.nrrd"); wr->Update(); break; } case (SignalGenerationParameters::RANDOM_DIRECTIONS): { ItkUcharImgType::Pointer numDirectionsImage = ItkUcharImgType::New(); - numDirectionsImage->SetSpacing( m_UpsampledSpacing ); - numDirectionsImage->SetOrigin( m_UpsampledOrigin ); + numDirectionsImage->SetSpacing( m_WorkingSpacing ); + numDirectionsImage->SetOrigin( m_WorkingOrigin ); numDirectionsImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); - numDirectionsImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); - numDirectionsImage->SetBufferedRegion( m_UpsampledImageRegion ); - numDirectionsImage->SetRequestedRegion( m_UpsampledImageRegion ); + numDirectionsImage->SetLargestPossibleRegion( m_WorkingImageRegion ); + numDirectionsImage->SetBufferedRegion( m_WorkingImageRegion ); + numDirectionsImage->SetRequestedRegion( m_WorkingImageRegion ); numDirectionsImage->Allocate(); numDirectionsImage->FillBuffer(0); double sepAngle = cos(m_Parameters.m_SignalGen.m_FiberSeparationThreshold*M_PI/180.0); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; - boost::progress_display disp(m_MaskImage->GetLargestPossibleRegion().GetNumberOfPixels()); - ImageRegionIterator it(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); + boost::progress_display disp(m_TransformedMaskImage->GetLargestPossibleRegion().GetNumberOfPixels()); + ImageRegionIterator it(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } if (it.Get()>0) { int numFibs = m_RandGen->GetIntegerVariate(2)+1; DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(it.GetIndex()); double volume = m_RandGen->GetVariateWithClosedRange(0.3); // double sum = 0; std::vector< double > fractions; for (int i=0; iGetVariateWithClosedRange(0.5)); // sum += fractions.at(i); } // for (int i=0; i > directions; for (int i=0; iGetVariateWithClosedRange(2)-1.0; fib[1] = m_RandGen->GetVariateWithClosedRange(2)-1.0; fib[2] = m_RandGen->GetVariateWithClosedRange(2)-1.0; fib.Normalize(); double min = 0; for (unsigned int d=0; dmin) min = angle; } if (minSetFiberDirection(fib); pix += m_Parameters.m_FiberModelList.at(0)->SimulateMeasurement()*fractions[i]; directions.push_back(fib); } else i--; } pix *= (1-volume); m_CompartmentImages.at(0)->SetPixel(it.GetIndex(), pix); // CSF/GM { pix += volume*m_Parameters.m_NonFiberModelList.at(0)->SimulateMeasurement(); } numDirectionsImage->SetPixel(it.GetIndex(), numFibs); } ++it; } itk::ImageFileWriter< ItkUcharImgType >::Pointer wr = itk::ImageFileWriter< ItkUcharImgType >::New(); wr->SetInput(numDirectionsImage); wr->SetFileName(mitk::IOUtil::GetTempPath()+"/NumDirections_RandomDirections.nrrd"); wr->Update(); } } if (m_Logfile.is_open()) { m_Logfile << "DONE"; m_Logfile.close(); } m_StatusText += "\n\n"; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } DoubleDwiType::Pointer doubleOutImage; if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition ) // do k-space stuff { m_StatusText += this->GetTime()+" > Adjusting complex signal\n"; MITK_INFO << "Adjusting complex signal:"; if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation) m_StatusText += "Simulating signal relaxation\n"; if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull()) m_StatusText += "Simulating distortions\n"; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) m_StatusText += "Simulating ringing artifacts\n"; if (m_Parameters.m_SignalGen.m_EddyStrength>0) m_StatusText += "Simulating eddy currents\n"; if (m_Parameters.m_SignalGen.m_Spikes>0) m_StatusText += "Simulating spikes\n"; if (m_Parameters.m_SignalGen.m_CroppingFactor<1.0) m_StatusText += "Simulating aliasing artifacts\n"; if (m_Parameters.m_SignalGen.m_KspaceLineOffset>0) m_StatusText += "Simulating ghosts\n"; doubleOutImage = DoKspaceStuff(m_CompartmentImages); m_Parameters.m_SignalGen.m_SignalScale = 1; // already scaled in DoKspaceStuff } else // don't do k-space stuff, just sum compartments { m_StatusText += this->GetTime()+" > Summing compartments\n"; MITK_INFO << "Summing compartments"; doubleOutImage = m_CompartmentImages.at(0); for (unsigned int i=1; i::Pointer adder = itk::AddImageFilter< DoubleDwiType, DoubleDwiType, DoubleDwiType>::New(); adder->SetInput1(doubleOutImage); adder->SetInput2(m_CompartmentImages.at(i)); adder->Update(); doubleOutImage = adder->GetOutput(); } } if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } m_StatusText += this->GetTime()+" > Finalizing image\n"; MITK_INFO << "Finalizing image"; if (m_Parameters.m_SignalGen.m_SignalScale>1) m_StatusText += " Scaling signal\n"; if (m_Parameters.m_NoiseModel!=NULL) m_StatusText += " Adding noise\n"; unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); - ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); + ImageRegionIterator it4 (m_OutputImage, m_OutputImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); - boost::progress_display disp2(outImage->GetLargestPossibleRegion().GetNumberOfPixels()); + boost::progress_display disp2(m_OutputImage->GetLargestPossibleRegion().GetNumberOfPixels()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; lastTick = 0; while(!it4.IsAtEnd()) { if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } ++disp2; unsigned long newTick = 50*disp2.count()/disp2.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; typename OutputImageType::IndexType index = it4.GetIndex(); signal = doubleOutImage->GetPixel(index)*m_Parameters.m_SignalGen.m_SignalScale; if (m_Parameters.m_NoiseModel!=NULL) m_Parameters.m_NoiseModel->AddNoise(signal); for (unsigned int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]>window) window = signal[i]; if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]SetNthOutput(0, outImage); + this->SetNthOutput(0, m_OutputImage); m_StatusText += "\n\n"; m_StatusText += "Finished simulation\n"; m_StatusText += "Simulation time: "+GetTime(); m_TimeProbe.Stop(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::SimulateMotion(int g) { if (m_Parameters.m_SignalGen.m_DoAddMotion && gGetDeepCopy(); m_Rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2)-m_Parameters.m_SignalGen.m_Rotation[0]; m_Rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2)-m_Parameters.m_SignalGen.m_Rotation[1]; m_Rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2)-m_Parameters.m_SignalGen.m_Rotation[2]; m_Translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2)-m_Parameters.m_SignalGen.m_Translation[0]; m_Translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2)-m_Parameters.m_SignalGen.m_Translation[1]; m_Translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2)-m_Parameters.m_SignalGen.m_Translation[2]; } // rotate mask image if (m_MaskImageSet) { ImageRegionIterator maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion()); - m_MaskImage->FillBuffer(0); + m_TransformedMaskImage->FillBuffer(0); while(!maskIt.IsAtEnd()) { if (maskIt.Get()<=0) { ++maskIt; continue; } DoubleDwiType::IndexType index = maskIt.GetIndex(); itk::Point point; m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, point); if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); else point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), m_Rotation[0]*(g+1),m_Rotation[1]*(g+1),m_Rotation[2]*(g+1),m_Translation[0]*(g+1),m_Translation[1]*(g+1),m_Translation[2]*(g+1)); - m_MaskImage->TransformPhysicalPointToIndex(point, index); - if (m_MaskImage->GetLargestPossibleRegion().IsInside(index)) - m_MaskImage->SetPixel(index,100); + m_TransformedMaskImage->TransformPhysicalPointToIndex(point, index); + if (m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(index)) + m_TransformedMaskImage->SetPixel(index,100); ++maskIt; } } // rotate fibers if (m_Logfile.is_open()) { m_Logfile << g+1 << " rotation: " << m_Rotation[0] << "," << m_Rotation[1] << "," << m_Rotation[2] << ";"; m_Logfile << " translation: " << m_Translation[0] << "," << m_Translation[1] << "," << m_Translation[2] << "\n"; } m_FiberBundleTransformed->TransformFibers(m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); } } template< class PixelType > -void TractsToDWIImageFilter< PixelType >::SimulateNonFiberSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g) +void TractsToDWIImageFilter< PixelType >::SimulateExtraAxonalSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); if (intraAxonalVolume>0.0001 && m_Parameters.m_SignalGen.m_DoDisablePartialVolume) // only fiber in voxel { DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); if (g>=0) pix[g] *= m_VoxelVolume/intraAxonalVolume; else pix *= m_VoxelVolume/intraAxonalVolume; m_CompartmentImages.at(0)->SetPixel(index, pix); - m_VolumeFractions.at(0)->SetPixel(index, 1); + if (g==0) + m_VolumeFractions.at(0)->SetPixel(index, 1); for (int i=1; iGetPixel(index); if (g>=0) pix[g] = 0.0; else pix.Fill(0.0); m_CompartmentImages.at(i)->SetPixel(index, pix); } } else { - m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume); + if (g==0) + m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume); + // get non-transformed point (remove headmotion tranformation) + // this point can then be transformed to each of the original images, regardless of their geometry itk::Point point; - m_MaskImage->TransformIndexToPhysicalPoint(index, point); + m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, point); if (m_Parameters.m_SignalGen.m_DoAddMotion) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion && g>0) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0],-m_Rotation[1],-m_Rotation[2],-m_Translation[0],-m_Translation[1],-m_Translation[2]); else if (g>=0) point = m_FiberBundleWorkingCopy->TransformPoint(point.GetVnlVector(), -m_Rotation[0]*g,-m_Rotation[1]*g,-m_Rotation[2]*g,-m_Translation[0]*g,-m_Translation[1]*g,-m_Translation[2]*g); } if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) { int maxVolumeIndex = 0; double maxWeight = 0; for (int i=0; i1) { +// ItkUcharImgType::IndexType maskIndex; +// m_UpsampledMaskImage->TransformPhysicalPointToIndex(point, maskIndex); +// if (!m_UpsampledMaskImage->GetLargestPossibleRegion().IsInside(maskIndex) || m_UpsampledMaskImage->GetPixel(maskIndex)==0) +// continue; DoubleDwiType::IndexType newIndex; m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); if (!m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) continue; weight = m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex); } if (weight>maxWeight) { maxWeight = weight; maxVolumeIndex = i; } } DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(maxVolumeIndex+numFiberCompartments); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); if (g>=0) pix[g] += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(g); else pix += m_Parameters.m_NonFiberModelList[maxVolumeIndex]->SimulateMeasurement(); doubleDwi->SetPixel(index, pix); - m_VolumeFractions.at(maxVolumeIndex+numFiberCompartments)->SetPixel(index, 1); + if (g==0) + m_VolumeFractions.at(maxVolumeIndex+numFiberCompartments)->SetPixel(index, 1); } else { double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume; // non-fiber volume + if (extraAxonalVolume<0) + { + MITK_ERROR << "Coorupted intra-axonal signal voxel detected. Fiber volume larger voxel volume!"; + extraAxonalVolume = 0; + } double interAxonalVolume = 0; if (numFiberCompartments>1) - interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment scales linearly with f + interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment double other = extraAxonalVolume - interAxonalVolume; // rest of compartment - double singleinter = interAxonalVolume/(numFiberCompartments-1); + if (other<0) + { + MITK_ERROR << "Coorupted signal voxel detected. Fiber volume larger voxel volume!"; + other = 0; + } // adjust non-fiber and intra-axonal signal for (int i=1; iGetPixel(index); if (intraAxonalVolume>0) // remove scaling by intra-axonal volume from inter-axonal compartment { if (g>=0) pix[g] /= intraAxonalVolume; else pix /= intraAxonalVolume; } + + if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()!=nullptr) + { +// ItkUcharImgType::IndexType maskIndex; +// m_UpsampledMaskImage->TransformPhysicalPointToIndex(point, maskIndex); +// if (!m_UpsampledMaskImage->GetLargestPossibleRegion().IsInside(maskIndex) || m_UpsampledMaskImage->GetPixel(maskIndex)==0) +// continue; + DoubleDwiType::IndexType newIndex; + m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); + if (!m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) + continue; + weight = m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex)*m_VoxelVolume; + } + if (g>=0) - pix[g] *= singleinter; + pix[g] *= weight; else - pix *= singleinter; + pix *= weight; m_CompartmentImages.at(i)->SetPixel(index, pix); - m_VolumeFractions.at(i)->SetPixel(index, singleinter/m_VoxelVolume); + if (g==0) + m_VolumeFractions.at(i)->SetPixel(index, weight/m_VoxelVolume); } for (int i=0; i1) + double weight = other; + DoubleDwiType::PixelType pix = m_CompartmentImages.at(i+numFiberCompartments)->GetPixel(index); + if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()!=nullptr) { +// ItkUcharImgType::IndexType maskIndex; +// m_UpsampledMaskImage->TransformPhysicalPointToIndex(point, maskIndex); +// if (!m_UpsampledMaskImage->GetLargestPossibleRegion().IsInside(maskIndex) || m_UpsampledMaskImage->GetPixel(maskIndex)==0) +// continue; DoubleDwiType::IndexType newIndex; m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->TransformPhysicalPointToIndex(point, newIndex); if (!m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetLargestPossibleRegion().IsInside(newIndex)) continue; - weight = m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex); + weight = m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()->GetPixel(newIndex)*m_VoxelVolume; } - DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(i+numFiberCompartments); - DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); - if (g>=0) - pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*other*weight; + pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*weight; else - pix += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement()*other*weight; - doubleDwi->SetPixel(index, pix); - m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, other/m_VoxelVolume*weight); + pix += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement()*weight; + m_CompartmentImages.at(i+numFiberCompartments)->SetPixel(index, pix); + if (g==0) + m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, weight/m_VoxelVolume); } } } } template< class PixelType > itk::Point TractsToDWIImageFilter< PixelType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > itk::Vector TractsToDWIImageFilter< PixelType >::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(Vector& vector) { vnl_vector_fixed vnlVector; vnlVector[0] = vector[0]; vnlVector[1] = vector[1]; vnlVector[2] = vector[2]; return vnlVector; } template< class PixelType > double TractsToDWIImageFilter< PixelType >::RoundToNearest(double num) { return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5); } template< class PixelType > std::string TractsToDWIImageFilter< PixelType >::GetTime() { m_TimeProbe.Stop(); unsigned long total = RoundToNearest(m_TimeProbe.GetTotal()); unsigned long hours = total/3600; unsigned long minutes = (total%3600)/60; unsigned long seconds = total%60; std::string out = ""; out.append(boost::lexical_cast(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); m_TimeProbe.Start(); return out; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h index ee42dfddc7..7e28f3403a 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,131 +1,140 @@ /*=================================================================== 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 __itkTractsToDWIImageFilter_h__ #define __itkTractsToDWIImageFilter_h__ #include #include #include #include #include #include #include #include namespace itk { /** * \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. * See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ template< class PixelType > class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > > { public: typedef TractsToDWIImageFilter Self; typedef ImageSource< itk::VectorImage< PixelType, 3 > > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename Superclass::OutputImageType OutputImageType; typedef itk::Image ItkDoubleImgType; + typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; - typedef mitk::FiberBundle::Pointer FiberBundleType; + typedef mitk::FiberBundle::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef itk::Matrix MatrixType; typedef itk::Image< double, 2 > SliceType; typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; typedef itk::Vector< double,3> DoubleVectorType; itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkTypeMacro( TractsToDWIImageFilter, ImageSource ) /** Input */ itkSetMacro( FiberBundle, FiberBundleType ) ///< Input fiber bundle itkSetMacro( UseConstantRandSeed, bool ) ///< Seed for random generator. void SetParameters( FiberfoxParameters param ) ///< Simulation parameters. { m_Parameters = param; } /** Output */ FiberfoxParameters GetParameters(){ return m_Parameters; } std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel { return m_VolumeFractions; } mitk::LevelWindow GetLevelWindow(){ return m_LevelWindow; } itkGetMacro( StatusText, std::string ) void GenerateData(); protected: TractsToDWIImageFilter(); virtual ~TractsToDWIImageFilter(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< float, 3 >& vector); double RoundToNearest(double num); std::string GetTime(); /** Transform generated image compartment by compartment, channel by channel and slice by slice using DFT and add k-space artifacts. */ DoubleDwiType::Pointer DoKspaceStuff(std::vector< DoubleDwiType::Pointer >& images); /** Generate signal of non-fiber compartments. */ - void SimulateNonFiberSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g=-1); + void SimulateExtraAxonalSignal(ItkUcharImgType::IndexType index, double intraAxonalVolume, int g=-1); /** Move fibers to simulate headmotion */ void SimulateMotion(int g=-1); + void CheckVolumeFractionImages(); + void InitializeData(); + void InitializeFiberData(); + // input mitk::FiberfoxParameters m_Parameters; FiberBundleType m_FiberBundle; // output + typename OutputImageType::Pointer m_OutputImage; mitk::LevelWindow m_LevelWindow; std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; std::string m_StatusText; // MISC itk::TimeProbe m_TimeProbe; bool m_UseConstantRandSeed; bool m_MaskImageSet; ofstream m_Logfile; // signal generation FiberBundleType m_FiberBundleWorkingCopy; ///< we work on an upsampled version of the input bundle FiberBundleType m_FiberBundleTransformed; ///< transformed bundle simulating headmotion - itk::Vector m_UpsampledSpacing; - itk::Point m_UpsampledOrigin; - ImageRegion<3> m_UpsampledImageRegion; + itk::Vector m_WorkingSpacing; + itk::Point m_WorkingOrigin; + ImageRegion<3> m_WorkingImageRegion; double m_VoxelVolume; std::vector< DoubleDwiType::Pointer > m_CompartmentImages; - ItkUcharImgType::Pointer m_MaskImage; ///< copy of mask image (changes for each motion step) + ItkUcharImgType::Pointer m_TransformedMaskImage; ///< copy of mask image (changes for each motion step) ItkUcharImgType::Pointer m_UpsampledMaskImage; ///< helper image for motion simulation DoubleVectorType m_Rotation; DoubleVectorType m_Translation; + ImageRegion<3> m_CroppedRegion; + double mmRadius; + double segmentVolume; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToDWIImageFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp index 90ba6c6a1e..1c1709f2f8 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp @@ -1,1980 +1,1979 @@ /*=================================================================== 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 _USE_MATH_DEFINES #include "mitkFiberBundle.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundle::FIBER_ID_ARRAY = "Fiber_IDs"; using namespace std; mitk::FiberBundle::FiberBundle( vtkPolyData* fiberPolyData ) : m_NumFibers(0) , m_FiberSampling(0) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != NULL) { m_FiberPolyData = fiberPolyData; this->ColorFibersByOrientation(); } this->UpdateFiberGeometry(); this->GenerateFiberIds(); } mitk::FiberBundle::~FiberBundle() { } mitk::FiberBundle::Pointer mitk::FiberBundle::GetDeepCopy() { mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(m_FiberPolyData); newFib->SetFiberColors(this->m_FiberColors); newFib->SetFiberWeights(this->m_FiberWeights); return newFib; } vtkSmartPointer mitk::FiberBundle::GeneratePolyDataByIds(std::vector fiberIds) { vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); std::vector::iterator finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundle(mitk::FiberBundle* fib) { if (fib==NULL) { MITK_WARN << "trying to call AddBundle with NULL argument"; return NULL; } MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers()); unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // subtract two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::SubtractBundle(mitk::FiberBundle* fib) { MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // iterate over current fibers boost::progress_display disp(m_NumFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==NULL || numPoints<=0) continue; int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetFiberPolyData()->GetCell(i2); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (points2==NULL)// || numPoints2<=0) continue; // check endpoints if (numPoints2==numPoints) { itk::Point point_start = GetItkPoint(points->GetPoint(0)); itk::Point point_end = GetItkPoint(points->GetPoint(numPoints-1)); itk::Point point2_start = GetItkPoint(points2->GetPoint(0)); itk::Point point2_end = GetItkPoint(points2->GetPoint(numPoints2-1)); if ((point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps) || (point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps)) { // further checking ??? contained = true; break; } } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(j)); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } } if(vNewLines->GetNumberOfCells()==0) return NULL; // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle return mitk::FiberBundle::New(vNewPolyData); } itk::Point mitk::FiberBundle::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundle::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == NULL) this->m_FiberPolyData = vtkSmartPointer::New(); else { m_FiberPolyData->DeepCopy(fiberPD); ColorFibersByOrientation(); } m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); GenerateFiberIds(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundle::GetFiberPolyData() const { return m_FiberPolyData; } void mitk::FiberBundle::ColorFibersByOrientation() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= vtkPoints* extrPoints = NULL; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=NULL) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(numOfPoints * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) return; /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } m_FiberColors->InsertTupleValue(idList[i], rgba); } } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByCurvature() { double window = 5; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); vector< double > values; double min = 1; double max = 0; MITK_INFO << "Coloring fibers by curvature"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures for (int j=0; j > vectors; vnl_vector_fixed< float, 3 > meanV; meanV.fill(0.0); while(dist1) { double p1[3]; points->GetPoint(c-1, p1); double p2[3]; points->GetPoint(c, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c--; } c = j; dist = 0; while(distGetPoint(c, p1); double p2[3]; points->GetPoint(c+1, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c++; } meanV.normalize(); double dev = 0; - for (int c=0; c1.0) angle = 1.0; if (angle<-1.0) angle = -1.0; dev += acos(angle)*180/M_PI; } if (vectors.size()>0) dev /= vectors.size(); dev = 1.0-dev/180.0; values.push_back(dev); if (devmax) max = dev; } } - MITK_INFO << min << " - " << max; unsigned int count = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); for (int j=0; jGetColor(dev, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTupleValue(cell->GetPointId(j), rgba); count++; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberOpacity(vtkDoubleArray* FAValArray) { for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; m_FiberColors->SetComponent(i,3, (unsigned char) faValue ); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ResetFiberOpacity() { for(long i=0; iGetNumberOfTuples(); i++) m_FiberColors->SetComponent(i,3, 255.0 ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity) { mitkPixelTypeMultiplex2( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } template void mitk::FiberBundle::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); unsigned char rgba[4] = {0,0,0,0}; vtkPoints* pointSet = m_FiberPolyData->GetPoints(); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double pixelValue = readimage.GetPixelByWorldCoordinates(px); double color[3]; lookupTable->GetColor(1-pixelValue, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * pixelValue); else rgba[3] = (unsigned char) (255.0); m_FiberColors->InsertTupleValue(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberColors(float r, float g, float b, float alpha) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); unsigned char rgba[4] = {0,0,0,0}; for(long i=0; iGetNumberOfPoints(); ++i) { rgba[0] = (unsigned char) r; rgba[1] = (unsigned char) g; rgba[2] = (unsigned char) b; rgba[3] = (unsigned char) alpha; m_FiberColors->InsertTupleValue(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::GenerateFiberIds() { if (m_FiberPolyData == NULL) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); } mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert) { vtkSmartPointer polyData = m_FiberPolyData; if (anyPoint) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/5); polyData = fibCopy->GetFiberPolyData(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Extracting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } break; } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { includeFiber = false; break; } } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( mask->GetPixel(idxStart)>0 && mask->GetPixel(idxEnd)>0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); return mitk::FiberBundle::New(newPolyData); } mitk::FiberBundle::Pointer mitk::FiberBundle::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleSpline(minSpacing/10); vtkSmartPointer polyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx)<=0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(newPolyData); newFib->ResampleSpline(minSpacing/2); return newFib; } mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(DataNode* roi, DataStorage* storage) { if (roi==NULL || !(dynamic_cast(roi->GetData()) || dynamic_cast(roi->GetData())) ) return NULL; std::vector tmp = ExtractFiberIdSubset(roi, storage); if (tmp.size()<=0) return mitk::FiberBundle::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); return mitk::FiberBundle::New(pTmp); } std::vector mitk::FiberBundle::ExtractFiberIdSubset(DataNode *roi, DataStorage* storage) { std::vector result; if (roi==NULL || roi->GetData()==NULL) return result; mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi->GetData()); if (!pfc.IsNull()) // handle composite { DataStorage::SetOfObjects::ConstPointer children = storage->GetDerivations(roi); if (children->size()==0) return result; switch (pfc->getOperationType()) { case 0: // AND { MITK_INFO << "AND"; result = this->ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; - for (int i=1; iSize(); ++i) + for (unsigned int i=1; iSize(); ++i) { std::vector inRoi = this->ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(std::min(result.size(),inRoi.size())); it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } case 1: // OR { MITK_INFO << "OR"; result = ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; - for (int i=1; iSize(); ++i) + for (unsigned int i=1; iSize(); ++i) { it = result.end(); std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); result.insert(it, inRoi.begin(), inRoi.end()); } // remove duplicates sort(result.begin(), result.end()); it = unique(result.begin(), result.end()); result.resize( it - result.begin() ); break; } case 2: // NOT { MITK_INFO << "NOT"; for(long i=0; iGetNumFibers(); i++) result.push_back(i); std::vector::iterator it; for (long i=0; iSize(); ++i) { std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(result.size()-inRoi.size()); it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } } } else if ( dynamic_cast(roi->GetData()) ) // actual extraction { if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarPoly = dynamic_cast(roi->GetData()); //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkSmartPointer::New(); for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) { itk::Point p = planarPoly->GetWorldControlPoint(i); vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); polygonVtk->GetPointIds()->InsertNextId(id); } MITK_INFO << "Extracting with polygon"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); double tolerance = 0.001; // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection double pcoords[3] = {0,0,0}; int subId = 0; int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId); if (iD!=0) { result.push_back(i); break; } } } } else if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi->GetData()); Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); planeNormal.Normalize(); //calculate circle radius mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint double radius = V1w.EuclideanDistanceTo(V2w); radius *= radius; MITK_INFO << "Extracting with circle"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection int iD = vtkPlane::IntersectWithLine(p1,p2,planeNormal.GetDataPointer(),V1w.GetDataPointer(),t,x); if (iD!=0) { double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]); if( dist <= radius) { result.push_back(i); break; } } } } } return result; } return result; } void mitk::FiberBundle::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); if (m_FiberColors==NULL || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints()) this->ColorFibersByOrientation(); if (m_FiberWeights->GetSize()!=m_NumFibers) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberWeights->SetNumberOfValues(m_NumFibers); this->SetFiberWeights(1); } if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(false); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } double b[6]; m_FiberPolyData->GetBounds(b); // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } float mitk::FiberBundle::GetFiberWeight(unsigned int fiber) { return m_FiberWeights->GetValue(fiber); } void mitk::FiberBundle::SetFiberWeights(float newWeight) { for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, newWeight); } void mitk::FiberBundle::SetFiberWeights(vtkSmartPointer weights) { if (m_NumFibers!=weights->GetSize()) return; for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, weights->GetValue(i)); m_FiberWeights->SetName("FIBER_WEIGHTS"); } void mitk::FiberBundle::SetFiberWeight(unsigned int fiber, float weight) { m_FiberWeights->SetValue(fiber, weight); } void mitk::FiberBundle::SetFiberColors(vtkSmartPointer fiberColors) { for(long i=0; iGetNumberOfPoints(); ++i) { unsigned char source[4] = {0,0,0,0}; fiberColors->GetTupleValue(i, source); unsigned char target[4] = {0,0,0,0}; target[0] = source[0]; target[1] = source[1]; target[2] = source[2]; target[3] = source[3]; m_FiberColors->InsertTupleValue(i, target); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } itk::Matrix< double, 3, 3 > mitk::FiberBundle::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } itk::Point mitk::FiberBundle::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } void mitk::FiberBundle::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::ScaleFibers(double x, double y, double z, bool subtractCenter) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); if (subtractCenter) { p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; } p[0] *= x; p[1] *= y; p[2] *= z; if (subtractCenter) { p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; } vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RemoveDir(vnl_vector_fixed dir, double threshold) { dir.normalize(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); bool discard = false; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); vnl_vector_fixed< double, 3 > v1; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; if (v1.magnitude()>0.001) { v1.normalize(); if (fabs(dot_product(v1,dir))>threshold) { discard = true; break; } } } if (!discard) { for (int j=0; jGetPoint(j, p1); vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); // UpdateColorCoding(); // UpdateFiberGeometry(); } bool mitk::FiberBundle::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } void mitk::FiberBundle::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkSmartPointer::New(); //cellcontainer for smoothed lines vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer newPoints = vtkSmartPointer::New(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); float length = m_FiberLengths.at(i); int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkSmartPointer::New(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); this->SetFiberPolyData(m_FiberPolyData, true); m_FiberSampling = 10/pointDistance; } void mitk::FiberBundle::ResampleSpline(float pointDistance) { ResampleSpline(pointDistance, 0, 0, 0 ); } unsigned long mitk::FiberBundle::GetNumberOfPoints() { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } void mitk::FiberBundle::Compress(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { double ref[3]; points->GetPoint(k, ref); pred[0]=ref[0]; pred[1]=ref[1]; pred[2]=ref[2]; validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; kGetPoint(k, ref); succ[0]=ref[0]; succ[1]=ref[1]; succ[2]=ref[2]; validS = k; break; } if (validP>=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcGetPoint(j, cand); vtkIdType id = vtkNewPoints->InsertNextPoint(cand); container->GetPointIds()->InsertNextId(id); } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } // reapply selected colorcoding in case polydata structure has changed bool mitk::FiberBundle::Equals(mitk::FiberBundle* fib, double eps) { if (fib==NULL) { MITK_INFO << "Reference bundle is NULL!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundle::UpdateOutputInformation() { } void mitk::FiberBundle::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundle::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundle::VerifyRequestedRegion() { return true; } void mitk::FiberBundle::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h index e90e50c591..4f43a70a78 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h @@ -1,321 +1,325 @@ /*=================================================================== 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_FiberfoxParameters_H #define _MITK_FiberfoxParameters_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace mitk { /** Signal generation */ class SignalGenerationParameters { public: typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef itk::Vector GradientType; typedef std::vector GradientListType; enum DiffusionDirectionMode { FIBER_TANGENT_DIRECTIONS, MAIN_FIBER_DIRECTIONS, RANDOM_DIRECTIONS }; SignalGenerationParameters() : m_SignalScale(100) , m_tEcho(100) + , m_tRep(500) , m_tLine(1) , m_tInhom(50) + , m_ReversePhase(false) , m_Bvalue(1000) , m_SimulateKspaceAcquisition(false) , m_AxonRadius(0) , m_DoDisablePartialVolume(false) , m_DiffusionDirectionMode(SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS) , m_FiberSeparationThreshold(30) , m_Spikes(0) , m_SpikeAmplitude(1) , m_KspaceLineOffset(0) , m_EddyStrength(0) , m_Tau(70) , m_CroppingFactor(1) , m_DoAddGibbsRinging(false) , m_DoSimulateRelaxation(true) , m_DoAddMotion(false) , m_DoRandomizeMotion(true) , m_FrequencyMap(NULL) , m_MaskImage(NULL) { m_ImageRegion.SetSize(0, 12); m_ImageRegion.SetSize(1, 12); m_ImageRegion.SetSize(2, 3); m_ImageSpacing.Fill(2.0); m_ImageOrigin.Fill(0.0); m_ImageDirection.SetIdentity(); m_Translation.Fill(0.0); m_Rotation.Fill(0.0); SetNumWeightedVolumes(6); } /** input/output image specifications */ itk::ImageRegion<3> m_ImageRegion; ///< Image size. itk::Vector m_ImageSpacing; ///< Image voxel size. itk::Point m_ImageOrigin; ///< Image origin. itk::Matrix m_ImageDirection; ///< Image rotation matrix. /** Other acquisitions parameters */ double m_SignalScale; ///< Scaling factor for output signal (before noise is added). double m_tEcho; ///< Echo time TE. - double m_tLine; ///< k-space line readout time. + double m_tRep; ///< Echo time TR. + double m_tLine; ///< k-space line readout time (dwell time). double m_tInhom; ///< T2' + bool m_ReversePhase; ///< If true, the phase readout direction will be inverted (-y instead of y) double m_Bvalue; ///< Acquisition b-value bool m_SimulateKspaceAcquisition;///< Flag to enable/disable k-space acquisition simulation double m_AxonRadius; ///< Determines compartment volume fractions (0 == automatic axon radius estimation) bool m_DoDisablePartialVolume; ///< Disable partial volume effects. Each voxel is either all fiber or all non-fiber. DiffusionDirectionMode m_DiffusionDirectionMode; ///< Determines how the main diffusion direction of the signal models is selected double m_FiberSeparationThreshold; ///< Used for random and and mein fiber deriction DiffusionDirectionMode /** Artifacts and other effects */ unsigned int m_Spikes; ///< Number of spikes randomly appearing in the image double m_SpikeAmplitude; ///< amplitude of spikes relative to the largest signal intensity (magnitude of complex) double m_KspaceLineOffset; ///< Causes N/2 ghosts. Larger offset means stronger ghost. double m_EddyStrength; ///< Strength of eddy current induced gradients in mT/m. double m_Tau; ///< Eddy current decay constant (in ms) double m_CroppingFactor; ///< FOV size in y-direction is multiplied by this factor. Causes aliasing artifacts. bool m_DoAddGibbsRinging; ///< Add Gibbs ringing artifact bool m_DoSimulateRelaxation; ///< Add T2 relaxation effects bool m_DoAddMotion; ///< Enable motion artifacts. bool m_DoRandomizeMotion; ///< Toggles between random and linear motion. itk::Vector m_Translation; ///< Maximum translational motion. itk::Vector m_Rotation; ///< Maximum rotational motion. ItkDoubleImgType::Pointer m_FrequencyMap; ///< If != NULL, distortions are added to the image using this frequency map. ItkUcharImgType::Pointer m_MaskImage; ///< Signal is only genrated inside of the mask image. inline void GenerateGradientHalfShell(); ///< Generates half shell of gradient directions (with m_NumGradients non-zero directions) inline std::vector< int > GetBaselineIndices(); ///< Returns list of nun-diffusion-weighted image volume indices inline unsigned int GetFirstBaselineIndex(); ///< Returns index of first non-diffusion-weighted image volume inline bool IsBaselineIndex(unsigned int idx); ///< Checks if image volume with given index is non-diffusion-weighted volume or not. inline unsigned int GetNumWeightedVolumes(); ///< Get number of diffusion-weighted image volumes inline unsigned int GetNumBaselineVolumes(); ///< Get number of non-diffusion-weighted image volumes inline unsigned int GetNumVolumes(); ///< Get number of baseline and diffusion-weighted image volumes inline GradientListType GetGradientDirections(); ///< Return gradient direction container inline GradientType GetGradientDirection(unsigned int i); inline void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards. inline void SetGradienDirections(GradientListType gradientList); inline void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList); protected: unsigned int m_NumGradients; ///< Number of diffusion-weighted image volumes. unsigned int m_NumBaseline; ///< Number of non-diffusion-weighted image volumes. GradientListType m_GradientDirections; ///< Total number of image volumes. }; /** Fiber generation */ class FiberGenerationParameters { public: enum FiberDistribution{ DISTRIBUTE_UNIFORM, // distribute fibers uniformly in the ROIs DISTRIBUTE_GAUSSIAN // distribute fibers using a 2D gaussian }; typedef vector< vector< mitk::PlanarEllipse::Pointer > > FiducialListType; typedef vector< vector< unsigned int > > FlipListType; FiberGenerationParameters() : m_Distribution(DISTRIBUTE_UNIFORM) , m_Density(100) , m_Variance(100) , m_Sampling(1) , m_Tension(0) , m_Continuity(0) , m_Bias(0) { m_Rotation.Fill(0.0); m_Translation.Fill(0.0); m_Scale.Fill(1.0); } FiberDistribution m_Distribution; unsigned int m_Density; double m_Variance; double m_Sampling; double m_Tension; double m_Continuity; double m_Bias; mitk::Vector3D m_Rotation; mitk::Vector3D m_Translation; mitk::Vector3D m_Scale; FlipListType m_FlipList; ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting) FiducialListType m_Fiducials; ///< container of the planar ellipses used as fiducials for the fiber generation process }; /** GUI persistence, input, output, ... */ class MiscFiberfoxParameters { public: MiscFiberfoxParameters() : m_ResultNode(DataNode::New()) , m_ParentNode(NULL) , m_SignalModelString("") , m_ArtifactModelString("") , m_OutputPath("") , m_CheckOutputVolumeFractionsBox(false) , m_CheckAdvancedSignalOptionsBox(false) , m_CheckAddNoiseBox(false) , m_CheckAddGhostsBox(false) , m_CheckAddAliasingBox(false) , m_CheckAddSpikesBox(false) , m_CheckAddEddyCurrentsBox(false) , m_CheckAddDistortionsBox(false) , m_CheckRealTimeFibersBox(true) , m_CheckAdvancedFiberOptionsBox(false) , m_CheckConstantRadiusBox(false) , m_CheckIncludeFiducialsBox(true) {} DataNode::Pointer m_ResultNode; ///< Stores resulting image. DataNode::Pointer m_ParentNode; ///< Parent node of result node. string m_SignalModelString; ///< Appendet to the name of the result node string m_ArtifactModelString; ///< Appendet to the name of the result node string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished. /** member variables that store the check-state of GUI checkboxes */ // image generation bool m_CheckOutputVolumeFractionsBox; bool m_CheckAdvancedSignalOptionsBox; bool m_CheckAddNoiseBox; bool m_CheckAddGhostsBox; bool m_CheckAddAliasingBox; bool m_CheckAddSpikesBox; bool m_CheckAddEddyCurrentsBox; bool m_CheckAddDistortionsBox; // fiber generation bool m_CheckRealTimeFibersBox; bool m_CheckAdvancedFiberOptionsBox; bool m_CheckConstantRadiusBox; bool m_CheckIncludeFiducialsBox; }; /** * \brief Datastructure to manage the Fiberfox signal generation parameters. * */ template< class ScalarType = double > class FiberfoxParameters { public: typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef DiffusionSignalModel DiffusionModelType; typedef std::vector< DiffusionModelType* > DiffusionModelListType; typedef DiffusionNoiseModel NoiseModelType; FiberfoxParameters(); ~FiberfoxParameters(); /** Get same parameter object with different template parameter */ template< class OutType > FiberfoxParameters< OutType > CopyParameters() { FiberfoxParameters< OutType > out; out.m_FiberGen = m_FiberGen; out.m_SignalGen = m_SignalGen; out.m_Misc = m_Misc; if (m_NoiseModel!=NULL) { if (dynamic_cast*>(m_NoiseModel)) out.m_NoiseModel = new mitk::RicianNoiseModel(); else if (dynamic_cast*>(m_NoiseModel)) out.m_NoiseModel = new mitk::ChiSquareNoiseModel(); out.m_NoiseModel->SetNoiseVariance(m_NoiseModel->GetNoiseVariance()); } for (unsigned int i=0; i* outModel = NULL; mitk::DiffusionSignalModel* signalModel = NULL; if (i*>(signalModel)) outModel = new mitk::StickModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::TensorModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::RawShModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::BallModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::AstroStickModel(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::DotModel(dynamic_cast*>(signalModel)); if (i #include #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion signal models * */ template< class ScalarType = double > class DiffusionSignalModel { public: DiffusionSignalModel() : m_T2(100) + , m_T1(800) {} ~DiffusionSignalModel(){} typedef itk::Image ItkDoubleImgType; typedef itk::VariableLengthVector< ScalarType > PixelType; typedef itk::Vector GradientType; typedef std::vector GradientListType; typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType; /** Realizes actual signal generation. Has to be implemented in subclass. **/ virtual PixelType SimulateMeasurement() = 0; virtual ScalarType SimulateMeasurement(unsigned int dir) = 0; virtual void SetFiberDirection(GradientType fiberDirection) = 0; GradientType GetFiberDirection(){ return m_FiberDirection; } virtual void SetGradientList(GradientListType gradientList) = 0; GradientListType GetGradientList(){ return m_GradientList; } GradientType GetGradientDirection(int i) { return m_GradientList.at(i); } void SetT2(double T2) { m_T2 = T2; } double GetT2() { return m_T2; } + void SetT1(double T1) { m_T1 = T1; } + double GetT1() { return m_T1; } + void SetVolumeFractionImage(ItkDoubleImgType::Pointer img){ m_VolumeFractionImage = img; } ItkDoubleImgType::Pointer GetVolumeFractionImage(){ return m_VolumeFractionImage; } void SetRandomGenerator(ItkRandGenType::Pointer randgen){ m_RandGen = randgen; } ItkRandGenType::Pointer GetRandomGenerator(){ return m_RandGen; } void SetSeed(int s) ///< set seed for random generator { if (m_RandGen.IsNull()) m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(s); } unsigned int m_CompartmentId; ///< GUI flag. Which compartment is this model assigned to? protected: GradientType m_FiberDirection; ///< Needed to generate anisotropc signal to determin direction of anisotropy GradientListType m_GradientList; ///< Diffusion gradient direction container - double m_T2; ///< Tissue specific relaxation time + double m_T2; ///< Tissue specific transversal relaxation time + double m_T1; ///< Tissue specific longitudinal relaxation time ItkDoubleImgType::Pointer m_VolumeFractionImage; ///< Tissue specific volume fraction for each voxel (only relevant for non fiber compartments) ItkRandGenType::Pointer m_RandGen; ///< Random number generator }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp index 7265da47be..b6604ff129 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp @@ -1,293 +1,297 @@ /*=================================================================== 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 #include #include #include #include #include #include typedef itk::VectorImage< short, 3> ItkDwiType; /**Documentation * Test the Fiberfox simulation functions (fiberBundle -> diffusion weighted image) */ bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) + { + MITK_INFO << it1.GetIndex() << ":" << it1.Get(); + MITK_INFO << it2.GetIndex() << ":" << it2.Get(); return false; + } ++it1; ++it2; } } catch(...) { return false; } return true; } void StartSimulation(FiberfoxParameters parameters, FiberBundle::Pointer fiberBundle, mitk::Image::Pointer refImage, string message) { itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetUseConstantRandSeed(true); tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(fiberBundle); tractsToDwiFilter->Update(); mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() ); testImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() ) ); testImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue ) ); mitk::DiffusionPropertyHelper propertyHelper( testImage ); propertyHelper.InitializeImage(); if (refImage.IsNotNull()) { if( static_cast( refImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer().IsNotNull() ) { ItkDwiType::Pointer itkTestImagePointer = ItkDwiType::New(); mitk::CastToItkImage(testImage, itkTestImagePointer); ItkDwiType::Pointer itkRefImagePointer = ItkDwiType::New(); mitk::CastToItkImage(refImage, itkRefImagePointer); bool cond = CompareDwi(itkTestImagePointer, itkRefImagePointer); if (!cond) { MITK_INFO << "Saving test and rference image to " << mitk::IOUtil::GetTempPath(); mitk::IOUtil::SaveBaseData(testImage, mitk::IOUtil::GetTempPath()+"testImage.nrrd"); mitk::IOUtil::SaveBaseData(refImage, mitk::IOUtil::GetTempPath()+"refImage.nrrd"); } MITK_TEST_CONDITION_REQUIRED(cond, message); } } } int mitkFiberfoxSignalGenerationTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberfoxSignalGenerationTest"); MITK_TEST_CONDITION_REQUIRED(argc>=19,"check for input data"); // input fiber bundle FiberBundle::Pointer fiberBundle = dynamic_cast(mitk::IOUtil::Load(argv[1])[0].GetPointer()); // reference diffusion weighted images mitk::Image::Pointer stickBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); mitk::Image::Pointer stickAstrosticks = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); mitk::Image::Pointer stickDot = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); mitk::Image::Pointer tensorBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); mitk::Image::Pointer stickTensorBall = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); mitk::Image::Pointer stickTensorBallAstrosticks = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); mitk::Image::Pointer gibbsringing = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); mitk::Image::Pointer ghost = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); mitk::Image::Pointer aliasing = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); mitk::Image::Pointer eddy = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); mitk::Image::Pointer linearmotion = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); mitk::Image::Pointer randommotion = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[13])->GetData()); mitk::Image::Pointer spikes = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[14])->GetData()); mitk::Image::Pointer riciannoise = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[15])->GetData()); mitk::Image::Pointer chisquarenoise = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[16])->GetData()); mitk::Image::Pointer distortions = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[17])->GetData()); mitk::Image::Pointer mitkFMap = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[18])->GetData()); typedef itk::Image ItkDoubleImgType; ItkDoubleImgType::Pointer fMap = ItkDoubleImgType::New(); mitk::CastToItkImage(mitkFMap, fMap); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(stickBall, itkVectorImagePointer); FiberfoxParameters parameters; parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_SignalScale = 10000; parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast(stickBall->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); parameters.m_SignalGen.SetGradienDirections( static_cast( stickBall->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); // intra and inter axonal compartments mitk::StickModel stickModel; stickModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); stickModel.SetT2(110); stickModel.SetDiffusivity(0.001); stickModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::TensorModel tensorModel; tensorModel.SetT2(110); stickModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); tensorModel.SetDiffusivity1(0.001); tensorModel.SetDiffusivity2(0.00025); tensorModel.SetDiffusivity3(0.00025); tensorModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); // extra axonal compartment models mitk::BallModel ballModel; ballModel.SetT2(80); ballModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); ballModel.SetDiffusivity(0.001); ballModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::AstroStickModel astrosticksModel; astrosticksModel.SetT2(80); astrosticksModel.SetBvalue(parameters.m_SignalGen.m_Bvalue); astrosticksModel.SetDiffusivity(0.001); astrosticksModel.SetRandomizeSticks(true); astrosticksModel.SetSeed(0); astrosticksModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); mitk::DotModel dotModel; dotModel.SetT2(80); dotModel.SetGradientList(parameters.m_SignalGen.GetGradientDirections()); // noise models mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); ricianNoiseModel->SetNoiseVariance(1000000); ricianNoiseModel->SetSeed(0); // Rician noise mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); chiSquareNoiseModel->SetNoiseVariance(1000000); chiSquareNoiseModel->SetSeed(0); try{ // Stick-Ball parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickBall, argv[2]); // Srick-Astrosticks parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&astrosticksModel); StartSimulation(parameters, fiberBundle, stickAstrosticks, argv[3]); // Stick-Dot parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&dotModel); StartSimulation(parameters, fiberBundle, stickDot, argv[4]); // Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, tensorBall, argv[5]); // Stick-Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickTensorBall, argv[6]); // Stick-Tensor-Ball-Astrosticks - parameters.m_NonFiberModelList.push_back(&astrosticksModel); - StartSimulation(parameters, fiberBundle, stickTensorBallAstrosticks, argv[7]); +// parameters.m_NonFiberModelList.push_back(&astrosticksModel); +// StartSimulation(parameters, fiberBundle, stickTensorBallAstrosticks, argv[7]); // Gibbs ringing parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); parameters.m_SignalGen.m_DoAddGibbsRinging = true; StartSimulation(parameters, fiberBundle, gibbsringing, argv[8]); // Ghost parameters.m_SignalGen.m_DoAddGibbsRinging = false; parameters.m_SignalGen.m_KspaceLineOffset = 0.25; StartSimulation(parameters, fiberBundle, ghost, argv[9]); // Aliasing parameters.m_SignalGen.m_KspaceLineOffset = 0; parameters.m_SignalGen.m_CroppingFactor = 0.4; parameters.m_SignalGen.m_SignalScale = 1000; StartSimulation(parameters, fiberBundle, aliasing, argv[10]); // Eddy currents parameters.m_SignalGen.m_CroppingFactor = 1; parameters.m_SignalGen.m_SignalScale = 10000; parameters.m_SignalGen.m_EddyStrength = 0.05; StartSimulation(parameters, fiberBundle, eddy, argv[11]); // Motion (linear) parameters.m_SignalGen.m_EddyStrength = 0.0; parameters.m_SignalGen.m_DoAddMotion = true; parameters.m_SignalGen.m_DoRandomizeMotion = false; parameters.m_SignalGen.m_Translation[1] = 10; parameters.m_SignalGen.m_Rotation[2] = 90; StartSimulation(parameters, fiberBundle, linearmotion, argv[12]); // Motion (random) parameters.m_SignalGen.m_DoRandomizeMotion = true; parameters.m_SignalGen.m_Translation[1] = 5; parameters.m_SignalGen.m_Rotation[2] = 45; StartSimulation(parameters, fiberBundle, randommotion, argv[13]); // Spikes parameters.m_SignalGen.m_DoAddMotion = false; parameters.m_SignalGen.m_Spikes = 5; parameters.m_SignalGen.m_SpikeAmplitude = 1; StartSimulation(parameters, fiberBundle, spikes, argv[14]); // Rician noise parameters.m_SignalGen.m_Spikes = 0; parameters.m_NoiseModel = ricianNoiseModel; StartSimulation(parameters, fiberBundle, riciannoise, argv[15]); delete parameters.m_NoiseModel; // Chi-square noise parameters.m_NoiseModel = chiSquareNoiseModel; StartSimulation(parameters, fiberBundle, chisquarenoise, argv[16]); delete parameters.m_NoiseModel; // Distortions parameters.m_NoiseModel = NULL; parameters.m_SignalGen.m_FrequencyMap = fMap; StartSimulation(parameters, fiberBundle, distortions, argv[17]); } catch (std::exception &e) { MITK_TEST_CONDITION_REQUIRED(false, e.what()); } // always end with this! MITK_TEST_END(); } diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp index f20b95dbf6..284f49bd92 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.cpp @@ -1,1354 +1,1387 @@ /*=================================================================== 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 "QmitkBasicImageProcessingView.h" // QT includes (GUI) #include #include #include #include #include #include #include // Berry includes (selection service) #include #include // MITK includes (GUI) #include "QmitkStdMultiWidget.h" #include "QmitkDataNodeSelectionProvider.h" #include "mitkDataNodeObject.h" // MITK includes (general) #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateDimension.h" #include "mitkNodePredicateAnd.h" #include "mitkImageTimeSelector.h" #include "mitkVectorImageMapper2D.h" #include "mitkProperties.h" // Includes for image casting between ITK and MITK #include "mitkImageCast.h" #include "mitkITKImageImport.h" // ITK includes (general) #include #include // Morphological Operations #include #include #include #include #include // Smoothing #include #include #include // Threshold #include // Inversion #include // Derivatives #include #include #include // Resampling #include #include #include #include // Image Arithmetics #include #include #include #include // Boolean operations #include #include #include // Flip Image #include #include +#include // Convenient Definitions typedef itk::Image ImageType; typedef itk::Image SegmentationImageType; -typedef itk::Image FloatImageType; +typedef itk::Image DoubleImageType; typedef itk::Image, 3> VectorImageType; typedef itk::BinaryBallStructuringElement BallType; typedef itk::GrayscaleDilateImageFilter DilationFilterType; typedef itk::GrayscaleErodeImageFilter ErosionFilterType; typedef itk::GrayscaleMorphologicalOpeningImageFilter OpeningFilterType; typedef itk::GrayscaleMorphologicalClosingImageFilter ClosingFilterType; typedef itk::MedianImageFilter< ImageType, ImageType > MedianFilterType; typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType> GaussianFilterType; -typedef itk::TotalVariationDenoisingImageFilter TotalVariationFilterType; +typedef itk::TotalVariationDenoisingImageFilter TotalVariationFilterType; typedef itk::TotalVariationDenoisingImageFilter VectorTotalVariationFilterType; typedef itk::BinaryThresholdImageFilter< ImageType, ImageType > ThresholdFilterType; typedef itk::InvertIntensityImageFilter< ImageType, ImageType > InversionFilterType; typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< ImageType, ImageType > GradientFilterType; -typedef itk::LaplacianImageFilter< FloatImageType, FloatImageType > LaplacianFilterType; -typedef itk::SobelEdgeDetectionImageFilter< FloatImageType, FloatImageType > SobelFilterType; +typedef itk::LaplacianImageFilter< DoubleImageType, DoubleImageType > LaplacianFilterType; +typedef itk::SobelEdgeDetectionImageFilter< DoubleImageType, DoubleImageType > SobelFilterType; typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType; typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleImageFilterType2; -typedef itk::CastImageFilter< ImageType, FloatImageType > ImagePTypeToFloatPTypeCasterType; +typedef itk::CastImageFilter< ImageType, DoubleImageType > ImagePTypeToFloatPTypeCasterType; typedef itk::AddImageFilter< ImageType, ImageType, ImageType > AddFilterType; typedef itk::SubtractImageFilter< ImageType, ImageType, ImageType > SubtractFilterType; typedef itk::MultiplyImageFilter< ImageType, ImageType, ImageType > MultiplyFilterType; -typedef itk::DivideImageFilter< ImageType, ImageType, FloatImageType > DivideFilterType; +typedef itk::DivideImageFilter< ImageType, ImageType, DoubleImageType > DivideFilterType; typedef itk::OrImageFilter< ImageType, ImageType > OrImageFilterType; typedef itk::AndImageFilter< ImageType, ImageType > AndImageFilterType; typedef itk::XorImageFilter< ImageType, ImageType > XorImageFilterType; typedef itk::FlipImageFilter< ImageType > FlipImageFilterType; typedef itk::LinearInterpolateImageFunction< ImageType, double > LinearInterpolatorType; typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestInterpolatorType; QmitkBasicImageProcessing::QmitkBasicImageProcessing() : QmitkFunctionality(), m_Controls(NULL), m_SelectedImageNode(NULL), m_TimeStepperAdapter(NULL) { } QmitkBasicImageProcessing::~QmitkBasicImageProcessing() { //berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); //if(s) // s->RemoveSelectionListener(m_SelectionListener); } void QmitkBasicImageProcessing::CreateQtPartControl(QWidget *parent) { if (m_Controls == NULL) { m_Controls = new Ui::QmitkBasicImageProcessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); //setup predictaes for combobox mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image"); m_Controls->m_ImageSelector2->SetDataStorage(this->GetDefaultDataStorage()); m_Controls->m_ImageSelector2->SetPredicate(mitk::NodePredicateAnd::New(dimensionPredicate, imagePredicate)); } m_Controls->gbTwoImageOps->hide(); m_SelectedImageNode = mitk::DataStorageSelection::New(this->GetDefaultDataStorage(), false); } void QmitkBasicImageProcessing::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->cbWhat1), SIGNAL( activated(int) ), this, SLOT( SelectAction(int) ) ); connect( (QObject*)(m_Controls->btnDoIt), SIGNAL(clicked()),(QObject*) this, SLOT(StartButtonClicked())); - connect( (QObject*)(m_Controls->cbWhat2), SIGNAL( activated(int) ), this, SLOT( SelectAction2(int) ) ); connect( (QObject*)(m_Controls->btnDoIt2), SIGNAL(clicked()),(QObject*) this, SLOT(StartButton2Clicked())); - connect( (QObject*)(m_Controls->rBOneImOp), SIGNAL( clicked() ), this, SLOT( ChangeGUI() ) ); connect( (QObject*)(m_Controls->rBTwoImOp), SIGNAL( clicked() ), this, SLOT( ChangeGUI() ) ); - connect( (QObject*)(m_Controls->cbParam4), SIGNAL( activated(int) ), this, SLOT( SelectInterpolator(int) ) ); } m_TimeStepperAdapter = new QmitkStepperAdapter((QObject*) m_Controls->sliceNavigatorTime, GetActiveStdMultiWidget()->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromBIP"); } void QmitkBasicImageProcessing::Activated() { QmitkFunctionality::Activated(); this->m_Controls->cbWhat1->clear(); this->m_Controls->cbWhat1->insertItem( NOACTIONSELECTED, "Please select operation"); this->m_Controls->cbWhat1->insertItem( CATEGORY_DENOISING, "--- Denoising ---"); this->m_Controls->cbWhat1->insertItem( GAUSSIAN, "Gaussian"); this->m_Controls->cbWhat1->insertItem( MEDIAN, "Median"); this->m_Controls->cbWhat1->insertItem( TOTALVARIATION, "Total Variation"); this->m_Controls->cbWhat1->insertItem( CATEGORY_MORPHOLOGICAL, "--- Morphological ---"); this->m_Controls->cbWhat1->insertItem( DILATION, "Dilation"); this->m_Controls->cbWhat1->insertItem( EROSION, "Erosion"); this->m_Controls->cbWhat1->insertItem( OPENING, "Opening"); this->m_Controls->cbWhat1->insertItem( CLOSING, "Closing"); this->m_Controls->cbWhat1->insertItem( CATEGORY_EDGE_DETECTION, "--- Edge Detection ---"); this->m_Controls->cbWhat1->insertItem( GRADIENT, "Gradient"); this->m_Controls->cbWhat1->insertItem( LAPLACIAN, "Laplacian (2nd Derivative)"); this->m_Controls->cbWhat1->insertItem( SOBEL, "Sobel Operator"); this->m_Controls->cbWhat1->insertItem( CATEGORY_MISC, "--- Misc ---"); this->m_Controls->cbWhat1->insertItem( THRESHOLD, "Threshold"); this->m_Controls->cbWhat1->insertItem( INVERSION, "Image Inversion"); this->m_Controls->cbWhat1->insertItem( DOWNSAMPLING, "Downsampling"); this->m_Controls->cbWhat1->insertItem( FLIPPING, "Flipping"); this->m_Controls->cbWhat1->insertItem( RESAMPLING, "Resample to"); - this->m_Controls->cbWhat1->insertItem( RESCALE, "Rescale image values"); + this->m_Controls->cbWhat1->insertItem( RESCALE, "Rescale values to interval"); + this->m_Controls->cbWhat1->insertItem( RESCALE2, "Rescale values by scalar"); this->m_Controls->cbWhat2->clear(); this->m_Controls->cbWhat2->insertItem( TWOIMAGESNOACTIONSELECTED, "Please select on operation" ); this->m_Controls->cbWhat2->insertItem( CATEGORY_ARITHMETIC, "--- Arithmetric operations ---" ); this->m_Controls->cbWhat2->insertItem( ADD, "Add to Image 1:" ); this->m_Controls->cbWhat2->insertItem( SUBTRACT, "Subtract from Image 1:" ); this->m_Controls->cbWhat2->insertItem( MULTIPLY, "Multiply with Image 1:" ); this->m_Controls->cbWhat2->insertItem( RESAMPLE_TO, "Resample Image 1 to fit geometry:" ); this->m_Controls->cbWhat2->insertItem( DIVIDE, "Divide Image 1 by:" ); this->m_Controls->cbWhat2->insertItem( CATEGORY_BOOLEAN, "--- Boolean operations ---" ); this->m_Controls->cbWhat2->insertItem( AND, "AND" ); this->m_Controls->cbWhat2->insertItem( OR, "OR" ); this->m_Controls->cbWhat2->insertItem( XOR, "XOR" ); this->m_Controls->cbParam4->clear(); this->m_Controls->cbParam4->insertItem( LINEAR, "Linear" ); this->m_Controls->cbParam4->insertItem( NEAREST, "Nearest neighbor" ); m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); m_Controls->cbParam4->hide(); } //datamanager selection changed void QmitkBasicImageProcessing::OnSelectionChanged(std::vector nodes) { //any nodes there? if (!nodes.empty()) { // reset GUI // this->ResetOneImageOpPanel(); m_Controls->sliceNavigatorTime->setEnabled(false); m_Controls->leImage1->setText("Select an Image in Data Manager"); m_Controls->tlWhat1->setEnabled(false); m_Controls->cbWhat1->setEnabled(false); m_Controls->tlWhat2->setEnabled(false); m_Controls->cbWhat2->setEnabled(false); m_SelectedImageNode->RemoveAllNodes(); //get the selected Node mitk::DataNode* _DataNode = nodes.front(); *m_SelectedImageNode = _DataNode; //try to cast to image mitk::Image::Pointer tempImage = dynamic_cast(m_SelectedImageNode->GetNode()->GetData()); //no image if( tempImage.IsNull() || (tempImage->IsInitialized() == false) ) { m_Controls->leImage1->setText("Not an image."); return; } //2D image if( tempImage->GetDimension() < 3) { m_Controls->leImage1->setText("2D images are not supported."); return; } //image m_Controls->leImage1->setText(QString(m_SelectedImageNode->GetNode()->GetName().c_str())); // button coding if ( tempImage->GetDimension() > 3 ) { m_Controls->sliceNavigatorTime->setEnabled(true); m_Controls->tlTime->setEnabled(true); } m_Controls->tlWhat1->setEnabled(true); m_Controls->cbWhat1->setEnabled(true); m_Controls->tlWhat2->setEnabled(true); m_Controls->cbWhat2->setEnabled(true); } } void QmitkBasicImageProcessing::ChangeGUI() { if(m_Controls->rBOneImOp->isChecked()) { m_Controls->gbTwoImageOps->hide(); m_Controls->gbOneImageOps->show(); } else if(m_Controls->rBTwoImOp->isChecked()) { m_Controls->gbOneImageOps->hide(); m_Controls->gbTwoImageOps->show(); } } void QmitkBasicImageProcessing::ResetOneImageOpPanel() { m_Controls->tlParam1->setText("Param1"); m_Controls->tlParam2->setText("Param2"); m_Controls->cbWhat1->setCurrentIndex(0); m_Controls->tlTime->setEnabled(false); this->ResetParameterPanel(); m_Controls->btnDoIt->setEnabled(false); m_Controls->cbHideOrig->setEnabled(false); } void QmitkBasicImageProcessing::ResetParameterPanel() { m_Controls->tlParam->setEnabled(false); m_Controls->tlParam1->setEnabled(false); m_Controls->tlParam2->setEnabled(false); m_Controls->tlParam3->setEnabled(false); m_Controls->tlParam4->setEnabled(false); m_Controls->sbParam1->setEnabled(false); m_Controls->sbParam2->setEnabled(false); m_Controls->dsbParam1->setEnabled(false); m_Controls->dsbParam2->setEnabled(false); m_Controls->dsbParam3->setEnabled(false); m_Controls->cbParam4->setEnabled(false); m_Controls->sbParam1->setValue(0); m_Controls->sbParam2->setValue(0); m_Controls->dsbParam1->setValue(0); m_Controls->dsbParam2->setValue(0); m_Controls->dsbParam3->setValue(0); m_Controls->sbParam1->show(); m_Controls->sbParam2->show(); m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->cbParam4->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); } void QmitkBasicImageProcessing::ResetTwoImageOpPanel() { m_Controls->cbWhat2->setCurrentIndex(0); m_Controls->tlImage2->setEnabled(false); m_Controls->m_ImageSelector2->setEnabled(false); m_Controls->btnDoIt2->setEnabled(false); } void QmitkBasicImageProcessing::SelectAction(int action) { if ( ! m_SelectedImageNode->GetNode() ) return; // Prepare GUI this->ResetParameterPanel(); m_Controls->btnDoIt->setEnabled(false); m_Controls->cbHideOrig->setEnabled(false); QString text1 = "No Parameters"; QString text2 = "No Parameters"; QString text3 = "No Parameters"; QString text4 = "No Parameters"; if (action != 19) { m_Controls->dsbParam1->hide(); m_Controls->dsbParam2->hide(); m_Controls->dsbParam3->hide(); m_Controls->tlParam3->hide(); m_Controls->tlParam4->hide(); m_Controls->sbParam1->show(); m_Controls->sbParam2->show(); m_Controls->cbParam4->hide(); } // check which operation the user has selected and set parameters and GUI accordingly switch (action) { case 2: { m_SelectedAction = GAUSSIAN; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Variance:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 2 ); break; } case 3: { m_SelectedAction = MEDIAN; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 4: { m_SelectedAction = TOTALVARIATION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(true); text1 = "Number Iterations:"; text2 = "Regularization\n(Lambda/1000):"; m_Controls->sbParam1->setMinimum( 1 ); m_Controls->sbParam1->setMaximum( 1000 ); m_Controls->sbParam1->setValue( 40 ); m_Controls->sbParam2->setMinimum( 0 ); m_Controls->sbParam2->setMaximum( 100000 ); m_Controls->sbParam2->setValue( 1 ); break; } case 6: { m_SelectedAction = DILATION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 7: { m_SelectedAction = EROSION; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 8: { m_SelectedAction = OPENING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 9: { m_SelectedAction = CLOSING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "&Radius:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 3 ); break; } case 11: { m_SelectedAction = GRADIENT; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Sigma of Gaussian Kernel:\n(in Image Spacing Units)"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 200 ); m_Controls->sbParam1->setValue( 2 ); break; } case 12: { m_SelectedAction = LAPLACIAN; break; } case 13: { m_SelectedAction = SOBEL; break; } case 15: { m_SelectedAction = THRESHOLD; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(true); text1 = "Lower threshold:"; text2 = "Upper threshold:"; m_Controls->sbParam1->setMinimum( -100000 ); m_Controls->sbParam1->setMaximum( 100000 ); m_Controls->sbParam1->setValue( 0 ); m_Controls->sbParam2->setMinimum( -100000 ); m_Controls->sbParam2->setMaximum( 100000 ); m_Controls->sbParam2->setValue( 300 ); break; } case 16: { m_SelectedAction = INVERSION; break; } case 17: { m_SelectedAction = DOWNSAMPLING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Downsampling by Factor:"; m_Controls->sbParam1->setMinimum( 1 ); m_Controls->sbParam1->setMaximum( 100 ); m_Controls->sbParam1->setValue( 2 ); break; } case 18: { m_SelectedAction = FLIPPING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(true); text1 = "Flip across axis:"; m_Controls->sbParam1->setMinimum( 0 ); m_Controls->sbParam1->setMaximum( 2 ); m_Controls->sbParam1->setValue( 1 ); break; } case 19: { m_SelectedAction = RESAMPLING; m_Controls->tlParam1->setEnabled(true); m_Controls->sbParam1->setEnabled(false); m_Controls->sbParam1->hide(); m_Controls->dsbParam1->show(); m_Controls->dsbParam1->setEnabled(true); m_Controls->tlParam2->setEnabled(true); m_Controls->sbParam2->setEnabled(false); m_Controls->sbParam2->hide(); m_Controls->dsbParam2->show(); m_Controls->dsbParam2->setEnabled(true); m_Controls->tlParam3->show(); m_Controls->tlParam3->setEnabled(true); m_Controls->dsbParam3->show(); m_Controls->dsbParam3->setEnabled(true); m_Controls->tlParam4->show(); m_Controls->tlParam4->setEnabled(true); m_Controls->cbParam4->show(); m_Controls->cbParam4->setEnabled(true); m_Controls->dsbParam1->setMinimum(0.01); m_Controls->dsbParam1->setMaximum(10.0); m_Controls->dsbParam1->setSingleStep(0.1); m_Controls->dsbParam1->setValue(0.3); m_Controls->dsbParam2->setMinimum(0.01); m_Controls->dsbParam2->setMaximum(10.0); m_Controls->dsbParam2->setSingleStep(0.1); m_Controls->dsbParam2->setValue(0.3); m_Controls->dsbParam3->setMinimum(0.01); m_Controls->dsbParam3->setMaximum(10.0); m_Controls->dsbParam3->setSingleStep(0.1); m_Controls->dsbParam3->setValue(1.5); text1 = "x-spacing:"; text2 = "y-spacing:"; text3 = "z-spacing:"; text4 = "Interplation:"; break; } case 20: { m_SelectedAction = RESCALE; m_Controls->dsbParam1->show(); m_Controls->tlParam1->show(); m_Controls->dsbParam1->setEnabled(true); m_Controls->tlParam1->setEnabled(true); m_Controls->dsbParam2->show(); m_Controls->tlParam2->show(); m_Controls->dsbParam2->setEnabled(true); m_Controls->tlParam2->setEnabled(true); text1 = "Output minimum:"; text2 = "Output maximum:"; break; } + case 21: + { + m_SelectedAction = RESCALE2; + m_Controls->dsbParam1->show(); + m_Controls->tlParam1->show(); + m_Controls->dsbParam1->setEnabled(true); + m_Controls->tlParam1->setEnabled(true); + text1 = "Scaling value:"; + break; + } default: return; } m_Controls->tlParam->setEnabled(true); m_Controls->tlParam1->setText(text1); m_Controls->tlParam2->setText(text2); m_Controls->tlParam3->setText(text3); m_Controls->tlParam4->setText(text4); m_Controls->btnDoIt->setEnabled(true); m_Controls->cbHideOrig->setEnabled(true); } void QmitkBasicImageProcessing::StartButtonClicked() { if(!m_SelectedImageNode->GetNode()) return; this->BusyCursorOn(); mitk::Image::Pointer newImage; try { newImage = dynamic_cast(m_SelectedImageNode->GetNode()->GetData()); } catch ( std::exception &e ) { QString exceptionString = "An error occured during image loading:\n"; exceptionString.append( e.what() ); QMessageBox::warning( NULL, "Basic Image Processing", exceptionString , QMessageBox::Ok, QMessageBox::NoButton ); this->BusyCursorOff(); return; } // check if input image is valid, casting does not throw exception when casting from 'NULL-Object' if ( (! newImage) || (newImage->IsInitialized() == false) ) { this->BusyCursorOff(); QMessageBox::warning( NULL, "Basic Image Processing", "Input image is broken or not initialized. Returning.", QMessageBox::Ok, QMessageBox::NoButton ); return; } // check if operation is done on 4D a image time step if(newImage->GetDimension() > 3) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(newImage); timeSelector->SetTimeNr( ((QmitkSliderNavigatorWidget*)m_Controls->sliceNavigatorTime)->GetPos() ); timeSelector->Update(); newImage = timeSelector->GetOutput(); } // check if image or vector image ImageType::Pointer itkImage = ImageType::New(); VectorImageType::Pointer itkVecImage = VectorImageType::New(); int isVectorImage = newImage->GetPixelType().GetNumberOfComponents(); if(isVectorImage > 1) { CastToItkImage( newImage, itkVecImage ); } else { CastToItkImage( newImage, itkImage ); } std::stringstream nameAddition(""); int param1 = m_Controls->sbParam1->value(); int param2 = m_Controls->sbParam2->value(); double dparam1 = m_Controls->dsbParam1->value(); double dparam2 = m_Controls->dsbParam2->value(); double dparam3 = m_Controls->dsbParam3->value(); try{ switch (m_SelectedAction) { case GAUSSIAN: { GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New(); gaussianFilter->SetInput( itkImage ); gaussianFilter->SetVariance( param1 ); gaussianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(gaussianFilter->GetOutput())->Clone(); nameAddition << "_Gaussian_var_" << param1; std::cout << "Gaussian filtering successful." << std::endl; break; } case MEDIAN: { MedianFilterType::Pointer medianFilter = MedianFilterType::New(); MedianFilterType::InputSizeType size; size.Fill(param1); medianFilter->SetRadius( size ); medianFilter->SetInput(itkImage); medianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(medianFilter->GetOutput())->Clone(); nameAddition << "_Median_radius_" << param1; std::cout << "Median Filtering successful." << std::endl; break; } case TOTALVARIATION: { if(isVectorImage > 1) { VectorTotalVariationFilterType::Pointer TVFilter = VectorTotalVariationFilterType::New(); TVFilter->SetInput( itkVecImage.GetPointer() ); TVFilter->SetNumberIterations(param1); TVFilter->SetLambda(double(param2)/1000.); TVFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone(); } else { ImagePTypeToFloatPTypeCasterType::Pointer floatCaster = ImagePTypeToFloatPTypeCasterType::New(); floatCaster->SetInput( itkImage ); floatCaster->Update(); - FloatImageType::Pointer fImage = floatCaster->GetOutput(); + DoubleImageType::Pointer fImage = floatCaster->GetOutput(); TotalVariationFilterType::Pointer TVFilter = TotalVariationFilterType::New(); TVFilter->SetInput( fImage.GetPointer() ); TVFilter->SetNumberIterations(param1); TVFilter->SetLambda(double(param2)/1000.); TVFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(TVFilter->GetOutput())->Clone(); } nameAddition << "_TV_Iter_" << param1 << "_L_" << param2; std::cout << "Total Variation Filtering successful." << std::endl; break; } case DILATION: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); DilationFilterType::Pointer dilationFilter = DilationFilterType::New(); dilationFilter->SetInput( itkImage ); dilationFilter->SetKernel( binaryBall ); dilationFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(dilationFilter->GetOutput())->Clone(); nameAddition << "_Dilated_by_" << param1; std::cout << "Dilation successful." << std::endl; break; } case EROSION: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); ErosionFilterType::Pointer erosionFilter = ErosionFilterType::New(); erosionFilter->SetInput( itkImage ); erosionFilter->SetKernel( binaryBall ); erosionFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(erosionFilter->GetOutput())->Clone(); nameAddition << "_Eroded_by_" << param1; std::cout << "Erosion successful." << std::endl; break; } case OPENING: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); OpeningFilterType::Pointer openFilter = OpeningFilterType::New(); openFilter->SetInput( itkImage ); openFilter->SetKernel( binaryBall ); openFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(openFilter->GetOutput())->Clone(); nameAddition << "_Opened_by_" << param1; std::cout << "Opening successful." << std::endl; break; } case CLOSING: { BallType binaryBall; binaryBall.SetRadius( param1 ); binaryBall.CreateStructuringElement(); ClosingFilterType::Pointer closeFilter = ClosingFilterType::New(); closeFilter->SetInput( itkImage ); closeFilter->SetKernel( binaryBall ); closeFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(closeFilter->GetOutput())->Clone(); nameAddition << "_Closed_by_" << param1; std::cout << "Closing successful." << std::endl; break; } case GRADIENT: { GradientFilterType::Pointer gradientFilter = GradientFilterType::New(); gradientFilter->SetInput( itkImage ); gradientFilter->SetSigma( param1 ); gradientFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(gradientFilter->GetOutput())->Clone(); nameAddition << "_Gradient_sigma_" << param1; std::cout << "Gradient calculation successful." << std::endl; break; } case LAPLACIAN: { // the laplace filter requires a float type image as input, we need to cast the itkImage // to correct type ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New(); caster->SetInput( itkImage ); caster->Update(); - FloatImageType::Pointer fImage = caster->GetOutput(); + DoubleImageType::Pointer fImage = caster->GetOutput(); LaplacianFilterType::Pointer laplacianFilter = LaplacianFilterType::New(); laplacianFilter->SetInput( fImage ); laplacianFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(laplacianFilter->GetOutput())->Clone(); nameAddition << "_Second_Derivative"; std::cout << "Laplacian filtering successful." << std::endl; break; } case SOBEL: { // the sobel filter requires a float type image as input, we need to cast the itkImage // to correct type ImagePTypeToFloatPTypeCasterType::Pointer caster = ImagePTypeToFloatPTypeCasterType::New(); caster->SetInput( itkImage ); caster->Update(); - FloatImageType::Pointer fImage = caster->GetOutput(); + DoubleImageType::Pointer fImage = caster->GetOutput(); SobelFilterType::Pointer sobelFilter = SobelFilterType::New(); sobelFilter->SetInput( fImage ); sobelFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(sobelFilter->GetOutput())->Clone(); nameAddition << "_Sobel"; std::cout << "Edge Detection successful." << std::endl; break; } case THRESHOLD: { ThresholdFilterType::Pointer thFilter = ThresholdFilterType::New(); thFilter->SetLowerThreshold(param1 < param2 ? param1 : param2); thFilter->SetUpperThreshold(param2 > param1 ? param2 : param1); thFilter->SetInsideValue(1); thFilter->SetOutsideValue(0); thFilter->SetInput(itkImage); thFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(thFilter->GetOutput())->Clone(); nameAddition << "_Threshold"; std::cout << "Thresholding successful." << std::endl; break; } case INVERSION: { InversionFilterType::Pointer invFilter = InversionFilterType::New(); mitk::ScalarType min = newImage->GetScalarValueMin(); mitk::ScalarType max = newImage->GetScalarValueMax(); invFilter->SetMaximum( max + min ); invFilter->SetInput(itkImage); invFilter->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(invFilter->GetOutput())->Clone(); nameAddition << "_Inverted"; std::cout << "Image inversion successful." << std::endl; break; } case DOWNSAMPLING: { ResampleImageFilterType::Pointer downsampler = ResampleImageFilterType::New(); downsampler->SetInput( itkImage ); NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New(); downsampler->SetInterpolator( interpolator ); downsampler->SetDefaultPixelValue( 0 ); ResampleImageFilterType::SpacingType spacing = itkImage->GetSpacing(); spacing *= (double) param1; downsampler->SetOutputSpacing( spacing ); downsampler->SetOutputOrigin( itkImage->GetOrigin() ); downsampler->SetOutputDirection( itkImage->GetDirection() ); ResampleImageFilterType::SizeType size = itkImage->GetLargestPossibleRegion().GetSize(); for ( int i = 0; i < 3; ++i ) { size[i] /= param1; } downsampler->SetSize( size ); downsampler->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(downsampler->GetOutput())->Clone(); nameAddition << "_Downsampled_by_" << param1; std::cout << "Downsampling successful." << std::endl; break; } case FLIPPING: { FlipImageFilterType::Pointer flipper = FlipImageFilterType::New(); flipper->SetInput( itkImage ); itk::FixedArray flipAxes; for(int i=0; i<3; ++i) { if(i == param1) { flipAxes[i] = true; } else { flipAxes[i] = false; } } flipper->SetFlipAxes(flipAxes); flipper->UpdateLargestPossibleRegion(); newImage = mitk::ImportItkImage(flipper->GetOutput())->Clone(); std::cout << "Image flipping successful." << std::endl; break; } case RESAMPLING: { std::string selectedInterpolator; ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New(); switch (m_SelectedInterpolation) { case LINEAR: { LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Linear"; break; } case NEAREST: { NearestInterpolatorType::Pointer interpolator = NearestInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Nearest"; break; } default: { LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New(); resampler->SetInterpolator(interpolator); selectedInterpolator = "Linear"; break; } } resampler->SetInput( itkImage ); resampler->SetOutputOrigin( itkImage->GetOrigin() ); ImageType::SizeType input_size = itkImage->GetLargestPossibleRegion().GetSize(); ImageType::SpacingType input_spacing = itkImage->GetSpacing(); ImageType::SizeType output_size; ImageType::SpacingType output_spacing; output_size[0] = input_size[0] * (input_spacing[0] / dparam1); output_size[1] = input_size[1] * (input_spacing[1] / dparam2); output_size[2] = input_size[2] * (input_spacing[2] / dparam3); output_spacing [0] = dparam1; output_spacing [1] = dparam2; output_spacing [2] = dparam3; resampler->SetSize( output_size ); resampler->SetOutputSpacing( output_spacing ); resampler->SetOutputDirection( itkImage->GetDirection() ); resampler->UpdateLargestPossibleRegion(); ImageType::Pointer resampledImage = resampler->GetOutput(); newImage = mitk::ImportItkImage( resampledImage )->Clone(); nameAddition << "_Resampled_" << selectedInterpolator; std::cout << "Resampling successful." << std::endl; break; } case RESCALE: { - FloatImageType::Pointer floatImage = FloatImageType::New(); + DoubleImageType::Pointer floatImage = DoubleImageType::New(); CastToItkImage( newImage, floatImage ); - itk::RescaleIntensityImageFilter::Pointer filter = itk::RescaleIntensityImageFilter::New(); + itk::RescaleIntensityImageFilter::Pointer filter = itk::RescaleIntensityImageFilter::New(); filter->SetInput(0, floatImage); filter->SetOutputMinimum(dparam1); filter->SetOutputMaximum(dparam2); filter->Update(); floatImage = filter->GetOutput(); newImage = mitk::Image::New(); newImage->InitializeByItk(floatImage.GetPointer()); newImage->SetVolume(floatImage->GetBufferPointer()); nameAddition << "_Rescaled"; std::cout << "Rescaling successful." << std::endl; break; } + case RESCALE2: + { + DoubleImageType::Pointer floatImage = DoubleImageType::New(); + CastToItkImage( newImage, floatImage ); + itk::ShiftScaleImageFilter::Pointer filter = itk::ShiftScaleImageFilter::New(); + filter->SetInput(0, floatImage); + filter->SetScale(dparam1); + + filter->Update(); + floatImage = filter->GetOutput(); + + newImage = mitk::Image::New(); + newImage->InitializeByItk(floatImage.GetPointer()); + newImage->SetVolume(floatImage->GetBufferPointer()); + nameAddition << "_Rescaled"; + std::cout << "Rescaling successful." << std::endl; + break; + } default: this->BusyCursorOff(); return; } } catch (...) { this->BusyCursorOff(); QMessageBox::warning(NULL, "Warning", "Problem when applying filter operation. Check your input..."); return; } newImage->DisconnectPipeline(); // adjust level/window to new image mitk::LevelWindow levelwindow; levelwindow.SetAuto( newImage ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); // compose new image name std::string name = m_SelectedImageNode->GetNode()->GetName(); if (name.find(".pic.gz") == name.size() -7 ) { name = name.substr(0,name.size() -7); } name.append( nameAddition.str() ); // create final result MITK data storage node mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "levelwindow", levWinProp ); result->SetProperty( "name", mitk::StringProperty::New( name.c_str() ) ); result->SetData( newImage ); // for vector images, a different mapper is needed if(isVectorImage > 1) { mitk::VectorImageMapper2D::Pointer mapper = mitk::VectorImageMapper2D::New(); result->SetMapper(1,mapper); } // reset GUI to ease further processing // this->ResetOneImageOpPanel(); // add new image to data storage and set as active to ease further processing GetDefaultDataStorage()->Add( result, m_SelectedImageNode->GetNode() ); if ( m_Controls->cbHideOrig->isChecked() == true ) m_SelectedImageNode->GetNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); // TODO!! m_Controls->m_ImageSelector1->SetSelectedNode(result); // show the results mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->BusyCursorOff(); } void QmitkBasicImageProcessing::SelectAction2(int operation) { // check which operation the user has selected and set parameters and GUI accordingly switch (operation) { case 2: m_SelectedOperation = ADD; break; case 3: m_SelectedOperation = SUBTRACT; break; case 4: m_SelectedOperation = MULTIPLY; break; case 5: m_SelectedOperation = DIVIDE; break; case 6: m_SelectedOperation = RESAMPLE_TO; break; case 8: m_SelectedOperation = AND; break; case 9: m_SelectedOperation = OR; break; case 10: m_SelectedOperation = XOR; break; default: // this->ResetTwoImageOpPanel(); return; } m_Controls->tlImage2->setEnabled(true); m_Controls->m_ImageSelector2->setEnabled(true); m_Controls->btnDoIt2->setEnabled(true); } void QmitkBasicImageProcessing::StartButton2Clicked() { mitk::Image::Pointer newImage1 = dynamic_cast (m_SelectedImageNode->GetNode()->GetData()); mitk::Image::Pointer newImage2 = dynamic_cast (m_Controls->m_ImageSelector2->GetSelectedNode()->GetData()); // check if images are valid if( (!newImage1) || (!newImage2) || (newImage1->IsInitialized() == false) || (newImage2->IsInitialized() == false) ) { itkGenericExceptionMacro(<< "At least one of the input images are broken or not initialized. Returning"); return; } this->BusyCursorOn(); // this->ResetTwoImageOpPanel(); // check if 4D image and use filter on correct time step int time = ((QmitkSliderNavigatorWidget*)m_Controls->sliceNavigatorTime)->GetPos(); if(newImage1->GetDimension() > 3) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(newImage1); timeSelector->SetTimeNr( time ); timeSelector->UpdateLargestPossibleRegion(); newImage1 = timeSelector->GetOutput(); newImage1->DisconnectPipeline(); timeSelector->SetInput(newImage2); timeSelector->SetTimeNr( time ); timeSelector->UpdateLargestPossibleRegion(); newImage2 = timeSelector->GetOutput(); newImage2->DisconnectPipeline(); } // reset GUI for better usability // this->ResetTwoImageOpPanel(); ImageType::Pointer itkImage1 = ImageType::New(); ImageType::Pointer itkImage2 = ImageType::New(); CastToItkImage( newImage1, itkImage1 ); CastToItkImage( newImage2, itkImage2 ); // Remove temp image - newImage2 = NULL; +// newImage2 = NULL; std::string nameAddition = ""; try { switch (m_SelectedOperation) { case ADD: { AddFilterType::Pointer addFilter = AddFilterType::New(); addFilter->SetInput1( itkImage1 ); addFilter->SetInput2( itkImage2 ); addFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(addFilter->GetOutput())->Clone(); nameAddition = "_Added"; } break; case SUBTRACT: { SubtractFilterType::Pointer subFilter = SubtractFilterType::New(); subFilter->SetInput1( itkImage1 ); subFilter->SetInput2( itkImage2 ); subFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(subFilter->GetOutput())->Clone(); nameAddition = "_Subtracted"; } break; case MULTIPLY: { MultiplyFilterType::Pointer multFilter = MultiplyFilterType::New(); multFilter->SetInput1( itkImage1 ); multFilter->SetInput2( itkImage2 ); multFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(multFilter->GetOutput())->Clone(); nameAddition = "_Multiplied"; } break; case DIVIDE: { DivideFilterType::Pointer divFilter = DivideFilterType::New(); divFilter->SetInput1( itkImage1 ); divFilter->SetInput2( itkImage2 ); divFilter->UpdateLargestPossibleRegion(); - newImage1 = mitk::ImportItkImage(divFilter->GetOutput())->Clone(); + newImage1 = mitk::ImportItkImage(divFilter->GetOutput())->Clone(); nameAddition = "_Divided"; } break; case AND: { AndImageFilterType::Pointer andFilter = AndImageFilterType::New(); andFilter->SetInput1( itkImage1 ); andFilter->SetInput2( itkImage2 ); andFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(andFilter->GetOutput())->Clone(); nameAddition = "_AND"; break; } case OR: { OrImageFilterType::Pointer orFilter = OrImageFilterType::New(); orFilter->SetInput1( itkImage1 ); orFilter->SetInput2( itkImage2 ); orFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(orFilter->GetOutput())->Clone(); nameAddition = "_OR"; break; } case XOR: { XorImageFilterType::Pointer xorFilter = XorImageFilterType::New(); xorFilter->SetInput1( itkImage1 ); xorFilter->SetInput2( itkImage2 ); xorFilter->UpdateLargestPossibleRegion(); newImage1 = mitk::ImportItkImage(xorFilter->GetOutput())->Clone(); nameAddition = "_XOR"; break; } case RESAMPLE_TO: { - itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator - = itk::NearestNeighborInterpolateImageFunction::New(); + itk::LinearInterpolateImageFunction::Pointer nn_interpolator + = itk::LinearInterpolateImageFunction::New(); + + DoubleImageType::Pointer itkImage1 = DoubleImageType::New(); + DoubleImageType::Pointer itkImage2 = DoubleImageType::New(); + + CastToItkImage( newImage1, itkImage1 ); + CastToItkImage( newImage2, itkImage2 ); - ResampleImageFilterType2::Pointer resampleFilter = ResampleImageFilterType2::New(); + itk::ResampleImageFilter< DoubleImageType, DoubleImageType >::Pointer resampleFilter = itk::ResampleImageFilter< DoubleImageType, DoubleImageType >::New(); resampleFilter->SetInput( itkImage1 ); resampleFilter->SetReferenceImage( itkImage2 ); resampleFilter->SetUseReferenceImage( true ); resampleFilter->SetInterpolator( nn_interpolator ); resampleFilter->SetDefaultPixelValue( 0 ); try { resampleFilter->UpdateLargestPossibleRegion(); } catch( const itk::ExceptionObject &e) { MITK_WARN << "Updating resampling filter failed. "; MITK_WARN << "REASON: " << e.what(); } - ImageType::Pointer resampledImage = resampleFilter->GetOutput(); + DoubleImageType::Pointer resampledImage = resampleFilter->GetOutput(); newImage1 = mitk::ImportItkImage( resampledImage )->Clone(); nameAddition = "_Resampled"; break; } default: std::cout << "Something went wrong..." << std::endl; this->BusyCursorOff(); return; } } catch (const itk::ExceptionObject& e ) { this->BusyCursorOff(); QMessageBox::warning(NULL, "ITK Exception", e.what() ); QMessageBox::warning(NULL, "Warning", "Problem when applying arithmetic operation to two images. Check dimensions of input images."); return; } // disconnect pipeline; images will not be reused newImage1->DisconnectPipeline(); itkImage1 = NULL; itkImage2 = NULL; // adjust level/window to new image and compose new image name mitk::LevelWindow levelwindow; levelwindow.SetAuto( newImage1 ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); levWinProp->SetLevelWindow( levelwindow ); std::string name = m_SelectedImageNode->GetNode()->GetName(); if (name.find(".pic.gz") == name.size() -7 ) { name = name.substr(0,name.size() -7); } // create final result MITK data storage node mitk::DataNode::Pointer result = mitk::DataNode::New(); result->SetProperty( "levelwindow", levWinProp ); result->SetProperty( "name", mitk::StringProperty::New( (name + nameAddition ).c_str() )); result->SetData( newImage1 ); GetDefaultDataStorage()->Add( result, m_SelectedImageNode->GetNode() ); // show only the newly created image m_SelectedImageNode->GetNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); m_Controls->m_ImageSelector2->GetSelectedNode()->SetProperty( "visible", mitk::BoolProperty::New(false) ); // show the newly created image mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->BusyCursorOff(); } void QmitkBasicImageProcessing::SelectInterpolator(int interpolator) { switch (interpolator) { case 0: { m_SelectedInterpolation = LINEAR; break; } case 1: { m_SelectedInterpolation = NEAREST; break; } } } diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.h b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.h index 0e11c58395..3d0d7a1d51 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.h +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingView.h @@ -1,185 +1,186 @@ /*=================================================================== 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. ===================================================================*/ #if !defined(QmitkBasicImageProcessingView_H__INCLUDED) #define QmitkBasicImageProcessingView_H__INCLUDED #include "QmitkFunctionality.h" #include #include "ui_QmitkBasicImageProcessingViewControls.h" #include "QmitkStepperAdapter.h" #include /*! \brief This module allows to use some basic image processing filters for preprocessing, image enhancement and testing purposes Several basic ITK image processing filters, like denoising, morphological and edge detection are encapsulated in this module and can be selected via a list and an intuitive parameter input. The selected filter will be applied on the image, and a new image showing the output is displayed as result. Also, some image arithmetic operations are available. Images can be 3D or 4D. In the 4D case, the filters work on the 3D image selected via the time slider. The result is also a 3D image. \sa QmitkFunctionality, QObject \class QmitkBasicImageProcessing \author Tobias Schwarz \version 1.0 (3M3) \date 2009-05-10 \ingroup Bundles */ class BASICIMAGEPROCESSING_EXPORT QmitkBasicImageProcessing : public QmitkFunctionality { Q_OBJECT public: /*! \brief default constructor */ QmitkBasicImageProcessing(); /*! \brief default destructor */ virtual ~QmitkBasicImageProcessing(); /*! \brief method for creating the widget containing the application controls, like sliders, buttons etc. */ virtual void CreateQtPartControl(QWidget *parent); /*! \brief method for creating the connections of main and control widget */ virtual void CreateConnections(); virtual void Activated(); /*! \brief Invoked when the DataManager selection changed */ virtual void OnSelectionChanged(std::vector nodes); protected slots: /* * When an action is selected in the "one image ops" list box */ void SelectAction(int action); /* * When an action is selected in the "two image ops" list box */ void SelectAction2(int operation); /* * The "Execute" button in the "one image ops" box was triggered */ void StartButtonClicked(); /* * The "Execute" button in the "two image ops" box was triggered */ void StartButton2Clicked(); /* * Switch between the one and the two image operations GUI */ void ChangeGUI(); void SelectInterpolator(int interpolator); private: /* * After a one image operation, reset the "one image ops" panel */ void ResetOneImageOpPanel(); /* * Helper method to reset the parameter set panel */ void ResetParameterPanel(); /* * After a two image operation, reset the "two image ops" panel */ void ResetTwoImageOpPanel(); /*! * controls containing sliders for scrolling through the slices */ Ui::QmitkBasicImageProcessingViewControls *m_Controls; //mitk::DataNode* m_SelectedImageNode; mitk::DataStorageSelection::Pointer m_SelectedImageNode; QmitkStepperAdapter* m_TimeStepperAdapter; enum ActionType { NOACTIONSELECTED, CATEGORY_DENOISING, GAUSSIAN, MEDIAN, TOTALVARIATION, CATEGORY_MORPHOLOGICAL, DILATION, EROSION, OPENING, CLOSING, CATEGORY_EDGE_DETECTION, GRADIENT, LAPLACIAN, SOBEL, CATEGORY_MISC, THRESHOLD, INVERSION, DOWNSAMPLING, FLIPPING, RESAMPLING, - RESCALE + RESCALE, + RESCALE2 } m_SelectedAction; enum OperationType{ TWOIMAGESNOACTIONSELECTED, CATEGORY_ARITHMETIC, ADD, SUBTRACT, MULTIPLY, DIVIDE, RESAMPLE_TO, CATEGORY_BOOLEAN, AND, OR, XOR } m_SelectedOperation; enum InterpolationType{ LINEAR, NEAREST } m_SelectedInterpolation; }; #endif // !defined(QmitkBasicImageProcessing_H__INCLUDED) diff --git a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingViewControls.ui index 0febdf1c5a..179daf05a9 100644 --- a/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.basicimageprocessing/src/internal/QmitkBasicImageProcessingViewControls.ui @@ -1,443 +1,473 @@ QmitkBasicImageProcessingViewControls 0 0 - 349 + 448 980 Form true 0 6 0 6 Filters (One Image) true Arithmetic (Two Images) Select an Image in Data Manager true false Output image will be 3D Choose time step if 4D (Slider for both images) false false Output image will be 3D true true false false 0 6 0 0 false Select second image: false m_ImageSelector2 false false E&xecute false Select an operation: false cbWhat2 false Qt::Vertical 254 403 true 0 6 0 0 false Select an operation: false cbWhat1 false false ... and parameters: false false Parameter 1: false sbParam1 false Parameter 2: false sbParam2 false &Execute false Hide Original Image true false Parameter 3: false Parameter 4: false 0 0 false 0 0 Qt::LeftToRight Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + 4 + + + -999999999.000000000000000 + + + 999999999.000000000000000 + false 0 0 + + 4 + + + -999999999.000000000000000 + 999999999.000000000000000 false 0 0 - 2 + 4 + + + -999999999.000000000000000 999999999.000000000000000 false 0 0 + + -999999999 + + + 999999999 + false 0 0 + + -999999999 + + + 999999999 + QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkSliderNavigatorWidget QWidget
QmitkSliderNavigatorWidget.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h index 17208db130..b0759e2f95 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h @@ -1,62 +1,64 @@ /*=================================================================== 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 _QMITKAstrosticksModelParametersWidget_H_INCLUDED #define _QMITKAstrosticksModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkAstrosticksModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkAstrosticksModelParametersWidget : public QWidget { //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; QmitkAstrosticksModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkAstrosticksModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } void SetD(double d){ m_Controls->m_D1box->setValue(d); } void SetRandomizeSticks(bool r){ m_Controls->m_RandomCheck->setChecked(r); } double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } bool GetRandomizeSticks(){ return m_Controls->m_RandomCheck->isChecked(); } public slots: protected: // member variables Ui::QmitkAstrosticksModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKAstrosticksModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui index 0028acef40..fa9620359c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui @@ -1,127 +1,147 @@ QmitkAstrosticksModelParametersWidgetControls 0 0 - 410 - 106 + 356 + 133 0 0 Form 0 0 0 0 Use random number and orientation of sticks. Randomize Sticks true QFrame::NoFrame QFrame::Raised 0 0 0 0 - + + + + <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s</span><span style=" font-style:italic;">]</span>:</p></body></html> + + + + + + + Diffusivity along sticks. + + + 5 + + + 1.000000000000000 + + + 0.000100000000000 + + + 0.001000000000000 + + + + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> - + T2 relaxation time of this compartment (in milliseconds). - 10000 + 999999999 80 - - + + - <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s</span><span style=" font-style:italic;">]</span>:</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">T1</span> - Relaxation:</p></body></html> - - + + - Diffusivity along sticks. - - - 5 + T1 relaxation time of this compartment (in milliseconds). - 1.000000000000000 - - - 0.000100000000000 + 999999999 - 0.001000000000000 + 920 m_T2box m_D1box m_RandomCheck diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h index 7c116906d3..e74062407c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h @@ -1,60 +1,62 @@ /*=================================================================== 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 _QMITKBallModelParametersWidget_H_INCLUDED #define _QMITKBallModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkBallModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkBallModelParametersWidget : public QWidget { //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; QmitkBallModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkBallModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } void SetD(double d){ m_Controls->m_D1box->setValue(d); } double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } public slots: protected: // member variables Ui::QmitkBallModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKBallModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui index 16e5f0a9d4..668e522493 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui @@ -1,89 +1,109 @@ QmitkBallModelParametersWidgetControls 0 0 - 410 - 78 + 373 + 102 0 0 Form 0 0 0 0 - - - - <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> - - - - - - - <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> - - - - + T2 relaxation time of this compartment (in milliseconds). - 10000 + 999999999 80 - + Diffusivity along stick. 5 1.000000000000000 0.000100000000000 0.001000000000000 + + + + <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + + + + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> + + + + + + + <html><head/><body><p><span style=" font-style:italic;">T1</span> - Relaxation:</p></body></html> + + + + + + + T1 relaxation time of this compartment (in milliseconds). + + + 999999999 + + + 920 + + + m_T2box m_D1box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h index 2be6744353..2168ace09b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h @@ -1,57 +1,59 @@ /*=================================================================== 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 _QMITKDotModelParametersWidget_H_INCLUDED #define _QMITKDotModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkDotModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkDotModelParametersWidget : public QWidget { //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; QmitkDotModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkDotModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } public slots: protected: // member variables Ui::QmitkDotModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKDotModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui index aff8841f3c..34f6759c00 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui @@ -1,50 +1,82 @@ QmitkDotModelParametersWidgetControls 0 0 - 410 - 45 + 349 + 56 0 0 Form - + 0 - + + 0 + + + 0 + + + 0 + + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> - + T2 relaxation time of this compartment (in milliseconds). - 10000 + 999999999 80 + + + + <html><head/><body><p><span style=" font-style:italic;">T1</span> - Relaxation:</p></body></html> + + + + + + + T1 relaxation time of this compartment (in milliseconds). + + + -1 + + + 999999999 + + + 920 + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h index 5aecaa1589..8356234101 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h @@ -1,60 +1,62 @@ /*=================================================================== 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 _QMITKStickModelParametersWidget_H_INCLUDED #define _QMITKStickModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkStickModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkStickModelParametersWidget : public QWidget { //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; QmitkStickModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkStickModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } void SetD(double d){ m_Controls->m_D1box->setValue(d); } double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } public slots: protected: // member variables Ui::QmitkStickModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKStickModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui index 8b6911712d..d69890d390 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui @@ -1,89 +1,109 @@ QmitkStickModelParametersWidgetControls 0 0 - 410 - 78 + 342 + 92 0 0 Form 0 0 0 0 - - - - <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + Diffusivity along stick. - - - - - - <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> + + 5 + + + 1.000000000000000 + + + 0.000100000000000 + + + 0.001000000000000 - + T2 relaxation time of this compartment (in milliseconds). - 10000 + 999999999 110 - - - - Diffusivity along stick. + + + + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> - - 5 + + + + + + <html><head/><body><p><span style=" font-style:italic;">d [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> - - 1.000000000000000 + + + + + + <html><head/><body><p><span style=" font-style:italic;">T1 </span>- Relaxation:</p></body></html> - - 0.000100000000000 + + + + + + T1 relaxation time of this compartment (in milliseconds). + + + 999999999 - 0.001000000000000 + 780 m_T2box m_D1box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h index a61e9e3861..ca4bd137a9 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h @@ -1,67 +1,69 @@ /*=================================================================== 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 _QMITKTensorModelParametersWidget_H_INCLUDED #define _QMITKTensorModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkTensorModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkTensorModelParametersWidget : public QWidget { //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; QmitkTensorModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkTensorModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); } void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); } void SetD3(double d3){ m_Controls->m_D3box->setValue(d3); } double GetD1(){ return m_Controls->m_D1box->value(); } double GetD2(){ return m_Controls->m_D2box->value(); } double GetD3(){ return m_Controls->m_D3box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } public slots: void DChanged( double value ); protected: // member variables Ui::QmitkTensorModelParametersWidgetControls* m_Controls; void UpdateUi(); private: }; #endif // _QMITKTensorModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui index bceeeec920..2917f41732 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui @@ -1,160 +1,180 @@ QmitkTensorModelParametersWidgetControls 0 0 - 410 - 167 + 364 + 190 0 0 Form 0 0 0 0 - - - - <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> - - - - + - <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂1</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> - - + + - Diffusivity along second eigenvector. + Diffusivity along third eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 + + + + <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂2</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + - + - <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> - + + + + Fractional anisotropy of resulting tensor. + + + <html><head/><body><p>-</p></body></html> + + + + + + + <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂1</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + Diffusivity along largest eigenvector. 5 1.000000000000000 0.000100000000000 0.001000000000000 + + + + <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> + + + - + - Diffusivity along third eigenvector. + Diffusivity along second eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 - - - - <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂2</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> - - - - - + + - Fractional anisotropy of resulting tensor. + T2 relaxation time of this compartment (in milliseconds). - - <html><head/><body><p>-</p></body></html> + + 999999999 + + + 110 - + - <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">T1</span> - Relaxation:</p></body></html> - + - T2 relaxation time of this compartment (in milliseconds). + T1 relaxation time of this compartment (in milliseconds). - 10000 + 999999999 - 110 + 780 m_T2box m_D1box m_D2box m_D3box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h index c1cc871f5c..747627f206 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h @@ -1,65 +1,67 @@ /*=================================================================== 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 _QMITKZeppelinModelParametersWidget_H_INCLUDED #define _QMITKZeppelinModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkZeppelinModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkZeppelinModelParametersWidget : public QWidget { //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; QmitkZeppelinModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkZeppelinModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); } void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); } void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); } double GetD1(){ return m_Controls->m_D1box->value(); } double GetD2(){ return m_Controls->m_D2box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } + unsigned int GetT1(){ return m_Controls->m_T1box->value(); } public slots: void DChanged( double value ); protected: // member variables Ui::QmitkZeppelinModelParametersWidgetControls* m_Controls; void UpdateUi(); private: }; #endif // _QMITKZeppelinModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui index 8fc23021d0..7d230c7f41 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui @@ -1,133 +1,153 @@ QmitkZeppelinModelParametersWidgetControls 0 0 - 410 - 116 + 355 + 154 0 0 Form 0 0 0 0 - - + + + + <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + + + + <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> + + + + + - Fractional anisotropy of resulting tensor. + T2 relaxation time of this compartment (in milliseconds). + + 999999999 + + + 110 + + + + + - <html><head/><body><p>-</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> - + + + + <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + Diffusivity along second and third eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 - - - - T2 relaxation time of this compartment (in milliseconds). - - - 10000 - - - 110 - - - - + Diffusivity along largest eigenvector. 5 1.000000000000000 0.000100000000000 0.001000000000000 - - - - <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + + + + Fractional anisotropy of resulting tensor. - - - - - <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span><span style=" font-style:italic;"> [mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">/s]</span>:</p></body></html> + <html><head/><body><p>-</p></body></html> - + - <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> + <html><head/><body><p><span style=" font-style:italic;">T1</span> - Relaxation:</p></body></html> - - - - <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> + + + + T1 relaxation time of this compartment (in milliseconds). + + + 999999999 + + + 780 m_T2box m_D1box m_D2box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp index eb69396981..d6aba3b5f3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp @@ -1,1030 +1,1029 @@ /*=================================================================== 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 "QmitkControlVisualizationPropertiesView.h" #include "mitkNodePredicateDataType.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkResliceMethodProperty.h" #include "mitkRenderingManager.h" #include "mitkTbssImage.h" #include "mitkPlanarFigure.h" #include "mitkFiberBundle.h" #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkFiberBundleInteractor.h" #include "mitkPlanarFigureInteractor.h" #include #include #include #include #include #include "mitkGlobalInteraction.h" #include "usModuleRegistry.h" #include "mitkPlaneGeometry.h" #include "berryIWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryISelectionService.h" #include "berryConstants.h" #include "berryPlatformUI.h" #include "itkRGBAPixel.h" #include #include "qwidgetaction.h" #include "qcolordialog.h" #include #include #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) const std::string QmitkControlVisualizationPropertiesView::VIEW_ID = "org.mitk.views.controlvisualizationpropertiesview"; using namespace berry; QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_NodeUsedForOdfVisualization(NULL), m_IconTexOFF(new QIcon(":/QmitkDiffusionImaging/texIntOFFIcon.png")), m_IconTexON(new QIcon(":/QmitkDiffusionImaging/texIntONIcon.png")), m_IconGlyOFF_T(new QIcon(":/QmitkDiffusionImaging/glyphsoff_T.png")), m_IconGlyON_T(new QIcon(":/QmitkDiffusionImaging/glyphson_T.png")), m_IconGlyOFF_C(new QIcon(":/QmitkDiffusionImaging/glyphsoff_C.png")), m_IconGlyON_C(new QIcon(":/QmitkDiffusionImaging/glyphson_C.png")), m_IconGlyOFF_S(new QIcon(":/QmitkDiffusionImaging/glyphsoff_S.png")), m_IconGlyON_S(new QIcon(":/QmitkDiffusionImaging/glyphson_S.png")), m_CurrentSelection(0), m_CurrentPickingNode(0), m_GlyIsOn_S(false), m_GlyIsOn_C(false), m_GlyIsOn_T(false), m_FiberBundleObserverTag(0), m_FiberBundleObserveOpacityTag(0), m_Color(NULL) { currentThickSlicesMode = 1; m_MyMenu = NULL; int numThread = itk::MultiThreader::GetGlobalMaximumNumberOfThreads(); if (numThread > 12) numThread = 12; itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThread); } QmitkControlVisualizationPropertiesView::~QmitkControlVisualizationPropertiesView() { if(m_SlicesRotationObserverTag1 ) { mitk::SlicesCoordinator::Pointer coordinator = m_MultiWidget->GetSlicesRotator(); if( coordinator.IsNotNull() ) coordinator->RemoveObserver(m_SlicesRotationObserverTag1); } if( m_SlicesRotationObserverTag2) { mitk::SlicesCoordinator::Pointer coordinator = m_MultiWidget->GetSlicesRotator(); if( coordinator.IsNotNull() ) coordinator->RemoveObserver(m_SlicesRotationObserverTag1); } this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->RemovePostSelectionListener(/*"org.mitk.views.datamanager",*/ m_SelListener.data()); } void QmitkControlVisualizationPropertiesView::OnThickSlicesModeSelected( QAction* action ) { currentThickSlicesMode = action->data().toInt(); switch(currentThickSlicesMode) { default: case 1: this->m_Controls->m_TSMenu->setText("MIP"); break; case 2: this->m_Controls->m_TSMenu->setText("SUM"); break; case 3: this->m_Controls->m_TSMenu->setText("WEIGH"); break; } mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); mitk::BaseRenderer::Pointer renderer = this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer(); if(renderer.IsNotNull()) { renderer->SendUpdateSlice(); } renderer->GetRenderingManager()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::OnTSNumChanged(int num) { if(num==0) { mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( 0 ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( false ) ); } else { mitk::DataNode* n; n = this->m_MultiWidget->GetWidgetPlane1(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); n = this->m_MultiWidget->GetWidgetPlane2(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); n = this->m_MultiWidget->GetWidgetPlane3(); if(n) n->SetProperty( "reslice.thickslices", mitk::ResliceMethodProperty::New( currentThickSlicesMode ) ); if(n) n->SetProperty( "reslice.thickslices.num", mitk::IntProperty::New( num ) ); if(n) n->SetProperty( "reslice.thickslices.showarea", mitk::BoolProperty::New( (num>0) ) ); } m_TSLabel->setText(QString::number(num*2+1)); mitk::BaseRenderer::Pointer renderer = this->GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer(); if(renderer.IsNotNull()) renderer->SendUpdateSlice(); renderer = this->GetActiveStdMultiWidget()->GetRenderWindow2()->GetRenderer(); if(renderer.IsNotNull()) renderer->SendUpdateSlice(); renderer = this->GetActiveStdMultiWidget()->GetRenderWindow3()->GetRenderer(); if(renderer.IsNotNull()) renderer->SendUpdateSlice(); renderer->GetRenderingManager()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); } void QmitkControlVisualizationPropertiesView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkControlVisualizationPropertiesViewControls; m_Controls->setupUi(parent); this->CreateConnections(); // hide warning (ODFs in rotated planes) m_Controls->m_lblRotatedPlanesWarning->hide(); m_MyMenu = new QMenu(parent); m_Controls->m_TSMenu->setMenu( m_MyMenu ); QIcon iconFiberFade(":/QmitkDiffusionImaging/MapperEfx2D.png"); m_Controls->m_FiberFading2D->setIcon(iconFiberFade); #ifndef DIFFUSION_IMAGING_EXTENDED int size = m_Controls->m_AdditionalScaling->count(); for(int t=0; tm_AdditionalScaling->itemText(t).toStdString() == "Scale by ASR") { m_Controls->m_AdditionalScaling->removeItem(t); } } #endif m_Controls->m_ScalingFrame->setVisible(false); m_Controls->m_NormalizationFrame->setVisible(false); } } void QmitkControlVisualizationPropertiesView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; if (m_MultiWidget) { mitk::SlicesCoordinator* coordinator = m_MultiWidget->GetSlicesRotator(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation ); m_SlicesRotationObserverTag1 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } coordinator = m_MultiWidget->GetSlicesSwiveller(); if (coordinator) { itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SliceRotation ); m_SlicesRotationObserverTag2 = coordinator->AddObserver( mitk::SliceRotationEvent(), command2 ); } } } void QmitkControlVisualizationPropertiesView::SliceRotation(const itk::EventObject&) { // test if plane rotated if( m_GlyIsOn_T || m_GlyIsOn_C || m_GlyIsOn_S ) { if( this->IsPlaneRotated() ) { // show label m_Controls->m_lblRotatedPlanesWarning->show(); } else { //hide label m_Controls->m_lblRotatedPlanesWarning->hide(); } } } void QmitkControlVisualizationPropertiesView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkControlVisualizationPropertiesView::NodeRemoved(const mitk::DataNode* /*node*/) { } #include void QmitkControlVisualizationPropertiesView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_VisibleOdfsON_T), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_T()) ); connect( (QObject*)(m_Controls->m_VisibleOdfsON_S), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_S()) ); connect( (QObject*)(m_Controls->m_VisibleOdfsON_C), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_C()) ); connect( (QObject*)(m_Controls->m_ShowMaxNumber), SIGNAL(editingFinished()), this, SLOT(ShowMaxNumberChanged()) ); connect( (QObject*)(m_Controls->m_NormalizationDropdown), SIGNAL(currentIndexChanged(int)), this, SLOT(NormalizationDropdownChanged(int)) ); connect( (QObject*)(m_Controls->m_ScalingFactor), SIGNAL(valueChanged(double)), this, SLOT(ScalingFactorChanged(double)) ); connect( (QObject*)(m_Controls->m_AdditionalScaling), SIGNAL(currentIndexChanged(int)), this, SLOT(AdditionalScaling(int)) ); connect( (QObject*)(m_Controls->m_ScalingCheckbox), SIGNAL(clicked()), this, SLOT(ScalingCheckbox()) ); connect((QObject*) m_Controls->m_ResetColoring, SIGNAL(clicked()), (QObject*) this, SLOT(BundleRepresentationResetColoring())); connect((QObject*) m_Controls->m_FiberFading2D, SIGNAL(clicked()), (QObject*) this, SLOT( Fiber2DfadingEFX() ) ); connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(sliderReleased()), (QObject*) this, SLOT( FiberSlicingThickness2D() ) ); connect((QObject*) m_Controls->m_FiberThicknessSlider, SIGNAL(valueChanged(int)), (QObject*) this, SLOT( FiberSlicingUpdateLabel(int) )); connect((QObject*) m_Controls->m_Crosshair, SIGNAL(clicked()), (QObject*) this, SLOT(SetInteractor())); connect((QObject*) m_Controls->m_LineWidth, SIGNAL(editingFinished()), (QObject*) this, SLOT(LineWidthChanged())); connect((QObject*) m_Controls->m_TubeWidth, SIGNAL(editingFinished()), (QObject*) this, SLOT(TubeRadiusChanged())); } } void QmitkControlVisualizationPropertiesView::Activated() { } void QmitkControlVisualizationPropertiesView::Deactivated() { } // set diffusion image channel to b0 volume void QmitkControlVisualizationPropertiesView::NodeAdded(const mitk::DataNode *node) { mitk::DataNode* notConst = const_cast(node); bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); if (isDiffusionImage) { mitk::Image::Pointer dimg = dynamic_cast(notConst->GetData()); // if there is no b0 image in the dataset, the GetB0Indices() returns a vector of size 0 // and hence we cannot set the Property directly to .front() int displayChannelPropertyValue = 0; mitk::BValueMapProperty* bmapproperty = static_cast(dimg->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() ); mitk::DiffusionPropertyHelper::BValueMapType map = bmapproperty->GetBValueMap(); if( map[0].size() > 0) displayChannelPropertyValue = map[0].front(); notConst->SetIntProperty("DisplayChannel", displayChannelPropertyValue ); } } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkControlVisualizationPropertiesView::OnSelectionChanged( std::vector nodes ) { m_Controls->m_BundleControlsFrame->setVisible(false); m_Controls->m_ImageControlsFrame->setVisible(false); if (nodes.size()>1) // only do stuff if one node is selected return; m_Controls->m_NumberGlyphsFrame->setVisible(false); m_Controls->m_GlyphFrame->setVisible(false); m_Controls->m_TSMenu->setVisible(false); m_SelectedNode = NULL; int numOdfImages = 0; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if(node.IsNull()) continue; mitk::BaseData* nodeData = node->GetData(); if(nodeData == NULL) continue; m_SelectedNode = node; if (dynamic_cast(nodeData)) { // handle fiber bundle property observers if (m_Color.IsNotNull()) m_Color->RemoveObserver(m_FiberBundleObserverTag); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor ); m_Color = dynamic_cast(node->GetProperty("color", NULL)); if (m_Color.IsNotNull()) m_FiberBundleObserverTag = m_Color->AddObserver( itk::ModifiedEvent(), command ); if (m_Opacity.IsNotNull()) m_Opacity->RemoveObserver(m_FiberBundleObserveOpacityTag); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetFiberBundleOpacity ); m_Opacity = dynamic_cast(node->GetProperty("opacity", NULL)); if (m_Opacity.IsNotNull()) m_FiberBundleObserveOpacityTag = m_Opacity->AddObserver( itk::ModifiedEvent(), command2 ); m_Controls->m_BundleControlsFrame->setVisible(true); // ??? if(m_CurrentPickingNode != 0 && node.GetPointer() != m_CurrentPickingNode) m_Controls->m_Crosshair->setEnabled(false); else m_Controls->m_Crosshair->setEnabled(true); int width; node->GetIntProperty("shape.linewidth", width); m_Controls->m_LineWidth->setValue(width); float radius; node->GetFloatProperty("shape.tuberadius", radius); m_Controls->m_TubeWidth->setValue(radius); float range; node->GetFloatProperty("Fiber2DSliceThickness",range); mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); mitk::BaseGeometry::Pointer geo = fib->GetGeometry(); mitk::ScalarType max = geo->GetExtentInMM(0); max = std::max(max, geo->GetExtentInMM(1)); max = std::max(max, geo->GetExtentInMM(2)); m_Controls->m_FiberThicknessSlider->setMaximum(max * 10); m_Controls->m_FiberThicknessSlider->setValue(range * 10); - m_Controls->m_FiberThicknessSlider->setFocus(); } else if(dynamic_cast(nodeData) || dynamic_cast(nodeData)) { m_Controls->m_ImageControlsFrame->setVisible(true); m_Controls->m_NumberGlyphsFrame->setVisible(true); m_Controls->m_GlyphFrame->setVisible(true); if(m_NodeUsedForOdfVisualization.IsNotNull()) { m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", false); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", false); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", false); } m_NodeUsedForOdfVisualization = node; m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C); m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T); int val; node->GetIntProperty("ShowMaxNumber", val); m_Controls->m_ShowMaxNumber->setValue(val); m_Controls->m_NormalizationDropdown->setCurrentIndex(dynamic_cast(node->GetProperty("Normalization"))->GetValueAsId()); float fval; node->GetFloatProperty("Scaling",fval); m_Controls->m_ScalingFactor->setValue(fval); m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast(node->GetProperty("ScaleBy"))->GetValueAsId()); numOdfImages++; } else if(dynamic_cast(nodeData)) { PlanarFigureFocus(); } else if( dynamic_cast(nodeData) ) { m_Controls->m_ImageControlsFrame->setVisible(true); m_Controls->m_TSMenu->setVisible(true); } } if( nodes.empty() ) return; mitk::DataNode::Pointer node = nodes.at(0); if( node.IsNull() ) return; QMenu *myMenu = m_MyMenu; myMenu->clear(); QActionGroup* thickSlicesActionGroup = new QActionGroup(myMenu); thickSlicesActionGroup->setExclusive(true); int currentTSMode = 0; { mitk::ResliceMethodProperty::Pointer m = dynamic_cast(node->GetProperty( "reslice.thickslices" )); if( m.IsNotNull() ) currentTSMode = m->GetValueAsId(); } int maxTS = 30; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::Image* image = dynamic_cast((*it)->GetData()); if (image) { int size = std::max(image->GetDimension(0), std::max(image->GetDimension(1), image->GetDimension(2))); if (size>maxTS) maxTS=size; } } maxTS /= 2; int currentNum = 0; { mitk::IntProperty::Pointer m = dynamic_cast(node->GetProperty( "reslice.thickslices.num" )); if( m.IsNotNull() ) { currentNum = m->GetValue(); if(currentNum < 0) currentNum = 0; if(currentNum > maxTS) currentNum = maxTS; } } if(currentTSMode==0) currentNum=0; QSlider *m_TSSlider = new QSlider(myMenu); m_TSSlider->setMinimum(0); m_TSSlider->setMaximum(maxTS-1); m_TSSlider->setValue(currentNum); m_TSSlider->setOrientation(Qt::Horizontal); connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) ); QHBoxLayout* _TSLayout = new QHBoxLayout; _TSLayout->setContentsMargins(4,4,4,4); _TSLayout->addWidget(m_TSSlider); _TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),myMenu)); QWidget* _TSWidget = new QWidget; _TSWidget->setLayout(_TSLayout); QActionGroup* thickSliceModeActionGroup = new QActionGroup(myMenu); thickSliceModeActionGroup->setExclusive(true); QWidgetAction *m_TSSliderAction = new QWidgetAction(myMenu); m_TSSliderAction->setDefaultWidget(_TSWidget); myMenu->addAction(m_TSSliderAction); QAction* mipThickSlicesAction = new QAction(myMenu); mipThickSlicesAction->setActionGroup(thickSliceModeActionGroup); mipThickSlicesAction->setText("MIP (max. intensity proj.)"); mipThickSlicesAction->setCheckable(true); mipThickSlicesAction->setChecked(currentThickSlicesMode==1); mipThickSlicesAction->setData(1); myMenu->addAction( mipThickSlicesAction ); QAction* sumThickSlicesAction = new QAction(myMenu); sumThickSlicesAction->setActionGroup(thickSliceModeActionGroup); sumThickSlicesAction->setText("SUM (sum intensity proj.)"); sumThickSlicesAction->setCheckable(true); sumThickSlicesAction->setChecked(currentThickSlicesMode==2); sumThickSlicesAction->setData(2); myMenu->addAction( sumThickSlicesAction ); QAction* weightedThickSlicesAction = new QAction(myMenu); weightedThickSlicesAction->setActionGroup(thickSliceModeActionGroup); weightedThickSlicesAction->setText("WEIGHTED (gaussian proj.)"); weightedThickSlicesAction->setCheckable(true); weightedThickSlicesAction->setChecked(currentThickSlicesMode==3); weightedThickSlicesAction->setData(3); myMenu->addAction( weightedThickSlicesAction ); connect( thickSliceModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnThickSlicesModeSelected(QAction*)) ); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_S() { m_GlyIsOn_S = m_Controls->m_VisibleOdfsON_S->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_T() { m_GlyIsOn_T = m_Controls->m_VisibleOdfsON_T->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::VisibleOdfsON_C() { m_GlyIsOn_C = m_Controls->m_VisibleOdfsON_C->isChecked(); if (m_NodeUsedForOdfVisualization.IsNull()) { MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is NULL"; return; } m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } bool QmitkControlVisualizationPropertiesView::IsPlaneRotated() { mitk::Image* currentImage = dynamic_cast( m_NodeUsedForOdfVisualization->GetData() ); if( currentImage == NULL ) { MITK_ERROR << " Casting problems. Returning false"; return false; } mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0); mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1); mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2); imageNormal0.Normalize(); imageNormal1.Normalize(); imageNormal2.Normalize(); double eps = 0.000001; // for all 2D renderwindows of m_MultiWidget check alignment { mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; mitk::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } { mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow2()->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; mitk::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } { mitk::PlaneGeometry::ConstPointer displayPlane = dynamic_cast( m_MultiWidget->GetRenderWindow3()->GetRenderer()->GetCurrentWorldGeometry2D() ); if (displayPlane.IsNull()) return false; mitk::Vector3D normal = displayPlane->GetNormal(); normal.Normalize(); int test = 0; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) test++; if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) test++; if (test==3) return true; } return false; } void QmitkControlVisualizationPropertiesView::ShowMaxNumberChanged() { int maxNr = m_Controls->m_ShowMaxNumber->value(); if ( maxNr < 1 ) { m_Controls->m_ShowMaxNumber->setValue( 1 ); maxNr = 1; } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetIntProperty("ShowMaxNumber", maxNr); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::NormalizationDropdownChanged(int normDropdown) { typedef mitk::OdfNormalizationMethodProperty PropType; PropType::Pointer normMeth = PropType::New(); switch(normDropdown) { case 0: normMeth->SetNormalizationToMinMax(); break; case 1: normMeth->SetNormalizationToMax(); break; case 2: normMeth->SetNormalizationToNone(); break; case 3: normMeth->SetNormalizationToGlobalMax(); break; default: normMeth->SetNormalizationToMinMax(); } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetProperty("Normalization", normMeth.GetPointer()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor) { if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetFloatProperty("Scaling", scalingFactor); if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkControlVisualizationPropertiesView::AdditionalScaling(int additionalScaling) { typedef mitk::OdfScaleByProperty PropType; PropType::Pointer scaleBy = PropType::New(); switch(additionalScaling) { case 0: scaleBy->SetScaleByNothing(); break; case 1: scaleBy->SetScaleByGFA(); //m_Controls->params_frame->setVisible(true); break; #ifdef DIFFUSION_IMAGING_EXTENDED case 2: scaleBy->SetScaleByPrincipalCurvature(); // commented in for SPIE paper, Principle curvature scaling //m_Controls->params_frame->setVisible(true); break; #endif default: scaleBy->SetScaleByNothing(); } if (dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData())) m_SelectedNode->SetProperty("Normalization", scaleBy.GetPointer()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::ScalingCheckbox() { m_Controls->m_ScalingFrame->setVisible( m_Controls->m_ScalingCheckbox->isChecked()); if(!m_Controls->m_ScalingCheckbox->isChecked()) { m_Controls->m_AdditionalScaling->setCurrentIndex(0); m_Controls->m_ScalingFactor->setValue(1.0); } } void QmitkControlVisualizationPropertiesView::Fiber2DfadingEFX() { if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData()) ) { bool currentMode; m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode); m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode)); dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D() { if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float fibThickness = m_Controls->m_FiberThicknessSlider->value() * 0.1; float currentThickness = 0; m_SelectedNode->GetFloatProperty("Fiber2DSliceThickness", currentThickness); if (fabs(fibThickness-currentThickness)<0.001) return; m_SelectedNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(fibThickness)); dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingUpdateLabel(int value) { QString label = "Range %1 mm"; label = label.arg(value * 0.1); m_Controls->label_range->setText(label); FiberSlicingThickness2D(); } void QmitkControlVisualizationPropertiesView::SetFiberBundleOpacity(const itk::EventObject& /*e*/) { if(m_SelectedNode) { mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->RequestUpdate(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::SetFiberBundleCustomColor(const itk::EventObject& /*e*/) { if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float color[3]; m_SelectedNode->GetColor(color); mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->SetFiberColors(color[0]*255, color[1]*255, color[2]*255); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::BundleRepresentationResetColoring() { if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->ColorFibersByOrientation(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::PlanarFigureFocus() { if(m_SelectedNode) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (m_SelectedNode->GetData()); if (_PlanarFigure && _PlanarFigure->GetPlaneGeometry()) { QmitkRenderWindow* selectedRenderWindow = 0; bool PlanarFigureInitializedWindow = false; QmitkRenderWindow* RenderWindow1 = this->GetActiveStdMultiWidget()->GetRenderWindow1(); if (m_SelectedNode->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow1->GetRenderer())) { selectedRenderWindow = RenderWindow1; } QmitkRenderWindow* RenderWindow2 = this->GetActiveStdMultiWidget()->GetRenderWindow2(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow2->GetRenderer())) { selectedRenderWindow = RenderWindow2; } QmitkRenderWindow* RenderWindow3 = this->GetActiveStdMultiWidget()->GetRenderWindow3(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow3->GetRenderer())) { selectedRenderWindow = RenderWindow3; } QmitkRenderWindow* RenderWindow4 = this->GetActiveStdMultiWidget()->GetRenderWindow4(); if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, RenderWindow4->GetRenderer())) { selectedRenderWindow = RenderWindow4; } const mitk::PlaneGeometry* _PlaneGeometry = _PlanarFigure->GetPlaneGeometry(); mitk::VnlVector normal = _PlaneGeometry->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry1 = RenderWindow1->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane1 = dynamic_cast( worldGeometry1.GetPointer() ); mitk::VnlVector normal1 = _Plane1->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry2 = RenderWindow2->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane2 = dynamic_cast( worldGeometry2.GetPointer() ); mitk::VnlVector normal2 = _Plane2->GetNormalVnl(); mitk::Geometry2D::ConstPointer worldGeometry3 = RenderWindow3->GetRenderer()->GetCurrentWorldGeometry2D(); mitk::PlaneGeometry::ConstPointer _Plane3 = dynamic_cast( worldGeometry3.GetPointer() ); mitk::VnlVector normal3 = _Plane3->GetNormalVnl(); normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]); normal1[0] = fabs(normal1[0]); normal1[1] = fabs(normal1[1]); normal1[2] = fabs(normal1[2]); normal2[0] = fabs(normal2[0]); normal2[1] = fabs(normal2[1]); normal2[2] = fabs(normal2[2]); normal3[0] = fabs(normal3[0]); normal3[1] = fabs(normal3[1]); normal3[2] = fabs(normal3[2]); double ang1 = angle(normal, normal1); double ang2 = angle(normal, normal2); double ang3 = angle(normal, normal3); if(ang1 < ang2 && ang1 < ang3) { selectedRenderWindow = RenderWindow1; } else { if(ang2 < ang3) { selectedRenderWindow = RenderWindow2; } else { selectedRenderWindow = RenderWindow3; } } // make node visible if (selectedRenderWindow) { const mitk::Point3D& centerP = _PlaneGeometry->GetOrigin(); selectedRenderWindow->GetSliceNavigationController()->ReorientSlices( centerP, _PlaneGeometry->GetNormal()); } } // set interactor for new node (if not already set) mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(m_SelectedNode->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( m_SelectedNode ); } m_SelectedNode->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true)); } } void QmitkControlVisualizationPropertiesView::SetInteractor() { typedef std::vector Container; Container _NodeSet = this->GetDataManagerSelection(); mitk::DataNode* node = 0; mitk::FiberBundle* bundle = 0; mitk::FiberBundleInteractor::Pointer bundleInteractor = 0; // finally add all nodes to the model for(Container::const_iterator it=_NodeSet.begin(); it!=_NodeSet.end() ; it++) { node = const_cast(*it); bundle = dynamic_cast(node->GetData()); if(bundle) { bundleInteractor = dynamic_cast(node->GetInteractor()); if(bundleInteractor.IsNotNull()) mitk::GlobalInteraction::GetInstance()->RemoveInteractor(bundleInteractor); if(!m_Controls->m_Crosshair->isChecked()) { m_Controls->m_Crosshair->setChecked(false); this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::ArrowCursor); m_CurrentPickingNode = 0; } else { m_Controls->m_Crosshair->setChecked(true); bundleInteractor = mitk::FiberBundleInteractor::New("FiberBundleInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(bundleInteractor); this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::CrossCursor); m_CurrentPickingNode = node; } } } } void QmitkControlVisualizationPropertiesView::TubeRadiusChanged() { if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float newRadius = m_Controls->m_TubeWidth->value(); m_SelectedNode->SetFloatProperty("shape.tuberadius", newRadius); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::LineWidthChanged() { if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { int newWidth = m_Controls->m_LineWidth->value(); int currentWidth = 0; m_SelectedNode->GetIntProperty("shape.linewidth", currentWidth); if (currentWidth==newWidth) return; m_SelectedNode->SetIntProperty("shape.linewidth", newWidth); dynamic_cast(m_SelectedNode->GetData())->RequestUpdate(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::Welcome() { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( GetSite()->GetWorkbenchWindow(), false); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui index 30c0704d5d..1babb00a07 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesViewControls.ui @@ -1,722 +1,719 @@ QmitkControlVisualizationPropertiesViewControls 0 0 567 619 0 100 0 0 QmitkTemplate 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Multislice Projection MIP QToolButton::MenuButtonPopup Qt::NoArrow QFrame::NoFrame QFrame::Plain 0 0 0 0 Toggle visibility of ODF glyphs (axial) :/QmitkDiffusionImaging/glyphsoff_T.png :/QmitkDiffusionImaging/glyphson_T.png:/QmitkDiffusionImaging/glyphsoff_T.png true false Toggle visibility of ODF glyphs (sagittal) :/QmitkDiffusionImaging/glyphsoff_S.png :/QmitkDiffusionImaging/glyphson_S.png:/QmitkDiffusionImaging/glyphsoff_S.png true false Toggle visibility of ODF glyphs (coronal) :/QmitkDiffusionImaging/glyphsoff_C.png :/QmitkDiffusionImaging/glyphson_C.png:/QmitkDiffusionImaging/glyphsoff_C.png true false #Glyphs 9999 Qt::Horizontal 20 20 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 0 QFrame::NoFrame QFrame::Plain 0 0 0 0 false None By GFA By ASR * Additional scaling factor 3 999999999.000000000000000 0.100000000000000 1.000000000000000 Scaling QFrame::NoFrame QFrame::Plain 0 0 0 0 0 ODF normalization false Min-Max Max None QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Reset to Default Coloring :/QmitkDiffusionImaging/reset.png:/QmitkDiffusionImaging/reset.png Position Crosshair by 3D-Click :/QmitkDiffusionImaging/crosshair.png:/QmitkDiffusionImaging/crosshair.png true false 2D Fiberfading on/off Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 0 0 0 2D Clipping 100 10 10 10 Qt::Horizontal 90 0 10000 16777215 Range QFrame::NoFrame QFrame::Raised 0 0 0 0 - - - - Tube Width + + + + 1 + + + 10 Line Width - - - - 1 - - - 10 + + + + Tube Radius - - Fiber tube radius in mm. If > 0, fibers are rendered as tubes in 3D. - 4 0.100000000000000 50 false false <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ff0000;">One or more slices are rotated. ODF Visualisation is not possible in rotated planes. Use 'Reinit' on the image node to reset. </span></p></body></html> Qt::AutoText true Qt::Vertical 20 40 QmitkDataStorageComboBox.h diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp index 94e15c8103..a95f56d5a9 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp @@ -1,1359 +1,1361 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberProcessingView.h" #include // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" #include #include "mitkNodePredicateDataType.h" #include #include #include #include // ITK #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberProcessingView::VIEW_ID = "org.mitk.views.fiberprocessing"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberProcessingView::QmitkFiberProcessingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_CircleCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(1) { } // Destructor QmitkFiberProcessingView::~QmitkFiberProcessingView() { } void QmitkFiberProcessingView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberProcessingViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) ); connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) ); connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) ); connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) ); connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) ); connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) ); connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) ); connect(m_Controls->m_ExtractFibersButton, SIGNAL(clicked()), this, SLOT(Extract())); connect(m_Controls->m_RemoveButton, SIGNAL(clicked()), this, SLOT(Remove())); connect(m_Controls->m_ModifyButton, SIGNAL(clicked()), this, SLOT(Modify())); connect(m_Controls->m_ExtractionMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_RemovalMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect(m_Controls->m_ModificationMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); m_Controls->m_ColorMapBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_ColorMapBox->SetPredicate(finalPredicate); } UpdateGui(); } void QmitkFiberProcessingView::Modify() { switch (m_Controls->m_ModificationMethodBox->currentIndex()) { case 0: { ResampleSelectedBundles(); break; } case 1: { CompressSelectedBundles(); break; } case 2: { DoImageColorCoding(); break; } case 3: { MirrorFibers(); break; } case 4: { WeightFibers(); break; } case 5: { DoCurvatureColorCoding(); break; } } } void QmitkFiberProcessingView::WeightFibers() { float weight = this->m_Controls->m_BundleWeightBox->value(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); fib->SetFiberWeights(weight); } } void QmitkFiberProcessingView::Remove() { switch (m_Controls->m_RemovalMethodBox->currentIndex()) { case 0: { RemoveDir(); break; } case 1: { PruneBundle(); break; } case 2: { ApplyCurvatureThreshold(); break; } case 3: { RemoveWithMask(false); break; } case 4: { RemoveWithMask(true); break; } } } void QmitkFiberProcessingView::Extract() { switch (m_Controls->m_ExtractionMethodBox->currentIndex()) { case 0: { ExtractWithPlanarFigure(); break; } case 1: { switch (m_Controls->m_ExtractionBoxMask->currentIndex()) { { case 0: ExtractWithMask(true, false); break; } { case 1: ExtractWithMask(true, true); break; } { case 2: ExtractWithMask(false, false); break; } { case 3: ExtractWithMask(false, true); break; } } break; } } } void QmitkFiberProcessingView::PruneBundle() { int minLength = this->m_Controls->m_PruneFibersMinBox->value(); int maxLength = this->m_Controls->m_PruneFibersMaxBox->value(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); if (!fib->RemoveShortFibers(minLength)) QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); else if (!fib->RemoveLongFibers(maxLength)) QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::ApplyCurvatureThreshold() { int angle = this->m_Controls->m_CurvSpinBox->value(); int dist = this->m_Controls->m_CurvDistanceSpinBox->value(); std::vector< DataNode::Pointer > nodes = m_SelectedFB; for (int i=0; i(nodes.at(i)->GetData()); itk::FiberCurvatureFilter::Pointer filter = itk::FiberCurvatureFilter::New(); filter->SetInputFiberBundle(fib); filter->SetAngularDeviation(angle); filter->SetDistance(dist); filter->SetRemoveFibers(m_Controls->m_RemoveCurvedFibersBox->isChecked()); filter->Update(); mitk::FiberBundle::Pointer newFib = filter->GetOutputFiberBundle(); if (newFib->GetNumFibers()>0) { nodes.at(i)->SetVisibility(false); DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); newNode->SetName(nodes.at(i)->GetName()+"_Curvature"); GetDefaultDataStorage()->Add(newNode, nodes.at(i)); } else QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); // if (!fib->ApplyCurvatureThreshold(mm, this->m_Controls->m_RemoveCurvedFibersBox->isChecked())) // QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveDir() { for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); vnl_vector_fixed dir; dir[0] = m_Controls->m_ExtractDirX->value(); dir[1] = m_Controls->m_ExtractDirY->value(); dir[2] = m_Controls->m_ExtractDirZ->value(); fib->RemoveDir(dir,cos((float)m_Controls->m_ExtractAngle->value()*M_PI/180)); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::RemoveWithMask(bool removeInside) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundle::Pointer newFib = fib->RemoveFibersOutside(mask, removeInside); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); if (removeInside) name += "_Inside"; else name += "_Outside"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberProcessingView::ExtractWithMask(bool onlyEnds, bool invert) { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); - mitk::FiberBundle::Pointer newFib = fib->ExtractFiberSubset(mask, onlyEnds, invert); + mitk::FiberBundle::Pointer newFib = fib->ExtractFiberSubset(mask, !onlyEnds, invert); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); if (invert) { name += "_not"; if (onlyEnds) name += "-ending-in-mask"; else name += "-passing-mask"; } else { if (onlyEnds) name += "_ending-in-mask"; else name += "_passing-mask"; } newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberProcessingView::GenerateRoiImage() { if (m_SelectedPF.empty()) return; mitk::BaseGeometry::Pointer geometry; if (!m_SelectedFB.empty()) { mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); geometry = fib->GetGeometry(); } else if (m_SelectedImage) geometry = m_SelectedImage->GetGeometry(); else return; itk::Vector spacing = geometry->GetSpacing(); spacing /= m_UpsamplingFactor; mitk::Point3D newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); itk::Matrix direction; itk::ImageRegion<3> imageRegion; for (int i=0; i<3; i++) for (int j=0; j<3; j++) direction[j][i] = geometry->GetMatrixColumn(i)[j]/spacing[j]; imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); m_PlanarFigureImage = itkUCharImageType::New(); m_PlanarFigureImage->SetSpacing( spacing ); // Set the image spacing m_PlanarFigureImage->SetOrigin( newOrigin ); // Set the image origin m_PlanarFigureImage->SetDirection( direction ); // Set the image direction m_PlanarFigureImage->SetRegions( imageRegion ); m_PlanarFigureImage->Allocate(); m_PlanarFigureImage->FillBuffer( 0 ); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); std::string name = m_SelectedPF.at(0)->GetName(); WritePfToImage(m_SelectedPF.at(0), tmpImage); for (unsigned int i=1; iGetName(); WritePfToImage(m_SelectedPF.at(i), tmpImage); } DataNode::Pointer node = DataNode::New(); tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); node->SetName(name); this->GetDefaultDataStorage()->Add(node); } void QmitkFiberProcessingView::WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image) { if (dynamic_cast(node->GetData())) { m_PlanarFigure = dynamic_cast(node->GetData()); AccessFixedDimensionByItk_2( image, InternalReorientImagePlane, 3, m_PlanarFigure->GetGeometry(), -1); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } else if (dynamic_cast(node->GetData())) { DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(node); for (int j=0; jsize(); j++) { WritePfToImage(children->ElementAt(j), image); } } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); float upsamp = m_UpsamplingFactor; float gausssigma = 0.5; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; resampler->SetOutputSpacing( spacing ); // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetExtentInMM(0) / spacing[0]; size[1] = planegeo->GetExtentInMM(1) / spacing[1]; size[2] = 1; resampler->SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; corrorig[2] += 0; planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) sigma[d] = gausssigma * image->GetSpacing()[d]; double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); resampler->Update(); if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". itkUCharImageType::Pointer newMaskImage = itkUCharImageType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour vtkPoints *points = vtkPoints::New(); PlanarFigure::PolyLineType::const_iterator it; unsigned int numberOfPoints = 0; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected image Point2D point2D = *it; planarFigurePlaneGeometry->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigurePlaneGeometry->IndexToWorld(point2D, point2D); planarFigurePlaneGeometry->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { float bounds[2] = {0,0}; bounds[0] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0); bounds[1] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1); imageGeometry3D->WorldToIndex( point3D, point3D ); if (point3D[i0]<0) point3D[i0] = 0.0; else if (point3D[i0]>bounds[0]) point3D[i0] = bounds[0]-0.001; if (point3D[i1]<0) point3D[i1] = 0.0; else if (point3D[i1]>bounds[1]) point3D[i1] = bounds[1]-0.001; points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } else { imageGeometry3D->WorldToIndex( point3D, point3D ); // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } } polyline->SetPoints( points ); points->Delete(); vtkIdType *ptIds = new vtkIdType[numberOfPoints]; for ( vtkIdType i = 0; i < numberOfPoints; ++i ) ptIds[i] = i; polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInputData( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< itkUCharImageType > ImageImportType; typedef itk::VTKImageExport< itkUCharImageType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); typename ImageType::SizeType lowersize = {{itk::NumericTraits::max(),itk::NumericTraits::max(),itk::NumericTraits::max()}}; typename ImageType::SizeType uppersize = {{0,0,0}}; while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) itimage.Set(0); else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size); // crop internal mask typedef itk::RegionOfInterestImageFilter< itkUCharImageType, itkUCharImageType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(cropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer()); tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer()); Image::Pointer tmpImage2 = Image::New(); tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer()); const BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 ); typedef itk::ImageRegionIteratorWithIndex IteratorType; IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion()); imageIterator.GoToBegin(); while ( !imageIterator.IsAtEnd() ) { unsigned char val = imageIterator.Value(); if (val>0) { itk::Index<3> index = imageIterator.GetIndex(); Point3D point; point[0] = index[0]; point[1] = index[1]; point[2] = index[2]; intImageGeometry3D->IndexToWorld(point, point); pfImageGeometry3D->WorldToIndex(point, point); point[i0] += 0.5; point[i1] += 0.5; index[0] = point[0]; index[1] = point[1]; index[2] = point[2]; if (pfImageGeometry3D->IsIndexInside(index)) m_PlanarFigureImage->SetPixel(index, 1); } ++imageIterator; } // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void QmitkFiberProcessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberProcessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkFiberProcessingView::UpdateGui() { m_Controls->m_FibLabel->setText("mandatory"); m_Controls->m_PfLabel->setText("needed for extraction"); m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_RemoveButton->setEnabled(false); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(false); m_Controls->m_GenerateRoiImage->setEnabled(false); m_Controls->m_ExtractFibersButton->setEnabled(false); m_Controls->m_ModifyButton->setEnabled(false); m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); // disable alle frames m_Controls->m_BundleWeightFrame->setVisible(false); m_Controls->m_ExtractionBoxMask->setVisible(false); m_Controls->m_ExtactionFramePF->setVisible(false); m_Controls->m_RemoveDirectionFrame->setVisible(false); m_Controls->m_RemoveLengthFrame->setVisible(false); m_Controls->m_RemoveCurvatureFrame->setVisible(false); m_Controls->m_SmoothFibersFrame->setVisible(false); m_Controls->m_CompressFibersFrame->setVisible(false); m_Controls->m_ColorFibersFrame->setVisible(false); m_Controls->m_MirrorFibersFrame->setVisible(false); bool pfSelected = !m_SelectedPF.empty(); bool fibSelected = !m_SelectedFB.empty(); bool multipleFibsSelected = (m_SelectedFB.size()>1); bool maskSelected = m_MaskImageNode.IsNotNull(); bool imageSelected = m_SelectedImage.IsNotNull(); // toggle visibility of elements according to selected method switch ( m_Controls->m_ExtractionMethodBox->currentIndex() ) { case 0: m_Controls->m_ExtactionFramePF->setVisible(true); break; case 1: m_Controls->m_ExtractionBoxMask->setVisible(true); break; } switch ( m_Controls->m_RemovalMethodBox->currentIndex() ) { case 0: m_Controls->m_RemoveDirectionFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 1: m_Controls->m_RemoveLengthFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 2: m_Controls->m_RemoveCurvatureFrame->setVisible(true); if ( fibSelected ) m_Controls->m_RemoveButton->setEnabled(true); break; case 3: break; case 4: break; } switch ( m_Controls->m_ModificationMethodBox->currentIndex() ) { case 0: m_Controls->m_SmoothFibersFrame->setVisible(true); break; case 1: m_Controls->m_CompressFibersFrame->setVisible(true); break; case 2: m_Controls->m_ColorFibersFrame->setVisible(true); break; case 3: m_Controls->m_MirrorFibersFrame->setVisible(true); break; case 4: m_Controls->m_BundleWeightFrame->setVisible(true); } // are fiber bundles selected? if ( fibSelected ) { m_Controls->m_ModifyButton->setEnabled(true); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str())); // one bundle and one planar figure needed to extract fibers if (pfSelected) { m_Controls->m_InputData->setTitle("Input Data"); m_Controls->m_PfLabel->setText(QString(m_SelectedPF.at(0)->GetName().c_str())); m_Controls->m_ExtractFibersButton->setEnabled(true); } // more than two bundles needed to join/subtract if (multipleFibsSelected) { m_Controls->m_FibLabel->setText("multiple bundles selected"); m_Controls->m_JoinBundles->setEnabled(true); m_Controls->m_SubstractBundles->setEnabled(true); } if (maskSelected) { m_Controls->m_RemoveButton->setEnabled(true); m_Controls->m_ExtractFibersButton->setEnabled(true); } } // are planar figures selected? if (pfSelected) { if ( fibSelected || m_SelectedImage.IsNotNull()) m_Controls->m_GenerateRoiImage->setEnabled(true); if (m_SelectedPF.size() > 1) { m_Controls->PFCompoANDButton->setEnabled(true); m_Controls->PFCompoORButton->setEnabled(true); } else m_Controls->PFCompoNOTButton->setEnabled(true); } // is image selected if (imageSelected || maskSelected) { m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); } } void QmitkFiberProcessingView::NodeRemoved(const mitk::DataNode* node) { std::vector nodes; OnSelectionChanged(nodes); } void QmitkFiberProcessingView::NodeAdded(const mitk::DataNode* node) { std::vector nodes; OnSelectionChanged(nodes); } void QmitkFiberProcessingView::OnSelectionChanged( std::vector nodes ) { //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedPF.clear(); m_SelectedSurfaces.clear(); m_SelectedImage = NULL; m_MaskImageNode = NULL; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); else if (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); else if (dynamic_cast(node->GetData())) { m_SelectedImage = dynamic_cast(node->GetData()); bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_MaskImageNode = node; } else if (dynamic_cast(node->GetData())) m_SelectedSurfaces.push_back(dynamic_cast(node->GetData())); } if (m_SelectedFB.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedFB.clear(); m_SelectedFB.push_back(nodes->at(i)); } } } if (m_SelectedPF.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData())) { mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); if (sources->Size()>0) continue; int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { maxLayer = layer; m_SelectedPF.clear(); m_SelectedPF.push_back(nodes->at(i)); } } } UpdateGui(); } void QmitkFiberProcessingView::OnDrawPolygon() { mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); } void QmitkFiberProcessingView::OnDrawCircle() { mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); } void QmitkFiberProcessingView::Activated() { } void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *, mitk::BaseProperty* ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->SetPlaneGeometry( emptygeometry ); //set desired data to DataNode where Planarfigure is stored mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); newNode->SetBoolProperty("planarfigure.3drendering", true); newNode->SetBoolProperty("planarfigure.3drendering.fill", true); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(newNode->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode(newNode); } // figure drawn on the topmost layer / image GetDataStorage()->Add(newNode ); for(unsigned int i = 0; i < m_SelectedPF.size(); i++) m_SelectedPF[i]->SetSelected(false); newNode->SetSelected(true); m_SelectedPF.clear(); m_SelectedPF.push_back(newNode); UpdateGui(); } void QmitkFiberProcessingView::ExtractWithPlanarFigure() { if ( m_SelectedFB.empty() || m_SelectedPF.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); return; } std::vector fiberBundles = m_SelectedFB; mitk::DataNode::Pointer planarFigure = m_SelectedPF.at(0); for (unsigned int i=0; i(fiberBundles.at(i)->GetData()); mitk::FiberBundle::Pointer extFB = fib->ExtractFiberSubset(planarFigure, GetDataStorage()); if (extFB->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } mitk::DataNode::Pointer node; node = mitk::DataNode::New(); node->SetData(extFB); QString name(fiberBundles.at(i)->GetName().c_str()); - name += "_"; - name += planarFigure->GetName().c_str(); + name += "*"; + //name += planarFigure->GetName().c_str(); node->SetName(name.toStdString()); fiberBundles.at(i)->SetVisibility(false); GetDataStorage()->Add(node); } } void QmitkFiberProcessingView::GenerateAndComposite() { mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New(); PFCAnd->setOperationType(mitk::PlanarFigureComposite::AND); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("AND"); newPFCNode->SetData(PFCAnd); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); UpdateGui(); } void QmitkFiberProcessingView::GenerateOrComposite() { mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New(); PFCOr->setOperationType(mitk::PlanarFigureComposite::OR); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("OR"); newPFCNode->SetData(PFCOr); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); UpdateGui(); } void QmitkFiberProcessingView::GenerateNotComposite() { mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New(); PFCNot->setOperationType(mitk::PlanarFigureComposite::NOT); mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName("NOT"); newPFCNode->SetData(PFCNot); AddCompositeToDatastorage(newPFCNode, m_SelectedPF); m_SelectedPF.clear(); m_SelectedPF.push_back(newPFCNode); UpdateGui(); } void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::DataNode::Pointer pfc, std::vector children, mitk::DataNode::Pointer parentNode ) { pfc->SetSelected(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(pfc, parentNode); else GetDataStorage()->Add(pfc); for (int i=0; i(children.at(i)->GetData())) { mitk::DataNode::Pointer newChild; newChild = mitk::DataNode::New(); newChild->SetData(dynamic_cast(children.at(i)->GetData())); newChild->SetName( children.at(i)->GetName() ); GetDataStorage()->Add(newChild, pfc); GetDataStorage()->Remove(children.at(i)); } else if (dynamic_cast(children.at(i)->GetData())) { mitk::DataNode::Pointer newChild; newChild = mitk::DataNode::New(); newChild->SetData(dynamic_cast(children.at(i)->GetData())); newChild->SetName( children.at(i)->GetName() ); std::vector< mitk::DataNode::Pointer > grandChildVector; mitk::DataStorage::SetOfObjects::ConstPointer grandchildren = GetDataStorage()->GetDerivations(children.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = grandchildren->begin(); it != grandchildren->end(); ++it ) grandChildVector.push_back(*it); AddCompositeToDatastorage(newChild, grandChildVector, pfc); GetDataStorage()->Remove(children.at(i)); } } } void QmitkFiberProcessingView::JoinBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iAddBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); name += "+"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::SubstractBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundle::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iSubtractBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); if (newBundle.IsNull()) break; name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } if (newBundle.IsNull()) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!"); return; } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::ResampleSelectedBundles() { double factor = this->m_Controls->m_SmoothFibersBox->value(); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); fib->ResampleSpline(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::CompressSelectedBundles() { double factor = this->m_Controls->m_ErrorThresholdBox->value(); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); fib->Compress(factor); } RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberProcessingView::DoImageColorCoding() { if (m_Controls->m_ColorMapBox->GetSelectedNode().IsNull()) { QMessageBox::information(NULL, "Bundle coloring aborted:", "No image providing the scalar values for coloring the selected bundle available."); return; } for(unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); fib->ColorFibersByScalarMap(dynamic_cast(m_Controls->m_ColorMapBox->GetSelectedNode()->GetData()), m_Controls->m_FiberOpacityBox->isChecked()); } if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkFiberProcessingView::DoCurvatureColorCoding() { for(unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); fib->ColorFibersByCurvature(); } if(m_MultiWidget) m_MultiWidget->RequestUpdate(); } void QmitkFiberProcessingView::MirrorFibers() { unsigned int axis = this->m_Controls->m_MirrorFibersBox->currentIndex(); for (int i=0; i(m_SelectedFB.at(i)->GetData()); + if (m_SelectedImage.IsNotNull()) + fib->SetReferenceGeometry(m_SelectedImage->GetGeometry()); fib->MirrorFibers(axis); } if (m_SelectedSurfaces.size()>0) { for (int i=0; i poly = surf->GetVtkPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); for (int i=0; iGetNumberOfPoints(); i++) { double* point = poly->GetPoint(i); point[axis] *= -1; vtkNewPoints->InsertNextPoint(point); } poly->SetPoints(vtkNewPoints); surf->CalculateBoundingBox(); } } RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui index df61dedca9..f26e24c7fa 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingViewControls.ui @@ -1,1325 +1,1325 @@ QmitkFiberProcessingViewControls 0 0 386 540 Form 0 0 0 355 308 Fiber Extraction Extract a fiber subset from the selected fiber bundle using manually placed planar figures as waypoints or binary regions of interest. false 0 0 200 16777215 11 Extract fibers passing through selected ROI or composite ROI. Select ROI and fiber bundle to execute. Extract Qt::Vertical 20 40 0 0 Ending in mask Not ending in mask Passing mask Not passing mask QFrame::NoFrame QFrame::Raised 9 9 9 9 0 false 0 0 16777215 16777215 11 Generate a binary image containing all selected ROIs. Select at least one ROI (planar figure) and a reference fiber bundle or image. Generate ROI Image 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 false 60 16777215 Create OR composition with selected ROIs. OR Qt::Horizontal 40 20 false 60 16777215 Create NOT composition from selected ROI. NOT false 60 16777215 Create AND composition with selected ROIs. AND 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 30 30 Draw circular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true Qt::Horizontal 40 20 30 30 Draw polygonal ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true 0 0 Extract using planar figures Extract using binary ROI image 0 0 306 410 Fiber Removal Remove fibers that satisfy certain criteria from the selected bundle. 0 0 Remove fibers in direction Remove fibers by length Remove fibers by curvature Remove fiber parts outside mask Remove fiber parts inside mask QFrame::NoFrame QFrame::Raised 0 0 0 0 Qt::Horizontal 40 20 Minimum fiber length in mm 0 999999999 20 Max. Length: Min. Length: Maximum fiber length in mm 0 999999999 300 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 X: Y: Z: Angle: Angular deviation threshold in degree 1 90.000000000000000 1.000000000000000 5.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 If unchecked, the fiber exceeding the threshold will be split in two instead of removed. Remove Fiber false QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Max. Angular Deviation: Qt::Horizontal 40 20 Maximum angular deviation in degree 180.000000000000000 0.100000000000000 30.000000000000000 Distance: Distance in mm 1 999.000000000000000 1.000000000000000 5.000000000000000 false 0 0 200 16777215 11 Remove Qt::Vertical 20 40 0 0 355 382 Bundle Modification Modify the selected bundle with operations such as fiber resampling, FA coloring, etc. QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Error threshold in mm: 999999999.000000000000000 0.100000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 - Axial + Sagittal - Sagittal + Coronal - Coronal + Axial Select direction: QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Scalar map: If checked, the image values are not only used to color the fibers but are also used as opaxity values. Values as opacity true 0 0 Smooth fibers Compress fibers Color fibers by scalar map (e.g. FA) Mirror fibers Weight Bundle Color fibers by curvature QFrame::NoFrame QFrame::Raised 0 0 0 0 0 0.010000000000000 999999999.000000000000000 1.000000000000000 Point distance in mm: Qt::Vertical 20 40 false 0 0 200 16777215 11 Execute QFrame::NoFrame QFrame::Raised 0 0 0 0 0 Weight: 7 - 1.000000000000000 + 999999999.000000000000000 0.100000000000000 1.000000000000000 0 0 360 61 Binary Bundle Operations Join or subtract bundles. false 0 0 200 16777215 11 Returns all fibers contained in bundle X that are not contained in bundle Y (not commutative!). Select at least two fiber bundles to execute. Substract false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Join Qt::Vertical 20 40 Please Select Input Data <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true <html><head/><body><p><span style=" color:#969696;">needed for extraction</span></p></body></html> true Input DTI Fiber Bundle: Binary seed ROI. If not specified, the whole image area is seeded. ROI: Qt::Vertical 20 40 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index 547db4afeb..aab7594158 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,2695 +1,2698 @@ /*=================================================================== 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. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkFiberfoxView.h" // MITK #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 "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ switch (m_FilterType) { case 0: m_View->m_TractsToDwiFilter->Update(); break; case 1: m_View->m_ArtifactsToDwiFilter->Update(); break; } } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) - , m_SelectedImage( NULL ) + , m_SelectedImageNode( NULL ) , m_Worker(this) , m_ThreadIsRunning(false) { m_Worker.moveToThread(&m_Thread); connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run())); connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_SimulationTimer = new QTimer(this); } void QmitkFiberfoxView::KillThread() { MITK_INFO << "Aborting DWI simulation."; switch (m_Worker.m_FilterType) { case 0: m_TractsToDwiFilter->SetAbortGenerateData(true); break; case 1: m_ArtifactsToDwiFilter->SetAbortGenerateData(true); break; } m_Controls->m_AbortSimulationButton->setEnabled(false); m_Controls->m_AbortSimulationButton->setText("Aborting simulation ..."); } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); m_Controls->m_AbortSimulationButton->setVisible(true); m_Controls->m_GenerateImageButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(true); m_ThreadIsRunning = true; } void QmitkFiberfoxView::AfterThread() { UpdateSimulationStatus(); m_SimulationTimer->stop(); m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_AbortSimulationButton->setEnabled(true); m_Controls->m_AbortSimulationButton->setText("Abort simulation"); m_Controls->m_GenerateImageButton->setVisible(true); m_ThreadIsRunning = false; QString statusText; FiberfoxParameters parameters; mitk::Image::Pointer mitkImage = mitk::Image::New(); switch (m_Worker.m_FilterType) { case 0: { statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_TractsToDwiFilter->GetParameters(); mitkImage = mitk::GrabItkImageMemory( m_TractsToDwiFilter->GetOutput() ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( parameters.m_SignalGen.GetGradientDirections() )); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( parameters.m_SignalGen.m_Bvalue )); mitk::DiffusionPropertyHelper propertyHelper( mitkImage ); propertyHelper.InitializeImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() +"_b"+QString::number(parameters.m_SignalGen.m_Bvalue).toStdString() +"_"+parameters.m_Misc.m_SignalModelString +parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); parameters.m_Misc.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions(); for (unsigned int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(parameters.m_Misc.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, parameters.m_Misc.m_ParentNode); } } m_TractsToDwiFilter = NULL; break; } case 1: { statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); if (m_ArtifactsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_ArtifactsToDwiFilter->GetParameters().CopyParameters(); mitk::Image::Pointer diffImg = dynamic_cast(parameters.m_Misc.m_ParentNode->GetData()); mitkImage = mitk::GrabItkImageMemory( m_ArtifactsToDwiFilter->GetOutput() ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); mitkImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); mitk::DiffusionPropertyHelper propertyHelper( mitkImage ); propertyHelper.InitializeImage(); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName()+parameters.m_Misc.m_ArtifactModelString); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); m_ArtifactsToDwiFilter = NULL; break; } } mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (!parameters.m_Misc.m_OutputPath.empty()) { try{ QString outputFileName(parameters.m_Misc.m_OutputPath.c_str()); outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str(); outputFileName.replace(QString("."), QString("_")); outputFileName += ".dwi"; QString status("Saving output image to "); status += outputFileName; m_Controls->m_SimulationStatusText->append(status); mitk::IOUtil::SaveBaseData(mitkImage, outputFileName.toStdString()); m_Controls->m_SimulationStatusText->append("File saved successfully."); } catch (itk::ExceptionObject &e) { QString status("Exception during DWI writing: "); status += e.GetDescription(); m_Controls->m_SimulationStatusText->append(status); } catch (...) { m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!"); } } parameters.m_SignalGen.m_FrequencyMap = NULL; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText; switch (m_Worker.m_FilterType) { case 0: statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); break; case 1: statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); break; } if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); statusText = "
"+statusText+"
"; m_Controls->m_SimulationStatusText->setText(statusText); QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar(); vScrollBar->triggerAction(QScrollBar::SliderToMaximum); } } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { delete m_SimulationTimer; } void QmitkFiberfoxView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); // commented out m_Controls->m_DiffusionDirectionBox->setVisible(false); m_Controls->label_3->setVisible(false); m_Controls->m_SeparationAngleBox->setVisible(false); m_Controls->label_4->setVisible(false); // m_Controls->m_StickWidget1->setVisible(true); m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_BallWidget1->setVisible(true); m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); m_Controls->m_PrototypeWidget2->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_PrototypeWidget3->SetMinFa(0.0); m_Controls->m_PrototypeWidget3->SetMaxFa(0.15); m_Controls->m_PrototypeWidget4->SetMinFa(0.0); m_Controls->m_PrototypeWidget4->SetMaxFa(0.15); m_Controls->m_PrototypeWidget3->SetMinAdc(0.0); m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001); m_Controls->m_PrototypeWidget4->SetMinAdc(0.003); m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004); + m_Controls->m_Comp2FractionFrame->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_SpikeFrame->setVisible(false); m_Controls->m_AliasingFrame->setVisible(false); m_Controls->m_MotionArtifactFrame->setVisible(false); m_ParameterFile = QDir::currentPath()+"/param.ffp"; m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(false); m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage()); + m_Controls->m_Comp1VolumeFraction->SetDataStorage(this->GetDataStorage()); + m_Controls->m_Comp2VolumeFraction->SetDataStorage(this->GetDataStorage()); + m_Controls->m_Comp3VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TemplateComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_FiberBundleComboBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isFiberBundle = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New( ); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer isNonDiffMitkImage = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isBinaryMitkImage = mitk::NodePredicateAnd::New( isNonDiffMitkImage, isBinaryPredicate ); m_Controls->m_FrequencyMapBox->SetPredicate(isNonDiffMitkImage); + m_Controls->m_Comp1VolumeFraction->SetPredicate(isNonDiffMitkImage); + m_Controls->m_Comp1VolumeFraction->SetZeroEntryText("--"); + m_Controls->m_Comp2VolumeFraction->SetPredicate(isNonDiffMitkImage); + m_Controls->m_Comp2VolumeFraction->SetZeroEntryText("--"); + m_Controls->m_Comp3VolumeFraction->SetPredicate(isNonDiffMitkImage); + m_Controls->m_Comp3VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp4VolumeFraction->SetPredicate(isNonDiffMitkImage); + m_Controls->m_Comp4VolumeFraction->SetZeroEntryText("--"); m_Controls->m_MaskComboBox->SetPredicate(isBinaryMitkImage); m_Controls->m_MaskComboBox->SetZeroEntryText("--"); m_Controls->m_TemplateComboBox->SetPredicate(isMitkImage); m_Controls->m_TemplateComboBox->SetZeroEntryText("--"); m_Controls->m_FiberBundleComboBox->SetPredicate(isFiberBundle); m_Controls->m_FiberBundleComboBox->SetZeroEntryText("--"); -// mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); + // mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) ); connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int))); connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int))); connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int))); connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int))); connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int))); connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int))); connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath())); connect((QObject*) m_Controls->m_MaskComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnMaskSelected(int))); connect((QObject*) m_Controls->m_TemplateComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnTemplateSelected(int))); connect((QObject*) m_Controls->m_FiberBundleComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnFibSelected(int))); } } void QmitkFiberfoxView::OnMaskSelected(int value) { UpdateGui(); } void QmitkFiberfoxView::OnTemplateSelected(int value) { UpdateGui(); } void QmitkFiberfoxView::OnFibSelected(int value) { UpdateGui(); } template< class ScalarType > FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters() { FiberfoxParameters< ScalarType > parameters; parameters.m_Misc.m_OutputPath = ""; parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); if (outputPath.compare("-")!=0) { parameters.m_Misc.m_OutputPath = outputPath; parameters.m_Misc.m_OutputPath += "/"; } if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mitkMaskImage = dynamic_cast(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData()); mitk::CastToItkImage(mitkMaskImage, parameters.m_SignalGen.m_MaskImage); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(parameters.m_SignalGen.m_MaskImage); duplicator->Update(); parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); } - if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) // use parameters of selected DWI + if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) // use parameters of selected DWI { mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); parameters.m_SignalGen.m_Bvalue = static_cast(dwi->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); parameters.m_SignalGen.SetGradienDirections(static_cast( dwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()); } else if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); CastToItkImage< itk::Image< float, 3 > >(img, itkImg); parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); } + else if (parameters.m_SignalGen.m_MaskImage.IsNotNull()) // use geometry of mask image + { + ItkUcharImgType::Pointer itkImg = parameters.m_SignalGen.m_MaskImage; + parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); + parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); + parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); + parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); + parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); + parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); + } else // use GUI parameters { parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); parameters.m_SignalGen.m_ImageOrigin[0] = parameters.m_SignalGen.m_ImageSpacing[0]/2; parameters.m_SignalGen.m_ImageOrigin[1] = parameters.m_SignalGen.m_ImageSpacing[1]/2; parameters.m_SignalGen.m_ImageOrigin[2] = parameters.m_SignalGen.m_ImageSpacing[2]/2; parameters.m_SignalGen.m_ImageDirection.SetIdentity(); parameters.m_SignalGen.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); parameters.m_SignalGen.m_Bvalue = m_Controls->m_BvalueBox->value(); parameters.m_SignalGen.GenerateGradientHalfShell(); } // signal relaxation parameters.m_SignalGen.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); parameters.m_SignalGen.m_SimulateKspaceAcquisition = parameters.m_SignalGen.m_DoSimulateRelaxation; if (parameters.m_SignalGen.m_DoSimulateRelaxation && m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() ) parameters.m_Misc.m_ArtifactModelString += "_RELAX"; // N/2 ghosts parameters.m_Misc.m_CheckAddGhostsBox = m_Controls->m_AddGhosts->isChecked(); if (m_Controls->m_AddGhosts->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_GHOST"; parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_SignalGen.m_KspaceLineOffset)); } else parameters.m_SignalGen.m_KspaceLineOffset = 0; // Aliasing parameters.m_Misc.m_CheckAddAliasingBox = m_Controls->m_AddAliasing->isChecked(); if (m_Controls->m_AddAliasing->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Spikes parameters.m_Misc.m_CheckAddSpikesBox = m_Controls->m_AddSpikes->isChecked(); if (m_Controls->m_AddSpikes->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_SignalGen.m_Spikes)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SignalGen.m_SpikeAmplitude)); } // gibbs ringing parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); parameters.m_Misc.m_ArtifactModelString += "_RINGING"; } // add distortions parameters.m_Misc.m_CheckAddDistortionsBox = m_Controls->m_AddDistortions->isChecked(); if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); mitk::Image* img = dynamic_cast(fMapNode->GetData()); ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); CastToItkImage< ItkDoubleImgType >(img, itkImg); if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) // use geometry of frequency map { parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); } if (parameters.m_SignalGen.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && parameters.m_SignalGen.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && parameters.m_SignalGen.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) { parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImg); duplicator->Update(); parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } } parameters.m_SignalGen.m_EddyStrength = 0; parameters.m_Misc.m_CheckAddEddyCurrentsBox = m_Controls->m_AddEddy->isChecked(); if (m_Controls->m_AddEddy->isChecked()) { parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); parameters.m_Misc.m_ArtifactModelString += "_EDDY"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_SignalGen.m_EddyStrength)); } // Motion parameters.m_SignalGen.m_DoAddMotion = m_Controls->m_AddMotion->isChecked(); parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); if ( m_Controls->m_AddMotion->isChecked() && m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() ) { parameters.m_Misc.m_ArtifactModelString += "_MOTION"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_SignalGen.m_DoRandomizeMotion)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_SignalGen.m_Translation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_SignalGen.m_Translation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_SignalGen.m_Translation[2])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[0])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[1])); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[2])); } // other imaging parameters + parameters.m_SignalGen.m_ReversePhase = m_Controls->m_ReversePhaseBox->isChecked(); parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); + parameters.m_SignalGen.m_tRep = m_Controls->m_TRbox->value(); parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); // adjust echo time if needed if ( parameters.m_SignalGen.m_tEcho < parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ) { this->m_Controls->m_TEbox->setValue( parameters.m_SignalGen.m_ImageRegion.GetSize(1)*parameters.m_SignalGen.m_tLine ); parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(parameters.m_SignalGen.m_tEcho)+" ms"); } // Noise parameters.m_Misc.m_CheckAddNoiseBox = m_Controls->m_AddNoise->isChecked(); if (m_Controls->m_AddNoise->isChecked()) { double noiseVariance = m_Controls->m_NoiseLevel->value(); { switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); break; } case 1: { parameters.m_NoiseModel = new mitk::ChiSquareNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); break; } default: { parameters.m_NoiseModel = new mitk::RicianNoiseModel(); parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); } } } parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); parameters.m_Misc.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); } // adjusting line readout time to the adapted image size needed for the DFT unsigned int y = parameters.m_SignalGen.m_ImageRegion.GetSize(1); y += y%2; if ( y>parameters.m_SignalGen.m_ImageRegion.GetSize(1) ) parameters.m_SignalGen.m_tLine *= (double)parameters.m_SignalGen.m_ImageRegion.GetSize(1)/y; // signal models { // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget1->GetD()); model->SetT2(m_Controls->m_StickWidget1->GetT2()); + model->SetT1(m_Controls->m_StickWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); + model->SetT1(m_Controls->m_ZeppelinWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); model->SetT2(m_Controls->m_TensorWidget1->GetT2()); + model->SetT1(m_Controls->m_TensorWidget1->GetT1()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc()); model->m_CompartmentId = 1; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); break; } } + if (m_Controls->m_Comp1VolumeFraction->GetSelectedNode().IsNotNull()) + { + mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp1VolumeFraction->GetSelectedNode(); + ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); + mitk::Image* img = dynamic_cast(volumeNode->GetData()); + CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); + parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); + } // compartment 2 switch (m_Controls->m_Compartment2Box->currentIndex()) { case 0: break; case 1: { mitk::StickModel* model = new mitk::StickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_StickWidget2->GetD()); model->SetT2(m_Controls->m_StickWidget2->GetT2()); + model->SetT1(m_Controls->m_StickWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Stick"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); + model->SetT1(m_Controls->m_ZeppelinWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Zeppelin"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::TensorModel* model = new mitk::TensorModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); model->SetT2(m_Controls->m_TensorWidget2->GetT2()); + model->SetT1(m_Controls->m_TensorWidget2->GetT1()); model->m_CompartmentId = 2; parameters.m_FiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Tensor"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } } + if (m_Controls->m_Comp2VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_FiberModelList.size()==2) + { + mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp2VolumeFraction->GetSelectedNode(); + ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); + mitk::Image* img = dynamic_cast(volumeNode->GetData()); + CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); + parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); + } // compartment 3 switch (m_Controls->m_Compartment3Box->currentIndex()) { case 0: { mitk::BallModel* model = new mitk::BallModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_BallWidget1->GetD()); model->SetT2(m_Controls->m_BallWidget1->GetT2()); + model->SetT1(m_Controls->m_BallWidget1->GetT1()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Ball"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetBvalue(parameters.m_SignalGen.m_Bvalue); model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); + model->SetT1(m_Controls->m_AstrosticksWidget1->GetT1()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Astrosticks"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; } case 2: { mitk::DotModel* model = new mitk::DotModel(); model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget1->GetT2()); + model->SetT1(m_Controls->m_DotWidget1->GetT1()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Dot"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); parameters.m_SignalGen.m_DoSimulateRelaxation = false; model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc()); model->m_CompartmentId = 3; parameters.m_NonFiberModelList.push_back(model); parameters.m_Misc.m_SignalModelString += "Prototype"; parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); break; } } - - // compartment 4 - ItkDoubleImgType::Pointer comp4VolumeImage = NULL; - ItkDoubleImgType::Pointer comp3VolumeImage = NULL; - if (m_Controls->m_Compartment4Box->currentIndex()>0) + if (m_Controls->m_Comp3VolumeFraction->GetSelectedNode().IsNotNull()) { - mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); - if (volumeNode.IsNull()) - { - QMessageBox::information( NULL, "Information", "No volume fraction image selected! Second extra-axonal compartment has been disabled for this simultation."); - MITK_WARN << "No volume fraction image selected! Second extra-axonal compartment has been disabled."; - } - else - { - MITK_INFO << "Rescaling volume fraction image..."; - comp4VolumeImage = ItkDoubleImgType::New(); - mitk::Image* img = dynamic_cast(volumeNode->GetData()); - CastToItkImage< ItkDoubleImgType >(img, comp4VolumeImage); - - double max = itk::NumericTraits::min(); - double min = itk::NumericTraits::max(); - - itk::ImageRegionIterator< ItkDoubleImgType > it(comp4VolumeImage, comp4VolumeImage->GetLargestPossibleRegion()); - while(!it.IsAtEnd()) - { - if (parameters.m_SignalGen.m_MaskImage.IsNotNull() && parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0) - { - it.Set(0.0); - ++it; - continue; - } - if (it.Get()>900) - it.Set(900); - - if (it.Get()>max) - max = it.Get(); - if (it.Get()::Pointer scaler = itk::ShiftScaleImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); - scaler->SetInput(comp4VolumeImage); - scaler->SetShift(-min); - scaler->SetScale(1.0/(max-min)); - scaler->Update(); - comp4VolumeImage = scaler->GetOutput(); - -// itk::ImageFileWriter< ItkDoubleImgType >::Pointer wr = itk::ImageFileWriter< ItkDoubleImgType >::New(); -// wr->SetInput(comp4VolumeImage); -// wr->SetFileName("/local/comp4.nrrd"); -// wr->Update(); - - // if (max>1 || min<0) // are volume fractions between 0 and 1? - // { - // itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); - // rescaler->SetInput(0, comp4VolumeImage); - // rescaler->SetOutputMaximum(1); - // rescaler->SetOutputMinimum(0); - // rescaler->Update(); - // comp4VolumeImage = rescaler->GetOutput(); - // } - - itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New(); - inverter->SetMaximum(1.0); - inverter->SetInput(comp4VolumeImage); - inverter->Update(); - comp3VolumeImage = inverter->GetOutput(); - } + mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp3VolumeFraction->GetSelectedNode(); + ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); + mitk::Image* img = dynamic_cast(volumeNode->GetData()); + CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); + parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } - if (comp4VolumeImage.IsNotNull()) + switch (m_Controls->m_Compartment4Box->currentIndex()) { - switch (m_Controls->m_Compartment4Box->currentIndex()) - { - case 0: - break; - case 1: - { - mitk::BallModel* model = new mitk::BallModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.m_Bvalue); - model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); - model->SetT2(m_Controls->m_BallWidget2->GetT2()); - model->SetVolumeFractionImage(comp4VolumeImage); - model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Ball"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); - break; - } - case 2: - { - mitk::AstroStickModel* model = new mitk::AstroStickModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.m_Bvalue); - model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); - model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); - model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); - model->SetVolumeFractionImage(comp4VolumeImage); - model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Astrosticks"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); - break; - } - case 3: - { - mitk::DotModel* model = new mitk::DotModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetT2(m_Controls->m_DotWidget2->GetT2()); - model->SetVolumeFractionImage(comp4VolumeImage); - model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Dot"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); - break; - } - case 4: - { - mitk::RawShModel* model = new mitk::RawShModel(); - parameters.m_SignalGen.m_DoSimulateRelaxation = false; - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); - model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); - model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); - model->SetVolumeFractionImage(comp4VolumeImage); - model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp3VolumeImage); - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Prototype"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); - break; - } - } + case 0: + break; + case 1: + { + mitk::BallModel* model = new mitk::BallModel(); + model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(parameters.m_SignalGen.m_Bvalue); + model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); + model->SetT2(m_Controls->m_BallWidget2->GetT2()); + model->SetT1(m_Controls->m_BallWidget2->GetT1()); + model->m_CompartmentId = 4; + parameters.m_NonFiberModelList.push_back(model); + parameters.m_Misc.m_SignalModelString += "Ball"; + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + break; + } + case 2: + { + mitk::AstroStickModel* model = new mitk::AstroStickModel(); + model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(parameters.m_SignalGen.m_Bvalue); + model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); + model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); + model->SetT1(m_Controls->m_AstrosticksWidget2->GetT1()); + model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); + model->m_CompartmentId = 4; + parameters.m_NonFiberModelList.push_back(model); + parameters.m_Misc.m_SignalModelString += "Astrosticks"; + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); + break; + } + case 3: + { + mitk::DotModel* model = new mitk::DotModel(); + model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetT2(m_Controls->m_DotWidget2->GetT2()); + model->SetT1(m_Controls->m_DotWidget2->GetT1()); + model->m_CompartmentId = 4; + parameters.m_NonFiberModelList.push_back(model); + parameters.m_Misc.m_SignalModelString += "Dot"; + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + break; + } + case 4: + { + mitk::RawShModel* model = new mitk::RawShModel(); + parameters.m_SignalGen.m_DoSimulateRelaxation = false; + model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); + model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); + model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); + model->m_CompartmentId = 4; + parameters.m_NonFiberModelList.push_back(model); + parameters.m_Misc.m_SignalModelString += "Prototype"; + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); + break; + } + } + if (m_Controls->m_Comp4VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_NonFiberModelList.size()==2) + { + mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); + ItkDoubleImgType::Pointer compVolumeImage = ItkDoubleImgType::New(); + mitk::Image* img = dynamic_cast(volumeNode->GetData()); + CastToItkImage< ItkDoubleImgType >(img, compVolumeImage); + parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(compVolumeImage); } } - parameters.m_SignalGen.m_FiberSeparationThreshold = m_Controls->m_SeparationAngleBox->value(); - switch (m_Controls->m_DiffusionDirectionBox->currentIndex()) - { - case 0: - parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; - break; - case 1: - parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::MAIN_FIBER_DIRECTIONS; - break; - case 2: - parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::RANDOM_DIRECTIONS; - parameters.m_SignalGen.m_DoAddMotion = false; - parameters.m_SignalGen.m_DoAddGibbsRinging = false; - parameters.m_SignalGen.m_KspaceLineOffset = 0.0; - parameters.m_SignalGen.m_FrequencyMap = NULL; - parameters.m_SignalGen.m_CroppingFactor = 1.0; - parameters.m_SignalGen.m_EddyStrength = 0; - break; - default: - parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; - } + // check if comp 3 or 4 volume fraction image is set + if (parameters.m_NonFiberModelList.size()==2 && (parameters.m_NonFiberModelList[0]->GetVolumeFractionImage()==nullptr || parameters.m_NonFiberModelList[1]->GetVolumeFractionImage()==nullptr)) + { + m_Controls->m_Compartment4Box->setCurrentIndex(0); + parameters.m_NonFiberModelList.pop_back(); + QMessageBox::information(NULL, "Compartment 4 disabled", "More than one non-fiber compartment selected but no volume fraction maps set!"); + } + +// RELICT +// parameters.m_SignalGen.m_FiberSeparationThreshold = m_Controls->m_SeparationAngleBox->value(); +// switch (m_Controls->m_DiffusionDirectionBox->currentIndex()) +// { +// case 0: +// parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; +// break; +// case 1: +// parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::MAIN_FIBER_DIRECTIONS; +// break; +// case 2: +// parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::RANDOM_DIRECTIONS; +// parameters.m_SignalGen.m_DoAddMotion = false; +// parameters.m_SignalGen.m_DoAddGibbsRinging = false; +// parameters.m_SignalGen.m_KspaceLineOffset = 0.0; +// parameters.m_SignalGen.m_FrequencyMap = NULL; +// parameters.m_SignalGen.m_CroppingFactor = 1.0; +// parameters.m_SignalGen.m_EddyStrength = 0; +// break; +// default: +// parameters.m_SignalGen.m_DiffusionDirectionMode = SignalGenerationParameters::FIBER_TANGENT_DIRECTIONS; +// } parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalGen.m_SignalScale)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_SignalGen.m_AxonRadius)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_SignalGen.m_tInhom)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_SignalGen.m_tLine)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_SignalGen.m_tEcho)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_SignalGen.m_Bvalue)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_SignalGen.m_DoDisablePartialVolume)); parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_SignalGen.m_DoSimulateRelaxation)); parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); return parameters; } void QmitkFiberfoxView::SaveParameters() { FiberfoxParameters<> ffParamaters = UpdateImageParameters(); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); bool ok = true; bool first = true; bool dosampling = false; mitk::Image::Pointer diffImg = NULL; itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(ffParamaters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(ffParamaters.m_NonFiberModelList.at(i-ffParamaters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { if (QMessageBox::question(NULL, "Prototype signal sampling", "Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?",QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes) dosampling = true; first = false; if (dosampling && (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData())))) { QMessageBox::information(NULL, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from."); return; } else if (dosampling) { - diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); - - typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; - TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(diffImg, itkVectorImagePointer); - filter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); - filter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - - filter->Update(); - tensorImage = filter->GetOutput(); - - const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; - QballFilterType::Pointer qballfilter = QballFilterType::New(); - qballfilter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); - qballfilter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - qballfilter->SetLambda(0.006); - qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); - qballfilter->Update(); - itkFeatureImage = qballfilter->GetCoefficientImage(); - - itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); - adcFilter->SetInput( itkVectorImagePointer ); - adcFilter->SetGradientDirections( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - adcFilter->SetB_value( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - adcFilter->Update(); - adcImage = adcFilter->GetOutput(); + diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); + + typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; + TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); + ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); + mitk::CastToItkImage(diffImg, itkVectorImagePointer); + filter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); + filter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + + filter->Update(); + tensorImage = filter->GetOutput(); + + const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; + QballFilterType::Pointer qballfilter = QballFilterType::New(); + qballfilter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); + qballfilter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + qballfilter->SetLambda(0.006); + qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); + qballfilter->Update(); + itkFeatureImage = qballfilter->GetCoefficientImage(); + + itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); + adcFilter->SetInput( itkVectorImagePointer ); + adcFilter->SetGradientDirections( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + adcFilter->SetB_value( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + adcFilter->Update(); + adcImage = adcFilter->GetOutput(); } } if (dosampling && diffImg.IsNotNull()) { ok = model->SampleKernels(diffImg, ffParamaters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) { QMessageBox::information( NULL, "Parameter file not saved", "No valid prototype signals could be sampled."); return; } } } } ffParamaters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberfoxView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; FiberfoxParameters<> parameters; parameters.LoadParameters(filename.toStdString()); m_Controls->m_RealTimeFibers->setChecked(parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(parameters.m_FiberGen.m_Scale[2]); // image generation parameters m_Controls->m_SizeX->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(0)); m_Controls->m_SizeY->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(1)); m_Controls->m_SizeZ->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(2)); m_Controls->m_SpacingX->setValue(parameters.m_SignalGen.m_ImageSpacing[0]); m_Controls->m_SpacingY->setValue(parameters.m_SignalGen.m_ImageSpacing[1]); m_Controls->m_SpacingZ->setValue(parameters.m_SignalGen.m_ImageSpacing[2]); m_Controls->m_NumGradientsBox->setValue(parameters.m_SignalGen.GetNumWeightedVolumes()); m_Controls->m_BvalueBox->setValue(parameters.m_SignalGen.m_Bvalue); m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); m_Controls->m_TEbox->setValue(parameters.m_SignalGen.m_tEcho); m_Controls->m_LineReadoutTimeBox->setValue(parameters.m_SignalGen.m_tLine); m_Controls->m_T2starBox->setValue(parameters.m_SignalGen.m_tInhom); m_Controls->m_FiberRadius->setValue(parameters.m_SignalGen.m_AxonRadius); m_Controls->m_RelaxationBox->setChecked(parameters.m_SignalGen.m_DoSimulateRelaxation); m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(parameters.m_SignalGen.m_DoDisablePartialVolume); if (parameters.m_NoiseModel!=NULL) { m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_CheckAddNoiseBox); if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(0); else if (dynamic_cast*>(parameters.m_NoiseModel)) m_Controls->m_NoiseDistributionBox->setCurrentIndex(1); m_Controls->m_NoiseLevel->setValue(parameters.m_NoiseModel->GetNoiseVariance()); } else m_Controls->m_AddNoise->setChecked(false); m_Controls->m_VolumeFractionsBox->setChecked(parameters.m_Misc.m_CheckOutputVolumeFractionsBox); m_Controls->m_AdvancedOptionsBox_2->setChecked(parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); m_Controls->m_AddGhosts->setChecked(parameters.m_Misc.m_CheckAddGhostsBox); m_Controls->m_AddAliasing->setChecked(parameters.m_Misc.m_CheckAddAliasingBox); m_Controls->m_AddDistortions->setChecked(parameters.m_Misc.m_CheckAddDistortionsBox); m_Controls->m_AddSpikes->setChecked(parameters.m_Misc.m_CheckAddSpikesBox); m_Controls->m_AddEddy->setChecked(parameters.m_Misc.m_CheckAddEddyCurrentsBox); m_Controls->m_kOffsetBox->setValue(parameters.m_SignalGen.m_KspaceLineOffset); m_Controls->m_WrapBox->setValue(100*(1-parameters.m_SignalGen.m_CroppingFactor)); m_Controls->m_SpikeNumBox->setValue(parameters.m_SignalGen.m_Spikes); m_Controls->m_SpikeScaleBox->setValue(parameters.m_SignalGen.m_SpikeAmplitude); m_Controls->m_EddyGradientStrength->setValue(parameters.m_SignalGen.m_EddyStrength); m_Controls->m_AddGibbsRinging->setChecked(parameters.m_SignalGen.m_DoAddGibbsRinging); m_Controls->m_AddMotion->setChecked(parameters.m_SignalGen.m_DoAddMotion); m_Controls->m_RandomMotion->setChecked(parameters.m_SignalGen.m_DoRandomizeMotion); m_Controls->m_MaxTranslationBoxX->setValue(parameters.m_SignalGen.m_Translation[0]); m_Controls->m_MaxTranslationBoxY->setValue(parameters.m_SignalGen.m_Translation[1]); m_Controls->m_MaxTranslationBoxZ->setValue(parameters.m_SignalGen.m_Translation[2]); m_Controls->m_MaxRotationBoxX->setValue(parameters.m_SignalGen.m_Rotation[0]); m_Controls->m_MaxRotationBoxY->setValue(parameters.m_SignalGen.m_Rotation[1]); m_Controls->m_MaxRotationBoxZ->setValue(parameters.m_SignalGen.m_Rotation[2]); m_Controls->m_DiffusionDirectionBox->setCurrentIndex(parameters.m_SignalGen.m_DiffusionDirectionMode); m_Controls->m_SeparationAngleBox->setValue(parameters.m_SignalGen.m_FiberSeparationThreshold); m_Controls->m_Compartment1Box->setCurrentIndex(0); m_Controls->m_Compartment2Box->setCurrentIndex(0); m_Controls->m_Compartment3Box->setCurrentIndex(0); m_Controls->m_Compartment4Box->setCurrentIndex(0); for (unsigned int i=0; i* signalModel = NULL; if (im_CompartmentId) { case 1: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget1->SetT2(model->GetT2()); m_Controls->m_StickWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment1Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget1->SetT2(model->GetT2()); m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment1Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment1Box->setCurrentIndex(3); break; } break; } case 2: { if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget2->SetT2(model->GetT2()); m_Controls->m_StickWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment2Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget2->SetT2(model->GetT2()); m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment2Box->setCurrentIndex(3); break; } break; } case 3: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget1->SetT2(model->GetT2()); m_Controls->m_BallWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment3Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment3Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget1->SetT2(model->GetT2()); m_Controls->m_Compartment3Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment3Box->setCurrentIndex(3); break; } break; } case 4: { if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget2->SetT2(model->GetT2()); m_Controls->m_BallWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment4Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment4Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget2->SetT2(model->GetT2()); m_Controls->m_Compartment4Box->setCurrentIndex(3); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment4Box->setCurrentIndex(4); break; } break; } } } } void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); m_Controls->m_AdvancedOptionsBox_2->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); m_Controls->m_AdvancedOptionsBox_2->setChecked(false); } } void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index) { m_Controls->m_StickWidget1->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_PrototypeWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_StickWidget1->setVisible(true); break; case 1: m_Controls->m_ZeppelinWidget1->setVisible(true); break; case 2: m_Controls->m_TensorWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index) { m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); + m_Controls->m_Comp2FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); + m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); + m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); + m_Controls->m_Comp2FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index) { m_Controls->m_BallWidget1->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); switch (index) { case 0: m_Controls->m_BallWidget1->setVisible(true); break; case 1: m_Controls->m_AstrosticksWidget1->setVisible(true); break; case 2: m_Controls->m_DotWidget1->setVisible(true); break; case 3: m_Controls->m_PrototypeWidget3->setVisible(true); break; } } void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index) { m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_BallWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 2: m_Controls->m_AstrosticksWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 3: m_Controls->m_DotWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 4: m_Controls->m_PrototypeWidget4->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddMotion(int value) { if (value>0) m_Controls->m_MotionArtifactFrame->setVisible(true); else m_Controls->m_MotionArtifactFrame->setVisible(false); } void QmitkFiberfoxView::OnAddAliasing(int value) { if (value>0) m_Controls->m_AliasingFrame->setVisible(true); else m_Controls->m_AliasingFrame->setVisible(false); } void QmitkFiberfoxView::OnAddSpikes(int value) { if (value>0) m_Controls->m_SpikeFrame->setVisible(true); else m_Controls->m_SpikeFrame->setVisible(false); } void QmitkFiberfoxView::OnAddEddy(int value) { if (value>0) m_Controls->m_EddyFrame->setVisible(true); else m_Controls->m_EddyFrame->setVisible(false); } void QmitkFiberfoxView::OnAddDistortions(int value) { if (value>0) m_Controls->m_DistortionsFrame->setVisible(true); else m_Controls->m_DistortionsFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGhosts(int value) { if (value>0) m_Controls->m_GhostFrame->setVisible(true); else m_Controls->m_GhostFrame->setVisible(false); } void QmitkFiberfoxView::OnAddNoise(int value) { if (value>0) m_Controls->m_NoiseFrame->setVisible(true); else m_Controls->m_NoiseFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; GradientListType pointshell; int numB0 = NPoints/20; if (numB0==0) numB0=1; GradientType g; g.Fill(0.0); for (int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); 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); } return retval; } void QmitkFiberfoxView::OnAddBundle() { - if (m_SelectedImage.IsNull()) + if (m_SelectedImageNode.IsNull()) return; - mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage); + mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); - GetDataStorage()->Add(node, m_SelectedImage); + GetDataStorage()->Add(node, m_SelectedImageNode); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); node->SetBoolProperty("planarfigure.3drendering.fill", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } - FiberfoxParameters parameters = UpdateImageParameters(); + FiberfoxParameters parameters; // = UpdateImageParameters(); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); sort(childVector.begin(), childVector.end(), CompareLayer); vector< mitk::PlanarEllipse::Pointer > fib; vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { parameters.m_FiberGen.m_Fiducials.push_back(fib); parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(parameters.m_FiberGen); filter->Update(); vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { - if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) + if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value(); unsigned int level = window/2; mitk::LevelWindow lw; lw.SetLevelWindow(level, window); node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(node); - m_SelectedImage = node; + m_SelectedImageNode = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); + QMessageBox::information(NULL, "Template image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image. A template image with the specified geometry has been generated that can be used to draw artificial fibers (see tab 'Fiber Definition')."); } else if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull()) SimulateImageFromFibers(m_Controls->m_FiberBundleComboBox->GetSelectedNode()); - else if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() ) + else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode()) ) SimulateForExistingDwi(m_Controls->m_TemplateComboBox->GetSelectedNode()); + else + QMessageBox::information(NULL, "No image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image."); } void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(imageNode->GetData())) ); - if ( !isDiffusionImage ) - { - return; - } + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(imageNode->GetData())) ); + if ( !isDiffusionImage ) + { + return; + } FiberfoxParameters parameters = UpdateImageParameters(); if (parameters.m_NoiseModel==NULL && parameters.m_SignalGen.m_Spikes==0 && parameters.m_SignalGen.m_FrequencyMap.IsNull() && parameters.m_SignalGen.m_KspaceLineOffset<=0.000001 && !parameters.m_SignalGen.m_DoAddGibbsRinging && !(parameters.m_SignalGen.m_EddyStrength>0) && parameters.m_SignalGen.m_CroppingFactor>0.999) { QMessageBox::information( NULL, "Simulation cancelled", "No valid artifact enabled! Motion artifacts and relaxation effects can NOT be added to an existing diffusion weighted image."); return; } mitk::Image::Pointer diffImg = dynamic_cast(imageNode->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); m_ArtifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); m_ArtifactsToDwiFilter->SetInput(itkVectorImagePointer); parameters.m_Misc.m_ParentNode = imageNode; m_ArtifactsToDwiFilter->SetParameters(parameters); m_Worker.m_FilterType = 1; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { mitk::FiberBundle::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) return; FiberfoxParameters parameters = UpdateImageParameters(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); parameters.m_Misc.m_ParentNode = fiberNode; if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) { bool first = true; bool ok = true; mitk::Image::Pointer diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = NULL; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = NULL; ItkDoubleImgType::Pointer adcImage = NULL; for (unsigned int i=0; i* model = NULL; if (i* >(parameters.m_FiberModelList.at(i)); else model = dynamic_cast< mitk::RawShModel<>* >(parameters.m_NonFiberModelList.at(i-parameters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(diffImg, itkVectorImagePointer); + ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); + mitk::CastToItkImage(diffImg, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); filter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); filter->Update(); tensorImage = filter->GetOutput(); const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder; QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(), itkVectorImagePointer ); qballfilter->SetBValue( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( static_cast( diffImg->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); adcFilter->SetB_value( static_cast(diffImg->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } ok = model->SampleKernels(diffImg, parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) break; } } if (!ok) { QMessageBox::information( NULL, "Simulation cancelled", "No valid prototype signals could be sampled."); return; } } else if ( m_Controls->m_Compartment1Box->currentIndex()==3 || m_Controls->m_Compartment3Box->currentIndex()==3 || m_Controls->m_Compartment4Box->currentIndex()==4 ) { QMessageBox::information( NULL, "Simulation cancelled", "Prototype signal but no diffusion-weighted image selected to sample signal from."); return; } m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); m_Worker.m_FilterType = 0; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::ApplyTransform() { vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberFoxView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData())->Clone(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberFoxView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); // Fiber generation gui if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } - if (m_SelectedImage.IsNotNull() || !m_SelectedBundles.empty()) + if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } - if (m_SelectedImage.IsNotNull() && !m_SelectedBundles.empty()) + if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) m_Controls->m_AlignOnGrid->setEnabled(true); if (!m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } // Signal generation gui if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull() || m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()))) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = NULL; m_SelectedBundles.clear(); - m_SelectedImage = NULL; + m_SelectedImageNode = NULL; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData())); -// } + // bool isDiffusionImage(false); + // if ( node.IsNotNull() ) + // { + // isDiffusionImage = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())); + // } -// if ( node.IsNotNull() && isDiffusionImage ) -// { -// m_SelectedDWI = node; -// m_SelectedImage = node; -// m_SelectedImages.push_back(node); -// } + // if ( node.IsNotNull() && isDiffusionImage ) + // { + // m_SelectedDWI = node; + // m_SelectedImage = node; + // m_SelectedImages.push_back(node); + // } if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImages.push_back(node); - m_SelectedImage = node; + m_SelectedImageNode = node; } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundle::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { MITK_DEBUG << "EnableCrosshairNavigation"; // enable the crosshair navigation if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "enabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(true); // linkedRenderWindow->EnableSlicingPlanes(true); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { MITK_DEBUG << "DisableCrosshairNavigation"; // disable the crosshair navigation during the drawing if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "disabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(false); // linkedRenderWindow->EnableSlicingPlanes(false); } } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } void QmitkFiberfoxView::SetOutputPath() { // SELECT FOLDER DIALOG string outputPath = QFileDialog::getExistingDirectory(NULL, "Save images to...", QString(outputPath.c_str())).toStdString(); if (outputPath.empty()) m_Controls->m_SavePathEdit->setText("-"); else { outputPath += "/"; m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str())); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h index 3d261cdab2..75f7990c86 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h @@ -1,218 +1,219 @@ /*=================================================================== 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 "ui_QmitkFiberfoxViewControls.h" #include #include #include #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. \sa QmitkFunctionality \ingroup Functionalities */ // Forward Qt class declarations using namespace std; class QmitkFiberfoxView; class QmitkFiberfoxWorker : public QObject { Q_OBJECT public: QmitkFiberfoxWorker(QmitkFiberfoxView* view); int m_FilterType; public slots: void run(); private: QmitkFiberfoxView* m_View; }; class QmitkFiberfoxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent); void SetFocus(); typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef itk::Vector GradientType; typedef vector GradientListType; - typedef itk::VectorImage< short, 3 > ItkDwiType; + typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image ItkDoubleImgType; + typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; template vector > MakeGradientList(); protected slots: void SetOutputPath(); ///< path where image is automatically saved to after the simulation is finished void LoadParameters(); ///< load fiberfox parameters void SaveParameters(); ///< save fiberfox parameters void BeforeThread(); void AfterThread(); void KillThread(); ///< abort simulation void UpdateSimulationStatus(); ///< print simulation progress and satus messages void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void GenerateImage(); ///< start image simulation void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void Comp1ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 1 void Comp2ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 2 void Comp3ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 3 void Comp4ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 4 void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(double value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); void OnConstantRadius(int value); /** update GUI elements */ void OnAddNoise(int value); void OnAddGhosts(int value); void OnAddDistortions(int value); void OnAddEddy(int value); void OnAddSpikes(int value); void OnAddAliasing(int value); void OnAddMotion(int value); void OnMaskSelected(int value); void OnFibSelected(int value); void OnTemplateSelected(int value); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList&); GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image template< class ScalarType > FiberfoxParameters< ScalarType > UpdateImageParameters(); ///< update fiberfox paramater object (template parameter defines noise model type) void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ); ///< add observers void NodeRemoved(const mitk::DataNode* node); ///< remove observers /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse - mitk::DataNode::Pointer m_SelectedImage; + mitk::DataNode::Pointer m_SelectedImageNode; vector< mitk::DataNode::Pointer > m_SelectedBundles; vector< mitk::DataNode::Pointer > m_SelectedBundles2; vector< mitk::DataNode::Pointer > m_SelectedFiducials; vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name // GUI thread QmitkFiberfoxWorker m_Worker; ///< runs filter QThread m_Thread; ///< worker thread bool m_ThreadIsRunning; QTimer* m_SimulationTimer; QTime m_SimulationTime; QString m_SimulationStatusText; /** Image filters that do all the simulations. */ itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; itk::AddArtifactsToDwiImageFilter< short >::Pointer m_ArtifactsToDwiFilter; friend class QmitkFiberfoxWorker; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui index 160817ca4d..6afa25f654 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,3108 +1,3254 @@ QmitkFiberfoxViewControls 0 0 - 479 - 2397 + 524 + 2652 Form Load Parameters :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico - 0 + 1 Fiber Definition Qt::Vertical 20 40 color: rgb(255, 0, 0); Please select an image or an existing fiber bundle to draw the fiber fiducials. If you can't provide a suitable image, generate one using the "Signal Generation" tab. Qt::AutoText Qt::AlignJustify|Qt::AlignVCenter true Fiducial Options All fiducials are treated as circles with the same radius as the first fiducial. Use Constant Fiducial Radius false false Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. Align With Grid :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico Operations false Join Bundles :/QmitkDiffusionImaging/general_icons/plus.ico:/QmitkDiffusionImaging/general_icons/plus.ico QFrame::NoFrame QFrame::Raised 0 0 0 0 Y false Rotation angle (in degree) around x-axis. + + 3 + -360.000000000000000 360.000000000000000 0.100000000000000 Axis: false Rotation angle (in degree) around y-axis. + + 3 + -360.000000000000000 360.000000000000000 0.100000000000000 Translation: false Translation (in mm) in direction of the z-axis. + + 3 + -1000.000000000000000 1000.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. + + 3 + -1000.000000000000000 1000.000000000000000 0.100000000000000 X false Rotation: false Z false Rotation angle (in degree) around z-axis. + + 3 + -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. + + 3 + -1000.000000000000000 1000.000000000000000 0.100000000000000 Scaling: false Scaling factor for selected fiber bundle along the x-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the y-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the z-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 false Copy Bundles :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico false Transform Selection :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Fiber Options QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Tension: false Fiber Sampling: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Distance of fiber sampling points (in mm) 1 0.100000000000000 0.100000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false Generate Fibers :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico QFrame::NoFrame QFrame::Raised 0 0 0 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false Variance of the gaussian 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true Disable to only generate fibers if "Generate Fibers" button is pressed. Advanced Options false QFrame::NoFrame QFrame::Raised 0 0 0 0 false 30 30 Draw elliptical fiducial. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true false 30 30 Flip fiber waypoints of selcted fiducial around one axis. :/QmitkDiffusionImaging/refresh.xpm:/QmitkDiffusionImaging/refresh.xpm 32 32 false true Qt::Horizontal 40 20 Signal Generation Extra-axonal Compartments - + QFrame::NoFrame QFrame::Raised - + 0 0 0 0 - + Volume Fraction: - + Select signal model for extra-axonal compartment. Ball Model Astrosticks Model Dot Model Prototype Signal - + - + Qt::Horizontal - + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + + + - + - + Select signal model for extra-axonal compartment. -- Ball Model Astrosticks Model Dot Model Prototype Signal - + Qt::Vertical 20 40 Image Settings Advanced Options QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Gradient Directions: Number of gradient directions distributed over the half sphere. 0 10000 1 30 <html><head/><body><p>b-Value<span style=" font-style:italic;"> [s/mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">]</span>:</p></body></html> false b-value in s/mm² 0 10000 100 1000 color: rgb(255, 0, 0); Using geometry of selected image! color: rgb(255, 0, 0); Using gradients of selected DWI! QFrame::NoFrame QFrame::Raised 0 0 0 0 6 - - + + - TE in milliseconds + Output one image per compartment containing the corresponding volume fractions per voxel. + + + Reverse Phase Encoding Direction + + + false + + + + + + + Signal Scale: + + + + + + + Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). 1 10000 1 - 100 + 50 - - + + - - - - - - - + Output one image per compartment containing the corresponding volume fractions per voxel. - <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> + Output Volume Fractions - + false - + + + + Fiber Radius: + + + + T2* relaxation time (in milliseconds). 100.000000000000000 0.100000000000000 1.000000000000000 - - - - Output one image per compartment containing the corresponding volume fractions per voxel. - - - Output Volume Fractions - - - false - - - - - - - - Fiber tangent - - - - - Main fiber directions - - - - - Random - - - - - + <html><head/><body><p><span style=" font-style:italic;">TE</span>, <span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> and <span style=" font-style:italic;">T2</span> will have no effect if unchecked.</p></body></html> Simulate Signal Relaxation true - - - - Fiber Radius: + + + + Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. + + + 0 + + + 1000 + + + 0 - - + + - + TE in milliseconds - - + + 1 - - + + 10000 - - Line Readout Time: + + 1 - - false + + 100 - + - <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> + Dwell time: false - - + + + + Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. + - Diffusion Direction: + Disable Partial Volume Effects + + + false - - + + - Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). + - - 1 + + - - 10000 + + - - 1 + + <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> - - 50 + + false - - + + TE in milliseconds 1 10000 1 100 - - + + + + + + + + + + + - Signal Scale: + <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> + + + false - - + + - Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. + TR in milliseconds - 0 + 1 - 1000 + 999999999 - - 0 + + 1 - - - - - - Separation Angle: + + 2000 - - + + - Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. - - - Disable Partial Volume Effects + - - false + + - - - - - - 1 + + - - 90.000000000000000 + + <html><head/><body><p>Repetition Time <span style=" font-style:italic;">TR</span>: </p></body></html> - - 45.000000000000000 + + false QFrame::NoFrame QFrame::Raised 0 0 0 0 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Spacing: 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Dimensions: Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 11 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 11 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 3 Inter-axonal Compartment Select signal model for intra-axonal compartment. -- Stick Model Zeppelin Model Tensor Model + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + + true Stop current simulation. Abort Simulation :/QmitkDiffusionImaging/general_icons/abort.ico:/QmitkDiffusionImaging/general_icons/abort.ico Data QFrame::NoFrame QFrame::Raised 0 0 0 0 0 - ... <html><head/><body><p>Select a binary image to define the area of signal generation. Outside of the mask image only noise will be actively generated.</p></body></html> + + QComboBox::AdjustToMinimumContentsLength + Fiber Bundle: false Save path: false Tissue Mask: false <html><head/><body><p>Select a fiber bundle to generate the white matter signal from. You can either use the fiber definition tab to manually define an input fiber bundle or you can also use any existing bundle, e.g. yielded by a tractography algorithm.</p></body></html> + + QComboBox::AdjustToMinimumContentsLength + Template Image: false <html><head/><body><p>The parameters for the simulation (e.g. spacing, size, diffuison-weighted gradients, b-value) are adopted from this image.</p></body></html> + + QComboBox::AdjustToMinimumContentsLength + 8 true Noise and other Artifacts Qt::Horizontal Add Noise false Add ringing artifacts occuring at strong edges in the image. Add Gibbs Ringing false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Shrink FOV (%): false Shrink FOV by this percentage. 1 0.000000000000000 90.000000000000000 0.100000000000000 25.000000000000000 Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 0 0 0 Num. Spikes: The number of randomly occurring signal spikes. 1 Spike amplitude relative to the largest signal amplitude of the corresponding k-space slice. 0.100000000000000 0.100000000000000 Scale: !!!EXPERIMENTAL!!! Add Eddy Current Effects false Add Spikes false QFrame::NoFrame QFrame::Raised 0 0 0 0 Variance: Variance of selected noise distribution. 4 0.000000000000000 999999999.000000000000000 0.001000000000000 50.000000000000000 Distribution: Noise distribution Rician Chi-squared Add N/2 Ghosts false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Frequency Map: false Select image specifying the frequency inhomogeneities (in Hz). Qt::Horizontal Qt::Horizontal Qt::Horizontal true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 6 0 0 Toggle between random movement and linear movement. Randomize motion true Rotation 0 9 0 0 Degree: false x false Axis: false Maximum rotation around x-axis. 1 360.000000000000000 1.000000000000000 0.000000000000000 Maximum rotation around z-axis. 1 360.000000000000000 1.000000000000000 15.000000000000000 y false z false Maximum rotation around y-axis. 1 360.000000000000000 1.000000000000000 0.000000000000000 Translation 0 0 0 Distance: false x false y false Axis: false z false Maximum translation along x-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along y-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along z-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Add Motion Artifacts false Add Distortions false Add Aliasing false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 K-Space Line Offset: false A larger offset increases the inensity of the ghost image. 3 1.000000000000000 0.010000000000000 0.250000000000000 true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 0 0 0 Magnitude: false Maximum magnitude of eddy current induced magnetic field inhomogeneities (in mT). 5 1000.000000000000000 0.001000000000000 0.005000000000000 color: rgb(255, 0, 0); Experimental! Qt::Horizontal Qt::Horizontal true <html><head/><body><p>Start DWI generation from selected fiber bundle.</p><p>If no fiber bundle but an existing diffusion weighted image is selected, the enabled artifacts are added to this image.</p><p>If neither a fiber bundle nor a diffusion weighted image is selected, a grayscale image containing a simple gradient is generated.</p></body></html> Start Simulation :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico Intra-axonal Compartment - - - + + + + + + Select signal model for intra-axonal compartment. Stick Model Zeppelin Model Tensor Model Prototype Signal - - + + - - + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + Save Parameters :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkTensorModelParametersWidget QWidget
QmitkTensorModelParametersWidget.h
1
QmitkStickModelParametersWidget QWidget
QmitkStickModelParametersWidget.h
1
QmitkZeppelinModelParametersWidget QWidget
QmitkZeppelinModelParametersWidget.h
1
QmitkBallModelParametersWidget QWidget
QmitkBallModelParametersWidget.h
1
QmitkAstrosticksModelParametersWidget QWidget
QmitkAstrosticksModelParametersWidget.h
1
QmitkDotModelParametersWidget QWidget
QmitkDotModelParametersWidget.h
1
QmitkPrototypeSignalParametersWidget QWidget
QmitkPrototypeSignalParametersWidget.h
1
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
m_CircleButton m_FlipButton m_RealTimeFibers m_AdvancedOptionsBox m_DistributionBox m_VarianceBox m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_GenerateFibersButton m_ConstantRadiusBox m_AlignOnGrid m_XrotBox m_YrotBox m_ZrotBox m_XtransBox m_YtransBox m_ZtransBox m_XscaleBox m_YscaleBox m_ZscaleBox m_TransformBundlesButton m_CopyBundlesButton m_JoinBundlesButton m_IncludeFiducials m_GenerateImageButton m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox m_BvalueBox m_AdvancedOptionsBox_2 m_SignalScaleBox m_TEbox m_LineReadoutTimeBox m_T2starBox m_FiberRadius m_RelaxationBox m_EnforcePureFiberVoxelsBox m_VolumeFractionsBox m_Compartment1Box m_Compartment2Box m_Compartment3Box m_Compartment4Box m_AddNoise m_NoiseLevel m_AddSpikes m_SpikeNumBox m_SpikeScaleBox m_AddGhosts m_kOffsetBox m_AddAliasing m_WrapBox m_AddDistortions m_FrequencyMapBox m_AddMotion m_RandomMotion m_MaxRotationBoxX m_MaxRotationBoxY m_MaxRotationBoxZ m_MaxTranslationBoxX m_MaxTranslationBoxY m_MaxTranslationBoxZ m_AddEddy m_EddyGradientStrength m_AddGibbsRinging m_SaveParametersButton m_LoadParametersButton tabWidget
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp index 17a6ff10c7..15f67a5772 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp @@ -1,1872 +1,2036 @@ /*=================================================================== 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 // Multishell includes #include // Multishell Functors #include #include #include #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.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() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL) { } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_DirectionMatrixTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); #else 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); #endif } } void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkPreprocessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } 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 isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); + mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); finalPredicate = mitk::NodePredicateAnd::New(finalPredicate, isBinaryPredicate); m_Controls->m_NormalizationMaskBox->SetPredicate(finalPredicate); + m_Controls->m_SelctedImageComboBox->SetPredicate(isMitkImage); + 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_CalcAdcButton), SIGNAL(clicked()), this, SLOT(DoAdcCalculation()) ); 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_SelctedImageComboBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnImageSelectionChanged()) ); // connect( (QObject*)(m_Controls->m_ExtractBrainMask), SIGNAL(clicked()), this, SLOT(DoExtractBrainMask()) ); } } +void QmitkPreprocessingView::DoFlipAxis() +{ + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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() )->GetGradientDirectionsContainer(); + mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer newGradients = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New(); + + for (unsigned int i=0; iSize(); i++) + { + mitk::GradientDirectionsProperty::GradientDirectionType g = oldGradients->GetElement(i); + mitk::GradientDirectionsProperty::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 ); + 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()); + GetDefaultDataStorage()->Add(imageNode, node); + + mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + else + AccessFixedDimensionByItk(image, TemplatedFlipAxis,3); +} + + +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()); + + 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()); + GetDefaultDataStorage()->Add(imageNode, node); + + mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + void QmitkPreprocessingView::DoRemoveGradient() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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(m_SelectedImage, itkVectorImagePointer); + mitk::CastToItkImage(image, itkVectorImagePointer); itk::RemoveDwiChannelFilter< short >::Pointer filter = itk::RemoveDwiChannelFilter< short >::New(); filter->SetInput(itkVectorImagePointer); filter->SetChannelIndices(channelsToRemove); - filter->SetDirections( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + filter->SetDirections( static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); filter->Update(); - mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetNewDirections() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_removedgradients").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoExtractGradient() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + 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 mitkImage = mitk::Image::New(); - mitkImage->InitializeByItk( filter->GetOutput() ); - mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); + 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( mitkImage ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_direction-"+QString::number(channel)).toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews(imageNode->GetData()->GetTimeGeometry(),mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::DoCropImage() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + 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(); - mitk::Image::Pointer image = mitk::GrabItkImageMemory( cropper->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + mitk::Image::Pointer newimage = mitk::GrabItkImageMemory( cropper->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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newimage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->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(m_SelectedImage.IsNotNull()) + else { - AccessFixedDimensionByItk(m_SelectedImage, TemplatedCropImage,3); + AccessFixedDimensionByItk(image, TemplatedCropImage,3); } } 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(); + itk::Point origin = itkOutImage->GetOrigin(); + origin[0] += lower[0]*itkOutImage->GetSpacing()[0]; + origin[1] += lower[1]*itkOutImage->GetSpacing()[1]; + origin[2] += lower[2]*itkOutImage->GetSpacing()[2]; + itkOutImage->SetOrigin(origin); mitk::Image::Pointer image = mitk::Image::New(); - image->InitializeByItk( cropper->GetOutput() ); - image->SetVolume( cropper->GetOutput()->GetBufferPointer() ); + image->InitializeByItk( itkOutImage.GetPointer() ); + image->SetVolume( itkOutImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); - QString name = m_SelectedImageNode->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_cropped").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedImageNode); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoApplySpacing() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_SelectedImageNode) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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 image = m_SelectedImage->Clone(); - image->GetGeometry()->SetSpacing( spacing ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + mitk::Image::Pointer newImage = image->Clone(); + newImage->GetGeometry()->SetSpacing( spacing ); + mitk::DiffusionPropertyHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_newspacing").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - else if(m_SelectedImage.IsNotNull()) + else { - AccessFixedDimensionByItk(m_SelectedImage, TemplatedSetImageSpacing,3); + AccessFixedDimensionByItk(image, TemplatedSetImageSpacing,3); } } 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 = m_SelectedImageNode->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_newspacing").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedImageNode); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPreprocessingView::DoApplyOrigin() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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 image = m_SelectedImage->Clone(); + mitk::Image::Pointer newImage = image->Clone(); - image->GetGeometry()->SetOrigin( origin ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + newImage->GetGeometry()->SetOrigin( origin ); + mitk::DiffusionPropertyHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_neworigin").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - else if(m_SelectedImage.IsNotNull()) + else { - AccessFixedDimensionByItk(m_SelectedImage, TemplatedSetImageOrigin,3); + AccessFixedDimensionByItk(image, TemplatedSetImageOrigin,3); } } 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 = m_SelectedImageNode->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_neworigin").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedImageNode); + GetDefaultDataStorage()->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()); + 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); - if (m_SelectedImage.IsNotNull()) - { - mitk::BaseGeometry* geom = m_SelectedImage->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]); - } + 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); - if (m_SelectedImage.IsNotNull()) - { - mitk::BaseGeometry* geom = m_SelectedImage->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)); - } + 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() { - // if (m_SelectedImage.IsNull()) + // if (image.IsNull()) // return; // typedef itk::Image ShortImageType; // ShortImageType::Pointer itkImage = ShortImageType::New(); - // mitk::CastToItkImage(m_SelectedImage, itkImage); + // mitk::CastToItkImage(image, itkImage); // typedef itk::BrainMaskExtractionImageFilter< unsigned char > FilterType; // FilterType::Pointer filter = FilterType::New(); // filter->SetInput(itkImage); // filter->SetMaxNumIterations(m_Controls->m_BrainMaskIterationsBox->value()); // filter->Update(); // mitk::Image::Pointer image = mitk::Image::New(); // image->InitializeByItk( filter->GetOutput() ); // image->SetVolume( filter->GetOutput()->GetBufferPointer() ); // mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); // imageNode->SetData( image ); // imageNode->SetName("BRAINMASK"); // GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::DoResampleImage() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( isDiffusionImage ) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + 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 image = mitk::GrabItkImageMemory( resampler->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + imageNode->SetVisibility(false); + GetDefaultDataStorage()->Add(imageNode, node); } - else if (m_SelectedImage.IsNotNull()) + else { - AccessFixedDimensionByItk(m_SelectedImage, TemplatedResampleImage,3); + AccessFixedDimensionByItk(image, TemplatedResampleImage,3); } } 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 = m_SelectedImageNode->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedImageNode); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoApplyDirectionMatrix() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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(m_SelectedImage, itkDwi); + 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( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); + mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer oldGradients = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.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, newG*mag); } 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(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - newDwi2->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi2 ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_newdirection").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - else if (m_SelectedImage.IsNotNull()) + else { - AccessFixedDimensionByItk(m_SelectedImage, TemplatedApplyRotation,3); + AccessFixedDimensionByItk(image, TemplatedApplyRotation,3); } } 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 = m_SelectedImageNode->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_newdirection").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedImageNode); + GetDefaultDataStorage()->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() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) return; - GradientDirectionContainerType::Pointer gradientContainer = static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); + GradientDirectionContainerType::Pointer gradientContainer = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::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(m_SelectedImage, itkVectorImagePointer); + mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); - filter->SetGradientDirections( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + filter->SetGradientDirections( static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); UcharImageType::Pointer itkImage = NULL; if (m_Controls->m_NormalizationMaskBox->GetSelectedNode().IsNotNull()) { itkImage = UcharImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()), itkImage); filter->SetMaskImage(itkImage); } // determin normalization reference switch(m_Controls->m_NormalizationReferenceBox->currentIndex()) { case 0: // normalize relative to mean white matter signal intensity { typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer dtFilter = TensorReconstructionImageFilterType::New(); dtFilter->SetGradientImage( gradientContainer, itkVectorImagePointer ); - dtFilter->SetBValue( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + dtFilter->SetBValue( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); dtFilter->Update(); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = dtFilter->GetOutput(); itk::ImageRegionIterator< itk::Image< itk::DiffusionTensor3D< double >, 3 > > inIt(tensorImage, tensorImage->GetLargestPossibleRegion()); double ref = 0; unsigned int count = 0; while ( !inIt.IsAtEnd() ) { if (itkImage.IsNotNull() && itkImage->GetPixel(inIt.GetIndex())<=0) { ++inIt; continue; } double FA = inIt.Get().GetFractionalAnisotropy(); if (FA>0.4 && FA<0.99) { ref += itkVectorImagePointer->GetPixel(inIt.GetIndex())[b0Index]; count++; } ++inIt; } if (count>0) { ref /= count; filter->SetUseGlobalReference(true); filter->SetReference(ref); } break; } case 1: // normalize relative to mean CSF signal intensity { itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections( gradientContainer); - adcFilter->SetB_value( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + adcFilter->SetB_value( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); adcFilter->Update(); ItkDoubleImageType::Pointer adcImage = adcFilter->GetOutput(); itk::ImageRegionIterator inIt(adcImage, adcImage->GetLargestPossibleRegion()); double max = 0.0030; double ref = 0; unsigned int count = 0; while ( !inIt.IsAtEnd() ) { if (itkImage.IsNotNull() && itkImage->GetPixel(inIt.GetIndex())<=0) { ++inIt; continue; } if (inIt.Get()>max && inIt.Get()<0.004) { ref += itkVectorImagePointer->GetPixel(inIt.GetIndex())[b0Index]; count++; } ++inIt; } if (count>0) { ref /= count; filter->SetUseGlobalReference(true); filter->SetReference(ref); } break; } case 2: { filter->SetUseGlobalReference(false); } } filter->Update(); - mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_normalized").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoLengthCorrection() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) return; typedef itk::DwiGradientLengthCorrectionFilter FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); - filter->SetReferenceBValue( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - filter->SetReferenceGradientDirectionContainer( static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + filter->SetReferenceBValue( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + filter->SetReferenceGradientDirectionContainer( static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); filter->Update(); - mitk::Image::Pointer image = mitk::ImportItkImage( itkVectorImagePointer ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradientDirectionContainer() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetNewBValue() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + mitk::Image::Pointer newImage = mitk::ImportItkImage( itkVectorImagePointer ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_rounded").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i) { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(node) ); if ( ! isDiffusionImage ) return; - //m_DiffusionImage->UpdateBValueMap(); + UpdateBValueTableWidget(i); } -void QmitkPreprocessingView::CallMultishellToSingleShellFilter(itk::DWIVoxelFunctor * functor, mitk::Image::Pointer ImPtr, QString imageName, mitk::DataNode* parent) +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(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + &originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + mitk::CastToItkImage(image, itkVectorImagePointer); ItkDwiType *vectorImage = itkVectorImagePointer.GetPointer(); const mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer - gradientContainer = static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); + gradientContainer = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); const unsigned int - &bValue = static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue(); + &bValue = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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() ) ); outImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( m_Controls->m_targetBValueSpinBox->value() ) ); - outImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); + outImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); mitk::DiffusionPropertyHelper propertyHelper( outImage ); propertyHelper.InitializeImage(); imageNode = mitk::DataNode::New(); imageNode->SetData( outImage ); imageNode->SetName(imageName.toStdString().c_str()); GetDefaultDataStorage()->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()); // GetDefaultDataStorage()->Add(imageNode); // } } void QmitkPreprocessingView::DoBiExpFit() { - itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); - - for (unsigned int i=0; i(m_SelectedDiffusionNodes.at(i)->GetData()); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( ! isDiffusionImage ) + return; - const mitk::BValueMapProperty::BValueMap - &originalShellMap = static_cast(inImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); - 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); + QString name(node->GetName().c_str()); - const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); - functor->setListOfBValues(bValueList); - functor->setTargetBValue(targetBValue); - CallMultishellToSingleShellFilter(functor,inImage,name + "_BiExp", m_SelectedDiffusionNodes.at(i)); - } + const mitk::BValueMapProperty::BValueMap + &originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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() { - itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); - - for (unsigned int i=0; i(m_SelectedDiffusionNodes.at(i)->GetData()); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( ! isDiffusionImage ) + return; - const mitk::BValueMapProperty::BValueMap - &originalShellMap = static_cast(inImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); - 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); + QString name(node->GetName().c_str()); - const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); - functor->setListOfBValues(bValueList); - functor->setTargetBValue(targetBValue); - CallMultishellToSingleShellFilter(functor,inImage,name + "_AKC", m_SelectedDiffusionNodes.at(i)); - } + const mitk::BValueMapProperty::BValueMap + &originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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() { - itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); - - for (unsigned int i=0; i(m_SelectedDiffusionNodes.at(i)->GetData()); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( ! isDiffusionImage ) + return; - const mitk::BValueMapProperty::BValueMap - &originalShellMap = static_cast(inImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); - 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); + QString name(node->GetName().c_str()); - const double targetBValue = m_Controls->m_targetBValueSpinBox->value(); - functor->setListOfBValues(bValueList); - functor->setTargetBValue(targetBValue); - CallMultishellToSingleShellFilter(functor,inImage,name + "_ADC", m_SelectedDiffusionNodes.at(i)); - } + const mitk::BValueMapProperty::BValueMap + &originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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::DoAdcCalculation() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( ! isDiffusionImage ) return; typedef itk::AdcImageFilter< DiffusionPixelType, double > 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() )->GetGradientDirectionsContainer() ); + filter->SetB_value( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); + filter->Update(); - for (unsigned int i=0; i(m_SelectedDiffusionNodes.at(i)->GetData()); - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(inImage, itkVectorImagePointer); - FilterType::Pointer filter = FilterType::New(); - filter->SetInput( itkVectorImagePointer ); - filter->SetGradientDirections( static_cast( inImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - filter->SetB_value( static_cast(inImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - filter->Update(); - - mitk::Image::Pointer image = mitk::Image::New(); - image->InitializeByItk( filter->GetOutput() ); - image->SetVolume( filter->GetOutput()->GetBufferPointer() ); - mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); - QString name = m_SelectedDiffusionNodes.at(i)->GetName().c_str(); + mitk::Image::Pointer newImage = mitk::Image::New(); + newImage->InitializeByItk( filter->GetOutput() ); + newImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); + mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); + imageNode->SetData( newImage ); + QString name = node->GetName().c_str(); - imageNode->SetName((name+"_ADC").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.at(i)); - } + imageNode->SetName((name+"_ADC").toStdString().c_str()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::UpdateBValueTableWidget(int i) { + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + bool isDiffusionImage(false); - if( m_SelectedImageNode && m_SelectedImageNode.IsNotNull() ) - { - isDiffusionImage = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())); - } + isDiffusionImage = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image); if ( ! isDiffusionImage ) { 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("-")); }else{ typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator; BValueMapIterator it; - BValueMap roundedBValueMap = static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + BValueMap roundedBValueMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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); } } -void QmitkPreprocessingView::OnSelectionChanged( std::vector nodes ) +void QmitkPreprocessingView::OnImageSelectionChanged() { - bool foundDwiVolume = false; - bool foundImageVolume = false; - m_SelectedImage = NULL; - m_SelectedImageNode = NULL; - m_SelectedDiffusionNodes.clear(); - - // iterate selection - for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) - { - mitk::DataNode::Pointer node = *it; - - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) - { - foundImageVolume = true; - m_SelectedImage = dynamic_cast(node->GetData()); - m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); - m_SelectedImageNode = node; - - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_SelectedImageNode ) ); - if( isDiffusionImage ) - { - foundDwiVolume = true; - m_SelectedDiffusionNodes.push_back(node); - } - } - } + bool foundImageVolume = true; + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + foundImageVolume; + bool foundDwiVolume( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( node ) ); 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_CalcAdcButton->setEnabled(foundDwiVolume); m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume); m_Controls->m_NormalizeImageValuesButton->setEnabled(foundDwiVolume); m_Controls->m_DirectionMatrixTable->setEnabled(foundImageVolume); m_Controls->m_ModifyDirection->setEnabled(foundImageVolume); m_Controls->m_ExtractBrainMask->setEnabled(foundImageVolume); m_Controls->m_ResampleImageButton->setEnabled(foundImageVolume); m_Controls->m_ModifySpacingButton->setEnabled(foundImageVolume); m_Controls->m_ModifyOriginButton->setEnabled(foundImageVolume); m_Controls->m_CropImageButton->setEnabled(foundImageVolume); m_Controls->m_RemoveGradientButton->setEnabled(foundDwiVolume); m_Controls->m_ExtractGradientButton->setEnabled(foundDwiVolume); + m_Controls->m_FlipAxis->setEnabled(foundImageVolume); // 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( m_SelectedImageNode.IsNull() ) - { - return; - } - - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_SelectedImageNode) ); - - if (foundDwiVolume && isDiffusionImage) + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + if (foundDwiVolume) { m_Controls->m_InputData->setTitle("Input Data"); - vnl_matrix_fixed< double, 3, 3 > mf = static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame(); + vnl_matrix_fixed< double, 3, 3 > mf = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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(m_SelectedImage, itkVectorImagePointer); + 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(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + const mitk::BValueMapProperty::BValueMap & bValMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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(m_SelectedImage->GetGeometry()->GetSpacing()[0]); - m_Controls->m_HeaderSpacingY->setValue(m_SelectedImage->GetGeometry()->GetSpacing()[1]); - m_Controls->m_HeaderSpacingZ->setValue(m_SelectedImage->GetGeometry()->GetSpacing()[2]); - m_Controls->m_HeaderOriginX->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[0]); - m_Controls->m_HeaderOriginY->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[1]); - m_Controls->m_HeaderOriginZ->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[2]); - m_Controls->m_XstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(0)-1); - m_Controls->m_YstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(1)-1); - m_Controls->m_ZstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(2)-1); - m_Controls->m_XendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(0)-1); - m_Controls->m_YendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(1)-1); - m_Controls->m_ZendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(2)-1); - m_Controls->m_RemoveGradientBox->setMaximum(static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->Size()-1); - m_Controls->m_ExtractGradientBox->setMaximum(static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->Size()-1); + 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() )->GetGradientDirectionsContainer()->Size()-1); + m_Controls->m_ExtractGradientBox->setMaximum(static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer()->Size()-1); } else if (foundImageVolume) { 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(m_SelectedImage->GetGeometry()->GetSpacing()[0]); - m_Controls->m_HeaderSpacingY->setValue(m_SelectedImage->GetGeometry()->GetSpacing()[1]); - m_Controls->m_HeaderSpacingZ->setValue(m_SelectedImage->GetGeometry()->GetSpacing()[2]); - m_Controls->m_HeaderOriginX->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[0]); - m_Controls->m_HeaderOriginY->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[1]); - m_Controls->m_HeaderOriginZ->setValue(m_SelectedImage->GetGeometry()->GetOrigin()[2]); - m_Controls->m_XstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(0)-1); - m_Controls->m_YstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(1)-1); - m_Controls->m_ZstartBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(2)-1); - m_Controls->m_XendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(0)-1); - m_Controls->m_YendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(1)-1); - m_Controls->m_ZendBox->setMaximum(m_SelectedImage->GetGeometry()->GetExtent(2)-1); - - AccessFixedDimensionByItk(m_SelectedImage, TemplatedUpdateGui,3); + 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); } } - - m_Controls->m_DiffusionImageLabel->setText("mandatory"); - m_Controls->m_InputData->setTitle("Please Select Input Data"); } } void QmitkPreprocessingView::Activated() { QmitkFunctionality::Activated(); } void QmitkPreprocessingView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - mitk::Image::Pointer newDwi = m_SelectedImage->Clone(); + mitk::Image::Pointer newDwi = image->Clone(); GradientDirectionContainerType::Pointer gradientContainer = static_cast( newDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.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::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( gradientContainer ) ); mitk::DiffusionPropertyHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_halfsphere").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoApplyMesurementFrame() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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 = m_SelectedImage->Clone(); + mitk::Image::Pointer newDwi = image->Clone(); newDwi->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); mitk::DiffusionPropertyHelper propertyHelper( newDwi ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); - QString name = m_SelectedDiffusionNodes.back()->GetName().c_str(); + QString name = node->GetName().c_str(); imageNode->SetName((name+"_new-MF").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::DoShowGradientDirections() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) return; int maxIndex = 0; - unsigned int maxSize = m_SelectedImage->GetDimension(0); - if (maxSizeGetDimension(1)) + unsigned int maxSize = image->GetDimension(0); + if (maxSizeGetDimension(1)) { - maxSize = m_SelectedImage->GetDimension(1); + maxSize = image->GetDimension(1); maxIndex = 1; } - if (maxSizeGetDimension(2)) + if (maxSizeGetDimension(2)) { - maxSize = m_SelectedImage->GetDimension(2); + maxSize = image->GetDimension(2); maxIndex = 2; } - mitk::Point3D origin = m_SelectedImage->GetGeometry()->GetOrigin(); + 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(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + BValueMap bValMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); - GradientDirectionContainerType::Pointer gradientContainer = static_cast( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); - mitk::BaseGeometry::Pointer geometry = m_SelectedImage->GetGeometry(); + GradientDirectionContainerType::Pointer gradientContainer = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::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]); - MITK_INFO << v; if (v.magnitude()>mitk::eps) { - ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_SelectedImage->GetDimension(0)/2; - ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_SelectedImage->GetDimension(1)/2; - ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_SelectedImage->GetDimension(2)/2; + 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]*m_SelectedImage->GetDimension(0)/2; - ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_SelectedImage->GetDimension(1)/2; - ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_SelectedImage->GetDimension(2)/2; + 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->firstSetData(pointset); - QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + newNode->SetData(pointset); + QString name = node->GetName().c_str(); name += "_Shell_"; name += QString::number(it->first); - node->SetName(name.toStdString().c_str()); - node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); + 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; - node->SetProperty("color", mitk::ColorProperty::New(b2, b1, b0)); - GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); + newNode->SetProperty("color", mitk::ColorProperty::New(b2, b1, b0)); + GetDefaultDataStorage()->Add(newNode, node); shellCount++; } // add origin to datastorage - mitk::DataNode::Pointer node = mitk::DataNode::New(); - node->SetData(originSet); - QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + newNode->SetData(originSet); + QString name = node->GetName().c_str(); name += "_Origin"; - node->SetName(name.toStdString().c_str()); - node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); - node->SetProperty("color", mitk::ColorProperty::New(1,1,1)); - GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); + newNode->SetName(name.toStdString().c_str()); + newNode->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); + newNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); + GetDefaultDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoReduceGradientDirections() { - bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_SelectedImageNode->GetData())) ); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) return; typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef mitk::BValueMapProperty::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; - BValueMap originalShellMap = static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); + BValueMap originalShellMap = static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).GetPointer() )->GetBValueMap(); std::vector newNumGradientDirections; int shellCounter = 0; - QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); + 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( m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); + GradientDirectionContainerType::Pointer gradientContainer = static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(m_SelectedImage, itkVectorImagePointer); + 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 image = mitk::GrabItkImageMemory( filter->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetGradientDirections() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast(m_SelectedImage->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + 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 ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); + imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, m_SelectedDiffusionNodes.back()); + GetDefaultDataStorage()->Add(imageNode, node); } void QmitkPreprocessingView::MergeDwis() { typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; - if (m_SelectedDiffusionNodes.size()<2) + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::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()); + 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 = m_SelectedDiffusionNodes.front()->GetName().c_str(); - for (unsigned int i=0; i( m_SelectedDiffusionNodes.at(i)->GetData() ); - if ( dwi.IsNotNull() ) - { - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(dwi, itkVectorImagePointer); + ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); + mitk::CastToItkImage(image, itkVectorImagePointer); - imageContainer.push_back( itkVectorImagePointer ); - gradientListContainer.push_back( static_cast( dwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - bValueContainer.push_back( static_cast(dwi->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ); - if (i>0) - { - name += "+"; - name += m_SelectedDiffusionNodes.at(i)->GetName().c_str(); - } - } + imageContainer.push_back( itkVectorImagePointer ); + gradientListContainer.push_back( static_cast( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); + bValueContainer.push_back( static_cast(image->GetProperty(mitk::DiffusionPropertyHelper::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() )->GetGradientDirectionsContainer() ); + bValueContainer.push_back( static_cast(image2->GetProperty(mitk::DiffusionPropertyHelper::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 image = mitk::GrabItkImageMemory( filter->GetOutput() ); + mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() ); - image->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); - image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); - mitk::DiffusionPropertyHelper propertyHelper( image ); + newImage->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( filter->GetOutputGradients() ) ); + newImage->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) ); + newImage->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( filter->GetB_Value() ) ); + mitk::DiffusionPropertyHelper propertyHelper( newImage ); propertyHelper.InitializeImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( image ); + imageNode->SetData( newImage ); imageNode->SetName(name.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { - typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( !isDiffusionImage ) + return; - int nrFiles = m_SelectedDiffusionNodes.size(); - if (!nrFiles) return; + typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } - mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); - mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); - - std::vector nodes; - while ( itemiter != itemiterend ) // for all items - { - - mitk::Image* vols = - static_cast( - (*itemiter)->GetData()); - - std::string nodename; - (*itemiter)->GetStringProperty("name", nodename); - - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(vols, itkVectorImagePointer); - - // Extract image using found index - typedef itk::B0ImageExtractionImageFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - filter->SetInput( itkVectorImagePointer ); - filter->SetDirections( static_cast( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - filter->Update(); + ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); + mitk::CastToItkImage(image, itkVectorImagePointer); - mitk::Image::Pointer mitkImage = mitk::Image::New(); - mitkImage->InitializeByItk( filter->GetOutput() ); - mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( mitkImage ); - node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0")); + // 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() )->GetGradientDirectionsContainer() ); + filter->Update(); - GetDefaultDataStorage()->Add(node, (*itemiter)); + 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")); - ++itemiter; - } + GetDefaultDataStorage()->Add(newNode, node); } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { - // typedefs - typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; - typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; - - // check number of selected objects, return if empty - int nrFiles = m_SelectedDiffusionNodes.size(); - if (!nrFiles) + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); - mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); - - while ( itemiter != itemiterend ) // for all items - { - mitk::Image* vols = - static_cast( - (*itemiter)->GetData()); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( !isDiffusionImage ) + return; - std::string nodename; - (*itemiter)->GetStringProperty("name", nodename); + // typedefs + typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientContainerType; + typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; - ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); - mitk::CastToItkImage(vols, itkVectorImagePointer); + 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( vols->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ); - filter->Update(); + // 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() )->GetGradientDirectionsContainer() ); + filter->Update(); - mitk::Image::Pointer mitkImage = mitk::Image::New(); - mitkImage->InitializeByItk( filter->GetOutput() ); - mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( mitkImage ); - node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0_ALL")); + 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")); - GetDefaultDataStorage()->Add(node, (*itemiter)); + GetDefaultDataStorage()->Add(newNode, node); - /*A reinitialization is needed to access the time channels via the ImageNavigationController + /*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(node->GetData()->GetTimeGeometry(),mitk::RenderingManager::REQUEST_UPDATE_ALL, true); - - ++itemiter; - } + mitk::RenderingManager::GetInstance()->InitializeViews(newNode->GetData()->GetTimeGeometry(),mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } void QmitkPreprocessingView::AverageGradients() { - int nrFiles = m_SelectedDiffusionNodes.size(); - if (!nrFiles) return; - - mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); - mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); - - while ( itemiter != itemiterend ) // for all items - { - mitk::Image* mitkDwi = - static_cast( - (*itemiter)->GetData()); + mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); + if (node.IsNull()) + return; + mitk::Image::Pointer image = dynamic_cast(node->GetData()); - mitk::Image::Pointer newDwi = mitkDwi->Clone(); - newDwi->SetPropertyList(mitkDwi->GetPropertyList()->Clone()); + bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) ); + if ( !isDiffusionImage ) + return; - mitk::DiffusionPropertyHelper propertyHelper(newDwi); - propertyHelper.AverageRedundantGradients(m_Controls->m_Blur->value()); - propertyHelper.InitializeImage(); + mitk::Image::Pointer newDwi = image->Clone(); + newDwi->SetPropertyList(image->GetPropertyList()->Clone()); - mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); - imageNode->SetData( newDwi ); - QString name = (*itemiter)->GetName().c_str(); - imageNode->SetName((name+"_averaged").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode, (*itemiter)); + mitk::DiffusionPropertyHelper propertyHelper(newDwi); + propertyHelper.AverageRedundantGradients(m_Controls->m_Blur->value()); + propertyHelper.InitializeImage(); - ++itemiter; - } + mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); + imageNode->SetData( newDwi ); + QString name = node->GetName().c_str(); + imageNode->SetName((name+"_averaged").toStdString().c_str()); + GetDefaultDataStorage()->Add(imageNode, node); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h index d2e798d963..8b7ccd6cde 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h @@ -1,159 +1,159 @@ /*=================================================================== 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 "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 QmitkPreprocessingView * * Document your class here. * * \sa QmitkFunctionality */ class QmitkPreprocessingView : public QmitkFunctionality { 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; QmitkPreprocessingView(); virtual ~QmitkPreprocessingView(); virtual void CreateQtPartControl(QWidget *parent); /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); /// \brief Called when the functionality is activated virtual void Activated(); virtual void Deactivated(); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); 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 DoAdcCalculation(); void DoDwiNormalization(); void DoProjectSignal(); void DoExtractBrainMask(); void DoResampleImage(); void DoCropImage(); void DoUpdateInterpolationGui(int i); void DoRemoveGradient(); void DoExtractGradient(); + void DoFlipAxis(); + void OnImageSelectionChanged(); 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 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 i); /// \brief called by QmitkFunctionality when DataManager's selection has changed - virtual void OnSelectionChanged( std::vector nodes ); +// virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkPreprocessingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name); - - mitk::DataNode::Pointer m_SelectedImageNode; - mitk::Image::Pointer m_SelectedImage; - std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes; - void CallMultishellToSingleShellFilter(itk::DWIVoxelFunctor * functor, mitk::Image::Pointer ImPtr, QString imageName, mitk::DataNode* parent); }; #endif // _QMITKPREPROCESSINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui index b2460f04b2..1641e5acfa 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui @@ -1,1574 +1,1645 @@ QmitkPreprocessingViewControls 0 0 - 639 - 1148 + 523 + 1158 0 0 false QmitkPreprocessingViewControls true Please Select Input Data Image: - - - <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> - - - true + + + QComboBox::AdjustToMinimumContentsLength 0 Gradients - - - - Qt::Vertical + + + + + 0 + 0 + - - - 20 - 40 - + + Qt::ScrollBarAsNeeded - + + Qt::ScrollBarAlwaysOff + + + true + + + 100 + + + true + + + false + + + true + + + + b-Value + + + + + Number of gradients + + + QFrame::NoFrame QFrame::Raised 0 0 0 0 6 false Sometimes the gradient directions are not located on one half sphere. Mirror gradients to half sphere false Round b-values 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. Reduce number of 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 Generate pointset displaying the gradient vectors (applied measurement frame). Show gradients - - - - - 0 - 0 - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAlwaysOff - - - true - - - 100 - - - true - - - false - - - true - - - - b-Value - - - - - Number of gradients - - - - - - + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 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 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 Select binary mask image. + + QComboBox::AdjustToMinimumContentsLength + Select normalization reference. + + QComboBox::AdjustToMinimumContentsLength + White matter CSF Voxel-wise baseline + + + + 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 - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Voxel size - - - - 0 - - - 0 - - - 0 - - - - - 4 - - - - - - - 4 - - - - - - - 4 - - - 0.000000000000000 - - - 99.989999999999995 - - - - - - - false - - - - - - - - - - - - Set new voxel size - - - - - - 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 - - + + - Origin + 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 - - -999999999.000000000000000 - - - 999999999.000000000000000 - - - + + 4 - - -999999999.000000000000000 - - - 999999999.000000000000000 - - - + + 4 - -99999999.000000000000000 + 0.000000000000000 - 999999999.000000000000000 + 99.989999999999995 - + false - Set new origin + Set new voxel size - - + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - + + + + + 0 + 0 + + - Direction matrix + Measurment frame - + 0 - - 9 - 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 direction + Apply new measurement frame - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - + + - Measurment frame + Direction matrix - + 0 + + 9 + 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 + Apply new direction + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - + + - Remove or extract gradient volumes + Origin - + + + 0 + + + 0 + + + 0 + - - - false + + + 4 - - Generate pointset displaying the gradient vectors (applied measurement frame). + + -999999999.000000000000000 - - + + 999999999.000000000000000 - - + + + + + + 4 - - Remove + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + 4 + + + -99999999.000000000000000 + + + 999999999.000000000000000 - + false - Generate pointset displaying the gradient vectors (applied measurement frame). + - Extract + Set new origin - - - - - - Other Create a 3D+t data set containing all b0 images as timesteps Disable averaging false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Extract baseline image Qt::Vertical 20 40 false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Calculate ADC map 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 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.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_CalcAdcButton m_ExtractBrainMask
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp index da8fb53113..340a80c5b8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.cpp @@ -1,286 +1,286 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkStreamlineTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include // MITK #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include #include const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStreamlineTrackingView::QmitkStreamlineTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_MaskImage( NULL ) , m_SeedRoi( NULL ) { } // Destructor QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView() { } void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStreamlineTrackingViewControls; m_Controls->setupUi( parent ); m_Controls->m_FaImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate ); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate ); mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); m_Controls->m_FaImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) ); connect( m_Controls->m_MinTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMinTractLengthChanged(int)) ); - connect( m_Controls->m_FaThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnFaThresholdChanged(int)) ); + connect( m_Controls->m_ScalarThresholdBox, SIGNAL(valueChanged(double)), this, SLOT(OnFaThresholdChanged(double)) ); connect( m_Controls->m_AngularThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAngularThresholdChanged(int)) ); connect( m_Controls->m_StepsizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnStepsizeChanged(int)) ); connect( m_Controls->m_fSlider, SIGNAL(valueChanged(int)), this, SLOT(OnfChanged(int)) ); connect( m_Controls->m_gSlider, SIGNAL(valueChanged(int)), this, SLOT(OngChanged(int)) ); } } void QmitkStreamlineTrackingView::OnfChanged(int value) { m_Controls->m_fLabel->setText(QString("f: ")+QString::number((float)value/100)); } void QmitkStreamlineTrackingView::OngChanged(int value) { m_Controls->m_gLabel->setText(QString("g: ")+QString::number((float)value/100)); } void QmitkStreamlineTrackingView::OnAngularThresholdChanged(int value) { if (value<0) m_Controls->m_AngularThresholdLabel->setText(QString("Min. Curvature Radius: auto")); else m_Controls->m_AngularThresholdLabel->setText(QString("Min. Curvature Radius: ")+QString::number((float)value/10)+QString("mm")); } void QmitkStreamlineTrackingView::OnSeedsPerVoxelChanged(int value) { m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value)); } void QmitkStreamlineTrackingView::OnMinTractLengthChanged(int value) { m_Controls->m_MinTractLengthLabel->setText(QString("Min. Tract Length: ")+QString::number(value)+QString("mm")); } -void QmitkStreamlineTrackingView::OnFaThresholdChanged(int value) +void QmitkStreamlineTrackingView::OnFaThresholdChanged(double value) { - m_Controls->m_FaThresholdLabel->setText(QString("FA Threshold: ")+QString::number((float)value/100)); + m_Controls->m_FaThresholdLabel->setText(QString("FA Threshold: ")+QString::number(value)); } void QmitkStreamlineTrackingView::OnStepsizeChanged(int value) { if (value==0) m_Controls->m_StepsizeLabel->setText(QString("Stepsize: auto")); else m_Controls->m_StepsizeLabel->setText(QString("Stepsize: ")+QString::number((float)value/10)+QString("mm")); } void QmitkStreamlineTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkStreamlineTrackingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkStreamlineTrackingView::OnSelectionChanged( std::vector nodes ) { m_TensorImageNodes.clear(); m_TensorImages.clear(); m_SeedRoi = NULL; m_MaskImage = NULL; m_Controls->m_TensorImageLabel->setText("mandatory"); m_Controls->m_RoiImageLabel->setText("optional"); m_Controls->m_MaskImageLabel->setText("optional"); for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { if( dynamic_cast(node->GetData()) ) { m_TensorImageNodes.push_back(node); m_TensorImages.push_back(dynamic_cast(node->GetData())); } else { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary && m_SeedRoi.IsNull()) { m_SeedRoi = dynamic_cast(node->GetData()); m_Controls->m_RoiImageLabel->setText(node->GetName().c_str()); } else if (isBinary) { m_MaskImage = dynamic_cast(node->GetData()); m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); } } } } if(!m_TensorImageNodes.empty()) { if (m_TensorImageNodes.size()>1) m_Controls->m_TensorImageLabel->setText(m_TensorImageNodes.size()+" tensor images selected"); else m_Controls->m_TensorImageLabel->setText(m_TensorImageNodes.at(0)->GetName().c_str()); m_Controls->m_InputData->setTitle("Input Data"); m_Controls->commandLinkButton->setEnabled(true); } else { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->commandLinkButton->setEnabled(false); } } void QmitkStreamlineTrackingView::DoFiberTracking() { if (m_TensorImages.empty()) return; typedef itk::Image< itk::DiffusionTensor3D, 3> TensorImageType; typedef mitk::ImageToItk CastType; typedef mitk::ImageToItk CastType2; typedef itk::StreamlineTrackingFilter< float > FilterType; FilterType::Pointer filter = FilterType::New(); for (int i=0; i<(int)m_TensorImages.size(); i++) { CastType::Pointer caster = CastType::New(); caster->SetInput(m_TensorImages.at(i)); caster->Update(); filter->SetInput(i, caster->GetOutput()); } if (m_Controls->m_UseFaImage->isChecked()) { mitk::ImageToItk::Pointer floatCast = mitk::ImageToItk::New(); floatCast->SetInput(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData())); floatCast->Update(); filter->SetFaImage(floatCast->GetOutput()); } //filter->SetNumberOfThreads(1); filter->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelSlider->value()); - filter->SetFaThreshold((float)m_Controls->m_FaThresholdSlider->value()/100); + filter->SetFaThreshold(m_Controls->m_ScalarThresholdBox->value()); filter->SetMinCurvatureRadius((float)m_Controls->m_AngularThresholdSlider->value()/10); filter->SetStepSize((float)m_Controls->m_StepsizeSlider->value()/10); filter->SetF((float)m_Controls->m_fSlider->value()/100); filter->SetG((float)m_Controls->m_gSlider->value()/100); filter->SetInterpolate(m_Controls->m_InterpolationBox->isChecked()); filter->SetMinTractLength(m_Controls->m_MinTractLengthSlider->value()); if (m_SeedRoi.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(m_SeedRoi, mask); filter->SetSeedImage(mask); } if (m_MaskImage.IsNotNull()) { ItkUCharImageType::Pointer mask = ItkUCharImageType::New(); mitk::CastToItkImage(m_MaskImage, mask); filter->SetMaskImage(mask); } filter->Update(); vtkSmartPointer fiberBundle = filter->GetFiberPolyData(); if ( fiberBundle->GetNumberOfLines()==0 ) { QMessageBox warnBox; warnBox.setWindowTitle("Warning"); warnBox.setText("No fiberbundle was generated!"); warnBox.setDetailedText("No fibers were generated using the parameters: \n\n" + m_Controls->m_FaThresholdLabel->text() + "\n" + m_Controls->m_AngularThresholdLabel->text() + "\n" + m_Controls->m_fLabel->text() + "\n" + m_Controls->m_gLabel->text() + "\n" + m_Controls->m_StepsizeLabel->text() + "\n" + m_Controls->m_MinTractLengthLabel->text() + "\n" + m_Controls->m_SeedsPerVoxelLabel->text() + "\n\nPlease check your parametersettings."); warnBox.setIcon(QMessageBox::Warning); warnBox.exec(); return; } mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(dynamic_cast(m_TensorImageNodes.at(0)->GetData())->GetGeometry()); if (m_Controls->m_ResampleFibersBox->isChecked()) fib->Compress(m_Controls->m_FiberErrorBox->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(fib); QString name("FiberBundle_"); name += m_TensorImageNodes.at(0)->GetName().c_str(); name += "_Streamline"; node->SetName(name.toStdString()); node->SetVisibility(true); GetDataStorage()->Add(node, m_TensorImageNodes.at(0)); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h index fb4407ab0f..e0ec22fa08 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h @@ -1,90 +1,90 @@ /*=================================================================== 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 QmitkStreamlineTrackingView_h #define QmitkStreamlineTrackingView_h #include #include "ui_QmitkStreamlineTrackingViewControls.h" #include #include #include #include #include /*! \brief View for tensor based deterministic streamline fiber tracking. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkStreamlineTrackingView : public QmitkFunctionality { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; typedef itk::Image< unsigned char, 3 > ItkUCharImageType; typedef itk::Image< float, 3 > ItkFloatImageType; QmitkStreamlineTrackingView(); virtual ~QmitkStreamlineTrackingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); protected slots: void DoFiberTracking(); ///< start fiber tracking protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkStreamlineTrackingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; protected slots: /** update labels if parameters have changed */ void OnSeedsPerVoxelChanged(int value); void OnMinTractLengthChanged(int value); - void OnFaThresholdChanged(int value); + void OnFaThresholdChanged(double value); void OnAngularThresholdChanged(int value); void OnfChanged(int value); void OngChanged(int value); void OnStepsizeChanged(int value); private: mitk::Image::Pointer m_MaskImage; ///< abort tracking if leaving mask mitk::Image::Pointer m_SeedRoi; ///< binary image defining seed voxels for tracking process std::vector< mitk::DataNode::Pointer > m_TensorImageNodes; ///< input images std::vector< mitk::TensorImage::Pointer > m_TensorImages; ///< input image datanode }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingViewControls.ui index a15bdec4bf..a08598a6ac 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingViewControls.ui @@ -1,434 +1,434 @@ QmitkStreamlineTrackingViewControls 0 0 382 538 0 0 QmitkTemplate 3 3 0 Qt::Vertical QSizePolicy::Expanding 20 220 false Start Tractography Parameters Weighting factor between input vector (g=0) and tensor deflection (g=1 equals TEND tracking) 0 100 0 Qt::Horizontal Stepsize in mm (auto = 0.1*minimal spacing) 0 100 0 Qt::Horizontal Minimally allowed curcature radius (in mm, interpolated auto = 0.5 minimal spacing, noninterpolated auto = 0.5 * minimal spacing) -1 50 -1 Qt::Horizontal Min. Tract Length: 20mm FA Threshold: 0.2 g: 0 Qt::Horizontal QSizePolicy::Fixed 200 0 Seeds per Voxel: 1 Number of tracts started in each voxel of the seed ROI. 1 100 Qt::Horizontal Step Size: auto Weighting factor between first eigenvector (f=1 equals FACT tracking) and input vector dependent direction (f=0). 0 100 100 Qt::Horizontal - - - - Fractional Anisotropy Threshold - - - 0 - - - 100 - - - 20 - - - Qt::Horizontal - - - Minimum tract length in mm. 0 500 20 Qt::Horizontal Default is nearest neighbor interpolation. Enable Trilinear Interpolation true f: 1 Min. Curvature Radius: auto Resample fibers using the specified error constraint. Compress Fibers false Qt::StrongFocus Maximum error in mm. 3 10.000000000000000 0.010000000000000 0.100000000000000 + + + + 5 + + + 1.000000000000000 + + + 0.100000000000000 + + + 0.200000000000000 + + + Please Select Input Data <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> true + + QComboBox::AdjustToMinimumContentsLength + - <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> true Only track insida mask area. Mask Image: Binary seed ROI. If not specified, the whole image area is seeded. Seed ROI: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Input DTI Tensor Image: Check to use selected FA image instead of internally calculated one. Recommended for multi-tensor tractography. FA image false QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h