Commit 1c433866 authored by Guillaume Pasero's avatar Guillaume Pasero

ENH: add map storage into XML, improve existing API of StatisticsXMLFileReader/Writer

parent e0197d7e
......@@ -58,6 +58,9 @@ public:
typedef std::pair<std::string , MeasurementVectorType> InputDataType;
typedef std::vector< InputDataType > MeasurementVectorContainer;
typedef std::map<std::string , std::string> GenericMapType;
typedef std::map<std::string , GenericMapType> GenericMapContainer;
virtual void Modified() const
{
m_IsUpdated = false;
......@@ -68,18 +71,29 @@ public:
itkGetStringMacro(FileName);
/** Get the number of Outputs*/
itkGetMacro(NumberOfOutputs, unsigned int);
unsigned int GetNumberOfOutputs();
/** Get the list of vector statistics names */
std::vector<std::string> GetStatisticVectorNames();
/** Get the list of map statistics names */
std::vector<std::string> GetStatisticMapNames();
/** Method to get the MeasurementVector by name */
MeasurementVectorType GetStatisticVectorByName(const char * statisticName);
/** Method to get a statistics map by name */
template <typename MapType>
MapType GetStatisticMapByName(const char * statisticName);
protected:
/** Read into the file and extract information in vector and map containers */
virtual void Read();
StatisticsXMLFileReader();
virtual ~StatisticsXMLFileReader() {}
void PrintSelf(std::ostream& os, itk::Indent indent) const;
virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
private:
StatisticsXMLFileReader(const Self&); //purposely not implemented
......@@ -87,8 +101,8 @@ private:
std::string m_FileName;
MeasurementVectorContainer m_MeasurementVectorContainer;
unsigned int m_NumberOfOutputs;
mutable bool m_IsUpdated;
GenericMapContainer m_GenericMapContainer;
}; // end of class StatisticsXMLFileReader
......
......@@ -22,6 +22,7 @@
#include "itkMacro.h"
#include "itksys/SystemTools.hxx"
#include "otb_tinyxml.h"
#include "otbStringUtils.h"
namespace otb {
......@@ -29,10 +30,57 @@ namespace otb {
template < class TMeasurementVector >
StatisticsXMLFileReader<TMeasurementVector>
::StatisticsXMLFileReader(): m_FileName(""),
m_NumberOfOutputs(0),
m_IsUpdated(false)
{}
template < class TMeasurementVector >
unsigned int
StatisticsXMLFileReader<TMeasurementVector>
::GetNumberOfOutputs()
{
return m_MeasurementVectorContainer.size() + m_GenericMapContainer.size();
}
template < class TMeasurementVector >
std::vector<std::string>
StatisticsXMLFileReader<TMeasurementVector>
::GetStatisticVectorNames()
{
// Read the xml file once
if(!m_IsUpdated)
{
this->Read();
}
std::vector<std::string> output;
for (unsigned int i=0 ; i < m_MeasurementVectorContainer.size() ; ++i )
{
output.push_back(m_MeasurementVectorContainer[i].first);
}
return output;
}
template < class TMeasurementVector >
std::vector<std::string>
StatisticsXMLFileReader<TMeasurementVector>
::GetStatisticMapNames()
{
// Read the xml file once
if(!m_IsUpdated)
{
this->Read();
}
std::vector<std::string> output;
for ( GenericMapContainer::iterator it = m_GenericMapContainer.begin() ;
it != m_GenericMapContainer.end() ;
++it)
{
output.push_back(it->first);
}
return output;
}
template < class TMeasurementVector >
typename StatisticsXMLFileReader<TMeasurementVector>
::MeasurementVectorType
......@@ -48,7 +96,7 @@ StatisticsXMLFileReader<TMeasurementVector>
// Check if the name of the Statistic is present
bool found = false;
unsigned int index = 0;
for(unsigned int idx = 0; idx < m_NumberOfOutputs; ++idx)
for(unsigned int idx = 0; idx < m_MeasurementVectorContainer.size() ; ++idx)
{
if(strcmp(m_MeasurementVectorContainer[idx].first.c_str(), statisticName) == 0 )
{
......@@ -64,6 +112,39 @@ StatisticsXMLFileReader<TMeasurementVector>
return m_MeasurementVectorContainer[index].second;
}
template < class TMeasurementVector >
template <typename MapType>
MapType
StatisticsXMLFileReader<TMeasurementVector>
::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<typename MapType::key_type>(it->first);
tmpVal = boost::lexical_cast<typename MapType::mapped_type>(it->second);
outputMap[tmpKey] = tmpVal;
}
return outputMap;
}
template < class TMeasurementVector >
void
StatisticsXMLFileReader<TMeasurementVector>
......@@ -80,6 +161,10 @@ StatisticsXMLFileReader<TMeasurementVector>
<<" 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())
......@@ -88,45 +173,73 @@ StatisticsXMLFileReader<TMeasurementVector>
}
TiXmlHandle hDoc(&doc);
TiXmlHandle root = hDoc.FirstChildElement("FeatureStatistics");
TiXmlElement *root = hDoc.FirstChildElement("FeatureStatistics").ToElement();
// Iterate through the tree to get all the stats
for( TiXmlElement* currentStat = root.FirstChildElement().ToElement();
currentStat != NULL;
currentStat = currentStat->NextSiblingElement() )
if (root)
{
InputDataType currentStatisticVector;
// Iterate through the tree to get all the stats
for( TiXmlElement* currentStat = root->FirstChildElement();
currentStat != NULL;
currentStat = currentStat->NextSiblingElement() )
{
InputDataType currentStatisticVector;
// Store the stat type name
currentStatisticVector.first = currentStat->Attribute("name");
// 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<double> tempMeasurementVector;
// 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<double> tempMeasurementVector;
for( TiXmlElement* sample = currentStat->FirstChildElement("StatisticVector");
sample != NULL;
sample = sample->NextSiblingElement() )
{
// Get the current value of the statistic vector
double value;
sample->QueryDoubleAttribute("value", &value);
// Store the value
tempMeasurementVector.push_back(value);
for( TiXmlElement* sample = currentStat->FirstChildElement("StatisticVector");
sample != NULL;
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<InputValueType>(tempMeasurementVector[i])));
m_MeasurementVectorContainer.push_back(currentStatisticVector);
}
}
// resize the Measurement Vector
currentStatisticVector.second.SetSize(tempMeasurementVector.size());
for(unsigned int i = 0; i < tempMeasurementVector.size(); ++i)
currentStatisticVector.second.SetElement(i,
(static_cast<InputValueType>(tempMeasurementVector[i])));
// Parse Map statistics
root = hDoc.FirstChildElement("GeneralStatistics").ToElement();
if (root)
{
// Iterate through the tree to get all the stats
for( TiXmlElement* currentStat = root->FirstChildElement();
currentStat != NULL;
currentStat = currentStat->NextSiblingElement() )
{
GenericMapType currentMap;
std::string currentName(currentStat->Attribute("name"));
// Increment the number of output
m_MeasurementVectorContainer.push_back(currentStatisticVector);
m_NumberOfOutputs++;
for( TiXmlElement* sample = currentStat->FirstChildElement("StatisticMap");
sample != NULL;
sample = sample->NextSiblingElement() )
{
// Get the current pair of the statistic map
std::string key;
std::string value;
sample->QueryStringAttribute("key", &key);
sample->QueryStringAttribute("value", &value);
// Store the pair
currentMap[key] = value;
}
m_GenericMapContainer[currentName] = currentMap;
}
}
// Reader is up-to-date
m_IsUpdated = true;
}
......@@ -134,10 +247,27 @@ StatisticsXMLFileReader<TMeasurementVector>
template < class TMeasurementVector >
void
StatisticsXMLFileReader<TMeasurementVector>
::PrintSelf(std::ostream& itkNotUsed(os), itk::Indent itkNotUsed(indent)) const
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
// Call superclass implementation
//Superclass::PrintSelf(os, indent);
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
......
......@@ -67,9 +67,13 @@ public:
/** Method to set/get the input list sample */
void AddInput(const char * name, const MeasurementVectorType& inputVector );
/** Method to add a map statistic with a given type */
template <typename MapType>
void AddInputMap(const char * name, const MapType& map );
/** Remove previously added inputs (vectors and maps) */
void CleanInputs();
/** Trigger the processing */
void Update()
{
......@@ -94,10 +98,8 @@ private:
std::string m_FileName;
MeasurementVectorContainer m_MeasurementVectorContainer;
GenericMapContainer m_GenericMapContainer;
}; // end of class StatisticsXMLFileWriter
} // end of namespace otb
......
......@@ -22,6 +22,7 @@
#include "itkMacro.h"
#include "itksys/SystemTools.hxx"
#include "otb_tinyxml.h"
#include "otbStringUtils.h"
namespace otb {
......@@ -167,15 +168,13 @@ StatisticsXMLFileWriter<TMeasurementVector>
typename MapType::const_iterator it;
GenericMapType insideMap;
std::ostringstream oss;
std::ostringstream ossKey;
std::string tmpKey;
std::string tmpVal;
for ( it = map.begin() ; it != map.end() ; ++it)
{
oss.str(std::string(""));
oss << it->second;
ossKey.str(std::string(""));
ossKey << it->first;
insideMap[ossKey.str()] = oss.str();
tmpKey = boost::lexical_cast<std::string>(it->first);
tmpVal = boost::lexical_cast<std::string>(it->second);
insideMap[tmpKey] = tmpVal;
}
m_GenericMapContainer[token] = insideMap;
}
......@@ -183,10 +182,37 @@ StatisticsXMLFileWriter<TMeasurementVector>
template < class TMeasurementVector >
void
StatisticsXMLFileWriter<TMeasurementVector>
::PrintSelf(std::ostream& itkNotUsed(os), itk::Indent itkNotUsed(indent)) const
::CleanInputs()
{
// clear both containers
m_MeasurementVectorContainer.clear();
m_GenericMapContainer.clear();
}
template < class TMeasurementVector >
void
StatisticsXMLFileWriter<TMeasurementVector>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
// Call superclass implementation
//Superclass::PrintSelf(os, indent);
Superclass::PrintSelf(os, indent);
// Print Writer state
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
......
......@@ -3,10 +3,13 @@ files.")
otb_module(OTBIOXML
DEPENDS
OTBBoostAdapters
OTBITK
OTBTinyXML
TEST_DEPENDS
OTBTestKernel
DESCRIPTION
"${DOCUMENTATION}"
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment