File indexing completed on 2023-03-17 10:45:44
0001 #include <cppunit/extensions/HelperMacros.h>
0002
0003 #include "CommonTools/Utils/interface/ExpressionEvaluator.h"
0004 #include "CommonTools/Utils/interface/ExpressionEvaluatorTemplates.h"
0005
0006 #include "DataFormats/TrackReco/interface/Track.h"
0007 #include "DataFormats/TrackReco/interface/TrackExtra.h"
0008 #include "DataFormats/Candidate/interface/CompositeCandidate.h"
0009 #include "DataFormats/Candidate/interface/LeafCandidate.h"
0010 #include "DataFormats/PatCandidates/interface/Jet.h"
0011 #include "DataFormats/PatCandidates/interface/Muon.h"
0012
0013 class testExpressionEvaluator : public CppUnit::TestFixture {
0014 CPPUNIT_TEST_SUITE(testExpressionEvaluator);
0015 CPPUNIT_TEST(checkAll);
0016 CPPUNIT_TEST_SUITE_END();
0017
0018 public:
0019 testExpressionEvaluator() {}
0020 ~testExpressionEvaluator() {}
0021 void checkAll();
0022 };
0023
0024 CPPUNIT_TEST_SUITE_REGISTRATION(testExpressionEvaluator);
0025
0026 #include <iostream>
0027 namespace {
0028 void checkCandidate(reco::LeafCandidate const &cand, const std::string &expression, double x) {
0029 std::cerr << "testing " << expression << std::endl;
0030 try {
0031
0032 std::string sexpr = "double eval(reco::LeafCandidate const& cand) const override { return ";
0033 sexpr += expression + ";}";
0034
0035 reco::ExpressionEvaluator eval(
0036 "CommonTools/CandUtils", "reco::ValueOnObject<reco::LeafCandidate>", sexpr.c_str());
0037
0038 reco::ValueOnObject<reco::LeafCandidate> const *expr = eval.expr<reco::ValueOnObject<reco::LeafCandidate>>();
0039 CPPUNIT_ASSERT(expr);
0040
0041 CPPUNIT_ASSERT(std::abs(expr->eval(cand) - x) < 1.e-6);
0042 } catch (cms::Exception const &e) {
0043
0044 std::cerr << e.what() << std::endl;
0045 CPPUNIT_ASSERT("ExpressionEvaluator threw" == 0);
0046 }
0047 }
0048
0049 std::vector<reco::LeafCandidate> generate() {
0050 reco::Candidate::LorentzVector p1(10, -10, -10, 15);
0051 reco::Candidate::LorentzVector incr(0, 3, 3, 0);
0052
0053 int sign = 1;
0054 std::vector<reco::LeafCandidate> ret;
0055 for (int i = 0; i < 10; ++i) {
0056 ret.emplace_back(sign, p1);
0057 sign = -sign;
0058 p1 += incr;
0059 }
0060 return ret;
0061 }
0062
0063 struct MyAnalyzer {
0064 using Selector = reco::MaskCollection<reco::LeafCandidate>;
0065 explicit MyAnalyzer(std::string const &cut) {
0066 std::string sexpr = "void eval(Collection const & c, Mask & m) const override{";
0067 sexpr += "\n auto cut = [](reco::LeafCandidate const & cand){ return " + cut + ";};\n";
0068 sexpr += "mask(c,m,cut); }";
0069 std::cerr << "testing " << sexpr << std::endl;
0070 try {
0071 reco::ExpressionEvaluator eval(
0072 "CommonTools/CandUtils", "reco::MaskCollection<reco::LeafCandidate>", sexpr.c_str());
0073 m_selector = eval.expr<Selector>();
0074 CPPUNIT_ASSERT(m_selector);
0075 } catch (cms::Exception const &e) {
0076 std::cerr << e.what() << std::endl;
0077 CPPUNIT_ASSERT("ExpressionEvaluator threw" == 0);
0078 }
0079 }
0080
0081 void analyze() const {
0082 auto inputColl = generate();
0083 Selector::Collection cands;
0084 cands.reserve(inputColl.size());
0085 for (auto const &c : inputColl)
0086 cands.push_back(&c);
0087 Selector::Mask mask;
0088 m_selector->eval(cands, mask);
0089 CPPUNIT_ASSERT(2 == std::count(mask.begin(), mask.end(), true));
0090 int ind = 0;
0091 cands.erase(
0092 std::remove_if(
0093 cands.begin(), cands.end(), [&](Selector::Collection::value_type const &) { return !mask[ind++]; }),
0094 cands.end());
0095 CPPUNIT_ASSERT(2 == cands.size());
0096 }
0097
0098 Selector const *m_selector = nullptr;
0099 };
0100
0101 struct MyAnalyzer2 {
0102 using Selector = reco::SelectInCollection<reco::LeafCandidate>;
0103 explicit MyAnalyzer2(std::string const &cut) {
0104 std::string sexpr = "void eval(Collection & c) const override{";
0105 sexpr += "\n auto cut = [](reco::LeafCandidate const & cand){ return " + cut + ";};\n";
0106 sexpr += "select(c,cut); }";
0107 std::cerr << "testing " << sexpr << std::endl;
0108 try {
0109 reco::ExpressionEvaluator eval(
0110 "CommonTools/CandUtils", "reco::SelectInCollection<reco::LeafCandidate>", sexpr.c_str());
0111 m_selector = eval.expr<Selector>();
0112 CPPUNIT_ASSERT(m_selector);
0113 } catch (cms::Exception const &e) {
0114 std::cerr << e.what() << std::endl;
0115 CPPUNIT_ASSERT("ExpressionEvaluator threw" == 0);
0116 }
0117 }
0118
0119 void analyze() const {
0120 auto inputColl = generate();
0121 Selector::Collection cands;
0122 cands.reserve(inputColl.size());
0123 for (auto const &c : inputColl)
0124 cands.push_back(&c);
0125 m_selector->eval(cands);
0126 CPPUNIT_ASSERT(2 == cands.size());
0127 }
0128
0129 Selector const *m_selector = nullptr;
0130 };
0131
0132 }
0133
0134 void testExpressionEvaluator::checkAll() {
0135 reco::CompositeCandidate cand;
0136
0137 reco::Candidate::LorentzVector p1(1, 2, 3, 4);
0138 reco::Candidate::LorentzVector p2(1.1, -2.5, 4.3, 13.7);
0139 reco::LeafCandidate c1(+1, p1);
0140 reco::LeafCandidate c2(-1, p2);
0141 cand.addDaughter(c1);
0142 cand.addDaughter(c2);
0143 CPPUNIT_ASSERT(cand.numberOfDaughters() == 2);
0144 CPPUNIT_ASSERT(cand.daughter(0) != 0);
0145 CPPUNIT_ASSERT(cand.daughter(1) != 0);
0146 {
0147 checkCandidate(cand, "cand.numberOfDaughters()", cand.numberOfDaughters());
0148 checkCandidate(cand, "cand.daughter(0)->isStandAloneMuon()", cand.daughter(0)->isStandAloneMuon());
0149 checkCandidate(cand, "cand.daughter(1)->isStandAloneMuon()", cand.daughter(1)->isStandAloneMuon());
0150 checkCandidate(cand, "cand.daughter(0)->pt()", cand.daughter(0)->pt());
0151 checkCandidate(cand, "cand.daughter(1)->pt()", cand.daughter(1)->pt());
0152 checkCandidate(cand,
0153 "std::min(cand.daughter(0)->pt(), cand.daughter(1)->pt())",
0154 std::min(cand.daughter(0)->pt(), cand.daughter(1)->pt()));
0155 checkCandidate(cand,
0156 "std::max(cand.daughter(0)->pt(), cand.daughter(1)->pt())",
0157 std::max(cand.daughter(0)->pt(), cand.daughter(1)->pt()));
0158 checkCandidate(cand,
0159 "reco::deltaPhi(cand.daughter(0)->phi(), cand.daughter(1)->phi())",
0160 reco::deltaPhi(cand.daughter(0)->phi(), cand.daughter(1)->phi()));
0161
0162 checkCandidate(cand,
0163 "reco::deltaPhi(cand.daughter(1)->phi(), cand.daughter(0)->phi())",
0164 reco::deltaPhi(cand.daughter(1)->phi(), cand.daughter(0)->phi()));
0165 checkCandidate(
0166 cand, "reco::deltaR(*cand.daughter(0), *cand.daughter(1))", reco::deltaR(*cand.daughter(0), *cand.daughter(1)));
0167 }
0168
0169 MyAnalyzer analyzer("cand.pt()>15 & std::abs(cand.eta())<2");
0170 analyzer.analyze();
0171
0172 MyAnalyzer2 analyzer2("cand.pt()>15 & std::abs(cand.eta())<2");
0173 analyzer2.analyze();
0174
0175
0176
0177 std::vector<reco::LeafCandidate> cands;
0178 cands.push_back(c1);
0179 cands.push_back(c2);
0180 edm::TestHandle<std::vector<reco::LeafCandidate>> constituentsHandle(&cands, edm::ProductID(42));
0181 reco::Jet::Constituents constituents;
0182 constituents.push_back(reco::Jet::Constituent(constituentsHandle, 0));
0183 constituents.push_back(reco::Jet::Constituent(constituentsHandle, 1));
0184 reco::CaloJet::Specific caloSpecific;
0185 caloSpecific.mMaxEInEmTowers = 0.5;
0186 pat::Jet jet(reco::CaloJet(p1 + p2, reco::Jet::Point(), caloSpecific, constituents));
0187 {
0188 std::string expression = "jet.userData<math::XYZVector>(\"my2int\")";
0189 std::cerr << "testing " << expression << std::endl;
0190 try {
0191
0192 std::string sexpr = "math::XYZVector const * operator()(pat::Jet const& jet) const override { return ";
0193 sexpr += expression + ";}";
0194
0195 auto const *expr =
0196 reco_expressionEvaluator("CommonTools/RecoUtils",
0197 SINGLE_ARG(reco::genericExpression<math::XYZVector const *, pat::Jet const &>),
0198 sexpr);
0199 CPPUNIT_ASSERT(expr);
0200
0201 CPPUNIT_ASSERT((*expr)(jet) == nullptr);
0202 jet.addUserData("my2int", math::XYZVector(-2, -1, 2));
0203 CPPUNIT_ASSERT(jet.userData<math::XYZVector>("my2int")->z() == 2);
0204 std::cout << "now expr eval" << std::endl;
0205 CPPUNIT_ASSERT((*expr)(jet)->z() == 2);
0206 } catch (cms::Exception const &e) {
0207
0208 std::cerr << e.what() << std::endl;
0209 CPPUNIT_ASSERT("ExpressionEvaluator threw" == 0);
0210 }
0211 }
0212 }