Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:04:54

0001 #ifndef __DataFormats_PatCandidates_PackedCandidate_h__
0002 #define __DataFormats_PatCandidates_PackedCandidate_h__
0003 
0004 #include "DataFormats/Candidate/interface/Candidate.h"
0005 #include "DataFormats/Candidate/interface/CandidateFwd.h"
0006 #include "DataFormats/Common/interface/Association.h"
0007 #include "DataFormats/Common/interface/RefVector.h"
0008 #include "DataFormats/Math/interface/deltaPhi.h"
0009 #include "DataFormats/PatCandidates/interface/CovarianceParameterization.h"
0010 #include "DataFormats/VertexReco/interface/Vertex.h"
0011 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0012 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0013 #include <atomic>
0014 #include <mutex>
0015 
0016 /* #include "DataFormats/Math/interface/PtEtaPhiMass.h" */
0017 
0018 // forward declare testing structure
0019 class testPackedCandidate;
0020 
0021 namespace pat {
0022   class PackedCandidate : public reco::Candidate {
0023   public:
0024     /// collection of daughter candidates
0025     typedef reco::CandidateCollection daughters;
0026     /// Lorentz vector
0027     typedef math::XYZTLorentzVector LorentzVector;
0028     /// Lorentz vector
0029     typedef math::PtEtaPhiMLorentzVector PolarLorentzVector;
0030     /// point in the space
0031     typedef math::XYZPoint Point;
0032     /// point in the space
0033     typedef math::XYZVector Vector;
0034 
0035     typedef unsigned int index;
0036     /// default constructor
0037     PackedCandidate()
0038         : packedPt_(0),
0039           packedEta_(0),
0040           packedPhi_(0),
0041           packedM_(0),
0042           packedDxy_(0),
0043           packedDz_(0),
0044           packedDPhi_(0),
0045           packedDEta_(0),
0046           packedDTrkPt_(0),
0047           packedCovariance_(),
0048           packedPuppiweight_(0),
0049           packedPuppiweightNoLepDiff_(0),
0050           rawCaloFraction_(0),
0051           rawHcalFraction_(0),
0052           caloFraction_(0),
0053           hcalFraction_(0),
0054           packedTime_(0),
0055           packedTimeError_(0),
0056           isIsolatedChargedHadron_(false),
0057           p4_(new PolarLorentzVector(0, 0, 0, 0)),
0058           p4c_(new LorentzVector(0, 0, 0, 0)),
0059           vertex_(new Point(0, 0, 0)),
0060           dphi_(0),
0061           deta_(0),
0062           dtrkpt_(0),
0063           track_(nullptr),
0064           pdgId_(0),
0065           qualityFlags_(0),
0066           pvRefKey_(reco::VertexRef::invalidKey()),
0067           m_(nullptr),
0068           packedHits_(0),
0069           packedLayers_(0),
0070           normalizedChi2_(0),
0071           covarianceVersion_(0),
0072           covarianceSchema_(0),
0073           firstHit_(0) {}
0074 
0075     explicit PackedCandidate(const reco::Candidate &c,
0076                              const reco::VertexRefProd &pvRefProd,
0077                              reco::VertexRef::key_type pvRefKey)
0078         : packedPuppiweight_(0),
0079           packedPuppiweightNoLepDiff_(0),
0080           rawCaloFraction_(0),
0081           rawHcalFraction_(0),
0082           caloFraction_(0),
0083           hcalFraction_(0),
0084           packedTime_(0),
0085           packedTimeError_(0),
0086           isIsolatedChargedHadron_(false),
0087           p4_(new PolarLorentzVector(c.pt(), c.eta(), c.phi(), c.mass())),
0088           p4c_(new LorentzVector(*p4_)),
0089           vertex_(new Point(c.vertex())),
0090           dphi_(0),
0091           deta_(0),
0092           dtrkpt_(0),
0093           track_(nullptr),
0094           pdgId_(c.pdgId()),
0095           qualityFlags_(0),
0096           pvRefProd_(pvRefProd),
0097           pvRefKey_(pvRefKey),
0098           m_(nullptr),
0099           packedHits_(0),
0100           packedLayers_(0),
0101           normalizedChi2_(0),
0102           covarianceVersion_(0),
0103           covarianceSchema_(0),
0104           firstHit_(0) {
0105       packBoth();
0106     }
0107 
0108     explicit PackedCandidate(const PolarLorentzVector &p4,
0109                              const Point &vtx,
0110                              float trkPt,
0111                              float etaAtVtx,
0112                              float phiAtVtx,
0113                              int pdgId,
0114                              const reco::VertexRefProd &pvRefProd,
0115                              reco::VertexRef::key_type pvRefKey)
0116         : packedPuppiweight_(0),
0117           packedPuppiweightNoLepDiff_(0),
0118           rawCaloFraction_(0),
0119           rawHcalFraction_(0),
0120           caloFraction_(0),
0121           hcalFraction_(0),
0122           packedTime_(0),
0123           packedTimeError_(0),
0124           isIsolatedChargedHadron_(false),
0125           p4_(new PolarLorentzVector(p4)),
0126           p4c_(new LorentzVector(*p4_)),
0127           vertex_(new Point(vtx)),
0128           dphi_(reco::deltaPhi(phiAtVtx, p4_.load()->phi())),
0129           deta_(std::abs(etaAtVtx - p4_.load()->eta()) >= kMinDEtaToStore_ ? etaAtVtx - p4_.load()->eta() : 0.),
0130           dtrkpt_(std::abs(trkPt - p4_.load()->pt()) >= kMinDTrkPtToStore_ ? trkPt - p4_.load()->pt() : 0.),
0131           track_(nullptr),
0132           pdgId_(pdgId),
0133           qualityFlags_(0),
0134           pvRefProd_(pvRefProd),
0135           pvRefKey_(pvRefKey),
0136           m_(nullptr),
0137           packedHits_(0),
0138           packedLayers_(0),
0139           normalizedChi2_(0),
0140           covarianceVersion_(0),
0141           covarianceSchema_(0),
0142           firstHit_(0) {
0143       packBoth();
0144     }
0145 
0146     explicit PackedCandidate(const LorentzVector &p4,
0147                              const Point &vtx,
0148                              float trkPt,
0149                              float etaAtVtx,
0150                              float phiAtVtx,
0151                              int pdgId,
0152                              const reco::VertexRefProd &pvRefProd,
0153                              reco::VertexRef::key_type pvRefKey)
0154         : packedPuppiweight_(0),
0155           packedPuppiweightNoLepDiff_(0),
0156           rawCaloFraction_(0),
0157           rawHcalFraction_(0),
0158           caloFraction_(0),
0159           hcalFraction_(0),
0160           packedTime_(0),
0161           packedTimeError_(0),
0162           isIsolatedChargedHadron_(false),
0163           p4_(new PolarLorentzVector(p4.Pt(), p4.Eta(), p4.Phi(), p4.M())),
0164           p4c_(new LorentzVector(p4)),
0165           vertex_(new Point(vtx)),
0166           dphi_(reco::deltaPhi(phiAtVtx, p4_.load()->phi())),
0167           deta_(std::abs(etaAtVtx - p4_.load()->eta()) >= kMinDEtaToStore_ ? etaAtVtx - p4_.load()->eta() : 0.),
0168           dtrkpt_(std::abs(trkPt - p4_.load()->pt()) >= kMinDTrkPtToStore_ ? trkPt - p4_.load()->pt() : 0.),
0169           track_(nullptr),
0170           pdgId_(pdgId),
0171           qualityFlags_(0),
0172           pvRefProd_(pvRefProd),
0173           pvRefKey_(pvRefKey),
0174           m_(nullptr),
0175           packedHits_(0),
0176           packedLayers_(0),
0177           normalizedChi2_(0),
0178           covarianceVersion_(0),
0179           covarianceSchema_(0),
0180           firstHit_(0) {
0181       packBoth();
0182     }
0183 
0184     PackedCandidate(const PackedCandidate &iOther)
0185         : packedPt_(iOther.packedPt_),
0186           packedEta_(iOther.packedEta_),
0187           packedPhi_(iOther.packedPhi_),
0188           packedM_(iOther.packedM_),
0189           packedDxy_(iOther.packedDxy_),
0190           packedDz_(iOther.packedDz_),
0191           packedDPhi_(iOther.packedDPhi_),
0192           packedDEta_(iOther.packedDEta_),
0193           packedDTrkPt_(iOther.packedDTrkPt_),
0194           packedCovariance_(iOther.packedCovariance_),
0195           packedPuppiweight_(iOther.packedPuppiweight_),
0196           packedPuppiweightNoLepDiff_(iOther.packedPuppiweightNoLepDiff_),
0197           rawCaloFraction_(iOther.rawCaloFraction_),
0198           rawHcalFraction_(iOther.rawHcalFraction_),
0199           caloFraction_(iOther.caloFraction_),
0200           hcalFraction_(iOther.hcalFraction_),
0201           packedTime_(iOther.packedTime_),
0202           packedTimeError_(iOther.packedTimeError_),
0203           isIsolatedChargedHadron_(iOther.isIsolatedChargedHadron_),
0204           // Need to trigger unpacking in iOther
0205           p4_(new PolarLorentzVector(iOther.polarP4())),
0206           p4c_(new LorentzVector(iOther.p4())),
0207           vertex_((iOther.vertex_ ? new Point(iOther.vertex()) : nullptr)),
0208           dxy_(vertex_ ? iOther.dxy_ : 0),
0209           dz_(vertex_ ? iOther.dz_ : 0),
0210           dphi_(vertex_ ? iOther.dphi_ : 0),
0211           deta_(vertex_ ? iOther.deta_ : 0),
0212           dtrkpt_(vertex_ ? iOther.dtrkpt_ : 0),
0213           track_(iOther.track_ ? new reco::Track(*iOther.track_) : nullptr),
0214           pdgId_(iOther.pdgId_),
0215           qualityFlags_(iOther.qualityFlags_),
0216           pvRefProd_(iOther.pvRefProd_),
0217           pvRefKey_(iOther.pvRefKey_),
0218           m_(iOther.m_ ? new reco::TrackBase::CovarianceMatrix(*iOther.m_) : nullptr),
0219           packedHits_(iOther.packedHits_),
0220           packedLayers_(iOther.packedLayers_),
0221           normalizedChi2_(iOther.normalizedChi2_),
0222           covarianceVersion_(iOther.covarianceVersion_),
0223           covarianceSchema_(iOther.covarianceSchema_),
0224           firstHit_(iOther.firstHit_),
0225           trkAlgoPacked_(iOther.trkAlgoPacked_) {}
0226 
0227     PackedCandidate(PackedCandidate &&iOther)
0228         : packedPt_(iOther.packedPt_),
0229           packedEta_(iOther.packedEta_),
0230           packedPhi_(iOther.packedPhi_),
0231           packedM_(iOther.packedM_),
0232           packedDxy_(iOther.packedDxy_),
0233           packedDz_(iOther.packedDz_),
0234           packedDPhi_(iOther.packedDPhi_),
0235           packedDEta_(iOther.packedDEta_),
0236           packedDTrkPt_(iOther.packedDTrkPt_),
0237           packedCovariance_(iOther.packedCovariance_),
0238           packedPuppiweight_(iOther.packedPuppiweight_),
0239           packedPuppiweightNoLepDiff_(iOther.packedPuppiweightNoLepDiff_),
0240           rawCaloFraction_(iOther.rawCaloFraction_),
0241           rawHcalFraction_(iOther.rawHcalFraction_),
0242           caloFraction_(iOther.caloFraction_),
0243           hcalFraction_(iOther.hcalFraction_),
0244           packedTime_(iOther.packedTime_),
0245           packedTimeError_(iOther.packedTimeError_),
0246           isIsolatedChargedHadron_(iOther.isIsolatedChargedHadron_),
0247           p4_(iOther.p4_.exchange(nullptr)),
0248           p4c_(iOther.p4c_.exchange(nullptr)),
0249           vertex_(iOther.vertex_.exchange(nullptr)),
0250           dxy_(iOther.dxy_),
0251           dz_(iOther.dz_),
0252           dphi_(iOther.dphi_),
0253           deta_(iOther.deta_),
0254           dtrkpt_(iOther.dtrkpt_),
0255           track_(iOther.track_.exchange(nullptr)),
0256           pdgId_(iOther.pdgId_),
0257           qualityFlags_(iOther.qualityFlags_),
0258           pvRefProd_(iOther.pvRefProd_),
0259           pvRefKey_(iOther.pvRefKey_),
0260           m_(iOther.m_.exchange(nullptr)),
0261           packedHits_(iOther.packedHits_),
0262           packedLayers_(iOther.packedLayers_),
0263           normalizedChi2_(iOther.normalizedChi2_),
0264           covarianceVersion_(iOther.covarianceVersion_),
0265           covarianceSchema_(iOther.covarianceSchema_),
0266           firstHit_(iOther.firstHit_),
0267           trkAlgoPacked_(iOther.trkAlgoPacked_) {}
0268 
0269     PackedCandidate &operator=(const PackedCandidate &iOther) {
0270       if (this == &iOther) {
0271         return *this;
0272       }
0273       packedPt_ = iOther.packedPt_;
0274       packedEta_ = iOther.packedEta_;
0275       packedPhi_ = iOther.packedPhi_;
0276       packedM_ = iOther.packedM_;
0277       packedDxy_ = iOther.packedDxy_;
0278       packedDz_ = iOther.packedDz_;
0279       packedDPhi_ = iOther.packedDPhi_;
0280       packedDEta_ = iOther.packedDEta_;
0281       packedDTrkPt_ = iOther.packedDTrkPt_;
0282       packedCovariance_ = iOther.packedCovariance_;
0283       packedPuppiweight_ = iOther.packedPuppiweight_;
0284       packedPuppiweightNoLepDiff_ = iOther.packedPuppiweightNoLepDiff_;
0285       rawCaloFraction_ = iOther.rawCaloFraction_;
0286       rawHcalFraction_ = iOther.rawHcalFraction_;
0287       caloFraction_ = iOther.caloFraction_;
0288       hcalFraction_ = iOther.hcalFraction_;
0289       packedTime_ = iOther.packedTime_;
0290       packedTimeError_ = iOther.packedTimeError_;
0291       isIsolatedChargedHadron_ = iOther.isIsolatedChargedHadron_;
0292       // Need to trigger unpacking in iOther
0293       if (p4_) {
0294         *p4_ = iOther.polarP4();
0295       } else {
0296         p4_.store(new PolarLorentzVector(iOther.polarP4()));
0297       }
0298       if (p4c_) {
0299         *p4c_ = iOther.p4();
0300       } else {
0301         p4c_.store(new LorentzVector(iOther.p4()));
0302       }
0303       if (vertex_) {
0304         *vertex_ = iOther.vertex();
0305       } else {
0306         vertex_.store(new Point(iOther.vertex()));
0307       }
0308       dxy_ = iOther.dxy_;
0309       dz_ = iOther.dz_;
0310       dphi_ = iOther.dphi_;
0311       deta_ = iOther.deta_;
0312       dtrkpt_ = iOther.dtrkpt_;
0313 
0314       if (!iOther.track_) {
0315         delete track_.exchange(nullptr);
0316       } else {
0317         if (!track_) {
0318           track_.store(new reco::Track(*iOther.track_));
0319         } else {
0320           *track_ = *(iOther.track_);
0321         }
0322       }
0323 
0324       pdgId_ = iOther.pdgId_;
0325       qualityFlags_ = iOther.qualityFlags_;
0326       pvRefProd_ = iOther.pvRefProd_;
0327       pvRefKey_ = iOther.pvRefKey_;
0328       if (!iOther.m_) {
0329         delete m_.exchange(nullptr);
0330       } else {
0331         if (!m_) {
0332           m_.store(new reco::Track::CovarianceMatrix(*iOther.m_));
0333         } else {
0334           *m_ = *(iOther.m_);
0335         }
0336       }
0337 
0338       packedHits_ = iOther.packedHits_;
0339       packedLayers_ = iOther.packedLayers_;
0340       normalizedChi2_ = iOther.normalizedChi2_;
0341       covarianceVersion_ = iOther.covarianceVersion_;
0342       covarianceSchema_ = iOther.covarianceSchema_;
0343       firstHit_ = iOther.firstHit_;
0344       trkAlgoPacked_ = iOther.trkAlgoPacked_;
0345       return *this;
0346     }
0347 
0348     PackedCandidate &operator=(PackedCandidate &&iOther) {
0349       if (this == &iOther) {
0350         return *this;
0351       }
0352       packedPt_ = iOther.packedPt_;
0353       packedEta_ = iOther.packedEta_;
0354       packedPhi_ = iOther.packedPhi_;
0355       packedM_ = iOther.packedM_;
0356       packedDxy_ = iOther.packedDxy_;
0357       packedDz_ = iOther.packedDz_;
0358       packedDPhi_ = iOther.packedDPhi_;
0359       packedDEta_ = iOther.packedDEta_;
0360       packedDTrkPt_ = iOther.packedDTrkPt_;
0361       packedCovariance_ = iOther.packedCovariance_;
0362       packedPuppiweight_ = iOther.packedPuppiweight_;
0363       packedPuppiweightNoLepDiff_ = iOther.packedPuppiweightNoLepDiff_;
0364       rawCaloFraction_ = iOther.rawCaloFraction_;
0365       rawHcalFraction_ = iOther.rawHcalFraction_;
0366       caloFraction_ = iOther.caloFraction_;
0367       hcalFraction_ = iOther.hcalFraction_;
0368       packedTime_ = iOther.packedTime_;
0369       packedTimeError_ = iOther.packedTimeError_;
0370       isIsolatedChargedHadron_ = iOther.isIsolatedChargedHadron_;
0371       delete p4_.exchange(iOther.p4_.exchange(nullptr));
0372       delete p4c_.exchange(iOther.p4c_.exchange(nullptr));
0373       delete vertex_.exchange(iOther.vertex_.exchange(nullptr));
0374       dxy_ = iOther.dxy_;
0375       dz_ = iOther.dz_;
0376       dphi_ = iOther.dphi_;
0377       deta_ = iOther.deta_;
0378       dtrkpt_ = iOther.dtrkpt_;
0379       delete track_.exchange(iOther.track_.exchange(nullptr));
0380       pdgId_ = iOther.pdgId_;
0381       qualityFlags_ = iOther.qualityFlags_;
0382       pvRefProd_ = iOther.pvRefProd_;
0383       pvRefKey_ = iOther.pvRefKey_;
0384       delete m_.exchange(iOther.m_.exchange(nullptr));
0385       packedHits_ = iOther.packedHits_;
0386       packedLayers_ = iOther.packedLayers_;
0387       normalizedChi2_ = iOther.normalizedChi2_;
0388       covarianceVersion_ = iOther.covarianceVersion_;
0389       covarianceSchema_ = iOther.covarianceSchema_;
0390       firstHit_ = iOther.firstHit_;
0391       trkAlgoPacked_ = iOther.trkAlgoPacked_;
0392       return *this;
0393     }
0394 
0395     /// destructor
0396     ~PackedCandidate() override;
0397     /// number of daughters
0398     size_t numberOfDaughters() const override;
0399     /// return daughter at a given position (throws an exception)
0400     const reco::Candidate *daughter(size_type) const override;
0401     /// number of mothers
0402     size_t numberOfMothers() const override;
0403     /// return mother at a given position (throws an exception)
0404     const reco::Candidate *mother(size_type) const override;
0405     /// return daughter at a given position (throws an exception)
0406     reco::Candidate *daughter(size_type) override;
0407     /// return daughter with a specified role name
0408     reco::Candidate *daughter(const std::string &s) override;
0409     /// return daughter with a specified role name
0410     const reco::Candidate *daughter(const std::string &s) const override;
0411     /// return the number of source Candidates
0412     /// ( the candidates used to construct this Candidate)
0413     size_t numberOfSourceCandidatePtrs() const override { return 0; }
0414     /// return a Ptr to one of the source Candidates
0415     /// ( the candidates used to construct this Candidate)
0416     reco::CandidatePtr sourceCandidatePtr(size_type i) const override { return reco::CandidatePtr(); }
0417 
0418     /// electric charge
0419     int charge() const override {
0420       switch (abs(pdgId_)) {
0421         case 211:
0422           return (pdgId_ > 0) - (pdgId_ < 0);
0423         case 11:
0424           return (-1) * (pdgId_ > 0) + (pdgId_ < 0);  // e
0425         case 13:
0426           return (-1) * (pdgId_ > 0) + (pdgId_ < 0);  // mu
0427         case 15:
0428           return (-1) * (pdgId_ > 0) + (pdgId_ < 0);  // tau
0429         case 24:
0430           return (pdgId_ > 0) - (pdgId_ < 0);  // W
0431         default:
0432           return 0;  // FIXME: charge is not defined
0433       }
0434     }
0435     /// set electric charge
0436     void setCharge(int charge) override {}
0437     /// electric charge
0438     int threeCharge() const override { return charge() * 3; }
0439     /// set electric charge
0440     void setThreeCharge(int threecharge) override {}
0441     /// four-momentum Lorentz vecto r
0442     const LorentzVector &p4() const override {
0443       if (!p4c_)
0444         unpack();
0445       return *p4c_;
0446     }
0447     /// four-momentum Lorentz vector
0448     const PolarLorentzVector &polarP4() const override {
0449       if (!p4c_)
0450         unpack();
0451       return *p4_;
0452     }
0453     /// spatial momentum vector
0454     Vector momentum() const override {
0455       if (!p4c_)
0456         unpack();
0457       return p4c_.load()->Vect();
0458     }
0459     /// boost vector to boost a Lorentz vector
0460     /// to the particle center of mass system
0461     Vector boostToCM() const override {
0462       if (!p4c_)
0463         unpack();
0464       return p4c_.load()->BoostToCM();
0465     }
0466     /// magnitude of momentum vector
0467     double p() const override {
0468       if (!p4c_)
0469         unpack();
0470       return p4c_.load()->P();
0471     }
0472     /// energy
0473     double energy() const override {
0474       if (!p4c_)
0475         unpack();
0476       return p4c_.load()->E();
0477     }
0478     /// transverse energy
0479     double et() const override { return (pt() <= 0) ? 0 : p4c_.load()->Et(); }
0480     /// transverse energy squared (use this for cuts)!
0481     double et2() const override { return (pt() <= 0) ? 0 : p4c_.load()->Et2(); }
0482     /// mass
0483     double mass() const override {
0484       if (!p4c_)
0485         unpack();
0486       return p4_.load()->M();
0487     }
0488     /// mass squared
0489     double massSqr() const override {
0490       if (!p4c_)
0491         unpack();
0492       auto m = p4_.load()->M();
0493       return m * m;
0494     }
0495 
0496     /// transverse mass
0497     double mt() const override {
0498       if (!p4c_)
0499         unpack();
0500       return p4_.load()->Mt();
0501     }
0502     /// transverse mass squared
0503     double mtSqr() const override {
0504       if (!p4c_)
0505         unpack();
0506       return p4_.load()->Mt2();
0507     }
0508     /// x coordinate of momentum vector
0509     double px() const override {
0510       if (!p4c_)
0511         unpack();
0512       return p4c_.load()->Px();
0513     }
0514     /// y coordinate of momentum vector
0515     double py() const override {
0516       if (!p4c_)
0517         unpack();
0518       return p4c_.load()->Py();
0519     }
0520     /// z coordinate of momentum vector
0521     double pz() const override {
0522       if (!p4c_)
0523         unpack();
0524       return p4c_.load()->Pz();
0525     }
0526     /// transverse momentum
0527     double pt() const override {
0528       if (!p4c_)
0529         unpack();
0530       return p4_.load()->Pt();
0531     }
0532     /// momentum azimuthal angle
0533     double phi() const override {
0534       if (!p4c_)
0535         unpack();
0536       return p4_.load()->Phi();
0537     }
0538 
0539     /// pt from the track (normally identical to pt())
0540     virtual double ptTrk() const {
0541       maybeUnpackBoth();
0542       return p4_.load()->pt() + dtrkpt_;
0543     }
0544     /// momentum azimuthal angle from the track (normally identical to phi())
0545     virtual float phiAtVtx() const {
0546       maybeUnpackBoth();
0547       float ret = p4_.load()->Phi() + dphi_;
0548       while (ret > float(M_PI))
0549         ret -= 2 * float(M_PI);
0550       while (ret < -float(M_PI))
0551         ret += 2 * float(M_PI);
0552       return ret;
0553     }
0554     /// eta from the track (normally identical to eta())
0555     virtual float etaAtVtx() const {
0556       maybeUnpackBoth();
0557       return p4_.load()->eta() + deta_;
0558     }
0559 
0560     /// momentum polar angle
0561     double theta() const override {
0562       if (!p4c_)
0563         unpack();
0564       return p4_.load()->Theta();
0565     }
0566     /// momentum pseudorapidity
0567     double eta() const override {
0568       if (!p4c_)
0569         unpack();
0570       return p4_.load()->Eta();
0571     }
0572     /// rapidity
0573     double rapidity() const override {
0574       if (!p4c_)
0575         unpack();
0576       return p4_.load()->Rapidity();
0577     }
0578     /// rapidity
0579     double y() const override {
0580       if (!p4c_)
0581         unpack();
0582       return p4_.load()->Rapidity();
0583     }
0584     /// set 4-momentum
0585     void setP4(const LorentzVector &p4) override {
0586       maybeUnpackBoth();  // changing px,py,pz changes also mapping between dxy,dz
0587                           // and x,y,z
0588       dphi_ += polarP4().Phi() - p4.Phi();
0589       deta_ += polarP4().Eta() - p4.Eta();
0590       dtrkpt_ += polarP4().Pt() - p4.Pt();
0591       *p4_ = PolarLorentzVector(p4.Pt(), p4.Eta(), p4.Phi(), p4.M());
0592       packBoth();
0593     }
0594     /// set 4-momentum
0595     void setP4(const PolarLorentzVector &p4) override {
0596       maybeUnpackBoth();  // changing px,py,pz changes also mapping between dxy,dz
0597                           // and x,y,z
0598       dphi_ += polarP4().Phi() - p4.Phi();
0599       deta_ += polarP4().Eta() - p4.Eta();
0600       dtrkpt_ += polarP4().Pt() - p4.Pt();
0601       *p4_ = p4;
0602       packBoth();
0603     }
0604     /// set particle mass
0605     void setMass(double m) override {
0606       if (!p4c_)
0607         unpack();
0608       *p4_ = PolarLorentzVector(p4_.load()->Pt(), p4_.load()->Eta(), p4_.load()->Phi(), m);
0609       pack();
0610     }
0611     void setPz(double pz) override {
0612       maybeUnpackBoth();  // changing px,py,pz changes also mapping between dxy,dz
0613                           // and x,y,z
0614       *p4c_ = LorentzVector(p4c_.load()->Px(), p4c_.load()->Py(), pz, p4c_.load()->E());
0615       dphi_ += polarP4().Phi() - p4c_.load()->Phi();
0616       deta_ += polarP4().Eta() - p4c_.load()->Eta();
0617       dtrkpt_ += polarP4().Pt() - p4c_.load()->Pt();
0618       *p4_ = PolarLorentzVector(p4c_.load()->Pt(), p4c_.load()->Eta(), p4c_.load()->Phi(), p4c_.load()->M());
0619       packBoth();
0620     }
0621     /// set impact parameters covariance
0622 
0623     // Note: mask is also the maximum value
0624     enum trackHitShiftsAndMasks { trackPixelHitsMask = 7, trackStripHitsMask = 31, trackStripHitsShift = 3 };
0625 
0626     // set number of tracker hits and layers
0627     virtual void setHits(const reco::Track &tk) {
0628       // first we count the number of layers with hits
0629       int numberOfPixelLayers_ = tk.hitPattern().pixelLayersWithMeasurement();
0630       if (numberOfPixelLayers_ > trackPixelHitsMask)
0631         numberOfPixelLayers_ = trackPixelHitsMask;
0632       int numberOfStripLayers_ = tk.hitPattern().stripLayersWithMeasurement();
0633       if (numberOfStripLayers_ > trackStripHitsMask)
0634         numberOfStripLayers_ = trackStripHitsMask;
0635       packedLayers_ = (numberOfPixelLayers_ & trackPixelHitsMask) | (numberOfStripLayers_ << trackStripHitsShift);
0636       // now we count number of additional hits, beyond the one-per-layer implied
0637       // by packedLayers_
0638       int numberOfPixelHits_ = tk.hitPattern().numberOfValidPixelHits() - numberOfPixelLayers_;
0639       if (numberOfPixelHits_ > trackPixelHitsMask)
0640         numberOfPixelHits_ = trackPixelHitsMask;
0641       int numberOfStripHits_ =
0642           tk.hitPattern().numberOfValidHits() - numberOfPixelHits_ - numberOfPixelLayers_ - numberOfStripLayers_;
0643       if (numberOfStripHits_ > trackStripHitsMask)
0644         numberOfStripHits_ = trackStripHitsMask;
0645 
0646       packedHits_ = (numberOfPixelHits_ & trackPixelHitsMask) | (numberOfStripHits_ << trackStripHitsShift);
0647     }
0648 
0649     virtual void setTrackProperties(const reco::Track &tk,
0650                                     const reco::Track::CovarianceMatrix &covariance,
0651                                     int quality,
0652                                     int covarianceVersion) {
0653       covarianceVersion_ = covarianceVersion;
0654       covarianceSchema_ = quality;
0655       normalizedChi2_ = tk.normalizedChi2();
0656       setHits(tk);
0657       maybeUnpackBoth();
0658       packBoth();
0659       packCovariance(covariance, false);
0660     }
0661 
0662     // set track properties using quality and covarianceVersion to define the
0663     // level of details in the cov. matrix
0664     virtual void setTrackProperties(const reco::Track &tk, int quality, int covarianceVersion) {
0665       setTrackProperties(tk, tk.covariance(), quality, covarianceVersion);
0666     }
0667 
0668     void setTrackPropertiesLite(unsigned int covSchema,
0669                                 unsigned int covarianceVersion,
0670                                 unsigned int nHits,
0671                                 unsigned int nPixelHits) {
0672       covarianceVersion_ = covarianceVersion;
0673       covarianceSchema_ = covSchema;
0674       packedHits_ =
0675           (nPixelHits & trackPixelHitsMask) | (((nHits - nPixelHits) & trackStripHitsMask) << trackStripHitsShift);
0676     }
0677 
0678     int numberOfPixelHits() const { return (packedHits_ & trackPixelHitsMask) + pixelLayersWithMeasurement(); }
0679     int numberOfHits() const {
0680       return (packedHits_ >> trackStripHitsShift) + stripLayersWithMeasurement() + numberOfPixelHits();
0681     }
0682     int pixelLayersWithMeasurement() const { return packedLayers_ & trackPixelHitsMask; }
0683     int stripLayersWithMeasurement() const { return (packedLayers_ >> trackStripHitsShift); }
0684     int trackerLayersWithMeasurement() const { return stripLayersWithMeasurement() + pixelLayersWithMeasurement(); }
0685     virtual void setCovarianceVersion(int v) { covarianceVersion_ = v; }
0686     int covarianceVersion() const { return covarianceVersion_; }
0687     int covarianceSchema() const { return covarianceSchema_; }
0688 
0689     /// vertex position
0690     const Point &vertex() const override {
0691       maybeUnpackBoth();
0692       return *vertex_;
0693     }  //{ if (fromPV_) return Point(0,0,0); else return Point(0,0,100); }
0694     /// x coordinate of vertex position
0695     double vx() const override {
0696       maybeUnpackBoth();
0697       return vertex_.load()->X();
0698     }  //{ return 0; }
0699     /// y coordinate of vertex position
0700     double vy() const override {
0701       maybeUnpackBoth();
0702       return vertex_.load()->Y();
0703     }  //{ return 0; }
0704     /// z coordinate of vertex position
0705     double vz() const override {
0706       maybeUnpackBoth();
0707       return vertex_.load()->Z();
0708     }  //{ if (fromPV_) return 0; else return 100; }
0709     /// set vertex
0710     void setVertex(const Point &vertex) override {
0711       maybeUnpackBoth();
0712       *vertex_ = vertex;
0713       packVtx();
0714     }
0715 
0716     /// This refers to the association to PV=ipv. >=PVLoose corresponds to JME
0717     /// definition, >=PVTight to isolation definition
0718     enum PVAssoc { NoPV = 0, PVLoose = 1, PVTight = 2, PVUsedInFit = 3 };
0719     const PVAssoc fromPV(size_t ipv = 0) const {
0720       reco::VertexRef pvRef = vertexRef();
0721       if (pvAssociationQuality() == UsedInFitTight and pvRef.key() == ipv)
0722         return PVUsedInFit;
0723       if (pvRef.key() == ipv or abs(pdgId()) == 13 or abs(pdgId()) == 11)
0724         return PVTight;
0725       if (pvAssociationQuality() == CompatibilityBTag and std::abs(dzAssociatedPV()) > std::abs(dz(ipv)))
0726         return PVTight;  // it is not closest, but at least prevents the B
0727                          // assignment stealing
0728       if (pvAssociationQuality() < UsedInFitLoose or pvRef->ndof() < 4.0)
0729         return PVLoose;
0730       return NoPV;
0731     }
0732 
0733     /// The following contains information about how the association to the PV,
0734     /// given in vertexRef, is obtained.
0735     ///
0736     enum PVAssociationQuality {
0737       NotReconstructedPrimary = 0,
0738       OtherDeltaZ = 1,
0739       CompatibilityBTag = 4,
0740       CompatibilityDz = 5,
0741       UsedInFitLoose = 6,
0742       UsedInFitTight = 7
0743     };
0744     const PVAssociationQuality pvAssociationQuality() const {
0745       return PVAssociationQuality((qualityFlags_ & assignmentQualityMask) >> assignmentQualityShift);
0746     }
0747     void setAssociationQuality(PVAssociationQuality q) {
0748       qualityFlags_ =
0749           (qualityFlags_ & ~assignmentQualityMask) | ((q << assignmentQualityShift) & assignmentQualityMask);
0750     }
0751 
0752     const reco::VertexRef vertexRef() const { return reco::VertexRef(pvRefProd_, pvRefKey_); }
0753 
0754     /// dxy with respect to the PV ref
0755     virtual float dxy() const {
0756       maybeUnpackBoth();
0757       return dxy_;
0758     }
0759 
0760     /// dz with respect to the PV[ipv]
0761     virtual float dz(size_t ipv = 0) const {
0762       maybeUnpackBoth();
0763       return dz_ + (*pvRefProd_)[pvRefKey_].position().z() - (*pvRefProd_)[ipv].position().z();
0764     }
0765     /// dz with respect to the PV ref
0766     virtual float dzAssociatedPV() const {
0767       maybeUnpackBoth();
0768       return dz_;
0769     }
0770 
0771     /// dxy with respect to another point
0772     virtual float dxy(const Point &p) const;
0773     /// dz  with respect to another point
0774     virtual float dz(const Point &p) const;
0775 
0776     /// uncertainty on dz
0777     float dzError() const override {
0778       maybeUnpackCovariance();
0779       return sqrt((*m_.load())(4, 4));
0780     }
0781     /// uncertainty on dxy
0782     float dxyError() const override {
0783       maybeUnpackCovariance();
0784       return sqrt((*m_.load())(3, 3));
0785     }
0786 
0787     /// Return reference to a pseudo track made with candidate kinematics,
0788     /// parameterized error for eta,phi,pt and full IP covariance
0789     virtual const reco::Track &pseudoTrack() const {
0790       if (!track_)
0791         unpackTrk();
0792       return *track_;
0793     }
0794     /// Return reference to a pseudo track made with candidate kinematics,
0795     /// parameterized error for eta,phi,pt and full IP covariance
0796     /// and the coviriance matrix is forced to be positive definite according to BPH recommandations
0797     virtual const reco::Track pseudoPosDefTrack() const;
0798 
0799     /// return a pointer to the track if present. otherwise, return a null pointer
0800     const reco::Track *bestTrack() const override {
0801       if (packedHits_ != 0 || packedLayers_ != 0) {
0802         maybeUnpackTrack();
0803         return track_.load();
0804       } else
0805         return nullptr;
0806     }
0807     /// Return true if a bestTrack can be extracted from this Candidate
0808     bool hasTrackDetails() const { return (packedHits_ != 0 || packedLayers_ != 0); }
0809     /// Return true if the original candidate had a track associated
0810     /// even if the PackedCandidate has no track
0811     bool fromTrackCandidate() const { return (packedDz_ != 0 || (packedDxy_ != 0 && packedDxy_ != 32768)); }
0812     /// true if the track had the highPurity quality bit
0813     bool trackHighPurity() const { return (qualityFlags_ & trackHighPurityMask) >> trackHighPurityShift; }
0814     /// set to true if the track had the highPurity quality bit
0815     void setTrackHighPurity(bool highPurity) {
0816       qualityFlags_ =
0817           (qualityFlags_ & ~trackHighPurityMask) | ((highPurity << trackHighPurityShift) & trackHighPurityMask);
0818     }
0819 
0820     /// Enumerator specifying the
0821     enum LostInnerHits {
0822       validHitInFirstPixelBarrelLayer = -1,
0823       noLostInnerHits = 0,  // it could still not have a hit in the first layer,
0824                             // e.g. if it crosses an inactive sensor
0825       oneLostInnerHit = 1,
0826       moreLostInnerHits = 2
0827     };
0828     LostInnerHits lostInnerHits() const {
0829       return LostInnerHits(int16_t((qualityFlags_ & lostInnerHitsMask) >> lostInnerHitsShift) - 1);
0830     }
0831     void setLostInnerHits(LostInnerHits hits) {
0832       int lost = hits;
0833       if (lost > 2)
0834         lost = 2;  // protection against misuse
0835       lost++;      // shift so it's 0 .. 3 instead of (-1) .. 2
0836       qualityFlags_ = (qualityFlags_ & ~lostInnerHitsMask) | ((lost << lostInnerHitsShift) & lostInnerHitsMask);
0837     }
0838 
0839     /// Set first hit from HitPattern
0840     void setFirstHit(uint16_t pattern) { firstHit_ = pattern; }
0841     /// Return first hit from HitPattern for tracks with high level details
0842     uint16_t firstHit() const { return firstHit_; }
0843 
0844     /// Set/get track algo
0845     void setTrkAlgo(uint8_t algo, uint8_t original) {
0846       trkAlgoPacked_ = algo | ((algo == original ? 0 : original) << 8);
0847     }
0848     uint8_t trkAlgo() const { return trkAlgoPacked_ & 0xff; }
0849     uint8_t trkOriginalAlgo() const {
0850       return (trkAlgoPacked_ & 0xff00) == 0 ? trkAlgo() : ((trkAlgoPacked_ >> 8) & 0xff);
0851     }
0852 
0853     void setMuonID(bool isStandAlone, bool isGlobal) {
0854       int16_t muonFlags = isStandAlone | (2 * isGlobal);
0855       qualityFlags_ = (qualityFlags_ & ~muonFlagsMask) | ((muonFlags << muonFlagsShift) & muonFlagsMask);
0856     }
0857 
0858     void setGoodEgamma(bool isGoodEgamma = true) {
0859       int16_t egFlags = (isGoodEgamma << egammaFlagsShift) & egammaFlagsMask;
0860       qualityFlags_ = (qualityFlags_ & ~egammaFlagsMask) | egFlags;
0861     }
0862 
0863     /// PDG identifier
0864     int pdgId() const override { return pdgId_; }
0865     // set PDG identifier
0866     void setPdgId(int pdgId) override { pdgId_ = pdgId; }
0867     /// status word
0868     int status() const override { return qualityFlags_; } /*FIXME*/
0869     /// set status word
0870     void setStatus(int status) override {} /*FIXME*/
0871     /// long lived flag
0872     static const unsigned int longLivedTag = 0; /*FIXME*/
0873     /// set long lived flag
0874     void setLongLived() override {} /*FIXME*/
0875     /// is long lived?
0876     bool longLived() const override;
0877     /// do mass constraint flag
0878     static const unsigned int massConstraintTag = 0; /*FIXME*/
0879     /// set mass constraint flag
0880     void setMassConstraint() override {} /*FIXME*/
0881     /// do mass constraint?
0882     bool massConstraint() const override;
0883 
0884     /// returns a clone of the Candidate object
0885     PackedCandidate *clone() const override { return new PackedCandidate(*this); }
0886 
0887     /// chi-squares
0888     double vertexChi2() const override;
0889     /** Number of degrees of freedom
0890    *  Meant to be Double32_t for soft-assignment fitters:
0891    *  tracks may contribute to the vertex with fractional weights.
0892    *  The ndof is then = to the sum of the track weights.
0893    *  see e.g. CMS NOTE-2006/032, CMS NOTE-2004/002
0894    */
0895     double vertexNdof() const override;
0896     /// chi-squared divided by n.d.o.f.
0897     double vertexNormalizedChi2() const override;
0898     /// (i, j)-th element of error matrix, i, j = 0, ... 2
0899     double vertexCovariance(int i, int j) const override;
0900     /// return SMatrix
0901     CovarianceMatrix vertexCovariance() const override {
0902       CovarianceMatrix m;
0903       fillVertexCovariance(m);
0904       return m;
0905     }
0906     /// fill SMatrix
0907     void fillVertexCovariance(CovarianceMatrix &v) const override;
0908     /// returns true if this candidate has a reference to a master clone.
0909     /// This only happens if the concrete Candidate type is ShallowCloneCandidate
0910     bool hasMasterClone() const override;
0911     /// returns ptr to master clone, if existing.
0912     /// Throws an exception unless the concrete Candidate type is
0913     /// ShallowCloneCandidate
0914     const reco::CandidateBaseRef &masterClone() const override;
0915     /// returns true if this candidate has a ptr to a master clone.
0916     /// This only happens if the concrete Candidate type is
0917     /// ShallowClonePtrCandidate
0918     bool hasMasterClonePtr() const override;
0919     /// returns ptr to master clone, if existing.
0920     /// Throws an exception unless the concrete Candidate type is
0921     /// ShallowClonePtrCandidate
0922 
0923     const reco::CandidatePtr &masterClonePtr() const override;
0924 
0925     /// cast master clone reference to a concrete type
0926     template <typename Ref>
0927     Ref masterRef() const {
0928       return masterClone().template castTo<Ref>();
0929     }
0930 
0931     bool isElectron() const override { return false; }
0932     bool isMuon() const override { return false; }
0933     bool isStandAloneMuon() const override { return ((qualityFlags_ & muonFlagsMask) >> muonFlagsShift) & 1; }
0934     bool isGlobalMuon() const override { return ((qualityFlags_ & muonFlagsMask) >> muonFlagsShift) & 2; }
0935     bool isTrackerMuon() const override { return false; }
0936     bool isCaloMuon() const override { return false; }
0937     bool isPhoton() const override { return false; }
0938     bool isConvertedPhoton() const override { return false; }
0939     bool isJet() const override { return false; }
0940     bool isGoodEgamma() const { return (qualityFlags_ & egammaFlagsMask) != 0; }
0941 
0942     // puppiweights
0943     void setPuppiWeight(float p,
0944                         float p_nolep = 0.0);  /// Set both weights at once (with
0945                                                /// option for only full PUPPI)
0946     float puppiWeight() const;                 /// Weight from full PUPPI
0947     float puppiWeightNoLep() const;            /// Weight from PUPPI removing leptons
0948 
0949     // for the neutral fractions
0950     void setRawCaloFraction(float p);  /// Set the raw ECAL+HCAL energy over candidate
0951                                        /// energy for isolated charged hadrons
0952     float rawCaloFraction() const {
0953       return (rawCaloFraction_ / 100.);
0954     }                                  /// Raw ECAL+HCAL energy over candidate energy for isolated charged hadrons
0955     void setRawHcalFraction(float p);  /// Set the fraction of Hcal needed isolated charged hadrons
0956     float rawHcalFraction() const {
0957       return (rawHcalFraction_ / 100.);
0958     }                               /// Fraction of Hcal for isolated charged hadrons
0959     void setCaloFraction(float p);  /// Set the fraction of ECAL+HCAL energy over candidate energy
0960     float caloFraction() const {
0961       return (caloFraction_ / 100.);
0962     }                               /// Fraction of ECAL+HCAL energy over candidate energy
0963     void setHcalFraction(float p);  /// Set the fraction of Hcal needed for HF,
0964                                     /// neutral hadrons, and charged particles
0965     float hcalFraction() const {
0966       return (hcalFraction_ / 100.);
0967     }  /// Fraction of Hcal for HF, neutral hadrons, and charged particles
0968 
0969     // isolated charged hadrons
0970     void setIsIsolatedChargedHadron(bool p);  /// Set isolation (as in particle flow, i.e. at calorimeter
0971                                               /// surface rather than at PV) flat for charged hadrons
0972     bool isIsolatedChargedHadron() const {
0973       return isIsolatedChargedHadron_;
0974     }  /// Flag isolation (as in particle flow, i.e. at calorimeter surface rather
0975     /// than at PV) flag for charged hadrons
0976 
0977     struct PackedCovariance {
0978       PackedCovariance()
0979           : dxydxy(0), dxydz(0), dzdz(0), dlambdadz(0), dphidxy(0), dptdpt(0), detadeta(0), dphidphi(0) {}
0980       // 3D IP covariance
0981       uint16_t dxydxy;
0982       uint16_t dxydz;
0983       uint16_t dzdz;
0984       // other IP relevant elements
0985       uint16_t dlambdadz;
0986       uint16_t dphidxy;
0987       // other diag elements
0988       uint16_t dptdpt;
0989       uint16_t detadeta;
0990       uint16_t dphidphi;
0991     };
0992 
0993     /// time (wrt nominal zero of the collision)
0994     virtual float time() const { return vertexRef()->t() + dtimeAssociatedPV(); }
0995     /// dtime with respect to the PV[ipv]
0996     virtual float dtime(size_t ipv = 0) const {
0997       return dtimeAssociatedPV() + (*pvRefProd_)[pvRefKey_].t() - (*pvRefProd_)[ipv].t();
0998     }
0999     /// dtime with respect to the PV ref
1000     virtual float dtimeAssociatedPV() const {
1001       if (packedTime_ == 0)
1002         return 0.f;
1003       if (packedTimeError_ > 0)
1004         return unpackTimeWithError(packedTime_, packedTimeError_);
1005       else
1006         return unpackTimeNoError(packedTime_);
1007     }
1008     /// time measurement uncertainty (-1 if not available)
1009     virtual float timeError() const { return unpackTimeError(packedTimeError_); }
1010     /// set time measurement
1011     void setDTimeAssociatedPV(float aTime, float aTimeError = 0);
1012     /// set time measurement
1013     void setTime(float aTime, float aTimeError = 0) { setDTimeAssociatedPV(aTime - vertexRef()->t(), aTimeError); }
1014 
1015   private:
1016     void unpackCovarianceElement(reco::TrackBase::CovarianceMatrix &m, uint16_t packed, int i, int j) const {
1017       m(i, j) = covarianceParameterization().unpack(
1018           packed, covarianceSchema_, i, j, pt(), eta(), numberOfHits(), numberOfPixelHits());
1019     }
1020     uint16_t packCovarianceElement(const reco::TrackBase::CovarianceMatrix &m, int i, int j) const {
1021       return covarianceParameterization().pack(
1022           m(i, j), covarianceSchema_, i, j, pt(), eta(), numberOfHits(), numberOfPixelHits());
1023     }
1024 
1025   protected:
1026     friend class ::testPackedCandidate;
1027     static constexpr float kMinDEtaToStore_ = 0.001;
1028     static constexpr float kMinDTrkPtToStore_ = 0.001;
1029 
1030     uint16_t packedPt_, packedEta_, packedPhi_, packedM_;
1031     uint16_t packedDxy_, packedDz_, packedDPhi_, packedDEta_, packedDTrkPt_;
1032     PackedCovariance packedCovariance_;
1033 
1034     void pack(bool unpackAfterwards = true);
1035     void unpack() const;
1036     void packVtx(bool unpackAfterwards = true);
1037     void unpackVtx() const;
1038     void packCovariance(const reco::TrackBase::CovarianceMatrix &m, bool unpackAfterwards = true);
1039     void unpackCovariance() const;
1040     void maybeUnpackBoth() const {
1041       if (!p4c_)
1042         unpack();
1043       if (!vertex_)
1044         unpackVtx();
1045     }
1046     void maybeUnpackTrack() const {
1047       if (!track_)
1048         unpackTrk();
1049     }
1050     void maybeUnpackCovariance() const {
1051       if (!m_)
1052         unpackCovariance();
1053     }
1054     void packBoth() {
1055       pack(false);
1056       packVtx(false);
1057       delete p4_.exchange(nullptr);
1058       delete p4c_.exchange(nullptr);
1059       delete vertex_.exchange(nullptr);
1060       unpack();
1061       unpackVtx();
1062     }  // do it this way, so that we don't loose precision on the angles before
1063     // computing dxy,dz
1064     void unpackTrk() const;
1065 
1066     uint8_t packedPuppiweight_;
1067     int8_t packedPuppiweightNoLepDiff_;  // storing the DIFFERENCE of (all - "no
1068                                          // lep") for compression optimization
1069     uint8_t rawCaloFraction_;
1070     int8_t rawHcalFraction_;
1071     uint8_t caloFraction_;
1072     int8_t hcalFraction_;
1073     int16_t packedTime_;
1074     uint8_t packedTimeError_;
1075 
1076     bool isIsolatedChargedHadron_;
1077 
1078     /// the four vector
1079     mutable std::atomic<PolarLorentzVector *> p4_;
1080     mutable std::atomic<LorentzVector *> p4c_;
1081     /// vertex position
1082     mutable std::atomic<Point *> vertex_;
1083     CMS_THREAD_GUARD(vertex_) mutable float dxy_, dz_, dphi_, deta_, dtrkpt_;
1084     /// reco::Track
1085     mutable std::atomic<reco::Track *> track_;
1086     /// PDG identifier
1087     int pdgId_;
1088     uint16_t qualityFlags_;
1089     /// Use these to build a Ref to primary vertex
1090     reco::VertexRefProd pvRefProd_;
1091     reco::VertexRef::key_type pvRefKey_;
1092 
1093     /// IP covariance
1094     mutable std::atomic<reco::TrackBase::CovarianceMatrix *> m_;
1095     uint8_t packedHits_,
1096         packedLayers_;  // packedLayers_ -> layers with valid hits; packedHits_ ->
1097                         // extra hits beyond the one-per-layer implied by
1098                         // packedLayers_
1099 
1100     /// track quality information
1101     uint8_t normalizedChi2_;
1102     uint16_t covarianceVersion_;
1103     uint16_t covarianceSchema_;
1104     CMS_THREAD_SAFE static CovarianceParameterization covarianceParameterization_;
1105     // static std::atomic<CovarianceParameterization*>
1106     // covarianceParameterization_;
1107     static std::once_flag covariance_load_flag;
1108     const CovarianceParameterization &covarianceParameterization() const {
1109       if (!hasTrackDetails())
1110         throw edm::Exception(edm::errors::InvalidReference,
1111                              "Trying to access covariance matrix for a "
1112                              "PackedCandidate for which it's not available. "
1113                              "Check hasTrackDetails() before!\n");
1114       std::call_once(
1115           covariance_load_flag, [](int v) { covarianceParameterization_.load(v); }, covarianceVersion_);
1116       if (covarianceParameterization_.loadedVersion() != covarianceVersion_) {
1117         throw edm::Exception(edm::errors::UnimplementedFeature)
1118             << "Attempting to load multiple covariance version in same process. "
1119                "This is not supported.";
1120       }
1121       return covarianceParameterization_;
1122     }
1123 
1124     /// details (hit pattern) of the first hit on track
1125     uint16_t firstHit_;
1126 
1127     /// track algorithm details
1128     uint16_t trkAlgoPacked_ = 0;
1129 
1130     /// check overlap with another Candidate
1131     bool overlap(const reco::Candidate &) const override;
1132     template <typename, typename, typename>
1133     friend struct component;
1134     friend class ::OverlapChecker;
1135     friend class ShallowCloneCandidate;
1136     friend class ShallowClonePtrCandidate;
1137 
1138     enum qualityFlagsShiftsAndMasks {
1139       assignmentQualityMask = 0x7,
1140       assignmentQualityShift = 0,
1141       trackHighPurityMask = 0x8,
1142       trackHighPurityShift = 3,
1143       lostInnerHitsMask = 0x30,
1144       lostInnerHitsShift = 4,
1145       muonFlagsMask = 0x0600,
1146       muonFlagsShift = 9,
1147       egammaFlagsMask = 0x0800,
1148       egammaFlagsShift = 11
1149     };
1150 
1151     /// static to allow unit testing
1152     static uint8_t packTimeError(float timeError);
1153     static float unpackTimeError(uint8_t timeError);
1154     static float unpackTimeNoError(int16_t time);
1155     static int16_t packTimeNoError(float time);
1156     static float unpackTimeWithError(int16_t time, uint8_t timeError);
1157     static int16_t packTimeWithError(float time, float timeError);
1158     static constexpr float MIN_TIMEERROR = 0.002f;      // 2 ps, smallest storable non-zero uncertainty
1159     static constexpr float MIN_TIME_NOERROR = 0.0002f;  // 0.2 ps, smallest non-zero time that can be stored by
1160                                                         // packTimeNoError
1161     static constexpr int EXPO_TIMEERROR = 5;            // power of 2 used in encoding timeError
1162     static constexpr int EXPO_TIME_NOERROR = 6;         // power of 2 used in encoding time without timeError
1163     static constexpr int EXPO_TIME_WITHERROR = -6;      // power of 2 used in encoding time with timeError
1164   };
1165 
1166   typedef std::vector<pat::PackedCandidate> PackedCandidateCollection;
1167   typedef edm::Ref<pat::PackedCandidateCollection> PackedCandidateRef;
1168   typedef edm::RefVector<pat::PackedCandidateCollection> PackedCandidateRefVector;
1169 }  // namespace pat
1170 
1171 #endif