Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkDiffusionDICOMFileReader.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 
18 
20 
26 #include <mitkITKImageImport.h>
27 
28 #include "mitkStringProperty.h"
29 #include <mitkImageCast.h>
30 
32 {
33  unsigned int images = headers.size();
34 
35  unsigned int unweighted_images = 0;
36  unsigned int weighted_images = 0;
37 
38  mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType::const_iterator c_iter = headers.begin();
39  while( c_iter != headers.end() )
40  {
42  if( h.baseline ) unweighted_images++;
43  if( h.b_value > 0 ) weighted_images++;
44 
45  ++c_iter;
46  }
47 
48  MITK_INFO << " :: Analyzed volumes " << images << "\n"
49  << " :: \t"<< unweighted_images << " b = 0" << "\n"
50  << " :: \t"<< weighted_images << " b > 0";
51 }
52 
54 {
55 
56 }
57 
59 {
60 
61 }
62 
65 {
66  unsigned int numberOfOutputs = this->GetNumberOfOutputs();
67  bool success = true;
68 
69  for(unsigned int o = 0; o < numberOfOutputs; ++o)
70  {
71  success &= this->LoadSingleOutputImage( this->m_OutputHeaderContainer.at(o),
72  this->InternalGetOutput(o), this->m_IsMosaicData.at(o) );
73  }
74 
75  return success;
76 }
77 
80  DICOMImageBlockDescriptor& block, bool is_mosaic)
81 {
82  // prepare data reading
85 
87  int numberOfDWImages = block.GetIntProperty("timesteps", 1);
88 
89  int numberOfFramesPerDWImage = frames.size() / numberOfDWImages;
90 
91  assert( int( double((double) frames.size() / (double) numberOfDWImages)) == numberOfFramesPerDWImage );
92  for( int idx = 0; idx < numberOfDWImages; idx++ )
93  {
94  std::vector< std::string > FileNamesPerVolume;
95 
96  auto timeStepStart = frames.begin() + idx * numberOfFramesPerDWImage;
97  auto timeStepEnd = frames.begin() + (idx+1) * numberOfFramesPerDWImage;
98  for (auto frameIter = timeStepStart;
99  frameIter != timeStepEnd;
100  ++frameIter)
101  {
102  FileNamesPerVolume.push_back( (*frameIter)->Filename );
103  }
104 
105  filenames.push_back( FileNamesPerVolume );
106  }
107 
108  // TODO : only prototyping to test loading of diffusion images
109  // we need some solution for the different types
110  mitk::Image::Pointer output_image = mitk::Image::New();
111 
114 
115 
116  double max_bvalue = 0;
117  for( int idx = 0; idx < numberOfDWImages; idx++ )
118  {
119  DiffusionImageDICOMHeaderInformation header = retrievedHeader.at(idx);
120 
121  if( max_bvalue < header.b_value )
122  max_bvalue = header.b_value;
123  }
124 
125  // normalize the retrieved gradient directions according to the set b-value (maximal one)
126  for( int idx = 0; idx < numberOfDWImages; idx++ )
127  {
128  DiffusionImageDICOMHeaderInformation header = retrievedHeader.at(idx);
130 
131  grad.normalize();
132  grad *= sqrt( header.b_value / max_bvalue );
133 
134  directions->push_back( grad );
135  }
136 
137  // initialize the output image
139  output_image->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( max_bvalue ) );
140 
141  if( is_mosaic && this->m_ResolveMosaic )
142  {
145 
146  // retrieve the remaining meta-information needed for mosaic reconstruction
147  // it suffices to get it exemplatory from the first file in the file list
148  mosaic_reader->RetrieveMosaicInformation( filenames.at(0).at(0) );
149 
150  mitk::MosaicDescriptor mdesc = mosaic_reader->GetMosaicDescriptor();
151  mitk::CastToMitkImage( helper.LoadMosaicToVector<short, 3>( filenames, mdesc ), output_image );
152 
153  }
154  else
155  {
156  mitk::CastToMitkImage( helper.LoadToVector<short, 3>( filenames ), output_image );
157  }
158 
159  mitk::DiffusionPropertyHelper propertyHelper( output_image );
160  propertyHelper.InitializeImage();
161 
162  output_image->SetProperty("diffusion.dicom.importname", mitk::StringProperty::New( helper.GetOutputName(filenames) ) );
163  block.SetMitkImage( (mitk::Image::Pointer) output_image );
164 
165  return block.GetMitkImage().IsNotNull();
166 
167 }
168 
171 {
172  this->SetGroup3DandT(true);
173 
174  Superclass::AnalyzeInputFiles();
175 
176  // collect output from superclass
177  size_t number_of_outputs = this->GetNumberOfOutputs();
178 
179  if(number_of_outputs == 0)
180  {
181  MITK_ERROR << "Failed to parse input, retrieved 0 outputs from SeriesGDCMReader ";
182  }
183 
184  MITK_INFO("diffusion.dicomreader") << "Retrieved " << number_of_outputs << " outputs.";
185  std::vector< bool > valid_input_list;
186 
187  for( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); outputidx++ )
188  {
189  DICOMImageBlockDescriptor block_0 = this->GetOutput(outputidx);
190 
191  // collect vendor ID from the first output, first image
192  StringList inputFilename;
193  DICOMImageFrameInfo::Pointer frame_0 = block_0.GetImageFrameList().at(0);
194  inputFilename.push_back( frame_0->Filename );
195 
196 
198 
199  bool isMosaic = false;
200  gdcm::Scanner gdcmScanner;
201 
202  gdcm::Tag t_vendor(0x008, 0x0070);
203  gdcm::Tag t_imagetype(0x008, 0x008);
204 
205  // add DICOM Tag for vendor
206  gdcmScanner.AddTag( t_vendor );
207  // add DICOM Tag for image type
208  gdcmScanner.AddTag( t_imagetype );
209  if( gdcmScanner.Scan( inputFilename ) )
210  {
211 
212  // retrieve both vendor and image type
213  const char* ch_vendor = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_vendor );
214  const char* ch_image_type = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_imagetype );
215 
216  if( ch_vendor == NULL || ch_image_type == NULL )
217  {
218  MITK_WARN << "Unable to retrieve vendor/image information from " << frame_0->Filename.c_str() << "\n" <<
219  "Output " << outputidx+1 << " is not valid, skipping analysis.";
220  valid_input_list.push_back(false);
221  continue;
222 
223  }
224 
225  std::string vendor = std::string( ch_vendor );
226  std::string image_type = std::string( ch_image_type );
227  MITK_INFO("diffusion.dicomreader") << "Output " << outputidx+1 << " Got vendor: " << vendor << " image type " << image_type;
228 
229  // parse vendor tag
230  if( vendor.find("SIEMENS") != std::string::npos )
231  //&& image_type.find("DIFFUSION") != std::string::npos )
232  {
233  if( image_type.find("MOSAIC") != std::string::npos )
234  {
236  isMosaic = true;
237  }
238  else
239  {
241  }
242 
243  }
244  else if( vendor.find("GE") != std::string::npos )
245  {
247  }
248  else if( vendor.find("Philips") != std::string::npos )
249  {
251  }
252  else
253  {
254  // unknown vendor
255  }
256 
257  if( headerReader.IsNull() )
258  {
259  MITK_ERROR << "No header reader for given vendor. ";
260  valid_input_list.push_back(false);
261  continue;
262  }
263 
264  }
265  else
266  {
267  valid_input_list.push_back(false);
268  continue;
269  }
270 
271 
272  bool canread = false;
273  // iterate over the threeD+t block
274 
275  int numberOfTimesteps = block_0.GetIntProperty("timesteps", 1);
276  int framesPerTimestep = block_0.GetImageFrameList().size() / numberOfTimesteps;
277 
278  for( int idx = 0; idx < numberOfTimesteps; idx++ )
279  {
280  int access_idx = idx * framesPerTimestep;
281  DICOMImageFrameInfo::Pointer frame = this->GetOutput( outputidx ).GetImageFrameList().at( access_idx );
282  canread = headerReader->ReadDiffusionHeader( frame->Filename );
283  }
284 
285  if( canread )
286  {
287  // collect the information
288  mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType retrievedHeader = headerReader->GetHeaderInformation();
289 
290  m_IsMosaicData.push_back(isMosaic);
291  m_OutputHeaderContainer.push_back( retrievedHeader );
292  m_OutputReaderContainer.push_back( headerReader );
293  valid_input_list.push_back(true);
294  }
295  }
296 
297  // check status of the outputs and remove the non-valid
298  std::vector< DICOMImageBlockDescriptor > valid_outputs;
299  for ( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); ++outputidx )
300  {
301  if( valid_input_list.at(outputidx) )
302  {
303  valid_outputs.push_back( this->InternalGetOutput( outputidx ) );
304  }
305  }
306 
307  // clear complete list
308  this->ClearOutputs();
309  this->SetNumberOfOutputs( valid_outputs.size() );
310 
311  // insert only the valid ones
312  for ( unsigned int outputidx = 0; valid_outputs.size(); ++outputidx )
313  {
314  this->SetOutput( outputidx, valid_outputs.at( outputidx ) );
315  }
316 
317 
318 
319  for( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); outputidx++ )
320  {
321  // TODO : Analyze outputs + header information, i.e. for the loading confidence
322  MITK_INFO("diffusion.dicomreader") << "---- DICOM Analysis Report ---- :: Output " << outputidx+1 << " of " << this->GetNumberOfOutputs();
323 
324  try{
325  PerformHeaderAnalysis( this->m_OutputHeaderContainer.at( outputidx) );
326  }
327  catch( const std::exception& se)
328  {
329  MITK_ERROR << "STD Exception " << se.what();
330  }
331 
332  MITK_INFO("diffusion.dicomreader") << "===========================================";
333 
334  }
335 
336 
337 
338 }
339 
340 
342 ::CanHandleFile(const std::string & /* filename */)
343 {
344  //FIXME :
345  return true;
346 }
347 
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)
static const std::string REFERENCEBVALUEPROPERTYNAME
itk::SmartPointer< Self > Pointer
The MosaicDescriptor struct is a help struct holding the necessary information for loading a mosaic D...
int GetIntProperty(const std::string &key, int defaultValue) const
Convenience function around GetProperty()
#define MITK_INFO
Definition: mitkLogMacros.h:22
#define MITK_ERROR
Definition: mitkLogMacros.h:24
Helper class for mitk::Images containing diffusion weighted data.
bool LoadSingleOutputImage(DiffusionHeaderDICOMFileReader::DICOMHeaderListType, DICOMImageBlockDescriptor &, bool)
static void PerformHeaderAnalysis(mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType headers)
void SetMitkImage(Image::Pointer image)
The 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList.
void InitializeImage()
Make certain the owned image is up to date with all necessary properties.
The DiffusionImageHeaderInformation struct.
#define MITK_WARN
Definition: mitkLogMacros.h:23
std::string GetOutputName(const VolumeFileNamesContainer &filenames)
std::vector< DICOMImageFrameInfo::Pointer > DICOMImageFrameList
Output descriptor for DICOMFileReader.
GradientDirectionsProperty::GradientDirectionType GradientDirectionType
itk::VectorImage< PixelType, VecImageDimension >::Pointer LoadMosaicToVector(const VolumeFileNamesContainer &filenames, const MosaicDescriptor &mosaicInfo)
static Pointer New()
std::vector< std::string > StringList
static Pointer New()
Image::Pointer GetMitkImage() const
the 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:78
virtual bool CanHandleFile(const std::string &filename) override
Indicate whether this reader can handle given file.
std::vector< DiffusionImageDICOMHeaderInformation > DICOMHeaderListType
virtual bool LoadImages() override
Load via multiple calls to itk::ImageSeriesReader.
static const std::string GRADIENTCONTAINERPROPERTYNAME
itk::VectorImage< PixelType, VecImageDimension >::Pointer LoadToVector(const VolumeFileNamesContainer &filenames)
static Pointer New()
section MAP_FRAME_Mapper_Settings Mapper settings For the mapping of corrected images
virtual void AnalyzeInputFiles() override
Runs the sorting / splitting process described in Loading strategy. Method required by DICOMFileReade...
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.