diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp index ead4fce7af..be51ca4621 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp @@ -1,238 +1,239 @@ /*=================================================================== 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 __itkibersFromPlanarFiguresFilter_cpp #define __itkibersFromPlanarFiguresFilter_cpp #include "itkFibersFromPlanarFiguresFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk{ FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter() { } FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter() { } void FibersFromPlanarFiguresFilter::GeneratePoints() { Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); randGen->SetSeed((unsigned int)0); m_2DPoints.clear(); unsigned int count = 0; while (count < m_Parameters.m_Density) { mitk::Vector2D p; switch (m_Parameters.m_Distribution) { case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); break; default: p[0] = randGen->GetUniformVariate(-1, 1); p[1] = randGen->GetUniformVariate(-1, 1); } if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) { m_2DPoints.push_back(p); count++; } } } void FibersFromPlanarFiguresFilter::GenerateData() { // check if enough fiducials are available for (unsigned int i=0; i m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); std::vector< unsigned int > fliplist; if (i container = vtkSmartPointer::New(); mitk::PlanarEllipse::Pointer figure = bundle.at(0); mitk::Point2D p0 = figure->GetControlPoint(0); mitk::Point2D p1 = figure->GetControlPoint(1); mitk::Point2D p2 = figure->GetControlPoint(2); mitk::Point2D p3 = figure->GetControlPoint(3); double r1 = p0.EuclideanDistanceTo(p1); double r2 = p0.EuclideanDistanceTo(p2); mitk::Vector2D eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir = p3-p0; tDir.Normalize(); // apply twist vnl_matrix_fixed tRot; tRot[0][0] = tDir[0]; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (tDir[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); // apply new ellipse shape vnl_vector_fixed< double, 2 > newP; newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; double alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*itk::Math::pi-alpha; vnl_matrix_fixed eRot; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); mitk::Point3D w, wc; planeGeo->Map(p0, w); wc = figure->GetWorldControlPoint(0); vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); for (unsigned int k=1; kGetControlPoint(0); p1 = figure->GetControlPoint(1); p2 = figure->GetControlPoint(2); p3 = figure->GetControlPoint(3); r1 = p0.EuclideanDistanceTo(p1); r2 = p0.EuclideanDistanceTo(p2); eDir = p1-p0; eDir.Normalize(); mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); mitk::Vector2D temp; temp.Fill(0); temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); // apply twist tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; + if (tRot[0][0]>1.0) + tRot[0][0] = 1.0; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (temp[1]<0) tRot.inplace_transpose(); m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); tDir = tDir2; // apply new ellipse shape newP[0] = m_2DPoints.at(j)[0]; newP[1] = m_2DPoints.at(j)[1]; // calculate normal mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); wc = figure->GetWorldControlPoint(0); // is flip needed? if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) newP[0] *= -1; if (fliplist.at(k)>0) newP[0] *= -1; n = n2; alpha = acos(eDir[0]); if (eDir[1]>0) alpha = 2*itk::Math::pi-alpha; eRot[0][0] = cos(alpha); eRot[1][1] = eRot[0][0]; eRot[1][0] = sin(alpha); eRot[0][1] = -eRot[1][0]; newP = eRot*newP; newP[0] *= r1; newP[1] *= r2; newP = eRot.transpose()*newP; p0[0] += newP[0]; p0[1] += newP[1]; mitk::Point3D w; planeGeo->Map(p0, w); - vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); container->GetPointIds()->InsertNextId(id); } m_VtkCellArray->InsertNextCell(container); } vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); fiberPolyData->SetPoints(m_VtkPoints); fiberPolyData->SetLines(m_VtkCellArray); mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); m_FiberBundles.push_back(mitkFiberBundle); } } } #endif // __itkFibersFromPlanarFiguresFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp new file mode 100644 index 0000000000..bbaadbd74c --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.cpp @@ -0,0 +1,439 @@ +/*=================================================================== + +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 __itkRandomPhantomFilter_cpp +//#define __itkRandomPhantomFilter_cpp + +#include "itkRandomPhantomFilter.h" + +#include +#include +#include + +namespace itk{ + +RandomPhantomFilter::RandomPhantomFilter() + : m_NumTracts(1) + , m_MinStreamlineDensity(25) + , m_MaxStreamlineDensity(200) + , m_StartRadiusMin(5) + , m_StartRadiusMax(30) + , m_CurvynessMin(10) + , m_CurvynessMax(45) + , m_StepSizeMin(15) + , m_StepSizeMax(30) + , m_MinTwist(10) + , m_MaxTwist(30) +{ + m_VolumeSize[0] = 500; + m_VolumeSize[1] = 500; + m_VolumeSize[2] = 500; +} + +RandomPhantomFilter::~RandomPhantomFilter() +{ + +} + + +void RandomPhantomFilter::TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2) +{ + mitk::BaseGeometry* geom = pe->GetGeometry(); + + // translate + geom->Translate(translation); + + // calculate rotation matrix + double x = rotation[0]*itk::Math::pi/180; + double y = rotation[1]*itk::Math::pi/180; + double z = rotation[2]*itk::Math::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; + + // rotate fiducial + geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); + + // adjust control points + auto p0 = pe->GetControlPoint(0); + auto p1 = pe->GetControlPoint(1); + auto p2 = pe->GetControlPoint(2); + auto p3 = pe->GetControlPoint(3); + + auto v1 = p1 - p0; + auto v2 = p2 - p0; + auto dot = std::cos(itk::Math::pi*twistangle/180.0); + + vnl_matrix_fixed tRot; + tRot[0][0] = dot; + tRot[1][1] = tRot[0][0]; + tRot[1][0] = sin(acos(tRot[0][0])); + tRot[0][1] = -tRot[1][0]; + if (twistangle<0) + tRot = tRot.transpose(); + vnl_vector_fixed vt; vt[0]=1; vt[1]=0; + vnl_vector_fixed v3 = tRot*vt; + + v1.Normalize(); + v2.Normalize(); + + p1 = p0 + radius1; + p2 = p0 + radius2; + + p3 = p0 + mitk::Vector2D(v3); + pe->SetControlPoint(1, p1); + pe->SetControlPoint(2, p2); + pe->SetControlPoint(3, p3); + + + pe->Modified(); +} + +mitk::PlanarEllipse::Pointer RandomPhantomFilter::CreatePlanarFigure() +{ + mitk::PlaneGeometry::Pointer pl = mitk::PlaneGeometry::New(); + pl->SetIdentity(); + // mitk::Point3D o; o.Fill(10.0); + // pl->SetOrigin(o); + mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); + figure->ResetNumberOfControlPoints(0); + figure->SetPlaneGeometry(pl); + + mitk::Point2D p0; p0.Fill(0.0); + mitk::Point2D p1; p1.Fill(0.0); p1[0] = 1; + mitk::Point2D p2; p2.Fill(0.0); p2[1] = 1; + + figure->PlaceFigure(p0); + figure->AddControlPoint(p0); + figure->AddControlPoint(p1); + figure->AddControlPoint(p2); + figure->AddControlPoint(p2); + figure->SetProperty("initiallyplaced", mitk::BoolProperty::New(true)); + return figure; +} + +void RandomPhantomFilter::SetNumTracts(unsigned int NumTracts) +{ + m_NumTracts = NumTracts; +} + +void RandomPhantomFilter::GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot) +{ + Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); + randGen->SetSeed(); + int plane = randGen->GetIntegerVariate(5) + 1; + MITK_INFO << "Plane: " << plane; + switch(plane) + { + case 1: + { + pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); + pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); + pos[2] = 0; + + rot[0] = 0; + rot[1] = 0; + rot[2] = 0; + break; + } + case 2: + { + pos[0] = 0; + pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); + pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); + + rot[0] = 0; + rot[1] = 90; + rot[2] = 0; + break; + } + case 3: + { + pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); + pos[1] = 0; + pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); + + rot[0] = -90; + rot[1] = 0; + rot[2] = 0; + break; + } + case 4: + { + pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); + pos[1] = m_VolumeSize[1]; + pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); + + rot[0] = 90; + rot[1] = 0; + rot[2] = 0; + break; + } + case 5: + { + pos[0] = m_VolumeSize[0]; + pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); + pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]); + + rot[0] = 0; + rot[1] = -90; + rot[2] = 0; + break; + } + case 6: + { + pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]); + pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]); + pos[2] = m_VolumeSize[2]; + + rot[0] = 180; + rot[1] = 0; + rot[2] = 0; + break; + } + } +} + +bool RandomPhantomFilter::IsInVolume(mitk::Vector3D pos) +{ + if (pos[0]>=0 && + pos[0]<=m_VolumeSize[0] && + pos[1]>=0 && + pos[1]<=m_VolumeSize[1] && + pos[2]>=0 && + pos[2]<=m_VolumeSize[2]) + return true; + return false; +} + +void RandomPhantomFilter::setMinTwist(unsigned int MinTwist) +{ + m_MinTwist = MinTwist; +} + +void RandomPhantomFilter::setMaxStreamlineDensity(unsigned int MaxStreamlineDensity) +{ + m_MaxStreamlineDensity = MaxStreamlineDensity; +} + +void RandomPhantomFilter::setMinStreamlineDensity(unsigned int MinStreamlinDensity) +{ + m_MinStreamlineDensity = MinStreamlinDensity; +} + +void RandomPhantomFilter::setMaxTwist(unsigned int MaxTwist) +{ + m_MaxTwist = MaxTwist; +} + +void RandomPhantomFilter::setVolumeSize(const mitk::Vector3D &VolumeSize) +{ + m_VolumeSize = VolumeSize; +} + +void RandomPhantomFilter::setStepSizeMax(unsigned int StepSizeMax) +{ + m_StepSizeMax = StepSizeMax; +} + +void RandomPhantomFilter::setStepSizeMin(unsigned int StepSizeMin) +{ + m_StepSizeMin = StepSizeMin; +} + +void RandomPhantomFilter::setCurvynessMax(unsigned int CurvynessMax) +{ + m_CurvynessMax = CurvynessMax; +} + +void RandomPhantomFilter::setCurvynessMin(unsigned int CurvynessMin) +{ + m_CurvynessMin = CurvynessMin; +} + +void RandomPhantomFilter::setStartRadiusMax(unsigned int StartRadiusMax) +{ + m_StartRadiusMax = StartRadiusMax; +} + +void RandomPhantomFilter::setStartRadiusMin(unsigned int StartRadiusMin) +{ + m_StartRadiusMin = StartRadiusMin; +} + +void RandomPhantomFilter::GenerateData() +{ + Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); + randGen->SetSeed(); + + for (unsigned int i=0; i bundle_waypoints; + + double curvyness = randGen->GetUniformVariate(m_CurvynessMin, m_CurvynessMax); + int twistdir = static_cast(randGen->GetIntegerVariate(2)) - 1; + double dtwist = randGen->GetUniformVariate(m_MinTwist, m_MaxTwist); + + mitk::Vector3D pos; pos.Fill(0.0); + mitk::Vector3D rot; rot.Fill(0.0); + double twist = 0; + double radius1 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax); + double radius2 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax); + + GetPfOnBoundingPlane(pos, rot); + rot[0] += randGen->GetUniformVariate(-curvyness, curvyness); + rot[1] += randGen->GetUniformVariate(-curvyness, curvyness); + rot[2] += randGen->GetUniformVariate(-curvyness, curvyness); + + mitk::PlanarEllipse::Pointer start = CreatePlanarFigure(); + TransformPlanarFigure(start, pos, rot, twist, radius1, radius2); + bundle_waypoints.push_back(start); + + double c_area = M_PI*radius1*radius2; + + int sizestrategy = static_cast(randGen->GetIntegerVariate(2)) - 1; + + MITK_INFO << "Twist: " << dtwist; + MITK_INFO << "Twist direction: " << twistdir; + MITK_INFO << "Curvyness: " << curvyness; + MITK_INFO << "Size strategy: " << sizestrategy; + + int c = 1; + while(IsInVolume(pos)) + { + pos += bundle_waypoints.at(c-1)->GetPlaneGeometry()->GetNormal() * randGen->GetUniformVariate(m_StepSizeMin, m_StepSizeMax); + rot[0] += randGen->GetUniformVariate(-curvyness, curvyness); + rot[1] += randGen->GetUniformVariate(-curvyness, curvyness); + rot[2] += randGen->GetUniformVariate(-curvyness, curvyness); + + twist += dtwist * twistdir; + if (randGen->GetUniformVariate(0.0, 1.0) < 0.25) + { + int temp = static_cast(randGen->GetIntegerVariate(2)) - 1; + if (temp!=twistdir) + { + twistdir = temp; + MITK_INFO << "Twist direction change: " << twistdir; + } + } + + if (randGen->GetUniformVariate(0.0, 1.0) < 0.25) + { + int temp = static_cast(randGen->GetIntegerVariate(2)) - 1; + if (temp!=sizestrategy) + { + sizestrategy = temp; + MITK_INFO << "Size strategy change: " << sizestrategy; + } + } + + double dsize = 3.0; + double minradius = 5.0; + double maxradius = 2.0*m_StartRadiusMax; + if (sizestrategy==0) + { + radius1 += randGen->GetUniformVariate(-dsize, dsize); + radius2 += randGen->GetUniformVariate(-dsize, dsize); + while (radius1 < 5) + radius1 += randGen->GetUniformVariate(-dsize, dsize); + while (radius2 < 5) + radius2 += randGen->GetUniformVariate(-dsize, dsize); + } + else if (sizestrategy==1) + { + radius1 += randGen->GetUniformVariate(0, dsize); + radius2 += randGen->GetUniformVariate(0, dsize); + if (radius1 > maxradius) + { + radius1 = maxradius; + sizestrategy = static_cast(randGen->GetIntegerVariate(1)) - 1; + } + if (radius2 > maxradius) + { + radius2 = maxradius; + sizestrategy = static_cast(randGen->GetIntegerVariate(1)) - 1; + } + } + else if (sizestrategy==-1) + { + radius1 += randGen->GetUniformVariate(-dsize, 0); + radius2 += randGen->GetUniformVariate(-dsize, 0); + if (radius1 < minradius) + { + radius1 = minradius; + sizestrategy = static_cast(randGen->GetIntegerVariate(1)); + } + if (radius2 < minradius) + { + radius2 = minradius; + sizestrategy = static_cast(randGen->GetIntegerVariate(1)); + } + } + + c_area += M_PI*radius1*radius2; + + mitk::PlanarEllipse::Pointer pf = CreatePlanarFigure(); + TransformPlanarFigure(pf, pos, rot, twist, radius1, radius2); + + bundle_waypoints.push_back(pf); + ++c; + } + c_area /= c; + c_area /= 100; + MITK_INFO << "Average crossectional area: " << c_area << "cm²"; + + fiber_params.m_Fiducials.push_back(bundle_waypoints); + auto density = randGen->GetUniformVariate(m_MinStreamlineDensity, m_MaxStreamlineDensity); + MITK_INFO << "Density: " << density; + fiber_params.m_Density = static_cast(std::ceil(c_area*density)); + + MITK_INFO << "Num. fibers: " << fiber_params.m_Density; + MITK_INFO << "Num. fiducials: " << c; + MITK_INFO << "------------\n"; + + std::streambuf *old = cout.rdbuf(); // <-- save + std::stringstream ss; + std::cout.rdbuf (ss.rdbuf()); // <-- redirect + itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); + filter->SetParameters(fiber_params); + filter->Update(); + m_FiberBundles.push_back(filter->GetFiberBundles().at(0)); + std::cout.rdbuf (old); // <-- restore + } +} + +} +//#endif // __itkRandomPhantomFilter_cpp + diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h new file mode 100644 index 0000000000..6d0cdf079a --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkRandomPhantomFilter.h @@ -0,0 +1,109 @@ +/*=================================================================== + +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 itkRandomPhantomFilter_h +#define itkRandomPhantomFilter_h + +// MITK +#include +#include +#include + +// ITK +#include + +namespace itk{ + +/** +* \brief */ + +class RandomPhantomFilter : public ProcessObject +{ +public: + + typedef RandomPhantomFilter Self; + typedef ProcessObject Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + typedef mitk::FiberBundle::Pointer FiberType; + typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; + + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + itkTypeMacro( RandomPhantomFilter, ProcessObject ) + + void Update() override{ + this->GenerateData(); + } + + // output + FiberContainerType GetFiberBundles(){ return m_FiberBundles; } + + void SetNumTracts(unsigned int NumTracts); + + void setStartRadiusMin(unsigned int StartRadiusMin); + + void setStartRadiusMax(unsigned int StartRadiusMax); + + void setCurvynessMin(unsigned int CurvynessMin); + + void setCurvynessMax(unsigned int CurvynessMax); + + void setStepSizeMin(unsigned int StepSizeMin); + + void setStepSizeMax(unsigned int StepSizeMax); + + void setVolumeSize(const mitk::Vector3D &VolumeSize); + + void setMaxTwist(unsigned int MaxTwist); + + void setMinStreamlineDensity(unsigned int MinStreamlinDensity); + + void setMaxStreamlineDensity(unsigned int MaxStreamlineDensity); + + void setMinTwist(unsigned int MinTwist); + +protected: + + void GenerateData() override; + + RandomPhantomFilter(); + ~RandomPhantomFilter() override; + void TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2); + mitk::PlanarEllipse::Pointer CreatePlanarFigure(); + void GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot); + bool IsInVolume(mitk::Vector3D pos); + + FiberContainerType m_FiberBundles; ///< container for the output fiber bundles + unsigned int m_NumTracts; + unsigned int m_MinStreamlineDensity; + unsigned int m_MaxStreamlineDensity; + unsigned int m_StartRadiusMin; + unsigned int m_StartRadiusMax; + unsigned int m_CurvynessMin; + unsigned int m_CurvynessMax; + unsigned int m_StepSizeMin; + unsigned int m_StepSizeMax; + unsigned int m_MinTwist; + unsigned int m_MaxTwist; + mitk::Vector3D m_VolumeSize; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkRandomPhantomFilter.cpp" +#endif + +#endif diff --git a/Modules/DiffusionImaging/FiberTracking/files.cmake b/Modules/DiffusionImaging/FiberTracking/files.cmake index 765654b61e..a93ec3dcd5 100644 --- a/Modules/DiffusionImaging/FiberTracking/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/files.cmake @@ -1,107 +1,108 @@ set(CPP_FILES mitkFiberTrackingModuleActivator.cpp ## IO datastructures IODataStructures/FiberBundle/mitkFiberBundle.cpp IODataStructures/FiberBundle/mitkTrackvis.cpp IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp IODataStructures/mitkTractographyForest.cpp IODataStructures/mitkFiberfoxParameters.cpp # Interactions # Tractography Algorithms/GibbsTracking/mitkParticleGrid.cpp Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp Algorithms/GibbsTracking/mitkEnergyComputer.cpp Algorithms/GibbsTracking/mitkGibbsEnergyComputer.cpp Algorithms/GibbsTracking/mitkFiberBuilder.cpp Algorithms/GibbsTracking/mitkSphereInterpolator.cpp Algorithms/itkStreamlineTrackingFilter.cpp Algorithms/TrackingHandlers/mitkTrackingDataHandler.cpp Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.cpp Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.cpp Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.cpp ) set(H_FILES # DataStructures -> FiberBundle IODataStructures/FiberBundle/mitkFiberBundle.h IODataStructures/FiberBundle/mitkTrackvis.h IODataStructures/mitkFiberfoxParameters.h IODataStructures/mitkTractographyForest.h # Algorithms Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkTractsToVectorImageFilter.h Algorithms/itkEvaluateDirectionImagesFilter.h Algorithms/itkEvaluateTractogramDirectionsFilter.h Algorithms/itkFiberCurvatureFilter.h Algorithms/itkFitFibersToImageFilter.h Algorithms/itkTractClusteringFilter.h Algorithms/itkTractDistanceFilter.h Algorithms/itkFiberExtractionFilter.h Algorithms/itkTdiToVolumeFractionFilter.h # Tractography Algorithms/TrackingHandlers/mitkTrackingDataHandler.h Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h Algorithms/itkGibbsTrackingFilter.h Algorithms/itkStochasticTractographyFilter.h Algorithms/GibbsTracking/mitkParticle.h Algorithms/GibbsTracking/mitkParticleGrid.h Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h Algorithms/GibbsTracking/mitkSimpSamp.h Algorithms/GibbsTracking/mitkEnergyComputer.h Algorithms/GibbsTracking/mitkGibbsEnergyComputer.h Algorithms/GibbsTracking/mitkSphereInterpolator.h Algorithms/GibbsTracking/mitkFiberBuilder.h Algorithms/itkStreamlineTrackingFilter.h # Clustering Algorithms/ClusteringMetrics/mitkClusteringMetric.h Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMean.h Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMax.h Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanStd.h Algorithms/ClusteringMetrics/mitkClusteringMetricAnatomic.h Algorithms/ClusteringMetrics/mitkClusteringMetricScalarMap.h Algorithms/ClusteringMetrics/mitkClusteringMetricInnerAngles.h Algorithms/ClusteringMetrics/mitkClusteringMetricLength.h # Fiberfox Fiberfox/itkFibersFromPlanarFiguresFilter.h Fiberfox/itkTractsToDWIImageFilter.h Fiberfox/itkKspaceImageFilter.h Fiberfox/itkDftImageFilter.h Fiberfox/itkFieldmapGeneratorFilter.h + Fiberfox/itkRandomPhantomFilter.h Fiberfox/SignalModels/mitkDiffusionSignalModel.h Fiberfox/SignalModels/mitkTensorModel.h Fiberfox/SignalModels/mitkBallModel.h Fiberfox/SignalModels/mitkDotModel.h Fiberfox/SignalModels/mitkAstroStickModel.h Fiberfox/SignalModels/mitkStickModel.h Fiberfox/SignalModels/mitkRawShModel.h Fiberfox/SignalModels/mitkDiffusionNoiseModel.h Fiberfox/SignalModels/mitkRicianNoiseModel.h Fiberfox/SignalModels/mitkChiSquareNoiseModel.h Fiberfox/Sequences/mitkAcquisitionType.h Fiberfox/Sequences/mitkSingleShotEpi.h Fiberfox/Sequences/mitkCartesianReadout.h ) set(RESOURCE_FILES # Binary directory resources FiberTrackingLUTBaryCoords.bin FiberTrackingLUTIndices.bin ) diff --git a/Modules/PlanarFigure/include/mitkPlanarFigure.h b/Modules/PlanarFigure/include/mitkPlanarFigure.h index 57ff0d3ae5..ada4fc879c 100644 --- a/Modules/PlanarFigure/include/mitkPlanarFigure.h +++ b/Modules/PlanarFigure/include/mitkPlanarFigure.h @@ -1,382 +1,382 @@ /*=================================================================== 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_PLANAR_FIGURE_H_ #define _MITK_PLANAR_FIGURE_H_ #include "mitkBaseData.h" #include "mitkCommon.h" #include #include namespace mitk { class PlaneGeometry; /** * \brief Base-class for geometric planar (2D) figures, such as * lines, circles, rectangles, polygons, etc. * * \warning Currently does not support time-resolved data handling * * Behavior and appearance of PlanarFigures are controlled by various properties; for a detailed * list of appearance properties see mitk::PlanarFigureMapper2D * * The following properties control general PlanarFigure behavior: * *
    *
  • "selected": true if the planar figure is selected *
  • "planarfigure.ishovering": true if the mouse "hovers" over the planar figure *
  • "planarfigure.iseditable": true if the planar figure can be edited (otherwise, * it can only be picked/selected, but its control points cannot be edited); default is true *
  • "planarfigure.isextendable": true if new control points can be inserted into the list of control points; * default is false *
* * * TODO: Implement local 2D transform (including center of rotation...) * */ class MITKPLANARFIGURE_EXPORT PlanarFigure : public BaseData { public: mitkClassMacro(PlanarFigure, BaseData) itkCloneMacro(Self) typedef Point2D PolyLineElement; typedef itk::VectorContainer BoolContainerType; typedef std::deque ControlPointListType; typedef std::vector PolyLineType; /** \brief Sets the 2D geometry on which this figure will be placed. * * In most cases, this is a Geometry already owned by another object, e.g. * describing the slice of the image on which measurements will be * performed. */ virtual void SetPlaneGeometry(mitk::PlaneGeometry *geometry); /** \brief Returns (previously set) 2D geometry of this figure. */ virtual const PlaneGeometry *GetPlaneGeometry() const; /** \brief True if the planar figure is closed. * * Default is false. The "closed" boolean property must be set in sub-classes. */ virtual bool IsClosed() const; /** \brief True if the planar figure has been placed (and can be * displayed/interacted with). */ virtual bool IsPlaced() const { return m_FigurePlaced; }; /** \brief Place figure at the given point (in 2D index coordinates) onto * the given 2D geometry. * * By default, the first two control points of the figure are set to the * passed point. Further points can be set via AddControlPoint(), if the * current number of control points is below the maximum number of control * points. * * Can be re-implemented in sub-classes as needed. */ virtual void PlaceFigure(const Point2D &point); /** * \brief Adds / inserts new control-points * * This method adds a new control-point with the coordinates defined by point at the given index. * If 'index' == -1 or index is greater than the number of control-points the new point is appended * to the back of the list of control points. * If a control-point already exists for 'index', an additional point is inserted at that position. * It is not possible to add more points if the maximum number of control-points (GetMaximumNumberOfControlPoints()) * has been reached. */ virtual bool AddControlPoint(const Point2D &point, int index = -1); virtual bool SetControlPoint(unsigned int index, const Point2D &point, bool createIfDoesNotExist = false); virtual bool SetCurrentControlPoint(const Point2D &point); /** \brief Returns the current number of 2D control points defining this figure. */ unsigned int GetNumberOfControlPoints() const; /** \brief Returns the minimum number of control points needed to represent * this figure. * * Must be implemented in sub-classes. */ virtual unsigned int GetMinimumNumberOfControlPoints() const = 0; /** \brief Returns the maximum number of control points allowed for * this figure (e.g. 3 for triangles). * * Must be implemented in sub-classes. */ virtual unsigned int GetMaximumNumberOfControlPoints() const = 0; /** \brief Selects currently active control points. */ virtual bool SelectControlPoint(unsigned int index); /** \brief Deselect control point; no control point active. */ virtual bool DeselectControlPoint(); /** \brief Return currently selected control point. */ virtual int GetSelectedControlPoint() const { return m_SelectedControlPoint; } /** \brief Returns specified control point in 2D world coordinates. */ Point2D GetControlPoint(unsigned int index) const; /** * \brief Returns the id of the control-point that corresponds to the given * polyline-point. */ virtual int GetControlPointForPolylinePoint(int indexOfPolylinePoint, int polyLineIndex) const; /** \brief Returns specified control point in world coordinates. */ Point3D GetWorldControlPoint(unsigned int index) const; /** \brief Returns the polyline representing the planar figure * (for rendering, measurements, etc.). */ const PolyLineType GetPolyLine(unsigned int index); /** \brief Returns the polyline representing the planar figure * (for rendering, measurments, etc.). */ const PolyLineType GetPolyLine(unsigned int index) const; /** \brief Returns the polyline that should be drawn the same size at every scale * (for text, angles, etc.). */ const PolyLineType GetHelperPolyLine(unsigned int index, double mmPerDisplayUnit, unsigned int displayHeight); /** \brief Sets the position of the PreviewControlPoint. Automatically sets it visible.*/ void SetPreviewControlPoint(const Point2D &point); /** \brief Marks the PreviewControlPoint as invisible.*/ void ResetPreviewContolPoint(); /** \brief Returns whether or not the PreviewControlPoint is visible.*/ bool IsPreviewControlPointVisible() const; /** \brief Returns the coordinates of the PreviewControlPoint. */ Point2D GetPreviewControlPoint() const; /** \brief Returns the number of features available for this PlanarFigure * (such as, radius, area, ...). */ virtual unsigned int GetNumberOfFeatures() const; /** \brief Returns the name (identifier) of the specified features. */ const char *GetFeatureName(unsigned int index) const; /** \brief Returns the physical unit of the specified features. */ const char *GetFeatureUnit(unsigned int index) const; /** Returns quantity of the specified feature (e.g., length, radius, * area, ... ) */ double GetQuantity(unsigned int index) const; /** \brief Returns true if the feature with the specified index exists and * is active (an inactive feature may e.g. be the area of a non-closed * polygon. */ bool IsFeatureActive(unsigned int index) const; /** \brief Returns true if the feature with the specified index exists and is set visible */ bool IsFeatureVisible(unsigned int index) const; /** \brief Defines if the feature with the specified index will be shown as an * Annotation in the RenderWindow */ void SetFeatureVisible(unsigned int index, bool visible); /** \brief Calculates quantities of all features of this planar figure. */ virtual void EvaluateFeatures(); /** \brief Intherited from parent */ void UpdateOutputInformation() override; /** \brief Intherited from parent */ void SetRequestedRegionToLargestPossibleRegion() override; /** \brief Intherited from parent */ bool RequestedRegionIsOutsideOfTheBufferedRegion() override; /** \brief Intherited from parent */ bool VerifyRequestedRegion() override; /** \brief Intherited from parent */ void SetRequestedRegion(const itk::DataObject *data) override; /** \brief Returns the current number of polylines */ virtual unsigned short GetPolyLinesSize(); /** \brief Returns the current number of helperpolylines */ virtual unsigned short GetHelperPolyLinesSize() const; /** \brief Returns whether a helper polyline should be painted or not */ virtual bool IsHelperToBePainted(unsigned int index) const; /** \brief Returns true if the planar figure is reset to "add points" mode * when a point is selected. * * Default return value is false. Subclasses can overwrite this method and * execute any reset / initialization statements required. */ virtual bool ResetOnPointSelect(); virtual bool ResetOnPointSelectNeeded() const; /** \brief removes the point with the given index from the list of controlpoints. */ virtual void RemoveControlPoint(unsigned int index); /** \brief Removes last control point */ virtual void RemoveLastControlPoint(); /** \brief Allow sub-classes to apply constraints on control points. * * Sub-classes can define spatial constraints to certain control points by * overwriting this method and returning a constrained point. By default, * the points are constrained by the image bounds. */ virtual Point2D ApplyControlPointConstraints(unsigned int /*index*/, const Point2D &point); /** * \brief Compare two PlanarFigure objects * Note: all subclasses have to implement the method on their own. */ virtual bool Equals(const mitk::PlanarFigure &other) const; + /** \brief Set the initial number of control points of the planar figure */ + void ResetNumberOfControlPoints(int numberOfControlPoints); + protected: PlanarFigure(); PlanarFigure(const Self &other); - /** \brief Set the initial number of control points of the planar figure */ - void ResetNumberOfControlPoints(int numberOfControlPoints); - /** Adds feature (e.g., circumference, radius, angle, ...) to feature vector * of a planar figure object and returns integer ID for the feature element. * Should be called in sub-class constructors. */ virtual unsigned int AddFeature(const char *featureName, const char *unitName); /** Sets the name of the specified feature. INTERNAL METHOD. */ void SetFeatureName(unsigned int index, const char *featureName); /** Sets the physical unit of the specified feature. INTERNAL METHOD. */ void SetFeatureUnit(unsigned int index, const char *unitName); /** Sets quantity of the specified feature. INTERNAL METHOD. */ void SetQuantity(unsigned int index, double quantity); /** Sets the specified feature as active. INTERAL METHOD. */ void ActivateFeature(unsigned int index); /** Sets the specified feature as active. INTERAL METHOD. */ void DeactivateFeature(unsigned int index); /** \brief Generates the poly-line representation of the planar figure. * Must be implemented in sub-classes. */ virtual void GeneratePolyLine() = 0; /** \brief Generates the poly-lines that should be drawn the same size regardless of zoom. * Must be implemented in sub-classes. */ virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight) = 0; /** \brief Calculates quantities of all features of this planar figure. * Must be implemented in sub-classes. */ virtual void EvaluateFeaturesInternal() = 0; /** \brief Initializes the TimeGeometry describing the (time-resolved) * geometry of this figure. Note that each time step holds one PlaneGeometry. */ void InitializeTimeGeometry(unsigned int timeSteps = 1) override; /** \brief defines the number of PolyLines that will be available */ void SetNumberOfPolyLines(unsigned int numberOfPolyLines); /** \brief Append a point to the PolyLine # index */ void AppendPointToPolyLine(unsigned int index, PolyLineElement element); /** \brief clears the list of PolyLines. Call before re-calculating a new Polyline. */ void ClearPolyLines(); /** \brief defines the number of HelperPolyLines that will be available */ void SetNumberOfHelperPolyLines(unsigned int numberOfHelperPolyLines); /** \brief Append a point to the HelperPolyLine # index */ void AppendPointToHelperPolyLine(unsigned int index, PolyLineElement element); /** \brief clears the list of HelperPolyLines. Call before re-calculating a new HelperPolyline. */ void ClearHelperPolyLines(); void PrintSelf(std::ostream &os, itk::Indent indent) const override; ControlPointListType m_ControlPoints; unsigned int m_NumberOfControlPoints; // Currently selected control point; -1 means no point selected int m_SelectedControlPoint; std::vector m_PolyLines; std::vector m_HelperPolyLines; BoolContainerType::Pointer m_HelperPolyLinesToBePainted; // this point is used to store the coordiantes an additional 'ControlPoint' that is rendered // when the mouse cursor is above the figure (and not a control-point) and when the // property 'planarfigure.isextendable' is set to true Point2D m_PreviewControlPoint; bool m_PreviewControlPointVisible; bool m_FigurePlaced; private: // not implemented to prevent PlanarFigure::New() calls which would create an itk::Object. static Pointer New(); struct Feature { Feature(const char *name, const char *unit) : Name(name), Unit(unit), Quantity(0.0), Active(true), Visible(true) { } std::string Name; std::string Unit; double Quantity; bool Active; bool Visible; }; itk::LightObject::Pointer InternalClone() const override = 0; PlaneGeometry *m_PlaneGeometry; bool m_PolyLineUpToDate; bool m_HelperLinesUpToDate; bool m_FeaturesUpToDate; // Vector of features available for this geometric figure typedef std::vector FeatureVectorType; FeatureVectorType m_Features; unsigned long m_FeaturesMTime; // this pair is used to store the mmInDisplayUnits (m_DisplaySize.first) and the displayHeight // (m_DisplaySize.second) // that the helperPolyLines have been calculated for. // It's used to determine whether or not GetHelperPolyLine() needs to recalculate the HelperPolyLines. std::pair m_DisplaySize; }; MITKPLANARFIGURE_EXPORT bool Equal(const mitk::PlanarFigure &leftHandSide, const mitk::PlanarFigure &rightHandSide, ScalarType eps, bool verbose); } // namespace mitk #endif //_MITK_PLANAR_FIGURE_H_ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp index 27b5819b9b..9a7af8be07 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp @@ -1,1121 +1,1165 @@ /*=================================================================== 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 "QmitkFiberGenerationView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include +#include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberGenerationView::VIEW_ID = "org.mitk.views.fibergenerationview"; QmitkFiberGenerationView::QmitkFiberGenerationView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImageNode( nullptr ) { } // Destructor QmitkFiberGenerationView::~QmitkFiberGenerationView() { } void QmitkFiberGenerationView::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::QmitkFiberGenerationViewControls; m_Controls->setupUi( parent ); m_ParameterFile = QDir::currentPath()+"/param.ffp"; + + connect(static_cast(m_Controls->m_RandomPhantomButton), SIGNAL(clicked()), static_cast(this), SLOT(RandomPhantom())); connect(static_cast(m_Controls->m_GenerateFibersButton), SIGNAL(clicked()), static_cast(this), SLOT(GenerateFibers())); connect(static_cast(m_Controls->m_CircleButton), SIGNAL(clicked()), static_cast(this), SLOT(OnDrawROI())); connect(static_cast(m_Controls->m_FlipButton), SIGNAL(clicked()), static_cast(this), SLOT(OnFlipButton())); connect(static_cast(m_Controls->m_JoinBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(JoinBundles())); connect(static_cast(m_Controls->m_VarianceBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnVarianceChanged(double))); connect(static_cast(m_Controls->m_DistributionBox), SIGNAL(currentIndexChanged(int)), static_cast(this), SLOT(OnDistributionChanged(int))); connect(static_cast(m_Controls->m_FiberDensityBox), SIGNAL(valueChanged(int)), static_cast(this), SLOT(OnFiberDensityChanged(int))); connect(static_cast(m_Controls->m_FiberSamplingBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnFiberSamplingChanged(double))); connect(static_cast(m_Controls->m_TensionBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnTensionChanged(double))); connect(static_cast(m_Controls->m_ContinuityBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnContinuityChanged(double))); connect(static_cast(m_Controls->m_BiasBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnBiasChanged(double))); connect(static_cast(m_Controls->m_ConstantRadiusBox), SIGNAL(stateChanged(int)), static_cast(this), SLOT(OnConstantRadius(int))); connect(static_cast(m_Controls->m_CopyBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(CopyBundles())); connect(static_cast(m_Controls->m_TransformBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(ApplyTransform())); connect(static_cast(m_Controls->m_AlignOnGrid), SIGNAL(clicked()), static_cast(this), SLOT(AlignOnGrid())); connect(static_cast(m_Controls->m_FidAxis1), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidAxis2), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosX), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosY), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidPosZ), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_FidTwist), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); connect(static_cast(m_Controls->m_AdvancedOptionsBox), SIGNAL( stateChanged(int)), static_cast(this), SLOT(ShowAdvancedOptions(int))); connect(static_cast(m_Controls->m_SaveParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(SaveParameters())); connect(static_cast(m_Controls->m_LoadParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(LoadParameters())); } UpdateGui(); } +void QmitkFiberGenerationView::RandomPhantom() +{ + itk::RandomPhantomFilter::Pointer filter = itk::RandomPhantomFilter::New(); + filter->SetNumTracts(m_Controls->m_NumBundlesBox->value()); + filter->setMinStreamlineDensity(m_Controls->m_MinDensityBox->value()); + filter->setMaxStreamlineDensity(m_Controls->m_MaxDensityBox->value()); + mitk::Vector3D vol; + vol[0] = m_Controls->m_VolumeSizeX->value(); + vol[1] = m_Controls->m_VolumeSizeY->value(); + vol[2] = m_Controls->m_VolumeSizeZ->value(); + filter->setVolumeSize(vol); + filter->setStepSizeMin(m_Controls->m_StepSizeMinBox->value()); + filter->setStepSizeMax(m_Controls->m_StepSizeMaxBox->value()); + filter->setCurvynessMin(m_Controls->m_CurvyMinBox->value()); + filter->setCurvynessMax(m_Controls->m_CurvyMaxBox->value()); + filter->setStartRadiusMin(m_Controls->m_SizeMinBox->value()); + filter->setStartRadiusMax(m_Controls->m_SizeMaxBox->value()); + filter->setMinTwist(m_Controls->m_MinTwistBox->value()); + filter->setMaxTwist(m_Controls->m_MaxTwistBox->value()); + filter->Update(); + auto fibs = filter->GetFiberBundles(); + + std::vector< mitk::DataNode::Pointer > fiber_nodes; + int c = 1; + for (auto fib : fibs) + { + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData( fib ); + node->SetName("Bundle_" + boost::lexical_cast(c)); + GetDataStorage()->Add(node); + fiber_nodes.push_back(node); + ++c; + } + +// mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + mitk::RenderingManager::GetInstance()->InitializeViews(GetDataStorage()->ComputeVisibleBoundingGeometry3D()); +} + void QmitkFiberGenerationView::UpdateParametersFromGui() { m_Parameters.ClearFiberParameters(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } m_Parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); m_Parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); m_Parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); m_Parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); m_Parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); m_Parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); m_Parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); m_Parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); m_Parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); m_Parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); m_Parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); m_Parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); m_Parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); m_Parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); } void QmitkFiberGenerationView::SaveParameters(QString filename) { UpdateParametersFromGui(); m_Parameters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberGenerationView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); SaveParameters(filename); } void QmitkFiberGenerationView::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; m_Parameters.LoadParameters(filename.toStdString()); if (m_Parameters.m_MissingTags.size()>0) { QString missing("Parameter file might be corrupted. The following parameters could not be read: "); missing += QString(m_Parameters.m_MissingTags.c_str()); missing += "\nDefault values have been assigned to the missing parameters."; QMessageBox::information( nullptr, "Warning!", missing); } m_Controls->m_RealTimeFibers->setChecked(m_Parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(m_Parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(m_Parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(m_Parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(m_Parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(m_Parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(m_Parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(m_Parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(m_Parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(m_Parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[2]); } void QmitkFiberGenerationView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); } } void QmitkFiberGenerationView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::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 QmitkFiberGenerationView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::UpdateFiducialPosition() { if (m_SelectedFiducials.size()!=1) return; mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Point3D origin; origin[0] = m_Controls->m_FidPosX->value(); origin[1] = m_Controls->m_FidPosY->value(); origin[2] = m_Controls->m_FidPosZ->value(); // transform control point coordinate into geometry translation auto p0 = pe->GetControlPoint(0); auto p1 = pe->GetControlPoint(1); auto p2 = pe->GetControlPoint(2); auto p3 = pe->GetControlPoint(3); auto v1 = p1 - p0; auto v2 = p2 - p0; auto angle_deg = m_Controls->m_FidTwist->value(); auto dot = std::cos(itk::Math::pi*angle_deg/180.0); vnl_matrix_fixed tRot; tRot[0][0] = dot; tRot[1][1] = tRot[0][0]; tRot[1][0] = sin(acos(tRot[0][0])); tRot[0][1] = -tRot[1][0]; if (angle_deg<0) tRot = tRot.transpose(); vnl_vector_fixed vt; vt[0]=1; vt[1]=0; vnl_vector_fixed v3 = tRot*vt; if (v1.GetNorm()<0.0001 || v2.GetNorm()<0.0001) { QMessageBox::information( nullptr, "", "Please select exactly one fiducial."); return; } v1.Normalize(); v2.Normalize(); p1 = p0 + v1*m_Controls->m_FidAxis1->value(); p2 = p0 + v2*m_Controls->m_FidAxis2->value(); p3 = p0 + mitk::Vector2D(v3); pe->SetControlPoint(1, p1); pe->SetControlPoint(2, p2); pe->SetControlPoint(3, p3); geom->SetOrigin(origin); pe->Modified(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); UpdateGui(); } void QmitkFiberGenerationView::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 QmitkFiberGenerationView::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(); } void QmitkFiberGenerationView::OnAddBundle() { if (m_SelectedImageNode.IsNull()) return; 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_SelectedImageNode); } void QmitkFiberGenerationView::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 QmitkFiberGenerationView::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; } UpdateParametersFromGui(); 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); std::sort(childVector.begin(), childVector.end(), CompareLayer); std::vector< mitk::PlanarEllipse::Pointer > fib; std::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) { m_Parameters.m_FiberGen.m_Fiducials.push_back(fib); m_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(m_Parameters.m_FiberGen); filter->Update(); std::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 QmitkFiberGenerationView::ApplyTransform() { std::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()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::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()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::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 QmitkFiberGenerationView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberGenerationView") << "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 QmitkFiberGenerationView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberGenerationView") << "Select at least two fiber bundles!"; return; } + std::vector< mitk::FiberBundle::Pointer > to_add; std::vector::const_iterator it = m_SelectedBundles.begin(); + (*it)->SetVisibility(false); 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()); + (*it)->SetVisibility(false); + to_add.push_back(dynamic_cast((*it)->GetData())); } + newBundle = newBundle->AddBundles(to_add); mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); - fbNode->SetName(name.toStdString()); + fbNode->SetName("Joined"); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::UpdateGui() { 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_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); m_Controls->m_FiducialAttributeBox->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_SelectedFiducials.size()==1) { m_Controls->m_FiducialAttributeBox->setEnabled(true); mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); auto origin = pe->GetGeometry()->GetOrigin(); m_Controls->m_FidPosX->setValue(origin[0]); m_Controls->m_FidPosY->setValue(origin[1]); m_Controls->m_FidPosZ->setValue(origin[2]); auto p0 = pe->GetControlPoint(0); auto p1 = pe->GetControlPoint(1); auto p2 = pe->GetControlPoint(2); auto p3 = pe->GetControlPoint(3); auto v1 = p1 - p0; auto v2 = p2 - p0; m_Controls->m_FidAxis1->setValue(v1.GetNorm()); m_Controls->m_FidAxis2->setValue(v2.GetNorm()); vnl_vector_fixed vt; vt[0]=1; vt[1]=0; auto v3 = p3-p0; v3.Normalize(); auto angle = dot_product(vt, v3.GetVnlVector()); angle = std::acos(angle)*180.0/itk::Math::pi; if (v3[1]<0) angle *= -1; m_Controls->m_FidTwist->setValue(angle); } else { m_Controls->m_FidPosX->setValue(0); m_Controls->m_FidPosY->setValue(0); m_Controls->m_FidPosZ->setValue(0); m_Controls->m_FidAxis1->setValue(1); m_Controls->m_FidAxis2->setValue(1); m_Controls->m_FidTwist->setValue(0); } if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } 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); } } void QmitkFiberGenerationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = nullptr; m_SelectedBundles.clear(); m_SelectedImageNode = nullptr; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData()) ) { m_SelectedImages.push_back(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()!=static_cast(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 QmitkFiberGenerationView::EnableCrosshairNavigation() { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::DisableCrosshairNavigation() { } void QmitkFiberGenerationView::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 QmitkFiberGenerationView::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< QmitkFiberGenerationView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberGenerationView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::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, &QmitkFiberGenerationView::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, &QmitkFiberGenerationView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberGenerationView::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 QmitkFiberGenerationView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h index c7637d763b..5eba22b325 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h @@ -1,147 +1,148 @@ /*=================================================================== 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_QmitkFiberGenerationViewControls.h" #include #include #include #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include class QmitkFiberGenerationView : 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 std::string VIEW_ID; QmitkFiberGenerationView(); virtual ~QmitkFiberGenerationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; protected slots: void LoadParameters(); ///< load FiberGeneration parameters void SaveParameters(); ///< save FiberGeneration parameters 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 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 RandomPhantom(); 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); void UpdateFiducialPosition(); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; Ui::QmitkFiberGenerationViewControls* m_Controls; void UpdateParametersFromGui(); 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 ) override; ///< add observers void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers void SaveParameters(QString filename); static bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j); /** 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_SelectedImageNode; std::vector< mitk::DataNode::Pointer > m_SelectedBundles; std::vector< mitk::DataNode::Pointer > m_SelectedBundles2; std::vector< mitk::DataNode::Pointer > m_SelectedFiducials; std::vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name FiberfoxParameters m_Parameters; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui index ed6ff1f5bc..cce8b2a89c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui @@ -1,1403 +1,1987 @@ QmitkFiberGenerationViewControls 0 0 413 - 1282 + 1461 Form - - + + - 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 Fiberfox View. - - - Qt::AutoText - - - Qt::AlignJustify|Qt::AlignVCenter + Save Parameters - - true + + + :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico - - - - QFrame::NoFrame + + + + - - QFrame::Raised + + Load Parameters + + + + :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico - - - 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/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico - - - - 32 - 32 - - - - false - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - QGroupBox { - background-color: transparent; -} + + + + Qt::Vertical - - Fiber Options + + + 20 + 40 + - - - 6 - - - 6 - - - 6 - - - 6 + + + + + + 0 + + + + + 0 + 0 + 381 + 741 + - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 + + Manual Fiber Design + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + false - - 0 + + + 30 + 30 + - - 0 + + Draw elliptical fiducial. - - 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 + + + :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png - - 0 + + + 32 + 32 + - - 0 + + false - - 0 + + true + + + + + + + false + + + + 30 + 30 + + + + Flip fiber waypoints of selcted fiducial around one axis. + + + + + + + :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico + + + + 32 + 32 + + + + false + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 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 Fiberfox View. + + + Qt::AutoText + + + Qt::AlignJustify|Qt::AlignVCenter + + + true + + + + + + + QGroupBox { + background-color: transparent; +} + + + Fiber Options + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + QFrame::NoFrame - - 6 - - - - - - - - - - - - - - #Fibers: - - - false - - - - - - - Specify number of fibers to generate for the selected bundle. - - - 1 - - - 1000000 - - - 100 - - - 100 - - - - - - - - - - - - - false - - - QCommandLinkButton:disabled { + + 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 + + + QCommandLinkButton:disabled { border: none; } - - - 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 - - - - - - - - - - - - - QGroupBox { + 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 + + + + + + + + + + + + + QGroupBox { background-color: transparent; } - - - Operations - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - false - - - QCommandLinkButton:disabled { + + + Fiducial Options + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Fiducial Attributes + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Length of fiducial axis 2 + + + 2 + + + 0.000000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Axis 1: + + + false + + + + + + + + + + + + + + + + Position X: + + + false + + + + + + + World Position in mm + + + 2 + + + -99999.000000000000000 + + + 99999.000000000000000 + + + 0.100000000000000 + + + + + + + World Position in mm + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + World Position in mm + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + Length of fiducial axis 1 + + + 2 + + + 0.000000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Position Z: + + + false + + + + + + + + + + + + + + + + Position Y: + + + false + + + + + + + + + + + + + + + + Axis 2: + + + false + + + + + + + + + + + + + + + + Twist: + + + false + + + + + + + Twist in degree + + + 2 + + + -180.000000000000000 + + + 180.000000000000000 + + + 0.100000000000000 + + + + + + + + + + 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. + + + QCommandLinkButton:disabled { border: none; } - - - 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. - - - 2 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Axis: - - - false - - - - - - - Rotation angle (in degree) around y-axis. - - - 2 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Translation: - - - false - - - - - - - Translation (in mm) in direction of the z-axis. - - - 2 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 0.100000000000000 - - - - - - - Translation (in mm) in direction of the y-axis. - - - 2 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - X - - - false - - - - - - - - - - - - - - - - Rotation: - - - false - - - - - - - - - - - - - - - - Z - - - false - - - - - - - Rotation angle (in degree) around z-axis. - - - 2 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - Translation (in mm) in direction of the x-axis. - - - 2 - - - -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 - - - QCommandLinkButton:disabled { + + + Align With Grid + + + + :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico + + + + + + + + + + + + 0 + 0 + 403 + 282 + + + + Random Phantom + + + + + + + + + + + + + + + Volume Size: + + + false + + + + + + + + + + + + + + + + Curvyness: + + + false + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 0 + + + 90 + + + 10 + + + 30 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 0 + + + 90 + + + 10 + + + 15 + + + + + + + + + + + + + + + + + + + Step Size: + + + false + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 100 + + + 1 + + + 15 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 100 + + + 1 + + + 30 + + + + + + + + + + + + + + + + + + + Streamline Density: + + + false + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 1000 + + + 1 + + + 50 + + + + + + + + + + + + + + + + Start Radii: + + + false + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 90 + + + 1 + + + 5 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 90 + + + 1 + + + 45 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 1000 + + + 1 + + + 250 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 1000 + + + 1 + + + 250 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 1000 + + + 1 + + + 250 + + + + + + + + + + + + + + + + + + + Twist: + + + false + + + + + + + + + + + + + + + + #Bundles: + + + false + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 300 + + + 1 + + + 5 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 300 + + + 1 + + + 25 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 10000 + + + 10 + + + 200 + + + + + + + Specify number of fibers to generate for the selected bundle. + + + 1 + + + 10000 + + + 10 + + + 50 + + + + + + + + + + true + + + QCommandLinkButton:disabled { border: none; } - - - Copy Bundles - - - - :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico - - - - - - - false - - - QCommandLinkButton:disabled { + + + Generate + + + + :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico + + + + + + + + + 0 + 0 + 395 + 298 + + + + Operations + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + Y + + + false + + + + + + + Rotation angle (in degree) around x-axis. + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Axis: + + + false + + + + + + + Rotation angle (in degree) around y-axis. + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Translation: + + + false + + + + + + + Translation (in mm) in direction of the z-axis. + + + 2 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + Translation (in mm) in direction of the y-axis. + + + 2 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + X + + + false + + + + + + + + + + + + + + + + Rotation: + + + false + + + + + + + + + + + + + + + + Z + + + false + + + + + + + Rotation angle (in degree) around z-axis. + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + Translation (in mm) in direction of the x-axis. + + + 2 + + + -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 + + + QCommandLinkButton:disabled { border: none; } - - - 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 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Save Parameters - - - - :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico - - - - - - - QGroupBox { - background-color: transparent; + + + Copy Bundles + + + + :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico + + + + + + + false + + + QCommandLinkButton:disabled { + border: none; } - - - Fiducial Options - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - Fiducial Attributes - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - Length of fiducial axis 2 - - - 2 - - - 0.000000000000000 - - - 9999.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Axis 1: - - - false - - - - - - - - - - - - - - - - Position X: - - - false - - - - - - - World Position in mm - - - 2 - - - -99999.000000000000000 - - - 99999.000000000000000 - - - 0.100000000000000 - - - - - - - World Position in mm - - - 2 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - World Position in mm - - - 2 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - Length of fiducial axis 1 - - - 2 - - - 0.000000000000000 - - - 9999.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Position Z: - - - false - - - - - - - - - - - - - - - - Position Y: - - - false - - - - - - - - - - - - - - - - Axis 2: - - - false - - - - - - - - - - - - - - - - Twist: - - - false - - - - - - - Twist in degree - - - 2 - - - -180.000000000000000 - - - 180.000000000000000 - - - 0.100000000000000 - - - - - - - - - - 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. - - - QCommandLinkButton:disabled { + + + Transform Selection + + + + :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico + + + + + + + false + + + QCommandLinkButton:disabled { border: none; } - - - Align With Grid - - - - :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico - - - - - - - - - - - - - Load Parameters - - - - :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico - + + + Join Bundles + + + + :/QmitkDiffusionImaging/general_icons/plus.ico:/QmitkDiffusionImaging/general_icons/plus.ico + + + + + + + If checked, the fiducials belonging to the modified bundle are also modified. + + + Include Fiducials + + + true + + + + + 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_SaveParametersButton m_LoadParametersButton