SMILX  1.01
milxModelApp.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 <milxModel.h>
30 
31 using namespace TCLAP;
32 
33 typedef std::vector< std::string >::iterator stringiterator;
34 
35 //Supported operations
36 enum operations {none = 0, convert, duplicate, cat, split, scale, decimate, smooth, laplacian, thresholdscalars, clip, flip, diffscalars, copyscalars, diffscalarspairs, statscalars, removescalars, mse, procrustes, icp};
37 
71 int main(int argc, char *argv[])
72 {
73  //---------------------------
75  milx::PrintInfo("--------------------------------------------------------");
76  milx::PrintInfo("SMILI Model Tool for Models/Surfaces/Meshes.");
77  milx::PrintInfo("(c) Copyright Chandra et al., 2015.");
78  milx::PrintInfo("Version: " + milx::NumberToString(milx::Version));
79  milx::PrintInfo("University of Queensland, Australia.");
80  milx::PrintInfo("Australian e-Health Research Centre, CSIRO, Australia.");
81  milx::PrintInfo("--------------------------------------------------------\n");
82 
83  //---------------------------
85  CmdLine cmd("A diagnostic tool for models/surface operations", ' ', milx::NumberToString(milx::Version));
86 
88  ValueArg<size_t> threadsArg("", "threads", "Set he number of global threads to use.", false, milx::NumberOfProcessors(), "Threads");
89  ValueArg<std::string> outputArg("o", "output", "Output Surface", false, "result.vtk", "Output");
90  ValueArg<std::string> prefixArg("p", "prefix", "Output prefix for multiple output", false, "surface_", "Output Prefix");
91  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");
92 // MultiArg<std::string> altmultinames("s", "altsurfaces", "Another set of surfaces to be used in operation", false, "AltSurfaces");
93  ValueArg<float> decimateArg("d", "decimate", "Decimate all the meshes provided using the Quadric Decimate algorithm with decimation factor.", false, 0.5, "Decimate");
94  ValueArg<float> smoothArg("", "smooth", "Smooth all the meshes provided using the Windowed Sinc Algorithm with iterations.", false, 18, "Smooth");
95  ValueArg<float> laplacianArg("", "laplacian", "Smooth all the meshes provided using the Laplacian Algorithm with iterations.", false, 18, "Laplacian");
96  ValueArg<float> scaleArg("s", "scale", "Scale the coordinates of the points by scale.", false, 0.9, "Scale");
97  ValueArg<float> thresholdAboveArg("", "thresholdabove", "Thresold scalars above value.", false, 0.0, "Above");
98  ValueArg<float> thresholdBelowArg("", "thresholdbelow", "Thresold scalars below value.", false, 0.0, "Below");
99  ValueArg<float> clipArg("", "clip", "Clip model based on scalars value (keeping only parts with value).", false, 1.0, "Clip");
100  MultiArg<std::string> componentsArg("", "component", "Surface is a component of the surfaces.", false, "Component");
102  std::vector<size_t> axesAllowed;
103  axesAllowed.push_back(0);
104  axesAllowed.push_back(1);
105  axesAllowed.push_back(2);
106  ValuesConstraint<size_t> allowedAxesVals( axesAllowed );
107  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);
109  SwitchArg partitionArg("", "partitionList", "Partition the list of surfaces provided into two for operating on one vs the other", false);
111  SwitchArg duplicateArg("", "duplicate", "Simply open and save the input file(s). Supports single (-o) or multiple (-p) input.", false);
112  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);
113  SwitchArg concatenateArg("", "cat", "Concatenate N surfaces into single mesh with filename provided.", false);
114  SwitchArg colourConcatenateArg("", "colourcat", "Concatenate N surfaces into single mesh with filename provided and colour them.", false);
115  SwitchArg splitArg("", "split", "Split each surface given components.", false);
116  SwitchArg diffScalarArg("", "scalardiff", "Compute the differences in Scalars to the first mesh in list.", false);
117  SwitchArg statsScalarArg("", "scalarstats", "Compute statistics of scalars (mean, variance etc. per point) output mesh with stats as arrays.", false);
118  SwitchArg removeScalarArg("", "scalarremove", "Remove the scalars.", false);
119  SwitchArg copyScalarArg("", "scalarcopy", "Copy the Scalars from first mesh to all others while removing existing ones.", false);
120  SwitchArg mseArg("", "mse", "Mean Squared Error of Points in models.", false);
121  SwitchArg procrustesArg("", "procrustes", "Similarity alignment of surfaces assuming points have correspondence. Use --rigid if rigid alignment is required.", false);
122  SwitchArg rigidArg("", "rigid", "Rigid alignment of surfaces assuming points have correspondence. Use with procrustes or other registration arguments.", false);
123  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);
124  SwitchArg saveTransformsArg("", "savetransforms", "Save the transformation matrix after surface alignment. For use with --icp", false);
125 
127  UnlabeledMultiArg<std::string> multinames("surfaces", "Surfaces to operate on", true, "Surfaces");
128 
130  cmd.add( threadsArg );
131  cmd.add( multinames );
132 // cmd.add( altmultinames );
133  cmd.add( outputArg );
134  cmd.add( prefixArg );
135  cmd.add( outputFormatArg );
136  cmd.add( componentsArg );
137  cmd.add( rigidArg );
138  cmd.add( partitionArg );
139  cmd.add( saveTransformsArg );
140 // cmd.add( thresholdAboveArg );
141 // cmd.add( thresholdBelowArg );
143  std::vector<Arg*> xorlist;
144  xorlist.push_back(&duplicateArg);
145  xorlist.push_back(&convertArg);
146  xorlist.push_back(&concatenateArg);
147  xorlist.push_back(&colourConcatenateArg);
148  xorlist.push_back(&splitArg);
149  xorlist.push_back(&scaleArg);
150  xorlist.push_back(&decimateArg);
151  xorlist.push_back(&smoothArg);
152  xorlist.push_back(&laplacianArg);
153  xorlist.push_back(&diffScalarArg);
154  xorlist.push_back(&statsScalarArg);
155  xorlist.push_back(&removeScalarArg);
156  xorlist.push_back(&copyScalarArg);
157  xorlist.push_back(&mseArg);
158  xorlist.push_back(&procrustesArg);
159  xorlist.push_back(&icpArg);
160  xorlist.push_back(&thresholdAboveArg);
161  xorlist.push_back(&thresholdBelowArg);
162  xorlist.push_back(&clipArg);
163  xorlist.push_back(&flipArg);
164  cmd.xorAdd(xorlist);
165 
167  cmd.parse( argc, argv );
168 
170  const size_t threads = threadsArg.getValue();
171  //Filenames of surfaces
172  std::vector<std::string> filenames = multinames.getValue();
173 // std::vector<std::string> altfilenames = altmultinames.getValue();
174  std::string outputName = outputArg.getValue();
175  const std::string prefixName = prefixArg.getValue();
176  const float decimateFactor = decimateArg.getValue();
177  const float scaleFactor = scaleArg.getValue();
178  const float smoothIterations = smoothArg.getValue();
179  const float laplacianIterations = laplacianArg.getValue();
180  float thresholdAbove = thresholdAboveArg.getValue();
181  float thresholdBelow = thresholdBelowArg.getValue();
182  float clipValue = clipArg.getValue();
183  size_t flipAxis = flipArg.getValue();
184  std::vector<std::string> componentNames = componentsArg.getValue();
185 
187  vtkMultiThreader::SetGlobalDefaultNumberOfThreads(threads);
188  milx::PrintInfo("Threads to use: " + milx::NumberToString(threads));
189 
191  operations operation = none;
192  bool componentsValid = false;
193  if(duplicateArg.isSet())
194  {
195  //Duplicate files
196  milx::PrintInfo("Duplicating surfaces: ");
197  operation = duplicate;
198  }
199  if(convertArg.isSet())
200  {
201  //Info
202  milx::PrintInfo("Converting surfaces: ");
203  operation = convert;
204  }
205  if(concatenateArg.isSet() || colourConcatenateArg.isSet())
206  {
207  //Cat
208  milx::PrintInfo("Concatenating surfaces: ");
209  operation = cat;
210  }
211  if(mseArg.isSet())
212  {
213  //Cat
214  milx::PrintInfo("MSE of surfaces: ");
215  operation = mse;
216  }
217  if(componentsArg.isSet())
218  {
219  if(!splitArg.isSet())
220  {
221  milx::PrintError("Components Argument Error: One or more of the operations");
222  milx::PrintError("required to use components is not set (such as split)");
223  milx::PrintError("Operations needing components are split.");
224  exit(EXIT_FAILURE);
225  }
226  milx::PrintInfo("Using components: ");
227  for(stringiterator name = componentNames.begin(); name != componentNames.end(); name ++)
228  std::cout << *name << ", ";
229  std::cout << std::endl;
230  }
231  if(splitArg.isSet())
232  {
233  //Split
234  if(!componentsArg.isSet())
235  {
236  milx::PrintError("Split Argument Error: Components of the given surfaces must be set.");
237  milx::PrintError("These surfaces provide info for the splitting process.");
238  milx::PrintError("Set components via the component argument as many times as needed.");
239  exit(EXIT_FAILURE);
240  }
241  milx::PrintInfo("For splitting surfaces: ");
242  operation = split;
243  componentsValid = true;
244  }
245  if(scaleArg.isSet())
246  {
247  //Scale
248  milx::PrintInfo("Scaling coordinates of each point in the surfaces: ");
249  operation = scale;
250  }
251  if(smoothArg.isSet())
252  {
253  //Smooth
254  milx::PrintInfo("Smoothing points in the surfaces: ");
255  operation = smooth;
256  }
257  if(laplacianArg.isSet())
258  {
259  //Smooth Laplacian
260  milx::PrintInfo("Laplacian smoothing points in the surfaces: ");
261  operation = laplacian;
262  }
263  if(decimateArg.isSet())
264  {
265  //Smooth
266  milx::PrintInfo("Decimating number of points in the surfaces: ");
267  operation = decimate;
268  }
269  if(thresholdAboveArg.isSet() || thresholdBelowArg.isSet())
270  {
271  if(!prefixArg.isSet())
272  {
273  milx::PrintError("Threshold Argument Error: Output Prefix (-p) must be provided.");
274  milx::PrintError("Re-run with the prefix name set.");
275  exit(EXIT_FAILURE);
276  }
277  if(thresholdAboveArg.isSet() && !thresholdBelowArg.isSet())
278  {
279  thresholdBelow = -std::numeric_limits<float>::max(); //min negative value
280  }
281  else if(!thresholdAboveArg.isSet() && thresholdBelowArg.isSet())
282  {
283  thresholdAbove = std::numeric_limits<float>::max();
284  }
285  std::cout << "Threshold Above Value: " << thresholdAbove << std::endl;
286  std::cout << "Threshold Below Value: " << thresholdBelow << std::endl;
287  //threshold
288  milx::PrintInfo("Thresholding Scalars of surfaces: ");
289  operation = thresholdscalars;
290  }
291  if(clipArg.isSet())
292  {
293  //Scale
294  milx::PrintInfo("Clipping surfaces: ");
295  operation = clip;
296  }
297  if(diffScalarArg.isSet())
298  {
299  //Scale
300  milx::PrintInfo("Differencing Scalars of surfaces: ");
301  operation = diffscalars;
302  }
303  if(flipArg.isSet())
304  {
305  //Scale
306  milx::PrintInfo("Flipping surfaces: ");
307  operation = flip;
308  }
309  if(statsScalarArg.isSet())
310  {
311  //Scale
312  milx::PrintInfo("Statistics of Scalars in surfaces: ");
313  operation = statscalars;
314  }
315  if(removeScalarArg.isSet())
316  {
317  //Remove scalars
318  milx::PrintInfo("Removing Scalars of surfaces: ");
319  operation = removescalars;
320  }
321  if(copyScalarArg.isSet())
322  {
323  if(filenames.size() == 1)
324  {
325  milx::PrintError("Argument Error: Need another filename to copy from mesh A to mesh B.");
326  exit(EXIT_FAILURE);
327  }
328  else if(filenames.size() == 2 && !outputArg.isSet())
329  {
330  milx::PrintError("Argument Error: Use Output (-o) for copying from mesh A to mesh B.");
331  milx::PrintError("Re-run with the output name set.");
332  exit(EXIT_FAILURE);
333  }
334  else if(filenames.size() > 2 && !prefixArg.isSet())
335  {
336  milx::PrintError("Argument Error: Output Prefix (-p) must be provided for more than 2 meshes.");
337  milx::PrintError("Re-run with the prefix name set.");
338  exit(EXIT_FAILURE);
339  }
340 
341  //Remove scalars
342  milx::PrintInfo("Copying Scalars of surfaces: ");
343  operation = copyscalars;
344  }
345  if(rigidArg.isSet() && (!procrustesArg.isSet() && !icpArg.isSet()))
346  {
347  //Scale
348  milx::PrintError("Rigid option can only be used with the Procrustes/ICP option");
349  exit(EXIT_FAILURE);
350  }
351  if(procrustesArg.isSet())
352  {
353  if(!prefixArg.isSet())
354  {
355  milx::PrintError("Procrustes Argument Error: Output Prefix (-p) must be provided.");
356  milx::PrintError("Re-run with the prefix name set.");
357  exit(EXIT_FAILURE);
358  }
359  //align
360  milx::PrintInfo("Computing Procrustes Alignment of surfaces: ");
361  operation = procrustes;
362  }
363  if(icpArg.isSet())
364  {
365  if(!prefixArg.isSet())
366  {
367  milx::PrintError("ICP Argument Error: Output Prefix (-p) must be provided.");
368  milx::PrintError("Re-run with the prefix name set.");
369  exit(EXIT_FAILURE);
370  }
371  //align
372  milx::PrintInfo("Computing ICP Alignment of surfaces: ");
373  operation = icp;
374  }
375 
377  std::vector<std::string> altfilenames;
378  if(partitionArg.isSet())
379  {
380  for(size_t j = filenames.size()/2; j < filenames.size(); j ++)
381  altfilenames.push_back( filenames[j] );
382 
383  for(size_t j = 0; j < altfilenames.size(); j ++)
384  filenames.pop_back();
385  }
386 
387  std::cout << "Total Surfaces: " << filenames.size() << std::endl;
388  for(stringiterator name = filenames.begin(); name != filenames.end(); name ++)
389  std::cout << *name << ", ";
390  std::cout << std::endl;
391 
392  if(partitionArg.isSet())
393  {
394  if(!diffScalarArg.isSet())
395  {
396  milx::PrintError("Partitioning list of surfaces is only supported with the following operations:");
397  milx::PrintError(diffScalarArg.getName());
398  exit(EXIT_FAILURE);
399  }
400  if(!prefixArg.isSet())
401  {
402  milx::PrintError("Partition Surfaces List Argument Error: Output Prefix (-p) must be provided.");
403  milx::PrintError("Re-run with the prefix name set.");
404  exit(EXIT_FAILURE);
405  }
406 
407  //alt
408  milx::PrintInfo("Operation will be applied in conjuction with surfaces: ");
409  std::cout << "Total Surfaces: " << altfilenames.size() << std::endl;
410  for(stringiterator name = altfilenames.begin(); name != altfilenames.end(); name ++)
411  std::cout << *name << ", ";
412  std::cout << std::endl;
413 
414  if(diffScalarArg.isSet())
415  operation = diffscalarspairs;
416  }
417 
418  //---------------------------
420  std::cerr << "Reading Surfaces... ";
421  vtkSmartPointer<vtkPolyDataCollection> collection;
422  if( !milx::File::OpenModelCollection(filenames, collection) ) //Error printed inside
423  exit(EXIT_FAILURE);
424  std::cerr << "Done" << std::endl;
425  std::cout << "Read " << collection->GetNumberOfItems() << " models" << std::endl;
426 
427  vtkSmartPointer<vtkPolyDataCollection> altcollection;
428  if(partitionArg.isSet())
429  {
430  std::cerr << "Reading Alterate Surfaces... ";
431  if( !milx::File::OpenModelCollection(altfilenames, altcollection) ) //Error printed inside
432  exit(EXIT_FAILURE);
433  std::cerr << "Done" << std::endl;
434  }
435 
436  vtkSmartPointer<vtkPolyDataCollection> components;
437  if(componentsArg.isSet() && componentsValid)
438  {
439  std::cerr << "Reading Components... ";
440  if( !milx::File::OpenModelCollection(componentNames, components) ) //Error printed inside
441  exit(EXIT_FAILURE);
442  std::cerr << "Done" << std::endl;
443  }
444 
445  if(colourConcatenateArg.isSet())
446  {
447  size_t count = 0;
448  collection->InitTraversal();
449  for(int j = 0; j < collection->GetNumberOfItems(); j ++)
450  {
451  vtkSmartPointer<vtkPolyData> mesh = collection->GetNextItem();
452  const size_t numPoints = mesh->GetNumberOfPoints();
453 
454  vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
455  weights->SetNumberOfComponents(1);
456  weights->SetNumberOfTuples(numPoints);
457  weights->FillComponent(0, count);
458 
459  mesh->GetPointData()->SetScalars(weights);
460  count ++;
461  }
462  }
463 
464  //---------------------------
466  vtkSmartPointer<vtkTransformCollection> transformCollection = vtkSmartPointer<vtkTransformCollection>::New();
467 
468  //---------------------------
470  milx::Model Model;
471  bool outputRequired = true;
472  bool multiOutputRequired = false;
473  bool standardOperation = false;
474  vtkSmartPointer<vtkPolyDataCollection> resultCollections;
475 
476  if (collection->GetNumberOfItems() == 1)
477  {
478  outputRequired = true;
479  multiOutputRequired = false;
480  }
481  else
482  {
483  outputRequired = false;
484  multiOutputRequired = true;
485  }
486 
487  std::cerr << "Applying... ";
488  switch(operation)
489  {
490  case duplicate: //Tested 04/2016
491  standardOperation = true;
492  break;
493 
494  case convert: //Tested 04/2016
495  standardOperation = true; //requires user to set output format
496  break;
497 
498  case cat: //Tested 04/2016
499  Model.ConcatenateCollection(collection);
500  outputRequired = true;
501  multiOutputRequired = false;
502  break;
503 
504  case mse: //--------------------------------
505  milx::PrintInfo( "MSE: " + milx::NumberToString(Model.MeanSquaredErrorCollection(collection)) );
506  outputRequired = false; //write mean
507  break;
508 
509  case split: //--------------------------------
510  {// scope for local variables
511  std::vector< vtkSmartPointer<vtkPolyDataCollection> > splitCollections;
512 
513  //Split surfaces
514  Model.SplitCollection(collection, components, splitCollections);
515 
516  //write
517  typedef std::vector< vtkSmartPointer<vtkPolyDataCollection> >::iterator iterator;
518  stringiterator name = filenames.begin();
519  for(iterator surfaces = splitCollections.begin();
520  surfaces != splitCollections.end();
521  surfaces ++, name ++)
522  {
523  std::vector<std::string> splitNames;
524 
525  std::string splitName = prefixName + milx::File::GetBaseName(*name) + "_";
526  std::string ext = milx::File::GetFileExtension(*name);
527  for(stringiterator componentname = componentNames.begin(); componentname != componentNames.end(); componentname ++)
528  {
529  splitNames.push_back(splitName + milx::File::GetBaseName(*componentname) + "." + ext);
530  milx::PrintInfo("Wrote " + splitName + milx::File::GetBaseName(*componentname) + "." + ext);
531  }
532  if( !milx::File::SaveModelCollection(splitNames, *surfaces) )
533  exit(EXIT_FAILURE);
534  }
535  }// scope for local variables
536 
537  outputRequired = false;
538  multiOutputRequired = false;
539  break;
540 
541  case scale: //Tested 04/2016
542  Model.ScaleCollection(collection, scaleFactor);
543 
544  standardOperation = true;
545  break;
546 
547  case smooth: //Tested 04/2016
548  Model.SmoothCollection(collection, smoothIterations);
549 
550  standardOperation = true;
551  break;
552 
553  case laplacian: //Tested 04/2016
554  Model.LaplacianCollection(collection, laplacianIterations);
555 
556  standardOperation = true;
557  break;
558 
559  case decimate: //Tested 04/2016
560  Model.DecimateCollection(collection, decimateFactor);
561 
562  standardOperation = true;
563  break;
564 
565  case thresholdscalars:
566  Model.ScalarThresholdCollection(collection, thresholdAbove, thresholdBelow);
567 
568  standardOperation = true;
569  break;
570 
571  case clip:
572  Model.ClipCollection(collection, clipValue, clipValue);
573 
574  standardOperation = true;
575  break;
576 
577  case flip:
578  {
579  bool xAxis = false, yAxis = false, zAxis = false;
580  if(flipAxis == 2)
581  zAxis = true;
582  else if(flipAxis == 1)
583  yAxis = true;
584  else
585  xAxis = true;
586  Model.FlipCollection(collection, xAxis, yAxis, zAxis);
587 
588  standardOperation = true;
589  break;
590  }
591 
592  case diffscalars:
593  Model.ScalarDifferenceCollection(collection);
594  outputRequired = true;
595  multiOutputRequired = false;
596  break;
597 
598  case diffscalarspairs:
599  resultCollections = vtkSmartPointer<vtkPolyDataCollection>::New();
600  Model.ScalarDifferenceCollection(collection, altcollection, resultCollections);
601 
602  standardOperation = true;
603  collection = resultCollections;
604  break;
605 
606  case statscalars:
607  Model.ScalarStatisticsCollection(collection);
608  outputRequired = true;
609  multiOutputRequired = false;
610  break;
611 
612  case removescalars:
613  Model.ScalarRemoveCollection(collection);
614 
615  standardOperation = true;
616  break;
617 
618  case copyscalars:
619  Model.ScalarCopyCollection(collection);
620 
621  if(filenames.size() == 2)
622  {
623  outputRequired = true;
624  multiOutputRequired = false;
625  collection->InitTraversal();
626  collection->GetNextItem();
627  Model.SetInput(collection->GetNextItem());
628  }
629  else
630  standardOperation = true;
631  break;
632 
633  case procrustes:
634  {
635  collection = Model.ProcrustesAlignCollection(collection, rigidArg.isSet());
636 
637  std::string ext = milx::File::GetFileExtension(filenames[0]);
638  outputName = prefixName + "_mean." + ext;
639  outputRequired = true; //write mean
640  multiOutputRequired = true; //write collection
641  break;
642  } //scope for ext
643 
644  case icp:
645  collection = Model.IterativeClosestPointsAlignCollection(collection, rigidArg.isSet(), transformCollection);
646 
647  standardOperation = true; //write collection
648  break;
649 
650  case none: //--------------------------------
651  break;
652  }
653  std::cerr << "Done" << std::endl;
654 
655  if (collection->GetNumberOfItems() == 1 && standardOperation)
656  {
657  collection->InitTraversal();
658  Model.Result() = collection->GetNextItem();
659  }
660 
661  //---------------------------
663  if(outputRequired)
664  {
665  milx::PrintInfo("Writing result to " + outputName);
666  milx::File::SaveModel(outputName, Model.Result());
667  }
668  if(multiOutputRequired)
669  {
670  if(collection->GetNumberOfItems() > 0)
671  {
672  const int N = collection->GetNumberOfItems();
673 
674  milx::PrintInfo("Writing results with prefix " + prefixName);
675  std::vector<std::string> names;
676 
677  int n = 0;
678  for(stringiterator filename = filenames.begin(); filename != filenames.end() && n < N; filename ++, n ++)
679  {
680  std::string ext;
681  if (outputFormatArg.isSet()) {
682  ext = outputFormatArg.getValue();
683  } else {
684  ext = milx::File::GetFileExtension(*filename);
685  }
686 
687  names.push_back(prefixName + milx::File::GetBaseName(*filename) + "." + ext);
688  milx::PrintInfo("Will be writing " + prefixName + milx::File::GetBaseName(*filename) + "." + ext);
689  }
690 
691  milx::File::SaveModelCollection(names, collection);
692 
693  // Saving the vtkTransforms
694  if (saveTransformsArg.isSet() && transformCollection->GetNumberOfItems() == collection->GetNumberOfItems())
695  {
696  const std::string ext = "trsf.gz";
697  std::vector<std::string> tnames;
698  n = 0;
699  for(stringiterator name = names.begin(); name != names.end() && n < N; name ++, n++)
700  {
701  tnames.push_back(milx::File::StripFileExtension(*name) + "." + ext);
702  milx::PrintInfo("Will be writing " + tnames.back());
703  }
704  milx::File::SaveTransformCollection(tnames, transformCollection, false);
705  }
706  }
707  else
708  {
709  milx::PrintError("Result was empty. Skipping Output.");
710  }
711  }
712 
713  milx::PrintInfo("Operation Complete");
714  return EXIT_SUCCESS;
715 }
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
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 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
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
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
Represents a model (i.e. a model with cells and scalar values) and their common operations. Also allows batch operations on collection of models.
Definition: milxModel.h:113
void ScalarRemoveCollection(vtkSmartPointer< vtkPolyDataCollection > collection)
Removes the scalars over the collection assuming the meshes have the same number of points...
Definition: milxModel.cxx:1917
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
int main(int argc, char *argv[])
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