Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
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 
181 mitk::ThreeDnTDICOMSeriesReader::Pointer
182 mitk::DICOMReaderConfigurator
183 ::ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const
184 {
185  assert(element);
186 
187  // use all the base class configuration
188  if (this->ConfigureDICOMITKSeriesGDCMReader( reader.GetPointer(), element ).IsNull())
189  {
190  return nullptr;
191  }
192 
193  this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader,element);
194  return reader;
195 }
196 
197 void
198 mitk::DICOMReaderConfigurator
199 ::ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const
200 {
201  assert(element);
202 
203  const char* configLabelC = element->Attribute("label");
204  if (configLabelC)
205  {
206  std::string configLabel(configLabelC);
207  reader->SetConfigurationLabel(configLabel);
208  }
209 
210  const char* configDescriptionC = element->Attribute("description");
211  if (configDescriptionC)
212  {
213  reader->SetConfigurationDescription(configDescriptionC);
214  }
215 
216  // "fixTiltByShearing" flag
217  bool fixTiltByShearing = QueryBooleanAttribute(element, "fixTiltByShearing", DICOMITKSeriesGDCMReader::GetDefaultFixTiltByShearing());
218 
219  reader->SetFixTiltByShearing( fixTiltByShearing );
220 }
221 
222 mitk::DICOMITKSeriesGDCMReader::Pointer
223 mitk::DICOMReaderConfigurator
224 ::ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const
225 {
226  assert(element);
227 
228  this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader, element);
229 
230  // "acceptTwoSlicesGroups" flag
231  bool acceptTwoSlicesGroups = QueryBooleanAttribute(element, "acceptTwoSlicesGroups", true);
232 
233  reader->SetAcceptTwoSlicesGroups( acceptTwoSlicesGroups );
234 
235  // "toleratedOriginError" attribute (double)
236  bool toleratedOriginErrorIsAbsolute = QueryBooleanAttribute(element, "toleratedOriginErrorIsAbsolute", false);
237 
238  double toleratedOriginError(0.3);
239  if (element->QueryDoubleAttribute("toleratedOriginError", &toleratedOriginError) == TIXML_SUCCESS) // attribute present and a double value
240  {
241  if (toleratedOriginErrorIsAbsolute)
242  {
243  reader->SetToleratedOriginOffset( toleratedOriginError );
244  }
245  else
246  {
247  reader->SetToleratedOriginOffsetToAdaptive( toleratedOriginError );
248  }
249  }
250 
251  // DICOMTagBasedSorters are the only thing we create at this point
252  // TODO for-loop over all child elements of type DICOMTagBasedSorter, BUT actually a single sorter of this type is enough.
253  TiXmlElement* dElement = element->FirstChildElement("DICOMDatasetSorter");
254  if (dElement)
255  {
256  const char* classnameC = dElement->Attribute("class");
257  if (!classnameC)
258  {
259  MITK_ERROR << "File should name a DICOMDatasetSorter class in the class attribute of <DICOMDatasetSorter class=\"...\">. Found nothing instead";
260  return nullptr;
261  }
262 
263  std::string classname(classnameC);
264 
265  if (classname == "DICOMTagBasedSorter")
266  {
267  DICOMTagBasedSorter::Pointer tagSorter = CreateDICOMTagBasedSorter(dElement);
268  if (tagSorter.IsNotNull())
269  {
270  reader->AddSortingElement( tagSorter );
271  }
272  }
273  else
274  {
275  MITK_ERROR << "DICOMDatasetSorter tag names unknown class '" << classname << "'";
276  return nullptr;
277  }
278  }
279 
280  return reader;
281 }
282 
283 mitk::DICOMTagBasedSorter::Pointer
284 mitk::DICOMReaderConfigurator
285 ::CreateDICOMTagBasedSorter(TiXmlElement* element) const
286 {
287  mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
288 
289  // "strictSorting" parameter!
290  bool strictSorting = QueryBooleanAttribute(element, "strictSorting", mitk::DICOMTagBasedSorter::GetDefaultStrictSorting());
291  tagSorter->SetStrictSorting(strictSorting);
292 
293  // "strictSorting" parameter!
294  bool expectDistanceOne = QueryBooleanAttribute(element, "expectDistanceOne", mitk::DICOMTagBasedSorter::GetDefaultExpectDistanceOne());
295  tagSorter->SetExpectDistanceOne(expectDistanceOne);
296 
297  TiXmlElement* dElement = element->FirstChildElement("Distinguishing");
298  if (dElement)
299  {
300  for ( TiXmlElement* tChild = dElement->FirstChildElement();
301  tChild != nullptr;
302  tChild = tChild->NextSiblingElement() )
303  {
304  try
305  {
306  mitk::DICOMTag tag = tagFromXMLElement(tChild);
307  int i(5);
308  if (tChild->QueryIntAttribute("cutDecimalPlaces", &i) == TIXML_SUCCESS)
309  {
310  tagSorter->AddDistinguishingTag( tag, new mitk::DICOMTagBasedSorter::CutDecimalPlaces(i) );
311  }
312  else
313  {
314  tagSorter->AddDistinguishingTag( tag );
315  }
316  }
317  catch(...)
318  {
319  return nullptr;
320  }
321  }
322  }
323 
324  // "sorting tags"
325  TiXmlElement* sElement = element->FirstChildElement("Sorting");
326  if (sElement)
327  {
328  DICOMSortCriterion::Pointer previousCriterion;
329  DICOMSortCriterion::Pointer currentCriterion;
330 
331  for ( TiXmlNode* tChildNode = sElement->LastChild();
332  tChildNode != nullptr;
333  tChildNode = tChildNode->PreviousSibling() )
334  {
335  TiXmlElement* tChild = tChildNode->ToElement();
336  if (!tChild) continue;
337 
338  if (!strcmp(tChild->Value(), "Tag"))
339  {
340  try
341  {
342  currentCriterion = this->CreateDICOMSortByTag(tChild, previousCriterion);
343  }
344  catch(...)
345  {
346  std::stringstream ss;
347  ss << "Could not parse <Tag> element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!";
348  MITK_ERROR << ss.str();
349  return nullptr;
350  }
351  }
352  else
353  if (!strcmp(tChild->Value(), "ImagePositionPatient"))
354  {
355  try
356  {
357  currentCriterion = this->CreateSortByImagePositionPatient(tChild, previousCriterion);
358  }
359  catch(...)
360  {
361  std::stringstream ss;
362  ss << "Could not parse <ImagePositionPatient> element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!";
363  MITK_ERROR << ss.str();
364  return nullptr;
365  }
366  }
367  else
368  {
369  MITK_ERROR << "File contain unknown tag <" << tChild->Value() << "> tag as child to <Sorting>! Cannot interpret...";
370  }
371 
372  previousCriterion = currentCriterion;
373  }
374 
375  tagSorter->SetSortCriterion( currentCriterion.GetPointer() );
376  }
377 
378  return tagSorter;
379 }
380 
381 std::string
382 mitk::DICOMReaderConfigurator
383 ::requiredStringAttribute(TiXmlElement* xmlElement, const std::string& key) const
384 {
385  assert(xmlElement);
386 
387  const char* gC = xmlElement->Attribute(key.c_str());
388  if (gC)
389  {
390  std::string gS(gC);
391  return gS;
392  }
393  else
394  {
395  std::stringstream ss;
396  ss << "Expected an attribute '" << key << "' at this position "
397  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
398  MITK_ERROR << ss.str();
399  throw std::invalid_argument( ss.str() );
400  }
401 }
402 
403 unsigned int
404 mitk::DICOMReaderConfigurator
405 ::hexStringToUInt(const std::string& s) const
406 {
407  std::stringstream converter(s);
408  unsigned int ui;
409  converter >> std::hex >> ui;
410  MITK_DEBUG << "Converted string '" << s << "' to unsigned int " << ui;
411  return ui;
412 }
413 
415 mitk::DICOMReaderConfigurator
416 ::tagFromXMLElement(TiXmlElement* xmlElement) const
417 {
418  assert(xmlElement);
419 
420  if (strcmp(xmlElement->Value(), "Tag")) // :-( no std::string methods
421  {
422  std::stringstream ss;
423  ss << "Expected a <Tag group=\"..\" element=\"..\"> tag at this position "
424  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
425  MITK_ERROR << ss.str();
426  throw std::invalid_argument( ss.str() );
427  }
428 
429  std::string groupS = requiredStringAttribute(xmlElement, "group");
430  std::string elementS = requiredStringAttribute(xmlElement, "element");
431 
432  try
433  {
434  // convert string to int (assuming string is in hex format with leading "0x" like "0x0020")
435  unsigned int group = hexStringToUInt(groupS);
436  unsigned int element = hexStringToUInt(elementS);
437  return DICOMTag(group, element);
438  }
439  catch(...)
440  {
441  std::stringstream ss;
442  ss << "Expected group and element values in <Tag group=\"..\" element=\"..\"> to be hexadecimal with leading 0x, e.g. '0x0020'"
443  "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!";
444  MITK_ERROR << ss.str();
445  throw std::invalid_argument( ss.str() );
446  }
447 }
448 
449 mitk::DICOMSortCriterion::Pointer
450 mitk::DICOMReaderConfigurator
451 ::CreateDICOMSortByTag(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const
452 {
453  mitk::DICOMTag tag = tagFromXMLElement(xmlElement);
454  return DICOMSortByTag::New(tag, secondaryCriterion).GetPointer();
455 }
456 
457 mitk::DICOMSortCriterion::Pointer
458 mitk::DICOMReaderConfigurator
459 ::CreateSortByImagePositionPatient(TiXmlElement*, DICOMSortCriterion::Pointer secondaryCriterion) const
460 {
461  return SortByImagePositionPatient::New(secondaryCriterion).GetPointer();
462 }
463 
464 
465 
466 std::string
468 ::CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const
469 {
470  // check possible sub-classes from the most-specific one up to the most generic one
471  const DICOMFileReader* cPointer = reader;
472  TiXmlElement* root;
473  if (const auto* specificReader = dynamic_cast<const ClassicDICOMSeriesReader*>(cPointer))
474  {
475  root = this->CreateConfigStringFromReader(specificReader);
476  }
477  else
478  if (const auto* specificReader = dynamic_cast<const ThreeDnTDICOMSeriesReader*>(cPointer))
479  {
480  root = this->CreateConfigStringFromReader(specificReader);
481  }
482  else
483  if (const auto* specificReader = dynamic_cast<const DICOMITKSeriesGDCMReader*>(cPointer))
484  {
485  root = this->CreateConfigStringFromReader(specificReader);
486  }
487  else
488  {
489  MITK_WARN << "Unknown reader class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize.";
490  return ""; // no serialization, what a pity
491  }
492 
493  if (root)
494  {
495  TiXmlDocument document;
496  document.LinkEndChild( root );
497 
498  TiXmlPrinter printer;
499  printer.SetIndent( " " );
500 
501  document.Accept( &printer );
502  std::string xmltext = printer.CStr();
503  return xmltext;
504  }
505  else
506  {
507  MITK_WARN << "DICOMReaderConfigurator::CreateConfigStringFromReader() created empty serialization. Problem?";
508  return "";
509  }
510 }
511 
512 TiXmlElement*
515 {
516  TiXmlElement* root = this->CreateDICOMFileReaderTag(reader);
517  assert(root);
518 
519  root->SetAttribute("fixTiltByShearing", toString(reader->GetFixTiltByShearing()));
520  root->SetAttribute("acceptTwoSlicesGroups", toString(reader->GetAcceptTwoSlicesGroups()));
521  root->SetDoubleAttribute("toleratedOriginError", reader->GetToleratedOriginError());
522  root->SetAttribute("toleratedOriginErrorIsAbsolute", toString(reader->IsToleratedOriginOffsetAbsolute()));
523  root->SetDoubleAttribute("decimalPlacesForOrientation", reader->GetDecimalPlacesForOrientation());
524 
525  // iterate DICOMDatasetSorter objects
527  for(auto sorterIter = sorterList.begin();
528  sorterIter != sorterList.end();
529  ++sorterIter)
530  {
531  const DICOMDatasetSorter* sorter = *sorterIter;
532  if (const auto* specificSorter = dynamic_cast<const DICOMTagBasedSorter*>(sorter))
533  {
534  TiXmlElement* sorterTag = this->CreateConfigStringFromDICOMDatasetSorter(specificSorter);
535  root->LinkEndChild(sorterTag);
536  }
537  else
538  {
539  MITK_WARN << "Unknown DICOMDatasetSorter class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize.";
540  return nullptr;
541  }
542  }
543 
544  return root;
545 }
546 
547 TiXmlElement*
548 mitk::DICOMReaderConfigurator
549 ::CreateConfigStringFromDICOMDatasetSorter(const DICOMTagBasedSorter* sorter) const
550 {
551  assert(sorter);
552 
553  auto sorterTag = new TiXmlElement("DICOMDatasetSorter");
554  sorterTag->SetAttribute("class", sorter->GetNameOfClass());
555  sorterTag->SetAttribute("strictSorting", toString(sorter->GetStrictSorting()));
556  sorterTag->SetAttribute("expectDistanceOne", toString(sorter->GetExpectDistanceOne()));
557 
558  auto distinguishingTagsElement = new TiXmlElement("Distinguishing");
559  sorterTag->LinkEndChild(distinguishingTagsElement);
560  mitk::DICOMTagList distinguishingTags = sorter->GetDistinguishingTags();
561  for (auto tagIter = distinguishingTags.begin();
562  tagIter != distinguishingTags.end();
563  ++tagIter)
564  {
565  TiXmlElement* tag = this->CreateConfigStringFromDICOMTag(*tagIter);
566  distinguishingTagsElement->LinkEndChild(tag);
567 
569  if (const auto* specificProcessor = dynamic_cast<const DICOMTagBasedSorter::CutDecimalPlaces*>(processor))
570  {
571  tag->SetDoubleAttribute("cutDecimalPlaces", specificProcessor->GetPrecision());
572  }
573  }
574 
575  auto sortingElement = new TiXmlElement("Sorting");
576  sorterTag->LinkEndChild(sortingElement);
577  mitk::DICOMSortCriterion::ConstPointer sortCriterion = sorter->GetSortCriterion();
578  while (sortCriterion.IsNotNull())
579  {
580  std::string classname = sortCriterion->GetNameOfClass();
581  if (classname == "SortByImagePositionPatient")
582  {
583  sortingElement->LinkEndChild( new TiXmlElement("ImagePositionPatient") ); // no parameters
584  }
585  else
586  if (classname == "DICOMSortByTag")
587  {
588  DICOMTagList pseudoTagList = sortCriterion->GetTagsOfInterest();
589  if (pseudoTagList.size() == 1)
590  {
591  DICOMTag firstTag = pseudoTagList.front();
592 
593  TiXmlElement* tagElement = this->CreateConfigStringFromDICOMTag(firstTag);
594 
595  sortingElement->LinkEndChild( tagElement );
596  }
597  else
598  {
599  MITK_ERROR << "Encountered SortByTag class with MULTIPLE tag in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize.";
600  return nullptr;
601  }
602  }
603  else
604  {
605  MITK_ERROR << "Encountered unknown class '" << classname << "' in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize.";
606  return nullptr;
607  }
608 
609  sortCriterion = sortCriterion->GetSecondaryCriterion();
610  }
611 
612  return sorterTag;
613 }
614 
615 TiXmlElement*
616 mitk::DICOMReaderConfigurator
617 ::CreateConfigStringFromDICOMTag(const DICOMTag& tag) const
618 {
619  auto tagElement = new TiXmlElement("Tag"); // name group element
620  tagElement->SetAttribute("name", tag.GetName().c_str());
621  tagElement->SetAttribute("group", toHexString(tag.GetGroup()));
622  tagElement->SetAttribute("element", toHexString(tag.GetElement()));
623  return tagElement;
624 }
625 
626 std::string
627 mitk::DICOMReaderConfigurator
628 ::toHexString(unsigned int i) const
629 {
630  std::stringstream ss;
631  ss << "0x" << std::setfill ('0') << std::setw(4) << std::hex << i;
632  return ss.str();
633 }
634 
635 
636 TiXmlElement*
639 {
640  TiXmlElement* root = this->CreateConfigStringFromReader(static_cast<const DICOMITKSeriesGDCMReader*>(reader));
641  assert(root);
642 
643  root->SetAttribute("group3DnT", toString(reader->GetGroup3DandT()));
644 
645  return root;
646 }
647 
648 const char*
649 mitk::DICOMReaderConfigurator
650 ::toString(bool b) const
651 {
652  return b ? "true" : "false";
653 }
654 
655 TiXmlElement*
658 {
659  return this->CreateDICOMFileReaderTag(reader);
660 }
661 
662 TiXmlElement*
663 mitk::DICOMReaderConfigurator
664 ::CreateDICOMFileReaderTag(const DICOMFileReader* reader) const
665 {
666  auto readerTag = new TiXmlElement("DICOMFileReader");
667  readerTag->SetAttribute("class", reader->GetNameOfClass());
668  readerTag->SetAttribute("label", reader->GetConfigurationLabel().c_str());
669  readerTag->SetAttribute("description", reader->GetConfigurationDescription().c_str());
670  readerTag->SetAttribute("version", "1");
671 
672  return readerTag;
673 }
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