Slicer 5.9
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
Loading...
Searching...
No Matches
vtkITKArchetypeImageSeriesReader.h
Go to the documentation of this file.
1/*=========================================================================
2
3Copyright Brigham and Women's Hospital (BWH) All Rights Reserved.
4
5See COPYRIGHT.txt
6or http://www.slicer.org/copyright/copyright.txt for details.
7
8Program: vtkITK
9Module: $HeadURL$
10Date: $Date$
11Version: $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"
23class 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
53class VTK_ITK_EXPORT vtkITKArchetypeImageSeriesReader : public vtkImageAlgorithm
54{
55public:
57 vtkTypeMacro(vtkITKArchetypeImageSeriesReader, vtkImageAlgorithm);
58 void PrintSelf(ostream& os, vtkIndent indent) override;
59
60 using CoordinateOrientationCode = itk::SpatialOrientationEnums::ValidCoordinateOrientations;
61
64 vtkSetStringMacro(Archetype);
65 vtkGetStringMacro(Archetype);
66
69 unsigned int GetNumberOfFileNames();
72 const std::vector<std::string>& GetFileNames();
73
78 unsigned int AddFileName(const char* filename);
79 const char* GetFileName(unsigned int n);
81
85 vtkSetVector3Macro(DefaultDataSpacing, double);
86 vtkGetVector3Macro(DefaultDataSpacing, double);
87
92 vtkSetVector3Macro(DefaultDataOrigin, double);
93 vtkGetVector3Macro(DefaultDataOrigin, double);
94
98 vtkSetMacro(FileNameSliceOffset, int);
99 vtkGetMacro(FileNameSliceOffset, int);
100
105 vtkSetMacro(FileNameSliceSpacing, int);
106 vtkGetMacro(FileNameSliceSpacing, int);
107
111 vtkSetMacro(FileNameSliceCount, int);
112 vtkGetMacro(FileNameSliceCount, int);
113
115 virtual int CanReadFile(const char* filename);
116
120 {
121 this->DesiredCoordinateOrientation = CoordinateOrientationCode::ITK_COORDINATE_ORIENTATION_RAI;
124 this->Modified();
125 }
127 {
128 this->DesiredCoordinateOrientation = CoordinateOrientationCode::ITK_COORDINATE_ORIENTATION_RSA;
131 this->Modified();
132 }
134 {
135 this->DesiredCoordinateOrientation = CoordinateOrientationCode::ITK_COORDINATE_ORIENTATION_ASL;
138 this->Modified();
139 }
141 {
143 this->Modified();
144 }
147
153 {
155 this->SetOutputScalarType(VTK_DOUBLE);
156 }
158 {
160 this->SetOutputScalarType(VTK_FLOAT);
161 }
163 {
165 this->SetOutputScalarType(VTK_LONG);
166 }
168 {
170 this->SetOutputScalarType(VTK_UNSIGNED_LONG);
171 }
173 {
175 this->SetOutputScalarType(VTK_INT);
176 }
178 {
180 this->SetOutputScalarType(VTK_UNSIGNED_INT);
181 }
183 {
185 this->SetOutputScalarType(VTK_SHORT);
186 }
188 {
190 this->SetOutputScalarType(VTK_UNSIGNED_SHORT);
191 }
193 {
195 this->SetOutputScalarType(VTK_CHAR);
196 }
198 {
200 this->SetOutputScalarType(VTK_UNSIGNED_CHAR);
201 }
203 {
205 this->Modified();
206 }
207
211
215
218 enum
219 {
220 GDCM = 0,
222 };
224 vtkGetMacro(DICOMImageIOApproach, int);
227
230 vtkSetMacro(OutputScalarType, int);
231 vtkGetMacro(OutputScalarType, int);
232
235 vtkSetMacro(NumberOfComponents, unsigned int);
236 vtkGetMacro(NumberOfComponents, unsigned int);
237
240 vtkSetMacro(SingleFile, int);
241 vtkGetMacro(SingleFile, int);
242
245 vtkSetMacro(AnalyzeHeader, bool);
246 vtkGetMacro(AnalyzeHeader, bool);
247
250 vtkSetMacro(UseOrientationFromFile, int);
251 vtkGetMacro(UseOrientationFromFile, int);
252
255 vtkMatrix4x4* GetRasToIjkMatrix();
256
260
262 vtkSetMacro(VoxelVectorType, int);
263 vtkGetMacro(VoxelVectorType, int);
264
267 const itk::MetaDataDictionary& GetMetaDataDictionary() const;
268 std::vector<std::string> Tags;
269 std::vector<std::string> TagValues;
271
273 bool HasKey(char* tag);
274 const char* GetNthKey(unsigned int n);
275 const char* GetNthValue(unsigned int n);
276 const char* GetTagValue(char* tag);
277
280
282
284
286 int GetSelectedUID() { return SelectedUID; }
287
288 void SetSelectedUID(int v)
289 {
290 SelectedUID = v;
292 }
293
296
298 {
301 }
302
305
307 {
310 }
311
314
316 {
319 }
320
323
325 {
328 }
329
332
334 {
335 SelectedSlice = v;
337 }
338
341
343 {
346 }
347
349 unsigned int GetNumberOfSeriesInstanceUIDs() { return this->SeriesInstanceUIDs.size(); }
350
351 unsigned int GetNumberOfContentTime() { return this->ContentTime.size(); }
352
353 unsigned int GetNumberOfTriggerTime() { return this->TriggerTime.size(); }
354
355 unsigned int GetNumberOfEchoNumbers() { return this->EchoNumbers.size(); }
356
357 unsigned int GetNumberOfSliceLocation() { return this->SliceLocation.size(); }
358
360
361 unsigned int GetNumberOfImageOrientationPatient() { return this->ImageOrientationPatient.size(); };
362
363 unsigned int GetNumberOfImagePositionPatient() { return this->ImagePositionPatient.size(); }
364
366 int ExistSeriesInstanceUID(const char* SeriesInstanceUID)
367 {
368 for (unsigned int k = 0; k < GetNumberOfSeriesInstanceUIDs(); k++)
369 {
370 if (this->SeriesInstanceUIDs[k].find(SeriesInstanceUID) != std::string::npos)
371 {
372 return k;
373 }
374 }
375 return -1;
376 }
377
378 int ExistContentTime(const char* contentTime)
379 {
380 for (unsigned int k = 0; k < GetNumberOfContentTime(); k++)
381 {
382 if (this->ContentTime[k].find(contentTime) != std::string::npos)
383 {
384 return k;
385 }
386 }
387 return -1;
388 }
389
390 int ExistTriggerTime(const char* triggerTime)
391 {
392 for (unsigned int k = 0; k < GetNumberOfTriggerTime(); k++)
393 {
394 if (this->TriggerTime[k].find(triggerTime) != std::string::npos)
395 {
396 return k;
397 }
398 }
399 return -1;
400 }
401
402 int ExistEchoNumbers(const char* echoNumbers)
403 {
404 for (unsigned int k = 0; k < GetNumberOfEchoNumbers(); k++)
405 {
406 if (this->EchoNumbers[k].find(echoNumbers) != std::string::npos)
407 {
408 return k;
409 }
410 }
411 return -1;
412 }
413
415 {
416 float a = 0;
417 for (int n = 0; n < 3; n++)
418 {
419 a += dgo[n] * dgo[n];
420 }
421
422 for (unsigned int k = 0; k < GetNumberOfDiffusionGradientOrientation(); k++)
423 {
424 float b = 0;
425 float c = 0;
426 for (int n = 0; n < 3; n++)
427 {
428 b += this->DiffusionGradientOrientation[k][n] * this->DiffusionGradientOrientation[k][n];
429 c += this->DiffusionGradientOrientation[k][n] * dgo[n];
430 }
431 c = fabs(c) / sqrt(a * b);
432
433 if (c > 0.99999)
434 {
435 return k;
436 }
437 }
438 return -1;
439 }
440
441 int ExistSliceLocation(float sliceLocation)
442 {
443 std::vector<float>::iterator iter = std::find(this->SliceLocation.begin(), this->SliceLocation.end(), sliceLocation);
444 return iter != this->SliceLocation.end() ? std::distance(this->SliceLocation.begin(), iter) : -1;
445 }
446
447 int ExistImageOrientationPatient(float* directionCosine)
448 {
450 float a = sqrt(directionCosine[0] * directionCosine[0] + directionCosine[1] * directionCosine[1] + directionCosine[2] * directionCosine[2]);
451 for (int k = 0; k < 3; k++)
452 {
453 directionCosine[k] /= a;
454 }
455 a = sqrt(directionCosine[3] * directionCosine[3] + directionCosine[4] * directionCosine[4] + directionCosine[5] * directionCosine[5]);
456 for (int k = 3; k < 6; k++)
457 {
458 directionCosine[k] /= a;
459 }
460
461 for (unsigned int k = 0; k < GetNumberOfImageOrientationPatient(); k++)
462 {
463 std::vector<float> aVec = ImageOrientationPatient[k];
464 a = sqrt(aVec[0] * aVec[0] + aVec[1] * aVec[1] + aVec[2] * aVec[2]);
465 float b = (directionCosine[0] * aVec[0] + directionCosine[1] * aVec[1] + directionCosine[2] * aVec[2]) / a;
466 if (b < 0.99999)
467 {
468 continue;
469 }
470
471 a = sqrt(aVec[3] * aVec[3] + aVec[4] * aVec[4] + aVec[5] * aVec[5]);
472 b = (directionCosine[3] * aVec[3] + directionCosine[4] * aVec[4] + directionCosine[5] * aVec[5]) / a;
473 if (b > 0.99999)
474 {
475 return k;
476 }
477 }
478 return -1;
479 }
480
482 {
483 float a = 0;
484 for (int n = 0; n < 3; n++)
485 {
486 a += ipp[n] * ipp[n];
487 }
488
489 for (unsigned int k = 0; k < GetNumberOfImagePositionPatient(); k++)
490 {
491 float b = 0;
492 float c = 0;
493 for (int n = 0; n < 3; n++)
494 {
495 b += this->ImagePositionPatient[k][n] * this->ImagePositionPatient[k][n];
496 c += this->ImagePositionPatient[k][n] * ipp[n];
497 }
498 c = fabs(c) / sqrt(a * b);
499 if (c > 0.99999)
500 {
501 return k;
502 }
503 }
504 return -1;
505 }
506
508 const char* GetNthSeriesInstanceUID(unsigned int n)
509 {
510 if (n >= this->GetNumberOfSeriesInstanceUIDs())
511 {
512 return nullptr;
513 }
514 return this->SeriesInstanceUIDs[n].c_str();
515 }
516
517 const char* GetNthContentTime(unsigned int n)
518 {
519 if (n >= this->GetNumberOfContentTime())
520 {
521 return nullptr;
522 }
523 return this->ContentTime[n].c_str();
524 }
525
526 const char* GetNthTriggerTime(unsigned int n)
527 {
528 if (n >= this->GetNumberOfTriggerTime())
529 {
530 return nullptr;
531 }
532 return this->TriggerTime[n].c_str();
533 }
534
535 const char* GetNthEchoNumbers(unsigned int n)
536 {
537 if (n >= this->GetNumberOfEchoNumbers())
538 {
539 return nullptr;
540 }
541 return this->EchoNumbers[n].c_str();
542 }
543
545 {
547 {
548 return nullptr;
549 }
550 float* dgo = new float[3];
551 for (int k = 0; k < 3; k++)
552 {
553 dgo[k] = this->DiffusionGradientOrientation[n][k];
554 }
555 return dgo;
556 }
557
558 float GetNthSliceLocation(unsigned int n)
559 {
560 if (n >= this->GetNumberOfSliceLocation())
561 {
562 return this->SliceLocation[0];
563 }
564 return this->SliceLocation[0];
565 }
566
567 float* GetNthImageOrientationPatient(unsigned int n)
568 {
569 if (n >= this->GetNumberOfImageOrientationPatient())
570 {
571 return nullptr;
572 }
573 float* dgo = new float[6];
574 for (int k = 0; k < 6; k++)
575 {
576 dgo[k] = this->ImageOrientationPatient[n][k];
577 }
578 return dgo;
579 }
580
581 float* GetNthImagePositionPatient(unsigned int n)
582 {
583 if (n >= this->GetNumberOfImagePositionPatient())
584 {
585 return nullptr;
586 }
587 float* ipp = new float[3];
588 for (int k = 0; k < 3; k++)
589 {
590 ipp[k] = this->ImagePositionPatient[n][k];
591 }
592 return ipp;
593 }
594
597 int InsertSeriesInstanceUIDs(const char* aUID)
598 {
599 int k = ExistSeriesInstanceUID(aUID);
600 if (k >= 0)
601 {
602 return k;
603 }
604
605 std::string aVector(aUID);
606 this->SeriesInstanceUIDs.push_back(aVector);
607 return (this->SeriesInstanceUIDs.size() - 1);
608 }
609
610 int InsertContentTime(const char* aTime)
611 {
612 int k = ExistContentTime(aTime);
613 if (k >= 0)
614 {
615 return k;
616 }
617
618 std::string aVector(aTime);
619 this->ContentTime.push_back(aVector);
620 return (this->ContentTime.size() - 1);
621 }
622
623 int InsertTriggerTime(const char* aTime)
624 {
625 int k = ExistTriggerTime(aTime);
626 if (k >= 0)
627 {
628 return k;
629 }
630
631 std::string aVector(aTime);
632 this->TriggerTime.push_back(aVector);
633 return (this->TriggerTime.size() - 1);
634 }
635
636 int InsertEchoNumbers(const char* aEcho)
637 {
638 int k = ExistEchoNumbers(aEcho);
639 if (k >= 0)
640 {
641 return k;
642 }
643
644 std::string aVector(aEcho);
645 this->EchoNumbers.push_back(aVector);
646 return (this->EchoNumbers.size() - 1);
647 }
648
650 {
652 if (k >= 0)
653 {
654 return k;
655 }
656 std::vector<float> aVector(3);
657 float aMag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
658 for (k = 0; k < 3; k++)
659 {
660 aVector[k] = a[k] / aMag;
661 }
662
663 this->DiffusionGradientOrientation.push_back(aVector);
664 return (this->DiffusionGradientOrientation.size() - 1);
665 }
666
671 {
672 int k = ExistSliceLocation(a);
673 if (k >= 0)
674 {
675 return k;
676 }
677
678 this->SliceLocation.push_back(a);
679 return (this->SliceLocation.size() - 1);
680 }
681
684 {
685 int size = this->SliceLocation.size();
686 this->SliceLocation.push_back(size > 0 ? this->SliceLocation.back() + 1 : 0.f);
687 return size;
688 }
689
691 {
693 if (k >= 0)
694 {
695 return k;
696 }
697 std::vector<float> aVector(6);
698 float aMag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
699 float bMag = sqrt(a[3] * a[3] + a[4] * a[4] + a[5] * a[5]);
700 for (k = 0; k < 3; k++)
701 {
702 aVector[k] = a[k] / aMag;
703 aVector[k + 3] = a[k + 3] / bMag;
704 }
705
706 this->ImageOrientationPatient.push_back(aVector);
707 return (this->ImageOrientationPatient.size() - 1);
708 }
709
711 {
712 int k = ExistImagePositionPatient(a);
713 if (k >= 0)
714 {
715 return k;
716 }
717
718 std::vector<float> aVector(3);
719 for (unsigned int i = 0; i < 3; i++)
720 {
721 aVector[i] = a[i];
722 }
723 this->ImagePositionPatient.push_back(aVector);
724 return (this->ImagePositionPatient.size() - 1);
725 }
726
728
729 void AssembleNthVolume(int n);
731
732 void GroupFiles(int idxSeriesInstanceUID,
733 int idxContentTime,
734 int idxTriggerTime,
735 int idxEchoNumbers,
736 int idxDiffusionGradientOrientation,
737 int idxSliceLocation,
738 int idxImageOrientationPatient);
739
740 const char* GetNthFileName(int idxSeriesInstanceUID,
741 int idxContentTime,
742 int idxTriggerTime,
743 int idxEchoNumbers,
744 int idxDiffusionGradientOrientation,
745 int idxSliceLocation,
746 int idxImageOrientationPatient,
747 int n);
748
749 static bool ReadMeasurementFrameMatrixFromMetaDataDictionary(const itk::MetaDataDictionary& dictionary, vtkMatrix4x4* measurementFrameMatrix);
750
755 static bool IsListPixelComponentTypeInMetaDataDictionary(const itk::MetaDataDictionary& dictionary);
756
757protected:
760
762 static std::string GetMetaDataWithoutSpaces(const itk::MetaDataDictionary& dict, const std::string& tag);
763
765 itk::ImageIOBase::Pointer GetImageIO(const char* filename);
766
771
773 unsigned int NumberOfComponents;
774
775 std::vector<double> MetaDataScalarRangeMinima;
776 std::vector<double> MetaDataScalarRangeMaxima;
777 void GetScalarRangeMetaDataKeys(itk::ImageIOBase::Pointer imageIO, std::string range_keys[2]);
779
782 float ScanAxis[3];
783 float ScanOrigin[3];
784
788
789 vtkMatrix4x4* RasToIjkMatrix;
791
795
797
806
807 unsigned int IndexArchetype;
808
809 std::vector<std::string> FileNames;
810 std::vector<std::pair<double, int>> FileNameSliceKey;
812 int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
813
814 itk::MetaDataDictionary Dictionary;
815
829
830 std::vector<std::string> AllFileNames;
834
835 std::vector<std::string> SeriesInstanceUIDs;
836 std::vector<std::string> ContentTime;
837 std::vector<std::string> TriggerTime;
838 std::vector<std::string> EchoNumbers;
839 std::vector<std::vector<float>> DiffusionGradientOrientation;
840 std::vector<float> SliceLocation;
841 std::vector<std::vector<float>> ImageOrientationPatient;
842 std::vector<std::vector<float>> ImagePositionPatient;
843
845 std::vector<long int> IndexSeriesInstanceUIDs;
846 std::vector<long int> IndexContentTime;
847 std::vector<long int> IndexTriggerTime;
848 std::vector<long int> IndexEchoNumbers;
850 std::vector<long int> IndexSliceLocation;
851 std::vector<long int> IndexImageOrientationPatient;
852 std::vector<long int> IndexImagePositionPatient;
853
855
856private:
858 void operator=(const vtkITKArchetypeImageSeriesReader&) = delete;
859};
860
861#endif
bool GetGroupingByTags()
set/get functions for grouping by tags
void GetScalarRangeMetaDataKeys(itk::ImageIOBase::Pointer imageIO, std::string range_keys[2])
const char * GetNthFileName(int idxSeriesInstanceUID, int idxContentTime, int idxTriggerTime, int idxEchoNumbers, int idxDiffusionGradientOrientation, int idxSliceLocation, int idxImageOrientationPatient, int n)
std::vector< std::vector< float > > DiffusionGradientOrientation
virtual int CanReadFile(const char *filename)
Determine if the file can be read using ITK.
static bool IsListPixelComponentTypeInMetaDataDictionary(const itk::MetaDataDictionary &dictionary)
unsigned int AddFileName(const char *filename)
itk::SpatialOrientationEnums::ValidCoordinateOrientations CoordinateOrientationCode
int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override
std::vector< std::vector< float > > ImageOrientationPatient
void SetMetaDataScalarRangeToPointDataInfo(vtkImageData *data)
void SetDesiredCoordinateOrientationToAxial()
Set the orientation of the output image.
unsigned int GetNumberOfFileNames()
See how many file names were generated during ExecuteInformation.
void SetUseNativeOriginOn()
Use image origin from the file.
void PrintSelf(ostream &os, vtkIndent indent) override
int ExistImageOrientationPatient(float *directionCosine)
static vtkITKArchetypeImageSeriesReader * New()
std::vector< std::vector< float > > ImagePositionPatient
virtual void SetDICOMImageIOApproach(int)
static std::string GetMetaDataWithoutSpaces(const itk::MetaDataDictionary &dict, const std::string &tag)
Get MetaData from dictionary, removing all whitespaces from the string.
vtkMatrix4x4 * GetRasToIjkMatrix()
Returns an IJK to RAS transformation matrix.
int ExistSeriesInstanceUID(const char *SeriesInstanceUID)
check the existence of given discriminator
const char * GetNthValue(unsigned int n)
unsigned int GetNumberOfItemsInDictionary()
void SetUseNativeOriginOff()
Use image center as origin.
const char * GetTagValue(char *tag)
const char * GetNthSeriesInstanceUID(unsigned int n)
methods to get N-th discriminator
const itk::MetaDataDictionary & GetMetaDataDictionary() const
Return the MetaDataDictionary from the ITK layer.
const char * GetNthKey(unsigned int n)
void GroupFiles(int idxSeriesInstanceUID, int idxContentTime, int idxTriggerTime, int idxEchoNumbers, int idxDiffusionGradientOrientation, int idxSliceLocation, int idxImageOrientationPatient)
static bool ReadMeasurementFrameMatrixFromMetaDataDictionary(const itk::MetaDataDictionary &dictionary, vtkMatrix4x4 *measurementFrameMatrix)
std::vector< std::pair< double, int > > FileNameSliceKey
unsigned int GetNumberOfSeriesInstanceUIDs()
get number of certain discriminators in the directory
vtkMatrix4x4 * GetMeasurementFrameMatrix()
Returns the Measurement frame matrix.
itk::ImageIOBase::Pointer GetImageIO(const char *filename)
Get the image IO for the specified filename.
const char * GetFileName(unsigned int n)
const std::vector< std::string > & GetFileNames()
Return all the file names.
virtual void SetOutputScalarType(int)
Get the file format. Pixels are this type in the file.
std::vector< long int > IndexSeriesInstanceUIDs
index of each dicom file into the above arrays