// ---------------------------------------------------------------------- // // HepHistProf.cc - implementation of generic profile histogram // // HepHistProf is a generic profile histogram. It is derived from // HepHist, and its final implementation is defined by a manager class/ // histogram subclass. HepHistProf provides methods for filling a // histogram and retreiving information from and about it. // // HepHistProf objects are not directly instantiated. Instead, the manager // creates the object using its own implementation of the histogram. // // Typical usage: // // HepFileManager* m = new [define the manager]; // : // : // HepHistProf & h(m->histProf("Title", 100, 0.0, 2.0, 0.0, 2.0)); // float x, y, weight; // : // [gather data] // : // h->accumulate(x, y, weight); // // // Note that the constructor can take an ID number which is used by // some implementations of HepHistProf. If omitted, the ID number is // generated automatically (which is recommended). The ID number is // available through the id() method. // // Most of the methods in HepHistProf do nothing more than generate an // error when called. It is up to the manager-specific derived class to // implement the appropriate ones. // // // History: // ??-???-19?? Bob Jacobsen Initial draft, based on ideas in HepTuple // and the SLT histogram classes of Joe Boudreau // 05-May-1997 Walter Brown Initial design & draft of Hist class // 22-May-1997 Walter Brown Merged Hist into HepHistogram // 30-May-1997 Walter Brown Added cloning functions // 29-May-1992 Jason Luther Added comments // 30-Jul-1998 Philippe Canal Added typeId // 04-Aug-1998 Philippe Canal Added weight, entries, sum, etc.. // 25-Feb-1999 J. Marraffino Added increment operators for histograms // // ---------------------------------------------------------------------- #ifndef HEPTRACE_H #include "HepTuple/HepTrace.h" #endif #ifndef HEPFILEMANAGER_H #include "HepTuple/HepFileManager.h" #endif #ifndef HEPHISTPROF_H #include "HepTuple/HepHistProf.h" #endif #ifndef HEPRAWHIST_H #include "HepTuple/HepRawHist.h" #endif #include "ZMutility/iostream" #include USING( std::string ) ZM_BEGIN_NAMESPACE( zmht ) /* namespace zmht { */ // type identifier ( is equal to type() for this object ) const char HepHistProf::typeId = 'P'; #define BADCALL(fctnName) \ ZMthrow( \ ZMxHepUnsupported(" your profile histogram class does not support the " \ #fctnName " call.")); // create a profile histogram with the given title and binning HepHistProf::HepHistProf( HepFileManager * const manager , const string& title , const int nBinsX, const float lowX, const float highX , const float lowY, const float highY , const string& chopt , const int id_req ) : HepHist( manager, title, id_req ) , _nBinsX( nBinsX ) , _minX ( lowX ) , _maxX ( highX ) , _minY ( lowY ) , _maxY ( highY ) { HEP_DEBUG( "HepHistProf::constructor( \"" << title << "\", " << id_ << " )" ); type_ = 'P'; } HepHistProf::HepHistProf( HepFileManager * const manager, const string& title, const int nBinsX, const float lowX, const float highX, const float lowY, const float highY, const int id_req ) : HepHist( manager, title, id_req ) , _nBinsX( nBinsX ) , _minX ( lowX ) , _maxX ( highX ) , _minY ( lowY ) , _maxY ( highY ) { HEP_DEBUG( "HepHistProf::constructor( \"" << title << "\", " << id_ ); type_ = 'P'; } // Used for dummy construction ... // the object is then not valid ... HepHistProf::HepHistProf() : HepHist() , _nBinsX(0 ) , _minX (0 ) , _maxX (0 ) , _minY (0 ) , _maxY (0 ) { HEP_DEBUG( "HepHistProf::constructor( )" ); type_ = 'P'; } HepHistProf::~HepHistProf() { HEP_DEBUG( "HepHistProf::destructor( \"" << *title_ << "\", " << id_ ); } void HepHistProf::accumulate( float x, float y, float weight ) { BADCALL(accumulate(xValue,yValue,weight)); } void HepHistProf::_accumulate( float x, float y, float weight ) { if ( manager()->isReadOnly() ) { ZMthrow(ZMxHepCantWriteFile( manager()->fileName() + " is read only. Can not fill histogram." )); } else { isDirty( true ); } } float HepHistProf::binError( const int binNum ) const { BADCALL(binError(binNum)); return 0.0; } void HepHistProf::getSumW( float * data ) const { BADCALL(getSumW(data)); } void HepHistProf::getSumWY( float * data ) const { BADCALL(getSumWY(data)); } void HepHistProf::getSumWY2( float * data ) const { BADCALL(getSumWY2(data)); } void HepHistProf::getStatistics( int & NumEntries , float & sumW , float & sumW2 , double & sumWX , double & sumWX2 ) const { BADCALL(getStatistics(arglist)); } void HepHistProf::getOverflows( float * numOver , float * numUnder ) const { BADCALL(getOverflows(numOver,numUnder)); } void HepHistProf::setXTitle( const std::string& label ) { BADCALL(setXTitle(label)); } void HepHistProf::setYTitle( const std::string& label ) { BADCALL(setYTitle(label)); } void HepHistProf::setZTitle( const std::string& label ) { BADCALL(setZTitle(label)); } HepRawHist HepHistProf::importHistProf( const HepHistProf & h ) { BADCALL(importHistProf(HepHistProf & h)); int nullid = 0; HepRawHist dummy = HepRawHist( nullid ); return dummy; } void HepHistProf::addHistProf( const HepRawHist & h ) { BADCALL(addHistProf(HepRawHist & h)); } void HepHistProf::subtractHistProf( const HepRawHist & h ) { BADCALL(subtractHistProf(HepRawHist & h)); } void HepHistProf::multiplyHistProf( const HepRawHist & h ) { BADCALL(multiplyHistProf(HepRawHist & h)); } void HepHistProf::divideHistProf( const HepRawHist & h ) { BADCALL(multiplystProf(HepRawHist & h)); } void HepHistProf::removeImportedHistProf( const HepRawHist & h ) { BADCALL(removeImportedHistProf(HepRawHist & h)); } void HepHistProf::reset() { BADCALL(reset); } float HepHistProf::bin( const int binNum ) const { BADCALL(bin(binNumX)); return 0.0; } int HepHistProf::nBinsX() const { // retrieve # of in-range X bins return _nBinsX; } float HepHistProf::minX() const { // retrieve low end of binned X range return _minX; } float HepHistProf::minY() const { // retrieve high end of binned X range return _minY; } float HepHistProf::maxX() const { // retrieve low end of binned X range return _maxX; } float HepHistProf::maxY() const { // retrieve high end of binned X range return _maxY; } int HepHistProf::entries() const { // number of entries BADCALL(entries); return 0; } int HepHistProf::entries( const int binNumX) const { // number of entries in X-bin BADCALL(entries); return 0; } float HepHistProf::weight() const { // sum of all weight BADCALL(weight); return 0; } float HepHistProf::weight2() const { // sum of all weight BADCALL(weight2); return 0; } float HepHistProf::weight( const int binNumX) const { // sum of all weight in X-bin BADCALL(weight); return 0; } float HepHistProf::sumX() const { // retrieve weighted sum of X BADCALL(sumX); return 0; } float HepHistProf::sumY() const { // retrieve weighted sum of Y BADCALL(sumY); return 0; } float HepHistProf::sumX2() const { // retrieve weighted sum of X^2 BADCALL(sumX2); return 0; } float HepHistProf::sumY2() const { // retrieve weighted sum of Y^2 BADCALL(sumY2); return 0; } float HepHistProf::sumY( const int binNumX) const { // retrieve sum of Y in X-bin BADCALL(sumY); return 0; } float HepHistProf::sumY2( const int binNumX) const{ // retrieve sum of Y^2 in X-bin BADCALL(sumY2); return 0; } ZM_COVARIANT_TYPE(HepObj,HepHistProf) & HepHistProf::makeClone( // clone existing histogram, filling bins HepFileManager * manager , const string& title , const int id ) const { if ( ! mayUse() ) { ZMthrow(ZMxHepUnmanagedItem( string("attempt to makeClone() to unmanaged histogram ") +title+string("."))); return manager->deadHistProf(); } // Static cast for platform without covariant return type for virtual member function HepHistProf & clone = static_cast ( makeEmpty( manager, title, id ) ); clone += *this; return clone; } ZM_COVARIANT_TYPE(HepObj,HepHistProf) & HepHistProf::makeEmpty( // clone existing histogram, but zero bins HepFileManager * mgr , const string& title , const int id ) const { if ( ! mayUse() ) { ZMthrow(ZMxHepUnmanagedItem( string("attempt to makeEmpty() to unmanaged histogram ") +title+string("."))); return mgr->deadHistProf(); } return mgr->histProf( title, nBinsX(), minX(), maxX(), minY(), maxY(), " ", id ); } ZM_COVARIANT_TYPE(HepObj,HepHistProf) & HepHistProf::makeClone( // clone existing histogram, filling bins const string& title , const int id ) const { return makeClone( manager(), title, id ); } ZM_COVARIANT_TYPE(HepObj,HepHistProf) & HepHistProf::makeEmpty( // clone existing histogram, but zero bins const string& title , const int id ) const { return makeEmpty( manager(), title, id ); } bool HepHistProf::compatibleHistProf ( const HepHistProf & h ) { // First check that the two histogram objects are accessible. float maxDiff = 1.0e-6f; if( !mayUse() || !h.mayUse() ) { ZMthrow(ZMxHepUnmanagedItem( string("attempt to manipulate one or more unmanaged histograms."))); return false; } // And Check that the this histogram can be modified if ( manager()->isReadOnly() ) { ZMthrow(ZMxHepCantWriteFile( manager()->fileName() + " is read only. Can not modify the " + title() + " histogram." )); return false; } // Check that the two histogram objects are compatible -- this means // they have the same number of bins and span the same range. int numBins1 = nBinsX(); // Number of in-range bins in *this int numBins2 = h.nBinsX(); // Number of in-range bins in h if( numBins1 != numBins2 ) { ZMthrow(ZMxHepIncompatible( string("Histograms do not have the same number of bins."))); return false; } float minX1 = minX(); // Low end of range for *this float maxX1 = maxX(); // High end of range for *this float minX2 = h.minX(); // Low end of range for h float maxX2 = h.maxX(); // High end of range for h float deltaXLow = minX2 - minX1; float deltaXHigh = maxX2 - maxX1; // Make this work for both Kai and gcc. That means don't use abs()! float absDeltaXLow = ( deltaXLow > 0.0 ? deltaXLow : -deltaXLow ); float absDeltaXHigh = ( deltaXHigh > 0.0 ? deltaXHigh : -deltaXHigh ); if(( absDeltaXLow > maxDiff ) || ( absDeltaXHigh > maxDiff )) { ZMthrow(ZMxHepIncompatible( string("Histograms do not have the same range."))); return false; } return true; } HepHistProf & HepHistProf::operator += ( const HepHistProf & h ) { // Check that the two histogram objects are compatible. if( !compatibleHistProf( h ) ) return *this; // Check that there are some entries already int numEntries = h.entries(); // Number of entries in h // If h is empty, we're done already if( numEntries == 0 ) return *this; // Otherwise, set up to combine histograms. First convert h to the //inplementation of *this. // The manager-dependent method instantiates an unmanaged histogram object // of the right type via a call to HepHistProf and then fills it so that it is // equivalent to h but in the implementation of *this HepRawHist temp = importHistProf( h ); if( temp.isValid() ) { // Now the thing identified by temp and *this are in the same implementation. // Pass them to another manager-dependent method that uses the methods within // that implementation to combine them according to it's rules. addHistProf( temp ); isDirty( true ); // Still need to go to the appropriate descendant method to delete // the RawHist object. It's still lying around. removeImportedHistProf( temp ); } return *this; } HepHistProf & HepHistProf::operator -= ( const HepHistProf & h ) { // Check that the two histogram objects are compatible. if( !compatibleHistProf( h ) ) return *this; // Check that there are some entries already int numEntries = h.entries(); // Number of entries in h // If h is empty, we're done already if( numEntries == 0 ) return *this; // Otherwise, set up to combine histograms. First convert h to the //inplementation of *this. // The manager-dependent method instantiates an unmanaged histogram object // of the right type via a call to HepHistProf and then fills it so that it is // equivalent to h but in the implementation of *this HepRawHist temp = importHistProf( h ); if( temp.isValid() ) { // Now the thing identified by temp and *this are in the same implementation. // Pass them to another manager-dependent method that uses the methods within // that implementation to combine them according to it's rules. subtractHistProf( temp ); isDirty( true ); // Still need to go to the appropriate descendant method to delete // the RawHist object. It's still lying around. removeImportedHistProf( temp ); } return *this; } HepHistProf & HepHistProf::operator *= ( const HepHistProf & h ) { // Check that the two histogram objects are compatible. if( !compatibleHistProf( h ) ) return *this; // Check that there are some entries already int numEntries = h.entries(); // Number of entries in h // If h is empty, we're done already if( numEntries == 0 ) return *this; // Otherwise, set up to combine histograms. First convert h to the //inplementation of *this. // The manager-dependent method instantiates an unmanaged histogram object // of the right type via a call to HepHistProf and then fills it so that it is // equivalent to h but in the implementation of *this HepRawHist temp = importHistProf( h ); if( temp.isValid() ) { // Now the thing identified by temp and *this are in the same implementation. // Pass them to another manager-dependent method that uses the methods within // that implementation to combine them according to it's rules. multiplyHistProf( temp ); isDirty( true ); // Still need to go to the appropriate descendant method to delete // the RawHist object. It's still lying around. removeImportedHistProf( temp ); } return *this; } HepHistProf & HepHistProf::operator /= ( const HepHistProf & h ) { // Check that the two histogram objects are compatible. if( !compatibleHistProf( h ) ) return *this; // Check that there are some entries already int numEntries = h.entries(); // Number of entries in h // If h is empty, we're done already if( numEntries == 0 ) return *this; // Otherwise, set up to combine histograms. First convert h to the //inplementation of *this. // The manager-dependent method instantiates an unmanaged histogram object // of the right type via a call to HepHistProf and then fills it so that it is // equivalent to h but in the implementation of *this HepRawHist temp = importHistProf( h ); if( temp.isValid() ) { // Now the thing identified by temp and *this are in the same implementation. // Pass them to another manager-dependent method that uses the methods within // that implementation to combine them according to it's rules. divideHistProf( temp ); isDirty( true ); // Still need to go to the appropriate descendant method to delete // the RawHist object. It's still lying around. removeImportedHistProf( temp ); } return *this; } ZM_END_NAMESPACE( zmht ) /* } // namespace zmht */