Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-19 23:20:31

0001 //  .
0002 // ..: P. Chang, philip@physics.ucsd.edu
0003 
0004 #ifndef looper_cc
0005 #define looper_cc
0006 
0007 // C/C++
0008 #include <unistd.h>
0009 #include <algorithm>
0010 #include <fstream>
0011 #include <iostream>
0012 #include <map>
0013 #include <string>
0014 #include <unordered_map>
0015 #include <vector>
0016 #include <stdarg.h>
0017 #include <functional>
0018 #include <cmath>
0019 
0020 // ROOT
0021 #include "TBenchmark.h"
0022 #include "TBits.h"
0023 #include "TChain.h"
0024 #include "TFile.h"
0025 #include "TTree.h"
0026 #include "TBranch.h"
0027 #include "TLeaf.h"
0028 #include "TH1.h"
0029 #include "TH1D.h"
0030 #include "TH2D.h"
0031 #include "TChainElement.h"
0032 #include "TTreeCache.h"
0033 #include "TTreePerfStats.h"
0034 #include "TStopwatch.h"
0035 #include "TSystem.h"
0036 #include "TString.h"
0037 #include "TLorentzVector.h"
0038 #include "Math/LorentzVector.h"
0039 
0040 #include "printutil.h"
0041 #include "eventindexmap.h"
0042 
0043 //#include "cpptqdm/tqdm.h"
0044 
0045 namespace RooUtil {
0046 
0047   ///////////////////////////////////////////////////////////////////////////////////////////////
0048   // Looper class
0049   ///////////////////////////////////////////////////////////////////////////////////////////////
0050   // NOTE: This class assumes accessing TTree in the SNT style which uses the following,
0051   // https://github.com/cmstas/Software/blob/master/makeCMS3ClassFiles/makeCMS3ClassFiles.C
0052   // It is assumed that the "template" class passed to this class will have
0053   // 1. "Init(TTree*)"
0054   // 2. "GetEntry(uint)"
0055   // 3. "progress(nevtProc'ed, total)"
0056   template <class TREECLASS>
0057   class Looper {
0058     // Members
0059     TChain* tchain;
0060     TBenchmark* bmark;
0061     TObjArray* listOfFiles;
0062     TObjArrayIter* fileIter;
0063     TFile* tfile;
0064     TTree* ttree;
0065     TTreePerfStats* ps;
0066     unsigned int nEventsTotalInChain;
0067     unsigned int nEventsTotalInTree;
0068     int nEventsToProcess;
0069     unsigned int nEventsProcessed;
0070     unsigned int indexOfEventInTTree;
0071     bool fastmode;
0072     TREECLASS* treeclass;
0073     TStopwatch my_timer;
0074     int bar_id;
0075     int print_rate;
0076     bool doskim;
0077     TString skimfilename;
0078     TFile* skimfile;
0079     TTree* skimtree;
0080     unsigned int nEventsSkimmed;
0081     std::vector<TString> skimbrfiltpttn;
0082     bool silent;
0083     bool isinit;
0084     bool use_treeclass_progress;
0085     bool isnewfileopened;
0086     //        bool use_tqdm_progress_bar;
0087     unsigned int nskipped_batch;
0088     unsigned int nskipped;
0089     unsigned int nbatch_skip_threshold;
0090     unsigned int nbatch_to_skip;
0091     unsigned int nskipped_threshold;
0092     unsigned int ncounter;
0093     //        tqdm bar;
0094     EventIndexMap eventindexmap;
0095     TEventList* teventlist;
0096 
0097   public:
0098     // Functions
0099     Looper();
0100     Looper(TChain* chain, TREECLASS* treeclass, int nEventsToProcess = -1);
0101     ~Looper();
0102     void init(TChain* chain, TREECLASS* treeclass, int nEventsToProcess);
0103     void setTChain(TChain* c);
0104     void setTreeClass(TREECLASS* t);
0105     void printCurrentEventIndex();
0106     void setSilent(bool s = true) { silent = s; }
0107     void setEventIndexMap(TString file) { eventindexmap.load(file); }
0108     bool allEventsInTreeProcessed();
0109     bool allEventsInChainProcessed();
0110     bool nextEvent();
0111     bool isNewFileInChain();
0112     TTree* getTree() { return ttree; }
0113     TChain* getTChain() { return tchain; }
0114     unsigned int getNEventsProcessed() { return nEventsProcessed; }
0115     void setSkim(TString ofilename);
0116     void setSkimBranchFilterPattern(std::vector<TString> x) { skimbrfiltpttn = x; }
0117     void fillSkim();
0118     void saveSkim();
0119     TTree* getSkimTree() { return skimtree; }
0120     void setSkimMaxSize(Long64_t maxsize) { skimtree->SetMaxTreeSize(maxsize); }
0121     TTreePerfStats* getTTreePerfStats() { return ps; }
0122     unsigned int getCurrentEventIndex() { return indexOfEventInTTree - 1; }
0123     TFile* getCurrentFile() { return tfile; }
0124     TString getCurrentFileBaseName() { return gSystem->BaseName(tfile->GetName()); }
0125     TString getCurrentFileName() { return TString(tfile->GetName()); }
0126     TString getListOfFileNames();
0127     TString getCurrentFileTitle() { return TString(tfile->GetTitle()); }
0128     unsigned int getNEventsTotalInChain() { return nEventsTotalInChain; }
0129     void setNbatchToSkip(unsigned int n) { nbatch_to_skip = n; }
0130     void setNbadEventThreshold(unsigned int n) { nskipped_threshold = n; }
0131     void setNbadEventThresholdToTriggerBatchSkip(unsigned int n) { nbatch_skip_threshold = n; }
0132     bool handleBadEvent();
0133     void printStatus();
0134     void printSkippedBadEventStatus();
0135     void setFastMode(bool f = true) { fastmode = f; }
0136     void addCount() { ncounter++; }
0137     void resetCounter() { ncounter = 0; }
0138     bool doesBranchExist(TString bname);
0139     TString getSkimFileName() { return skimfilename; }
0140     TFile* getSkimFile() { return skimfile; }
0141 
0142   private:
0143     void setFileList();
0144     void setNEventsToProcess();
0145     bool nextTree();
0146     bool nextEventInTree();
0147     void initProgressBar();
0148     void printProgressBar(bool force = false);
0149     void createSkimTree();
0150     void copyAddressesToSkimTree();
0151   };
0152 
0153 }  // namespace RooUtil
0154 
0155 ///////////////////////////////////////////////////////////////////////////////////////////////////
0156 //
0157 //
0158 // Event Looper (Looper) class template implementation
0159 //
0160 //
0161 ///////////////////////////////////////////////////////////////////////////////////////////////////
0162 
0163 // It's easier to put the implementation in the header file to avoid compilation issues.
0164 
0165 //_________________________________________________________________________________________________
0166 template <class TREECLASS>
0167 RooUtil::Looper<TREECLASS>::Looper()
0168     : tchain(0),
0169       listOfFiles(0),
0170       fileIter(0),
0171       tfile(0),
0172       ttree(0),
0173       ps(0),
0174       nEventsTotalInChain(0),
0175       nEventsTotalInTree(0),
0176       nEventsToProcess(-1),
0177       nEventsProcessed(0),
0178       indexOfEventInTTree(0),
0179       fastmode(true),
0180       treeclass(0),
0181       bar_id(0),
0182       print_rate(432),
0183       doskim(false),
0184       skimfilename(""),
0185       skimfile(0),
0186       skimtree(0),
0187       nEventsSkimmed(0),
0188       silent(false),
0189       isinit(false),
0190       use_treeclass_progress(false),
0191       //    use_tqdm_progress_bar( isatty(1) ),
0192       nskipped_batch(0),
0193       nskipped(0),
0194       nbatch_skip_threshold(500),
0195       nbatch_to_skip(5000),
0196       nskipped_threshold(100000),
0197       ncounter(0),
0198       teventlist(0) {
0199   bmark = new TBenchmark();
0200   //    bar.disable_colors();
0201 }
0202 
0203 //_________________________________________________________________________________________________
0204 template <class TREECLASS>
0205 RooUtil::Looper<TREECLASS>::Looper(TChain* c, TREECLASS* t, int nevtToProc)
0206     : tchain(0),
0207       listOfFiles(0),
0208       fileIter(0),
0209       tfile(0),
0210       ttree(0),
0211       ps(0),
0212       nEventsTotalInChain(0),
0213       nEventsTotalInTree(0),
0214       nEventsToProcess(nevtToProc),
0215       nEventsProcessed(0),
0216       indexOfEventInTTree(0),
0217       fastmode(true),
0218       treeclass(0),
0219       bar_id(0),
0220       print_rate(432),
0221       doskim(false),
0222       skimfilename(""),
0223       skimfile(0),
0224       skimtree(0),
0225       nEventsSkimmed(0),
0226       silent(false),
0227       isinit(false),
0228       use_treeclass_progress(false),
0229       //    use_tqdm_progress_bar( isatty(1) ),
0230       nskipped_batch(0),
0231       nskipped(0),
0232       nbatch_skip_threshold(500),
0233       nbatch_to_skip(5000),
0234       nskipped_threshold(100000),
0235       ncounter(0),
0236       teventlist(0) {
0237   bmark = new TBenchmark();
0238   if (c && t)
0239     init(c, t, nevtToProc);
0240   //    bar.disable_colors();
0241 }
0242 
0243 //_________________________________________________________________________________________________
0244 template <class TREECLASS>
0245 void RooUtil::Looper<TREECLASS>::init(TChain* c, TREECLASS* t, int nevtToProc) {
0246   listOfFiles = 0;
0247   if (fileIter)
0248     delete fileIter;
0249   fileIter = 0;
0250   tfile = 0;
0251   ttree = 0;
0252   ps = 0;
0253   nEventsTotalInChain = 0;
0254   nEventsTotalInTree = 0;
0255   nEventsToProcess = nevtToProc;
0256   nEventsProcessed = 0;
0257   indexOfEventInTTree = 0;
0258   fastmode = true;
0259   treeclass = 0;
0260   bar_id = 0;
0261   print_rate = 432;
0262   doskim = false;
0263   skimfilename = "";
0264   skimfile = 0;
0265   skimtree = 0;
0266   nEventsSkimmed = 0;
0267   silent = false;
0268   isinit = false;
0269   use_treeclass_progress = false;
0270   //    use_tqdm_progress_bar( isatty(1) ),
0271   nskipped_batch = 0;
0272   nskipped = 0;
0273   nbatch_skip_threshold = 500;
0274   nbatch_to_skip = 5000;
0275   nskipped_threshold = 100000;
0276   ncounter = 0;
0277   teventlist = 0;
0278 
0279   if (isinit)
0280     error(
0281         "The Looper is already initialized! Are you calling Looper::init(TChain* c, TREECLASS* t, int nevtToProcess) "
0282         "for the second time?",
0283         __FUNCTION__);
0284 
0285   initProgressBar();
0286   print("Start EventLooping");
0287   start();
0288 
0289   nEventsToProcess = nevtToProc;
0290 
0291   if (c)
0292     setTChain(c);
0293 
0294   if (t)
0295     setTreeClass(t);
0296 
0297   if (nEventsToProcess > 5000 || nEventsToProcess == -1)
0298     fastmode = true;
0299 
0300   c->GetEntry(0);
0301 
0302   // Check tree exists
0303   if (not c->GetTree()) {
0304     throw std::ios_base::failure("Failed to get TTree from input ntuple");
0305   }
0306 
0307   t->Init(c->GetTree());
0308 
0309   bmark->Start("benchmark");
0310   isinit = true;
0311 }
0312 
0313 //_________________________________________________________________________________________________
0314 template <class TREECLASS>
0315 RooUtil::Looper<TREECLASS>::~Looper() {
0316   if (isinit) {
0317     end();
0318 
0319     // return
0320     using namespace std;
0321     bmark->Stop("benchmark");
0322     cout << endl;
0323     cout << "------------------------------" << endl;
0324     cout << "CPU  Time: " << Form("%.01f", bmark->GetCpuTime("benchmark")) << endl;
0325     cout << "Real Time: " << Form("%.01f", bmark->GetRealTime("benchmark")) << endl;
0326     cout << endl;
0327     // delete bmark;
0328 
0329     //        if ( fileIter )
0330     //            delete fileIter;
0331     //
0332     //        if ( tfile )
0333     //            delete tfile;
0334   }
0335 }
0336 
0337 //_________________________________________________________________________________________________
0338 template <class TREECLASS>
0339 void RooUtil::Looper<TREECLASS>::setTChain(TChain* c) {
0340   if (c) {
0341     tchain = c;
0342     setNEventsToProcess();
0343     setFileList();
0344   } else
0345     error("You provided a null TChain pointer!", __FUNCTION__);
0346 }
0347 
0348 //_________________________________________________________________________________________________
0349 template <class TREECLASS>
0350 void RooUtil::Looper<TREECLASS>::setTreeClass(TREECLASS* t) {
0351   if (t)
0352     treeclass = t;
0353   else
0354     error("You provided a null TreeClass pointer!", __FUNCTION__);
0355 }
0356 
0357 //_________________________________________________________________________________________________
0358 template <class TREECLASS>
0359 void RooUtil::Looper<TREECLASS>::printCurrentEventIndex() {
0360   RooUtil::print(TString::Format("Current TFile = %s", tfile->GetName()));
0361   RooUtil::print(TString::Format("Current TTree = %s", ttree->GetName()));
0362   RooUtil::print(TString::Format("Current Entry # in TTree = %d", indexOfEventInTTree));
0363 }
0364 
0365 //_________________________________________________________________________________________________
0366 template <class TREECLASS>
0367 bool RooUtil::Looper<TREECLASS>::nextTree() {
0368   if (!fileIter)
0369     error("fileIter not set but you are trying to access the next file", __FUNCTION__);
0370 
0371   // Get the TChainElement from TObjArrayIter.
0372   // If no more to run over, Next returns 0.
0373   TChainElement* chainelement = (TChainElement*)fileIter->Next();
0374 
0375   if (chainelement) {
0376     // If doskim is true and if this is the very first file being opened in the TChain,
0377     // flag it to create a tfile and ttree where the skimmed events will go to.
0378     bool createskimtree = false;
0379 
0380     if (!ttree && doskim)
0381       createskimtree = true;
0382 
0383     // // If there is already a TFile opened from previous iteration, close it.
0384     // if ( tfile )
0385     //     tfile->Close();
0386 
0387     // Open up a new file
0388     tfile = TFile::Open(chainelement->GetTitle());
0389     // Get the ttree
0390     ttree = (TTree*)tfile->Get(tchain->GetName());
0391 
0392     // If an eventindexmap has a key for this file then set the TEventList for this TTree
0393     // std::cout <<  " chainelement->GetTitle(): " << chainelement->GetTitle() <<  std::endl;
0394     // std::cout <<  " eventindexmap.hasEventList(chainelement->GetTitle()): " << eventindexmap.hasEventList(chainelement->GetTitle()) <<  std::endl;
0395     if (eventindexmap.hasEventList(chainelement->GetTitle())) {
0396       // std::cout << chainelement->GetTitle() << std::endl;
0397       teventlist = eventindexmap.getEventList(chainelement->GetTitle());
0398       ttree->SetEventList(teventlist);
0399     } else {
0400       teventlist = 0;
0401     }
0402 
0403     if (!ttree)
0404       error("TTree is null!??", __FUNCTION__);
0405 
0406     // Set some fast mode stuff
0407     if (fastmode) {
0408       TTreeCache::SetLearnEntries(1000);
0409       print("TTreeCache enabled");
0410     }
0411 
0412     if (fastmode)
0413       ttree->SetCacheSize(128 * 1024 * 1024);
0414     else
0415       ttree->SetCacheSize(-1);
0416 
0417     // Print some info to stdout
0418     print("Looping " + TString(tfile->GetName()) + "/TTree:" + TString(ttree->GetName()));
0419     //        printProgressBar(true);
0420     // Reset the nEventsTotalInTree in this tree
0421     nEventsTotalInTree = ttree->GetEntries();
0422     // Reset the event index as we got a new ttree
0423     indexOfEventInTTree = 0;
0424     // Set the ttree to the TREECLASS
0425     treeclass->Init(ttree);
0426 
0427     // If skimming create the skim tree after the treeclass inits it.
0428     // This is to make sure the branch addresses are correct.
0429     if (createskimtree)
0430       createSkimTree();
0431     else if (doskim)
0432       copyAddressesToSkimTree();
0433 
0434     //        // TTreePerfStats
0435     //        if ( ps )
0436     //            ps->SaveAs( "perf.root" );
0437     //
0438     //        ps = new TTreePerfStats( "ioperf", ttree );
0439     // Return that I got a good one
0440     return true;
0441   } else {
0442     // Announce that we are done with this chain
0443     //        print("");
0444     //        print("Done with all trees in this chain", __FUNCTION__);
0445     return false;
0446   }
0447 }
0448 
0449 //_________________________________________________________________________________________________
0450 template <class TREECLASS>
0451 bool RooUtil::Looper<TREECLASS>::allEventsInTreeProcessed() {
0452   if (teventlist) {
0453     if (indexOfEventInTTree >= (unsigned int)teventlist->GetN()) {
0454       unsigned int curindex =
0455           teventlist->GetEntry(indexOfEventInTTree - 1);  // since I just increased by one a few lines before
0456       unsigned int previndex = indexOfEventInTTree >= 2 ? teventlist->GetEntry(indexOfEventInTTree - 2) : 0;
0457       nEventsToProcess += (curindex - previndex);
0458       return true;
0459     } else {
0460       return false;
0461     }
0462   } else {
0463     if (indexOfEventInTTree >= nEventsTotalInTree)
0464       return true;
0465     else
0466       return false;
0467   }
0468 }
0469 
0470 //_________________________________________________________________________________________________
0471 template <class TREECLASS>
0472 bool RooUtil::Looper<TREECLASS>::allEventsInChainProcessed() {
0473   if (nEventsProcessed >= (unsigned int)nEventsToProcess)
0474     return true;
0475   else
0476     return false;
0477 }
0478 
0479 //_________________________________________________________________________________________________
0480 template <class TREECLASS>
0481 bool RooUtil::Looper<TREECLASS>::nextEventInTree() {
0482   //    treeclass->progress(nEventsProcessed, nEventsToProcess);
0483   // Sanity check before loading the next event.
0484   if (!ttree)
0485     error("current ttree not set!", __FUNCTION__);
0486 
0487   if (!tfile)
0488     error("current tfile not set!", __FUNCTION__);
0489 
0490   if (!fileIter)
0491     error("fileIter not set!", __FUNCTION__);
0492 
0493   // Check whether I processed everything
0494   if (allEventsInTreeProcessed())
0495     return false;
0496 
0497   if (allEventsInChainProcessed())
0498     return false;
0499 
0500   // if fast mode do some extra
0501   if (fastmode)
0502     ttree->LoadTree(teventlist ? teventlist->GetEntry(indexOfEventInTTree) : indexOfEventInTTree);
0503 
0504   // Set the event index in TREECLASS
0505   treeclass->GetEntry(teventlist ? teventlist->GetEntry(indexOfEventInTTree) : indexOfEventInTTree);
0506   // Increment the counter for this ttree
0507   ++indexOfEventInTTree;
0508   // Increment the counter for the entire tchain
0509   // If there is teventlist set then the skipping is a bit more complex...
0510   if (teventlist) {
0511     unsigned int curindex =
0512         teventlist->GetEntry(indexOfEventInTTree - 1);  // since I just increased by one a few lines before
0513     unsigned int previndex = indexOfEventInTTree >= 2 ? teventlist->GetEntry(indexOfEventInTTree - 2) : 0;
0514     nEventsToProcess += (curindex - previndex);
0515   } else {
0516     ++nEventsProcessed;
0517   }
0518   // Print progress
0519   printProgressBar();
0520   // If all fine return true
0521   return true;
0522 }
0523 
0524 //_________________________________________________________________________________________________
0525 template <class TREECLASS>
0526 bool RooUtil::Looper<TREECLASS>::nextEvent() {
0527   if (!isinit)
0528     error(
0529         "The Looper is not initialized! please call properly Looper::init(TChain* c, TREECLASS* t, int nevtToProcess) "
0530         "first!",
0531         __FUNCTION__);
0532 
0533   // If no tree it means this is the beginning of the loop.
0534   if (!ttree) {
0535     //        std::cout << " I think this is the first tree " << std::endl;
0536     // Load the next tree if it returns true, then proceed to next event in tree.
0537     while (nextTree()) {
0538       // If the next event in tree was successfully loaded return true, that it's good.
0539       if (nextEventInTree()) {
0540         //                std::cout << " I think this is the first event in first tree" << std::endl;
0541         // Set the boolean that a new file opened for this event
0542         isnewfileopened = true;
0543         return true;
0544       }
0545       // If the first event in this tree was not good, continue to the next tree
0546       else
0547         continue;
0548     }
0549 
0550     // If looping over all trees, we fail to find first event that's good,
0551     // return false and call it quits.
0552     // At this point it will exit the loop without processing any events.
0553     //        printProgressBar();
0554     // Set the boolean that a new file has not opened for this event
0555     isnewfileopened = false;
0556     return false;
0557   }
0558   // If tree exists, it means that we're in the middle of a loop
0559   else {
0560     // If next event is successfully loaded proceed.
0561     if (nextEventInTree()) {
0562       // Set the boolean that a new file has not opened for this event
0563       isnewfileopened = false;
0564       return true;
0565     }
0566     // If next event is not loaded then check why.
0567     else {
0568       // If failed because it was the last event in the whole chain to process, exit the loop.
0569       // You're done!
0570       if (allEventsInChainProcessed()) {
0571         //                printProgressBar();
0572         // Set the boolean that a new file has not opened for this event
0573         isnewfileopened = false;
0574         return false;
0575       }
0576       // If failed because it's last in the tree then load the next tree and the event
0577       else if (allEventsInTreeProcessed()) {
0578         // Load the next tree if it returns true, then proceed to next event in tree.
0579         while (nextTree()) {
0580           // If the next event in tree was successfully loaded return true, that it's good.
0581           if (nextEventInTree()) {
0582             // Set the boolean that a new file has opened for this event
0583             isnewfileopened = true;
0584             return true;
0585           }
0586           // If the first event in this tree was not good, continue to the next tree
0587           else
0588             continue;
0589         }
0590 
0591         // If looping over all trees, we fail to find first event that's good,
0592         // return false and call it quits.
0593         // Again you're done!
0594         //                printProgressBar();
0595         // Set the boolean that a new file has not opened for this event
0596         isnewfileopened = false;
0597         return false;
0598       } else {
0599         // Why are you even here?
0600         // spit error and return false to avoid warnings
0601         error("You should not be here! Please contact philip@physics.ucsd.edu", __FUNCTION__);
0602         // Set the boolean that a new file has not opened for this event
0603         isnewfileopened = false;
0604         return false;
0605       }
0606     }
0607   }
0608 }
0609 
0610 //_________________________________________________________________________________________________
0611 template <class TREECLASS>
0612 bool RooUtil::Looper<TREECLASS>::isNewFileInChain() {
0613   return isnewfileopened;
0614 }
0615 
0616 //_________________________________________________________________________________________________
0617 template <class TREECLASS>
0618 void RooUtil::Looper<TREECLASS>::setFileList() {
0619   if (!fileIter) {
0620     listOfFiles = tchain->GetListOfFiles();
0621     fileIter = new TObjArrayIter(listOfFiles);
0622   }
0623 }
0624 
0625 //_________________________________________________________________________________________________
0626 template <class TREECLASS>
0627 void RooUtil::Looper<TREECLASS>::setNEventsToProcess() {
0628   if (tchain) {
0629     nEventsTotalInChain = tchain->GetEntries();
0630 
0631     if (nEventsToProcess < 0)
0632       nEventsToProcess = nEventsTotalInChain;
0633 
0634     if (nEventsToProcess > (int)nEventsTotalInChain) {
0635       print(TString::Format("Asked to process %d events, but there aren't that many events", nEventsToProcess));
0636       nEventsToProcess = nEventsTotalInChain;
0637     }
0638 
0639     print(TString::Format("Total Events in this Chain to process = %d", nEventsToProcess));
0640   }
0641 }
0642 
0643 //_________________________________________________________________________________________________
0644 template <class TREECLASS>
0645 void RooUtil::Looper<TREECLASS>::initProgressBar() {
0646   /// Init progress bar
0647   my_timer.Start();
0648   bar_id = 0;
0649 }
0650 
0651 //_________________________________________________________________________________________________
0652 template <class TREECLASS>
0653 void RooUtil::Looper<TREECLASS>::printProgressBar(bool force) {
0654   if (silent)
0655     return;
0656 
0657   /// Print progress bar
0658 
0659   int entry = nEventsProcessed;
0660   int totalN = nEventsToProcess;
0661 
0662   //    if (use_tqdm_progress_bar)
0663   //    {
0664   //        if (force) return;  // N.B. If i am not using my own scheme i shouldn't force it.
0665   //        bar.progress(nEventsProcessed-1, nEventsToProcess); // tqdm expects 0 to N-1 index not 1 to N
0666   //        return;
0667   //    }
0668 
0669   if (use_treeclass_progress) {
0670     if (force)
0671       return;  // N.B. If i am not using my own scheme i shouldn't force it.
0672     // treeclass->progress(nEventsProcessed, nEventsToProcess);
0673     return;
0674   }
0675 
0676   if (totalN < 20)
0677     totalN = 20;
0678 
0679   // Progress bar
0680   if (entry > totalN) {
0681     //        printf( "Why are you here?\n" );
0682   } else if (entry == totalN) {
0683     Double_t elapsed = my_timer.RealTime();
0684     Double_t rate;
0685 
0686     if (elapsed != 0)
0687       rate = entry / elapsed;
0688     else
0689       rate = -999;
0690 
0691     const int mins_in_hour = 60;
0692     const int secs_to_min = 60;
0693     Int_t input_seconds = elapsed;
0694     Int_t seconds = input_seconds % secs_to_min;
0695     Int_t minutes = input_seconds / secs_to_min % mins_in_hour;
0696     Int_t hours = input_seconds / secs_to_min / mins_in_hour;
0697 
0698     printf("\rRooUtil::");
0699     printf("+");
0700     printf("|====================");
0701 
0702     //for ( int nb = 0; nb < 20; ++nb )
0703     //{
0704     //  printf("=");
0705     //}
0706 
0707     printf("| %.1f %% (%d/%d) with  [avg. %d Hz]   Total Time: %.2d:%.2d:%.2d         \n",
0708            100.0,
0709            entry,
0710            totalN,
0711            (int)rate,
0712            hours,
0713            minutes,
0714            seconds);
0715     fflush(stdout);
0716   }
0717   //else if ( entry % ( ( ( int ) print_rate ) ) < (0.3) * print_rate || force )
0718   else if (entry % (((int)print_rate)) == 0 || force) {
0719     // sanity check
0720     if (entry >=
0721         totalN +
0722             10)  // +2 instead of +1 since, the loop might be a while loop where to check I got a bad event the index may go over 1.
0723     {
0724       TString msg = TString::Format("%d %d", entry, totalN);
0725       RooUtil::print(msg, __FUNCTION__);
0726       RooUtil::error("Total number of events processed went over max allowed! Check your loop boundary conditions!!",
0727                      __FUNCTION__);
0728     }
0729 
0730     int nbars = entry / (totalN / 20);
0731     Double_t elapsed = my_timer.RealTime();
0732     Double_t rate;
0733 
0734     if (elapsed != 0)
0735       rate = entry / elapsed;
0736     else
0737       rate = -999;
0738 
0739     Double_t percentage = entry / (totalN * 1.) * 100;
0740     const int mins_in_hour = 60;
0741     const int secs_to_min = 60;
0742     Int_t input_seconds = (totalN - entry) / rate;
0743     Int_t seconds = input_seconds % secs_to_min;
0744     Int_t minutes = input_seconds / secs_to_min % mins_in_hour;
0745     Int_t hours = input_seconds / secs_to_min / mins_in_hour;
0746 
0747     print_rate = (int)(rate / 5) + 1;
0748 
0749     printf("RooUtil:: ");
0750 
0751     if (bar_id % 4 == 3)
0752       printf("-");
0753 
0754     if (bar_id % 4 == 2)
0755       printf("/");
0756 
0757     if (bar_id % 4 == 1)
0758       printf("|");
0759 
0760     if (bar_id % 4 == 0)
0761       printf("\\");
0762 
0763     printf("|");
0764     bar_id++;
0765 
0766     for (int nb = 0; nb < 20; ++nb) {
0767       if (nb < nbars)
0768         printf("=");
0769       else
0770         printf(".");
0771     }
0772 
0773     printf("| %.1f %% (%d/%d) with  [%d Hz]   ETA %.2d:%.2d:%.2d         \r",
0774            percentage,
0775            entry + 1,
0776            totalN,
0777            (int)rate,
0778            hours,
0779            minutes,
0780            seconds);
0781     fflush(stdout);
0782   }
0783 
0784   my_timer.Start(kFALSE);
0785 }
0786 
0787 //_________________________________________________________________________________________________
0788 template <class TREECLASS>
0789 void RooUtil::Looper<TREECLASS>::setSkim(TString ofilename) {
0790   skimfilename = ofilename;
0791   doskim = true;
0792 }
0793 
0794 //_________________________________________________________________________________________________
0795 template <class TREECLASS>
0796 void RooUtil::Looper<TREECLASS>::createSkimTree() {
0797   skimfile = new TFile(skimfilename, "recreate");
0798   TObjArray* toa = ttree->GetListOfBranches();
0799 
0800   if (skimbrfiltpttn.size() > 0) {
0801     ttree->SetBranchStatus("*", 0);
0802 
0803     for (auto& pttn : skimbrfiltpttn) {
0804       for (const auto& brobj : *toa) {
0805         TString brname = brobj->GetName();
0806 
0807         if (pttn.Contains("*")) {
0808           TString modpttn = pttn;
0809           modpttn.ReplaceAll("*", "");
0810           if (brname.Contains(modpttn) && brname.BeginsWith(modpttn)) {
0811             // std::cout << brname << std::endl;
0812             ttree->SetBranchStatus(brname + "*", 1);
0813           }
0814         } else {
0815           if (brname.EqualTo(pttn)) {
0816             // std::cout << brname << std::endl;
0817             ttree->SetBranchStatus(brname, 1);
0818           }
0819         }
0820       }
0821     }
0822   }
0823 
0824   skimtree = ttree->CloneTree(0);
0825 }
0826 
0827 //_________________________________________________________________________________________________
0828 template <class TREECLASS>
0829 void RooUtil::Looper<TREECLASS>::copyAddressesToSkimTree() {
0830   ttree->CopyAddresses(skimtree);
0831 }
0832 
0833 //_________________________________________________________________________________________________
0834 template <class TREECLASS>
0835 void RooUtil::Looper<TREECLASS>::fillSkim() {
0836   treeclass->LoadAllBranches();
0837   skimtree->Fill();
0838   nEventsSkimmed++;
0839 }
0840 
0841 //_________________________________________________________________________________________________
0842 template <class TREECLASS>
0843 void RooUtil::Looper<TREECLASS>::saveSkim() {
0844   double frac_skimmed = (double)nEventsSkimmed / (double)nEventsProcessed * 100;
0845   RooUtil::print(Form("Skimmed events %d out of %d. [%f%%]", nEventsSkimmed, nEventsProcessed, frac_skimmed));
0846   skimtree->GetCurrentFile()->cd();
0847   skimtree->Write();
0848   //    skimfile->Close();
0849 }
0850 
0851 //_________________________________________________________________________________________________
0852 template <class TREECLASS>
0853 bool RooUtil::Looper<TREECLASS>::handleBadEvent() {
0854   using namespace std;
0855   cout << endl;
0856   cout << "RooUtil::Looper [CheckCorrupt] Caught an I/O failure in the ROOT file." << endl;
0857   cout << "RooUtil::Looper [CheckCorrupt] Possibly corrupted hadoop file." << endl;
0858   cout << "RooUtil::Looper [CheckCorrupt] event index = " << getCurrentEventIndex() << " out of "
0859        << tchain->GetEntries() << endl;
0860   cout << endl;
0861 
0862   // If the total nskip reaches a threshold just fail the whole thing...
0863   if (nskipped >= nskipped_threshold) {
0864     nskipped += tchain->GetEntries() - getCurrentEventIndex() - 1;
0865     return false;
0866   }
0867 
0868   nskipped_batch++;
0869 
0870   // If the nskipped is quite large than skip the entire file
0871   if (nskipped_batch > nbatch_skip_threshold) {
0872     nskipped += nskipped_batch;
0873     nskipped_batch = 0;
0874     for (unsigned int i = 0; i < nbatch_to_skip; ++i) {
0875       if (!nextEvent())
0876         return false;
0877       nskipped++;
0878     }
0879   }
0880 
0881   return true;
0882 }
0883 
0884 //_________________________________________________________________________________________________
0885 template <class TREECLASS>
0886 void RooUtil::Looper<TREECLASS>::printStatus() {
0887   getTree()->PrintCacheStats();
0888   printSkippedBadEventStatus();
0889 }
0890 
0891 //_________________________________________________________________________________________________
0892 template <class TREECLASS>
0893 TString RooUtil::Looper<TREECLASS>::getListOfFileNames() {
0894   TString rtnstring = "";
0895   TObjArray* filepaths = tchain->GetListOfFiles();
0896   TObjArrayIter* iter = new TObjArrayIter(listOfFiles);
0897   for (Int_t ifile = 0; ifile < filepaths->GetEntries(); ++ifile) {
0898     TChainElement* chainelement = (TChainElement*)iter->Next();
0899     if (chainelement) {
0900       TString filepath = chainelement->GetTitle();
0901       if (rtnstring.IsNull())
0902         rtnstring = filepath;
0903       else
0904         rtnstring += "," + filepath;
0905     }
0906   }
0907   return rtnstring;
0908 }
0909 
0910 //_________________________________________________________________________________________________
0911 template <class TREECLASS>
0912 void RooUtil::Looper<TREECLASS>::printSkippedBadEventStatus() {
0913   using namespace std;
0914   nskipped += nskipped_batch;
0915 
0916   if (nskipped) {
0917     cout << "RooUtil:Looper [CheckCorrupt] Skipped " << nskipped << " events out of " << tchain->GetEntries() << " ["
0918          << float(nskipped) / float(tchain->GetEntries()) * 100 << "% loss]"
0919          << " POSSIBLE BADFILES = " << getListOfFileNames() << endl;
0920   }
0921 }
0922 
0923 //_________________________________________________________________________________________________
0924 template <class TREECLASS>
0925 bool RooUtil::Looper<TREECLASS>::doesBranchExist(TString bname) {
0926   if (ttree->GetBranch(bname))
0927     return true;
0928   if (ttree->GetBranch(ttree->GetAlias(bname)))
0929     return true;
0930   return false;
0931 }
0932 
0933 #endif