Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:35:52

0001 #ifndef GsfElectron_h
0002 #define GsfElectron_h
0003 
0004 #include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
0005 #include "DataFormats/EgammaCandidates/interface/GsfElectronCore.h"
0006 #include "DataFormats/RecoCandidate/interface/RecoCandidate.h"
0007 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
0008 //#include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
0009 #include "DataFormats/TrackReco/interface/TrackFwd.h"
0010 #include "DataFormats/TrackReco/interface/Track.h"
0011 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
0012 #include "DataFormats/EgammaReco/interface/SuperClusterFwd.h"
0013 #include "DataFormats/CaloRecHit/interface/CaloClusterFwd.h"
0014 #include "DataFormats/CaloTowers/interface/CaloTowerDetId.h"
0015 //#include "DataFormats/Math/interface/LorentzVector.h"
0016 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0017 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
0018 #include <vector>
0019 #include <limits>
0020 #include <numeric>
0021 
0022 namespace reco {
0023 
0024   /****************************************************************************
0025  * \class reco::GsfElectron
0026  *
0027  * An Electron with a GsfTrack seeded from an ElectronSeed.
0028  * Renamed from PixelMatchGsfElectron.
0029  * Originally adapted from the TRecElectron class in ORCA.
0030  *
0031  * \author Claude Charlot - Laboratoire Leprince-Ringuet - École polytechnique, CNRS/IN2P3
0032  * \author David Chamont  - Laboratoire Leprince-Ringuet - École polytechnique, CNRS/IN2P3
0033  *
0034  ****************************************************************************/
0035 
0036   class GsfElectron : public RecoCandidate {
0037     //=======================================================
0038     // Constructors
0039     //
0040     // The clone() method with arguments, and the copy
0041     // constructor with edm references is designed for
0042     // someone which want to duplicates all
0043     // collections.
0044     //=======================================================
0045 
0046   public:
0047     // some nested structures defined later on
0048     struct ChargeInfo;
0049     struct TrackClusterMatching;
0050     struct TrackExtrapolations;
0051     struct ClosestCtfTrack;
0052     struct FiducialFlags;
0053     struct ShowerShape;
0054     struct IsolationVariables;
0055     struct ConversionRejection;
0056     struct ClassificationVariables;
0057     struct SaturationInfo;
0058 
0059     GsfElectron();
0060     GsfElectron(const GsfElectronCoreRef &);
0061     GsfElectron(const GsfElectron &, const GsfElectronCoreRef &);
0062     GsfElectron(const GsfElectron &electron,
0063                 const GsfElectronCoreRef &core,
0064                 const CaloClusterPtr &electronCluster,
0065                 const TrackRef &closestCtfTrack,
0066                 const TrackBaseRef &conversionPartner,
0067                 const GsfTrackRefVector &ambiguousTracks);
0068     GsfElectron(int charge,
0069                 const ChargeInfo &,
0070                 const GsfElectronCoreRef &,
0071                 const TrackClusterMatching &,
0072                 const TrackExtrapolations &,
0073                 const ClosestCtfTrack &,
0074                 const FiducialFlags &,
0075                 const ShowerShape &,
0076                 const ConversionRejection &);
0077     GsfElectron(int charge,
0078                 const ChargeInfo &,
0079                 const GsfElectronCoreRef &,
0080                 const TrackClusterMatching &,
0081                 const TrackExtrapolations &,
0082                 const ClosestCtfTrack &,
0083                 const FiducialFlags &,
0084                 const ShowerShape &,
0085                 const ShowerShape &,
0086                 const ConversionRejection &,
0087                 const SaturationInfo &);
0088     GsfElectron *clone() const override;
0089     GsfElectron *clone(const GsfElectronCoreRef &core,
0090                        const CaloClusterPtr &electronCluster,
0091                        const TrackRef &closestCtfTrack,
0092                        const TrackBaseRef &conversionPartner,
0093                        const GsfTrackRefVector &ambiguousTracks) const;
0094     ~GsfElectron() override {}
0095 
0096   private:
0097     void init();
0098 
0099     //=======================================================
0100     // Candidate methods and complementary information
0101     //
0102     // The gsf electron producer has tried to best evaluate
0103     // the four momentum and charge and given those values to
0104     // the GsfElectron constructor, which forwarded them to
0105     // the Candidate constructor. Those values can be retreived
0106     // with getters inherited from Candidate : p4() and charge().
0107     //=======================================================
0108 
0109   public:
0110     // Inherited from Candidate
0111     // const LorentzVector & charge() const ;
0112     // const LorentzVector & p4() const ;
0113 
0114     // Complementary struct
0115     struct ChargeInfo {
0116       int scPixCharge;
0117       bool isGsfCtfScPixConsistent;
0118       bool isGsfScPixConsistent;
0119       bool isGsfCtfConsistent;
0120       ChargeInfo()
0121           : scPixCharge(0), isGsfCtfScPixConsistent(false), isGsfScPixConsistent(false), isGsfCtfConsistent(false) {}
0122     };
0123 
0124     // Charge info accessors
0125     // to get gsf track charge: gsfTrack()->charge()
0126     // to get ctf track charge, if closestCtfTrackRef().isNonnull(): closestCtfTrackRef()->charge()
0127     int scPixCharge() const { return chargeInfo_.scPixCharge; }
0128     bool isGsfCtfScPixChargeConsistent() const { return chargeInfo_.isGsfCtfScPixConsistent; }
0129     bool isGsfScPixChargeConsistent() const { return chargeInfo_.isGsfScPixConsistent; }
0130     bool isGsfCtfChargeConsistent() const { return chargeInfo_.isGsfCtfConsistent; }
0131     const ChargeInfo &chargeInfo() const { return chargeInfo_; }
0132 
0133     // Candidate redefined methods
0134     bool isElectron() const override { return true; }
0135     bool overlap(const Candidate &) const override;
0136 
0137   private:
0138     // Complementary attributes
0139     ChargeInfo chargeInfo_;
0140 
0141     //=======================================================
0142     // Core Attributes
0143     //
0144     // They all have been computed before, when building the
0145     // collection of GsfElectronCore instances. Each GsfElectron
0146     // has a reference toward a GsfElectronCore.
0147     //=======================================================
0148 
0149   public:
0150     // accessors
0151     virtual GsfElectronCoreRef core() const;
0152     void setCore(const reco::GsfElectronCoreRef &core) { core_ = core; }
0153 
0154     // forward core methods
0155     SuperClusterRef superCluster() const override { return core()->superCluster(); }
0156     GsfTrackRef gsfTrack() const override { return core()->gsfTrack(); }
0157     float ctfGsfOverlap() const { return core()->ctfGsfOverlap(); }
0158     bool ecalDrivenSeed() const { return core()->ecalDrivenSeed(); }
0159     bool trackerDrivenSeed() const { return core()->trackerDrivenSeed(); }
0160     virtual SuperClusterRef parentSuperCluster() const { return core()->parentSuperCluster(); }
0161     bool closestCtfTrackRefValid() const {
0162       return closestCtfTrackRef().isAvailable() && closestCtfTrackRef().isNonnull();
0163     }
0164     //methods used for MVA variables
0165     float closestCtfTrackNormChi2() const {
0166       return closestCtfTrackRefValid() ? closestCtfTrackRef()->normalizedChi2() : 0;
0167     }
0168     int closestCtfTrackNLayers() const {
0169       return closestCtfTrackRefValid() ? closestCtfTrackRef()->hitPattern().trackerLayersWithMeasurement() : -1;
0170     }
0171 
0172     // backward compatibility
0173     struct ClosestCtfTrack {
0174       TrackRef ctfTrack;      // best matching ctf track
0175       float shFracInnerHits;  // fraction of common hits between the ctf and gsf tracks
0176       ClosestCtfTrack() : shFracInnerHits(0.) {}
0177       ClosestCtfTrack(TrackRef track, float sh) : ctfTrack(track), shFracInnerHits(sh) {}
0178     };
0179     float shFracInnerHits() const { return core()->ctfGsfOverlap(); }
0180     virtual TrackRef closestCtfTrackRef() const { return core()->ctfTrack(); }
0181     virtual ClosestCtfTrack closestCtfTrack() const {
0182       return ClosestCtfTrack(core()->ctfTrack(), core()->ctfGsfOverlap());
0183     }
0184 
0185   private:
0186     // attributes
0187     GsfElectronCoreRef core_;
0188 
0189     //=======================================================
0190     // Track-Cluster Matching Attributes
0191     //=======================================================
0192 
0193   public:
0194     struct TrackClusterMatching {
0195       CaloClusterPtr electronCluster;  // basic cluster best matching gsf track
0196       float eSuperClusterOverP;        // the supercluster energy / track momentum at the PCA to the beam spot
0197       float eSeedClusterOverP;         // the seed cluster energy / track momentum at the PCA to the beam spot
0198       float eSeedClusterOverPout;  // the seed cluster energy / track momentum at calo extrapolated from the outermost track state
0199       float eEleClusterOverPout;  // the electron cluster energy / track momentum at calo extrapolated from the outermost track state
0200       float deltaEtaSuperClusterAtVtx;  // the supercluster eta - track eta position at calo extrapolated from innermost track state
0201       float deltaEtaSeedClusterAtCalo;  // the seed cluster eta - track eta position at calo extrapolated from the outermost track state
0202       float deltaEtaEleClusterAtCalo;  // the electron cluster eta - track eta position at calo extrapolated from the outermost state
0203       float deltaPhiEleClusterAtCalo;  // the electron cluster phi - track phi position at calo extrapolated from the outermost track state
0204       float deltaPhiSuperClusterAtVtx;  // the supercluster phi - track phi position at calo extrapolated from the innermost track state
0205       float deltaPhiSeedClusterAtCalo;  // the seed cluster phi - track phi position at calo extrapolated from the outermost track state
0206       TrackClusterMatching()
0207           : eSuperClusterOverP(0.),
0208             eSeedClusterOverP(0.),
0209             eSeedClusterOverPout(0.),
0210             eEleClusterOverPout(0.),
0211             deltaEtaSuperClusterAtVtx(std::numeric_limits<float>::max()),
0212             deltaEtaSeedClusterAtCalo(std::numeric_limits<float>::max()),
0213             deltaEtaEleClusterAtCalo(std::numeric_limits<float>::max()),
0214             deltaPhiEleClusterAtCalo(std::numeric_limits<float>::max()),
0215             deltaPhiSuperClusterAtVtx(std::numeric_limits<float>::max()),
0216             deltaPhiSeedClusterAtCalo(std::numeric_limits<float>::max()) {}
0217     };
0218 
0219     // accessors
0220     CaloClusterPtr electronCluster() const { return trackClusterMatching_.electronCluster; }
0221     float eSuperClusterOverP() const { return trackClusterMatching_.eSuperClusterOverP; }
0222     float eSeedClusterOverP() const { return trackClusterMatching_.eSeedClusterOverP; }
0223     float eSeedClusterOverPout() const { return trackClusterMatching_.eSeedClusterOverPout; }
0224     float eEleClusterOverPout() const { return trackClusterMatching_.eEleClusterOverPout; }
0225     float deltaEtaSuperClusterTrackAtVtx() const { return trackClusterMatching_.deltaEtaSuperClusterAtVtx; }
0226     float deltaEtaSeedClusterTrackAtCalo() const { return trackClusterMatching_.deltaEtaSeedClusterAtCalo; }
0227     float deltaEtaEleClusterTrackAtCalo() const { return trackClusterMatching_.deltaEtaEleClusterAtCalo; }
0228     float deltaPhiSuperClusterTrackAtVtx() const { return trackClusterMatching_.deltaPhiSuperClusterAtVtx; }
0229     float deltaPhiSeedClusterTrackAtCalo() const { return trackClusterMatching_.deltaPhiSeedClusterAtCalo; }
0230     float deltaPhiEleClusterTrackAtCalo() const { return trackClusterMatching_.deltaPhiEleClusterAtCalo; }
0231     float deltaEtaSeedClusterTrackAtVtx() const {
0232       return superCluster().isNonnull() && superCluster()->seed().isNonnull()
0233                  ? trackClusterMatching_.deltaEtaSuperClusterAtVtx - superCluster()->eta() +
0234                        superCluster()->seed()->eta()
0235                  : std::numeric_limits<float>::max();
0236     }
0237     const TrackClusterMatching &trackClusterMatching() const { return trackClusterMatching_; }
0238 
0239     // for backward compatibility, usefull ?
0240     void setDeltaEtaSuperClusterAtVtx(float de) { trackClusterMatching_.deltaEtaSuperClusterAtVtx = de; }
0241     void setDeltaPhiSuperClusterAtVtx(float dphi) { trackClusterMatching_.deltaPhiSuperClusterAtVtx = dphi; }
0242 
0243   private:
0244     // attributes
0245     TrackClusterMatching trackClusterMatching_;
0246 
0247     //=======================================================
0248     // Track extrapolations
0249     //=======================================================
0250 
0251   public:
0252     struct TrackExtrapolations {
0253       math::XYZPointF positionAtVtx;   // the track PCA to the beam spot
0254       math::XYZPointF positionAtCalo;  // the track PCA to the supercluster position
0255       math::XYZVectorF momentumAtVtx;  // the track momentum at the PCA to the beam spot
0256       // the track momentum extrapolated at the supercluster position from the innermost track state
0257       math::XYZVectorF momentumAtCalo;
0258       // the track momentum extrapolated at the seed cluster position from the outermost track state
0259       math::XYZVectorF momentumOut;
0260       // the track momentum extrapolated at the ele cluster position from the outermost track state
0261       math::XYZVectorF momentumAtEleClus;
0262       math::XYZVectorF momentumAtVtxWithConstraint;  // the track momentum at the PCA to the beam spot using bs constraint
0263     };
0264 
0265     // accessors
0266     math::XYZPointF trackPositionAtVtx() const { return trackExtrapolations_.positionAtVtx; }
0267     math::XYZPointF trackPositionAtCalo() const { return trackExtrapolations_.positionAtCalo; }
0268     math::XYZVectorF trackMomentumAtVtx() const { return trackExtrapolations_.momentumAtVtx; }
0269     math::XYZVectorF trackMomentumAtCalo() const { return trackExtrapolations_.momentumAtCalo; }
0270     math::XYZVectorF trackMomentumOut() const { return trackExtrapolations_.momentumOut; }
0271     math::XYZVectorF trackMomentumAtEleClus() const { return trackExtrapolations_.momentumAtEleClus; }
0272     math::XYZVectorF trackMomentumAtVtxWithConstraint() const {
0273       return trackExtrapolations_.momentumAtVtxWithConstraint;
0274     }
0275     const TrackExtrapolations &trackExtrapolations() const { return trackExtrapolations_; }
0276 
0277     // setter (if you know what you're doing)
0278     void setTrackExtrapolations(const TrackExtrapolations &te) { trackExtrapolations_ = te; }
0279 
0280     // for backward compatibility
0281     math::XYZPointF TrackPositionAtVtx() const { return trackPositionAtVtx(); }
0282     math::XYZPointF TrackPositionAtCalo() const { return trackPositionAtCalo(); }
0283 
0284   private:
0285     // attributes
0286     TrackExtrapolations trackExtrapolations_;
0287 
0288     //=======================================================
0289     // SuperCluster direct access
0290     //=======================================================
0291 
0292   public:
0293     // direct accessors
0294     math::XYZPoint superClusterPosition() const { return superCluster()->position(); }  // the super cluster position
0295     int basicClustersSize() const {
0296       return superCluster()->clustersSize();
0297     }  // number of basic clusters inside the supercluster
0298     CaloCluster_iterator basicClustersBegin() const { return superCluster()->clustersBegin(); }
0299     CaloCluster_iterator basicClustersEnd() const { return superCluster()->clustersEnd(); }
0300 
0301     // for backward compatibility
0302     math::XYZPoint caloPosition() const { return superCluster()->position(); }
0303 
0304     //=======================================================
0305     // Fiducial Flags
0306     //=======================================================
0307 
0308   public:
0309     struct FiducialFlags {
0310       bool isEB;         // true if particle is in ECAL Barrel
0311       bool isEE;         // true if particle is in ECAL Endcaps
0312       bool isEBEEGap;    // true if particle is in the crack between EB and EE
0313       bool isEBEtaGap;   // true if particle is in EB, and inside the eta gaps between modules
0314       bool isEBPhiGap;   // true if particle is in EB, and inside the phi gaps between modules
0315       bool isEEDeeGap;   // true if particle is in EE, and inside the gaps between dees
0316       bool isEERingGap;  // true if particle is in EE, and inside the gaps between rings
0317       FiducialFlags()
0318           : isEB(false),
0319             isEE(false),
0320             isEBEEGap(false),
0321             isEBEtaGap(false),
0322             isEBPhiGap(false),
0323             isEEDeeGap(false),
0324             isEERingGap(false) {}
0325     };
0326 
0327     // accessors
0328     bool isEB() const { return fiducialFlags_.isEB; }
0329     bool isEE() const { return fiducialFlags_.isEE; }
0330     bool isGap() const { return ((isEBEEGap()) || (isEBGap()) || (isEEGap())); }
0331     bool isEBEEGap() const { return fiducialFlags_.isEBEEGap; }
0332     bool isEBGap() const { return (isEBEtaGap() || isEBPhiGap()); }
0333     bool isEBEtaGap() const { return fiducialFlags_.isEBEtaGap; }
0334     bool isEBPhiGap() const { return fiducialFlags_.isEBPhiGap; }
0335     bool isEEGap() const { return (isEEDeeGap() || isEERingGap()); }
0336     bool isEEDeeGap() const { return fiducialFlags_.isEEDeeGap; }
0337     bool isEERingGap() const { return fiducialFlags_.isEERingGap; }
0338     const FiducialFlags &fiducialFlags() const { return fiducialFlags_; }
0339     // setters... not necessary in regular situations
0340     // but handy for late stage modifications of electron objects
0341     void setFFlagIsEB(const bool b) { fiducialFlags_.isEB = b; }
0342     void setFFlagIsEE(const bool b) { fiducialFlags_.isEE = b; }
0343     void setFFlagIsEBEEGap(const bool b) { fiducialFlags_.isEBEEGap = b; }
0344     void setFFlagIsEBEtaGap(const bool b) { fiducialFlags_.isEBEtaGap = b; }
0345     void setFFlagIsEBPhiGap(const bool b) { fiducialFlags_.isEBPhiGap = b; }
0346     void setFFlagIsEEDeeGap(const bool b) { fiducialFlags_.isEEDeeGap = b; }
0347     void setFFlagIsEERingGap(const bool b) { fiducialFlags_.isEERingGap = b; }
0348 
0349   private:
0350     // attributes
0351     FiducialFlags fiducialFlags_;
0352 
0353     //=======================================================
0354     // Shower Shape Variables
0355     //=======================================================
0356 
0357   public:
0358     struct ShowerShape {
0359       float sigmaEtaEta;    // weighted cluster rms along eta and inside 5x5 (absolute eta)
0360       float sigmaIetaIeta;  // weighted cluster rms along eta and inside 5x5 (Xtal eta)
0361       float sigmaIphiIphi;  // weighted cluster rms along phi and inside 5x5 (Xtal phi)
0362       float e1x5;           // energy inside 1x5 in etaxphi around the seed Xtal
0363       float e2x5Max;        // energy inside 2x5 in etaxphi around the seed Xtal (max bwt the 2 possible sums)
0364       float e5x5;           // energy inside 5x5 in etaxphi around the seed Xtal
0365       float r9;             // ratio of the 3x3 energy and supercluster energy
0366       float hcalDepth1OverEcal;  // run2 hcal over ecal seed cluster energy using 1st hcal depth (using hcal towers within a cone)
0367       float hcalDepth2OverEcal;  // run2 hcal over ecal seed cluster energy using 2nd hcal depth (using hcal towers within a cone)
0368       float hcalDepth1OverEcalBc;  // run2 hcal over ecal seed cluster energy using 1st hcal depth (using hcal towers behind clusters)
0369       float hcalDepth2OverEcalBc;  // run2 hcal over ecal seed cluster energy using 2nd hcal depth (using hcal towers behind clusters)
0370       std::array<float, 7>
0371           hcalOverEcal;  // run3 hcal over ecal seed cluster energy per depth (using rechits within a cone)
0372       std::array<float, 7>
0373           hcalOverEcalBc;  // run3 hcal over ecal seed cluster energy per depth (using rechits behind clusters)
0374       std::vector<CaloTowerDetId> hcalTowersBehindClusters;
0375       bool invalidHcal;  // set to true if the hcal energy estimate is not valid (e.g. the corresponding tower was off or masked)
0376       bool pre7DepthHcal;  // to work around an ioread rule issue on legacy RECO files
0377       float sigmaIetaIphi;
0378       float eMax;
0379       float e2nd;
0380       float eTop;
0381       float eLeft;
0382       float eRight;
0383       float eBottom;
0384       float e2x5Top;
0385       float e2x5Left;
0386       float e2x5Right;
0387       float e2x5Bottom;
0388       ShowerShape()
0389           : sigmaEtaEta(std::numeric_limits<float>::max()),
0390             sigmaIetaIeta(std::numeric_limits<float>::max()),
0391             sigmaIphiIphi(std::numeric_limits<float>::max()),
0392             e1x5(0.f),
0393             e2x5Max(0.f),
0394             e5x5(0.f),
0395             r9(-std::numeric_limits<float>::max()),
0396             hcalDepth1OverEcal(0.f),
0397             hcalDepth2OverEcal(0.f),
0398             hcalDepth1OverEcalBc(0.f),
0399             hcalDepth2OverEcalBc(0.f),
0400             hcalOverEcal{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
0401             hcalOverEcalBc{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
0402             invalidHcal(false),
0403             pre7DepthHcal(true),
0404             sigmaIetaIphi(0.f),
0405             eMax(0.f),
0406             e2nd(0.f),
0407             eTop(0.f),
0408             eLeft(0.f),
0409             eRight(0.f),
0410             eBottom(0.f),
0411             e2x5Top(0.f),
0412             e2x5Left(0.f),
0413             e2x5Right(0.f),
0414             e2x5Bottom(0.f) {}
0415     };
0416 
0417     // accessors
0418     float sigmaEtaEta() const { return showerShape_.sigmaEtaEta; }
0419     float sigmaIetaIeta() const { return showerShape_.sigmaIetaIeta; }
0420     float sigmaIphiIphi() const { return showerShape_.sigmaIphiIphi; }
0421     float e1x5() const { return showerShape_.e1x5; }
0422     float e2x5Max() const { return showerShape_.e2x5Max; }
0423     float e5x5() const { return showerShape_.e5x5; }
0424     float r9() const { return showerShape_.r9; }
0425     float hcalOverEcal(const ShowerShape &ss, int depth) const {
0426       if (ss.pre7DepthHcal) {
0427         if (depth == 0)
0428           return ss.hcalDepth1OverEcal + ss.hcalDepth2OverEcal;
0429         else if (depth == 1)
0430           return ss.hcalDepth1OverEcal;
0431         else if (depth == 2)
0432           return ss.hcalDepth2OverEcal;
0433 
0434         return 0.f;
0435       } else {
0436         const auto &hovere = ss.hcalOverEcal;
0437         return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hovere), std::end(hovere), 0.f)
0438                                             : hovere[depth - 1];
0439       }
0440     }
0441     float hcalOverEcal(int depth = 0) const { return hcalOverEcal(showerShape_, depth); }
0442     float hcalOverEcalBc(const ShowerShape &ss, int depth) const {
0443       if (ss.pre7DepthHcal) {
0444         if (depth == 0)
0445           return ss.hcalDepth1OverEcalBc + ss.hcalDepth2OverEcalBc;
0446         else if (depth == 1)
0447           return ss.hcalDepth1OverEcalBc;
0448         else if (depth == 2)
0449           return ss.hcalDepth2OverEcalBc;
0450 
0451         return 0.f;
0452       } else {
0453         const auto &hovere = ss.hcalOverEcalBc;
0454         return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hovere), std::end(hovere), 0.f)
0455                                             : hovere[depth - 1];
0456       }
0457     }
0458     float hcalOverEcalBc(int depth = 0) const { return hcalOverEcalBc(showerShape_, depth); }
0459     const std::vector<CaloTowerDetId> &hcalTowersBehindClusters() const {
0460       return showerShape_.hcalTowersBehindClusters;
0461     }
0462     bool hcalOverEcalValid() const { return !showerShape_.invalidHcal; }
0463     float eLeft() const { return showerShape_.eLeft; }
0464     float eRight() const { return showerShape_.eRight; }
0465     float eTop() const { return showerShape_.eTop; }
0466     float eBottom() const { return showerShape_.eBottom; }
0467     const ShowerShape &showerShape() const { return showerShape_; }
0468     // non-zero-suppressed and no-fractions shower shapes
0469     // ecal energy is always that from the full 5x5
0470     float full5x5_sigmaEtaEta() const { return full5x5_showerShape_.sigmaEtaEta; }
0471     float full5x5_sigmaIetaIeta() const { return full5x5_showerShape_.sigmaIetaIeta; }
0472     float full5x5_sigmaIphiIphi() const { return full5x5_showerShape_.sigmaIphiIphi; }
0473     float full5x5_e1x5() const { return full5x5_showerShape_.e1x5; }
0474     float full5x5_e2x5Max() const { return full5x5_showerShape_.e2x5Max; }
0475     float full5x5_e5x5() const { return full5x5_showerShape_.e5x5; }
0476     float full5x5_r9() const { return full5x5_showerShape_.r9; }
0477     float full5x5_hcalOverEcal(int depth = 0) const { return hcalOverEcal(full5x5_showerShape_, depth); }
0478     float full5x5_hcalOverEcalBc(int depth = 0) const { return hcalOverEcalBc(full5x5_showerShape_, depth); }
0479     bool full5x5_hcalOverEcalValid() const { return !full5x5_showerShape_.invalidHcal; }
0480     float full5x5_e2x5Left() const { return full5x5_showerShape_.e2x5Left; }
0481     float full5x5_e2x5Right() const { return full5x5_showerShape_.e2x5Right; }
0482     float full5x5_e2x5Top() const { return full5x5_showerShape_.e2x5Top; }
0483     float full5x5_e2x5Bottom() const { return full5x5_showerShape_.e2x5Bottom; }
0484     float full5x5_eLeft() const { return full5x5_showerShape_.eLeft; }
0485     float full5x5_eRight() const { return full5x5_showerShape_.eRight; }
0486     float full5x5_eTop() const { return full5x5_showerShape_.eTop; }
0487     float full5x5_eBottom() const { return full5x5_showerShape_.eBottom; }
0488     const ShowerShape &full5x5_showerShape() const { return full5x5_showerShape_; }
0489 
0490     // setters (if you know what you're doing)
0491     void setShowerShape(const ShowerShape &s) { showerShape_ = s; }
0492     void full5x5_setShowerShape(const ShowerShape &s) { full5x5_showerShape_ = s; }
0493 
0494     // for backward compatibility (this will only ever be the ZS shapes!)
0495     float scSigmaEtaEta() const { return sigmaEtaEta(); }
0496     float scSigmaIEtaIEta() const { return sigmaIetaIeta(); }
0497     float scE1x5() const { return e1x5(); }
0498     float scE2x5Max() const { return e2x5Max(); }
0499     float scE5x5() const { return e5x5(); }
0500     float hadronicOverEm() const { return hcalOverEcal(); }
0501 
0502   private:
0503     // attributes
0504     ShowerShape showerShape_;
0505     ShowerShape full5x5_showerShape_;
0506 
0507     //=======================================================
0508     // SaturationInfo
0509     //=======================================================
0510 
0511   public:
0512     struct SaturationInfo {
0513       int nSaturatedXtals;
0514       bool isSeedSaturated;
0515       SaturationInfo() : nSaturatedXtals(0), isSeedSaturated(false) {}
0516     };
0517 
0518     // accessors
0519     float nSaturatedXtals() const { return saturationInfo_.nSaturatedXtals; }
0520     float isSeedSaturated() const { return saturationInfo_.isSeedSaturated; }
0521     const SaturationInfo &saturationInfo() const { return saturationInfo_; }
0522     void setSaturationInfo(const SaturationInfo &s) { saturationInfo_ = s; }
0523 
0524   private:
0525     SaturationInfo saturationInfo_;
0526 
0527     //=======================================================
0528     // Isolation Variables
0529     //=======================================================
0530 
0531   public:
0532     struct IsolationVariables {
0533       float tkSumPt;                           // track iso with electron footprint removed
0534       float tkSumPtHEEP;                       // track iso used for the HEEP ID
0535       float ecalRecHitSumEt;                   // ecal iso deposit with electron footprint removed
0536       float hcalDepth1TowerSumEt;              // hcal depth 1 iso deposit with electron footprint removed
0537       float hcalDepth2TowerSumEt;              // hcal depth 2 iso deposit with electron footprint removed
0538       float hcalDepth1TowerSumEtBc;            // hcal depth 1 iso deposit without towers behind clusters
0539       float hcalDepth2TowerSumEtBc;            // hcal depth 2 iso deposit without towers behind clusters
0540       std::array<float, 7> hcalRecHitSumEt;    // ...per depth, with electron footprint removed
0541       std::array<float, 7> hcalRecHitSumEtBc;  // ...per depth, with hcal rechit behind cluster removed
0542       bool pre7DepthHcal;                      // to work around an ioread rule issue on legacy RECO files
0543       IsolationVariables()
0544           : tkSumPt(0.),
0545             tkSumPtHEEP(0.),
0546             ecalRecHitSumEt(0.),
0547             hcalDepth1TowerSumEt(0.f),
0548             hcalDepth2TowerSumEt(0.f),
0549             hcalDepth1TowerSumEtBc(0.f),
0550             hcalDepth2TowerSumEtBc(0.f),
0551             hcalRecHitSumEt{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
0552             hcalRecHitSumEtBc{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
0553             pre7DepthHcal(true) {}
0554     };
0555 
0556     // 03 accessors
0557     float dr03TkSumPt() const { return dr03_.tkSumPt; }
0558     float dr03TkSumPtHEEP() const { return dr03_.tkSumPtHEEP; }
0559     float dr03EcalRecHitSumEt() const { return dr03_.ecalRecHitSumEt; }
0560     float hcalTowerSumEt(const IsolationVariables &iv, int depth) const {
0561       if (iv.pre7DepthHcal) {
0562         if (depth == 0)
0563           return iv.hcalDepth1TowerSumEt + iv.hcalDepth2TowerSumEt;
0564         else if (depth == 1)
0565           return iv.hcalDepth1TowerSumEt;
0566         else if (depth == 2)
0567           return iv.hcalDepth2TowerSumEt;
0568 
0569         return 0.f;
0570       } else {
0571         const auto &hcaliso = iv.hcalRecHitSumEt;
0572         return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hcaliso), std::end(hcaliso), 0.f)
0573                                             : hcaliso[depth - 1];
0574       }
0575     }
0576     float dr03HcalTowerSumEt(int depth = 0) const { return hcalTowerSumEt(dr03_, depth); }
0577     float hcalTowerSumEtBc(const IsolationVariables &iv, int depth) const {
0578       if (iv.pre7DepthHcal) {
0579         if (depth == 0)
0580           return iv.hcalDepth1TowerSumEtBc + iv.hcalDepth2TowerSumEtBc;
0581         else if (depth == 1)
0582           return iv.hcalDepth1TowerSumEtBc;
0583         else if (depth == 2)
0584           return iv.hcalDepth2TowerSumEtBc;
0585 
0586         return 0.f;
0587       } else {
0588         const auto &hcaliso = iv.hcalRecHitSumEtBc;
0589         return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hcaliso), std::end(hcaliso), 0.f)
0590                                             : hcaliso[depth - 1];
0591       }
0592     }
0593     float dr03HcalTowerSumEtBc(int depth = 0) const { return hcalTowerSumEtBc(dr03_, depth); }
0594     const IsolationVariables &dr03IsolationVariables() const { return dr03_; }
0595 
0596     // 04 accessors
0597     float dr04TkSumPt() const { return dr04_.tkSumPt; }
0598     float dr04TkSumPtHEEP() const { return dr04_.tkSumPtHEEP; }
0599     float dr04EcalRecHitSumEt() const { return dr04_.ecalRecHitSumEt; }
0600     float dr04HcalTowerSumEt(int depth = 0) const { return hcalTowerSumEt(dr04_, depth); }
0601     float dr04HcalTowerSumEtBc(int depth = 0) const { return hcalTowerSumEtBc(dr04_, depth); }
0602     const IsolationVariables &dr04IsolationVariables() const { return dr04_; }
0603 
0604     // setters ?!?
0605     void setDr03Isolation(const IsolationVariables &dr03) { dr03_ = dr03; }
0606     void setDr04Isolation(const IsolationVariables &dr04) { dr04_ = dr04; }
0607 
0608     // for backward compatibility
0609     void setIsolation03(const IsolationVariables &dr03) { dr03_ = dr03; }
0610     void setIsolation04(const IsolationVariables &dr04) { dr04_ = dr04; }
0611     const IsolationVariables &isolationVariables03() const { return dr03_; }
0612     const IsolationVariables &isolationVariables04() const { return dr04_; }
0613 
0614     // go back to run2-like 2 effective depths if desired - depth 1 is the normal depth 1, depth 2 is the sum over the rest
0615     void hcalToRun2EffDepth();
0616 
0617   private:
0618     // attributes
0619     IsolationVariables dr03_;
0620     IsolationVariables dr04_;
0621 
0622     //=======================================================
0623     // Conversion Rejection Information
0624     //=======================================================
0625 
0626   public:
0627     struct ConversionRejection {
0628       int flags;             // -max:not-computed, other: as computed by Puneeth conversion code
0629       TrackBaseRef partner;  // conversion partner
0630       float dist;            // distance to the conversion partner
0631       float dcot;            // difference of cot(angle) with the conversion partner track
0632       float radius;          // signed conversion radius
0633       float vtxFitProb;      //fit probablity (chi2/ndof) of the matched conversion vtx
0634       ConversionRejection()
0635           : flags(-1),
0636             dist(std::numeric_limits<float>::max()),
0637             dcot(std::numeric_limits<float>::max()),
0638             radius(std::numeric_limits<float>::max()),
0639             vtxFitProb(std::numeric_limits<float>::max()) {}
0640     };
0641 
0642     // accessors
0643     int convFlags() const { return conversionRejection_.flags; }
0644     TrackBaseRef convPartner() const { return conversionRejection_.partner; }
0645     float convDist() const { return conversionRejection_.dist; }
0646     float convDcot() const { return conversionRejection_.dcot; }
0647     float convRadius() const { return conversionRejection_.radius; }
0648     float convVtxFitProb() const { return conversionRejection_.vtxFitProb; }
0649     const ConversionRejection &conversionRejectionVariables() const { return conversionRejection_; }
0650     void setConversionRejectionVariables(const ConversionRejection &convRej) { conversionRejection_ = convRej; }
0651 
0652   private:
0653     // attributes
0654     ConversionRejection conversionRejection_;
0655 
0656     //=======================================================
0657     // Pflow Information
0658     //=======================================================
0659 
0660   public:
0661     struct PflowIsolationVariables {
0662       //first three data members that changed names, according to DataFormats/MuonReco/interface/MuonPFIsolation.h
0663       float sumChargedHadronPt;  //!< sum-pt of charged Hadron    // old float chargedHadronIso ;
0664       float sumNeutralHadronEt;  //!< sum pt of neutral hadrons  // old float neutralHadronIso ;
0665       float sumPhotonEt;         //!< sum pt of PF photons              // old float photonIso ;
0666       //then four new data members, corresponding to DataFormats/MuonReco/interface/MuonPFIsolation.h
0667       float sumChargedParticlePt;             //!< sum-pt of charged Particles(inludes e/mu)
0668       float sumNeutralHadronEtHighThreshold;  //!< sum pt of neutral hadrons with a higher threshold
0669       float sumPhotonEtHighThreshold;         //!< sum pt of PF photons with a higher threshold
0670       float sumPUPt;                          //!< sum pt of charged Particles not from PV  (for Pu corrections)
0671       //new pf cluster based isolation values
0672       float sumEcalClusterEt;  //sum pt of ecal clusters, vetoing clusters part of electron
0673       float sumHcalClusterEt;  //sum pt of hcal clusters, vetoing clusters part of electron
0674       PflowIsolationVariables()
0675           : sumChargedHadronPt(0),
0676             sumNeutralHadronEt(0),
0677             sumPhotonEt(0),
0678             sumChargedParticlePt(0),
0679             sumNeutralHadronEtHighThreshold(0),
0680             sumPhotonEtHighThreshold(0),
0681             sumPUPt(0),
0682             sumEcalClusterEt(0),
0683             sumHcalClusterEt(0) {}
0684     };
0685 
0686     struct MvaInput {
0687       int earlyBrem;                // Early Brem detected (-2=>unknown,-1=>could not be evaluated,0=>wrong,1=>true)
0688       int lateBrem;                 // Late Brem detected (-2=>unknown,-1=>could not be evaluated,0=>wrong,1=>true)
0689       float sigmaEtaEta;            // Sigma-eta-eta with the PF cluster
0690       float hadEnergy;              // Associated PF Had Cluster energy
0691       float deltaEta;               // PF-cluster GSF track delta-eta
0692       int nClusterOutsideMustache;  // -2 => unknown, -1 =>could not be evaluated, 0 and more => number of clusters
0693       float etOutsideMustache;
0694       MvaInput()
0695           : earlyBrem(-2),
0696             lateBrem(-2),
0697             sigmaEtaEta(std::numeric_limits<float>::max()),
0698             hadEnergy(0.),
0699             deltaEta(std::numeric_limits<float>::max()),
0700             nClusterOutsideMustache(-2),
0701             etOutsideMustache(-std::numeric_limits<float>::max()) {}
0702     };
0703 
0704     static constexpr float mvaPlaceholder = -999999999.;
0705 
0706     struct MvaOutput {
0707       int status;  // see PFCandidateElectronExtra::StatusFlag
0708       float mva_Isolated;
0709       float mva_e_pi;
0710       float mvaByPassForIsolated;  // complementary MVA used in preselection
0711       float dnn_e_sigIsolated;
0712       float dnn_e_sigNonIsolated;
0713       float dnn_e_bkgNonIsolated;
0714       float dnn_e_bkgTau;
0715       float dnn_e_bkgPhoton;
0716       MvaOutput()
0717           : status(-1),
0718             mva_Isolated(mvaPlaceholder),
0719             mva_e_pi(mvaPlaceholder),
0720             mvaByPassForIsolated(mvaPlaceholder),
0721             dnn_e_sigIsolated(mvaPlaceholder),
0722             dnn_e_sigNonIsolated(mvaPlaceholder),
0723             dnn_e_bkgNonIsolated(mvaPlaceholder),
0724             dnn_e_bkgTau(mvaPlaceholder),
0725             dnn_e_bkgPhoton(mvaPlaceholder) {}
0726     };
0727 
0728     // accessors
0729     const PflowIsolationVariables &pfIsolationVariables() const { return pfIso_; }
0730     //backwards compat functions for pat::Electron
0731     float ecalPFClusterIso() const { return pfIso_.sumEcalClusterEt; };
0732     float hcalPFClusterIso() const { return pfIso_.sumHcalClusterEt; };
0733 
0734     const MvaInput &mvaInput() const { return mvaInput_; }
0735     const MvaOutput &mvaOutput() const { return mvaOutput_; }
0736 
0737     // setters
0738     void setPfIsolationVariables(const PflowIsolationVariables &iso) { pfIso_ = iso; }
0739     void setMvaInput(const MvaInput &mi) { mvaInput_ = mi; }
0740     void setMvaOutput(const MvaOutput &mo) { mvaOutput_ = mo; }
0741 
0742     // for backward compatibility
0743     float mva_Isolated() const { return mvaOutput_.mva_Isolated; }
0744     float mva_e_pi() const { return mvaOutput_.mva_e_pi; }
0745     float dnn_signal_Isolated() const { return mvaOutput_.dnn_e_sigIsolated; }
0746     float dnn_signal_nonIsolated() const { return mvaOutput_.dnn_e_sigNonIsolated; }
0747     float dnn_bkg_nonIsolated() const { return mvaOutput_.dnn_e_bkgNonIsolated; }
0748     float dnn_bkg_Tau() const { return mvaOutput_.dnn_e_bkgTau; }
0749     float dnn_bkg_Photon() const { return mvaOutput_.dnn_e_bkgPhoton; }
0750 
0751   private:
0752     PflowIsolationVariables pfIso_;
0753     MvaInput mvaInput_;
0754     MvaOutput mvaOutput_;
0755 
0756     //=======================================================
0757     // Preselection and Ambiguity
0758     //=======================================================
0759 
0760   public:
0761     // accessors
0762     bool ecalDriven() const;  // return true if ecalDrivenSeed() and passingCutBasedPreselection()
0763     bool passingCutBasedPreselection() const { return passCutBasedPreselection_; }
0764     bool passingPflowPreselection() const { return passPflowPreselection_; }
0765     bool ambiguous() const { return ambiguous_; }
0766     GsfTrackRefVector::size_type ambiguousGsfTracksSize() const { return ambiguousGsfTracks_.size(); }
0767     auto const &ambiguousGsfTracks() const { return ambiguousGsfTracks_; }
0768 
0769     // setters
0770     void setPassCutBasedPreselection(bool flag) { passCutBasedPreselection_ = flag; }
0771     void setPassPflowPreselection(bool flag) { passPflowPreselection_ = flag; }
0772     void setAmbiguous(bool flag) { ambiguous_ = flag; }
0773     void clearAmbiguousGsfTracks() { ambiguousGsfTracks_.clear(); }
0774     void addAmbiguousGsfTrack(const reco::GsfTrackRef &t) { ambiguousGsfTracks_.push_back(t); }
0775 
0776     // backward compatibility
0777     void setPassMvaPreselection(bool flag) { passMvaPreslection_ = flag; }
0778     bool passingMvaPreselection() const { return passMvaPreslection_; }
0779 
0780   private:
0781     // attributes
0782     bool passCutBasedPreselection_;
0783     bool passPflowPreselection_;
0784     bool passMvaPreslection_;  // to be removed : passPflowPreslection_
0785     bool ambiguous_;
0786     GsfTrackRefVector ambiguousGsfTracks_;  // ambiguous gsf tracks
0787 
0788     //=======================================================
0789     // Brem Fractions and Classification
0790     //=======================================================
0791 
0792   public:
0793     struct ClassificationVariables {
0794       float trackFbrem;  // the brem fraction from gsf fit: (track momentum in - track momentum out) / track momentum in
0795       float superClusterFbrem;  // the brem fraction from supercluster: (supercluster energy - electron cluster energy) / supercluster energy
0796       constexpr static float kDefaultValue = -1.e30;
0797       ClassificationVariables() : trackFbrem(kDefaultValue), superClusterFbrem(kDefaultValue) {}
0798     };
0799     enum Classification { UNKNOWN = -1, GOLDEN = 0, BIGBREM = 1, BADTRACK = 2, SHOWERING = 3, GAP = 4 };
0800 
0801     // accessors
0802     float trackFbrem() const { return classVariables_.trackFbrem; }
0803     float superClusterFbrem() const { return classVariables_.superClusterFbrem; }
0804     const ClassificationVariables &classificationVariables() const { return classVariables_; }
0805     Classification classification() const { return class_; }
0806 
0807     // utilities
0808     int numberOfBrems() const { return basicClustersSize() - 1; }
0809     float fbrem() const { return trackFbrem(); }
0810 
0811     // setters
0812     void setTrackFbrem(float fbrem) { classVariables_.trackFbrem = fbrem; }
0813     void setSuperClusterFbrem(float fbrem) { classVariables_.superClusterFbrem = fbrem; }
0814     void setClassificationVariables(const ClassificationVariables &cv) { classVariables_ = cv; }
0815     void setClassification(Classification myclass) { class_ = myclass; }
0816 
0817   private:
0818     // attributes
0819     ClassificationVariables classVariables_;
0820     Classification class_;  // fbrem and number of clusters based electron classification
0821 
0822     //=======================================================
0823     // Corrections
0824     //
0825     // The only methods, with classification, which modify
0826     // the electrons after they have been constructed.
0827     // They change a given characteristic, such as the super-cluster
0828     // energy, and propagate the change consistently
0829     // to all the depending attributes.
0830     // We expect the methods to be called in a given order
0831     // and so to store specific kind of corrections
0832     // 1) classify()
0833     // 2) correctEcalEnergy() : depending on classification and eta
0834     // 3) correctMomemtum() : depending on classification and ecal energy and tracker momentum errors
0835     //
0836     // Beware that correctEcalEnergy() is modifying few attributes which
0837     // were potentially used for preselection, whose value used in
0838     // preselection will not be available any more :
0839     // hcalOverEcal, eSuperClusterOverP,
0840     // eSeedClusterOverP, eEleClusterOverPout.
0841     //=======================================================
0842 
0843   public:
0844     enum P4Kind { P4_UNKNOWN = -1, P4_FROM_SUPER_CLUSTER = 0, P4_COMBINATION = 1, P4_PFLOW_COMBINATION = 2 };
0845 
0846     struct Corrections {
0847       bool isEcalEnergyCorrected;  // true if ecal energy has been corrected
0848       float correctedEcalEnergy;  // corrected energy (if !isEcalEnergyCorrected this value is identical to the supercluster energy)
0849       float correctedEcalEnergyError;  // error on energy
0850       //bool isMomentumCorrected ;     // DEPRECATED
0851       float trackMomentumError;  // track momentum error from gsf fit
0852       //
0853       LorentzVector fromSuperClusterP4;  // for P4_FROM_SUPER_CLUSTER
0854       float fromSuperClusterP4Error;     // for P4_FROM_SUPER_CLUSTER
0855       LorentzVector combinedP4;          // for P4_COMBINATION
0856       float combinedP4Error;             // for P4_COMBINATION
0857       LorentzVector pflowP4;             // for P4_PFLOW_COMBINATION
0858       float pflowP4Error;                // for P4_PFLOW_COMBINATION
0859       P4Kind candidateP4Kind;            // say which momentum has been stored in reco::Candidate
0860       //
0861       Corrections()
0862           : isEcalEnergyCorrected(false),
0863             correctedEcalEnergy(0.),
0864             correctedEcalEnergyError(999.),
0865             /*isMomentumCorrected(false),*/ trackMomentumError(999.),
0866             fromSuperClusterP4Error(999.),
0867             combinedP4Error(999.),
0868             pflowP4Error(999.),
0869             candidateP4Kind(P4_UNKNOWN) {}
0870     };
0871 
0872     // setters
0873     void setCorrectedEcalEnergyError(float newEnergyError);
0874     void setCorrectedEcalEnergy(float newEnergy);
0875     void setCorrectedEcalEnergy(float newEnergy, bool rescaleDependentValues);
0876     void setTrackMomentumError(float trackMomentumError);
0877     void setP4(P4Kind kind, const LorentzVector &p4, float p4Error, bool setCandidate);
0878     using RecoCandidate::setP4;
0879 
0880     // accessors
0881     bool isEcalEnergyCorrected() const { return corrections_.isEcalEnergyCorrected; }
0882     float correctedEcalEnergy() const { return corrections_.correctedEcalEnergy; }
0883     float correctedEcalEnergyError() const { return corrections_.correctedEcalEnergyError; }
0884     float trackMomentumError() const { return corrections_.trackMomentumError; }
0885     const LorentzVector &p4(P4Kind kind) const;
0886     using RecoCandidate::p4;
0887     float p4Error(P4Kind kind) const;
0888     P4Kind candidateP4Kind() const { return corrections_.candidateP4Kind; }
0889     const Corrections &corrections() const { return corrections_; }
0890 
0891     // bare setter (if you know what you're doing)
0892     void setCorrections(const Corrections &c) { corrections_ = c; }
0893 
0894     // for backward compatibility
0895     void setEcalEnergyError(float energyError) { setCorrectedEcalEnergyError(energyError); }
0896     float ecalEnergy() const { return correctedEcalEnergy(); }
0897     float ecalEnergyError() const { return correctedEcalEnergyError(); }
0898     //bool isMomentumCorrected() const { return corrections_.isMomentumCorrected ; }
0899     float caloEnergy() const { return correctedEcalEnergy(); }
0900     bool isEnergyScaleCorrected() const { return isEcalEnergyCorrected(); }
0901     void correctEcalEnergy(float newEnergy, float newEnergyError, bool corrEovP = true) {
0902       setCorrectedEcalEnergy(newEnergy, corrEovP);
0903       setEcalEnergyError(newEnergyError);
0904     }
0905     void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error) {
0906       setTrackMomentumError(trackMomentumError);
0907       setP4(P4_COMBINATION, p4, p4Error, true);
0908     }
0909 
0910   private:
0911     // attributes
0912     Corrections corrections_;
0913 
0914   public:
0915     struct PixelMatchVariables {
0916       //! Pixel match variable: deltaPhi for innermost hit
0917       float dPhi1;
0918       //! Pixel match variable: deltaPhi for second hit
0919       float dPhi2;
0920       //! Pixel match variable: deltaRz for innermost hit
0921       float dRz1;
0922       //! Pixel match variable: deltaRz for second hit
0923       float dRz2;
0924       //! Subdetectors for first and second pixel hit
0925       unsigned char subdetectors;
0926       PixelMatchVariables() : dPhi1(-999), dPhi2(-999), dRz1(-999), dRz2(-999), subdetectors(0) {}
0927       ~PixelMatchVariables() {}
0928     };
0929     void setPixelMatchSubdetectors(int sd1, int sd2) { pixelMatchVariables_.subdetectors = 10 * sd1 + sd2; }
0930     void setPixelMatchDPhi1(float dPhi1) { pixelMatchVariables_.dPhi1 = dPhi1; }
0931     void setPixelMatchDPhi2(float dPhi2) { pixelMatchVariables_.dPhi2 = dPhi2; }
0932     void setPixelMatchDRz1(float dRz1) { pixelMatchVariables_.dRz1 = dRz1; }
0933     void setPixelMatchDRz2(float dRz2) { pixelMatchVariables_.dRz2 = dRz2; }
0934 
0935     int pixelMatchSubdetector1() const { return pixelMatchVariables_.subdetectors / 10; }
0936     int pixelMatchSubdetector2() const { return pixelMatchVariables_.subdetectors % 10; }
0937     float pixelMatchDPhi1() const { return pixelMatchVariables_.dPhi1; }
0938     float pixelMatchDPhi2() const { return pixelMatchVariables_.dPhi2; }
0939     float pixelMatchDRz1() const { return pixelMatchVariables_.dRz1; }
0940     float pixelMatchDRz2() const { return pixelMatchVariables_.dRz2; }
0941 
0942   private:
0943     PixelMatchVariables pixelMatchVariables_;
0944   };
0945 
0946 }  // namespace reco
0947 
0948 #endif