Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkSiemensDicomDiffusionImageHeaderReader.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 
21 
22 #include "gdcmGlobal.h"
23 //#include <gdcmVersion.h>
24 
25 #include "gdcmFile.h"
26 #include "gdcmImageReader.h"
27 #include "gdcmDictEntry.h"
28 #include "gdcmDicts.h"
29 #include "gdcmTag.h"
30 
32 {
33 }
34 
36 {
37 }
38 
39 int mitk::SiemensDicomDiffusionImageHeaderReader::ExtractSiemensDiffusionInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray, int startPos )
40 {
41  std::string::size_type atPosition = tagString.find( nameString, startPos );
42  if ( atPosition == std::string::npos)
43  {
44  return 0;
45  }
46  else
47  {
48  std::string infoAsString = tagString.substr( atPosition, tagString.size()-atPosition+1 );
49  const char * infoAsCharPtr = infoAsString.c_str();
50 
51  int vm = *(infoAsCharPtr+64);
52 
53  int offset = 84;
54  for (int k = 0; k < vm; k++)
55  {
56  int itemLength = *(infoAsCharPtr+offset+4);
57  int strideSize = static_cast<int> (ceil(static_cast<double>(itemLength)/4) * 4);
58  std::string valueString = infoAsString.substr( offset+16, itemLength );
59  valueArray.push_back( atof(valueString.c_str()) );
60  offset += 16+strideSize;
61  }
62  return vm;
63  }
64 }
65 
66 int mitk::SiemensDicomDiffusionImageHeaderReader::ExtractSiemensDiffusionGradientInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray )
67 {
68  int nItems = 0;
69  std::string::size_type pos = -1;
70  while(nItems != 3)
71  {
72  nItems = ExtractSiemensDiffusionInformation( tagString, nameString, valueArray, pos+1 );
73  pos = tagString.find( nameString, pos+1 );
74  if ( pos == std::string::npos )
75  {
76  break;
77  }
78  }
79  return nItems;
80 }
81 
82 // do the work
84 {
85 
86  // check if there are filenames
87  if(m_DicomFilenames.size())
88  {
89  mitk::LocaleSwitch localeSwitch("C");
90 
91  // adapted from slicer
92  // DicomToNrrdConverter.cxx
93 
94  VolumeReaderType::DictionaryArrayRawPointer
95  inputDict = m_VolumeReader->GetMetaDataDictionaryArray();
96 
97  ReadPublicTags();
98 
99  float x0, y0, z0;
100  float x1, y1, z1;
101  std::string tag;
102  tag.clear();
103  itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag );
104  sscanf( tag.c_str(), "%f\\%f\\%f", &x0, &y0, &z0 );
105  //MITK_INFO << "Slice 0: " << tag << std::endl;
106  tag.clear();
107 
108  // assume volume interleaving, i.e. the second dicom file stores
109  // the second slice in the same volume as the first dicom file
110  if((*inputDict).size() > 1)
111  {
112  itk::ExposeMetaData<std::string> ( *(*inputDict)[1], "0020|0032", tag );
113  sscanf( tag.c_str(), "%f\\%f\\%f", &x1, &y1, &z1 );
114  //MITK_INFO << "Slice 1: " << tag << std::endl;
115  x1 -= x0; y1 -= y0; z1 -= z0;
116  x0 = x1*this->m_Output->xSlice + y1*this->m_Output->ySlice + z1*this->m_Output->zSlice;
117  if (x0 < 0)
118  {
119  m_SliceOrderIS = false;
120  }
121  }
122 
123  ReadPublicTags2();
124 
125  int nStride = 1;
126  this->m_Output->nSliceInVolume = m_sliceLocations.size();
127 
128  nStride = this->m_Output->nSliceInVolume;
129 
130  MITK_INFO << m_DicomFilenames[0] << std::endl;
131  MITK_INFO << "Dims " << this->m_Output->nRows << "x"
132  << this->m_Output->nCols << "x" << this->m_Output->nSliceInVolume << " " << std::endl;
133 
134  for (int k = 0; k < m_nSlice; k += nStride )
135  {
136 
137  gdcm::ImageReader reader;
138  reader.SetFileName( m_DicomFilenames[k].c_str() );
139  if( !reader.Read() )
140  {
141  itkExceptionMacro(<< "Cannot read requested file");
142  }
143  const gdcm::File &f = reader.GetFile();
144  const gdcm::DataSet &ds = f.GetDataSet();
145 
146  // gdcm::DataSet ds = header0->GetDataSet();
147  auto it = ds.Begin();
148 
149  // Copy of the header->content
150  // copy information stored in 0029,1010 into a string for parsing
151  for(; it != ds.End(); ++it)
152  {
153  const gdcm::DataElement &ref = *it;
154  if (ref.GetTag() == gdcm::Tag(0x0029,0x1010)) {
155  tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
156  }
157  }
158 
159  // parse B_value from 0029,1010 tag
160  std::vector<double> valueArray(0);
161  vnl_vector_fixed<double, 3> vect3d;
162  int nItems = ExtractSiemensDiffusionInformation(tag, "B_value", valueArray);
163  if (nItems != 1 || valueArray[0] == 0) // did not find enough information
164  {
165  tag.clear();
166  MITK_INFO << "Reading diffusion info from 0019|100c and 0019|100e tags" << std::endl;
167  bool success = false;
168 
169  for(it = ds.Begin(); it != ds.End(); ++it)
170  {
171  const gdcm::DataElement &ref = *it;
172  if (ref.GetTag() == gdcm::Tag(0x0019,0x100c)) {
173  tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
174  this->m_Output->bValue = atof( tag.c_str() );
175  success = true;
176  }
177  }
178 
179  tag.clear();
180  if(success)
181  {
182  if(this->m_Output->bValue == 0)
183  {
184  MITK_INFO << "BV: 0 (Baseline image)";
185  continue;
186  }
187 
188  success = false;
189  for(it = ds.Begin(); it != ds.End(); ++it)
190  {
191  const gdcm::DataElement &ref = *it;
192  if (ref.GetTag() == gdcm::Tag(0x0019,0x100e)) {
193  tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
194  success = true;
195  }
196  }
197 
198  if(success)
199  {
200  memcpy( &vect3d[0], tag.c_str()+0, 8 );
201  memcpy( &vect3d[1], tag.c_str()+8, 8 );
202  memcpy( &vect3d[2], tag.c_str()+16, 8 );
203  vect3d.normalize();
204  this->m_Output->DiffusionVector = vect3d;
205  TransformGradients();
206  MITK_INFO << "BV: " << this->m_Output->bValue;
207  MITK_INFO << " GD: " << this->m_Output->DiffusionVector;
208  continue;
209  }
210  }
211  }
212  else
213  {
214  MITK_INFO << "Reading diffusion info from 0029,1010 tag" << std::endl;
215  this->m_Output->bValue = valueArray[0];
216 
217  if(this->m_Output->bValue == 0)
218  {
219  MITK_INFO << "BV: 0 (Baseline image)";
220  continue;
221  }
222 
223  valueArray.resize(0);
224  nItems = ExtractSiemensDiffusionGradientInformation(tag, "DiffusionGradientDirection", valueArray);
225  if (nItems == 3)
226  {
227  vect3d[0] = valueArray[0];
228  vect3d[1] = valueArray[1];
229  vect3d[2] = valueArray[2];
230  vect3d.normalize();
231  this->m_Output->DiffusionVector = vect3d;
232  TransformGradients();
233  MITK_INFO << "BV: " << this->m_Output->bValue;
234  MITK_INFO << " GD: " << this->m_Output->DiffusionVector;
235  continue;
236  }
237  }
238 
239  MITK_ERROR << "No diffusion info found, forcing to BASELINE image." << std::endl;
240  this->m_Output->bValue = 0.0;
241  vect3d.fill( 0.0 );
242  this->m_Output->DiffusionVector = vect3d;
243 
244  }
245  }
246 }
int ExtractSiemensDiffusionGradientInformation(std::string tagString, std::string nameString, std::vector< double > &valueArray)
#define MITK_INFO
Definition: mitkLogMacros.h:22
#define MITK_ERROR
Definition: mitkLogMacros.h:24
static Vector3D offset
Convenience class to temporarily change the current locale.
int ExtractSiemensDiffusionInformation(std::string tagString, std::string nameString, std::vector< double > &valueArray, int startPos=0)