Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef cutflowutil_h
0002 #define cutflowutil_h
0003 
0004 #include "ttreex.h"
0005 #include "printutil.h"
0006 #include <tuple>
0007 #include <vector>
0008 #include <map>
0009 #include "TH1.h"
0010 #include "TString.h"
0011 #include <iostream>
0012 #include <algorithm>
0013 #include <sys/ioctl.h>
0014 #include <functional>
0015 
0016 //#define USE_TTREEX
0017 #define USE_CUTLAMBDA
0018 #define TREEMAPSTRING std::string
0019 #define CUTFLOWMAPSTRING TString
0020 #define DATA c_str
0021 #define THist TH1D
0022 
0023 namespace RooUtil {
0024   namespace CutflowUtil {
0025 
0026     class CutNameList {
0027     public:
0028       std::vector<TString> cutlist;
0029       CutNameList() {}
0030       CutNameList(const CutNameList& cutnamelist) { cutlist = cutnamelist.cutlist; }
0031       void clear() { cutlist.clear(); }
0032       void addCutName(TString cutname) { cutlist.push_back(cutname); }
0033       void print() {
0034         for (auto& str : cutlist)
0035           std::cout << str << std::endl;
0036       }
0037     };
0038 
0039     class CutNameListMap {
0040     public:
0041       std::map<TString, CutNameList> cutlists;
0042       std::vector<TString> cutlist;
0043       CutNameList& operator[](TString name) { return cutlists[name]; }
0044       void clear() { cutlists.clear(); }
0045       void print() {
0046         for (auto& cl : cutlists) {
0047           std::cout << "CutNameList - " << cl.first << std::endl;
0048           cl.second.print();
0049         }
0050       }
0051       std::map<TString, std::vector<TString>> getStdVersion() {
0052         std::map<TString, std::vector<TString>> obj_cutlists;
0053         for (auto& cl : cutlists)
0054           obj_cutlists[cl.first] = cl.second.cutlist;
0055         return obj_cutlists;
0056       }
0057     };
0058 
0059     void createCutflowBranches(CutNameListMap& cutlists, RooUtil::TTreeX& tx);
0060     void createCutflowBranches(std::map<TString, std::vector<TString>>& cutlists, RooUtil::TTreeX& tx);
0061     std::tuple<std::vector<bool>, std::vector<float>> getCutflow(std::vector<TString> cutlist, RooUtil::TTreeX& tx);
0062     std::pair<bool, float> passCuts(std::vector<TString> cutlist, RooUtil::TTreeX& tx);
0063     void fillCutflow(std::vector<TString> cutlist, RooUtil::TTreeX& tx, THist* h);
0064     void fillRawCutflow(std::vector<TString> cutlist, RooUtil::TTreeX& tx, THist* h);
0065     std::tuple<std::map<CUTFLOWMAPSTRING, THist*>, std::map<CUTFLOWMAPSTRING, THist*>> createCutflowHistograms(
0066         CutNameListMap& cutlists, TString syst = "");
0067     std::tuple<std::map<CUTFLOWMAPSTRING, THist*>, std::map<CUTFLOWMAPSTRING, THist*>> createCutflowHistograms(
0068         std::map<TString, std::vector<TString>>& cutlists, TString syst = "");
0069     void saveCutflowHistograms(std::map<CUTFLOWMAPSTRING, THist*>& cutflows,
0070                                std::map<CUTFLOWMAPSTRING, THist*>& rawcutflows);
0071     //        void fillCutflowHistograms(CutNameListMap& cutlists, RooUtil::TTreeX& tx, std::map<TString, THist*>& cutflows, std::map<TString, THist*>& rawcutflows);
0072     //        void fillCutflowHistograms(std::map<TString, std::vector<TString>>& cutlists, RooUtil::TTreeX& tx, std::map<TString, THist*>& cutflows, std::map<TString, THist*>& rawcutflows);
0073 
0074   }  // namespace CutflowUtil
0075 
0076   class CutTree {
0077   public:
0078     TString name;
0079     CutTree* parent;
0080     std::vector<CutTree*> parents;
0081     std::vector<CutTree*> children;
0082     std::vector<TString> systcutnames;
0083     std::vector<CutTree*> systcuts;
0084     std::map<TString, CutTree*> systs;
0085     int pass;
0086     float weight;
0087     std::vector<int> systpasses;
0088     std::vector<float> systweights;
0089     bool pass_this_cut;
0090     float weight_this_cut;
0091     std::function<bool()> pass_this_cut_func;
0092     std::function<float()> weight_this_cut_func;
0093 //            std::vector<TString> hists1d;
0094 //            std::vector<std::tuple<TString, TString>> hists2d;
0095 #ifdef USE_CUTLAMBDA
0096     std::map<TString, std::vector<std::tuple<THist*, std::function<float()>>>> hists1d;
0097     std::map<TString,
0098              std::vector<std::tuple<THist*, std::function<std::vector<float>()>, std::function<std::vector<float>()>>>>
0099         hists1dvec;
0100     std::map<TString, std::vector<std::tuple<TH2F*, std::function<float()>, std::function<float()>>>> hists2d;
0101     std::map<TString,
0102              std::vector<std::tuple<TH2F*,
0103                                     std::function<std::vector<float>()>,
0104                                     std::function<std::vector<float>()>,
0105                                     std::function<std::vector<float>()>>>>
0106         hists2dvec;
0107 #else
0108     std::map<TString, std::vector<std::tuple<THist*, TString>>> hists1d;
0109     std::map<TString, std::vector<std::tuple<TH2F*, TString, TString>>> hists2d;
0110 #endif
0111     std::vector<std::tuple<int, int, unsigned long long>> eventlist;
0112     CutTree(TString n) : name(n), parent(0), pass(false), weight(0) {}
0113     ~CutTree() {
0114       for (auto& child : children) {
0115         if (child)
0116           delete child;
0117       }
0118     }
0119     void printCuts(int indent = 0, std::vector<int> multichild = std::vector<int>()) {
0120       struct winsize w;
0121       ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
0122       int colsize = std::min(w.ws_col - 100, 600);
0123       if (indent == 0) {
0124         TString header = "Cut name";
0125         int extra = colsize - header.Length();
0126         for (int i = 0; i < extra; ++i)
0127           header += " ";
0128         header += "|pass|weight|systs";
0129         print(header);
0130         TString delimiter = "";
0131         for (int i = 0; i < w.ws_col - 10; ++i)
0132           delimiter += "=";
0133         print(delimiter);
0134       }
0135       TString msg = "";
0136       for (int i = 0; i < indent; ++i) {
0137         if (std::find(multichild.begin(), multichild.end(), i + 1) != multichild.end()) {
0138           if (indent == i + 1)
0139             msg += " +";
0140           else
0141             msg += " |";
0142         } else
0143           msg += "  ";
0144       }
0145       msg += name;
0146       int extrapad = colsize - msg.Length() > 0 ? colsize - msg.Length() : 0;
0147       for (int i = 0; i < extrapad; ++i)
0148         msg += " ";
0149       //msg += TString::Format("| %d | %.5f|", pass, weight);
0150       msg += TString::Format("| %d | %f|", pass, weight);
0151       for (auto& key : systs) {
0152         msg += key.first + " ";
0153       }
0154       print(msg);
0155       if (children.size() > 1)
0156         multichild.push_back(indent + 1);
0157       for (auto& child : children) {
0158         (*child).printCuts(indent + 1, multichild);
0159       }
0160     }
0161     void printEventList() {
0162       print(TString::Format("Print event list for the cut = %s", name.Data()));
0163       for (auto& eventid : eventlist) {
0164         int run = std::get<0>(eventid);
0165         int lumi = std::get<1>(eventid);
0166         unsigned long long evt = std::get<2>(eventid);
0167         TString msg = TString::Format("%d:%d:%llu", run, lumi, evt);
0168         std::cout << msg << std::endl;
0169       }
0170     }
0171     void writeEventList(TString ofilename) {
0172       std::ofstream outFile(ofilename);
0173       for (auto& tuple : eventlist) {
0174         int run = std::get<0>(tuple);
0175         int lumi = std::get<1>(tuple);
0176         unsigned long long evt = std::get<2>(tuple);
0177         outFile << run << ":" << lumi << ":" << evt << std::endl;
0178       }
0179       outFile.close();
0180     }
0181     void addCut(TString n) {
0182       CutTree* obj = new CutTree(n);
0183       obj->parent = this;
0184       obj->parents.push_back(this);
0185       children.push_back(obj);
0186     }
0187     void addSyst(TString syst) {
0188       // If already added ignore
0189       if (systs.find(syst) != systs.end())
0190         return;
0191       // Syst CutTree object knows the parents, and children, however, the children does not know the syst-counter-part parent, nor the parent knows the syste-counter-part children.
0192       CutTree* obj = new CutTree(this->name + syst);
0193       systs[syst] = obj;
0194       systcutnames.push_back(syst);
0195       systcuts.push_back(obj);
0196       systpasses.push_back(1);
0197       systweights.push_back(1);
0198       obj->children = this->children;
0199       obj->parents = this->parents;
0200       obj->parent = this->parent;
0201     }
0202 #ifdef USE_CUTLAMBDA
0203     void addHist1D(THist* h, std::function<float()> var, TString syst) {
0204       if (syst.IsNull())
0205         hists1d["Nominal"].push_back(std::make_tuple(h, var));
0206       else
0207         hists1d[syst].push_back(std::make_tuple(h, var));
0208     }
0209     void addHist1DVec(THist* h,
0210                       std::function<std::vector<float>()> var,
0211                       std::function<std::vector<float>()> wgt,
0212                       TString syst) {
0213       if (syst.IsNull())
0214         hists1dvec["Nominal"].push_back(std::make_tuple(h, var, wgt));
0215       else
0216         hists1dvec[syst].push_back(std::make_tuple(h, var, wgt));
0217     }
0218     void addHist2D(TH2F* h, std::function<float()> varx, std::function<float()> vary, TString syst) {
0219       if (syst.IsNull())
0220         hists2d["Nominal"].push_back(std::make_tuple(h, varx, vary));
0221       else
0222         hists2d[syst].push_back(std::make_tuple(h, varx, vary));
0223     }
0224     void addHist2DVec(TH2F* h,
0225                       std::function<std::vector<float>()> varx,
0226                       std::function<std::vector<float>()> vary,
0227                       std::function<std::vector<float>()> elemwgt,
0228                       TString syst) {
0229       if (syst.IsNull())
0230         hists2dvec["Nominal"].push_back(std::make_tuple(h, varx, vary, elemwgt));
0231       else
0232         hists2dvec[syst].push_back(std::make_tuple(h, varx, vary, elemwgt));
0233     }
0234 #else
0235     void addHist1D(THist* h, TString var, TString syst) {
0236       if (syst.IsNull())
0237         hists1d["Nominal"].push_back(std::make_tuple(h, var));
0238       else
0239         hists1d[syst].push_back(std::make_tuple(h, var));
0240     }
0241     void addHist2D(TH2F* h, TString varx, TString vary, TString syst) {
0242       if (syst.IsNull())
0243         hists2d["Nominal"].push_back(std::make_tuple(h, varx, vary));
0244       else
0245         hists2d[syst].push_back(std::make_tuple(h, varx, vary));
0246     }
0247 #endif
0248     CutTree* getCutPointer(TString n) {
0249       // If the name match then return itself
0250       if (name.EqualTo(n)) {
0251         return this;
0252       } else {
0253         // Otherwise, loop over the children an if a children has the correct one return the found CutTree
0254         for (auto& child : children) {
0255           CutTree* c = child->getCutPointer(n);
0256           if (c)
0257             return c;
0258         }
0259         return 0;
0260       }
0261     }
0262     // Wrapper to return the object instead of pointer
0263     CutTree& getCut(TString n) {
0264       CutTree* c = getCutPointer(n);
0265       if (c) {
0266         return *c;
0267       } else {
0268         RooUtil::error(TString::Format("Asked for %s cut, but did not find the cut", n.Data()));
0269         return *this;
0270       }
0271     }
0272     std::vector<TString> getCutList(TString n, std::vector<TString> cut_list = std::vector<TString>()) {
0273       // Main idea: start from the end node provided by the first argument "n", and work your way up to the root node.
0274       //
0275       // The algorithm will first determine whether I am starting from a specific cut requested by the user or within in recursion.
0276       // If the cut_list.size() == 0, the function is called by the user (since no list is aggregated so far)
0277       // In that case, first find the pointer to the object we want and set it to "c"
0278       // If cut_list.size() is non-zero then take this as the cut that I am starting and I go up the chain to aggregate all the cuts prior to the requested cut
0279       CutTree* c = 0;
0280       if (cut_list.size() == 0) {
0281         c = &getCut(n);
0282         cut_list.push_back(c->name);
0283       } else {
0284         c = this;
0285         cut_list.push_back(n);
0286       }
0287       if (c->parent) {
0288         return (c->parent)->getCutList((c->parent)->name, cut_list);
0289       } else {
0290         std::reverse(cut_list.begin(), cut_list.end());
0291         return cut_list;
0292       }
0293     }
0294     std::vector<TString> getEndCuts(std::vector<TString> endcuts = std::vector<TString>()) {
0295       if (children.size() == 0) {
0296         endcuts.push_back(name);
0297         return endcuts;
0298       }
0299       for (auto& child : children)
0300         endcuts = child->getEndCuts(endcuts);
0301       return endcuts;
0302     }
0303     std::vector<TString> getCutListBelow(TString n, std::vector<TString> cut_list = std::vector<TString>()) {
0304       // Main idea: start from the node provided by the first argument "n", and work your way down to the ends.
0305       CutTree* c = 0;
0306       if (cut_list.size() == 0) {
0307         c = &getCut(n);
0308         cut_list.push_back(c->name);
0309       } else {
0310         c = this;
0311         cut_list.push_back(n);
0312       }
0313       if (children.size() > 0) {
0314         for (auto& child : c->children) {
0315           cut_list = child->getCutListBelow(child->name, cut_list);
0316         }
0317         return cut_list;
0318       } else {
0319         return cut_list;
0320       }
0321     }
0322     void clear() {
0323       pass = false;
0324       weight = 0;
0325       for (auto& child : children)
0326         child->clear();
0327     }
0328     void addSyst(TString syst,
0329                  std::vector<TString> patterns,
0330                  std::vector<TString> vetopatterns = std::vector<TString>()) {
0331       for (auto& pattern : patterns)
0332         if (name.Contains(pattern)) {
0333           bool veto = false;
0334           for (auto& vetopattern : vetopatterns) {
0335             if (name.Contains(vetopattern))
0336               veto = true;
0337           }
0338           if (not veto)
0339             addSyst(syst);
0340         }
0341       for (auto& child : children)
0342         child->addSyst(syst, patterns, vetopatterns);
0343     }
0344     void clear_passbits() {
0345       pass = 0;
0346       weight = 0;
0347       for (auto& child : children)
0348         child->clear_passbits();
0349     }
0350     void evaluate(RooUtil::TTreeX& tx,
0351                   TString cutsystname = "",
0352                   bool doeventlist = false,
0353                   bool aggregated_pass = true,
0354                   float aggregated_weight = 1) {
0355 #ifdef USE_TTREEX
0356       evaluate_use_ttreex(tx, cutsystname, doeventlist, aggregated_pass, aggregated_weight);
0357 #else
0358 #ifdef USE_CUTLAMBDA
0359       evaluate_use_lambda(tx, cutsystname, doeventlist, aggregated_pass, aggregated_weight);
0360 #else
0361       evaluate_use_internal_variable(tx, cutsystname, doeventlist, aggregated_pass, aggregated_weight);
0362 #endif
0363 #endif
0364     }
0365     void evaluate_use_lambda(RooUtil::TTreeX& tx,
0366                              TString cutsystname = "",
0367                              bool doeventlist = false,
0368                              bool aggregated_pass = true,
0369                              float aggregated_weight = 1) {
0370       if (!parent) {
0371         clear_passbits();
0372         pass = 1;
0373         weight = 1;
0374       } else {
0375         if (cutsystname.IsNull()) {
0376           if (pass_this_cut_func) {
0377             pass = pass_this_cut_func() && aggregated_pass;
0378             weight = weight_this_cut_func() * aggregated_weight;
0379             if (!pass)
0380               return;
0381           } else {
0382             TString msg = "cowardly passing the event because cut and weight func not set! cut name = " + name;
0383             warning(msg);
0384             pass = aggregated_pass;
0385             weight = aggregated_weight;
0386           }
0387         } else {
0388           if (systs.find(cutsystname) == systs.end()) {
0389             if (pass_this_cut_func) {
0390               pass = pass_this_cut_func() && aggregated_pass;
0391               weight = weight_this_cut_func() * aggregated_weight;
0392               if (!pass)
0393                 return;
0394             } else {
0395               TString msg = "cowardly passing the event because cut and weight func not set! cut name = " + name;
0396               warning(msg);
0397               pass = aggregated_pass;
0398               weight = aggregated_weight;
0399             }
0400           } else {
0401             if (systs[cutsystname]->pass_this_cut_func) {
0402               pass = systs[cutsystname]->pass_this_cut_func() && aggregated_pass;
0403               weight = systs[cutsystname]->weight_this_cut_func() * aggregated_weight;
0404               if (!pass)
0405                 return;
0406             } else {
0407               TString msg = "cowardly passing the event because cut and weight func not set! cut name = " + name +
0408                             " syst name = " + cutsystname;
0409               warning(msg);
0410               pass = aggregated_pass;
0411               weight = aggregated_weight;
0412             }
0413           }
0414         }
0415       }
0416       if (doeventlist and pass and cutsystname.IsNull()) {
0417         if (tx.hasBranch<int>("run") && tx.hasBranch<int>("lumi") && tx.hasBranch<unsigned long long>("evt")) {
0418           eventlist.push_back(std::make_tuple(
0419               tx.getBranch<int>("run"), tx.getBranch<int>("lumi"), tx.getBranch<unsigned long long>("evt")));
0420         }
0421       }
0422       for (auto& child : children)
0423         child->evaluate_use_lambda(tx, cutsystname, doeventlist, pass, weight);
0424     }
0425     void evaluate_use_internal_variable(RooUtil::TTreeX& tx,
0426                                         TString cutsystname = "",
0427                                         bool doeventlist = false,
0428                                         bool aggregated_pass = true,
0429                                         float aggregated_weight = 1) {
0430       if (!parent) {
0431         clear_passbits();
0432         pass = 1;
0433         weight = 1;
0434       } else {
0435         if (cutsystname.IsNull()) {
0436           pass = pass_this_cut && aggregated_pass;
0437           weight = weight_this_cut * aggregated_weight;
0438           if (!pass)
0439             return;
0440         } else {
0441           if (systs.find(cutsystname) == systs.end()) {
0442             pass = pass_this_cut && aggregated_pass;
0443             weight = weight_this_cut * aggregated_weight;
0444             if (!pass)
0445               return;
0446           } else {
0447             pass = systs[cutsystname]->pass_this_cut && aggregated_pass;
0448             weight = systs[cutsystname]->weight_this_cut * aggregated_weight;
0449             if (!pass)
0450               return;
0451           }
0452         }
0453       }
0454       if (doeventlist and pass and cutsystname.IsNull()) {
0455         if (tx.hasBranch<int>("run") && tx.hasBranch<int>("lumi") && tx.hasBranch<unsigned long long>("evt")) {
0456           eventlist.push_back(std::make_tuple(
0457               tx.getBranch<int>("run"), tx.getBranch<int>("lumi"), tx.getBranch<unsigned long long>("evt")));
0458         }
0459       }
0460       for (auto& child : children)
0461         child->evaluate_use_internal_variable(tx, cutsystname, doeventlist, pass, weight);
0462     }
0463     void evaluate_use_ttreex(RooUtil::TTreeX& tx,
0464                              TString cutsystname = "",
0465                              bool doeventlist = false,
0466                              bool aggregated_pass = true,
0467                              float aggregated_weight = 1) {
0468       if (!parent) {
0469         pass = tx.getBranch<bool>(name);
0470         weight = tx.getBranch<float>(name + "_weight");
0471       } else {
0472         if (cutsystname.IsNull()) {
0473           if (!tx.hasBranch<bool>(name))
0474             return;
0475           pass = tx.getBranch<bool>(name) && aggregated_pass;
0476           weight = tx.getBranch<float>(name + "_weight") * aggregated_weight;
0477         } else {
0478           if (systs.find(cutsystname) == systs.end()) {
0479             if (!tx.hasBranch<bool>(name))
0480               return;
0481             pass = tx.getBranch<bool>(name) && aggregated_pass;
0482             weight = tx.getBranch<float>(name + "_weight") * aggregated_weight;
0483           } else {
0484             if (!tx.hasBranch<bool>(name + cutsystname))
0485               return;
0486             pass = tx.getBranch<bool>(name + cutsystname) && aggregated_pass;
0487             weight = tx.getBranch<float>(name + cutsystname + "_weight") * aggregated_weight;
0488           }
0489         }
0490       }
0491       if (doeventlist and pass and cutsystname.IsNull()) {
0492         if (tx.hasBranch<int>("run") && tx.hasBranch<int>("lumi") && tx.hasBranch<unsigned long long>("evt")) {
0493           eventlist.push_back(std::make_tuple(
0494               tx.getBranch<int>("run"), tx.getBranch<int>("lumi"), tx.getBranch<unsigned long long>("evt")));
0495         }
0496       }
0497       for (auto& child : children)
0498         child->evaluate_use_ttreex(tx, cutsystname, doeventlist, pass, weight);
0499     }
0500     void sortEventList() {
0501       std::sort(
0502           eventlist.begin(),
0503           eventlist.end(),
0504           [](const std::tuple<int, int, unsigned long long>& a, const std::tuple<int, int, unsigned long long>& b) {
0505             if (std::get<0>(a) != std::get<0>(b))
0506               return std::get<0>(a) < std::get<0>(b);
0507             else if (std::get<1>(a) != std::get<1>(b))
0508               return std::get<1>(a) < std::get<1>(b);
0509             else if (std::get<2>(a) != std::get<2>(b))
0510               return std::get<2>(a) < std::get<2>(b);
0511             else
0512               return true;
0513           });
0514     }
0515     void clearEventList() { eventlist.clear(); }
0516     void addEventList(int run, int lumi, unsigned long long evt) {
0517       eventlist.push_back(std::make_tuple(run, lumi, evt));
0518     }
0519 #ifdef USE_CUTLAMBDA
0520     void fillHistograms(TString syst, float extrawgt) {
0521       // If the cut didn't pass then stop
0522       if (!pass)
0523         return;
0524 
0525       if (hists1d.size() != 0 or hists2d.size() != 0 or hists2dvec.size() != 0 or hists1dvec.size() != 0) {
0526         TString systkey = syst.IsNull() ? "Nominal" : syst;
0527         for (auto& tuple : hists1d[systkey]) {
0528           THist* h = std::get<0>(tuple);
0529           std::function<float()> vardef = std::get<1>(tuple);
0530           h->Fill(vardef(), weight * extrawgt);
0531         }
0532         for (auto& tuple : hists2d[systkey]) {
0533           TH2F* h = std::get<0>(tuple);
0534           std::function<float()> varxdef = std::get<1>(tuple);
0535           std::function<float()> varydef = std::get<2>(tuple);
0536           h->Fill(varxdef(), varydef(), weight * extrawgt);
0537         }
0538         for (auto& tuple : hists1dvec[systkey]) {
0539           THist* h = std::get<0>(tuple);
0540           std::function<std::vector<float>()> vardef = std::get<1>(tuple);
0541           std::function<std::vector<float>()> wgtdef = std::get<2>(tuple);
0542           std::vector<float> varx = vardef();
0543           std::vector<float> elemwgts;
0544           if (wgtdef)
0545             elemwgts = wgtdef();
0546           for (unsigned int i = 0; i < varx.size(); ++i) {
0547             if (wgtdef)
0548               h->Fill(varx[i], weight * extrawgt * elemwgts[i]);
0549             else
0550               h->Fill(varx[i], weight * extrawgt);
0551           }
0552         }
0553         for (auto& tuple : hists2dvec[systkey]) {
0554           TH2F* h = std::get<0>(tuple);
0555           std::function<std::vector<float>()> varxdef = std::get<1>(tuple);
0556           std::function<std::vector<float>()> varydef = std::get<2>(tuple);
0557           std::function<std::vector<float>()> wgtdef = std::get<3>(tuple);
0558           std::vector<float> varx = varxdef();
0559           std::vector<float> vary = varydef();
0560           if (varx.size() != vary.size()) {
0561             TString msg =
0562                 "the vector input to be looped over do not have same length for x and y! check the variable definition "
0563                 "for histogram ";
0564             msg += h->GetName();
0565             warning(msg);
0566           }
0567           std::vector<float> elemwgts;
0568           if (wgtdef)
0569             elemwgts = wgtdef();
0570           for (unsigned int i = 0; i < varx.size(); ++i) {
0571             if (wgtdef)
0572               h->Fill(varx[i], vary[i], weight * extrawgt * elemwgts[i]);
0573             else
0574               h->Fill(varx[i], vary[i], weight * extrawgt);
0575           }
0576         }
0577       }
0578       for (auto& child : children)
0579         child->fillHistograms(syst, extrawgt);
0580     }
0581 #else
0582     void fillHistograms(RooUtil::TTreeX& tx, TString syst, float extrawgt) {
0583       // If the cut didn't pass then stop
0584       if (!pass)
0585         return;
0586 
0587       if (hists1d.size() != 0 or hists2d.size() != 0) {
0588         TString systkey = syst.IsNull() ? "Nominal" : syst;
0589         for (auto& tuple : hists1d[systkey]) {
0590           THist* h = std::get<0>(tuple);
0591           TString varname = std::get<1>(tuple);
0592           h->Fill(tx.getBranch<float>(varname), weight * extrawgt);
0593         }
0594         for (auto& tuple : hists2d[systkey]) {
0595           TH2F* h = std::get<0>(tuple);
0596           TString varname = std::get<1>(tuple);
0597           TString varnamey = std::get<2>(tuple);
0598           h->Fill(tx.getBranch<float>(varname), tx.getBranch<float>(varnamey), weight * extrawgt);
0599         }
0600       }
0601       for (auto& child : children)
0602         child->fillHistograms(tx, syst, extrawgt);
0603 
0604       //                if (!parent)
0605       //                {
0606       //                    pass = pass_this_cut;
0607       //                    weight = weight_this_cut;
0608       //                }
0609       //                else
0610       //                {
0611       //                    if (cutsystname.IsNull())
0612       //                    {
0613       //                        pass = pass_this_cut && aggregated_pass;
0614       //                        weight = weight_this_cut * aggregated_weight;
0615       //                    }
0616       //                    else
0617       //                    {
0618       //                        if (systs.find(cutsystname) == systs.end())
0619       //                        {
0620       //                            pass = pass_this_cut && aggregated_pass;
0621       //                            weight = weight_this_cut * aggregated_weight;
0622       //                        }
0623       //                        else
0624       //                        {
0625       //                            pass = systs[cutsystname]->pass_this_cut && aggregated_pass;
0626       //                            weight = systs[cutsystname]->weight_this_cut * aggregated_weight;
0627       //                        }
0628       //                    }
0629       //                }
0630     }
0631 #endif
0632   };
0633 }  // namespace RooUtil
0634 
0635 #endif