Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkdump.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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
38 
39 using mitk::DICOMTag;
40 
41 std::string buildDateString()
42 {
43  std::time_t rawtime;
44  std::tm *timeinfo;
45  char buffer[80];
46 
47  std::time(&rawtime);
48  timeinfo = std::localtime(&rawtime);
49 
50  std::strftime(buffer, 80, "%Y%m%d-%H%M%S", timeinfo);
51 
52  return std::string(buffer);
53 }
54 
55 void gen_random(char *s, const int len)
56 {
57  static const char alphanum[] = "0123456789"
58  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
59 
60  for (int i = 0; i < len; ++i)
61  {
62  s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
63  }
64 
65  s[len] = 0;
66 }
67 
68 std::string gen_random(const int len)
69 {
70  if (len > 0 && len < 100)
71  {
72  char retval[100];
73  gen_random(retval, len);
74  return std::string(retval);
75  }
76  else
77  {
78  return std::string("");
79  }
80 }
81 
82 std::string removeUnsafeChars(const std::string &str)
83 {
84  std::string retval;
85  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
86  {
87  const char &c = *it;
88  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '.') || (c == '-') ||
89  (c == '_'))
90  {
91  retval += c;
92  }
93  }
94  return retval;
95 }
96 
97 std::string extractDirString(const std::string &dirString)
98 {
99  std::string wholeprefix = dirString.substr(0, dirString.find_last_of("/\\"));
100  std::string lastDirectoryPart = wholeprefix.substr(wholeprefix.find_last_of("/\\") + 1);
101  std::string cleanLastDirectoryPart = removeUnsafeChars(lastDirectoryPart);
102  if (!cleanLastDirectoryPart.empty())
103  {
104  return cleanLastDirectoryPart;
105  }
106  else
107  {
108  std::stringstream emptydirname;
109  emptydirname << "noname_" << gen_random(6);
110 
111  return emptydirname.str();
112  }
113 }
114 
115 int main(int argc, char *argv[])
116 {
117  bool fileDetails(false);
118  bool loadimage(false);
119  int firstFileIndex = 1;
120 
121  // see if we got the '-v' flag to output file details
122  if (argc > 1 && std::string(argv[firstFileIndex]) == "-v")
123  {
124  fileDetails = true;
125  ++firstFileIndex;
126  }
127 
128  // see if we got the '-l' flag
129  if (argc > 1 && std::string(argv[firstFileIndex]) == "-l")
130  {
131  loadimage = true;
132  ++firstFileIndex;
133  }
134 
135  // analyze files from argv
136  mitk::StringList inputFiles;
137  for (int a = firstFileIndex; a < argc; ++a)
138  {
139  inputFiles.push_back(std::string(argv[a]));
140  }
141 
142  if (inputFiles.empty())
143  {
144  MITK_INFO << "0 input files given, exiting...";
145  return EXIT_SUCCESS;
146  }
147 
148  mitk::DICOMFileReaderSelector::Pointer configSelector = mitk::DICOMFileReaderSelector::New();
149  configSelector->LoadBuiltIn3DConfigs(); // a set of compiled in ressources with standard configurations that work well
150  configSelector->SetInputFiles(inputFiles);
151  mitk::DICOMFileReader::Pointer reader = configSelector->GetFirstReaderWithMinimumNumberOfOutputImages();
152  if (reader.IsNull())
153  {
154  MITK_ERROR << "Could not configure any DICOM reader.. Exiting...";
155  return EXIT_FAILURE;
156  }
157 
158  // output best reader result
159  MITK_INFO << "---- Best reader configuration '" << reader->GetConfigurationLabel() << "' with "
160  << reader->GetNumberOfOutputs() << " outputs";
161  if (fileDetails)
162  {
163  reader->PrintOutputs(std::cout, fileDetails);
164  }
165 
166  // construct the name of a log file
167  std::string datestring = buildDateString();
168  ;
169  std::string dirString = extractDirString(argv[firstFileIndex]);
170  std::string logfilename = datestring + "_dir_" + dirString + ".mitkdump";
171  MITK_INFO << "Logfile " << logfilename;
172 
173  // write output to file for later analysis
174  std::ofstream fs;
175  fs.open(logfilename.c_str());
176  fs << "---- " << dirString << ": Best reader configuration '" << reader->GetConfigurationLabel() << "' with "
177  << reader->GetNumberOfOutputs() << " outputs" << std::endl;
178  reader->PrintOutputs(fs, true); // always verbose in log file
179  fs.close();
180 
181  // serialize, deserialize, analyze again, verify result!
182  mitk::DICOMReaderConfigurator::Pointer serializer = mitk::DICOMReaderConfigurator::New();
183  std::string readerSerialization = serializer->CreateConfigStringFromReader(reader.GetPointer());
184 
185  bool outputError(false);
186  for (unsigned int outputIndex = 0; outputIndex < reader->GetNumberOfOutputs(); ++outputIndex)
187  {
188  const mitk::DICOMImageBlockDescriptor &outputDescriptor = reader->GetOutput(outputIndex);
189 
190  mitk::StringList filenamesOfThisGroup;
191  const mitk::DICOMImageFrameList &frames = outputDescriptor.GetImageFrameList();
192  for (auto fIter = frames.begin(); fIter != frames.end(); ++fIter)
193  {
194  filenamesOfThisGroup.push_back((*fIter)->Filename);
195  }
196 
197  mitk::DICOMReaderConfigurator::Pointer readerConfigurator = mitk::DICOMReaderConfigurator::New();
198  mitk::DICOMFileReader::Pointer dicomReader = readerConfigurator->CreateFromUTF8ConfigString(readerSerialization);
199  dicomReader->SetInputFiles(filenamesOfThisGroup);
200  dicomReader->AnalyzeInputFiles();
201  if (dicomReader->GetNumberOfOutputs() != 1)
202  {
203  MITK_ERROR << "****** Re-analyzing files of output group " << outputIndex << " yields "
204  << dicomReader->GetNumberOfOutputs() << " groups";
205  outputError = true;
206 
207  for (auto fIter = frames.begin(); fIter != frames.end(); ++fIter)
208  {
209  MITK_INFO << "filename group " << outputIndex << ": " << (*fIter)->Filename;
210  }
211  }
212  else
213  {
214  MITK_INFO << "Re-analyzing files of output group " << outputIndex << " yields "
215  << dicomReader->GetNumberOfOutputs() << " groups";
216  }
217  }
218 
219  if (outputError)
220  {
221  std::stringstream es;
222  es << "Original reader configuration: " << std::endl;
223  reader->PrintConfiguration(es);
224  es << std::endl;
225  mitk::DICOMReaderConfigurator::Pointer readerConfigurator = mitk::DICOMReaderConfigurator::New();
226  mitk::DICOMFileReader::Pointer dicomReader = readerConfigurator->CreateFromUTF8ConfigString(readerSerialization);
227  es << "New reader configuration: " << std::endl;
228  dicomReader->PrintConfiguration(es);
229  es << std::endl;
230 
231  es << "Original XML: \n" << readerSerialization << std::endl;
232  std::string newSerialization = serializer->CreateConfigStringFromReader(dicomReader.GetPointer());
233  es << "New XML: \n" << newSerialization << std::endl;
234  MITK_ERROR << es.str();
235  }
236 
237  if (loadimage)
238  {
239  MITK_INFO << "Loading...";
240  reader->LoadImages();
241  mitk::Image::Pointer image = reader->GetOutput(0).GetMitkImage();
242  MITK_INFO << "---- Output image:";
243  mitk::BaseGeometry::Pointer geo3D = image->GetGeometry();
244  if (geo3D.IsNotNull())
245  {
246  mitk::SlicedGeometry3D::Pointer sg = dynamic_cast<mitk::SlicedGeometry3D *>(geo3D.GetPointer());
247  if (sg.IsNotNull())
248  {
249  unsigned int nos = sg->GetSlices();
250  mitk::PlaneGeometry::ConstPointer first = sg->GetPlaneGeometry(0);
251  mitk::PlaneGeometry::ConstPointer last = sg->GetPlaneGeometry(nos - 1);
252 
253  mitk::Point3D firstOrigin = first->GetOrigin();
254  mitk::Point3D lastOrigin = last->GetOrigin();
255  MITK_INFO << "Geometry says: First slice at " << firstOrigin << ", last slice at " << lastOrigin;
256 
258  dynamic_cast<mitk::StringLookupTableProperty *>(image->GetProperty("dicom.image.0020.1041").GetPointer());
259  if (sliceLocations.IsNotNull())
260  {
261  std::string firstSliceLocation = sliceLocations->GetValue().GetTableValue(0);
262  std::string lastSliceLocation = sliceLocations->GetValue().GetTableValue(nos - 1);
263  MITK_INFO << "Image properties says: first slice location at " << firstSliceLocation
264  << ", last slice location at " << lastSliceLocation;
265  }
266 
268  dynamic_cast<mitk::StringLookupTableProperty *>(image->GetProperty("dicom.image.0020.0013").GetPointer());
269  if (instanceNumbers.IsNotNull())
270  {
271  std::string firstInstanceNumber = instanceNumbers->GetValue().GetTableValue(0);
272  std::string lastInstanceNumber = instanceNumbers->GetValue().GetTableValue(nos - 1);
273  MITK_INFO << "Image properties says: first instance number at " << firstInstanceNumber
274  << ", last instance number at " << lastInstanceNumber;
275  }
276  }
277  }
278  MITK_INFO << "---- End of output";
279  }
280 
281  // if we got so far, everything is fine
282  return EXIT_SUCCESS;
283 }
std::string removeUnsafeChars(const std::string &str)
Definition: mitkdump.cpp:82
#define MITK_INFO
Definition: mitkLogMacros.h:18
#define MITK_ERROR
Definition: mitkLogMacros.h:20
Representation of a DICOM tag.
Definition: mitkDICOMTag.h:32
const DICOMImageFrameList & GetImageFrameList() const
List of frames that constitute the mitk::Image (DICOMImageFrames)
int main(int argc, char *argv[])
Definition: mitkdump.cpp:115
std::string extractDirString(const std::string &dirString)
Definition: mitkdump.cpp:97
void gen_random(char *s, const int len)
Definition: mitkdump.cpp:55
std::vector< DICOMImageFrameInfo::Pointer > DICOMImageFrameList
Output descriptor for DICOMFileReader.
mitk::Image::Pointer image
std::vector< std::string > StringList
Describes the geometry of a data object consisting of slices.
std::string buildDateString()
Definition: mitkdump.cpp:41