Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
Medical Imaging Interaction Toolkit
mitkDICOMReaderConfigurator.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 
14 
15 #include "mitkDICOMSortByTag.h"
17 
18 
21 {
22 }
23 
26 {
27 }
28 
29 mitk::DICOMFileReader::Pointer
31 ::CreateFromConfigFile(const std::string& filename) const
32 {
33  TiXmlDocument doc (filename);
34  if (doc.LoadFile())
35  {
36  return this->CreateFromTiXmlDocument( doc );
37  }
38  else
39  {
40  MITK_ERROR << "Unable to load file at '" << filename <<"'";
41  return DICOMFileReader::Pointer();
42  }
43 }
44 
45 mitk::DICOMFileReader::Pointer
47 ::CreateFromUTF8ConfigString(const std::string& xmlContents) const
48 {
49  TiXmlDocument doc;
50  doc.Parse(xmlContents.c_str(), nullptr, TIXML_ENCODING_UTF8);
51 
52  return this->CreateFromTiXmlDocument( doc );
53 }
54 
55 mitk::DICOMFileReader::Pointer
56 mitk::DICOMReaderConfigurator
57 ::CreateFromTiXmlDocument(TiXmlDocument& doc) const
58 {
59  TiXmlHandle root(doc.RootElement());
60 
61  if (TiXmlElement* rootElement = root.ToElement())
62  {
63  if (strcmp(rootElement->Value(), "DICOMFileReader")) // :-( no std::string methods
64  {
65  MITK_ERROR << "File should contain a <DICOMFileReader> tag at top-level! Found '"
66  << (rootElement->Value() ? std::string(rootElement->Value()) : std::string("!nothing!")) << "' instead";
67  return nullptr;
68  }
69 
70  const char* classnameC = rootElement->Attribute("class");
71  if (!classnameC)
72  {
73  MITK_ERROR << "File should name a reader class in the class attribute: <DICOMFileReader class=\"...\">. Found nothing instead";
74  return nullptr;
75  }
76 
77  int version(1);
78  if ( rootElement->QueryIntAttribute("version", &version) == TIXML_SUCCESS)
79  {
80  if (version == 1)
81  {
82  MITK_WARN << "Warning the given configuration is for DICOMFileReaders of version 1. "
83  << "This old version may be interpreted differently. Reason: "
84  << "The default values for the following xml settings have been changed: "
85  << "FixTiltByShearing (false -> true); StrictSorting (true -> false); ExpectDistanceOne (true -> false).";
86  }
87  else if (version >2)
88  {
89  MITK_WARN << "This reader is only capable of creating DICOMFileReaders of version 1 and 2. "
90  << "Will not continue, because given configuration is meant for version " << version << ".";
91  return nullptr;
92  }
93  }
94  else
95  {
96  MITK_ERROR << "File should name the version of the reader class in the version attribute: <DICOMFileReader class=\"" << classnameC << "\" version=\"...\">."
97  << " Found nothing instead, assuming version 1!";
98  version = 1;
99  }
100 
101  std::string classname(classnameC);
102 
103  double decimalPlacesForOrientation(mitk::DICOMITKSeriesGDCMReader::GetDefaultDecimalPlacesForOrientation());
104  bool useDecimalPlacesForOrientation(false);
105  useDecimalPlacesForOrientation =
106  rootElement->QueryDoubleAttribute("decimalPlacesForOrientation", &decimalPlacesForOrientation) == TIXML_SUCCESS; // attribute present and a double value
107 
108  if (classname == "ClassicDICOMSeriesReader")
109  {
110  mitk::ClassicDICOMSeriesReader::Pointer reader = mitk::ClassicDICOMSeriesReader::New();
111  this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader.GetPointer(), rootElement);
112  this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader.GetPointer(), rootElement);
113  return reader.GetPointer();
114  }
115  if (classname == "ThreeDnTDICOMSeriesReader")
116  {
117  mitk::ThreeDnTDICOMSeriesReader::Pointer reader;
118  if (useDecimalPlacesForOrientation)
119  reader = mitk::ThreeDnTDICOMSeriesReader::New(decimalPlacesForOrientation);
120  else
122 
123  return ConfigureThreeDnTDICOMSeriesReader(reader, rootElement).GetPointer();
124  }
125  else
126  if (classname == "DICOMITKSeriesGDCMReader")
127  {
128  bool simpleVolumeImport = QueryBooleanAttribute(rootElement, "simpleVolumeImport", mitk::DICOMITKSeriesGDCMReader::GetDefaultSimpleVolumeImport());
129 
130  mitk::DICOMITKSeriesGDCMReader::Pointer reader;
131  if (useDecimalPlacesForOrientation)
132  reader = mitk::DICOMITKSeriesGDCMReader::New( decimalPlacesForOrientation, simpleVolumeImport );
133  else
135 
136  // simple volume import that ignores number of frames and inter slice distance
137 
138  return ConfigureDICOMITKSeriesGDCMReader(reader, rootElement).GetPointer();
139  }
140  else
141  {
142  MITK_ERROR << "DICOMFileReader tag names unknown class '" << classname << "'";
143  return nullptr;
144  }
145  }
146  else
147  {
148  MITK_ERROR << "Great confusion: no root element in XML document. Expecting a DICOMFileReader tag at top-level.";
149  return nullptr;
150  }
151 }
152 
153 #define boolStringTrue(s) \
154  ( s == "true" || s == "on" || s == "1" \
155  || s == "TRUE" || s == "ON")
156 
157 bool
158 mitk::DICOMReaderConfigurator
159 ::QueryBooleanAttribute(const TiXmlElement* element, const char* attributeName, bool defaultValue) const
160 {
161  bool value(defaultValue);
162  const char* valueC = element->Attribute(attributeName);
163  if (valueC)
164  {
165  std::string valueS(valueC);
166  value = boolStringTrue(valueS);
167  }
168  return value;
169 }
170 
171 void
172 mitk::DICOMReaderConfigurator
173 ::ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const
174 {
175  // add the "group3DnT" flag
176  bool group3DnT = QueryBooleanAttribute(element, "group3DnT", ThreeDnTDICOMSeriesReader::GetDefaultGroup3DandT());
177 
178  reader->SetGroup3DandT( group3DnT );
179 
180  // add the "onlyCondenseSameSeries" flag
181  bool onlyCondenseSameSeries = QueryBooleanAttribute(element, "onlyCondenseSameSeries", ThreeDnTDICOMSeriesReader::GetDefaultOnlyCondenseSameSeries());
182 
183  reader->SetOnlyCondenseSameSeries(onlyCondenseSameSeries);
184 }
185 
186 mitk::ThreeDnTDICOMSeriesReader::Pointer
187 mitk::DICOMReaderConfigurator
188 ::ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const
189 {
190  assert(element);
191 
192  // use all the base class configuration
193  if (this->ConfigureDICOMITKSeriesGDCMReader( reader.GetPointer(), element ).IsNull())
194  {
195  return nullptr;
196  }
197 
198  this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader,element);
199  return reader;
200 }
201 
202 void
203 mitk::DICOMReaderConfigurator
204 ::ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const
205 {
206  assert(element);
207 
208  const char* configLabelC = element->Attribute("label");
209  if (configLabelC)
210  {
211  std::string configLabel(configLabelC);
212  reader->SetConfigurationLabel(configLabel);
213  }
214 
215  const char* configDescriptionC = element->Attribute("description");
216  if (configDescriptionC)
217  {
218  reader->SetConfigurationDescription(configDescriptionC);
219  }
220 
221  // "fixTiltByShearing" flag
222  bool fixTiltByShearing = QueryBooleanAttribute(element, "fixTiltByShearing", DICOMITKSeriesGDCMReader::GetDefaultFixTiltByShearing());
223 
224  reader->SetFixTiltByShearing( fixTiltByShearing );
225 }
226 
227 mitk::DICOMITKSeriesGDCMReader::Pointer
228 mitk::DICOMReaderConfigurator
229 ::ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const
230 {
231  assert(element);
232 
233  this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader, element);
234 
235  // "acceptTwoSlicesGroups" flag
236  bool acceptTwoSlicesGroups = QueryBooleanAttribute(element, "acceptTwoSlicesGroups", true);
237 
238  reader->SetAcceptTwoSlicesGroups( acceptTwoSlicesGroups );
239 
240  // "toleratedOriginError" attribute (double)
241  bool toleratedOriginErrorIsAbsolute = QueryBooleanAttribute(element, "toleratedOriginErrorIsAbsolute", false);
242 
243  double toleratedOriginError(0.3);
244  if (element->QueryDoubleAttribute("toleratedOriginError", &toleratedOriginError) == TIXML_SUCCESS) // attribute present and a double value
245  {
246  if (toleratedOriginErrorIsAbsolute)
247  {
248  reader->SetToleratedOriginOffset( toleratedOriginError );
249  }
250  else
251  {
252  reader->SetToleratedOriginOffsetToAdaptive( toleratedOriginError );
253  }
254  }
255 
256  // DICOMTagBasedSorters are the only thing we create at this point
257  // TODO for-loop over all child elements of type DICOMTagBasedSorter, BUT actually a single sorter of this type is enough.
258  TiXmlElement* dElement = element->FirstChildElement("DICOMDatasetSorter");
259  if (dElement)
260  {
261  const char* classnameC = dElement->Attribute("class");
262  if (!classnameC)
263  {
264  MITK_ERROR << "File should name a DICOMDatasetSorter class in the class attribute of <DICOMDatasetSorter class=\"...\">. Found nothing instead";
265  return nullptr;
266  }
267 
268  std::string classname(classnameC);
269 
270  if (classname == "DICOMTagBasedSorter")
271  {
272  DICOMTagBasedSorter::Pointer tagSorter = CreateDICOMTagBasedSorter(dElement);
273  if (tagSorter.IsNotNull())
274  {
275  reader->AddSortingElement( tagSorter );
276  }
277  }
278  else
279  {
280  MITK_ERROR << "DICOMDatasetSorter tag names unknown class '" << classname << "'";
281  return nullptr;
282  }
283  }
284 
285  return reader;
286 }
287 
288 mitk::DICOMTagBasedSorter::Pointer
289 mitk::DICOMReaderConfigurator
290 ::CreateDICOMTagBasedSorter(TiXmlElement* element) const
291 {
292  mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
293 
294  // "strictSorting" parameter!
295  bool strictSorting = QueryBooleanAttribute(element, "strictSorting", mitk::DICOMTagBasedSorter::GetDefaultStrictSorting());
296  tagSorter->SetStrictSorting(strictSorting);
297 
298  // "strictSorting" parameter!
299  bool expectDistanceOne = QueryBooleanAttribute(element, "expectDistanceOne", mitk::DICOMTagBasedSorter::GetDefaultExpectDistanceOne());
300  tagSorter->SetExpectDistanceOne(expectDistanceOne);
301 
302  TiXmlElement* dElement = element->FirstChildElement("Distinguishing");
303  if (dElement)
304  {
305  for ( TiXmlElement* tChild = dElement->FirstChildElement();
306  tChild != nullptr;
307  tChild = tChild->NextSiblingElement() )
308  {
309  try
310  {
311  mitk::DICOMTag tag = tagFromXMLElement(tChild);
312  int i(5);
313  if (tChild->QueryIntAttribute("cutDecimalPlaces", &i) == TIXML_SUCCESS)
314  {
315  tagSorter->AddDistinguishingTag( tag, new mitk::DICOMTagBasedSorter::CutDecimalPlaces(i) );
316  }
317  else
318  {
319  tagSorter->AddDistinguishingTag( tag );
320  }
321  }
322  catch(...)
323  {
324  return nullptr;
325  }
326  }
327  }
328 
329  // "sorting tags"
330  TiXmlElement* sElement = element->FirstChildElement("Sorting");
331  if (sElement)
332  {
333  DICOMSortCriterion::Pointer previousCriterion;
334  DICOMSortCriterion::Pointer currentCriterion;
335 
336  for ( TiXmlNode* tChildNode = sElement->LastChild();
337  tChildNode != nullptr;
338  tChildNode = tChildNode->PreviousSibling() )
339  {
340  TiXmlElement* tChild = tChildNode->ToElement();
341  if (!tChild) continue;
342 
343  if (!strcmp(tChild->Value(), "Tag"))
344  {
345  try
346  {
347  currentCriterion = this->CreateDICOMSortByTag(tChild, previousCriterion);
348  }
349  catch(...)
350  {
351  std::stringstream ss;
352  ss << "Could not parse <Tag> element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!";
353  MITK_ERROR << ss.str();
354  return nullptr;
355  }
356  }
357  else
358  if (!strcmp(tChild->Value(), "ImagePositionPatient"))
359  {
360  try
361  {
362  currentCriterion = this->CreateSortByImagePositionPatient(tChild, previousCriterion);
363  }
364  catch(...)
365  {
366  std::stringstream ss;
367  ss << "Could not parse <ImagePositionPatient> element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!";
368  MITK_ERROR << ss.str();
369  return nullptr;
370  }
371  }
372  else
373  {
374  MITK_ERROR << "File contain unknown tag <" << tChild->Value() << "> tag as child to <Sorting>! Cannot interpret...";
375  }
376 
377  previousCriterion = currentCriterion;
378  }
379 
380  tagSorter->SetSortCriterion( currentCriterion.GetPointer() );
381  }
382 
383  return tagSorter;
384 }
385 
386 std::string
387 mitk::DICOMReaderConfigurator
388 ::requiredStringAttribute(TiXmlElement* xmlElement, const std::string& key) const
389 {
390  assert(xmlElement);
391 
392  const char* gC = xmlElement->Attribute(key.c_str());
393  if (gC)
394  {
395  std::string gS(gC);
396  return gS;
397  }
398  else
399  {
400  std::stringstream ss;
401  ss << "Expected an attribute '" << key << "' at this position "
402  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
403  MITK_ERROR << ss.str();
404  throw std::invalid_argument( ss.str() );
405  }
406 }
407 
408 unsigned int
409 mitk::DICOMReaderConfigurator
410 ::hexStringToUInt(const std::string& s) const
411 {
412  std::stringstream converter(s);
413  unsigned int ui;
414  converter >> std::hex >> ui;
415  MITK_DEBUG << "Converted string '" << s << "' to unsigned int " << ui;
416  return ui;
417 }
418 
420 mitk::DICOMReaderConfigurator
421 ::tagFromXMLElement(TiXmlElement* xmlElement) const
422 {
423  assert(xmlElement);
424 
425  if (strcmp(xmlElement->Value(), "Tag")) // :-( no std::string methods
426  {
427  std::stringstream ss;
428  ss << "Expected a <Tag group=\"..\" element=\"..\"> tag at this position "
429  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
430  MITK_ERROR << ss.str();
431  throw std::invalid_argument( ss.str() );
432  }
433 
434  std::string groupS = requiredStringAttribute(xmlElement, "group");
435  std::string elementS = requiredStringAttribute(xmlElement, "element");
436 
437  try
438  {
439  // convert string to int (assuming string is in hex format with leading "0x" like "0x0020")
440  unsigned int group = hexStringToUInt(groupS);
441  unsigned int element = hexStringToUInt(elementS);
442  return DICOMTag(group, element);
443  }
444  catch(...)
445  {
446  std::stringstream ss;
447  ss << "Expected group and element values in <Tag group=\"..\" element=\"..\"> to be hexadecimal with leading 0x, e.g. '0x0020'"
448  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
449  MITK_ERROR << ss.str();
450  throw std::invalid_argument( ss.str() );
451  }
452 }
453 
454 mitk::DICOMSortCriterion::Pointer
455 mitk::DICOMReaderConfigurator
456 ::CreateDICOMSortByTag(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const
457 {
458  mitk::DICOMTag tag = tagFromXMLElement(xmlElement);
459  return DICOMSortByTag::New(tag, secondaryCriterion).GetPointer();
460 }
461 
462 mitk::DICOMSortCriterion::Pointer
463 mitk::DICOMReaderConfigurator
464 ::CreateSortByImagePositionPatient(TiXmlElement*, DICOMSortCriterion::Pointer secondaryCriterion) const
465 {
466  return SortByImagePositionPatient::New(secondaryCriterion).GetPointer();
467 }
468 
469 
470 
471 std::string
473 ::CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const
474 {
475  // check possible sub-classes from the most-specific one up to the most generic one
476  const DICOMFileReader* cPointer = reader;
477  TiXmlElement* root;
478  if (const auto* specificReader = dynamic_cast<const ClassicDICOMSeriesReader*>(cPointer))
479  {
480  root = this->CreateConfigStringFromReader(specificReader);
481  }
482  else
483  if (const auto* specificReader = dynamic_cast<const ThreeDnTDICOMSeriesReader*>(cPointer))
484  {
485  root = this->CreateConfigStringFromReader(specificReader);
486  }
487  else
488  if (const auto* specificReader = dynamic_cast<const DICOMITKSeriesGDCMReader*>(cPointer))
489  {
490  root = this->CreateConfigStringFromReader(specificReader);
491  }
492  else
493  {
494  MITK_WARN << "Unknown reader class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize.";
495  return ""; // no serialization, what a pity
496  }
497 
498  if (root)
499  {
500  TiXmlDocument document;
501  document.LinkEndChild( root );
502 
503  TiXmlPrinter printer;
504  printer.SetIndent( " " );
505 
506  document.Accept( &printer );
507  std::string xmltext = printer.CStr();
508  return xmltext;
509  }
510  else
511  {
512  MITK_WARN << "DICOMReaderConfigurator::CreateConfigStringFromReader() created empty serialization. Problem?";
513  return "";
514  }
515 }
516 
517 TiXmlElement*
520 {
521  TiXmlElement* root = this->CreateDICOMFileReaderTag(reader);
522  assert(root);
523 
524  root->SetAttribute("fixTiltByShearing", toString(reader->GetFixTiltByShearing()));
525  root->SetAttribute("acceptTwoSlicesGroups", toString(reader->GetAcceptTwoSlicesGroups()));
526  root->SetDoubleAttribute("toleratedOriginError", reader->GetToleratedOriginError());
527  root->SetAttribute("toleratedOriginErrorIsAbsolute", toString(reader->IsToleratedOriginOffsetAbsolute()));
528  root->SetDoubleAttribute("decimalPlacesForOrientation", reader->GetDecimalPlacesForOrientation());
529 
530  // iterate DICOMDatasetSorter objects
532  for(auto sorterIter = sorterList.begin();
533  sorterIter != sorterList.end();
534  ++sorterIter)
535  {
536  const DICOMDatasetSorter* sorter = *sorterIter;
537  if (const auto* specificSorter = dynamic_cast<const DICOMTagBasedSorter*>(sorter))
538  {
539  TiXmlElement* sorterTag = this->CreateConfigStringFromDICOMDatasetSorter(specificSorter);
540  root->LinkEndChild(sorterTag);
541  }
542  else
543  {
544  MITK_WARN << "Unknown DICOMDatasetSorter class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize.";
545  return nullptr;
546  }
547  }
548 
549  return root;
550 }
551 
552 TiXmlElement*
553 mitk::DICOMReaderConfigurator
554 ::CreateConfigStringFromDICOMDatasetSorter(const DICOMTagBasedSorter* sorter) const
555 {
556  assert(sorter);
557 
558  auto sorterTag = new TiXmlElement("DICOMDatasetSorter");
559  sorterTag->SetAttribute("class", sorter->GetNameOfClass());
560  sorterTag->SetAttribute("strictSorting", toString(sorter->GetStrictSorting()));
561  sorterTag->SetAttribute("expectDistanceOne", toString(sorter->GetExpectDistanceOne()));
562 
563  auto distinguishingTagsElement = new TiXmlElement("Distinguishing");
564  sorterTag->LinkEndChild(distinguishingTagsElement);
565  mitk::DICOMTagList distinguishingTags = sorter->GetDistinguishingTags();
566  for (auto tagIter = distinguishingTags.begin();
567  tagIter != distinguishingTags.end();
568  ++tagIter)
569  {
570  TiXmlElement* tag = this->CreateConfigStringFromDICOMTag(*tagIter);
571  distinguishingTagsElement->LinkEndChild(tag);
572 
574  if (const auto* specificProcessor = dynamic_cast<const DICOMTagBasedSorter::CutDecimalPlaces*>(processor))
575  {
576  tag->SetDoubleAttribute("cutDecimalPlaces", specificProcessor->GetPrecision());
577  }
578  }
579 
580  auto sortingElement = new TiXmlElement("Sorting");
581  sorterTag->LinkEndChild(sortingElement);
582  mitk::DICOMSortCriterion::ConstPointer sortCriterion = sorter->GetSortCriterion();
583  while (sortCriterion.IsNotNull())
584  {
585  std::string classname = sortCriterion->GetNameOfClass();
586  if (classname == "SortByImagePositionPatient")
587  {
588  sortingElement->LinkEndChild( new TiXmlElement("ImagePositionPatient") ); // no parameters
589  }
590  else
591  if (classname == "DICOMSortByTag")
592  {
593  DICOMTagList pseudoTagList = sortCriterion->GetTagsOfInterest();
594  if (pseudoTagList.size() == 1)
595  {
596  DICOMTag firstTag = pseudoTagList.front();
597 
598  TiXmlElement* tagElement = this->CreateConfigStringFromDICOMTag(firstTag);
599 
600  sortingElement->LinkEndChild( tagElement );
601  }
602  else
603  {
604  MITK_ERROR << "Encountered SortByTag class with MULTIPLE tag in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize.";
605  return nullptr;
606  }
607  }
608  else
609  {
610  MITK_ERROR << "Encountered unknown class '" << classname << "' in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize.";
611  return nullptr;
612  }
613 
614  sortCriterion = sortCriterion->GetSecondaryCriterion();
615  }
616 
617  return sorterTag;
618 }
619 
620 TiXmlElement*
621 mitk::DICOMReaderConfigurator
622 ::CreateConfigStringFromDICOMTag(const DICOMTag& tag) const
623 {
624  auto tagElement = new TiXmlElement("Tag"); // name group element
625  tagElement->SetAttribute("name", tag.GetName().c_str());
626  tagElement->SetAttribute("group", toHexString(tag.GetGroup()));
627  tagElement->SetAttribute("element", toHexString(tag.GetElement()));
628  return tagElement;
629 }
630 
631 std::string
632 mitk::DICOMReaderConfigurator
633 ::toHexString(unsigned int i) const
634 {
635  std::stringstream ss;
636  ss << "0x" << std::setfill ('0') << std::setw(4) << std::hex << i;
637  return ss.str();
638 }
639 
640 
641 TiXmlElement*
644 {
645  TiXmlElement* root = this->CreateConfigStringFromReader(static_cast<const DICOMITKSeriesGDCMReader*>(reader));
646  assert(root);
647 
648  root->SetAttribute("group3DnT", toString(reader->GetGroup3DandT()));
649 
650  return root;
651 }
652 
653 const char*
654 mitk::DICOMReaderConfigurator
655 ::toString(bool b) const
656 {
657  return b ? "true" : "false";
658 }
659 
660 TiXmlElement*
663 {
664  return this->CreateDICOMFileReaderTag(reader);
665 }
666 
667 TiXmlElement*
668 mitk::DICOMReaderConfigurator
669 ::CreateDICOMFileReaderTag(const DICOMFileReader* reader) const
670 {
671  auto readerTag = new TiXmlElement("DICOMFileReader");
672  readerTag->SetAttribute("class", reader->GetNameOfClass());
673  readerTag->SetAttribute("label", reader->GetConfigurationLabel().c_str());
674  readerTag->SetAttribute("description", reader->GetConfigurationDescription().c_str());
675  readerTag->SetAttribute("version", "1");
676 
677  return readerTag;
678 }
Sorting and grouping like mitk::DicomSeriesReader until 2013.
unsigned int GetElement() const
#define boolStringTrue(s)
The sorting/splitting building-block of DICOMITKSeriesGDCMReader.
const TagValueProcessor * GetTagValueProcessorForDistinguishingTag(const DICOMTag &) const
static Pointer New()
Flexible reader based on itk::ImageSeriesReader and GDCM, for single-slice modalities like CT...
#define MITK_ERROR
Definition: mitkLogMacros.h:20
std::vector< DICOMTag > DICOMTagList
Definition: mitkDICOMTag.h:59
ConstSorterList GetFreelyConfiguredSortingElements() const
Representation of a DICOM tag.
Definition: mitkDICOMTag.h:32
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
DICOMFileReader::Pointer CreateFromConfigFile(const std::string &filename) const
std::string CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const
const std::list< DICOMDatasetSorter::ConstPointer > ConstSorterList
std::string GetConfigurationDescription() const
One-sentence description of the reader&#39;s loading "strategy".
#define MITK_WARN
Definition: mitkLogMacros.h:19
DICOMTagList GetDistinguishingTags() const
DICOMSortCriterion::ConstPointer GetSortCriterion() const
Extends DICOMITKSeriesGDCMReader by sorting/grouping into 3D+t image blocks.
std::string GetConfigurationLabel() const
Short label/name to describe this reader.
Cuts a number after configured number of decimal places. An instance of this class can be used to avo...
std::string GetName() const
Return the name of this tag (e.g. "SeriesDescription" instead of "(0008,103e)")
Sort DICOM datasets based on configurable tags.
Processes tag values before they are compared. These classes could do some kind of normalization such...
Interface for DICOM readers that produce mitk::Images.
unsigned int GetGroup() const
DICOMFileReader::Pointer CreateFromUTF8ConfigString(const std::string &xmlContents) const