Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkLabelSetIOHelper.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 
13 #include "mitkLabelSetIOHelper.h"
14 
15 #include "mitkLabelSetImage.h"
17 #include <tinyxml.h>
18 
19 bool mitk::LabelSetIOHelper::SaveLabelSetImagePreset(std::string &presetFilename,
20  mitk::LabelSetImage::Pointer &inputImage)
21 {
22  if (presetFilename.find(".lsetp") == std::string::npos)
23  {
24  presetFilename.append(".lsetp");
25  }
26 
27  auto *presetXmlDoc = new TiXmlDocument();
28 
29  auto *decl = new TiXmlDeclaration("1.0", "", "");
30  presetXmlDoc->LinkEndChild(decl);
31 
32  auto *presetElement = new TiXmlElement("LabelSetImagePreset");
33  presetElement->SetAttribute("layers", inputImage->GetNumberOfLayers());
34 
35  presetXmlDoc->LinkEndChild(presetElement);
36 
37  for (unsigned int layerIdx = 0; layerIdx < inputImage->GetNumberOfLayers(); layerIdx++)
38  {
39  auto *layerElement = new TiXmlElement("Layer");
40  layerElement->SetAttribute("index", layerIdx);
41  layerElement->SetAttribute("labels", inputImage->GetNumberOfLabels(layerIdx));
42 
43  presetElement->LinkEndChild(layerElement);
44 
45  for (unsigned int labelIdx = 0; labelIdx < inputImage->GetNumberOfLabels(layerIdx); labelIdx++)
46  {
47  TiXmlElement *labelAsXml = LabelSetIOHelper::GetLabelAsTiXmlElement(inputImage->GetLabel(labelIdx, layerIdx));
48  layerElement->LinkEndChild(labelAsXml);
49  }
50  }
51 
52  bool wasSaved = presetXmlDoc->SaveFile(presetFilename);
53  delete presetXmlDoc;
54 
55  return wasSaved;
56 }
57 
58 void mitk::LabelSetIOHelper::LoadLabelSetImagePreset(std::string &presetFilename,
59  mitk::LabelSetImage::Pointer &inputImage)
60 {
61  if (presetFilename.find(".lsetp") == std::string::npos)
62  {
63  presetFilename.append(".lsetp");
64  }
65 
66  std::unique_ptr<TiXmlDocument> presetXmlDoc(new TiXmlDocument());
67 
68  bool ok = presetXmlDoc->LoadFile(presetFilename);
69  if (!ok)
70  return;
71 
72  TiXmlElement *presetElem = presetXmlDoc->FirstChildElement("LabelSetImagePreset");
73  if (!presetElem)
74  {
75  MITK_INFO << "No valid preset XML";
76  return;
77  }
78 
79  int numberOfLayers;
80  presetElem->QueryIntAttribute("layers", &numberOfLayers);
81 
82  for (int i = 0; i < numberOfLayers; i++)
83  {
84  TiXmlElement *layerElem = presetElem->FirstChildElement("Layer");
85  int numberOfLabels;
86  layerElem->QueryIntAttribute("labels", &numberOfLabels);
87 
88  if (inputImage->GetLabelSet(i) == nullptr)
89  inputImage->AddLayer();
90 
91  TiXmlElement *labelElement = layerElem->FirstChildElement("Label");
92  if (labelElement == nullptr)
93  break;
94  for (int j = 0; j < numberOfLabels; j++)
95  {
97 
98  if (label->GetValue() == 0)
99  inputImage->SetExteriorLabel(label);
100  else
101  inputImage->GetLabelSet()->AddLabel(label);
102 
103  labelElement = labelElement->NextSiblingElement("Label");
104  if (labelElement == nullptr)
105  break;
106  }
107  }
108 }
109 
111 {
112  auto *labelElem = new TiXmlElement("Label");
113 
114  // add XML contents
115  const PropertyList::PropertyMap *propmap = label->GetMap();
116  for (auto iter = propmap->begin(); iter != propmap->end(); ++iter)
117  {
118  std::string key = iter->first;
119  const BaseProperty *property = iter->second;
120  TiXmlElement *element = PropertyToXmlElem(key, property);
121  if (element)
122  labelElem->LinkEndChild(element);
123  }
124  return labelElem;
125 }
126 
128 {
129  // reread
130  TiXmlElement *propElem = labelElem->FirstChildElement("property");
131 
132  std::string name;
134 
136  while (propElem)
137  {
138  LabelSetIOHelper::PropertyFromXmlElem(name, prop, propElem);
139  label->SetProperty(name, prop);
140  propElem = propElem->NextSiblingElement("property");
141  }
142 
143  return label.GetPointer();
144 }
145 
146 TiXmlElement *mitk::LabelSetIOHelper::PropertyToXmlElem(const std::string &key, const BaseProperty *property)
147 {
148  auto *keyelement = new TiXmlElement("property");
149  keyelement->SetAttribute("key", key);
150  keyelement->SetAttribute("type", property->GetNameOfClass());
151 
152  // construct name of serializer class
153  std::string serializername(property->GetNameOfClass());
154  serializername += "Serializer";
155 
156  std::list<itk::LightObject::Pointer> allSerializers =
157  itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
158  if (allSerializers.size() < 1)
159  MITK_ERROR << "No serializer found for " << property->GetNameOfClass() << ". Skipping object";
160 
161  if (allSerializers.size() > 1)
162  MITK_WARN << "Multiple serializers found for " << property->GetNameOfClass() << "Using arbitrarily the first one.";
163 
164  for (auto iter = allSerializers.begin(); iter != allSerializers.end();
165  ++iter)
166  {
167  if (auto *serializer = dynamic_cast<BasePropertySerializer *>(iter->GetPointer()))
168  {
169  serializer->SetProperty(property);
170  try
171  {
172  TiXmlElement *valueelement = serializer->Serialize();
173  if (valueelement)
174  keyelement->LinkEndChild(valueelement);
175  }
176  catch (std::exception &e)
177  {
178  MITK_ERROR << "Serializer " << serializer->GetNameOfClass() << " failed: " << e.what();
179  }
180  break;
181  }
182  }
183  return keyelement;
184 }
185 
188  TiXmlElement *elem)
189 {
190  std::string type;
191  elem->QueryStringAttribute("type", &type);
192  elem->QueryStringAttribute("key", &key);
193 
194  // construct name of serializer class
195  std::string serializername(type);
196  serializername += "Serializer";
197 
198  std::list<itk::LightObject::Pointer> allSerializers =
199  itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
200  if (allSerializers.size() < 1)
201  MITK_ERROR << "No serializer found for " << type << ". Skipping object";
202 
203  if (allSerializers.size() > 1)
204  MITK_WARN << "Multiple deserializers found for " << type << "Using arbitrarily the first one.";
205 
206  for (auto iter = allSerializers.begin(); iter != allSerializers.end();
207  ++iter)
208  {
209  if (auto *serializer = dynamic_cast<BasePropertySerializer *>(iter->GetPointer()))
210  {
211  try
212  {
213  prop = serializer->Deserialize(elem->FirstChildElement());
214  }
215  catch (std::exception &e)
216  {
217  MITK_ERROR << "Deserializer " << serializer->GetNameOfClass() << " failed: " << e.what();
218  return false;
219  }
220  break;
221  }
222  }
223  if (prop.IsNull())
224  return false;
225  return true;
226 }
#define MITK_INFO
Definition: mitkLogMacros.h:18
static itk::SmartPointer< mitk::Label > LoadLabelFromTiXmlDocument(TiXmlElement *labelElem)
Creates a mitk::Label from a TiXmlElement.
#define MITK_ERROR
Definition: mitkLogMacros.h:20
static TiXmlElement * PropertyToXmlElem(const std::string &key, const BaseProperty *property)
Since a mitk::Label is basically a mitk::PropertyList this function coverts the label&#39;s properties in...
A data structure describing a label.
Definition: mitkLabel.h:31
static bool PropertyFromXmlElem(std::string &key, itk::SmartPointer< mitk::BaseProperty > &prop, TiXmlElement *elem)
Since a mitk::Label is basically a mitk::PropertyList this function coverts a XML element into a prop...
static void LoadLabelSetImagePreset(std::string &presetFilename, itk::SmartPointer< mitk::LabelSetImage > &inputImage)
Loads an existing preset for a mitk::LabelSetImage from presetFilename and applies it to inputImage...
static Pointer New()
Abstract base class for properties.
#define MITK_WARN
Definition: mitkLogMacros.h:19
std::map< std::string, BaseProperty::Pointer > PropertyMap
static TiXmlElement * GetLabelAsTiXmlElement(Label *label)
Creates a TiXmlElement from a mitk::Label.
static bool SaveLabelSetImagePreset(std::string &presetFilename, itk::SmartPointer< mitk::LabelSetImage > &inputImage)
Saves the mitk::LabelSet configuration of inputImage to presetFilename. The preset is stored as "*...
const PropertyMap * GetMap() const