Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkThreeDnTDICOMSeriesReader.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
19 
21 ::ThreeDnTDICOMSeriesReader(unsigned int decimalPlacesForOrientation)
22 :DICOMITKSeriesGDCMReader(decimalPlacesForOrientation)
23 ,m_Group3DandT(true)
24 {
25 }
26 
30 ,m_Group3DandT(true)
31 {
32 }
33 
36 {
37 }
38 
42 {
43  if (this != &other)
44  {
46  this->m_Group3DandT = other.m_Group3DandT;
47  }
48  return *this;
49 }
50 
51 bool
53 ::operator==(const DICOMFileReader& other) const
54 {
55  if (const Self* otherSelf = dynamic_cast<const Self*>(&other))
56  {
57  return
59  && this->m_Group3DandT == otherSelf->m_Group3DandT;
60  }
61  else
62  {
63  return false;
64  }
65 }
66 
67 void
70 {
71  m_Group3DandT = on;
72 }
73 
74 bool
77 {
78  return m_Group3DandT;
79 }
80 
84 {
85  if (!m_Group3DandT)
86  {
87  return resultOf3DGrouping; // don't work if nobody asks us to
88  }
89 
90  SortingBlockList remainingBlocks = resultOf3DGrouping;
91 
92  SortingBlockList non3DnTBlocks;
93  SortingBlockList true3DnTBlocks;
94  std::vector<unsigned int> true3DnTBlocksTimeStepCount;
95 
96  // we should describe our need for this tag as needed via a function
97  // (however, we currently know that the superclass will always need this tag)
98  const DICOMTag tagImagePositionPatient(0x0020, 0x0032);
99 
100  while (!remainingBlocks.empty())
101  {
102  // new block to fill up
103  const DICOMDatasetAccessingImageFrameList& firstBlock = remainingBlocks.front();
104  DICOMDatasetAccessingImageFrameList current3DnTBlock = firstBlock;
105  int current3DnTBlockNumberOfTimeSteps = 1;
106 
107  // get block characteristics of first block
108  const unsigned int currentBlockNumberOfSlices = firstBlock.size();
109  const std::string currentBlockFirstOrigin = firstBlock.front()->GetTagValueAsString( tagImagePositionPatient ).value;
110  const std::string currentBlockLastOrigin = firstBlock.back()->GetTagValueAsString( tagImagePositionPatient ).value;
111 
112  remainingBlocks.erase( remainingBlocks.begin() );
113 
114  // compare all other blocks against the first one
115  for (auto otherBlockIter = remainingBlocks.begin();
116  otherBlockIter != remainingBlocks.cend();
117  /*++otherBlockIter*/) // <-- inside loop
118  {
119  // get block characteristics from first block
120  const DICOMDatasetAccessingImageFrameList otherBlock = *otherBlockIter;
121 
122  const unsigned int otherBlockNumberOfSlices = otherBlock.size();
123  const std::string otherBlockFirstOrigin = otherBlock.front()->GetTagValueAsString( tagImagePositionPatient ).value;
124  const std::string otherBlockLastOrigin = otherBlock.back()->GetTagValueAsString( tagImagePositionPatient ).value;
125 
126  // add matching blocks to current3DnTBlock
127  // keep other blocks for later
128  if ( otherBlockNumberOfSlices == currentBlockNumberOfSlices
129  && otherBlockFirstOrigin == currentBlockFirstOrigin
130  && otherBlockLastOrigin == currentBlockLastOrigin
131  )
132  { // matching block
133  ++current3DnTBlockNumberOfTimeSteps;
134  current3DnTBlock.insert( current3DnTBlock.end(), otherBlock.begin(), otherBlock.end() ); // append
135  // remove this block from remainingBlocks
136  otherBlockIter = remainingBlocks.erase(otherBlockIter); // make sure iterator otherBlockIter is valid afterwards
137  }
138  else
139  {
140  ++otherBlockIter;
141  }
142  }
143 
144  // in any case, we now now all about the first block of our list ...
145  // ... and we wither call it 3D o 3D+t
146  if (current3DnTBlockNumberOfTimeSteps > 1)
147  {
148  true3DnTBlocks.push_back(current3DnTBlock);
149  true3DnTBlocksTimeStepCount.push_back(current3DnTBlockNumberOfTimeSteps);
150  }
151  else
152  {
153  non3DnTBlocks.push_back(current3DnTBlock);
154  }
155  }
156 
157  // create output for real 3D+t blocks (other outputs will be created by superclass)
158  // set 3D+t flag on output block
159  this->SetNumberOfOutputs( true3DnTBlocks.size() );
160  unsigned int o = 0;
161  for (auto blockIter = true3DnTBlocks.cbegin();
162  blockIter != true3DnTBlocks.cend();
163  ++o, ++blockIter)
164  {
165  // bad copy&paste code from DICOMITKSeriesGDCMReader, should be handled in a better way
166  DICOMDatasetAccessingImageFrameList gdcmFrameInfoList = *blockIter;
167  assert(!gdcmFrameInfoList.empty());
168 
169  // reverse frames if necessary
170  // update tilt information from absolute last sorting
171  const DICOMDatasetList datasetList = ConvertToDICOMDatasetList( gdcmFrameInfoList );
172  m_NormalDirectionConsistencySorter->SetInput( datasetList );
173  m_NormalDirectionConsistencySorter->Sort();
174  const DICOMDatasetAccessingImageFrameList sortedGdcmInfoFrameList = ConvertToDICOMDatasetAccessingImageFrameList( m_NormalDirectionConsistencySorter->GetOutput(0) );
175  const GantryTiltInformation& tiltInfo = m_NormalDirectionConsistencySorter->GetTiltInformation();
176 
177  // set frame list for current block
178  const DICOMImageFrameList frameList = ConvertToDICOMImageFrameList( sortedGdcmInfoFrameList );
179  assert(!frameList.empty());
180 
182  block.SetTagCache( this->GetTagCache() ); // important: this must be before SetImageFrameList(), because SetImageFrameList will trigger reading of lots of interesting tags!
183  block.SetAdditionalTagsOfInterest(GetAdditionalTagsOfInterest());
184  block.SetTagLookupTableToPropertyFunctor(GetTagLookupTableToPropertyFunctor());
185  block.SetImageFrameList( frameList );
186  block.SetTiltInformation( tiltInfo );
187 
188  block.SetFlag("3D+t", true);
189  block.SetIntProperty("timesteps", true3DnTBlocksTimeStepCount[o]);
190  MITK_DEBUG << "Found " << true3DnTBlocksTimeStepCount[o] << " timesteps";
191 
192  this->SetOutput( o, block );
193  }
194 
195  return non3DnTBlocks;
196 }
197 
198 bool
201 {
202  bool success = true;
203 
204  unsigned int numberOfOutputs = this->GetNumberOfOutputs();
205  for (unsigned int o = 0; o < numberOfOutputs; ++o)
206  {
207  const DICOMImageBlockDescriptor& block = this->InternalGetOutput(o);
208 
209  if (block.GetFlag("3D+t", false))
210  {
211  success &= this->LoadMitkImageForOutput(o);
212  }
213  else
214  {
215  success &= DICOMITKSeriesGDCMReader::LoadMitkImageForOutput(o); // let superclass handle non-3D+t
216  }
217  }
218 
219  return success;
220 }
221 
222 bool
225 {
226  PushLocale();
228  const GantryTiltInformation tiltInfo = block.GetTiltInformation();
229  const bool hasTilt = tiltInfo.IsRegularGantryTilt();
230 
231  const int numberOfTimesteps = block.GetNumberOfTimeSteps();
232 
233  if (numberOfTimesteps == 1)
234  {
236  }
237 
238  const int numberOfFramesPerTimestep = block.GetNumberOfFramesPerTimeStep();
239 
241  for (int timeStep = 0; timeStep<numberOfTimesteps; ++timeStep)
242  {
243  // use numberOfFramesPerTimestep frames for a new item in filenamesPerTimestep
244  ITKDICOMSeriesReaderHelper::StringContainer filenamesOfThisTimeStep;
245  auto timeStepStart = frames.cbegin() + timeStep * numberOfFramesPerTimestep;
246  auto timeStepEnd = frames.cbegin() + (timeStep+1) * numberOfFramesPerTimestep;
247  for (auto frameIter = timeStepStart;
248  frameIter != timeStepEnd;
249  ++frameIter)
250  {
251  filenamesOfThisTimeStep.push_back( (*frameIter)->Filename );
252  }
253  filenamesPerTimestep.push_back( filenamesOfThisTimeStep );
254  }
255 
257  mitk::Image::Pointer mitkImage = helper.Load3DnT( filenamesPerTimestep, m_FixTiltByShearing && hasTilt, tiltInfo );
258 
259  block.SetMitkImage( mitkImage );
260 
261  PopLocale();
262 
263  return true;
264 }
section MAP_FRAME_Mapper_Settings Mapper settings For the mapping of corrected you have several settings but high interpolation errors for gray value images Right choice for label images or masks li Details of the frame selection In this tab you can specify the frames of the currently selected image that should be corrected As default all frames of an image will be corrected If you only select specific frames
const DICOMImageFrameList & GetImageFrameList() const
List of frames that constitute the mitk::Image (DICOMImageFrames)
virtual bool operator==(const DICOMFileReader &other) const override
bool IsRegularGantryTilt() const
Whether the shearing is a gantry tilt or more complicated.
Flexible reader based on itk::ImageSeriesReader and GDCM, for single-slice modalities like CT...
virtual bool operator==(const DICOMFileReader &other) const override
Representation of a DICOM tag.
Definition: mitkDICOMTag.h:37
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
const GantryTiltInformation GetTiltInformation() const
Describe the gantry tilt of the acquisition.
MITKDICOMREADER_EXPORT mitk::DICOMDatasetList ConvertToDICOMDatasetList(const DICOMDatasetAccessingImageFrameList &input)
MITKDICOMREADER_EXPORT mitk::DICOMDatasetAccessingImageFrameList ConvertToDICOMDatasetAccessingImageFrameList(const DICOMDatasetList &input)
void SetMitkImage(Image::Pointer image)
The 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList.
ThreeDnTDICOMSeriesReader(unsigned int decimalPlacesForOrientation=5)
Image::Pointer Load3DnT(const StringContainerList &filenamesLists, bool correctTilt, const GantryTiltInformation &tiltInfo)
virtual SortingBlockList Condense3DBlocks(SortingBlockList &) override
Analyze the groups produced by DICOMITKSeriesGDCMReader for 3D+t properties. This method tests whethe...
std::vector< DICOMImageFrameInfo::Pointer > DICOMImageFrameList
void SetGroup3DandT(bool on)
Control whether 3D+t grouping shall actually be attempted.
virtual bool LoadMitkImageForImageBlockDescriptor(DICOMImageBlockDescriptor &block) const
bool GetFlag(const std::string &key, bool defaultValue) const
Convenience function around GetProperty()
Output descriptor for DICOMFileReader.
void SetTagCache(DICOMTagCache *privateCache)
bool LoadMitkImageForImageBlockDescriptor(DICOMImageBlockDescriptor &block) const override
ThreeDnTDICOMSeriesReader & operator=(const ThreeDnTDICOMSeriesReader &other)
Extends DICOMITKSeriesGDCMReader by sorting/grouping into 3D+t image blocks.
virtual bool LoadImages() override
Load via multiple calls to itk::ImageSeriesReader.
std::list< StringContainer > StringContainerList
virtual bool LoadMitkImageForOutput(unsigned int o)
Loads the mitk::Image by means of an itk::ImageSeriesReader.
std::vector< DICOMDatasetAccessingImageFrameList > SortingBlockList
MITKDICOMREADER_EXPORT mitk::DICOMImageFrameList ConvertToDICOMImageFrameList(const DICOMDatasetAccessingImageFrameList &input)
std::vector< DICOMDatasetAccessingImageFrameInfo::Pointer > DICOMDatasetAccessingImageFrameList
Gantry tilt analysis result.
DICOMITKSeriesGDCMReader & operator=(const DICOMITKSeriesGDCMReader &other)
std::vector< DICOMDatasetAccess * > DICOMDatasetList
Interface for DICOM readers that produce mitk::Images.