OTB  9.0.0
Orfeo Toolbox
otbStatisticsXMLFileWriter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbStatisticsXMLFileWriter_hxx
22 #define otbStatisticsXMLFileWriter_hxx
23 
25 #include "itkMacro.h"
26 #include "itksys/SystemTools.hxx"
27 #include "otb_tinyxml.h"
28 #include "otbStringUtils.h"
29 
30 namespace otb
31 {
32 
33 
34 template <class TMeasurementVector>
36 {
37 }
38 
39 
40 template <class TMeasurementVector>
42 {
43  InputDataType inputData;
44  inputData.first = name;
45 
46  // Check if the statistic name is already added
47  for (unsigned int idx = 0; idx < m_MeasurementVectorContainer.size(); ++idx)
48  {
49  if (m_MeasurementVectorContainer[idx].first == name)
50  {
51  itkExceptionMacro(<< "Token selected (" << name << ") is already added to the XML file");
52  }
53  }
54 
55  inputData.second = inputVector;
56  m_MeasurementVectorContainer.push_back(inputData);
57 }
58 
59 template <class TMeasurementVector>
61 {
62  // Check if the input are not null
63  if (m_MeasurementVectorContainer.size() == 0 && m_GenericMapContainer.size() == 0)
64  itkExceptionMacro(<< "At least one input is required, please set input using the methods AddInput or AddInputMap");
65 
66  // Check if the filename is not empty
67  if (m_FileName.empty())
68  itkExceptionMacro(<< "The XML output FileName is empty, please set the filename via the method SetFileName");
69 
70  // Check that the right extension is given : expected .xml */
71  const std::string extension = itksys::SystemTools::GetFilenameLastExtension(m_FileName);
72  if (itksys::SystemTools::LowerCase(extension) != ".xml")
73  {
74  itkExceptionMacro(<< extension << " is a wrong Extension FileName : Expected .xml");
75  }
76 
77  // Write the XML file
78  TiXmlDocument doc;
79 
80  TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "", "");
81  doc.LinkEndChild(decl);
82 
83  TiXmlElement* root = nullptr;
84  if (m_MeasurementVectorContainer.size())
85  {
86  root = new TiXmlElement("FeatureStatistics");
87  doc.LinkEndChild(root);
88  }
89 
90  // Iterate through the input
91  for (unsigned int i = 0; i < m_MeasurementVectorContainer.size(); ++i)
92  {
93  std::string featureName = m_MeasurementVectorContainer[i].first;
94  MeasurementVectorType currentMeasurementVector = m_MeasurementVectorContainer[i].second;
95 
96  // The current statistic
97  TiXmlElement* feature = new TiXmlElement("Statistic");
98  feature->SetAttribute("name", featureName.c_str());
99  root->LinkEndChild(feature);
100 
101  // Store the value for this statistic
102  for (unsigned int cindex = 0; cindex < currentMeasurementVector.Size(); ++cindex)
103  {
104  // For each value in Measurementvector
105  TiXmlElement* curStatisticVector = new TiXmlElement("StatisticVector");
106  curStatisticVector->SetDoubleAttribute("value", currentMeasurementVector.GetElement(cindex));
107  feature->LinkEndChild(curStatisticVector);
108  }
109  }
110 
111  // Iterate on map containers
112  TiXmlElement* mapRoot = nullptr;
113  if (m_GenericMapContainer.size())
114  {
115  mapRoot = new TiXmlElement("GeneralStatistics");
116  doc.LinkEndChild(mapRoot);
117  }
118 
119  GenericMapContainer::const_iterator containerIt;
120  for (containerIt = m_GenericMapContainer.begin(); containerIt != m_GenericMapContainer.end(); ++containerIt)
121  {
122  std::string mapName = containerIt->first;
123  GenericMapType::const_iterator mapIter;
124 
125  // The current statistic
126  TiXmlElement* feature = new TiXmlElement("Statistic");
127  feature->SetAttribute("name", mapName.c_str());
128  mapRoot->LinkEndChild(feature);
129 
130  // Store the value for this statistic
131  for (mapIter = containerIt->second.begin(); mapIter != containerIt->second.end(); ++mapIter)
132  {
133  // For each value in Measurementvector
134  TiXmlElement* curStatisticMap = new TiXmlElement("StatisticMap");
135  curStatisticMap->SetAttribute("key", mapIter->first.c_str());
136  curStatisticMap->SetAttribute("value", mapIter->second.c_str());
137  feature->LinkEndChild(curStatisticMap);
138  }
139  }
140 
141 
142  // Finally, write the file
143  if (!doc.SaveFile(m_FileName.c_str()))
144  {
145  itkExceptionMacro(<< "Unable to write the XML file in " << itksys::SystemTools::GetFilenamePath(m_FileName)
146  << " (permission issue? Directory does not exist?).");
147  }
148 }
149 
150 template <class TMeasurementVector>
151 template <typename MapType>
152 void StatisticsXMLFileWriter<TMeasurementVector>::AddInputMap(const char* name, const MapType& map)
153 {
154  std::string token(name);
155 
156  if (m_GenericMapContainer.count(token) > 0)
157  {
158  itkExceptionMacro(<< "Token selected (" << name << ") is already added to the XML file");
159  }
160 
161  typename MapType::const_iterator it;
162  GenericMapType insideMap;
163  std::string tmpKey;
164  std::string tmpVal;
165  for (it = map.begin(); it != map.end(); ++it)
166  {
167  tmpKey = boost::lexical_cast<std::string>(it->first);
168  tmpVal = boost::lexical_cast<std::string>(it->second);
169  insideMap[tmpKey] = tmpVal;
170  }
171  m_GenericMapContainer[token] = insideMap;
172 }
173 
174 template <class TMeasurementVector>
176 {
177  // clear both containers
178  m_MeasurementVectorContainer.clear();
179  m_GenericMapContainer.clear();
180 }
181 
182 template <class TMeasurementVector>
183 void StatisticsXMLFileWriter<TMeasurementVector>::PrintSelf(std::ostream& os, itk::Indent indent) const
184 {
185  // Call superclass implementation
186  Superclass::PrintSelf(os, indent);
187 
188  // Print Writer state
189  os << indent << "Input FileName: " << m_FileName << std::endl;
190  os << indent << "Vector statistics: ";
191  for (unsigned int i = 0; i < m_MeasurementVectorContainer.size(); ++i)
192  {
193  if (i > 0)
194  os << ", ";
195  os << m_MeasurementVectorContainer[i].first;
196  }
197  os << std::endl;
198  os << indent << "Map statistics: ";
199  for (GenericMapContainer::const_iterator it = m_GenericMapContainer.begin(); it != m_GenericMapContainer.end(); ++it)
200  {
201  if (it != m_GenericMapContainer.begin())
202  os << ", ";
203  os << it->first;
204  }
205  os << std::endl;
206 }
207 
208 } // End namespace otb
209 
210 #endif
otb::StatisticsXMLFileWriter::InputDataType
std::pair< std::string, MeasurementVectorType > InputDataType
Definition: otbStatisticsXMLFileWriter.h:64
otb::StatisticsXMLFileWriter::GenericMapType
std::map< std::string, std::string > GenericMapType
Definition: otbStatisticsXMLFileWriter.h:67
otb::StatisticsXMLFileWriter::AddInputMap
void AddInputMap(const char *name, const MapType &map)
Definition: otbStatisticsXMLFileWriter.hxx:152
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::StatisticsXMLFileWriter::StatisticsXMLFileWriter
StatisticsXMLFileWriter()
Definition: otbStatisticsXMLFileWriter.hxx:35
otb::StatisticsXMLFileWriter::MeasurementVectorType
TMeasurementVector MeasurementVectorType
Definition: otbStatisticsXMLFileWriter.h:57
otb::StatisticsXMLFileWriter::AddInput
void AddInput(const char *name, const MeasurementVectorType &inputVector)
Definition: otbStatisticsXMLFileWriter.hxx:41
otbStringUtils.h
otb::StatisticsXMLFileWriter::CleanInputs
void CleanInputs()
Definition: otbStatisticsXMLFileWriter.hxx:175
otbStatisticsXMLFileWriter.h
otb::StatisticsXMLFileWriter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbStatisticsXMLFileWriter.hxx:183
otb::StatisticsXMLFileWriter::GenerateData
virtual void GenerateData()
Definition: otbStatisticsXMLFileWriter.hxx:60