Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-02-20 03:45:23

0001 #include "TrigObjTnPHistColl.h"
0002 
0003 #include "FWCore/Common/interface/TriggerNames.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 
0006 namespace {
0007   std::vector<float> convertToFloat(const std::vector<double>& vecD) {
0008     return std::vector<float>(vecD.begin(), vecD.end());
0009   }
0010 }  // namespace
0011 
0012 TrigObjTnPHistColl::TrigObjTnPHistColl(const edm::ParameterSet& config)
0013     : tagCuts_(config.getParameter<std::vector<edm::ParameterSet>>("tagCuts")),
0014       probeCuts_(config.getParameter<std::vector<edm::ParameterSet>>("probeCuts")),
0015       tagFilters_(config.getParameter<edm::ParameterSet>("tagFilters")),
0016       collName_(config.getParameter<std::string>("collName")),
0017       folderName_(config.getParameter<std::string>("folderName")),
0018       histDefs_(config.getParameter<edm::ParameterSet>("histDefs")),
0019       evtTrigSel_(config.getParameter<edm::ParameterSet>("evtTrigSel"))
0020 
0021 {
0022   auto probeFilters = config.getParameter<std::vector<std::string>>("probeFilters");
0023   for (auto& probeFilter : probeFilters) {
0024     probeHists_.emplace_back(ProbeData(std::move(probeFilter)));
0025   }
0026 }
0027 
0028 edm::ParameterSetDescription TrigObjTnPHistColl::makePSetDescription() {
0029   edm::ParameterSetDescription desc;
0030   desc.addVPSet(
0031       "tagCuts", VarRangeCut<trigger::TriggerObject>::makePSetDescription(), std::vector<edm::ParameterSet>());
0032   desc.addVPSet(
0033       "probeCuts", VarRangeCut<trigger::TriggerObject>::makePSetDescription(), std::vector<edm::ParameterSet>());
0034   desc.add<edm::ParameterSetDescription>("tagFilters", FilterSelector::makePSetDescription());
0035   desc.add<std::string>("collName", "stdTag");
0036   desc.add<std::string>("folderName", "HLT/EGM/TrigObjTnP");
0037   desc.add<edm::ParameterSetDescription>("histDefs", HistDefs::makePSetDescription());
0038   desc.add<std::vector<std::string>>("probeFilters", std::vector<std::string>());
0039   desc.add<edm::ParameterSetDescription>("evtTrigSel", PathSelector::makePSetDescription());
0040   return desc;
0041 }
0042 
0043 void TrigObjTnPHistColl::bookHists(DQMStore::IBooker& iBooker) {
0044   iBooker.setCurrentFolder(folderName_);
0045   for (auto& probe : probeHists_) {
0046     probe.bookHists(collName_, iBooker, histDefs_);
0047   }
0048 }
0049 
0050 void TrigObjTnPHistColl::fill(const trigger::TriggerEvent& trigEvt,
0051                               const edm::TriggerResults& trigResults,
0052                               const edm::TriggerNames& trigNames) const {
0053   if (evtTrigSel_(trigResults, trigNames) == false)
0054     return;
0055 
0056   auto tagTrigKeys = tagFilters_.getPassingKeys(trigEvt);
0057   for (auto& tagKey : tagTrigKeys) {
0058     const trigger::TriggerObject& tagObj = trigEvt.getObjects()[tagKey];
0059     if (tagCuts_(tagObj)) {
0060       for (auto& probeColl : probeHists_)
0061         probeColl.fill(tagKey, trigEvt, probeCuts_);
0062     }
0063   }
0064 }
0065 
0066 //trigger::Keys is likely a vector containing 0-3 short ints (probably 10 max),
0067 // passing by value makes this much  easier code wise (otherwise would have to
0068 //create a dummy empty vector) and shouldnt be too much of a performance hit
0069 const trigger::Keys TrigObjTnPHistColl::getKeys(const trigger::TriggerEvent& trigEvt, const std::string& filterName) {
0070   edm::InputTag filterTag(filterName, "", trigEvt.usedProcessName());
0071   trigger::size_type filterIndex = trigEvt.filterIndex(filterTag);
0072   if (filterIndex < trigEvt.sizeFilters())
0073     return trigEvt.filterKeys(filterIndex);
0074   else
0075     return trigger::Keys();
0076 }
0077 
0078 TrigObjTnPHistColl::FilterSelector::FilterSelector(const edm::ParameterSet& config)
0079     : isAND_(config.getParameter<bool>("isAND")) {
0080   auto filterSetConfigs = config.getParameter<std::vector<edm::ParameterSet>>("filterSets");
0081   for (auto& filterSetConfig : filterSetConfigs)
0082     filterSets_.emplace_back(FilterSet(filterSetConfig));
0083 }
0084 
0085 edm::ParameterSetDescription TrigObjTnPHistColl::FilterSelector::makePSetDescription() {
0086   edm::ParameterSetDescription desc;
0087   desc.addVPSet("filterSets", FilterSet::makePSetDescription(), std::vector<edm::ParameterSet>());
0088   desc.add<bool>("isAND", false);
0089   return desc;
0090 }
0091 
0092 const trigger::Keys TrigObjTnPHistColl::FilterSelector::getPassingKeys(const trigger::TriggerEvent& trigEvt) const {
0093   trigger::Keys passingKeys;
0094   bool isFirstFilterSet = true;
0095   for (const auto& filterSet : filterSets_) {
0096     auto keysOfFilterSet = filterSet.getPassingKeys(trigEvt);
0097     if (isFirstFilterSet)
0098       passingKeys = keysOfFilterSet;
0099     else
0100       mergeTrigKeys(passingKeys, keysOfFilterSet, isAND_);
0101     isFirstFilterSet = false;
0102   }
0103   cleanTrigKeys(passingKeys);
0104   return passingKeys;
0105 }
0106 
0107 void TrigObjTnPHistColl::FilterSelector::mergeTrigKeys(trigger::Keys& keys,
0108                                                        const trigger::Keys& keysToMerge,
0109                                                        bool isAND) {
0110   if (isAND) {
0111     for (auto& key : keys) {
0112       if (std::count(keysToMerge.begin(), keysToMerge.end(), key) == 0) {
0113         key = std::numeric_limits<trigger::size_type>::max();
0114       }
0115     }
0116   } else {
0117     for (const auto key : keysToMerge) {
0118       keys.push_back(key);
0119     }
0120   }
0121 }
0122 
0123 void TrigObjTnPHistColl::FilterSelector::cleanTrigKeys(trigger::Keys& keys) {
0124   std::sort(keys.begin(), keys.end());
0125   auto last = std::unique(keys.begin(), keys.end());
0126   keys.erase(last, keys.end());
0127   while (!keys.empty() && keys.back() == std::numeric_limits<trigger::size_type>::max()) {
0128     keys.pop_back();
0129   }
0130 }
0131 
0132 TrigObjTnPHistColl::FilterSelector::FilterSet::FilterSet(const edm::ParameterSet& config)
0133     : filters_(config.getParameter<std::vector<std::string>>("filters")), isAND_(config.getParameter<bool>("isAND")) {}
0134 
0135 TrigObjTnPHistColl::PathSelector::PathSelector(const edm::ParameterSet& config)
0136     : selectionStr_(config.getParameter<std::string>("selectionStr")),
0137       isANDForExpandedPaths_(config.getParameter<bool>("isANDForExpandedPaths")),
0138       verbose_(config.getParameter<int>("verbose")),
0139       isInited_(false) {}
0140 
0141 edm::ParameterSetDescription TrigObjTnPHistColl::PathSelector::makePSetDescription() {
0142   edm::ParameterSetDescription desc;
0143   desc.add<std::string>("selectionStr", std::string(""));
0144   desc.add<bool>("isANDForExpandedPaths", false);
0145   desc.add<int>("verbose", 1);
0146   return desc;
0147 }
0148 
0149 void TrigObjTnPHistColl::PathSelector::init(const HLTConfigProvider& hltConfig) {
0150   expandedSelStr_ = expandSelectionStr(selectionStr_, hltConfig, isANDForExpandedPaths_, verbose_);
0151   isInited_ = true;
0152   if (verbose_ > 1) {
0153     edm::LogInfo("TrigObjTnPHistColl::PathSelector") << "trigger selection string: \"" << expandedSelStr_ << "\"";
0154   }
0155 }
0156 
0157 bool TrigObjTnPHistColl::PathSelector::operator()(const edm::TriggerResults& trigResults,
0158                                                   const edm::TriggerNames& trigNames) const {
0159   if (selectionStr_.empty())
0160     return true;  //didnt specify any selection, default to pass
0161   else if (!isInited_) {
0162     edm::LogError("TrigObjTnPHistColl")
0163         << " error, TrigObjTnPHistColl::PathSelector is not initalised, returning false ";
0164     return false;
0165   } else if (expandedSelStr_.empty()) {
0166     //there was a problem parsing the expression, it was logged at the start, no need to do each run
0167     return false;
0168   } else {
0169     //as of 20/08/18, there is a bug in L1GtLogicParser, it must take a non-const std::string
0170     //as input because it overloads the constructor between const and non-const std::string
0171     //for like no reason. And the const version is broken, you have to use non-const
0172     //hence we make a non-const copy of the selection string
0173     std::string selStr = expandedSelStr_;
0174     L1GtLogicParser logicParser(selStr);
0175     for (auto& token : logicParser.operandTokenVector()) {
0176       const std::string& pathName = token.tokenName;
0177       auto pathIndex = trigNames.triggerIndex(pathName);
0178       bool accept = pathIndex < trigNames.size() ? trigResults.accept(pathIndex) : false;
0179       token.tokenResult = accept;
0180     }
0181     return logicParser.expressionResult();
0182   }
0183 }
0184 
0185 //a port of https://github.com/cms-sw/cmssw/blob/51eb73f59e2016d54618e2a8e19abab84fe33b47/CommonTools/TriggerUtils/src/GenericTriggerEventFlag.cc#L225-L238
0186 std::string TrigObjTnPHistColl::PathSelector::expandSelectionStr(const std::string& selStr,
0187                                                                  const HLTConfigProvider& hltConfig,
0188                                                                  bool isAND,
0189                                                                  int verbose) {
0190   std::string expandedSelStr(selStr);
0191   //it is very important to pass in as a non-const std::string, see comments else where
0192   L1GtLogicParser logicParser(expandedSelStr);
0193   for (const auto& token : logicParser.operandTokenVector()) {
0194     const std::string& pathName = token.tokenName;
0195     if (pathName.find('*') != std::string::npos) {
0196       std::string pathPatternExpanded = expandPath(pathName, hltConfig, isAND, verbose);
0197       expandedSelStr.replace(expandedSelStr.find(pathName), pathName.size(), pathPatternExpanded);
0198     }
0199   }
0200   return expandedSelStr;
0201 }
0202 
0203 //a port of GenericTriggerEventFlag::expandLogicalExpression
0204 //https://github.com/cms-sw/cmssw/blob/51eb73f59e2016d54618e2a8e19abab84fe33b47/CommonTools/TriggerUtils/src/GenericTriggerEventFlag.cc#L600-L632
0205 std::string TrigObjTnPHistColl::PathSelector::expandPath(const std::string& pathPattern,
0206                                                          const HLTConfigProvider& hltConfig,
0207                                                          bool isAND,
0208                                                          int verbose) {
0209   // Find matching entries in the menu
0210   const std::vector<std::string>& trigNames = hltConfig.triggerNames();
0211   std::vector<std::string> matched;
0212   const std::string versionWildcard("_v*");
0213   if (pathPattern.substr(pathPattern.size() - versionWildcard.size()) == versionWildcard) {
0214     const std::string pathPatternBase(pathPattern.substr(0, pathPattern.size() - versionWildcard.size()));
0215     matched = hltConfig.restoreVersion(trigNames, pathPatternBase);
0216   } else {
0217     matched = hltConfig.matched(trigNames, pathPattern);
0218   }
0219 
0220   if (matched.empty()) {
0221     if (verbose >= 1)
0222       edm::LogWarning("TrigObjTnPHistColl::PathSelector")
0223           << "pattern: \"" << pathPattern
0224           << "\" could not be resolved, please check your triggers are spelt correctly and present in the data you are "
0225              "running over";
0226     return "";
0227   }
0228 
0229   // Compose logical expression
0230   std::string expanded("(");
0231   for (unsigned iVers = 0; iVers < matched.size(); ++iVers) {
0232     if (iVers > 0)
0233       expanded.append(isAND ? " AND " : " OR ");
0234     expanded.append(matched.at(iVers));
0235   }
0236   expanded.append(")");
0237   if (verbose > 1) {
0238     edm::LogInfo("TrigObjTnPHistColl::PathSelector") << "Logical expression : \"" << pathPattern << "\"\n"
0239                                                      << "        expanded to:  \"" << expanded << "\"";
0240   }
0241   return expanded;
0242 }
0243 
0244 edm::ParameterSetDescription TrigObjTnPHistColl::FilterSelector::FilterSet::makePSetDescription() {
0245   edm::ParameterSetDescription desc;
0246   desc.add<std::vector<std::string>>("filters", std::vector<std::string>());
0247   desc.add<bool>("isAND", true);
0248   return desc;
0249 }
0250 
0251 const trigger::Keys TrigObjTnPHistColl::FilterSelector::FilterSet::getPassingKeys(
0252     const trigger::TriggerEvent& trigEvt) const {
0253   trigger::Keys passingKeys;
0254   bool firstFilter = true;
0255   for (const auto& filterName : filters_) {
0256     const trigger::Keys& trigKeys = getKeys(trigEvt, filterName);
0257     if (firstFilter) {
0258       passingKeys = trigKeys;
0259       firstFilter = false;
0260     } else
0261       mergeTrigKeys(passingKeys, trigKeys, isAND_);
0262   }
0263   cleanTrigKeys(passingKeys);
0264 
0265   return passingKeys;
0266 }
0267 
0268 TrigObjTnPHistColl::TrigObjVarF::TrigObjVarF(std::string varName) : isAbs_(false) {
0269   //first look for "Abs" at the end of the string
0270   auto absPos = varName.rfind("Abs");
0271   if (absPos != std::string::npos && absPos + 3 == varName.size()) {
0272     isAbs_ = true;
0273     varName = varName.erase(absPos);
0274   }
0275   if (varName == "pt")
0276     varFunc_ = &trigger::TriggerObject::pt;
0277   else if (varName == "eta")
0278     varFunc_ = &trigger::TriggerObject::eta;
0279   else if (varName == "phi")
0280     varFunc_ = &trigger::TriggerObject::phi;
0281   else {
0282     std::ostringstream msg;
0283     msg << "var " << varName << " not recognised (use pt or p rather than et or e for speed!) ";
0284     if (isAbs_)
0285       msg << " varName was \"Abs\" suffex cleaned where it tried to remove \"Abs\" at the end of the variable name ";
0286     msg << __FILE__ << "," << __LINE__ << std::endl;
0287     throw cms::Exception("ConfigError") << msg.str();
0288   }
0289 }
0290 
0291 TrigObjTnPHistColl::HistFiller::HistFiller(const edm::ParameterSet& config)
0292     : localCuts_(config.getParameter<std::vector<edm::ParameterSet>>("localCuts")),
0293       var_(config.getParameter<std::string>("var")) {}
0294 
0295 edm::ParameterSetDescription TrigObjTnPHistColl::HistFiller::makePSetDescription() {
0296   edm::ParameterSetDescription desc;
0297   desc.addVPSet("localCuts", VarRangeCut<trigger::TriggerObject>::makePSetDescription());
0298   desc.add<std::string>("var", "pt");
0299   return desc;
0300 }
0301 
0302 void TrigObjTnPHistColl::HistFiller::operator()(const trigger::TriggerObject& probe,
0303                                                 float mass,
0304                                                 dqm::reco::MonitorElement* hist) const {
0305   if (localCuts_(probe))
0306     hist->Fill(var_(probe), mass);
0307 }
0308 
0309 TrigObjTnPHistColl::HistDefs::HistDefs(const edm::ParameterSet& config)
0310     : massBins_(convertToFloat(config.getParameter<std::vector<double>>("massBins"))) {
0311   const auto histConfigs = config.getParameter<std::vector<edm::ParameterSet>>("configs");
0312   for (const auto& histConfig : histConfigs) {
0313     histData_.emplace_back(Data(histConfig));
0314   }
0315 }
0316 
0317 edm::ParameterSetDescription TrigObjTnPHistColl::HistDefs::makePSetDescription() {
0318   edm::ParameterSetDescription desc;
0319   desc.addVPSet("configs", Data::makePSetDescription(), std::vector<edm::ParameterSet>());
0320   std::vector<double> massBins;
0321   for (float mass = 60; mass <= 120; mass += 1)
0322     massBins.push_back(mass);
0323   desc.add<std::vector<double>>("massBins", massBins);
0324   return desc;
0325 }
0326 
0327 std::vector<std::pair<TrigObjTnPHistColl::HistFiller, dqm::reco::MonitorElement*>>
0328 TrigObjTnPHistColl::HistDefs::bookHists(DQMStore::IBooker& iBooker,
0329                                         const std::string& name,
0330                                         const std::string& title) const {
0331   std::vector<std::pair<HistFiller, dqm::reco::MonitorElement*>> hists;
0332   hists.reserve(histData_.size());
0333   for (const auto& data : histData_) {
0334     hists.push_back({data.filler(), data.book(iBooker, name, title, massBins_)});
0335   }
0336   return hists;
0337 }
0338 
0339 TrigObjTnPHistColl::HistDefs::Data::Data(const edm::ParameterSet& config)
0340     : histFiller_(config.getParameter<edm::ParameterSet>("filler")),
0341       bins_(convertToFloat(config.getParameter<std::vector<double>>("bins"))),
0342       nameSuffex_(config.getParameter<std::string>("nameSuffex")),
0343       titleSuffex_(config.getParameter<std::string>("titleSuffex")) {}
0344 
0345 edm::ParameterSetDescription TrigObjTnPHistColl::HistDefs::Data::makePSetDescription() {
0346   edm::ParameterSetDescription desc;
0347   desc.add<edm::ParameterSetDescription>("filler", TrigObjTnPHistColl::HistFiller::makePSetDescription());
0348   desc.add<std::vector<double>>("bins", {-2.5, -1.5, 0, 1.5, 2.5});
0349   desc.add<std::string>("nameSuffex", "_eta");
0350   desc.add<std::string>("titleSuffex", ";#eta;mass [GeV]");
0351   return desc;
0352 }
0353 
0354 dqm::reco::MonitorElement* TrigObjTnPHistColl::HistDefs::Data::book(DQMStore::IBooker& iBooker,
0355                                                                     const std::string& name,
0356                                                                     const std::string& title,
0357                                                                     const std::vector<float>& massBins) const {
0358   return iBooker.book2D((name + nameSuffex_).c_str(),
0359                         (title + titleSuffex_).c_str(),
0360                         bins_.size() - 1,
0361                         bins_.data(),
0362                         massBins.size() - 1,
0363                         massBins.data());
0364 }
0365 
0366 void TrigObjTnPHistColl::HistColl::bookHists(DQMStore::IBooker& iBooker,
0367                                              const std::string& name,
0368                                              const std::string& title,
0369                                              const HistDefs& histDefs) {
0370   hists_ = histDefs.bookHists(iBooker, name, title);
0371 }
0372 
0373 void TrigObjTnPHistColl::HistColl::fill(const trigger::TriggerObject& probe, float mass) const {
0374   for (auto& hist : hists_) {
0375     hist.first(probe, mass, hist.second);
0376   }
0377 }
0378 
0379 void TrigObjTnPHistColl::ProbeData::bookHists(const std::string& tagName,
0380                                               DQMStore::IBooker& iBooker,
0381                                               const HistDefs& histDefs) {
0382   hists_.bookHists(iBooker, tagName + "_" + probeFilter_, tagName + "_" + probeFilter_, histDefs);
0383 }
0384 
0385 void TrigObjTnPHistColl::ProbeData::fill(const trigger::size_type tagKey,
0386                                          const trigger::TriggerEvent& trigEvt,
0387                                          const VarRangeCutColl<trigger::TriggerObject>& probeCuts) const {
0388   auto probeKeys = getKeys(trigEvt, probeFilter_);
0389   for (auto probeKey : probeKeys) {
0390     const trigger::TriggerObject& probe = trigEvt.getObjects()[probeKey];
0391     if (tagKey != probeKey && probeCuts(probe)) {
0392       const trigger::TriggerObject& tag = trigEvt.getObjects()[tagKey];
0393       auto massFunc = [](float pt1, float eta1, float phi1, float pt2, float eta2, float phi2) {
0394         return std::sqrt(2 * pt1 * pt2 * (std::cosh(eta1 - eta2) - std::cos(phi1 - phi2)));
0395       };
0396       float mass = massFunc(tag.pt(), tag.eta(), tag.phi(), probe.pt(), probe.eta(), probe.phi());
0397       hists_.fill(probe, mass);
0398     }
0399   }
0400 }