Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:45:44

0001 #include <cppunit/extensions/HelperMacros.h>
0002 #include "CommonTools/Utils/interface/expressionParser.h"
0003 #include "CommonTools/Utils/interface/StringObjectFunction.h"
0004 #include "DataFormats/TrackReco/interface/Track.h"
0005 #include "DataFormats/TrackReco/interface/TrackExtra.h"
0006 #include "DataFormats/Candidate/interface/CompositeCandidate.h"
0007 #include "DataFormats/Candidate/interface/LeafCandidate.h"
0008 #include "DataFormats/PatCandidates/interface/Jet.h"
0009 #include "DataFormats/PatCandidates/interface/Muon.h"
0010 #include "CommonTools/Utils/interface/StringToEnumValue.h"
0011 
0012 #include <iostream>
0013 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0014 #include "FWCore/Reflection/interface/TypeWithDict.h"
0015 #include <typeinfo>
0016 #include "DataFormats/Common/interface/TestHandle.h"
0017 
0018 class testExpressionParser : public CppUnit::TestFixture {
0019   CPPUNIT_TEST_SUITE(testExpressionParser);
0020   CPPUNIT_TEST(testStringToEnum);
0021   CPPUNIT_TEST(checkAll);
0022   CPPUNIT_TEST_SUITE_END();
0023 
0024 public:
0025   void setUp() {}
0026   void tearDown() {}
0027   void checkAll();
0028   void testStringToEnum();
0029   void checkTrack(const std::string &, double);
0030   void checkCandidate(const std::string &, double, bool lazy = false);
0031   void checkJet(const std::string &, double);
0032   void checkMuon(const std::string &, double);
0033   reco::Track trk;
0034   reco::CompositeCandidate cand;
0035   edm::ObjectWithDict o;
0036   reco::parser::ExpressionPtr expr;
0037   pat::Jet jet;
0038   pat::Muon muon;
0039 };
0040 
0041 CPPUNIT_TEST_SUITE_REGISTRATION(testExpressionParser);
0042 
0043 void testExpressionParser::checkTrack(const std::string &expression, double x) {
0044   for (int lazyMode = 0; lazyMode <= 1; ++lazyMode) {
0045     std::cerr << "checking " << (lazyMode ? "lazy " : "") << "expression: \"" << expression << "\"" << std::flush;
0046     expr.reset();
0047     CPPUNIT_ASSERT(reco::parser::expressionParser<reco::Track>(expression, expr, lazyMode));
0048     CPPUNIT_ASSERT(expr.get() != 0);
0049     double res = expr->value(o);
0050     StringObjectFunction<reco::Track> f(expression, lazyMode);
0051     CPPUNIT_ASSERT(fabs(f(trk) - res) < 1.e-6);
0052     CPPUNIT_ASSERT(fabs(f(trk) - x) < 1.e-6);
0053     std::cerr << " = " << res << std::endl;
0054   }
0055 }
0056 
0057 void testExpressionParser::checkCandidate(const std::string &expression, double x, bool lazyMode) {
0058   std::cerr << "checking " << (lazyMode ? "lazy " : "") << "expression: \"" << expression << "\"" << std::flush;
0059   expr.reset();
0060   CPPUNIT_ASSERT(reco::parser::expressionParser<reco::Candidate>(expression, expr, lazyMode));
0061   CPPUNIT_ASSERT(expr.get() != 0);
0062   double res = 0;
0063   CPPUNIT_ASSERT_NO_THROW(res = expr->value(o));
0064   StringObjectFunction<reco::Candidate> f(expression, lazyMode);
0065   CPPUNIT_ASSERT(fabs(f(cand) - res) < 1.e-6);
0066   CPPUNIT_ASSERT(fabs(f(cand) - x) < 1.e-6);
0067   std::cerr << " = " << res << std::endl;
0068 }
0069 
0070 void testExpressionParser::checkJet(const std::string &expression, double x) {
0071   for (int lazyMode = 0; lazyMode <= 1; ++lazyMode) {
0072     std::cerr << "checking " << (lazyMode ? "lazy " : "") << "expression: \"" << expression << "\"" << std::flush;
0073     expr.reset();
0074     CPPUNIT_ASSERT(reco::parser::expressionParser<pat::Jet>(expression, expr, lazyMode));
0075     CPPUNIT_ASSERT(expr.get() != 0);
0076     double res = expr->value(o);
0077     StringObjectFunction<pat::Jet> f(expression, lazyMode);
0078     CPPUNIT_ASSERT(fabs(f(jet) - res) < 1.e-6);
0079     CPPUNIT_ASSERT(fabs(f(jet) - x) < 1.e-6);
0080     std::cerr << " = " << res << std::endl;
0081   }
0082 }
0083 
0084 void testExpressionParser::checkMuon(const std::string &expression, double x) {
0085   for (int lazyMode = 0; lazyMode <= 1; ++lazyMode) {
0086     std::cerr << "checking " << (lazyMode ? "lazy " : "") << "expression: \"" << expression << "\"" << std::flush;
0087     expr.reset();
0088     CPPUNIT_ASSERT(reco::parser::expressionParser<pat::Muon>(expression, expr, lazyMode));
0089     CPPUNIT_ASSERT(expr.get() != 0);
0090     double res = expr->value(o);
0091     StringObjectFunction<pat::Muon> f(expression, lazyMode);
0092     std::cerr << " = " << x << " (reference), " << res << " (bare), " << f(muon) << " (full)" << std::endl;
0093     CPPUNIT_ASSERT(fabs(f(muon) - res) < 1.e-6);
0094     CPPUNIT_ASSERT(fabs(f(muon) - x) < 1.e-6);
0095   }
0096 }
0097 
0098 void testExpressionParser::testStringToEnum() {
0099   std::cout << "Testing reco::Muon::ArbitrationType SegmentArbitration" << std::endl;
0100   CPPUNIT_ASSERT_EQUAL(StringToEnumValue<reco::Muon::ArbitrationType>("SegmentArbitration"),
0101                        int(reco::Muon::SegmentArbitration));
0102   std::cout << "Testing reco::TrackBase::TrackQuality (tight, highPurity)" << std::endl;
0103   std::vector<std::string> algos;
0104   algos.push_back("tight");
0105   algos.push_back("highPurity");
0106   std::vector<int> algoValues = StringToEnumValue<reco::TrackBase::TrackQuality>(algos);
0107   CPPUNIT_ASSERT(algoValues.size() == 2);
0108   CPPUNIT_ASSERT_EQUAL(algoValues[0], int(reco::TrackBase::tight));
0109   CPPUNIT_ASSERT_EQUAL(algoValues[1], int(reco::TrackBase::highPurity));
0110 }
0111 
0112 void testExpressionParser::checkAll() {
0113   using namespace reco;
0114   const double chi2 = 20.0;
0115   const int ndof = 10;
0116   reco::Track::Point v(1, 2, 3);
0117   reco::Track::Vector p(5, 3, 10);
0118   double e[] = {1.1, 1.2, 2.2, 1.3, 2.3, 3.3, 1.4, 2.4, 3.4, 4.4, 1.5, 2.5, 3.5, 4.5, 5.5};
0119   reco::TrackBase::CovarianceMatrix cov(e, e + 15);
0120   cov(0, 0) = 1.2345;
0121   cov(1, 0) = 123.456;
0122   cov(1, 1) = 5.4321;
0123   trk = reco::Track(chi2, ndof, v, p, -1, cov);
0124 
0125   edm::ProductID const pid(1);
0126   reco::TrackExtraCollection trkExtras;
0127   reco::Track::Point outerV(100, 200, 300), innerV(v);
0128   reco::Track::Vector outerP(0.5, 3.5, 10.5), innerP(p);
0129   reco::Track::CovarianceMatrix outerC, innerC;
0130   unsigned int outerId = 123, innerId = 456;
0131   reco::TrackExtra trkExtra(outerV, outerP, true, innerV, innerP, true, outerC, outerId, innerC, innerId, anyDirection);
0132   trkExtras.push_back(trkExtra);
0133   edm::TestHandle<reco::TrackExtraCollection> h(&trkExtras, pid);
0134   reco::TrackExtraRef trkExtraRef(h, 0);
0135   trk.setExtra(trkExtraRef);
0136   trk.setAlgorithm(reco::Track::pixelPairStep);
0137   {
0138     edm::TypeWithDict t(typeid(reco::Track));
0139     o = edm::ObjectWithDict(t, &trk);
0140     checkTrack("pt", trk.pt());
0141     checkTrack("charge", trk.charge());
0142     checkTrack("pt/3", trk.pt() / 3);
0143     checkTrack("covariance(0, 0)", trk.covariance(0, 0));
0144     checkTrack("covariance(1, 0)", trk.covariance(1, 0));
0145     checkTrack("covariance(1, 1)", trk.covariance(1, 1));
0146     checkTrack("momentum.x", trk.momentum().x());
0147     checkTrack("hitPattern.numberOfValidHits", trk.hitPattern().numberOfValidHits());
0148     checkTrack("extra.outerPhi", trk.extra()->outerPhi());
0149     checkTrack("referencePoint.R", trk.referencePoint().R());
0150     checkTrack("algo", reco::Track::pixelPairStep);
0151     checkTrack("quality('highPurity')", trk.quality(reco::TrackBase::highPurity));
0152     checkTrack("cosh(theta)", cosh(trk.theta()));
0153     checkTrack("hypot(px, py)", hypot(trk.px(), trk.py()));
0154     checkTrack("?ndof<0?1:0", trk.ndof() < 0 ? 1 : 0);
0155     checkTrack("?ndof=10?1:0", trk.ndof() == 10 ? 1 : 0);
0156   }
0157   reco::Candidate::LorentzVector p1(1, 2, 3, 4);
0158   reco::Candidate::LorentzVector p2(1.1, -2.5, 4.3, 13.7);
0159   reco::LeafCandidate c1(+1, p1);
0160   reco::LeafCandidate c2(-1, p2);
0161   cand.addDaughter(c1);
0162   cand.addDaughter(c2);
0163   CPPUNIT_ASSERT(cand.numberOfDaughters() == 2);
0164   CPPUNIT_ASSERT(cand.daughter(0) != 0);
0165   CPPUNIT_ASSERT(cand.daughter(1) != 0);
0166   {
0167     edm::TypeWithDict t(typeid(reco::Candidate));
0168     o = edm::ObjectWithDict(t, &cand);
0169     // these can be checked in both modes
0170     for (int lazyMode = 0; lazyMode <= 1; ++lazyMode) {
0171       checkCandidate("numberOfDaughters", cand.numberOfDaughters(), lazyMode);
0172       checkCandidate("daughter(0).isStandAloneMuon", cand.daughter(0)->isStandAloneMuon(), lazyMode);
0173       checkCandidate("daughter(1).isStandAloneMuon", cand.daughter(1)->isStandAloneMuon(), lazyMode);
0174       checkCandidate("daughter(0).pt", cand.daughter(0)->pt(), lazyMode);
0175       checkCandidate("daughter(1).pt", cand.daughter(1)->pt(), lazyMode);
0176       checkCandidate(
0177           "min(daughter(0).pt, daughter(1).pt)", std::min(cand.daughter(0)->pt(), cand.daughter(1)->pt()), lazyMode);
0178       checkCandidate(
0179           "max(daughter(0).pt, daughter(1).pt)", std::max(cand.daughter(0)->pt(), cand.daughter(1)->pt()), lazyMode);
0180       checkCandidate("deltaPhi(daughter(0).phi, daughter(1).phi)",
0181                      reco::deltaPhi(cand.daughter(0)->phi(), cand.daughter(1)->phi()));
0182       // check also opposite order, to see that the sign is correct
0183       checkCandidate("deltaPhi(daughter(1).phi, daughter(0).phi)",
0184                      reco::deltaPhi(cand.daughter(1)->phi(), cand.daughter(0)->phi()));
0185       checkCandidate("deltaR(daughter(0).eta, daughter(0).phi, daughter(1).eta, daughter(1).phi)",
0186                      reco::deltaR(*cand.daughter(0), *cand.daughter(1)));
0187     }
0188     // these can be checked only in lazy mode
0189     checkCandidate("name.empty()", true, true);
0190     checkCandidate("roles.size()", 0, true);
0191   }
0192 
0193   std::vector<reco::LeafCandidate> cands;
0194   cands.push_back(c1);
0195   cands.push_back(c2);
0196   edm::TestHandle<std::vector<reco::LeafCandidate> > constituentsHandle(&cands, edm::ProductID(42));
0197   reco::Jet::Constituents constituents;
0198   constituents.push_back(reco::Jet::Constituent(constituentsHandle, 0));
0199   constituents.push_back(reco::Jet::Constituent(constituentsHandle, 1));
0200   reco::CaloJet::Specific caloSpecific;
0201   caloSpecific.mMaxEInEmTowers = 0.5;
0202   jet = pat::Jet(reco::CaloJet(p1 + p2, reco::Jet::Point(), caloSpecific, constituents));
0203   CPPUNIT_ASSERT(jet.nConstituents() == 2);
0204   CPPUNIT_ASSERT(jet.nCarrying(1.0) == 2);
0205   CPPUNIT_ASSERT(jet.nCarrying(0.1) == 1);
0206   {
0207     edm::TypeWithDict t(typeid(pat::Jet));
0208     o = edm::ObjectWithDict(t, &jet);
0209     checkJet("nCarrying(1.0)", jet.nCarrying(1.0));
0210     checkJet("nCarrying(0.1)", jet.nCarrying(0.1));
0211   }
0212   {
0213     // Check a method that starts with the same string as a predefined function
0214     CPPUNIT_ASSERT(jet.maxEInEmTowers() == 0.5);
0215     checkJet("maxEInEmTowers", jet.maxEInEmTowers());
0216   }
0217 
0218   std::pair<std::string, float> bp;
0219   bp = std::pair<std::string, float>("aaa", 1.0);
0220   jet.addBDiscriminatorPair(bp);
0221   bp = std::pair<std::string, float>("b c", 2.0);
0222   jet.addBDiscriminatorPair(bp);
0223   bp = std::pair<std::string, float>("d ", 3.0);
0224   jet.addBDiscriminatorPair(bp);
0225   CPPUNIT_ASSERT(jet.bDiscriminator("aaa") == 1.0);
0226   CPPUNIT_ASSERT(jet.bDiscriminator("b c") == 2.0);
0227   CPPUNIT_ASSERT(jet.bDiscriminator("d ") == 3.0);
0228   CPPUNIT_ASSERT(jet.getPairDiscri().size() == 3);
0229   {
0230     edm::TypeWithDict t(typeid(pat::Jet));
0231     o = edm::ObjectWithDict(t, &jet);
0232     checkJet("bDiscriminator(\"aaa\")", jet.bDiscriminator("aaa"));
0233     checkJet("bDiscriminator('aaa')", jet.bDiscriminator("aaa"));
0234     checkJet("bDiscriminator(\"b c\")", jet.bDiscriminator("b c"));
0235     checkJet("bDiscriminator(\"d \")", jet.bDiscriminator("d "));
0236   }
0237 
0238   muon = pat::Muon(reco::Muon(+1, p1 + p2));
0239   muon.setUserIso(2.0);
0240   muon.setUserIso(42.0, 1);
0241   CPPUNIT_ASSERT(muon.userIso() == 2.0);
0242   CPPUNIT_ASSERT(muon.userIso(0) == 2.0);
0243   CPPUNIT_ASSERT(muon.userIso(1) == 42.0);
0244   reco::IsoDeposit dep;
0245   dep.addCandEnergy(2.0);
0246   CPPUNIT_ASSERT(dep.candEnergy() == 2.0);
0247   muon.setIsoDeposit(pat::TrackIso, dep);
0248   CPPUNIT_ASSERT(muon.trackIsoDeposit() != 0);
0249   CPPUNIT_ASSERT(muon.trackIsoDeposit()->candEnergy() == 2.0);
0250   pat::TriggerObjectStandAlone tosa;
0251   tosa.addPathName("HLT_Something");
0252   muon.addTriggerObjectMatch(tosa);
0253   {
0254     edm::TypeWithDict t(typeid(pat::Muon));
0255     o = edm::ObjectWithDict(t, &muon);
0256     checkMuon("userIso", muon.userIso());
0257     checkMuon("userIso()", muon.userIso());
0258     checkMuon("userIso(0)", muon.userIso(0));
0259     checkMuon("userIso(1)", muon.userIso(1));
0260     checkMuon("trackIsoDeposit.candEnergy", muon.trackIsoDeposit()->candEnergy());
0261     //checkMuon("isoDeposit('TrackIso').candEnergy", muon.isoDeposit(pat::TrackIso)->candEnergy());
0262     checkMuon("triggerObjectMatchesByPath('HLT_Something').size()", 1);
0263     for (int b = 0; b <= 1; ++b) {
0264       std::cout << "Check for leaks in the " << (b ? "Lazy" : "standard") << " string parser" << std::endl;
0265       expr.reset();
0266       reco::parser::expressionParser<pat::Muon>("triggerObjectMatchesByPath('HLT_Something').size()", expr, b);
0267       expr->value(o);
0268     }
0269   }
0270   reco::CandidatePtrVector ptrOverlaps;
0271   ptrOverlaps.push_back(reco::CandidatePtr(constituentsHandle, 0));
0272   muon.setOverlaps("test", ptrOverlaps);
0273   CPPUNIT_ASSERT(muon.hasOverlaps("test"));
0274   CPPUNIT_ASSERT(muon.overlaps("test").size() == 1);
0275   CPPUNIT_ASSERT(muon.overlaps("test")[0]->pt() == c1.pt());
0276   {
0277     edm::TypeWithDict t(typeid(pat::Muon));
0278     o = edm::ObjectWithDict(t, &muon);
0279     checkMuon("overlaps('test')[0].pt", muon.overlaps("test")[0]->pt());
0280   }
0281 }