/* * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * * https://www.orfeo-toolbox.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef otbStatisticsXMLFileReader_hxx #define otbStatisticsXMLFileReader_hxx #include "otbStatisticsXMLFileReader.h" #include "itkMacro.h" #include "itksys/SystemTools.hxx" #include "otb_tinyxml.h" #include "otbStringUtils.h" namespace otb { template StatisticsXMLFileReader::StatisticsXMLFileReader() : m_FileName(""), m_IsUpdated(false) { } template unsigned int StatisticsXMLFileReader::GetNumberOfOutputs() { return m_MeasurementVectorContainer.size() + m_GenericMapContainer.size(); } template std::vector StatisticsXMLFileReader::GetStatisticVectorNames() { // Read the xml file once if (!m_IsUpdated) { this->Read(); } std::vector output; for (unsigned int i = 0; i < m_MeasurementVectorContainer.size(); ++i) { output.push_back(m_MeasurementVectorContainer[i].first); } return output; } template std::vector StatisticsXMLFileReader::GetStatisticMapNames() { // Read the xml file once if (!m_IsUpdated) { this->Read(); } std::vector output; for (GenericMapContainer::iterator it = m_GenericMapContainer.begin(); it != m_GenericMapContainer.end(); ++it) { output.push_back(it->first); } return output; } template typename StatisticsXMLFileReader::MeasurementVectorType StatisticsXMLFileReader::GetStatisticVectorByName(const char* statisticName) { // Read the xml file once if (!m_IsUpdated) { this->Read(); } // Check if the name of the Statistic is present bool found = false; unsigned int index = 0; for (unsigned int idx = 0; idx < m_MeasurementVectorContainer.size(); ++idx) { if (m_MeasurementVectorContainer[idx].first == statisticName) { found = true; index = idx; } } // if token not found throw an axception if (!found) itkExceptionMacro(<< "No entry corresponding to the token selected (" << statisticName << ") in the XML file"); return m_MeasurementVectorContainer[index].second; } template template MapType StatisticsXMLFileReader::GetStatisticMapByName(const char* statisticName) { // Read the xml file once if (!m_IsUpdated) { this->Read(); } // Check if the name of the Statistic is present std::string statName(statisticName); if (m_GenericMapContainer.count(statName) == 0) { itkExceptionMacro(<< "No entry corresponding to the token selected (" << statName << ") in the XML file"); } MapType outputMap; typename MapType::key_type tmpKey; typename MapType::mapped_type tmpVal; for (GenericMapType::iterator it = m_GenericMapContainer[statName].begin(); it != m_GenericMapContainer[statName].end(); ++it) { tmpKey = boost::lexical_cast(it->first); tmpVal = boost::lexical_cast(it->second); outputMap[tmpKey] = tmpVal; } return outputMap; } template void StatisticsXMLFileReader::Read() { // Check if the filename is not empty if (m_FileName.empty()) itkExceptionMacro(<< "The XML output FileName is empty, please set the filename via the method SetFileName"); // Check that the right extension is given : expected .xml */ std::string extension = itksys::SystemTools::GetFilenameLastExtension(m_FileName); if (itksys::SystemTools::LowerCase(extension) != ".xml") { itkExceptionMacro(<< extension << " is a wrong Extension FileName : Expected .xml"); } // Clean outputs m_MeasurementVectorContainer.clear(); m_GenericMapContainer.clear(); // Open the xml file TiXmlDocument doc(m_FileName.c_str()); if (!doc.LoadFile()) { itkExceptionMacro(<< "Can't open file " << m_FileName); } TiXmlHandle hDoc(&doc); TiXmlElement* root = hDoc.FirstChildElement("FeatureStatistics").ToElement(); if (root) { // Iterate through the tree to get all the stats for (TiXmlElement* currentStat = root->FirstChildElement(); currentStat != nullptr; currentStat = currentStat->NextSiblingElement()) { InputDataType currentStatisticVector; // Store the stat type name currentStatisticVector.first = currentStat->Attribute("name"); // The size is not stored in the XML file // Store the value in a std::vector, get the size and then // build a measurement vector std::vector tempMeasurementVector; for (TiXmlElement* sample = currentStat->FirstChildElement("StatisticVector"); sample != nullptr; sample = sample->NextSiblingElement()) { // Get the current value of the statistic vector double value; sample->QueryDoubleAttribute("value", &value); // Store the value tempMeasurementVector.push_back(value); } // resize the Measurement Vector currentStatisticVector.second.SetSize(tempMeasurementVector.size()); for (unsigned int i = 0; i < tempMeasurementVector.size(); ++i) currentStatisticVector.second.SetElement(i, (static_cast(tempMeasurementVector[i]))); m_MeasurementVectorContainer.push_back(currentStatisticVector); } } // Parse Map statistics std::string key; std::string value; root = hDoc.FirstChildElement("GeneralStatistics").ToElement(); if (root) { // Iterate through the tree to get all the stats for (TiXmlElement* currentStat = root->FirstChildElement(); currentStat != nullptr; currentStat = currentStat->NextSiblingElement()) { GenericMapType currentMap; std::string currentName(currentStat->Attribute("name")); for (TiXmlElement* sample = currentStat->FirstChildElement("StatisticMap"); sample != nullptr; sample = sample->NextSiblingElement()) { // Get the current pair of the statistic map const char* c_key = sample->Attribute("key"); const char* c_value = sample->Attribute("value"); if (c_key == nullptr) { itkExceptionMacro("'key' attribute not found in StatisticMap !"); } if (c_value == nullptr) { itkExceptionMacro("'value' attribute not found in StatisticMap !"); } key = std::string(c_key); value = std::string(c_value); // Store the pair currentMap[key] = value; } m_GenericMapContainer[currentName] = currentMap; } } // Reader is up-to-date m_IsUpdated = true; } template void StatisticsXMLFileReader::PrintSelf(std::ostream& os, itk::Indent indent) const { // Call superclass implementation Superclass::PrintSelf(os, indent); // Print info about statistics os << indent << "Input FileName: " << m_FileName << std::endl; os << indent << "Vector statistics: "; for (unsigned int i = 0; i < m_MeasurementVectorContainer.size(); ++i) { if (i > 0) os << ", "; os << m_MeasurementVectorContainer[i].first; } os << std::endl; os << indent << "Map statistics: "; for (GenericMapContainer::const_iterator it = m_GenericMapContainer.begin(); it != m_GenericMapContainer.end(); ++it) { if (it != m_GenericMapContainer.begin()) os << ", "; os << it->first; } os << std::endl; } } // End namespace otb #endif