/* * EffCollection.cpp * * Created on: 10/ago/2009 * Author: Nicola Mori */ /*! @file EffCollection.cpp The EffCollection class implementation file. */ #include "EffCollection.h" #include "TGraphAsymmErrors.h" extern "C" { /*! @brief Fortran routine by Sergio Ricciarini which computes errors on the efficiency. * * This routine has been developed to carefully evaluate the error bars on the efficiency, * which must have a value between 0 and 1. See the appendix of Sergio's PhD thesis for more * details. * The important thing is that the computed efficiency will have the unphysical value 1.1 * if there are less than 8 events in the efficiency sample (eg., the sample used to compute the * efficiency). This is necessary to have a reliable estimate of the errors. * * @param sel Pointer to an Int_t variable containing the number of events in the efficiency sample. * @param det Pointer to an Int_t variable containing the number of events in the efficiency sample * which satisfied the set of cuts for which the efficiency is being measured. * @param eff Pointer to a Double_t variable where the computed efficiency will be returned. * @param errLow Pointer to a Double_t variable where the length of the lower error bar will * be returned. * @param errHigh Pointer to a Double_t variable where the length of the upper error bar will * be returned. * @return Not clear at this point... ignore it. */ bool efficiency_(Int_t* sel, Int_t* det, Double_t* eff, Double_t* errLow, Double_t* errHigh); } EffCollection::EffCollection(const char *collectionName, TString outFileBase, int errMethod, bool owns) : VerboseCollection(collectionName, false), _selCollection("selCollection",owns), _detCollection("detCollection", owns), _outFileBase(outFileBase), _errMethod(errMethod), _det(0), _sel(0) { } void EffCollection::AddDetectorCut(PamCut *cut) { _detCollection.AddCut(cut); } void EffCollection::AddSelectionCut(PamCut *cut) { _selCollection.AddCut(cut); } void EffCollection::AddDetectorAction(CollectionAction *action) { _detCollection.AddAction(action); } void EffCollection::AddSelectionAction(CollectionAction *action) { _selCollection.AddAction(action); } void EffCollection::Setup(PamLevel2 *events){ // Base class have a single vector for cuts and another for actions. Here the cuts and actions // are not contained inside these vectors but rather inside two SmartCollection object members. // So we must call their Setup(). _selCollection.Setup(events); _detCollection.Setup(events); // We call also base class' Setup(), which will likely do nothing since _sel and _det are empty. VerboseCollection::Setup(events); } int EffCollection::ApplyCut(PamLevel2 *event) { _nEv++; if (_selCollection.ApplyCut(event) == CUTOK) { _sel++; if (_detCollection.ApplyCut(event) == CUTOK) { _det++; _nGood++; return CUTOK; } } return 0; } void EffCollection::Finalize() { // Let's add all the cuts to the vector of the collection before calling VerboseCollection::Finalize for (unsigned int i = 0; i < _selCollection.GetSize(); i++) _cuts.push_back(_selCollection.GetCut(i)); for (unsigned int i = 0; i < _selCollection.GetActionsSize(); i++){ _actions.push_back(_selCollection.GetAction(i)); _actionsPositions.push_back(_selCollection.GetActionPosition(i)); } for (unsigned int i = 0; i < _detCollection.GetSize(); i++) _cuts.push_back(_detCollection.GetCut(i)); for (unsigned int i = 0; i < _detCollection.GetActionsSize(); i++){ _actions.push_back(_detCollection.GetAction(i)); _actionsPositions.push_back(_detCollection.GetActionPosition(i) + _selCollection.GetSize()); } // Now all the cuts and actions are in place, and VerboseCollection can print its report and call Finalize() for // every cut and action (calling SmartCollection::Finalize(). VerboseCollection::Finalize(); // Compute the error Int_t sel = (Int_t) _sel; Int_t det = (Int_t) _det; Double_t eff, errLow, errHigh; if (_errMethod == EFFERR_ROOT) { if (sel < 8) { eff = 1.1; errLow = errHigh = 0.; } else { TH1I pass("pass", "pass", 1, 0., 1.); TH1I total("total", "total", 1, 0., 1.); pass.Fill(0.5, det); total.Fill(0.5, sel); TGraphAsymmErrors errGraph; errGraph.BayesDivide(&pass, &total); Double_t dummy; errGraph.GetPoint(0, dummy, eff); errLow = errGraph.GetErrorYlow(0); errHigh = errGraph.GetErrorYhigh(0); } } if (_errMethod == EFFERR_SERGIO) { efficiency_(&sel, &det, &eff, &errLow, &errHigh); } // Add some info about efficiency to the stdout cout << " ****** Efficiency informations ******\n"; cout << " Detector cuts:\n"; for (unsigned int i = 0; i < _detCollection.GetSize(); i++) cout << " - " << _detCollection.GetCut(i)->GetName() << "\n"; cout << " Total detector efficiency: " << eff << " +" << errHigh << "-" << errLow << endl; // Write the output file if (_outFileBase != "") { ofstream outTextFile((_outFileBase + "-" + GetName() + ".txt").Data(), ios_base::out); streamsize newPrec = 4; outTextFile.precision(newPrec); outTextFile.setf(ios::fixed, ios::floatfield); outTextFile << setw(10) << det << setw(10) << sel << setw(10) << eff << setw(10) << errLow << setw(10) << errHigh << endl; outTextFile.close(); } }