diff --git a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp index a2332fa..d64a0c3 100644 --- a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp +++ b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp @@ -1,335 +1,336 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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 "mitkFiberBundleMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" #include <vtkActor.h> #include <vtkOpenGLPolyDataMapper.h> #include <vtkOpenGLHelper.h> #include <vtkShaderProgram.h> #include <vtkPlane.h> #include <vtkPolyData.h> #include <vtkPointData.h> #include <vtkProperty.h> #include <vtkLookupTable.h> #include <vtkPoints.h> #include <vtkCamera.h> #include <vtkPolyLine.h> #include <vtkRenderer.h> #include <vtkCellArray.h> #include <vtkMatrix4x4.h> #include <vtkTubeFilter.h> #include <mitkPlaneGeometry.h> #include <mitkSliceNavigationController.h> #include <mitkCoreServices.h> #include <vtkShaderProperty.h> #include <vtkPlaneCollection.h> class vtkShaderCallback : public vtkCommand { public: static vtkShaderCallback *New() { return new vtkShaderCallback; } mitk::BaseRenderer *renderer; mitk::DataNode *node; void Execute(vtkObject *, unsigned long, void*cbo) override { vtkShaderProgram *program = reinterpret_cast<vtkShaderProgram*>(cbo); float fiberOpacity; bool fiberFading = false; float fiberThickness = 0.0; node->GetOpacity(fiberOpacity, nullptr); node->GetFloatProperty("Fiber2DSliceThickness", fiberThickness); node->GetBoolProperty("Fiber2DfadeEFX", fiberFading); program->SetUniformf("fiberOpacity", fiberOpacity); program->SetUniformi("fiberFadingON", fiberFading); program->SetUniformf("fiberThickness", fiberThickness); // if (this->renderer) // { // //get information about current position of views // mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); // mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); // //generate according cutting planes based on the view position // float planeNormal[3]; // planeNormal[0] = planeGeo->GetNormal()[0]; // planeNormal[1] = planeGeo->GetNormal()[1]; // planeNormal[2] = planeGeo->GetNormal()[2]; // float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0]; // float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1]; // float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2]; // float odotn = tmp1 + tmp2 + tmp3; // float a[4]; // for (int i = 0; i < 3; ++i) // a[i] = planeNormal[i]; // a[3] = odotn; // MITK_INFO << "IN CALLBACK"; // MITK_INFO << planeGeo->GetNormal(); // MITK_INFO << planeGeo->GetOrigin(); // for (int i = 0; i < 4; ++i) // MITK_INFO << a[i]; // program->SetUniform4f("slicingPlane", a); // } } vtkShaderCallback() { this->renderer = nullptr; } }; mitk::FiberBundleMapper2D::FiberBundleMapper2D() : m_LineWidth(1) { m_lut = vtkSmartPointer<vtkLookupTable>::New(); m_lut->Build(); } mitk::FiberBundleMapper2D::~FiberBundleMapper2D() { } mitk::FiberBundle* mitk::FiberBundleMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundle * > ( GetDataNode()->GetData() ); } void mitk::FiberBundleMapper2D::Update(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); //set renderer independent shader properties const DataNode::Pointer node = this->GetDataNode(); float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; mitk::FiberBundle* fiberBundle = this->GetInput(); if (fiberBundle==nullptr) return; - int lineWidth = 1.0; - node->GetIntProperty("LineWidth", lineWidth); - if (m_LineWidth!=lineWidth) - { - m_LineWidth = lineWidth; - fiberBundle->RequestUpdate2D(); - } - vtkProperty *property = localStorage->m_Actor->GetProperty(); property->SetLighting(false); if ( localStorage->m_LastUpdateTime<renderer->GetCurrentWorldPlaneGeometryUpdateTime() || localStorage->m_LastUpdateTime<fiberBundle->GetUpdateTime2D() ) { this->UpdateShaderParameter(renderer); this->GenerateDataForRenderer( renderer ); } } void mitk::FiberBundleMapper2D::UpdateShaderParameter(mitk::BaseRenderer *) { // see new vtkShaderCallback } // vtkActors and Mappers are feeded here void mitk::FiberBundleMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { mitk::FiberBundle* fiberBundle = this->GetInput(); //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); mitk::DataNode* node = this->GetDataNode(); if (node == nullptr) return; vtkSmartPointer<vtkPolyData> fiberPolyData = fiberBundle->GetFiberPolyData(); if (fiberPolyData == nullptr) return; fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); localStorage->m_Mapper->ScalarVisibilityOn(); localStorage->m_Mapper->SetScalarModeToUsePointFieldData(); // localStorage->m_Mapper->SetLookupTable(m_lut); //apply the properties after the slice was set // localStorage->m_Actor->GetProperty()->SetOpacity(0.999); localStorage->m_Mapper->SelectColorArray("FIBER_COLORS"); localStorage->m_Mapper->SetInputData(fiberPolyData); float d = 1.0; node->GetFloatProperty("Fiber2DSliceThickness", d); mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); const Point3D &origin = planeGeo->GetOrigin(); const Vector3D &normal = planeGeo->GetNormal(); vtkSmartPointer<vtkPlane> plane1 = vtkSmartPointer<vtkPlane>::New(); plane1->SetOrigin(origin[0]+normal[0]*d, origin[1]+normal[1]*d, origin[2]+normal[2]*d); // plane1->SetOrigin(origin[0], origin[1], origin[2]); plane1->SetNormal(-normal[0], -normal[1], -normal[2]); vtkSmartPointer<vtkPlane> plane2 = vtkSmartPointer<vtkPlane>::New(); plane2->SetOrigin(origin[0]-normal[0]*d, origin[1]-normal[1]*d, origin[2]-normal[2]*d); plane2->SetNormal(normal[0], normal[1], normal[2]); vtkSmartPointer<vtkPlaneCollection> planes = vtkSmartPointer<vtkPlaneCollection>::New();; planes->AddItem(plane1); planes->AddItem(plane2); localStorage->m_Mapper->SetClippingPlanes(planes); // localStorage->m_Actor->GetShaderProperty()->SetVertexShaderCode( // "//VTK::System::Dec\n" // "attribute vec4 vertexMC;\n" // "//VTK::Normal::Dec\n" // "uniform mat4 MCDCMatrix;\n" // "//VTK::Color::Dec\n" // "varying vec4 positionWorld;\n" // "varying vec4 colorVertex;\n" // "void main(void)\n" // "{\n" // " colorVertex = scalarColor;\n" // " positionWorld = vertexMC;\n" // " gl_Position = MCDCMatrix * vertexMC;\n" // "}\n" // ); // localStorage->m_Actor->GetShaderProperty()->SetFragmentShaderCode( // "//VTK::System::Dec\n" // always start with this line // "//VTK::Output::Dec\n" // always have this line in your FS // "uniform vec4 slicingPlane;\n" // "uniform float fiberThickness;\n" // "uniform int fiberFadingON;\n" // "uniform float fiberOpacity;\n" // "varying vec4 positionWorld;\n" // "varying vec4 colorVertex;\n" // "out vec4 out_Color;\n" // "void main(void)\n" // "{\n" // " float r1 = dot(positionWorld.xyz, slicingPlane.xyz) - slicingPlane.w;\n" // " if (abs(r1) >= fiberThickness)\n" // " discard;\n" // " if (fiberFadingON != 0)\n" // " {\n" // " float x = (r1 + fiberThickness) / (fiberThickness*2.0);\n" // " x = 1.0 - x;\n" // " out_Color = vec4(colorVertex.xyz*x, fiberOpacity);\n" // " }\n" // " else{\n" // " out_Color = vec4(colorVertex.xyz, fiberOpacity);\n" // " }\n" // "}\n" // ); // localStorage->m_Actor->GetShaderProperty()->AddVertexShaderReplacement("//VTK::TCoord::Dec", true, "uniform vec4 slicingPlane;\n" // "out float fade_dist;", true); // localStorage->m_Actor->GetShaderProperty()->AddVertexShaderReplacement("//VTK::TCoord::Impl", true, "fade_dist = abs(dot(vertexMC.xyz, slicingPlane.xyz) - slicingPlane.w);", true); // localStorage->m_Actor->GetShaderProperty()->AddFragmentShaderReplacement("//VTK::TCoord::Dec", true, "uniform float fiberThickness;\n" // "in float fade_dist;\n" // "uniform int fiberFadingON;", true); //// std::string colorImpl = " if (fade_dist > fiberThickness) discard;\n" //// " vec3 ambientColor = ambientIntensity * vertexColorVSOutput.rgb;\n" //// " vec3 diffuseColor = diffuseIntensity * vertexColorVSOutput.rgb;\n" //// " float opacity = opacityUniform * vertexColorVSOutput.a;\n"; ////// " if (fiberFadingON != 0)\n" ////// " opacity = opacity*fade_dist;\n"; //// localStorage->m_Actor->GetShaderProperty()->AddFragmentShaderReplacement("//VTK::Color::Impl", true, colorImpl, true); // localStorage->m_Actor->GetShaderProperty()->AddFragmentShaderReplacement("//VTK::Clip::Impl", true, "for (int planeNum = 0; planeNum < numClipPlanes; planeNum++)\n" // " {\n" // " if (abs(clipDistancesVSOutput[planeNum]) > fiberThickness) discard;\n" // " }\n", true); // vtkSmartPointer<vtkShaderCallback> myCallback = vtkSmartPointer<vtkShaderCallback>::New(); // myCallback->renderer = renderer; // myCallback->node = this->GetDataNode(); // localStorage->m_Mapper->AddObserver(vtkCommand::UpdateShaderEvent,myCallback); localStorage->m_Actor->SetMapper(localStorage->m_Mapper); + + int lineWidth = 0; + node->GetIntProperty("shape.linewidth", lineWidth); + if (m_LineWidth!=lineWidth) + { + m_LineWidth = lineWidth; + fiberBundle->RequestUpdate2D(); + } + localStorage->m_Actor->GetProperty()->SetLineWidth(m_LineWidth); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { this->Update(renderer); return m_LocalStorageHandler.GetLocalStorage(renderer)->m_Actor; } void mitk::FiberBundleMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); // node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); } mitk::FiberBundleMapper2D::FBXLocalStorage::FBXLocalStorage() { m_Actor = vtkSmartPointer<vtkActor>::New(); m_Mapper = vtkSmartPointer<MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER>::New(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp index 09d0d27..0f36d5a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp @@ -1,1218 +1,1219 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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 <berryISelectionService.h> #include <berryIWorkbenchWindow.h> #include <berryIStructuredSelection.h> // Qmitk #include "QmitkStreamlineTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include <QMessageBox> #include <QFileDialog> // MITK #include <mitkLookupTable.h> #include <mitkLookupTableProperty.h> #include <mitkImageToItk.h> #include <mitkFiberBundle.h> #include <mitkImageCast.h> #include <mitkImageToItk.h> #include <mitkNodePredicateDataType.h> #include <mitkNodePredicateNot.h> #include <mitkNodePredicateAnd.h> #include <mitkNodePredicateProperty.h> #include <mitkNodePredicateDimension.h> #include <mitkOdfImage.h> #include <mitkShImage.h> #include <mitkSliceNavigationController.h> // VTK #include <vtkRenderWindowInteractor.h> #include <vtkPolyData.h> #include <vtkPoints.h> #include <vtkCellArray.h> #include <vtkSmartPointer.h> #include <vtkPolyLine.h> #include <vtkCellData.h> #include <itkTensorImageToOdfImageFilter.h> #include <omp.h> #include <mitkLexicalCast.h> const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStreamlineTrackingWorker::QmitkStreamlineTrackingWorker(QmitkStreamlineTrackingView* view) : m_View(view) { } void QmitkStreamlineTrackingWorker::run() { m_View->m_Tracker->Update(); m_View->m_TrackingThread.quit(); } QmitkStreamlineTrackingView::QmitkStreamlineTrackingView() : m_TrackingWorker(this) , m_Controls(nullptr) , m_FirstTensorProbRun(true) , m_FirstInteractiveRun(true) , m_TrackingHandler(nullptr) , m_ThreadIsRunning(false) , m_DeleteTrackingHandler(false) , m_Visible(false) , m_LastPrior(nullptr) , m_TrackingPriorHandler(nullptr) { m_TrackingWorker.moveToThread(&m_TrackingThread); connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); m_TrackingTimer = new QTimer(this); } // Destructor QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView() { if (m_Tracker.IsNull()) return; m_Tracker->SetStopTracking(true); m_TrackingThread.wait(); } void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStreamlineTrackingViewControls; m_Controls->setupUi( parent ); m_Controls->m_FaImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_SeedImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_TargetImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_PriorImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_StopImageSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_ForestSelectionWidget->SetDataStorage(this->GetDataStorage()); m_Controls->m_ExclusionImageSelectionWidget->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType<mitk::PeakImage>::Pointer isPeakImagePredicate = mitk::TNodePredicateDataType<mitk::PeakImage>::New(); mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New(); mitk::TNodePredicateDataType<mitk::TractographyForest>::Pointer isTractographyForest = mitk::TNodePredicateDataType<mitk::TractographyForest>::New(); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate ); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate ); mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); m_Controls->m_ForestSelectionWidget->SetNodePredicate(isTractographyForest); m_Controls->m_FaImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); m_Controls->m_FaImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_FaImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_SeedImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_SeedImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_SeedImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_MaskImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_MaskImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_MaskImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_StopImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_StopImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_StopImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_TargetImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_TargetImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_TargetImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_PriorImageSelectionWidget->SetNodePredicate( isPeakImagePredicate ); m_Controls->m_PriorImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_PriorImageSelectionWidget->SetSelectionIsOptional(true); m_Controls->m_ExclusionImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_ExclusionImageSelectionWidget->SetEmptyInfo("--"); m_Controls->m_ExclusionImageSelectionWidget->SetSelectionIsOptional(true); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); connect( m_Controls->m_SaveParametersButton, SIGNAL(clicked()), this, SLOT(SaveParameters()) ); connect( m_Controls->m_LoadParametersButton, SIGNAL(clicked()), this, SLOT(LoadParameters()) ); connect( m_Controls->commandLinkButton_2, SIGNAL(clicked()), this, SLOT(StopTractography()) ); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_InteractiveBox, SIGNAL(stateChanged(int)), this, SLOT(ToggleInteractive()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_FaImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::DeleteTrackingHandler ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) ); connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OutputStyleSwitched()) ); connect( m_Controls->m_SeedImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StopImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_TargetImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_PriorImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_ExclusionImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_MaskImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_FaImageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_ForestSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::ForestSwitched ); connect( m_Controls->m_ForestSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkStreamlineTrackingView::OnParameterChanged ); connect( m_Controls->m_SeedsPerVoxelBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_NumFibersBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_ScalarThresholdBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_OdfCutoffBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StepSizeBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SamplingDistanceBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_AngularThresholdBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MinTractLengthBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MaxTractLengthBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_fBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_gBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_NumSamplesBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SeedRadiusBox, SIGNAL(editingFinished()), this, SLOT(InteractiveSeedChanged()) ); connect( m_Controls->m_NumSeedsBox, SIGNAL(editingFinished()), this, SLOT(InteractiveSeedChanged()) ); connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SharpenOdfsBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_InterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MaskInterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipXBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipYBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipZBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_PriorFlipXBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_PriorFlipYBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_PriorFlipZBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FrontalSamplesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StopVotesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_LoopCheckBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_TrialsPerSeedBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_EpConstraintsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_PeakJitterBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); + connect( m_Controls->m_SecondOrderBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); m_Controls->m_SharpenOdfsBox->editingFinished(); m_Controls->m_SeedsPerVoxelBox->editingFinished(); m_Controls->m_NumFibersBox->editingFinished(); m_Controls->m_ScalarThresholdBox->editingFinished(); m_Controls->m_OdfCutoffBox->editingFinished(); m_Controls->m_StepSizeBox->editingFinished(); m_Controls->m_SamplingDistanceBox->editingFinished(); m_Controls->m_AngularThresholdBox->editingFinished(); m_Controls->m_MinTractLengthBox->editingFinished(); m_Controls->m_MaxTractLengthBox->editingFinished(); m_Controls->m_fBox->editingFinished(); m_Controls->m_gBox->editingFinished(); m_Controls->m_NumSamplesBox->editingFinished(); m_Controls->m_SeedRadiusBox->editingFinished(); m_Controls->m_NumSeedsBox->editingFinished(); m_Controls->m_LoopCheckBox->editingFinished(); m_Controls->m_TrialsPerSeedBox->editingFinished(); m_Controls->m_PeakJitterBox->editingFinished(); StartStopTrackingGui(false); } m_ParameterFile = QDir::currentPath()+"/param.stp"; UpdateGui(); } void QmitkStreamlineTrackingView::ParametersToGui(mitk::StreamlineTractographyParameters& params) { m_Controls->m_SeedRadiusBox->setValue(params.m_InteractiveRadiusMm); m_Controls->m_NumSeedsBox->setValue(params.m_NumInteractiveSeeds); m_Controls->m_InteractiveBox->setChecked(params.m_EnableInteractive); m_Controls->m_ResampleFibersBox->setChecked(params.m_CompressFibers); m_Controls->m_SeedRadiusBox->setValue(params.m_InteractiveRadiusMm); m_Controls->m_NumFibersBox->setValue(params.m_MaxNumFibers); m_Controls->m_ScalarThresholdBox->setValue(params.m_Cutoff); m_Controls->m_fBox->setValue(params.m_F); m_Controls->m_gBox->setValue(params.m_G); m_Controls->m_OdfCutoffBox->setValue(params.m_OdfCutoff); m_Controls->m_SharpenOdfsBox->setValue(params.m_SharpenOdfs); m_Controls->m_PriorWeightBox->setValue(params.m_Weight); m_Controls->m_PriorAsMaskBox->setChecked(params.m_RestrictToPrior); m_Controls->m_NewDirectionsFromPriorBox->setChecked(params.m_NewDirectionsFromPrior); m_Controls->m_PriorFlipXBox->setChecked(params.m_PriorFlipX); m_Controls->m_PriorFlipYBox->setChecked(params.m_PriorFlipY); m_Controls->m_PriorFlipZBox->setChecked(params.m_PriorFlipZ); m_Controls->m_FlipXBox->setChecked(params.m_FlipX); m_Controls->m_FlipYBox->setChecked(params.m_FlipY); m_Controls->m_FlipZBox->setChecked(params.m_FlipZ); m_Controls->m_InterpolationBox->setChecked(params.m_InterpolateTractographyData); m_Controls->m_MaskInterpolationBox->setChecked(params.m_InterpolateRoiImages); m_Controls->m_SeedsPerVoxelBox->setValue(params.m_SeedsPerVoxel); m_Controls->m_StepSizeBox->setValue(params.GetStepSizeVox()); m_Controls->m_SamplingDistanceBox->setValue(params.GetSamplingDistanceVox()); m_Controls->m_StopVotesBox->setChecked(params.m_StopVotes); m_Controls->m_FrontalSamplesBox->setChecked(params.m_OnlyForwardSamples); m_Controls->m_TrialsPerSeedBox->setValue(params.m_TrialsPerSeed); m_Controls->m_NumSamplesBox->setValue(params.m_NumSamples); m_Controls->m_LoopCheckBox->setValue(params.GetLoopCheckDeg()); m_Controls->m_AngularThresholdBox->setValue(params.GetAngularThresholdDeg()); m_Controls->m_MinTractLengthBox->setValue(params.m_MinTractLengthMm); m_Controls->m_MaxTractLengthBox->setValue(params.m_MaxTractLengthMm); m_Controls->m_OutputProbMap->setChecked(params.m_OutputProbMap); m_Controls->m_FixSeedBox->setChecked(params.m_FixRandomSeed); m_Controls->m_SecondOrderBox->setChecked(params.m_SecondOrder); m_Controls->m_PeakJitterBox->setValue(params.m_PeakJitter); switch (params.m_Mode) { case mitk::TrackingDataHandler::MODE::DETERMINISTIC: m_Controls->m_ModeBox->setCurrentIndex(0); break; case mitk::TrackingDataHandler::MODE::PROBABILISTIC: m_Controls->m_ModeBox->setCurrentIndex(1); break; } switch (params.m_EpConstraints) { case itk::StreamlineTrackingFilter::EndpointConstraints::NONE: m_Controls->m_EpConstraintsBox->setCurrentIndex(0); break; case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET: m_Controls->m_EpConstraintsBox->setCurrentIndex(1); break; case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF: m_Controls->m_EpConstraintsBox->setCurrentIndex(2); break; case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET: m_Controls->m_EpConstraintsBox->setCurrentIndex(3); break; case itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET: m_Controls->m_EpConstraintsBox->setCurrentIndex(4); break; case itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET: m_Controls->m_EpConstraintsBox->setCurrentIndex(5); break; case itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET: m_Controls->m_EpConstraintsBox->setCurrentIndex(6); break; } } std::shared_ptr<mitk::StreamlineTractographyParameters> QmitkStreamlineTrackingView::GetParametersFromGui() { std::shared_ptr<mitk::StreamlineTractographyParameters> params = std::make_shared<mitk::StreamlineTractographyParameters>(); // NOT IN GUI // unsigned int m_NumPreviousDirections = 1; // bool m_AvoidStop = true; // bool m_RandomSampling = false; // float m_DeflectionMod = 1.0; // bool m_ApplyDirectionMatrix = false; // NOT IN GUI BUT AUTOMATICALLY SET if (!m_InputImageNodes.empty()) { float min_sp = 999; auto spacing = dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())->GetGeometry()->GetSpacing(); if (spacing[0] < min_sp) min_sp = spacing[0]; if (spacing[1] < min_sp) min_sp = spacing[1]; if (spacing[2] < min_sp) min_sp = spacing[2]; params->m_Compression = min_sp/10; } params->m_InteractiveRadiusMm = m_Controls->m_SeedRadiusBox->value(); params->m_NumInteractiveSeeds = m_Controls->m_NumSeedsBox->value(); params->m_EnableInteractive = m_Controls->m_InteractiveBox->isChecked(); params->m_CompressFibers = m_Controls->m_ResampleFibersBox->isChecked(); params->m_InteractiveRadiusMm = m_Controls->m_SeedRadiusBox->value(); params->m_MaxNumFibers = m_Controls->m_NumFibersBox->value(); params->m_Cutoff = static_cast<float>(m_Controls->m_ScalarThresholdBox->value()); params->m_F = static_cast<float>(m_Controls->m_fBox->value()); params->m_G = static_cast<float>(m_Controls->m_gBox->value()); params->m_OdfCutoff = static_cast<float>(m_Controls->m_OdfCutoffBox->value()); params->m_SharpenOdfs = m_Controls->m_SharpenOdfsBox->value(); params->m_Weight = static_cast<float>(m_Controls->m_PriorWeightBox->value()); params->m_RestrictToPrior = m_Controls->m_PriorAsMaskBox->isChecked(); params->m_NewDirectionsFromPrior = m_Controls->m_NewDirectionsFromPriorBox->isChecked(); params->m_PriorFlipX = m_Controls->m_PriorFlipXBox->isChecked(); params->m_PriorFlipY = m_Controls->m_PriorFlipYBox->isChecked(); params->m_PriorFlipZ = m_Controls->m_PriorFlipZBox->isChecked(); params->m_FlipX = m_Controls->m_FlipXBox->isChecked(); params->m_FlipY = m_Controls->m_FlipYBox->isChecked(); params->m_FlipZ = m_Controls->m_FlipZBox->isChecked(); params->m_InterpolateTractographyData = m_Controls->m_InterpolationBox->isChecked(); params->m_InterpolateRoiImages = m_Controls->m_MaskInterpolationBox->isChecked(); params->m_SeedsPerVoxel = m_Controls->m_SeedsPerVoxelBox->value(); params->SetStepSizeVox(m_Controls->m_StepSizeBox->value()); params->SetSamplingDistanceVox(m_Controls->m_SamplingDistanceBox->value()); params->m_StopVotes = m_Controls->m_StopVotesBox->isChecked(); params->m_OnlyForwardSamples = m_Controls->m_FrontalSamplesBox->isChecked(); params->m_TrialsPerSeed = m_Controls->m_TrialsPerSeedBox->value(); params->m_NumSamples = m_Controls->m_NumSamplesBox->value(); params->SetLoopCheckDeg(m_Controls->m_LoopCheckBox->value()); params->SetAngularThresholdDeg(m_Controls->m_AngularThresholdBox->value()); params->m_MinTractLengthMm = m_Controls->m_MinTractLengthBox->value(); params->m_MaxTractLengthMm = m_Controls->m_MaxTractLengthBox->value(); params->m_OutputProbMap = m_Controls->m_OutputProbMap->isChecked(); params->m_FixRandomSeed = m_Controls->m_FixSeedBox->isChecked(); params->m_SecondOrder = m_Controls->m_SecondOrderBox->isChecked(); params->m_PeakJitter = static_cast<float>(m_Controls->m_PeakJitterBox->value()); switch (m_Controls->m_ModeBox->currentIndex()) { case 0: params->m_Mode = mitk::TrackingDataHandler::MODE::DETERMINISTIC; break; case 1: params->m_Mode = mitk::TrackingDataHandler::MODE::PROBABILISTIC; break; default: params->m_Mode = mitk::TrackingDataHandler::MODE::DETERMINISTIC; } switch (m_Controls->m_EpConstraintsBox->currentIndex()) { case 0: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NONE; break; case 1: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET; break; case 2: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF; break; case 3: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET; break; case 4: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET; break; case 5: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET; break; case 6: params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET; break; } return params; } void QmitkStreamlineTrackingView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Tractography Parameters"), m_ParameterFile, tr("Streamline Tractography Parameters (*.stp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; auto params = GetParametersFromGui(); params->SaveParameters(m_ParameterFile.toStdString()); } void QmitkStreamlineTrackingView::LoadParameters() { QString filename = QFileDialog::getOpenFileName( 0, tr("Load Tractography Parameters"), m_ParameterFile, tr("Streamline Tractography Parameters (*.stp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; mitk::StreamlineTractographyParameters params; params.LoadParameters(m_ParameterFile.toStdString()); ParametersToGui(params); } void QmitkStreamlineTrackingView::StopTractography() { if (m_Tracker.IsNull()) return; m_Tracker->SetStopTracking(true); } void QmitkStreamlineTrackingView::TimerUpdate() { if (m_Tracker.IsNull()) return; QString status_text(m_Tracker->GetStatusText().c_str()); m_Controls->m_StatusTextBox->setText(status_text); } void QmitkStreamlineTrackingView::BeforeThread() { m_TrackingTimer->start(1000); } void QmitkStreamlineTrackingView::AfterThread() { auto params = m_Tracker->GetParameters(); m_TrackingTimer->stop(); if (!params->m_OutputProbMap) { vtkSmartPointer<vtkPolyData> fiberBundle = m_Tracker->GetFiberPolyData(); if (!m_Controls->m_InteractiveBox->isChecked() && fiberBundle->GetNumberOfLines() == 0) { QMessageBox warnBox; warnBox.setWindowTitle("Warning"); warnBox.setText("No fiberbundle was generated!"); warnBox.setDetailedText("No fibers were generated using the chosen parameters. Typical reasons are:\n\n- Cutoff too high. Some images feature very low FA/GFA/peak size. Try to lower this parameter.\n- Angular threshold too strict. Try to increase this parameter.\n- A small step sizes also means many steps to go wrong. Especially in the case of probabilistic tractography. Try to adjust the angular threshold.\n- In case of probabilistic tractography, try to increase the parameter for ODF sharpening (for ODF and tensor tractography) or decrease the peak jitter (for peak tracking)."); warnBox.setIcon(QMessageBox::Warning); warnBox.exec(); if (m_InteractivePointSetNode.IsNotNull()) m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); StartStopTrackingGui(false); if (m_DeleteTrackingHandler) DeleteTrackingHandler(); UpdateGui(); return; } mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetTrackVisHeader(dynamic_cast<mitk::Image*>(m_ParentNode->GetData())->GetGeometry()); if (params->m_CompressFibers && fiberBundle->GetNumberOfLines()>0) fib->Compress(params->m_Compression); fib->ColorFibersByOrientation(); m_Tracker->SetDicomProperties(fib); mitk::DiffusionPropertyHelper::CopyDICOMProperties(m_ParentNode->GetData(), fib); if (m_Controls->m_InteractiveBox->isChecked()) { if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("Interactive"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } m_InteractiveNode->SetData(fib); m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", params->GetMinVoxelSizeMm()/2); if (auto renderWindowPart = this->GetRenderWindowPart()) renderWindowPart->RequestUpdate(); } else { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(fib); QString name("FiberBundle_"); name += m_ParentNode->GetName().c_str(); name += "_Streamline"; node->SetName(name.toStdString()); node->SetFloatProperty("Fiber2DSliceThickness", params->GetMinVoxelSizeMm()/2); GetDataStorage()->Add(node, m_ParentNode); } } else { TrackerType::ItkDoubleImgType::Pointer outImg = m_Tracker->GetOutputProbabilityMap(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); mitk::DiffusionPropertyHelper::CopyDICOMProperties(m_ParentNode->GetData(), img); if (m_Controls->m_InteractiveBox->isChecked()) { if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("Interactive"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } m_InteractiveNode->SetData(img); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType(mitk::LookupTable::JET_TRANSPARENT); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable(lut); m_InteractiveNode->SetProperty("LookupTable", lut_prop); m_InteractiveNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", params->GetMinVoxelSizeMm()/2); if (auto renderWindowPart = this->GetRenderWindowPart()) renderWindowPart->RequestUpdate(); } else { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); QString name("ProbabilityMap_"); name += m_ParentNode->GetName().c_str(); node->SetName(name.toStdString()); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType(mitk::LookupTable::JET_TRANSPARENT); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable(lut); node->SetProperty("LookupTable", lut_prop); node->SetProperty("opacity", mitk::FloatProperty::New(0.5)); GetDataStorage()->Add(node, m_ParentNode); } } if (m_InteractivePointSetNode.IsNotNull()) m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); StartStopTrackingGui(false); if (m_DeleteTrackingHandler) DeleteTrackingHandler(); UpdateGui(); } void QmitkStreamlineTrackingView::InteractiveSeedChanged(bool posChanged) { if(!CheckAndStoreLastParams(sender()) && !posChanged) return; if (m_ThreadIsRunning || !m_Visible) return; if (!posChanged && (!m_Controls->m_InteractiveBox->isChecked() || !m_Controls->m_ParamUpdateBox->isChecked()) ) return; std::srand(std::time(0)); m_SeedPoints.clear(); itk::Point<double> world_pos = this->GetRenderWindowPart()->GetSelectedPosition(); m_SeedPoints.push_back(world_pos); float radius = m_Controls->m_SeedRadiusBox->value(); int num = m_Controls->m_NumSeedsBox->value(); mitk::PointSet::Pointer pointset = mitk::PointSet::New(); pointset->InsertPoint(0, world_pos); m_InteractivePointSetNode->SetProperty("pointsize", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetProperty("point 2D size", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetData(pointset); for (int i=1; i<num; i++) { itk::Vector<float> p; p[0] = rand()%1000-500; p[1] = rand()%1000-500; p[2] = rand()%1000-500; p.Normalize(); p *= radius; m_SeedPoints.push_back(world_pos+p); } m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,0,0)); DoFiberTracking(); } bool QmitkStreamlineTrackingView::CheckAndStoreLastParams(QObject* obj) { if (obj!=nullptr) { std::string new_val = ""; if(qobject_cast<QDoubleSpinBox*>(obj)!=nullptr) new_val = boost::lexical_cast<std::string>(qobject_cast<QDoubleSpinBox*>(obj)->value()); else if (qobject_cast<QSpinBox*>(obj)!=nullptr) new_val = boost::lexical_cast<std::string>(qobject_cast<QSpinBox*>(obj)->value()); else return true; if (m_LastTractoParams.find(obj->objectName())==m_LastTractoParams.end()) { m_LastTractoParams[obj->objectName()] = new_val; return false; } else if (m_LastTractoParams.at(obj->objectName()) != new_val) { m_LastTractoParams[obj->objectName()] = new_val; return true; } else if (m_LastTractoParams.at(obj->objectName()) == new_val) return false; } return true; } void QmitkStreamlineTrackingView::OnParameterChanged() { UpdateGui(); if(!CheckAndStoreLastParams(sender())) return; if (m_Controls->m_InteractiveBox->isChecked() && m_Controls->m_ParamUpdateBox->isChecked()) DoFiberTracking(); } void QmitkStreamlineTrackingView::ToggleInteractive() { UpdateGui(); m_Controls->m_SeedsPerVoxelBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_SeedsPerVoxelLabel->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_SeedImageSelectionWidget->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->label_6->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); if ( m_Controls->m_InteractiveBox->isChecked() ) { if (m_FirstInteractiveRun) { QMessageBox::information(nullptr, "Information", "Place and move a spherical seed region anywhere in the image by left-clicking and dragging. If the seed region is colored red, tracking is in progress. If the seed region is colored white, tracking is finished.\nPlacing the seed region for the first time in a newly selected dataset might cause a short delay, since the tracker needs to be initialized."); m_FirstInteractiveRun = false; } QApplication::setOverrideCursor(Qt::PointingHandCursor); QApplication::processEvents(); m_InteractivePointSetNode = mitk::DataNode::New(); m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); m_InteractivePointSetNode->SetName("InteractiveSeedRegion"); mitk::PointSetShapeProperty::Pointer shape_prop = mitk::PointSetShapeProperty::New(); shape_prop->SetValue(mitk::PointSetShapeProperty::PointSetShape::CIRCLE); m_InteractivePointSetNode->SetProperty("Pointset.2D.shape", shape_prop); GetDataStorage()->Add(m_InteractivePointSetNode); m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); } else { QApplication::restoreOverrideCursor(); QApplication::processEvents(); m_InteractiveNode = nullptr; m_InteractivePointSetNode = nullptr; m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); disconnect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); } } void QmitkStreamlineTrackingView::Activated() { } void QmitkStreamlineTrackingView::Deactivated() { } void QmitkStreamlineTrackingView::Visible() { m_Visible = true; } void QmitkStreamlineTrackingView::Hidden() { m_Visible = false; m_Controls->m_InteractiveBox->setChecked(false); ToggleInteractive(); } void QmitkStreamlineTrackingView::OnSliceChanged() { InteractiveSeedChanged(true); } void QmitkStreamlineTrackingView::SetFocus() { } void QmitkStreamlineTrackingView::DeleteTrackingHandler() { if (!m_ThreadIsRunning && m_TrackingHandler != nullptr) { if (m_TrackingPriorHandler != nullptr) { delete m_TrackingPriorHandler; m_TrackingPriorHandler = nullptr; } delete m_TrackingHandler; m_TrackingHandler = nullptr; m_DeleteTrackingHandler = false; m_LastPrior = nullptr; } else if (m_ThreadIsRunning) { m_DeleteTrackingHandler = true; } } void QmitkStreamlineTrackingView::ForestSwitched() { DeleteTrackingHandler(); } void QmitkStreamlineTrackingView::OutputStyleSwitched() { if (m_InteractiveNode.IsNotNull()) GetDataStorage()->Remove(m_InteractiveNode); m_InteractiveNode = nullptr; } void QmitkStreamlineTrackingView::OnSelectionChanged( berry::IWorkbenchPart::Pointer , const QList<mitk::DataNode::Pointer>& nodes ) { std::vector< mitk::DataNode::Pointer > last_nodes = m_InputImageNodes; m_InputImageNodes.clear(); m_AdditionalInputImages.clear(); bool retrack = false; for( auto node : nodes ) { if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) ) { if( dynamic_cast<mitk::TensorImage*>(node->GetData()) || dynamic_cast<mitk::OdfImage*>(node->GetData()) || dynamic_cast<mitk::ShImage*>(node->GetData()) || dynamic_cast<mitk::PeakImage*>(node->GetData()) || mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(node->GetData()))) { m_InputImageNodes.push_back(node); retrack = true; } else { mitk::Image* img = dynamic_cast<mitk::Image*>(node->GetData()); if (img!=nullptr && img->GetDimension()==3) m_AdditionalInputImages.push_back(dynamic_cast<mitk::Image*>(node->GetData())); } } } // sometimes the OnSelectionChanged event is sent twice and actually no selection has changed for the first event. We need to catch that. if (last_nodes.size() == m_InputImageNodes.size()) { bool same_nodes = true; for (unsigned int i=0; i<m_InputImageNodes.size(); i++) if (last_nodes.at(i)!=m_InputImageNodes.at(i)) { same_nodes = false; break; } if (same_nodes) return; } DeleteTrackingHandler(); UpdateGui(); if (retrack) OnParameterChanged(); } void QmitkStreamlineTrackingView::UpdateGui() { m_Controls->m_TensorImageLabel->setText("<font color='red'>select in data-manager</font>"); m_Controls->m_fBox->setEnabled(false); m_Controls->m_fLabel->setEnabled(false); m_Controls->m_gBox->setEnabled(false); m_Controls->m_gLabel->setEnabled(false); m_Controls->m_FaImageSelectionWidget->setEnabled(true); m_Controls->mFaImageLabel->setEnabled(true); m_Controls->m_OdfCutoffBox->setEnabled(false); m_Controls->m_OdfCutoffLabel->setEnabled(false); m_Controls->m_SharpenOdfsBox->setEnabled(false); m_Controls->m_ForestSelectionWidget->setVisible(false); m_Controls->m_ForestLabel->setVisible(false); m_Controls->commandLinkButton->setEnabled(false); m_Controls->m_TrialsPerSeedBox->setEnabled(false); m_Controls->m_TrialsPerSeedLabel->setEnabled(false); m_Controls->m_TargetImageSelectionWidget->setEnabled(false); m_Controls->m_TargetImageLabel->setEnabled(false); m_Controls->m_PeakJitterBox->setEnabled(false); if (m_Controls->m_InteractiveBox->isChecked()) { m_Controls->m_InteractiveSeedingFrame->setVisible(true); m_Controls->m_StaticSeedingFrame->setVisible(false); m_Controls->commandLinkButton_2->setVisible(false); m_Controls->commandLinkButton->setVisible(false); } else { m_Controls->m_InteractiveSeedingFrame->setVisible(false); m_Controls->m_StaticSeedingFrame->setVisible(true); m_Controls->commandLinkButton_2->setVisible(m_ThreadIsRunning); m_Controls->commandLinkButton->setVisible(!m_ThreadIsRunning); } if (m_Controls->m_EpConstraintsBox->currentIndex()>0) { m_Controls->m_TargetImageSelectionWidget->setEnabled(true); m_Controls->m_TargetImageLabel->setEnabled(true); } // stuff that is only important for probabilistic tractography if (m_Controls->m_ModeBox->currentIndex()==1) { m_Controls->m_TrialsPerSeedBox->setEnabled(true); m_Controls->m_TrialsPerSeedLabel->setEnabled(true); } if(!m_InputImageNodes.empty()) { if (m_InputImageNodes.size()>1) m_Controls->m_TensorImageLabel->setText( ( std::to_string(m_InputImageNodes.size()) + " images selected").c_str() ); else m_Controls->m_TensorImageLabel->setText(m_InputImageNodes.at(0)->GetName().c_str()); m_Controls->commandLinkButton->setEnabled(!m_Controls->m_InteractiveBox->isChecked() && !m_ThreadIsRunning); m_Controls->m_ScalarThresholdBox->setEnabled(true); m_Controls->m_FaThresholdLabel->setEnabled(true); if ( dynamic_cast<mitk::TensorImage*>(m_InputImageNodes.at(0)->GetData()) ) { if (m_Controls->m_ModeBox->currentIndex()==1) { m_Controls->m_OdfCutoffBox->setEnabled(true); m_Controls->m_OdfCutoffLabel->setEnabled(true); m_Controls->m_SharpenOdfsBox->setEnabled(true); } else { m_Controls->m_fBox->setEnabled(true); m_Controls->m_fLabel->setEnabled(true); m_Controls->m_gBox->setEnabled(true); m_Controls->m_gLabel->setEnabled(true); } } else if ( dynamic_cast<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData()) || dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData())) { m_Controls->m_OdfCutoffBox->setEnabled(true); m_Controls->m_OdfCutoffLabel->setEnabled(true); m_Controls->m_SharpenOdfsBox->setEnabled(true); } else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(m_InputImageNodes.at(0)->GetData())) ) { m_Controls->m_ForestSelectionWidget->setVisible(true); m_Controls->m_ForestLabel->setVisible(true); m_Controls->m_ScalarThresholdBox->setEnabled(false); m_Controls->m_FaThresholdLabel->setEnabled(false); } else if ( dynamic_cast<mitk::PeakImage*>(m_InputImageNodes.at(0)->GetData()) && m_Controls->m_ModeBox->currentIndex()==1) { m_Controls->m_PeakJitterBox->setEnabled(true); } } } void QmitkStreamlineTrackingView::StartStopTrackingGui(bool start) { m_ThreadIsRunning = start; if (!m_Controls->m_InteractiveBox->isChecked()) { m_Controls->commandLinkButton_2->setVisible(start); m_Controls->commandLinkButton->setVisible(!start); m_Controls->m_InteractiveBox->setEnabled(!start); m_Controls->m_StatusTextBox->setVisible(start); } } void QmitkStreamlineTrackingView::DoFiberTracking() { auto params = GetParametersFromGui(); if (m_InputImageNodes.empty()) { QMessageBox::information(nullptr, "Information", "Please select an input image in the datamaneger (tensor, ODF, peak or dMRI image)!"); return; } if (m_ThreadIsRunning || !m_Visible) return; if (m_Controls->m_InteractiveBox->isChecked() && m_SeedPoints.empty()) return; StartStopTrackingGui(true); m_Tracker = TrackerType::New(); if (params->m_EpConstraints == itk::StreamlineTrackingFilter::EndpointConstraints::NONE) m_Tracker->SetTargetRegions(nullptr); if( dynamic_cast<mitk::TensorImage*>(m_InputImageNodes.at(0)->GetData()) ) { if (m_Controls->m_ModeBox->currentIndex()==1) { if (m_InputImageNodes.size()>1) { QMessageBox::information(nullptr, "Information", "Probabilistic tensor tractography is only implemented for single-tensor mode!"); StartStopTrackingGui(false); return; } if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerOdf(); typedef itk::TensorImageToOdfImageFilter< float, float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( mitk::convert::GetItkTensorFromTensorImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())) ); filter->Update(); dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(filter->GetOutput()); if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg); dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetGfaImage(itkImg); } } dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetIsOdfFromTensor(true); } else { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerTensor(); for (unsigned int i=0; i<m_InputImageNodes.size(); ++i) dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler)->AddTensorImage(mitk::convert::GetItkTensorFromTensorImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(i)->GetData())).GetPointer()); if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg); dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler)->SetFaImage(itkImg); } } } } else if ( dynamic_cast<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData()) || dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData())) { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerOdf(); if (dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData())) dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(mitk::convert::GetItkOdfFromShImage(dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData()))); else dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(mitk::convert::GetItkOdfFromOdfImage(dynamic_cast<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData()))); if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg); dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetGfaImage(itkImg); } } } else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())) ) { if ( m_Controls->m_ForestSelectionWidget->GetSelectedNode().IsNull() ) { QMessageBox::information(nullptr, "Information", "Not random forest for machine learning based tractography (raw dMRI tractography) selected. Did you accidentally select the raw diffusion-weighted image in the datamanager?"); StartStopTrackingGui(false); return; } if (m_TrackingHandler==nullptr) { mitk::TractographyForest::Pointer forest = dynamic_cast<mitk::TractographyForest*>(m_Controls->m_ForestSelectionWidget->GetSelectedNode()->GetData()); mitk::Image::Pointer dwi = dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData()); std::vector< std::vector< ItkFloatImageType::Pointer > > additionalFeatureImages; additionalFeatureImages.push_back(std::vector< ItkFloatImageType::Pointer >()); for (auto img : m_AdditionalInputImages) { ItkFloatImageType::Pointer itkimg = ItkFloatImageType::New(); mitk::CastToItkImage(img, itkimg); additionalFeatureImages.at(0).push_back(itkimg); } bool forest_valid = false; if (forest->GetNumFeatures()>=100) { params->m_NumPreviousDirections = static_cast<unsigned int>((forest->GetNumFeatures() - (100 + additionalFeatureImages.at(0).size()))/3); m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 100>(); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->AddDwi(dwi); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->SetForest(forest); forest_valid = dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->IsForestValid(); } else { params->m_NumPreviousDirections = static_cast<unsigned int>((forest->GetNumFeatures() - (28 + additionalFeatureImages.at(0).size()))/3); m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 28>(); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->AddDwi(dwi); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages); dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->SetForest(forest); forest_valid = dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->IsForestValid(); } if (!forest_valid) { QMessageBox::information(nullptr, "Information", "Random forest is invalid. The forest signatue does not match the parameters of TrackingHandlerRandomForest."); StartStopTrackingGui(false); return; } } } else { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerPeaks(); dynamic_cast<mitk::TrackingHandlerPeaks*>(m_TrackingHandler)->SetPeakImage(mitk::convert::GetItkPeakFromPeakImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData()))); } } if (m_Controls->m_InteractiveBox->isChecked()) { m_Tracker->SetSeedPoints(m_SeedPoints); } else if (m_Controls->m_SeedImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_SeedImageSelectionWidget->GetSelectedNode()->GetData()), mask); m_Tracker->SetSeedImage(mask); } if (m_Controls->m_MaskImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_MaskImageSelectionWidget->GetSelectedNode()->GetData()), mask); m_Tracker->SetMaskImage(mask); } if (m_Controls->m_StopImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_StopImageSelectionWidget->GetSelectedNode()->GetData()), mask); m_Tracker->SetStoppingRegions(mask); } if (m_Controls->m_TargetImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_TargetImageSelectionWidget->GetSelectedNode()->GetData()), mask); m_Tracker->SetTargetRegions(mask); } if (m_Controls->m_PriorImageSelectionWidget->GetSelectedNode().IsNotNull()) { auto prior_params = GetParametersFromGui(); if (m_LastPrior!=m_Controls->m_PriorImageSelectionWidget->GetSelectedNode() || m_TrackingPriorHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(dynamic_cast<mitk::PeakImage*>(m_Controls->m_PriorImageSelectionWidget->GetSelectedNode()->GetData())); caster->SetCopyMemFlag(true); caster->Update(); mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput(); m_TrackingPriorHandler = new mitk::TrackingHandlerPeaks(); dynamic_cast<mitk::TrackingHandlerPeaks*>(m_TrackingPriorHandler)->SetPeakImage(itkImg); m_LastPrior = m_Controls->m_PriorImageSelectionWidget->GetSelectedNode(); } prior_params->m_FlipX = m_Controls->m_PriorFlipXBox->isChecked(); prior_params->m_FlipY = m_Controls->m_PriorFlipYBox->isChecked(); prior_params->m_FlipZ = m_Controls->m_PriorFlipZBox->isChecked(); m_TrackingPriorHandler->SetParameters(prior_params); m_Tracker->SetTrackingPriorHandler(m_TrackingPriorHandler); } else if (m_Controls->m_PriorImageSelectionWidget->GetSelectedNode().IsNull()) m_Tracker->SetTrackingPriorHandler(nullptr); if (m_Controls->m_ExclusionImageSelectionWidget->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_ExclusionImageSelectionWidget->GetSelectedNode()->GetData()), mask); m_Tracker->SetExclusionRegions(mask); } if (params->m_EpConstraints!=itk::StreamlineTrackingFilter::EndpointConstraints::NONE && m_Controls->m_TargetImageSelectionWidget->GetSelectedNode().IsNull()) { QMessageBox::information(nullptr, "Error", "Endpoint constraints are used but no target image is set!"); StartStopTrackingGui(false); return; } else if (params->m_EpConstraints==itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET && (m_Controls->m_SeedImageSelectionWidget->GetSelectedNode().IsNull()|| m_Controls->m_TargetImageSelectionWidget->GetSelectedNode().IsNull()) ) { QMessageBox::information(nullptr, "Error", "Endpoint constraint EPS_IN_SEED_AND_TARGET is used but no target or no seed image is set!"); StartStopTrackingGui(false); return; } float min_sp = 999; auto spacing = dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())->GetGeometry()->GetSpacing(); if (spacing[0] < min_sp) min_sp = spacing[0]; if (spacing[1] < min_sp) min_sp = spacing[1]; if (spacing[2] < min_sp) min_sp = spacing[2]; params->m_Compression = min_sp/10; // float max_size = 0; // for (int i=0; i<3; ++i) // if (dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())->GetGeometry()->GetExtentInMM(i)>max_size) // max_size = dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())->GetGeometry()->GetExtentInMM(i); // if (params->m_MinTractLengthMm >= max_size) // { // MITK_INFO << "Max. image size: " << max_size << "mm"; // MITK_INFO << "Min. tract length: " << params->m_MinTractLengthMm << "mm"; // QMessageBox::information(nullptr, "Error", "Minimum tract length exceeds the maximum image extent! Recommended value is about 1/10 of the image extent."); // StartStopTrackingGui(false); // return; // } // else if (params->m_MinTractLengthMm > max_size/10) // { // MITK_INFO << "Max. image size: " << max_size << "mm"; // MITK_INFO << "Min. tract length: " << params->m_MinTractLengthMm << "mm"; // MITK_WARN << "Minimum tract length is larger than 1/10 the maximum image extent! Decrease recommended."; // } m_Tracker->SetParameters(params); m_Tracker->SetTrackingHandler(m_TrackingHandler); m_Tracker->SetVerbose(!m_Controls->m_InteractiveBox->isChecked()); m_ParentNode = m_InputImageNodes.at(0); m_TrackingThread.start(QThread::LowestPriority); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui index 5e8138d..7acc145 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingViewControls.ui @@ -1,1674 +1,1674 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>QmitkStreamlineTrackingViewControls</class> <widget class="QWidget" name="QmitkStreamlineTrackingViewControls"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>453</width> <height>859</height> </rect> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="windowTitle"> <string>QmitkTemplate</string> </property> <property name="styleSheet"> <string>QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; }</string> </property> <layout class="QGridLayout" name="gridLayout_11"> <property name="topMargin"> <number>3</number> </property> <property name="bottomMargin"> <number>3</number> </property> <property name="horizontalSpacing"> <number>0</number> </property> <property name="verticalSpacing"> <number>40</number> </property> <item row="1" column="0"> <widget class="QFrame" name="frame_6"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_12"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>15</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <property name="horizontalSpacing"> <number>6</number> </property> <property name="verticalSpacing"> <number>15</number> </property> <item row="1" column="0"> <widget class="QTextEdit" name="m_StatusTextBox"> <property name="enabled"> <bool>true</bool> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> <item row="4" column="0"> <widget class="QFrame" name="frame_11"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_21"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <property name="verticalSpacing"> <number>0</number> </property> <item row="0" column="1"> <widget class="QCommandLinkButton" name="m_SaveParametersButton"> <property name="enabled"> <bool>true</bool> </property> <property name="toolTip"> <string>Save parameters to json file</string> </property> <property name="text"> <string>Save Parameters</string> </property> <property name="icon"> <iconset resource="../../resources/QmitkTractography.qrc"> <normaloff>:/QmitkTractography/download.png</normaloff>:/QmitkTractography/download.png</iconset> </property> </widget> </item> <item row="0" column="0"> <widget class="QCommandLinkButton" name="m_LoadParametersButton"> <property name="enabled"> <bool>true</bool> </property> <property name="toolTip"> <string>Load parameters from json file</string> </property> <property name="text"> <string>Load Parameters</string> </property> <property name="icon"> <iconset resource="../../resources/QmitkTractography.qrc"> <normaloff>:/QmitkTractography/upload.png</normaloff>:/QmitkTractography/upload.png</iconset> </property> </widget> </item> </layout> </widget> </item> <item row="3" column="0"> <widget class="QCommandLinkButton" name="commandLinkButton"> <property name="enabled"> <bool>false</bool> </property> <property name="text"> <string>Start Tractography</string> </property> <property name="icon"> <iconset resource="../../resources/QmitkTractography.qrc"> <normaloff>:/QmitkTractography/right.png</normaloff>:/QmitkTractography/right.png</iconset> </property> </widget> </item> <item row="2" column="0"> <widget class="QCommandLinkButton" name="commandLinkButton_2"> <property name="enabled"> <bool>true</bool> </property> <property name="toolTip"> <string>Stop tractography and return all fibers reconstructed until now.</string> </property> <property name="text"> <string>Stop Tractography</string> </property> <property name="icon"> <iconset resource="../../resources/QmitkTractography.qrc"> <normaloff>:/QmitkTractography/stop.png</normaloff>:/QmitkTractography/stop.png</iconset> </property> </widget> </item> <item row="0" column="0"> <widget class="QFrame" name="frame_9"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_19"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QLabel" name="label_2"> <property name="toolTip"> <string>Input Image. ODF, tensor and peak images are currently supported.</string> </property> <property name="text"> <string>Input Image:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QLabel" name="m_TensorImageLabel"> <property name="toolTip"> <string>Input Image. ODF, tensor, peak, and, in case of ML tractography, raw diffusion-weighted images are currently supported.</string> </property> <property name="text"> <string><html><head/><body><p><span style=" color:#ff0000;">select image in data-manager</span></p></body></html></string> </property> <property name="wordWrap"> <bool>true</bool> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="m_ForestLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Tractography Forest:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_ForestSelectionWidget" native="true"> <property name="styleSheet"> <string notr="true"/> </property> </widget> </item> </layout> </widget> </item> </layout> </widget> </item> <item row="2" column="0" rowspan="6"> <widget class="QToolBox" name="toolBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="font"> <font> <bold>true</bold> </font> </property> <property name="currentIndex"> <number>0</number> </property> <widget class="QWidget" name="page_seed"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>421</width> <height>254</height> </rect> </property> <attribute name="label"> <string>Seeding</string> </attribute> <attribute name="toolTip"> <string>Specify how, where and how many tractography seed points are placed.</string> </attribute> <layout class="QGridLayout" name="gridLayout_17"> <item row="0" column="0"> <widget class="QFrame" name="m_InteractiveSeedingFrame"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_15"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="1" column="0"> <widget class="QFrame" name="frame_7"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_13"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="2" column="1"> <widget class="QSpinBox" name="m_NumSeedsBox"> <property name="toolTip"> <string>Number of seed points equally distributed around selected position. </string> </property> <property name="minimum"> <number>1</number> </property> <property name="maximum"> <number>9999999</number> </property> <property name="value"> <number>50</number> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="m_FaThresholdLabel_4"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Radius:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QDoubleSpinBox" name="m_SeedRadiusBox"> <property name="toolTip"> <string>Seedpoints are equally distributed within a sphere centered at the selected position with the specified radius (in mm).</string> </property> <property name="decimals"> <number>2</number> </property> <property name="maximum"> <double>50.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>2.000000000000000</double> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="m_SeedsPerVoxelLabel_4"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Num. Seeds:</string> </property> </widget> </item> </layout> </widget> </item> <item row="0" column="0"> <widget class="QCheckBox" name="m_ParamUpdateBox"> <property name="enabled"> <bool>true</bool> </property> <property name="toolTip"> <string>When checked, parameter changes cause instant retracking while in interactive mode.</string> </property> <property name="text"> <string>Update on Parameter Change </string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> </layout> </widget> </item> <item row="2" column="0"> <widget class="QFrame" name="frame_8"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_16"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="0" column="1"> <widget class="QSpinBox" name="m_TrialsPerSeedBox"> <property name="toolTip"> <string>Try each seed N times until a valid streamline is obtained (only for probabilistic tractography).</string> </property> <property name="statusTip"> <string>Minimum fiber length (in mm)</string> </property> <property name="minimum"> <number>1</number> </property> <property name="maximum"> <number>999</number> </property> <property name="value"> <number>10</number> </property> </widget> </item> <item row="0" column="0"> <widget class="QLabel" name="m_TrialsPerSeedLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Trials Per Seed:</string> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="m_FaThresholdLabel_2"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Max. Num. Fibers:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QSpinBox" name="m_NumFibersBox"> <property name="toolTip"> <string>Tractography is stopped after the desired number of fibers is reached, even before all seed points are processed (-1 means no limit).</string> </property> <property name="minimum"> <number>-1</number> </property> <property name="maximum"> <number>999999999</number> </property> <property name="value"> <number>-1</number> </property> </widget> </item> </layout> </widget> </item> <item row="1" column="0"> <widget class="QFrame" name="m_StaticSeedingFrame"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_2"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="2" column="0"> <widget class="QLabel" name="m_SeedsPerVoxelLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Seeds per Voxel:</string> </property> </widget> </item> <item row="0" column="0"> <widget class="QLabel" name="label_6"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Seed Image:</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QSpinBox" name="m_SeedsPerVoxelBox"> <property name="toolTip"> <string>Number of seed points placed in each voxel.</string> </property> <property name="minimum"> <number>1</number> </property> <property name="maximum"> <number>9999999</number> </property> </widget> </item> <item row="0" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_SeedImageSelectionWidget" native="true"> <property name="styleSheet"> <string notr="true"/> </property> </widget> </item> </layout> </widget> </item> <item row="3" column="0"> <widget class="QCheckBox" name="m_InteractiveBox"> <property name="enabled"> <bool>true</bool> </property> <property name="toolTip"> <string>Dynamically pick a seed location by click into image.</string> </property> <property name="text"> <string>Enable Interactive Tractography</string> </property> </widget> </item> <item row="4" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> </layout> </widget> <widget class="QWidget" name="page_constraints"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>541</width> <height>175</height> </rect> </property> <attribute name="label"> <string>ROI Constraints</string> </attribute> <attribute name="toolTip"> <string>Specify various ROI and mask images to constrain the tractography process.</string> </attribute> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="label_7"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Mask Image:</string> </property> </widget> </item> <item row="3" column="1"> <widget class="QComboBox" name="m_EpConstraintsBox"> <property name="toolTip"> <string>Select which fibers should be accepted or rejected based on the location of their endpoints.</string> </property> <item> <property name="text"> <string>No Constraints on EP locations</string> </property> </item> <item> <property name="text"> <string>Both EPs in Target Image</string> </property> </item> <item> <property name="text"> <string>Both EPs in Target Image But Different Label</string> </property> </item> <item> <property name="text"> <string>One EP in Seed Image and One EP in Target Image</string> </property> </item> <item> <property name="text"> <string>At Least One EP in Target Image</string> </property> </item> <item> <property name="text"> <string>Exactly One EP in Target Image</string> </property> </item> <item> <property name="text"> <string>No EP in Target Image</string> </property> </item> </widget> </item> <item row="3" column="0"> <widget class="QLabel" name="label_10"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Endpoint Constraints:</string> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="label_9"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Stop ROI Image:</string> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="label_11"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Exclusion ROI Image:</string> </property> </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="m_TargetImageLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Target ROI Image:</string> </property> </widget> </item> <item row="6" column="0"> <spacer name="verticalSpacer_6"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="0" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_MaskImageSelectionWidget" native="true"/> </item> <item row="1" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_StopImageSelectionWidget" native="true"/> </item> <item row="2" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_ExclusionImageSelectionWidget" native="true"/> </item> <item row="4" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_TargetImageSelectionWidget" native="true"/> </item> </layout> </widget> <widget class="QWidget" name="page_trackingparam"> <property name="geometry"> <rect> <x>0</x> <y>-270</y> <width>421</width> <height>459</height> </rect> </property> <attribute name="label"> <string>Tractography Parameters</string> </attribute> <attribute name="toolTip"> <string>Specify the behavior of the tractography at each streamline integration step (step size, deterministic/probabilistic, ...).</string> </attribute> <layout class="QGridLayout" name="gridLayout_14"> <item row="5" column="1"> <widget class="QDoubleSpinBox" name="m_OdfCutoffBox"> <property name="toolTip"> <string>Additional threshold on the ODF magnitude. This is useful in case of CSD fODF tractography. For fODFs a good default value is 0.1, for normalized dODFs, e.g. Q-ball ODFs, this threshold should be very low (0.00025) or 0.</string> </property> <property name="decimals"> <number>5</number> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.000250000000000</double> </property> </widget> </item> <item row="14" column="1"> <widget class="QDoubleSpinBox" name="m_PeakJitterBox"> <property name="toolTip"> <string>Important for probabilistic peak tractography and peak prior. Actual jitter is drawn from a normal distribution with peak_jitter*fabs(direction_value) as standard deviation.</string> </property> <property name="decimals"> <number>3</number> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.010000000000000</double> </property> </widget> </item> <item row="16" column="0"> <widget class="QLabel" name="m_FaThresholdLabel_6"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Fix Random Seed:</string> </property> </widget> </item> <item row="18" column="0"> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="1" column="0"> <widget class="QLabel" name="m_FaThresholdLabel_3"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Mode:</string> </property> </widget> </item> <item row="3" column="0"> <widget class="QLabel" name="m_FaThresholdLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Cutoff:</string> </property> </widget> </item> <item row="8" column="1"> <widget class="QDoubleSpinBox" name="m_MinTractLengthBox"> <property name="toolTip"> <string>Minimum tract length in mm. Shorter fibers are discarded.</string> </property> <property name="statusTip"> <string>Minimum fiber length (in mm)</string> </property> <property name="decimals"> <number>1</number> </property> <property name="maximum"> <double>999.000000000000000</double> </property> <property name="singleStep"> <double>1.000000000000000</double> </property> <property name="value"> <double>20.000000000000000</double> </property> </widget> </item> <item row="10" column="0"> <widget class="QLabel" name="m_AngularThresholdLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Angular Threshold:</string> </property> </widget> </item> <item row="12" column="1"> <widget class="QDoubleSpinBox" name="m_fBox"> <property name="toolTip"> <string>f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).</string> </property> <property name="decimals"> <number>2</number> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>1.000000000000000</double> </property> </widget> </item> <item row="11" column="1"> <widget class="QSpinBox" name="m_LoopCheckBox"> <property name="toolTip"> <string>Maximum allowed angular SDTEV over 4 voxel lengths. Default: 30°</string> </property> <property name="statusTip"> <string/> </property> <property name="minimum"> <number>-1</number> </property> <property name="maximum"> <number>180</number> </property> <property name="value"> <number>30</number> </property> </widget> </item> <item row="13" column="0"> <widget class="QLabel" name="m_gLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>g:</string> </property> </widget> </item> <item row="16" column="1"> <widget class="QCheckBox" name="m_FixSeedBox"> <property name="toolTip"> <string>Always produce the same random numbers.</string> </property> <property name="text"> <string/> </property> </widget> </item> <item row="9" column="1"> <widget class="QDoubleSpinBox" name="m_MaxTractLengthBox"> <property name="toolTip"> <string>Minimum tract length in mm. Shorter fibers are discarded.</string> </property> <property name="statusTip"> <string>Maximum fiber length (in mm)</string> </property> <property name="decimals"> <number>1</number> </property> <property name="maximum"> <double>999.000000000000000</double> </property> <property name="singleStep"> <double>1.000000000000000</double> </property> <property name="value"> <double>400.000000000000000</double> </property> </widget> </item> <item row="6" column="1"> <widget class="QDoubleSpinBox" name="m_StepSizeBox"> <property name="toolTip"> <string>Step size (in voxels)</string> </property> <property name="decimals"> <number>2</number> </property> <property name="minimum"> <double>0.010000000000000</double> </property> <property name="maximum"> <double>10.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.500000000000000</double> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="m_FaThresholdLabel_5"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Sharpen ODFs:</string> </property> </widget> </item> <item row="3" column="1"> <widget class="QDoubleSpinBox" name="m_ScalarThresholdBox"> <property name="toolTip"> <string>Threshold on peak magnitude, FA, GFA, ...</string> </property> <property name="decimals"> <number>5</number> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.100000000000000</double> </property> </widget> </item> <item row="4" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_FaImageSelectionWidget" native="true"/> </item> <item row="14" column="0"> <widget class="QLabel" name="m_PeakJitterLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Peak Jitter:</string> </property> </widget> </item> <item row="11" column="0"> <widget class="QLabel" name="m_LoopCheckLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Loop Check:</string> </property> </widget> </item> <item row="6" column="0"> <widget class="QLabel" name="m_StepsizeLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Step Size:</string> </property> </widget> </item> <item row="9" column="0"> <widget class="QLabel" name="m_MinTractLengthLabel_2"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Max. Tract Length:</string> </property> </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="mFaImageLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>FA/GFA Image:</string> </property> </widget> </item> <item row="5" column="0"> <widget class="QLabel" name="m_OdfCutoffLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>ODF Cutoff:</string> </property> </widget> </item> <item row="13" column="1"> <widget class="QDoubleSpinBox" name="m_gBox"> <property name="toolTip"> <string>f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).</string> </property> <property name="decimals"> <number>2</number> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.000000000000000</double> </property> </widget> </item> <item row="10" column="1"> <widget class="QSpinBox" name="m_AngularThresholdBox"> <property name="toolTip"> <string>Angular threshold between two steps (in degree). Default: 90° * step_size</string> </property> <property name="minimum"> <number>-1</number> </property> <property name="maximum"> <number>90</number> </property> <property name="singleStep"> <number>1</number> </property> <property name="value"> <number>-1</number> </property> </widget> </item> <item row="1" column="1"> <widget class="QComboBox" name="m_ModeBox"> <property name="toolTip"> <string>Toggle between deterministic and probabilistic tractography. Some modes might not be available for all types of tractography.</string> </property> <item> <property name="text"> <string>Deterministic</string> </property> </item> <item> <property name="text"> <string>Probabilistic</string> </property> </item> </widget> </item> <item row="12" column="0"> <widget class="QLabel" name="m_fLabel"> <property name="toolTip"> <string>f parameter of tensor tractography. f=1 + g=0 means FACT (depending on the chosen interpolation). f=0 and g=1 means TEND (disable interpolation for this mode!).</string> </property> <property name="text"> <string>f:</string> </property> </widget> </item> <item row="8" column="0"> <widget class="QLabel" name="m_MinTractLengthLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Min. Tract Length:</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QSpinBox" name="m_SharpenOdfsBox"> <property name="toolTip"> <string>Rais ODF to the power of X</string> </property> <property name="minimum"> <number>1</number> </property> <property name="value"> <number>8</number> </property> </widget> </item> <item row="15" column="0"> <widget class="QLabel" name="m_SecondOrderLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Second Order:</string> </property> </widget> </item> <item row="15" column="1"> <widget class="QCheckBox" name="m_SecondOrderBox"> <property name="toolTip"> - <string>Always produce the same random numbers.</string> + <string>Use second order integration to avoid streamline overshoot</string> </property> <property name="text"> <string/> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> </layout> </widget> <widget class="QWidget" name="page_prior"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>435</width> <height>189</height> </rect> </property> <attribute name="label"> <string>Tractography Prior</string> </attribute> <layout class="QGridLayout" name="gridLayout_9"> <item row="1" column="0"> <widget class="QLabel" name="m_PriorLabel_2"> <property name="text"> <string>Weight:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QDoubleSpinBox" name="m_PriorWeightBox"> <property name="toolTip"> <string>Weighting factor between prior and data.</string> </property> <property name="maximum"> <double>1.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.500000000000000</double> </property> </widget> </item> <item row="0" column="0"> <widget class="QLabel" name="m_PriorLabel"> <property name="text"> <string>Peak Image:</string> </property> </widget> </item> <item row="5" column="0"> <spacer name="verticalSpacer_7"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="3" column="1"> <widget class="QCheckBox" name="m_NewDirectionsFromPriorBox"> <property name="toolTip"> <string>If unchecked, the prior cannot create directions where there are none in the data.</string> </property> <property name="text"> <string/> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="3" column="0"> <widget class="QLabel" name="m_PriorLabel_4"> <property name="text"> <string>New Directions from Prior:</string> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="m_PriorLabel_3"> <property name="text"> <string>Restrict to Prior:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QmitkSingleNodeSelectionWidget" name="m_PriorImageSelectionWidget" native="true"/> </item> <item row="2" column="1"> <widget class="QCheckBox" name="m_PriorAsMaskBox"> <property name="toolTip"> <string>Restrict tractography to regions where the prior is valid.</string> </property> <property name="text"> <string/> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="4" column="1"> <widget class="QFrame" name="frame_10"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_20"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <property name="spacing"> <number>0</number> </property> <item row="0" column="1"> <widget class="QCheckBox" name="m_PriorFlipYBox"> <property name="text"> <string>y</string> </property> </widget> </item> <item row="0" column="0"> <widget class="QCheckBox" name="m_PriorFlipXBox"> <property name="text"> <string>x</string> </property> </widget> </item> <item row="0" column="2"> <widget class="QCheckBox" name="m_PriorFlipZBox"> <property name="text"> <string>z</string> </property> </widget> </item> </layout> </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="m_PriorLabel_5"> <property name="text"> <string>Flip Directions:</string> </property> </widget> </item> </layout> </widget> <widget class="QWidget" name="page_neighborhood"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>435</width> <height>189</height> </rect> </property> <attribute name="label"> <string>Neighborhood Sampling</string> </attribute> <attribute name="toolTip"> <string>Specify if and how information about the current streamline neighborhood should be used.</string> </attribute> <layout class="QGridLayout" name="gridLayout_18"> <item row="1" column="0"> <widget class="QCheckBox" name="m_FrontalSamplesBox"> <property name="toolTip"> <string>Only neighborhood samples in front of the current streamline position are considered.</string> </property> <property name="text"> <string>Use Only Frontal Samples</string> </property> <property name="checked"> <bool>false</bool> </property> </widget> </item> <item row="2" column="0"> <widget class="QCheckBox" name="m_StopVotesBox"> <property name="toolTip"> <string>If checked, the majority of sampling points has to place a stop-vote for the streamline to terminate. If not checked, all sampling positions have to vote for a streamline termination.</string> </property> <property name="text"> <string>Use Stop-Votes</string> </property> <property name="checked"> <bool>false</bool> </property> </widget> </item> <item row="0" column="0"> <widget class="QFrame" name="frame_4"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_10"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QLabel" name="m_SeedsPerVoxelLabel_2"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Num. Samples:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QSpinBox" name="m_NumSamplesBox"> <property name="toolTip"> <string>Number of neighborhood samples that are used to determine the next fiber progression direction.</string> </property> <property name="maximum"> <number>50</number> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="m_SamplingDistanceLabel"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Sampling Distance:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QDoubleSpinBox" name="m_SamplingDistanceBox"> <property name="toolTip"> <string>Sampling distance (in voxels)</string> </property> <property name="decimals"> <number>2</number> </property> <property name="maximum"> <double>10.000000000000000</double> </property> <property name="singleStep"> <double>0.100000000000000</double> </property> <property name="value"> <double>0.250000000000000</double> </property> </widget> </item> </layout> </widget> </item> <item row="3" column="0"> <spacer name="verticalSpacer_3"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> </layout> </widget> <widget class="QWidget" name="page_data"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>435</width> <height>189</height> </rect> </property> <attribute name="label"> <string>Data Handling</string> </attribute> <attribute name="toolTip"> <string>Specify interpolation and direction flips.</string> </attribute> <layout class="QGridLayout" name="gridLayout_6"> <item row="1" column="0"> <widget class="QFrame" name="frame_3"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_7"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QCheckBox" name="m_InterpolationBox"> <property name="toolTip"> <string>Trilinearly interpolate the input image used for tractography.</string> </property> <property name="text"> <string>Interpolate Tractography Data</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="1" column="0"> <widget class="QCheckBox" name="m_MaskInterpolationBox"> <property name="toolTip"> <string>Trilinearly interpolate the ROI images used to constrain the tractography.</string> </property> <property name="text"> <string>Interpolate ROI Images</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> </layout> </widget> </item> <item row="0" column="0"> <widget class="QFrame" name="frame_2"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_3"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="7" column="1"> <widget class="QFrame" name="frame"> <property name="frameShape"> <enum>QFrame::NoFrame</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_4"> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item row="0" column="0"> <widget class="QCheckBox" name="m_FlipXBox"> <property name="toolTip"> <string>Internally flips progression directions. This might be necessary depending on the input data.</string> </property> <property name="text"> <string>x</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QCheckBox" name="m_FlipYBox"> <property name="toolTip"> <string>Internally flips progression directions. This might be necessary depending on the input data.</string> </property> <property name="text"> <string>y</string> </property> </widget> </item> <item row="0" column="2"> <widget class="QCheckBox" name="m_FlipZBox"> <property name="toolTip"> <string>Internally flips progression directions. This might be necessary depending on the input data.</string> </property> <property name="text"> <string>z</string> </property> </widget> </item> </layout> </widget> </item> <item row="7" column="0"> <widget class="QLabel" name="m_SeedsPerVoxelLabel_3"> <property name="toolTip"> <string/> </property> <property name="text"> <string>Flip directions:</string> </property> </widget> </item> </layout> </widget> </item> <item row="2" column="0"> <spacer name="verticalSpacer_4"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> </layout> </widget> <widget class="QWidget" name="page_output"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>435</width> <height>189</height> </rect> </property> <attribute name="label"> <string>Output and Postprocessing</string> </attribute> <attribute name="toolTip"> <string>Specify the tractography output (streamlines or probability maps) and postprocessing steps.</string> </attribute> <layout class="QGridLayout" name="gridLayout_5"> <item row="3" column="0"> <spacer name="verticalSpacer_5"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="1" column="0"> <widget class="QCheckBox" name="m_ResampleFibersBox"> <property name="toolTip"> <string>Compress fibers using the specified error constraint.</string> </property> <property name="text"> <string>Compress Fibers</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="2" column="0"> <widget class="QCheckBox" name="m_OutputProbMap"> <property name="toolTip"> <string>Output map with voxel-wise visitation counts instead of streamlines.</string> </property> <property name="text"> <string>Output Probability Map</string> </property> <property name="checked"> <bool>false</bool> </property> </widget> </item> </layout> </widget> </widget> </item> </layout> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> <customwidget> <class>QmitkSingleNodeSelectionWidget</class> <extends>QWidget</extends> <header>QmitkSingleNodeSelectionWidget.h</header> <container>1</container> </customwidget> </customwidgets> <resources> <include location="../../resources/QmitkTractography.qrc"/> </resources> <connections/> </ui>