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
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)