Shapeworks Studio  2.1
Shape analysis software suite
List of all members | Public Types | Public Member Functions | Protected Member Functions
itk::PSMCommandLineClass< VDimension > Class Template Reference

This class provides a command line tool to run the Particle Shape Modeling. It runs the optimization as well as Procrustes Registration if the option is in the project parameter file. For now, the tool only uses the PSMEntropyModelFilter for the optimization. More...

#include <itkPSMCommandLineClass.h>

+ Inheritance diagram for itk::PSMCommandLineClass< VDimension >:
+ Collaboration diagram for itk::PSMCommandLineClass< VDimension >:

Public Types

typedef PSMCommandLineClass Self
 
typedef DataObject Superclass
 
typedef SmartPointer< SelfPointer
 
typedef SmartPointer< const SelfConstPointer
 
typedef itk::Image< float, VDimension > ImageType
 
typedef PSMEntropyModelFilter< typename PSMCommandLineClass::ImageTypeEntropyModelFilterType
 
typedef PSMProcrustesRegistration< VDimension > ProcrustesRegistrationType
 
typedef PSMProjectReader ProjectReaderType
 
typedef PSMProject ProjectType
 

Public Member Functions

 itkNewMacro (Self)
 
 itkTypeMacro (PSMCommandLineClass, DataObject)
 
void ReadProjectFile (const char *fn)
 
void ReadDistanceTransforms (std::string input_path_prefix)
 
void ReadCuttingPlanes ()
 
void ReadModelPointFiles ()
 
void SetPSMFilterParameters ()
 
void WriteOutputs (std::string output_path)
 
void Run (const char *fname, std::string input_path_prefix, std::string output_path)
 
 PSMCommandLineClass ()
 
 itkGetObjectMacro (PSMFilter, EntropyModelFilterType)
 
 itkGetMacro (ReportInterval, unsigned int)
 
 itkSetMacro (ReportInterval, unsigned int)
 

Protected Member Functions

void IterateCallback (itk::Object *, const itk::EventObject &)
 

Detailed Description

template<unsigned int VDimension>
class itk::PSMCommandLineClass< VDimension >

This class provides a command line tool to run the Particle Shape Modeling. It runs the optimization as well as Procrustes Registration if the option is in the project parameter file. For now, the tool only uses the PSMEntropyModelFilter for the optimization.

Definition at line 47 of file itkPSMCommandLineClass.h.

Member Typedef Documentation

template<unsigned int VDimension>
typedef PSMEntropyModelFilter<typename PSMCommandLineClass::ImageType> itk::PSMCommandLineClass< VDimension >::EntropyModelFilterType

PSM model optimization filter typedef

Definition at line 67 of file itkPSMCommandLineClass.h.

template<unsigned int VDimension>
typedef itk::Image<float, VDimension> itk::PSMCommandLineClass< VDimension >::ImageType

Input distance transforms image typedef

Definition at line 63 of file itkPSMCommandLineClass.h.

template<unsigned int VDimension>
typedef PSMProcrustesRegistration<VDimension> itk::PSMCommandLineClass< VDimension >::ProcrustesRegistrationType

Procrustes Registration typedef

Definition at line 70 of file itkPSMCommandLineClass.h.

template<unsigned int VDimension>
typedef PSMProjectReader itk::PSMCommandLineClass< VDimension >::ProjectReaderType

Project Reader typedef

Definition at line 73 of file itkPSMCommandLineClass.h.

template<unsigned int VDimension>
typedef PSMProject itk::PSMCommandLineClass< VDimension >::ProjectType

Project typedef

Definition at line 76 of file itkPSMCommandLineClass.h.

template<unsigned int VDimension>
typedef PSMCommandLineClass itk::PSMCommandLineClass< VDimension >::Self

Standard class typedefs.

Definition at line 51 of file itkPSMCommandLineClass.h.

Constructor & Destructor Documentation

template<unsigned int VDimension>
itk::PSMCommandLineClass< VDimension >::PSMCommandLineClass ( )

Constructor and destructor

Definition at line 33 of file itkPSMCommandLineClass.hxx.

34  {
35  m_ProcrustesCounter = 0;
36  m_ReportInterval = 10;
37  m_ProjectReader = ProjectReaderType::New();
38  m_Project = ProjectType::New();
39  m_ProcrustesRegistration = ProcrustesRegistrationType::New();
40  m_PSMFilter = EntropyModelFilterType::New();
41 
42 
43  }

Member Function Documentation

template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::IterateCallback ( itk::Object *  caller,
const itk::EventObject &   
)
protected

Callback to run Procrustes Registration on the shapes at the interval specified in the project parameter file or by default.

Definition at line 47 of file itkPSMCommandLineClass.hxx.

48  {
50  static_cast<EntropyModelFilterType *>(caller);
51 
52  // Print every 10 iterations
53  if (o->GetNumberOfElapsedIterations() % m_ReportInterval != 0) { return; }
54 
55  std::cout << "Iteration # " << o->GetNumberOfElapsedIterations() << std::endl;
56  std::cout << " Eigenmode variances: ";
57  for (unsigned int i = 0; i < o->GetShapePCAVariances().size(); i++)
58  {
59  std::cout << o->GetShapePCAVariances()[i] << " ";
60  }
61  std::cout << std::endl;
62  std::cout << " Regularization = " << o->GetRegularizationConstant() << std::endl;
63 
64  // Check if optimization is run using scales. Get Procrustes
65  // interval for the current scale.
66  int interval = 0;
67  std::cout << "Optimization Scale " << (o->GetCurrentScale() + 1) << "/"
68  << o->GetNumberOfScales() << std::endl;
69 
70  if (o->GetNumberOfScales() > 1)
71  {
72  interval = m_ProcrustesInterval[o->GetCurrentScale()];
73  std::cout << "Interval = " << interval << std::endl;
74  } else // Use the default interval
75  {
76  interval = m_ProcrustesRegistration->GetProcrustesInterval();
77  }
78 
79  // Check if the Procrustes interval is set to a value other than 0
80  if (interval > 0)
81  {
82  this->m_ProcrustesCounter++;
83 
84  // If the counter is greater than the interval value, run
85  // Procrustes registration
86  if (this->m_ProcrustesCounter >= interval)
87  {
88  // Reset the counter
89  this->m_ProcrustesCounter = 0;
90  this->m_ProcrustesRegistration->RunRegistration();
91  std::cout << "Ran Procrustes Registration" << std::endl;
92  }
93  }
94  }
PSMEntropyModelFilter< typename PSMCommandLineClass::ImageType > EntropyModelFilterType
template<unsigned int VDimension>
itk::PSMCommandLineClass< VDimension >::itkGetMacro ( ReportInterval  ,
unsigned  int 
)

Get/Set the number of optimization iterations between reporting of the optimized values.

template<unsigned int VDimension>
itk::PSMCommandLineClass< VDimension >::itkGetObjectMacro ( PSMFilter  ,
EntropyModelFilterType   
)

Returns the particle system used in the shape model computation.

template<unsigned int VDimension>
itk::PSMCommandLineClass< VDimension >::itkNewMacro ( Self  )

Method for creation through the object factory.

template<unsigned int VDimension>
itk::PSMCommandLineClass< VDimension >::itkTypeMacro ( PSMCommandLineClass< VDimension >  ,
DataObject   
)

Run-time type information (and related methods).

template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::ReadCuttingPlanes ( )

Reads any cutting plane data from the domain fields in the project file and loads this information into the PSM Filter.

Definition at line 138 of file itkPSMCommandLineClass.hxx.

139  {
140  if (!m_Project->HasDomains())
141  {
142  itkExceptionMacro("Domains must be defined in the project file.");
143  }
144 
145  // Compile the list of domains
146  std::vector<std::string> domain_names = m_Project->GetDomainNames();
147 
148  for (unsigned int i = 0; i < domain_names.size(); i++)
149  {
150  if (m_Project->HasDomainCuttingPlanes(domain_names[i]))
151  {
152  // Cutting planes are returned as a list of vnl_vectors.
153  std::vector<vnl_vector_fixed<double, 3> > planes
154  = m_Project->GetDomainCuttingPlanes(domain_names[i]);
155 
156  // The list should have size that is multiple of 3, since
157  // every plane is defined by exactly 3 points.
158  if (planes.size() % 3 != 0)
159  {
160  itkExceptionMacro("Something is wrong with the cutting plane data for domain " + domain_names[i] + ". Correct number of points was not found.");
161  }
162 
163  // Traverse the list and pull out sets of 3 points. Each
164  // set of 3 defines a cutting plane.
165  vnl_vector_fixed<double, 3> x;
166  vnl_vector_fixed<double, 3> y;
167  vnl_vector_fixed<double, 3> z;
168  std::vector<vnl_vector_fixed<double, 3> >::iterator it =
169  planes.begin();
170 
171  while (it != planes.end())
172  {
173  x = *it; it++;
174  y = *it; it++;
175  z = *it; it++;
176 
177  std::cout << "Found cutting plane for domain " << domain_names[i] <<
178  ": " << std::endl;
179  std::cout << x[0] << " " << x[1] << " " << x[2] << std::endl;
180  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
181  std::cout << z[0] << " " << z[1] << " " << z[2] << std::endl;
182 
183  // Add cutting plane to the PSM filter by domain name
184 
185  m_PSMFilter->AddCuttingPlane(x, y, z, domain_names[i]);
186 
187  // int d = m_PSMFilter->GetDomainIndexByName(domain_names[i]);
188  // m_PSMFilter->GetDomain(d)->SetCuttingPlane(x,y,z);
189 
190  }
191 
192 
193  } // end has cutting planes
194  } // end traverse domains
195 
196  }
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::ReadDistanceTransforms ( std::string  input_path_prefix)

Read the distance transforms that are provided as inputs to the optimzation filter.

Definition at line 98 of file itkPSMCommandLineClass.hxx.

99  {
100  if (!m_Project->HasDomains())
101  {
102  throw itk::ExceptionObject("Domains must be defined in the project file.");
103  }
104 
105  // Compile the list of distance transforms
106  std::vector<std::string> domain_names = m_Project->GetDomainNames();
107  std::vector<std::string> dt_files;
108  for (unsigned int i = 0; i < domain_names.size(); i++)
109  {
110  std::string s = (m_Project->GetDomainDistanceTransform(domain_names[i]))[0];
111  dt_files.push_back(s);
112 
113 
114  this->m_PSMFilter->SetDomainName(domain_names[i], i);
115  }
116 
117  // Read in the distance transforms
118  // const std::vector<std::string> &dt_files = this->m_Project->GetDistanceTransforms();
119  std::cout << "Reading distance transforms ..." << std::endl;
120  for (unsigned int i = 0; i < dt_files.size(); i++)
121  {
122  typename itk::ImageFileReader<PSMCommandLineClass::ImageType>::Pointer reader =
123  itk::ImageFileReader<PSMCommandLineClass::ImageType>::New();
124  reader->SetFileName(input_path_prefix + dt_files[i]);
125  //reader->SetFileName(dt_files[i]);
126  reader->Update();
127 
128  std::cout << domain_names[i] << ": " << dt_files[i] << std::endl;
129 
130  this->m_PSMFilter->SetInput(i, reader->GetOutput());
131 
132  }
133  std::cout << "Done!" << std::endl;
134  }
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::ReadModelPointFiles ( )

Read the input point files, if any.

Definition at line 200 of file itkPSMCommandLineClass.hxx.

201  {
202  // double value1, value2, value3;
203  // unsigned int numOfPoints;
204  // typename PSMCommandLineClass::EntropyModelFilterType::PointType pt;
205 
206  // // Check if model initialization is supplied. If not, then optimization scales will need to be
207  // // used later.
208  // if(this->m_Project->HasModel(std::string("initialization")))
209  // {
210  // const std::vector<std::string> &pt_files = this->m_Project->GetModel(std::string("initialization"));
211  // std::cout << "Reading the initial model correspondences ..." << std::endl;
212  // for (unsigned int i = 0; i < pt_files.size(); i++)
213  // {
214  // // Read the points for this file and add as a list
215  // typename std::vector<typename PSMCommandLineClass::EntropyModelFilterType::PointType> init_points;
216  // numOfPoints = 0;
217  // // Open the ascii file.
218  // std::ifstream in( (input_path_prefix + pt_files[i]).c_str() );
219  // if ( !in )
220  // {
221  // std::cerr << "Could not open point file for input." << std::endl;
222  // break;
223  // }
224 
225  // // Read all of the points, one point per line.
226  // while (in)
227  // {
228  // in>>value1>>value2>>value3;
229  // pt[0] = value1;
230  // pt[1] = value2;
231  // if(VDimension == 3)
232  // {
233  // pt[2] = value3;
234  // }
235  // init_points.push_back(pt);
236  // numOfPoints++;
237  // }
238  // // this algorithm pushes the last point twice
239  // init_points.pop_back();
240  // std::cout << "Read " << numOfPoints-1 << " points. " << std::endl;
241  // in.close();
242  // this->m_PSMFilter->SetInputCorrespondencePoints(i,init_points);
243  // std::cout << " " << pt_files[i] << std::endl;
244  // }
245  // std::cout << "Done!" << std::endl;
246 
247 
248  // }
249  // else
250  // {
251  // // Check if scales have been supplied
252  // if(this->m_Project->HasOptimizationAttribute("number_of_scales")
253  // &&
254  // (this->m_Project->GetNumberOfOptimizationScales()) > 0)
255  // {
256  // // Read the input optimization scales from the project file.
257  // this->ReadOptimizationScales();
258  // }
259  // else
260  // {
261  // // REQUIRE THAT WE HAVE SCALES DEFINED. If there is only a single
262  // // optimization scale, it should be defined as scale 0, but for now
263  // // we are enforcing that scales be defined in the parameter file.
264 
265  // throw itk::ExceptionObject("The number of optimization scales and their parameters were not defined in the parameter file.");
266 
267  // //this->SetDefaultScales();
268  // }
269  // }
270  }
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::ReadProjectFile ( const char *  fn)

Parse the project file and store in the m_Project member variable.

Definition at line 274 of file itkPSMCommandLineClass.hxx.

275  {
276  // Read the project parameter file
277  m_ProjectFileName = fn;
278  this->m_ProjectReader->SetFileName(fn);
279  this->m_ProjectReader->Update();
280 
281  // Store the project parameters
282  this->m_Project = m_ProjectReader->GetOutput();
283  }
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::Run ( const char *  fname,
std::string  input_path_prefix,
std::string  output_path 
)

Run the steps of the optimization process

Definition at line 404 of file itkPSMCommandLineClass.hxx.

406  {
407  // Read the project parameter files. Also sets the project
408  // filename (m_ProjectFileName)
409  this->ReadProjectFile(fname);
410 
411  // Set the optimization parameters. This also checks to be sure
412  // everything is there. If not, this method throws an exception.
413  this->SetPSMFilterParameters();
414 
415  // Read the distance transform files
416  this->ReadDistanceTransforms(input_path_prefix);
417 
418  // Read any geometric contraints (cutting planes)
419  this->ReadCuttingPlanes();
420 
421  // Create the callback function to run Procrustes and report
422  // progress.
423  m_IterateCmd = itk::MemberCommand<PSMCommandLineClass>::New();
424  m_IterateCmd->SetCallbackFunction(this, &PSMCommandLineClass::IterateCallback);
425  this->m_PSMFilter->AddObserver(itk::IterationEvent(), m_IterateCmd);
426 
427  // Set ParticleSystem for ProcrustesRegistration
428  this->m_ProcrustesRegistration->SetPSMParticleSystem(m_PSMFilter->GetParticleSystem());
429 
430  // Run the optimization filter
431  this->m_PSMFilter->Update();
432  // TODO: Is this error message really required?
433  if (this->m_PSMFilter->GetNumberOfElapsedIterations() >= this->m_PSMFilter->GetMaximumNumberOfIterations())
434  {
435  std::cerr << "Optimization did not converge based on tolerance criteria." << std::endl;
436  }
437 
438  std::cout << "Optimization done " << std::endl;
439 
440  // Write out the optimized point sets
441  this->WriteOutputs(output_path);
442  }
void ReadProjectFile(const char *fn)
void IterateCallback(itk::Object *, const itk::EventObject &)
void ReadDistanceTransforms(std::string input_path_prefix)
void WriteOutputs(std::string output_path)
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::SetPSMFilterParameters ( )

Sets the optimization parameters. Assumes that the parameter file has been parsed.

Definition at line 287 of file itkPSMCommandLineClass.hxx.

288  {
289  // Read the optimization parameters and set their corresponding
290  // parameters in the PSM optimization filter. All of the following
291  // parameters are required to be present in the project file.
292  std::cout << "Reading optimization parameters ... " << std::endl;
293  unsigned int number_of_scales = this->m_Project->GetNumberOfOptimizationScales();
294  std::cout << " Optimization scales = " << number_of_scales << std::endl;
295 
296  if (number_of_scales > 0) {
297  // We need vectors of parameters, one for each scale.
298  std::vector<double> regularization_initial(number_of_scales);
299  std::vector<double> regularization_final(number_of_scales);
300  std::vector<double> regularization_decayspan(number_of_scales);
301  std::vector<double> tolerance(number_of_scales);
302  std::vector<unsigned int> maximum_iterations(number_of_scales);
303  m_ProcrustesInterval.resize(number_of_scales);
304 
305  // Read parameters for each scale
306  for (unsigned int i = 0; i < number_of_scales; i++) {
307  std::cout << "Optimization parameters for scale " << i << ": " << std::endl;
308  if (this->m_Project->HasOptimizationAttribute("regularization_initial", i))
309  {
310  regularization_initial[i] = this->m_Project->GetOptimizationAttribute("regularization_initial", i);
311  } else { throw itk::ExceptionObject("Missing parameter: regularization_initial"); }
312  std::cout << " regularization_initial = " << regularization_initial[i] << std::endl;
313 
314  if (this->m_Project->HasOptimizationAttribute("regularization_final", i))
315  {
316  regularization_final[i] = this->m_Project->GetOptimizationAttribute("regularization_final", i);
317  } else { throw itk::ExceptionObject("Missing parameter: regularization_final"); }
318  std::cout << " regularization_final = " << regularization_final[i] << std::endl;
319 
320  if (this->m_Project->HasOptimizationAttribute("regularization_decayspan", i))
321  {
322  regularization_decayspan[i]
323  = this->m_Project->GetOptimizationAttribute("regularization_decayspan", i);
324  } else { throw itk::ExceptionObject("Missing parameter: regularization_decayspan"); }
325  std::cout << " regularization_decayspan = " << regularization_decayspan[i] << std::endl;
326 
327  if (this->m_Project->HasOptimizationAttribute("tolerance", i))
328  {
329  tolerance[i] = this->m_Project->GetOptimizationAttribute("tolerance", i);
330  } else { throw itk::ExceptionObject("Missing parameter: tolerance"); }
331  std::cout << " tolerance = " << tolerance[i] << std::endl;
332 
333  if (this->m_Project->HasOptimizationAttribute("maximum_iterations", i))
334  {
335  maximum_iterations[i]
336  = static_cast<unsigned int>(this->m_Project->GetOptimizationAttribute("maximum_iterations", i));
337  } else { throw itk::ExceptionObject("Missing parameter: maximum_iterations"); }
338  std::cout << " maximum_iterations = " << maximum_iterations[i] << std::endl;
339 
340  // if(this->m_Project->HasProcrustes() == true)
341  // {
342  if (this->m_Project->HasOptimizationAttribute("procrustes_interval", i))
343  {
344  m_ProcrustesInterval[i]
345  = static_cast<unsigned int>(this->m_Project->GetOptimizationAttribute("procrustes_interval", i));
346  } else { throw itk::ExceptionObject("Missing parameter: procrustes_interval"); }
347  std::cout << " procrustes_interval = " << m_ProcrustesInterval[i] << std::endl;
348  //}
349  }
350 
351  // Now set the parameters in the filter
352  this->m_PSMFilter->SetNumberOfScales(number_of_scales);
353  this->m_PSMFilter->SetRegularizationInitial(regularization_initial);
354  this->m_PSMFilter->SetRegularizationFinal(regularization_final);
355  this->m_PSMFilter->SetRegularizationDecaySpan(regularization_decayspan);
356  this->m_PSMFilter->SetTolerance(tolerance);
357  this->m_PSMFilter->SetMaximumNumberOfIterations(maximum_iterations);
358  } else
359  {
360  throw itk::ExceptionObject("Project must define at least one optimization scale");
361  }
362  }
template<unsigned int VDimension>
void itk::PSMCommandLineClass< VDimension >::WriteOutputs ( std::string  output_path)

Write out the optimized point sets to user specified files

Definition at line 366 of file itkPSMCommandLineClass.hxx.

367  {
368  const std::vector<std::string> &out_files = this->m_Project->GetModel(std::string("optimized"));
369  if (out_files.size() != this->m_PSMFilter->GetParticleSystem()->GetNumberOfDomains())
370  {
371  std::cerr << "Number of output files does not match the number of particle domains (inputs)." << std::endl;
372  } else
373  {
374  for (unsigned int d = 0; d < this->m_PSMFilter->GetParticleSystem()->GetNumberOfDomains(); d++)
375  {
376  // Open the output file.
377  std::string fname = output_path + out_files[d];
378  std::ofstream out(fname.c_str());
379  if (!out)
380  {
381  std::cerr << "Could not open point file for output: " << std::endl;
382  break;
383  } else
384  {
385  for (unsigned int j = 0; j < this->m_PSMFilter->GetParticleSystem()->GetNumberOfParticles(d); j++)
386  {
387  for (unsigned int i = 0; i < VDimension; i++)
388  {
389  out << this->m_PSMFilter->GetParticleSystem()->GetPosition(j, d)[i] << " ";
390  }
391  if (VDimension == 2)
392  {
393  out << "0.0"; // printed for display in ShapeWorksViewer2
394  }
395  out << std::endl;
396  }
397  }
398  } // end for number of domains
399  }
400  }

The documentation for this class was generated from the following files: