Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.