SMILX  1.01
milxFile.cxx
1 /*=========================================================================
2  Program: milxSMILI
3  Module: milxModel
4  Author: Shekhar Chandra
5  Language: C++
6  Created: 18 Apr 2011 12:03:00 EST
7 
8  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
9  ABN 41 687 119 230.
10  All rights reserved.
11 
12  Licensed under the CSIRO BSD 3-Clause License
13  You may not use this file except in compliance with the License.
14  You may obtain a copy of the License in the file LICENSE.md or at
15 
16  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
17 
18  Unless required by applicable law or agreed to in writing, software
19  distributed under the License is distributed on an "AS IS" BASIS,
20  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  See the License for the specific language governing permissions and
22  limitations under the License.
23 =========================================================================*/
24 #include "milxFile.h"
25 //ITK
26 #ifndef VTK_ONLY
27  #include <itkAffineTransform.h>
28  #include <itkVersorRigid3DTransform.h>
29  #include <itkRigid3DTransform.h>
30  #include <itkCenteredEuler3DTransform.h>
31  #include <itkEuler3DTransform.h>
32  #include <itkTransformFileWriter.h>
33 #endif
34 //VTK
35 #ifndef ITK_ONLY
36  #include <vtkOBJReader.h>
37  #include <vtkSTLReader.h>
38  #include <vtkSTLWriter.h>
39  #include <vtkPLYReader.h>
40  #include <vtkPLYWriter.h>
41  #include <vtkPolyDataReader.h>
42  #include <vtkUnstructuredGridReader.h>
43  #include <vtkGeometryFilter.h>
44  #include <vtkPolyDataWriter.h>
45  #include <vtkXMLPolyDataReader.h>
46  #include <vtkXMLPolyDataWriter.h>
47  #include <vtkXMLImageDataReader.h>
48  #include <vtkXMLImageDataWriter.h>
49  #include <vtkDelimitedTextReader.h>
50  #include <vtkDelimitedTextWriter.h>
51 #endif
52 
53 #include <zlib.h>
54 
55 namespace milx
56 {
57 
58 #ifndef VTK_ONLY
59  bool File::CanReadImage(const std::string filename)
60  {
61  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::ReadMode);
62 
63  if(!imageIO)
64  return false;
65  else
66  return true;
67  }
68 
69  bool File::ReadImageInformation(const std::string filename, std::string &pixeltype, std::string &componentType, size_t &dimensions)
70  {
71  if(CanReadImage(filename))
72  {
73  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::ReadMode);
74  imageIO->SetFileName(filename.c_str());
75  try
76  {
77  imageIO->ReadImageInformation();
78  }
79  catch( itk::ExceptionObject & err )
80  {
81  std::cerr << "File Exception caught while reading header!" << std::endl;
82  std::cerr << err << std::endl;
83  return false;
84  }
85 
86  pixeltype = imageIO->GetPixelTypeAsString(imageIO->GetPixelType());
87  componentType = imageIO->GetComponentTypeAsString(imageIO->GetComponentType());
88  dimensions = imageIO->GetNumberOfDimensions();
89  }
90  else
91  return false;
92 
93  return true;
94  }
95 
96  std::vector<std::string> File::GetSupportedImageFileExtensions()
97  {
98  std::vector<std::string> extensions;
99 
100  //Code taken from itk::ImageIOFactory->CreateImageIO() member in ITK 3.20
101  std::list<itk::LightObject::Pointer> allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase");
102  for(std::list<itk::LightObject::Pointer>::iterator i = allobjects.begin(); i != allobjects.end(); ++i)
103  {
104  itk::ImageIOBase* imageIO = dynamic_cast<itk::ImageIOBase*>(i->GetPointer());
105  if(imageIO)
106  {
107  for(size_t j = 0; j < imageIO->GetSupportedReadExtensions().size(); j ++)
108  extensions.push_back(imageIO->GetSupportedReadExtensions()[j]);
109  }
110  }
111 
112  return extensions;
113  }
114 
115  std::vector<std::string> File::GetDICOMSeriesUIDs(const std::string directoryPath, bool recursive)
116  {
117  std::vector<std::string> UIDs;
118  typedef itk::GDCMSeriesFileNames GeneratorType;
119  GeneratorType::Pointer nameGenerator = GeneratorType::New();
120  nameGenerator->SetUseSeriesDetails(true);
121  if(recursive)
122  nameGenerator->RecursiveOn(); //order important
123  nameGenerator->AddSeriesRestriction("0020|0010"); //StudyID
124  nameGenerator->AddSeriesRestriction("0018|0024"); //SeriesName
125  nameGenerator->AddSeriesRestriction("0018|0086"); //EchoNumber
126  nameGenerator->AddSeriesRestriction("0008|0021"); //SeriesDate
127  nameGenerator->AddSeriesRestriction("0020|0011"); //SeriesNumber
128  nameGenerator->AddSeriesRestriction("0020|0012"); //AcquisitionNumber
129 // nameGenerator->AddSeriesRestriction("300A,0282"); //ChannelNumber
130 // nameGenerator->AddSeriesRestriction("0020|0013"); //InstanceNumber
131  nameGenerator->SetDirectory(directoryPath.c_str());
132  nameGenerator->AddObserver(itk::ProgressEvent(), ProgressUpdates);
133  #if (ITK_VERSION_MAJOR > 3)
134  try
135  {
136  nameGenerator->Update();
137  }
138  catch (itk::ExceptionObject &excp)
139  {
140  std::cerr << "File Exception caught while reading filenames in directory!" << std::endl;
141  std::cerr << excp << std::endl;
142  return UIDs;
143  }
144  #endif
145 
146  UIDs = nameGenerator->GetSeriesUIDs();
147 
148  return UIDs;
149  }
150 
151  std::vector<std::string> File::GetDICOMSeriesFilenames(const std::string directoryPath, const std::string seriesName, bool recursive)
152  {
153  std::vector<std::string> filenames;
154  typedef itk::GDCMSeriesFileNames GeneratorType;
155  GeneratorType::Pointer nameGenerator = GeneratorType::New();
156  nameGenerator->SetUseSeriesDetails(true);
157  if(recursive)
158  nameGenerator->RecursiveOn(); //order important
159  nameGenerator->AddSeriesRestriction("0020|0010"); //StudyID
160  nameGenerator->AddSeriesRestriction("0018|0024"); //SeriesName
161  nameGenerator->AddSeriesRestriction("0018|0086"); //EchoNumber
162  nameGenerator->AddSeriesRestriction("0008|0021"); //SeriesDate
163  nameGenerator->AddSeriesRestriction("0020|0011"); //SeriesNumber
164  nameGenerator->AddSeriesRestriction("0020|0012"); //AcquisitionNumber
165 // nameGenerator->AddSeriesRestriction("300A,0282"); //ChannelNumber
166 // nameGenerator->AddSeriesRestriction("0020|0013"); //InstanceNumber
167  nameGenerator->SetDirectory(directoryPath.c_str());
168  nameGenerator->AddObserver(itk::ProgressEvent(), ProgressUpdates);
169  #if (ITK_VERSION_MAJOR > 3)
170  try
171  {
172  nameGenerator->Update();
173  }
174  catch (itk::ExceptionObject &excp)
175  {
176  std::cerr << "File Exception caught while reading filenames in directory!" << std::endl;
177  std::cerr << excp << std::endl;
178  return filenames;
179  }
180  #endif
181 
182  filenames = nameGenerator->GetFileNames(seriesName);
183 
184  return filenames;
185  }
186 #endif
187 
188 #ifndef ITK_ONLY
189  #ifndef VTK_ONLY
190  vtkMatrix4x4* File::OpenITKTransform(std::string filename)
191  {
192  vtkMatrix4x4 * matrix = vtkMatrix4x4::New();
193  matrix->Identity();
194 
195  typedef itk::TransformFileReader TransformReaderType;
196  typedef TransformReaderType::TransformListType * TransformListType;
197  typedef itk::AffineTransform< double, 3 > AffineTransformType;
198  typedef AffineTransformType::Pointer AffineTransformPointer;
199  typedef itk::VersorRigid3DTransform<double> VersorRigidTransformType;
200  typedef VersorRigidTransformType::Pointer VersorRigidTransformPointer;
201  typedef itk::Rigid3DTransform<double> RigidTransformType;
202  typedef RigidTransformType::Pointer RigidTransformPointer;
203  typedef itk::CenteredEuler3DTransform<double> CenteredEuler3DTransformType;
204  typedef CenteredEuler3DTransformType::Pointer CenteredEuler3DTransformPointer;
205  typedef itk::Euler3DTransform<double> Euler3DTransformType;
206  typedef Euler3DTransformType::Pointer Euler3DTransformPointer;
207 
208  TransformReaderType::Pointer affineReader = TransformReaderType::New();
209  affineReader->SetFileName(filename);
210  affineReader->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
211  try
212  {
213  affineReader->Update();
214  }
215  catch(itk::ExceptionObject &ex)
216  {
217  PrintError("milxFile: Failed reading Transform " + std::string(ex.GetDescription()));
218  return matrix;
219  }
220  TransformListType transforms = affineReader->GetTransformList();
221  TransformReaderType::TransformListType::const_iterator tit = transforms->begin();
222  AffineTransformPointer affineTransform;
223  VersorRigidTransformPointer versorRigidTransform;
224  RigidTransformPointer rigidTransform;
225  CenteredEuler3DTransformPointer centeredEulerTransform;
226  Euler3DTransformPointer euler3DTransform;
227 
228  if( !strcmp((*tit)->GetNameOfClass(),"AffineTransform") )
229  {
230  AffineTransformPointer affine_read = static_cast<AffineTransformType*>((*tit).GetPointer());
231  affineTransform = dynamic_cast< AffineTransformType * >( affine_read.GetPointer() );
232  if( affineTransform )
233  {
234  PrintInfo("Successfully Read Affine Transform file.");
235  }
236  else
237  {
238  PrintError("milxFile: Transform is not of Affine Transform Type. Returning Identity.");
239  return matrix;
240  }
241 
242  for (unsigned long i = 0; i < 3; i++)
243  {
244  matrix->SetElement(i, 0, affineTransform->GetMatrix()(i,0));
245  matrix->SetElement(i, 1, affineTransform->GetMatrix()(i,1));
246  matrix->SetElement(i, 2, affineTransform->GetMatrix()(i,2));
247  matrix->SetElement(i, 3, affineTransform->GetOffset()[i]);
248  }
249  }
250  else if( !strcmp((*tit)->GetNameOfClass(),"VersorRigid3DTransform") )
251  {
252  VersorRigidTransformPointer rigid_read = static_cast<VersorRigidTransformType*>((*tit).GetPointer());
253  versorRigidTransform = dynamic_cast< VersorRigidTransformType * >( rigid_read.GetPointer() );
254  if( versorRigidTransform )
255  {
256  PrintInfo("Successfully Read Versor Rigid Transform file.");
257  }
258  else
259  {
260  PrintError("milxFile: Transform Input is not of Versor Rigid Type. Returning Identity.");
261  return matrix;
262  }
263 
264  for (unsigned long i = 0; i < 3; i++)
265  {
266  matrix->SetElement(i, 0, versorRigidTransform->GetMatrix()(i,0));
267  matrix->SetElement(i, 1, versorRigidTransform->GetMatrix()(i,1));
268  matrix->SetElement(i, 2, versorRigidTransform->GetMatrix()(i,2));
269  matrix->SetElement(i, 3, versorRigidTransform->GetOffset()[i]);
270  }
271  }
272  else if( !strcmp((*tit)->GetNameOfClass(),"Rigid3DTransform") )
273  {
274  RigidTransformPointer rigid_read = static_cast<RigidTransformType*>((*tit).GetPointer());
275  rigidTransform = dynamic_cast< RigidTransformType * >( rigid_read.GetPointer() );
276  if( rigidTransform )
277  {
278  PrintInfo("Successfully Read Rigid Transform file.");
279  }
280  else
281  {
282  PrintError("milxFile: Transform Input is not of Rigid Type. Returning Identity.");
283  return matrix;
284  }
285 
286  for (unsigned long i = 0; i < 3; i++)
287  {
288  matrix->SetElement(i, 0, rigidTransform->GetMatrix()(i,0));
289  matrix->SetElement(i, 1, rigidTransform->GetMatrix()(i,1));
290  matrix->SetElement(i, 2, rigidTransform->GetMatrix()(i,2));
291  matrix->SetElement(i, 3, rigidTransform->GetOffset()[i]);
292  }
293  }
294  else if( !strcmp((*tit)->GetNameOfClass(),"CenteredEuler3DTransform") )
295  {
296  CenteredEuler3DTransformPointer rigid_read = static_cast<CenteredEuler3DTransformType*>((*tit).GetPointer());
297  centeredEulerTransform = dynamic_cast< CenteredEuler3DTransformType * >( rigid_read.GetPointer() );
298  if( centeredEulerTransform )
299  {
300  PrintInfo("Successfully Read Centered Euler 3D Transform file.");
301  }
302  else
303  {
304  PrintError("milxFile: Transform Input is not of Centered Euler 3D Type. Returning Identity.");
305  return matrix;
306  }
307 
308  for (unsigned long i = 0; i < 3; i++)
309  {
310  matrix->SetElement(i, 0, centeredEulerTransform->GetMatrix()(i,0));
311  matrix->SetElement(i, 1, centeredEulerTransform->GetMatrix()(i,1));
312  matrix->SetElement(i, 2, centeredEulerTransform->GetMatrix()(i,2));
313  matrix->SetElement(i, 3, centeredEulerTransform->GetOffset()[i]);
314  }
315  }
316  else if( !strcmp((*tit)->GetNameOfClass(),"Euler3DTransform") )
317  {
318  Euler3DTransformPointer rigid_read = static_cast<Euler3DTransformType*>((*tit).GetPointer());
319  euler3DTransform = dynamic_cast< Euler3DTransformType * >( rigid_read.GetPointer() );
320  if( euler3DTransform )
321  {
322  PrintInfo("Successfully Read Euler 3D Transform file.");
323  }
324  else
325  {
326  PrintError("milxFile: Transform Input is not of Euler 3D Type. Returning Identity.");
327  return matrix;
328  }
329 
330  for (unsigned long i = 0; i < 3; i++)
331  {
332  matrix->SetElement(i, 0, euler3DTransform->GetMatrix()(i,0));
333  matrix->SetElement(i, 1, euler3DTransform->GetMatrix()(i,1));
334  matrix->SetElement(i, 2, euler3DTransform->GetMatrix()(i,2));
335  matrix->SetElement(i, 3, euler3DTransform->GetOffset()[i]);
336  }
337  }
338  else
339  {
340  PrintError("milxFile: Transform Input is not of known type");
341  }
342 
343  return matrix;
344  }
345 
346  vtkMatrix4x4* File::OpenVTKTransform(std::string filename)
347  {
348  vtkMatrix4x4 * matrix = vtkMatrix4x4::New();
349 
350  char * buffer = new char[512];
351  gzFile fin = ::gzopen( filename.c_str(), "rb" );
352  if(fin == NULL)
353  {
354  cerr << "Cannot read " << filename << endl;
355  delete [] buffer;
356  }
357  buffer = ::gzgets (fin, buffer, 512);
358  if(buffer[0] != '(')
359  {
360  cerr << "File is not a transform file" << endl;
361  }
362  buffer = ::gzgets (fin, buffer, 512);
363  if((buffer[0] != 0) && (buffer[1] != '8'))
364  {
365  // Failed Magic number test ;)
366  cerr << buffer << endl;
367  cerr << "File is not a transform file" << endl;
368  }
369  char str1 [128];
370  char str2 [128];
371  char str3 [128];
372  char str4 [128];
373  for (unsigned long i = 0; i < 4; i++)
374  {
375  //fin >> value;
376  buffer = ::gzgets (fin, buffer, 512);
377 
378  //sscanf(buffer,"%f %f %f", &x, &y, &z);
379  sscanf(buffer,"%s %s %s %s", &str1[0], &str2[0], &str3[0], &str4[0]);
380  matrix->SetElement(i, 0, atof(str1));
381  matrix->SetElement(i, 1, atof(str2));
382  matrix->SetElement(i, 2, atof(str3));
383  matrix->SetElement(i, 3, atof(str4));
384  std::cout << atof(str1) << " " << atof(str2) << " " << atof(str3) << " " << atof(str4) << std::endl;
385  }
386  buffer = ::gzgets (fin, buffer, 512);
387  if(buffer[0] != ')')
388  {
389  cerr << buffer << endl;
390  cerr << "File is not a transform file" << endl;
391  }
392  delete [] buffer;
393  gzclose(fin);
394  return matrix;
395  }
396 
397  void File::SaveITKTransform(std::string filename, const vtkMatrix4x4 * matrix)
398  {
399  // Step 1.: Convert VTK matrix to an ITK transform
400  typedef itk::AffineTransform<double,3> TransformType;
401  TransformType::Pointer transform = TransformType::New();
402  TransformType::MatrixType itkmat;
403 
404  for (size_t i=0; i<3; i++) {
405  for (size_t j=0; j<3; j++) {
406  itkmat(i,j) = matrix->GetElement(i,j);
407  }
408  }
409  transform->SetMatrix(itkmat);
410 
411  TransformType::OutputVectorType trans;
412  trans[0] = matrix->GetElement(0,3);
413  trans[1] = matrix->GetElement(1,3);
414  trans[2] = matrix->GetElement(2,3);
415  transform->SetTranslation(trans);
416 
417  // Step 2.: Save
418  typedef itk::TransformFileWriter TransformWriterType;
419  TransformWriterType::Pointer transformWriter = TransformWriterType::New();
420  transformWriter->SetFileName(filename);
421  transformWriter->SetInput(transform);
422  try {
423  transformWriter->Update();
424  } catch( itk::ExceptionObject & err) {
425  std::cerr << "Exception occurred while writing transform file:\n " << filename << std::endl;
426  std::cerr << err << std::endl;
427  std::cout << err.what() << std::endl;
428  }
429  }
430 
431  /*The file syntax is like, eg:
432  (
433  O8
434  1.000000 0.000000 0.000000 22.500000
435  0.000000 1.000000 0.000000 22.500000
436  0.000000 0.000000 1.000000 22.500000
437  0.000000 0.000000 0.000000 1.000000
438  )
439  Note: 08 is a magic number.
440  */
441  void File::SaveVTKTransform(std::string filename, const vtkMatrix4x4 * matrix)
442  {
443  std::string ext = milx::File::GetFileExtension(filename);
444 
445  if (ext == "gz")
446  {
447  gzFile fout = ::gzopen( filename.c_str(), "wb" );
448 
449  if(fout == NULL)
450  {
451  cerr << "Cannot open for writing: " << filename << endl;
452  }
453 
454  ::gzputs(fout, "(\n08\n");
455 
456  for (unsigned long i = 0; i < 4; i++)
457  {
458  ::gzprintf(fout, "%- 24.18g %- 24.18g %- 24.18g %- 24.18g\n", matrix->GetElement(i, 0), matrix->GetElement(i, 1), matrix->GetElement(i, 2), matrix->GetElement(i, 3));
459  }
460 
461  ::gzputs(fout, ")\n");
462  ::gzclose(fout);
463  }
464  else
465  {
466  FILE * fout = ::fopen( filename.c_str(), "wb" );
467 
468  if(fout == NULL)
469  {
470  cerr << "Cannot open for writing: " << filename << endl;
471  }
472 
473  ::fputs("(\n08\n", fout);
474 
475  for (unsigned long i = 0; i < 4; i++)
476  {
477  ::fprintf(fout, "%- 24.18g %- 24.18g %- 24.18g %- 24.18g\n", matrix->GetElement(i, 0), matrix->GetElement(i, 1), matrix->GetElement(i, 2), matrix->GetElement(i, 3));
478  }
479 
480  ::fputs(")\n", fout);
481  ::fclose(fout);
482  }
483 
484 
485  }
486  #endif // VTK_ONLY
487 
488 bool File::OpenModel(const std::string filename, vtkSmartPointer<vtkPolyData> &data)
489 {
490  bool legacy = false, wavefront = false, stanford = false, stereoLith = false;
491  std::string extension = GetFileExtension(filename);
492 
493  if (extension == "vtk")
494  legacy = true; //Load legacy VTK file
495  else if (extension == "obj")
496  wavefront = true;
497  else if (extension == "ply")
498  stanford = true;
499  else if(extension == "stl")
500  stereoLith = true;
501 
502  if(data != NULL)
503  PrintError("milxFile: PolyData pointer is not NULL. May get a memory leak.");
504 
505  vtkSmartPointer<vtkErrorWarning> errorObserver = vtkSmartPointer<vtkErrorWarning>::New();
506  if (legacy)
507  {
508  //Check legacy data type
509  vtkSmartPointer<vtkDataReader> dreader = vtkSmartPointer<vtkDataReader>::New();
510  dreader->SetFileName(filename.c_str());
511  dreader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
512  dreader->OpenVTKFile();
513  dreader->ReadHeader();
514  dreader->CloseVTKFile();
515 
516  if(dreader->IsFilePolyData())
517  {
518  PrintDebug("Found Poly Data.");
519  vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
520  reader->SetFileName(filename.c_str());
521  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
522  reader->Update();
523 
524  if(!errorObserver->ReportsFailure())
525  {
526  data = reader->GetOutput();
527  return true;
528  }
529  }
530  else if(dreader->IsFileUnstructuredGrid())
531  {
532  PrintDebug("Found Unstructured Grid Data.");
533  vtkSmartPointer<vtkUnstructuredGridReader> reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
534  reader->SetFileName(filename.c_str());
535  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
536  reader->Update();
537 
538  vtkSmartPointer<vtkGeometryFilter> geometryFilter = vtkSmartPointer<vtkGeometryFilter>::New();
539  geometryFilter->SetInputConnection(reader->GetOutputPort());
540  geometryFilter->Update();
541 
542  if(!errorObserver->ReportsFailure())
543  {
544  data = geometryFilter->GetOutput();
545  return true;
546  }
547  }
548  else
549  {
550  PrintError("VTK Legacy Data Type Not Supported.");
551  }
552  }
553  else if (wavefront)
554  {
555  vtkSmartPointer<vtkOBJReader> reader = vtkSmartPointer<vtkOBJReader>::New();
556  reader->SetFileName(filename.c_str());
557  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
558  reader->Update();
559 
560  if (!errorObserver->ReportsFailure())
561  {
562  data = reader->GetOutput();
563  return true;
564  }
565  }
566  else if (stanford)
567  {
568  vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
569  reader->SetFileName(filename.c_str());
570  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
571  reader->Update();
572 
573  if (!errorObserver->ReportsFailure())
574  {
575  data = reader->GetOutput();
576  return true;
577  }
578  }
579  else if(stereoLith)
580  {
581  vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
582  reader->SetFileName(filename.c_str());
583  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
584  reader->Update();
585 
586  if (!errorObserver->ReportsFailure())
587  {
588  data = reader->GetOutput();
589  return true;
590  }
591  }
592  else
593  {
594  vtkSmartPointer<vtkXMLPolyDataReader> reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
595  reader->SetFileName(filename.c_str());
596  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
597  reader->Update();
598 
599  if (!errorObserver->ReportsFailure())
600  {
601  data = reader->GetOutput();
602  return true;
603  }
604  }
605 
606  PrintError("Reader Encountered the following error.");
607  PrintError(errorObserver->GetMessage());
608  return false;
609 }
610 
611 bool File::OpenModelCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkPolyDataCollection> &collection)
612 {
613  collection = vtkSmartPointer<vtkPolyDataCollection>::New();
614 
615  for(std::vector<std::string>::iterator name = filenames.begin(); name != filenames.end(); name ++)
616  {
617  vtkSmartPointer<vtkPolyData> surface;
618 
619  if( !File::OpenModel(*name, surface) ) //Error printed inside
620  continue;
621 
622  collection->AddItem( surface );
623  }
624 
625  return true;
626 }
627 
628 bool File::SaveModel(const std::string filename, vtkSmartPointer<vtkPolyData> data, const bool binary)
629 {
630  bool legacy = false, stanford = false, stereoLith = false;
631  std::string extension = GetFileExtension(filename);
632 
633  if (extension == "vtk")
634  legacy = true; //Save legacy VTK file
635  else if (extension == "ply")
636  stanford = true; //Save Stanford Poly file
637  else if(extension == "stl")
638  stereoLith = true; //STL files
639 
640  if(data == NULL)
641  {
642  PrintError("PolyData pointer is NULL. Not saving.");
643  return false;
644  }
645 
646  if (legacy)
647  {
648  vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
649  writer->SetFileName(filename.c_str());
650  #if VTK_MAJOR_VERSION <= 5
651  writer->SetInput(data);
652  #else
653  writer->SetInputData(data);
654  #endif
655  writer->Write();
656  }
657  else if (stanford)
658  {
659  vtkSmartPointer<vtkPLYWriter> writer = vtkSmartPointer<vtkPLYWriter>::New();
660  writer->SetFileName(filename.c_str());
661  #if VTK_MAJOR_VERSION <= 5
662  writer->SetInput(data);
663  #else
664  writer->SetInputData(data);
665  #endif
666  writer->Write();
667  }
668  else if(stereoLith)
669  {
670  vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();
671  writer->SetFileName(filename.c_str());
672  #if VTK_MAJOR_VERSION <= 5
673  writer->SetInput(data);
674  #else
675  writer->SetInputData(data);
676  #endif
677  writer->Write();
678  }
679  else
680  {
681  vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
682  writer->SetFileName(filename.c_str());
683  #if VTK_MAJOR_VERSION <= 5
684  writer->SetInput(data);
685  #else
686  writer->SetInputData(data);
687  #endif
688  if (binary)
689  writer->SetDataModeToBinary();
690  writer->SetCompressorTypeToZLib();
691  writer->Write();
692  }
693 
694  return true;
695 }
696 
697 bool File::SaveModelCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkPolyDataCollection> collection, const bool binary)
698 {
699  collection->InitTraversal();
700  for(std::vector<std::string>::iterator name = filenames.begin(); name != filenames.end(); name ++)
701  {
702  if( !File::SaveModel(*name, collection->GetNextItem(), binary) ) //Error printed inside
703  continue;
704  }
705 
706  return true;
707 }
708 
709 bool File::SaveTransform(const std::string filename, vtkSmartPointer<vtkTransform> data, const bool ITK)
710 {
711  if(data == NULL)
712  {
713  PrintError("Transform pointer is NULL. Not saving.");
714  return false;
715  }
716 
717  if (ITK) {
718  SaveITKTransform(filename, data->GetMatrix());
719  } else {
720  SaveVTKTransform(filename, data->GetMatrix());
721  }
722 
723  return true;
724 }
725 
726 bool File::SaveTransformCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkTransformCollection> collection, const bool ITK)
727 {
728  collection->InitTraversal();
729  for(std::vector<std::string>::iterator name = filenames.begin(); name != filenames.end(); name ++)
730  {
731  if( !File::SaveTransform(*name, collection->GetNextItem(), ITK) ) //Error printed inside
732  continue;
733  }
734 
735  return true;
736 }
737 
738 bool File::OpenDelimitedText(const std::string filename, vtkSmartPointer<vtkTable> &data, const std::string delimiter)
739 {
740  PrintInfo("Reading file: " + filename);
741  vtkSmartPointer<vtkDelimitedTextReader> csv_vert_source = vtkSmartPointer<vtkDelimitedTextReader>::New();
742  csv_vert_source->SetFieldDelimiterCharacters(delimiter.c_str());
743  csv_vert_source->DetectNumericColumnsOn();
744  csv_vert_source->SetHaveHeaders(true);
745  csv_vert_source->SetFileName(filename.c_str());
746  csv_vert_source->Update();
747  PrintInfo("Has " + NumberToString(csv_vert_source->GetOutput()->GetNumberOfColumns()) + " columns");
748 
749  data = csv_vert_source->GetOutput();
750 
751  return true;
752 }
753 
754 bool File::SaveDelimitedText(const std::string filename, const vtkSmartPointer<vtkTable> data, const std::string delimiter)
755 {
756  PrintInfo("Writing file: " + filename);
757  vtkSmartPointer<vtkDelimitedTextWriter> csv_vert_source = vtkSmartPointer<vtkDelimitedTextWriter>::New();
758  csv_vert_source->SetFieldDelimiter(delimiter.c_str());
759  csv_vert_source->SetFileName(filename.c_str());
760  #if VTK_MAJOR_VERSION <= 5
761  csv_vert_source->SetInput(data);
762  #else
763  csv_vert_source->SetInputData(data);
764  #endif
765  csv_vert_source->Write();
766 
767  return true;
768 }
769 
770 bool File::SaveCamera(const std::string filename, const vtkSmartPointer<vtkCamera> camera)
771 {
772  if(!camera || filename.empty())
773  return false;
774 
775  ofstream file(filename.c_str(), ios::out);
776 
777  if(file.fail())
778  return false;
779 
780  file << camera->GetClippingRange()[0] << " "
781  << camera->GetClippingRange()[1] << " "
782 
783  << camera->GetFocalPoint()[0] << " "
784  << camera->GetFocalPoint()[1] << " "
785  << camera->GetFocalPoint()[2] << " "
786 
787  << camera->GetPosition()[0] << " "
788  << camera->GetPosition()[1] << " "
789  << camera->GetPosition()[2] << " "
790 
791  << camera->GetViewAngle() << " "
792 
793  << camera->GetViewUp()[0] << " "
794  << camera->GetViewUp()[1] << " "
795  << camera->GetViewUp()[2] << " "
796  << std::endl;
797  file.close();
798 
799  return true;
800 }
801 
802 bool File::LoadCamera(const std::string filename, vtkSmartPointer<vtkCamera> &camera)
803 {
804  if(!camera || filename.empty())
805  return false;
806 
807  double clippingRange[2];
808  double focal[3];
809  double pos[3];
810  double viewAngle;
811  double up[3];
812 
813  ifstream file (filename.c_str());
814 
815  if(file.fail())
816  return false;
817 
818  file
819  >> clippingRange[0]
820  >> clippingRange[1]
821 
822  >> focal[0]
823  >> focal[1]
824  >> focal[2]
825 
826  >> pos[0]
827  >> pos[1]
828  >> pos[2]
829 
830  >> viewAngle
831 
832  >> up[0]
833  >> up[1]
834  >> up[2];
835  file.close();
836 
837  // set the camera details
838  camera->SetClippingRange(clippingRange);
839  camera->SetFocalPoint(focal);
840  camera->SetPosition(pos);
841  camera->SetViewAngle(viewAngle);
842  camera->SetViewUp(up);
843 
844  return true;
845 }
846 #endif //ITK_ONLY
847 
848 } //end milx namespace
void PrintDebug(const std::string msg)
Displays a generic msg to standard error with carriage return if in Debug mode.
Definition: milxGlobal.h:192
static std::vector< std::string > GetSupportedImageFileExtensions()
Determines the supported image file format as file extensions from internal libraries and returns a l...
Definition: milxFile.cxx:96
static vtkMatrix4x4 * OpenVTKTransform(std::string filename)
Opens a VTK transform file and converts it to a VTK transform matrix.
Definition: milxFile.cxx:346
static bool OpenDelimitedText(const std::string filename, vtkSmartPointer< vtkTable > &data, const std::string delimiter=",")
Opens ASCII Delimited text files such as CSV files. Data is loaded into the table.
Definition: milxFile.cxx:738
static std::vector< std::string > GetDICOMSeriesFilenames(const std::string directoryPath, const std::string seriesName, bool recursive=false)
Returns the filenames for a given UID/Series name for a given directory.
Definition: milxFile.cxx:151
void PrintError(const std::string msg)
Displays a generic msg to standard error with carriage return.
Definition: milxGlobal.h:202
static bool SaveDelimitedText(const std::string filename, const vtkSmartPointer< vtkTable > data, const std::string delimiter=",")
Saves table as an ASCII Delimited text files such as a CSV file.
Definition: milxFile.cxx:754
static bool OpenModel(const std::string filename, vtkSmartPointer< vtkPolyData > &data)
Opens a model file, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
Definition: milxFile.cxx:488
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
static vtkMatrix4x4 * OpenITKTransform(std::string filename)
Opens an ITK transform file and converts it to a VTK transform matrix.
Definition: milxFile.cxx:190
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
static bool SaveTransform(const std::string filename, vtkSmartPointer< vtkTransform > data, const bool ITK=false)
Saves a transform file, which can be VTK .trsf or ITK from a collection.
Definition: milxFile.cxx:709
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
static bool ReadImageInformation(const std::string filename, std::string &pixeltype, std::string &componentType, size_t &dimensions)
Reads just the header of an image file (without reading the image data), and writes the info into the...
Definition: milxFile.cxx:69
static std::vector< std::string > GetDICOMSeriesUIDs(const std::string directoryPath, bool recursive=false)
DICOM Related.
Definition: milxFile.cxx:115
static std::string GetFileExtension(const std::string &filename)
Returns the file extension (in lower case) of the given filename.
Definition: milxFile.h:472
static bool CanReadImage(const std::string filename)
Checks if the image can be read by supported libraries.
Definition: milxFile.h:104