/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
DQM/TrackingMonitor/src/PackedCandidateTrackValidator.cc
1 168 строк
53 KB
camolezi
removed boost dependency
01 июл 2020, 01:41
01 июл 2020, 01:41
96b2850
Код
Авторство
О чём код?
#include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/Utilities/interface/VecArray.h" #include "FWCore/Utilities/interface/isFinite.h" #include "DQMServices/Core/interface/DQMEDAnalyzer.h" #include "DQMServices/Core/interface/DQMStore.h" #include "DataFormats/Common/interface/Association.h" #include "DataFormats/TrackReco/interface/Track.h" #include "DataFormats/PatCandidates/interface/PackedCandidate.h" #include "DataFormats/Math/interface/libminifloat.h" #include "DataFormats/Math/interface/liblogintpack.h" #include "DataFormats/VertexReco/interface/Vertex.h" #include "DataFormats/VertexReco/interface/VertexFwd.h" #include "DataFormats/Math/interface/deltaPhi.h" #include "DataFormats/TrackerCommon/interface/TrackerTopology.h" #include "Geometry/Records/interface/TrackerTopologyRcd.h" #include <iomanip> namespace { using dqm::reco::DQMStore; using dqm::reco::MonitorElement; template <typename T> void fillNoFlow(MonitorElement* me, T val) { auto h = me->getTH1(); const auto xaxis = h->GetXaxis(); if (val <= xaxis->GetXmin()) h->AddBinContent(xaxis->GetFirst()); else if (val >= xaxis->GetXmax()) h->AddBinContent(xaxis->GetLast()); else h->Fill(val); } class HitPatternPrinter { public: explicit HitPatternPrinter(const reco::Track& trk) : track(trk) {} void print(std::ostream& os) const { const reco::HitPattern& p = track.hitPattern(); for (int i = 0; i < p.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++i) { uint32_t hit = p.getHitPattern(reco::HitPattern::TRACK_HITS, i); detLayer(os, p, hit); if (p.missingHitFilter(hit)) { os << "(miss)"; } else if (p.inactiveHitFilter(hit)) { os << "(inact)"; } else if (p.badHitFilter(hit)) { os << "(bad)"; } os << " "; } if (p.numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) > 0) { os << "lost inner "; for (int i = 0; i < p.numberOfAllHits(reco::HitPattern::MISSING_INNER_HITS); ++i) { uint32_t hit = p.getHitPattern(reco::HitPattern::MISSING_INNER_HITS, i); detLayer(os, p, hit); if (p.missingHitFilter(hit)) { os << "(miss)"; } else if (p.inactiveHitFilter(hit)) { os << "(inact)"; } } } if (p.numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) > 0) { os << "lost outer "; for (int i = 0; i < p.numberOfAllHits(reco::HitPattern::MISSING_OUTER_HITS); ++i) { uint32_t hit = p.getHitPattern(reco::HitPattern::MISSING_OUTER_HITS, i); detLayer(os, p, hit); if (p.missingHitFilter(hit)) { os << "(miss)"; } else if (p.inactiveHitFilter(hit)) { os << "(inact)"; } } } } private: static void detLayer(std::ostream& os, const reco::HitPattern& p, uint32_t hit) { if (p.pixelBarrelHitFilter(hit)) { os << "BPIX"; } else if (p.pixelEndcapHitFilter(hit)) { os << "FPIX"; } else if (p.stripTIBHitFilter(hit)) { os << "TIB"; } else if (p.stripTIDHitFilter(hit)) { os << "TID"; } else if (p.stripTOBHitFilter(hit)) { os << "TOB"; } else if (p.stripTECHitFilter(hit)) { os << "TEC"; } os << p.getLayer(hit); } const reco::Track& track; }; std::ostream& operator<<(std::ostream& os, const HitPatternPrinter& hpp) { hpp.print(os); return os; } class TrackAlgoPrinter { public: explicit TrackAlgoPrinter(const reco::Track& trk) : track(trk) {} void print(std::ostream& os) const { edm::VecArray<reco::TrackBase::TrackAlgorithm, reco::TrackBase::algoSize> algos; for (int ialgo = 0; ialgo < reco::TrackBase::algoSize; ++ialgo) { auto algo = static_cast<reco::TrackBase::TrackAlgorithm>(ialgo); if (track.isAlgoInMask(algo)) { algos.push_back(algo); } } os << "algo " << reco::TrackBase::algoName(track.algo()); if (track.originalAlgo() != track.algo()) os << " originalAlgo " << reco::TrackBase::algoName(track.originalAlgo()); if (algos.size() > 1) { os << " algoMask"; for (auto algo : algos) { os << " " << reco::TrackBase::algoName(algo); } } } private: const reco::Track& track; }; std::ostream& operator<<(std::ostream& os, const TrackAlgoPrinter& tap) { tap.print(os); return os; } double diffRelative(double a, double b) { return (a - b) / b; } class LogIntHelper { public: LogIntHelper(double lmin, double lmax) : lmin_(lmin), lmax_(lmax) {} class UnderOverflow { public: UnderOverflow(double largestValue, double smallestValue, std::function<double(double)> modifyUnpack) : unpackedLargestValue_(modifyUnpack ? modifyUnpack(largestValue) : largestValue), unpackedSmallestValue_(modifyUnpack ? modifyUnpack(smallestValue) : smallestValue) {} bool compatibleWithUnderflow(double value) const { return value == unpackedSmallestValue_; } void printNonOkUnderflow(std::ostream& os) const { os << " (not min " << unpackedSmallestValue_ << ")"; } bool compatibleWithOverflow(double value) const { return value == unpackedLargestValue_; } void printNonOkOverflow(std::ostream& os) const { os << " (not max " << unpackedLargestValue_ << ")"; } private: // narrow to float to compare apples to apples with values from // PackedCandidate (even though the final comparison is done in // double) const float unpackedLargestValue_; const float unpackedSmallestValue_; }; static std::string maxName() { return "max"; } static std::string minName() { return "min"; } UnderOverflow underOverflowHelper(double value, std::function<double(double)> modifyUnpack) const { return UnderOverflow( largestValue(), value >= 0 ? smallestPositiveValue() : std::abs(smallestNegativeValue()), modifyUnpack); } double largestValue() const { return logintpack::unpack8log(127, lmin_, lmax_); } static bool wouldBeDenorm(double value) { return false; } // lessThan means closer to zero bool lessThanSmallestValue(double value) const { if (value >= 0) return value < smallestPositiveValue(); else return value > smallestNegativeValue(); } double smallestPositiveValue() const { return logintpack::unpack8log(logintpack::smallestPositive, lmin_, lmax_); } double smallestNegativeValue() const { return logintpack::unpack8log(logintpack::smallestNegative, lmin_, lmax_); } private: const double lmin_; const double lmax_; }; class Float16Helper { public: class UnderOverflow { public: static void printNonOkUnderflow(std::ostream& os) { os << " (not 0)"; } static bool compatibleWithUnderflow(double value) { return value == 0.0; } static void printNonOkOverflow(std::ostream& os) { os << " (not inf)"; } static bool compatibleWithOverflow(double value) { return edm::isNotFinite(value); } }; static std::string maxName() { return "inf"; } static std::string minName() { return "0"; } static UnderOverflow underOverflowHelper(double value, std::function<double(double)>) { return UnderOverflow(); } static double largestValue() { return MiniFloatConverter::max32RoundedToMax16(); } static bool wouldBeDenorm(double value) { const float valuef = static_cast<float>(value); return valuef >= MiniFloatConverter::denorm_min() && valuef < MiniFloatConverter::min(); } static bool lessThanSmallestValue(double value) { return std::abs(value) < smallestValue(); } static double smallestValue() { return MiniFloatConverter::denorm_min(); } }; enum class RangeStatus { inrange = 0, inrange_signflip = 1, denormal = 2, underflow_OK = 3, underflow_notOK = 4, overflow_OK = 5, overflow_notOK = 6 }; bool isInRange(RangeStatus status) { return status == RangeStatus::inrange || status == RangeStatus::denormal; } template <typename T> class PackedValueCheckResult { public: PackedValueCheckResult(RangeStatus status, double diff, double pcvalue, double trackvalue, double rangeMin, double rangeMax, const typename T::UnderOverflow& underOverflow) : diff_(diff), pcvalue_(pcvalue), trackvalue_(trackvalue), rangeMin_(rangeMin), rangeMax_(rangeMax), status_(status), underOverflow_(underOverflow) {} RangeStatus status() const { return status_; } double diff() const { return diff_; } bool outsideExpectedRange() const { if (status_ == RangeStatus::inrange) return diff_ < rangeMin_ || diff_ > rangeMax_; // denormal is considered as "in range" regardless of the expected range return status_ == RangeStatus::underflow_notOK || status_ == RangeStatus::overflow_notOK || status_ == RangeStatus::inrange_signflip; } void print(std::ostream& os) const { if (outsideExpectedRange()) os << "!! "; os << "(" << rangeMin_ << "," << rangeMax_ << ") "; os << diff_ << " " << pcvalue_; if (status_ == RangeStatus::underflow_OK || status_ == RangeStatus::underflow_notOK) { os << " (underflow) "; if (status_ == RangeStatus::underflow_notOK) underOverflow_.printNonOkUnderflow(os); } else if (status_ == RangeStatus::overflow_OK || status_ == RangeStatus::overflow_notOK) { os << " (overflow) "; if (status_ == RangeStatus::overflow_notOK) underOverflow_.printNonOkOverflow(os); } else if (status_ == RangeStatus::denormal) os << " (denormal)"; os << " " << trackvalue_; } private: const double diff_; const double pcvalue_; const double trackvalue_; const double rangeMin_; const double rangeMax_; const RangeStatus status_; const typename T::UnderOverflow underOverflow_; }; struct Range { Range(double mi, double ma) : min(mi), max(ma) {} const double min, max; }; struct RangeAbs { RangeAbs(double val) : min(-val), max(val) {} const double min, max; }; template <typename T> class PackedValueCheck { public: template <typename R, typename... Args> PackedValueCheck(const R& range, Args&&... args) : helper_(std::forward<Args>(args)...), rangeMin_(range.min), rangeMax_(range.max) {} void book(DQMStore::IBooker& iBooker, const std::string& name, const std::string& title, int nbins, double min, double max, int flow_nbins, double flow_min, double flow_max) { hInrange = iBooker.book1D(name, title, nbins, min, max); hUnderOverflowSign = iBooker.book1D(name + "UnderOverFlowSign", title + " with over- and underflow, and sign flip", flow_nbins, flow_min, flow_max); hStatus = iBooker.book1D(name + "Status", title + " status", 7, -0.5, 6.5); hStatus->setBinLabel(1, "In range"); hStatus->setBinLabel(2, "In range, sign flip"); hStatus->setBinLabel(3, "Denormal"); hStatus->setBinLabel(4, "Underflow, PC is " + T::minName()); hStatus->setBinLabel(5, "Underflow, PC is not " + T::minName()); hStatus->setBinLabel(6, "Overflow, PC is " + T::maxName()); hStatus->setBinLabel(7, "Overflow, PC is not " + T::maxName()); } PackedValueCheckResult<T> fill(double pcvalue, double trackvalue, std::function<double(double)> modifyPack = std::function<double(double)>(), std::function<double(double)> modifyUnpack = std::function<double(double)>()) { const auto diff = diffRelative(pcvalue, trackvalue); const auto tmpSigned = modifyPack ? modifyPack(trackvalue) : trackvalue; const auto tmp = std::abs(tmpSigned); const auto underOverflow = helper_.underOverflowHelper(tmpSigned, modifyUnpack); RangeStatus status; if (tmp > helper_.largestValue()) { fillNoFlow(hUnderOverflowSign, diff); if (underOverflow.compatibleWithOverflow(std::abs(pcvalue))) { status = RangeStatus::overflow_OK; } else { status = RangeStatus::overflow_notOK; } } else if (helper_.lessThanSmallestValue(tmpSigned)) { fillNoFlow(hUnderOverflowSign, diff); if (underOverflow.compatibleWithUnderflow(std::abs(pcvalue))) { status = RangeStatus::underflow_OK; } else { status = RangeStatus::underflow_notOK; } } else { //Check if both numbers have same sign or both are zero. if (pcvalue * trackvalue > 0 || pcvalue == trackvalue) { if (T::wouldBeDenorm(tmp)) { status = RangeStatus::denormal; } else { status = RangeStatus::inrange; } fillNoFlow(hInrange, diff); } else { fillNoFlow(hUnderOverflowSign, diff); status = RangeStatus::inrange_signflip; } } hStatus->Fill(static_cast<int>(status)); return PackedValueCheckResult<T>(status, diff, pcvalue, trackvalue, rangeMin_, rangeMax_, underOverflow); } private: const T helper_; const double rangeMin_; const double rangeMax_; MonitorElement* hInrange; MonitorElement* hUnderOverflowSign; MonitorElement* hStatus; }; template <typename T> std::ostream& operator<<(std::ostream& os, const PackedValueCheckResult<T>& res) { res.print(os); return os; } } // namespace class PackedCandidateTrackValidator : public DQMEDAnalyzer { public: PackedCandidateTrackValidator(const edm::ParameterSet& pset); ~PackedCandidateTrackValidator() override; void bookHistograms(DQMStore::IBooker&, edm::Run const&, edm::EventSetup const&) override; void analyze(const edm::Event&, const edm::EventSetup&) override; static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); private: edm::EDGetTokenT<edm::View<reco::Track>> tracksToken_; edm::EDGetTokenT<reco::VertexCollection> verticesToken_; edm::EDGetTokenT<edm::Association<pat::PackedCandidateCollection>> trackToPackedCandidateToken_; std::string rootFolder_; bool debug_; enum { sf_AllTracks = 0, sf_AssociatedToPC = 1, sf_PCIsCharged = 2, sf_PCHasTrack = 3, sf_PCIsNotElectron = 4, sf_PCHasHits = 5, sf_PCNdofNot0 = 6, sf_NoMissingInnerHits = 7 }; MonitorElement* h_selectionFlow; MonitorElement* h_diffVx; MonitorElement* h_diffVy; MonitorElement* h_diffVz; MonitorElement* h_diffNormalizedChi2; MonitorElement* h_diffNdof; MonitorElement* h_diffCharge; MonitorElement* h_diffIsHighPurity; MonitorElement* h_diffPt; MonitorElement* h_diffEta; MonitorElement* h_diffPhi; PackedValueCheck<Float16Helper> h_diffDxyAssocPV; PackedValueCheck<Float16Helper> h_diffDzAssocPV; MonitorElement* h_diffDxyPV; MonitorElement* h_diffDzPV; MonitorElement* h_diffTrackDxyAssocPV; MonitorElement* h_diffTrackDzAssocPV; PackedValueCheck<LogIntHelper> h_diffCovQoverpQoverp; PackedValueCheck<LogIntHelper> h_diffCovLambdaLambda; PackedValueCheck<LogIntHelper> h_diffCovLambdaDsz; PackedValueCheck<LogIntHelper> h_diffCovPhiPhi; PackedValueCheck<LogIntHelper> h_diffCovPhiDxy; PackedValueCheck<Float16Helper> h_diffCovDxyDxy; PackedValueCheck<Float16Helper> h_diffCovDxyDsz; PackedValueCheck<Float16Helper> h_diffCovDszDsz; MonitorElement* h_diffDxyError; MonitorElement* h_diffDszError; MonitorElement* h_diffDzError; MonitorElement* h_diffTrackDxyError; MonitorElement* h_diffTrackDzError; MonitorElement* h_diffPtError; MonitorElement* h_diffEtaError; MonitorElement* h_diffNumberOfPixelLayers; MonitorElement* h_diffNumberOfStripLayers; MonitorElement* h_diffNumberOfPixelHits; MonitorElement* h_diffNumberOfHits; MonitorElement* h_diffLostInnerHits; MonitorElement* h_diffHitPatternPixelLayersWithMeasurement; MonitorElement* h_diffHitPatternTrackerLayersWithMeasurement; MonitorElement* h_diffHitPatternStripLayersWithMeasurement; MonitorElement* h_diffHitPatternNumberOfValidPixelHits; MonitorElement* h_diffHitPatternNumberOfValidHits; MonitorElement* h_diffHitPatternNumberOfLostInnerHits; MonitorElement* h_diffHitPatternHasValidHitInFirstPixelBarrel; MonitorElement* h_numberPixelLayersOverMax; MonitorElement* h_numberStripLayersOverMax; MonitorElement* h_numberLayersOverMax; MonitorElement* h_numberPixelHitsOverMax; MonitorElement* h_numberStripHitsOverMax; MonitorElement* h_numberHitsOverMax; }; PackedCandidateTrackValidator::PackedCandidateTrackValidator(const edm::ParameterSet& iConfig) : tracksToken_(consumes<edm::View<reco::Track>>(iConfig.getUntrackedParameter<edm::InputTag>("tracks"))), verticesToken_(consumes<reco::VertexCollection>(iConfig.getUntrackedParameter<edm::InputTag>("vertices"))), trackToPackedCandidateToken_(consumes<edm::Association<pat::PackedCandidateCollection>>( iConfig.getUntrackedParameter<edm::InputTag>("trackToPackedCandidateAssociation"))), rootFolder_(iConfig.getUntrackedParameter<std::string>("rootFolder")), debug_(iConfig.getUntrackedParameter<bool>("debug")), h_diffDxyAssocPV(RangeAbs(0.001)), h_diffDzAssocPV(RangeAbs(0.001)), h_diffCovQoverpQoverp(Range(-1e-6, 0.13), -15, 0), // despite of ceil in pack, there is rounding in double->float h_diffCovLambdaLambda( Range(-1e-6, 0.13), -20, -5), // despite of ceil in pack, there is rounding in double->float h_diffCovLambdaDsz(RangeAbs(0.13), -17, -4), h_diffCovPhiPhi(RangeAbs(0.13), -15, 0), h_diffCovPhiDxy(RangeAbs(0.13), -17, -4), h_diffCovDxyDxy(RangeAbs(0.001)), h_diffCovDxyDsz(RangeAbs(0.001)), h_diffCovDszDsz(RangeAbs(0.001)) {} PackedCandidateTrackValidator::~PackedCandidateTrackValidator() {} void PackedCandidateTrackValidator::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; desc.addUntracked<edm::InputTag>("tracks", edm::InputTag("generalTracks")); desc.addUntracked<edm::InputTag>("vertices", edm::InputTag("offlinePrimaryVertices")); desc.addUntracked<edm::InputTag>("trackToPackedCandidateAssociation", edm::InputTag("packedPFCandidates")); desc.addUntracked<std::string>("rootFolder", "Tracking/PackedCandidate"); desc.addUntracked<bool>("debug", false); descriptions.add("packedCandidateTrackValidator", desc); } void PackedCandidateTrackValidator::bookHistograms(DQMStore::IBooker& iBooker, edm::Run const&, edm::EventSetup const&) { iBooker.setCurrentFolder(rootFolder_); h_selectionFlow = iBooker.book1D("selectionFlow", "Track selection flow", 8, -0.5, 7.5); h_selectionFlow->setBinLabel(1, "All tracks"); h_selectionFlow->setBinLabel(2, "Associated to PackedCandidate"); h_selectionFlow->setBinLabel(3, "PC is charged"), h_selectionFlow->setBinLabel(4, "PC has track"); h_selectionFlow->setBinLabel(5, "PC is not electron"); h_selectionFlow->setBinLabel(6, "PC has hits"); h_selectionFlow->setBinLabel(7, "PC ndof != 0"); h_selectionFlow->setBinLabel(8, "Track: no missing inner hits"); constexpr int diffBins = 50; h_diffVx = iBooker.book1D("diffVx", "PackedCandidate::bestTrack() - reco::Track in vx()", diffBins, -0.2, 0.2); // not equal h_diffVy = iBooker.book1D("diffVy", "PackedCandidate::bestTrack() - reco::Track in vy()", diffBins, -0.2, 0.2); // not equal h_diffVz = iBooker.book1D("diffVz", "PackedCandidate::bestTrack() - reco::Track in vz()", diffBins, -0.4, 0.4); // not equal h_diffNormalizedChi2 = iBooker.book1D("diffNormalizedChi2", "PackedCandidate::bestTrack() - reco::Track in normalizedChi2()", 30, -1.5, 1.5); // expected difference in -1...0 h_diffNdof = iBooker.book1D( "diffNdof", "PackedCandidate::bestTrack() - reco::Track in ndof()", 33, -30.5, 2.5); // to monitor the difference h_diffCharge = iBooker.book1D( "diffCharge", "PackedCandidate::bestTrack() - reco::Track in charge()", 5, -2.5, 2.5); // expect equality h_diffIsHighPurity = iBooker.book1D("diffIsHighPurity", "PackedCandidate::bestTrack() - reco::Track in quality(highPurity)", 3, -1.5, 1.5); // expect equality h_diffPt = iBooker.book1D("diffPt", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in pt()", diffBins, -1.1, 1.1); // not equal, keep h_diffEta = iBooker.book1D( "diffEta", "PackedCandidate::bestTrack() - reco::Track in eta()", diffBins, -0.001, 0.001); // not equal, keep h_diffPhi = iBooker.book1D("diffPhi", "PackedCandidate::bestTrack() - reco::Track in phi()", diffBins, -0.0005, 0.0005); // expect equality within precision h_diffDxyAssocPV.book(iBooker, "diffDxyAssocPV", "(PackedCandidate::dxy() - reco::Track::dxy(assocPV))/reco::Track", 40, -0.001, 0.001, // expect equality within precision 50, -0.5, 0.5); h_diffDzAssocPV.book(iBooker, "diffDzAssocPV", "(PackedCandidate::dzAssociatedPV() - reco::Track::dz(assocPV))/reco::Track", 40, -0.001, 0.001, // expect equality within precision 50, -0.5, 0.5); h_diffDxyPV = iBooker.book1D("diffDxyPV", "(PackedCandidate::dxy(PV) - reco::Track::dxy(PV))/reco::Track", diffBins, -0.01, 0.01); // expect equality within precision (worse than assocPV) h_diffDzPV = iBooker.book1D("diffDzPV", "(PackedCandidate::dz(PV) - reco::Track::dz(PV))/reco::Track", diffBins, -0.01, 0.01); // expect equality wihtin precision (worse than assocPV) h_diffTrackDxyAssocPV = iBooker.book1D("diffTrackDxyAssocPV", "(PackedCandidate::bestTrack()::dxy(assocPV)) - reco::Track::dxy(assocPV))/reco::Track", diffBins, -0.01, 0.01); // not equal h_diffTrackDzAssocPV = iBooker.book1D("diffTrackDzAssocPV", "(PackedCandidate::bestTrack()::dz(assocPV)) - reco::Track::dz(assocPV))/reco::Track", diffBins, -0.01, 0.01); // not equal h_diffCovQoverpQoverp.book(iBooker, "diffCovQoverpQoverp", "(PackedCandidate::bestTrack() - reco::Track)/reco::track in cov(qoverp, qoverp)", 40, -0.05, 0.15, // expect equality within precision (worst precision is exp(1/128*15) =~ 12 % 50, -0.5, 0.5); h_diffCovLambdaLambda.book( iBooker, "diffCovLambdaLambda", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(lambda, lambda)", 40, -0.05, 0.15, // expect equality within precision worst precision is exp(1/128*(20-5)) =~ 12 % (multiplied by pt^2 in packing & unpacking) 50, -0.5, 0.5); h_diffCovLambdaDsz.book(iBooker, "diffCovLambdaDsz", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(lambda, dsz)", 60, -0.15, 0.15, // expect equality within precision, worst precision is exp(1/128*(17-4) =~ 11 % 50, -1, 1); h_diffCovPhiPhi.book( iBooker, "diffCovPhiPhi", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(phi, phi)", 40, -0.05, 0.15, // expect equality within precision worst precision is exp(1/128*(20-5)) =~ 12 % (multiplied by pt^2 in packing & unpacking) 50, -0.5, 0.5); h_diffCovPhiDxy.book(iBooker, "diffCovPhiDxy", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(phi, dxy)", 60, -0.15, 0.15, // expect equality within precision, wors precision is exp(1/128)*(17-4) =~ 11 % 50, -1, 1); h_diffCovDxyDxy.book(iBooker, "diffCovDxyDxy", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(dxy, dxy)", 40, -0.001, 0.001, 50, -0.1, 0.1); h_diffCovDxyDsz.book(iBooker, "diffCovDxyDsz", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(dxy, dsz)", 40, -0.001, 0.001, // expect equality within precision 50, -0.5, 0.5); h_diffCovDszDsz.book(iBooker, "diffCovDszDsz", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in cov(dsz, dsz)", 40, -0.001, 0.001, // expect equality within precision 50, -0.1, 0.1); h_diffDxyError = iBooker.book1D("diffDxyError", "(PackedCandidate::dxyError() - reco::Track::dxyError())/reco::Track", 40, -0.001, 0.001); // expect equality within precision h_diffDszError = iBooker.book1D("diffDszError", "(PackedCandidate::dzError() - reco::Track::dszError())/reco::Track", 40, -0.001, 0.001); // ideally, not equal, but for now they are h_diffDzError = iBooker.book1D("diffDzError", "(PackedCandidate::dzError() - reco::Track::dzError())/reco::Track", 40, -0.001, 0.001); // expect equality within precision (not currently the case) h_diffTrackDxyError = iBooker.book1D("diffTrackDxyError", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in dxyError()", 40, -0.001, 0.001); // expect equality within precision h_diffTrackDzError = iBooker.book1D("diffTrackDzError", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in dzError()", 40, -0.05, 0.05); // not equal h_diffPtError = iBooker.book1D("diffPtError", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in ptError()", diffBins, -1.1, 1.1); // not equal h_diffEtaError = iBooker.book1D("diffEtaError", "(PackedCandidate::bestTrack() - reco::Track)/reco::Track in etaError()", 60, -0.15, 0.15); // not equal h_diffNumberOfPixelLayers = iBooker.book1D( "diffNumberOfPixelLayers", "PackedCandidate::pixelLayersWithMeasurement() - reco::Track::hitPattern::pixelLayersWithMeasurement()", 5, -2.5, 2.5); // expect equality h_diffNumberOfStripLayers = iBooker.book1D( "diffNumberOfStripLayers", "PackedCandidate::stripLayersWithMeasurement() - reco::Track::hitPattern::stripLayersWithMeasurement()", 5, -2.5, 2.5); // expect equality h_diffNumberOfPixelHits = iBooker.book1D("diffNumberOfPixelHits", "PackedCandidate::numberOfPixelHits() - reco::Track::hitPattern::numberOfValidPixelHits()", 5, -2.5, 2.5); // expect equality h_diffNumberOfHits = iBooker.book1D("diffNumberOfHits", "PackedCandidate::numberHits() - reco::Track::hitPattern::numberOfValidHits()", 5, -2.5, 2.5); // expect equality h_diffLostInnerHits = iBooker.book1D("diffLostInnerHits", "PackedCandidate::lostInnerHits() - reco::Track::hitPattern::numberOfLostHits(MISSING_INNER_HITS)", 5, -2.5, 2.5); // expect equality h_diffHitPatternPixelLayersWithMeasurement = iBooker.book1D("diffHitPatternPixelLayersWithMeasurement", "PackedCandidate::bestTrack() - reco::Track in hitPattern::pixelLayersWithMeasurement()", 13, -10.5, 2.5); // not equal h_diffHitPatternStripLayersWithMeasurement = iBooker.book1D("diffHitPatternStripLayersWithMeasurement", "PackedCandidate::bestTrack() - reco::Track in hitPattern::stripLayersWithMeasurement()", 13, -10.5, 2.5); // not equal h_diffHitPatternTrackerLayersWithMeasurement = iBooker.book1D("diffHitPatternTrackerLayersWithMeasurement", "PackedCandidate::bestTrack() - reco::Track in hitPattern::trackerLayersWithMeasurement()", 13, -10.5, 2.5); // not equal h_diffHitPatternNumberOfValidPixelHits = iBooker.book1D("diffHitPatternNumberOfValidPixelHits", "PackedCandidate::bestTrack() - reco::Track in hitPattern::numberOfValidPixelHits()", 13, -10.5, 2.5); // not equal h_diffHitPatternNumberOfValidHits = iBooker.book1D("diffHitPatternNumberOfValidHits", "PackedCandidate::bestTrack() - reco::Track in hitPattern::numberOfValidHits()", 13, -10.5, 2.5); // not equal h_diffHitPatternNumberOfLostInnerHits = iBooker.book1D("diffHitPatternNumberOfLostPixelHits", "PackedCandidate::bestTrack() - reco::Track in hitPattern::numberOfLostHits(MISSING_INNER_HITS)", 13, -10.5, 2.5); // not equal h_diffHitPatternHasValidHitInFirstPixelBarrel = iBooker.book1D("diffHitPatternHasValidHitInFirstPixelBarrel", "PackedCandidate::bestTrack() - reco::Track in hitPattern::hasValidHitInFirstPixelBarrel", 3, -1.5, 1.5); // expect equality h_numberPixelLayersOverMax = iBooker.book1D( "numberPixelLayersOverMax", "Number of pixel layers over the maximum of PackedCandidate", 10, 0, 10); h_numberStripLayersOverMax = iBooker.book1D( "numberStripLayersOverMax", "Number of strip layers over the maximum of PackedCandidate", 10, 0, 10); h_numberLayersOverMax = iBooker.book1D("numberLayersOverMax", "Number of layers over the maximum of PackedCandidate", 20, 0, 20); h_numberPixelHitsOverMax = iBooker.book1D("numberPixelHitsOverMax", "Number of pixel hits over the maximum of PackedCandidate", 10, 0, 10); h_numberStripHitsOverMax = iBooker.book1D("numberStripHitsOverMax", "Number of strip hits over the maximum of PackedCandidate", 10, 0, 10); h_numberHitsOverMax = iBooker.book1D("numberHitsOverMax", "Number of hits over the maximum of PackedCandidate", 20, 0, 20); } void PackedCandidateTrackValidator::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { edm::Handle<edm::View<reco::Track>> htracks; iEvent.getByToken(tracksToken_, htracks); const auto& tracks = *htracks; edm::Handle<reco::VertexCollection> hvertices; iEvent.getByToken(verticesToken_, hvertices); const auto& vertices = *hvertices; if (vertices.empty()) return; const reco::Vertex& pv = vertices[0]; edm::Handle<edm::Association<pat::PackedCandidateCollection>> hassoc; iEvent.getByToken(trackToPackedCandidateToken_, hassoc); const auto& trackToPackedCandidate = *hassoc; for (size_t i = 0; i < tracks.size(); ++i) { auto trackPtr = tracks.ptrAt(i); const reco::Track& track = *trackPtr; h_selectionFlow->Fill(sf_AllTracks); pat::PackedCandidateRef pcRef = trackToPackedCandidate[trackPtr]; if (pcRef.isNull()) { continue; } h_selectionFlow->Fill(sf_AssociatedToPC); // Filter out neutral PackedCandidates, some of them may have track associated, and for those the charge comparison fails if (pcRef->charge() == 0) { continue; } h_selectionFlow->Fill(sf_PCIsCharged); const reco::Track* trackPcPtr = pcRef->bestTrack(); if (!trackPcPtr) { continue; } h_selectionFlow->Fill(sf_PCHasTrack); // Filter out electrons to avoid comparisons to PackedCandidates with GsfTrack if (std::abs(pcRef->pdgId()) == 11) { continue; } h_selectionFlow->Fill(sf_PCIsNotElectron); // Filter out PackedCandidate-tracks with no hits, as they won't have their details filled const reco::Track& trackPc = *trackPcPtr; if (trackPc.hitPattern().numberOfValidHits() == 0) { continue; } h_selectionFlow->Fill(sf_PCHasHits); auto slimmedVertexRef = pcRef->vertexRef(); const reco::Vertex& pcVertex = vertices[slimmedVertexRef.key()]; fillNoFlow(h_diffVx, trackPc.vx() - track.vx()); fillNoFlow(h_diffVy, trackPc.vy() - track.vy()); fillNoFlow(h_diffVz, trackPc.vz() - track.vz()); // PackedCandidate recalculates the ndof in unpacking as // (nhits+npixelhits-5), but some strip hits may have dimension 2. // If PackedCandidate has ndof=0, the resulting normalizedChi2 // will be 0 too. Hence, the comparison makes sense only for those // PackedCandidates that have ndof != 0. double diffNormalizedChi2 = 0; if (trackPc.ndof() != 0) { h_selectionFlow->Fill(sf_PCNdofNot0); diffNormalizedChi2 = trackPc.normalizedChi2() - track.normalizedChi2(); fillNoFlow(h_diffNormalizedChi2, diffNormalizedChi2); } fillNoFlow(h_diffNdof, trackPc.ndof() - track.ndof()); auto diffCharge = trackPc.charge() - track.charge(); fillNoFlow(h_diffCharge, diffCharge); int diffHP = static_cast<int>(trackPc.quality(reco::TrackBase::highPurity)) - static_cast<int>(track.quality(reco::TrackBase::highPurity)); fillNoFlow(h_diffIsHighPurity, diffHP); const auto diffPt = diffRelative(trackPc.pt(), track.pt()); const auto diffPhi = reco::deltaPhi(trackPc.phi(), track.phi()); fillNoFlow(h_diffPt, diffPt); fillNoFlow(h_diffEta, trackPc.eta() - track.eta()); fillNoFlow(h_diffPhi, diffPhi); const auto diffDxyAssocPV = h_diffDxyAssocPV.fill(pcRef->dxy(), track.dxy(pcVertex.position()), [](double value) { return value * 100.; }); const auto diffDzAssocPV = h_diffDzAssocPV.fill( pcRef->dzAssociatedPV(), track.dz(pcVertex.position()), [](double value) { return value * 100.; }); const auto diffDxyPV = diffRelative(pcRef->dxy(pv.position()), track.dxy(pv.position())); const auto diffDzPV = diffRelative(pcRef->dz(pv.position()), track.dz(pv.position())); fillNoFlow(h_diffDxyPV, diffDxyPV); fillNoFlow(h_diffDzPV, diffDzPV); fillNoFlow(h_diffTrackDxyAssocPV, diffRelative(trackPc.dxy(pcVertex.position()), track.dxy(pcVertex.position()))); fillNoFlow(h_diffTrackDzAssocPV, diffRelative(trackPc.dz(pcVertex.position()), track.dz(pcVertex.position()))); auto fillCov1 = [&](auto& hlp, const int i, const int j) { return hlp.fill(trackPc.covariance(i, j), track.covariance(i, j)); }; auto fillCov2 = [&](auto& hlp, const int i, const int j, std::function<double(double)> modifyPack) { return hlp.fill(trackPc.covariance(i, j), track.covariance(i, j), modifyPack); }; auto fillCov3 = [&](auto& hlp, const int i, const int j, std::function<double(double)> modifyPack, std::function<double(double)> modifyUnpack) { return hlp.fill(trackPc.covariance(i, j), track.covariance(i, j), modifyPack, modifyUnpack); }; const auto pcPt = pcRef->pt(); const auto diffCovQoverpQoverp = fillCov3( h_diffCovQoverpQoverp, reco::TrackBase::i_qoverp, reco::TrackBase::i_qoverp, [=](double val) { return val * pcPt * pcPt; }, [=](double val) { return val / pcPt / pcPt; }); const auto diffCovLambdaLambda = fillCov1(h_diffCovLambdaLambda, reco::TrackBase::i_lambda, reco::TrackBase::i_lambda); const auto diffCovLambdaDsz = fillCov1(h_diffCovLambdaDsz, reco::TrackBase::i_lambda, reco::TrackBase::i_dsz); const auto diffCovPhiPhi = fillCov3( h_diffCovPhiPhi, reco::TrackBase::i_phi, reco::TrackBase::i_phi, [=](double val) { return val * pcPt * pcPt; }, [=](double val) { return val / pcPt / pcPt; }); const auto diffCovPhiDxy = fillCov1(h_diffCovPhiDxy, reco::TrackBase::i_phi, reco::TrackBase::i_dxy); const auto diffCovDxyDxy = fillCov2( h_diffCovDxyDxy, reco::TrackBase::i_dxy, reco::TrackBase::i_dxy, [](double value) { return value * 10000.; }); const auto diffCovDxyDsz = fillCov2( h_diffCovDxyDsz, reco::TrackBase::i_dxy, reco::TrackBase::i_dsz, [](double value) { return value * 10000.; }); const auto diffCovDszDsz = fillCov2( h_diffCovDszDsz, reco::TrackBase::i_dsz, reco::TrackBase::i_dsz, [](double value) { return value * 10000.; }); if (isInRange(diffCovDszDsz.status())) { fillNoFlow(h_diffDszError, diffRelative(pcRef->dzError(), track.dszError())); fillNoFlow(h_diffDzError, diffRelative(pcRef->dzError(), track.dzError())); fillNoFlow(h_diffTrackDzError, diffRelative(trackPc.dzError(), track.dzError())); } if (isInRange(diffCovDxyDxy.status())) { fillNoFlow(h_diffDxyError, diffRelative(pcRef->dxyError(), track.dxyError())); fillNoFlow(h_diffTrackDxyError, diffRelative(trackPc.dxyError(), track.dxyError())); } fillNoFlow(h_diffPtError, diffRelative(trackPc.ptError(), track.ptError())); fillNoFlow(h_diffEtaError, diffRelative(trackPc.etaError(), track.etaError())); // For the non-HitPattern ones, take into account the PackedCandidate packing precision const auto trackNumberOfHits = track.hitPattern().numberOfValidHits(); const auto trackNumberOfPixelHits = track.hitPattern().numberOfValidPixelHits(); const auto trackNumberOfStripHits = track.hitPattern().numberOfValidStripHits(); const auto pcNumberOfHits = pcRef->numberOfHits(); const auto pcNumberOfPixelHits = pcRef->numberOfPixelHits(); const auto pcNumberOfStripHits = pcNumberOfHits - pcNumberOfPixelHits; const auto trackNumberOfLayers = track.hitPattern().trackerLayersWithMeasurement(); const auto trackNumberOfPixelLayers = track.hitPattern().pixelLayersWithMeasurement(); const auto trackNumberOfStripLayers = track.hitPattern().stripLayersWithMeasurement(); const auto pcNumberOfLayers = pcRef->trackerLayersWithMeasurement(); const auto pcNumberOfPixelLayers = pcRef->pixelLayersWithMeasurement(); const auto pcNumberOfStripLayers = pcRef->stripLayersWithMeasurement(); // layer number overflow (should be zero) const int pixelLayerOverflow = trackNumberOfPixelLayers > pat::PackedCandidate::trackPixelHitsMask ? trackNumberOfPixelLayers - pat::PackedCandidate::trackPixelHitsMask : 0; const int stripLayerOverflow = trackNumberOfStripLayers > pat::PackedCandidate::trackStripHitsMask ? trackNumberOfStripLayers - pat::PackedCandidate::trackStripHitsMask : 0; const int layerOverflow = trackNumberOfLayers > (pat::PackedCandidate::trackPixelHitsMask + pat::PackedCandidate::trackStripHitsMask) ? trackNumberOfLayers - (pat::PackedCandidate::trackPixelHitsMask + pat::PackedCandidate::trackStripHitsMask) : 0; // hit overflow (should also be zero) const int pixelOverflow = trackNumberOfPixelHits - pcNumberOfPixelLayers > pat::PackedCandidate::trackPixelHitsMask ? trackNumberOfPixelHits - pcNumberOfPixelLayers - pat::PackedCandidate::trackPixelHitsMask : 0; const int stripOverflow = trackNumberOfStripHits - pcNumberOfStripLayers > pat::PackedCandidate::trackStripHitsMask ? trackNumberOfStripHits - pcNumberOfStripLayers - pat::PackedCandidate::trackStripHitsMask : 0; const int hitsOverflow = trackNumberOfHits - pcNumberOfLayers > (pat::PackedCandidate::trackPixelHitsMask + pat::PackedCandidate::trackStripHitsMask) ? trackNumberOfHits - pcNumberOfLayers - (pat::PackedCandidate::trackPixelHitsMask + pat::PackedCandidate::trackStripHitsMask) : 0; // PackedCandidate counts overflow pixel hits as strip const int pixelInducedStripOverflow = (trackNumberOfStripHits + pixelOverflow - pcNumberOfStripLayers) > pat::PackedCandidate::trackStripHitsMask ? (trackNumberOfStripHits + pixelOverflow - stripOverflow - pcNumberOfStripLayers) - pat::PackedCandidate::trackStripHitsMask : 0; h_numberPixelLayersOverMax->Fill(pixelLayerOverflow); h_numberStripLayersOverMax->Fill(stripLayerOverflow); h_numberLayersOverMax->Fill(layerOverflow); h_numberPixelHitsOverMax->Fill(pixelOverflow); h_numberStripHitsOverMax->Fill(stripOverflow); h_numberHitsOverMax->Fill(hitsOverflow); int diffNumberOfPixelHits = 0; int diffNumberOfHits = 0; int diffNumberOfPixelLayers = 0; int diffNumberOfStripLayers = 0; if (pixelLayerOverflow) { diffNumberOfPixelLayers = pcNumberOfPixelLayers - pat::PackedCandidate::trackPixelHitsMask; } else { diffNumberOfPixelLayers = pcNumberOfPixelLayers - trackNumberOfPixelLayers; } if (pixelOverflow) { diffNumberOfPixelHits = pcNumberOfPixelHits - pcNumberOfPixelLayers - pat::PackedCandidate::trackPixelHitsMask; } else { diffNumberOfPixelHits = pcNumberOfPixelHits - trackNumberOfPixelHits; } if (stripLayerOverflow) { diffNumberOfStripLayers = pcNumberOfStripLayers - pat::PackedCandidate::trackStripHitsMask; } else { diffNumberOfStripLayers = pcNumberOfStripLayers - trackNumberOfStripLayers; } if (stripOverflow || pixelInducedStripOverflow || pixelOverflow) { int diffNumberOfStripHits = 0; if (stripOverflow || pixelInducedStripOverflow) { diffNumberOfStripHits = pcNumberOfStripHits - pat::PackedCandidate::trackStripHitsMask; } else if (pixelOverflow) { diffNumberOfStripHits = (pcNumberOfStripHits - pixelOverflow) - trackNumberOfStripHits; } diffNumberOfHits = diffNumberOfPixelHits + diffNumberOfStripHits; } else { diffNumberOfHits = pcNumberOfHits - trackNumberOfHits; } fillNoFlow(h_diffNumberOfPixelHits, diffNumberOfPixelHits); fillNoFlow(h_diffNumberOfHits, diffNumberOfHits); fillNoFlow(h_diffNumberOfPixelLayers, diffNumberOfPixelLayers); fillNoFlow(h_diffNumberOfStripLayers, diffNumberOfStripLayers); int diffLostInnerHits = 0; const auto trackLostInnerHits = track.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS); switch (pcRef->lostInnerHits()) { case pat::PackedCandidate::validHitInFirstPixelBarrelLayer: case pat::PackedCandidate::noLostInnerHits: diffLostInnerHits = -trackLostInnerHits; break; case pat::PackedCandidate::oneLostInnerHit: diffLostInnerHits = 1 - trackLostInnerHits; break; case pat::PackedCandidate::moreLostInnerHits: diffLostInnerHits = trackLostInnerHits >= 2 ? 0 : 2 - trackLostInnerHits; break; } fillNoFlow(h_diffLostInnerHits, diffLostInnerHits); // For HitPattern ones, calculate the full diff (i.e. some differences are expected) auto diffHitPatternPixelLayersWithMeasurement = trackPc.hitPattern().pixelLayersWithMeasurement() - trackNumberOfPixelLayers; fillNoFlow(h_diffHitPatternPixelLayersWithMeasurement, diffHitPatternPixelLayersWithMeasurement); auto diffHitPatternStripLayersWithMeasurement = trackPc.hitPattern().stripLayersWithMeasurement() - trackNumberOfStripLayers; fillNoFlow(h_diffHitPatternStripLayersWithMeasurement, diffHitPatternStripLayersWithMeasurement); auto diffHitPatternTrackerLayersWithMeasurement = trackPc.hitPattern().trackerLayersWithMeasurement() - trackNumberOfLayers; fillNoFlow(h_diffHitPatternTrackerLayersWithMeasurement, diffHitPatternTrackerLayersWithMeasurement); auto diffHitPatternNumberOfValidPixelHits = trackPc.hitPattern().numberOfValidPixelHits() - trackNumberOfPixelHits; fillNoFlow(h_diffHitPatternNumberOfValidPixelHits, diffHitPatternNumberOfValidPixelHits); auto diffHitPatternNumberOfValidHits = trackPc.hitPattern().numberOfValidHits() - trackNumberOfHits; fillNoFlow(h_diffHitPatternNumberOfValidHits, diffHitPatternNumberOfValidHits); fillNoFlow(h_diffHitPatternNumberOfLostInnerHits, trackPc.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) - track.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS)); // hasValidHitInFirstPixelBarrel is set only if numberOfLostHits(MISSING_INNER_HITS) == 0 int diffHitPatternHasValidHitInFirstPixelBarrel = 0; if (track.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) == 0) { h_selectionFlow->Fill(sf_NoMissingInnerHits); diffHitPatternHasValidHitInFirstPixelBarrel = static_cast<int>( trackPc.hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1)) - static_cast<int>(track.hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1)); fillNoFlow(h_diffHitPatternHasValidHitInFirstPixelBarrel, diffHitPatternHasValidHitInFirstPixelBarrel); } // Print warning if there are differences outside the expected range if (debug_ && (diffNormalizedChi2 < -1 || diffNormalizedChi2 > 0 || diffCharge != 0 || diffHP != 0 || std::abs(diffPhi) > 5e-4 || diffDxyAssocPV.outsideExpectedRange() || diffDzAssocPV.outsideExpectedRange() || std::abs(diffDxyPV) > 0.05 || std::abs(diffDzPV) > 0.05 || diffCovQoverpQoverp.outsideExpectedRange() || diffCovLambdaLambda.outsideExpectedRange() || diffCovLambdaDsz.outsideExpectedRange() || diffCovPhiPhi.outsideExpectedRange() || diffCovPhiDxy.outsideExpectedRange() || diffCovDxyDxy.outsideExpectedRange() || diffCovDxyDsz.outsideExpectedRange() || diffCovDszDsz.outsideExpectedRange() || diffNumberOfPixelHits != 0 || diffNumberOfHits != 0 || diffLostInnerHits != 0 || diffHitPatternHasValidHitInFirstPixelBarrel != 0)) { edm::LogInfo("PackedCandidateTrackValidator") << "Track " << i << " pt " << track.pt() << " eta " << track.eta() << " phi " << track.phi() << " chi2 " << track.chi2() << " ndof " << track.ndof() << "\n" << " ptError " << track.ptError() << " etaError " << track.etaError() << " phiError " << track.phiError() << " dxyError " << track.dxyError() << " dzError " << track.dzError() << "\n" << " refpoint " << track.referencePoint() << " momentum " << track.momentum() << "\n" << " dxy " << track.dxy() << " dz " << track.dz() << "\n" << " " << TrackAlgoPrinter(track) << " lost inner hits " << trackLostInnerHits << " lost outer hits " << track.hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << " hitpattern " << HitPatternPrinter(track) << " \n" << " PC " << pcRef.id() << ":" << pcRef.key() << " track pt " << trackPc.pt() << " eta " << trackPc.eta() << " phi " << trackPc.phi() << " (PC " << pcRef->phi() << ") chi2 " << trackPc.chi2() << " ndof " << trackPc.ndof() << " pdgId " << pcRef->pdgId() << " mass " << pcRef->mass() << "\n" << " ptError " << trackPc.ptError() << " etaError " << trackPc.etaError() << " phiError " << trackPc.phiError() << "\n" << " pc.vertex " << pcRef->vertex() << " momentum " << pcRef->momentum() << " track " << trackPc.momentum() << "\n" << " dxy " << trackPc.dxy() << " dz " << trackPc.dz() << " pc.dz " << pcRef->dz() << " dxyError " << trackPc.dxyError() << " dzError " << trackPc.dzError() << "\n" << " dxy(PV) " << trackPc.dxy(pv.position()) << " dz(PV) " << trackPc.dz(pv.position()) << " dxy(assocPV) " << trackPc.dxy(pcVertex.position()) << " dz(assocPV) " << trackPc.dz(pcVertex.position()) << "\n" << " (diff PackedCandidate track)" << " highPurity " << diffHP << " " << trackPc.quality(reco::TrackBase::highPurity) << " " << track.quality(reco::TrackBase::highPurity) << " charge " << diffCharge << " " << trackPc.charge() << " " << track.charge() << " normalizedChi2 " << diffNormalizedChi2 << " " << trackPc.normalizedChi2() << " " << track.normalizedChi2() << "\n " << " numberOfAllHits " << diffNumberOfHits << " " << pcNumberOfHits << " " << trackNumberOfHits << " numberOfPixelHits " << diffNumberOfPixelHits << " " << pcNumberOfPixelHits << " " << trackNumberOfPixelHits << " numberOfStripHits # " << pcNumberOfStripHits << " " << trackNumberOfStripHits << "\n " << " hitPattern.numberOfValidPixelHits " << diffHitPatternNumberOfValidPixelHits << " " << trackPc.hitPattern().numberOfValidPixelHits() << " " << track.hitPattern().numberOfValidPixelHits() << " hitPattern.numberOfValidHits " << diffHitPatternNumberOfValidHits << " " << trackPc.hitPattern().numberOfValidHits() << " " << track.hitPattern().numberOfValidHits() << " hitPattern.hasValidHitInFirstPixelBarrel " << diffHitPatternHasValidHitInFirstPixelBarrel << " " << trackPc.hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1) << " " << track.hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1) << "\n " << " lostInnerHits " << diffLostInnerHits << " " << pcRef->lostInnerHits() << " #" << " phi (5e-4) " << diffPhi << " " << trackPc.phi() << " " << track.phi() << "\n " << " dxy(assocPV) " << diffDxyAssocPV << "\n " << " dz(assocPV) " << diffDzAssocPV << "\n " << " dxy(PV) (0.05) " << diffDxyPV << " " << pcRef->dxy(pv.position()) << " " << track.dxy(pv.position()) << "\n " << " dz(PV) (0.05) " << diffDzPV << " " << pcRef->dz(pv.position()) << " " << track.dz(pv.position()) << "\n " << " cov(qoverp, qoverp) " << diffCovQoverpQoverp << "\n " << " cov(lambda, lambda) " << diffCovLambdaLambda << "\n " << " cov(lambda, dsz) " << diffCovLambdaDsz << "\n " << " cov(phi, phi) " << diffCovPhiPhi << "\n " << " cov(phi, dxy) " << diffCovPhiDxy << "\n " << " cov(dxy, dxy) " << diffCovDxyDxy << "\n " << " cov(dxy, dsz) " << diffCovDxyDsz << "\n " << " cov(dsz, dsz) " << diffCovDszDsz; } } } #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(PackedCandidateTrackValidator);