diff --git a/Modules/DiffusionImaging/CMakeLists.txt b/Modules/DiffusionImaging/CMakeLists.txt index 0baae5d9ef..7a6789cdff 100644 --- a/Modules/DiffusionImaging/CMakeLists.txt +++ b/Modules/DiffusionImaging/CMakeLists.txt @@ -1,28 +1,28 @@ find_package(ITK) if(ITK_GDCM_DIR) include(${ITK_GDCM_DIR}/GDCMConfig.cmake) if(GDCM_MAJOR_VERSION EQUAL 2) add_definitions(-DGDCM2) set(ITK_USES_GDCM2 1) endif(GDCM_MAJOR_VERSION EQUAL 2) endif(ITK_GDCM_DIR) MITK_CREATE_MODULE( MitkDiffusionImaging SUBPROJECTS MITK-DTI - INCLUDE_DIRS IODataStructures Reconstruction Tractography Rendering Algorithms DicomImport Interactions IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures/FiberBundle IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite IODataStructures/TbssImages Algorithms/Connectomics IODataStructures/ConnectomicsNetwork ${CMAKE_CURRENT_BINARY_DIR} + INCLUDE_DIRS IODataStructures Reconstruction Tractography Tractography/GibbsTracking Rendering Algorithms DicomImport Interactions IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures/FiberBundle IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite IODataStructures/TbssImages Algorithms/Connectomics IODataStructures/ConnectomicsNetwork ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MitkExt SceneSerializationBase QmitkExt MitkGraphAlgorithms PACKAGE_DEPENDS Boost ) MITK_USE_MODULE(MitkDiffusionImaging) if(MitkDiffusionImaging_IS_ENABLED) file(DOWNLOAD http://mitk.org/download/data/FibertrackingLUT.tar.gz ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FibertrackingLUT.tar.gz TIMEOUT 10) execute_process(COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} tar xzf FibertrackingLUT.tar.gz) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Rendering/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml) MITK_INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTBaryCoords.bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTIndices.bin) endif() add_subdirectory(Testing) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mitkDiffusionImagingConfigure.h.in ${CMAKE_CURRENT_BINARY_DIR}/mitkDiffusionImagingConfigure.h) diff --git a/Modules/DiffusionImaging/CMakeLists.txt~ b/Modules/DiffusionImaging/CMakeLists.txt~ deleted file mode 100644 index 67913004df..0000000000 --- a/Modules/DiffusionImaging/CMakeLists.txt~ +++ /dev/null @@ -1,28 +0,0 @@ -FIND_PACKAGE(ITK) -IF(ITK_GDCM_DIR) - INCLUDE(${ITK_GDCM_DIR}/GDCMConfig.cmake) - IF(GDCM_MAJOR_VERSION EQUAL 2) - ADD_DEFINITIONS(-DGDCM2) - SET(ITK_USES_GDCM2 1) - ENDIF(GDCM_MAJOR_VERSION EQUAL 2) -ENDIF(ITK_GDCM_DIR) - -MITK_CREATE_MODULE( MitkDiffusionImaging - SUBPROJECTS MITK-DTI - INCLUDE_DIRS IODataStructures Reconstruction Tractography Rendering Algorithms DicomImport Interactions IODataStructures/DiffusionWeightedImages IODataStructures/QBallImages IODataStructures/TensorImages IODataStructures/FiberBundle IODataStructures/FiberBundleX IODataStructures/PlanarFigureComposite IODataStructures/TbssImages ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS MitkExt SceneSerializationBase QmitkExt GraphAlgorithms - PACKAGE_DEPENDS Boost -) - -MITK_USE_MODULE(MitkDiffusionImaging) -if(MitkDiffusionImaging_IS_ENABLED) - file(DOWNLOAD http://mitk.org/download/data/FibertrackingLUT.tar.gz ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FibertrackingLUT.tar.gz TIMEOUT 10) - execute_process(COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} tar xzf FibertrackingLUT.tar.gz) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Rendering/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml) - MITK_INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mitkShaderFiberClipping.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTBaryCoords.bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FiberTrackingLUTIndices.bin) -endif() - -ADD_SUBDIRECTORY(Testing) - -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mitkDiffusionImagingConfigure.h.in ${CMAKE_CURRENT_BINARY_DIR}/mitkDiffusionImagingConfigure.h) - diff --git a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp index b2b3397b97..631218e626 100644 --- a/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkFiberBundleXMapper3D.cpp @@ -1,201 +1,195 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +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 +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 "mitkFiberBundleXMapper3D.h" #include //#include //#include #include #include #include //not essential for mapper #include mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() { } const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() { - MITK_INFO << "FiberBundleXxXXMapper3D() GetInput()"; return static_cast ( GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::FiberBundleXMapper3D::GenerateData(mitk::BaseRenderer *renderer) { //MITK_INFO << "GENERATE DATA FOR FBX :)"; //=====timer measurement==== QTime myTimer; myTimer.start(); //========================== mitk::FiberBundleX* FBX = dynamic_cast (this->GetData()); if (FBX == NULL) return; vtkSmartPointer FiberData = FBX->GetFiberPolyData(); if (FiberData == NULL) return; FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); localStorage->m_FiberMapper->SetInput(FiberData); if ( FiberData->GetPointData()->GetNumberOfArrays() > 0 ) localStorage->m_FiberMapper->SelectColorArray( FBX->GetCurrentColorCoding() ); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper); // localStorage->m_FiberActor->GetProperty()->SetOpacity(0.999); localStorage->m_FiberMapper->SetLookupTable(m_lut); // set Opacity float tmpopa; this->GetDataNode()->GetOpacity(tmpopa, NULL); localStorage->m_FiberActor->GetProperty()->SetOpacity((double) tmpopa); // set color if (FBX->GetCurrentColorCoding() != NULL){ // localStorage->m_FiberMapper->SelectColorArray(""); localStorage->m_FiberMapper->SelectColorArray(FBX->GetCurrentColorCoding()); MITK_DEBUG << "MapperFBX: " << FBX->GetCurrentColorCoding(); if(FBX->GetCurrentColorCoding() == FBX->COLORCODING_CUSTOM) { float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_FiberActor->GetProperty()->SetColor(trgb); } } localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor); localStorage->m_LastUpdateTime.Modified(); //since this method is called after generating all necessary data for fiber visualization, all modifications are represented so far. - - //====timer measurement======== - MITK_INFO << "Execution Time GenerateData() (nmiliseconds): " << myTimer.elapsed(); - //============================= - } void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { if ( !this->IsVisible( renderer ) ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { - MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); + MITK_DEBUG << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateData(renderer); } } void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; //MITK_INFO << "FiberBundleMapperX3D SetDefault Properties(...)"; // node->AddProperty( "DisplayChannel", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); // node->AddProperty( "VertexOpacity_1", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "Set_FA_VertexAlpha", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "pointSize", mitk::FloatProperty::New(0.5), renderer, overwrite); // node->AddProperty( "setShading", mitk::IntProperty::New(1), renderer, overwrite); // node->AddProperty( "Xmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Ymove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Zmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "RepPoints", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "TubeSides", mitk::IntProperty::New( 8 ), renderer, overwrite); // node->AddProperty( "TubeRadius", mitk::FloatProperty::New( 0.15 ), renderer, overwrite); // node->AddProperty( "TubeOpacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_LSH.GetLocalStorage(renderer)->m_FiberAssembly; } void mitk::FiberBundleXMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { } void mitk::FiberBundleXMapper3D::UpdateVtkObjects() { } void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } mitk::FiberBundleXMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() { m_FiberActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); m_FiberAssembly = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp deleted file mode 100644 index 04e8638711..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/BuildFibres.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/*=================================================================== - -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 _BUILDFIBRES -#define _BUILDFIBRES - -//#include "matrix.h" -#define _USE_MATH_DEFINES -#include - -#include -#include -#include - -using namespace std; - -#define PI M_PI - -#include "ParticleGrid.cpp" - -#include -#include -#include -#include -#include -#include - -#include -#include - -class FiberBuilder -{ -public: - Particle *particles; - int pcnt; - int attrcnt; - typedef vector< Particle* > ParticleContainerType; - typedef vector< ParticleContainerType* > FiberContainerType; - - vtkSmartPointer m_VtkCellArray; - vtkSmartPointer m_VtkPoints; - - typedef itk::Vector OdfVectorType; - typedef itk::Image ItkQBallImgType; - ItkQBallImgType::Pointer m_ItkQBallImage; - float m_FiberLength; - itk::Point m_LastPoint; - - FiberBuilder(float *points, int numPoints, double spacing[], ItkQBallImgType::Pointer image) - { - m_FiberLength = 0; - m_ItkQBallImage = image; - particles = (Particle*) malloc(sizeof(Particle)*numPoints); - pcnt = numPoints; - attrcnt = 10; - for (int k = 0; k < numPoints; k++) - { - Particle *p = &(particles[k]); - p->R = pVector(points[attrcnt*k]/spacing[0]-0.5, points[attrcnt*k+1]/spacing[1]-0.5,points[attrcnt*k+2]/spacing[2]-0.5); - p->N = pVector(points[attrcnt*k+3],points[attrcnt*k+4],points[attrcnt*k+5]); - p->cap = points[attrcnt*k+6]; - p->len = points[attrcnt*k+7]; - p->mID = (int) points[attrcnt*k+8]; - p->pID = (int) points[attrcnt*k+9]; - p->ID = k; - p->label = 0; - } - m_VtkCellArray = vtkSmartPointer::New(); - m_VtkPoints = vtkSmartPointer::New(); - } - - ~FiberBuilder() - { - free(particles); - } - - vtkSmartPointer iterate(int minFiberLength) - { - int cur_label = 1; - int numFibers = 0; - m_FiberLength = 0; - for (int k = 0; k < pcnt;k++) - { - Particle *dp = &(particles[k]); - if (dp->label == 0) - { - vtkSmartPointer container = vtkSmartPointer::New(); - dp->label = cur_label; - dp->numerator = 0; - labelPredecessors(dp, container); - labelSuccessors(dp, container); - cur_label++; - if(m_FiberLength >= minFiberLength) - { - m_VtkCellArray->InsertNextCell(container); - numFibers++; - } - m_FiberLength = 0; - } - } - vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); - fiberPolyData->SetPoints(m_VtkPoints); - fiberPolyData->SetLines(m_VtkCellArray); -// vtkSmartPointer cleaner = vtkSmartPointer::New(); -// cleaner->SetInput(fiberPolyData); -// cleaner->Update(); -// fiberPolyData = cleaner->GetOutput(); - return fiberPolyData; - } - - void AddPoint(Particle *dp, vtkSmartPointer container) - { - if (dp->inserted) - return; - - dp->inserted = true; - - itk::ContinuousIndex index; - index[0] = dp->R[0]; - index[1] = dp->R[1]; - index[2] = dp->R[2]; - itk::Point point; - m_ItkQBallImage->TransformContinuousIndexToPhysicalPoint( index, point ); - vtkIdType id = m_VtkPoints->InsertNextPoint(point.GetDataPointer()); - container->GetPointIds()->InsertNextId(id); - - if(container->GetNumberOfPoints()>1) - m_FiberLength += m_LastPoint.EuclideanDistanceTo(point); - - m_LastPoint = point; - } - - void labelPredecessors(Particle *dp, vtkSmartPointer container) - { - if (dp->mID != -1 && dp->mID!=dp->ID) - { - if (dp->ID!=particles[dp->mID].pID) - { - if (dp->ID==particles[dp->mID].mID) - { - int tmp = particles[dp->mID].pID; - particles[dp->mID].pID = particles[dp->mID].mID; - particles[dp->mID].mID = tmp; - } - } - if (particles[dp->mID].label == 0) - { - particles[dp->mID].label = dp->label; - particles[dp->mID].numerator = dp->numerator-1; - labelPredecessors(&(particles[dp->mID]), container); - } - } - - AddPoint(dp, container); - } - - void labelSuccessors(Particle *dp, vtkSmartPointer container) - { - AddPoint(dp, container); - - if (dp->pID != -1 && dp->pID!=dp->ID) - { - if (dp->ID!=particles[dp->pID].mID) - { - if (dp->ID==particles[dp->pID].pID) - { - int tmp = particles[dp->pID].pID; - particles[dp->pID].pID = particles[dp->pID].mID; - particles[dp->pID].mID = tmp; - } - } - if (particles[dp->pID].label == 0) - { - particles[dp->pID].label = dp->label; - particles[dp->pID].numerator = dp->numerator+1; - labelSuccessors(&(particles[dp->pID]), container); - } - } - } -}; - -#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp deleted file mode 100644 index b21e77ce88..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputerBase.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/*=================================================================== - -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 _ENCOMPINTERFACE -#define _ENCOMPINTERFACE - - -#include "SphereInterpolator.cpp" -#include "ParticleGrid.cpp" -#include -#include -#include - -inline float myATAN2(float y,float x) -{ - float phi = acos(x); - // float phi = ((x>=1.0) ? ((0.0000*x+-0.0000)) : ((x>=1.0) ? ((-10.0167*x+10.0167)) : ((x>=0.9) ? ((-3.1336*x+3.2713)) : ((x>=0.8) ? ((-1.9247*x+2.1833)) : ((x>=0.5) ? ((-1.3457*x+1.7200)) : ((x>=0.0) ? ((-1.0472*x+1.5708)) : ((x>=-0.5) ? ((-1.0472*x+1.5708)) : ((x>=-0.8) ? ((-1.3457*x+1.4216)) : ((x>=-0.9) ? ((-1.9247*x+0.9583)) : ((x>=-1.0) ? ((-3.1336*x+-0.1297)) : ((x>=-1.0) ? ((-10.0167*x+-6.8751)) : 1 ))))))))))); - if (y < 0) phi = 2*PI - phi; - if (phi<0) phi = phi + PI; - return phi; - -} - - -class EnergyComputerBase -{ - -public: - - float *m_QBallImageData; - const int *m_QBallImageSize; - SphereInterpolator *m_SphereInterpolator; - ParticleGrid *m_ParticleGrid; - - int w,h,d; - float voxsize_w; - float voxsize_h; - float voxsize_d; - - int w_sp,h_sp,d_sp; - float voxsize_sp_w; - float voxsize_sp_h; - float voxsize_sp_d; - - - int nip; // number of data vertices on sphere - - - float *m_MaskImageData; - float *cumulspatprob; - int *spatidx; - int scnt; - - - - float eigen_energy; - vnl_matrix_fixed m_RotationMatrix; - - EnergyComputerBase(float *qBallImageData, const int *qBallImageSize, double *voxsize, SphereInterpolator *sp, ParticleGrid *pcon, float *maskImageData, int spmult, vnl_matrix_fixed rotMatrix) - { - m_RotationMatrix = rotMatrix; - m_QBallImageData = qBallImageData; - m_QBallImageSize = qBallImageSize; - m_SphereInterpolator = sp; - - m_MaskImageData = maskImageData; - - nip = m_QBallImageSize[0]; - - - w = m_QBallImageSize[1]; - h = m_QBallImageSize[2]; - d = m_QBallImageSize[3]; - - voxsize_w = voxsize[0]; - voxsize_h = voxsize[1]; - voxsize_d = voxsize[2]; - - - w_sp = m_QBallImageSize[1]*spmult; - h_sp = m_QBallImageSize[2]*spmult; - d_sp = m_QBallImageSize[3]*spmult; - - voxsize_sp_w = voxsize[0]/spmult; - voxsize_sp_h = voxsize[1]/spmult; - voxsize_sp_d = voxsize[2]/spmult; - - - fprintf(stderr,"Data size (voxels) : %i x %i x %i\n",w,h,d); - fprintf(stderr,"voxel size: %f x %f x %f\n",voxsize_w,voxsize_h,voxsize_d); - fprintf(stderr,"mask_oversamp_mult: %i\n",spmult); - - if (nip != sp->nverts) - { - fprintf(stderr,"EnergyComputer: error during init: data does not match with interpolation scheme\n"); - } - - m_ParticleGrid = pcon; - - - int totsz = w_sp*h_sp*d_sp; - cumulspatprob = (float*) malloc(sizeof(float) * totsz); - spatidx = (int*) malloc(sizeof(int) * totsz); - if (cumulspatprob == 0 || spatidx == 0) - { - fprintf(stderr,"EnergyCOmputerBase: out of memory!\n"); - return ; - } - - - scnt = 0; - cumulspatprob[0] = 0; - for (int x = 1; x < w_sp;x++) - for (int y = 1; y < h_sp;y++) - for (int z = 1; z < d_sp;z++) - { - int idx = x+(y+z*h_sp)*w_sp; - if (m_MaskImageData[idx] > 0.5) - { - cumulspatprob[scnt+1] = cumulspatprob[scnt] + m_MaskImageData[idx]; - spatidx[scnt] = idx; - scnt++; - } - } - - for (int k = 0; k < scnt; k++) - { - cumulspatprob[k] /= cumulspatprob[scnt]; - } - - fprintf(stderr,"#active voxels: %i (in mask units) \n",scnt); - - - - } - - ~EnergyComputerBase() - { - free(cumulspatprob); - free(spatidx); - } - - virtual void setParameters() - { - - } - - - - void drawSpatPosition(pVector *R) - { - float r = mtrand.frand(); - int j; - int rl = 1; - int rh = scnt; - while(rh != rl) - { - j = rl + (rh-rl)/2; - if (r < cumulspatprob[j]) - { - rh = j; - continue; - } - if (r > cumulspatprob[j]) - { - rl = j+1; - continue; - } - break; - } - R->SetXYZ(voxsize_sp_w*((float)(spatidx[rh-1] % w_sp) + mtrand.frand()), - voxsize_sp_h*((float)((spatidx[rh-1]/w_sp) % h_sp) + mtrand.frand()), - voxsize_sp_d*((float)(spatidx[rh-1]/(w_sp*h_sp)) + mtrand.frand())); - } - - float SpatProb(pVector R) - { - int rx = int(R.GetX()/voxsize_sp_w); - int ry = int(R.GetY()/voxsize_sp_h); - int rz = int(R.GetZ()/voxsize_sp_d); - if (rx >= 0 && rx < w_sp && ry >= 0 && ry < h_sp && rz >= 0 && rz < d_sp){ - return m_MaskImageData[rx + w_sp* (ry + h_sp*rz)]; - } - else - return 0; - } - - /* - inline float evaluateODF(pVector &R, pVector &N, float &len) - { - const int CU = 10; - pVector Rs; - float Dn = 0; - int xint,yint,zint,spatindex; - - sinterp->getInterpolation(N); - for (int i=-CU; i < CU;i++) - { - Rs = R + (N * len) * ((float)i/CU); - xint = int(Rs.x); - yint = int(Rs.y); - zint = int(Rs.z); - if (xint > 0 && xint < w-1 && yint > 0 && yint < h-1 && zint > 0 && zint < d-1) - { - spatindex = (xint + w*(yint+h*zint)) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2]); - } - } - - Dn /= (float)(2*CU+1); - return Dn; - } -*/ - - - inline float evaluateODF(pVector &R, pVector &N, float &len) - { - const int CU = 10; - pVector Rs; - float Dn = 0; - int xint,yint,zint,spatindex; - - vnl_vector_fixed n; - n[0] = N[0]; - n[1] = N[1]; - n[2] = N[2]; - n = m_RotationMatrix*n; - m_SphereInterpolator->getInterpolation(n); - - for (int i=-CU; i <= CU;i++) - { - Rs = R + (N * len) * ((float)i/CU); - - float Rx = Rs[0]/voxsize_w-0.5; - float Ry = Rs[1]/voxsize_h-0.5; - float Rz = Rs[2]/voxsize_d-0.5; - - - xint = int(floor(Rx)); - yint = int(floor(Ry)); - zint = int(floor(Rz)); - - - if (xint >= 0 && xint < w-1 && yint >= 0 && yint < h-1 && zint >= 0 && zint < d-1) - { - float xfrac = Rx-xint; - float yfrac = Ry-yint; - float zfrac = Rz-zint; - - float weight; - - weight = (1-xfrac)*(1-yfrac)*(1-zfrac); - spatindex = (xint + w*(yint+h*zint)) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (xfrac)*(1-yfrac)*(1-zfrac); - spatindex = (xint+1 + w*(yint+h*zint)) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (1-xfrac)*(yfrac)*(1-zfrac); - spatindex = (xint + w*(yint+1+h*zint)) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (1-xfrac)*(1-yfrac)*(zfrac); - spatindex = (xint + w*(yint+h*(zint+1))) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (xfrac)*(yfrac)*(1-zfrac); - spatindex = (xint+1 + w*(yint+1+h*zint)) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (1-xfrac)*(yfrac)*(zfrac); - spatindex = (xint + w*(yint+1+h*(zint+1))) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (xfrac)*(1-yfrac)*(zfrac); - spatindex = (xint+1 + w*(yint+h*(zint+1))) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - weight = (xfrac)*(yfrac)*(zfrac); - spatindex = (xint+1 + w*(yint+1+h*(zint+1))) *nip; - Dn += (m_QBallImageData[spatindex + m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + m_QBallImageData[spatindex + m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; - - - } - - - } - - Dn *= 1.0/(2*CU+1); - return Dn; - } - - - /* - inline float evaluateODF(pVector &R, pVector &N, float &len) - { - - R.storeXYZ(); - - float Rx = pVector::store[0]/voxsize_w; - float Ry = pVector::store[1]/voxsize_h; - float Rz = pVector::store[2]/voxsize_d; - - - int xint = int(Rx); - int yint = int(Ry); - int zint = int(Rz); - - if (xint >= 0 && xint < w-1 && yint >= 0 && yint < h-1 && zint >= 0 && zint < d-1) - { - float xfrac = Rx-xint; - float yfrac = Ry-yint; - float zfrac = Rz-zint; - sinterp->getInterpolation(N); - - float weight; - int spatindex; - float Dn = 0; - - weight = (1-xfrac)*(1-yfrac)*(1-zfrac); - spatindex = (xint + w*(yint+h*zint)) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (xfrac)*(1-yfrac)*(1-zfrac); - spatindex = (xint+1 + w*(yint+h*zint)) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (1-xfrac)*(yfrac)*(1-zfrac); - spatindex = (xint + w*(yint+1+h*zint)) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (1-xfrac)*(1-yfrac)*(zfrac); - spatindex = (xint + w*(yint+h*(zint+1))) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (xfrac)*(yfrac)*(1-zfrac); - spatindex = (xint+1 + w*(yint+1+h*zint)) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (1-xfrac)*(yfrac)*(zfrac); - spatindex = (xint + w*(yint+1+h*(zint+1))) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (xfrac)*(1-yfrac)*(zfrac); - spatindex = (xint+1 + w*(yint+h*(zint+1))) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - weight = (xfrac)*(yfrac)*(zfrac); - spatindex = (xint+1 + w*(yint+1+h*(zint+1))) *nip; - Dn += (dataimg[spatindex + sinterp->idx[0]]*sinterp->interpw[0] + dataimg[spatindex + sinterp->idx[1]]*sinterp->interpw[1] + dataimg[spatindex + sinterp->idx[2]]* sinterp->interpw[2])*weight; - - return Dn; - - } - return 0; - } - -*/ - - virtual inline float computeExternalEnergy(pVector &R, pVector &N, float &cap, float &len, Particle *dp) { return 0;} - virtual inline float computeInternalEnergy(Particle *p1) {return 0;} - virtual inline float computeInternalEnergyConnection(Particle *p1,int ep1) {return 0;} - virtual inline float computeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) {return 0;} - - - -}; - -#endif - - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp deleted file mode 100644 index ec23b23b27..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/EnergyComputer_connec.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - - - -/// bessel for wid = 1 - -//#define mbesseli0(x) ((x>=1.0) ? ((-0.2578*x+0.7236)*exp(x)) : ((x>=0.9) ? ((-0.2740*x+0.7398)*exp(x)) : ((x>=0.8) ? ((-0.3099*x+0.7720)*exp(x)) : ((x>=0.7) ? ((-0.3634*x+0.8149)*exp(x)) : ((x>=0.5) ? ((-0.4425*x+0.8663)*exp(x)) : ((x>=0.3) ? ((-0.5627*x+0.9264)*exp(x)) : ((x>=0.2) ? ((-0.6936*x+0.9657)*exp(x)) : ((x>=0.1) ? ((-0.8016*x+0.9873)*exp(x)) : ((x>=0.0) ? ((-0.9290*x+1.0000)*exp(x)) : 1 ))))))))) -//#define mbesseli0(x) ((x>=1.0) ? ((0.5652*x+0.7009)) : ((x>=0.8) ? ((0.4978*x+0.7683)) : ((x>=0.6) ? ((0.3723*x+0.8686)) : ((x>=0.4) ? ((0.2582*x+0.9371)) : ((x>=0.2) ? ((0.1519*x+0.9796)) : ((x>=0.0) ? ((0.0501*x+1.0000)) : 1 )))))) - - -inline float mbesseli0(float x) -{ - float y = x*x; - float erg = BESSEL_APPROXCOEFF[0]; - erg += y*BESSEL_APPROXCOEFF[1]; - erg += y*y*BESSEL_APPROXCOEFF[2]; - erg += y*y*y*BESSEL_APPROXCOEFF[3]; - return erg; -} - -// -// -// inline REAL mbesseli0(REAL x) -// { -// REAL y = x*x; -// REAL erg = BESSEL_APPROXCOEFF[0]; -// erg += y*BESSEL_APPROXCOEFF[1]; -// erg += y*x*BESSEL_APPROXCOEFF[2]; -// erg += x*x*BESSEL_APPROXCOEFF[3]; -// return erg; -// } - -inline float mexp(float x) -{ - - return((x>=7.0) ? 0 : ((x>=5.0) ? (-0.0029*x+0.0213) : ((x>=3.0) ? (-0.0215*x+0.1144) : ((x>=2.0) ? (-0.0855*x+0.3064) : ((x>=1.0) ? (-0.2325*x+0.6004) : ((x>=0.5) ? (-0.4773*x+0.8452) : ((x>=0.0) ? (-0.7869*x+1.0000) : 1 ))))))); - // return exp(-x); - -} - - -#include "ParticleGrid.cpp" - -#include "EnergyComputerBase.cpp" -#include - - -class EnergyComputer : public EnergyComputerBase -{ - -public: - - - float eigencon_energy; - - float chempot2; - float meanval_sq; - - float gamma_s; - float gamma_reg_s; - - float particle_weight; - float ex_strength; - float in_strength; - - float particle_length_sq; - float curv_hard; - - - EnergyComputer(float *data, const int *dsz, double *cellsize, SphereInterpolator *sp, ParticleGrid *pcon, float *spimg, int spmult, vnl_matrix_fixed rotMatrix) : EnergyComputerBase(data,dsz,cellsize,sp,pcon,spimg,spmult,rotMatrix) - { - - } - - void setParameters(float pwei,float pwid,float chempot_connection, float length,float curv_hardthres, float inex_balance, float chempot2, float meanv) - { - this->chempot2 = chempot2; - meanval_sq = meanv; - - eigencon_energy = chempot_connection; - eigen_energy = 0; - particle_weight = pwei; - - float bal = 1/(1+exp(-inex_balance)); - ex_strength = 2*bal; // cleanup (todo) - in_strength = 2*(1-bal)/length/length; // cleanup (todo) - // in_strength = 0.64/length/length; // cleanup (todo) - - particle_length_sq = length*length; - curv_hard = curv_hardthres; - - float sigma_s = pwid; - gamma_s = 1/(sigma_s*sigma_s); - gamma_reg_s =1/(length*length/4); - } - - - - //////////////////////////////////////////////////////////////////////////// - ////// External Energy - //////////////////////////////////////////////////////////////////////////// - inline float computeExternalEnergy(pVector &R, pVector &N, float &cap, float &len, Particle *dp) - { - float m = SpatProb(R); - if (m == 0) - { - return -INFINITY; - } - - float Dn = evaluateODF(R,N,len); - - float Sn = 0; - float Pn = 0; - - m_ParticleGrid->computeNeighbors(R); - for (;;) - { - Particle *p = m_ParticleGrid->getNextNeighbor(); - if (p == 0) break; - if (dp != p) - { - float dot = fabs(N*p->N); - float bw = mbesseli0(dot); - float dpos = (p->R-R).norm_square(); - float w = mexp(dpos*gamma_s); - Sn += w*(bw+chempot2)*p->cap ; - //Sn += w*(bw-meanval_sq)*p->cap ; - w = mexp(dpos*gamma_reg_s); - Pn += w*bw; - } - } - - float energy = 0; - energy += (2*(Dn/particle_weight-Sn) - (mbesseli0(1.0)+chempot2)*cap)*cap; - //energy += (2*(Dn/particle_weight-Sn) - (mbesseli0(1.0)-meanval_sq)*cap)*cap; - - return energy*ex_strength; - } - - - //////////////////////////////////////////////////////////////////////////// - ////// Internal Energy - //////////////////////////////////////////////////////////////////////////// - - inline float computeInternalEnergy(Particle *dp) - { - float energy = eigen_energy; - - if (dp->pID != -1) - energy += computeInternalEnergyConnection(dp,+1); - - if (dp->mID != -1) - energy += computeInternalEnergyConnection(dp,-1); - - //ie_file << energy << "\n"; - - return energy; - } - - inline float computeInternalEnergyConnection(Particle *p1,int ep1) - { - Particle *p2 = 0; - int ep2; - if (ep1 == 1) - p2 = m_ParticleGrid->ID_2_address[p1->pID]; - else - p2 = m_ParticleGrid->ID_2_address[p1->mID]; - if (p2->mID == p1->ID) - ep2 = -1; - else if (p2->pID == p1->ID) - ep2 = 1; - else - fprintf(stderr,"EnergyComputer_connec: Connections are inconsistent!\n"); - - if (p2 == 0) - fprintf(stderr,"bug2"); - - return computeInternalEnergyConnection(p1,ep1,p2,ep2); - } - - inline float computeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) - { -#ifdef TIMING - tic(&internalenergy_time); -#endif - - if ((p1->N*p2->N)*ep1*ep2 > -curv_hard) - return -INFINITY; - - pVector R1 = p1->R + (p1->N * (p1->len * ep1)); - pVector R2 = p2->R + (p2->N * (p2->len * ep2)); - - if ((R1-R2).norm_square() > particle_length_sq) - return -INFINITY; - - pVector R = (p2->R + p1->R)*0.5; - - if (SpatProb(R) == 0) - return -INFINITY; - - float norm1 = (R1-R).norm_square(); - float norm2 = (R2-R).norm_square(); - - - float energy = (eigencon_energy-norm1-norm2)*in_strength; - -#ifdef TIMING - toc(&internalenergy_time); -#endif - - return energy; - } - - - - - - - - - -}; - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h deleted file mode 100644 index 01d0784e24..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/MersenneTwister.h +++ /dev/null @@ -1,611 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ -// MersenneTwister.h -// Mersenne Twister random number generator -- a C++ class MTRand -// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus -// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com - -// The Mersenne Twister is an algorithm for generating random numbers. It -// was designed with consideration of the flaws in various other generators. -// The period, 2^19937-1, and the order of equidistribution, 623 dimensions, -// are far greater. The generator is also fast; it avoids multiplication and -// division, and it benefits from caches and pipelines. For more information -// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html - -// Reference -// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally -// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on -// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. - -// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, -// Copyright (C) 2000 - 2003, Richard J. Wagner -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The names of its contributors may not be used to endorse or promote -// products derived from this software without specific prior written -// permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// The original code included the following notice: -// -// When you use this, send an email to: matumoto@math.keio.ac.jp -// with an appropriate reference to your work. -// -// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu -// when you write. - -#ifndef MERSENNETWISTER_H -#define MERSENNETWISTER_H - -// Not thread safe (unless auto-initialization is avoided and each thread has -// its own MTRand object) - -#include -#include -#include -#include - -#define _USE_MATH_DEFINES -#include - -class MTRand { -// Data -public: - typedef unsigned long uint32; // unsigned integer type, at least 32 bits - - enum { N = 624 }; // length of state vector - enum { SAVE = N + 1 }; // length of array for save() - -// protected: - enum { M = 397 }; // period parameter - - uint32 state[N]; // internal state - uint32 *pNext; // next value to get from state - int left; // number of values left before reload needed - - -//Methods -public: - MTRand( const uint32& oneSeed ); // initialize with a simple uint32 - MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array - MTRand(); // auto-initialize with /dev/urandom or time() and clock() - ~MTRand(); - - // Do NOT use for CRYPTOGRAPHY without securely hashing several returned - // values together, otherwise the generator state can be learned after - // reading 624 consecutive values. - - // Access to 32-bit random numbers - double rand(); // real number in [0,1] - float frand(); // real number in [0,1] - double rand( const double& n ); // real number in [0,n] - double randExc(); // real number in [0,1) - double randExc( const double& n ); // real number in [0,n) - double randDblExc(); // real number in (0,1) - double randDblExc( const double& n ); // real number in (0,n) - uint32 randInt(); // integer in [0,2^32-1] - uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32 - double operator()() { return rand(); } // same as rand() - - // Access to 53-bit random numbers (capacity of IEEE double precision) - double rand53(); // real number in [0,1) - - // Access to nonuniform random number distributions - double randNorm( const double& mean = 0.0, const double& variance = 0.0 ); - float frandn(); - - // Re-seeding functions with same behavior as initializers - void seed( const uint32 oneSeed ); - void seed( uint32 *const bigSeed, const uint32 seedLength = N ); - void seed(); - - - ////// - int Poisson(); - void initPoisson(float mean, int accuracy); - float *cumulPoisson; - int accuracyPoisson; - - int drawGamma(); - void initGamma(float theta, int shape); - float *cumulGamma; - int accuracyGamma; - - - - // Saving and loading generator state - void save( uint32* saveArray ) const; // to array of size SAVE - void load( uint32 *const loadArray ); // from such array - friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ); - friend std::istream& operator>>( std::istream& is, MTRand& mtrand ); - -protected: - void initialize( const uint32 oneSeed ); - void reload(); - uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; } - uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; } - uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; } - uint32 mixBits( const uint32& u, const uint32& v ) const - { return hiBit(u) | loBits(v); } - uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const - { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); } - static uint32 hash( time_t t, clock_t c ); -}; - - -inline MTRand::MTRand( const uint32& oneSeed ) - { seed(oneSeed); - cumulPoisson = 0; - cumulGamma = 0; - } - -inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength ) - { seed(bigSeed,seedLength); - cumulPoisson = 0; - cumulGamma = 0; - - } - -inline MTRand::MTRand() - { seed(); - cumulPoisson = 0; - cumulGamma = 0; - } - -inline MTRand::~MTRand() -{ - if (cumulPoisson != 0) - free(cumulPoisson); - if (cumulGamma != 0) - free(cumulGamma); -} -inline double MTRand::rand() - { return double(randInt()) * (1.0/4294967295.0); } - -inline float MTRand::frand() - { - return float(randInt()) * (1.0/4294967295.0); - } - - -inline double MTRand::rand( const double& n ) - { return rand() * n; } - -inline double MTRand::randExc() - { return double(randInt()) * (1.0/4294967296.0); } - -inline double MTRand::randExc( const double& n ) - { return randExc() * n; } - -inline double MTRand::randDblExc() - { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } - -inline double MTRand::randDblExc( const double& n ) - { return randDblExc() * n; } - -inline double MTRand::rand53() -{ - uint32 a = randInt() >> 5, b = randInt() >> 6; - return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada -} - -inline double MTRand::randNorm( const double& mean, const double& variance ) -{ - // Return a real number from a normal (Gaussian) distribution with given - // mean and variance by Box-Muller method - double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance; - double phi = 2.0 * M_PI * randExc(); - return mean + r * cos(phi); -} - -inline float MTRand::frandn() -{ - // Return a real number from a normal (Gaussian) distribution with given - // mean and variance by Box-Muller method - float r = sqrt( -2.0 * log( 1.0-randDblExc()) ); - double phi = 2.0 * M_PI * randExc(); - return r * cos(phi); -} - -inline int MTRand::Poisson() -{ - int j; - - float r = frand(); - - int rl = 0; - int rh = accuracyPoisson-1; - while(rh != rl) - { - j = rl + (rh-rl)/2; - if (r < cumulPoisson[j]) - { - rh = j; - continue; - } - if (r > cumulPoisson[j]) - { - rl = j+1; - continue; - } - break; - } - j = rh; - - return j; -} - - -inline int MTRand::drawGamma() -{ - int j; - - float r = frand(); - - int rl = 0; - int rh = accuracyGamma-1; - while(rh != rl) - { - j = rl + (rh-rl)/2; - if (r < cumulGamma[j]) - { - rh = j; - continue; - } - if (r > cumulGamma[j]) - { - rl = j+1; - continue; - } - break; - } - j = rh; - - return j; -} - - -/* -inline void MTRand::initPoisson(float mean,int accuracy) -{ - float p[accuracy]; - float Z = exp(-mean); - p[0] = 1; - for (int i = 1; i < accuracy;i++) - p[i] = p[i-1]*mean/i; - for (int i = 0; i < accuracy;i++) - p[i] *= Z; - - if (cumulPoisson != 0) - free(cumulPoisson); - - cumulPoisson = (float*) malloc(sizeof(float)*accuracy); - cumulPoisson[0] = p[0]; - for (int i = 1; i < accuracy;i++) - cumulPoisson[i] = cumulPoisson[i-1]+p[i]; - for (int i = 0; i < accuracy;i++) - cumulPoisson[i] = cumulPoisson[i]/cumulPoisson[accuracy-1]; - - accuracyPoisson = accuracy; - - -} - - - - - -inline void MTRand::initGamma(float theta,int k) -{ - int accuracy = int(k*theta*5); - - float p[accuracy]; - int fac = 1; - for (int i = 1; i < k-1;i++) - fac *= i; - - for (int i = 0; i < accuracy;i++) - { - p[i] = pow(i/theta,k-1)/fac * exp(i/theta); - } - if (cumulGamma != 0) - free(cumulGamma); - - cumulGamma = (float*) malloc(sizeof(float)*accuracy); - cumulGamma[0] = p[0]; - for (int i = 1; i < accuracy;i++) - cumulGamma[i] = cumulGamma[i-1]+p[i]; - for (int i = 0; i < accuracy;i++) - cumulGamma[i] = cumulGamma[i]/cumulGamma[accuracy-1]; - - accuracyGamma = accuracy; - - -} - - -*/ - - - - -inline MTRand::uint32 MTRand::randInt() -{ - // Pull a 32-bit integer from the generator state - // Every other access function simply transforms the numbers extracted here - - if( left == 0 ) reload(); - --left; - - register uint32 s1; - s1 = *pNext++; - s1 ^= (s1 >> 11); - s1 ^= (s1 << 7) & 0x9d2c5680UL; - s1 ^= (s1 << 15) & 0xefc60000UL; - return ( s1 ^ (s1 >> 18) ); -} - -inline MTRand::uint32 MTRand::randInt( const uint32& n ) -{ - // Find which bits are used in n - // Optimized by Magnus Jonsson (magnus@smartelectronix.com) - uint32 used = n; - used |= used >> 1; - used |= used >> 2; - used |= used >> 4; - used |= used >> 8; - used |= used >> 16; - - // Draw numbers until one is found in [0,n] - uint32 i; - do - i = randInt() & used; // toss unused bits to shorten search - while( i > n ); - return i; -} - - -inline void MTRand::seed( const uint32 oneSeed ) -{ - // Seed the generator with a simple uint32 - initialize(oneSeed); - reload(); -} - - -inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength ) -{ - // Seed the generator with an array of uint32's - // There are 2^19937-1 possible initial states. This function allows - // all of those to be accessed by providing at least 19937 bits (with a - // default seed length of N = 624 uint32's). Any bits above the lower 32 - // in each element are discarded. - // Just call seed() if you want to get array from /dev/urandom - initialize(19650218UL); - register int i = 1; - register uint32 j = 0; - register int k = ( N > seedLength ? N : seedLength ); - for( ; k; --k ) - { - state[i] = - state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); - state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; - state[i] &= 0xffffffffUL; - ++i; ++j; - if( i >= N ) { state[0] = state[N-1]; i = 1; } - if( j >= seedLength ) j = 0; - } - for( k = N - 1; k; --k ) - { - state[i] = - state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); - state[i] -= i; - state[i] &= 0xffffffffUL; - ++i; - if( i >= N ) { state[0] = state[N-1]; i = 1; } - } - state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array - reload(); -} - - -inline void MTRand::seed() -{ - // Seed the generator with an array from /dev/urandom if available - // Otherwise use a hash of time() and clock() values - - // First try getting an array from /dev/urandom - FILE* urandom = fopen( "/dev/urandom", "rb" ); - if( urandom ) - { - uint32 bigSeed[N]; - register uint32 *s = bigSeed; - register int i = N; - register bool success = true; - while( success && i-- ) - success = fread( s++, sizeof(uint32), 1, urandom ); - fclose(urandom); - if( success ) { seed( bigSeed, N ); return; } - } - - // Was not successful, so use time() and clock() instead - seed( hash( time(NULL), clock() ) ); -} - - -inline void MTRand::initialize( const uint32 seed ) -{ - // Initialize generator state with seed - // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. - // In previous versions, most significant bits (MSBs) of the seed affect - // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. - register uint32 *s = state; - register uint32 *r = state; - register int i = 1; - *s++ = seed & 0xffffffffUL; - for( ; i < N; ++i ) - { - *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; - r++; - } -} - - -inline void MTRand::reload() -{ - // Generate N new values in state - // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) - register uint32 *p = state; - register int i; - for( i = N - M; i--; ++p ) - *p = twist( p[M], p[0], p[1] ); - for( i = M; --i; ++p ) - *p = twist( p[M-N], p[0], p[1] ); - *p = twist( p[M-N], p[0], state[0] ); - - left = N, pNext = state; -} - - -inline MTRand::uint32 MTRand::hash( time_t t, clock_t c ) -{ - // Get a uint32 from t and c - // Better than uint32(x) in case x is floating point in [0,1] - // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk) - - static uint32 differ = 0; // guarantee time-based seeds will change - - uint32 h1 = 0; - unsigned char *p = (unsigned char *) &t; - for( size_t i = 0; i < sizeof(t); ++i ) - { - h1 *= UCHAR_MAX + 2U; - h1 += p[i]; - } - uint32 h2 = 0; - p = (unsigned char *) &c; - for( size_t j = 0; j < sizeof(c); ++j ) - { - h2 *= UCHAR_MAX + 2U; - h2 += p[j]; - } - return ( h1 + differ++ ) ^ h2; -} - - -inline void MTRand::save( uint32* saveArray ) const -{ - register uint32 *sa = saveArray; - register const uint32 *s = state; - register int i = N; - for( ; i--; *sa++ = *s++ ) {} - *sa = left; -} - - -inline void MTRand::load( uint32 *const loadArray ) -{ - register uint32 *s = state; - register uint32 *la = loadArray; - register int i = N; - for( ; i--; *s++ = *la++ ) {} - left = *la; - pNext = &state[N-left]; -} - - -inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ) -{ - register const MTRand::uint32 *s = mtrand.state; - register int i = mtrand.N; - for( ; i--; os << *s++ << "\t" ) {} - return os << mtrand.left; -} - - -inline std::istream& operator>>( std::istream& is, MTRand& mtrand ) -{ - register MTRand::uint32 *s = mtrand.state; - register int i = mtrand.N; - for( ; i--; is >> *s++ ) {} - is >> mtrand.left; - mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; - return is; -} - -#endif // MERSENNETWISTER_H - -// Change log: -// -// v0.1 - First release on 15 May 2000 -// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus -// - Translated from C to C++ -// - Made completely ANSI compliant -// - Designed convenient interface for initialization, seeding, and -// obtaining numbers in default or user-defined ranges -// - Added automatic seeding from /dev/urandom or time() and clock() -// - Provided functions for saving and loading generator state -// -// v0.2 - Fixed bug which reloaded generator one step too late -// -// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew -// -// v0.4 - Removed trailing newline in saved generator format to be consistent -// with output format of built-in types -// -// v0.5 - Improved portability by replacing static const int's with enum's and -// clarifying return values in seed(); suggested by Eric Heimburg -// - Removed MAXINT constant; use 0xffffffffUL instead -// -// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits -// - Changed integer [0,n] generator to give better uniformity -// -// v0.7 - Fixed operator precedence ambiguity in reload() -// - Added access for real numbers in (0,1) and (0,n) -// -// v0.8 - Included time.h header to properly support time_t and clock_t -// -// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto -// - Allowed for seeding with arrays of any length -// - Added access for real numbers in [0,1) with 53-bit resolution -// - Added access for real numbers from normal (Gaussian) distributions -// - Increased overall speed by optimizing twist() -// - Doubled speed of integer [0,n] generation -// - Fixed out-of-range number generation on 64-bit machines -// - Improved portability by substituting literal constants for long enum's -// - Changed license from GNU LGPL to BSD diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp deleted file mode 100644 index ab8c49410a..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/ParticleGrid.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/*=================================================================== - -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 _PARTICLEGRID -#define _PARTICLEGRID - - -#include "auxilary_classes.cpp" - - -template - class ParticleGrid -{ - - //////////////// Container -public: - T *particles; // particles in linear array - int pcnt; // actual number of particles - int concnt; // number of connections - int celloverflows; - - T **ID_2_address; - -private: - - int capacity; // maximal number of particles - int increase_step; - - /////////////////// Grid - - T **grid; // the grid - - // grid size - int nx; - int ny; - int nz; - - // scaling factor for grid - float mulx; - float muly; - float mulz; - - int csize; // particle capacity of single cell in grid - int *occnt; // occupation count of grid cells - int gridsize; // total number of cells - float m_Memory; - - struct NeighborTracker // to run over the neighbors - { - int cellidx[8]; - int cellidx_c[8]; - - int cellcnt; - int pcnt; - - } nbtrack; - - - -public: - - - ParticleGrid() - { - - //// involving the container - capacity = 0; - particles = 0; - ID_2_address = 0; - pcnt = 0; - concnt = 0; - celloverflows = 0; - - ////// involvin the grid - nx = 0; ny = 0; nz = 0; csize = 0; - gridsize = 0; - grid = (T**) 0; - occnt = (int*) 0; - - increase_step = 100000; - m_Memory = 0; - } - - float GetMemoryUsage() - { - return m_Memory; - } - - int allocate(int _capacity, - int _nx, int _ny, int _nz, float cellsize, int cellcapacity) - { - //// involving the container - capacity = _capacity; - particles = (T*) malloc(sizeof(T)*capacity); - ID_2_address = (T**) malloc(sizeof(T*)*capacity); - - if (particles == 0 || ID_2_address == 0) - { - fprintf(stderr,"error: Out of Memory\n"); - capacity = 0; - return -1; - } - else - { - fprintf(stderr,"Allocated Memory for %i particles \n",capacity); - } - - pcnt = 0; - int i; - for (i = 0;i < capacity;i++) - { - ID_2_address[i] = &(particles[i]); // initialize pointer in LUT - particles[i].ID = i; // initialize unique IDs - } - - ////// involvin the grid - nx = _nx; ny = _ny; nz = _nz; csize = cellcapacity; - gridsize = nx*ny*nz; - - m_Memory = (float)(sizeof(T*)*gridsize*csize)/1000000; - - grid = (T**) malloc(sizeof(T*)*gridsize*csize); - occnt = (int*) malloc(sizeof(int)*gridsize); - - if (grid == 0 || occnt == 0) - { - fprintf(stderr,"error: Out of Memory\n"); - capacity = 0; - return -1; - } - - for (i = 0;i < gridsize;i++) - occnt[i] = 0; - - mulx = 1/cellsize; - muly = 1/cellsize; - mulz = 1/cellsize; - - return 1; - } - - - - int reallocate() - { - int new_capacity = capacity + increase_step; - T* new_particles = (T*) realloc(particles,sizeof(T)*new_capacity); - T** new_ID_2_address = (T**) realloc(ID_2_address,sizeof(T*)*new_capacity); - if (new_particles == 0 || new_ID_2_address == 0) - { - fprintf(stderr,"ParticleGird:reallocate: out of memory!\n"); - return -1; - } - fprintf(stderr," now %i particles are allocated \n",new_capacity); - m_Memory = (float)(sizeof(T*)*new_capacity)/1000000; - - int i; - for (i = 0; i < capacity; i++) - { - new_ID_2_address[i] = new_ID_2_address[i] - particles + new_particles; // shift address - } - for (i = capacity; i < new_capacity; i++) - { - new_particles[i].ID = i; // initialize unique IDs - new_ID_2_address[i] = &(new_particles[i]) ; // initliaze pointer in LUT - } - for (i = 0; i < nx*ny*nz*csize; i++) - { - grid[i] = grid[i] - particles + new_particles; - } - particles = new_particles; - ID_2_address = new_ID_2_address; - capacity = new_capacity; - - return 1; - } - - - - ~ParticleGrid() - { - if (particles != 0) - free(particles); - if (grid != 0) - free(grid); - if (occnt != 0) - free(occnt); - if (ID_2_address != 0) - free(ID_2_address); - } - - - - int ID_2_index(int ID) - { - if (ID == -1) - return -1; - else - return (ID_2_address[ID] - particles); - - } - - - T* newParticle(pVector R) - { - /////// get free place in container; - if (pcnt >= capacity) - { - fprintf(stderr,"capacity overflow , reallocating ...\n"); - if (reallocate() == -1) - { - fprintf(stderr,"out of Memory!!\n"); - return 0; - } - } - - int xint = int(R[0]*mulx); - if (xint < 0) { //fprintf(stderr,"error: out of grid\n"); - return 0;} - if (xint >= nx) { // fprintf(stderr,"error: out of grid\n"); - return 0;} - int yint = int(R[1]*muly); - if (yint < 0) { //fprintf(stderr,"error: out of grid\n"); - return 0;} - if (yint >= ny) {// fprintf(stderr,"error: out of grid\n"); - return 0;} - int zint = int(R[2]*mulz); - if (zint < 0) {// fprintf(stderr,"error: out of grid\n"); - return 0;} - if (zint >= nz) { //fprintf(stderr,"error: out of grid\n"); - return 0;} - - int idx = xint + nx*(yint + ny*zint); - if (occnt[idx] < csize) - { - T *p = &(particles[pcnt]); - p->R = R; - p->mID = -1; - p->pID = -1; - pcnt++; - p->gridindex = csize*idx + occnt[idx]; - grid[p->gridindex] = p; - occnt[idx]++; - return p; - } - else - { - celloverflows++; - //fprintf(stderr,"error: cell overflow \n"); - return 0; - } - } - - - inline void updateGrid(int k) - { - T* p = &(particles[k]); - - /////// find new grid cell - int xint = int(p->R[0]*mulx); - if (xint < 0) { remove(k); return; } - if (xint >= nx) { remove(k); return; } - int yint = int(p->R[1]*muly); - if (yint < 0) { remove(k); return; } - if (yint >= ny) { remove(k); return; } - int zint = int(p->R[2]*mulz); - if (zint < 0) { remove(k); return; } - if (zint >= nz) { remove(k); return; } - - - int idx = xint + nx*(yint+ zint*ny); - int cellidx = p->gridindex/csize; - if (idx != cellidx) // cell has changed - { - - if (occnt[idx] < csize) - { - // remove from old position in grid; - int grdindex = p->gridindex; - grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; - grid[grdindex]->gridindex = grdindex; - occnt[cellidx]--; - - // insert at new position in grid - p->gridindex = idx*csize + occnt[idx]; - grid[p->gridindex] = p; - occnt[idx]++; - } - else - remove(k); - - } - } - - - inline bool tryUpdateGrid(int k) - { - T* p = &(particles[k]); - - /////// find new grid cell - int xint = int(p->R[0]*mulx); - if (xint < 0) { return false; } - if (xint >= nx) { return false; } - int yint = int(p->R[1]*muly); - if (yint < 0) { return false; } - if (yint >= ny) { return false; } - int zint = int(p->R[2]*mulz); - if (zint < 0) { return false; } - if (zint >= nz) { return false; } - - - int idx = xint + nx*(yint+ zint*ny); - int cellidx = p->gridindex/csize; - if (idx != cellidx) // cell has changed - { - - if (occnt[idx] < csize) - { - // remove from old position in grid; - int grdindex = p->gridindex; - grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; - grid[grdindex]->gridindex = grdindex; - occnt[cellidx]--; - - // insert at new position in grid - p->gridindex = idx*csize + occnt[idx]; - grid[p->gridindex] = p; - occnt[idx]++; - return true; - } - else - return false; - - } - return true; - } - - - - inline void remove(int k) - { - T* p = &(particles[k]); - int grdindex = p->gridindex; - int cellidx = grdindex/csize; - int idx = grdindex%csize; - - // remove pending connections - if (p->mID != -1) - destroyConnection(p,-1); - if (p->pID != -1) - destroyConnection(p,+1); - - // remove from grid - if (idx < occnt[cellidx]-1) - { - grid[grdindex] = grid[cellidx*csize + occnt[cellidx]-1]; - grid[grdindex]->gridindex = grdindex; - } - occnt[cellidx]--; - - - - // remove from container - if (kID; - int move_ID = particles[pcnt-1].ID; - - *p = particles[pcnt-1]; // move very last particle to empty slot - particles[pcnt-1].ID = todel_ID; // keep IDs unique - grid[p->gridindex] = p; // keep gridindex consistent - - // permute address table - ID_2_address[todel_ID] = &(particles[pcnt-1]); - ID_2_address[move_ID] = p; - - } - pcnt--; - - - - } - - inline void computeNeighbors(pVector &R) - { - float xfrac = R.GetX()*mulx; - float yfrac = R.GetY()*muly; - float zfrac = R.GetZ()*mulz; - int xint = int(xfrac); - int yint = int(yfrac); - int zint = int(zfrac); - - int dx = -1; - if (xfrac-xint > 0.5) dx = 1; - if (xint <= 0) { xint = 0; dx = 1; } - if (xint >= nx-1) { xint = nx-1; dx = -1; } - - int dy = -1; - if (yfrac-yint > 0.5) dy = 1; - if (yint <= 0) {yint = 0; dy = 1; } - if (yint >= ny-1) {yint = ny-1; dy = -1;} - - int dz = -1; - if (zfrac-zint > 0.5) dz = 1; - if (zint <= 0) {zint = 0; dz = 1; } - if (zint >= nz-1) {zint = nz-1; dz = -1;} - - - nbtrack.cellidx[0] = xint + nx*(yint+zint*ny); - nbtrack.cellidx[1] = nbtrack.cellidx[0] + dx; - nbtrack.cellidx[2] = nbtrack.cellidx[1] + dy*nx; - nbtrack.cellidx[3] = nbtrack.cellidx[2] - dx; - nbtrack.cellidx[4] = nbtrack.cellidx[0] + dz*nx*ny; - nbtrack.cellidx[5] = nbtrack.cellidx[4] + dx; - nbtrack.cellidx[6] = nbtrack.cellidx[5] + dy*nx; - nbtrack.cellidx[7] = nbtrack.cellidx[6] - dx; - - - nbtrack.cellidx_c[0] = csize*nbtrack.cellidx[0]; - nbtrack.cellidx_c[1] = csize*nbtrack.cellidx[1]; - nbtrack.cellidx_c[2] = csize*nbtrack.cellidx[2]; - nbtrack.cellidx_c[3] = csize*nbtrack.cellidx[3]; - nbtrack.cellidx_c[4] = csize*nbtrack.cellidx[4]; - nbtrack.cellidx_c[5] = csize*nbtrack.cellidx[5]; - nbtrack.cellidx_c[6] = csize*nbtrack.cellidx[6]; - nbtrack.cellidx_c[7] = csize*nbtrack.cellidx[7]; - - - - nbtrack.cellcnt = 0; - nbtrack.pcnt = 0; - - } - - - - inline T *getNextNeighbor() - { - - if (nbtrack.pcnt < occnt[nbtrack.cellidx[nbtrack.cellcnt]]) - { - - return grid[nbtrack.cellidx_c[nbtrack.cellcnt] + (nbtrack.pcnt++)]; - - } - else - { - - for(;;) - { - nbtrack.cellcnt++; - if (nbtrack.cellcnt >= 8) - return 0; - if (occnt[nbtrack.cellidx[nbtrack.cellcnt]] > 0) - break; - } - - nbtrack.pcnt = 1; - return grid[nbtrack.cellidx_c[nbtrack.cellcnt]]; - } - } - - - inline void createConnection(T *P1,int ep1, T *P2, int ep2) - { - if (ep1 == -1) - P1->mID = P2->ID; - else - P1->pID = P2->ID; - - if (ep2 == -1) - P2->mID = P1->ID; - else - P2->pID = P1->ID; - - concnt++; - } - - inline void destroyConnection(T *P1,int ep1, T *P2, int ep2) - { - if (ep1 == -1) - P1->mID = -1; - else - P1->pID = -1; - - if (ep2 == -1) - P2->mID = -1; - else - P2->pID = -1; - concnt--; - } - - inline void destroyConnection(T *P1,int ep1) - { - - T *P2 = 0; - if (ep1 == 1) - { - P2 = ID_2_address[P1->pID]; - P1->pID = -1; - } - else - { - P2 = ID_2_address[P1->mID]; - P1->mID = -1; - } - if (P2->mID == P1->ID) - { - P2->mID = -1; - } - else - { - P2->pID = -1; - } - concnt--; - - } -}; - - - - -/* - - -struct Connection -{ - int lID; - int rID; -}; - - -class ConnectionContainer -{ - - //////////////// Container -public: - Connection *cons; // cons in linear array - int ccnt; // actual number of cons - -private: - - int capacity; // maximal number of particles - - - -public: - - - ConnectionContainer() - { - - //// involving the container - capacity = 0; - cons = 0; - ccnt = 0; - - } - - - - void allocate(int _capacity) - { - - //// involving the container - capacity = _capacity; - cons = (Connection*) malloc(sizeof(Connection)*capacity); - ccnt = 0; - - } - - ~ConnectionContainer() - { - if (cons != 0) - free(cons); - } - - - Connection* newConnection(int lid,int rid) - { - /////// get free place in container; - if (ccnt < capacity) - { - Connection *c = &(cons[ccnt]); - c->lID = lid; - c->rID = rid; - ccnt++; - return c; - } - return 0; - } - - inline void remove(int k) - { - Connection* c = &(cons[k]); - - // remove from container - if (k -#include "MersenneTwister.h" - -class RJMCMCBase -{ -public: - - ParticleGrid m_ParticleGrid; - float *m_QBallImageData; - const int *datasz; - EnergyComputerBase *enc; - int m_Iterations; - float width; - float height; - float depth; - double *voxsize; - int m_NumAttributes; - int m_AcceptedProposals; - - RJMCMCBase(float *points,int numPoints, float *dimg, const int *dsz, double *voxsize, double cellsize) - : m_QBallImageData(dimg) - , datasz(dsz) - , enc(0) - , width(dsz[1]*voxsize[0]) - , height(dsz[2]*voxsize[1]) - , depth(dsz[3]*voxsize[2]) - , voxsize(voxsize) - , m_NumAttributes(0) - , m_AcceptedProposals(0) - { - fprintf(stderr,"Data dimensions (mm) : %f x %f x %f\n",width,height,depth); - fprintf(stderr,"Data dimensions (voxel) : %i x %i x %i\n",datasz[1],datasz[2],datasz[3]); - fprintf(stderr,"voxel size (mm) : %lf x %lf x %lf\n",voxsize[0],voxsize[1],voxsize[2]); - - float cellcnt_x = (int)((float)width/cellsize) +1; - float cellcnt_y = (int)((float)height/cellsize) +1; - float cellcnt_z = (int)((float)depth/cellsize) +1; - //int cell_capacity = 2048; - //int cell_capacity = 64; - int cell_capacity = 512; - - fprintf(stderr,"grid dimensions : %f x %f x %f\n",cellcnt_x,cellcnt_y,cellcnt_z); - fprintf(stderr,"grid cell size (mm) : %f^3\n",cellsize); - fprintf(stderr,"cell capacity : %i\n",cell_capacity); - fprintf(stderr,"#cells*cellcap : %.1f K\n",cell_capacity*cellcnt_x*cellcnt_y*cellcnt_z/1000); - - int minsize = 1000000; - int err = m_ParticleGrid.allocate(((numPoints>minsize)? (numPoints+100000) : minsize), cellcnt_x, cellcnt_y, cellcnt_z, cellsize, cell_capacity); - - if (err == -1) - { - fprintf(stderr,"RJMCMCBase: out of Memory!\n"); - return; - } - - m_NumAttributes = 10; - for (int k = 0; k < numPoints; k++) - { - Particle *p = m_ParticleGrid.newParticle(pVector(points[m_NumAttributes*k], points[m_NumAttributes*k+1],points[m_NumAttributes*k+2])); - if (p!=0) - { - p->N = pVector(points[m_NumAttributes*k+3],points[m_NumAttributes*k+4],points[m_NumAttributes*k+5]); - p->cap = points[m_NumAttributes*k+6]; - p->len = points[m_NumAttributes*k+7]; - p->mID = (int) points[m_NumAttributes*k+8]; - p->pID = (int) points[m_NumAttributes*k+9]; - if (p->mID != -1) - m_ParticleGrid.concnt++; - if (p->pID != -1) - m_ParticleGrid.concnt++; - p->label = 0; - } - else - { - fprintf(stderr,"error: cannot allocate particle, con. indices will be wrong! \n"); - } - } - m_ParticleGrid.concnt /= 2; - - m_Iterations = 0; - m_AcceptedProposals = 0; - } - - ~RJMCMCBase() - { - - } - - void WriteOutParticles(float *npoints) - { - for (int k = 0; k < m_ParticleGrid.pcnt; k++) - { - Particle *p = &(m_ParticleGrid.particles[k]); - npoints[m_NumAttributes*k] = p->R.GetX(); - npoints[m_NumAttributes*k+1] = p->R.GetY(); - npoints[m_NumAttributes*k+2] = p->R.GetZ(); - npoints[m_NumAttributes*k+3] = p->N.GetX(); - npoints[m_NumAttributes*k+4] = p->N.GetY(); - npoints[m_NumAttributes*k+5] = p->N.GetZ(); - npoints[m_NumAttributes*k+6] = p->cap; - npoints[m_NumAttributes*k+7] = p->len; - npoints[m_NumAttributes*k+8] = m_ParticleGrid.ID_2_index(p->mID); - npoints[m_NumAttributes*k+9] = m_ParticleGrid.ID_2_index(p->pID); - } - } - - void SetEnergyComputer(EnergyComputerBase *e) - { - enc = e; - } - - void Iterate(float* acceptance, unsigned long* numCon, unsigned long* numPart, bool *abort) - { - m_AcceptedProposals = 0; - for (int it = 0; it < m_Iterations;it++) - { - if (*abort) - break; - - IterateOneStep(); - - *numCon = m_ParticleGrid.concnt; - *numPart = m_ParticleGrid.pcnt; - } - *acceptance = (float)m_AcceptedProposals/m_Iterations; - } - - virtual void IterateOneStep() - { - - } -}; - - - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp deleted file mode 100644 index 0f15ef7675..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/RJMCMC_randshift.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/*=================================================================== - -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 "ParticleGrid.cpp" -#include "RJMCMCBase.cpp" -#include - -class RJMCMC : public RJMCMCBase -{ -public: - - float T_in ; - float T_ex ; - float dens; - - - float p_birth; - float p_death; - float p_shift; - float p_shiftopt; - float p_cap; - float p_con; - - - - float sigma_g; - float gamma_g; - float Z_g; - - float dthres; - float nthres; - float T_prop; - float stopprobability; - float del_prob; - - - - float len_def; - float len_sig; - - float cap_def; - float cap_sig; - - float externalEnergy; - float internalEnergy; - - float m_ChempotParticle; - - - Track TrackProposal, TrackBackup; - - - SimpSamp simpsamp; - - - RJMCMC(float *points,int numPoints, float *dimg, const int *dsz, double *voxsz, double cellsz) : RJMCMCBase(points,numPoints,dimg,dsz,voxsz,cellsz) - { - externalEnergy = 0; - internalEnergy = 0; - } - - void SetParameters(float Temp, int numit, float plen, float curv_hardthres, float chempot_particle) - { - m_Iterations = numit; - - p_birth = 0.25; - p_death = 0.05; - p_shift = 0.15; - p_shiftopt = 0.1; - p_con = 0.45; - p_cap = 0.0; - - m_ChempotParticle = chempot_particle; - - float sum = p_birth+p_death+p_shift+p_shiftopt+p_con; - p_birth /= sum; p_death /= sum; p_shift /= sum; p_shiftopt /= sum; - - T_in = Temp; - T_ex = 0.01; - dens = exp(-chempot_particle/T_in); - - len_def = plen; - len_sig = 0.0; - cap_def = 1.0; - cap_sig = 0.0; - - // shift proposal - sigma_g = len_def/8.0; - gamma_g = 1/(sigma_g*sigma_g*2); - Z_g = pow(2*PI*sigma_g,3.0/2.0)*(PI*sigma_g/len_def); - - // conn proposal - dthres = len_def; - nthres = curv_hardthres; - T_prop = 0.5; - dthres *= dthres; - stopprobability = exp(-1/T_prop); - del_prob = 0.1; - } - - void SetTemperature(float temp) - { - T_in = temp; - dens = exp(-m_ChempotParticle/T_in); - } - - void IterateOneStep() - { - float randnum = mtrand.frand(); - //randnum = 0; - - /////////////////////////////////////////////////////////////// - //////// Birth Proposal - /////////////////////////////////////////////////////////////// - if (randnum < p_birth) - { - -#ifdef TIMING - tic(&birthproposal_time); - birthstats.propose(); -#endif - - pVector R; - enc->drawSpatPosition(&R); - - //fprintf(stderr,"drawn: %f, %f, %f\n",R[0],R[1],R[2]); - //R.setXYZ(20.5*3, 35.5*3, 1.5*3); - - pVector N; N.rand_sphere(); - //N.setXYZ(1,0,0); - float cap = cap_def - cap_sig*mtrand.frand(); - float len = len_def;// + len_sig*(mtrand.frand()-0.5); - Particle prop; - prop.R = R; - prop.N = N; - prop.cap = cap; - prop.len = len; - - - float prob = dens * p_death /((p_birth)*(m_ParticleGrid.pcnt+1)); - - float ex_energy = enc->computeExternalEnergy(R,N,cap,len,0); - float in_energy = enc->computeInternalEnergy(&prop); - - prob *= exp((in_energy/T_in+ex_energy/T_ex)) ; - - if (prob > 1 || mtrand.frand() < prob) - { - Particle *p = m_ParticleGrid.newParticle(R); - if (p!=0) - { - p->R = R; - p->N = N; - p->cap = cap; - p->len = len; -#ifdef TIMING - birthstats.accepted(); -#endif - m_AcceptedProposals++; - } - } - -#ifdef TIMING - toc(&birthproposal_time); -#endif - } - /////////////////////////////////////////////////////////////// - //////// Death Proposal - /////////////////////////////////////////////////////////////// - else if (randnum < p_birth+p_death) - { - if (m_ParticleGrid.pcnt > 0) - { -#ifdef TIMING - tic(&deathproposal_time); - deathstats.propose(); -#endif - - int pnum = rand()%m_ParticleGrid.pcnt; - Particle *dp = &(m_ParticleGrid.particles[pnum]); - if (dp->pID == -1 && dp->mID == -1) - { - - float ex_energy = enc->computeExternalEnergy(dp->R,dp->N,dp->cap,dp->len,dp); - float in_energy = enc->computeInternalEnergy(dp); - - float prob = m_ParticleGrid.pcnt * (p_birth) /(dens*p_death); //*SpatProb(dp->R); - prob *= exp(-(in_energy/T_in+ex_energy/T_ex)) ; - if (prob > 1 || mtrand.frand() < prob) - { - m_ParticleGrid.remove(pnum); -#ifdef TIMING - deathstats.accepted(); -#endif - m_AcceptedProposals++; - } - } -#ifdef TIMING - toc(&deathproposal_time); -#endif - } - - } - /////////////////////////////////////////////////////////////// - //////// Cap change Proposal - /////////////////////////////////////////////////////////////// - else if (randnum < p_birth+p_death+p_cap) - { - if (m_ParticleGrid.pcnt > 0) - { - - int pnum = rand()%m_ParticleGrid.pcnt; - Particle *p = &(m_ParticleGrid.particles[pnum]); - Particle prop_p = *p; - - prop_p.cap = cap_def - cap_sig*mtrand.frand(); - - float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,prop_p.cap,p->len,p) - - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); - //float in_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) - // - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); - float prob = exp(ex_energy/T_ex); - // * SpatProb(p->R) / SpatProb(prop_p.R); - if (mtrand.frand() < prob) - { - p->cap = prop_p.cap; - m_AcceptedProposals++; - } - - } - - } - - /////////////////////////////////////////////////////////////// - //////// Shift Proposal - /////////////////////////////////////////////////////////////// - else if (randnum < p_birth+p_death+p_shift+p_cap) - { - float energy = 0; - if (m_ParticleGrid.pcnt > 0) - { -#ifdef TIMING - tic(&shiftproposal_time); - shiftstats.propose(); -#endif - - int pnum = rand()%m_ParticleGrid.pcnt; - Particle *p = &(m_ParticleGrid.particles[pnum]); - Particle prop_p = *p; - - prop_p.R.distortn(sigma_g); - prop_p.N.distortn(sigma_g/(2*p->len)); - prop_p.N.normalize(); - - - float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) - - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); - float in_energy = enc->computeInternalEnergy(&prop_p) - enc->computeInternalEnergy(p); - - float prob = exp(ex_energy/T_ex+in_energy/T_in); - // * SpatProb(p->R) / SpatProb(prop_p.R); - if (mtrand.frand() < prob) - { - pVector Rtmp = p->R; - pVector Ntmp = p->N; - p->R = prop_p.R; - p->N = prop_p.N; - if (!m_ParticleGrid.tryUpdateGrid(pnum)) - { - p->R = Rtmp; - p->N = Ntmp; - } -#ifdef TIMING - shiftstats.accepted(); -#endif - m_AcceptedProposals++; - } - -#ifdef TIMING - toc(&shiftproposal_time); -#endif - - } - - } - else if (randnum < p_birth+p_death+p_shift+p_shiftopt+p_cap) - { - float energy = 0; - if (m_ParticleGrid.pcnt > 0) - { - - int pnum = rand()%m_ParticleGrid.pcnt; - Particle *p = &(m_ParticleGrid.particles[pnum]); - - bool no_proposal = false; - Particle prop_p = *p; - if (p->pID != -1 && p->mID != -1) - { - Particle *plus = m_ParticleGrid.ID_2_address[p->pID]; - int ep_plus = (plus->pID == p->ID)? 1 : -1; - Particle *minus = m_ParticleGrid.ID_2_address[p->mID]; - int ep_minus = (minus->pID == p->ID)? 1 : -1; - prop_p.R = (plus->R + plus->N * (plus->len * ep_plus) + minus->R + minus->N * (minus->len * ep_minus))*0.5; - prop_p.N = plus->R - minus->R; - prop_p.N.normalize(); - } - else if (p->pID != -1) - { - Particle *plus = m_ParticleGrid.ID_2_address[p->pID]; - int ep_plus = (plus->pID == p->ID)? 1 : -1; - prop_p.R = plus->R + plus->N * (plus->len * ep_plus * 2); - prop_p.N = plus->N; - } - else if (p->mID != -1) - { - Particle *minus = m_ParticleGrid.ID_2_address[p->mID]; - int ep_minus = (minus->pID == p->ID)? 1 : -1; - prop_p.R = minus->R + minus->N * (minus->len * ep_minus * 2); - prop_p.N = minus->N; - } - else - no_proposal = true; - - if (!no_proposal) - { - float cos = prop_p.N*p->N; - float p_rev = exp(-((prop_p.R-p->R).norm_square() + (1-cos*cos))*gamma_g)/Z_g; - - float ex_energy = enc->computeExternalEnergy(prop_p.R,prop_p.N,p->cap,p->len,p) - - enc->computeExternalEnergy(p->R,p->N,p->cap,p->len,p); - float in_energy = enc->computeInternalEnergy(&prop_p) - enc->computeInternalEnergy(p); - - float prob = exp(ex_energy/T_ex+in_energy/T_in)*p_shift*p_rev/(p_shiftopt+p_shift*p_rev); - //* SpatProb(p->R) / SpatProb(prop_p.R); - - if (mtrand.frand() < prob) - { - pVector Rtmp = p->R; - pVector Ntmp = p->N; - p->R = prop_p.R; - p->N = prop_p.N; - if (!m_ParticleGrid.tryUpdateGrid(pnum)) - { - p->R = Rtmp; - p->N = Ntmp; - } - m_AcceptedProposals++; - } - } - } - - } - else - { - - - if (m_ParticleGrid.pcnt > 0) - { - -#ifdef TIMING - tic(&connproposal_time); - connstats.propose(); -#endif - - int pnum = rand()%m_ParticleGrid.pcnt; - Particle *p = &(m_ParticleGrid.particles[pnum]); - - EndPoint P; - P.p = p; - P.ep = (mtrand.frand() > 0.5)? 1 : -1; - - RemoveAndSaveTrack(P); - if (TrackBackup.proposal_probability != 0) - { - MakeTrackProposal(P); - - float prob = (TrackProposal.energy-TrackBackup.energy)/T_in ; - - // prob = exp(prob)*(TrackBackup.proposal_probability) - // /(TrackProposal.proposal_probability); - prob = exp(prob)*(TrackBackup.proposal_probability * pow(del_prob,TrackProposal.length)) - /(TrackProposal.proposal_probability * pow(del_prob,TrackBackup.length)); - if (mtrand.frand() < prob) - { - ImplementTrack(TrackProposal); -#ifdef TIMING - connstats.accepted(); -#endif - m_AcceptedProposals++; - } - else - { - ImplementTrack(TrackBackup); - } - } - else - ImplementTrack(TrackBackup); - -#ifdef TIMING - toc(&connproposal_time); -#endif - } - } - } - - - void ImplementTrack(Track &T) - { - for (int k = 1; k < T.length;k++) - { - m_ParticleGrid.createConnection(T.track[k-1].p,T.track[k-1].ep,T.track[k].p,-T.track[k].ep); - } - } - - - - void RemoveAndSaveTrack(EndPoint P) - { - EndPoint Current = P; - - int cnt = 0; - float energy = 0; - float AccumProb = 1.0; - TrackBackup.track[cnt] = Current; - - EndPoint Next; - - - - for (;;) - { - Next.p = 0; - if (Current.ep == 1) - { - if (Current.p->pID != -1) - { - Next.p = m_ParticleGrid.ID_2_address[Current.p->pID]; - Current.p->pID = -1; - m_ParticleGrid.concnt--; - } - } - else if (Current.ep == -1) - { - if (Current.p->mID != -1) - { - Next.p = m_ParticleGrid.ID_2_address[Current.p->mID]; - Current.p->mID = -1; - m_ParticleGrid.concnt--; - } - } - else - { fprintf(stderr,"RJMCMC_randshift: Connection inconsistent 3\n"); break; } - - if (Next.p == 0) // no successor - { - Next.ep = 0; // mark as empty successor - break; - } - else - { - if (Next.p->pID == Current.p->ID) - { - Next.p->pID = -1; - Next.ep = 1; - } - else if (Next.p->mID == Current.p->ID) - { - Next.p->mID = -1; - Next.ep = -1; - } - else - { fprintf(stderr,"RJMCMC_randshift: Connection inconsistent 4\n"); break; } - } - - - ComputeEndPointProposalDistribution(Current); - - AccumProb *= (simpsamp.probFor(Next)); - - if (Next.p == 0) // no successor -> break - break; - - energy += enc->computeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); - - Current = Next; - Current.ep *= -1; - cnt++; - TrackBackup.track[cnt] = Current; - - - if (mtrand.rand() > del_prob) - { - break; - } - - } - TrackBackup.energy = energy; - TrackBackup.proposal_probability = AccumProb; - TrackBackup.length = cnt+1; - - } - - - - void MakeTrackProposal(EndPoint P) - { - EndPoint Current = P; - int cnt = 0; - float energy = 0; - float AccumProb = 1.0; - TrackProposal.track[cnt++] = Current; - Current.p->label = 1; - - for (;;) - { - - // next candidate is already connected - if ((Current.ep == 1 && Current.p->pID != -1) || (Current.ep == -1 && Current.p->mID != -1)) - break; - - // track too long - if (cnt > 250) - break; - - ComputeEndPointProposalDistribution(Current); - - // // no candidates anymore - // if (simpsamp.isempty()) - // break; - - int k = simpsamp.draw(); - - // stop tracking proposed - if (k==0) - break; - - EndPoint Next = simpsamp.objs[k]; - float probability = simpsamp.probFor(k); - - // accumulate energy and proposal distribution - energy += enc->computeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); - AccumProb *= probability; - - // track to next endpoint - Current = Next; - Current.ep *= -1; - - Current.p->label = 1; // put label to avoid loops - TrackProposal.track[cnt++] = Current; - - - - } - - TrackProposal.energy = energy; - TrackProposal.proposal_probability = AccumProb; - TrackProposal.length = cnt; - - // clear labels - for (int j = 0; j < TrackProposal.length;j++) - { - TrackProposal.track[j].p->label = 0; - } - - } - - - - - void ComputeEndPointProposalDistribution(EndPoint P) - { - Particle *p = P.p; - int ep = P.ep; - - float dist,dot; - pVector R = p->R + (p->N * ep*p->len); - m_ParticleGrid.computeNeighbors(R); - simpsamp.clear(); - - simpsamp.add(stopprobability,EndPoint(0,0)); - - for (;;) - { - Particle *p2 = m_ParticleGrid.getNextNeighbor(); - if (p2 == 0) break; - if (p!=p2 && p2->label == 0) - { - if (p2->mID == -1) - { - dist = (p2->R - p2->N * p2->len - R).norm_square(); - if (dist < dthres) - { - dot = p2->N*p->N * ep; - if (dot > nthres) - { - float en = enc->computeInternalEnergyConnection(p,ep,p2,-1); - simpsamp.add(exp(en/T_prop),EndPoint(p2,-1)); - } - } - } - if (p2->pID == -1) - { - dist = (p2->R + p2->N * p2->len - R).norm_square(); - if (dist < dthres) - { - dot = p2->N*p->N * (-ep); - if (dot > nthres) - { - float en = enc->computeInternalEnergyConnection(p,ep,p2,+1); - simpsamp.add(exp(en/T_prop),EndPoint(p2,+1)); - } - } - } - } - } - } - - -}; - - - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp deleted file mode 100644 index f13bfbd18b..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/SphereInterpolator.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/*=================================================================== - -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 "auxilary_classes.cpp" - - -class SphereInterpolator -{ -public: - float *barycoords; - int *indices; - int size; // size of LUT - int sN; // (sizeofLUT-1)/2 - int nverts; // number of data vertices - - - float beta; - float inva; - float b; - - - int *idx; - float *interpw; - - SphereInterpolator(float *barycoords, int *indices, int numverts, int sizeLUT, float beta) - { - this->barycoords = barycoords; - this->indices = indices; - this->size = sizeLUT; - this->sN = (sizeLUT-1)/2; - this->nverts = numverts; - this->beta = beta; - - inva = (sqrt(1+beta)-sqrt(beta)); - b = 1/(1-sqrt(1/beta + 1)); - - } - - - inline void getInterpolation(vnl_vector_fixed N) - { - float nx = N[0]; - float ny = N[1]; - float nz = N[2]; - - if (nz > 0.5) - { - int x = float2int(nx); - int y = float2int(ny); - int i = 3*6*(x+y*size); // (:,1,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - if (nz < -0.5) - { - int x = float2int(nx); - int y = float2int(ny); - int i = 3*(1+6*(x+y*size)); // (:,2,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - if (nx > 0.5) - { - int z = float2int(nz); - int y = float2int(ny); - int i = 3*(2+6*(z+y*size)); // (:,2,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - if (nx < -0.5) - { - int z = float2int(nz); - int y = float2int(ny); - int i = 3*(3+6*(z+y*size)); // (:,2,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - if (ny > 0) - { - int x = float2int(nx); - int z = float2int(nz); - int i = 3*(4+6*(x+z*size)); // (:,1,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - else - { - int x = float2int(nx); - int z = float2int(nz); - int i = 3*(5+6*(x+z*size)); // (:,1,x,y) - idx = indices+i; - interpw = barycoords +i; - return; - } - - } - - - inline float invrescale(float f) - { - float x = (fabs(f)-b)*inva; - if (f>0) - return (x*x-beta); - else - return beta - x*x; - } - - inline int float2int(float x) - { - return int((invrescale(x)+1)*sN-0.5); - - } - - -}; - - - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp deleted file mode 100644 index 297649be37..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/auxilary_classes.cpp +++ /dev/null @@ -1,658 +0,0 @@ -/*=================================================================== - -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 _AUXCLASS -#define _AUXCLASS - -#ifndef INFINITY -#define INFINITY 1000000000 -#endif - -//#define INLINE __attribute__ ((always_inline)) -#define INLINE inline - -//#define __SSE2 - - - -#ifdef __SSE2 -#include - -class pVector -{ - -private: - __m128 r; - -public: - - static float store[4]; - - pVector() - { - - } - - pVector(__m128 q) - { - r = q; - } - - - pVector(float x,float y,float z) - { - r = _mm_set_ps(0,z,y,x); - } - - - INLINE void storeXYZ() - { - _mm_store_ps(store,r); - } - - INLINE void setXYZ(float sx,float sy,float sz) - { - r = _mm_set_ps(0,sz,sy,sx); - } - - - - - INLINE void rand(float w,float h,float d) - { - float x = mtrand.frand()*w; - float y = mtrand.frand()*h; - float z = mtrand.frand()*d; - r = _mm_set_ps(0,z,y,x); - - } - - INLINE void rand_sphere() - { - r = _mm_set_ps(0,mtrand.frandn(),mtrand.frandn(),mtrand.frandn()); - normalize(); - } - - INLINE void normalize() - { - __m128 q = _mm_mul_ps(r,r); - _mm_store_ps(store,q); - float norm = sqrt(store[0]+store[1]+store[2]) + 0.00000001; - q = _mm_set_ps1(1/norm); - r = _mm_mul_ps(r,q); - - } - - INLINE float norm_square() - { - __m128 q = _mm_mul_ps(r,r); - _mm_store_ps(store,q); - return store[0]+store[1]+store[2]; - } - - INLINE void distortn(float sigma) - { - __m128 s = _mm_set_ps(0,mtrand.frandn(),mtrand.frandn(),mtrand.frandn()); - __m128 q = _mm_set_ps1(sigma); - r = _mm_add_ps(r,_mm_mul_ps(q,s)); - } - - INLINE pVector operator*(float s) - { - __m128 q = _mm_set_ps1(s); - return pVector(_mm_mul_ps(q,r)); - } - - INLINE void operator*=(float &s) - { - __m128 q = _mm_set_ps1(s); - r = _mm_mul_ps(q,r); - } - - INLINE pVector operator+(pVector R) - { - return pVector(_mm_add_ps(R.r,r)); - } - - INLINE void operator+=(pVector R) - { - r = _mm_add_ps(r,R.r); - } - - INLINE pVector operator-(pVector R) - { - return pVector(_mm_sub_ps(r,R.r)); - } - - INLINE void operator-=(pVector R) - { - r = _mm_sub_ps(r,R.r); - } - - INLINE pVector operator/(float &s) - { - __m128 q = _mm_set_ps1(s); - return pVector(_mm_div_ps(q,r)); - } - - INLINE void operator/=(float &s) - { - __m128 q = _mm_set_ps1(s); - r = _mm_div_ps(r,q); - } - - INLINE float operator*(pVector R) - { - __m128 q = _mm_mul_ps(r,R.r); - _mm_store_ps(store,q); - return store[0]+store[1]+store[2]; - } - - -}; - -float pVector::store[4]; - -#else - -class pVector -{ -private: - float x; - float y; - float z; - -public: - - pVector() - { - - } - - pVector(float x,float y,float z) - { - this->x = x; - this->y = y; - this->z = z; - } - - INLINE void SetXYZ(float sx,float sy, float sz) - { - x = sx; - y = sy; - z = sz; - } - - INLINE void GetXYZ(float *xyz) - { - xyz[0] = x; - xyz[1] = y; - xyz[2] = z; - } - - INLINE float GetX() - { - return x; - } - - INLINE float GetY() - { - return y; - } - - INLINE float GetZ() - { - return z; - } - - INLINE void rand(float w, float h, float d) - { - this->x = mtrand.frand()*w; - this->y = mtrand.frand()*h; - this->z = mtrand.frand()*d; - } - - INLINE void rand_sphere() - { - this->x = mtrand.frandn(); - this->y = mtrand.frandn(); - this->z = mtrand.frandn(); - normalize(); - } - - INLINE void normalize() - { - float norm = sqrt(x*x+y*y+z*z)+ 0.00000001; - *this /= norm; - } - - INLINE float norm_square() - { - return x*x + y*y + z*z; - } - - INLINE void distortn(float sigma) - { - x += sigma*mtrand.frandn(); - y += sigma*mtrand.frandn(); - z += sigma*mtrand.frandn(); - } - - INLINE float operator[](int index) - { - switch(index) - { - case 0: - return x; - case 1: - return y; - case 2: - return z; - default: - return 0.0f; - } - } - - INLINE pVector operator*(float s) - { - return pVector(s*x,s*y,s*z); - } - - INLINE void operator*=(float &s) - { - x *= s; - y *= s; - z *= s; - } - - INLINE pVector operator+(pVector R) - { - return pVector(x+R.x,y+R.y,z+R.z); - } - - INLINE void operator+=(pVector R) - { - x += R.x; - y += R.y; - z += R.z; - } - - INLINE pVector operator-(pVector R) - { - return pVector(x-R.x,y-R.y,z-R.z); - } - - INLINE void operator-=(pVector R) - { - x -= R.x; - y -= R.y; - z -= R.z; - } - - INLINE pVector operator/(float &s) - { - return pVector(x/s,y/s,z/s); - } - - INLINE void operator/=(float &s) - { - x /= s; - y /= s; - z /= s; - } - - - INLINE float operator*(pVector R) - { - return x*R.x+y*R.y+z*R.z; - } -}; - -#endif - - -class Particle -{ -public: - - Particle() - { - label = 0; - pID = -1; - mID = -1; - inserted = false; - } - - ~Particle() - { - } - - pVector R; - pVector N; - float cap; - float len; - - int gridindex; // index in the grid where it is living - int ID; - int pID; - int mID; - - int label; - int numerator; - bool inserted; -}; - - -class EnergyGradient -{ -public: - pVector gR; - pVector gN; - - INLINE float norm2() - { - return gR.norm_square() + gN.norm_square(); - } -} ; - - -template -class SimpSamp -{ - - float *P; - int cnt; - -public: - T *objs; - - - SimpSamp() - { - P = (float*) malloc(sizeof(float)*1000); - objs = (T*) malloc(sizeof(T)*1000); - } - ~SimpSamp() - { - free(P); - free(objs); - } - - INLINE void clear() - { - cnt = 1; - P[0] = 0; - } - - INLINE void add(float p, T obj) - { - P[cnt] = P[cnt-1] + p; - objs[cnt-1] = obj; - cnt++; - } - - // INLINE int draw() - // { - // float r = mtrand.frand()*P[cnt-1]; - // for (int i = 1; i < cnt; i++) - // { - // if (r <= P[i]) - // return i-1; - // } - // return cnt-2; - // } - - INLINE int draw() - { - float r = mtrand.frand()*P[cnt-1]; - int j; - int rl = 1; - int rh = cnt-1; - while(rh != rl) - { - j = rl + (rh-rl)/2; - if (r < P[j]) - { - rh = j; - continue; - } - if (r > P[j]) - { - rl = j+1; - continue; - } - break; - } - return rh-1; - } - - - - - - INLINE T drawObj() - { - return objs[draw()]; - } - - INLINE bool isempty() - { - if (cnt == 1) - return true; - else - return false; - } - - - float probFor(int idx) - { - return (P[idx+1]-P[idx])/P[cnt-1]; - } - - float probFor(T &t) - { - for (int i = 1; i< cnt;i++) - { - if (t == objs[i-1]) - return probFor(i-1); - } - return 0; - } - - - -}; - - -class EndPoint -{ -public: - EndPoint() - {} - - EndPoint(Particle *p,int ep) - { - this->p = p; - this->ep = ep; - } - Particle *p; - int ep; - - inline bool operator==(EndPoint P) - { - return (P.p == p) && (P.ep == ep); - } -}; - -class Track -{ -public: - EndPoint track[1000]; - float energy; - float proposal_probability; - int length; - - void clear() - { - length = 0; - energy = 0; - proposal_probability = 1; - } - - - bool isequal(Track &t) - { - for (int i = 0; i < length;i++) - { - if (track[i].p != t.track[i].p || track[i].ep != t.track[i].ep) - return false; - } - return true; - } - -}; - -float getMax(float *arr, int cnt) -{ - float max = arr[0]; - for (int i = 1; i < cnt; i++) - { - if (arr[i] > max) - max = arr[i]; - } - return max; -} - - - -float getMin(float *arr, int cnt) -{ - float min = arr[0]; - for (int i = 1; i < cnt; i++) - { - if (arr[i] < min) - min = arr[i]; - } - return min; -} - - -int getArgMin(float *arr, int cnt) -{ - float min = arr[0]; - int idx = 0; - for (int i = 1; i < cnt; i++) - { - if (arr[i] < min) - { - min = arr[i]; - idx = i; - } - } - return idx; -} - - - - -inline float distLseg(pVector &R1,pVector &N1,pVector &R2,pVector &N2,float &len) -{ - - pVector D = R1-R2; - float beta = N1*N2; - float divisor = 1.001-beta*beta; - float gamma1 = N1*D; - float gamma2 = N2*D; - float t,u; - float EPdist[4]; - - pVector Q; - float dist = 102400000.0; - - while(true) - { - - t = -(gamma1+beta*gamma2) / divisor; - u = (gamma1*beta+gamma2) / divisor; - if (fabs(t) < len && fabs(u) < len) - { - Q = D + N1*t - N2*u; - dist = Q*Q; - break; - } - - beta = len*beta; - - t = beta - gamma1; - if (fabs(t) < len) - { - Q = D + N1*t - N2*len; - float d = Q*Q; - if (d < dist) dist = d; - } - - t = -beta - gamma1; - if (fabs(t) < len) - { - Q = D + N1*t + N2*len; - float d = Q*Q; - if (d < dist) dist = d; - } - - u = beta + gamma2; - if (fabs(u) < len) - { - Q = D + N1*len - N2*u; - float d = Q*Q; - if (d < dist) dist = d; - } - - u = -beta + gamma2; - if (fabs(u) < len) - { - Q = D - N1*len - N2*u; - float d = Q*Q; - if (d < dist) dist = d; - } - - if (dist != 102400000.0) - break; - - - EPdist[0] = beta + gamma1 - gamma2; - EPdist[1] = -beta + gamma1 + gamma2; - EPdist[2] = -beta - gamma1 - gamma2; - EPdist[3] = beta - gamma1 + gamma2; - int c = getArgMin(EPdist,4); - if (c==0) {t = +len; u = +len; } - if (c==1) {t = +len; u = -len; } - if (c==2) {t = -len; u = +len; } - if (c==3) {t = -len; u = -len; } - Q = D + N1*t - N2*u; - dist = Q*Q; - break; - - } - - - return dist; - -} - - -#endif - - diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.cpp new file mode 100644 index 0000000000..6176198c36 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.cpp @@ -0,0 +1,459 @@ +/*=================================================================== + +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 "mitkEnergyComputer.h" +#include + +using namespace mitk; + +EnergyComputer::EnergyComputer(ItkQBallImgType* qballImage, ItkFloatImageType* mask, ParticleGrid* particleGrid, SphereInterpolator* interpolator, ItkRandGenType* randGen) + : m_UseTrilinearInterpolation(true) +{ + m_ParticleGrid = particleGrid; + m_RandGen = randGen; + m_Image = qballImage; + m_SphereInterpolator = interpolator; + m_Mask = mask; + + m_ParticleLength = m_ParticleGrid->m_ParticleLength; + m_SquaredParticleLength = m_ParticleLength*m_ParticleLength; + + m_Size[0] = m_Image->GetLargestPossibleRegion().GetSize()[0]; + m_Size[1] = m_Image->GetLargestPossibleRegion().GetSize()[1]; + m_Size[2] = m_Image->GetLargestPossibleRegion().GetSize()[2]; + + if (m_Size[0]<3 || m_Size[1]<3 || m_Size[2]<3) + m_UseTrilinearInterpolation = false; + + m_Spacing[0] = m_Image->GetSpacing()[0]; + m_Spacing[1] = m_Image->GetSpacing()[1]; + m_Spacing[2] = m_Image->GetSpacing()[2]; + + // calculate rotation matrix + vnl_matrix temp = m_Image->GetDirection().GetVnlMatrix(); + vnl_matrix directionMatrix; directionMatrix.set_size(3,3); + vnl_copy(temp, directionMatrix); + vnl_vector_fixed d0 = directionMatrix.get_column(0); d0.normalize(); + vnl_vector_fixed d1 = directionMatrix.get_column(1); d1.normalize(); + vnl_vector_fixed d2 = directionMatrix.get_column(2); d2.normalize(); + directionMatrix.set_column(0, d0); + directionMatrix.set_column(1, d1); + directionMatrix.set_column(2, d2); + vnl_matrix_fixed I = directionMatrix*directionMatrix.transpose(); + if(!I.is_identity(mitk::eps)) + fprintf(stderr,"itkGibbsTrackingFilter: image direction is not a rotation matrix. Tracking not possible!\n"); + m_RotationMatrix = directionMatrix; + + if (QBALL_ODFSIZE != m_SphereInterpolator->nverts) + fprintf(stderr,"EnergyComputer: error during init: data does not match with interpolation scheme\n"); + + int totsz = m_Size[0]*m_Size[1]*m_Size[2]; + m_CumulatedSpatialProbability.resize(totsz, 0.0); // +1? + m_ActiveIndices.resize(totsz, 0); + + // calculate active voxels and cumulate probabilities + m_NumActiveVoxels = 0; + m_CumulatedSpatialProbability[0] = 0; + for (int x = 0; x < m_Size[0];x++) + for (int y = 0; y < m_Size[1];y++) + for (int z = 0; z < m_Size[2];z++) + { + int idx = x+(y+z*m_Size[1])*m_Size[0]; + ItkFloatImageType::IndexType index; + index[0] = x; index[1] = y; index[2] = z; + if (m_Mask->GetPixel(index) > 0.5) + { + m_CumulatedSpatialProbability[m_NumActiveVoxels+1] = m_CumulatedSpatialProbability[m_NumActiveVoxels] + m_Mask->GetPixel(index); + m_ActiveIndices[m_NumActiveVoxels] = idx; + m_NumActiveVoxels++; + } + } + for (int k = 0; k < m_NumActiveVoxels; k++) + m_CumulatedSpatialProbability[k] /= m_CumulatedSpatialProbability[m_NumActiveVoxels]; + + std::cout << "EnergyComputer: " << m_NumActiveVoxels << " active voxels found" << std::endl; +} + +void EnergyComputer::SetParameters(float particleWeight, float particleWidth, float connectionPotential, float curvThres, float inexBalance, float particlePotential) +{ + m_ParticleChemicalPotential = particlePotential; + m_ConnectionPotential = connectionPotential; + m_ParticleWeight = particleWeight; + + float bal = 1/(1+exp(-inexBalance)); + m_ExtStrength = 2*bal; + m_IntStrength = 2*(1-bal)/m_SquaredParticleLength; + + m_CurvatureThreshold = curvThres; + + float sigma_s = particleWidth; + gamma_s = 1/(sigma_s*sigma_s); + gamma_reg_s =1/(m_SquaredParticleLength/4); +} + +// draw random position from active voxels +void EnergyComputer::DrawRandomPosition(vnl_vector_fixed& R) +{ + float r = m_RandGen->GetVariate();//m_RandGen->frand(); + int j; + int rl = 1; + int rh = m_NumActiveVoxels; + while(rh != rl) + { + j = rl + (rh-rl)/2; + if (r < m_CumulatedSpatialProbability[j]) + { + rh = j; + continue; + } + if (r > m_CumulatedSpatialProbability[j]) + { + rl = j+1; + continue; + } + break; + } + R[0] = m_Spacing[0]*((float)(m_ActiveIndices[rh-1] % m_Size[0]) + m_RandGen->GetVariate()); + R[1] = m_Spacing[1]*((float)((m_ActiveIndices[rh-1]/m_Size[0]) % m_Size[1]) + m_RandGen->GetVariate()); + R[2] = m_Spacing[2]*((float)(m_ActiveIndices[rh-1]/(m_Size[0]*m_Size[1])) + m_RandGen->GetVariate()); +} + +// return spatial probability of position +float EnergyComputer::SpatProb(vnl_vector_fixed pos) +{ + ItkFloatImageType::IndexType index; + index[0] = floor(pos[0]/m_Spacing[0]); + index[1] = floor(pos[1]/m_Spacing[1]); + index[2] = floor(pos[2]/m_Spacing[2]); + + if (m_Mask->GetLargestPossibleRegion().IsInside(index)) // is inside image? + return m_Mask->GetPixel(index); + else + return 0; +} + +float EnergyComputer::EvaluateOdf(vnl_vector_fixed& pos, vnl_vector_fixed dir) +{ + const int sampleSteps = 10; // evaluate ODF at 2*sampleSteps+1 positions along dir + vnl_vector_fixed samplePos; // current position to evaluate + float result = 0; // average of sampled ODF values + int xint, yint, zint; // voxel containing samplePos + + // rotate particle direction according to image rotation + dir = m_RotationMatrix*dir; + + // get interpolation for rotated direction + m_SphereInterpolator->getInterpolation(dir); + + // sample ODF values along particle direction + for (int i=-sampleSteps; i <= sampleSteps;i++) + { + samplePos = pos + (dir * m_ParticleLength) * ((float)i/sampleSteps); + + if (!m_UseTrilinearInterpolation) // image has not enough slices to use trilinear interpolation + { + ItkQBallImgType::IndexType index; + index[0] = floor(pos[0]/m_Spacing[0]); + index[1] = floor(pos[1]/m_Spacing[1]); + index[2] = floor(pos[2]/m_Spacing[2]); + if (m_Image->GetLargestPossibleRegion().IsInside(index)) + { + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2]); + } + } + else // use trilinear interpolation + { + float Rx = samplePos[0]/m_Spacing[0]-0.5; + float Ry = samplePos[1]/m_Spacing[1]-0.5; + float Rz = samplePos[2]/m_Spacing[2]-0.5; + + xint = floor(Rx); + yint = floor(Ry); + zint = floor(Rz); + + if (xint >= 0 && xint < m_Size[0]-1 && yint >= 0 && yint < m_Size[1]-1 && zint >= 0 && zint < m_Size[2]-1) + { + float xfrac = Rx-xint; + float yfrac = Ry-yint; + float zfrac = Rz-zint; + + ItkQBallImgType::IndexType index; + float weight; + + weight = (1-xfrac)*(1-yfrac)*(1-zfrac); + index[0] = xint; index[1] = yint; index[2] = zint; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (xfrac)*(1-yfrac)*(1-zfrac); + index[0] = xint+1; index[1] = yint; index[2] = zint; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (1-xfrac)*(yfrac)*(1-zfrac); + index[0] = xint; index[1] = yint+1; index[2] = zint; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (1-xfrac)*(1-yfrac)*(zfrac); + index[0] = xint; index[1] = yint; index[2] = zint+1; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (xfrac)*(yfrac)*(1-zfrac); + index[0] = xint+1; index[1] = yint+1; index[2] = zint; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (1-xfrac)*(yfrac)*(zfrac); + index[0] = xint; index[1] = yint+1; index[2] = zint+1; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (xfrac)*(1-yfrac)*(zfrac); + index[0] = xint+1; index[1] = yint; index[2] = zint+1; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + + weight = (xfrac)*(yfrac)*(zfrac); + index[0] = xint+1; index[1] = yint+1; index[2] = zint+1; + result += (m_Image->GetPixel(index)[m_SphereInterpolator->idx[0]-1]*m_SphereInterpolator->interpw[0] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[1]-1]*m_SphereInterpolator->interpw[1] + + m_Image->GetPixel(index)[m_SphereInterpolator->idx[2]-1]* m_SphereInterpolator->interpw[2])*weight; + } + } + } + result /= (2*sampleSteps+1); // average result over taken samples + return result; +} + +float EnergyComputer::ComputeExternalEnergy(vnl_vector_fixed &R, vnl_vector_fixed &N, Particle *dp) +{ + if (SpatProb(R) == 0) // check if position is inside mask + return -INFINITY; + + float odfVal = EvaluateOdf(R, N); // evaluate ODF in given direction + + float modelVal = 0; + m_ParticleGrid->ComputeNeighbors(R); // retrieve neighbouring particles from particle grid + Particle* neighbour = m_ParticleGrid->GetNextNeighbor(); + while (neighbour!=NULL) // iterate over nieghbouring particles + { + if (dp != neighbour) // don't evaluate against itself + { + // see Reisert et al. "Global Reconstruction of Neuronal Fibers", MICCAI 2009 + float dot = fabs(dot_product(N,neighbour->dir)); + float bw = mbesseli0(dot); + float dpos = (neighbour->pos-R).squared_magnitude(); + float w = mexp(dpos*gamma_s); + modelVal += w*(bw+m_ParticleChemicalPotential); + w = mexp(dpos*gamma_reg_s); + } + neighbour = m_ParticleGrid->GetNextNeighbor(); + } + + float energy = 2*(odfVal/m_ParticleWeight-modelVal) - (mbesseli0(1.0)+m_ParticleChemicalPotential); + return energy*m_ExtStrength; +} + +float EnergyComputer::ComputeInternalEnergy(Particle *dp) +{ + float energy = 0; + + if (dp->pID != -1) // has predecessor + energy += ComputeInternalEnergyConnection(dp,+1); + + if (dp->mID != -1) // has successor + energy += ComputeInternalEnergyConnection(dp,-1); + + return energy; +} + +float EnergyComputer::ComputeInternalEnergyConnection(Particle *p1,int ep1) +{ + Particle *p2 = 0; + int ep2; + + if (ep1 == 1) + p2 = m_ParticleGrid->GetParticle(p1->pID); // get predecessor + else + p2 = m_ParticleGrid->GetParticle(p1->mID); // get successor + + // check in which direction the connected particle is pointing + if (p2->mID == p1->ID) + ep2 = -1; + else if (p2->pID == p1->ID) + ep2 = 1; + else + std::cout << "EnergyComputer: Connections are inconsistent!" << std::endl; + + return ComputeInternalEnergyConnection(p1,ep1,p2,ep2); +} + +float EnergyComputer::ComputeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) +{ + // see Reisert et al. "Global Reconstruction of Neuronal Fibers", MICCAI 2009 + if ((dot_product(p1->dir,p2->dir))*ep1*ep2 > -m_CurvatureThreshold) // angle between particles is too sharp + return -INFINITY; + + // calculate the endpoints of the two particles + vnl_vector_fixed endPoint1 = p1->pos + (p1->dir * (m_ParticleLength * ep1)); + vnl_vector_fixed endPoint2 = p2->pos + (p2->dir * (m_ParticleLength * ep2)); + + // check if endpoints are too far apart to connect + if ((endPoint1-endPoint2).squared_magnitude() > m_SquaredParticleLength) + return -INFINITY; + + // calculate center point of the two particles + vnl_vector_fixed R = (p2->pos + p1->pos); R *= 0.5; + + // they are not allowed to connect if the mask image does not allow it + if (SpatProb(R) == 0) + return -INFINITY; + + // get distances of endpoints to center point + float norm1 = (endPoint1-R).squared_magnitude(); + float norm2 = (endPoint2-R).squared_magnitude(); + + // calculate actual internal energy + float energy = (m_ConnectionPotential-norm1-norm2)*m_IntStrength; + return energy; +} + +float EnergyComputer::mbesseli0(float x) +{ + // BESSEL_APPROXCOEFF[0] = -0.1714; + // BESSEL_APPROXCOEFF[1] = 0.5332; + // BESSEL_APPROXCOEFF[2] = -1.4889; + // BESSEL_APPROXCOEFF[3] = 2.0389; + float y = x*x; + float erg = -0.1714; + erg += y*0.5332; + erg += y*y*-1.4889; + erg += y*y*y*2.0389; + return erg; +} + +float EnergyComputer::mexp(float x) +{ + return((x>=7.0) ? 0 : ((x>=5.0) ? (-0.0029*x+0.0213) : ((x>=3.0) ? (-0.0215*x+0.1144) : ((x>=2.0) ? (-0.0855*x+0.3064) : ((x>=1.0) ? (-0.2325*x+0.6004) : ((x>=0.5) ? (-0.4773*x+0.8452) : ((x>=0.0) ? (-0.7869*x+1.0000) : 1 ))))))); + // return exp(-x); +} + +//ComputeFiberCorrelation() +//{ +// float bD = 15; + +// vnl_matrix_fixed bDir = +// *itk::PointShell >::DistributePointShell(); + +// const int N = QBALL_ODFSIZE; + +// vnl_matrix_fixed temp = bDir.transpose(); +// vnl_matrix_fixed C = temp*bDir; +// vnl_matrix_fixed Q = C; +// vnl_vector_fixed mean; +// for(int i=0; i repMean; +// for (int i=0; i P = Q*Q; + +// std::vector pointer; +// pointer.reserve(N*N); +// double * start = C.data_block(); +// double * end = start + N*N; +// for (double * iter = start; iter != end; ++iter) +// { +// pointer.push_back(iter); +// } +// std::sort(pointer.begin(), pointer.end(), LessDereference()); + +// vnl_vector_fixed alpha; +// vnl_vector_fixed beta; +// for (int i=0; im_Meanval_sq = (sum*sum)/N; + +// vnl_vector_fixed alpha_0; +// vnl_vector_fixed alpha_2; +// vnl_vector_fixed alpha_4; +// vnl_vector_fixed alpha_6; +// for(int i=0; i T; +// T.set_column(0,alpha_0); +// T.set_column(1,alpha_2); +// T.set_column(2,alpha_4); +// T.set_column(3,alpha_6); + +// vnl_vector_fixed coeff = vnl_matrix_inverse(T).pinverse()*beta; + +// MITK_INFO << "itkGibbsTrackingFilter: Bessel oefficients: " << coeff; + +// BESSEL_APPROXCOEFF = new float[4]; + +// BESSEL_APPROXCOEFF[0] = coeff(0); +// BESSEL_APPROXCOEFF[1] = coeff(1); +// BESSEL_APPROXCOEFF[2] = coeff(2); +// BESSEL_APPROXCOEFF[3] = coeff(3); +// BESSEL_APPROXCOEFF[0] = -0.1714; +// BESSEL_APPROXCOEFF[1] = 0.5332; +// BESSEL_APPROXCOEFF[2] = -1.4889; +// BESSEL_APPROXCOEFF[3] = 2.0389; +//} diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.h new file mode 100644 index 0000000000..21f72bfd26 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkEnergyComputer.h @@ -0,0 +1,84 @@ +/*=================================================================== + +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 _ENCOMP +#define _ENCOMP + +#include +#include +#include +#include +#include + +using namespace mitk; + +class MitkDiffusionImaging_EXPORT EnergyComputer +{ + +public: + + typedef itk::Vector OdfVectorType; + typedef itk::Image ItkQBallImgType; + typedef itk::Image ItkFloatImageType; + typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType; + + EnergyComputer(ItkQBallImgType* qballImage, ItkFloatImageType* mask, ParticleGrid* particleGrid, SphereInterpolator* interpolator, ItkRandGenType* randGen); + void SetParameters(float particleWeight, float particleWidth, float connectionPotential, float curvThres, float inexBalance, float particlePotential); + + // get random position inside mask + void DrawRandomPosition(vnl_vector_fixed& R); + + // external energy calculation + float ComputeExternalEnergy(vnl_vector_fixed& R, vnl_vector_fixed& N, Particle* dp); + + // internal energy calculation + float ComputeInternalEnergyConnection(Particle *p1,int ep1); + float ComputeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2); + float ComputeInternalEnergy(Particle *dp); + +protected: + + vnl_matrix_fixed m_RotationMatrix; + SphereInterpolator* m_SphereInterpolator; + ParticleGrid* m_ParticleGrid; + ItkRandGenType* m_RandGen; + ItkQBallImgType* m_Image; + ItkFloatImageType* m_Mask; + vnl_vector_fixed m_Size; + vnl_vector_fixed m_Spacing; + std::vector< float > m_CumulatedSpatialProbability; + std::vector< int > m_ActiveIndices; // indices inside mask + + bool m_UseTrilinearInterpolation; // is deactivated if less than 3 image slices are available + int m_NumActiveVoxels; // voxels inside mask + float m_ConnectionPotential; // larger value results in larger energy value -> higher proposal acceptance probability + float m_ParticleChemicalPotential; // larger value results in larger energy value -> higher proposal acceptance probability + float gamma_s; + float gamma_reg_s; + float m_ParticleWeight; // defines how much one particle contributes to the artificial signal + float m_ExtStrength; + float m_IntStrength; + float m_ParticleLength; + float m_SquaredParticleLength; + float m_CurvatureThreshold; + + float SpatProb(vnl_vector_fixed pos); + float EvaluateOdf(vnl_vector_fixed &pos, vnl_vector_fixed dir); + float mbesseli0(float x); + float mexp(float x); +}; + +#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.cpp new file mode 100644 index 0000000000..f5add08263 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.cpp @@ -0,0 +1,138 @@ +/*=================================================================== + +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 "mitkFiberBuilder.h" + +using namespace mitk; + +FiberBuilder::FiberBuilder(ParticleGrid* grid, ItkFloatImageType* image) +{ + m_Grid = grid; + m_Image = image; + m_FiberLength = 0; +} + +FiberBuilder::~FiberBuilder() +{ + +} + +vtkSmartPointer FiberBuilder::iterate(int minFiberLength) +{ + m_VtkCellArray = vtkSmartPointer::New(); + m_VtkPoints = vtkSmartPointer::New(); + + int cur_label = 1; + int numFibers = 0; + m_FiberLength = 0; + for (int k = 0; k < m_Grid->m_NumParticles;k++) + { + Particle *dp = m_Grid->GetParticle(k); + if (dp->label == 0) + { + vtkSmartPointer container = vtkSmartPointer::New(); + dp->label = cur_label; + LabelPredecessors(dp, -1, container); + LabelSuccessors(dp, 1, container); + cur_label++; + if(m_FiberLength >= minFiberLength) + { + m_VtkCellArray->InsertNextCell(container); + numFibers++; + } + m_FiberLength = 0; + } + } + for (int k = 0; k < m_Grid->m_NumParticles;k++) + { + Particle *dp = m_Grid->GetParticle(k); + dp->label = 0; + } + + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + fiberPolyData->SetPoints(m_VtkPoints); + fiberPolyData->SetLines(m_VtkCellArray); + return fiberPolyData; +} + +void FiberBuilder::LabelPredecessors(Particle* p, int ep, vtkPolyLine* container) +{ + Particle* p2 = NULL; + if (ep==1) + p2 = m_Grid->GetParticle(p->pID); + else + p2 = m_Grid->GetParticle(p->mID); + + if (p2!=NULL && p2->label==0) + { + p2->label = 1; // assign particle to current fiber + + if (p2->pID==p->ID) + LabelPredecessors(p2, -1, container); + else if (p2->mID==p->ID) + LabelPredecessors(p2, 1, container); + else + std::cout << "FiberBuilder: connection inconsistent (LabelPredecessors)" << std::endl; + } + + AddPoint(p, container); +} + + +void FiberBuilder::LabelSuccessors(Particle* p, int ep, vtkPolyLine* container) +{ + AddPoint(p, container); + + Particle* p2 = NULL; + if (ep==1) + p2 = m_Grid->GetParticle(p->pID); + else + p2 = m_Grid->GetParticle(p->mID); + + if (p2!=NULL && p2->label==0) + { + p2->label = 1; // assign particle to current fiber + + if (p2->pID==p->ID) + LabelSuccessors(p2, -1, container); + else if (p2->mID==p->ID) + LabelSuccessors(p2, 1, container); + else + std::cout << "FiberBuilder: connection inconsistent (LabelPredecessors)" << std::endl; + } +} + +void FiberBuilder::AddPoint(Particle *dp, vtkSmartPointer container) +{ + if (dp->label!=1) + return; + + dp->label = 2; + + itk::ContinuousIndex index; + index[0] = dp->pos[0]/m_Image->GetSpacing()[0]-0.5; + index[1] = dp->pos[1]/m_Image->GetSpacing()[1]-0.5; + index[2] = dp->pos[2]/m_Image->GetSpacing()[2]-0.5; + itk::Point point; + m_Image->TransformContinuousIndexToPhysicalPoint( index, point ); + vtkIdType id = m_VtkPoints->InsertNextPoint(point.GetDataPointer()); + container->GetPointIds()->InsertNextId(id); + + if(container->GetNumberOfPoints()>1) + m_FiberLength += m_LastPoint.EuclideanDistanceTo(point); + + m_LastPoint = point; +} diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.h new file mode 100644 index 0000000000..e30f456a4c --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkFiberBuilder.h @@ -0,0 +1,67 @@ +/*=================================================================== + +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 _BUILDFIBRES +#define _BUILDFIBRES + +// MITK +#include +#include + +// VTK +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT FiberBuilder +{ +public: + + typedef itk::Image ItkFloatImageType; + + FiberBuilder(ParticleGrid* grid, ItkFloatImageType* image); + ~FiberBuilder(); + + vtkSmartPointer iterate(int minFiberLength); + +protected: + + void AddPoint(Particle *dp, vtkSmartPointer container); + + void LabelPredecessors(Particle* p, int ep, vtkPolyLine* container); + void LabelSuccessors(Particle* p, int ep, vtkPolyLine* container); + + itk::Point m_LastPoint; + float m_FiberLength; + ItkFloatImageType::Pointer m_Image; + ParticleGrid* m_Grid; + vtkSmartPointer m_VtkCellArray; + vtkSmartPointer m_VtkPoints; + +}; + +} + +#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.cpp new file mode 100644 index 0000000000..c8c7c62d23 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.cpp @@ -0,0 +1,478 @@ +/*=================================================================== + +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 "mitkMetropolisHastingsSampler.h" + +using namespace mitk; + +MetropolisHastingsSampler::MetropolisHastingsSampler(ParticleGrid* grid, EnergyComputer* enComp, ItkRandGenType* randGen, float curvThres) + : m_AcceptedProposals(0) + , m_ExTemp(0.01) + , m_BirthProb(0.25) + , m_DeathProb(0.05) + , m_ShiftProb(0.15) + , m_OptShiftProb(0.1) + , m_ConnectionProb(0.45) + , m_TractProb(0.5) + , m_DelProb(0.1) + , m_ChempotParticle(0.0) +{ + m_RandGen = randGen; + m_ParticleGrid = grid; + m_EnergyComputer = enComp; + + m_ParticleLength = m_ParticleGrid->m_ParticleLength; + m_DistanceThreshold = m_ParticleLength*m_ParticleLength; + m_Sigma = m_ParticleLength/8.0; + m_Gamma = 1/(m_Sigma*m_Sigma*2); + m_Z = pow(2*M_PI*m_Sigma,3.0/2.0)*(M_PI*m_Sigma/m_ParticleLength); + + m_CurvatureThreshold = curvThres; + m_StopProb = exp(-1/m_TractProb); +} + +void MetropolisHastingsSampler::SetProbabilities(float birth, float death, float shift, float optShift, float connect) +{ + m_BirthProb = birth; + m_DeathProb = death; + m_ShiftProb = shift; + m_OptShiftProb = optShift; + m_ConnectionProb = connect; + float sum = m_BirthProb+m_DeathProb+m_ShiftProb+m_OptShiftProb+m_ConnectionProb; + if (sum!=1 && sum>mitk::eps) + { + m_BirthProb /= sum; + m_DeathProb /= sum; + m_ShiftProb /= sum; + m_OptShiftProb /= sum; + m_ConnectionProb /= sum; + } + std::cout << "Update proposal probabilities:" << std::endl; + std::cout << "Birth: " << m_BirthProb << std::endl; + std::cout << "Death: " << m_DeathProb << std::endl; + std::cout << "Shift: " << m_ShiftProb << std::endl; + std::cout << "Optimal shift: " << m_OptShiftProb << std::endl; + std::cout << "Connection: " << m_ConnectionProb << std::endl; +} + +// update temperature of simulated annealing process +void MetropolisHastingsSampler::SetTemperature(float val) +{ + m_InTemp = val; + m_Density = exp(-m_ChempotParticle/m_InTemp); +} + +// add small random number drawn from gaussian to each vector element +vnl_vector_fixed MetropolisHastingsSampler::DistortVector(float sigma, vnl_vector_fixed& vec) +{ + vec[0] += m_RandGen->GetNormalVariate(0.0, sigma); + vec[1] += m_RandGen->GetNormalVariate(0.0, sigma); + vec[2] += m_RandGen->GetNormalVariate(0.0, sigma); +} + +// generate normalized random vector +vnl_vector_fixed MetropolisHastingsSampler::GetRandomDirection() +{ + vnl_vector_fixed vec; + vec[0] = m_RandGen->GetNormalVariate(); + vec[1] = m_RandGen->GetNormalVariate(); + vec[2] = m_RandGen->GetNormalVariate(); + vec.normalize(); + return vec; +} + +// generate actual proposal (birth, death, shift and connection of particle) +void MetropolisHastingsSampler::MakeProposal() +{ + float randnum = m_RandGen->GetVariate(); + + // Birth Proposal + if (randnum < m_BirthProb) + { + vnl_vector_fixed R; + m_EnergyComputer->DrawRandomPosition(R); + vnl_vector_fixed N = GetRandomDirection(); + Particle prop; + prop.pos = R; + prop.dir = N; + + float prob = m_Density * m_DeathProb /((m_BirthProb)*(m_ParticleGrid->m_NumParticles+1)); + + float ex_energy = m_EnergyComputer->ComputeExternalEnergy(R,N,0); + float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop); + prob *= exp((in_energy/m_InTemp+ex_energy/m_ExTemp)) ; + + if (prob > 1 || m_RandGen->GetVariate() < prob) + { + Particle *p = m_ParticleGrid->NewParticle(R); + if (p!=0) + { + p->pos = R; + p->dir = N; + m_AcceptedProposals++; + } + } + } + // Death Proposal + else if (randnum < m_BirthProb+m_DeathProb) + { + if (m_ParticleGrid->m_NumParticles > 0) + { + int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; + Particle *dp = m_ParticleGrid->GetParticle(pnum); + if (dp->pID == -1 && dp->mID == -1) + { + float ex_energy = m_EnergyComputer->ComputeExternalEnergy(dp->pos,dp->dir,dp); + float in_energy = m_EnergyComputer->ComputeInternalEnergy(dp); + + float prob = m_ParticleGrid->m_NumParticles * (m_BirthProb) /(m_Density*m_DeathProb); //*SpatProb(dp->R); + prob *= exp(-(in_energy/m_InTemp+ex_energy/m_ExTemp)) ; + if (prob > 1 || m_RandGen->GetVariate() < prob) + { + m_ParticleGrid->RemoveParticle(pnum); + m_AcceptedProposals++; + } + } + } + + } + // Shift Proposal + else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb) + { + if (m_ParticleGrid->m_NumParticles > 0) + { + int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; + Particle *p = m_ParticleGrid->GetParticle(pnum); + Particle prop_p = *p; + + DistortVector(m_Sigma, prop_p.pos); + DistortVector(m_Sigma/(2*m_ParticleLength), prop_p.dir); + prop_p.dir.normalize(); + + + float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.pos,prop_p.dir,p) + - m_EnergyComputer->ComputeExternalEnergy(p->pos,p->dir,p); + float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p); + + float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp); + if (m_RandGen->GetVariate() < prob) + { + vnl_vector_fixed Rtmp = p->pos; + vnl_vector_fixed Ntmp = p->dir; + p->pos = prop_p.pos; + p->dir = prop_p.dir; + if (!m_ParticleGrid->TryUpdateGrid(pnum)) + { + p->pos = Rtmp; + p->dir = Ntmp; + } + m_AcceptedProposals++; + } + } + } + // Optimal Shift Proposal + else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb+m_OptShiftProb) + { + if (m_ParticleGrid->m_NumParticles > 0) + { + + int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; + Particle *p = m_ParticleGrid->GetParticle(pnum); + + bool no_proposal = false; + Particle prop_p = *p; + if (p->pID != -1 && p->mID != -1) + { + Particle *plus = m_ParticleGrid->GetParticle(p->pID); + int ep_plus = (plus->pID == p->ID)? 1 : -1; + Particle *minus = m_ParticleGrid->GetParticle(p->mID); + int ep_minus = (minus->pID == p->ID)? 1 : -1; + prop_p.pos = (plus->pos + plus->dir * (m_ParticleLength * ep_plus) + minus->pos + minus->dir * (m_ParticleLength * ep_minus)); + prop_p.pos *= 0.5; + prop_p.dir = plus->pos - minus->pos; + prop_p.dir.normalize(); + } + else if (p->pID != -1) + { + Particle *plus = m_ParticleGrid->GetParticle(p->pID); + int ep_plus = (plus->pID == p->ID)? 1 : -1; + prop_p.pos = plus->pos + plus->dir * (m_ParticleLength * ep_plus * 2); + prop_p.dir = plus->dir; + } + else if (p->mID != -1) + { + Particle *minus = m_ParticleGrid->GetParticle(p->mID); + int ep_minus = (minus->pID == p->ID)? 1 : -1; + prop_p.pos = minus->pos + minus->dir * (m_ParticleLength * ep_minus * 2); + prop_p.dir = minus->dir; + } + else + no_proposal = true; + + if (!no_proposal) + { + float cos = dot_product(prop_p.dir, p->dir); + float p_rev = exp(-((prop_p.pos-p->pos).squared_magnitude() + (1-cos*cos))*m_Gamma)/m_Z; + + float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.pos,prop_p.dir,p) + - m_EnergyComputer->ComputeExternalEnergy(p->pos,p->dir,p); + float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p); + + float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp)*m_ShiftProb*p_rev/(m_OptShiftProb+m_ShiftProb*p_rev); + + if (m_RandGen->GetVariate() < prob) + { + vnl_vector_fixed Rtmp = p->pos; + vnl_vector_fixed Ntmp = p->dir; + p->pos = prop_p.pos; + p->dir = prop_p.dir; + if (!m_ParticleGrid->TryUpdateGrid(pnum)) + { + p->pos = Rtmp; + p->dir = Ntmp; + } + m_AcceptedProposals++; + } + } + } + } + else + { + if (m_ParticleGrid->m_NumParticles > 0) + { + int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; + Particle *p = m_ParticleGrid->GetParticle(pnum); + + EndPoint P; + P.p = p; + P.ep = (m_RandGen->GetVariate() > 0.5)? 1 : -1; + + RemoveAndSaveTrack(P); + if (m_BackupTrack.m_Probability != 0) + { + MakeTrackProposal(P); + + float prob = (m_ProposalTrack.m_Energy-m_BackupTrack.m_Energy)/m_InTemp ; + + prob = exp(prob)*(m_BackupTrack.m_Probability * pow(m_DelProb,m_ProposalTrack.m_Length)) + /(m_ProposalTrack.m_Probability * pow(m_DelProb,m_BackupTrack.m_Length)); + if (m_RandGen->GetVariate() < prob) + { + ImplementTrack(m_ProposalTrack); + m_AcceptedProposals++; + } + else + { + ImplementTrack(m_BackupTrack); + } + } + else + ImplementTrack(m_BackupTrack); + } + } +} + +// establish connections between particles stored in input Track +void MetropolisHastingsSampler::ImplementTrack(Track &T) +{ + for (int k = 1; k < T.m_Length;k++) + m_ParticleGrid->CreateConnection(T.track[k-1].p,T.track[k-1].ep,T.track[k].p,-T.track[k].ep); +} + +// remove pending track from random particle, save it in m_BackupTrack and calculate its probability +void MetropolisHastingsSampler::RemoveAndSaveTrack(EndPoint P) +{ + EndPoint Current = P; + int cnt = 0; + float energy = 0; + float AccumProb = 1.0; + m_BackupTrack.track[cnt] = Current; + EndPoint Next; + + for (;;) + { + Next.p = 0; + if (Current.ep == 1) + { + if (Current.p->pID != -1) + { + Next.p = m_ParticleGrid->GetParticle(Current.p->pID); + Current.p->pID = -1; + m_ParticleGrid->m_NumConnections--; + } + } + else if (Current.ep == -1) + { + if (Current.p->mID != -1) + { + Next.p = m_ParticleGrid->GetParticle(Current.p->mID); + Current.p->mID = -1; + m_ParticleGrid->m_NumConnections--; + } + } + else + { fprintf(stderr,"MetropolisHastingsSampler_randshift: Connection inconsistent 3\n"); break; } + + if (Next.p == 0) // no successor + { + Next.ep = 0; // mark as empty successor + break; + } + else + { + if (Next.p->pID == Current.p->ID) + { + Next.p->pID = -1; + Next.ep = 1; + } + else if (Next.p->mID == Current.p->ID) + { + Next.p->mID = -1; + Next.ep = -1; + } + else + { fprintf(stderr,"MetropolisHastingsSampler_randshift: Connection inconsistent 4\n"); break; } + } + + ComputeEndPointProposalDistribution(Current); + AccumProb *= (m_SimpSamp.probFor(Next)); + + if (Next.p == 0) // no successor -> break + break; + + energy += m_EnergyComputer->ComputeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); + + Current = Next; + Current.ep *= -1; + cnt++; + m_BackupTrack.track[cnt] = Current; + + if (m_RandGen->GetVariate() > m_DelProb) + break; + } + m_BackupTrack.m_Energy = energy; + m_BackupTrack.m_Probability = AccumProb; + m_BackupTrack.m_Length = cnt+1; +} + +// generate new track using kind of a local tracking starting from P in the given direction, store it in m_ProposalTrack and calculate its probability +void MetropolisHastingsSampler::MakeTrackProposal(EndPoint P) +{ + EndPoint Current = P; + int cnt = 0; + float energy = 0; + float AccumProb = 1.0; + m_ProposalTrack.track[cnt++] = Current; + Current.p->label = 1; + + for (;;) + { + // next candidate is already connected + if ((Current.ep == 1 && Current.p->pID != -1) || (Current.ep == -1 && Current.p->mID != -1)) + break; + + // track too long +// if (cnt > 250) +// break; + + ComputeEndPointProposalDistribution(Current); + + int k = m_SimpSamp.draw(m_RandGen->GetVariate()); + + // stop tracking proposed + if (k==0) + break; + + EndPoint Next = m_SimpSamp.objs[k]; + float probability = m_SimpSamp.probFor(k); + + // accumulate energy and proposal distribution + energy += m_EnergyComputer->ComputeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep); + AccumProb *= probability; + + // track to next endpoint + Current = Next; + Current.ep *= -1; + + Current.p->label = 1; // put label to avoid loops + m_ProposalTrack.track[cnt++] = Current; + } + + m_ProposalTrack.m_Energy = energy; + m_ProposalTrack.m_Probability = AccumProb; + m_ProposalTrack.m_Length = cnt; + + // clear labels + for (int j = 0; j < m_ProposalTrack.m_Length;j++) + m_ProposalTrack.track[j].p->label = 0; +} + +// get neigbouring particles of P and calculate the according connection probabilities +void MetropolisHastingsSampler::ComputeEndPointProposalDistribution(EndPoint P) +{ + Particle *p = P.p; + int ep = P.ep; + + float dist,dot; + vnl_vector_fixed R = p->pos + (p->dir * (ep*m_ParticleLength) ); + m_ParticleGrid->ComputeNeighbors(R); + m_SimpSamp.clear(); + + m_SimpSamp.add(m_StopProb,EndPoint(0,0)); + + for (;;) + { + Particle *p2 = m_ParticleGrid->GetNextNeighbor(); + if (p2 == 0) break; + if (p!=p2 && p2->label == 0) + { + if (p2->mID == -1) + { + dist = (p2->pos - p2->dir * m_ParticleLength - R).squared_magnitude(); + if (dist < m_DistanceThreshold) + { + dot = dot_product(p2->dir,p->dir) * ep; + if (dot > m_CurvatureThreshold) + { + float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,-1); + m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,-1)); + } + } + } + if (p2->pID == -1) + { + dist = (p2->pos + p2->dir * m_ParticleLength - R).squared_magnitude(); + if (dist < m_DistanceThreshold) + { + dot = dot_product(p2->dir,p->dir) * (-ep); + if (dot > m_CurvatureThreshold) + { + float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,+1); + m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,+1)); + } + } + } + } + } +} + +// return number of accepted proposals +int MetropolisHastingsSampler::GetNumAcceptedProposals() +{ + return m_AcceptedProposals; +} + + diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.h new file mode 100644 index 0000000000..852fc88399 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkMetropolisHastingsSampler.h @@ -0,0 +1,98 @@ +/*=================================================================== + +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 _SAMPLER +#define _SAMPLER + +// MITK +#include +#include +#include +#include + +// ITK +#include +#include + +// MISC +#include + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT MetropolisHastingsSampler +{ +public: + + typedef itk::Image< float, 3 > ItkFloatImageType; + typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType; + + MetropolisHastingsSampler(ParticleGrid* grid, EnergyComputer* enComp, ItkRandGenType* randGen, float curvThres); + void SetTemperature(float val); + + void MakeProposal(); + int GetNumAcceptedProposals(); + void SetProbabilities(float birth, float death, float shift, float optShift, float connect); + +protected: + + // connection proposal related methods + void ImplementTrack(Track& T); + void RemoveAndSaveTrack(EndPoint P); + void MakeTrackProposal(EndPoint P); + void ComputeEndPointProposalDistribution(EndPoint P); + + // generate random vectors + vnl_vector_fixed DistortVector(float sigma, vnl_vector_fixed& vec); + vnl_vector_fixed GetRandomDirection(); + + ItkRandGenType* m_RandGen; // random generator + Track m_ProposalTrack; // stores proposal track + Track m_BackupTrack; // stores track removed for new proposal traCK + SimpSamp m_SimpSamp; // neighbouring particles and their probabilities for the local tracking + + float m_InTemp; // simulated annealing temperature + float m_ExTemp; // simulated annealing temperature + float m_Density; + + float m_BirthProb; // probability for particle birth + float m_DeathProb; // probability for particle death + float m_ShiftProb; // probability for particle shift + float m_OptShiftProb; // probability for optimal particle shift + float m_ConnectionProb; // probability for particle connection proposal + + float m_Sigma; + float m_Gamma; + float m_Z; + + float m_DistanceThreshold; // threshold for maximum distance between connected particles + float m_CurvatureThreshold; // threshold for maximum angle between connected particles + float m_TractProb; + float m_StopProb; + float m_DelProb; + float m_ParticleLength; + float m_ChempotParticle; + + ParticleGrid* m_ParticleGrid; + EnergyComputer* m_EnergyComputer; + int m_AcceptedProposals; +}; + +} + +#endif + + diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticle.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticle.h new file mode 100644 index 0000000000..14e04b2cc5 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticle.h @@ -0,0 +1,73 @@ +/*=================================================================== + +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 _PARTICLE +#define _PARTICLE + +#include +#include + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT Particle +{ +public: + + Particle() + { + label = 0; + pID = -1; + mID = -1; + } + + ~Particle() + { + } + + vnl_vector_fixed pos; // particle position (world coordinates. corner based voxels. not accounted for image rotation. + vnl_vector_fixed dir; // normalized direction vector + + int gridindex; // index in the grid where it is living + int ID; // particle ID + int pID; // successor ID + int mID; // predecessor ID + unsigned char label; // label used in the fiber building process +}; + +class MitkDiffusionImaging_EXPORT EndPoint +{ +public: + EndPoint() + {} + + EndPoint(Particle *p,int ep) + { + this->p = p; + this->ep = ep; + } + Particle *p; + int ep; + + inline bool operator==(EndPoint P) + { + return (P.p == p) && (P.ep == ep); + } +}; + +} + +#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.cpp new file mode 100644 index 0000000000..c9d08b8b3c --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.cpp @@ -0,0 +1,389 @@ +/*=================================================================== + +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 "mitkParticleGrid.h" +#include +#include + +using namespace mitk; + +ParticleGrid::ParticleGrid(ItkFloatImageType* image, float particleLength) +{ + // initialize counters + m_NumParticles = 0; + m_NumConnections = 0; + m_NumCellOverflows = 0; + m_ParticleLength = particleLength; + + // define isotropic grid from voxel spacing and particle length + float cellSize = 2*m_ParticleLength; + m_GridSize[0] = image->GetLargestPossibleRegion().GetSize()[0]*image->GetSpacing()[0]/cellSize +1; + m_GridSize[1] = image->GetLargestPossibleRegion().GetSize()[1]*image->GetSpacing()[1]/cellSize +1; + m_GridSize[2] = image->GetLargestPossibleRegion().GetSize()[2]*image->GetSpacing()[2]/cellSize +1; + m_GridScale[0] = 1/cellSize; + m_GridScale[1] = 1/cellSize; + m_GridScale[2] = 1/cellSize; + + m_CellCapacity = 1024; // maximum number of particles per grid cell + m_ContainerCapacity = 100000; // initial particle container capacity + int numCells = m_GridSize[0]*m_GridSize[1]*m_GridSize[2]; // number of grid cells + + m_Particles.resize(m_ContainerCapacity); // allocate and initialize particles + m_Grid.resize(numCells*m_CellCapacity, NULL); // allocate and initialize particle grid + m_OccupationCount.resize(numCells, 0); // allocate and initialize occupation counter array + m_NeighbourTracker.cellidx.resize(8, 0); // allocate and initialize neighbour tracker + m_NeighbourTracker.cellidx_c.resize(8, 0); + + for (int i = 0;i < m_ContainerCapacity;i++) // initialize particle IDs + m_Particles[i].ID = i; + + std::cout << "ParticleGrid: allocated " << (sizeof(Particle)*m_ContainerCapacity + sizeof(Particle*)*m_GridSize[0]*m_GridSize[1]*m_GridSize[2])/1048576 << "mb for " << m_ContainerCapacity/1000 << "k particles." << std::endl; +} + +ParticleGrid::~ParticleGrid() +{ +} + +bool ParticleGrid::ReallocateGrid() +{ + std::cout << "ParticleGrid: reallocating ..." << std::endl; + int new_capacity = m_ContainerCapacity + 100000; // increase container capacity by 100k particles + try + { + m_Particles.resize(new_capacity); // reallocate particles + + for (int i = 0; i R) +{ + if (m_NumParticles >= m_ContainerCapacity) + { + if (!ReallocateGrid()) + return NULL; + } + + int xint = int(R[0]*m_GridScale[0]); + if (xint < 0) + return NULL; + if (xint >= m_GridSize[0]) + return NULL; + int yint = int(R[1]*m_GridScale[1]); + if (yint < 0) + return NULL; + if (yint >= m_GridSize[1]) + return NULL; + int zint = int(R[2]*m_GridScale[2]); + if (zint < 0) + return NULL; + if (zint >= m_GridSize[2]) + return NULL; + + int idx = xint + m_GridSize[0]*(yint + m_GridSize[1]*zint); + if (m_OccupationCount[idx] < m_CellCapacity) + { + Particle *p = &(m_Particles[m_NumParticles]); + p->pos = R; + p->mID = -1; + p->pID = -1; + m_NumParticles++; + p->gridindex = m_CellCapacity*idx + m_OccupationCount[idx]; + m_Grid[p->gridindex] = p; + m_OccupationCount[idx]++; + return p; + } + else + { + m_NumCellOverflows++; + return NULL; + } +} + +bool ParticleGrid::TryUpdateGrid(int k) +{ + Particle* p = &(m_Particles[k]); + + int xint = int(p->pos[0]*m_GridScale[0]); + if (xint < 0) + return false; + if (xint >= m_GridSize[0]) + return false; + int yint = int(p->pos[1]*m_GridScale[1]); + if (yint < 0) + return false; + if (yint >= m_GridSize[1]) + return false; + int zint = int(p->pos[2]*m_GridScale[2]); + if (zint < 0) + return false; + if (zint >= m_GridSize[2]) + return false; + + int idx = xint + m_GridSize[0]*(yint+ zint*m_GridSize[1]); + int cellidx = p->gridindex/m_CellCapacity; + if (idx != cellidx) // cell has changed + { + + if (m_OccupationCount[idx] < m_CellCapacity) + { + // remove from old position in grid; + int grdindex = p->gridindex; + m_Grid[grdindex] = m_Grid[cellidx*m_CellCapacity + m_OccupationCount[cellidx]-1]; + m_Grid[grdindex]->gridindex = grdindex; + m_OccupationCount[cellidx]--; + + // insert at new position in grid + p->gridindex = idx*m_CellCapacity + m_OccupationCount[idx]; + m_Grid[p->gridindex] = p; + m_OccupationCount[idx]++; + return true; + } + else + { + m_NumCellOverflows++; + return false; + } + } + return true; +} + +void ParticleGrid::RemoveParticle(int k) +{ + Particle* p = &(m_Particles[k]); + int gridIndex = p->gridindex; + int cellIdx = gridIndex/m_CellCapacity; + int idx = gridIndex%m_CellCapacity; + + // remove pending connections + if (p->mID != -1) + DestroyConnection(p,-1); + if (p->pID != -1) + DestroyConnection(p,+1); + + // remove from grid + if (idx < m_OccupationCount[cellIdx]-1) + { + m_Grid[gridIndex] = m_Grid[cellIdx*m_CellCapacity+m_OccupationCount[cellIdx]-1]; + m_Grid[cellIdx*m_CellCapacity+m_OccupationCount[cellIdx]-1] = NULL; + m_Grid[gridIndex]->gridindex = gridIndex; + } + m_OccupationCount[cellIdx]--; + + // remove from container + if (k < m_NumParticles-1) + { + Particle* last = &m_Particles[m_NumParticles-1]; // last particle + + // update connections of last particle because its index is changing + if (last->mID!=-1) + { + if ( m_Particles[last->mID].mID == m_NumParticles-1 ) + m_Particles[last->mID].mID = k; + else if ( m_Particles[last->mID].pID == m_NumParticles-1 ) + m_Particles[last->mID].pID = k; + } + if (last->pID!=-1) + { + if ( m_Particles[last->pID].mID == m_NumParticles-1 ) + m_Particles[last->pID].mID = k; + else if ( m_Particles[last->pID].pID == m_NumParticles-1 ) + m_Particles[last->pID].pID = k; + } + + m_Particles[k] = m_Particles[m_NumParticles-1]; // move very last particle to empty slot + m_Particles[m_NumParticles-1].ID = m_NumParticles-1; // update ID of removed particle to match the index + m_Particles[k].ID = k; // update ID of moved particle + m_Grid[m_Particles[k].gridindex] = &m_Particles[k]; // update address of moved particle + } + m_NumParticles--; +} + +void ParticleGrid::ComputeNeighbors(vnl_vector_fixed &R) +{ + float xfrac = R[0]*m_GridScale[0]; + float yfrac = R[1]*m_GridScale[1]; + float zfrac = R[2]*m_GridScale[2]; + int xint = int(xfrac); + int yint = int(yfrac); + int zint = int(zfrac); + + int dx = -1; + if (xfrac-xint > 0.5) dx = 1; + if (xint <= 0) { xint = 0; dx = 1; } + if (xint >= m_GridSize[0]-1) { xint = m_GridSize[0]-1; dx = -1; } + + int dy = -1; + if (yfrac-yint > 0.5) dy = 1; + if (yint <= 0) {yint = 0; dy = 1; } + if (yint >= m_GridSize[1]-1) {yint = m_GridSize[1]-1; dy = -1;} + + int dz = -1; + if (zfrac-zint > 0.5) dz = 1; + if (zint <= 0) {zint = 0; dz = 1; } + if (zint >= m_GridSize[2]-1) {zint = m_GridSize[2]-1; dz = -1;} + + + m_NeighbourTracker.cellidx[0] = xint + m_GridSize[0]*(yint+zint*m_GridSize[1]); + m_NeighbourTracker.cellidx[1] = m_NeighbourTracker.cellidx[0] + dx; + m_NeighbourTracker.cellidx[2] = m_NeighbourTracker.cellidx[1] + dy*m_GridSize[0]; + m_NeighbourTracker.cellidx[3] = m_NeighbourTracker.cellidx[2] - dx; + m_NeighbourTracker.cellidx[4] = m_NeighbourTracker.cellidx[0] + dz*m_GridSize[0]*m_GridSize[1]; + m_NeighbourTracker.cellidx[5] = m_NeighbourTracker.cellidx[4] + dx; + m_NeighbourTracker.cellidx[6] = m_NeighbourTracker.cellidx[5] + dy*m_GridSize[0]; + m_NeighbourTracker.cellidx[7] = m_NeighbourTracker.cellidx[6] - dx; + + + m_NeighbourTracker.cellidx_c[0] = m_CellCapacity*m_NeighbourTracker.cellidx[0]; + m_NeighbourTracker.cellidx_c[1] = m_CellCapacity*m_NeighbourTracker.cellidx[1]; + m_NeighbourTracker.cellidx_c[2] = m_CellCapacity*m_NeighbourTracker.cellidx[2]; + m_NeighbourTracker.cellidx_c[3] = m_CellCapacity*m_NeighbourTracker.cellidx[3]; + m_NeighbourTracker.cellidx_c[4] = m_CellCapacity*m_NeighbourTracker.cellidx[4]; + m_NeighbourTracker.cellidx_c[5] = m_CellCapacity*m_NeighbourTracker.cellidx[5]; + m_NeighbourTracker.cellidx_c[6] = m_CellCapacity*m_NeighbourTracker.cellidx[6]; + m_NeighbourTracker.cellidx_c[7] = m_CellCapacity*m_NeighbourTracker.cellidx[7]; + + m_NeighbourTracker.cellcnt = 0; + m_NeighbourTracker.pcnt = 0; +} + +Particle* ParticleGrid::GetNextNeighbor() +{ + if (m_NeighbourTracker.pcnt < m_OccupationCount[m_NeighbourTracker.cellidx[m_NeighbourTracker.cellcnt]]) + { + return m_Grid[m_NeighbourTracker.cellidx_c[m_NeighbourTracker.cellcnt] + (m_NeighbourTracker.pcnt++)]; + } + else + { + for(;;) + { + m_NeighbourTracker.cellcnt++; + if (m_NeighbourTracker.cellcnt >= 8) + return 0; + if (m_OccupationCount[m_NeighbourTracker.cellidx[m_NeighbourTracker.cellcnt]] > 0) + break; + } + m_NeighbourTracker.pcnt = 1; + return m_Grid[m_NeighbourTracker.cellidx_c[m_NeighbourTracker.cellcnt]]; + } +} + +void ParticleGrid::CreateConnection(Particle *P1,int ep1, Particle *P2, int ep2) +{ + if (ep1 == -1) + P1->mID = P2->ID; + else + P1->pID = P2->ID; + + if (ep2 == -1) + P2->mID = P1->ID; + else + P2->pID = P1->ID; + + m_NumConnections++; +} + +void ParticleGrid::DestroyConnection(Particle *P1,int ep1, Particle *P2, int ep2) +{ + if (ep1 == -1) + P1->mID = -1; + else + P1->pID = -1; + + if (ep2 == -1) + P2->mID = -1; + else + P2->pID = -1; + m_NumConnections--; +} + +void ParticleGrid::DestroyConnection(Particle *P1,int ep1) +{ + + Particle *P2 = 0; + if (ep1 == 1) + { + P2 = &m_Particles[P1->pID]; + P1->pID = -1; + } + else + { + P2 = &m_Particles[P1->mID]; + P1->mID = -1; + } + + if (P2->mID == P1->ID) + P2->mID = -1; + else + P2->pID = -1; + + m_NumConnections--; +} + +bool ParticleGrid::CheckConsistency() +{ + for (int i=0; iID != i) + { + std::cout << "Particle ID error!" << std::endl; + return false; + } + + if (p->mID!=-1) + { + Particle* p2 = &m_Particles[p->mID]; + if (p2->mID!=p->ID && p2->pID!=p->ID) + { + std::cout << "Connection inconsistent!" << std::endl; + return false; + } + } + if (p->pID!=-1) + { + Particle* p2 = &m_Particles[p->pID]; + if (p2->mID!=p->ID && p2->pID!=p->ID) + { + std::cout << "Connection inconsistent!" << std::endl; + return false; + } + } + } + return true; +} diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.h new file mode 100644 index 0000000000..8d8d73e5a8 --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkParticleGrid.h @@ -0,0 +1,120 @@ +/*=================================================================== + +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 _PARTICLEGRID +#define _PARTICLEGRID + +// MITK +#include "MitkDiffusionImagingExports.h" +#include + +// ITK +#include + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT ParticleGrid +{ + +public: + + typedef itk::Image< float, 3 > ItkFloatImageType; + + int m_NumParticles; // number of particles + int m_NumConnections; // number of connections + int m_NumCellOverflows; // number of cell overflows + float m_ParticleLength; + + ParticleGrid(ItkFloatImageType* image, float particleLength); + ~ParticleGrid(); + + Particle* GetParticle(int ID); + + Particle* NewParticle(vnl_vector_fixed R); + bool TryUpdateGrid(int k); + void RemoveParticle(int k); + + void ComputeNeighbors(vnl_vector_fixed &R); + Particle* GetNextNeighbor(); + + void CreateConnection(Particle *P1,int ep1, Particle *P2, int ep2); + void DestroyConnection(Particle *P1,int ep1, Particle *P2, int ep2); + void DestroyConnection(Particle *P1,int ep1); + + bool CheckConsistency(); + +protected: + + bool ReallocateGrid(); + + std::vector< Particle* > m_Grid; // the grid + std::vector< Particle > m_Particles; // particle container + std::vector< int > m_OccupationCount; // number of particles per grid cell + + int m_ContainerCapacity; // maximal number of particles + + vnl_vector_fixed< int, 3 > m_GridSize; // grid dimensions + vnl_vector_fixed< float, 3 > m_GridScale; // scaling factor for grid + + int m_CellCapacity; // particle capacity of single cell in grid + + struct NeighborTracker // to run over the neighbors + { + std::vector< int > cellidx; + std::vector< int > cellidx_c; + int cellcnt; + int pcnt; + } m_NeighbourTracker; + +}; + +class MitkDiffusionImaging_EXPORT Track +{ +public: + std::vector< EndPoint > track; + float m_Energy; + float m_Probability; + int m_Length; + + Track() + { + track.resize(1000); + } + + ~Track(){} + + void clear() + { + m_Length = 0; + m_Energy = 0; + m_Probability = 1; + } + + bool isequal(Track& t) + { + for (int i = 0; i < m_Length;i++) + { + if (track[i].p != t.track[i].p || track[i].ep != t.track[i].ep) + return false; + } + return true; + } +}; + +} + +#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSimpSamp.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSimpSamp.h new file mode 100644 index 0000000000..acf68a767d --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSimpSamp.h @@ -0,0 +1,121 @@ +/*=================================================================== + +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 _SIMPSAMP +#define _SIMPSAMP + +#include +#include +#include + +using namespace std; + +namespace mitk +{ + +class MitkDiffusionImaging_EXPORT SimpSamp +{ + + float *P; + int cnt; + +public: + EndPoint* objs; + + + SimpSamp() + { + P = (float*) malloc(sizeof(float)*1000); + objs = (EndPoint*) malloc(sizeof(EndPoint)*1000); + } + ~SimpSamp() + { + free(P); + free(objs); + } + + inline void clear() + { + cnt = 1; + P[0] = 0; + } + + inline void add(float p, EndPoint obj) + { + P[cnt] = P[cnt-1] + p; + objs[cnt-1] = obj; + cnt++; + } + + inline int draw(float prob) + { + float r = prob*P[cnt-1]; + int j; + int rl = 1; + int rh = cnt-1; + while(rh != rl) + { + j = rl + (rh-rl)/2; + if (r < P[j]) + { + rh = j; + continue; + } + if (r > P[j]) + { + rl = j+1; + continue; + } + break; + } + return rh-1; + } + + inline EndPoint drawObj(float prob) + { + return objs[draw(prob)]; + } + + inline bool isempty() + { + if (cnt == 1) + return true; + else + return false; + } + + + float probFor(int idx) + { + return (P[idx+1]-P[idx])/P[cnt-1]; + } + + float probFor(EndPoint& t) + { + for (int i = 1; i< cnt;i++) + { + if (t == objs[i-1]) + return probFor(i-1); + } + return 0; + } +}; + +} + +#endif + + diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSphereInterpolator.h b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSphereInterpolator.h new file mode 100644 index 0000000000..385e18c3cb --- /dev/null +++ b/Modules/DiffusionImaging/Tractography/GibbsTracking/mitkSphereInterpolator.h @@ -0,0 +1,200 @@ +/*=================================================================== + +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 _SPHEREINTERPOLATOR +#define _SPHEREINTERPOLATOR + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +class MitkDiffusionImaging_EXPORT SphereInterpolator +{ + +public: + + int size; // size of LUT + int sN; // (sizeofLUT-1)/2 + int nverts; // number of data vertices + float beta; + float inva; + float b; + + float* barycoords; + int* indices; + int* idx; + float* interpw; + + SphereInterpolator() + { + if (!LoadLookuptables()) + return; + + size = 301; + sN = (size-1)/2; + nverts = QBALL_ODFSIZE; + beta = 0.5; + + inva = (sqrt(1+beta)-sqrt(beta)); + b = 1/(1-sqrt(1/beta + 1)); + } + + ~SphereInterpolator() + { + delete[] barycoords; + delete[] indices; + } + + bool LoadLookuptables() + { + std::cout << "SphereInterpolator: loading lookuptables" << std::endl; + QString applicationDir = QCoreApplication::applicationDirPath(); + applicationDir.append("/"); + mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); + applicationDir.append("../"); + mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); + applicationDir.append("../../"); + mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); + + string lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTBaryCoords.bin"); + std::ifstream BaryCoordsStream; + BaryCoordsStream.open(lutPath.c_str(), ios::in | ios::binary); + if (BaryCoordsStream.is_open()) + { + float tmp; + barycoords = new float [1630818]; + BaryCoordsStream.seekg (0, ios::beg); + for (int i=0; i<1630818; i++) + { + BaryCoordsStream.read((char *)&tmp, sizeof(tmp)); + barycoords[i] = tmp; + } + BaryCoordsStream.close(); + } + else + return false; + + ifstream IndicesStream; + lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTIndices.bin"); + IndicesStream.open(lutPath.c_str(), ios::in | ios::binary); + if (IndicesStream.is_open()) + { + int tmp; + indices = new int [1630818]; + IndicesStream.seekg (0, ios::beg); + for (int i=0; i<1630818; i++) + { + IndicesStream.read((char *)&tmp, 4); + indices[i] = tmp; + } + IndicesStream.close(); + } + else + return false; + + return true; + } + + inline void getInterpolation(vnl_vector_fixed N) + { + float nx = N[0]; + float ny = N[1]; + float nz = N[2]; + + if (nz > 0.5) + { + int x = float2int(nx); + int y = float2int(ny); + int i = 3*6*(x+y*size); // (:,1,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + if (nz < -0.5) + { + int x = float2int(nx); + int y = float2int(ny); + int i = 3*(1+6*(x+y*size)); // (:,2,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + if (nx > 0.5) + { + int z = float2int(nz); + int y = float2int(ny); + int i = 3*(2+6*(z+y*size)); // (:,2,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + if (nx < -0.5) + { + int z = float2int(nz); + int y = float2int(ny); + int i = 3*(3+6*(z+y*size)); // (:,2,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + if (ny > 0) + { + int x = float2int(nx); + int z = float2int(nz); + int i = 3*(4+6*(x+z*size)); // (:,1,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + else + { + int x = float2int(nx); + int z = float2int(nz); + int i = 3*(5+6*(x+z*size)); // (:,1,x,y) + idx = indices+i; + interpw = barycoords +i; + return; + } + + } + + + inline float invrescale(float f) + { + float x = (fabs(f)-b)*inva; + if (f>0) + return (x*x-beta); + else + return beta - x*x; + } + + inline int float2int(float x) + { + return int((invrescale(x)+1)*sN-0.5); + + } + + +}; + +#endif diff --git a/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp b/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp deleted file mode 100644 index 2a8d03222d..0000000000 --- a/Modules/DiffusionImaging/Tractography/GibbsTracking/pcRJMCMC.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/*=================================================================== - -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 __pcRJMCMC_cpp__ -#define __pcRJMCMC_cpp__ - -//#include "mex.h" -//#include "matrix.h" -#define _USE_MATH_DEFINES -#include - -#include -#include -#include - -using namespace std; - -#define float float -#define PI M_PI -//#define INFINITY 99999999999.0 - -//#define TIMING - -#ifdef TIMING - -static struct timeval timeS; - -class PropStats -{ - int N; - int accept; -public: - void clear() { N = 0; accept = 0;} - void propose() {N++;} - void accepted() {accept++;} - - void report(const char *s) - { - //mexPrintf("%s #proposals: %8.2fk acceptratio: %.2f \% \n",s,1.0*N/1000.0,100.0*accept/N); - } -}; - - -class Timing -{ -public: - Timing() { time = 0; ncalls = 0;} - void clear() {time = 0; ncalls=0;} - - - long time; - int ncalls; - - void report(const char *s) - { - //mexPrintf("%s total: %10.2fms calls: %10.1fk t/call: %10.3fms \n",s,time/1000.0,1.0*ncalls/1000.0,1.0*time/ncalls); - } - - void report_time(const char *s) - { - //mexPrintf("%s: %.2fms \n",s,time/1000.0); - } - -}; - -inline void tic(Timing *t) -{ - gettimeofday( &timeS, NULL); - t->time -= (timeS.tv_sec*1000000 + timeS.tv_usec); - t->ncalls++; -} -inline void toc(Timing *t) -{ - gettimeofday( &timeS, NULL); - t->time += (timeS.tv_sec*1000000 + timeS.tv_usec); -} - -Timing externalenergy_time; -Timing internalenergy_time; -Timing odfeval_time; -Timing total_time; - -Timing shiftproposal_time; -Timing birthproposal_time; -Timing deathproposal_time; -Timing capproposal_time; -Timing lenproposal_time; -Timing connproposal_time; - -PropStats deathstats; -PropStats birthstats; -PropStats connstats; -PropStats shiftstats; -PropStats capstats; -PropStats lenstats; - - -#endif - - - -#include "MersenneTwister.h" -MTRand mtrand; -float *BESSEL_APPROXCOEFF; - - -#include "EnergyComputer_connec.cpp" -//#include "EnergyComputer_center.cpp" -//#include "RJMCMC_singlegradprop.cpp" -#include "RJMCMC_randshift.cpp" - - -//void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) -//{ - -// if(nrhs != 7 && nrhs != 8) { - -// printf(" wrong usage!!!.\n\n"); -// return; -// } else if(nlhs>3) { -// printf("Too many output arguments\n"); -// return; -// } - -// int pcnt = 0; -// const mxArray *Points; -// Points = prhs[pcnt++]; -// int numPoints = mxGetN(Points); -// float *points = (float*) mxGetData(Points); - -// const mxArray *DataImg; -// DataImg = prhs[pcnt++]; -// float *dimg = (float*) mxGetData(DataImg); -// const int *dsize = mxGetDimensions(DataImg); - -// const mxArray *Mask; -// Mask = prhs[pcnt++]; -// float *mask = (float*) mxGetData(Mask); -// const int *dmsize = mxGetDimensions(Mask); -// int mask_oversamp_mult = dmsize[0]/dsize[1]; - - - -// const mxArray *VoxSize; -// VoxSize = prhs[pcnt++]; -// double *voxsize = (double*) mxGetPr(VoxSize); - - - -// const mxArray *Params; -// Params = prhs[pcnt++]; -// double *params = (double*) mxGetPr(Params); - -// float Temp = (float) params[0]; -// int numit = (int) params[1]; -// float conprob = (float) params[2]; -// float particle_weight = (float) params[3]; -// float particle_width = (float) params[4]; -// float particle_len = (float) params[5]; -// float chempot_connection = (float) params[6]; -// float chempot_particle = (float) params[7]; -// float inex_balance = (float) params[8]; -// float chempot2 = (float) params[9]; -// float meanval_sq = (float) params[10]; - -// const mxArray *BesselExpansion; -// BesselExpansion = prhs[pcnt++]; -// BESSEL_APPROXCOEFF = (float*) mxGetData(BesselExpansion); - - - -// // read spherical-interpolator data - -// const mxArray *sinterpstruct = prhs[pcnt++]; -// mxArray *Indices = mxGetField(sinterpstruct,0,"indices"); -// mxArray *BaryCoords = mxGetField(sinterpstruct,0,"barycoords"); -// mxArray *Beta = mxGetField(sinterpstruct,0,"beta"); -// mxArray *NumInterpPoints = mxGetField(sinterpstruct,0,"numpoints"); - -// float *indimg = (float*) mxGetData(Indices); -// const int *isize = mxGetDimensions(Indices); -// int totsz = isize[0]*isize[1]*isize[2]*isize[3]; -// int *indeximg = (int*) malloc(sizeof(int)*totsz); -// for (int k =0;k < totsz;k++) -// indeximg[k] = int(indimg[k])-1; -// float *barycoords = (float*) mxGetData(BaryCoords); -// float *beta = (float*) mxGetData(Beta); -// int nip = int(*((float*)mxGetData(NumInterpPoints))); - -// SphereInterpolator *sinterp = new SphereInterpolator(barycoords,indeximg,nip,isize[2],beta[0]); - -// double breakhandle = 0; -// const mxArray *BreakHandle; -// if (nrhs == 8) -// { -// BreakHandle = prhs[pcnt++]; -// breakhandle = *mxGetPr(BreakHandle); -// } - -// #ifdef TIMING -// externalenergy_time.clear(); -// internalenergy_time.clear(); -// odfeval_time.clear(); -// total_time.clear(); - -// shiftproposal_time.clear(); -// birthproposal_time.clear(); -// deathproposal_time.clear(); -// capproposal_time.clear(); -// lenproposal_time.clear(); -// connproposal_time.clear(); - -// deathstats.clear(); -// birthstats.clear(); -// connstats.clear(); -// shiftstats.clear(); -// capstats.clear(); -// lenstats.clear(); -// #endif - - - -// float cellsize = 2*particle_len; -// float curv_hardthres = 0.7; - -// fprintf(stderr,"setting up MH-sampler \n"); fflush(stderr); -// RJMCMC sampler(points,numPoints, dimg, dsize, voxsize, cellsize); -// fprintf(stderr,"setting up Energy-computer \n"); fflush(stderr); -// EnergyComputer encomp(dimg,dsize,voxsize,sinterp,&(sampler.pcontainer),mask,mask_oversamp_mult); - -// fprintf(stderr,"setting up parameters\n"); fflush(stderr); -// sampler.setParameters(Temp,numit,conprob,particle_len,curv_hardthres,chempot_particle); -// sampler.setEnergyComputer(&encomp); -// encomp.setParameters(particle_weight,particle_width,chempot_connection*particle_len*particle_len,particle_len,curv_hardthres,inex_balance,chempot2,meanval_sq); - -// fprintf(stderr,"starting to iterate\n"); fflush(stderr); -// sampler.iterate(breakhandle); - -// int cnt = sampler.pcontainer.pcnt; -// #ifdef TIMING -// mexPrintf("\nEnergy\n------------------------\n"); -// externalenergy_time.report("external "); -// odfeval_time.report("odfeval "); -// internalenergy_time.report("internal "); -// total_time.report_time("total energy comp. "); - -// mexPrintf("overhead for proposals und stuff:%.1fms\n", -// (total_time.time-(externalenergy_time.time+odfeval_time.time+internalenergy_time.time))/1000.0); - -// mexPrintf("\nProposals\n------------------------\n"); -// birthproposal_time.report("birth "); -// deathproposal_time.report("death "); -// shiftproposal_time.report("shift "); -// connproposal_time.report("conne "); -//// capproposal_time.report("capch "); -//// lenproposal_time.report("length "); -// mexPrintf("\n"); -// birthstats.report("birth "); -// deathstats.report("death "); -// shiftstats.report("shift "); -// connstats.report("conne "); -//// lenstats.report("length "); -//// capstats.report("capch "); -// mexPrintf("\n"); - - - -// #endif - - -// int dims[] = {sampler.attrcnt, sampler.pcontainer.pcnt}; -// plhs[0] = mxCreateNumericArray(2,dims,mxGetClassID(Points),mxfloat); -// float *npoints = (float*) mxGetData(plhs[0]); -// sampler.writeout(npoints); - - -// delete sinterp; -// free(indeximg); - - -//} - -#endif - diff --git a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp index 4ee60e05b9..38eaf77b72 100644 --- a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp +++ b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.cpp @@ -1,661 +1,324 @@ /*=================================================================== 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 "itkGibbsTrackingFilter.h" -#include - -#include -#include "itkPointShell.h" - -#include "GibbsTracking/BuildFibres.cpp" - -#pragma GCC visibility push(default) -#include -#pragma GCC visibility pop - -#include -#include -#include - -#include -#include -#include +// MITK #include -#include -#include #include +#include +#include +#include +#include +#include -struct LessDereference { - template - bool operator()(const T * lhs, const T * rhs) const { - return *lhs < *rhs; - } -}; +// ITK +#include +#include + +// MISC +#include +#include namespace itk{ -template< class TInputOdfImage, class TInputROIImage > -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::GibbsTrackingFilter(): - m_TempStart(0.1), - m_TempEnd(0.001), - m_NumIt(500000), +template< class ItkQBallImageType > +GibbsTrackingFilter< ItkQBallImageType >::GibbsTrackingFilter(): + m_StartTemperature(0.1), + m_EndTemperature(0.001), + m_Iterations(500000), m_ParticleWeight(0), m_ParticleWidth(0), m_ParticleLength(0), - m_ChempotConnection(10), - m_ChempotParticle(0), + m_ConnectionPotential(10), m_InexBalance(0), - m_Chempot2(0.2), - m_FiberLength(10), + m_ParticlePotential(0.2), + m_MinFiberLength(10), m_AbortTracking(false), m_NumConnections(0), m_NumParticles(0), m_NumAcceptedFibers(0), m_CurrentStep(0), - m_SubtractMean(true), m_BuildFibers(false), - m_Sampler(NULL), m_Steps(10), - m_Memory(0), m_ProposalAcceptance(0), - m_GfaImage(NULL), - m_CurvatureHardThreshold(0.7), - m_Meanval_sq(0.0) + m_CurvatureThreshold(0.7), + m_DuplicateImage(true), + m_RandomSeed(-1) { - //this->m_MeasurementFrame.set_identity(); - this->SetNumberOfRequiredInputs(2); //Filter needs a DWI image + a Mask Image -} - -template< class TInputOdfImage, class TInputROIImage > -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::~GibbsTrackingFilter(){ - delete BESSEL_APPROXCOEFF; - if (m_Sampler!=NULL) - delete m_Sampler; -} - -template< class TInputOdfImage, class TInputROIImage > -void -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::ComputeFiberCorrelationOriginal(){ - float bD = 15; - - vnl_matrix_fixed bDir = - *itk::PointShell >::DistributePointShell(); - - const int N = QBALL_ODFSIZE; - - vnl_matrix_fixed C = bDir.transpose()*bDir; - vnl_matrix_fixed Q = C; - for(int i=0; i P = Q*Q; - - std::vector pointer; - pointer.reserve(N*N); - double * start = C.data_block(); - double * end = start + N*N; - for (double * iter = start; iter != end; ++iter) - { - pointer.push_back(iter); - } - std::sort(pointer.begin(), pointer.end(), LessDereference()); - - vnl_vector_fixed alpha; - vnl_vector_fixed beta; - for (int i=0; i alpha_0; - vnl_vector_fixed alpha_2; - vnl_vector_fixed alpha_4; - vnl_vector_fixed alpha_6; - for(int i=0; i T; - T.set_column(0,alpha_0); - T.set_column(1,alpha_2); - T.set_column(2,alpha_4); - T.set_column(3,alpha_6); - - vnl_vector_fixed coeff = vnl_matrix_inverse(T).pinverse()*beta; - BESSEL_APPROXCOEFF = new float[4]; - BESSEL_APPROXCOEFF[0] = coeff(0); - BESSEL_APPROXCOEFF[1] = coeff(1); - BESSEL_APPROXCOEFF[2] = coeff(2); - BESSEL_APPROXCOEFF[3] = coeff(3); - -// // OLD -// BESSEL_APPROXCOEFF[0] = 0,1982; -// BESSEL_APPROXCOEFF[1] = 0.3415; -// BESSEL_APPROXCOEFF[2] = -0.9515; -// BESSEL_APPROXCOEFF[3] = 1.3423; -} -template< class TInputOdfImage, class TInputROIImage > -void -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::ComputeFiberCorrelation(){ - -// float bD = 15; - -// vnl_matrix_fixed bDir = -// *itk::PointShell >::DistributePointShell(); - -// const int N = QBALL_ODFSIZE; - -// vnl_matrix_fixed temp = bDir.transpose(); -// vnl_matrix_fixed C = temp*bDir; -// vnl_matrix_fixed Q = C; -// vnl_vector_fixed mean; -// for(int i=0; i repMean; -// for (int i=0; i P = Q*Q; - -// std::vector pointer; -// pointer.reserve(N*N); -// double * start = C.data_block(); -// double * end = start + N*N; -// for (double * iter = start; iter != end; ++iter) -// { -// pointer.push_back(iter); -// } -// std::sort(pointer.begin(), pointer.end(), LessDereference()); - -// vnl_vector_fixed alpha; -// vnl_vector_fixed beta; -// for (int i=0; im_Meanval_sq = (sum*sum)/N; - -// vnl_vector_fixed alpha_0; -// vnl_vector_fixed alpha_2; -// vnl_vector_fixed alpha_4; -// vnl_vector_fixed alpha_6; -// for(int i=0; i T; -// T.set_column(0,alpha_0); -// T.set_column(1,alpha_2); -// T.set_column(2,alpha_4); -// T.set_column(3,alpha_6); - -// vnl_vector_fixed coeff = vnl_matrix_inverse(T).pinverse()*beta; - -// MITK_INFO << "itkGibbsTrackingFilter: Bessel oefficients: " << coeff; - - BESSEL_APPROXCOEFF = new float[4]; - -// BESSEL_APPROXCOEFF[0] = coeff(0); -// BESSEL_APPROXCOEFF[1] = coeff(1); -// BESSEL_APPROXCOEFF[2] = coeff(2); -// BESSEL_APPROXCOEFF[3] = coeff(3); - BESSEL_APPROXCOEFF[0] = -0.1714; - BESSEL_APPROXCOEFF[1] = 0.5332; - BESSEL_APPROXCOEFF[2] = -1.4889; - BESSEL_APPROXCOEFF[3] = 2.0389; } -// build fibers from tracking result -template< class TInputOdfImage, class TInputROIImage > -void -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::BuildFibers(float* points, int numPoints) +template< class ItkQBallImageType > +GibbsTrackingFilter< ItkQBallImageType >::~GibbsTrackingFilter() { - double spacing[3]; - spacing[0] = m_ItkQBallImage->GetSpacing().GetElement(0); - spacing[1] = m_ItkQBallImage->GetSpacing().GetElement(1); - spacing[2] = m_ItkQBallImage->GetSpacing().GetElement(2); - - m_FiberPolyData = FiberPolyDataType::New(); - - // initialize array of particles - FiberBuilder fiberBuilder(points, numPoints, spacing, m_ItkQBallImage); - // label the particles according to fiber affiliation and return polydata - m_FiberPolyData = fiberBuilder.iterate(m_FiberLength); - m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines(); - MITK_INFO << "itkGibbsTrackingFilter: " << m_NumAcceptedFibers << " accepted"; } // fill output fiber bundle datastructure -template< class TInputOdfImage, class TInputROIImage > -typename GibbsTrackingFilter< TInputOdfImage, TInputROIImage >::FiberPolyDataType -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::GetFiberBundle() +template< class ItkQBallImageType > +typename GibbsTrackingFilter< ItkQBallImageType >::FiberPolyDataType GibbsTrackingFilter< ItkQBallImageType >::GetFiberBundle() { if (!m_AbortTracking) { m_BuildFibers = true; while (m_BuildFibers){} } return m_FiberPolyData; } -// get memory allocated for particle grid -template< class TInputOdfImage, class TInputROIImage > -float -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::GetMemoryUsage() -{ - if (m_Sampler!=NULL) - return m_Sampler->m_ParticleGrid.GetMemoryUsage(); - return 0; -} - -template< class TInputOdfImage, class TInputROIImage > +template< class ItkQBallImageType > bool -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > +GibbsTrackingFilter< ItkQBallImageType > ::EstimateParticleWeight() { MITK_INFO << "itkGibbsTrackingFilter: estimating particle weight"; typedef itk::DiffusionQballGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); - gfaFilter->SetInput(m_ItkQBallImage); + gfaFilter->SetInput(m_QBallImage); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); - m_GfaImage = gfaFilter->GetOutput(); + ItkFloatImageType::Pointer gfaImage = gfaFilter->GetOutput(); float samplingStart = 1.0; float samplingStop = 0.66; - // copy GFA image (original should not be changed) - typedef itk::ImageDuplicator< GfaImageType > DuplicateFilterType; - DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); - duplicator->SetInputImage( m_GfaImage ); - duplicator->Update(); - m_GfaImage = duplicator->GetOutput(); - - //// GFA iterator //// - typedef ImageRegionIterator< GfaImageType > GfaIteratorType; - GfaIteratorType gfaIt(m_GfaImage, m_GfaImage->GetLargestPossibleRegion() ); - - //// Mask iterator //// - typedef ImageRegionConstIterator< MaskImageType > MaskIteratorType; - MaskIteratorType maskIt(m_MaskImage, m_MaskImage->GetLargestPossibleRegion() ); - - // set unmasked region of gfa image to 0 - gfaIt.GoToBegin(); - maskIt.GoToBegin(); - while( !gfaIt.IsAtEnd() ) - { - if(maskIt.Get()<=0) - gfaIt.Set(0); - ++gfaIt; - ++maskIt; - } + // GFA iterator + typedef ImageRegionIterator< ItkFloatImageType > GfaIteratorType; + GfaIteratorType gfaIt(gfaImage, gfaImage->GetLargestPossibleRegion() ); - // rescale gfa image to [0,1] - typedef itk::RescaleIntensityImageFilter< GfaImageType, GfaImageType > RescaleFilterType; - RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); - rescaleFilter->SetInput( m_GfaImage ); - rescaleFilter->SetOutputMaximum( samplingStart ); - rescaleFilter->SetOutputMinimum( 0 ); - rescaleFilter->Update(); - m_GfaImage = rescaleFilter->GetOutput(); - gfaIt = GfaIteratorType(m_GfaImage, m_GfaImage->GetLargestPossibleRegion() ); + // Mask iterator + typedef ImageRegionConstIterator< ItkFloatImageType > MaskIteratorType; + MaskIteratorType mit(m_MaskImage, m_MaskImage->GetLargestPossibleRegion() ); - //// Input iterator //// - typedef ImageRegionConstIterator< InputQBallImageType > InputIteratorType; - InputIteratorType git(m_ItkQBallImage, m_ItkQBallImage->GetLargestPossibleRegion() ); + // Input iterator + typedef ImageRegionConstIterator< ItkQBallImageType > InputIteratorType; + InputIteratorType it(m_QBallImage, m_QBallImage->GetLargestPossibleRegion() ); float upper = 0; int count = 0; for(float thr=samplingStart; thr>samplingStop; thr-=0.01) { - git.GoToBegin(); + it.GoToBegin(); + mit.GoToBegin(); gfaIt.GoToBegin(); + while( !gfaIt.IsAtEnd() ) { - if(gfaIt.Get()>thr) + if(gfaIt.Get()>thr && mit.Get()>0) { - itk::OrientationDistributionFunction odf(git.Get().GetDataPointer()); + itk::OrientationDistributionFunction odf(it.Get().GetDataPointer()); upper += odf.GetMaxValue()-odf.GetMeanValue(); - ++count; } + ++it; + ++mit; ++gfaIt; - ++git; } } + if (count>0) upper /= count; else return false; m_ParticleWeight = upper/6; return true; } // perform global tracking -template< class TInputOdfImage, class TInputROIImage > -void -GibbsTrackingFilter< TInputOdfImage, TInputROIImage > -::GenerateData(){ - - // input qball image - m_ItkQBallImage = dynamic_cast(this->GetInput(0)); - m_NumAcceptedFibers = 0; - - // approximationscoeffizienten der - // teilchenkorrelationen im orientierungsraum - // 4er vektor - //ComputeFiberCorrelationOriginal(); - ComputeFiberCorrelation(); - - // image sizes and spacing - int qBallImageSize[4] = {QBALL_ODFSIZE, - m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(0), - m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(1), - m_ItkQBallImage->GetLargestPossibleRegion().GetSize().GetElement(2)}; - double qBallImageSpacing[3] = {m_ItkQBallImage->GetSpacing().GetElement(0),m_ItkQBallImage->GetSpacing().GetElement(1),m_ItkQBallImage->GetSpacing().GetElement(2)}; - - // make sure image has enough slices - if (qBallImageSize[1]<3 || qBallImageSize[2]<3 || qBallImageSize[3]<3) - { - MITK_INFO << "itkGibbsTrackingFilter: image size < 3 not supported"; - m_AbortTracking = true; - } - - // calculate rotation matrix - vnl_matrix_fixed directionMatrix = m_ItkQBallImage->GetDirection().GetVnlMatrix(); - vnl_vector_fixed d0 = directionMatrix.get_column(0); d0.normalize(); - vnl_vector_fixed d1 = directionMatrix.get_column(1); d1.normalize(); - vnl_vector_fixed d2 = directionMatrix.get_column(2); d2.normalize(); - directionMatrix.set_column(0, d0); - directionMatrix.set_column(1, d1); - directionMatrix.set_column(2, d2); - vnl_matrix_fixed I = directionMatrix*directionMatrix.transpose(); - if(!I.is_identity(mitk::eps)){ - MITK_INFO << "itkGibbsTrackingFilter: image direction is not a rotation matrix. Tracking not possible!"; - m_AbortTracking = true; - } - - // generate local working copy of image buffer - int bufferSize = qBallImageSize[0]*qBallImageSize[1]*qBallImageSize[2]*qBallImageSize[3]; - float* qBallImageBuffer = (float*) m_ItkQBallImage->GetBufferPointer(); - float* workingQballImage = new float[bufferSize]; - for (int i=0; i +void GibbsTrackingFilter< ItkQBallImageType >::GenerateData() +{ + // check if input is qball or tensor image and generate qball if necessary + if (m_QBallImage.IsNull() && m_TensorImage.IsNotNull()) { - float sum = 0; - for (int i=0; i0 && i%qBallImageSize[0] == 0 && i>0) - { - sum /= qBallImageSize[0]; - for (int j=i-qBallImageSize[0]; j::Pointer filter = TensorImageToQBallImageFilter::New(); + filter->SetInput( m_TensorImage ); + filter->Update(); + m_QBallImage = filter->GetOutput(); } - // mask image - int maskImageSize[3]; - float *mask; - if(m_MaskImage.IsNotNull()) - { - mask = (float*) m_MaskImage->GetBufferPointer(); - maskImageSize[0] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(0); - maskImageSize[1] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(1); - maskImageSize[2] = m_MaskImage->GetLargestPossibleRegion().GetSize().GetElement(2); - } - else - { - mask = 0; - maskImageSize[0] = qBallImageSize[1]; - maskImageSize[1] = qBallImageSize[2]; - maskImageSize[2] = qBallImageSize[3]; - } - int mask_oversamp_mult = maskImageSize[0]/qBallImageSize[1]; - - // load lookuptable - QString applicationDir = QCoreApplication::applicationDirPath(); - applicationDir.append("/"); - mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); - applicationDir.append("../"); - mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); - applicationDir.append("../../"); - mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); - - std::string lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTBaryCoords.bin"); - ifstream BaryCoords; - BaryCoords.open(lutPath.c_str(), ios::in | ios::binary); - float* coords; - if (BaryCoords.is_open()) + // generate local working copy of QBall image (if not disabled) + if (m_DuplicateImage) { - float tmp; - coords = new float [1630818]; - BaryCoords.seekg (0, ios::beg); - for (int i=0; i<1630818; i++) - { - BaryCoords.read((char *)&tmp, sizeof(tmp)); - coords[i] = tmp; - } - BaryCoords.close(); - } - else - { - MITK_INFO << "itkGibbsTrackingFilter: unable to open barycoords file"; - m_AbortTracking = true; + typedef itk::ImageDuplicator< ItkQBallImageType > DuplicateFilterType; + typename DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New(); + duplicator->SetInputImage( m_QBallImage ); + duplicator->Update(); + m_QBallImage = duplicator->GetOutput(); } - ifstream Indices; - lutPath = mitk::StandardFileLocations::GetInstance()->FindFile("FiberTrackingLUTIndices.bin"); - Indices.open(lutPath.c_str(), ios::in | ios::binary); - int* ind; - if (Indices.is_open()) - { - int tmp; - ind = new int [1630818]; - Indices.seekg (0, ios::beg); - for (int i=0; i<1630818; i++) - { - Indices.read((char *)&tmp, 4); - ind[i] = tmp; - } - Indices.close(); - } - else + // perform mean subtraction on odfs + typedef ImageRegionIterator< ItkQBallImageType > InputIteratorType; + InputIteratorType it(m_QBallImage, m_QBallImage->GetLargestPossibleRegion() ); + it.GoToBegin(); + while (!it.IsAtEnd()) { - MITK_INFO << "itkGibbsTrackingFilter: unable to open indices file"; - m_AbortTracking = true; + itk::OrientationDistributionFunction odf(it.Get().GetDataPointer()); + float mean = odf.GetMeanValue(); + odf -= mean; + it.Set(odf.GetDataPointer()); + ++it; } - // initialize sphere interpolator with lookuptables - SphereInterpolator *sinterp = new SphereInterpolator(coords, ind, QBALL_ODFSIZE, 301, 0.5); + // check if mask image is given if it needs resampling + PrepareMaskImage(); - // get paramters + // prepare parameters float minSpacing; - if(qBallImageSpacing[0]GetSpacing()[0]GetSpacing()[1] && m_QBallImage->GetSpacing()[0]GetSpacing()[2]) + minSpacing = m_QBallImage->GetSpacing()[0]; + else if (m_QBallImage->GetSpacing()[1] < m_QBallImage->GetSpacing()[2]) + minSpacing = m_QBallImage->GetSpacing()[1]; else - minSpacing = qBallImageSpacing[2]; + minSpacing = m_QBallImage->GetSpacing()[2]; if(m_ParticleLength == 0) m_ParticleLength = 1.5*minSpacing; if(m_ParticleWidth == 0) m_ParticleWidth = 0.5*minSpacing; if(m_ParticleWeight == 0) if (!EstimateParticleWeight()) { - MITK_INFO << "itkGibbsTrackingFilter: could not estimate particle weight!"; + MITK_INFO << "itkGibbsTrackingFilter: could not estimate particle weight. using default value."; m_ParticleWeight = 0.0001; } - m_CurrentStep = 0; - m_Memory = 0; - - float cellsize = 2*m_ParticleLength; - float alpha = log(m_TempEnd/m_TempStart); - m_Steps = m_NumIt/10000; + float alpha = log(m_EndTemperature/m_StartTemperature); + m_Steps = m_Iterations/10000; if (m_Steps<10) m_Steps = 10; - if (m_Steps>m_NumIt) + if (m_Steps>m_Iterations) { MITK_INFO << "itkGibbsTrackingFilter: not enough iterations!"; m_AbortTracking = true; } + if (m_CurvatureThreshold < mitk::eps) + m_CurvatureThreshold = 0; + unsigned long singleIts = (unsigned long)((1.0*m_Iterations) / (1.0*m_Steps)); + + // seed random generators + Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); + if (m_RandomSeed>-1) + randGen->SetSeed(m_RandomSeed); + + // load sphere interpolator to evaluate the ODFs + SphereInterpolator* interpolator = new SphereInterpolator(); + + // initialize the actual tracking components (ParticleGrid, Metropolis Hastings Sampler and Energy Computer) + ParticleGrid* particleGrid = new ParticleGrid(m_MaskImage, m_ParticleLength); - if (m_CurvatureHardThreshold < mitk::eps) - m_CurvatureHardThreshold = 0; - unsigned long singleIts = (unsigned long)((1.0*m_NumIt) / (1.0*m_Steps)); - - // setup metropolis hastings sampler - MITK_INFO << "itkGibbsTrackingFilter: setting up MH-sampler"; - if (m_Sampler!=NULL) - delete m_Sampler; - m_Sampler = new RJMCMC(NULL, 0, workingQballImage, qBallImageSize, qBallImageSpacing, cellsize); - - // setup energy computer - MITK_INFO << "itkGibbsTrackingFilter: setting up Energy-computer"; - EnergyComputer encomp(workingQballImage,qBallImageSize,qBallImageSpacing,sinterp,&(m_Sampler->m_ParticleGrid),mask,mask_oversamp_mult, directionMatrix); - encomp.setParameters(m_ParticleWeight,m_ParticleWidth,m_ChempotConnection*m_ParticleLength*m_ParticleLength,m_ParticleLength,m_CurvatureHardThreshold,m_InexBalance,m_Chempot2, m_Meanval_sq); - m_Sampler->SetEnergyComputer(&encomp); - m_Sampler->SetParameters(m_TempStart,singleIts,m_ParticleLength,m_CurvatureHardThreshold,m_ChempotParticle); - - - MITK_INFO << "itkGibbsTrackingFilter: Iterations: " << m_NumIt; - MITK_INFO << "itkGibbsTrackingFilter: steps: " << m_Steps; - MITK_INFO << "itkGibbsTrackingFilter: Particle weight: " << m_ParticleWeight; - MITK_INFO << "itkGibbsTrackingFilter: Particle width: " << m_ParticleWidth; - MITK_INFO << "itkGibbsTrackingFilter: Particle length: " << m_ParticleLength; - MITK_INFO << "itkGibbsTrackingFilter: Min. fiber length: " << m_ParticleLength; - MITK_INFO << "itkGibbsTrackingFilter: Start temperature: " << m_TempStart; - MITK_INFO << "itkGibbsTrackingFilter: End temperature: " << m_TempEnd; - MITK_INFO << "itkGibbsTrackingFilter: Energy balance: " << m_InexBalance; - MITK_INFO << "itkGibbsTrackingFilter: Curvature threshold: " << m_CurvatureHardThreshold; + EnergyComputer* encomp = new EnergyComputer(m_QBallImage, m_MaskImage, particleGrid, interpolator, randGen); + encomp->SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential); + + MetropolisHastingsSampler* sampler = new MetropolisHastingsSampler(particleGrid, encomp, randGen, m_CurvatureThreshold); // main loop - for( int step = 0; step < m_Steps; step++ ) + m_NumAcceptedFibers = 0; + unsigned long counter = 1; + for( m_CurrentStep = 1; m_CurrentStep <= m_Steps; m_CurrentStep++ ) { - if (m_AbortTracking) - break; - - m_CurrentStep = step+1; - float temperature = m_TempStart * exp(alpha*(((1.0)*step)/((1.0)*m_Steps))); - - m_Sampler->SetTemperature(temperature); - m_Sampler->Iterate(&m_ProposalAcceptance, &m_NumConnections, &m_NumParticles, &m_AbortTracking); - - MITK_INFO << "itkGibbsTrackingFilter: proposal acceptance: " << 100*m_ProposalAcceptance << "%"; - MITK_INFO << "itkGibbsTrackingFilter: particles: " << m_NumParticles; - MITK_INFO << "itkGibbsTrackingFilter: connections: " << m_NumConnections; - MITK_INFO << "itkGibbsTrackingFilter: progress: " << 100*(float)step/m_Steps << "%"; - - if (m_BuildFibers) - { - int numPoints = m_Sampler->m_ParticleGrid.pcnt; - float* points = new float[numPoints*m_Sampler->m_NumAttributes]; - m_Sampler->WriteOutParticles(points); - BuildFibers(points, numPoints); - delete points; - m_BuildFibers = false; - } - } + // update temperatur for simulated annealing process + float temperature = m_StartTemperature * exp(alpha*(((1.0)*m_CurrentStep)/((1.0)*m_Steps))); + sampler->SetTemperature(temperature); + + for (unsigned long i=0; iMakeProposal(); + + if (m_BuildFibers || (i==singleIts-1 && m_CurrentStep==m_Steps)) + { + m_ProposalAcceptance = (float)sampler->GetNumAcceptedProposals()/counter; + m_NumParticles = particleGrid->m_NumParticles; + m_NumConnections = particleGrid->m_NumConnections; + + FiberBuilder fiberBuilder(particleGrid, m_MaskImage); + m_FiberPolyData = fiberBuilder.iterate(m_MinFiberLength); + m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines(); + m_BuildFibers = false; + } + counter++; + } + + m_ProposalAcceptance = (float)sampler->GetNumAcceptedProposals()/counter; + m_NumParticles = particleGrid->m_NumParticles; + m_NumConnections = particleGrid->m_NumConnections; - int numPoints = m_Sampler->m_ParticleGrid.pcnt; - float* points = new float[numPoints*m_Sampler->m_NumAttributes]; - m_Sampler->WriteOutParticles(points); - BuildFibers(points, numPoints); - delete points; + MITK_INFO << "itkGibbsTrackingFilter: proposal acceptance: " << 100*m_ProposalAcceptance << "%"; + MITK_INFO << "itkGibbsTrackingFilter: particles: " << m_NumParticles; + MITK_INFO << "itkGibbsTrackingFilter: connections: " << m_NumConnections; + MITK_INFO << "itkGibbsTrackingFilter: progress: " << 100*(float)m_CurrentStep/m_Steps << "%"; + MITK_INFO << "----------------------------------------"; - delete sinterp; - delete coords; - delete ind; - delete workingQballImage; + if (m_AbortTracking) + break; + } + + delete sampler; + delete encomp; + delete interpolator; + delete particleGrid; m_AbortTracking = true; m_BuildFibers = false; MITK_INFO << "itkGibbsTrackingFilter: done generate data"; } + +template< class ItkQBallImageType > +void GibbsTrackingFilter< ItkQBallImageType >::PrepareMaskImage() +{ + if(m_MaskImage.IsNull()) + { + MITK_INFO << "itkGibbsTrackingFilter: generating default mask image"; + m_MaskImage = ItkFloatImageType::New(); + m_MaskImage->SetSpacing( m_QBallImage->GetSpacing() ); + m_MaskImage->SetOrigin( m_QBallImage->GetOrigin() ); + m_MaskImage->SetDirection( m_QBallImage->GetDirection() ); + m_MaskImage->SetRegions( m_QBallImage->GetLargestPossibleRegion() ); + m_MaskImage->Allocate(); + m_MaskImage->FillBuffer(1.0); + } + else if ( m_MaskImage->GetLargestPossibleRegion().GetSize()[0]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[0] || + m_MaskImage->GetLargestPossibleRegion().GetSize()[1]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[1] || + m_MaskImage->GetLargestPossibleRegion().GetSize()[2]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[2] || + m_MaskImage->GetSpacing()[0]!=m_QBallImage->GetSpacing()[0] || + m_MaskImage->GetSpacing()[1]!=m_QBallImage->GetSpacing()[1] || + m_MaskImage->GetSpacing()[2]!=m_QBallImage->GetSpacing()[2] ) + { + MITK_INFO << "itkGibbsTrackingFilter: resampling mask image"; + typedef itk::ResampleImageFilter< ItkFloatImageType, ItkFloatImageType, float > ResamplerType; + ResamplerType::Pointer resampler = ResamplerType::New(); + resampler->SetOutputSpacing( m_QBallImage->GetSpacing() ); + resampler->SetOutputOrigin( m_QBallImage->GetOrigin() ); + resampler->SetOutputDirection( m_QBallImage->GetDirection() ); + resampler->SetSize( m_QBallImage->GetLargestPossibleRegion().GetSize() ); + + resampler->SetInput( m_MaskImage ); + resampler->SetDefaultPixelValue(1.0); + resampler->Update(); + m_MaskImage = resampler->GetOutput(); + MITK_INFO << "itkGibbsTrackingFilter: resampling finished"; + } +} + } diff --git a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h index bfc43e1b10..4809a06159 100644 --- a/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h +++ b/Modules/DiffusionImaging/Tractography/itkGibbsTrackingFilter.h @@ -1,197 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +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 +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 itkGibbsTrackingFilter_h #define itkGibbsTrackingFilter_h -#include "itkProcessObject.h" -#include "itkVectorContainer.h" -#include "itkImage.h" +// MITK +#include -#include "GibbsTracking/pcRJMCMC.cpp" -#include "GibbsTracking/auxilary_classes.cpp" +// ITK +#include +#include +#include +#include -#include -#include +// VTK #include #include #include #include #include namespace itk{ - template< class TInputQBallImage, class TInputROIImage > - class GibbsTrackingFilter : - public ProcessObject{ - public: +template< class ItkQBallImageType > +class GibbsTrackingFilter : public ProcessObject +{ +public: typedef GibbsTrackingFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; - itkNewMacro(Self); - itkTypeMacro( GibbsTrackingFilter, ProcessObject ); + itkNewMacro(Self) + itkTypeMacro( GibbsTrackingFilter, ProcessObject ) + + typedef Image< DiffusionTensor3D, 3 > ItkTensorImage; + typedef typename ItkQBallImageType::Pointer ItkQBallImageTypePointer; + typedef Image< float, 3 > ItkFloatImageType; + typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType; + + // parameter setter + itkSetMacro( StartTemperature, float ) + itkSetMacro( EndTemperature, float ) + itkSetMacro( Iterations, unsigned long ) + itkSetMacro( ParticleWeight, float ) + itkSetMacro( ParticleWidth, float ) + itkSetMacro( ParticleLength, float ) + itkSetMacro( ConnectionPotential, float ) + itkSetMacro( InexBalance, float ) + itkSetMacro( ParticlePotential, float ) + itkSetMacro( MinFiberLength, int ) + itkSetMacro( AbortTracking, bool ) + itkSetMacro( CurvatureThreshold, float) + itkSetMacro( DuplicateImage, bool ) + itkSetMacro( RandomSeed, int ) + + // getter + itkGetMacro( ParticleWeight, float ) + itkGetMacro( ParticleWidth, float ) + itkGetMacro( ParticleLength, float ) + itkGetMacro( CurrentStep, unsigned long ) + itkGetMacro( NumParticles, int ) + itkGetMacro( NumConnections, int ) + itkGetMacro( NumAcceptedFibers, int ) + itkGetMacro( ProposalAcceptance, float ) + itkGetMacro( Steps, unsigned int) + + // input data + itkSetMacro(QBallImage, typename ItkQBallImageType::Pointer) + itkSetMacro(MaskImage, ItkFloatImageType::Pointer) + itkSetMacro(TensorImage, ItkTensorImage::Pointer) - /** Types for the DWI Input Image **/ - typedef TInputQBallImage InputQBallImageType; - - /** Types for the Mask Image **/ - typedef TInputROIImage MaskImageType; - typedef typename MaskImageType::Pointer MaskImageTypePointer; - - typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType; - - typedef Image< float, 3 > GfaImageType; - typedef typename GfaImageType::Pointer GfaImageTypePointer; - - itkSetMacro( TempStart, float ); - itkGetMacro( TempStart, float ); - - itkSetMacro( TempEnd, float ); - itkGetMacro( TempEnd, float ); - - itkSetMacro( NumIt, unsigned long ); - itkGetMacro( NumIt, unsigned long ); - - itkSetMacro( ParticleWeight, float ); - itkGetMacro( ParticleWeight, float ); - - /** width of particle sigma (std-dev of gaussian around center) **/ - itkSetMacro( ParticleWidth, float ); - itkGetMacro( ParticleWidth, float ); - - /** length of particle from midpoint to ends **/ - itkSetMacro( ParticleLength, float ); - itkGetMacro( ParticleLength, float ); - - itkSetMacro( ChempotConnection, float ); - itkGetMacro( ChempotConnection, float ); - - itkSetMacro( ChempotParticle, float ); - itkGetMacro( ChempotParticle, float ); - - itkSetMacro( InexBalance, float ); - itkGetMacro( InexBalance, float ); - - itkSetMacro( Chempot2, float ); - itkGetMacro( Chempot2, float ); - - itkSetMacro( FiberLength, int ); - itkGetMacro( FiberLength, int ); - - itkSetMacro( AbortTracking, bool ); - itkGetMacro( AbortTracking, bool ); - - itkSetMacro( CurrentStep, unsigned long ); - itkGetMacro( CurrentStep, unsigned long ); - - itkSetMacro( SubtractMean, bool); - itkGetMacro( SubtractMean, bool); - - itkSetMacro( CurvatureHardThreshold, float); - itkGetMacro( CurvatureHardThreshold, float); - - /** Set/Get the Odf Input Image **/ - itkSetInputMacro(OdfImage, InputQBallImageType, 0); - itkGetInputMacro(OdfImage, InputQBallImageType, 0); - - /** Set/Get the Input mask image **/ - itkSetMacro(MaskImage, MaskImageTypePointer); - itkGetMacro(MaskImage, MaskImageTypePointer); - - itkSetMacro(GfaImage, GfaImageTypePointer); - itkGetMacro(GfaImage, GfaImageTypePointer); - - itkGetMacro(NumParticles, unsigned long); - itkGetMacro(NumConnections, unsigned long); - itkGetMacro(NumAcceptedFibers, int); - itkGetMacro(ProposalAcceptance, float); - itkGetMacro(Steps, unsigned int); - - /** Entry Point For the Algorithm: Is invoked when Update() is called - either directly or through itk pipeline propagation - **/ void GenerateData(); - /** override the Process Object Update because we don't have a - dataobject as an outpgnome themeut. We can change this later by wrapping the - tractcontainer in a dataobject decorator and letting the Superclass - know about it. - **/ - struct StochasticTractGenerationCallbackStruct{ - Pointer Filter; - }; - virtual void Update(){ - this->GenerateData(); + this->GenerateData(); } FiberPolyDataType GetFiberBundle(); - float GetMemoryUsage(); - bool EstimateParticleWeight(); - protected: +protected: GibbsTrackingFilter(); virtual ~GibbsTrackingFilter(); - - void ComputeFiberCorrelation(); - void ComputeFiberCorrelationOriginal(); - - void BuildFibers(float* points, int numPoints); + bool EstimateParticleWeight(); + void PrepareMaskImage(); // Input Images - typename InputQBallImageType::Pointer m_ItkQBallImage; - typename MaskImageType::Pointer m_MaskImage; - typename GfaImageType::Pointer m_GfaImage; + typename ItkQBallImageType::Pointer m_QBallImage; + typename ItkFloatImageType::Pointer m_MaskImage; + typename ItkTensorImage::Pointer m_TensorImage; // Tracking parameters - float m_TempStart; // Start temperature - float m_TempEnd; // End temperature - unsigned long m_NumIt; // Total number of iterations - unsigned long m_CurrentStep; // current tracking step - float m_ParticleWeight; //w (unitless) - float m_ParticleWidth; //sigma (mm) - float m_ParticleLength; // ell (mm) - float m_ChempotConnection; // gross L (chemisches potential) - float m_ChempotParticle;// unbenutzt (immer null, wenn groesser dann insgesamt weniger teilchen) - float m_InexBalance; // gewichtung zwischen den lambdas - // -5 ... 5 -> nur intern ... nur extern,default 0 - float m_Chempot2; // typischerweise 0, - // korrektur fuer das geschaetzte integral - int m_FiberLength; - bool m_AbortTracking; - bool m_SubtractMean; - int m_NumAcceptedFibers; - volatile bool m_BuildFibers; - unsigned int m_Steps; - float m_Memory; - float m_ProposalAcceptance; - float m_CurvatureHardThreshold; - float m_Meanval_sq; - - RJMCMC* m_Sampler; - FiberPolyDataType m_FiberPolyData; - unsigned long m_NumParticles; - unsigned long m_NumConnections; - }; + float m_StartTemperature; // Start temperature + float m_EndTemperature; // End temperature + unsigned long m_Iterations; // Total number of iterations + unsigned long m_CurrentStep; // current tracking step + float m_ParticleWeight; // w (unitless) + float m_ParticleWidth; // sigma (mm) + float m_ParticleLength; // l (mm) + float m_ConnectionPotential; // gross L (chemisches potential, default 10) + float m_InexBalance; // gewichtung zwischen den lambdas; -5 ... 5 -> nur intern ... nur extern,default 0 + float m_ParticlePotential; // default 0.2 + int m_MinFiberLength; // discard all fibers shortan than the specified length in mm + bool m_AbortTracking; // set flag to abort tracking + int m_NumAcceptedFibers; // number of reconstructed fibers generated by the FiberBuilder + volatile bool m_BuildFibers; // set flag to generate fibers from particle grid + unsigned int m_Steps; // number of temperature decrease steps + float m_ProposalAcceptance; // proposal acceptance rate (0-1) + float m_CurvatureThreshold; // curvature threshold in radians (1 -> no curvature is accepted, -1 all curvature angles are accepted) + bool m_DuplicateImage; // generates a working copy of the qball image so that the original image won't be changed by the mean subtraction + int m_NumParticles; // current number of particles in grid + int m_NumConnections; // current number of connections between particles in grid + int m_RandomSeed; // seed value for random generator (-1 for standard seeding) + + FiberPolyDataType m_FiberPolyData; // container for reconstructed fibers +}; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkGibbsTrackingFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/files.cmake b/Modules/DiffusionImaging/files.cmake index cfadef37e8..0536570f09 100644 --- a/Modules/DiffusionImaging/files.cmake +++ b/Modules/DiffusionImaging/files.cmake @@ -1,228 +1,239 @@ set(CPP_FILES # DicomImport DicomImport/mitkDicomDiffusionImageReader.cpp DicomImport/mitkGroupDiffusionHeadersFilter.cpp DicomImport/mitkDicomDiffusionImageHeaderReader.cpp DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp # DataStructures IODataStructures/mitkDiffusionImagingObjectFactory.cpp # DataStructures -> DWI IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageReader.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageIOFactory.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriterFactory.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSerializer.cpp # DataStructures -> QBall IODataStructures/QBallImages/mitkQBallImageSource.cpp IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriter.cpp IODataStructures/QBallImages/mitkNrrdQBallImageIOFactory.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriterFactory.cpp IODataStructures/QBallImages/mitkQBallImage.cpp IODataStructures/QBallImages/mitkQBallImageSerializer.cpp # DataStructures -> Tensor IODataStructures/TensorImages/mitkTensorImageSource.cpp IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp IODataStructures/TensorImages/mitkNrrdTensorImageIOFactory.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriterFactory.cpp IODataStructures/TensorImages/mitkTensorImage.cpp IODataStructures/TensorImages/mitkTensorImageSerializer.cpp # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriter.cpp IODataStructures/FiberBundleX/mitkFiberBundleXReader.cpp IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.cpp IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.cpp # DataStructures -> PlanarFigureComposite IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp # DataStructures -> Tbss IODataStructures/TbssImages/mitkTbssImageSource.cpp IODataStructures/TbssImages/mitkTbssRoiImageSource.cpp IODataStructures/TbssImages/mitkNrrdTbssImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssImageIOFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageReader.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageIOFactory.cpp IODataStructures/TbssImages/mitkTbssImage.cpp IODataStructures/TbssImages/mitkTbssRoiImage.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssImageWriterFactory.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriter.cpp IODataStructures/TbssImages/mitkNrrdTbssRoiImageWriterFactory.cpp IODataStructures/TbssImages/mitkTbssImporter.cpp # DataStructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.cpp IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.cpp # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkCompositeMapper.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp Rendering/mitkFiberBundleXMapper2D.cpp Rendering/mitkFiberBundleXMapper3D.cpp Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp Rendering/mitkTbssImageMapper.cpp Rendering/mitkPlanarCircleMapper3D.cpp Rendering/mitkPlanarPolygonMapper3D.cpp Rendering/mitkConnectomicsNetworkMapper3D.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp Algorithms/mitkTractAnalyzer.cpp # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.cpp Algorithms/Connectomics/mitkConnectomicsHistogramBase.cpp Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.cpp Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.cpp Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.cpp Algorithms/Connectomics/mitkConnectomicsHistogramCache.cpp Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp - # Tractography - Tractography/itkStochasticTractographyFilter.h + # Tractography + Tractography/GibbsTracking/mitkParticleGrid.cpp + Tractography/GibbsTracking/mitkMetropolisHastingsSampler.cpp + Tractography/GibbsTracking/mitkEnergyComputer.cpp + Tractography/GibbsTracking/mitkFiberBuilder.cpp # Function Collection mitkDiffusionFunctionCollection.cpp ) set(H_FILES # function Collection mitkDiffusionFunctionCollection.h # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkTbssImageMapper.h Rendering/mitkOdfVtkMapper2D.h Rendering/mitkFiberBundleXMapper3D.h Rendering/mitkFiberBundleXMapper2D.h Rendering/mitkFiberBundleXThreadMonitorMapper3D.h Rendering/mitkPlanarCircleMapper3D.h Rendering/mitkPlanarPolygonMapper3D.h Rendering/mitkConnectomicsNetworkMapper3D.h # Reconstruction Reconstruction/itkDiffusionQballReconstructionImageFilter.h Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h Reconstruction/itkPointShell.h Reconstruction/itkOrientationDistributionFunction.h Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h Reconstruction/itkRegularizedIVIMLocalVariationImageFilter.h Reconstruction/itkRegularizedIVIMReconstructionFilter.h Reconstruction/itkRegularizedIVIMReconstructionSingleIteration.h # IO Datastructures IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h IODataStructures/TbssImages/mitkTbssImporter.h # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.h IODataStructures/FiberBundleX/mitkFiberBundleXWriter.h IODataStructures/FiberBundleX/mitkFiberBundleXReader.h IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.h IODataStructures/FiberBundleX/mitkFiberBundleXThreadMonitor.h # Datastructures Connectomics IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetwork.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkReader.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkIOFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkSerializer.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriter.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkWriterFactory.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsNetworkDefinitions.h IODataStructures/ConnectomicsNetwork/mitkConnectomicsConstantsManager.h # Tractography Tractography/itkGibbsTrackingFilter.h Tractography/itkStochasticTractographyFilter.h Tractography/itkStreamlineTrackingFilter.h + Tractography/GibbsTracking/mitkParticle.h + Tractography/GibbsTracking/mitkParticleGrid.h + Tractography/GibbsTracking/mitkMetropolisHastingsSampler.h + Tractography/GibbsTracking/mitkSimpSamp.h + Tractography/GibbsTracking/mitkEnergyComputer.h + Tractography/GibbsTracking/mitkSphereInterpolator.h + Tractography/GibbsTracking/mitkFiberBuilder.h # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkB0ImageExtractionToSeparateImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipleDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkSkeletonizationFilter.h Algorithms/itkReduceDirectionGradientsFilter.h Algorithms/itkResidualImageFilter.h Algorithms/itkExtractChannelFromRgbaImageFilter.h + Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h # Algorithms Connectomics Algorithms/Connectomics/mitkConnectomicsNetworkCreator.h Algorithms/Connectomics/mitkConnectomicsHistogramBase.h Algorithms/Connectomics/mitkConnectomicsDegreeHistogram.h Algorithms/Connectomics/mitkConnectomicsShortestPathHistogram.h Algorithms/Connectomics/mitkConnectomicsBetweennessHistogram.h Algorithms/Connectomics/mitkConnectomicsHistogramCache.h Algorithms/Connectomics/mitkConnectomicsSyntheticNetworkGenerator.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingPermutationModularity.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingManager.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h Algorithms/Connectomics/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h - Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h + ) set( TOOL_FILES ) if(WIN32) endif(WIN32) #MITK_MULTIPLEX_PICTYPE( Algorithms/mitkImageRegistrationMethod-TYPE.cpp ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp index b1b5eb8239..84ac05dda3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.cpp @@ -1,770 +1,737 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +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 +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 "QmitkGibbsTrackingView.h" #include // Qt #include #include #include // MITK #include #include #include #include #include // ITK #include #include #include // MISC #include QmitkTrackingWorker::QmitkTrackingWorker(QmitkGibbsTrackingView* view) - : m_View(view) + : m_View(view) { } void QmitkTrackingWorker::run() { - m_View->m_GlobalTracker = QmitkGibbsTrackingView::GibbsTrackingFilterType::New(); - - MITK_INFO << "Resampling mask images"; - // setup resampler - typedef itk::ResampleImageFilter ResamplerType; - ResamplerType::Pointer resampler = ResamplerType::New(); - resampler->SetOutputSpacing( m_View->m_ItkQBallImage->GetSpacing() ); - resampler->SetOutputOrigin( m_View->m_ItkQBallImage->GetOrigin() ); - resampler->SetOutputDirection( m_View->m_ItkQBallImage->GetDirection() ); - resampler->SetSize( m_View->m_ItkQBallImage->GetLargestPossibleRegion().GetSize() ); - - // resample mask image - resampler->SetInput( m_View->m_MaskImage ); - resampler->SetDefaultPixelValue(0); - resampler->Update(); - m_View->m_MaskImage = resampler->GetOutput(); - - m_View->m_GlobalTracker->SetInput0(m_View->m_ItkQBallImage.GetPointer()); - m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage); - m_View->m_GlobalTracker->SetTempStart((float)m_View->m_Controls->m_StartTempSlider->value()/100); - m_View->m_GlobalTracker->SetTempEnd((float)m_View->m_Controls->m_EndTempSlider->value()/10000); - m_View->m_GlobalTracker->SetNumIt(m_View->m_Iterations); - m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000); - m_View->m_GlobalTracker->SetSubtractMean(m_View->m_Controls->m_MeanSubtractionCheckbox->isChecked()); - m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10); - m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10); - m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10); - m_View->m_GlobalTracker->SetFiberLength(m_View->m_Controls->m_FiberLengthSlider->value()); - m_View->m_GlobalTracker->SetCurvatureHardThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*3.14159265/180)); - - m_View->m_GlobalTracker->Update(); - m_View->m_TrackingThread.quit(); + m_View->m_GlobalTracker = QmitkGibbsTrackingView::GibbsTrackingFilterType::New(); + + m_View->m_GlobalTracker->SetQBallImage(m_View->m_ItkQBallImage); + m_View->m_GlobalTracker->SetTensorImage(m_View->m_ItkTensorImage); + m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage); + m_View->m_GlobalTracker->SetStartTemperature((float)m_View->m_Controls->m_StartTempSlider->value()/100); + m_View->m_GlobalTracker->SetEndTemperature((float)m_View->m_Controls->m_EndTempSlider->value()/10000); + m_View->m_GlobalTracker->SetIterations(m_View->m_Iterations); + m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000); + m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10); + m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10); + m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10); + m_View->m_GlobalTracker->SetMinFiberLength(m_View->m_Controls->m_FiberLengthSlider->value()); + m_View->m_GlobalTracker->SetCurvatureThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*3.14159265/180)); + + m_View->m_GlobalTracker->Update(); + m_View->m_TrackingThread.quit(); } const std::string QmitkGibbsTrackingView::VIEW_ID = -"org.mitk.views.gibbstracking"; + "org.mitk.views.gibbstracking"; QmitkGibbsTrackingView::QmitkGibbsTrackingView() - : QmitkFunctionality() - , m_Controls( 0 ) - , m_MultiWidget( NULL ) - , m_ThreadIsRunning(false) - , m_GlobalTracker(NULL) - , m_QBallImage(NULL) - , m_MaskImage(NULL) - , m_QBallImageNode(NULL) - , m_ItkQBallImage(NULL) - , m_FiberBundleNode(NULL) - , m_MaskImageNode(NULL) - , m_TrackingWorker(this) - , m_Iterations(10000000) - , m_LastStep(0) -{ - m_TrackingWorker.moveToThread(&m_TrackingThread); - connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); - connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); - connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); - connect(&m_TrackingThread, SIGNAL(terminated()), this, SLOT(AfterThread())); - m_TrackingTimer = new QTimer(this); + : QmitkFunctionality() + , m_Controls( 0 ) + , m_MultiWidget( NULL ) + , m_ThreadIsRunning(false) + , m_GlobalTracker(NULL) + , m_QBallImage(NULL) + , m_MaskImage(NULL) + , m_ImageNode(NULL) + , m_ItkQBallImage(NULL) + , m_ItkTensorImage(NULL) + , m_FiberBundleNode(NULL) + , m_MaskImageNode(NULL) + , m_TrackingWorker(this) + , m_Iterations(10000000) + , m_LastStep(0) +{ + m_TrackingWorker.moveToThread(&m_TrackingThread); + connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); + connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); + connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); + connect(&m_TrackingThread, SIGNAL(terminated()), this, SLOT(AfterThread())); + m_TrackingTimer = new QTimer(this); } QmitkGibbsTrackingView::~QmitkGibbsTrackingView() { - delete m_TrackingTimer; + delete m_TrackingTimer; } // update tracking status and generate fiber bundle void QmitkGibbsTrackingView::TimerUpdate() { - int currentStep = m_GlobalTracker->GetCurrentStep(); - mitk::ProgressBar::GetInstance()->Progress(currentStep-m_LastStep); - UpdateTrackingStatus(); - GenerateFiberBundle(false); - m_LastStep = currentStep; + int currentStep = m_GlobalTracker->GetCurrentStep(); + mitk::ProgressBar::GetInstance()->Progress(currentStep-m_LastStep); + UpdateTrackingStatus(); + GenerateFiberBundle(false); + m_LastStep = currentStep; } // tell global tractography filter to stop after current step void QmitkGibbsTrackingView::StopGibbsTracking() { - if (m_GlobalTracker.IsNull()) - return; + if (m_GlobalTracker.IsNull()) + return; - //mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); - m_GlobalTracker->SetAbortTracking(true); - m_Controls->m_TrackingStop->setEnabled(false); - m_Controls->m_TrackingStop->setText("Stopping Tractography ..."); + //mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); + m_GlobalTracker->SetAbortTracking(true); + m_Controls->m_TrackingStop->setEnabled(false); + m_Controls->m_TrackingStop->setText("Stopping Tractography ..."); } // update gui elements and generate fiber bundle after tracking is finished void QmitkGibbsTrackingView::AfterThread() { - m_ThreadIsRunning = false; - m_TrackingTimer->stop(); - - mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); - UpdateGUI(); - UpdateTrackingStatus(); - - if(m_Controls->m_ParticleWeightSlider->value()==0) - { - m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight())); - m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000); - } - if(m_Controls->m_ParticleWidthSlider->value()==0) - { - m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth())); - m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10); - } - if(m_Controls->m_ParticleLengthSlider->value()==0) - { - m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength())); - m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10); - } - - GenerateFiberBundle(true); - m_FiberBundleNode = NULL; + m_ThreadIsRunning = false; + m_TrackingTimer->stop(); + + mitk::ProgressBar::GetInstance()->Progress(m_GlobalTracker->GetSteps()-m_LastStep+1); + UpdateGUI(); + UpdateTrackingStatus(); + + if(m_Controls->m_ParticleWeightSlider->value()==0) + { + m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight())); + m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000); + } + if(m_Controls->m_ParticleWidthSlider->value()==0) + { + m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth())); + m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10); + } + if(m_Controls->m_ParticleLengthSlider->value()==0) + { + m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength())); + m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10); + } + + GenerateFiberBundle(true); + m_FiberBundleNode = NULL; } // start tracking timer and update gui elements before tracking is started void QmitkGibbsTrackingView::BeforeThread() { - m_ThreadIsRunning = true; - m_TrackingTime = QTime::currentTime(); - m_ElapsedTime = 0; - m_TrackingTimer->start(1000); - m_LastStep = 0; + m_ThreadIsRunning = true; + m_TrackingTime = QTime::currentTime(); + m_ElapsedTime = 0; + m_TrackingTimer->start(1000); + m_LastStep = 0; - UpdateGUI(); + UpdateGUI(); } // setup gui elements and signal/slot connections void QmitkGibbsTrackingView::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::QmitkGibbsTrackingViewControls; - m_Controls->setupUi( parent ); - - AdvancedSettings(); - - connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); - connect( m_Controls->m_TrackingStop, SIGNAL(clicked()), this, SLOT(StopGibbsTracking()) ); - connect( m_Controls->m_TrackingStart, SIGNAL(clicked()), this, SLOT(StartGibbsTracking()) ); - connect( m_Controls->m_AdvancedSettingsCheckbox, SIGNAL(clicked()), this, SLOT(AdvancedSettings()) ); - connect( m_Controls->m_SaveTrackingParameters, SIGNAL(clicked()), this, SLOT(SaveTrackingParameters()) ); - connect( m_Controls->m_LoadTrackingParameters, SIGNAL(clicked()), this, SLOT(LoadTrackingParameters()) ); - connect( m_Controls->m_IterationsSlider, SIGNAL(valueChanged(int)), this, SLOT(SetIterations(int)) ); - connect( m_Controls->m_ParticleWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWidth(int)) ); - connect( m_Controls->m_ParticleLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleLength(int)) ); - connect( m_Controls->m_InExBalanceSlider, SIGNAL(valueChanged(int)), this, SLOT(SetInExBalance(int)) ); - connect( m_Controls->m_FiberLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetFiberLength(int)) ); - connect( m_Controls->m_ParticleWeightSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWeight(int)) ); - connect( m_Controls->m_StartTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetStartTemp(int)) ); - connect( m_Controls->m_EndTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetEndTemp(int)) ); - connect( m_Controls->m_CurvatureThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(SetCurvatureThreshold(int)) ); - connect( m_Controls->m_OutputFileButton, SIGNAL(clicked()), this, SLOT(SetOutputFile()) ); - } + // build up qt view, unless already done + if ( !m_Controls ) + { + // create GUI widgets from the Qt Designer's .ui file + m_Controls = new Ui::QmitkGibbsTrackingViewControls; + m_Controls->setupUi( parent ); + + AdvancedSettings(); + + connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); + connect( m_Controls->m_TrackingStop, SIGNAL(clicked()), this, SLOT(StopGibbsTracking()) ); + connect( m_Controls->m_TrackingStart, SIGNAL(clicked()), this, SLOT(StartGibbsTracking()) ); + connect( m_Controls->m_AdvancedSettingsCheckbox, SIGNAL(clicked()), this, SLOT(AdvancedSettings()) ); + connect( m_Controls->m_SaveTrackingParameters, SIGNAL(clicked()), this, SLOT(SaveTrackingParameters()) ); + connect( m_Controls->m_LoadTrackingParameters, SIGNAL(clicked()), this, SLOT(LoadTrackingParameters()) ); + connect( m_Controls->m_IterationsSlider, SIGNAL(valueChanged(int)), this, SLOT(SetIterations(int)) ); + connect( m_Controls->m_ParticleWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWidth(int)) ); + connect( m_Controls->m_ParticleLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleLength(int)) ); + connect( m_Controls->m_InExBalanceSlider, SIGNAL(valueChanged(int)), this, SLOT(SetInExBalance(int)) ); + connect( m_Controls->m_FiberLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetFiberLength(int)) ); + connect( m_Controls->m_ParticleWeightSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWeight(int)) ); + connect( m_Controls->m_StartTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetStartTemp(int)) ); + connect( m_Controls->m_EndTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetEndTemp(int)) ); + connect( m_Controls->m_CurvatureThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(SetCurvatureThreshold(int)) ); + connect( m_Controls->m_OutputFileButton, SIGNAL(clicked()), this, SLOT(SetOutputFile()) ); + } } void QmitkGibbsTrackingView::SetInExBalance(int value) { - m_Controls->m_InExBalanceLabel->setText(QString::number((float)value/10)); + m_Controls->m_InExBalanceLabel->setText(QString::number((float)value/10)); } void QmitkGibbsTrackingView::SetFiberLength(int value) { - m_Controls->m_FiberLengthLabel->setText(QString::number(value)+"mm"); + m_Controls->m_FiberLengthLabel->setText(QString::number(value)+"mm"); } void QmitkGibbsTrackingView::SetParticleWeight(int value) { - if (value>0) - m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000)); - else - m_Controls->m_ParticleWeightLabel->setText("auto"); + if (value>0) + m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000)); + else + m_Controls->m_ParticleWeightLabel->setText("auto"); } void QmitkGibbsTrackingView::SetStartTemp(int value) { - m_Controls->m_StartTempLabel->setText(QString::number((float)value/100)); + m_Controls->m_StartTempLabel->setText(QString::number((float)value/100)); } void QmitkGibbsTrackingView::SetEndTemp(int value) { - m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000)); + m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000)); } void QmitkGibbsTrackingView::SetParticleWidth(int value) { - if (value>0) - m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm"); - else - m_Controls->m_ParticleWidthLabel->setText("auto"); + if (value>0) + m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm"); + else + m_Controls->m_ParticleWidthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetParticleLength(int value) { - if (value>0) - m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm"); - else - m_Controls->m_ParticleLengthLabel->setText("auto"); + if (value>0) + m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm"); + else + m_Controls->m_ParticleLengthLabel->setText("auto"); } void QmitkGibbsTrackingView::SetCurvatureThreshold(int value) { - m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°"); + m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°"); } void QmitkGibbsTrackingView::SetIterations(int value) { - switch(value) - { - case 0: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^4"); - m_Iterations = 10000; - break; - case 1: - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); - m_Iterations = 50000; - break; - case 2: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^5"); - m_Iterations = 100000; - break; - case 3: - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); - m_Iterations = 500000; - break; - case 4: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^6"); - m_Iterations = 1000000; - break; - case 5: - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); - m_Iterations = 5000000; - break; - case 6: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^7"); - m_Iterations = 10000000; - break; - case 7: - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); - m_Iterations = 50000000; - break; - case 8: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^8"); - m_Iterations = 100000000; - break; - case 9: - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); - m_Iterations = 500000000; - break; - case 10: - m_Controls->m_IterationsLabel->setText("Iterations: 1x10^9"); - m_Iterations = 1000000000; - break; - } + switch(value) + { + case 0: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^4"); + m_Iterations = 10000; + break; + case 1: + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); + m_Iterations = 50000; + break; + case 2: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^5"); + m_Iterations = 100000; + break; + case 3: + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); + m_Iterations = 500000; + break; + case 4: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^6"); + m_Iterations = 1000000; + break; + case 5: + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); + m_Iterations = 5000000; + break; + case 6: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^7"); + m_Iterations = 10000000; + break; + case 7: + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); + m_Iterations = 50000000; + break; + case 8: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^8"); + m_Iterations = 100000000; + break; + case 9: + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); + m_Iterations = 500000000; + break; + case 10: + m_Controls->m_IterationsLabel->setText("Iterations: 1x10^9"); + m_Iterations = 1000000000; + break; + } } void QmitkGibbsTrackingView::StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget) { - m_MultiWidget = &stdMultiWidget; + m_MultiWidget = &stdMultiWidget; } void QmitkGibbsTrackingView::StdMultiWidgetNotAvailable() { - m_MultiWidget = NULL; + m_MultiWidget = NULL; } // called if datamanager selection changes void QmitkGibbsTrackingView::OnSelectionChanged( std::vector nodes ) { - if (m_ThreadIsRunning) - return; + if (m_ThreadIsRunning) + return; - m_QBallImageNode = NULL; - m_MaskImageNode = NULL; - - // iterate all selected objects - for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) - { - mitk::DataNode::Pointer node = *it; + m_ImageNode = NULL; + m_MaskImageNode = NULL; - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) - m_QBallImageNode = node; - else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + // iterate all selected objects + for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { - bool isBinary = false; - node->GetPropertyValue("binary", isBinary); - if (isBinary) - m_MaskImageNode = node; + mitk::DataNode::Pointer node = *it; + + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + m_ImageNode = node; + else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + m_ImageNode = node; + else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + bool isBinary = false; + node->GetPropertyValue("binary", isBinary); + if (isBinary) + m_MaskImageNode = node; + } } - } - UpdateGUI(); + UpdateGUI(); } // update gui elements displaying trackings status void QmitkGibbsTrackingView::UpdateTrackingStatus() { - if (m_GlobalTracker.IsNull()) - return; + if (m_GlobalTracker.IsNull()) + return; - m_ElapsedTime += m_TrackingTime.elapsed()/1000; - m_TrackingTime.restart(); - unsigned long hours = m_ElapsedTime/3600; - unsigned long minutes = (m_ElapsedTime%3600)/60; - unsigned long seconds = m_ElapsedTime%60; + m_ElapsedTime += m_TrackingTime.elapsed()/1000; + m_TrackingTime.restart(); + unsigned long hours = m_ElapsedTime/3600; + unsigned long minutes = (m_ElapsedTime%3600)/60; + unsigned long seconds = m_ElapsedTime%60; - m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%"); + m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%"); - m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") ); - m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) ); - m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) ); - m_Controls->m_CurrentStepLabel->setText( QString::number(100*(float)m_GlobalTracker->GetCurrentStep()/m_GlobalTracker->GetSteps())+"%" ); - m_Controls->m_AcceptedFibersLabel->setText( QString::number(m_GlobalTracker->GetNumAcceptedFibers()) ); + m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") ); + m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) ); + m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) ); + m_Controls->m_CurrentStepLabel->setText( QString::number(100*(float)(m_GlobalTracker->GetCurrentStep()-1)/m_GlobalTracker->GetSteps())+"%" ); + m_Controls->m_AcceptedFibersLabel->setText( QString::number(m_GlobalTracker->GetNumAcceptedFibers()) ); } // update gui elements (enable/disable elements and set tooltips) void QmitkGibbsTrackingView::UpdateGUI() { - if (m_QBallImageNode.IsNotNull()) - m_Controls->m_QballImageLabel->setText(m_QBallImageNode->GetName().c_str()); - else - m_Controls->m_QballImageLabel->setText("-"); - if (m_MaskImageNode.IsNotNull()) - m_Controls->m_MaskImageLabel->setText(m_MaskImageNode->GetName().c_str()); - else - m_Controls->m_MaskImageLabel->setText("-"); - - if (!m_ThreadIsRunning && m_QBallImageNode.IsNotNull()) - { - m_Controls->m_TrackingStop->setEnabled(false); - m_Controls->m_TrackingStart->setEnabled(true); - m_Controls->m_LoadTrackingParameters->setEnabled(true); - m_Controls->m_IterationsSlider->setEnabled(true); - m_Controls->m_AdvancedFrame->setEnabled(true); - m_Controls->m_TrackingStop->setText("Stop Tractography"); - m_Controls->m_TrackingStart->setToolTip("Start tractography. No further change of parameters possible."); - m_Controls->m_TrackingStop->setToolTip(""); - } - else if (!m_ThreadIsRunning) - { - m_Controls->m_TrackingStop->setEnabled(false); - m_Controls->m_TrackingStart->setEnabled(false); - m_Controls->m_LoadTrackingParameters->setEnabled(true); - m_Controls->m_IterationsSlider->setEnabled(true); - m_Controls->m_AdvancedFrame->setEnabled(true); - m_Controls->m_TrackingStop->setText("Stop Tractography"); - m_Controls->m_TrackingStart->setToolTip("No Q-Ball image selected."); - m_Controls->m_TrackingStop->setToolTip(""); - } - else - { - m_Controls->m_TrackingStop->setEnabled(true); - m_Controls->m_TrackingStart->setEnabled(false); - m_Controls->m_LoadTrackingParameters->setEnabled(false); - m_Controls->m_IterationsSlider->setEnabled(false); - m_Controls->m_AdvancedFrame->setEnabled(false); - m_Controls->m_AdvancedFrame->setVisible(false); - m_Controls->m_AdvancedSettingsCheckbox->setChecked(false); - m_Controls->m_TrackingStart->setToolTip("Tracking in progress."); - m_Controls->m_TrackingStop->setToolTip("Stop tracking and display results."); - } + if (m_ImageNode.IsNotNull()) + m_Controls->m_QballImageLabel->setText(m_ImageNode->GetName().c_str()); + else + m_Controls->m_QballImageLabel->setText("-"); + if (m_MaskImageNode.IsNotNull()) + m_Controls->m_MaskImageLabel->setText(m_MaskImageNode->GetName().c_str()); + else + m_Controls->m_MaskImageLabel->setText("-"); + + if (!m_ThreadIsRunning && m_ImageNode.IsNotNull()) + { + m_Controls->m_TrackingStop->setEnabled(false); + m_Controls->m_TrackingStart->setEnabled(true); + m_Controls->m_LoadTrackingParameters->setEnabled(true); + m_Controls->m_IterationsSlider->setEnabled(true); + m_Controls->m_AdvancedFrame->setEnabled(true); + m_Controls->m_TrackingStop->setText("Stop Tractography"); + m_Controls->m_TrackingStart->setToolTip("Start tractography. No further change of parameters possible."); + m_Controls->m_TrackingStop->setToolTip(""); + } + else if (!m_ThreadIsRunning) + { + m_Controls->m_TrackingStop->setEnabled(false); + m_Controls->m_TrackingStart->setEnabled(false); + m_Controls->m_LoadTrackingParameters->setEnabled(true); + m_Controls->m_IterationsSlider->setEnabled(true); + m_Controls->m_AdvancedFrame->setEnabled(true); + m_Controls->m_TrackingStop->setText("Stop Tractography"); + m_Controls->m_TrackingStart->setToolTip("No Q-Ball image selected."); + m_Controls->m_TrackingStop->setToolTip(""); + } + else + { + m_Controls->m_TrackingStop->setEnabled(true); + m_Controls->m_TrackingStart->setEnabled(false); + m_Controls->m_LoadTrackingParameters->setEnabled(false); + m_Controls->m_IterationsSlider->setEnabled(false); + m_Controls->m_AdvancedFrame->setEnabled(false); + m_Controls->m_AdvancedFrame->setVisible(false); + m_Controls->m_AdvancedSettingsCheckbox->setChecked(false); + m_Controls->m_TrackingStart->setToolTip("Tracking in progress."); + m_Controls->m_TrackingStop->setToolTip("Stop tracking and display results."); + } } // show/hide advanced settings frame void QmitkGibbsTrackingView::AdvancedSettings() { - m_Controls->m_AdvancedFrame->setVisible(m_Controls->m_AdvancedSettingsCheckbox->isChecked()); + m_Controls->m_AdvancedFrame->setVisible(m_Controls->m_AdvancedSettingsCheckbox->isChecked()); } // set mask image data node void QmitkGibbsTrackingView::SetMask() { - std::vector nodes = GetDataManagerSelection(); - if (nodes.empty()) - { - m_MaskImageNode = NULL; - m_Controls->m_MaskImageLabel->setText("-"); - return; - } - - for( std::vector::iterator it = nodes.begin(); - it != nodes.end(); - ++it ) - { - mitk::DataNode::Pointer node = *it; + std::vector nodes = GetDataManagerSelection(); + if (nodes.empty()) + { + m_MaskImageNode = NULL; + m_Controls->m_MaskImageLabel->setText("-"); + return; + } - if (node.IsNotNull() && dynamic_cast(node->GetData())) + for( std::vector::iterator it = nodes.begin(); + it != nodes.end(); + ++it ) { - m_MaskImageNode = node; - m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); - return; + mitk::DataNode::Pointer node = *it; + + if (node.IsNotNull() && dynamic_cast(node->GetData())) + { + m_MaskImageNode = node; + m_Controls->m_MaskImageLabel->setText(node->GetName().c_str()); + return; + } } - } } // cast image to float template void QmitkGibbsTrackingView::CastToFloat(InputImageType* image, mitk::Image::Pointer outImage) { - typedef itk::CastImageFilter ItkCastFilter; - typename ItkCastFilter::Pointer itkCaster = ItkCastFilter::New(); - itkCaster->SetInput(image); - itkCaster->Update(); - outImage->InitializeByItk(itkCaster->GetOutput()); - outImage->SetVolume(itkCaster->GetOutput()->GetBufferPointer()); + typedef itk::CastImageFilter ItkCastFilter; + typename ItkCastFilter::Pointer itkCaster = ItkCastFilter::New(); + itkCaster->SetInput(image); + itkCaster->Update(); + outImage->InitializeByItk(itkCaster->GetOutput()); + outImage->SetVolume(itkCaster->GetOutput()->GetBufferPointer()); } // check for mask and qbi and start tracking thread void QmitkGibbsTrackingView::StartGibbsTracking() { - if(m_ThreadIsRunning) - { - MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!"; - return; - } - - if (m_QBallImageNode.IsNull()) - { - // Nothing selected. Inform the user and return - QMessageBox::information( NULL, "Warning", "Please load and select a qball image before starting image processing."); - return; - } - - // a node itself is not very useful, we need its data item (the image) - mitk::BaseData* data = m_QBallImageNode->GetData(); - if (!data) - return; - - // test if this data item is an image or not (could also be a surface or something totally different) - m_QBallImage = dynamic_cast( data ); - if (m_QBallImage.IsNull()) - return; - - // cast qbi to itk - m_ItkQBallImage = ItkQBallImgType::New(); - mitk::CastToItkImage(m_QBallImage, m_ItkQBallImage); - - // mask image found? - // catch exceptions thrown by the itkAccess macros - try{ - if(m_MaskImageNode.IsNotNull()) + if(m_ThreadIsRunning) { - m_MaskImage = 0; - if (dynamic_cast(m_MaskImageNode->GetData())) + MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!"; + return; + } - mitk::CastToItkImage(dynamic_cast(m_MaskImageNode->GetData()), - m_MaskImage); + if (m_ImageNode.IsNull()) + { + QMessageBox::information( NULL, "Warning", "Please load and select a qball image before starting image processing."); + return; } - } - catch(...) - { - QMessageBox::warning(NULL, "Warning", "Incompatible mask image chosen. Processing without masking."); - //reset mask image + + if (dynamic_cast(m_ImageNode->GetData())) + m_QBallImage = dynamic_cast(m_ImageNode->GetData()); + else if (dynamic_cast(m_ImageNode->GetData())) + m_TensorImage = dynamic_cast(m_ImageNode->GetData()); + + if (m_QBallImage.IsNull() && m_TensorImage.IsNull()) + return; + + // cast qbi to itk + m_ItkTensorImage = NULL; + m_ItkQBallImage = NULL; m_MaskImage = NULL; - } - - - // if no mask image is selected generate it - if( m_MaskImage.IsNull() ) - { - m_MaskImage = MaskImgType::New(); - m_MaskImage->SetSpacing( m_ItkQBallImage->GetSpacing() ); // Set the image spacing - m_MaskImage->SetOrigin( m_ItkQBallImage->GetOrigin() ); // Set the image origin - m_MaskImage->SetDirection( m_ItkQBallImage->GetDirection() ); // Set the image direction - m_MaskImage->SetLargestPossibleRegion( m_ItkQBallImage->GetLargestPossibleRegion()); - m_MaskImage->SetBufferedRegion( m_ItkQBallImage->GetLargestPossibleRegion() ); - m_MaskImage->Allocate(); - - itk::ImageRegionIterator it (m_MaskImage, m_MaskImage->GetLargestPossibleRegion() ); - for (it = it.Begin(); !it.IsAtEnd(); ++it) + + if (m_QBallImage.IsNotNull()) { - it.Set(1); + m_ItkQBallImage = ItkQBallImgType::New(); + mitk::CastToItkImage(m_QBallImage, m_ItkQBallImage); + } + else + { + m_ItkTensorImage = ItkTensorImage::New(); + mitk::CastToItkImage(m_TensorImage, m_ItkTensorImage); + } + + // mask image found? + // catch exceptions thrown by the itkAccess macros + try{ + if(m_MaskImageNode.IsNotNull()) + { + if (dynamic_cast(m_MaskImageNode->GetData())) + mitk::CastToItkImage(dynamic_cast(m_MaskImageNode->GetData()), m_MaskImage); + } } - } + catch(...){}; - unsigned int steps = m_Iterations/10000; - if (steps<10) - steps = 10; + unsigned int steps = m_Iterations/10000; + if (steps<10) + steps = 10; - m_LastStep = 1; - mitk::ProgressBar::GetInstance()->AddStepsToDo(steps); + m_LastStep = 1; + mitk::ProgressBar::GetInstance()->AddStepsToDo(steps); - // start worker thread - m_TrackingThread.start(QThread::LowestPriority); + // start worker thread + m_TrackingThread.start(QThread::LowestPriority); } // generate mitkFiberBundle from tracking filter output void QmitkGibbsTrackingView::GenerateFiberBundle(bool smoothFibers) { - if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning)) - return; - - if (m_Controls->m_VisualizeOnceButton->isChecked()) - m_Controls->m_VisualizeOnceButton->setChecked(false); - - vtkSmartPointer fiberBundle = m_GlobalTracker->GetFiberBundle(); - if ( fiberBundle->GetNumberOfLines()==0 ) - return; - m_FiberBundle = mitk::FiberBundleX::New(fiberBundle); - - if (smoothFibers) - m_FiberBundle->DoFiberSmoothing(10); - - if (m_FiberBundleNode.IsNotNull()){ - GetDefaultDataStorage()->Remove(m_FiberBundleNode); - m_FiberBundleNode = 0; - } - m_FiberBundleNode = mitk::DataNode::New(); - m_FiberBundleNode->SetData(m_FiberBundle); - - QString name(m_QBallImageNode->GetName().c_str()); - name += "_FiberBundle"; - m_FiberBundleNode->SetName(name.toStdString()); - m_FiberBundleNode->SetVisibility(true); - - if (!m_OutputFileName.isEmpty()) - { - QString filename = m_OutputFileName; - mitk::FiberBundleXWriter::Pointer writer = mitk::FiberBundleXWriter::New(); - writer->SetFileName(filename.toStdString()); - writer->SetInputFiberBundleX(m_FiberBundle.GetPointer()); - try - { - writer->Update(); - QMessageBox::information(NULL, "Fiber bundle saved to", filename); + if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning)) + return; + + if (m_Controls->m_VisualizeOnceButton->isChecked()) + m_Controls->m_VisualizeOnceButton->setChecked(false); + + vtkSmartPointer fiberBundle = m_GlobalTracker->GetFiberBundle(); + if ( fiberBundle->GetNumberOfLines()==0 ) + return; + m_FiberBundle = mitk::FiberBundleX::New(fiberBundle); + + if (m_FiberBundleNode.IsNotNull()){ + GetDefaultDataStorage()->Remove(m_FiberBundleNode); + m_FiberBundleNode = 0; } - catch (itk::ExceptionObject &ex) - { - QMessageBox::information(NULL, "Fiber bundle could not be saved", QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription())); + m_FiberBundleNode = mitk::DataNode::New(); + m_FiberBundleNode->SetData(m_FiberBundle); - if(m_QBallImageNode.IsNull()) - GetDataStorage()->Add(m_FiberBundleNode); - else - GetDataStorage()->Add(m_FiberBundleNode, m_QBallImageNode); + QString name(m_ImageNode->GetName().c_str()); + name += "_FiberBundle"; + m_FiberBundleNode->SetName(name.toStdString()); + m_FiberBundleNode->SetVisibility(true); + + if (!m_OutputFileName.isEmpty()) + { + QString filename = m_OutputFileName; + mitk::FiberBundleXWriter::Pointer writer = mitk::FiberBundleXWriter::New(); + writer->SetFileName(filename.toStdString()); + writer->SetInputFiberBundleX(m_FiberBundle.GetPointer()); + try + { + writer->Update(); + QMessageBox::information(NULL, "Fiber bundle saved to", filename); + } + catch (itk::ExceptionObject &ex) + { + QMessageBox::information(NULL, "Fiber bundle could not be saved", QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription())); + + if(m_ImageNode.IsNull()) + GetDataStorage()->Add(m_FiberBundleNode); + else + GetDataStorage()->Add(m_FiberBundleNode, m_ImageNode); + } + } + else { + if(m_ImageNode.IsNull()) + GetDataStorage()->Add(m_FiberBundleNode); + else + GetDataStorage()->Add(m_FiberBundleNode, m_ImageNode); } - } - else { - if(m_QBallImageNode.IsNull()) - GetDataStorage()->Add(m_FiberBundleNode); - else - GetDataStorage()->Add(m_FiberBundleNode, m_QBallImageNode); - } } void QmitkGibbsTrackingView::SetOutputFile() { - // SELECT FOLDER DIALOG - m_OutputFileName = QFileDialog::getSaveFileName(0, - tr("Set file name"), - QDir::currentPath()+"/FiberBundle.fib", - tr("Fiber Bundle (*.fib)") ); - if (m_OutputFileName.isEmpty()) - m_Controls->m_OutputFileLabel->setText("N/A"); - else - m_Controls->m_OutputFileLabel->setText(m_OutputFileName); + // SELECT FOLDER DIALOG + m_OutputFileName = QFileDialog::getSaveFileName(0, + tr("Set file name"), + QDir::currentPath()+"/FiberBundle.fib", + tr("Fiber Bundle (*.fib)") ); + if (m_OutputFileName.isEmpty()) + m_Controls->m_OutputFileLabel->setText("N/A"); + else + m_Controls->m_OutputFileLabel->setText(m_OutputFileName); } // save current tracking paramters as xml file (.gtp) void QmitkGibbsTrackingView::SaveTrackingParameters() { - TiXmlDocument documentXML; - TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); - documentXML.LinkEndChild( declXML ); - - TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); - mainXML->SetAttribute("file_version", "0.1"); - documentXML.LinkEndChild(mainXML); - - TiXmlElement* paramXML = new TiXmlElement("parameter_set"); - paramXML->SetAttribute("iterations", QString::number(m_Iterations).toStdString()); - paramXML->SetAttribute("particle_length", QString::number((float)m_Controls->m_ParticleLengthSlider->value()/10).toStdString()); - paramXML->SetAttribute("particle_width", QString::number((float)m_Controls->m_ParticleWidthSlider->value()/10).toStdString()); - paramXML->SetAttribute("particle_weight", QString::number((float)m_Controls->m_ParticleWeightSlider->value()/10000).toStdString()); - paramXML->SetAttribute("temp_start", QString::number((float)m_Controls->m_StartTempSlider->value()/100).toStdString()); - paramXML->SetAttribute("temp_end", QString::number((float)m_Controls->m_EndTempSlider->value()/10000).toStdString()); - paramXML->SetAttribute("inexbalance", QString::number((float)m_Controls->m_InExBalanceSlider->value()/10).toStdString()); - paramXML->SetAttribute("fiber_length", QString::number(m_Controls->m_FiberLengthSlider->value()).toStdString()); - paramXML->SetAttribute("curvature_threshold", QString::number(m_Controls->m_CurvatureThresholdSlider->value()).toStdString()); - mainXML->LinkEndChild(paramXML); - QString filename = QFileDialog::getSaveFileName( - 0, - tr("Save Parameters"), - QDir::currentPath()+"/param.gtp", - tr("Global Tracking Parameters (*.gtp)") ); - - if(filename.isEmpty() || filename.isNull()) - return; - if(!filename.endsWith(".gtp")) - filename += ".gtp"; - documentXML.SaveFile( filename.toStdString() ); + TiXmlDocument documentXML; + TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); + documentXML.LinkEndChild( declXML ); + + TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file"); + mainXML->SetAttribute("file_version", "0.1"); + documentXML.LinkEndChild(mainXML); + + TiXmlElement* paramXML = new TiXmlElement("parameter_set"); + paramXML->SetAttribute("iterations", QString::number(m_Iterations).toStdString()); + paramXML->SetAttribute("particle_length", QString::number((float)m_Controls->m_ParticleLengthSlider->value()/10).toStdString()); + paramXML->SetAttribute("particle_width", QString::number((float)m_Controls->m_ParticleWidthSlider->value()/10).toStdString()); + paramXML->SetAttribute("particle_weight", QString::number((float)m_Controls->m_ParticleWeightSlider->value()/10000).toStdString()); + paramXML->SetAttribute("temp_start", QString::number((float)m_Controls->m_StartTempSlider->value()/100).toStdString()); + paramXML->SetAttribute("temp_end", QString::number((float)m_Controls->m_EndTempSlider->value()/10000).toStdString()); + paramXML->SetAttribute("inexbalance", QString::number((float)m_Controls->m_InExBalanceSlider->value()/10).toStdString()); + paramXML->SetAttribute("fiber_length", QString::number(m_Controls->m_FiberLengthSlider->value()).toStdString()); + paramXML->SetAttribute("curvature_threshold", QString::number(m_Controls->m_CurvatureThresholdSlider->value()).toStdString()); + mainXML->LinkEndChild(paramXML); + QString filename = QFileDialog::getSaveFileName( + 0, + tr("Save Parameters"), + QDir::currentPath()+"/param.gtp", + tr("Global Tracking Parameters (*.gtp)") ); + + if(filename.isEmpty() || filename.isNull()) + return; + if(!filename.endsWith(".gtp")) + filename += ".gtp"; + documentXML.SaveFile( filename.toStdString() ); } void QmitkGibbsTrackingView::UpdateIteraionsGUI(unsigned long iterations) { - switch(iterations) - { - case 10000: - m_Controls->m_IterationsSlider->setValue(0); - m_Controls->m_IterationsLabel->setText("Iterations: 10^4"); - break; - case 50000: - m_Controls->m_IterationsSlider->setValue(1); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); - break; - case 100000: - m_Controls->m_IterationsSlider->setValue(2); - m_Controls->m_IterationsLabel->setText("Iterations: 10^5"); - break; - case 500000: - m_Controls->m_IterationsSlider->setValue(3); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); - break; - case 1000000: - m_Controls->m_IterationsSlider->setValue(4); - m_Controls->m_IterationsLabel->setText("Iterations: 10^6"); - break; - case 5000000: - m_Controls->m_IterationsSlider->setValue(5); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); - break; - case 10000000: - m_Controls->m_IterationsSlider->setValue(6); - m_Controls->m_IterationsLabel->setText("Iterations: 10^7"); - break; - case 50000000: - m_Controls->m_IterationsSlider->setValue(7); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); - break; - case 100000000: - m_Controls->m_IterationsSlider->setValue(8); - m_Controls->m_IterationsLabel->setText("Iterations: 10^8"); - break; - case 500000000: - m_Controls->m_IterationsSlider->setValue(9); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); - break; - case 1000000000: - m_Controls->m_IterationsSlider->setValue(10); - m_Controls->m_IterationsLabel->setText("Iterations: 10^9"); - break; - case 5000000000: - m_Controls->m_IterationsSlider->setValue(11); - m_Controls->m_IterationsLabel->setText("Iterations: 5x10^9"); - break; - } + switch(iterations) + { + case 10000: + m_Controls->m_IterationsSlider->setValue(0); + m_Controls->m_IterationsLabel->setText("Iterations: 10^4"); + break; + case 50000: + m_Controls->m_IterationsSlider->setValue(1); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^4"); + break; + case 100000: + m_Controls->m_IterationsSlider->setValue(2); + m_Controls->m_IterationsLabel->setText("Iterations: 10^5"); + break; + case 500000: + m_Controls->m_IterationsSlider->setValue(3); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^5"); + break; + case 1000000: + m_Controls->m_IterationsSlider->setValue(4); + m_Controls->m_IterationsLabel->setText("Iterations: 10^6"); + break; + case 5000000: + m_Controls->m_IterationsSlider->setValue(5); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^6"); + break; + case 10000000: + m_Controls->m_IterationsSlider->setValue(6); + m_Controls->m_IterationsLabel->setText("Iterations: 10^7"); + break; + case 50000000: + m_Controls->m_IterationsSlider->setValue(7); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^7"); + break; + case 100000000: + m_Controls->m_IterationsSlider->setValue(8); + m_Controls->m_IterationsLabel->setText("Iterations: 10^8"); + break; + case 500000000: + m_Controls->m_IterationsSlider->setValue(9); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^8"); + break; + case 1000000000: + m_Controls->m_IterationsSlider->setValue(10); + m_Controls->m_IterationsLabel->setText("Iterations: 10^9"); + break; + case 5000000000: + m_Controls->m_IterationsSlider->setValue(11); + m_Controls->m_IterationsLabel->setText("Iterations: 5x10^9"); + break; + } } // load current tracking paramters from xml file (.gtp) void QmitkGibbsTrackingView::LoadTrackingParameters() { - QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Global Tracking Parameters (*.gtp)") ); - if(filename.isEmpty() || filename.isNull()) - return; - - TiXmlDocument doc( filename.toStdString() ); - doc.LoadFile(); - - TiXmlHandle hDoc(&doc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement().Element(); - hRoot = TiXmlHandle(pElem); - pElem = hRoot.FirstChildElement("parameter_set").Element(); - - QString iterations(pElem->Attribute("iterations")); - m_Iterations = iterations.toULong(); - UpdateIteraionsGUI(m_Iterations); - - QString particleLength(pElem->Attribute("particle_length")); - float pLength = particleLength.toFloat(); - QString particleWidth(pElem->Attribute("particle_width")); - float pWidth = particleWidth.toFloat(); - - if (pLength==0) - m_Controls->m_ParticleLengthLabel->setText("auto"); - else - m_Controls->m_ParticleLengthLabel->setText(particleLength+" mm"); - if (pWidth==0) - m_Controls->m_ParticleWidthLabel->setText("auto"); - else - m_Controls->m_ParticleWidthLabel->setText(particleWidth+" mm"); - - m_Controls->m_ParticleWidthSlider->setValue(pWidth*10); - m_Controls->m_ParticleLengthSlider->setValue(pLength*10); - - QString partWeight(pElem->Attribute("particle_weight")); - m_Controls->m_ParticleWeightSlider->setValue(partWeight.toFloat()*10000); - m_Controls->m_ParticleWeightLabel->setText(partWeight); - - QString startTemp(pElem->Attribute("temp_start")); - m_Controls->m_StartTempSlider->setValue(startTemp.toFloat()*100); - m_Controls->m_StartTempLabel->setText(startTemp); - - QString endTemp(pElem->Attribute("temp_end")); - m_Controls->m_EndTempSlider->setValue(endTemp.toFloat()*10000); - m_Controls->m_EndTempLabel->setText(endTemp); - - QString inExBalance(pElem->Attribute("inexbalance")); - m_Controls->m_InExBalanceSlider->setValue(inExBalance.toFloat()*10); - m_Controls->m_InExBalanceLabel->setText(inExBalance); - - QString fiberLength(pElem->Attribute("fiber_length")); - m_Controls->m_FiberLengthSlider->setValue(fiberLength.toInt()); - m_Controls->m_FiberLengthLabel->setText(fiberLength+"mm"); - - QString curvThres(pElem->Attribute("curvature_threshold")); - m_Controls->m_CurvatureThresholdSlider->setValue(curvThres.toInt()); - m_Controls->m_CurvatureThresholdLabel->setText(curvThres+"°"); + QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Global Tracking Parameters (*.gtp)") ); + if(filename.isEmpty() || filename.isNull()) + return; + + TiXmlDocument doc( filename.toStdString() ); + doc.LoadFile(); + + TiXmlHandle hDoc(&doc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement().Element(); + hRoot = TiXmlHandle(pElem); + pElem = hRoot.FirstChildElement("parameter_set").Element(); + + QString iterations(pElem->Attribute("iterations")); + m_Iterations = iterations.toULong(); + UpdateIteraionsGUI(m_Iterations); + + QString particleLength(pElem->Attribute("particle_length")); + float pLength = particleLength.toFloat(); + QString particleWidth(pElem->Attribute("particle_width")); + float pWidth = particleWidth.toFloat(); + + if (pLength==0) + m_Controls->m_ParticleLengthLabel->setText("auto"); + else + m_Controls->m_ParticleLengthLabel->setText(particleLength+" mm"); + if (pWidth==0) + m_Controls->m_ParticleWidthLabel->setText("auto"); + else + m_Controls->m_ParticleWidthLabel->setText(particleWidth+" mm"); + + m_Controls->m_ParticleWidthSlider->setValue(pWidth*10); + m_Controls->m_ParticleLengthSlider->setValue(pLength*10); + + QString partWeight(pElem->Attribute("particle_weight")); + m_Controls->m_ParticleWeightSlider->setValue(partWeight.toFloat()*10000); + m_Controls->m_ParticleWeightLabel->setText(partWeight); + + QString startTemp(pElem->Attribute("temp_start")); + m_Controls->m_StartTempSlider->setValue(startTemp.toFloat()*100); + m_Controls->m_StartTempLabel->setText(startTemp); + + QString endTemp(pElem->Attribute("temp_end")); + m_Controls->m_EndTempSlider->setValue(endTemp.toFloat()*10000); + m_Controls->m_EndTempLabel->setText(endTemp); + + QString inExBalance(pElem->Attribute("inexbalance")); + m_Controls->m_InExBalanceSlider->setValue(inExBalance.toFloat()*10); + m_Controls->m_InExBalanceLabel->setText(inExBalance); + + QString fiberLength(pElem->Attribute("fiber_length")); + m_Controls->m_FiberLengthSlider->setValue(fiberLength.toInt()); + m_Controls->m_FiberLengthLabel->setText(fiberLength+"mm"); + + QString curvThres(pElem->Attribute("curvature_threshold")); + m_Controls->m_CurvatureThresholdSlider->setValue(curvThres.toInt()); + m_Controls->m_CurvatureThresholdLabel->setText(curvThres+"°"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h index 74776790f4..4aca41d356 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingView.h @@ -1,165 +1,168 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, +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 +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 QmitkGibbsTrackingView_h #define QmitkGibbsTrackingView_h #include #include #include "ui_QmitkGibbsTrackingViewControls.h" #include #include #include #include #include #include #include +#include +#include class QmitkGibbsTrackingView; class QmitkTrackingWorker : public QObject { Q_OBJECT public: QmitkTrackingWorker(QmitkGibbsTrackingView* view); public slots: void run(); private: QmitkGibbsTrackingView* m_View; }; /*! \brief QmitkGibbsTrackingView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. \sa QmitkFunctionality \ingroup Functionalities */ typedef itk::Image< float, 3 > FloatImageType; namespace itk { -template +template class GibbsTrackingFilter; } class QmitkGibbsTrackingView : 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 MaskImgType; - - typedef itk::Vector OdfVectorType; - typedef itk::Image ItkQBallImgType; - - typedef itk::GibbsTrackingFilter GibbsTrackingFilterType; + typedef itk::Image ItkFloatImageType; + typedef itk::Vector OdfVectorType; + typedef itk::Image ItkQBallImgType; + typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; + typedef itk::GibbsTrackingFilter< ItkQBallImgType > GibbsTrackingFilterType; static const std::string VIEW_ID; QmitkGibbsTrackingView(); virtual ~QmitkGibbsTrackingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); signals: protected slots: void StartGibbsTracking(); void StopGibbsTracking(); void AfterThread(); void BeforeThread(); void TimerUpdate(); void SetMask(); void AdvancedSettings(); void SaveTrackingParameters(); void LoadTrackingParameters(); void SetIterations(int value); void SetParticleWidth(int value); void SetParticleLength(int value); void SetInExBalance(int value); void SetFiberLength(int value); void SetParticleWeight(int value); void SetStartTemp(int value); void SetEndTemp(int value); void SetCurvatureThreshold(int value); void SetOutputFile(); private: // Visualization & GUI void GenerateFiberBundle(bool smoothFibers); void UpdateGUI(); void UpdateTrackingStatus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); template void CastToFloat(InputImageType* image, typename mitk::Image::Pointer outImage); void UpdateIteraionsGUI(unsigned long iterations); Ui::QmitkGibbsTrackingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; // data objects mitk::FiberBundleX::Pointer m_FiberBundle; - MaskImgType::Pointer m_MaskImage; + ItkFloatImageType::Pointer m_MaskImage; + mitk::TensorImage::Pointer m_TensorImage; mitk::QBallImage::Pointer m_QBallImage; ItkQBallImgType::Pointer m_ItkQBallImage; + ItkTensorImage::Pointer m_ItkTensorImage; // data nodes - mitk::DataNode::Pointer m_QBallImageNode; + mitk::DataNode::Pointer m_ImageNode; mitk::DataNode::Pointer m_MaskImageNode; mitk::DataNode::Pointer m_FiberBundleNode; // flags etc. bool m_ThreadIsRunning; QTimer* m_TrackingTimer; QTime m_TrackingTime; unsigned long m_ElapsedTime; unsigned long m_Iterations; int m_LastStep; QString m_OutputFileName; // global tracker and friends itk::SmartPointer m_GlobalTracker; QmitkTrackingWorker m_TrackingWorker; QThread m_TrackingThread; friend class QmitkTrackingWorker; }; #endif // _QMITKGibbsTrackingVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui index de4d981ce9..44fbab145e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkGibbsTrackingViewControls.ui @@ -1,1045 +1,1013 @@ QmitkGibbsTrackingViewControls 0 0 463 1011 0 0 0 0 QmitkTemplate 0 9 3 9 3 Data - Q-Ball Image: + Q-Ball/Tensor Image: Mandatory input - Mask Image: Optional input to limit the algorithms search space. - Parameters 0 Iterations: 10^7 Specify number of iterations for the tracking algorithm. 10 6 Qt::Horizontal QSlider::TicksBelow true Activate continuous visualization of intermediate results. Visualize Tractography true Visualize intermediate result. :/QmitkDiffusionImaging/Refresh_48.png:/QmitkDiffusionImaging/Refresh_48.png true Advanced Settings Output File: QFrame::NoFrame QFrame::Plain 0 0 0 Select output file name and folder. ... N/A true true QFrame::StyledPanel QFrame::Raised 9 0 9 0 4 - - + + auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - auto + 0 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - auto = 0.5 * min. spacing; sigma + + + + + + + + + + Particle Width: + + + + + + + Only fibers longer than specified are accepted. - 100 + 500 1 + + 40 + Qt::Horizontal QSlider::NoTicks - - + + - auto + Curvature Threshold: + + + + + + + 0.001 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - automatic estimation from gfa map and q-ball data. - - - 0 - - - 1000 - - - 1 + - - 0 + + - - Qt::Horizontal + + - - true + + 40mm - - QSlider::NoTicks + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0.1 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - 1 - - - 100 - - - 1 - - - 10 - - - Qt::Horizontal - - - false + + + + - - false + + - - QSlider::NoTicks + + - - - - - 0.001 + auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - 1 - - - 99 - - - 1 - - - 10 - - - Qt::Horizontal - - - QSlider::NoTicks - - - - - + + - 0 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Balance In/Ex Energy: IE Bias < 0 < EE Bias -50 50 1 Qt::Horizontal QSlider::NoTicks - - + + - - - - - - - - - - 40mm - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + automatic estimation from gfa map and q-ball data. - - - - - - Only fibers longer than specified are accepted. + + 0 - 500 + 1000 1 - 40 + 0 Qt::Horizontal + + true + QSlider::NoTicks - - + + - Particle Length: + Min. Fiber Length: - - + + - Particle Width: + Particle Length: + + + + + + + 1 + + + 99 + + + 1 + + + 10 + + + Qt::Horizontal + + + QSlider::NoTicks Particle Weight: Start Temperature: - - - - End Temperature: - - - - - + + - + Allow only fiber curvature values smaller than the selected threshold. - - + + 180 - - + + 1 - - Balance In/Ex Energy: + + 45 + + + Qt::Horizontal + + + QSlider::NoTicks - - + + - + auto = 1.5 * min. spacing; l - - + + 100 - - + + 1 - - Min. Fiber Length: + + Qt::Horizontal + + + QSlider::NoTicks - - - - true - + + - Use mean subtracted ODFs (recommended). + auto = 0.5 * min. spacing; sigma - - Subtract ODF Mean + + 100 - - true + + 1 - - - - Qt::Horizontal - - QSizePolicy::Fixed - - - - 60 - 20 - + + QSlider::NoTicks - + - - + + - Curvature Threshold: + 45° + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - 45° + auto Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - Allow only fiber curvature values smaller than the selected threshold. - - - 180 - - - 1 - - - 45 - - - Qt::Horizontal - - - QSlider::NoTicks + + + + End Temperature: - - - - auto = 1.5 * min. spacing; l + + + + 1 100 1 + + 10 + Qt::Horizontal + + false + + + false + QSlider::NoTicks QFrame::NoFrame QFrame::Plain 0 0 0 true Save current parameters as xml (.gtp) Qt::LeftToRight Save Parameters :/qmitk/btnMoveDown.png:/qmitk/btnMoveDown.png true Load parameters from xml file (.gtp) Qt::LeftToRight Load Parameters :/qmitk/btnMoveUp.png:/qmitk/btnMoveUp.png false No Q-Ball image selected. Qt::LeftToRight Start Tractography :/qmitk/play.xpm:/qmitk/play.xpm false Qt::LeftToRight Stop Tractography :/qmitk/stop.xpm:/qmitk/stop.xpm Monitor Progress: - Will only be updated if tracking is visualized Will only be updated if tracking is visualized Accepted Fibers: Connections: Particles: Proposal Acceptance Rate: Tracking Time: Will only be updated if tracking is visualized - - - - - Qt::Vertical QSizePolicy::Expanding 0 0