diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp index f8f8c6f99c..a04083cce4 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.cpp @@ -1,2119 +1,1961 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define _USE_MATH_DEFINES #include "mitkFiberBundleX.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundleX::COLORCODING_ORIENTATION_BASED = "Color_Orient"; //const char* mitk::FiberBundleX::COLORCODING_FA_AS_OPACITY = "Color_Orient_FA_Opacity"; const char* mitk::FiberBundleX::COLORCODING_FA_BASED = "FA_Values"; const char* mitk::FiberBundleX::COLORCODING_CUSTOM = "custom"; const char* mitk::FiberBundleX::FIBER_ID_ARRAY = "Fiber_IDs"; using namespace std; mitk::FiberBundleX::FiberBundleX( vtkPolyData* fiberPolyData ) : m_CurrentColorCoding(NULL) , m_NumFibers(0) , m_FiberSampling(0) { m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != NULL) { m_FiberPolyData = fiberPolyData; //m_FiberPolyData->DeepCopy(fiberPolyData); this->DoColorCodingOrientationBased(); } this->UpdateFiberGeometry(); this->SetColorCoding(COLORCODING_ORIENTATION_BASED); this->GenerateFiberIds(); } mitk::FiberBundleX::~FiberBundleX() { } mitk::FiberBundleX::Pointer mitk::FiberBundleX::GetDeepCopy() { mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(m_FiberPolyData); newFib->SetColorCoding(m_CurrentColorCoding); return newFib; } vtkSmartPointer mitk::FiberBundleX::GeneratePolyDataByIds(std::vector fiberIds) { MITK_DEBUG << "\n=====FINAL RESULT: fib_id ======\n"; MITK_DEBUG << "Number of new Fibers: " << fiberIds.size(); // iterate through the vectorcontainer hosting all desired fiber Ids vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); // if FA array available, initialize fa double array // if color orient array is available init color array vtkSmartPointer faValueArray; vtkSmartPointer colorsT; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = sizeof(rgba); if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ MITK_DEBUG << "FA VALUES AVAILABLE, init array for new fiberbundle"; faValueArray = vtkSmartPointer::New(); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ MITK_DEBUG << "colorValues available, init array for new fiberbundle"; colorsT = vtkUnsignedCharArray::New(); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); } std::vector::iterator finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { // MITK_DEBUG << "id: " << fiber->GetPointId(i); // MITK_DEBUG << fibPoints->GetPoint(i)[0] << " | " << fibPoints->GetPoint(i)[1] << " | " << fibPoints->GetPoint(i)[2]; newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_FA_BASED)){ // MITK_DEBUG << m_FiberIdDataSet->GetPointData()->GetArray(FA_VALUE_ARRAY)->GetTuple(fiber->GetPointId(i)); } if (m_FiberIdDataSet->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED)){ // MITK_DEBUG << "ColorValue: " << m_FiberIdDataSet->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetTuple(fiber->GetPointId(i))[0]; } } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); MITK_DEBUG << "new fiberbundle polydata points: " << newFiberPolyData->GetNumberOfPoints(); MITK_DEBUG << "new fiberbundle polydata lines: " << newFiberPolyData->GetNumberOfLines(); MITK_DEBUG << "=====================\n"; // mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newFiberPolyData); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::AddBundle(mitk::FiberBundleX* fib) { if (fib==NULL) { MITK_WARN << "trying to call AddBundle with NULL argument"; return NULL; } MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(vNewPolyData); return newFib; } // subtract two fiber bundles mitk::FiberBundleX::Pointer mitk::FiberBundleX::SubtractBundle(mitk::FiberBundleX* fib) { MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // iterate over current fibers boost::progress_display disp(m_NumFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==NULL || numPoints<=0) continue; int numFibers2 = fib->GetNumFibers(); bool contained = false; for( int i2=0; i2GetFiberPolyData()->GetCell(i2); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (points2==NULL)// || numPoints2<=0) continue; // check endpoints if (numPoints2==numPoints) { itk::Point point_start = GetItkPoint(points->GetPoint(0)); itk::Point point_end = GetItkPoint(points->GetPoint(numPoints-1)); itk::Point point2_start = GetItkPoint(points2->GetPoint(0)); itk::Point point2_end = GetItkPoint(points2->GetPoint(numPoints2-1)); if ((point_start.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps) || (point_start.SquaredEuclideanDistanceTo(point2_end)<=mitk::eps && point_end.SquaredEuclideanDistanceTo(point2_start)<=mitk::eps)) { // further checking ??? contained = true; break; } } } // add to result because fiber is not subtracted if (!contained) { vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(j)); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } } if(vNewLines->GetNumberOfCells()==0) return NULL; // initialize polydata vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle return mitk::FiberBundleX::New(vNewPolyData); } itk::Point mitk::FiberBundleX::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set polydata (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundleX::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == NULL) this->m_FiberPolyData = vtkSmartPointer::New(); else { m_FiberPolyData->DeepCopy(fiberPD); DoColorCodingOrientationBased(); } m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); SetColorCoding(COLORCODING_ORIENTATION_BASED); GenerateFiberIds(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundleX::GetFiberPolyData() { return m_FiberPolyData; } void mitk::FiberBundleX::DoColorCodingOrientationBased() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also polydata needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= /* make sure that processing colorcoding is only called when necessary */ if ( m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) && m_FiberPolyData->GetNumberOfPoints() == m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)->GetNumberOfTuples() ) { // fiberstructure is already colorcoded MITK_DEBUG << " NO NEED TO REGENERATE COLORCODING! " ; this->ResetFiberOpacity(); this->SetColorCoding(COLORCODING_ORIENTATION_BASED); return; } /* Finally, execute color calculation */ vtkPoints* extrPoints = NULL; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=NULL) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; // int componentSize = sizeof(rgba); int componentSize = 4; vtkSmartPointer colorsT = vtkSmartPointer::New(); colorsT->Allocate(numOfPoints * componentSize); colorsT->SetNumberOfComponents(componentSize); colorsT->SetName(COLORCODING_ORIENTATION_BASED); /* checkpoint: does polydata contain any fibers */ int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) { MITK_DEBUG << "\n ========= Number of Fibers is 0 and below ========= \n"; return; } /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); // MITK_DEBUG << "Fib#: " << fi << " of " << numOfFibers << " pnts in fiber: " << pointsPerFiber ; /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } colorsT->InsertTupleValue(idList[i], rgba); } //end for loop } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; // colorsT->InsertTupleValue(0, rgba); } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } }//end for loop m_FiberPolyData->GetPointData()->AddArray(colorsT); /*========================= - this is more relevant for renderer than for fiberbundleX datastructure - think about sourcing this to a explicit method which coordinates colorcoding */ this->SetColorCoding(COLORCODING_ORIENTATION_BASED); // =========================== //mini test, shall be ported to MITK TESTINGS! if (colorsT->GetSize() != numOfPoints*componentSize) MITK_DEBUG << "ALLOCATION ERROR IN INITIATING COLOR ARRAY"; } void mitk::FiberBundleX::DoColorCodingFaBased() { if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) return; this->SetColorCoding(COLORCODING_FA_BASED); MITK_DEBUG << "FBX: done CC FA based"; this->GenerateFiberIds(); } void mitk::FiberBundleX::DoUseFaFiberOpacity() { if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED) != 1 ) return; if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_ORIENTATION_BASED) != 1 ) return; vtkDoubleArray* FAValArray = (vtkDoubleArray*) m_FiberPolyData->GetPointData()->GetArray(COLORCODING_FA_BASED); vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; ColorArray->SetComponent(i,3, (unsigned char) faValue ); } this->SetColorCoding(COLORCODING_ORIENTATION_BASED); MITK_DEBUG << "FBX: done CC OPACITY"; this->GenerateFiberIds(); } void mitk::FiberBundleX::ResetFiberOpacity() { vtkUnsignedCharArray* ColorArray = dynamic_cast (m_FiberPolyData->GetPointData()->GetArray(COLORCODING_ORIENTATION_BASED)); if (ColorArray==NULL) return; for(long i=0; iGetNumberOfTuples(); i++) ColorArray->SetComponent(i,3, 255.0 ); } void mitk::FiberBundleX::SetFAMap(mitk::Image::Pointer FAimage) { mitkPixelTypeMultiplex1( SetFAMap, FAimage->GetPixelType(), FAimage ); } template void mitk::FiberBundleX::SetFAMap(const mitk::PixelType, mitk::Image::Pointer FAimage) { MITK_DEBUG << "SetFAMap"; vtkSmartPointer faValues = vtkSmartPointer::New(); faValues->SetName(COLORCODING_FA_BASED); faValues->Allocate(m_FiberPolyData->GetNumberOfPoints()); faValues->SetNumberOfValues(m_FiberPolyData->GetNumberOfPoints()); mitk::ImagePixelReadAccessor readFAimage (FAimage, FAimage->GetVolumeData(0)); vtkPoints* pointSet = m_FiberPolyData->GetPoints(); for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double faPixelValue = 1-readFAimage.GetPixelByWorldCoordinates(px); faValues->InsertValue(i, faPixelValue); } m_FiberPolyData->GetPointData()->AddArray(faValues); this->GenerateFiberIds(); if(m_FiberPolyData->GetPointData()->HasArray(COLORCODING_FA_BASED)) MITK_DEBUG << "FA VALUE ARRAY SET"; } void mitk::FiberBundleX::GenerateFiberIds() { if (m_FiberPolyData == NULL) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); MITK_DEBUG << "Generating Fiber Ids...[done] | " << m_FiberIdDataSet->GetNumberOfCells(); } mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert) { vtkSmartPointer polyData = m_FiberPolyData; if (anyPoint) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleFibers(minSpacing/5); polyData = fibCopy->GetFiberPolyData(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Extracting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } break; } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { includeFiber = false; break; } } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if ( mask->GetPixel(idxStart)>0 && mask->GetPixel(idxEnd)>0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); return mitk::FiberBundleX::New(newPolyData); } mitk::FiberBundleX::Pointer mitk::FiberBundleX::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundleX::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleFibers(minSpacing/10); vtkSmartPointer polyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx)>0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx)<=0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return NULL; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); mitk::FiberBundleX::Pointer newFib = mitk::FiberBundleX::New(newPolyData); newFib->ResampleFibers(minSpacing/2); return newFib; } -mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(mitk::PlanarFigure* pf) +mitk::FiberBundleX::Pointer mitk::FiberBundleX::ExtractFiberSubset(BaseData* roi) { - if (pf==NULL) + if (roi==NULL || !(dynamic_cast(roi) || dynamic_cast(roi)) ) return NULL; - std::vector tmp = ExtractFiberIdSubset(pf); + std::vector tmp = ExtractFiberIdSubset(roi); if (tmp.size()<=0) return mitk::FiberBundleX::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); return mitk::FiberBundleX::New(pTmp); } -std::vector mitk::FiberBundleX::ExtractFiberIdSubset(mitk::PlanarFigure* pf) +std::vector mitk::FiberBundleX::ExtractFiberIdSubset(BaseData* roi) { - MITK_DEBUG << "Extracting fibers!"; - // vector which is returned, contains all extracted FiberIds - std::vector FibersInROI; - - if (pf==NULL) - return FibersInROI; - - /* Handle type of planarfigure */ - // if incoming pf is a pfc - mitk::PlanarFigureComposite::Pointer pfcomp= dynamic_cast(pf); - if (!pfcomp.IsNull()) { - // process requested boolean operation of PFC - switch (pfcomp->getOperationType()) { - case 0: - { - MITK_DEBUG << "AND PROCESSING"; - //AND - //temporarly store results of the child in this vector, we need that to accumulate the - std::vector childResults = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); - MITK_DEBUG << "first roi got fibers in ROI: " << childResults.size(); - MITK_DEBUG << "sorting..."; - std::sort(childResults.begin(), childResults.end()); - MITK_DEBUG << "sorting done"; - std::vector AND_Assamblage(childResults.size()); - //std::vector AND_Assamblage; - fill(AND_Assamblage.begin(), AND_Assamblage.end(), -1); - //AND_Assamblage.reserve(childResults.size()); //max size AND can reach anyway + std::vector result; + if (roi==NULL) + return result; + mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi); + if (!pfc.IsNull()) // handle composite + { + switch (pfc->getOperationType()) + { + case 0: // AND + { + result = this->ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; - for (int i=1; igetNumberOfChildren(); ++i) + for (int i=1; igetNumberOfChildren(); ++i) { - std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); - MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size(); - sort(tmpChild.begin(), tmpChild.end()); + std::vector inRoi = this->ExtractFiberIdSubset(pfc->getChildAt(i)); - it = std::set_intersection(childResults.begin(), childResults.end(), - tmpChild.begin(), tmpChild.end(), - AND_Assamblage.begin() ); + std::vector rest(std::min(result.size(),inRoi.size())); + it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); + rest.resize( it - rest.begin() ); + result = rest; } - - MITK_DEBUG << "resize Vector"; - unsigned long i=0; - while (i < AND_Assamblage.size() && AND_Assamblage[i] != -1){ //-1 represents a placeholder in the array - ++i; - } - AND_Assamblage.resize(i); - - MITK_DEBUG << "returning AND vector, size: " << AND_Assamblage.size(); - return AND_Assamblage; - // break; - + break; } - case 1: + case 1: // OR { - //OR - std::vector OR_Assamblage = this->ExtractFiberIdSubset(pfcomp->getChildAt(0)); + result = ExtractFiberIdSubset(pfc->getChildAt(0)); std::vector::iterator it; - MITK_DEBUG << OR_Assamblage.size(); - - for (int i=1; igetNumberOfChildren(); ++i) { - it = OR_Assamblage.end(); - std::vector tmpChild = this->ExtractFiberIdSubset(pfcomp->getChildAt(i)); - OR_Assamblage.insert(it, tmpChild.begin(), tmpChild.end()); - MITK_DEBUG << "ROI " << i << " has fibers in ROI: " << tmpChild.size() << " OR Assamblage: " << OR_Assamblage.size(); + for (int i=1; igetNumberOfChildren(); ++i) + { + it = result.end(); + std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); + result.insert(it, inRoi.begin(), inRoi.end()); } - sort(OR_Assamblage.begin(), OR_Assamblage.end()); - it = unique(OR_Assamblage.begin(), OR_Assamblage.end()); - OR_Assamblage.resize( it - OR_Assamblage.begin() ); - MITK_DEBUG << "returning OR vector, size: " << OR_Assamblage.size(); - - return OR_Assamblage; + // remove duplicates + sort(result.begin(), result.end()); + it = unique(result.begin(), result.end()); + result.resize( it - result.begin() ); + break; } - case 2: + case 2: // NOT { - //NOT - //get IDs of all fibers - std::vector childResults; - childResults.reserve(this->GetNumFibers()); - vtkSmartPointer idSet = m_FiberIdDataSet->GetCellData()->GetArray(FIBER_ID_ARRAY); - MITK_DEBUG << "m_NumOfFib: " << this->GetNumFibers() << " cellIdNum: " << idSet->GetNumberOfTuples(); for(long i=0; iGetNumFibers(); i++) - { - MITK_DEBUG << "i: " << i << " idset: " << idSet->GetTuple(i)[0]; - childResults.push_back(idSet->GetTuple(i)[0]); - } + result.push_back(i); - std::sort(childResults.begin(), childResults.end()); - std::vector NOT_Assamblage(childResults.size()); - //fill it with -1, otherwise 0 will be stored and 0 can also be an ID of fiber! - fill(NOT_Assamblage.begin(), NOT_Assamblage.end(), -1); std::vector::iterator it; - - for (long i=0; igetNumberOfChildren(); ++i) + for (long i=0; igetNumberOfChildren(); ++i) { - std::vector tmpChild = ExtractFiberIdSubset(pfcomp->getChildAt(i)); - sort(tmpChild.begin(), tmpChild.end()); - - it = std::set_difference(childResults.begin(), childResults.end(), - tmpChild.begin(), tmpChild.end(), - NOT_Assamblage.begin() ); - - } + std::vector inRoi = ExtractFiberIdSubset(pfc->getChildAt(i)); - MITK_DEBUG << "resize Vector"; - long i=0; - while (NOT_Assamblage[i] != -1){ //-1 represents a placeholder in the array - ++i; + std::vector rest(result.size()-inRoi.size()); + it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); + rest.resize( it - rest.begin() ); + result = rest; } - NOT_Assamblage.resize(i); - - return NOT_Assamblage; - } - default: - MITK_DEBUG << "we have an UNDEFINED composition... ERROR" ; break; - + } } } - else + else if ( dynamic_cast(roi) ) // actual extraction { - mitk::PlaneGeometry::ConstPointer pfgeometry = pf->GetPlaneGeometry(); - const mitk::PlaneGeometry* planeGeometry = dynamic_cast (pfgeometry.GetPointer()); - Vector3D planeNormal = planeGeometry->GetNormal(); + mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi); + Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); planeNormal.Normalize(); - Point3D planeOrigin = planeGeometry->GetOrigin(); - - MITK_DEBUG << "planeOrigin: " << planeOrigin[0] << " | " << planeOrigin[1] << " | " << planeOrigin[2] << endl; - MITK_DEBUG << "planeNormal: " << planeNormal[0] << " | " << planeNormal[1] << " | " << planeNormal[2] << endl; + Point3D planeOrigin = planarFigure->GetPlaneGeometry()->GetOrigin(); - std::vector PointsOnPlane; // contains all pointIds which are crossing the cutting plane - std::vector PointsInROI; // based on PointsOnPlane, all ROI relevant point IDs are stored here - - /* Define cutting plane by ROI (PlanarFigure) */ + // define cutting plane by ROI geometry (PlanarFigure) vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetOrigin(planeOrigin[0],planeOrigin[1],planeOrigin[2]); plane->SetNormal(planeNormal[0],planeNormal[1],planeNormal[2]); - /* get all points/fibers cutting the plane */ - MITK_DEBUG << "start clipping"; + // get all fiber/plane intersection points vtkSmartPointer clipper = vtkSmartPointer::New(); clipper->SetInputData(m_FiberIdDataSet); clipper->SetClipFunction(plane); clipper->GenerateClipScalarsOn(); clipper->GenerateClippedOutputOn(); clipper->Update(); vtkSmartPointer clipperout = clipper->GetClippedOutput(); - MITK_DEBUG << "end clipping"; - - MITK_DEBUG << "init and update clipperoutput"; - // clipperout->GetPointData()->Initialize(); - // clipperout->Update(); //VTK6_TODO - MITK_DEBUG << "init and update clipperoutput completed"; + if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) + return result; - MITK_DEBUG << "STEP 1: find all points which have distance 0 to the given plane"; - /*======STEP 1====== - * extract all points, which are crossing the plane */ - // Scalar values describe the distance between each remaining point to the given plane. Values sorted by point index vtkSmartPointer distanceList = clipperout->GetPointData()->GetScalars(); - vtkIdType sizeOfList = distanceList->GetNumberOfTuples(); - PointsOnPlane.reserve(sizeOfList); /* use reserve for high-performant push_back, no hidden copy procedures are processed then! - * size of list can be optimized by reducing allocation, but be aware of iterator and vector size*/ - - for (int i=0; iGetTuple(i); + vtkIdType numPoints = distanceList->GetNumberOfTuples(); - // check if point is on plane. - // 0.01 due to some approximation errors when calculating distance - if (distance[0] >= -0.01 && distance[0] <= 0.01) - PointsOnPlane.push_back(i); + std::vector pointsOnPlane; + pointsOnPlane.reserve(numPoints); + for (int i=0; iGetTuple(i)[0]; + // check if point is on plane + if (distance >= -0.01 && distance <= 0.01) + pointsOnPlane.push_back(i); } + if (pointsOnPlane.empty()) + return result; - - MITK_DEBUG << "Num Of points on plane: " << PointsOnPlane.size(); - - MITK_DEBUG << "Step 2: extract Interesting points with respect to given extraction planarFigure"; - - PointsInROI.reserve(PointsOnPlane.size()); - /*=======STEP 2===== - * extract ROI relevant pointIds */ - + // get all point IDs inside the ROI + std::vector pointsInROI; + pointsInROI.reserve(pointsOnPlane.size()); mitk::PlanarCircle::Pointer circleName = mitk::PlanarCircle::New(); mitk::PlanarPolygon::Pointer polyName = mitk::PlanarPolygon::New(); - if ( pf->GetNameOfClass() == circleName->GetNameOfClass() ) + if ( planarFigure->GetNameOfClass() == circleName->GetNameOfClass() ) { //calculate circle radius - mitk::Point3D V1w = pf->GetWorldControlPoint(0); //centerPoint - mitk::Point3D V2w = pf->GetWorldControlPoint(1); //radiusPoint + mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint + mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint - double distPF = V1w.EuclideanDistanceTo(V2w); + double radius = V1w.EuclideanDistanceTo(V2w); + radius *= radius; - for (unsigned int i=0; iGetPoint(PointsOnPlane[i])[0] - V1w[0]) * (clipperout->GetPoint(PointsOnPlane[i])[0] - V1w[0]) + - (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) * (clipperout->GetPoint(PointsOnPlane[i])[1] - V1w[1]) + - (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2]) * (clipperout->GetPoint(PointsOnPlane[i])[2] - V1w[2])) ; - - if( XdistPnt <= distPF) - PointsInROI.push_back(PointsOnPlane[i]); + double p[3]; clipperout->GetPoint(pointsOnPlane[i], p); + double dist = (p[0]-V1w[0])*(p[0]-V1w[0])+(p[1]-V1w[1])*(p[1]-V1w[1])+(p[2]-V1w[2])*(p[2]-V1w[2]); + if( dist <= radius) + pointsInROI.push_back(pointsOnPlane[i]); } } - else if ( pf->GetNameOfClass() == polyName->GetNameOfClass() ) + else if ( planarFigure->GetNameOfClass() == polyName->GetNameOfClass() ) { //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkSmartPointer::New(); - - //get the control points from pf and insert them to vtkPolygon - unsigned int nrCtrlPnts = pf->GetNumberOfControlPoints(); - - for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) { - polygonVtk->GetPoints()->InsertNextPoint((double)pf->GetWorldControlPoint(i)[0], (double)pf->GetWorldControlPoint(i)[1], (double)pf->GetWorldControlPoint(i)[2] ); + itk::Point p = planarFigure->GetWorldControlPoint(i); + polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); } - //prepare everything for using pointInPolygon function double n[3]; - polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), - static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); - + polygonVtk->ComputeNormal(polygonVtk->GetPoints()->GetNumberOfPoints(), static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), n); double bounds[6]; polygonVtk->GetPoints()->GetBounds(bounds); - for (unsigned int i=0; iGetPoint(PointsOnPlane[i])[0], clipperout->GetPoint(PointsOnPlane[i])[1], clipperout->GetPoint(PointsOnPlane[i])[2]}; - int isInPolygon = polygonVtk->PointInPolygon(checkIn, polygonVtk->GetPoints()->GetNumberOfPoints() - , static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); + double p[3]; clipperout->GetPoint(pointsOnPlane[i], p); + int isInPolygon = polygonVtk->PointInPolygon(p, polygonVtk->GetPoints()->GetNumberOfPoints(), static_cast(polygonVtk->GetPoints()->GetData()->GetVoidPointer(0)), bounds, n); if( isInPolygon ) - PointsInROI.push_back(PointsOnPlane[i]); + pointsInROI.push_back(pointsOnPlane[i]); } } + if (pointsInROI.empty()) + return result; - MITK_DEBUG << "Step3: Identify fibers"; - // we need to access the fiberId Array, so make sure that this array is available - if (!clipperout->GetCellData()->HasArray(FIBER_ID_ARRAY)) - { - MITK_DEBUG << "ERROR: FiberID array does not exist, no correlation between points and fiberIds possible! Make sure calling GenerateFiberIds()"; - return FibersInROI; // FibersInRoi is empty then - } - if (PointsInROI.size()<=0) - return FibersInROI; - - // prepare a structure where each point id is represented as an indexId. - // vector looks like: | pntId | fiberIdx | - std::vector< long > pointindexFiberMap; + // get the fiber IDs corresponding to all clipped points + std::vector< long > pointToFiberMap; // pointToFiberMap[PointID] = FiberIndex + pointToFiberMap.resize(clipperout->GetNumberOfPoints()); - // walk through the whole subline section and create an vector sorted by point index - vtkCellArray *clipperlines = clipperout->GetLines(); + vtkCellArray* clipperlines = clipperout->GetLines(); clipperlines->InitTraversal(); - long numOfLineCells = clipperlines->GetNumberOfCells(); - long numofClippedPoints = clipperout->GetNumberOfPoints(); - pointindexFiberMap.resize(numofClippedPoints); - - - //prepare resulting vector - FibersInROI.reserve(PointsInROI.size()); - - MITK_DEBUG << "\n===== Pointindex based structure initialized ======\n"; - - // go through resulting "sub"lines which are stored as cells, "i" corresponds to current line id. - for (int i=0, ic=0 ; iGetCell(ic, npts, pts); - - // go through point ids in hosting subline, "j" corresponds to current pointindex in current line i. eg. idx[0]=45; idx[1]=46 - for (long j=0; jGetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0] << " to pointId: " << pts[j]; - pointindexFiberMap[ pts[j] ] = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; - // MITK_DEBUG << "in array: " << pointindexFiberMap[ pts[j] ]; - } - + for (int i=0, ic=0 ; iGetNumberOfCells(); i++, ic+=3) + { + // ic is the index counter for the cells hosting the desired information. each cell consits of 3 items. + long fiberID = clipperout->GetCellData()->GetArray(FIBER_ID_ARRAY)->GetTuple(i)[0]; + vtkIdType numPoints; + vtkIdType* pointIDs; + clipperlines->GetCell(ic, numPoints, pointIDs); + + for (long j=0; j=0) - FibersInROI.push_back(pointindexFiberMap[ PointsInROI[k] ]); + if (pointToFiberMap[pointsInROI[k]]<=GetNumFibers() && pointToFiberMap[pointsInROI[k]]>=0) + result.push_back( pointToFiberMap[pointsInROI[k]] ); else MITK_INFO << "ERROR in ExtractFiberIdSubset; impossible fiber id detected"; } - m_PointsRoi = PointsInROI; - - } - - // detecting fiberId duplicates - MITK_DEBUG << "check for duplicates"; - - sort(FibersInROI.begin(), FibersInROI.end()); - bool hasDuplicats = false; - for(unsigned long i=0; i::iterator it; - it = unique (FibersInROI.begin(), FibersInROI.end()); - FibersInROI.resize( it - FibersInROI.begin() ); + sort(result.begin(), result.end()); + it = unique (result.begin(), result.end()); + result.resize( it - result.begin() ); } - return FibersInROI; + return result; } void mitk::FiberBundleX::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(true); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } - float min = itk::NumericTraits::NonpositiveMin(); - float max = itk::NumericTraits::max(); - float b[] = {max, min, max, min, max, min}; + double b[6]; + m_FiberPolyData->GetBounds(b); + // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; - for (int j=0; jGetPoint(j, p1); + double p2[3]; + points->GetPoint(j+1, p2); - if (p1[0]b[1]) - b[1]=p1[0]; - - if (p1[1]b[3]) - b[3]=p1[1]; - - if (p1[2]b[5]) - b[5]=p1[2]; - - // calculate statistics - if (jGetPoint(j+1, p2); - - float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); - length += dist; - } + float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); + length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); - // provide some border margin - for(int i=0; i<=4; i+=2) - b[i] -=10; - for(int i=1; i<=5; i+=2) - b[i] +=10; - mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); } std::vector mitk::FiberBundleX::GetAvailableColorCodings() { std::vector availableColorCodings; int numColors = m_FiberPolyData->GetPointData()->GetNumberOfArrays(); for(int i=0; iGetPointData()->GetArrayName(i)); } //this controlstructure shall be implemented by the calling method if (availableColorCodings.empty()) MITK_DEBUG << "no colorcodings available in fiberbundleX"; return availableColorCodings; } char* mitk::FiberBundleX::GetCurrentColorCoding() { return m_CurrentColorCoding; } void mitk::FiberBundleX::SetColorCoding(const char* requestedColorCoding) { if (requestedColorCoding==NULL) return; MITK_DEBUG << "SetColorCoding:" << requestedColorCoding; if( strcmp (COLORCODING_ORIENTATION_BASED,requestedColorCoding) == 0 ) { this->m_CurrentColorCoding = (char*) COLORCODING_ORIENTATION_BASED; } else if( strcmp (COLORCODING_FA_BASED,requestedColorCoding) == 0 ) { this->m_CurrentColorCoding = (char*) COLORCODING_FA_BASED; } else if( strcmp (COLORCODING_CUSTOM,requestedColorCoding) == 0 ) { this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; } else { MITK_DEBUG << "FIBERBUNDLE X: UNKNOWN COLORCODING in FIBERBUNDLEX Datastructure"; this->m_CurrentColorCoding = (char*) COLORCODING_CUSTOM; //will cause blank colorcoding of fibers } } itk::Matrix< double, 3, 3 > mitk::FiberBundleX::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } itk::Point mitk::FiberBundleX::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } void mitk::FiberBundleX::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } void mitk::FiberBundleX::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } void mitk::FiberBundleX::ScaleFibers(double x, double y, double z) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; p[0] *= x; p[1] *= y; p[2] *= z; p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } void mitk::FiberBundleX::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } void mitk::FiberBundleX::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } bool mitk::FiberBundleX::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); return true; } bool mitk::FiberBundleX::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); return true; } bool mitk::FiberBundleX::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); return true; } void mitk::FiberBundleX::DoFiberSmoothing(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkSmartPointer::New(); //cellcontainer for smoothed lines vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer newPoints = vtkSmartPointer::New(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); float length = m_FiberLengths.at(i); int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkSmartPointer::New(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); UpdateColorCoding(); UpdateFiberGeometry(); m_FiberSampling = 10/pointDistance; } void mitk::FiberBundleX::DoFiberSmoothing(float pointDistance) { DoFiberSmoothing(pointDistance, 0, 0, 0 ); } unsigned long mitk::FiberBundleX::GetNumberOfPoints() { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } void mitk::FiberBundleX::CompressFibers(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { double ref[3]; points->GetPoint(k, ref); pred[0]=ref[0]; pred[1]=ref[1]; pred[2]=ref[2]; validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; kGetPoint(k, ref); succ[0]=ref[0]; succ[1]=ref[1]; succ[2]=ref[2]; validS = k; break; } if (validP>=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcGetPoint(j, cand); vtkIdType id = vtkNewPoints->InsertNextPoint(cand); container->GetPointIds()->InsertNextId(id); } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); UpdateColorCoding(); UpdateFiberGeometry(); } } // Resample fiber to get equidistant points void mitk::FiberBundleX::ResampleFibers(float pointDistance) { if (pointDistance<=0.00001) return; vtkSmartPointer newPoly = vtkSmartPointer::New(); vtkSmartPointer newCellArray = vtkSmartPointer::New(); vtkSmartPointer newPoints = vtkSmartPointer::New(); int numberOfLines = m_NumFibers; MITK_INFO << "Resampling fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); double* point = points->GetPoint(0); vtkIdType pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); float dtau = 0; int cur_p = 1; itk::Vector dR; float normdR = 0; for (;;) { while (dtau <= pointDistance && cur_p < numPoints) { itk::Vector v1; point = points->GetPoint(cur_p-1); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2; point = points->GetPoint(cur_p); v2[0] = point[0]; v2[1] = point[1]; v2[2] = point[2]; dR = v2 - v1; normdR = std::sqrt(dR.GetSquaredNorm()); dtau += normdR; cur_p++; } if (dtau >= pointDistance) { itk::Vector v1; point = points->GetPoint(cur_p-1); v1[0] = point[0]; v1[1] = point[1]; v1[2] = point[2]; itk::Vector v2 = v1 - dR*( (dtau-pointDistance)/normdR ); pointId = newPoints->InsertNextPoint(v2.GetDataPointer()); container->GetPointIds()->InsertNextId(pointId); } else { point = points->GetPoint(numPoints-1); pointId = newPoints->InsertNextPoint(point); container->GetPointIds()->InsertNextId(pointId); break; } dtau = dtau-pointDistance; } newCellArray->InsertNextCell(container); } newPoly->SetPoints(newPoints); newPoly->SetLines(newCellArray); m_FiberPolyData = newPoly; UpdateFiberGeometry(); UpdateColorCoding(); m_FiberSampling = 10/pointDistance; } // reapply selected colorcoding in case polydata structure has changed void mitk::FiberBundleX::UpdateColorCoding() { char* cc = GetCurrentColorCoding(); if( strcmp (COLORCODING_ORIENTATION_BASED,cc) == 0 ) DoColorCodingOrientationBased(); else if( strcmp (COLORCODING_FA_BASED,cc) == 0 ) DoColorCodingFaBased(); } // reapply selected colorcoding in case polydata structure has changed bool mitk::FiberBundleX::Equals(mitk::FiberBundleX* fib, double eps) { if (fib==NULL) { MITK_INFO << "Reference bundle is NULL!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundleX::UpdateOutputInformation() { } void mitk::FiberBundleX::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundleX::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundleX::VerifyRequestedRegion() { return true; } void mitk::FiberBundleX::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h index 88942bca24..e6db6c0863 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundleX/mitkFiberBundleX.h @@ -1,173 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_FiberBundleX_H #define _MITK_FiberBundleX_H //includes for MITK datastructure #include #include #include //includes storing fiberdata #include #include #include #include #include //#include #include #include +#include namespace mitk { /** * \brief Base Class for Fiber Bundles; */ class MitkFiberTracking_EXPORT FiberBundleX : public BaseData { public: typedef itk::Image ItkUcharImgType; // fiber colorcodings static const char* COLORCODING_ORIENTATION_BASED; static const char* COLORCODING_FA_BASED; static const char* COLORCODING_CUSTOM; static const char* FIBER_ID_ARRAY; virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion(const itk::DataObject*); mitkClassMacro( FiberBundleX, BaseData ) itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkSmartPointer) // custom constructor // colorcoding related methods void SetColorCoding(const char*); void SetFAMap(mitk::Image::Pointer); template void SetFAMap(const mitk::PixelType pixelType, mitk::Image::Pointer); void DoColorCodingOrientationBased(); void DoColorCodingFaBased(); void DoUseFaFiberOpacity(); void ResetFiberOpacity(); // fiber smoothing/resampling void CompressFibers(float error = 0.0); void ResampleFibers(float pointDistance = 1); void DoFiberSmoothing(float pointDistance); void DoFiberSmoothing(float pointDistance, double tension, double continuity, double bias ); bool RemoveShortFibers(float lengthInMM); bool RemoveLongFibers(float lengthInMM); bool ApplyCurvatureThreshold(float minRadius, bool deleteFibers); void MirrorFibers(unsigned int axis); void RotateAroundAxis(double x, double y, double z); void TranslateFibers(double x, double y, double z); void ScaleFibers(double x, double y, double z); void TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz); itk::Point TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz); itk::Matrix< double, 3, 3 > TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz); // add/subtract fibers FiberBundleX::Pointer AddBundle(FiberBundleX* fib); FiberBundleX::Pointer SubtractBundle(FiberBundleX* fib); // fiber subset extraction - FiberBundleX::Pointer ExtractFiberSubset(PlanarFigure *pf); - std::vector ExtractFiberIdSubset(PlanarFigure* pf); + FiberBundleX::Pointer ExtractFiberSubset(BaseData* roi); + std::vector ExtractFiberIdSubset(BaseData* roi); FiberBundleX::Pointer ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert=false); FiberBundleX::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false); vtkSmartPointer GeneratePolyDataByIds( std::vector ); // TODO: make protected void GenerateFiberIds(); // TODO: make protected // get/set data void SetFiberPolyData(vtkSmartPointer, bool updateGeometry = true); vtkSmartPointer GetFiberPolyData(); std::vector< std::string > GetAvailableColorCodings(); char* GetCurrentColorCoding(); itkGetMacro( NumFibers, int) itkGetMacro( FiberSampling, int) itkGetMacro( MinFiberLength, float ) itkGetMacro( MaxFiberLength, float ) itkGetMacro( MeanFiberLength, float ) itkGetMacro( MedianFiberLength, float ) itkGetMacro( LengthStDev, float ) unsigned long GetNumberOfPoints(); - std::vector GetPointsRoi() - { - return m_PointsRoi; - } - // copy fiber bundle mitk::FiberBundleX::Pointer GetDeepCopy(); // compare fiber bundles bool Equals(FiberBundleX* fib, double eps=0.0001); itkSetMacro( ReferenceImage, mitk::Image::Pointer ) itkGetMacro( ReferenceImage, mitk::Image::Pointer ) protected: FiberBundleX( vtkPolyData* fiberPolyData = NULL ); virtual ~FiberBundleX(); itk::Point GetItkPoint(double point[3]); // calculate geometry from fiber extent void UpdateFiberGeometry(); // calculate colorcoding values according to m_CurrentColorCoding void UpdateColorCoding(); private: // actual fiber container vtkSmartPointer m_FiberPolyData; // contains fiber ids vtkSmartPointer m_FiberIdDataSet; char* m_CurrentColorCoding; int m_NumFibers; std::vector< float > m_FiberLengths; float m_MinFiberLength; float m_MaxFiberLength; float m_MeanFiberLength; float m_MedianFiberLength; float m_LengthStDev; int m_FiberSampling; - std::vector m_PointsRoi; // this global variable needs to be refactored - mitk::Image::Pointer m_ReferenceImage; }; } // namespace mitk #endif /* _MITK_FiberBundleX_H */ diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp index 76b5f7b6e5..b6e05e2ccc 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp @@ -1,143 +1,157 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /* * mitkPlanarFigureComposite.cpp * mitk-all * * Created by HAL9000 on 2/4/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkPlanarFigureComposite.h" mitk::PlanarFigureComposite::PlanarFigureComposite() { m_PFVector = CompositionContainer::New(); m_DNVector = DataNodeContainer::New(); } mitk::PlanarFigureComposite::~PlanarFigureComposite() { } -mitk::PlanarFigureComposite::PlanarFigureComposite(const Self& other) - : PlanarFigure(other), - m_PFVector(other.m_PFVector->Clone()), - m_compOperation(other.m_compOperation), - m_DNVector(other.m_DNVector->Clone()), - m_name(other.m_name) -{ -} - void mitk::PlanarFigureComposite::addDataNode(mitk::DataNode::Pointer dnode) { m_DNVector->InsertElement(m_DNVector->Size(), dnode); } -void mitk::PlanarFigureComposite::addPlanarFigure(PlanarFigure::Pointer pf) +void mitk::PlanarFigureComposite::addPlanarFigure(BaseData::Pointer pf) { m_PFVector->InsertElement(m_PFVector->Size(), pf); } void mitk::PlanarFigureComposite::replaceDataNodeAt(int idx, mitk::DataNode::Pointer dn) { m_DNVector->SetElement( idx, dn ); } void mitk::PlanarFigureComposite::setOperationType(PFCompositionOperation pfcOp) { this->m_compOperation = pfcOp; } mitk::PFCompositionOperation mitk::PlanarFigureComposite::getOperationType() { return this->m_compOperation; } void mitk::PlanarFigureComposite::setDisplayName(std::string displName) { m_name = displName; } std::string mitk::PlanarFigureComposite::getDisplayName() { return m_name; } int mitk::PlanarFigureComposite::getNumberOfChildren() { return m_PFVector->Size(); } -mitk::PlanarFigure::Pointer mitk::PlanarFigureComposite::getChildAt(int idx) +mitk::BaseData::Pointer mitk::PlanarFigureComposite::getChildAt(int idx) { return m_PFVector->ElementAt(idx); } mitk::DataNode::Pointer mitk::PlanarFigureComposite::getDataNodeAt(int idx) { return m_DNVector->ElementAt(idx); } //musthave implementations from superclass.... not sure if return true makes sense bool mitk::PlanarFigureComposite::SetControlPoint( unsigned int , const Point2D &, bool ) { return true; } void mitk::PlanarFigureComposite::GeneratePolyLine() { } void mitk::PlanarFigureComposite::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/) { // A circle does not require a helper object } void mitk::PlanarFigureComposite::EvaluateFeaturesInternal() { } void mitk::PlanarFigureComposite::PrintSelf( std::ostream&, itk::Indent) const { } + +/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ +void mitk::PlanarFigureComposite::UpdateOutputInformation() +{ + +} +void mitk::PlanarFigureComposite::SetRequestedRegionToLargestPossibleRegion() +{ + +} +bool mitk::PlanarFigureComposite::RequestedRegionIsOutsideOfTheBufferedRegion() +{ + return false; +} +bool mitk::PlanarFigureComposite::VerifyRequestedRegion() +{ + return true; +} +void mitk::PlanarFigureComposite::SetRequestedRegion(const itk::DataObject* ) +{ + +} + diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h index 12bf9d1b22..056f9c333d 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.h @@ -1,128 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /* * mitkPlanarFigureComposite.h * mitk-all * * Created by HAL9000 on 2/4/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #ifndef _MITK_PLANARFIGURECOMPOSITE_H #define _MITK_PLANARFIGURECOMPOSITE_H #include "mitkCommon.h" #include "mitkBaseData.h" #include #include "mitkPlanarFigure.h" #include "itkVectorContainer.h" #include "mitkDataNode.h" namespace mitk { - enum PFCompositionOperation { +enum PFCompositionOperation { PFCOMPOSITION_AND_OPERATION, PFCOMPOSITION_OR_OPERATION, PFCOMPOSITION_NOT_OPERATION, - }; +}; - class MitkFiberTracking_EXPORT PlanarFigureComposite : public PlanarFigure - { +class MitkFiberTracking_EXPORT PlanarFigureComposite : public BaseData +{ - typedef itk::VectorContainer CompositionContainer; + typedef itk::VectorContainer CompositionContainer; typedef itk::VectorContainer DataNodeContainer; - public: - mitkClassMacro(PlanarFigureComposite, PlanarFigure); +public: + mitkClassMacro(PlanarFigureComposite, BaseData) itkFactorylessNewMacro(Self) itkCloneMacro(Self) + virtual void UpdateOutputInformation(); + virtual void SetRequestedRegionToLargestPossibleRegion(); + virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); + virtual bool VerifyRequestedRegion(); + virtual void SetRequestedRegion(const itk::DataObject*); + // ///MUST HAVE IMPLEMENTATION////// bool SetControlPoint(unsigned int, const Point2D &, bool); unsigned int GetMinimumNumberOfControlPoints() const { - return 0; + return 0; } - /** \brief Circle has 2 control points per definition. */ unsigned int GetMaximumNumberOfControlPoints() const { - return 0; + return 0; } // ///////////////////////// - - int getNumberOfChildren(); - mitk::PlanarFigure::Pointer getChildAt(int); - void addPlanarFigure(PlanarFigure::Pointer); + mitk::BaseData::Pointer getChildAt(int); + void addPlanarFigure(BaseData::Pointer); mitk::DataNode::Pointer getDataNodeAt(int); void addDataNode(mitk::DataNode::Pointer); void replaceDataNodeAt(int, mitk::DataNode::Pointer); // set if this compsition is AND, OR, NOT void setOperationType(PFCompositionOperation); PFCompositionOperation getOperationType(); void setDisplayName(std::string); std::string getDisplayName(); - protected: +protected: PlanarFigureComposite(); virtual ~PlanarFigureComposite(); PlanarFigureComposite(const Self& other); - mitkCloneMacro(Self); - // ///MUST HAVE IMPLEMENTATION////// /** \brief Generates the poly-line representation of the planar figure. */ virtual void GeneratePolyLine(); /** \brief Generates the poly-lines that should be drawn the same size regardless of zoom.*/ virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight); /** \brief Calculates feature quantities of the planar figure. */ virtual void EvaluateFeaturesInternal(); virtual void PrintSelf(std::ostream &, itk::Indent) const; // //////////////////// - - - - private: +private: //this vector takes planarfigures and planarfigureComosite types CompositionContainer::Pointer m_PFVector; PFCompositionOperation m_compOperation; DataNodeContainer::Pointer m_DNVector; std::string m_name; - - - - }; - +}; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp index cf5fb5474b..59554ecd46 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberExtractionTest.cpp @@ -1,93 +1,101 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include +#include /**Documentation * Test if fiber transfortaiom methods work correctly */ int mitkFiberExtractionTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkFiberExtractionTest"); MITK_INFO << "argc: " << argc; MITK_TEST_CONDITION_REQUIRED(argc==13,"check for input data") try{ mitk::FiberBundleX::Pointer groundTruthFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[1])->GetData()); mitk::FiberBundleX::Pointer testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); // test planar figure based extraction mitk::PlanarFigure::Pointer pf1 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); mitk::PlanarFigure::Pointer pf2 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); mitk::PlanarFigure::Pointer pf3 = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); + + MITK_INFO << "TEST1"; + mitk::PlanarFigureComposite::Pointer pfc1 = mitk::PlanarFigureComposite::New(); pfc1->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); - pfc1->addPlanarFigure(pf2); - pfc1->addPlanarFigure(pf3); + pfc1->addPlanarFigure(dynamic_cast(pf2.GetPointer())); + pfc1->addPlanarFigure(dynamic_cast(pf3.GetPointer())); + MITK_INFO << "TEST2"; mitk::PlanarFigureComposite::Pointer pfc2 = mitk::PlanarFigureComposite::New(); pfc2->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); - pfc2->addPlanarFigure(pf1); - pfc2->addPlanarFigure(dynamic_cast(pfc1.GetPointer())); + pfc2->addPlanarFigure(dynamic_cast(pf1.GetPointer())); + pfc2->addPlanarFigure(pfc1.GetPointer()); + MITK_INFO << "TEST3"; mitk::FiberBundleX::Pointer extractedFibs = groundTruthFibs->ExtractFiberSubset(pfc2); + MITK_INFO << "TEST4"; MITK_TEST_CONDITION_REQUIRED(extractedFibs->Equals(testFibs),"check planar figure extraction") + MITK_INFO << "TEST5"; // test subtraction and addition mitk::FiberBundleX::Pointer notExtractedFibs = groundTruthFibs->SubtractBundle(extractedFibs); MITK_INFO << argv[11]; testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); MITK_TEST_CONDITION_REQUIRED(notExtractedFibs->Equals(testFibs),"check bundle subtraction") mitk::FiberBundleX::Pointer joinded = extractedFibs->AddBundle(notExtractedFibs); testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); MITK_TEST_CONDITION_REQUIRED(joinded->Equals(testFibs),"check bundle addition") // test binary image based extraction mitk::Image::Pointer mitkRoiImage = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); typedef itk::Image< unsigned char, 3 > itkUCharImageType; itkUCharImageType::Pointer itkRoiImage = itkUCharImageType::New(); mitk::CastToItkImage(mitkRoiImage, itkRoiImage); mitk::FiberBundleX::Pointer inside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, false); mitk::FiberBundleX::Pointer outside = groundTruthFibs->RemoveFibersOutside(itkRoiImage, true); mitk::FiberBundleX::Pointer passing = groundTruthFibs->ExtractFiberSubset(itkRoiImage, true); mitk::FiberBundleX::Pointer ending = groundTruthFibs->ExtractFiberSubset(itkRoiImage, false); testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); MITK_TEST_CONDITION_REQUIRED(inside->Equals(testFibs),"check inside mask extraction") testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); MITK_TEST_CONDITION_REQUIRED(outside->Equals(testFibs),"check outside mask extraction") testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); MITK_TEST_CONDITION_REQUIRED(passing->Equals(testFibs),"check passing mask extraction") testFibs = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); MITK_TEST_CONDITION_REQUIRED(ending->Equals(testFibs),"check ending in mask extraction") } catch(...) { return EXIT_FAILURE; } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp index 755b82435c..6b536d7874 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp @@ -1,154 +1,159 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "MiniAppManager.h" #include #include #include "ctkCommandLineParser.h" #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int FiberExtraction(int argc, char* argv[]) { ctkCommandLineParser parser; parser.setTitle("Fiber Extraction"); parser.setCategory("Fiber Tracking and Processing Methods"); parser.setContributor("MBI"); parser.setDescription(""); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", ctkCommandLineParser::String, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("out", "o", ctkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); parser.addArgument("planfirgure1", "pf1", ctkCommandLineParser::String, "Figure 1:", "first ROI", us::Any(), false); parser.addArgument("planfirgure2", "pf2", ctkCommandLineParser::String, "Figure 2:", "second ROI", us::Any()); parser.addArgument("operation", "op", ctkCommandLineParser::String, "Operation:", "logical operation (AND, OR, NOT)", us::Any()); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFib = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); string operation(""); string pf2_path(""); if (parsedArgs.count("operation")) { operation = us::any_cast(parsedArgs["operation"]); if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR")) pf2_path = us::any_cast(parsedArgs["planfirgure2"]); } try { typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFib)->GetData()); mitk::FiberBundleX::Pointer result; - mitk::PlanarFigure::Pointer pf1 = dynamic_cast(mitk::IOUtil::LoadDataNode(pf1_path)->GetData()); + mitk::BaseData::Pointer input1 = mitk::IOUtil::LoadDataNode(pf1_path)->GetData(); + mitk::PlanarFigure::Pointer pf1 = dynamic_cast(input1.GetPointer()); if (pf1.IsNotNull()) { + mitk::BaseData::Pointer input2; mitk::PlanarFigure::Pointer pf2; if (!pf2_path.empty()) - pf2 = dynamic_cast(mitk::IOUtil::LoadDataNode(pf2_path)->GetData()); + { + input2 = mitk::IOUtil::LoadDataNode(pf2_path)->GetData(); + pf2 = dynamic_cast(input2.GetPointer()); + } mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New(); if (operation.empty()) { - result = inputTractogram->ExtractFiberSubset(pf1); + result = inputTractogram->ExtractFiberSubset(input1); } else if (operation=="NOT") { pfc->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); - pfc->addPlanarFigure(pf1); + pfc->addPlanarFigure(input1); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="AND" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); - pfc->addPlanarFigure(pf1); - pfc->addPlanarFigure(pf2); + pfc->addPlanarFigure(input1); + pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="OR" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); - pfc->addPlanarFigure(pf1); - pfc->addPlanarFigure(pf2); + pfc->addPlanarFigure(input1); + pfc->addPlanarFigure(input2); result = inputTractogram->ExtractFiberSubset(pfc); } else { MITK_INFO << "Could not process input:"; MITK_INFO << pf1_path; MITK_INFO << pf2_path; MITK_INFO << operation; } } else { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(pf1_path)->GetData()); mitk::CastToItkImage(mitkMaskImage, itkMaskImage); if (operation=="NOT") result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, true); else result = inputTractogram->ExtractFiberSubset(itkMaskImage, true, false); } if (result.IsNotNull()) mitk::IOUtil::SaveBaseData(result, outFib); else MITK_INFO << "No valid fiber bundle extracted."; MITK_INFO << "DONE"; } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(FiberExtraction); diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp index a7038c0a82..d59a34ae7e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.cpp @@ -1,1483 +1,1208 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberExtractionView.h" #include // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" // ITK #include #include #include #include #include #include #include #include const std::string QmitkFiberExtractionView::VIEW_ID = "org.mitk.views.fiberextraction"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkFiberExtractionView::QmitkFiberExtractionView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) , m_CircleCounter(0) , m_PolygonCounter(0) , m_UpsamplingFactor(1) - , m_LastAddedPf(NULL) { } // Destructor QmitkFiberExtractionView::~QmitkFiberExtractionView() { } void QmitkFiberExtractionView::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::QmitkFiberExtractionViewControls; 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_PlanarFigureButtonsFrame->setEnabled(false); m_Controls->m_RectangleButton->setVisible(false); connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) ); connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) ); connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) ); connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) ); connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) ); connect(m_Controls->m_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_2, SIGNAL(clicked()), this, SLOT(ExtractNotPassingMask())); connect(m_Controls->m_Extract3dButton, SIGNAL(clicked()), this, SLOT(ExtractPassingMask())); connect( m_Controls->m_ExtractMask, SIGNAL(clicked()), this, SLOT(ExtractEndingInMask()) ); connect( m_Controls->doExtractFibersButton, SIGNAL(clicked()), this, SLOT(DoFiberExtraction()) ); connect( m_Controls->m_RemoveOutsideMaskButton, SIGNAL(clicked()), this, SLOT(DoRemoveOutsideMask())); connect( m_Controls->m_RemoveInsideMaskButton, SIGNAL(clicked()), this, SLOT(DoRemoveInsideMask())); } } void QmitkFiberExtractionView::DoRemoveInsideMask() { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundleX::Pointer newFib = fib->RemoveFibersOutside(mask, true); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); name += "_Cut"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberExtractionView::DoRemoveOutsideMask() { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundleX::Pointer newFib = fib->RemoveFibersOutside(mask); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); name += "_Cut"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberExtractionView::ExtractEndingInMask() { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, false); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); name += "_ending-in-mask"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberExtractionView::ExtractNotPassingMask() { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, true, true); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); name += "_not-passing-mask"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberExtractionView::ExtractPassingMask() { if (m_MaskImageNode.IsNull()) return; mitk::Image::Pointer mitkMask = dynamic_cast(m_MaskImageNode->GetData()); for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); QString name(m_SelectedFB.at(i)->GetName().c_str()); itkUCharImageType::Pointer mask = itkUCharImageType::New(); mitk::CastToItkImage(mitkMask, mask); mitk::FiberBundleX::Pointer newFib = fib->ExtractFiberSubset(mask, true); if (newFib->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } DataNode::Pointer newNode = DataNode::New(); newNode->SetData(newFib); name += "_passing-mask"; newNode->SetName(name.toStdString()); GetDefaultDataStorage()->Add(newNode); m_SelectedFB.at(i)->SetVisibility(false); } } -void QmitkFiberExtractionView::GenerateRoiImage(){ - +void QmitkFiberExtractionView::GenerateRoiImage() +{ if (m_SelectedPF.empty()) return; mitk::BaseGeometry::Pointer geometry; if (!m_SelectedFB.empty()) { mitk::FiberBundleX::Pointer fib = dynamic_cast(m_SelectedFB.front()->GetData()); geometry = fib->GetGeometry(); } else if (m_SelectedImage) geometry = m_SelectedImage->GetGeometry(); else return; itk::Vector spacing = geometry->GetSpacing(); spacing /= m_UpsamplingFactor; mitk::Point3D newOrigin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); newOrigin[0] += bounds.GetElement(0); newOrigin[1] += bounds.GetElement(2); newOrigin[2] += bounds.GetElement(4); itk::Matrix direction; itk::ImageRegion<3> imageRegion; for (int i=0; i<3; i++) for (int j=0; j<3; j++) direction[j][i] = geometry->GetMatrixColumn(i)[j]/spacing[j]; imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor); imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor); imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor); m_PlanarFigureImage = itkUCharImageType::New(); m_PlanarFigureImage->SetSpacing( spacing ); // Set the image spacing m_PlanarFigureImage->SetOrigin( newOrigin ); // Set the image origin m_PlanarFigureImage->SetDirection( direction ); // Set the image direction m_PlanarFigureImage->SetRegions( imageRegion ); m_PlanarFigureImage->Allocate(); m_PlanarFigureImage->FillBuffer( 0 ); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); - for (unsigned int i=0; iGetName(); + WritePfToImage(m_SelectedPF.at(0), tmpImage); + for (unsigned int i=1; iGetName(); + WritePfToImage(m_SelectedPF.at(i), tmpImage); + } DataNode::Pointer node = DataNode::New(); tmpImage = Image::New(); tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer()); tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer()); node->SetData(tmpImage); - node->SetName("ROI Image"); + node->SetName(name); this->GetDefaultDataStorage()->Add(node); } -void QmitkFiberExtractionView::CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image) +void QmitkFiberExtractionView::WritePfToImage(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); AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2, node->GetName() ); } } template < typename TPixel, unsigned int VImageDimension > void QmitkFiberExtractionView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ) { - - MITK_DEBUG << "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->GetExtentInMM(0) / spacing[0]; size[1] = planegeo->GetExtentInMM(1) / spacing[1]; size[2] = 1; resampler->SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; corrorig[2] += 0; planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(int c=0; cSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) - { sigma[d] = gausssigma * image->GetSpacing()[d]; - } double alpha = 2.0; - - typedef itk::GaussianInterpolateImageFunction - GaussianInterpolatorType; - - typename GaussianInterpolatorType::Pointer interpolator - = GaussianInterpolatorType::New(); - + 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(); - + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); - resampler->SetInterpolator( interpolator ); - } - // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); - - MITK_DEBUG << "Resampling requested image plane ... "; resampler->Update(); - MITK_DEBUG << " ... 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 QmitkFiberExtractionView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string ) { - - MITK_DEBUG << "InternalCalculateMaskFromPlanarFigure() start"; - typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, itkUCharImageType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". itkUCharImageType::Pointer newMaskImage = itkUCharImageType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; - case 1: i0 = 0; i1 = 2; break; - case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour vtkPoints *points = vtkPoints::New(); PlanarFigure::PolyLineType::const_iterator it; - std::vector indices; - unsigned int numberOfPoints = 0; - for ( it = planarFigurePolyline.begin(); - it != planarFigurePolyline.end(); - ++it ) + for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; - // Convert 2D point back to the local index coordinates of the selected - // image + // 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 + // 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->SetInputData( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() ); - - // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< itkUCharImageType > ImageImportType; typedef itk::VTKImageExport< itkUCharImageType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); - // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); - // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); typename ImageType::SizeType lowersize = {{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< itkUCharImageType, itkUCharImageType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(cropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); Image::Pointer tmpImage = Image::New(); tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer()); tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer()); Image::Pointer tmpImage2 = Image::New(); tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer()); const BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 ); const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 ); typedef itk::ImageRegionIteratorWithIndex IteratorType; IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion()); imageIterator.GoToBegin(); while ( !imageIterator.IsAtEnd() ) { unsigned char val = imageIterator.Value(); if (val>0) { itk::Index<3> index = imageIterator.GetIndex(); Point3D point; point[0] = index[0]; point[1] = index[1]; point[2] = index[2]; intImageGeometry3D->IndexToWorld(point, point); pfImageGeometry3D->WorldToIndex(point, point); point[i0] += 0.5; point[i1] += 0.5; index[0] = point[0]; index[1] = point[1]; index[2] = point[2]; if (pfImageGeometry3D->IsIndexInside(index)) m_PlanarFigureImage->SetPixel(index, 1); } ++imageIterator; } // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; - } void QmitkFiberExtractionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } - void QmitkFiberExtractionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } -/* OnSelectionChanged is registered to SelectionService, therefore no need to - implement SelectionService Listener explicitly */ - void QmitkFiberExtractionView::UpdateGui() { + m_Controls->m_FibLabel->setText("mandatory"); + m_Controls->m_PfLabel->setText("needed for extraction"); + m_Controls->m_InputData->setTitle("Please Select Input Data"); + m_Controls->m_Extract3dButton_2->setEnabled(false); m_Controls->m_Extract3dButton->setEnabled(false); m_Controls->m_ExtractMask->setEnabled(false); m_Controls->m_RemoveOutsideMaskButton->setEnabled(false); m_Controls->m_RemoveInsideMaskButton->setEnabled(false); - // are fiber bundles selected? - if ( m_SelectedFB.empty() ) - { - m_Controls->m_InputData->setTitle("Please Select Input Data"); + 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); - m_Controls->m_JoinBundles->setEnabled(false); - m_Controls->m_SubstractBundles->setEnabled(false); - m_Controls->doExtractFibersButton->setEnabled(false); - m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); - } - else - { - m_Controls->m_InputData->setTitle("Input Data"); + m_Controls->m_JoinBundles->setEnabled(false); + m_Controls->m_SubstractBundles->setEnabled(false); + m_Controls->doExtractFibersButton->setEnabled(false); + m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false); + // are fiber bundles selected? + if ( !m_SelectedFB.empty() ) + { + m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str())); m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true); // one bundle and one planar figure needed to extract fibers if (!m_SelectedPF.empty()) + { + m_Controls->m_InputData->setTitle("Input Data"); + m_Controls->m_PfLabel->setText(QString(m_SelectedPF.at(0)->GetName().c_str())); m_Controls->doExtractFibersButton->setEnabled(true); + } // more than two bundles needed to join/subtract if (m_SelectedFB.size() > 1) { + m_Controls->m_FibLabel->setText("multiple bundles selected"); + 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); - } if (m_MaskImageNode.IsNotNull()) { m_Controls->m_Extract3dButton_2->setEnabled(true); m_Controls->m_Extract3dButton->setEnabled(true); m_Controls->m_ExtractMask->setEnabled(true); m_Controls->m_RemoveOutsideMaskButton->setEnabled(true); m_Controls->m_RemoveInsideMaskButton->setEnabled(true); } } // 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_SelectedPF.empty() ) { if ( !m_SelectedFB.empty() || 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 QmitkFiberExtractionView::NodeRemoved(const mitk::DataNode* node) +{ + std::vector nodes; + OnSelectionChanged(nodes); +} + +void QmitkFiberExtractionView::NodeAdded(const mitk::DataNode* node) +{ + std::vector nodes; + OnSelectionChanged(nodes); +} + void QmitkFiberExtractionView::OnSelectionChanged( std::vector nodes ) { //reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection m_SelectedFB.clear(); m_SelectedPF.clear(); m_SelectedSurfaces.clear(); m_SelectedImage = NULL; m_MaskImageNode = NULL; - m_Controls->m_FibLabel->setText("mandatory"); - m_Controls->m_PfLabel->setText("needed for extraction"); - for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( dynamic_cast(node->GetData()) ) - { - m_Controls->m_FibLabel->setText(node->GetName().c_str()); m_SelectedFB.push_back(node); - } - else if (dynamic_cast(node->GetData())) - { - m_Controls->m_PfLabel->setText(node->GetName().c_str()); + else if (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) m_SelectedPF.push_back(node); - } else if (dynamic_cast(node->GetData())) { m_SelectedImage = dynamic_cast(node->GetData()); - bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) - { m_MaskImageNode = node; - m_Controls->m_PfLabel->setText(node->GetName().c_str()); - } } else if (dynamic_cast(node->GetData())) - { - m_Controls->m_PfLabel->setText(node->GetName().c_str()); m_SelectedSurfaces.push_back(dynamic_cast(node->GetData())); - } } if (m_SelectedFB.empty()) { int maxLayer = 0; itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); for (unsigned int i=0; iSize(); i++) if (dynamic_cast(nodes->at(i)->GetData())) { + mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); + if (sources->Size()>0) + continue; + int layer = 0; nodes->at(i)->GetPropertyValue("layer", layer); if (layer>=maxLayer) { - maxLayer = layer; - m_Controls->m_FibLabel->setText(nodes->at(i)->GetName().c_str()); m_SelectedFB.clear(); m_SelectedFB.push_back(nodes->at(i)); } } } - if (m_SelectedPF.empty() && m_LastAddedPf.IsNotNull()) + if (m_SelectedPF.empty()) { - m_Controls->m_PfLabel->setText(m_LastAddedPf->GetName().c_str()); - m_SelectedPF.push_back(m_LastAddedPf); - -// int maxLayer = 0; -// itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); -// for (unsigned int i=0; iSize(); i++) -// if (dynamic_cast(nodes->at(i)->GetData())) -// { -// int layer; -// nodes->at(i)->GetPropertyValue("layer", layer); -// if (layer>=maxLayer) -// { -// maxLayer = layer; -// m_Controls->m_PfLabel->setText(nodes->at(i)->GetName().c_str()); -// m_SelectedPF.clear(); -// m_SelectedPF.push_back(nodes->at(i)); -// } -// } + int maxLayer = 0; + itk::VectorContainer::ConstPointer nodes = this->GetDefaultDataStorage()->GetAll(); + for (unsigned int i=0; iSize(); i++) + if (dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData()) || dynamic_cast(nodes->at(i)->GetData())) + { + mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i)); + if (sources->Size()>0) + continue; + + int layer = 0; + nodes->at(i)->GetPropertyValue("layer", layer); + if (layer>=maxLayer) + { + m_SelectedPF.clear(); + m_SelectedPF.push_back(nodes->at(i)); + } + } } UpdateGui(); - GenerateStats(); } void QmitkFiberExtractionView::OnDrawPolygon() { - // 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_DEBUG << "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->GetDataInteractor().GetPointer()); - - if(figureInteractor.IsNull()) - { - figureInteractor = mitk::PlanarFigureInteractor::New(); - us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); - figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); - figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); - figureInteractor->SetDataNode( node ); - } - } - } - } void QmitkFiberExtractionView::OnDrawCircle() { mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New(); - this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter)); - - this->GetDataStorage()->Modified(); - - 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->GetDataInteractor().GetPointer()); - - if(figureInteractor.IsNull()) - { - figureInteractor = mitk::PlanarFigureInteractor::New(); - us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); - figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); - figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); - figureInteractor->SetDataNode( node ); - } - } - } } void QmitkFiberExtractionView::Activated() { } -void QmitkFiberExtractionView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, - const char *, mitk::BaseProperty * ) +void QmitkFiberExtractionView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *, mitk::BaseProperty* ) { // initialize figure's geometry with empty geometry mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New(); figure->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->SetBoolProperty("planarfigure.3drendering", true); + mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(newNode->GetDataInteractor().GetPointer()); + if(figureInteractor.IsNull()) + { + figureInteractor = mitk::PlanarFigureInteractor::New(); + us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); + figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); + figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); + figureInteractor->SetDataNode(newNode); + } + // figure drawn on the topmost layer / image - newNode->SetColor(1.0,1.0,1.0); - newNode->SetOpacity(0.8); GetDataStorage()->Add(newNode ); for(unsigned int i = 0; i < m_SelectedPF.size(); i++) m_SelectedPF[i]->SetSelected(false); newNode->SetSelected(true); m_SelectedPF.clear(); m_SelectedPF.push_back(newNode); - m_LastAddedPf = newNode; - m_Controls->m_PfLabel->setText(newNode->GetName().c_str()); + UpdateGui(); } void QmitkFiberExtractionView::DoFiberExtraction() { - if ( m_SelectedFB.empty() ){ + if ( m_SelectedFB.empty() || m_SelectedPF.empty() ){ QMessageBox::information( NULL, "Warning", "No fibe bundle selected!"); - MITK_WARN("QmitkFiberExtractionView") << "no fibe bundle selected"; return; } - for (unsigned int i=0; i fiberBundles = m_SelectedFB; + mitk::DataNode::Pointer planarFigure = m_SelectedPF.at(0); + for (unsigned int i=0; i(m_SelectedFB.at(i)->GetData()); - mitk::PlanarFigure::Pointer roi = dynamic_cast (m_SelectedPF.at(0)->GetData()); + mitk::FiberBundleX::Pointer fib = dynamic_cast(fiberBundles.at(i)->GetData()); + mitk::BaseData::Pointer roi = planarFigure->GetData(); mitk::FiberBundleX::Pointer extFB = fib->ExtractFiberSubset(roi); if (extFB->GetNumFibers()<=0) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers."); continue; } mitk::DataNode::Pointer node; node = mitk::DataNode::New(); node->SetData(extFB); - QString name(m_SelectedFB.at(i)->GetName().c_str()); + QString name(fiberBundles.at(i)->GetName().c_str()); name += "_"; - name += m_SelectedPF.at(0)->GetName().c_str(); + name += planarFigure->GetName().c_str(); node->SetName(name.toStdString()); + fiberBundles.at(i)->SetVisibility(false); GetDataStorage()->Add(node); - m_SelectedFB.at(i)->SetVisibility(false); } } void QmitkFiberExtractionView::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 ) + 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->addPlanarFigure( nodePF->GetData() ); PFCAnd->addDataNode( nodePF ); - PFCAnd->setDisplayName("AND_COMPO"); + PFCAnd->setDisplayName("AND"); } - - AddCompositeToDatastorage(PFCAnd, NULL); + AddCompositeToDatastorage(PFCAnd); } void QmitkFiberExtractionView::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 ) + 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->addPlanarFigure( nodePF->GetData() ); PFCOr->addDataNode( nodePF ); - PFCOr->setDisplayName("OR_COMPO"); + PFCOr->setDisplayName("OR"); } - - AddCompositeToDatastorage(PFCOr, NULL); + AddCompositeToDatastorage(PFCOr); } void QmitkFiberExtractionView::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 ) + 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->addPlanarFigure( nodePF->GetData() ); PFCNot->addDataNode( nodePF ); - PFCNot->setDisplayName("NOT_COMPO"); + PFCNot->setDisplayName("NOT"); } - - AddCompositeToDatastorage(PFCNot, NULL); + AddCompositeToDatastorage(PFCNot); } /* CLEANUP NEEDED */ -void QmitkFiberExtractionView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfcomp, mitk::DataNode::Pointer parentDataNode ) +void QmitkFiberExtractionView::AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfc, mitk::DataNode::Pointer parentNode ) { mitk::DataNode::Pointer newPFCNode; newPFCNode = mitk::DataNode::New(); - newPFCNode->SetName( pfcomp->getDisplayName() ); - newPFCNode->SetData(pfcomp); - newPFCNode->SetVisibility(true); - - for(unsigned int i = 0; i < m_SelectedPF.size(); i++) - m_SelectedPF[i]->SetSelected(false); + newPFCNode->SetName( pfc->getDisplayName() ); + newPFCNode->SetData(pfc); - newPFCNode->SetSelected(true); - m_LastAddedPf = newPFCNode; - m_SelectedPF.clear(); - m_SelectedPF.push_back(newPFCNode); - m_Controls->m_PfLabel->setText(newPFCNode->GetName().c_str()); - - switch (pfcomp->getOperationType()) { + switch (pfc->getOperationType()) { case 0: { - if (!parentDataNode.IsNull()) { - GetDataStorage()->Add(newPFCNode, parentDataNode); - - } else { + if (parentNode.IsNotNull()) + GetDataStorage()->Add(newPFCNode, parentNode); + else GetDataStorage()->Add(newPFCNode); - } //iterate through its childs - for(int i=0; igetNumberOfChildren(); ++i) + for(int i=0; igetNumberOfChildren(); ++i) { - mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); - mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); + mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); + mitk::DataNode::Pointer savedPFchildNode = pfc->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); - if ( !pfcompcast.IsNull() ) + if ( pfcompcast.IsNotNull() ) { // 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); + pfc->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_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - }else{ - MITK_DEBUG << "[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_DEBUG << 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); + newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector - pfcomp->replaceDataNodeAt(i, newPFchildNode); - + pfc->replaceDataNodeAt(i, newPFchildNode); - if ( GetDataStorage()->Exists(savedPFchildNode)) { - MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - } - else - { - MITK_DEBUG << "[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_DEBUG << savedPFchildNode->GetName() << " still exists"; - } - - MITK_DEBUG << "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_DEBUG << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; - GetDataStorage()->Add(newPFCNode, parentDataNode); - - } else { - MITK_DEBUG << "adding " << newPFCNode->GetName(); + if (!parentNode.IsNull()) + GetDataStorage()->Add(newPFCNode, parentNode); + else GetDataStorage()->Add(newPFCNode); - } - - for(int i=0; igetNumberOfChildren(); ++i) + for(int i=0; igetNumberOfChildren(); ++i) { - mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); - mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); - + mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); + mitk::DataNode::Pointer savedPFchildNode = pfc->getDataNodeAt(i); mitk::PlanarFigureComposite::Pointer pfcompcast= dynamic_cast(tmpPFchild.GetPointer()); if ( !pfcompcast.IsNull() ) - { // child is of type planar Figure composite + { + // 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); + pfc->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_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - }else{ - MITK_DEBUG << "[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_DEBUG << savedPFchildNode->GetName() << " still exists"; - } - } else { - + } + 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); + newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector - pfcomp->replaceDataNodeAt(i, newPFchildNode); + pfc->replaceDataNodeAt(i, newPFchildNode); - - if ( GetDataStorage()->Exists(savedPFchildNode)) { - MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - }else{ - MITK_DEBUG << "[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_DEBUG << savedPFchildNode->GetName() << " still exists"; - } - - MITK_DEBUG << "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_DEBUG << "adding " << newPFCNode->GetName() << " to " << parentDataNode->GetName() ; - GetDataStorage()->Add(newPFCNode, parentDataNode); - } + if (!parentNode.IsNull()) + GetDataStorage()->Add(newPFCNode, parentNode); else - { - MITK_DEBUG << "adding " << newPFCNode->GetName(); GetDataStorage()->Add(newPFCNode); - } - //iterate through its childs - - for(int i=0; igetNumberOfChildren(); ++i) + for(int i=0; igetNumberOfChildren(); ++i) { - mitk::PlanarFigure::Pointer tmpPFchild = pfcomp->getChildAt(i); - mitk::DataNode::Pointer savedPFchildNode = pfcomp->getDataNodeAt(i); + mitk::BaseData::Pointer tmpPFchild = pfc->getChildAt(i); + mitk::DataNode::Pointer savedPFchildNode = pfc->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 + pfcompcast->setDisplayName( savedPFchildNode->GetName() ); //name might be changed in DataManager by user //update inside vector the dataNodePointer - pfcomp->replaceDataNodeAt(i, newChildPFCNode); + pfc->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_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - }else{ - MITK_DEBUG << "[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_DEBUG << savedPFchildNode->GetName() << " still exists"; - } - - - } else { - + } + 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); + newPFchildNode->SetBoolProperty("planarfigure.3drendering", true); // replace the dataNode in PFComp DataNodeVector - pfcomp->replaceDataNodeAt(i, newPFchildNode); - + pfc->replaceDataNodeAt(i, newPFchildNode); - if ( GetDataStorage()->Exists(savedPFchildNode)) { - MITK_DEBUG << savedPFchildNode->GetName() << " exists in DS...trying to remove it"; - - }else{ - MITK_DEBUG << "[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_DEBUG << savedPFchildNode->GetName() << " still exists"; - } - - MITK_DEBUG << "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_DEBUG << "we have an UNDEFINED composition... ERROR" ; break; } -} + for(unsigned int i = 0; i < m_SelectedPF.size(); i++) + m_SelectedPF[i]->SetSelected(false); + + newPFCNode->SetSelected(true); + m_SelectedPF.clear(); + m_SelectedPF.push_back(newPFCNode); + UpdateGui(); +} void QmitkFiberExtractionView::JoinBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberExtractionView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundleX::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iAddBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); name += "+"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } void QmitkFiberExtractionView::SubstractBundles() { if ( m_SelectedFB.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberExtractionView") << "Select at least two fiber bundles!"; return; } mitk::FiberBundleX::Pointer newBundle = dynamic_cast(m_SelectedFB.at(0)->GetData()); m_SelectedFB.at(0)->SetVisibility(false); QString name(""); name += QString(m_SelectedFB.at(0)->GetName().c_str()); for (unsigned int i=1; iSubtractBundle(dynamic_cast(m_SelectedFB.at(i)->GetData())); if (newBundle.IsNull()) break; name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str()); m_SelectedFB.at(i)->SetVisibility(false); } if (newBundle.IsNull()) { QMessageBox::information(NULL, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!"); return; } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } - -void QmitkFiberExtractionView::GenerateStats() -{ - if ( m_SelectedFB.empty() ) - return; - - QString stats(""); - - for(unsigned 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()); - stats += "Number of fibers: "+ QString::number(fib->GetNumFibers()) + "\n"; - stats += "Min. length: "+ QString::number(fib->GetMinFiberLength(),'f',1) + " mm\n"; - stats += "Max. length: "+ QString::number(fib->GetMaxFiberLength(),'f',1) + " mm\n"; - stats += "Mean length: "+ QString::number(fib->GetMeanFiberLength(),'f',1) + " mm\n"; - stats += "Median length: "+ QString::number(fib->GetMedianFiberLength(),'f',1) + " mm\n"; - stats += "Standard deviation: "+ QString::number(fib->GetLengthStDev(),'f',1) + " mm\n"; - } - } - this->m_Controls->m_StatsTextEdit->setText(stats); -} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h index 327c1b1b4f..95affbe701 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h @@ -1,176 +1,177 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkFiberExtractionView_h #define QmitkFiberExtractionView_h #include #include "ui_QmitkFiberExtractionViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles and much more. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberExtractionView : 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: typedef itk::Image< unsigned char, 3 > itkUCharImageType; static const std::string VIEW_ID; QmitkFiberExtractionView(); virtual ~QmitkFiberExtractionView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void OnDrawCircle(); ///< add circle interactors etc. void OnDrawPolygon(); ///< add circle interactors etc. void DoFiberExtraction(); ///< Extract fibers from selected bundle void GenerateAndComposite(); void GenerateOrComposite(); void GenerateNotComposite(); void DoRemoveOutsideMask(); void DoRemoveInsideMask(); void JoinBundles(); ///< merge selected fiber bundles void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection. void GenerateRoiImage(); ///< generate binary image of selected planar figures. void ExtractPassingMask(); ///< extract all fibers passing the selected segmentation void ExtractNotPassingMask(); ///< extract all fibers NOT passing the selected segmentation void ExtractEndingInMask(); ///< extract all fibers passing the selected segmentation virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL ); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberExtractionViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** Connection from VTK to ITK */ template void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template < typename TPixel, unsigned int VImageDimension > void InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ); template < typename TPixel, unsigned int VImageDimension > void InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex ); - void GenerateStats(); ///< generate statistics of selected fiber bundles void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection int m_CircleCounter; ///< used for data node naming int m_PolygonCounter; ///< used for data node naming std::vector m_SelectedFB; ///< selected fiber bundle nodes std::vector m_SelectedPF; ///< selected planar figure nodes std::vector m_SelectedSurfaces; mitk::Image::Pointer m_SelectedImage; mitk::Image::Pointer m_InternalImage; mitk::PlanarFigure::Pointer m_PlanarFigure; itkUCharImageType::Pointer m_InternalImageMask3D; itkUCharImageType::Pointer m_PlanarFigureImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations mitk::DataNode::Pointer m_MaskImageNode; - mitk::DataNode::Pointer m_LastAddedPf; - void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer, mitk::DataNode::Pointer); + void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer pfc, mitk::DataNode::Pointer parentNode=NULL); void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int ); - void CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image); + void WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image); mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute); mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); + + void NodeAdded( const mitk::DataNode* node ); + void NodeRemoved(const mitk::DataNode* node); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionViewControls.ui index e3d7788aa4..fe1565f893 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionViewControls.ui @@ -1,669 +1,645 @@ QmitkFiberExtractionViewControls 0 0 492 866 Form Please Select Input Data <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> <html><head/><body><p><span style=" color:#969696;">needed for extraction</span></p></body></html> Input DTI Fiber Bundle: Binary seed ROI. If not specified, the whole image area is seeded. ROI: - - - - Qt::Vertical - - - - 20 - 40 - - - - Fiber Extraction 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 30 30 Draw circular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true 30 30 Draw rectangular ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/rectangle.png:/QmitkDiffusionImaging/rectangle.png 32 32 true true 30 30 Draw polygonal ROI. Select reference fiber bundle to execute. :/QmitkDiffusionImaging/polygon.png:/QmitkDiffusionImaging/polygon.png 32 32 true true Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 0 0 0 false 0 0 16777215 16777215 11 Generate a binary image containing all selected ROIs. Select at least one ROI (planar figure) and a reference fiber bundle or image. ROI Image false 0 0 200 16777215 11 Remove all fiber parts outside of the mask. Remove Outside Mask false 0 0 200 16777215 11 Merge selected fiber bundles. Select at least two fiber bundles to execute. Join false 0 0 200 16777215 11 Extract fibers passing through selected ROI or composite ROI. Select ROI and fiber bundle to execute. Extract false 0 0 200 16777215 11 Remove all fiber parts inside of the mask. Remove Inside Mask false 0 0 200 16777215 11 Extract fibers starting/ending inside of the selected binary mask. Ending in Mask false 0 0 200 16777215 11 Returns all fibers contained in bundle X that are not contained in bundle Y (not commutative!). Select at least two fiber bundles to execute. Substract false 0 0 200 16777215 11 Extract fibers passing through the selected binary mask. Passing Mask false 0 0 200 16777215 11 Extract fibers NOT passing through the selected binary mask. Not Passing Mask 0 0 200 0 16777215 60 QFrame::NoFrame QFrame::Raised 0 0 0 0 Qt::Horizontal 40 20 false 60 16777215 Create AND composition with selected ROIs. AND false 60 16777215 Create OR composition with selected ROIs. OR false 60 16777215 Create NOT composition from selected ROI. NOT - - - Fiber Statistics + + + Qt::Vertical - - - - - - Courier 10 Pitch - - - - false - - - true - - - - - + + + 20 + 40 + + +