1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
|
#ifndef GsfElectron_h
#define GsfElectron_h
#include "DataFormats/EgammaCandidates/interface/GsfElectronFwd.h"
#include "DataFormats/EgammaCandidates/interface/GsfElectronCore.h"
#include "DataFormats/RecoCandidate/interface/RecoCandidate.h"
#include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
//#include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"
#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/EgammaReco/interface/SuperCluster.h"
#include "DataFormats/EgammaReco/interface/SuperClusterFwd.h"
#include "DataFormats/CaloRecHit/interface/CaloClusterFwd.h"
#include "DataFormats/CaloTowers/interface/CaloTowerDetId.h"
//#include "DataFormats/Math/interface/LorentzVector.h"
#include "DataFormats/GeometryVector/interface/GlobalPoint.h"
#include "DataFormats/GeometryVector/interface/GlobalVector.h"
#include <vector>
#include <limits>
#include <numeric>
namespace reco {
/****************************************************************************
* \class reco::GsfElectron
*
* An Electron with a GsfTrack seeded from an ElectronSeed.
* Renamed from PixelMatchGsfElectron.
* Originally adapted from the TRecElectron class in ORCA.
*
* \author Claude Charlot - Laboratoire Leprince-Ringuet - École polytechnique, CNRS/IN2P3
* \author David Chamont - Laboratoire Leprince-Ringuet - École polytechnique, CNRS/IN2P3
*
****************************************************************************/
class GsfElectron : public RecoCandidate {
//=======================================================
// Constructors
//
// The clone() method with arguments, and the copy
// constructor with edm references is designed for
// someone which want to duplicates all
// collections.
//=======================================================
public:
// some nested structures defined later on
struct ChargeInfo;
struct TrackClusterMatching;
struct TrackExtrapolations;
struct ClosestCtfTrack;
struct FiducialFlags;
struct ShowerShape;
struct IsolationVariables;
struct ConversionRejection;
struct ClassificationVariables;
struct SaturationInfo;
GsfElectron();
GsfElectron(const GsfElectronCoreRef &);
GsfElectron(const GsfElectron &, const GsfElectronCoreRef &);
GsfElectron(const GsfElectron &electron,
const GsfElectronCoreRef &core,
const CaloClusterPtr &electronCluster,
const TrackRef &closestCtfTrack,
const TrackBaseRef &conversionPartner,
const GsfTrackRefVector &ambiguousTracks);
GsfElectron(int charge,
const ChargeInfo &,
const GsfElectronCoreRef &,
const TrackClusterMatching &,
const TrackExtrapolations &,
const ClosestCtfTrack &,
const FiducialFlags &,
const ShowerShape &,
const ConversionRejection &);
GsfElectron(int charge,
const ChargeInfo &,
const GsfElectronCoreRef &,
const TrackClusterMatching &,
const TrackExtrapolations &,
const ClosestCtfTrack &,
const FiducialFlags &,
const ShowerShape &,
const ShowerShape &,
const ConversionRejection &,
const SaturationInfo &);
GsfElectron *clone() const override;
GsfElectron *clone(const GsfElectronCoreRef &core,
const CaloClusterPtr &electronCluster,
const TrackRef &closestCtfTrack,
const TrackBaseRef &conversionPartner,
const GsfTrackRefVector &ambiguousTracks) const;
~GsfElectron() override {}
private:
void init();
//=======================================================
// Candidate methods and complementary information
//
// The gsf electron producer has tried to best evaluate
// the four momentum and charge and given those values to
// the GsfElectron constructor, which forwarded them to
// the Candidate constructor. Those values can be retreived
// with getters inherited from Candidate : p4() and charge().
//=======================================================
public:
// Inherited from Candidate
// const LorentzVector & charge() const ;
// const LorentzVector & p4() const ;
// Complementary struct
struct ChargeInfo {
int scPixCharge;
bool isGsfCtfScPixConsistent;
bool isGsfScPixConsistent;
bool isGsfCtfConsistent;
ChargeInfo()
: scPixCharge(0), isGsfCtfScPixConsistent(false), isGsfScPixConsistent(false), isGsfCtfConsistent(false) {}
};
// Charge info accessors
// to get gsf track charge: gsfTrack()->charge()
// to get ctf track charge, if closestCtfTrackRef().isNonnull(): closestCtfTrackRef()->charge()
int scPixCharge() const { return chargeInfo_.scPixCharge; }
bool isGsfCtfScPixChargeConsistent() const { return chargeInfo_.isGsfCtfScPixConsistent; }
bool isGsfScPixChargeConsistent() const { return chargeInfo_.isGsfScPixConsistent; }
bool isGsfCtfChargeConsistent() const { return chargeInfo_.isGsfCtfConsistent; }
const ChargeInfo &chargeInfo() const { return chargeInfo_; }
// Candidate redefined methods
bool isElectron() const override { return true; }
bool overlap(const Candidate &) const override;
private:
// Complementary attributes
ChargeInfo chargeInfo_;
//=======================================================
// Core Attributes
//
// They all have been computed before, when building the
// collection of GsfElectronCore instances. Each GsfElectron
// has a reference toward a GsfElectronCore.
//=======================================================
public:
// accessors
virtual GsfElectronCoreRef core() const;
void setCore(const reco::GsfElectronCoreRef &core) { core_ = core; }
// forward core methods
SuperClusterRef superCluster() const override { return core()->superCluster(); }
GsfTrackRef gsfTrack() const override { return core()->gsfTrack(); }
float ctfGsfOverlap() const { return core()->ctfGsfOverlap(); }
bool ecalDrivenSeed() const { return core()->ecalDrivenSeed(); }
bool trackerDrivenSeed() const { return core()->trackerDrivenSeed(); }
virtual SuperClusterRef parentSuperCluster() const { return core()->parentSuperCluster(); }
bool closestCtfTrackRefValid() const {
return closestCtfTrackRef().isAvailable() && closestCtfTrackRef().isNonnull();
}
//methods used for MVA variables
float closestCtfTrackNormChi2() const {
return closestCtfTrackRefValid() ? closestCtfTrackRef()->normalizedChi2() : 0;
}
int closestCtfTrackNLayers() const {
return closestCtfTrackRefValid() ? closestCtfTrackRef()->hitPattern().trackerLayersWithMeasurement() : -1;
}
// backward compatibility
struct ClosestCtfTrack {
TrackRef ctfTrack; // best matching ctf track
float shFracInnerHits; // fraction of common hits between the ctf and gsf tracks
ClosestCtfTrack() : shFracInnerHits(0.) {}
ClosestCtfTrack(TrackRef track, float sh) : ctfTrack(track), shFracInnerHits(sh) {}
};
float shFracInnerHits() const { return core()->ctfGsfOverlap(); }
virtual TrackRef closestCtfTrackRef() const { return core()->ctfTrack(); }
virtual ClosestCtfTrack closestCtfTrack() const {
return ClosestCtfTrack(core()->ctfTrack(), core()->ctfGsfOverlap());
}
private:
// attributes
GsfElectronCoreRef core_;
//=======================================================
// Track-Cluster Matching Attributes
//=======================================================
public:
struct TrackClusterMatching {
CaloClusterPtr electronCluster; // basic cluster best matching gsf track
float eSuperClusterOverP; // the supercluster energy / track momentum at the PCA to the beam spot
float eSeedClusterOverP; // the seed cluster energy / track momentum at the PCA to the beam spot
float eSeedClusterOverPout; // the seed cluster energy / track momentum at calo extrapolated from the outermost track state
float eEleClusterOverPout; // the electron cluster energy / track momentum at calo extrapolated from the outermost track state
float deltaEtaSuperClusterAtVtx; // the supercluster eta - track eta position at calo extrapolated from innermost track state
float deltaEtaSeedClusterAtCalo; // the seed cluster eta - track eta position at calo extrapolated from the outermost track state
float deltaEtaEleClusterAtCalo; // the electron cluster eta - track eta position at calo extrapolated from the outermost state
float deltaPhiEleClusterAtCalo; // the electron cluster phi - track phi position at calo extrapolated from the outermost track state
float deltaPhiSuperClusterAtVtx; // the supercluster phi - track phi position at calo extrapolated from the innermost track state
float deltaPhiSeedClusterAtCalo; // the seed cluster phi - track phi position at calo extrapolated from the outermost track state
TrackClusterMatching()
: eSuperClusterOverP(0.),
eSeedClusterOverP(0.),
eSeedClusterOverPout(0.),
eEleClusterOverPout(0.),
deltaEtaSuperClusterAtVtx(std::numeric_limits<float>::max()),
deltaEtaSeedClusterAtCalo(std::numeric_limits<float>::max()),
deltaEtaEleClusterAtCalo(std::numeric_limits<float>::max()),
deltaPhiEleClusterAtCalo(std::numeric_limits<float>::max()),
deltaPhiSuperClusterAtVtx(std::numeric_limits<float>::max()),
deltaPhiSeedClusterAtCalo(std::numeric_limits<float>::max()) {}
};
// accessors
CaloClusterPtr electronCluster() const { return trackClusterMatching_.electronCluster; }
float eSuperClusterOverP() const { return trackClusterMatching_.eSuperClusterOverP; }
float eSeedClusterOverP() const { return trackClusterMatching_.eSeedClusterOverP; }
float eSeedClusterOverPout() const { return trackClusterMatching_.eSeedClusterOverPout; }
float eEleClusterOverPout() const { return trackClusterMatching_.eEleClusterOverPout; }
float deltaEtaSuperClusterTrackAtVtx() const { return trackClusterMatching_.deltaEtaSuperClusterAtVtx; }
float deltaEtaSeedClusterTrackAtCalo() const { return trackClusterMatching_.deltaEtaSeedClusterAtCalo; }
float deltaEtaEleClusterTrackAtCalo() const { return trackClusterMatching_.deltaEtaEleClusterAtCalo; }
float deltaPhiSuperClusterTrackAtVtx() const { return trackClusterMatching_.deltaPhiSuperClusterAtVtx; }
float deltaPhiSeedClusterTrackAtCalo() const { return trackClusterMatching_.deltaPhiSeedClusterAtCalo; }
float deltaPhiEleClusterTrackAtCalo() const { return trackClusterMatching_.deltaPhiEleClusterAtCalo; }
float deltaEtaSeedClusterTrackAtVtx() const {
return superCluster().isNonnull() && superCluster()->seed().isNonnull()
? trackClusterMatching_.deltaEtaSuperClusterAtVtx - superCluster()->eta() +
superCluster()->seed()->eta()
: std::numeric_limits<float>::max();
}
const TrackClusterMatching &trackClusterMatching() const { return trackClusterMatching_; }
// for backward compatibility, usefull ?
void setDeltaEtaSuperClusterAtVtx(float de) { trackClusterMatching_.deltaEtaSuperClusterAtVtx = de; }
void setDeltaPhiSuperClusterAtVtx(float dphi) { trackClusterMatching_.deltaPhiSuperClusterAtVtx = dphi; }
private:
// attributes
TrackClusterMatching trackClusterMatching_;
//=======================================================
// Track extrapolations
//=======================================================
public:
struct TrackExtrapolations {
math::XYZPointF positionAtVtx; // the track PCA to the beam spot
math::XYZPointF positionAtCalo; // the track PCA to the supercluster position
math::XYZVectorF momentumAtVtx; // the track momentum at the PCA to the beam spot
// the track momentum extrapolated at the supercluster position from the innermost track state
math::XYZVectorF momentumAtCalo;
// the track momentum extrapolated at the seed cluster position from the outermost track state
math::XYZVectorF momentumOut;
// the track momentum extrapolated at the ele cluster position from the outermost track state
math::XYZVectorF momentumAtEleClus;
math::XYZVectorF momentumAtVtxWithConstraint; // the track momentum at the PCA to the beam spot using bs constraint
};
// accessors
math::XYZPointF trackPositionAtVtx() const { return trackExtrapolations_.positionAtVtx; }
math::XYZPointF trackPositionAtCalo() const { return trackExtrapolations_.positionAtCalo; }
math::XYZVectorF trackMomentumAtVtx() const { return trackExtrapolations_.momentumAtVtx; }
math::XYZVectorF trackMomentumAtCalo() const { return trackExtrapolations_.momentumAtCalo; }
math::XYZVectorF trackMomentumOut() const { return trackExtrapolations_.momentumOut; }
math::XYZVectorF trackMomentumAtEleClus() const { return trackExtrapolations_.momentumAtEleClus; }
math::XYZVectorF trackMomentumAtVtxWithConstraint() const {
return trackExtrapolations_.momentumAtVtxWithConstraint;
}
const TrackExtrapolations &trackExtrapolations() const { return trackExtrapolations_; }
// setter (if you know what you're doing)
void setTrackExtrapolations(const TrackExtrapolations &te) { trackExtrapolations_ = te; }
// for backward compatibility
math::XYZPointF TrackPositionAtVtx() const { return trackPositionAtVtx(); }
math::XYZPointF TrackPositionAtCalo() const { return trackPositionAtCalo(); }
private:
// attributes
TrackExtrapolations trackExtrapolations_;
//=======================================================
// SuperCluster direct access
//=======================================================
public:
// direct accessors
math::XYZPoint superClusterPosition() const { return superCluster()->position(); } // the super cluster position
int basicClustersSize() const {
return superCluster()->clustersSize();
} // number of basic clusters inside the supercluster
CaloCluster_iterator basicClustersBegin() const { return superCluster()->clustersBegin(); }
CaloCluster_iterator basicClustersEnd() const { return superCluster()->clustersEnd(); }
// for backward compatibility
math::XYZPoint caloPosition() const { return superCluster()->position(); }
//=======================================================
// Fiducial Flags
//=======================================================
public:
struct FiducialFlags {
bool isEB; // true if particle is in ECAL Barrel
bool isEE; // true if particle is in ECAL Endcaps
bool isEBEEGap; // true if particle is in the crack between EB and EE
bool isEBEtaGap; // true if particle is in EB, and inside the eta gaps between modules
bool isEBPhiGap; // true if particle is in EB, and inside the phi gaps between modules
bool isEEDeeGap; // true if particle is in EE, and inside the gaps between dees
bool isEERingGap; // true if particle is in EE, and inside the gaps between rings
FiducialFlags()
: isEB(false),
isEE(false),
isEBEEGap(false),
isEBEtaGap(false),
isEBPhiGap(false),
isEEDeeGap(false),
isEERingGap(false) {}
};
// accessors
bool isEB() const { return fiducialFlags_.isEB; }
bool isEE() const { return fiducialFlags_.isEE; }
bool isGap() const { return ((isEBEEGap()) || (isEBGap()) || (isEEGap())); }
bool isEBEEGap() const { return fiducialFlags_.isEBEEGap; }
bool isEBGap() const { return (isEBEtaGap() || isEBPhiGap()); }
bool isEBEtaGap() const { return fiducialFlags_.isEBEtaGap; }
bool isEBPhiGap() const { return fiducialFlags_.isEBPhiGap; }
bool isEEGap() const { return (isEEDeeGap() || isEERingGap()); }
bool isEEDeeGap() const { return fiducialFlags_.isEEDeeGap; }
bool isEERingGap() const { return fiducialFlags_.isEERingGap; }
const FiducialFlags &fiducialFlags() const { return fiducialFlags_; }
// setters... not necessary in regular situations
// but handy for late stage modifications of electron objects
void setFFlagIsEB(const bool b) { fiducialFlags_.isEB = b; }
void setFFlagIsEE(const bool b) { fiducialFlags_.isEE = b; }
void setFFlagIsEBEEGap(const bool b) { fiducialFlags_.isEBEEGap = b; }
void setFFlagIsEBEtaGap(const bool b) { fiducialFlags_.isEBEtaGap = b; }
void setFFlagIsEBPhiGap(const bool b) { fiducialFlags_.isEBPhiGap = b; }
void setFFlagIsEEDeeGap(const bool b) { fiducialFlags_.isEEDeeGap = b; }
void setFFlagIsEERingGap(const bool b) { fiducialFlags_.isEERingGap = b; }
private:
// attributes
FiducialFlags fiducialFlags_;
//=======================================================
// Shower Shape Variables
//=======================================================
public:
struct ShowerShape {
float sigmaEtaEta; // weighted cluster rms along eta and inside 5x5 (absolute eta)
float sigmaIetaIeta; // weighted cluster rms along eta and inside 5x5 (Xtal eta)
float sigmaIphiIphi; // weighted cluster rms along phi and inside 5x5 (Xtal phi)
float e1x5; // energy inside 1x5 in etaxphi around the seed Xtal
float e2x5Max; // energy inside 2x5 in etaxphi around the seed Xtal (max bwt the 2 possible sums)
float e5x5; // energy inside 5x5 in etaxphi around the seed Xtal
float r9; // ratio of the 3x3 energy and supercluster energy
float hcalDepth1OverEcal; // run2 hcal over ecal seed cluster energy using 1st hcal depth (using hcal towers within a cone)
float hcalDepth2OverEcal; // run2 hcal over ecal seed cluster energy using 2nd hcal depth (using hcal towers within a cone)
float hcalDepth1OverEcalBc; // run2 hcal over ecal seed cluster energy using 1st hcal depth (using hcal towers behind clusters)
float hcalDepth2OverEcalBc; // run2 hcal over ecal seed cluster energy using 2nd hcal depth (using hcal towers behind clusters)
std::array<float, 7>
hcalOverEcal; // run3 hcal over ecal seed cluster energy per depth (using rechits within a cone)
std::array<float, 7>
hcalOverEcalBc; // run3 hcal over ecal seed cluster energy per depth (using rechits behind clusters)
std::vector<CaloTowerDetId> hcalTowersBehindClusters;
bool invalidHcal; // set to true if the hcal energy estimate is not valid (e.g. the corresponding tower was off or masked)
bool pre7DepthHcal; // to work around an ioread rule issue on legacy RECO files
float sigmaIetaIphi;
float eMax;
float e2nd;
float eTop;
float eLeft;
float eRight;
float eBottom;
float e2x5Top;
float e2x5Left;
float e2x5Right;
float e2x5Bottom;
ShowerShape()
: sigmaEtaEta(std::numeric_limits<float>::max()),
sigmaIetaIeta(std::numeric_limits<float>::max()),
sigmaIphiIphi(std::numeric_limits<float>::max()),
e1x5(0.f),
e2x5Max(0.f),
e5x5(0.f),
r9(-std::numeric_limits<float>::max()),
hcalDepth1OverEcal(0.f),
hcalDepth2OverEcal(0.f),
hcalDepth1OverEcalBc(0.f),
hcalDepth2OverEcalBc(0.f),
hcalOverEcal{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
hcalOverEcalBc{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
invalidHcal(false),
pre7DepthHcal(true),
sigmaIetaIphi(0.f),
eMax(0.f),
e2nd(0.f),
eTop(0.f),
eLeft(0.f),
eRight(0.f),
eBottom(0.f),
e2x5Top(0.f),
e2x5Left(0.f),
e2x5Right(0.f),
e2x5Bottom(0.f) {}
};
// accessors
float sigmaEtaEta() const { return showerShape_.sigmaEtaEta; }
float sigmaIetaIeta() const { return showerShape_.sigmaIetaIeta; }
float sigmaIphiIphi() const { return showerShape_.sigmaIphiIphi; }
float e1x5() const { return showerShape_.e1x5; }
float e2x5Max() const { return showerShape_.e2x5Max; }
float e5x5() const { return showerShape_.e5x5; }
float r9() const { return showerShape_.r9; }
float hcalOverEcal(const ShowerShape &ss, int depth) const {
if (ss.pre7DepthHcal) {
if (depth == 0)
return ss.hcalDepth1OverEcal + ss.hcalDepth2OverEcal;
else if (depth == 1)
return ss.hcalDepth1OverEcal;
else if (depth == 2)
return ss.hcalDepth2OverEcal;
return 0.f;
} else {
const auto &hovere = ss.hcalOverEcal;
return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hovere), std::end(hovere), 0.f)
: hovere[depth - 1];
}
}
float hcalOverEcal(int depth = 0) const { return hcalOverEcal(showerShape_, depth); }
float hcalOverEcalBc(const ShowerShape &ss, int depth) const {
if (ss.pre7DepthHcal) {
if (depth == 0)
return ss.hcalDepth1OverEcalBc + ss.hcalDepth2OverEcalBc;
else if (depth == 1)
return ss.hcalDepth1OverEcalBc;
else if (depth == 2)
return ss.hcalDepth2OverEcalBc;
return 0.f;
} else {
const auto &hovere = ss.hcalOverEcalBc;
return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hovere), std::end(hovere), 0.f)
: hovere[depth - 1];
}
}
float hcalOverEcalBc(int depth = 0) const { return hcalOverEcalBc(showerShape_, depth); }
const std::vector<CaloTowerDetId> &hcalTowersBehindClusters() const {
return showerShape_.hcalTowersBehindClusters;
}
bool hcalOverEcalValid() const { return !showerShape_.invalidHcal; }
float eLeft() const { return showerShape_.eLeft; }
float eRight() const { return showerShape_.eRight; }
float eTop() const { return showerShape_.eTop; }
float eBottom() const { return showerShape_.eBottom; }
const ShowerShape &showerShape() const { return showerShape_; }
// non-zero-suppressed and no-fractions shower shapes
// ecal energy is always that from the full 5x5
float full5x5_sigmaEtaEta() const { return full5x5_showerShape_.sigmaEtaEta; }
float full5x5_sigmaIetaIeta() const { return full5x5_showerShape_.sigmaIetaIeta; }
float full5x5_sigmaIphiIphi() const { return full5x5_showerShape_.sigmaIphiIphi; }
float full5x5_e1x5() const { return full5x5_showerShape_.e1x5; }
float full5x5_e2x5Max() const { return full5x5_showerShape_.e2x5Max; }
float full5x5_e5x5() const { return full5x5_showerShape_.e5x5; }
float full5x5_r9() const { return full5x5_showerShape_.r9; }
float full5x5_hcalOverEcal(int depth = 0) const { return hcalOverEcal(full5x5_showerShape_, depth); }
float full5x5_hcalOverEcalBc(int depth = 0) const { return hcalOverEcalBc(full5x5_showerShape_, depth); }
bool full5x5_hcalOverEcalValid() const { return !full5x5_showerShape_.invalidHcal; }
float full5x5_e2x5Left() const { return full5x5_showerShape_.e2x5Left; }
float full5x5_e2x5Right() const { return full5x5_showerShape_.e2x5Right; }
float full5x5_e2x5Top() const { return full5x5_showerShape_.e2x5Top; }
float full5x5_e2x5Bottom() const { return full5x5_showerShape_.e2x5Bottom; }
float full5x5_eLeft() const { return full5x5_showerShape_.eLeft; }
float full5x5_eRight() const { return full5x5_showerShape_.eRight; }
float full5x5_eTop() const { return full5x5_showerShape_.eTop; }
float full5x5_eBottom() const { return full5x5_showerShape_.eBottom; }
const ShowerShape &full5x5_showerShape() const { return full5x5_showerShape_; }
// setters (if you know what you're doing)
void setShowerShape(const ShowerShape &s) { showerShape_ = s; }
void full5x5_setShowerShape(const ShowerShape &s) { full5x5_showerShape_ = s; }
// for backward compatibility (this will only ever be the ZS shapes!)
float scSigmaEtaEta() const { return sigmaEtaEta(); }
float scSigmaIEtaIEta() const { return sigmaIetaIeta(); }
float scE1x5() const { return e1x5(); }
float scE2x5Max() const { return e2x5Max(); }
float scE5x5() const { return e5x5(); }
float hadronicOverEm() const { return hcalOverEcal(); }
private:
// attributes
ShowerShape showerShape_;
ShowerShape full5x5_showerShape_;
//=======================================================
// SaturationInfo
//=======================================================
public:
struct SaturationInfo {
int nSaturatedXtals;
bool isSeedSaturated;
SaturationInfo() : nSaturatedXtals(0), isSeedSaturated(false) {}
};
// accessors
float nSaturatedXtals() const { return saturationInfo_.nSaturatedXtals; }
float isSeedSaturated() const { return saturationInfo_.isSeedSaturated; }
const SaturationInfo &saturationInfo() const { return saturationInfo_; }
void setSaturationInfo(const SaturationInfo &s) { saturationInfo_ = s; }
private:
SaturationInfo saturationInfo_;
//=======================================================
// Isolation Variables
//=======================================================
public:
struct IsolationVariables {
float tkSumPt; // track iso with electron footprint removed
float tkSumPtHEEP; // track iso used for the HEEP ID
float ecalRecHitSumEt; // ecal iso deposit with electron footprint removed
float hcalDepth1TowerSumEt; // hcal depth 1 iso deposit with electron footprint removed
float hcalDepth2TowerSumEt; // hcal depth 2 iso deposit with electron footprint removed
float hcalDepth1TowerSumEtBc; // hcal depth 1 iso deposit without towers behind clusters
float hcalDepth2TowerSumEtBc; // hcal depth 2 iso deposit without towers behind clusters
std::array<float, 7> hcalRecHitSumEt; // ...per depth, with electron footprint removed
std::array<float, 7> hcalRecHitSumEtBc; // ...per depth, with hcal rechit behind cluster removed
bool pre7DepthHcal; // to work around an ioread rule issue on legacy RECO files
IsolationVariables()
: tkSumPt(0.),
tkSumPtHEEP(0.),
ecalRecHitSumEt(0.),
hcalDepth1TowerSumEt(0.f),
hcalDepth2TowerSumEt(0.f),
hcalDepth1TowerSumEtBc(0.f),
hcalDepth2TowerSumEtBc(0.f),
hcalRecHitSumEt{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
hcalRecHitSumEtBc{{0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}},
pre7DepthHcal(true) {}
};
// 03 accessors
float dr03TkSumPt() const { return dr03_.tkSumPt; }
float dr03TkSumPtHEEP() const { return dr03_.tkSumPtHEEP; }
float dr03EcalRecHitSumEt() const { return dr03_.ecalRecHitSumEt; }
float hcalTowerSumEt(const IsolationVariables &iv, int depth) const {
if (iv.pre7DepthHcal) {
if (depth == 0)
return iv.hcalDepth1TowerSumEt + iv.hcalDepth2TowerSumEt;
else if (depth == 1)
return iv.hcalDepth1TowerSumEt;
else if (depth == 2)
return iv.hcalDepth2TowerSumEt;
return 0.f;
} else {
const auto &hcaliso = iv.hcalRecHitSumEt;
return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hcaliso), std::end(hcaliso), 0.f)
: hcaliso[depth - 1];
}
}
float dr03HcalTowerSumEt(int depth = 0) const { return hcalTowerSumEt(dr03_, depth); }
float hcalTowerSumEtBc(const IsolationVariables &iv, int depth) const {
if (iv.pre7DepthHcal) {
if (depth == 0)
return iv.hcalDepth1TowerSumEtBc + iv.hcalDepth2TowerSumEtBc;
else if (depth == 1)
return iv.hcalDepth1TowerSumEtBc;
else if (depth == 2)
return iv.hcalDepth2TowerSumEtBc;
return 0.f;
} else {
const auto &hcaliso = iv.hcalRecHitSumEtBc;
return (!(depth > 0 and depth < 8)) ? std::accumulate(std::begin(hcaliso), std::end(hcaliso), 0.f)
: hcaliso[depth - 1];
}
}
float dr03HcalTowerSumEtBc(int depth = 0) const { return hcalTowerSumEtBc(dr03_, depth); }
const IsolationVariables &dr03IsolationVariables() const { return dr03_; }
// 04 accessors
float dr04TkSumPt() const { return dr04_.tkSumPt; }
float dr04TkSumPtHEEP() const { return dr04_.tkSumPtHEEP; }
float dr04EcalRecHitSumEt() const { return dr04_.ecalRecHitSumEt; }
float dr04HcalTowerSumEt(int depth = 0) const { return hcalTowerSumEt(dr04_, depth); }
float dr04HcalTowerSumEtBc(int depth = 0) const { return hcalTowerSumEtBc(dr04_, depth); }
const IsolationVariables &dr04IsolationVariables() const { return dr04_; }
// setters ?!?
void setDr03Isolation(const IsolationVariables &dr03) { dr03_ = dr03; }
void setDr04Isolation(const IsolationVariables &dr04) { dr04_ = dr04; }
// for backward compatibility
void setIsolation03(const IsolationVariables &dr03) { dr03_ = dr03; }
void setIsolation04(const IsolationVariables &dr04) { dr04_ = dr04; }
const IsolationVariables &isolationVariables03() const { return dr03_; }
const IsolationVariables &isolationVariables04() const { return dr04_; }
// 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
void hcalToRun2EffDepth();
private:
// attributes
IsolationVariables dr03_;
IsolationVariables dr04_;
//=======================================================
// Conversion Rejection Information
//=======================================================
public:
struct ConversionRejection {
int flags; // -max:not-computed, other: as computed by Puneeth conversion code
TrackBaseRef partner; // conversion partner
float dist; // distance to the conversion partner
float dcot; // difference of cot(angle) with the conversion partner track
float radius; // signed conversion radius
float vtxFitProb; //fit probablity (chi2/ndof) of the matched conversion vtx
ConversionRejection()
: flags(-1),
dist(std::numeric_limits<float>::max()),
dcot(std::numeric_limits<float>::max()),
radius(std::numeric_limits<float>::max()),
vtxFitProb(std::numeric_limits<float>::max()) {}
};
// accessors
int convFlags() const { return conversionRejection_.flags; }
TrackBaseRef convPartner() const { return conversionRejection_.partner; }
float convDist() const { return conversionRejection_.dist; }
float convDcot() const { return conversionRejection_.dcot; }
float convRadius() const { return conversionRejection_.radius; }
float convVtxFitProb() const { return conversionRejection_.vtxFitProb; }
const ConversionRejection &conversionRejectionVariables() const { return conversionRejection_; }
void setConversionRejectionVariables(const ConversionRejection &convRej) { conversionRejection_ = convRej; }
private:
// attributes
ConversionRejection conversionRejection_;
//=======================================================
// Pflow Information
//=======================================================
public:
struct PflowIsolationVariables {
//first three data members that changed names, according to DataFormats/MuonReco/interface/MuonPFIsolation.h
float sumChargedHadronPt; //!< sum-pt of charged Hadron // old float chargedHadronIso ;
float sumNeutralHadronEt; //!< sum pt of neutral hadrons // old float neutralHadronIso ;
float sumPhotonEt; //!< sum pt of PF photons // old float photonIso ;
//then four new data members, corresponding to DataFormats/MuonReco/interface/MuonPFIsolation.h
float sumChargedParticlePt; //!< sum-pt of charged Particles(inludes e/mu)
float sumNeutralHadronEtHighThreshold; //!< sum pt of neutral hadrons with a higher threshold
float sumPhotonEtHighThreshold; //!< sum pt of PF photons with a higher threshold
float sumPUPt; //!< sum pt of charged Particles not from PV (for Pu corrections)
//new pf cluster based isolation values
float sumEcalClusterEt; //sum pt of ecal clusters, vetoing clusters part of electron
float sumHcalClusterEt; //sum pt of hcal clusters, vetoing clusters part of electron
PflowIsolationVariables()
: sumChargedHadronPt(0),
sumNeutralHadronEt(0),
sumPhotonEt(0),
sumChargedParticlePt(0),
sumNeutralHadronEtHighThreshold(0),
sumPhotonEtHighThreshold(0),
sumPUPt(0),
sumEcalClusterEt(0),
sumHcalClusterEt(0) {}
};
struct MvaInput {
int earlyBrem; // Early Brem detected (-2=>unknown,-1=>could not be evaluated,0=>wrong,1=>true)
int lateBrem; // Late Brem detected (-2=>unknown,-1=>could not be evaluated,0=>wrong,1=>true)
float sigmaEtaEta; // Sigma-eta-eta with the PF cluster
float hadEnergy; // Associated PF Had Cluster energy
float deltaEta; // PF-cluster GSF track delta-eta
int nClusterOutsideMustache; // -2 => unknown, -1 =>could not be evaluated, 0 and more => number of clusters
float etOutsideMustache;
MvaInput()
: earlyBrem(-2),
lateBrem(-2),
sigmaEtaEta(std::numeric_limits<float>::max()),
hadEnergy(0.),
deltaEta(std::numeric_limits<float>::max()),
nClusterOutsideMustache(-2),
etOutsideMustache(-std::numeric_limits<float>::max()) {}
};
static constexpr float mvaPlaceholder = -999999999.;
struct MvaOutput {
int status; // see PFCandidateElectronExtra::StatusFlag
float mva_Isolated;
float mva_e_pi;
float mvaByPassForIsolated; // complementary MVA used in preselection
float dnn_e_sigIsolated;
float dnn_e_sigNonIsolated;
float dnn_e_bkgNonIsolated;
float dnn_e_bkgTau;
float dnn_e_bkgPhoton;
MvaOutput()
: status(-1),
mva_Isolated(mvaPlaceholder),
mva_e_pi(mvaPlaceholder),
mvaByPassForIsolated(mvaPlaceholder),
dnn_e_sigIsolated(mvaPlaceholder),
dnn_e_sigNonIsolated(mvaPlaceholder),
dnn_e_bkgNonIsolated(mvaPlaceholder),
dnn_e_bkgTau(mvaPlaceholder),
dnn_e_bkgPhoton(mvaPlaceholder) {}
};
// accessors
const PflowIsolationVariables &pfIsolationVariables() const { return pfIso_; }
//backwards compat functions for pat::Electron
float ecalPFClusterIso() const { return pfIso_.sumEcalClusterEt; };
float hcalPFClusterIso() const { return pfIso_.sumHcalClusterEt; };
const MvaInput &mvaInput() const { return mvaInput_; }
const MvaOutput &mvaOutput() const { return mvaOutput_; }
// setters
void setPfIsolationVariables(const PflowIsolationVariables &iso) { pfIso_ = iso; }
void setMvaInput(const MvaInput &mi) { mvaInput_ = mi; }
void setMvaOutput(const MvaOutput &mo) { mvaOutput_ = mo; }
// for backward compatibility
float mva_Isolated() const { return mvaOutput_.mva_Isolated; }
float mva_e_pi() const { return mvaOutput_.mva_e_pi; }
float dnn_signal_Isolated() const { return mvaOutput_.dnn_e_sigIsolated; }
float dnn_signal_nonIsolated() const { return mvaOutput_.dnn_e_sigNonIsolated; }
float dnn_bkg_nonIsolated() const { return mvaOutput_.dnn_e_bkgNonIsolated; }
float dnn_bkg_Tau() const { return mvaOutput_.dnn_e_bkgTau; }
float dnn_bkg_Photon() const { return mvaOutput_.dnn_e_bkgPhoton; }
private:
PflowIsolationVariables pfIso_;
MvaInput mvaInput_;
MvaOutput mvaOutput_;
//=======================================================
// Preselection and Ambiguity
//=======================================================
public:
// accessors
bool ecalDriven() const; // return true if ecalDrivenSeed() and passingCutBasedPreselection()
bool passingCutBasedPreselection() const { return passCutBasedPreselection_; }
bool passingPflowPreselection() const { return passPflowPreselection_; }
bool ambiguous() const { return ambiguous_; }
GsfTrackRefVector::size_type ambiguousGsfTracksSize() const { return ambiguousGsfTracks_.size(); }
auto const &ambiguousGsfTracks() const { return ambiguousGsfTracks_; }
// setters
void setPassCutBasedPreselection(bool flag) { passCutBasedPreselection_ = flag; }
void setPassPflowPreselection(bool flag) { passPflowPreselection_ = flag; }
void setAmbiguous(bool flag) { ambiguous_ = flag; }
void clearAmbiguousGsfTracks() { ambiguousGsfTracks_.clear(); }
void addAmbiguousGsfTrack(const reco::GsfTrackRef &t) { ambiguousGsfTracks_.push_back(t); }
// backward compatibility
void setPassMvaPreselection(bool flag) { passMvaPreslection_ = flag; }
bool passingMvaPreselection() const { return passMvaPreslection_; }
private:
// attributes
bool passCutBasedPreselection_;
bool passPflowPreselection_;
bool passMvaPreslection_; // to be removed : passPflowPreslection_
bool ambiguous_;
GsfTrackRefVector ambiguousGsfTracks_; // ambiguous gsf tracks
//=======================================================
// Brem Fractions and Classification
//=======================================================
public:
struct ClassificationVariables {
float trackFbrem; // the brem fraction from gsf fit: (track momentum in - track momentum out) / track momentum in
float superClusterFbrem; // the brem fraction from supercluster: (supercluster energy - electron cluster energy) / supercluster energy
constexpr static float kDefaultValue = -1.e30;
ClassificationVariables() : trackFbrem(kDefaultValue), superClusterFbrem(kDefaultValue) {}
};
enum Classification { UNKNOWN = -1, GOLDEN = 0, BIGBREM = 1, BADTRACK = 2, SHOWERING = 3, GAP = 4 };
// accessors
float trackFbrem() const { return classVariables_.trackFbrem; }
float superClusterFbrem() const { return classVariables_.superClusterFbrem; }
const ClassificationVariables &classificationVariables() const { return classVariables_; }
Classification classification() const { return class_; }
// utilities
int numberOfBrems() const { return basicClustersSize() - 1; }
float fbrem() const { return trackFbrem(); }
// setters
void setTrackFbrem(float fbrem) { classVariables_.trackFbrem = fbrem; }
void setSuperClusterFbrem(float fbrem) { classVariables_.superClusterFbrem = fbrem; }
void setClassificationVariables(const ClassificationVariables &cv) { classVariables_ = cv; }
void setClassification(Classification myclass) { class_ = myclass; }
private:
// attributes
ClassificationVariables classVariables_;
Classification class_; // fbrem and number of clusters based electron classification
//=======================================================
// Corrections
//
// The only methods, with classification, which modify
// the electrons after they have been constructed.
// They change a given characteristic, such as the super-cluster
// energy, and propagate the change consistently
// to all the depending attributes.
// We expect the methods to be called in a given order
// and so to store specific kind of corrections
// 1) classify()
// 2) correctEcalEnergy() : depending on classification and eta
// 3) correctMomemtum() : depending on classification and ecal energy and tracker momentum errors
//
// Beware that correctEcalEnergy() is modifying few attributes which
// were potentially used for preselection, whose value used in
// preselection will not be available any more :
// hcalOverEcal, eSuperClusterOverP,
// eSeedClusterOverP, eEleClusterOverPout.
//=======================================================
public:
enum P4Kind { P4_UNKNOWN = -1, P4_FROM_SUPER_CLUSTER = 0, P4_COMBINATION = 1, P4_PFLOW_COMBINATION = 2 };
struct Corrections {
bool isEcalEnergyCorrected; // true if ecal energy has been corrected
float correctedEcalEnergy; // corrected energy (if !isEcalEnergyCorrected this value is identical to the supercluster energy)
float correctedEcalEnergyError; // error on energy
//bool isMomentumCorrected ; // DEPRECATED
float trackMomentumError; // track momentum error from gsf fit
//
LorentzVector fromSuperClusterP4; // for P4_FROM_SUPER_CLUSTER
float fromSuperClusterP4Error; // for P4_FROM_SUPER_CLUSTER
LorentzVector combinedP4; // for P4_COMBINATION
float combinedP4Error; // for P4_COMBINATION
LorentzVector pflowP4; // for P4_PFLOW_COMBINATION
float pflowP4Error; // for P4_PFLOW_COMBINATION
P4Kind candidateP4Kind; // say which momentum has been stored in reco::Candidate
//
Corrections()
: isEcalEnergyCorrected(false),
correctedEcalEnergy(0.),
correctedEcalEnergyError(999.),
/*isMomentumCorrected(false),*/ trackMomentumError(999.),
fromSuperClusterP4Error(999.),
combinedP4Error(999.),
pflowP4Error(999.),
candidateP4Kind(P4_UNKNOWN) {}
};
// setters
void setCorrectedEcalEnergyError(float newEnergyError);
void setCorrectedEcalEnergy(float newEnergy);
void setCorrectedEcalEnergy(float newEnergy, bool rescaleDependentValues);
void setTrackMomentumError(float trackMomentumError);
void setP4(P4Kind kind, const LorentzVector &p4, float p4Error, bool setCandidate);
using RecoCandidate::setP4;
// accessors
bool isEcalEnergyCorrected() const { return corrections_.isEcalEnergyCorrected; }
float correctedEcalEnergy() const { return corrections_.correctedEcalEnergy; }
float correctedEcalEnergyError() const { return corrections_.correctedEcalEnergyError; }
float trackMomentumError() const { return corrections_.trackMomentumError; }
const LorentzVector &p4(P4Kind kind) const;
using RecoCandidate::p4;
float p4Error(P4Kind kind) const;
P4Kind candidateP4Kind() const { return corrections_.candidateP4Kind; }
const Corrections &corrections() const { return corrections_; }
// bare setter (if you know what you're doing)
void setCorrections(const Corrections &c) { corrections_ = c; }
// for backward compatibility
void setEcalEnergyError(float energyError) { setCorrectedEcalEnergyError(energyError); }
float ecalEnergy() const { return correctedEcalEnergy(); }
float ecalEnergyError() const { return correctedEcalEnergyError(); }
//bool isMomentumCorrected() const { return corrections_.isMomentumCorrected ; }
float caloEnergy() const { return correctedEcalEnergy(); }
bool isEnergyScaleCorrected() const { return isEcalEnergyCorrected(); }
void correctEcalEnergy(float newEnergy, float newEnergyError, bool corrEovP = true) {
setCorrectedEcalEnergy(newEnergy, corrEovP);
setEcalEnergyError(newEnergyError);
}
void correctMomentum(const LorentzVector &p4, float trackMomentumError, float p4Error) {
setTrackMomentumError(trackMomentumError);
setP4(P4_COMBINATION, p4, p4Error, true);
}
private:
// attributes
Corrections corrections_;
public:
struct PixelMatchVariables {
//! Pixel match variable: deltaPhi for innermost hit
float dPhi1;
//! Pixel match variable: deltaPhi for second hit
float dPhi2;
//! Pixel match variable: deltaRz for innermost hit
float dRz1;
//! Pixel match variable: deltaRz for second hit
float dRz2;
//! Subdetectors for first and second pixel hit
unsigned char subdetectors;
PixelMatchVariables() : dPhi1(-999), dPhi2(-999), dRz1(-999), dRz2(-999), subdetectors(0) {}
~PixelMatchVariables() {}
};
void setPixelMatchSubdetectors(int sd1, int sd2) { pixelMatchVariables_.subdetectors = 10 * sd1 + sd2; }
void setPixelMatchDPhi1(float dPhi1) { pixelMatchVariables_.dPhi1 = dPhi1; }
void setPixelMatchDPhi2(float dPhi2) { pixelMatchVariables_.dPhi2 = dPhi2; }
void setPixelMatchDRz1(float dRz1) { pixelMatchVariables_.dRz1 = dRz1; }
void setPixelMatchDRz2(float dRz2) { pixelMatchVariables_.dRz2 = dRz2; }
int pixelMatchSubdetector1() const { return pixelMatchVariables_.subdetectors / 10; }
int pixelMatchSubdetector2() const { return pixelMatchVariables_.subdetectors % 10; }
float pixelMatchDPhi1() const { return pixelMatchVariables_.dPhi1; }
float pixelMatchDPhi2() const { return pixelMatchVariables_.dPhi2; }
float pixelMatchDRz1() const { return pixelMatchVariables_.dRz1; }
float pixelMatchDRz2() const { return pixelMatchVariables_.dRz2; }
private:
PixelMatchVariables pixelMatchVariables_;
};
} // namespace reco
#endif
|