Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-05-26 01:15:34

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   std::unique(keys.begin(), keys.end());
0126   while (!keys.empty() && keys.back() == std::numeric_limits<trigger::size_type>::max()) {
0127     keys.pop_back();
0128   }
0129 }
0130 
0131 TrigObjTnPHistColl::FilterSelector::FilterSet::FilterSet(const edm::ParameterSet& config)
0132     : filters_(config.getParameter<std::vector<std::string>>("filters")), isAND_(config.getParameter<bool>("isAND")) {}
0133 
0134 TrigObjTnPHistColl::PathSelector::PathSelector(const edm::ParameterSet& config)
0135     : selectionStr_(config.getParameter<std::string>("selectionStr")),
0136       isANDForExpandedPaths_(config.getParameter<bool>("isANDForExpandedPaths")),
0137       verbose_(config.getParameter<int>("verbose")),
0138       isInited_(false) {}
0139 
0140 edm::ParameterSetDescription TrigObjTnPHistColl::PathSelector::makePSetDescription() {
0141   edm::ParameterSetDescription desc;
0142   desc.add<std::string>("selectionStr", std::string(""));
0143   desc.add<bool>("isANDForExpandedPaths", false);
0144   desc.add<int>("verbose", 1);
0145   return desc;
0146 }
0147 
0148 void TrigObjTnPHistColl::PathSelector::init(const HLTConfigProvider& hltConfig) {
0149   expandedSelStr_ = expandSelectionStr(selectionStr_, hltConfig, isANDForExpandedPaths_, verbose_);
0150   isInited_ = true;
0151   if (verbose_ > 1) {
0152     edm::LogInfo("TrigObjTnPHistColl::PathSelector") << "trigger selection string: \"" << expandedSelStr_ << "\"";
0153   }
0154 }
0155 
0156 bool TrigObjTnPHistColl::PathSelector::operator()(const edm::TriggerResults& trigResults,
0157                                                   const edm::TriggerNames& trigNames) const {
0158   if (selectionStr_.empty())
0159     return true;  //didnt specify any selection, default to pass
0160   else if (!isInited_) {
0161     edm::LogError("TrigObjTnPHistColl")
0162         << " error, TrigObjTnPHistColl::PathSelector is not initalised, returning false ";
0163     return false;
0164   } else if (expandedSelStr_.empty()) {
0165     //there was a problem parsing the expression, it was logged at the start, no need to do each run
0166     return false;
0167   } else {
0168     //as of 20/08/18, there is a bug in L1GtLogicParser, it must take a non-const std::string
0169     //as input because it overloads the constructor between const and non-const std::string
0170     //for like no reason. And the const version is broken, you have to use non-const
0171     //hence we make a non-const copy of the selection string
0172     std::string selStr = expandedSelStr_;
0173     L1GtLogicParser logicParser(selStr);
0174     for (auto& token : logicParser.operandTokenVector()) {
0175       const std::string& pathName = token.tokenName;
0176       auto pathIndex = trigNames.triggerIndex(pathName);
0177       bool accept = pathIndex < trigNames.size() ? trigResults.accept(pathIndex) : false;
0178       token.tokenResult = accept;
0179     }
0180     return logicParser.expressionResult();
0181   }
0182 }
0183 
0184 //a port of https://github.com/cms-sw/cmssw/blob/51eb73f59e2016d54618e2a8e19abab84fe33b47/CommonTools/TriggerUtils/src/GenericTriggerEventFlag.cc#L225-L238
0185 std::string TrigObjTnPHistColl::PathSelector::expandSelectionStr(const std::string& selStr,
0186                                                                  const HLTConfigProvider& hltConfig,
0187                                                                  bool isAND,
0188                                                                  int verbose) {
0189   std::string expandedSelStr(selStr);
0190   //it is very important to pass in as a non-const std::string, see comments else where
0191   L1GtLogicParser logicParser(expandedSelStr);
0192   for (const auto& token : logicParser.operandTokenVector()) {
0193     const std::string& pathName = token.tokenName;
0194     if (pathName.find('*') != std::string::npos) {
0195       std::string pathPatternExpanded = expandPath(pathName, hltConfig, isAND, verbose);
0196       expandedSelStr.replace(expandedSelStr.find(pathName), pathName.size(), pathPatternExpanded);
0197     }
0198   }
0199   return expandedSelStr;
0200 }
0201 
0202 //a port of GenericTriggerEventFlag::expandLogicalExpression
0203 //https://github.com/cms-sw/cmssw/blob/51eb73f59e2016d54618e2a8e19abab84fe33b47/CommonTools/TriggerUtils/src/GenericTriggerEventFlag.cc#L600-L632
0204 std::string TrigObjTnPHistColl::PathSelector::expandPath(const std::string& pathPattern,
0205                                                          const HLTConfigProvider& hltConfig,
0206                                                          bool isAND,
0207                                                          int verbose) {
0208   // Find matching entries in the menu
0209   const std::vector<std::string>& trigNames = hltConfig.triggerNames();
0210   std::vector<std::string> matched;
0211   const std::string versionWildcard("_v*");
0212   if (pathPattern.substr(pathPattern.size() - versionWildcard.size()) == versionWildcard) {
0213     const std::string pathPatternBase(pathPattern.substr(0, pathPattern.size() - versionWildcard.size()));
0214     matched = hltConfig.restoreVersion(trigNames, pathPatternBase);
0215   } else {
0216     matched = hltConfig.matched(trigNames, pathPattern);
0217   }
0218 
0219   if (matched.empty()) {
0220     if (verbose >= 1)
0221       edm::LogWarning("TrigObjTnPHistColl::PathSelector")
0222           << "pattern: \"" << pathPattern
0223           << "\" could not be resolved, please check your triggers are spelt correctly and present in the data you are "
0224              "running over";
0225     return "";
0226   }
0227 
0228   // Compose logical expression
0229   std::string expanded("(");
0230   for (unsigned iVers = 0; iVers < matched.size(); ++iVers) {
0231     if (iVers > 0)
0232       expanded.append(isAND ? " AND " : " OR ");
0233     expanded.append(matched.at(iVers));
0234   }
0235   expanded.append(")");
0236   if (verbose > 1) {
0237     edm::LogInfo("TrigObjTnPHistColl::PathSelector") << "Logical expression : \"" << pathPattern << "\"\n"
0238                                                      << "        expanded to:  \"" << expanded << "\"";
0239   }
0240   return expanded;
0241 }
0242 
0243 edm::ParameterSetDescription TrigObjTnPHistColl::FilterSelector::FilterSet::makePSetDescription() {
0244   edm::ParameterSetDescription desc;
0245   desc.add<std::vector<std::string>>("filters", std::vector<std::string>());
0246   desc.add<bool>("isAND", true);
0247   return desc;
0248 }
0249 
0250 const trigger::Keys TrigObjTnPHistColl::FilterSelector::FilterSet::getPassingKeys(
0251     const trigger::TriggerEvent& trigEvt) const {
0252   trigger::Keys passingKeys;
0253   bool firstFilter = true;
0254   for (const auto& filterName : filters_) {
0255     const trigger::Keys& trigKeys = getKeys(trigEvt, filterName);
0256     if (firstFilter) {
0257       passingKeys = trigKeys;
0258       firstFilter = false;
0259     } else
0260       mergeTrigKeys(passingKeys, trigKeys, isAND_);
0261   }
0262   cleanTrigKeys(passingKeys);
0263 
0264   return passingKeys;
0265 }
0266 
0267 TrigObjTnPHistColl::TrigObjVarF::TrigObjVarF(std::string varName) : isAbs_(false) {
0268   //first look for "Abs" at the end of the string
0269   auto absPos = varName.rfind("Abs");
0270   if (absPos != std::string::npos && absPos + 3 == varName.size()) {
0271     isAbs_ = true;
0272     varName = varName.erase(absPos);
0273   }
0274   if (varName == "pt")
0275     varFunc_ = &trigger::TriggerObject::pt;
0276   else if (varName == "eta")
0277     varFunc_ = &trigger::TriggerObject::eta;
0278   else if (varName == "phi")
0279     varFunc_ = &trigger::TriggerObject::phi;
0280   else {
0281     std::ostringstream msg;
0282     msg << "var " << varName << " not recognised (use pt or p rather than et or e for speed!) ";
0283     if (isAbs_)
0284       msg << " varName was \"Abs\" suffex cleaned where it tried to remove \"Abs\" at the end of the variable name ";
0285     msg << __FILE__ << "," << __LINE__ << std::endl;
0286     throw cms::Exception("ConfigError") << msg.str();
0287   }
0288 }
0289 
0290 TrigObjTnPHistColl::HistFiller::HistFiller(const edm::ParameterSet& config)
0291     : localCuts_(config.getParameter<std::vector<edm::ParameterSet>>("localCuts")),
0292       var_(config.getParameter<std::string>("var")) {}
0293 
0294 edm::ParameterSetDescription TrigObjTnPHistColl::HistFiller::makePSetDescription() {
0295   edm::ParameterSetDescription desc;
0296   desc.addVPSet("localCuts", VarRangeCut<trigger::TriggerObject>::makePSetDescription());
0297   desc.add<std::string>("var", "pt");
0298   return desc;
0299 }
0300 
0301 void TrigObjTnPHistColl::HistFiller::operator()(const trigger::TriggerObject& probe,
0302                                                 float mass,
0303                                                 dqm::reco::MonitorElement* hist) const {
0304   if (localCuts_(probe))
0305     hist->Fill(var_(probe), mass);
0306 }
0307 
0308 TrigObjTnPHistColl::HistDefs::HistDefs(const edm::ParameterSet& config)
0309     : massBins_(convertToFloat(config.getParameter<std::vector<double>>("massBins"))) {
0310   const auto histConfigs = config.getParameter<std::vector<edm::ParameterSet>>("configs");
0311   for (const auto& histConfig : histConfigs) {
0312     histData_.emplace_back(Data(histConfig));
0313   }
0314 }
0315 
0316 edm::ParameterSetDescription TrigObjTnPHistColl::HistDefs::makePSetDescription() {
0317   edm::ParameterSetDescription desc;
0318   desc.addVPSet("configs", Data::makePSetDescription(), std::vector<edm::ParameterSet>());
0319   std::vector<double> massBins;
0320   for (float mass = 60; mass <= 120; mass += 1)
0321     massBins.push_back(mass);
0322   desc.add<std::vector<double>>("massBins", massBins);
0323   return desc;
0324 }
0325 
0326 std::vector<std::pair<TrigObjTnPHistColl::HistFiller, dqm::reco::MonitorElement*>>
0327 TrigObjTnPHistColl::HistDefs::bookHists(DQMStore::IBooker& iBooker,
0328                                         const std::string& name,
0329                                         const std::string& title) const {
0330   std::vector<std::pair<HistFiller, dqm::reco::MonitorElement*>> hists;
0331   hists.reserve(histData_.size());
0332   for (const auto& data : histData_) {
0333     hists.push_back({data.filler(), data.book(iBooker, name, title, massBins_)});
0334   }
0335   return hists;
0336 }
0337 
0338 TrigObjTnPHistColl::HistDefs::Data::Data(const edm::ParameterSet& config)
0339     : histFiller_(config.getParameter<edm::ParameterSet>("filler")),
0340       bins_(convertToFloat(config.getParameter<std::vector<double>>("bins"))),
0341       nameSuffex_(config.getParameter<std::string>("nameSuffex")),
0342       titleSuffex_(config.getParameter<std::string>("titleSuffex")) {}
0343 
0344 edm::ParameterSetDescription TrigObjTnPHistColl::HistDefs::Data::makePSetDescription() {
0345   edm::ParameterSetDescription desc;
0346   desc.add<edm::ParameterSetDescription>("filler", TrigObjTnPHistColl::HistFiller::makePSetDescription());
0347   desc.add<std::vector<double>>("bins", {-2.5, -1.5, 0, 1.5, 2.5});
0348   desc.add<std::string>("nameSuffex", "_eta");
0349   desc.add<std::string>("titleSuffex", ";#eta;mass [GeV]");
0350   return desc;
0351 }
0352 
0353 dqm::reco::MonitorElement* TrigObjTnPHistColl::HistDefs::Data::book(DQMStore::IBooker& iBooker,
0354                                                                     const std::string& name,
0355                                                                     const std::string& title,
0356                                                                     const std::vector<float>& massBins) const {
0357   return iBooker.book2D((name + nameSuffex_).c_str(),
0358                         (title + titleSuffex_).c_str(),
0359                         bins_.size() - 1,
0360                         bins_.data(),
0361                         massBins.size() - 1,
0362                         massBins.data());
0363 }
0364 
0365 void TrigObjTnPHistColl::HistColl::bookHists(DQMStore::IBooker& iBooker,
0366                                              const std::string& name,
0367                                              const std::string& title,
0368                                              const HistDefs& histDefs) {
0369   hists_ = histDefs.bookHists(iBooker, name, title);
0370 }
0371 
0372 void TrigObjTnPHistColl::HistColl::fill(const trigger::TriggerObject& probe, float mass) const {
0373   for (auto& hist : hists_) {
0374     hist.first(probe, mass, hist.second);
0375   }
0376 }
0377 
0378 void TrigObjTnPHistColl::ProbeData::bookHists(const std::string& tagName,
0379                                               DQMStore::IBooker& iBooker,
0380                                               const HistDefs& histDefs) {
0381   hists_.bookHists(iBooker, tagName + "_" + probeFilter_, tagName + "_" + probeFilter_, histDefs);
0382 }
0383 
0384 void TrigObjTnPHistColl::ProbeData::fill(const trigger::size_type tagKey,
0385                                          const trigger::TriggerEvent& trigEvt,
0386                                          const VarRangeCutColl<trigger::TriggerObject>& probeCuts) const {
0387   auto probeKeys = getKeys(trigEvt, probeFilter_);
0388   for (auto probeKey : probeKeys) {
0389     const trigger::TriggerObject& probe = trigEvt.getObjects()[probeKey];
0390     if (tagKey != probeKey && probeCuts(probe)) {
0391       const trigger::TriggerObject& tag = trigEvt.getObjects()[tagKey];
0392       auto massFunc = [](float pt1, float eta1, float phi1, float pt2, float eta2, float phi2) {
0393         return std::sqrt(2 * pt1 * pt2 * (std::cosh(eta1 - eta2) - std::cos(phi1 - phi2)));
0394       };
0395       float mass = massFunc(tag.pt(), tag.eta(), tag.phi(), probe.pt(), probe.eta(), probe.phi());
0396       hists_.fill(probe, mass);
0397     }
0398   }
0399 }