OTB  6.7.0
Orfeo Toolbox
otbStatisticsXMLFileReader.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2019 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 otbStatisticsXMLFileReader_hxx
22 #define otbStatisticsXMLFileReader_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 template < class TMeasurementVector >
35 ::StatisticsXMLFileReader(): m_FileName(""),
36  m_IsUpdated(false)
37 {}
38 
39 template < class TMeasurementVector >
40 unsigned int
43 {
44  return m_MeasurementVectorContainer.size() + m_GenericMapContainer.size();
45 }
46 
47 template < class TMeasurementVector >
48 std::vector<std::string>
51 {
52  // Read the xml file once
53  if(!m_IsUpdated)
54  {
55  this->Read();
56  }
57 
58  std::vector<std::string> output;
59  for (unsigned int i=0 ; i < m_MeasurementVectorContainer.size() ; ++i )
60  {
61  output.push_back(m_MeasurementVectorContainer[i].first);
62  }
63  return output;
64 }
65 
66 template < class TMeasurementVector >
67 std::vector<std::string>
70 {
71  // Read the xml file once
72  if(!m_IsUpdated)
73  {
74  this->Read();
75  }
76 
77  std::vector<std::string> output;
78  for ( GenericMapContainer::iterator it = m_GenericMapContainer.begin() ;
79  it != m_GenericMapContainer.end() ;
80  ++it)
81  {
82  output.push_back(it->first);
83  }
84  return output;
85 }
86 
87 template < class TMeasurementVector >
89 ::MeasurementVectorType
91 ::GetStatisticVectorByName(const char * statisticName)
92 {
93  // Read the xml file once
94  if(!m_IsUpdated)
95  {
96  this->Read();
97  }
98 
99  // Check if the name of the Statistic is present
100  bool found = false;
101  unsigned int index = 0;
102  for(unsigned int idx = 0; idx < m_MeasurementVectorContainer.size() ; ++idx)
103  {
104  if(m_MeasurementVectorContainer[idx].first == statisticName)
105  {
106  found = true;
107  index = idx;
108  }
109  }
110 
111  // if token not found throw an axception
112  if(!found)
113  itkExceptionMacro(<<"No entry corresponding to the token selected ("<<statisticName<<") in the XML file");
114 
115  return m_MeasurementVectorContainer[index].second;
116 }
117 
118 template < class TMeasurementVector >
119 template <typename MapType>
120 MapType
122 ::GetStatisticMapByName(const char * statisticName)
123 {
124  // Read the xml file once
125  if(!m_IsUpdated)
126  {
127  this->Read();
128  }
129 
130  // Check if the name of the Statistic is present
131  std::string statName(statisticName);
132  if (m_GenericMapContainer.count(statName) == 0)
133  {
134  itkExceptionMacro(<<"No entry corresponding to the token selected ("<<statName<<") in the XML file");
135  }
136 
137  MapType outputMap;
138  typename MapType::key_type tmpKey;
139  typename MapType::mapped_type tmpVal;
140  for ( GenericMapType::iterator it = m_GenericMapContainer[statName].begin() ;
141  it != m_GenericMapContainer[statName].end() ;
142  ++it)
143  {
144  tmpKey = boost::lexical_cast<typename MapType::key_type>(it->first);
145  tmpVal = boost::lexical_cast<typename MapType::mapped_type>(it->second);
146  outputMap[tmpKey] = tmpVal;
147  }
148  return outputMap;
149 }
150 
151 template < class TMeasurementVector >
152 void
155 {
156  // Check if the filename is not empty
157  if(m_FileName.empty())
158  itkExceptionMacro(<<"The XML output FileName is empty, please set the filename via the method SetFileName");
159 
160  // Check that the right extension is given : expected .xml */
161  std::string extension = itksys::SystemTools::GetFilenameLastExtension(m_FileName);
162  if (itksys::SystemTools::LowerCase(extension) != ".xml")
163  {
164  itkExceptionMacro(<<extension
165  <<" is a wrong Extension FileName : Expected .xml");
166  }
167 
168  // Clean outputs
169  m_MeasurementVectorContainer.clear();
170  m_GenericMapContainer.clear();
171 
172  // Open the xml file
173  TiXmlDocument doc(m_FileName.c_str());
174  if (!doc.LoadFile())
175  {
176  itkExceptionMacro(<<"Can't open file "<<m_FileName);
177  }
178 
179  TiXmlHandle hDoc(&doc);
180  TiXmlElement *root = hDoc.FirstChildElement("FeatureStatistics").ToElement();
181 
182  if (root)
183  {
184  // Iterate through the tree to get all the stats
185  for( TiXmlElement* currentStat = root->FirstChildElement();
186  currentStat != nullptr;
187  currentStat = currentStat->NextSiblingElement() )
188  {
189  InputDataType currentStatisticVector;
190 
191  // Store the stat type name
192  currentStatisticVector.first = currentStat->Attribute("name");
193 
194  // The size is not stored in the XML file
195  // Store the value in a std::vector, get the size and then
196  // build a measurement vector
197  std::vector<double> tempMeasurementVector;
198 
199  for( TiXmlElement* sample = currentStat->FirstChildElement("StatisticVector");
200  sample != nullptr;
201  sample = sample->NextSiblingElement() )
202  {
203  // Get the current value of the statistic vector
204  double value;
205  sample->QueryDoubleAttribute("value", &value);
206  // Store the value
207  tempMeasurementVector.push_back(value);
208  }
209 
210  // resize the Measurement Vector
211  currentStatisticVector.second.SetSize(tempMeasurementVector.size());
212  for(unsigned int i = 0; i < tempMeasurementVector.size(); ++i)
213  currentStatisticVector.second.SetElement(i,
214  (static_cast<InputValueType>(tempMeasurementVector[i])));
215  m_MeasurementVectorContainer.push_back(currentStatisticVector);
216  }
217  }
218 
219  // Parse Map statistics
220  std::string key;
221  std::string value;
222  root = hDoc.FirstChildElement("GeneralStatistics").ToElement();
223  if (root)
224  {
225  // Iterate through the tree to get all the stats
226  for( TiXmlElement* currentStat = root->FirstChildElement();
227  currentStat != nullptr;
228  currentStat = currentStat->NextSiblingElement() )
229  {
230  GenericMapType currentMap;
231  std::string currentName(currentStat->Attribute("name"));
232 
233  for( TiXmlElement* sample = currentStat->FirstChildElement("StatisticMap");
234  sample != nullptr;
235  sample = sample->NextSiblingElement() )
236  {
237  // Get the current pair of the statistic map
238  const char *c_key = sample->Attribute("key");
239  const char *c_value = sample->Attribute("value");
240  if (c_key == nullptr)
241  {
242  itkExceptionMacro("'key' attribute not found in StatisticMap !");
243  }
244  if (c_value == nullptr)
245  {
246  itkExceptionMacro("'value' attribute not found in StatisticMap !");
247  }
248  key = std::string(c_key);
249  value = std::string(c_value);
250  // Store the pair
251  currentMap[key] = value;
252  }
253  m_GenericMapContainer[currentName] = currentMap;
254  }
255  }
256  // Reader is up-to-date
257  m_IsUpdated = true;
258 }
259 
260 
261 template < class TMeasurementVector >
262 void
264 ::PrintSelf(std::ostream& os, itk::Indent indent) const
265 {
266  // Call superclass implementation
267  Superclass::PrintSelf(os, indent);
268 
269  // Print info about statistics
270  os << indent << "Input FileName: "<< m_FileName << std::endl;
271  os << indent << "Vector statistics: ";
272  for (unsigned int i=0 ; i < m_MeasurementVectorContainer.size() ; ++i)
273  {
274  if (i>0) os <<", ";
275  os << m_MeasurementVectorContainer[i].first;
276  }
277  os << std::endl;
278  os << indent << "Map statistics: ";
279  for (GenericMapContainer::const_iterator it = m_GenericMapContainer.begin() ; it != m_GenericMapContainer.end() ; ++it)
280  {
281  if (it != m_GenericMapContainer.begin()) os <<", ";
282  os << it->first;
283  }
284  os << std::endl;
285 }
286 
287 } // End namespace otb
288 
289 #endif
void PrintSelf(std::ostream &os, itk::Indent indent) const override
std::vector< std::string > GetStatisticVectorNames()
Read a xml file where are stored several statistics.
OTBApplicationEngine_EXPORT int Read(const std::string &filename, Application::Pointer application)
std::pair< std::string, MeasurementVectorType > InputDataType
std::vector< std::string > GetStatisticMapNames()
MapType GetStatisticMapByName(const char *statisticName)
MeasurementVectorType GetStatisticVectorByName(const char *statisticName)
std::map< std::string, std::string > GenericMapType