Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:50:17

0001 #include <cppunit/extensions/HelperMacros.h>
0002 #include "CommonTools/Utils/interface/cutParser.h"
0003 #include "CommonTools/Utils/interface/StringCutObjectSelector.h"
0004 #include "DataFormats/TrackReco/interface/Track.h"
0005 #include "DataFormats/TrackerRecHit2D/interface/SiStripRecHit2D.h"
0006 #include "DataFormats/MuonReco/interface/Muon.h"
0007 #include <iostream>
0008 #include "FWCore/Reflection/interface/ObjectWithDict.h"
0009 #include "FWCore/Reflection/interface/TypeWithDict.h"
0010 #include <typeinfo>
0011 
0012 #include "DataFormats/GeometrySurface/interface/Surface.h"
0013 #include "DataFormats/GeometrySurface/interface/BoundPlane.h"
0014 #include <Geometry/CommonDetUnit/interface/GeomDet.h>
0015 
0016 // A fake Det class
0017 
0018 class MyDet : public TrackerGeomDet {
0019 public:
0020   MyDet(BoundPlane *bp) : TrackerGeomDet(bp) {}
0021 
0022   virtual DetId geographicalId() const { return DetId(); }
0023   virtual std::vector<const GeomDet *> components() const { return std::vector<const GeomDet *>(); }
0024 
0025   /// Which subdetector
0026   virtual SubDetector subDetector() const { return GeomDetEnumerators::DT; }
0027 };
0028 
0029 class testCutParser : public CppUnit::TestFixture {
0030   CPPUNIT_TEST_SUITE(testCutParser);
0031   CPPUNIT_TEST(checkAll);
0032   CPPUNIT_TEST_SUITE_END();
0033 
0034 public:
0035   void setUp() {}
0036   void tearDown() {}
0037   void checkAll();
0038   void check(const std::string &, bool);
0039   void checkHit(const std::string &, bool, const SiStripRecHit2D &);
0040   void checkMuon(const std::string &, bool, const reco::Muon &);
0041   reco::Track trk;
0042   SiStripRecHit2D hitOk, hitThrow;
0043   edm::ObjectWithDict o;
0044   reco::parser::SelectorPtr sel;
0045 };
0046 
0047 CPPUNIT_TEST_SUITE_REGISTRATION(testCutParser);
0048 
0049 void testCutParser::check(const std::string &cut, bool res) {
0050   for (int lazy = 0; lazy <= 1; ++lazy) {
0051     std::cerr << "parsing " << (lazy ? "lazy " : "") << "cut: \"" << cut << "\"" << std::endl;
0052     sel.reset();
0053     CPPUNIT_ASSERT(reco::parser::cutParser<reco::Track>(cut, sel, lazy));
0054     CPPUNIT_ASSERT((*sel)(o) == res);
0055     StringCutObjectSelector<reco::Track> select(cut, lazy);
0056     CPPUNIT_ASSERT(select(trk) == res);
0057   }
0058 }
0059 
0060 void testCutParser::checkHit(const std::string &cut, bool res, const SiStripRecHit2D &hit) {
0061   edm::TypeWithDict t(typeid(SiStripRecHit2D));
0062   o = edm::ObjectWithDict(t, const_cast<void *>(static_cast<const void *>(&hit)));
0063   for (int lazy = 0; lazy <= 1; ++lazy) {
0064     std::cerr << "parsing " << (lazy ? "lazy " : "") << "cut: \"" << cut << "\"" << std::endl;
0065     sel.reset();
0066     CPPUNIT_ASSERT(reco::parser::cutParser<SiStripRecHit2D>(cut, sel, lazy));
0067     CPPUNIT_ASSERT((*sel)(o) == res);
0068     StringCutObjectSelector<SiStripRecHit2D> select(cut, lazy);
0069     CPPUNIT_ASSERT(select(hit) == res);
0070   }
0071 }
0072 
0073 void testCutParser::checkMuon(const std::string &cut, bool res, const reco::Muon &mu) {
0074   edm::TypeWithDict t(typeid(reco::Muon));
0075   o = edm::ObjectWithDict(t, const_cast<void *>(static_cast<const void *>(&mu)));
0076   sel.reset();
0077   for (int lazy = 0; lazy <= 1; ++lazy) {
0078     std::cerr << "parsing " << (lazy ? "lazy " : "") << "cut: \"" << cut << "\"" << std::endl;
0079     CPPUNIT_ASSERT(reco::parser::cutParser<reco::Muon>(cut, sel, lazy));
0080     CPPUNIT_ASSERT((*sel)(o) == res);
0081     StringCutObjectSelector<reco::Muon> select(cut, lazy);
0082     CPPUNIT_ASSERT(select(mu) == res);
0083   }
0084 }
0085 
0086 void testCutParser::checkAll() {
0087   using namespace reco;
0088   const double chi2 = 20.0;
0089   const int ndof = 10;
0090   reco::Track::Point v(1, 2, 3);
0091   reco::Track::Vector p(0, 3, 10);
0092   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};
0093   reco::TrackBase::CovarianceMatrix cov(e, e + 15);
0094   trk = reco::Track(chi2, ndof, v, p, -1, cov);
0095   trk.setQuality(reco::Track::highPurity);
0096 
0097   GlobalPoint gp(0, 0, 0);
0098   BoundPlane *plane = new BoundPlane(gp, Surface::RotationType());
0099   MyDet mdet(plane);
0100 
0101   hitOk = SiStripRecHit2D(LocalPoint(1, 1), LocalError(1, 1, 1), mdet, SiStripRecHit2D::ClusterRef());
0102 
0103   edm::TypeWithDict t(typeid(reco::Track));
0104   o = edm::ObjectWithDict(t, &trk);
0105 
0106   std::cerr << "Track pt: " << trk.pt() << std::endl;
0107   // note: pt = 3, charge = -1
0108   check("", true);
0109   check("  ", true);
0110   check("pt", true);
0111   check("px", false);
0112   check("pt > 2", true);
0113   check("charge < 0", true);
0114   check("pt < 2", false);
0115   check("pt >= 2", true);
0116   check("pt <= 2", false);
0117   check("pt = 3", true);
0118   check("pt == 3", true);
0119   check("pt != 3", false);
0120   check("! pt == 3", false);
0121   check("2.9 < pt < 3.1", true);
0122   check("pt > 2 & charge < 0", true);
0123   check("pt > 2 && charge < 0", true);
0124   check("pt < 2 & charge < 0", false);
0125   check("pt > 2 & charge > 0", false);
0126   check("pt < 2 & charge > 0", false);
0127   check("pt > 2 || charge > 0", true);
0128   check("pt > 2 | charge > 0", true);
0129   check("pt > 2 | charge < 0", true);
0130   check("pt < 2 | charge < 0", true);
0131   check("pt < 2 | charge > 0", false);
0132   check("pt > 2 | charge > 0 | pt < 2", true);
0133   check("pt > 2 | charge > 0 | (pt < 2 && charge < 0)", true);
0134   check("pt > 2 | charge < 0 | (pt < 2 && charge < 0)", true);
0135   check("pt > 2 | charge > 0 | (pt < 2 && charge > 0)", true);
0136   check("(pt) > 2", true);
0137   check("-pt < -2", true);
0138   check("3.9 < pt + 1 < 4.1", true);
0139   check("1.9 < pt - 1 < 2.1", true);
0140   check("5.9 < 2 * pt < 6.1", true);
0141   check("0.9 < pt / 3 < 1.1", true);
0142   check("8.9 < pt ^ 2 < 9.1", true);
0143   check("26.9 < 3 * pt ^ 2 < 27.1", true);
0144   check("27.9 < 3 * pt ^ 2 + 1 < 28.1", true);
0145   check(" 0.99 < sin( phi ) < 1.01", true);
0146   check(" -0.01 < cos( phi ) < 0.01", true);
0147   check(" 8.9 < pow( pt, 2 ) < 9.1", true);
0148   check("( 0.99 < sin( phi ) < 1.01 ) & ( -0.01 < cos( phi ) < 0.01 )", true);
0149   check("( 3.9 < pt + 1 < 4.1 ) | ( pt < 2 )", true);
0150   check(" pt = 3 &  pt > 2 | pt < 2", true);
0151   check("( ( pt = 3 &  pt > 2 ) | pt < 2 ) & 26.9 < 3 * pt ^ 2 < 27.1", true);
0152   check("! pt > 2", false);
0153   check("! pt < 2", true);
0154   check("! (( 0.99 < sin( phi ) < 1.01 ) & ( -0.01 < cos( phi ) < 0.01 ))", false);
0155   check("pt && pt > 1", true);
0156   // check trailing space
0157   check("pt > 2 ", true);
0158 
0159   // check bit tests
0160   check("test_bit(7, 0)", true);
0161   check("test_bit(7, 2)", true);
0162   check("test_bit(7, 3)", false);
0163   check("test_bit(4, 0)", false);
0164   check("test_bit(4, 2)", true);
0165   check("test_bit(4, 3)", false);
0166 
0167   // check quality
0168   check("quality('highPurity')", true);
0169   check("quality('loose')", false);
0170   check("quality('tight')", false);
0171   check("quality('confirmed')", false);
0172   check("quality('goodIterative')", true);
0173   check("quality('looseSetWithPV')", false);
0174   check("quality('highPuritySetWithPV')", false);
0175   check("quality('highPuritySetWithPV' )", false);
0176   check("quality( 'highPuritySetWithPV')", false);
0177   check("quality( 'highPuritySetWithPV' )", false);
0178 
0179   // check handling of errors
0180   //   first those who are the same in lazy and non lazy parsing
0181   for (int lazy = 0; lazy <= 1; ++lazy) {
0182     sel.reset();
0183     CPPUNIT_ASSERT(!reco::parser::cutParser<reco::Track>("1abc", sel, lazy));
0184     sel.reset();
0185     CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("(pt < 1", sel, lazy), edm::Exception);
0186     sel.reset();
0187     CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("pt < #", sel, lazy), edm::Exception);
0188     sel.reset();
0189     CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("pt <> 5", sel, lazy), edm::Exception);
0190     sel.reset();
0191     CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("cos( pt < .5", sel, lazy), edm::Exception);
0192     sel.reset();
0193     CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>(" 2 * (pt + 1 < .5", sel, lazy), edm::Exception);
0194     // These don't throw, but they return false.
0195     sel.reset();
0196     CPPUNIT_ASSERT(!reco::parser::cutParser<reco::Track>("pt() pt < .5", sel, lazy));
0197     sel.reset();
0198     CPPUNIT_ASSERT(!reco::parser::cutParser<reco::Track>("pt pt < .5", sel, lazy));
0199     // This throws or return false depending on the parsing:
0200     // without lazy parsing, it complains about non-existing method 'cos'
0201     sel.reset();
0202     if (lazy)
0203       CPPUNIT_ASSERT(!reco::parser::cutParser<reco::Track>("cos pt < .5", sel, lazy));
0204     else
0205       CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("cos pt < .5", sel, lazy), edm::Exception);
0206   }
0207   // then those which are specific to non lazy parsing
0208   sel.reset();
0209   CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("doesNotExist < 1", sel), edm::Exception);
0210   sel.reset();
0211   CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("pt.pt < 1", sel), edm::Exception);
0212   // and afterwards check that in lazy parsing they throw at runtime
0213   sel.reset();
0214   CPPUNIT_ASSERT(
0215       reco::parser::cutParser<reco::Track>("doesNotExist < 1", sel, true));  // with lazy parsing this doesn't throw
0216   CPPUNIT_ASSERT_THROW((*sel)(o), reco::parser::Exception);                  // but it throws here!
0217   sel.reset();
0218   CPPUNIT_ASSERT(reco::parser::cutParser<reco::Track>("pt.pt < 1", sel, true));  // same for this
0219   CPPUNIT_ASSERT_THROW((*sel)(o), reco::parser::Exception);                      // it throws wen called
0220 
0221   sel.reset();
0222   CPPUNIT_ASSERT_THROW(reco::parser::cutParser<reco::Track>("quality('notAnEnum')", sel, false), edm::Exception);
0223 
0224   // check hits (for re-implemented virtual functions and exception handling)
0225   CPPUNIT_ASSERT(hitOk.hasPositionAndError());
0226   checkHit("hasPositionAndError", true, hitOk);
0227   CPPUNIT_ASSERT(!hitThrow.hasPositionAndError());
0228   checkHit("hasPositionAndError", false, hitThrow);
0229   CPPUNIT_ASSERT(hitOk.localPosition().x() == 1);
0230   checkHit(".99 < localPosition.x < 1.01", true, hitOk);
0231   checkHit(".99 < localPosition.x < 1.01", false, hitThrow);
0232 
0233   // check underscores (would be better to build your own stub...)
0234   checkHit("cluster.isNull()", true, hitOk);
0235   checkHit("cluster_strip.isNull()", true, hitOk);
0236   checkHit("cluster.isNonnull()", false, hitOk);
0237   checkHit("cluster_strip.isNonnull()", false, hitOk);
0238 
0239   // check short cirtcuit logics
0240   CPPUNIT_ASSERT(hitOk.hasPositionAndError() && (hitOk.localPosition().x() == 1));
0241   CPPUNIT_ASSERT(!(hitThrow.hasPositionAndError() && (hitThrow.localPosition().x() == 1)));
0242   checkHit("hasPositionAndError && (localPosition.x = 1)", true, hitOk);
0243   checkHit("hasPositionAndError && (localPosition.x = 1)", false, hitThrow);
0244   CPPUNIT_ASSERT((!hitOk.hasPositionAndError()) || (hitOk.localPosition().x() == 1));
0245   CPPUNIT_ASSERT((!hitThrow.hasPositionAndError()) || (hitThrow.localPosition().x() == 1));
0246   checkHit("!hasPositionAndError || (localPosition.x = 1)", true, hitOk);
0247   checkHit("!hasPositionAndError || (localPosition.x = 1)", true, hitThrow);
0248 }