#ifndef __HPARTICLECUT_H__
#define __HPARTICLECUT_H__
#include "TString.h"
#include "TNamed.h"
#include "TTree.h"
#include "TTreeFormula.h"
#include "TDirectory.h"
#include "TROOT.h"
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
template <class T>
class HParticleCut : public TNamed {
private:
Int_t fCutNumber;
TString fcondition;
UInt_t fmaxCut;
TDirectory* fsaveDir;
vector<ULong64_t>fctFail;
vector<ULong64_t>fctCall;
Bool_t fbInverseCut;
T* fc;
TTree* fTree;
TTreeFormula* fselect;
public:
HParticleCut(TString name,Int_t num,TString cond);
~HParticleCut();
void setInverse(Bool_t inv) { fbInverseCut = inv;}
void setMaxCut(UInt_t max=4);
Bool_t eval(T* c,UInt_t version=0);
void print();
void resetCounter();
Float_t getCutRate(UInt_t version=0);
UInt_t getNCall(UInt_t version=0);
UInt_t getNFail(UInt_t version=0);
T* getClass() { return fc; }
TTree* getTree() { return fTree; }
TTreeFormula* getFormula() { return fselect;}
TString getCondition() { return fcondition;}
ClassDef(HParticleCut,1)
};
template <class T>
HParticleCut<T>::HParticleCut(TString name,Int_t num,TString cond)
{
fsaveDir = gDirectory;
gROOT->cd();
SetName(name);
fCutNumber = num;
fcondition = cond;
fbInverseCut = kFALSE;
fc = new T();
fTree = new TTree(Form("Tree_%s_%i",name.Data(),fCutNumber),Form("Tree_%s_%i",name.Data(),fCutNumber));
fTree->Branch(fc->ClassName(),fc->ClassName(),&fc,99);
fselect = new TTreeFormula(Form("Selection_%s_%i",name.Data(),fCutNumber),fcondition,fTree);
setMaxCut(4);
fsaveDir->cd();
}
template <class T>
HParticleCut<T>::~HParticleCut()
{
if(fselect)delete fselect;
if(fTree) delete fTree;
if(fc) delete fc;
}
template <class T>
void HParticleCut<T>::setMaxCut(UInt_t max)
{
fmaxCut = max;
if(fmaxCut == 0) fmaxCut = 1;
resetCounter();
}
template <class T>
Float_t HParticleCut<T>::getCutRate(UInt_t version)
{
return (version <fmaxCut && fctCall[version] > 0) ? (fctFail[version]/(Float_t)fctCall[version])*100.:0;
}
template <class T>
UInt_t HParticleCut<T>::getNCall(UInt_t version)
{
return (version <fmaxCut ) ? fctCall[version]:0;
}
template <class T>
UInt_t HParticleCut<T>::getNFail(UInt_t version)
{
return (version <fmaxCut ) ? fctFail[version]:0;
}
template <class T>
void HParticleCut<T>::resetCounter()
{
fctFail.clear();
fctCall.clear();
fctFail.assign(fmaxCut,0);
fctCall.assign(fmaxCut,0);
}
template <class T>
Bool_t HParticleCut<T>::eval(T* c,UInt_t version)
{
if(version<fmaxCut){
fctCall[version]++;
}
new (fc) T(*c);
if ( (!fbInverseCut && fselect->EvalInstance(0) == 0) ||
( fbInverseCut && fselect->EvalInstance(0) != 0)
)
{
if(version<fmaxCut)fctFail[version]++;
return kFALSE;
} else { return kTRUE; }
}
template <class T>
void HParticleCut<T>::print()
{
Int_t p = cout.precision();
std::ios_base::fmtflags fl =cout.flags();
cout<<"CutNumber : "<<setw(3)<<fCutNumber
<<" name : "<<setw(20)<<GetName()
<<", cut [%] : "<<flush;
for(UInt_t i = 0; i < fmaxCut ; i++){ cout<<setw(5)<<fixed<<right<<setprecision(1)<<getCutRate(i)<<" "<<flush;}
cout<<", cut = "<<fcondition <<setprecision(p)<<endl;
cout.flags(fl);
}
#endif