Slicer  4.8
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
vtkITKArchetypeImageSeriesReader.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3 Copyright Brigham and Women's Hospital (BWH) All Rights Reserved.
4 
5 See COPYRIGHT.txt
6 or http://www.slicer.org/copyright/copyright.txt for details.
7 
8 Program: vtkITK
9 Module: $HeadURL$
10 Date: $Date$
11 Version: $Revision$
12 
13 ==========================================================================*/
14 
15 #ifndef __vtkITKArchetypeImageSeriesReader_h
16 #define __vtkITKArchetypeImageSeriesReader_h
17 
18 // VTKITK includes
19 #include "vtkITK.h"
20 
21 // VTK includes
22 #include "vtkImageAlgorithm.h"
23 class vtkMatrix4x4;
24 
25 // ITK includes
26 #include "itkImageIOBase.h"
27 #include "itkMetaDataDictionary.h"
28 #include "itkSpatialOrientation.h"
29 
30 // STD includes
31 #include <algorithm>
32 #include <string>
33 #include <vector>
34 
45 class VTK_ITK_EXPORT vtkITKArchetypeImageSeriesReader : public vtkImageAlgorithm
46 {
47 public:
49  vtkTypeMacro(vtkITKArchetypeImageSeriesReader,vtkImageAlgorithm);
50  void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE;
51 
52  typedef itk::SpatialOrientation::ValidCoordinateOrientationFlags CoordinateOrientationCode;
53 
56  vtkSetStringMacro(Archetype);
57  vtkGetStringMacro(Archetype);
58 
61  unsigned int GetNumberOfFileNames();
64  const std::vector<std::string>& GetFileNames();
65 
70  unsigned int AddFileName( const char* filename );
71  const char* GetFileName( unsigned int n );
72  void ResetFileNames();
73 
77  vtkSetVector3Macro(DefaultDataSpacing,double);
78  vtkGetVector3Macro(DefaultDataSpacing,double);
79 
84  vtkSetVector3Macro(DefaultDataOrigin,double);
85  vtkGetVector3Macro(DefaultDataOrigin,double);
86 
90  vtkSetMacro(FileNameSliceOffset,int);
91  vtkGetMacro(FileNameSliceOffset,int);
92 
97  vtkSetMacro(FileNameSliceSpacing,int);
98  vtkGetMacro(FileNameSliceSpacing,int);
99 
103  vtkSetMacro(FileNameSliceCount,int);
104  vtkGetMacro(FileNameSliceCount,int);
105 
107  virtual int CanReadFile(const char* filename);
108 
112  {
113  this->DesiredCoordinateOrientation =
114  itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_RAI;
116  this->UseNativeCoordinateOrientation = 0;
117  this->Modified();
118  }
120  {
121  this->DesiredCoordinateOrientation =
122  itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_RSA;
124  this->UseNativeCoordinateOrientation = 0;
125  this->Modified();
126  }
128  {
129  this->DesiredCoordinateOrientation =
130  itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_ASL;
132  this->UseNativeCoordinateOrientation = 0;
133  this->Modified();
134  }
136  {
137  this->UseNativeCoordinateOrientation = 1;
138  this->Modified();
139  }
140  vtkGetMacro(DesiredCoordinateOrientation, CoordinateOrientationCode);
141  vtkGetMacro(UseNativeCoordinateOrientation, char);
142 
148  {
149  UseNativeScalarType = 0;
150  this->SetOutputScalarType(VTK_DOUBLE);
151  }
153  {
154  UseNativeScalarType = 0;
155  this->SetOutputScalarType(VTK_FLOAT);
156  }
158  {
159  UseNativeScalarType = 0;
160  this->SetOutputScalarType(VTK_LONG);
161  }
163  {
164  UseNativeScalarType = 0;
165  this->SetOutputScalarType(VTK_UNSIGNED_LONG);
166  }
168  {
169  UseNativeScalarType = 0;
170  this->SetOutputScalarType(VTK_INT);
171  }
173  {
174  UseNativeScalarType = 0;
175  this->SetOutputScalarType(VTK_UNSIGNED_INT);
176  }
178  {
179  UseNativeScalarType = 0;
180  this->SetOutputScalarType(VTK_SHORT);
181  }
183  {
184  UseNativeScalarType = 0;
185  this->SetOutputScalarType(VTK_UNSIGNED_SHORT);
186  }
188  {
189  UseNativeScalarType = 0;
190  this->SetOutputScalarType(VTK_CHAR);
191  }
193  {
194  UseNativeScalarType = 0;
195  this->SetOutputScalarType(VTK_UNSIGNED_CHAR);
196  }
198  {
199  UseNativeScalarType = 1;
200  this->Modified();
201  }
202 
206  {
207  UseNativeOrigin = true;
208  }
209 
213  {
214  UseNativeOrigin = false;
215  }
216 
219  enum
220  {
221  GDCM = 0,
222  DCMTK
223  };
224  vtkSetClampMacro(DICOMImageIOApproach, int, vtkITKArchetypeImageSeriesReader::GDCM, vtkITKArchetypeImageSeriesReader::DCMTK);
225  vtkGetMacro(DICOMImageIOApproach, int);
228 
231  vtkSetMacro(OutputScalarType, int);
232  vtkGetMacro(OutputScalarType, int);
233 
236  vtkSetMacro(NumberOfComponents, unsigned int);
237  vtkGetMacro(NumberOfComponents, unsigned int);
238 
241  vtkSetMacro(SingleFile, int);
242  vtkGetMacro(SingleFile, int);
243 
246  vtkSetMacro(AnalyzeHeader, bool);
247  vtkGetMacro(AnalyzeHeader, bool);
248 
251  vtkSetMacro(UseOrientationFromFile, int);
252  vtkGetMacro(UseOrientationFromFile, int);
253 
256  vtkMatrix4x4* GetRasToIjkMatrix();
257 
260  vtkMatrix4x4* GetMeasurementFrameMatrix();
261 
264  const itk::MetaDataDictionary &GetMetaDataDictionary() const;
265  std::vector<std::string> Tags;
266  std::vector<std::string> TagValues;
267  void ParseDictionary();
268 
269  unsigned int GetNumberOfItemsInDictionary();
270  bool HasKey( char* tag );
271  const char* GetNthKey( unsigned int n );
272  const char* GetNthValue( unsigned int n );
273  const char* GetTagValue( char* tag );
274 
277  {
278  return GroupingByTags;
279  }
280 
282  {
283  GroupingByTags = true;
284  }
285 
287  {
288  GroupingByTags = false;
289  }
290 
293  {
294  return SelectedUID;
295  }
296 
297  void SetSelectedUID( int v )
298  {
299  SelectedUID = v;
300  SetGroupingByTagsOn();
301  }
302 
305  {
306  return SelectedContentTime;
307  }
308 
310  {
311  SelectedContentTime = v;
312  SetGroupingByTagsOn();
313  }
314 
317  {
318  return SelectedTriggerTime;
319  }
320 
322  {
323  SelectedTriggerTime = v;
324  SetGroupingByTagsOn();
325  }
326 
329  {
330  return SelectedEchoNumbers;
331  }
332 
334  {
335  SelectedEchoNumbers = v;
336  SetGroupingByTagsOn();
337  }
338 
339 
342  {
343  return SelectedDiffusion;
344  }
345 
346  void SetSelectedDiffusion( int v )
347  {
348  SelectedDiffusion = v;
349  SetGroupingByTagsOn();
350  }
351 
354  {
355  return SelectedSlice;
356  }
357 
358  void SetSelectedSlice( int v )
359  {
360  SelectedSlice = v;
361  SetGroupingByTagsOn();
362  }
363 
366  {
367  return SelectedOrientation;
368  }
369 
371  {
372  SelectedOrientation = v;
373  SetGroupingByTagsOn();
374  }
375 
378  {
379  return this->SeriesInstanceUIDs.size();
380  }
381 
382  unsigned int GetNumberOfContentTime()
383  {
384  return this->ContentTime.size();
385  }
386 
387  unsigned int GetNumberOfTriggerTime()
388  {
389  return this->TriggerTime.size();
390  }
391 
392  unsigned int GetNumberOfEchoNumbers()
393  {
394  return this->EchoNumbers.size();
395  }
396 
398  {
399  return this->SliceLocation.size();
400  }
401 
403  {
404  return this->DiffusionGradientOrientation.size();
405  };
406 
408  {
409  return this->ImageOrientationPatient.size();
410  };
411 
413  {
414  return this->ImagePositionPatient.size();
415  }
416 
418  int ExistSeriesInstanceUID( const char* SeriesInstanceUID )
419  {
420  for (unsigned int k = 0; k < GetNumberOfSeriesInstanceUIDs(); k++)
421  {
422  if ( this->SeriesInstanceUIDs[k].find(SeriesInstanceUID) != std::string::npos )
423  {
424  return k;
425  }
426  }
427  return -1;
428  }
429 
430  int ExistContentTime( const char* contentTime )
431  {
432  for (unsigned int k = 0; k < GetNumberOfContentTime(); k++)
433  {
434  if ( this->ContentTime[k].find(contentTime) != std::string::npos )
435  {
436  return k;
437  }
438  }
439  return -1;
440  }
441 
442  int ExistTriggerTime( const char* triggerTime )
443  {
444  for (unsigned int k = 0; k < GetNumberOfTriggerTime(); k++)
445  {
446  if ( this->TriggerTime[k].find(triggerTime) != std::string::npos )
447  {
448  return k;
449  }
450  }
451  return -1;
452  }
453 
454  int ExistEchoNumbers( const char* echoNumbers )
455  {
456  for (unsigned int k = 0; k < GetNumberOfEchoNumbers(); k++)
457  {
458  if ( this->EchoNumbers[k].find(echoNumbers) != std::string::npos )
459  {
460  return k;
461  }
462  }
463  return -1;
464  }
465 
467  {
468  float a = 0;
469  for (int n = 0; n < 3; n++)
470  {
471  a += dgo[n]*dgo[n];
472  }
473 
474  for (unsigned int k = 0; k < GetNumberOfDiffusionGradientOrientation(); k++)
475  {
476  float b = 0;
477  float c = 0;
478  for (int n = 0; n < 3; n++)
479  {
480  b += this->DiffusionGradientOrientation[k][n] * this->DiffusionGradientOrientation[k][n];
481  c += this->DiffusionGradientOrientation[k][n] * dgo[n];
482  }
483  c = fabs(c)/sqrt(a*b);
484 
485  if ( c > 0.99999 )
486  {
487  return k;
488  }
489  }
490  return -1;
491  }
492 
493  int ExistSliceLocation( float sliceLocation )
494  {
495  std::vector<float>::iterator iter =
496  std::find(this->SliceLocation.begin(), this->SliceLocation.end(), sliceLocation);
497  return iter != this->SliceLocation.end() ?
498  std::distance(this->SliceLocation.begin(), iter) : -1;
499  }
500 
501  int ExistImageOrientationPatient( float * directionCosine )
502  {
504  float a = sqrt( directionCosine[0]*directionCosine[0] + directionCosine[1]*directionCosine[1] + directionCosine[2]*directionCosine[2] );
505  for (int k = 0; k < 3; k++)
506  {
507  directionCosine[k] /= a;
508  }
509  a = sqrt( directionCosine[3]*directionCosine[3] + directionCosine[4]*directionCosine[4] + directionCosine[5]*directionCosine[5] );
510  for (int k = 3; k < 6; k++)
511  {
512  directionCosine[k] /= a;
513  }
514 
515  for (unsigned int k = 0; k < GetNumberOfImageOrientationPatient(); k++)
516  {
517  std::vector<float> aVec = ImageOrientationPatient[k];
518  a = sqrt( aVec[0]*aVec[0] + aVec[1]*aVec[1] + aVec[2]*aVec[2] );
519  float b = (directionCosine[0]*aVec[0] + directionCosine[1]*aVec[1] + directionCosine[2]*aVec[2])/a;
520  if ( b < 0.99999 )
521  {
522  continue;
523  }
524 
525  a = sqrt( aVec[3]*aVec[3] + aVec[4]*aVec[4] + aVec[5]*aVec[5] );
526  b = (directionCosine[3]*aVec[3] + directionCosine[4]*aVec[4] + directionCosine[5]*aVec[5])/a;
527  if ( b > 0.99999 )
528  {
529  return k;
530  }
531  }
532  return -1;
533  }
534 
535  int ExistImagePositionPatient( float* ipp )
536  {
537  float a = 0;
538  for (int n = 0; n < 3; n++)
539  {
540  a += ipp[n]*ipp[n];
541  }
542 
543  for (unsigned int k = 0; k < GetNumberOfImagePositionPatient(); k++)
544  {
545  float b = 0;
546  float c = 0;
547  for (int n = 0; n < 3; n++)
548  {
549  b += this->ImagePositionPatient[k][n] * this->ImagePositionPatient[k][n];
550  c += this->ImagePositionPatient[k][n] * ipp[n];
551  }
552  c = fabs(c)/sqrt(a*b);
553  if ( c > 0.99999 )
554  {
555  return k;
556  }
557  }
558  return -1;
559  }
560 
562  const char* GetNthSeriesInstanceUID( unsigned int n )
563  {
564  if ( n >= this->GetNumberOfSeriesInstanceUIDs() )
565  {
566  return NULL;
567  }
568  return this->SeriesInstanceUIDs[n].c_str();
569  }
570 
571  const char* GetNthContentTime( unsigned int n )
572  {
573  if ( n >= this->GetNumberOfContentTime() )
574  {
575  return NULL;
576  }
577  return this->ContentTime[n].c_str();
578  }
579 
580  const char* GetNthTriggerTime( unsigned int n )
581  {
582  if ( n >= this->GetNumberOfTriggerTime() )
583  {
584  return NULL;
585  }
586  return this->TriggerTime[n].c_str();
587  }
588 
589  const char* GetNthEchoNumbers( unsigned int n )
590  {
591  if ( n >= this->GetNumberOfEchoNumbers() )
592  {
593  return NULL;
594  }
595  return this->EchoNumbers[n].c_str();
596  }
597 
598  float* GetNthDiffusionGradientOrientation( unsigned int n )
599  {
600  if ( n >= this->GetNumberOfDiffusionGradientOrientation() )
601  {
602  return NULL;
603  }
604  float *dgo = new float [3];
605  for (int k = 0; k <3; k++)
606  {
607  dgo[k] = this->DiffusionGradientOrientation[n][k];
608  }
609  return dgo;
610  }
611 
612  float GetNthSliceLocation( unsigned int n )
613  {
614  if ( n >= this->GetNumberOfSliceLocation() )
615  {
616  return this->SliceLocation[0];
617  }
618  return this->SliceLocation[0];
619  }
620 
621  float* GetNthImageOrientationPatient( unsigned int n )
622  {
623  if ( n >= this->GetNumberOfImageOrientationPatient() )
624  {
625  return NULL;
626  }
627  float *dgo = new float [6];
628  for (int k = 0; k <6; k++)
629  {
630  dgo[k] = this->ImageOrientationPatient[n][k];
631  }
632  return dgo;
633  }
634 
635  float* GetNthImagePositionPatient( unsigned int n )
636  {
637  if (n >= this->GetNumberOfImagePositionPatient() )
638  {
639  return NULL;
640  }
641  float *ipp = new float [3];
642  for (int k = 0; k <3; k++)
643  {
644  ipp[k] = this->ImagePositionPatient[n][k];
645  }
646  return ipp;
647  }
648 
651  int InsertSeriesInstanceUIDs ( const char * aUID )
652  {
653  int k = ExistSeriesInstanceUID( aUID );
654  if ( k >= 0 )
655  {
656  return k;
657  }
658 
659  std::string aVector(aUID);
660  this->SeriesInstanceUIDs.push_back( aVector );
661  return (this->SeriesInstanceUIDs.size()-1);
662  }
663 
664  int InsertContentTime ( const char * aTime )
665  {
666  int k = ExistContentTime( aTime );
667  if ( k >= 0 )
668  {
669  return k;
670  }
671 
672  std::string aVector(aTime);
673  this->ContentTime.push_back( aVector );
674  return (this->ContentTime.size()-1);
675  }
676 
677  int InsertTriggerTime ( const char * aTime )
678  {
679  int k = ExistTriggerTime( aTime );
680  if ( k >= 0 )
681  {
682  return k;
683  }
684 
685  std::string aVector(aTime);
686  this->TriggerTime.push_back( aVector );
687  return (this->TriggerTime.size()-1);
688  }
689 
690  int InsertEchoNumbers ( const char * aEcho )
691  {
692  int k = ExistEchoNumbers( aEcho );
693  if ( k >= 0 )
694  {
695  return k;
696  }
697 
698  std::string aVector(aEcho);
699  this->EchoNumbers.push_back( aVector );
700  return (this->EchoNumbers.size()-1);
701  }
702 
704  {
705  int k = ExistDiffusionGradientOrientation( a );
706  if ( k >= 0 )
707  {
708  return k;
709  }
710  std::vector< float > aVector(3);
711  float aMag = sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
712  for (k = 0; k < 3; k++)
713  {
714  aVector[k] = a[k]/aMag;
715  }
716 
717  this->DiffusionGradientOrientation.push_back( aVector );
718  return (this->DiffusionGradientOrientation.size()-1);
719  }
720 
724  int InsertSliceLocation ( float a )
725  {
726  int k = ExistSliceLocation( a );
727  if ( k >= 0 )
728  {
729  return k;
730  }
731 
732  this->SliceLocation.push_back( a );
733  return (this->SliceLocation.size()-1);
734  }
738  {
739  int size = this->SliceLocation.size();
740  this->SliceLocation.push_back(
741  size > 0 ? this->SliceLocation.back() + 1 : 0.f);
742  return size;
743  }
744 
746  {
747  int k = ExistImageOrientationPatient( a );
748  if ( k >= 0 )
749  {
750  return k;
751  }
752  std::vector< float > aVector(6);
753  float aMag = sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
754  float bMag = sqrt(a[3]*a[3]+a[4]*a[4]+a[5]*a[5]);
755  for (k = 0; k < 3; k++)
756  {
757  aVector[k] = a[k]/aMag;
758  aVector[k+3] = a[k+3]/bMag;
759  }
760 
761  this->ImageOrientationPatient.push_back( aVector );
762  return (this->ImageOrientationPatient.size()-1);
763  }
764 
765  int InsertImagePositionPatient ( float *a )
766  {
767  int k = ExistImagePositionPatient( a );
768  if ( k >= 0 )
769  {
770  return k;
771  }
772 
773  std::vector< float > aVector(3);
774  for ( unsigned int i = 0; i < 3; i++ ) aVector[i] = a[i];
775  this->ImagePositionPatient.push_back( aVector );
776  return (this->ImagePositionPatient.size()-1);
777  }
778 
779  void AnalyzeDicomHeaders( );
780 
781  void AssembleNthVolume( int n );
782  int AssembleVolumeContainingArchetype();
783 
784  void GroupFiles ( int idxSeriesInstanceUID,
785  int idxContentTime,
786  int idxTriggerTime,
787  int idxEchoNumbers,
788  int idxDiffusionGradientOrientation,
789  int idxSliceLocation,
790  int idxImageOrientationPatient );
791 
792  const char* GetNthFileName ( int idxSeriesInstanceUID,
793  int idxContentTime,
794  int idxTriggerTime,
795  int idxEchoNumbers,
796  int idxDiffusionGradientOrientation,
797  int idxSliceLocation,
798  int idxImageOrientationPatient,
799  int n );
800 
801 
802 protected:
805 
807  static std::string GetMetaDataWithoutSpaces(const itk::MetaDataDictionary &dict, const std::string& tag);
808 
809  char *Archetype;
812  int DataExtent[6];
813 
815  unsigned int NumberOfComponents;
816 
817  std::vector<double> MetaDataScalarRangeMinima;
818  std::vector<double> MetaDataScalarRangeMaxima;
819  void GetScalarRangeMetaDataKeys(itk::ImageIOBase::Pointer imageIO,
820  std::string range_keys[2]);
821  void SetMetaDataScalarRangeToPointDataInfo(vtkImageData* data);
822 
823  double DefaultDataSpacing[3];
824  double DefaultDataOrigin[3];
825  float ScanAxis[3];
826  float ScanOrigin[3];
827 
831 
832  vtkMatrix4x4* RasToIjkMatrix;
833  vtkMatrix4x4* MeasurementFrameMatrix;
834 
838 
840 
849 
850  unsigned int IndexArchetype;
851 
852  std::vector<std::string> FileNames;
853  std::vector<std::pair <double, int> > FileNameSliceKey;
854  CoordinateOrientationCode DesiredCoordinateOrientation;
855  virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *) VTK_OVERRIDE;
856 
857  itk::MetaDataDictionary Dictionary;
858 
872 
873  std::vector<std::string> AllFileNames;
877 
878  std::vector<std::string> SeriesInstanceUIDs;
879  std::vector<std::string> ContentTime;
880  std::vector<std::string> TriggerTime;
881  std::vector<std::string> EchoNumbers;
882  std::vector< std::vector<float> > DiffusionGradientOrientation;
883  std::vector<float> SliceLocation;
884  std::vector< std::vector<float> > ImageOrientationPatient;
885  std::vector< std::vector<float> > ImagePositionPatient;
886 
888  std::vector<long int> IndexSeriesInstanceUIDs;
889  std::vector<long int> IndexContentTime;
890  std::vector<long int> IndexTriggerTime;
891  std::vector<long int> IndexEchoNumbers;
892  std::vector<long int> IndexDiffusionGradientOrientation;
893  std::vector<long int> IndexSliceLocation;
894  std::vector<long int> IndexImageOrientationPatient;
895  std::vector<long int> IndexImagePositionPatient;
896 
897 private:
899  void operator=(const vtkITKArchetypeImageSeriesReader&);
900 };
901 
902 #endif
std::vector< long int > IndexSeriesInstanceUIDs
index of each dicom file into the above arrays
std::vector< std::vector< float > > ImageOrientationPatient
std::vector< std::vector< float > > DiffusionGradientOrientation
const char * GetNthSeriesInstanceUID(unsigned int n)
methods to get N-th discriminator
int ExistSeriesInstanceUID(const char *SeriesInstanceUID)
check the existance of given discriminator
void SetUseNativeOriginOff()
Use image center as origin.
Read a series of files that have a common naming convention.
void SetUseNativeOriginOn()
Use image origin from the file.
std::vector< std::pair< double, int > > FileNameSliceKey
unsigned int GetNumberOfSeriesInstanceUIDs()
get number of certain discriminators in the directory
bool GetGroupingByTags()
set/get functions for grouping by tags
int ExistImageOrientationPatient(float *directionCosine)
std::vector< std::vector< float > > ImagePositionPatient
itk::SpatialOrientation::ValidCoordinateOrientationFlags CoordinateOrientationCode
void SetDesiredCoordinateOrientationToAxial()
Set the orientation of the output image.