29 #include <itkImageDuplicator.h>
30 #include <itkResampleImageFilter.h>
31 #include <itkTimeProbe.h>
38 #include <boost/progress.hpp>
39 #include <boost/lexical_cast.hpp>
40 #include <boost/algorithm/string.hpp>
44 template<
class ItkQBallImageType >
46 m_StartTemperature(0.1),
47 m_EndTemperature(0.001),
49 m_CurrentIteration(0.0),
54 m_ConnectionPotential(10),
56 m_ParticlePotential(0.2),
58 m_AbortTracking(false),
59 m_NumAcceptedFibers(0),
61 m_ProposalAcceptance(0),
62 m_CurvatureThreshold(0.7),
63 m_DuplicateImage(true),
67 m_LoadParameterFile(
""),
69 m_IsInValidState(true)
74 template<
class ItkQBallImageType >
81 template<
class ItkQBallImageType >
87 while (m_BuildFibers){}
90 return m_FiberPolyData;
93 template<
class ItkQBallImageType >
98 MITK_INFO <<
"GibbsTrackingFilter: estimating particle weight";
101 if(m_QBallImage->GetSpacing()[0]<m_QBallImage->GetSpacing()[1] && m_QBallImage->GetSpacing()[0]<m_QBallImage->GetSpacing()[2])
102 minSpacing = m_QBallImage->GetSpacing()[0];
103 else if (m_QBallImage->GetSpacing()[1] < m_QBallImage->GetSpacing()[2])
104 minSpacing = m_QBallImage->GetSpacing()[1];
106 minSpacing = m_QBallImage->GetSpacing()[2];
107 float m_ParticleLength = 1.5*minSpacing;
108 float m_ParticleWidth = 0.5*minSpacing;
113 randGen->SetSeed(m_RandomSeed);
122 m_IsInValidState =
false;
123 m_AbortTracking =
true;
124 m_BuildFibers =
false;
125 mitkThrow() <<
"Unable to load lookup tables.";
133 float alpha = log(m_EndTemperature/m_StartTemperature);
134 m_ParticleWeight = 0.01;
137 int neededParts = 3000;
138 while (ppv<neededParts)
141 m_ParticleWeight /= 2;
143 m_ParticleWeight = ppv*m_ParticleWeight/neededParts;
145 encomp->
SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential);
146 for(
int step = 0; step < 10; step++ )
149 float temperature = m_StartTemperature * exp(alpha*(((1.0)*step)/((1.0)*10)));
152 for (
unsigned long i=0; i<10000; i++)
163 MITK_INFO <<
"GibbsTrackingFilter: finished estimating particle weight";
167 template<
class ItkQBallImageType >
170 TimeProbe preClock; preClock.Start();
172 if (m_QBallImage.IsNull() && m_TensorImage.IsNotNull())
175 filter->SetInput( m_TensorImage );
177 m_QBallImage = filter->GetOutput();
179 else if (m_DuplicateImage)
181 typedef itk::ImageDuplicator< ItkQBallImageType > DuplicateFilterType;
183 duplicator->SetInputImage( m_QBallImage );
184 duplicator->Update();
185 m_QBallImage = duplicator->GetOutput();
189 typedef ImageRegionIterator< ItkQBallImageType > InputIteratorType;
190 InputIteratorType it(m_QBallImage, m_QBallImage->GetLargestPossibleRegion() );
192 while (!it.IsAtEnd())
197 it.Set(odf.GetDataPointer());
209 if(m_QBallImage->GetSpacing()[0]<m_QBallImage->GetSpacing()[1] && m_QBallImage->GetSpacing()[0]<m_QBallImage->GetSpacing()[2])
210 minSpacing = m_QBallImage->GetSpacing()[0];
211 else if (m_QBallImage->GetSpacing()[1] < m_QBallImage->GetSpacing()[2])
212 minSpacing = m_QBallImage->GetSpacing()[1];
214 minSpacing = m_QBallImage->GetSpacing()[2];
216 if(m_ParticleLength == 0)
217 m_ParticleLength = 1.5*minSpacing;
218 if(m_ParticleWidth == 0)
219 m_ParticleWidth = 0.5*minSpacing;
221 if(m_ParticleWeight == 0)
222 EstimateParticleWeight();
224 float alpha = log(m_EndTemperature/m_StartTemperature);
227 m_CurvatureThreshold = 0;
232 randGen->SetSeed(m_RandomSeed);
242 m_IsInValidState =
false;
243 m_AbortTracking =
true;
244 m_BuildFibers =
false;
245 mitkThrow() <<
"Unable to load lookup tables.";
252 particleGrid =
new ParticleGrid(m_MaskImage, m_ParticleLength, m_ParticleGridCellCapacity);
253 encomp =
new GibbsEnergyComputer(m_QBallImage, m_MaskImage, particleGrid, interpolator, randGen);
254 encomp->
SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential);
259 MITK_ERROR <<
"Particle grid allocation failed. Not enough memory? Try to increase the particle length.";
260 m_IsInValidState =
false;
261 m_AbortTracking =
true;
262 m_BuildFibers =
false;
266 MITK_INFO <<
"----------------------------------------";
267 MITK_INFO <<
"Iterations: " << m_Iterations;
268 MITK_INFO <<
"Particle length: " << m_ParticleLength;
269 MITK_INFO <<
"Particle width: " << m_ParticleWidth;
270 MITK_INFO <<
"Particle weight: " << m_ParticleWeight;
271 MITK_INFO <<
"Start temperature: " << m_StartTemperature;
272 MITK_INFO <<
"End temperature: " << m_EndTemperature;
273 MITK_INFO <<
"In/Ex balance: " << m_InexBalance;
274 MITK_INFO <<
"Min. fiber length: " << m_MinFiberLength;
275 MITK_INFO <<
"Curvature threshold: " << m_CurvatureThreshold;
276 MITK_INFO <<
"Random seed: " << m_RandomSeed;
277 MITK_INFO <<
"----------------------------------------";
281 TimeProbe clock; clock.Start();
282 m_NumAcceptedFibers = 0;
283 m_CurrentIteration = 0;
284 boost::progress_display disp(m_Iterations);
285 if (!m_AbortTracking)
286 while (m_CurrentIteration<m_Iterations)
289 m_CurrentIteration++;
294 float temperature = m_StartTemperature * exp(alpha*m_CurrentIteration/m_Iterations);
307 m_FiberPolyData = fiberBuilder.
iterate(m_MinFiberLength);
308 m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines();
309 m_BuildFibers =
false;
318 m_FiberPolyData = fiberBuilder.
iterate(m_MinFiberLength);
319 m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines();
327 m_AbortTracking =
true;
328 m_BuildFibers =
false;
330 int h = clock.GetTotal()/3600;
331 int m = ((int)clock.GetTotal()%3600)/60;
332 int s = (int)clock.GetTotal()%60;
333 MITK_INFO <<
"GibbsTrackingFilter: finished gibbs tracking in " << h <<
"h, " << m <<
"m and " << s <<
"s";
334 m = (int)preClock.GetTotal()/60;
335 s = (int)preClock.GetTotal()%60;
336 MITK_INFO <<
"GibbsTrackingFilter: preparation of the data took " << m <<
"m and " << s <<
"s";
337 MITK_INFO <<
"GibbsTrackingFilter: " << m_NumAcceptedFibers <<
" fibers accepted";
344 template<
class ItkQBallImageType >
347 if(m_MaskImage.IsNull())
349 MITK_INFO <<
"GibbsTrackingFilter: generating default mask image";
351 m_MaskImage->SetSpacing( m_QBallImage->GetSpacing() );
352 m_MaskImage->SetOrigin( m_QBallImage->GetOrigin() );
353 m_MaskImage->SetDirection( m_QBallImage->GetDirection() );
354 m_MaskImage->SetRegions( m_QBallImage->GetLargestPossibleRegion() );
355 m_MaskImage->Allocate();
356 m_MaskImage->FillBuffer(1.0);
358 else if ( m_MaskImage->GetLargestPossibleRegion().GetSize()[0]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[0] ||
359 m_MaskImage->GetLargestPossibleRegion().GetSize()[1]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[1] ||
360 m_MaskImage->GetLargestPossibleRegion().GetSize()[2]!=m_QBallImage->GetLargestPossibleRegion().GetSize()[2] ||
361 m_MaskImage->GetSpacing()[0]!=m_QBallImage->GetSpacing()[0] ||
362 m_MaskImage->GetSpacing()[1]!=m_QBallImage->GetSpacing()[1] ||
363 m_MaskImage->GetSpacing()[2]!=m_QBallImage->GetSpacing()[2] )
365 MITK_INFO <<
"GibbsTrackingFilter: resampling mask image";
366 typedef itk::ResampleImageFilter< ItkFloatImageType, ItkFloatImageType, float > ResamplerType;
368 resampler->SetOutputSpacing( m_QBallImage->GetSpacing() );
369 resampler->SetOutputOrigin( m_QBallImage->GetOrigin() );
370 resampler->SetOutputDirection( m_QBallImage->GetDirection() );
371 resampler->SetSize( m_QBallImage->GetLargestPossibleRegion().GetSize() );
373 resampler->SetInput( m_MaskImage );
374 resampler->SetDefaultPixelValue(0.0);
376 m_MaskImage = resampler->GetOutput();
377 MITK_INFO <<
"GibbsTrackingFilter: resampling finished";
382 template<
class ItkQBallImageType >
385 m_AbortTracking =
true;
388 if( m_LoadParameterFile.length()==0 )
390 m_AbortTracking =
false;
394 MITK_INFO <<
"GibbsTrackingFilter: loading parameter file " << m_LoadParameterFile;
396 TiXmlDocument doc( m_LoadParameterFile );
399 TiXmlHandle hDoc(&doc);
401 TiXmlHandle hRoot(0);
403 pElem = hDoc.FirstChildElement().Element();
404 hRoot = TiXmlHandle(pElem);
405 pElem = hRoot.FirstChildElement(
"parameter_set").Element();
407 string iterations(pElem->Attribute(
"iterations"));
408 m_Iterations = boost::lexical_cast<
double>(iterations);
410 string particleLength(pElem->Attribute(
"particle_length"));
411 m_ParticleLength = boost::lexical_cast<
float>(particleLength);
413 string particleWidth(pElem->Attribute(
"particle_width"));
414 m_ParticleWidth = boost::lexical_cast<
float>(particleWidth);
416 string partWeight(pElem->Attribute(
"particle_weight"));
417 m_ParticleWeight = boost::lexical_cast<
float>(partWeight);
419 string startTemp(pElem->Attribute(
"temp_start"));
420 m_StartTemperature = boost::lexical_cast<
float>(startTemp);
422 string endTemp(pElem->Attribute(
"temp_end"));
423 m_EndTemperature = boost::lexical_cast<
float>(endTemp);
425 string inExBalance(pElem->Attribute(
"inexbalance"));
426 m_InexBalance = boost::lexical_cast<
float>(inExBalance);
428 string fiberLength(pElem->Attribute(
"fiber_length"));
429 m_MinFiberLength = boost::lexical_cast<
float>(fiberLength);
431 string curvThres(pElem->Attribute(
"curvature_threshold"));
432 m_CurvatureThreshold = cos(boost::lexical_cast<float>(curvThres)*
M_PI/180);
433 m_AbortTracking =
false;
434 MITK_INFO <<
"GibbsTrackingFilter: parameter file loaded successfully";
439 MITK_INFO <<
"GibbsTrackingFilter: could not load parameter file";
445 template<
class ItkQBallImageType >
450 if( m_SaveParameterFile.length()==0 )
452 MITK_INFO <<
"GibbsTrackingFilter: no filename specified to save parameters";
456 MITK_INFO <<
"GibbsTrackingFilter: saving parameter file " << m_SaveParameterFile;
458 TiXmlDocument documentXML;
459 TiXmlDeclaration* declXML =
new TiXmlDeclaration(
"1.0",
"",
"" );
460 documentXML.LinkEndChild( declXML );
462 TiXmlElement* mainXML =
new TiXmlElement(
"global_tracking_parameter_file");
463 mainXML->SetAttribute(
"file_version",
"0.1");
464 documentXML.LinkEndChild(mainXML);
466 TiXmlElement* paramXML =
new TiXmlElement(
"parameter_set");
467 paramXML->SetAttribute(
"iterations", boost::lexical_cast<string>(m_Iterations));
468 paramXML->SetAttribute(
"particle_length", boost::lexical_cast<string>(m_ParticleLength));
469 paramXML->SetAttribute(
"particle_width", boost::lexical_cast<string>(m_ParticleWidth));
470 paramXML->SetAttribute(
"particle_weight", boost::lexical_cast<string>(m_ParticleWeight));
471 paramXML->SetAttribute(
"temp_start", boost::lexical_cast<string>(m_StartTemperature));
472 paramXML->SetAttribute(
"temp_end", boost::lexical_cast<string>(m_EndTemperature));
473 paramXML->SetAttribute(
"inexbalance", boost::lexical_cast<string>(m_InexBalance));
474 paramXML->SetAttribute(
"fiber_length", boost::lexical_cast<string>(m_MinFiberLength));
475 paramXML->SetAttribute(
"curvature_threshold", boost::lexical_cast<string>(m_CurvatureThreshold));
476 mainXML->LinkEndChild(paramXML);
478 if(!boost::algorithm::ends_with(m_SaveParameterFile,
".gtp"))
479 m_SaveParameterFile.append(
".gtp");
480 documentXML.SaveFile( m_SaveParameterFile );
482 MITK_INFO <<
"GibbsTrackingFilter: parameter file saved successfully";
487 MITK_INFO <<
"GibbsTrackingFilter: could not save parameter file";
itk::SmartPointer< Self > Pointer
Contains and manages particles.
int GetNumAcceptedProposals()
ComponentType GetMeanValue() const
FiberPolyDataType GetFiberBundle()
Output fibers.
virtual ~GibbsTrackingFilter()
Lookuptable based trilinear interpolation of spherically arranged scalar values.
vtkSmartPointer< vtkPolyData > iterate(int minFiberLength)
vtkSmartPointer< vtkPolyData > FiberPolyDataType
Gnerates actual fiber structure (vtkPolyData) from the particle grid content.
void SetParameters(float particleWeight, float particleWidth, float connectionPotential, float curvThres, float inexBalance, float particlePotential)
Generates ne proposals of particle configurations.
MITKCORE_EXPORT const ScalarType eps
void EstimateParticleWeight()
bool IsInValidState() const
ODF lookuptable based energy computer.
void MakeProposal()
make proposal for birth/death/shift/connection of particles
void GenerateData() override
void SetTemperature(float val)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.