#ifndef _EFFVAL_HPP #define _EFFVAL_HPP #include #include namespace eff_utils { // this is a struct to save any value with errors in the specified bin in histogram // (not necessarily efficiency). For example, should be used directly by lumi reweighting struct Value { float val; float ehi; float elo; // bin number. Should no be used. Keep it for historical reasone (caf_util::Probability_nMuon use it). int binno ; Value(float v=0, float hi=0, float lo=0) : val(v), ehi(hi), elo(lo), binno(-1) {;} // reset value and efficiencies virtual void reset() {val = 0.0 ; ehi = 0; elo = 0; } // assignment Value& operator= (const Value& v) { if (this == &v) return *this ; val = v.val ; ehi = v.ehi; elo = v.elo ; return *this ; } // redefine this operator for the efficiency Value& operator += (const Value& eff) { val += eff.val ; ehi = sqrt(ehi*ehi+eff.ehi*eff.ehi) ; elo = sqrt(elo*elo+eff.elo*eff.elo) ; return *this ; } // following operators does not hace a sence for the efficiency and hence will be prohibitted Value& Scale(float sc) { val *= sc ; ehi *= sc ; elo *=sc ; return *this ; } const Value operator/ (const Value& right) const { float v = right.val == 0 ? NAN : val/right.val ; float hi = right.val == 0 ? NAN : sqrt(ehi*ehi+v*v*right.ehi*right.ehi)/fabs(right.val) ; float lo = right.val == 0 ? NAN : sqrt(elo*elo+v*v*right.elo*right.elo)/fabs(right.val) ; return Value(v,hi,lo) ; } const Value operator* (const Value& right) const { float v = val * right.val ; float hi = sqrt(right.val*ehi*right.val*ehi+ val*right.ehi*val*right.ehi) ; float lo = sqrt(right.val*elo*right.val*elo+ val*right.elo*val*right.elo) ; return Value(v,hi,lo) ; } }; // srtruct to save the efficiency value // only number of events is saved. Efficiency is calculated when needed struct EffVal : public Value { long unsigned int n, n0 ; EffVal( long unsigned int n_passed=0, long unsigned int n_ini=0) : Value(), n(n_passed), n0(n_ini) { if (n_ini > 0) recal_eff() ; } // add event, passed should be true if event passed selection or fired the trigger void Fill(bool passed=true) { n0++; if (passed) n++ ; recal_eff() ; } // set number of events and recalculated efficiency void setEfficiency(long unsigned int n_passed, long unsigned int n_ini) { n = n_passed ; n0 = n_ini ; recal_eff() ; } // Assignment from Value. Set only value number. Will invalidate the number of events EffVal& operator= (const Value& v) { n = 0 ; n0 = 0 ; val = v.val ; ehi = v.ehi; elo = v.elo; return *this ; } // recalculate efficiency (stored as Value) using n and n_ini number of events void recal_eff() { if (n0 <=0) return ; val = ((float) n) / n0 ; ehi = sqrt(val*(1.0-val)/n0) ; elo = ehi ; } void reset() { n = 0 ; n0 = 0; ((Value*)this)->reset() ; } EffVal& operator += (const EffVal& eff) { n += eff.n ; n0 += eff.n0 ; if (n0 > 0) recal_eff() ; else this->Value::operator += (eff) ; return *this ; } // scale efficiency, but reset number of events (after scaling they do not have too much sense) EffVal& Scale(float sc) { n = 0 ; n0 = 0 ; this->Value::Scale(sc) ; return *this ; } // prohibit scale operator* for the efficiency const EffVal operator*(float sc) { throw std::runtime_error("Operation * is not defined for EffVal!") ;} // prohibit scale operator/ for the efficiency const EffVal operator/(float sc) { throw std::runtime_error("Operation * is not defined for EffVal!") ;} } ; } #endif