From a93e5be3dae5472b813ff61dee883ecbdfbbccd9 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 15 Dec 2010 15:11:25 +0000 Subject: [PATCH] * ./crlcore: - New: Histogram object, imported from Kite. Made more generic to be reusable by all. - Change: In Measures, added Inspector support. NOTE: The hidden property holding MeasuresDatas no longer uses a pointer a value. This forces us to enable the copy constructor. It is needed for some inner STL container manipulation, but should *not* be used with non-empty datas. The copy constructor *do not* copy the internal datas (reset the object). - New: In Measurments, support for complex data sets, saved in separate Gnuplot <.dat> files. Used to integrate Histogram. - New: In Histogram, now a supported Measure type so it can be integrated along all others measurments. - Bug: In display.xml, forgotten gcut description in Alliance Classic black style. --- crlcore/etc/display.xml | 2 +- crlcore/src/ccore/CMakeLists.txt | 2 + crlcore/src/ccore/Catalog.cpp | 2 +- crlcore/src/ccore/Histogram.cpp | 204 ++++++++++++++++++++++ crlcore/src/ccore/crlcore/Histogram.h | 126 +++++++++++++ crlcore/src/ccore/crlcore/Measures.h | 61 +++++-- crlcore/src/ccore/properties/Measures.cpp | 77 ++++++-- 7 files changed, 444 insertions(+), 30 deletions(-) create mode 100644 crlcore/src/ccore/Histogram.cpp create mode 100644 crlcore/src/ccore/crlcore/Histogram.h diff --git a/crlcore/etc/display.xml b/crlcore/etc/display.xml index 72579b15..74a315f7 100644 --- a/crlcore/etc/display.xml +++ b/crlcore/etc/display.xml @@ -171,7 +171,7 @@ - + diff --git a/crlcore/src/ccore/CMakeLists.txt b/crlcore/src/ccore/CMakeLists.txt index e494a187..e35831ac 100644 --- a/crlcore/src/ccore/CMakeLists.txt +++ b/crlcore/src/ccore/CMakeLists.txt @@ -42,6 +42,7 @@ set ( includes crlcore/Utilities.h crlcore/Memory.h crlcore/Banner.h + crlcore/Histogram.h crlcore/COptions.h crlcore/XmlParser.h crlcore/GdsDriver.h @@ -83,6 +84,7 @@ Memory.cpp Banner.cpp COptions.cpp + Histogram.cpp XmlParser.cpp GdsDriver.cpp OAParserDriver.cpp diff --git a/crlcore/src/ccore/Catalog.cpp b/crlcore/src/ccore/Catalog.cpp index 704cb9c5..b25e1ca1 100644 --- a/crlcore/src/ccore/Catalog.cpp +++ b/crlcore/src/ccore/Catalog.cpp @@ -2,7 +2,7 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved // // =================================================================== // diff --git a/crlcore/src/ccore/Histogram.cpp b/crlcore/src/ccore/Histogram.cpp new file mode 100644 index 00000000..a19c7232 --- /dev/null +++ b/crlcore/src/ccore/Histogram.cpp @@ -0,0 +1,204 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | Alliance / Hurricane Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Histogram.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#include +#include +#include +namespace bfs = boost::filesystem; + +#include "crlcore/Histogram.h" + + + +namespace CRL { + + using std::string; + using std::ostream; + using std::ofstream; + using std::ostringstream; + using std::setprecision; + using std::vector; + using Hurricane::Record; + + + Histogram::Histogram ( double range, double step, size_t nbSets ) + : _range (range) + , _step (step) + , _mainTitle () + , _titles (nbSets) + , _colors (nbSets) + , _sets (nbSets) + , _totalSamples (nbSets) + , _fileExtension() + { + size_t binSize = (size_t)rint ( _range / _step ); + for ( size_t iset=0 ; iset(binSize); + } + } + + + Histogram::~Histogram () + { } + + + void Histogram::addSample ( double sample, size_t iset ) + { + if ( iset > _sets.size() ) return; + + size_t binIndex = (size_t)rint ( sample / _step ); + if ( binIndex > _sets.front().size() ) binIndex = _sets.front().size() - 1; + + _sets [iset][binIndex] += 1.0; + _totalSamples[iset]++; + } + + + float Histogram::getYRange () const + { + float yrange = 0.0; + + for ( size_t iset=0 ; iset<_sets.size() ; ++iset ) { + for ( size_t i=0 ; i<_sets[iset].size() ; ++i ) + yrange = std::max ( yrange, _sets[iset][i] ); + } + + return ceil(yrange*10.0) / 10.0; + } + + + void Histogram::normalize ( size_t iset ) + { + if ( iset > _sets.size() ) return; + for ( size_t i=0 ; i<_sets[iset].size() ; ++i ) _sets[iset][i] /= (float)_totalSamples[iset]; + } + + + void Histogram::toStream ( ostream& o ) + { + o << setprecision(3); + + for ( size_t i=0 ; i<_sets.front().size() ; ++i ) { + for ( size_t iset=0 ; iset<_sets.size() ; ++iset ) { + o << _sets[iset][i] << " "; + } + o << "\n"; + } + } + + + void Histogram::toFile ( const string& path ) + { + ofstream fd ( path.c_str() ); + toStream ( fd ); + fd.close (); + } + + + void Histogram::toGnuplot ( const string& basename ) + { + bfs::path datFile = basename + _fileExtension + ".dat"; + toFile ( datFile.string() ); + + bfs::path pltFile = basename + _fileExtension + ".plt"; + bfs::ofstream fd ( pltFile ); + + if ( not _mainTitle.empty() ) + fd << "set title \"" << _mainTitle << "\"\n"; + + fd << "set grid\n"; + fd << "set grid noxtics\n"; + fd << "set xrange [-0.5:9.5]\n"; + fd << "set xtics ( "; + for ( size_t i=0 ; i<10 ; ++i ) { + fd << ((i) ? " ," : "") << "\"<" << ((i+1)*10) << "%%\" " << i; + } + fd << " )\n"; + + fd << "set yrange [0:" << setprecision(3) << getYRange() << "]\n"; + fd << "set ytics ( "; + for ( float i=0.0 ; i<=40.0 ; i+=10.0 ) { + fd << ((i != 0.0) ? " ," : "") << "\"" << i << "%%\" " << (i/100.0); + } + fd << " )\n"; + + fd << "set style histogram cluster gap 1\n"; + fd << "set style fill solid noborder\n"; + fd << "set boxwidth 1\n"; + + for ( size_t iset=0 ; iset<_sets.size() ; ++iset ) { + fd << ((iset) ? " " : "plot "); + fd << "\"" << datFile.string() << "\" using " << (iset+1); + + if ( not _titles[iset].empty() ) fd << " title \"" << _titles[iset] << "\""; + + fd << " with histogram"; + + if ( not _colors[iset].empty() ) fd << " linecolor rgb \"" << _colors[iset] << "\""; + + fd << ((iset+1==_sets.size()) ? "\n" : ", \\\n"); + } + + fd.close (); + } + + + string Histogram::_getString () const + { + ostringstream s; + s << ""; + return s.str(); + } + + + Record* Histogram::_getRecord () const + { + Record* record = new Record ( _getString() ); + if ( record ) { + record->add ( getSlot("_mainTitle",_mainTitle) ); + for ( size_t iset=0 ; iset<_sets.size() ; ++iset ) { + ostringstream attributeName; + attributeName << "_titles[" << iset << "]"; + record->add ( getSlot(attributeName.str(),&_titles[iset]) ); + + attributeName.str(""); + attributeName << "_colors[" << iset << "]"; + record->add ( getSlot(attributeName.str(),&_colors[iset]) ); + + attributeName.str(""); + attributeName << "_sets[" << iset << "]"; + record->add ( getSlot(attributeName.str(),&_sets[iset]) ); + } + record->add ( getSlot("_fileExtension",_fileExtension) ); + } + + return record; + } + + +} // End of CRL namespace. diff --git a/crlcore/src/ccore/crlcore/Histogram.h b/crlcore/src/ccore/crlcore/Histogram.h new file mode 100644 index 00000000..bf8e2183 --- /dev/null +++ b/crlcore/src/ccore/crlcore/Histogram.h @@ -0,0 +1,126 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | Alliance / Hurricane Interface | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Histogram.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __CRL_HISTOGRAM__ +#define __CRL_HISTOGRAM__ + +#include +#include +#include +#include "hurricane/Commons.h" +#include "crlcore/Measures.h" + + +namespace CRL { + + + class Histogram { + public: + Histogram ( double range, double step, size_t nbSets ); + ~Histogram (); + inline void setMainTitle ( const std::string& ); + inline void setTitle ( const std::string&, size_t iset ); + inline void setColor ( const std::string&, size_t iset ); + void addSample ( double, size_t iset ); + inline void setFileExtension ( const std::string& ); + float getYRange () const; + void toStream ( std::ostream& ); + void toFile ( const std::string& ); + void toGnuplot ( const std::string& basename ); + void normalize ( size_t iset ); + std::string _getString () const; + Hurricane::Record* _getRecord () const; + private: + double _range; + double _step; + std::string _mainTitle; + std::vector< std::string > _titles; + std::vector< std::string > _colors; + std::vector< std::vector > _sets; + std::vector< int > _totalSamples; + std::string _fileExtension; + }; + + +// Inline Functions. + inline void Histogram::setMainTitle ( const std::string& title ) { _mainTitle=title; } + inline void Histogram::setTitle ( const std::string& title, size_t iset ) { if (iset<_titles.size()) _titles[iset] = title; } + inline void Histogram::setColor ( const std::string& color, size_t iset ) { if (iset<_colors.size()) _colors[iset] = color; } + inline void Histogram::setFileExtension ( const std::string& extension ) { _fileExtension=extension; } + + + template<> + class Measure : public BaseMeasure { + public: + inline Measure ( const Name&, Histogram* ); + virtual ~Measure (); + virtual bool isSimpleData () const; + inline Histogram* getData () const; + inline void setData ( Histogram* ); + virtual std::string toString () const; + virtual void toGnuplot ( const std::string& basename ) const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; + private: + Histogram* _data; + }; + + + inline Measure::Measure ( const Name& name, Histogram* data ) + : BaseMeasure(name,0), _data(data) { } + + Measure::~Measure () { delete _data; } + + bool Measure::isSimpleData () const { return false; } + + inline Histogram* Measure::getData () const { return _data; } + + inline void Measure::setData ( Histogram* data ) { _data=data; } + + std::string Measure::toString () const + { return "Unsupported"; } + + void Measure::toGnuplot ( const std::string& basename ) const + { _data->toGnuplot ( basename ); } + + std::string Measure::_getString () const + { return ""; } + + Record* Measure::_getRecord () const + { + Record* record = new Record ( _getString() ); + if ( record ) { + record->add ( getSlot("_data",_data) ); + } + return record; + } + + +} // End of CRL namespace. + + +INSPECTOR_P_SUPPORT(CRL::Histogram) + +#endif // __CRL_HISTOGRAM__ diff --git a/crlcore/src/ccore/crlcore/Measures.h b/crlcore/src/ccore/crlcore/Measures.h index 7b60ac13..40148bd5 100644 --- a/crlcore/src/ccore/crlcore/Measures.h +++ b/crlcore/src/ccore/crlcore/Measures.h @@ -23,8 +23,8 @@ // x-----------------------------------------------------------------x -#ifndef __STATISTICS_PROPERTY__ -#define __STATISTICS_PROPERTY__ +#ifndef __CRL_MEASURES_PROPERTY__ +#define __CRL_MEASURES_PROPERTY__ #include #include @@ -55,9 +55,13 @@ namespace CRL { public: inline BaseMeasure ( const Name&, unsigned int width ); virtual ~BaseMeasure (); + virtual bool isSimpleData () const; inline const Name& getName () const; inline unsigned int getFieldWidth () const; virtual std::string toString () const = 0; + virtual void toGnuplot ( const std::string& basename ) const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; private: Name _name; unsigned int _fieldWidth; @@ -72,10 +76,12 @@ namespace CRL { template class Measure : public BaseMeasure { public: - inline Measure ( const Name&, const Data&, unsigned int width ); - inline const Data& getData () const; - inline void setData ( const Data& ); - virtual std::string toString () const; + inline Measure ( const Name&, const Data&, unsigned int width ); + inline const Data& getData () const; + inline void setData ( const Data& ); + virtual std::string toString () const; + virtual std::string _getString () const; + virtual Record* _getRecord () const; private: Data _data; }; @@ -85,7 +91,6 @@ namespace CRL { inline Measure::Measure ( const Name& name, const Data& data, unsigned int width ) : BaseMeasure(name,width), _data(data) { } - template inline const Data& Measure::getData () const { return _data; } @@ -96,12 +101,29 @@ namespace CRL { std::string Measure::toString () const { std::ostringstream s; s << std::fixed << std::setprecision(2) << _data; return s.str(); } + template + std::string Measure::_getString () const + { return ""; } + + template + Record* Measure::_getRecord () const + { + Record* record = new Record ( _getString() ); + if ( record ) { + record->add ( getSlot("_data",&_data) ); + } + return record; + } + class MeasuresSet : public std::map { public: ~MeasuresSet (); std::string toStringHeaders ( const std::vector& ) const; std::string toStringDatas ( const std::vector& ) const; + void toGnuplot ( Name, const std::string& ) const; + std::string _getString () const; + Record* _getRecord () const; }; @@ -112,19 +134,18 @@ namespace CRL { class MeasuresDatas { public: MeasuresDatas (); + MeasuresDatas ( const MeasuresDatas& ); inline std::string _getTypeName () const; inline std::string _getString () const; inline Record* _getRecord () const; public: MeasuresSet _measures; - private: - MeasuresDatas ( const MeasuresDatas& ); }; inline std::string MeasuresDatas::_getTypeName () const { return "MeasuresDatas"; } inline std::string MeasuresDatas::_getString () const { return ""; } - inline Record* MeasuresDatas::_getRecord () const { return NULL; } + inline Record* MeasuresDatas::_getRecord () const { return _measures._getRecord(); } // ------------------------------------------------------------------- @@ -133,9 +154,10 @@ namespace CRL { class Measures { public: - typedef StandardPrivateProperty Extension; + typedef StandardPrivateProperty Extension; public: template friend inline void addMeasure ( DBo*, const Name&, const Data&, unsigned int width=8 ); + template friend inline void addMeasure ( DBo*, const Name&, Data* ); template friend inline const Measure* getMeasure ( DBo*, const Name& ); static const MeasuresSet* get ( const DBo* ); private: @@ -147,7 +169,15 @@ namespace CRL { inline void addMeasure ( DBo* object, const Name& name, const Data& data, unsigned int width ) { Measures::Extension* extension = Measures::_getOrCreate ( object ); - extension->getValue()->_measures.insert ( std::make_pair(name,new Measure(name,data,width)) ); + extension->getValue()._measures.insert ( std::make_pair(name,new Measure(name,data,width)) ); + } + + + template + inline void addMeasure ( DBo* object, const Name& name, Data* data ) + { + Measures::Extension* extension = Measures::_getOrCreate ( object ); + extension->getValue()._measures.insert ( std::make_pair(name,new Measure(name,data)) ); } @@ -155,9 +185,9 @@ namespace CRL { inline const Measure* getMeasure ( DBo* object, const Name& name ) { Measures::Extension* extension = Measures::_getOrCreate ( object ); - MeasuresSet::iterator imeasure = extension->getValue()->_measures.find(name); + MeasuresSet::iterator imeasure = extension->getValue()._measures.find(name); - if ( imeasure != extension->getValue()->_measures.end() ) + if ( imeasure != extension->getValue()._measures.end() ) return static_cast< Measure* >( (*imeasure).second ); return NULL; @@ -167,7 +197,8 @@ namespace CRL { } // End of CRL namespace. +INSPECTOR_P_SUPPORT(CRL::BaseMeasure); INSPECTOR_P_SUPPORT(CRL::MeasuresDatas); -#endif // __STATISTICS_PROPERTY__ +#endif // __CRL_MEASURES_PROPERTY__ diff --git a/crlcore/src/ccore/properties/Measures.cpp b/crlcore/src/ccore/properties/Measures.cpp index c7832465..e9805477 100644 --- a/crlcore/src/ccore/properties/Measures.cpp +++ b/crlcore/src/ccore/properties/Measures.cpp @@ -37,6 +37,8 @@ namespace CRL { using std::string; using std::vector; using std::ostringstream; + using std::cerr; + using std::endl; using std::setw; using std::right; using Hurricane::Error; @@ -44,23 +46,24 @@ namespace CRL { // ------------------------------------------------------------------- -// Class : "CRL::MeasuresSet". +// Class : "CRL::BaseMeasure". - BaseMeasure::~BaseMeasure () {} - - - const char* MissingMeasures = "Measures::%s(): %s missing the Measures extension."; - - - template<> - Name StandardPrivateProperty::_name = "CRL::Measures"; + BaseMeasure::~BaseMeasure () {} + bool BaseMeasure::isSimpleData () const { return true; } + void BaseMeasure::toGnuplot ( const string& ) const {} + string BaseMeasure::_getString () const { return ""; } + Record* BaseMeasure::_getRecord () const { return NULL; } // ------------------------------------------------------------------- // Class : "CRL::MeasuresSet". + template<> + Name StandardPrivateProperty::_name = "CRL::Measures"; + + MeasuresSet::~MeasuresSet () { iterator imeasure = begin(); @@ -79,7 +82,8 @@ namespace CRL { if ( imeasure == end() ) continue; const BaseMeasure* measure = (*imeasure).second; - out << setw(measure->getFieldWidth()) << right << measure->getName(); + if ( measure->isSimpleData() ) + out << setw(measure->getFieldWidth()) << right << measure->getName(); } return out.str(); @@ -96,12 +100,46 @@ namespace CRL { if ( imeasure == end() ) continue; const BaseMeasure* measure = (*imeasure).second; - out << setw(measure->getFieldWidth()) << right << measure->toString(); + if ( measure->isSimpleData() ) + out << setw(measure->getFieldWidth()) << right << measure->toString(); } return out.str(); } + + void MeasuresSet::toGnuplot ( Name name, const string& basename ) const + { + const_iterator imeasure = find ( name ); + if ( imeasure == end() ) return; + + const BaseMeasure* measure = (*imeasure).second; + if ( measure->isSimpleData() ) return; + + measure->toGnuplot ( basename ); + } + + + string MeasuresSet::_getString () const + { + ostringstream s; + s << ""; + return s.str(); + } + + + Record* MeasuresSet::_getRecord () const + { + Record* record = new Record ( _getString() ); + if ( record ) { + const_iterator imeasure = begin(); + for ( ; imeasure != end() ; ++imeasure ) { + record->add ( getSlot ( getString((*imeasure).first), ((*imeasure).second) ) ); + } + } + return record; + } + // ------------------------------------------------------------------- // Class : "CRL::MeasuresDatas". @@ -112,15 +150,28 @@ namespace CRL { { } + MeasuresDatas::MeasuresDatas ( const MeasuresDatas& other ) + : _measures() + { + // if ( not other._measures.empty() ) { + // cerr << Error("MeasuresDatas copy constructor called on non-empty MeasuresDatas is forbidden.\n" + // "(source has %u elements)", other._measures.size() ) << endl; + // } + } + + // ------------------------------------------------------------------- // Class : "CRL::Measures". + const char* MissingMeasures = "Measures::%s(): %s missing the Measures extension."; + + const MeasuresSet* Measures::get ( const DBo* object ) { Extension* extension = Extension::get ( object ); if ( extension != NULL ) - return &extension->getValue()->_measures; + return &extension->getValue()._measures; return NULL; } @@ -130,7 +181,7 @@ namespace CRL { { Extension* extension = Extension::get ( object ); if ( extension == NULL ) { - extension = Extension::create ( new MeasuresDatas() ); + extension = Extension::create ( MeasuresDatas() ); object->put ( extension ); } return extension;