diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp index 9d6a150..1503b05 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp @@ -1,233 +1,244 @@ /*=================================================================== 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 #include #include "QmitkFiberClusteringView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkFiberClusteringView::VIEW_ID = "org.mitk.views.fiberclustering"; using namespace mitk; QmitkFiberClusteringView::QmitkFiberClusteringView() : QmitkAbstractView() , m_Controls( nullptr ) { } // Destructor QmitkFiberClusteringView::~QmitkFiberClusteringView() { } void QmitkFiberClusteringView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberClusteringViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartClustering()) ); connect( m_Controls->m_TractBox, SIGNAL(currentIndexChanged(int)), this, SLOT(FiberSelectionChanged()) ); mitk::TNodePredicateDataType::Pointer isFib = mitk::TNodePredicateDataType::New(); m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TractBox->SetPredicate(isFib); m_Controls->m_InCentroidsBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_InCentroidsBox->SetPredicate(isFib); m_Controls->m_InCentroidsBox->SetZeroEntryText("--"); mitk::TNodePredicateDataType::Pointer imageP = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDimension::Pointer dimP = mitk::NodePredicateDimension::New(3); m_Controls->m_MapBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MapBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP)); m_Controls->m_ParcellationBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_ParcellationBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP)); m_Controls->m_MetricBox6->setVisible(false); m_Controls->m_MetricWeight6->setVisible(false); FiberSelectionChanged(); } } void QmitkFiberClusteringView::SetFocus() { FiberSelectionChanged(); } void QmitkFiberClusteringView::FiberSelectionChanged() { if (m_Controls->m_TractBox->GetSelectedNode().IsNull()) m_Controls->m_StartButton->setEnabled(false); else m_Controls->m_StartButton->setEnabled(true); } void QmitkFiberClusteringView::StartClustering() { if (m_Controls->m_TractBox->GetSelectedNode().IsNull()) return; mitk::DataNode::Pointer node = m_Controls->m_TractBox->GetSelectedNode(); float clusterSize = m_Controls->m_ClusterSizeBox->value(); mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); float max_d = 0; int i=1; std::vector< float > distances; while (max_d < fib->GetGeometry()->GetDiagonalLength()/2) { distances.push_back(clusterSize*i); max_d = clusterSize*i; ++i; } std::shared_ptr< mitk::TractClusteringFilter > clusterer = std::make_shared(); clusterer->SetDistances(distances); clusterer->SetTractogram(fib); if (m_Controls->m_InCentroidsBox->GetSelectedNode().IsNotNull()) { mitk::FiberBundle::Pointer in_centroids = dynamic_cast(m_Controls->m_InCentroidsBox->GetSelectedNode()->GetData()); clusterer->SetInCentroids(in_centroids); } std::vector< mitk::ClusteringMetric* > metrics; if (m_Controls->m_MetricBox1->isChecked()) { mitk::ClusteringMetricEuclideanMean* metric = new mitk::ClusteringMetricEuclideanMean(); metric->SetScale(m_Controls->m_MetricWeight1->value()); metrics.push_back(metric); } if (m_Controls->m_MetricBox2->isChecked()) { mitk::ClusteringMetricEuclideanStd* metric = new mitk::ClusteringMetricEuclideanStd(); metric->SetScale(m_Controls->m_MetricWeight2->value()); metrics.push_back(metric); } if (m_Controls->m_MetricBox3->isChecked()) { mitk::ClusteringMetricEuclideanMax* metric = new mitk::ClusteringMetricEuclideanMax(); metric->SetScale(m_Controls->m_MetricWeight3->value()); metrics.push_back(metric); } if (m_Controls->m_MetricBox6->isChecked()) { mitk::ClusteringMetricInnerAngles* metric = new mitk::ClusteringMetricInnerAngles(); metric->SetScale(m_Controls->m_MetricWeight6->value()); metrics.push_back(metric); } if (m_Controls->m_MetricBox7->isChecked()) { mitk::ClusteringMetricLength* metric = new mitk::ClusteringMetricLength(); metric->SetScale(m_Controls->m_MetricWeight7->value()); metrics.push_back(metric); } if (m_Controls->m_ParcellationBox->GetSelectedNode().IsNotNull() && m_Controls->m_MetricBox4->isChecked()) { mitk::Image::Pointer mitk_map = dynamic_cast(m_Controls->m_ParcellationBox->GetSelectedNode()->GetData()); ShortImageType::Pointer itk_map = ShortImageType::New(); mitk::CastToItkImage(mitk_map, itk_map); mitk::ClusteringMetricAnatomic* metric = new mitk::ClusteringMetricAnatomic(); metric->SetParcellations({itk_map}); metric->SetScale(m_Controls->m_MetricWeight4->value()); metrics.push_back(metric); } if (m_Controls->m_MapBox->GetSelectedNode().IsNotNull() && m_Controls->m_MetricBox5->isChecked()) { mitk::Image::Pointer mitk_map = dynamic_cast(m_Controls->m_MapBox->GetSelectedNode()->GetData()); FloatImageType::Pointer itk_map = FloatImageType::New(); mitk::CastToItkImage(mitk_map, itk_map); mitk::ClusteringMetricScalarMap* metric = new mitk::ClusteringMetricScalarMap(); metric->SetImages({itk_map}); metric->SetScale(m_Controls->m_MetricWeight5->value()); metrics.push_back(metric); } if (metrics.empty()) { QMessageBox::warning(nullptr, "Warning", "No metric selected!"); return; } clusterer->SetMetrics(metrics); clusterer->SetMergeDuplicateThreshold(m_Controls->m_MergeDuplicatesBox->value()); clusterer->SetNumPoints(m_Controls->m_FiberPointsBox->value()); clusterer->SetMaxClusters(m_Controls->m_MaxClustersBox->value()); clusterer->SetMinClusterSize(m_Controls->m_MinFibersBox->value()); clusterer->Update(); std::vector tracts = clusterer->GetOutTractograms(); std::vector centroids = clusterer->GetOutCentroids(); unsigned int c = 0; for (auto f : tracts) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); new_node->SetData(f); new_node->SetName("Cluster_" + boost::lexical_cast(c)); if (m_Controls->m_InCentroidsBox->GetSelectedNode().IsNotNull()) this->GetDataStorage()->Add(new_node, m_Controls->m_InCentroidsBox->GetSelectedNode()); else this->GetDataStorage()->Add(new_node, node); node->SetVisibility(false); - if (m_Controls->m_CentroidsBox->isChecked()) + if (m_Controls->m_CentroidsBox->isChecked() && !m_Controls->m_MergeCentroidsBox->isChecked()) { mitk::DataNode::Pointer new_node2 = mitk::DataNode::New(); new_node2->SetData(centroids.at(c)); new_node2->SetName("Centroid_" + boost::lexical_cast(c)); this->GetDataStorage()->Add(new_node2, new_node); } ++c; } + + if (m_Controls->m_CentroidsBox->isChecked() && m_Controls->m_MergeCentroidsBox->isChecked()) + { + mitk::DataNode::Pointer new_node2 = mitk::DataNode::New(); + auto centroid_bundle = centroids.at(0); + for (unsigned int i=1; iAddBundle(centroids.at(i)); + new_node2->SetData(centroid_bundle); + new_node2->SetName("Centroids"); + this->GetDataStorage()->Add(new_node2); + } } void QmitkFiberClusteringView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& ) { } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui index b9edec8..6c6122a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringViewControls.ui @@ -1,524 +1,538 @@ QmitkFiberClusteringViewControls 0 0 474 695 Form QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; } 25 Qt::Vertical 20 40 Metrics 6 6 6 6 Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean true Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean STDEV Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Euclidean Maximum Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 Inner Angles Weighting factor for metric values. 1 999.000000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Distance is based on the selected parcellation. Anatomical Distance is based on the selected parcellation. Weighting factor for metric values. 1 999.000000000000000 30.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Distance is based on the scalar map values along the tract. Scalar Map Distance is based on the scalar map values along the tract. Streamline Length Input Data 6 6 6 6 Input Centroids: If set, the input tractogram is clustered around the input centroids and no new clusters are created. false 0 0 200 16777215 11 Start Tractogram: Parameters - - + + + + Merge Duplicate Clusters: + + + + + - Only output clusters with ate least the specified number of fibers. + Merge duplicate clusters withthe specified distance threshold. If threshold is < 0, the threshold is set to half of the specified cluster size. - 1 + -1.000000000000000 - 9999999 + 99999.000000000000000 - 50 + -1.000000000000000 + + + + + + + Output Centroids: Only output the N largest clusters. Zero means no limit. 99999999 10 - - - - Min. Fibers per Cluster: + + + + Fibers are resampled to the desired number of points for clustering. Smaller is faster but less accurate. + + + 2 + + + 9999999 + + + 12 - - + + - Max. Clusters: + Min. Fibers per Cluster: Fiber Points: - - + + - Merge duplicate clusters withthe specified distance threshold. If threshold is < 0, the threshold is set to half of the specified cluster size. + Cluster size in mm. - -1.000000000000000 + 1 - 99999.000000000000000 + 9999999 - -1.000000000000000 + 20 - - + + - Cluster Size: + - - - - Cluster size in mm. - - - 1 - - - 9999999 - - - 20 + + + + Max. Clusters: - - + + - Fibers are resampled to the desired number of points for clustering. Smaller is faster but less accurate. + Only output clusters with ate least the specified number of fibers. - 2 + 1 9999999 - 12 + 50 - - + + - Merge Duplicate Clusters: + Cluster Size: - - + + - Output Centroids: + Merge Centroids: - - + + QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp index 7dc0143..a90a6f7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp @@ -1,689 +1,759 @@ /*=================================================================== 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 #include #include "QmitkTractometryView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkTractometryView::VIEW_ID = "org.mitk.views.tractometry"; using namespace mitk; QmitkTractometryView::QmitkTractometryView() : QmitkAbstractView() , m_Controls( nullptr ) , m_Visible(false) { } // Destructor QmitkTractometryView::~QmitkTractometryView() { } void QmitkTractometryView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkTractometryViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_MethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartTractometry()) ); mitk::TNodePredicateDataType::Pointer imageP = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDimension::Pointer dimP = mitk::NodePredicateDimension::New(3); m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_ImageBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP)); m_Controls->m_ChartWidget->SetXAxisLabel("Tract position"); m_Controls->m_ChartWidget->SetYAxisLabel("Image Value"); m_Controls->m_ChartWidget->SetTheme(QmitkChartWidget::ColorTheme::darkstyle); } } void QmitkTractometryView::SetFocus() { } void QmitkTractometryView::UpdateGui() { berry::IWorkbenchPart::Pointer nullPart; OnSelectionChanged(nullPart, QList(m_CurrentSelection)); } bool QmitkTractometryView::Flip(vtkSmartPointer< vtkPolyData > polydata1, int i, vtkSmartPointer< vtkPolyData > ref_poly) { double d_direct = 0; double d_flipped = 0; vtkCell* cell1 = polydata1->GetCell(0); if (ref_poly!=nullptr) cell1 = ref_poly->GetCell(0); auto numPoints1 = cell1->GetNumberOfPoints(); vtkPoints* points1 = cell1->GetPoints(); std::vector> ref_points; for (int j=0; jGetPoint(j); itk::Point itk_p; itk_p[0] = p1[0]; itk_p[1] = p1[1]; itk_p[2] = p1[2]; ref_points.push_back(itk_p); } vtkCell* cell2 = polydata1->GetCell(i); vtkPoints* points2 = cell2->GetPoints(); for (int j=0; jGetPoint(j); - d_direct = (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]); + d_direct += (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]); double* p3 = points2->GetPoint(numPoints1-j-1); - d_flipped = (p1[0]-p3[0])*(p1[0]-p3[0]) + (p1[1]-p3[1])*(p1[1]-p3[1]) + (p1[2]-p3[2])*(p1[2]-p3[2]); + d_flipped += (p1[0]-p3[0])*(p1[0]-p3[0]) + (p1[1]-p3[1])*(p1[1]-p3[1]) + (p1[2]-p3[2])*(p1[2]-p3[2]); } if (d_direct>d_flipped) return true; return false; } template void QmitkTractometryView::StaticResamplingTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector > &data, std::string& clipboard_string) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); unsigned int num_points = m_Controls->m_SamplingPointsBox->value(); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy(); working_fib->ResampleToNumPoints(num_points); vtkSmartPointer< vtkPolyData > polydata = working_fib->GetFiberPolyData(); double rgb[3] = {0,0,0}; mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetType(mitk::LookupTable::MULTILABEL); std::vector > all_values; std::vector< double > mean_values; for (unsigned int i=0; iGetNumFibers(); ++i) { vtkCell* cell = polydata->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); std::vector< double > fib_vals; bool flip = false; if (i>0) flip = Flip(polydata, i); else if (m_ReferencePolyData!=nullptr) flip = Flip(polydata, 0, m_ReferencePolyData); for (int j=0; jGetTableValue(j, rgb); double* p; if (flip) { auto p_idx = numPoints - j - 1; p = points->GetPoint(p_idx); working_fib->ColorSinglePoint(i, p_idx, rgb); } else { p = points->GetPoint(j); working_fib->ColorSinglePoint(i, j, rgb); } Point3D px; px[0] = p[0]; px[1] = p[1]; px[2] = p[2]; double pixelValue = static_cast(readimage.GetPixelByWorldCoordinates(px)); fib_vals.push_back(pixelValue); mean += pixelValue; if (pixelValuemax) max = pixelValue; mean_values.at(j) += pixelValue; } all_values.push_back(fib_vals); } if (m_ReferencePolyData==nullptr) m_ReferencePolyData = polydata; std::vector< double > std_values1; std::vector< double > std_values2; for (unsigned int i=0; iGetNumFibers(); double stdev = 0; for (unsigned int j=0; j(mean_values.at(i)); clipboard_string += " "; clipboard_string += boost::lexical_cast(stdev); clipboard_string += "\n"; } clipboard_string += "\n"; data.push_back(mean_values); data.push_back(std_values1); data.push_back(std_values2); MITK_INFO << "Min: " << min; MITK_INFO << "Max: " << max; MITK_INFO << "Mean: " << mean/working_fib->GetNumberOfPoints(); if (m_Controls->m_ShowBinned->isChecked()) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); auto children = GetDataStorage()->GetDerivations(node); for (unsigned int i=0; isize(); ++i) { if (children->at(i)->GetName() == "binned_static") { new_node = children->at(i); new_node->SetData(working_fib); new_node->SetVisibility(true); node->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } } new_node->SetData(working_fib); new_node->SetName("binned_static"); new_node->SetVisibility(true); node->SetVisibility(false); GetDataStorage()->Add(new_node, node); } } template void QmitkTractometryView::NearestCentroidPointTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector< std::vector< double > >& data, std::string& clipboard_string) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); unsigned int num_points = m_Controls->m_SamplingPointsBox->value(); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy(); working_fib->ResampleSpline(1.0); vtkSmartPointer< vtkPolyData > working_polydata = working_fib->GetFiberPolyData(); // clustering std::vector< mitk::ClusteringMetric* > metrics; metrics.push_back({new mitk::ClusteringMetricEuclideanStd()}); mitk::FiberBundle::Pointer fib_static_resampled = fib->GetDeepCopy(); fib_static_resampled->ResampleToNumPoints(num_points); vtkSmartPointer< vtkPolyData > polydata_static_resampled = fib_static_resampled->GetFiberPolyData(); std::vector centroids; std::shared_ptr< mitk::TractClusteringFilter > clusterer = std::make_shared(); int c=0; while (c<30 && (centroids.empty() || centroids.size()>static_cast(m_Controls->m_MaxCentroids->value()))) { float cluster_size = m_Controls->m_ClusterSize->value() + m_Controls->m_ClusterSize->value()*c*0.2; float max_d = 0; int i=1; std::vector< float > distances; while (max_d < working_fib->GetGeometry()->GetDiagonalLength()/2) { distances.push_back(cluster_size*i); max_d = cluster_size*i; ++i; } clusterer->SetDistances(distances); clusterer->SetTractogram(fib_static_resampled); clusterer->SetMetrics(metrics); clusterer->SetMergeDuplicateThreshold(cluster_size); clusterer->SetDoResampling(false); clusterer->SetNumPoints(num_points); // clusterer->SetMaxClusters(m_Controls->m_MaxCentroids->value()); clusterer->SetMinClusterSize(1); clusterer->Update(); centroids = clusterer->GetOutCentroids(); ++c; } double rgb[3] = {0,0,0}; mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetType(mitk::LookupTable::MULTILABEL); std::vector > all_values; std::vector< double > mean_values; std::vector< unsigned int > value_count; for (unsigned int i=0; iGetNumFibers(); ++i) { vtkCell* cell = working_polydata->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); std::vector< double > fib_vals; for (int j=0; jGetPoint(j); int min_bin = 0; float d=999999; for (auto centroid : centroids) { auto centroid_polydata = centroid->GetFiberPolyData(); vtkCell* centroid_cell = centroid_polydata->GetCell(0); auto centroid_numPoints = centroid_cell->GetNumberOfPoints(); vtkPoints* centroid_points = centroid_cell->GetPoints(); bool centroid_flip = Flip(centroid_polydata, 0, centroids.at(0)->GetFiberPolyData()); for (int bin=0; binGetPoint(bin); float temp_d = std::sqrt((p[0]-centroid_p[0])*(p[0]-centroid_p[0]) + (p[1]-centroid_p[1])*(p[1]-centroid_p[1]) + (p[2]-centroid_p[2])*(p[2]-centroid_p[2])); if (temp_dGetTableValue(min_bin, rgb); working_fib->ColorSinglePoint(i, j, rgb); Point3D px; px[0] = p[0]; px[1] = p[1]; px[2] = p[2]; double pixelValue = static_cast(readimage.GetPixelByWorldCoordinates(px)); fib_vals.push_back(pixelValue); mean += pixelValue; if (pixelValuemax) max = pixelValue; mean_values.at(min_bin) += pixelValue; value_count.at(min_bin) += 1; } all_values.push_back(fib_vals); } if (m_ReferencePolyData==nullptr) m_ReferencePolyData = working_polydata; std::vector< double > std_values1; std::vector< double > std_values2; for (unsigned int i=0; i(mean_values.at(i)); clipboard_string += " "; clipboard_string += boost::lexical_cast(stdev); clipboard_string += "\n"; } clipboard_string += "\n"; data.push_back(mean_values); data.push_back(std_values1); data.push_back(std_values2); MITK_INFO << "Min: " << min; MITK_INFO << "Max: " << max; MITK_INFO << "Mean: " << mean/working_fib->GetNumberOfPoints(); if (m_Controls->m_ShowBinned->isChecked()) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); // mitk::DataNode::Pointer new_node2; auto children = GetDataStorage()->GetDerivations(node); for (unsigned int i=0; isize(); ++i) { if (children->at(i)->GetName() == "binned_centroid") { new_node = children->at(i); new_node->SetData(working_fib); new_node->SetVisibility(true); node->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } } new_node->SetData(working_fib); new_node->SetName("binned_centroid"); new_node->SetVisibility(true); node->SetVisibility(false); GetDataStorage()->Add(new_node, node); } } void QmitkTractometryView::Activated() { } void QmitkTractometryView::Deactivated() { } void QmitkTractometryView::Visible() { m_Visible = true; QList selection = GetDataManagerSelection(); berry::IWorkbenchPart::Pointer nullPart; OnSelectionChanged(nullPart, selection); } void QmitkTractometryView::Hidden() { m_Visible = false; } std::string QmitkTractometryView::RGBToHexString(double *rgb) { std::ostringstream os; for (int i = 0; i < 3; ++i) { os << std::setw(2) << std::setfill('0') << std::hex << static_cast(rgb[i] * 255); } return os.str(); } void QmitkTractometryView::AlongTractRadiomicsPreprocessing(mitk::Image::Pointer image, mitk::DataNode::Pointer node) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); // calculate mask typedef unsigned int OutPixType; typedef itk::Image OutImageType; itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New(); generator->SetFiberBundle(fib); generator->SetMode(TDI_MODE::BINARY); OutImageType::Pointer itkImage = OutImageType::New(); CastToItkImage(image, itkImage); generator->SetInputImage(itkImage); generator->SetUseImageGeometry(true); generator->Update(); OutImageType::Pointer count_map = generator->GetOutput(); unsigned int num_points = m_Controls->m_SamplingPointsBox->value(); mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy(); working_fib->ResampleToNumPoints(num_points); vtkSmartPointer< vtkPolyData > polydata = working_fib->GetFiberPolyData(); +// // clustering +// MITK_INFO << "CLUSTERING"; +// std::vector< mitk::ClusteringMetric* > metrics; +// metrics.push_back({new mitk::ClusteringMetricEuclideanStd()}); + +// std::vector centroids; +// std::shared_ptr< mitk::TractClusteringFilter > clusterer = std::make_shared(); +// int c=0; +// while (c<30 && (centroids.empty() || centroids.size()>static_cast(m_Controls->m_MaxCentroids->value()))) +// { +// float cluster_size = m_Controls->m_ClusterSize->value() + m_Controls->m_ClusterSize->value()*c*0.2; +// float max_d = 0; +// int i=1; +// std::vector< float > distances; +// while (max_d < working_fib->GetGeometry()->GetDiagonalLength()/2) +// { +// distances.push_back(cluster_size*i); +// max_d = cluster_size*i; +// ++i; +// } + +// clusterer->SetDistances(distances); +// clusterer->SetTractogram(working_fib); +// clusterer->SetMetrics(metrics); +// clusterer->SetMergeDuplicateThreshold(cluster_size); +// clusterer->SetDoResampling(false); +// clusterer->SetNumPoints(num_points); +// clusterer->SetMaxClusters(1); +// clusterer->SetMinClusterSize(1); +// clusterer->Update(); +// centroids = clusterer->GetOutCentroids(); +// ++c; +// } +// m_ReferencePolyData = centroids.at(0)->GetFiberPolyData(); + + MITK_INFO << fib->GetMeanFiberLength()/(2*num_points); + float maxd = fib->GetMeanFiberLength()/(2*num_points); + + itk::ImageRegionIterator< OutImageType > it(count_map, count_map->GetLargestPossibleRegion()); + + unsigned long num_vox = 0; + while( !it.IsAtEnd() ) + { + if (it.Get()>0) + ++num_vox; + ++it; + } + it.GoToBegin(); + + MITK_INFO << "Parcellating tract"; + boost::progress_display disp(num_vox); while( !it.IsAtEnd() ) { if (it.Get()>0) { - std::vector seg_vote; seg_vote.resize(num_points, 0); - typename OutImageType::PointType image_point; - count_map->TransformIndexToPhysicalPoint(it.GetIndex(), image_point); + int final_seg_id = -1; + int mult = 1; - for (unsigned int i=0; iGetNumFibers(); ++i) + while(final_seg_id<0) { - vtkCell* cell = polydata->GetCell(i); - auto numPoints = cell->GetNumberOfPoints(); - vtkPoints* points = cell->GetPoints(); + std::vector seg_vote; seg_vote.resize(num_points, 0); + typename OutImageType::PointType image_point; + count_map->TransformIndexToPhysicalPoint(it.GetIndex(), image_point); - bool flip = false; - if (i>0) - flip = Flip(polydata, i); - else if (m_ReferencePolyData!=nullptr) - flip = Flip(polydata, 0, m_ReferencePolyData); + for (unsigned int i=0; iGetNumFibers(); ++i) + { + vtkCell* cell = polydata->GetCell(i); + auto numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); - float local_d = 99999999; - int local_closest_seg = -1; + bool flip = false; + if (i>0) + flip = Flip(polydata, i); + else if (m_ReferencePolyData!=nullptr) + flip = Flip(polydata, 0, m_ReferencePolyData); - for (int j=0; jGetPoint(segment_id); - } - else + float local_d = 99999999; + int local_closest_seg = -1; + + for (int j=0; jGetPoint(j); - segment_id = j; + double* p; + int segment_id = -1; + if (flip) + { + segment_id = numPoints - j - 1; + p = points->GetPoint(segment_id); + } + else + { + p = points->GetPoint(j); + segment_id = j; + } + + float d = std::fabs( (p[0]-image_point[0]) ) + std::fabs( (p[1]-image_point[1]) ) + std::fabs( (p[2]-image_point[2]) ); + if (dmax_count) { - local_d = d; - local_closest_seg = segment_id; + final_seg_id = i; + max_count = seg_vote.at(i); } } - seg_vote[local_closest_seg] += 1; - } - - unsigned char final_seg_id = -1; - unsigned int max_count = 0; - for (unsigned int i=0; i=max_count) + if (final_seg_id>=0) { - final_seg_id = i; - max_count = seg_vote.at(i); + it.Set(final_seg_id + 1); } + ++mult; } - it.Set(final_seg_id + 1); + ++disp; } ++it; } + MITK_INFO << "DONE"; mitk::Image::Pointer seg_img = mitk::Image::New(); seg_img->InitializeByItk(count_map.GetPointer()); seg_img->SetVolume(count_map->GetBufferPointer()); mitk::DataNode::Pointer new_node = mitk::DataNode::New(); new_node->SetData(seg_img); new_node->SetName("segment image"); new_node->SetVisibility(true); node->SetVisibility(false); GetDataStorage()->Add(new_node, node); } void QmitkTractometryView::StartTractometry() { m_ReferencePolyData = nullptr; double color[3] = {0,0,0}; mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetType(mitk::LookupTable::MULTILABEL); mitk::Image::Pointer image = dynamic_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData()); this->m_Controls->m_ChartWidget->Clear(); std::string clipboardString = ""; int c = 1; for (auto node : m_CurrentSelection) { clipboardString += node->GetName() + "\n"; clipboardString += "mean stdev\n"; std::vector< std::vector< double > > data; switch (m_Controls->m_MethodBox->currentIndex()) { - case 1: + case 0: { mitkPixelTypeMultiplex4( StaticResamplingTractometry, image->GetPixelType(), image, node, data, clipboardString ); break; } + case 1: + { + mitkPixelTypeMultiplex4( NearestCentroidPointTractometry, image->GetPixelType(), image, node, data, clipboardString ); + break; + } case 2: { AlongTractRadiomicsPreprocessing(image, node); return; } default: { - mitkPixelTypeMultiplex4( NearestCentroidPointTractometry, image->GetPixelType(), image, node, data, clipboardString ); + mitkPixelTypeMultiplex4( StaticResamplingTractometry, image->GetPixelType(), image, node, data, clipboardString ); } } m_Controls->m_ChartWidget->AddData1D(data.at(0), node->GetName() + " Mean", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " Mean", QmitkChartWidget::LineStyle::solid); if (m_Controls->m_StDevBox->isChecked()) { m_Controls->m_ChartWidget->AddData1D(data.at(1), node->GetName() + " +STDEV", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->AddData1D(data.at(2), node->GetName() + " -STDEV", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " +STDEV", QmitkChartWidget::LineStyle::dashed); m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " -STDEV", QmitkChartWidget::LineStyle::dashed); } lookupTable->GetTableValue(c, color); this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " Mean", RGBToHexString(color)); if (m_Controls->m_StDevBox->isChecked()) { color[0] *= 0.5; color[1] *= 0.5; color[2] *= 0.5; this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " +STDEV", RGBToHexString(color)); this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " -STDEV", RGBToHexString(color)); } this->m_Controls->m_ChartWidget->Show(true); this->m_Controls->m_ChartWidget->SetShowDataPoints(false); ++c; } QApplication::clipboard()->setText(clipboardString.c_str(), QClipboard::Clipboard); } void QmitkTractometryView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { m_Controls->m_StartButton->setEnabled(false); if (!m_Visible) return; if (m_Controls->m_MethodBox->currentIndex()==0) m_Controls->m_ClusterFrame->setVisible(false); else m_Controls->m_ClusterFrame->setVisible(true); m_CurrentSelection.clear(); if(m_Controls->m_ImageBox->GetSelectedNode().IsNull()) return; for (auto node: nodes) if ( dynamic_cast(node->GetData()) ) m_CurrentSelection.push_back(node); if (!m_CurrentSelection.empty()) m_Controls->m_StartButton->setEnabled(true); }