diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp index 57cca7752f..bb0514be9a 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.cpp @@ -1,1698 +1,1699 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberProcessingView.h" #include // Qt #include -//MITK +// MITK #include #include #include #include #include #include #include #include #include #include #include +#include // ITK #include #include #include #include #include #include #include const std::string QmitkFiberProcessingView::VIEW_ID = "org.mitk.views.fiberprocessing"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberProcessingView::QmitkFiberProcessingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_EllipseCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(5) { } // Destructor QmitkFiberProcessingView::~QmitkFiberProcessingView() { } void QmitkFiberProcessingView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberProcessingViewControls; m_Controls->setupUi( parent ); m_Controls->doExtractFibersButton->setDisabled(true); m_Controls->PFCompoANDButton->setDisabled(true); m_Controls->PFCompoORButton->setDisabled(true); m_Controls->PFCompoNOTButton->setDisabled(true); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_PolygonButton->setEnabled(false); m_Controls->m_RectangleButton->setEnabled(false); m_Controls->m_RectangleButton->setVisible(false); connect( m_Controls->doExtractFibersButton, SIGNAL(clicked()), this, SLOT(DoFiberExtraction()) ); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( ActionDrawEllipseTriggered() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( ActionDrawPolygonTriggered() ) ); connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) ); connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) ); connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) ); connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) ); connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) ); connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) ); connect(m_Controls->m_Extract3dButton, SIGNAL(clicked()), this, SLOT(Extract3d())); connect( m_Controls->m_ProcessFiberBundleButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedBundles()) ); } } void QmitkFiberProcessingView::Extract3d() { std::vector nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(); mitk::Surface::Pointer roi = mitk::Surface::New(); bool fibB = false; bool roiB = false; for (int i=0; i(nodes.at(i)->GetData())) { fib = dynamic_cast(nodes.at(i)->GetData()); fibB = true; } else if (dynamic_cast(nodes.at(i)->GetData())) { roi = dynamic_cast(nodes.at(i)->GetData()); roiB = true; } } if (!fibB) return; if (!roiB) return; vtkSmartPointer polyRoi = roi->GetVtkPolyData(); vtkSmartPointer polyFib = fib->GetFiberPolyData(); vtkSmartPointer selectEnclosedPoints = vtkSmartPointer::New(); selectEnclosedPoints->SetInput(polyFib); selectEnclosedPoints->SetSurface(polyRoi); selectEnclosedPoints->Update(); vtkSmartPointer newPoly = vtkSmartPointer::New(); vtkSmartPointer newCellArray = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer newPolyComplement = vtkSmartPointer::New(); vtkSmartPointer newCellArrayComplement = vtkSmartPointer::New(); vtkSmartPointer newPointsComplement = vtkSmartPointer::New(); vtkSmartPointer vLines = polyFib->GetLines(); vLines->InitTraversal(); int numberOfLines = vLines->GetNumberOfCells(); // each line for (int j=0; jGetNextCell ( numPoints, points ); bool isPassing = false; // each point of this line for (int k=0; kIsInside(points[k])) { isPassing = true; // fill new polydata vtkSmartPointer container = vtkSmartPointer::New(); for (int k=0; kGetPoint(points[k]); vtkIdType pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); } newCellArray->InsertNextCell(container); break; } } if (!isPassing) { vtkSmartPointer container = vtkSmartPointer::New(); for (int k=0; kGetPoint(points[k]); vtkIdType pointId = newPointsComplement->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); } newCellArrayComplement->InsertNextCell(container); } } newPoly->SetPoints(newPoints); newPoly->SetLines(newCellArray); mitk::FiberBundleX::Pointer fb = mitk::FiberBundleX::New(newPoly); DataNode::Pointer newNode = DataNode::New(); newNode->SetData(fb); newNode->SetName("passing surface"); GetDefaultDataStorage()->Add(newNode); newPolyComplement->SetPoints(newPointsComplement); newPolyComplement->SetLines(newCellArrayComplement); mitk::FiberBundleX::Pointer fbComplement = mitk::FiberBundleX::New(newPolyComplement); DataNode::Pointer newNodeComplement = DataNode::New(); newNodeComplement->SetData(fbComplement); newNodeComplement->SetName("not passing surface"); GetDefaultDataStorage()->Add(newNodeComplement); } void QmitkFiberProcessingView::GenerateRoiImage(){ if (m_SelectedImage.IsNull() || m_SelectedPF.empty()) return; mitk::Image* image = const_cast(m_SelectedImage.GetPointer()); UCharImageType::Pointer temp = UCharImageType::New(); mitk::CastToItkImage(m_SelectedImage, temp); m_PlanarFigureImage = UCharImageType::New(); m_PlanarFigureImage->SetSpacing( temp->GetSpacing() ); // Set the image spacing m_PlanarFigureImage->SetOrigin( temp->GetOrigin() ); // Set the image origin m_PlanarFigureImage->SetDirection( temp->GetDirection() ); // Set the image direction m_PlanarFigureImage->SetRegions( temp->GetLargestPossibleRegion() ); m_PlanarFigureImage->Allocate(); m_PlanarFigureImage->FillBuffer( 0 ); for (int i=0; iInitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); node->SetName("ROI Image"); this->GetDefaultDataStorage()->Add(node); } void QmitkFiberProcessingView::CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image) { if (dynamic_cast(node.GetPointer()->GetData()) && !dynamic_cast(node.GetPointer()->GetData())) { m_PlanarFigure = dynamic_cast(node.GetPointer()->GetData()); AccessFixedDimensionByItk_2( image, InternalReorientImagePlane, 3, m_PlanarFigure->GetGeometry(), -1); // itk::Image< unsigned char, 3 >::Pointer outimage = itk::Image< unsigned char, 3 >::New(); // outimage->SetSpacing( m_PlanarFigure->GetGeometry()->GetSpacing()/m_UpsamplingFactor ); // Set the image spacing // mitk::Point3D origin = m_PlanarFigure->GetGeometry()->GetOrigin(); // mitk::Point3D indexOrigin; // m_PlanarFigure->GetGeometry()->WorldToIndex(origin, indexOrigin); // indexOrigin[0] = indexOrigin[0] - .5 * (1.0-1.0/m_UpsamplingFactor); // indexOrigin[1] = indexOrigin[1] - .5 * (1.0-1.0/m_UpsamplingFactor); // indexOrigin[2] = indexOrigin[2] - .5 * (1.0-1.0/m_UpsamplingFactor); // mitk::Point3D newOrigin; // m_PlanarFigure->GetGeometry()->IndexToWorld(indexOrigin, newOrigin); // outimage->SetOrigin( newOrigin ); // Set the image origin // itk::Matrix matrix; // for (int i=0; i<3; i++) // for (int j=0; j<3; j++) // matrix[j][i] = m_PlanarFigure->GetGeometry()->GetMatrixColumn(i)[j]/m_PlanarFigure->GetGeometry()->GetSpacing().GetElement(i); // outimage->SetDirection( matrix ); // Set the image direction // itk::ImageRegion<3> upsampledRegion; // upsampledRegion.SetSize(0, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(0)/m_PlanarFigure->GetGeometry()->GetSpacing()[0]); // upsampledRegion.SetSize(1, m_PlanarFigure->GetGeometry()->GetParametricExtentInMM(1)/m_PlanarFigure->GetGeometry()->GetSpacing()[1]); // upsampledRegion.SetSize(2, 1); // typename itk::Image< unsigned char, 3 >::RegionType::SizeType upsampledSize = upsampledRegion.GetSize(); // for (unsigned int n = 0; n < 2; n++) // { // upsampledSize[n] = upsampledSize[n] * m_UpsamplingFactor; // } // upsampledRegion.SetSize( upsampledSize ); // outimage->SetRegions( upsampledRegion ); // outimage->Allocate(); // this->m_InternalImage = mitk::Image::New(); // this->m_InternalImage->InitializeByItk( outimage.GetPointer() ); // this->m_InternalImage->SetVolume( outimage->GetBufferPointer() ); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex ) { MITK_INFO << "InternalReorientImagePlane() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); float upsamp = m_UpsamplingFactor; float gausssigma = 0.5; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; resampler->SetOutputSpacing( spacing ); // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetParametricExtentInMM(0) / spacing[0]; size[1] = planegeo->GetParametricExtentInMM(1) / spacing[1]; size[2] = 1; resampler->SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; corrorig[2] += 0; planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = gausssigma * image->GetSpacing()[d]; } double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { // typedef typename itk::BSplineInterpolateImageFunction // InterpolatorType; typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); MITK_INFO << "Resampling requested image plane ... "; resampler->Update(); MITK_INFO << " ... done"; if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberProcessingView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ) { MITK_INFO << "InternalCalculateMaskFromPlanarFigure() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, UCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". UCharImageType::Pointer newMaskImage = UCharImageType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const Geometry3D *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour vtkPoints *points = vtkPoints::New(); PlanarFigure::PolyLineType::const_iterator it; std::vector indices; unsigned int numberOfPoints = 0; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image Point2D point2D = it->Point; planarFigureGeometry2D->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigureGeometry2D->IndexToWorld(point2D, point2D); planarFigureGeometry2D->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { float bounds[2] = {0,0}; bounds[0] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0); bounds[1] = this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1); imageGeometry3D->WorldToIndex( point3D, point3D ); // if (point3D[i0]<0) // point3D[i0] = 0.5; // else if (point3D[i0]>bounds[0]) // point3D[i0] = bounds[0]-0.5; // if (point3D[i1]<0) // point3D[i1] = 0.5; // else if (point3D[i1]>bounds[1]) // point3D[i1] = bounds[1]-0.5; if (point3D[i0]<0) point3D[i0] = 0.0; else if (point3D[i0]>bounds[0]) point3D[i0] = bounds[0]-0.001; if (point3D[i1]<0) point3D[i1] = 0.0; else if (point3D[i1]>bounds[1]) point3D[i1] = bounds[1]-0.001; points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } else { imageGeometry3D->WorldToIndex( point3D, point3D ); // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); numberOfPoints++; } } polyline->SetPoints( points ); points->Delete(); vtkIdType *ptIds = new vtkIdType[numberOfPoints]; for ( vtkIdType i = 0; i < numberOfPoints; ++i ) { ptIds[i] = i; } polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInput( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInput( extrudeFilter->GetOutput() ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< UCharImageType > ImageImportType; typedef itk::VTKImageExport< UCharImageType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencil( polyDataToImageStencil->GetOutput() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask = itmask.Begin(); itimage = itimage.Begin(); typename ImageType::SizeType lowersize = {{9999999999,9999999999,9999999999}}; typename ImageType::SizeType uppersize = {{0,0,0}}; while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) { itimage.Set(0); } else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size); // crop internal mask typedef itk::RegionOfInterestImageFilter< UCharImageType, UCharImageType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(cropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer()); tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer()); Image::Pointer tmpImage2 = Image::New(); tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer()); const Geometry3D *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const Geometry3D *intImageGeometry3D = tmpImage->GetGeometry( 0 ); typedef itk::ImageRegionIteratorWithIndex IteratorType; IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion()); imageIterator.GoToBegin(); while ( !imageIterator.IsAtEnd() ) { unsigned char val = imageIterator.Value(); if (val>0) { itk::Index<3> index = imageIterator.GetIndex(); Point3D point; point[0] = index[0]; point[1] = index[1]; point[2] = index[2]; intImageGeometry3D->IndexToWorld(point, point); pfImageGeometry3D->WorldToIndex(point, point); point[i0] += 0.5; point[i1] += 0.5; index[0] = point[0]; index[1] = point[1]; index[2] = point[2]; m_PlanarFigureImage->SetPixel(index, 1); } ++imageIterator; } // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void QmitkFiberProcessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkFiberProcessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } /* OnSelectionChanged is registered to SelectionService, therefore no need to implement SelectionService Listener explicitly */ void QmitkFiberProcessingView::UpdateGui() { // are fiber bundles selected? if ( m_SelectedFB.empty() ) { m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); m_Controls->m_ProcessFiberBundleButton->setEnabled(false); m_Controls->doExtractFibersButton->setEnabled(false); } else { m_Controls->m_ProcessFiberBundleButton->setEnabled(true); // one bundle and one planar figure needed to extract fibers if (!m_SelectedPF.empty()) m_Controls->doExtractFibersButton->setEnabled(true); // more than two bundles needed to join/subtract if (m_SelectedFB.size() > 1) { m_Controls->m_JoinBundles->setEnabled(true); m_Controls->m_SubstractBundles->setEnabled(true); } else { m_Controls->m_JoinBundles->setEnabled(false); m_Controls->m_SubstractBundles->setEnabled(false); } } // are planar figures selected? if ( m_SelectedPF.empty() ) { m_Controls->doExtractFibersButton->setEnabled(false); m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(false); m_Controls->m_GenerateRoiImage->setEnabled(false); } else { if ( m_SelectedImage.IsNotNull() ) m_Controls->m_GenerateRoiImage->setEnabled(true); else m_Controls->m_GenerateRoiImage->setEnabled(false); if (m_SelectedPF.size() > 1) { m_Controls->PFCompoANDButton->setEnabled(true); m_Controls->PFCompoORButton->setEnabled(true); m_Controls->PFCompoNOTButton->setEnabled(false); } else { m_Controls->PFCompoANDButton->setEnabled(false); m_Controls->PFCompoORButton->setEnabled(false); m_Controls->PFCompoNOTButton->setEnabled(true); } } } void QmitkFiberProcessingView::OnSelectionChanged( std::vector nodes ) { if ( !this->IsVisible() ) return; //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedPF.clear(); m_SelectedImage = NULL; for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); else if (dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); else if (dynamic_cast(node->GetData())) m_SelectedImage = dynamic_cast(node->GetData()); } UpdateGui(); GenerateStats(); } void QmitkFiberProcessingView::ActionDrawPolygonTriggered() { // bool checked = m_Controls->m_PolygonButton->isChecked(); // if(!this->AssertDrawingIsPossible(checked)) // return; mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New(); figure->ClosedOn(); this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter)); MITK_INFO << "PlanarPolygon created ..."; mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figureP = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figureP = dynamic_cast(node->GetData()); if(figureP) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } } void QmitkFiberProcessingView::ActionDrawEllipseTriggered() { //bool checked = m_Controls->m_CircleButton->isChecked(); //if(!this->AssertDrawingIsPossible(checked)) // return; mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_EllipseCounter)); this->GetDataStorage()->Modified(); MITK_INFO << "PlanarCircle created ..."; //call mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figureP = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figureP = dynamic_cast(node->GetData()); if(figureP) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } } void QmitkFiberProcessingView::Activated() { MITK_INFO << "FB OPerations ACTIVATED()"; /* mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDefaultDataStorage()->GetAll(); mitk::DataNode* node = 0; mitk::PlanarFigureInteractor::Pointer figureInteractor = 0; mitk::PlanarFigure* figure = 0; for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); } } */ } void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey, mitk::BaseProperty *property ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->SetGeometry2D( emptygeometry ); //set desired data to DataNode where Planarfigure is stored mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetName(name.toStdString()); newNode->SetData(figure); newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,0.0,0.0)); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true)); newNode->AddProperty( "selected", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(false) ); newNode->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) ); newNode->AddProperty( "planarfigure.line.width", mitk::FloatProperty::New(3.0) ); newNode->AddProperty( "planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.outline.width", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.helperline.width", mitk::FloatProperty::New(2.0) ); // PlanarFigureControlPointStyleProperty::Pointer styleProperty = // dynamic_cast< PlanarFigureControlPointStyleProperty* >( node->GetProperty( "planarfigure.controlpointshape" ) ); // if ( styleProperty.IsNotNull() ) // { // m_ControlPointShape = styleProperty->GetShape(); // } newNode->AddProperty( "planarfigure.default.line.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(0.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); newNode->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(2.0)); newNode->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(2.0) ); newNode->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); newNode->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(2.0)); // Add custom property, if available //if ( (propertyKey != NULL) && (property != NULL) ) //{ // newNode->AddProperty( propertyKey, property ); //} //get current selected DataNode -which should be a FiberBundle- and set PlanarFigure as child //this->GetDataStorage()->GetNodes() // mitk::FiberBundle::Pointer selectedFBNode = m_SelectedFBNodes.at(0); // figure drawn on the topmost layer / image this->GetDataStorage()->Add(newNode ); std::vector selectedNodes = GetDataManagerSelection(); for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } //selectedNodes = m_SelectedPlanarFigureNodes->GetNodes(); /*for(unsigned int i = 0; i < selectedNodes.size(); i++) { selectedNodes[i]->SetSelected(false); } */ newNode->SetSelected(true); //Select(newNode); } void QmitkFiberProcessingView::DoFiberExtraction() { if ( m_SelectedFB.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); MITK_WARN("QmitkFiberProcessingView") << "no fibe bundle selected"; return; } for (int i=0; i(m_SelectedFB.at(i)->GetData()); mitk::PlanarFigure::Pointer roi = dynamic_cast (m_SelectedPF.at(0)->GetData()); // std::vector extFBset = fib->extractFibersByPF(roi); // mitk::FiberBundleX::Pointer extFB = fib->extractFibersById(extFBset); mitk::DataNode::Pointer node; node = mitk::DataNode::New(); //fbNode->SetData(extFB); QString name(m_SelectedFB.at(0)->GetName().c_str()); name += "_extracted"; node->SetName(name.toStdString()); GetDataStorage()->Add(node); } } void QmitkFiberProcessingView::GenerateAndComposite() { mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCAnd->SetGeometry2D(currentGeometry2D); PFCAnd->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCAnd->addPlanarFigure( tmpPF ); PFCAnd->addDataNode( nodePF ); PFCAnd->setDisplayName("AND_COMPO"); } AddCompositeToDatastorage(PFCAnd, NULL); } void QmitkFiberProcessingView::GenerateOrComposite() { mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCOr->SetGeometry2D(currentGeometry2D); PFCOr->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCOr->addPlanarFigure( tmpPF ); PFCOr->addDataNode( nodePF ); PFCOr->setDisplayName("OR_COMPO"); } AddCompositeToDatastorage(PFCOr, NULL); } void QmitkFiberProcessingView::GenerateNotComposite() { mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New(); mitk::PlaneGeometry* currentGeometry2D = dynamic_cast( const_cast(GetActiveStdMultiWidget()->GetRenderWindow1()->GetRenderer()->GetCurrentWorldGeometry2D())); PFCNot->SetGeometry2D(currentGeometry2D); PFCNot->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); for( std::vector::iterator it = m_SelectedPF.begin(); it != m_SelectedPF.end(); ++it ) { mitk::DataNode::Pointer nodePF = *it; mitk::PlanarFigure::Pointer tmpPF = dynamic_cast( nodePF->GetData() ); PFCNot->addPlanarFigure( tmpPF ); PFCNot->addDataNode( nodePF ); PFCNot->setDisplayName("NOT_COMPO"); } AddCompositeToDatastorage(PFCNot, NULL); } /* CLEANUP NEEDED */ void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfcomp, mitk::DataNode::Pointer parentDataNode ) { mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); newPFCNode->SetName( pfcomp->getDisplayName() ); newPFCNode->SetData(pfcomp); newPFCNode->SetVisibility(true); switch (pfcomp->getOperationType()) { case 0: { if (!parentDataNode.IsNull()) { GetDataStorage()->Add(newPFCNode, parentDataNode); } else { GetDataStorage()->Add(newPFCNode); } //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // make new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; } else { MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } case 1: { if (!parentDataNode.IsNull()) { MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; GetDataStorage()->Add(newPFCNode, parentDataNode); } else { MITK_INFO << "adding " << newPFCNode->GetName(); GetDataStorage()->Add(newPFCNode); } for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // make new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } case 2: { if (!parentDataNode.IsNull()) { MITK_INFO << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; GetDataStorage()->Add(newPFCNode, parentDataNode); } else { MITK_INFO << "adding " << newPFCNode->GetName(); GetDataStorage()->Add(newPFCNode); } //iterate through its childs for(int i=0; igetNumberOfChildren(); ++i) { mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) { // child is of type planar Figure composite // makeRemoveBundle new node of the child, cuz later the child has to be removed of its old position in datamanager // feed new dataNode with information of the savedDataNode, which is gonna be removed soon mitk::DataNode::Pointer newChildPFCNode; newChildPFCNode = mitk::DataNode::New(); newChildPFCNode->SetData(tmpPFchild); newChildPFCNode->SetName( savedPFchildNode->GetName() ); pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer pfcomp->replaceDataNodeAt(i, newChildPFCNode); AddCompositeToDatastorage(pfcompcast, newPFCNode); //the current PFCNode becomes the childs parent // remove savedNode here, cuz otherwise its children will change their position in the dataNodeManager // without having its parent anymore //GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } } else { // child is not of type PlanarFigureComposite, so its one of the planarFigures // create new dataNode containing the data of the old dataNode, but position in dataManager will be // modified cuz we re setting a (new) parent. mitk::DataNode::Pointer newPFchildNode = mitk::DataNode::New(); newPFchildNode->SetName(savedPFchildNode->GetName() ); newPFchildNode->SetData(tmpPFchild); newPFchildNode->SetVisibility(true); // replace the dataNode in PFComp DataNodeVector pfcomp->replaceDataNodeAt(i, newPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; }else{ MITK_INFO << "[ERROR] does NOT exist, but can I read its Name? " << savedPFchildNode->GetName(); } // remove old child position in dataStorage GetDataStorage()->Remove(savedPFchildNode); if ( GetDataStorage()->Exists(savedPFchildNode)) { MITK_INFO << savedPFchildNode->GetName() << " still exists"; } MITK_INFO << "adding " << newPFchildNode->GetName() << " to " << newPFCNode->GetName(); //add new child to datamanager with its new position as child of newPFCNode parent GetDataStorage()->Add(newPFchildNode, newPFCNode); } } GetDataStorage()->Modified(); break; } default: MITK_INFO << "we have an UNDEFINED composition... ERROR" ; break; } } void QmitkFiberProcessingView::JoinBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedFB.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedFB.end(); ++it) { newBundle = *newBundle+dynamic_cast((*it)->GetData()); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::SubstractBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedFB.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedFB.end(); ++it) { newBundle = *newBundle-dynamic_cast((*it)->GetData()); name += "-"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberProcessingView::GenerateStats() { if ( m_SelectedFB.empty() ) return; QString stats(""); for( int i=0; i(node->GetData())) { if (i>0) stats += "\n-----------------------------\n"; stats += QString(node->GetName().c_str()) + "\n"; mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numberOfLines = vLines->GetNumberOfCells(); stats += "Number of fibers: "+ QString::number(numberOfLines) + "\n"; float length = 0; std::vector lengths; for (int i=0; iGetNextCell ( numPoints, points ); float l=0; for (unsigned int j=0; jGetPoint(points[j], p1); double p2[3] = {0,0,0}; fiberPolyData->GetPoint(points[j+1], p2); float a = p1[0]-p2[0]; float b = p1[1]-p2[1]; float c = p1[2]-p2[2]; float dist = std::sqrt(a*a+b*b+c*c); length += dist; l += dist; } lengths.push_back(l); } std::sort(lengths.begin(), lengths.end()); if (numberOfLines>0) length /= numberOfLines; float dev=0; int count = 0; vLines->InitTraversal(); for (int i=0; iGetNextCell ( numPoints, points ); float l=0; for (unsigned int j=0; jGetPoint(points[j], p1); double p2[3] = {0,0,0}; fiberPolyData->GetPoint(points[j+1], p2); float a = p1[0]-p2[0]; float b = p1[1]-p2[1]; float c = p1[2]-p2[2]; float dist = std::sqrt(a*a+b*b+c*c); l += dist; } dev += (length-l)*(length-l); count++; } if (numberOfLines>0) dev /= numberOfLines; stats += "Mean fiber length: "+ QString::number(length/10) + "cm\n"; stats += "Median fiber length: "+ QString::number(lengths.at(lengths.size()/2)/10) + "cm\n"; stats += "Standard deviation: "+ QString::number(dev/10) + "cm\n"; } } this->m_Controls->m_StatsTextEdit->setText(stats); } void QmitkFiberProcessingView::ProcessSelectedBundles() { if ( m_SelectedFB.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); MITK_WARN("QmitkFiberProcessingView") << "no fibe bundle selected"; return; } int generationMethod = m_Controls->m_GenerationBox->currentIndex(); for( int i=0; i(node->GetData())) { mitk::FiberBundleX::Pointer fib = dynamic_cast(node->GetData()); QString name(node->GetName().c_str()); DataNode::Pointer newNode = NULL; switch(generationMethod){ case 0: newNode = GenerateTractDensityImage(fib, false); name += "_TDI"; break; case 1: newNode = GenerateTractDensityImage(fib, true); name += "_envelope"; break; case 2: newNode = GenerateColorHeatmap(fib); break; case 3: newNode = GenerateFiberEndingsImage(fib); name += "_fiber_endings"; break; case 4: newNode = GenerateFiberEndingsPointSet(fib); name += "_fiber_endings"; break; } if (newNode.IsNotNull()) { newNode->SetName(name.toStdString()); GetDataStorage()->Add(newNode); } } } } // generate pointset displaying the fiber endings mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib) { mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); vtkSmartPointer fiberPolyData = fib->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int count = 0; int numFibers = fib->GetNumFibers(); for( int i=0; iGetNextCell ( numPoints, points ); if (numPoints>0) { double* point = fiberPolyData->GetPoint(points[0]); itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; pointSet->InsertPoint(count, itkPoint); count++; } if (numPoints>2) { double* point = fiberPolyData->GetPoint(points[numPoints-1]); itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; pointSet->InsertPoint(count, itkPoint); count++; } } mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( pointSet ); return node; } // generate image displaying the fiber endings mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib) { typedef unsigned char OutPixType; typedef itk::Image OutImageType; typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType; ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); generator->SetFiberBundle(fib); generator->SetInvertImage(m_Controls->m_InvertCheckbox->isChecked()); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); generator->Update(); // get output image OutImageType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } // generate rgba heatmap from fiber bundle mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib) { typedef itk::RGBAPixel OutPixType; typedef itk::Image OutImageType; typedef itk::TractsToRgbaImageFilter< OutImageType > ImageGeneratorType; ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); generator->SetFiberBundle(fib); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); generator->Update(); // get output image typedef itk::Image OutType; OutType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } // generate tract density image from fiber bundle mitk::DataNode::Pointer QmitkFiberProcessingView::GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary) { typedef float OutPixType; typedef itk::Image OutImageType; itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New(); generator->SetFiberBundle(fib); generator->SetBinaryOutput(binary); generator->SetInvertImage(m_Controls->m_InvertCheckbox->isChecked()); generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value()); generator->Update(); // get output image typedef itk::Image OutType; OutType::Pointer outImg = generator->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); // init data node mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); return node; } diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp index ffe3ef3acf..2db143d7d3 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.cpp @@ -1,669 +1,272 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ // Blueberry #include #include -#include "berryIStructuredSelection.h" - +#include // Qmitk #include "QmitkStochasticFiberTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include -//MITK -//#include "mitkNodePredicateProperty.h" -//#include "mitkNodePredicateAND.h" +// MITK #include +#include -#include - +// VTK #include #include #include -#include -#include #include #include - - - #include -#include -#include -#include -#include -#include -#include -#include -#include const std::string QmitkStochasticFiberTrackingView::VIEW_ID = "org.mitk.views.stochasticfibertracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; -// Strings for Data handling -const QString qDiffStr = "DiffusionImage"; -const QString qStatusErr = "[Err]"; -const QString qStatusOk = "[OK]"; -const QString qSeed = "Seed"; - - -//*****PERSONAL REMINDER****** -//############################## -/* THIS CLASS IS A MESS!! - * CLEANUP IN PROGRESS... - */ -//############################## - - - - QmitkStochasticFiberTrackingView::QmitkStochasticFiberTrackingView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) +, m_DiffusionImage( NULL ) +, m_SeedRoi( NULL ) { } // Destructor QmitkStochasticFiberTrackingView::~QmitkStochasticFiberTrackingView() { } - void QmitkStochasticFiberTrackingView::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::QmitkStochasticFiberTrackingViewControls; m_Controls->setupUi( parent ); - // set tableWidget column with - m_Controls->tableWidget->setColumnWidth(0,38); - m_Controls->tableWidget->setColumnWidth(1,250); - m_Controls->tableWidget->setEnabled(false); - m_Controls->tableWidget->setLineWidth(0); - connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); - //connect( m_Controls->comboBox_fiberAlgo, SIGNAL(selected()), this, SLOT(handleAlgoSelection() ); - - + connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) ); + connect( m_Controls->m_MaxCacheSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxCacheSizeChanged(int)) ); + connect( m_Controls->m_MaxTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMaxTractLengthChanged(int)) ); } } -void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) +void QmitkStochasticFiberTrackingView::OnSeedsPerVoxelChanged(int value) { - m_MultiWidget = &stdMultiWidget; + m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value)); } - -void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable() +void QmitkStochasticFiberTrackingView::OnMaxTractLengthChanged(int value) { - m_MultiWidget = NULL; + m_Controls->m_MaxTractLengthLabel->setText(QString("Max. Tract Length: ")+QString::number(value)); } -/* This method refreshes the Status-Message and its corresponding filename of tableWidget - Input: tmpVec: contains either dwi-image-DataNode or seedImage-DataNodes - tmpStatus: flag if dataNode-vector contains correct nodes or not */ -void QmitkStochasticFiberTrackingView::refreshTableWidget(std::vector tmpVec , QString tmpStatus) +void QmitkStochasticFiberTrackingView::OnMaxCacheSizeChanged(int value) { - - for(int idw=0; idw<(int)tmpVec.size(); idw++){ - mitk::DataNode::Pointer tmpnode; - QTableWidgetItem *itemStatus = new QTableWidgetItem; - QTableWidgetItem *itemText = new QTableWidgetItem; - tmpnode = tmpVec.at(idw); - itemText->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - itemText->setText( tmpnode->GetName().c_str() ); - itemStatus->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); - itemStatus->setText(tmpStatus); - if(tmpStatus.compare(qStatusErr) == 0){ - itemText->setTextColor(QColor(90, 0, 3, 255)); - itemStatus->setTextColor(QColor(90, 0, 3, 255)); - }else{ - itemText->setTextColor(QColor(92, 198, 10, 255)); - itemStatus->setTextColor(QColor(92, 198, 10, 255)); - } - /* take next available row */ - int row = m_Controls->tableWidget->rowCount(); - m_Controls->tableWidget->insertRow(row); - m_Controls->tableWidget->setItem(row,0,itemStatus); - m_Controls->tableWidget->setItem(row,1,itemText); - - } - + m_Controls->m_MaxCacheSizeLabel->setText(QString("Max. Cache Size: ")+QString::number(value)+"GB"); } -/* This method checks if given node is validSeed image*/ -bool QmitkStochasticFiberTrackingView::checkSeedROI( mitk::DataNode::Pointer node ) +void QmitkStochasticFiberTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { - bool isSeed = false; - QString qClassName = node->GetData()->GetNameOfClass(); - - /* propValue contains the result after calling GetPropertyValue - success contains the bool if desired propertyname is available or not */ - bool propValue = false; - bool success = node->GetPropertyValue("binary",propValue); - - if(qClassName.compare("Image") == 0 && success == true && propValue == true) - isSeed = true; - - return isSeed; + m_MultiWidget = &stdMultiWidget; } -/* This method checks if given node is dwi image*/ -bool QmitkStochasticFiberTrackingView::checkDWIType( mitk::DataNode::Pointer node ) -{ - bool isDwi = false; - QString qClassName = node->GetData()->GetNameOfClass(); // ie. TensorImage or DiffusionImage - if(qClassName.compare(qDiffStr) == 0) - isDwi = true; - return isDwi; +void QmitkStochasticFiberTrackingView::StdMultiWidgetNotAvailable() +{ + m_MultiWidget = NULL; } -/* OnSelectionChanged is registered to SelectionService, therefore no need to - implement SelectionService Listener explicitly */ - void QmitkStochasticFiberTrackingView::OnSelectionChanged( std::vector nodes ) { - //++++++++RESET GUI AND POINTER VECTORS+++++++++++++++ - /* clear GUI tableWidget */ - for( int i=m_Controls->tableWidget->rowCount(); i >= 0; --i) - { - m_Controls->tableWidget->removeRow(i); - } - - /* reset DWI selection vector */ - vPselDWImg.clear(); - vSeedROI.clear(); - //+++++++++++++++++++++++++++++++++++++++++++++++++++++ + m_DiffusionImage = NULL; + m_SeedRoi = NULL; + m_Controls->m_DiffusionImageLabel->setText("-"); + m_Controls->m_RoiImageLabel->setText("-"); - //############### HOMELAND SECURITY ################################ - /* When selection not empty, extract data of interest, - otherwise return */ - if(!nodes.empty()){ + if(nodes.empty()) + return; - /* Flag to set commandButton enabled or not - keep flag true until selection is not DWIImage */ - bool flag_execFTComd = true; - - /* checkpoint for singe Seedpoint track */ - // singleSeedpoint is depricated - // m_singleSeedpoint = false; //for debugging singleSeedpoint is init here, otherwise get boolean from GUI + for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) + { + mitk::DataNode::Pointer node = *it; - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); ++it ) + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { - //flags needed for algorithm execution logic - bool isDWI = false; - bool isSeed = false; - mitk::DataNode::Pointer node = *it; - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + if( dynamic_cast*>(node->GetData()) ) { - /* Check and sort image types */ - isDWI = checkDWIType(node); - if( isDWI ){ - vPselDWImg.push_back(*it); - - } else if(!m_singleSeedpoint){ - isSeed = checkSeedROI(node); - if( isSeed ) - vSeedROI.push_back(*it); - - } //else single seedPoint - - } //end if node.IsNotNull && dynamic_cast mitkImage - } //end node iterator - - - //############### BORDER CONTROL ################################ - /* ++++++++ Logic to en/disable execution of Algorithm +++++++++++ - Requirements: 1 dwi Image, >=1 Seedimage(s) or 1 single seedpoint */ - if(vPselDWImg.size() > 1){ - flag_execFTComd = false; - std::cout << "TODO GUI Warning, too much dwi images selected \n"; - refreshTableWidget(vPselDWImg, qStatusErr); - - }else if(vPselDWImg.empty()){ - flag_execFTComd = false; - std::cout << "TODO GUI Warning, NO dwi image selected \n"; - - }else{ // exactly 1 node in vector - flag_execFTComd = true; - refreshTableWidget(vPselDWImg, qStatusOk); - } - - if(!m_singleSeedpoint){ - //no manual selection - - if(vSeedROI.empty()){ - flag_execFTComd = false; - std::cout << "TODO GUI Warning, NO seed image selected \n"; - }else{ - //color seedImages green - refreshTableWidget(vSeedROI, qSeed); + m_DiffusionImage = dynamic_cast*>(node->GetData()); + m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); + } + else + { + bool isBinary = false; + node->GetPropertyValue("binary", isBinary); + if (isBinary) + { + m_SeedRoi = dynamic_cast(node->GetData()); + m_Controls->m_RoiImageLabel->setText(node->GetName().c_str()); + } } - - } - - /* Logic to Dis-/Enable Execute-FiberTracking-Button */ - if (m_Controls->commandLinkButton->isEnabled()) - { - if(!flag_execFTComd) - m_Controls->commandLinkButton->setEnabled(false); - - } else if(flag_execFTComd){ - - m_Controls->commandLinkButton->setEnabled(true); - } - } else { // else statement of " if node.isEmpty() " - - /* Selection from datamanager is empty - therefore set commandButton disable if necessary */ - if(m_Controls->commandLinkButton->isEnabled()) - { - m_Controls->commandLinkButton->setEnabled(false); - return; } } + if(m_DiffusionImage.IsNotNull() && m_SeedRoi.IsNotNull()) + m_Controls->commandLinkButton->setEnabled(true); + else + m_Controls->commandLinkButton->setEnabled(false); } void QmitkStochasticFiberTrackingView::DoFiberTracking() { - - // for debugging use only first image node - mitk::DataNode::Pointer SpDWI = vPselDWImg.at(0); - - - - - // cast node to compatible type - mitk::DiffusionImage::Pointer dwiImg = dynamic_cast< mitk::DiffusionImage* >( SpDWI->GetData() ); - /* get Gradients/Direction of dwi */ - itk::VectorContainer< unsigned int, vnl_vector_fixed >::Pointer Pdir = dwiImg->GetDirections(); + itk::VectorContainer< unsigned int, vnl_vector_fixed >::Pointer Pdir = m_DiffusionImage->GetDirections(); /* bValueContainer, Container includes b-values according to corresponding gradient-direction*/ PTFilterType::bValueContainerType::Pointer vecCont = PTFilterType::bValueContainerType::New(); /* for each gradient set b-Value; for 0-gradient set b-value eq. 0 */ for ( int i=0; i<(int)Pdir->size(); ++i) { vnl_vector_fixed valsGrad = Pdir->at(i); if (valsGrad.get(0) == 0 && valsGrad.get(1) == 0 && valsGrad.get(2) == 0) { //set 0-Gradient to bValue 0 vecCont->InsertElement(i,0); }else{ - vecCont->InsertElement(i,dwiImg->GetB_Value()); + vecCont->InsertElement(i,m_DiffusionImage->GetB_Value()); } } - /* former variant without setting 0-Gradient to 0 - for(int i=0; iGetDirections()->Size(); i++) - vecCont->InsertElement(i,dwiImg->GetB_Value()); - */ - /* define measurement frame (identity-matrix 3x3) */ - PTFilterType::MeasurementFrameType measurement_frame; - measurement_frame.set_identity(); + PTFilterType::MeasurementFrameType measurement_frame = m_DiffusionImage->GetMeasurementFrame(); - /* generate white matterImage */ + /* generate white matterImage (dummy?)*/ FloatImageType::Pointer wmImage = FloatImageType::New(); - wmImage->SetSpacing( dwiImg->GetVectorImage()->GetSpacing() ); - wmImage->SetOrigin( dwiImg->GetVectorImage()->GetOrigin() ); - wmImage->SetDirection( dwiImg->GetVectorImage()->GetDirection() ); - wmImage->SetLargestPossibleRegion( dwiImg->GetVectorImage()->GetLargestPossibleRegion() ); + wmImage->SetSpacing( m_DiffusionImage->GetVectorImage()->GetSpacing() ); + wmImage->SetOrigin( m_DiffusionImage->GetVectorImage()->GetOrigin() ); + wmImage->SetDirection( m_DiffusionImage->GetVectorImage()->GetDirection() ); + wmImage->SetLargestPossibleRegion( m_DiffusionImage->GetVectorImage()->GetLargestPossibleRegion() ); wmImage->SetBufferedRegion( wmImage->GetLargestPossibleRegion() ); wmImage->SetRequestedRegion( wmImage->GetLargestPossibleRegion() ); wmImage->Allocate(); itk::ImageRegionIterator ot(wmImage, wmImage->GetLargestPossibleRegion() ); while (!ot.IsAtEnd()) { ot.Set(1); ++ot; } - /* init TractographyFilter, note: it's a smartpointer */ - PTFilterType::Pointer ptfilterPtr = PTFilterType::New(); - - ptfilterPtr->SetInput(dwiImg->GetVectorImage().GetPointer()); - ptfilterPtr->SetbValues(vecCont); - ptfilterPtr->SetGradients(Pdir); - ptfilterPtr->SetMeasurementFrame(measurement_frame); - ptfilterPtr->SetWhiteMatterProbabilityImageInput(wmImage); - /*** get parameters from GUI ... TODO check validity during user input ***/ - ptfilterPtr->SetTotalTracts(m_Controls->lineEdit_totalTracts->text().toInt()); - ptfilterPtr->SetMaxLikelihoodCacheSize(m_Controls->lineEdit_likelihood_cache->text().toInt()); - ptfilterPtr->SetMaxTractLength(m_Controls->lineEdit_maxTractLength->text().toInt()); - - - /* define seed Index manual */ - //PTFilterType::InputDWIImageType::IndexType seedIdx; - //seedIdx[0] = m_Controls->lineEdit_seedIndex1->text().toInt(); - //seedIdx[1] = m_Controls->lineEdit_seedIndex2->text().toInt(); - //seedIdx[2] = m_Controls->lineEdit_seedIndex3->text().toInt(); - - + /* init TractographyFilter */ + PTFilterType::Pointer trackingFilter = PTFilterType::New(); + trackingFilter->SetInput(m_DiffusionImage->GetVectorImage().GetPointer()); + trackingFilter->SetbValues(vecCont); + trackingFilter->SetGradients(Pdir); + trackingFilter->SetMeasurementFrame(measurement_frame); + trackingFilter->SetWhiteMatterProbabilityImageInput(wmImage); + trackingFilter->SetTotalTracts(m_Controls->m_SeedsPerVoxelSlider->value()); + trackingFilter->SetMaxLikelihoodCacheSize(m_Controls->m_MaxCacheSizeSlider->value()*1000); + trackingFilter->SetMaxTractLength(m_Controls->m_MaxTractLengthSlider->value()); - - /* SEEDPOINT/REGION PREPARATION */ m_tractcontainer = PTFilterType::TractContainerType::New(); - - - //int seedROIcnt = vSeedROI.size(); - - // ############## SEED OPERATIONS ######## - // todo iterate over all seed ROIs - /// for(int si=0; si(SpSeedR->GetData()); - - /* nice structure of fibers in datamanager */ -/* mitk::DataNode::Pointer roiParentNode; - roiParentNode = mitk::DataNode::New(); - roiParentNode->SetName("FiberBundle_ROI_1"); - roiParentNode->SetData(mitkSeed); - roiParentNode->SetVisibility(true); - - GetDataStorage()->Add(roiParentNode);*/ - - - //itk::Image< char, 3 > - mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New(); - binaryImageToItk1->SetInput( mitkSeed ); + mitk::ImageToItk< itk::Image< unsigned char, 3 > >::Pointer binaryImageToItk1 = mitk::ImageToItk< itk::Image< unsigned char, 3 > >::New(); + binaryImageToItk1->SetInput( m_SeedRoi ); binaryImageToItk1->Update(); - - itk::ImageRegionConstIterator< BinaryImageType > it(binaryImageToItk1->GetOutput(), binaryImageToItk1->GetOutput()->GetRequestedRegion()); it.Begin(); while(!it.IsAtEnd()) { itk::ImageConstIterator::PixelType tmpPxValue = it.Get(); if(tmpPxValue != 0){ itk::ImageRegionConstIterator< BinaryImageType >::IndexType seedIdx = it.GetIndex(); - ptfilterPtr->SetSeedIndex(seedIdx); - ptfilterPtr->Update(); + trackingFilter->SetSeedIndex(seedIdx); + trackingFilter->Update(); /* get results from Filter */ /* write each single tract into member container */ - PTFilterType::TractContainerType::Pointer container_tmp = ptfilterPtr->GetOutputTractContainer(); - CImageType::Pointer cmap = ptfilterPtr->GetOutput(); - + PTFilterType::TractContainerType::Pointer container_tmp = trackingFilter->GetOutputTractContainer(); PTFilterType::TractContainerType::Iterator elIt = container_tmp->Begin(); PTFilterType::TractContainerType::Iterator end = container_tmp->End(); while( elIt != end ){ PTFilterType::TractContainerType::Element tract_tmp = elIt.Value(); m_tractcontainer->InsertElement(m_tractcontainer->Size(),tract_tmp); ++elIt; } } ++it; - } - // } /* allocate the VTK Polydata to output the tracts */ - vtkSmartPointer pts = vtkSmartPointer::New(); - - vtkSmartPointer cells = vtkSmartPointer::New(); - - float bounds[] = {0,0,0}; - bounds[0] = dwiImg->GetLargestPossibleRegion().GetSize().GetElement(0); - bounds[1] = dwiImg->GetLargestPossibleRegion().GetSize().GetElement(1); - bounds[2] = dwiImg->GetLargestPossibleRegion().GetSize().GetElement(2); - - - - mitk::FiberBundle::Pointer transformer = mitk::FiberBundle::New(); - transformer->additkStochTractContainer(m_tractcontainer); - transformer->initFiberGroup(); - transformer->SetGeometry(dwiImg->GetGeometry()); - transformer->SetBounds(bounds); - - - //transformer->debug_members(); - - //testing, get dti Fibers out of group - mitk::FiberBundle::FiberGroupType::Pointer fiberBundle = transformer->GetGroupFiberBundle(); - mitk::FiberBundle::ChildrenListType *fibersList = fiberBundle->GetChildren(); - for(mitk::FiberBundle::ChildrenListType::iterator itFibers = fibersList->begin(); - itFibers != fibersList->end(); - ++itFibers) - { - //we know we have DTITubeSpatialObjects stored in List - DTITubeType::Pointer dtiTract = dynamic_cast (itFibers->GetPointer()); - - - } - - mitk::DataNode::Pointer fbNode; - fbNode = mitk::DataNode::New(); - fbNode->SetData(transformer); - fbNode->SetName("GroupFinberBundle"); - fbNode->SetVisibility(true); - GetDataStorage()->Add(fbNode); + vtkSmartPointer vPoints = vtkSmartPointer::New(); + vtkSmartPointer vCellArray = vtkSmartPointer::New(); for( int i=0; i<(int)m_tractcontainer->Size(); i++ ) { - - /* for each iteration create a new dtiTube containing a list of its points */ - DTITubeType::Pointer dtiTube = DTITubeType::New(); - DTITubeType::PointListType list; - - mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); mitk::Point3D point; - PTFilterType::TractContainerType::Element tract = - m_tractcontainer->GetElement(i); - PTFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = - tract->GetVertexList(); + PTFilterType::TractContainerType::Element tract = m_tractcontainer->GetElement(i); + PTFilterType::TractContainerType::Element::ObjectType::VertexListType::ConstPointer vertexlist = tract->GetVertexList(); - /* create VTK points and PolyLine */ - - vtkSmartPointer polyLine = vtkSmartPointer::New(); - polyLine->GetPointIds()->SetNumberOfIds((int)vertexlist->Size()); - - unsigned long pntIdxHelper = pts->GetNumberOfPoints(); - - for( int j=0; j<(int)vertexlist->Size(); j++){ - - PTFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = - vertexlist->GetElement(j); - - float vertex_f[3] = {(float)vertex[0],(float)vertex[1],(float)vertex[2]}; - mitk::Point3D world(vertex_f); - - dwiImg->GetGeometry()->IndexToWorld(world, point); - - /* VTK add Points */ - double vertex_d[3] = {(double)vertex[0],(double)vertex[1],(double)vertex[2]}; - pts->InsertNextPoint(vertex_d); - polyLine->GetPointIds()->SetId(j,j+pntIdxHelper); + vtkSmartPointer vPolyLine = vtkSmartPointer::New(); + for( int j=0; j<(int)vertexlist->Size(); j++) + { + PTFilterType::TractContainerType::Element::ObjectType::VertexListType::Element vertex = vertexlist->GetElement(j); + mitk::Point3D index; + index[0] = (float)vertex[0]; + index[1] = (float)vertex[1]; + index[2] = (float)vertex[2]; + m_DiffusionImage->GetGeometry()->IndexToWorld(index, point); + vtkIdType id = vPoints->InsertNextPoint(point.GetDataPointer()); + vPolyLine->GetPointIds()->InsertNextId(id); } - - - /* dtiTubes - dtiTube->GetProperty()->SetName("dtiTube"); - dtiTube->SetId(i); - dtiTube->SetPoints(list); - myFiberScene->AddSpatialObject(dtiTube);*/ - - - /* VTK add line */ - cells->InsertNextCell(polyLine); - - - - /*mitk::DataNode::Pointer curveNode; - curveNode = mitk::DataNode::New(); - curveNode->SetData(spline); - curveNode->SetName("Fiber"); - curveNode->SetVisibility(true); - GetDataStorage()->Add(curveNode, roiParentNode); - */ - - mitk::Point3D newIdx3D; - - - // std::cout << "cross position world: " << m_MultiWidget->GetCrossPosition() << "\n" ; - // std::cout << "cross position index: " << newIdx3D << "\n" ; - - + vCellArray->InsertNextCell(vPolyLine); } + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + fiberPolyData->SetPoints(vPoints); + fiberPolyData->SetLines(vCellArray); - /* - ////////////// - // Klaus' Code - - ////////////////////// - // Generate RGBA Image - typedef itk::RGBAPixel OutPixType; - - // run generator - typedef itk::TractsToProbabilityImageFilter ImageGeneratorType; - ImageGeneratorType::Pointer generator = ImageGeneratorType::New(); - generator->SetInput(wmImage); - generator->SetTractContainer(m_tractcontainer); - generator->SetUpsamplingFactor(20); - generator->SetMinTractLength(10); - //generator->Update(); - - // get result - typedef itk::Image OutType; - OutType::Pointer outImg = generator->GetOutput(); - - mitk::Image::Pointer img = mitk::Image::New(); - img->InitializeByItk(outImg.GetPointer()); - img->SetVolume(outImg->GetBufferPointer()); - - // write to datastorage - mitk::DataNode::Pointer node1 = mitk::DataNode::New(); - node1->SetData(img); - node1->SetName("RgbImage"); - node1->SetVisibility(true); - - mitk::LevelWindow opaclevwin; - opaclevwin.SetRangeMinMax(0,255); - opaclevwin.SetWindowBounds(0,0); - mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); - node1->AddProperty( "opaclevelwindow", prop ); - - GetDataStorage()->Add(node1); - - /////////////////////////////// - // Generate unsigned char Image - typedef unsigned char OutPixType2; - - // run generator - typedef itk::TractsToProbabilityImageFilter ImageGeneratorType2; - ImageGeneratorType2::Pointer generator2 = ImageGeneratorType2::New(); - generator2->SetInput(wmImage); - generator2->SetTractContainer(m_tractcontainer); - generator2->SetUpsamplingFactor(20); - generator2->SetMinTractLength(10); - generator2->Update(); - - // get result - typedef itk::Image OutType2; - OutType2::Pointer outImg2 = generator2->GetOutput(); - - mitk::Image::Pointer img2 = mitk::Image::New(); - img2->InitializeByItk(outImg2.GetPointer()); - img2->SetVolume(outImg2->GetBufferPointer()); - - // to datastorage - mitk::DataNode::Pointer node2 = mitk::DataNode::New(); - node2->SetData(img2); - node2->SetName("ProbImage"); - node2->SetVisibility(true); - - mitk::LevelWindow opaclevwin2; - opaclevwin2.SetRangeMinMax(0,255); - opaclevwin2.SetWindowBounds(0,0); - mitk::LevelWindowProperty::Pointer prop2 = mitk::LevelWindowProperty::New(opaclevwin2); - node2->AddProperty( "opaclevelwindow", prop2 ); - - GetDataStorage()->Add(node2); - */ - - GetDataStorage()->Modified(); - - m_MultiWidget->RequestUpdate(); - - - /* - vtkSmartPointer linesPolyData = vtkSmartPointer::New(); - - linesPolyData->SetPoints(pts); - linesPolyData->SetLines(cells); - - //setup actor and mapper - vtkSmartPointer mapper = - vtkSmartPointer::New(); - mapper->SetInput(linesPolyData); - - vtkSmartPointer actor = - vtkSmartPointer::New(); - actor->SetMapper(mapper); - - //setup render window, renderer, and interactor - vtkSmartPointer renderer = - vtkSmartPointer::New(); - vtkSmartPointer renderWindow = - vtkSmartPointer::New(); - renderWindow->AddRenderer(renderer); - vtkSmartPointer renderWindowInteractor = - vtkSmartPointer::New(); - renderWindowInteractor->SetRenderWindow(renderWindow); - renderer->AddActor(actor); - - renderWindow->Render(); - renderWindowInteractor->Start(); - - */ - + mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberPolyData); + mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); + fbNode->SetData(fib); + fbNode->SetName("GroupFinberBundle"); + fbNode->SetVisibility(true); + GetDataStorage()->Add(fbNode); } diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.h b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.h index 4595c0560a..34f31895ba 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.h +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingView.h @@ -1,125 +1,102 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $ Version: $Revision: 21975 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef QmitkStochasticFiberTrackingView_h #define QmitkStochasticFiberTrackingView_h #include #include - #include -#include #include "ui_QmitkStochasticFiberTrackingViewControls.h" -#include -#include - #include -#include - #include + +#include +#include #include #include #include - -#include - - - - - +#include //define the input/output types typedef itk::VectorImage< short int, 3 > DWIVectorImageType; typedef itk::Image< float, 3 > FloatImageType; typedef itk::Image< unsigned int, 3 > CImageType; typedef itk::StochasticTractographyFilter< DWIVectorImageType, FloatImageType, CImageType > PTFilterType; typedef itk::DTITubeSpatialObject<3> DTITubeType; typedef itk::DTITubeSpatialObjectPoint<3> DTITubePointType; typedef itk::SceneSpatialObject<3> SceneSpatialObjectType; /*! \brief QmitkFiberTrackingView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ -class /*MitkDiffusionImaging_EXPORT*/ QmitkStochasticFiberTrackingView : public QmitkFunctionality +class QmitkStochasticFiberTrackingView : public QmitkFunctionality { - - // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkStochasticFiberTrackingView(); virtual ~QmitkStochasticFiberTrackingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); protected slots: - /// \brief Called when the user clicks the GUI button void DoFiberTracking(); -// void handleAlgoSelection(); - - protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); - Ui::QmitkStochasticFiberTrackingViewControls* m_Controls; - QmitkStdMultiWidget* m_MultiWidget; -private: +protected slots: + + void OnSeedsPerVoxelChanged(int value); + void OnMaxTractLengthChanged(int value); + void OnMaxCacheSizeChanged(int value); +private: -// \brief vector containing related (DiffusionImage) nodes of interest - std::vector vPselDWImg; -// \brief vector containing SeedRegions(binary) nodes of interest - std::vector vSeedROI; + mitk::Image::Pointer m_SeedRoi; + mitk::DiffusionImage::Pointer m_DiffusionImage; -// \brief flag to de-/activate manual seedPoint index-coordinates - bool m_singleSeedpoint; - bool checkDWIType( mitk::DataNode::Pointer ); - void refreshTableWidget(std::vector , QString ); - bool checkSeedROI( mitk::DataNode::Pointer ); typedef itk::Image< unsigned char, 3 > BinaryImageType; - // \brief container storing all found tracts PTFilterType::TractContainerType::Pointer m_tractcontainer; - - }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui index 3f1a1be865..7d32869673 100644 --- a/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui +++ b/Modules/Bundles/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStochasticFiberTrackingViewControls.ui @@ -1,173 +1,200 @@ QmitkStochasticFiberTrackingViewControls 0 0 - 290 - 331 + 480 + 553 0 0 QmitkTemplate - - - - - Selected Image(s) - + + + + + Data + + + + + + Diffusion Image: + + + + + + + - + + + + + + + ROI Image: + + + + + + + - + + + + - - - - true - - - - 204 - 0 - - - - QFrame::StyledPanel - - - true - - - Qt::NoPen - - - true - - - - Status - - - - - FileName - - + + + + Parameters + + + + + + Maximum tract length in voxel + + + 1 + + + 500 + + + 100 + + + Qt::Horizontal + + + + + + + Length of single tracts + + + Max. Tract Length: 100 + + + + + + + Number of tracts for each seedpoint + + + Seeds per Voxel: 1 + + + + + + + Likelihood cache in Megabytes + + + Max. Chache Size: 1GB + + + + + + + Number of tracts started in each voxel of the seed ROI + + + 1 + + + 10 + + + Qt::Horizontal + + + + + + + 1 + + + 10 + + + 1 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 200 + 0 + + + + + - - - - Qt::Horizontal - - - - 12 - 20 - - - - - + false - execute stochastic fiber tracking + Start Tracking - + Qt::Vertical QSizePolicy::Expanding 20 220 - - - - Length of single tracts - - - tarct length - - - - - - - define length of single tract - - - 50 - - - - - - - Number of tracts for each seedpoint - - - # of tracts - - - - - - - define number of tracts for each seedpoint - - - 1 - - - - - - - Likelihood cache in Megabytes - - - cache (MB) - - - - - - - define likelihood cache in Megabytes - - - 500 - - - - tableWidget commandLinkButton