Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkDicomDiffusionImageHeaderReader.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 
19 #include <mitkLocaleSwitch.h>
20 
25 
26 void InsertUnique( std::vector<float> & vec, float value )
27 {
28  int n = vec.size();
29  if (n == 0)
30  {
31  vec.push_back( value );
32  return;
33  }
34 
35  for (int k = 0; k < n ; k++)
36  {
37  if (vec[k] == value)
38  {
39  return;
40  }
41  }
42 
43  // if we get here, it means value is not in vec.
44  vec.push_back( value );
45  return;
46 
47 }
48 
50 {
51  m_SliceOrderIS = true;
52  m_SingleSeries = true;
53 }
54 
56 {
57 }
58 
61 {
62  // adapted from namic-sandbox
63  // DicomToNrrdConverter.cxx
64 
65  m_GdcmIO = ImageIOType::New();
66  m_GdcmIO->LoadPrivateTagsOn();
67  m_GdcmIO->SetMaxSizeLoadEntry( 65536 );
68 
69  m_VolumeReader = VolumeReaderType::New();
70  m_VolumeReader->SetImageIO( m_GdcmIO );
71  m_VolumeReader->SetFileNames( m_DicomFilenames );
72 
73  try
74  {
75  m_VolumeReader->Update();
76  }
77  catch (itk::ExceptionObject &excp)
78  {
79  std::cerr << "Exception thrown while reading slice" << std::endl;
80  std::cerr << excp << std::endl;
81  return SV_UNKNOWN_VENDOR;
82  }
83 
84  VolumeReaderType::DictionaryArrayRawPointer inputDict
85  = m_VolumeReader->GetMetaDataDictionaryArray();
86 
87  std::string vendor;
88  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|0070", vendor );
89  // std::cout << vendor << std::endl;
90 
91  std::string ImageType;
92  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|0008", ImageType );
93  //std::cout << ImageType << std::endl;
94 
95  if ( vendor.find("GE") != std::string::npos )
96  {
97  // for GE data
98  return SV_GE;
99  }
100  else if( vendor.find("SIEMENS") != std::string::npos )
101  {
102  if ( ImageType.find("MOSAIC") != std::string::npos )
103  {
104  // for Siemens MOSAIC
105  return SV_SIEMENS_MOSAIC;
106  }
107  else
108  {
109  // for Siemens SPLIT
110  return SV_SIEMENS;
111  }
112  }
113  else if( vendor.find("PHILIPS") != std::string::npos )
114  {
115  // for philips data
116  return SV_PHILIPS;
117  }
118  else
119  {
120  // for unrecognized vendors
121  return SV_UNKNOWN_VENDOR;
122  }
123 }
124 
125 // do the work
127 {
128 
129  // check if there are filenames
130  if(m_DicomFilenames.size())
131  {
132 
134  m_Output->m_DicomFilenames = m_DicomFilenames;
135 
136  // create correct reader
137  switch(GetVendorID())
138  {
139  case(SV_GE):
140  {
143  reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
144  reader->SetGdcmIO(this->m_GdcmIO);
145  reader->SetVolumeReader(this->m_VolumeReader);
146  reader->SetOutputPointer(this->m_Output);
147  reader->Update();
148  this->m_Output = reader->GetOutput();
149  break;
150  }
151  case(SV_SIEMENS):
152  {
155  reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
156  reader->SetGdcmIO(this->m_GdcmIO);
157  reader->SetVolumeReader(this->m_VolumeReader);
158  reader->SetOutputPointer(this->m_Output);
159  reader->Update();
160  this->m_Output = reader->GetOutput();
161  break;
162  }
163  case(SV_SIEMENS_MOSAIC):
164  {
165 
168  reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
169  reader->SetGdcmIO(this->m_GdcmIO);
170  reader->SetVolumeReader(this->m_VolumeReader);
171  reader->SetOutputPointer(this->m_Output);
172  reader->Update();
173  this->m_Output = reader->GetOutput();
174  break;
175  }
176  case(SV_PHILIPS):
177  {
178 
181  reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
182  reader->SetGdcmIO(this->m_GdcmIO);
183  reader->SetVolumeReader(this->m_VolumeReader);
184  reader->SetOutputPointer(this->m_Output);
185  reader->Update();
186  this->m_Output = reader->GetOutput();
187  break;
188  }
189  case(SV_UNKNOWN_VENDOR):
190  {
191  std::cerr << "diffusion header reader: unknown vendor" << std::endl;
192  break;
193  }
194  }
195  }
196 }
197 
198 // return output
201 {
202  return m_Output;
203 }
204 
206 {
207  mitk::LocaleSwitch localeSwitch("C");
208 
209  VolumeReaderType::DictionaryArrayRawPointer inputDict
210  = m_VolumeReader->GetMetaDataDictionaryArray();
211 
212  // load in all public tags
213  m_nSlice = inputDict->size();
214  std::string tag;
215 
216  tag.clear();
217  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|103e", tag );
218  this->m_Output->seriesDescription = tag.c_str();
219 
220  tag.clear();
221  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0011", tag );
222  this->m_Output->seriesNumber = atoi(tag.c_str());
223 
224  tag.clear();
225  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0010|0010", tag );
226  this->m_Output->patientName = tag.c_str();
227 
228  tag.clear();
229  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0010", tag );
230  this->m_Output->nRows = atoi( tag.c_str() );
231 
232  tag.clear();
233  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0011", tag );
234  this->m_Output->nCols = atoi( tag.c_str() );
235 
236  tag.clear();
237  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0030", tag );
238  sscanf( tag.c_str(), "%f\\%f", &this->m_Output->xRes, &this->m_Output->yRes );
239 
240  tag.clear();
241  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag );
242  sscanf( tag.c_str(), "%f\\%f\\%f", &this->m_Output->xOrigin, &this->m_Output->yOrigin, &this->m_Output->zOrigin );
243 
244  tag.clear();
245  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0050", tag );
246  this->m_Output->sliceThickness = atof( tag.c_str() );
247 
248  tag.clear();
249  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0088", tag );
250  this->m_Output->sliceSpacing = atof( tag.c_str() );
251 
252  // figure out how many slices are there in a volume, each unique
253  // SliceLocation represent one slice
254  for (int k = 0; k < m_nSlice; k++)
255  {
256  tag.clear();
257  itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0020|1041", tag);
258  float sliceLocation = atof( tag.c_str() );
259  InsertUnique( m_sliceLocations, sliceLocation );
260  }
261 
262  // check ImageOrientationPatient and figure out slice direction in
263  // L-P-I (right-handed) system.
264  // In Dicom, the coordinate frame is L-P by default. Look at
265  // http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301
266  tag.clear();
267  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0037", tag );
268  float xRow, yRow, zRow, xCol, yCol, zCol, xSlice, ySlice, zSlice /*, orthoSliceSpacing*/;
269  sscanf( tag.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", &xRow, &yRow, &zRow, &xCol, &yCol, &zCol );
270 
271  // In Dicom, the measurement frame is L-P by default. Look at
272  // http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301, in
273  // order to make this compatible with Slicer's RAS frame, we
274  // multiply the direction cosines by the negatives of the resolution
275  // (resolution is required by nrrd format). Direction cosine is not
276  // affacted since the resulting frame is still a right-handed frame.
277  xRow = -xRow;
278  yRow = -yRow;
279 
280  xCol = -xCol;
281  yCol = -yCol;
282 
283  // Cross product, this gives I-axis direction
284  xSlice = (yRow*zCol-zRow*yCol)*this->m_Output->sliceSpacing;
285  ySlice = (zRow*xCol-xRow*zCol)*this->m_Output->sliceSpacing;
286  zSlice = (xRow*yCol-yRow*xCol)*this->m_Output->sliceSpacing;
287 
288  xRow *= this->m_Output->xRes;
289  yRow *= this->m_Output->xRes;
290  zRow *= this->m_Output->xRes;
291 
292  xCol *= this->m_Output->yRes;
293  yCol *= this->m_Output->yRes;
294  zCol *= this->m_Output->yRes;
295 
296  this->m_Output->xRow = xRow;
297  this->m_Output->yRow = yRow;
298  this->m_Output->zRow = zRow;
299  this->m_Output->xCol = xCol;
300  this->m_Output->yCol = yCol;
301  this->m_Output->zCol = zCol;
302  this->m_Output->xSlice = xSlice;
303  this->m_Output->ySlice = ySlice;
304  this->m_Output->zSlice = zSlice;
305 }
306 
307 
309 {
310 
311  if (!m_SliceOrderIS)
312  {
313  this->m_Output->xSlice = -this->m_Output->xSlice;
314  this->m_Output->ySlice = -this->m_Output->ySlice;
315  this->m_Output->zSlice = -this->m_Output->zSlice;
316  }
317 
318 }
319 
321 {
322  // transform gradient directions into RAS frame
323  if ( !m_SliceOrderIS )
324  {
325  this->m_Output->DiffusionVector[2] = -this->m_Output->DiffusionVector[2]; // I -> S
326  }
327 }
328 
itk::SmartPointer< Self > Pointer
DiffusionImageHeaderInformation::Pointer GetOutput()
void InsertUnique(std::vector< float > &vec, float value)
map::core::discrete::Elements< 3 >::InternalImageType ImageType
Convenience class to temporarily change the current locale.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.