SMILX  1.01
milxDeformableModelApp.cxx
Go to the documentation of this file.
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
18 #include <vector>
19 #include <tclap/CmdLine.h> //Command line parser library
20 
21 // vtk includes
22 #include <vtkSmartPointer.h>
23 #include <vtkPolyData.h>
24 #include <vtkMultiThreader.h>
25 #include <vtkPolyDataCollection.h>
26 #include <vtkTransformCollection.h>
27 // SMILI
28 #include <milxFile.h>
29 #include <milxDeformableModel.h>
30 
31 using namespace TCLAP;
32 
33 typedef std::vector< std::string >::iterator stringiterator;
34 //Image output related
35 typedef unsigned char charPixelType;
36 typedef itk::Image<charPixelType, milx::imgDimension> charImageType;
37 
38 //Supported operations
39 enum operations {none = 0, convert, duplicate, cat, split, scale, decimate, smooth, laplacian, thresholdscalars, flip, diffscalars, copyscalars, diffscalarspairs, statscalars, removescalars, mse, procrustes, icp, clip,
40  voxelise, orient, flat};
41 
75 int main(int argc, char *argv[])
76 {
77  //---------------------------
79  milx::PrintInfo("--------------------------------------------------------");
80  milx::PrintInfo("SMILI Deformable Model Tool for Models/Surfaces/Meshes.");
81  milx::PrintInfo("(c) Copyright Chandra et al., 2015.");
82  milx::PrintInfo("Version: " + milx::NumberToString(milx::Version));
83  milx::PrintInfo("University of Queensland, Australia.");
84  milx::PrintInfo("Australian e-Health Research Centre, CSIRO, Australia.");
85  milx::PrintInfo("--------------------------------------------------------\n");
86 
87  //---------------------------
89  CmdLine cmd("A diagnostic tool for deformable models/surface operations", ' ', milx::NumberToString(milx::Version));
90 
92  ValueArg<size_t> threadsArg("", "threads", "Set he number of global threads to use.", false, milx::NumberOfProcessors(), "Threads");
93  ValueArg<std::string> outputArg("o", "output", "Output Surface", false, "result.vtk", "Output");
94  ValueArg<std::string> prefixArg("p", "prefix", "Output prefix for multiple output", false, "surface_", "Output Prefix");
95  ValueArg<std::string> outputFormatArg("", "outputformat", "Specify the default output format for multiple outputs (vtk, vtp, ply, stl, default: same as input)", false, "vtk", "Output format");
96 // MultiArg<std::string> altmultinames("s", "altsurfaces", "Another set of surfaces to be used in operation", false, "AltSurfaces");
97  ValueArg<float> decimateArg("d", "decimate", "Decimate all the meshes provided using the Quadric Decimate algorithm with decimation factor.", false, 0.5, "Decimate");
98  ValueArg<float> smoothArg("", "smooth", "Smooth all the meshes provided using the Windowed Sinc Algorithm with iterations.", false, 18, "Smooth");
99  ValueArg<float> laplacianArg("", "laplacian", "Smooth all the meshes provided using the Laplacian Algorithm with iterations.", false, 18, "Laplacian");
100  ValueArg<float> scaleArg("s", "scale", "Scale the coordinates of the points by scale.", false, 0.9, "Scale");
101  ValueArg<float> thresholdAboveArg("", "thresholdabove", "Thresold scalars above value.", false, 0.0, "Above");
102  ValueArg<float> thresholdBelowArg("", "thresholdbelow", "Thresold scalars below value.", false, 0.0, "Below");
103  ValueArg<float> clipArg("", "clip", "Clip model based on scalars value (keeping only parts with value).", false, 1.0, "Clip");
104  MultiArg<std::string> componentsArg("", "component", "Surface is a component of the surfaces.", false, "Component");
106  std::vector<size_t> axesAllowed;
107  axesAllowed.push_back(0);
108  axesAllowed.push_back(1);
109  axesAllowed.push_back(2);
110  ValuesConstraint<size_t> allowedAxesVals( axesAllowed );
111  ValueArg<size_t> flipArg("f", "flip", "Flip the meshes in the axis provided (0: x-axis, 1: y-axis, 2: z-axis).", false, 0, &allowedAxesVals);
113  SwitchArg partitionArg("", "partitionList", "Partition the list of surfaces provided into two for operating on one vs the other", false);
115  SwitchArg duplicateArg("", "duplicate", "Simply open and save the input file(s). Supports single (-o) or multiple (-p) input.", false);
116  SwitchArg convertArg("c", "convert", "Convert the model from the current format to the one given at output (from file extension). Supports single (-o) or multiple (-p) input.", false);
117  SwitchArg concatenateArg("", "cat", "Concatenate N surfaces into single mesh with filename provided.", false);
118  SwitchArg colourConcatenateArg("", "colourcat", "Concatenate N surfaces into single mesh with filename provided and colour them.", false);
119  SwitchArg splitArg("", "split", "Split each surface given components.", false);
120  SwitchArg diffScalarArg("", "scalardiff", "Compute the differences in Scalars.", false);
121  SwitchArg statsScalarArg("", "scalarstats", "Compute statistics of scalars (mean, variance etc. per point) output mesh with stats as arrays.", false);
122  SwitchArg removeScalarArg("", "scalarremove", "Remove the scalars.", false);
123  SwitchArg copyScalarArg("", "scalarcopy", "Copy the Scalars from first mesh to all others while removing existing ones.", false);
124  SwitchArg mseArg("", "mse", "Mean Squared Error of Points in models.", false);
125  SwitchArg procrustesArg("", "procrustes", "Similarity alignment of surfaces assuming points have correspondence. Use --rigid if rigid alignment is required.", false);
126  SwitchArg rigidArg("", "rigid", "Rigid alignment of surfaces assuming points have correspondence. Use with procrustes or other registration arguments.", false);
127  SwitchArg icpArg("", "icp", "Iterative Closest Points alignment of surfaces assuming points don't have correspondence. Last surface in list is used as the reference 'fixed' surface.", false);
128  SwitchArg saveTransformsArg("", "savetransforms", "Save the transformation matrix after surface alignment. For use with --icp", false);
129 
131  UnlabeledMultiArg<std::string> multinames("surfaces", "Surfaces to operate on", true, "Surfaces");
132 
134  ValueArg<float> voxeliseArg("", "voxelise", "Voxelise a model into image space with given spacing. Output will be in Nifty format (*.nii.gz).", false, 0.5, "Voxelise");
135  ValueArg<std::string> orientArg("", "orient", "Apply direction/orientation to a model from the given image", false, "image.nii.gz", "Orient");
136  ValueArg<size_t> flatArg("", "flatten", "Flatten a model to either a sphere (0) or plane (1). Needs to be a genus zero (no topological hole) mesh.", false, 0, "Flatten");
137 
139  cmd.add( threadsArg );
140  cmd.add( multinames );
141 // cmd.add( altmultinames );
142  cmd.add( outputArg );
143  cmd.add( prefixArg );
144  cmd.add( outputFormatArg );
145  cmd.add( componentsArg );
146  cmd.add( rigidArg );
147  cmd.add( partitionArg );
148  cmd.add( saveTransformsArg );
149 // cmd.add( thresholdAboveArg );
150 // cmd.add( thresholdBelowArg );
152  std::vector<Arg*> xorlist;
153  xorlist.push_back(&duplicateArg);
154  xorlist.push_back(&convertArg);
155  xorlist.push_back(&concatenateArg);
156  xorlist.push_back(&colourConcatenateArg);
157  xorlist.push_back(&splitArg);
158  xorlist.push_back(&scaleArg);
159  xorlist.push_back(&decimateArg);
160  xorlist.push_back(&smoothArg);
161  xorlist.push_back(&laplacianArg);
162  xorlist.push_back(&diffScalarArg);
163  xorlist.push_back(&statsScalarArg);
164  xorlist.push_back(&removeScalarArg);
165  xorlist.push_back(&copyScalarArg);
166  xorlist.push_back(&mseArg);
167  xorlist.push_back(&procrustesArg);
168  xorlist.push_back(&icpArg);
169  xorlist.push_back(&thresholdAboveArg);
170  xorlist.push_back(&thresholdBelowArg);
171  xorlist.push_back(&clipArg);
172  xorlist.push_back(&flipArg);
174  xorlist.push_back(&voxeliseArg);
175  xorlist.push_back(&orientArg);
176 #ifdef ITK_USE_REVIEW //Review only members
177  xorlist.push_back(&flatArg);
178 #endif
179 
181  cmd.xorAdd(xorlist);
182  cmd.parse( argc, argv );
183 
185  const size_t threads = threadsArg.getValue();
186  //Filenames of surfaces
187  std::vector<std::string> filenames = multinames.getValue();
188 // std::vector<std::string> altfilenames = altmultinames.getValue();
189  std::string outputName = outputArg.getValue();
190  std::string outputFormatName = outputFormatArg.getValue();
191  const std::string prefixName = prefixArg.getValue();
192  const float decimateFactor = decimateArg.getValue();
193  const float scaleFactor = scaleArg.getValue();
194  const float smoothIterations = smoothArg.getValue();
195  const float laplacianIterations = laplacianArg.getValue();
196  float thresholdAbove = thresholdAboveArg.getValue();
197  float thresholdBelow = thresholdBelowArg.getValue();
198  float clipValue = clipArg.getValue();
199  size_t flipAxis = flipArg.getValue();
200  std::vector<std::string> componentNames = componentsArg.getValue();
201 
203  vtkMultiThreader::SetGlobalDefaultNumberOfThreads(threads);
204  milx::PrintInfo("Threads to use: " + milx::NumberToString(threads));
205 
207  const float voxelSpacing = voxeliseArg.getValue();
208  std::string orientName = orientArg.getValue();
209  const size_t flatMode = flatArg.getValue();
210 
212  operations operation = none;
213  bool componentsValid = false;
214  if(duplicateArg.isSet())
215  {
216  //Duplicate files
217  milx::PrintInfo("Duplicating surfaces: ");
218  operation = duplicate;
219  }
220  if(convertArg.isSet())
221  {
222  //Info
223  milx::PrintInfo("Converting surfaces: ");
224 
225  //Info
226  operation = convert;
227  }
228  if(concatenateArg.isSet() || colourConcatenateArg.isSet())
229  {
230  //Cat
231  milx::PrintInfo("Concatenating surfaces: ");
232  operation = cat;
233  }
234  if(mseArg.isSet())
235  {
236  //Cat
237  milx::PrintInfo("MSE of surfaces: ");
238  operation = mse;
239  }
240  if(componentsArg.isSet())
241  {
242  if(!splitArg.isSet())
243  {
244  milx::PrintError("Components Argument Error: One or more of the operations");
245  milx::PrintError("required to use components is not set (such as split)");
246  milx::PrintError("Operations needing components are split.");
247  exit(EXIT_FAILURE);
248  }
249  milx::PrintInfo("Using components: ");
250  for(stringiterator name = componentNames.begin(); name != componentNames.end(); name ++)
251  std::cout << *name << ", ";
252  std::cout << std::endl;
253  }
254  if(splitArg.isSet())
255  {
256  //Split
257  if(!componentsArg.isSet())
258  {
259  milx::PrintError("Split Argument Error: Components of the given surfaces must be set.");
260  milx::PrintError("These surfaces provide info for the splitting process.");
261  milx::PrintError("Set components via the component argument as many times as needed.");
262  exit(EXIT_FAILURE);
263  }
264  milx::PrintInfo("For splitting surfaces: ");
265  operation = split;
266  componentsValid = true;
267  }
268  if(scaleArg.isSet())
269  {
270  //Scale
271  milx::PrintInfo("Scaling coordinates of each point in the surfaces: ");
272  operation = scale;
273  }
274  if(smoothArg.isSet())
275  {
276  //Smooth
277  milx::PrintInfo("Smoothing points in the surfaces: ");
278  operation = smooth;
279  }
280  if(laplacianArg.isSet())
281  {
282  //Smooth Laplacian
283  milx::PrintInfo("Laplacian smoothing points in the surfaces: ");
284  operation = laplacian;
285  }
286  if(decimateArg.isSet())
287  {
288  //Smooth
289  milx::PrintInfo("Decimating number of points in the surfaces: ");
290  operation = decimate;
291  }
292  if(thresholdAboveArg.isSet() || thresholdBelowArg.isSet())
293  {
294  if(!prefixArg.isSet())
295  {
296  milx::PrintError("Threshold Argument Error: Output Prefix (-p) must be provided.");
297  milx::PrintError("Re-run with the prefix name set.");
298  exit(EXIT_FAILURE);
299  }
300  if(thresholdAboveArg.isSet() && !thresholdBelowArg.isSet())
301  {
302  thresholdBelow = -std::numeric_limits<float>::max(); //min negative value
303  }
304  else if(!thresholdAboveArg.isSet() && thresholdBelowArg.isSet())
305  {
306  thresholdAbove = std::numeric_limits<float>::max();
307  }
308  std::cout << "Threshold Above Value: " << thresholdAbove << std::endl;
309  std::cout << "Threshold Below Value: " << thresholdBelow << std::endl;
310  //threshold
311  milx::PrintInfo("Thresholding Scalars of surfaces: ");
312  operation = thresholdscalars;
313  }
314  if(clipArg.isSet())
315  {
316  //Scale
317  milx::PrintInfo("Clipping surfaces: ");
318  operation = clip;
319  }
320  if(diffScalarArg.isSet())
321  {
322  //Scale
323  milx::PrintInfo("Differencing Scalars of surfaces: ");
324  operation = diffscalars;
325  }
326  if(flipArg.isSet())
327  {
328  //Scale
329  milx::PrintInfo("Flipping surfaces: ");
330  operation = flip;
331  }
332  if(statsScalarArg.isSet())
333  {
334  //Scale
335  milx::PrintInfo("Statistics of Scalars in surfaces: ");
336  operation = statscalars;
337  }
338  if(removeScalarArg.isSet())
339  {
340  //Remove scalars
341  milx::PrintInfo("Removing Scalars of surfaces: ");
342  operation = removescalars;
343  }
344  if(copyScalarArg.isSet())
345  {
346  if(filenames.size() == 1)
347  {
348  milx::PrintError("Argument Error: Need another filename to copy from mesh A to mesh B.");
349  exit(EXIT_FAILURE);
350  }
351  else if(filenames.size() == 2 && !outputArg.isSet())
352  {
353  milx::PrintError("Argument Error: Use Output (-o) for copying from mesh A to mesh B.");
354  milx::PrintError("Re-run with the output name set.");
355  exit(EXIT_FAILURE);
356  }
357  else if(filenames.size() > 2 && !prefixArg.isSet())
358  {
359  milx::PrintError("Argument Error: Output Prefix (-p) must be provided for more than 2 meshes.");
360  milx::PrintError("Re-run with the prefix name set.");
361  exit(EXIT_FAILURE);
362  }
363 
364  //Remove scalars
365  milx::PrintInfo("Copying Scalars of surfaces: ");
366  operation = copyscalars;
367  }
368  if(rigidArg.isSet() && (!procrustesArg.isSet() && !icpArg.isSet()))
369  {
370  //Scale
371  milx::PrintError("Rigid option can only be used with the Procrustes/ICP option");
372  exit(EXIT_FAILURE);
373  }
374  if(procrustesArg.isSet())
375  {
376  if(!prefixArg.isSet())
377  {
378  milx::PrintError("Procrustes Argument Error: Output Prefix (-p) must be provided.");
379  milx::PrintError("Re-run with the prefix name set.");
380  exit(EXIT_FAILURE);
381  }
382  //align
383  milx::PrintInfo("Computing Procrustes Alignment of surfaces: ");
384  operation = procrustes;
385  }
386  if(icpArg.isSet())
387  {
388  if(!prefixArg.isSet())
389  {
390  milx::PrintError("ICP Argument Error: Output Prefix (-p) must be provided.");
391  milx::PrintError("Re-run with the prefix name set.");
392  exit(EXIT_FAILURE);
393  }
394  //align
395  milx::PrintInfo("Computing ICP Alignment of surfaces: ");
396  operation = icp;
397  }
398 
400  if(voxeliseArg.isSet())
401  {
402  if(!prefixArg.isSet())
403  {
404  milx::PrintError("Voxelise Argument Error: Output Prefix (-p) must be provided.");
405  milx::PrintError("Re-run with the prefix name set.");
406  exit(EXIT_FAILURE);
407  }
408  if(!outputFormatArg.isSet())
409  {
410  milx::PrintWarning("No output format set. Using Nifty format (nii.gz) by default.");
411  outputFormatName = "nii.gz";
412  }
413  //voxel
414  milx::PrintInfo("Voxelising surfaces: ");
415  operation = voxelise;
416  }
417  if(orientArg.isSet())
418  {
419  if(!prefixArg.isSet())
420  {
421  milx::PrintError("Orient Argument Error: Output Prefix (-p) must be provided.");
422  milx::PrintError("Re-run with the prefix name set.");
423  exit(EXIT_FAILURE);
424  }
425  //orient
426  milx::PrintInfo("Orienting surfaces: ");
427  operation = orient;
428  }
429  if(flatArg.isSet())
430  {
431  if(!prefixArg.isSet())
432  {
433  milx::PrintError("Orient Argument Error: Output Prefix (-p) must be provided.");
434  milx::PrintError("Re-run with the prefix name set.");
435  exit(EXIT_FAILURE);
436  }
437  //flat
438  milx::PrintInfo("Flattening surfaces: ");
439  operation = flat;
440  }
441 
443  std::vector<std::string> altfilenames;
444  if(partitionArg.isSet())
445  {
446  for(size_t j = filenames.size()/2; j < filenames.size(); j ++)
447  altfilenames.push_back( filenames[j] );
448 
449  for(size_t j = 0; j < altfilenames.size(); j ++)
450  filenames.pop_back();
451  }
452 
453  std::cout << "Total Surfaces: " << filenames.size() << std::endl;
454  for(stringiterator name = filenames.begin(); name != filenames.end(); name ++)
455  std::cout << *name << ", ";
456  std::cout << std::endl;
457 
458  if(partitionArg.isSet())
459  {
460  if(!diffScalarArg.isSet())
461  {
462  milx::PrintError("Partitioning list of surfaces is only supported with the following operations:");
463  milx::PrintError(diffScalarArg.getName());
464  exit(EXIT_FAILURE);
465  }
466  if(!prefixArg.isSet())
467  {
468  milx::PrintError("Partition Surfaces List Argument Error: Output Prefix (-p) must be provided.");
469  milx::PrintError("Re-run with the prefix name set.");
470  exit(EXIT_FAILURE);
471  }
472 
473  //alt
474  milx::PrintInfo("Operation will be applied in conjuction with surfaces: ");
475  std::cout << "Total Surfaces: " << altfilenames.size() << std::endl;
476  for(stringiterator name = altfilenames.begin(); name != altfilenames.end(); name ++)
477  std::cout << *name << ", ";
478  std::cout << std::endl;
479 
480  if(diffScalarArg.isSet())
481  operation = diffscalarspairs;
482  }
483 
484  //---------------------------
486  std::cerr << "Reading Surfaces... ";
487  vtkSmartPointer<vtkPolyDataCollection> collection;
488  if( !milx::File::OpenModelCollection(filenames, collection) ) //Error printed inside
489  exit(EXIT_FAILURE);
490  std::cerr << "Done" << std::endl;
491  std::cout << "Read " << collection->GetNumberOfItems() << " models" << std::endl;
492 
493  vtkSmartPointer<vtkPolyDataCollection> altcollection;
494  if(partitionArg.isSet())
495  {
496  std::cerr << "Reading Alterate Surfaces... ";
497  if( !milx::File::OpenModelCollection(altfilenames, altcollection) ) //Error printed inside
498  exit(EXIT_FAILURE);
499  std::cerr << "Done" << std::endl;
500  }
501 
502  vtkSmartPointer<vtkPolyDataCollection> components;
503  if(componentsArg.isSet() && componentsValid)
504  {
505  std::cerr << "Reading Components... ";
506  if( !milx::File::OpenModelCollection(componentNames, components) ) //Error printed inside
507  exit(EXIT_FAILURE);
508  std::cerr << "Done" << std::endl;
509  }
510 
512  itk::SmartPointer<charImageType> refImage;
513  if(orientArg.isSet())
514  {
515  std::cerr << "Reading Reference Image... "; //dont need to read data just header
516  if( !milx::File::OpenImage<charImageType>(orientName, refImage) ) //Error printed inside
517  exit(EXIT_FAILURE);
518  std::cerr << "Done" << std::endl;
519  }
520 
521  if(colourConcatenateArg.isSet())
522  {
523  size_t count = 0;
524  collection->InitTraversal();
525  for(int j = 0; j < collection->GetNumberOfItems(); j ++)
526  {
527  vtkSmartPointer<vtkPolyData> mesh = collection->GetNextItem();
528  const size_t numPoints = mesh->GetNumberOfPoints();
529 
530  vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
531  weights->SetNumberOfComponents(1);
532  weights->SetNumberOfTuples(numPoints);
533  weights->FillComponent(0, count);
534 
535  mesh->GetPointData()->SetScalars(weights);
536  count ++;
537  }
538  }
539 
540  //---------------------------
542  vtkSmartPointer<vtkTransformCollection> transformCollection = vtkSmartPointer<vtkTransformCollection>::New();
543 
544  //---------------------------
546  milx::DeformableModel Model;
547  bool outputRequired = true;
548  bool multiOutputRequired = false;
549  bool standardOperation = false;
550  bool imageOutputRequired = false;
551  vtkSmartPointer<vtkPolyDataCollection> resultCollections;
552  std::vector< itk::SmartPointer<charImageType> > imgCollection;
553 
554  if (collection->GetNumberOfItems() == 1)
555  {
556  outputRequired = true;
557  multiOutputRequired = false;
558  }
559  else
560  {
561  outputRequired = false;
562  multiOutputRequired = true;
563  }
564 
565  std::cerr << "Applying... ";
566  switch(operation)
567  {
568  case duplicate: //Tested 04/2016
569  standardOperation = true;
570  break;
571 
572  case convert: //Tested 04/2016
573  standardOperation = true; //requires user to set output format
574  break;
575 
576  case cat: //Tested 04/2016
577  Model.ConcatenateCollection(collection);
578  outputRequired = true;
579  multiOutputRequired = false;
580  break;
581 
582  case mse: //--------------------------------
583  milx::PrintInfo( "MSE: " + milx::NumberToString(Model.MeanSquaredErrorCollection(collection)) );
584  outputRequired = false; //write mean
585  break;
586 
587  case split: //--------------------------------
588  {// scope for local variables
589  std::vector< vtkSmartPointer<vtkPolyDataCollection> > splitCollections;
590 
591  //Split surfaces
592  Model.SplitCollection(collection, components, splitCollections);
593 
594  //write
595  typedef std::vector< vtkSmartPointer<vtkPolyDataCollection> >::iterator iterator;
596  stringiterator name = filenames.begin();
597  for(iterator surfaces = splitCollections.begin();
598  surfaces != splitCollections.end();
599  surfaces ++, name ++)
600  {
601  std::vector<std::string> splitNames;
602 
603  std::string splitName = prefixName + milx::File::GetBaseName(*name) + "_";
604  std::string ext = milx::File::GetFileExtension(*name);
605  for(stringiterator componentname = componentNames.begin(); componentname != componentNames.end(); componentname ++)
606  {
607  splitNames.push_back(splitName + milx::File::GetBaseName(*componentname) + "." + ext);
608  milx::PrintInfo("Wrote " + splitName + milx::File::GetBaseName(*componentname) + "." + ext);
609  }
610  if( !milx::File::SaveModelCollection(splitNames, *surfaces) )
611  exit(EXIT_FAILURE);
612  }
613  }// scope for local variables
614 
615  outputRequired = false;
616  multiOutputRequired = false;
617  break;
618 
619  case scale: //Tested 04/2016
620  Model.ScaleCollection(collection, scaleFactor);
621 
622  standardOperation = true;
623  break;
624 
625  case smooth: //Tested 04/2016
626  Model.SmoothCollection(collection, smoothIterations);
627 
628  standardOperation = true;
629  break;
630 
631  case laplacian: //Tested 04/2016
632  Model.LaplacianCollection(collection, laplacianIterations);
633 
634  standardOperation = true;
635  break;
636 
637  case decimate: //Tested 04/2016
638  Model.DecimateCollection(collection, decimateFactor);
639 
640  standardOperation = true;
641  break;
642 
643  case thresholdscalars:
644  Model.ScalarThresholdCollection(collection, thresholdAbove, thresholdBelow);
645 
646  standardOperation = true;
647  break;
648 
649  case clip:
650  Model.ClipCollection(collection, clipValue, clipValue);
651 
652  standardOperation = true;
653  break;
654 
655  case flip:
656  {
657  bool xAxis = false, yAxis = false, zAxis = false;
658  if(flipAxis == 2)
659  zAxis = true;
660  else if(flipAxis == 1)
661  yAxis = true;
662  else
663  xAxis = true;
664  Model.FlipCollection(collection, xAxis, yAxis, zAxis);
665 
666  standardOperation = true;
667  break;
668  }
669 
670  case diffscalars:
671  Model.ScalarDifferenceCollection(collection);
672  break;
673 
674  case diffscalarspairs:
675  resultCollections = vtkSmartPointer<vtkPolyDataCollection>::New();
676  Model.ScalarDifferenceCollection(collection, altcollection, resultCollections);
677 
678  standardOperation = true;
679  collection = resultCollections;
680  break;
681 
682  case statscalars:
683  Model.ScalarStatisticsCollection(collection);
684  break;
685 
686  case removescalars:
687  Model.ScalarRemoveCollection(collection);
688 
689  standardOperation = true;
690  break;
691 
692  case copyscalars:
693  Model.ScalarCopyCollection(collection);
694 
695  if(filenames.size() == 2)
696  {
697  outputRequired = true;
698  multiOutputRequired = false;
699  collection->InitTraversal();
700  collection->GetNextItem();
701  Model.SetInput(collection->GetNextItem());
702  }
703  else
704  standardOperation = true;
705  break;
706 
707  case procrustes:
708  {
709  collection = Model.ProcrustesAlignCollection(collection, rigidArg.isSet());
710 
711  std::string ext = milx::File::GetFileExtension(filenames[0]);
712  outputName = prefixName + "_mean." + ext;
713  outputRequired = true; //write mean
714  multiOutputRequired = true; //write collection
715  break;
716  } //scope for ext
717 
718  case icp:
719  collection = Model.IterativeClosestPointsAlignCollection(collection, rigidArg.isSet(), transformCollection);
720 
721  standardOperation = true; //write collection
722  break;
723 
725  case voxelise:
726  Model.VoxeliseCollection<charImageType>(collection, voxelSpacing, imgCollection);
727 
728  outputRequired = false;
729  multiOutputRequired = true;
730  imageOutputRequired = true;
731  break;
732 
733  case orient:
734  Model.ApplyOrientationCollection<charImageType>(collection, refImage);
735 
736  outputRequired = false;
737  multiOutputRequired = true;
738  break;
739 #ifdef ITK_USE_REVIEW //Review only members
740  case flat:
741  Model.FlattenCollection(collection, flatMode);
742 
743  outputRequired = false;
744  multiOutputRequired = true;
745  break;
746 #endif
747 
748  case none: //--------------------------------
749  break;
750  }
751  std::cerr << "Done" << std::endl;
752 
753  if (collection->GetNumberOfItems() == 1 && standardOperation)
754  {
755  collection->InitTraversal();
756  Model.Result() = collection->GetNextItem();
757  }
758 
759  //---------------------------
761  if(outputRequired)
762  {
763  milx::PrintInfo("Writing result to " + outputName);
764  milx::File::SaveModel(outputName, Model.Result());
765  }
766  if(multiOutputRequired)
767  {
768  if(collection->GetNumberOfItems() > 0)
769  {
770  const int N = collection->GetNumberOfItems();
771 
772  milx::PrintInfo("Writing results with prefix " + prefixName);
773  std::vector<std::string> names;
774 
775  int n = 0;
776  for(stringiterator filename = filenames.begin(); filename != filenames.end() && n < N; filename ++, n ++)
777  {
778  std::string ext;
779  if (outputFormatArg.isSet() || imageOutputRequired) {
780  ext = outputFormatName;
781  } else {
782  ext = milx::File::GetFileExtension(*filename);
783  }
784 
785  names.push_back(prefixName + milx::File::GetBaseName(*filename) + "." + ext);
786  milx::PrintInfo("Will be writing " + prefixName + milx::File::GetBaseName(*filename) + "." + ext);
787  }
788 
789  if(imageOutputRequired)
790  milx::File::SaveImages<charImageType>(names, imgCollection);
791  else
792  milx::File::SaveModelCollection(names, collection);
793 
794  // Saving the vtkTransforms
795  if (saveTransformsArg.isSet() && transformCollection->GetNumberOfItems() == collection->GetNumberOfItems())
796  {
797  const std::string ext = "trsf.gz";
798  std::vector<std::string> tnames;
799  n = 0;
800  for(stringiterator name = names.begin(); name != names.end() && n < N; name ++, n++)
801  {
802  tnames.push_back(milx::File::StripFileExtension(*name) + "." + ext);
803  milx::PrintInfo("Will be writing " + tnames.back());
804  }
805  milx::File::SaveTransformCollection(tnames, transformCollection, false);
806  }
807  }
808  else
809  {
810  milx::PrintError("Result was empty. Skipping Output.");
811  }
812  }
813 
814  milx::PrintInfo("Operation Complete");
815  return EXIT_SUCCESS;
816 }
void ScalarStatisticsCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Computes the statistics (min, max, variance etc.) of the scalars over the collection assuming the mes...
Definition: milxModel.cxx:1831
void ConcatenateCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Concatenates all the models in the collection together into one model.
Definition: milxModel.cxx:1620
void ScaleCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const coordinateType scale)
Scales the coordinates of each point in all the models in the collection.
Definition: milxModel.cxx:1629
void PrintError(const std::string msg)
Displays a generic msg to standard error with carriage return.
Definition: milxGlobal.h:202
void DecimateCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const coordinateType factor)
Decimates all points in all the models in the collection using the Quadric algorithm algorithm...
Definition: milxModel.cxx:1689
This program Animates image slices and animates surfaces in the model view for creating movies...
static bool OpenModelCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkPolyDataCollection > &collection)
Opens model files, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
Definition: milxFile.cxx:611
void SplitCollection(vtkSmartPointer< vtkPolyDataCollection > collection, vtkSmartPointer< vtkPolyDataCollection > components, std::vector< vtkSmartPointer< vtkPolyDataCollection > > &splitCollections)
Splits each of the models in the collection into a collection of models.
Definition: milxModel.cxx:1706
vtkSmartPointer< vtkPolyData > & Result()
Returns the current model, i.e. the result of the latest operation.
Definition: milxModel.h:202
vtkSmartPointer< vtkPolyDataCollection > ProcrustesAlignCollection(vtkSmartPointer< vtkPolyDataCollection > collection, bool rigid=false)
Aligns the collection to the mean mesh (computed internally) of the collection assuming the meshes ha...
Definition: milxModel.cxx:1970
void SmoothCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const size_t iterations)
Smoothes all points in all the models in the collection using the Windowed Sinc algorithm.
Definition: milxModel.cxx:1638
void VoxeliseCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const coordinateType spacing, std::vector< typename itk::SmartPointer< TImage > > &images)
Voxelise a collection of models with isotropic spacing given. A vector of image pointers in set to &#39;i...
static bool SaveTransformCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkTransformCollection > collection, const bool ITK=false)
Saves transform files, which can be VTK .trsf or ITK from a collection.
Definition: milxFile.cxx:726
static bool SaveModelCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkPolyDataCollection > collection, const bool binary=false)
Saves model files, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
Definition: milxFile.cxx:697
void ApplyOrientationCollection(vtkSmartPointer< vtkPolyDataCollection > collection, itk::SmartPointer< TImage > refImage, const bool applyOrigin=true, const bool flipY=false)
Apply orientation/direction of a reference image to a collection of models.
void SetInput(vtkSmartPointer< vtkPolyData > model)
Assigns the input model to class.
Definition: milxModel.cxx:130
void ScalarThresholdCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const coordinateType aboveVal, const coordinateType belowVal)
Computes the Threshold of scalar values of meshes in place over the collection wrt the first mesh ass...
Definition: milxModel.cxx:1771
void PrintWarning(const std::string msg)
Displays a generic msg to standard output with carriage return.
Definition: milxGlobal.h:183
static bool SaveModel(const std::string filename, vtkSmartPointer< vtkPolyData > data, const bool binary=false)
Saves a model as a file, which can be a VTK XML or Legacy VTK PolyData File (i.e. either a *...
Definition: milxFile.cxx:628
void PrintInfo(const std::string msg)
Displays a generic msg to standard output with carriage return.
Definition: milxGlobal.h:174
std::string NumberToString(double num, unsigned zeroPad=0)
Number to string converter.
Definition: milxGlobal.h:112
double MeanSquaredErrorCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Computes the MSE of all models in collection accummulatively.
Definition: milxModel.cxx:1946
Represents a deformable model (i.e. a model with cells and scalar values that has special members for...
void ScalarCopyCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Copies the scalars over the collection (from the first mesh) assuming the meshes have the same number...
Definition: milxModel.cxx:1930
void LaplacianCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const size_t iterations)
Smoothes all points in all the models in the collection using the Laplacian algorithm.
Definition: milxModel.cxx:1655
void ScalarRemoveCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Removes the scalars over the collection assuming the meshes have the same number of points...
Definition: milxModel.cxx:1917
int main(int argc, char *argv[])
void FlipCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const bool xAxis, const bool yAxis, const bool zAxis)
Flips all points in all the models in the collection using the axis provided.
Definition: milxModel.cxx:1672
static std::string GetFileExtension(const std::string &filename)
Returns the file extension (in lower case) of the given filename.
Definition: milxFile.h:472
unsigned NumberOfProcessors()
Number of processors or cores on the machine.
Definition: milxGlobal.h:124
void ClipCollection(vtkSmartPointer< vtkPolyDataCollection > collection, const coordinateType aboveVal, const coordinateType belowVal)
Computes the Clipping of models via the Threshold of scalar values in place over the collection...
Definition: milxModel.cxx:1784
void ScalarDifferenceCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Computes the difference in scalars cummulatively over the collection wrt the first mesh assuming the ...
Definition: milxModel.cxx:1753
vtkSmartPointer< vtkPolyDataCollection > IterativeClosestPointsAlignCollection(vtkSmartPointer< vtkPolyDataCollection > collection, bool rigid=false, vtkSmartPointer< vtkTransformCollection > tCollection=0)
Aligns the collection to the mean mesh (computed internally) of the collection without needing corres...
Definition: milxModel.cxx:2064