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
|
#ifndef __AnalysisDataFormats_PackedGenParticle_h__
#define __AnalysisDataFormats_PackedGenParticle_h__
#include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
#include "DataFormats/HepMCCandidate/interface/GenStatusFlags.h"
#include "DataFormats/Candidate/interface/Candidate.h"
#include "DataFormats/Candidate/interface/CandidateFwd.h"
#include "DataFormats/Common/interface/RefVector.h"
#include "DataFormats/Common/interface/Association.h"
#include "DataFormats/VertexReco/interface/VertexFwd.h"
#include "DataFormats/VertexReco/interface/Vertex.h"
#include "DataFormats/Math/interface/deltaPhi.h"
/* #include "DataFormats/Math/interface/PtEtaPhiMass.h" */
class testPackedGenParticle;
namespace pat {
class PackedGenParticle : public reco::Candidate {
public:
friend class ::testPackedGenParticle;
/// collection of daughter candidates
typedef reco::CandidateCollection daughters;
/// Lorentz vector
typedef math::XYZTLorentzVector LorentzVector;
/// Lorentz vector
typedef math::PtEtaPhiMLorentzVector PolarLorentzVector;
/// point in the space
typedef math::XYZPoint Point;
/// point in the space
typedef math::XYZVector Vector;
typedef unsigned int index;
/// default constructor
PackedGenParticle()
: packedPt_(0),
packedY_(0),
packedPhi_(0),
packedM_(0),
p4_(nullptr),
p4c_(nullptr),
vertex_(0, 0, 0),
pdgId_(0),
charge_(0) {}
explicit PackedGenParticle(const reco::GenParticle& c)
: p4_(new PolarLorentzVector(c.pt(), c.eta(), c.phi(), c.mass())),
p4c_(new LorentzVector(*p4_)),
vertex_(0, 0, 0),
pdgId_(c.pdgId()),
charge_(c.charge()),
mother_(c.motherRef(0)),
statusFlags_(c.statusFlags()) {
pack();
}
explicit PackedGenParticle(const reco::GenParticle& c, const edm::Ref<reco::GenParticleCollection>& mother)
: p4_(new PolarLorentzVector(c.pt(), c.eta(), c.phi(), c.mass())),
p4c_(new LorentzVector(*p4_)),
vertex_(0, 0, 0),
pdgId_(c.pdgId()),
charge_(c.charge()),
mother_(mother),
statusFlags_(c.statusFlags()) {
pack();
}
PackedGenParticle(const PackedGenParticle& iOther)
: packedPt_(iOther.packedPt_),
packedY_(iOther.packedY_),
packedPhi_(iOther.packedPhi_),
packedM_(iOther.packedM_),
p4_(nullptr),
p4c_(nullptr),
vertex_(iOther.vertex_),
dxy_(iOther.dxy_),
dz_(iOther.dz_),
dphi_(iOther.dphi_),
pdgId_(iOther.pdgId_),
charge_(iOther.charge_),
mother_(iOther.mother_),
statusFlags_(iOther.statusFlags_) {
if (iOther.p4c_) {
p4_.store(new PolarLorentzVector(*iOther.p4_));
p4c_.store(new LorentzVector(*iOther.p4c_));
}
}
PackedGenParticle(PackedGenParticle&& iOther)
: packedPt_(iOther.packedPt_),
packedY_(iOther.packedY_),
packedPhi_(iOther.packedPhi_),
packedM_(iOther.packedM_),
p4_(nullptr),
p4c_(nullptr),
vertex_(std::move(iOther.vertex_)),
dxy_(iOther.dxy_),
dz_(iOther.dz_),
dphi_(iOther.dphi_),
pdgId_(iOther.pdgId_),
charge_(iOther.charge_),
mother_(iOther.mother_),
statusFlags_(iOther.statusFlags_) {
if (iOther.p4c_) {
p4_.store(p4_.exchange(nullptr));
p4c_.store(p4c_.exchange(nullptr));
}
}
PackedGenParticle& operator=(PackedGenParticle&& iOther) {
if (this != &iOther) {
packedPt_ = iOther.packedPt_;
packedY_ = iOther.packedY_;
packedPhi_ = iOther.packedPhi_;
packedM_ = iOther.packedM_;
if (p4c_) {
delete p4_.exchange(iOther.p4_.exchange(nullptr));
delete p4c_.exchange(iOther.p4c_.exchange(nullptr));
} else {
delete p4_.exchange(nullptr);
delete p4c_.exchange(nullptr);
}
vertex_ = std::move(iOther.vertex_);
dxy_ = iOther.dxy_;
dz_ = iOther.dz_;
dphi_ = iOther.dphi_;
pdgId_ = iOther.pdgId_;
charge_ = iOther.charge_;
mother_ = iOther.mother_;
statusFlags_ = iOther.statusFlags_;
}
return *this;
}
PackedGenParticle& operator=(PackedGenParticle const& iOther) {
PackedGenParticle c(iOther);
*this = std::move(c);
return *this;
}
/// destructor
~PackedGenParticle() override;
/// number of daughters
size_t numberOfDaughters() const override;
/// return daughter at a given position (throws an exception)
const reco::Candidate* daughter(size_type) const override;
/// number of mothers
size_t numberOfMothers() const override;
/// return mother at a given position (throws an exception)
const reco::Candidate* mother(size_type) const override;
/// direct access to the mother reference (may be null)
reco::GenParticleRef motherRef() const {
if (mother_.isNonnull() && mother_.isAvailable() &&
mother_->status() == 1) { //if pointing to the pruned version of myself
if (mother_->numberOfMothers() > 0)
return mother_->motherRef(0); // return my mother's (that is actually myself) mother
else
return edm::Ref<reco::GenParticleCollection>(); // return null ref
} else {
return mother_; //the stored ref is really my mother, or null, return that
}
}
/// last surviving in pruned
const reco::GenParticleRef& lastPrunedRef() const { return mother_; }
/// return daughter at a given position (throws an exception)
reco::Candidate* daughter(size_type) override;
/// return daughter with a specified role name
reco::Candidate* daughter(const std::string& s) override;
/// return daughter with a specified role name
const reco::Candidate* daughter(const std::string& s) const override;
/// return the number of source Candidates
/// ( the candidates used to construct this Candidate)
size_t numberOfSourceCandidatePtrs() const override { return 0; }
/// return a Ptr to one of the source Candidates
/// ( the candidates used to construct this Candidate)
reco::CandidatePtr sourceCandidatePtr(size_type i) const override { return reco::CandidatePtr(); }
/// electric charge
int charge() const override { return charge_; }
/// set electric charge
void setCharge(int charge) override { charge_ = charge; }
/// electric charge
int threeCharge() const override { return charge() * 3; }
/// set electric charge
void setThreeCharge(int threecharge) override {}
/// four-momentum Lorentz vecto r
const LorentzVector& p4() const override {
if (!p4c_)
unpack();
return *p4c_;
}
/// four-momentum Lorentz vector
const PolarLorentzVector& polarP4() const override {
if (!p4c_)
unpack();
return *p4_;
}
/// spatial momentum vector
Vector momentum() const override {
if (!p4c_)
unpack();
return p4c_.load()->Vect();
}
/// boost vector to boost a Lorentz vector
/// to the particle center of mass system
Vector boostToCM() const override {
if (!p4c_)
unpack();
return p4c_.load()->BoostToCM();
}
/// magnitude of momentum vector
double p() const override {
if (!p4c_)
unpack();
return p4c_.load()->P();
}
/// energy
double energy() const override {
if (!p4c_)
unpack();
return p4c_.load()->E();
}
/// transverse energy
double et() const override { return (pt() <= 0) ? 0 : p4c_.load()->Et(); }
/// transverse energy squared (use this for cuts)!
double et2() const override { return (pt() <= 0) ? 0 : p4c_.load()->Et2(); }
/// mass
double mass() const override {
if (!p4c_)
unpack();
return p4_.load()->M();
}
/// mass squared
double massSqr() const override {
if (!p4c_)
unpack();
return p4_.load()->M() * p4_.load()->M();
}
/// transverse mass
double mt() const override {
if (!p4c_)
unpack();
return p4_.load()->Mt();
}
/// transverse mass squared
double mtSqr() const override {
if (!p4c_)
unpack();
return p4_.load()->Mt2();
}
/// x coordinate of momentum vector
double px() const override {
if (!p4c_)
unpack();
return p4c_.load()->Px();
}
/// y coordinate of momentum vector
double py() const override {
if (!p4c_)
unpack();
return p4c_.load()->Py();
}
/// z coordinate of momentum vector
double pz() const override {
if (!p4c_)
unpack();
return p4c_.load()->Pz();
}
/// transverse momentum
double pt() const override {
if (!p4c_)
unpack();
return p4_.load()->Pt();
}
/// momentum azimuthal angle
double phi() const override {
if (!p4c_)
unpack();
return p4_.load()->Phi();
}
/// momentum polar angle
double theta() const override {
if (!p4c_)
unpack();
return p4_.load()->Theta();
}
/// momentum pseudorapidity
double eta() const override {
if (!p4c_)
unpack();
return p4_.load()->Eta();
}
/// rapidity
double rapidity() const override {
if (!p4c_)
unpack();
return p4_.load()->Rapidity();
}
/// rapidity
double y() const override {
if (!p4c_)
unpack();
return p4_.load()->Rapidity();
}
/// set 4-momentum
void setP4(const LorentzVector& p4) override {
unpack(); // changing px,py,pz changes also mapping between dxy,dz and x,y,z
*p4_ = PolarLorentzVector(p4.Pt(), p4.Eta(), p4.Phi(), p4.M());
pack();
}
/// set 4-momentum
void setP4(const PolarLorentzVector& p4) override {
unpack(); // changing px,py,pz changes also mapping between dxy,dz and x,y,z
*p4_ = p4;
pack();
}
/// set particle mass
void setMass(double m) override {
if (!p4c_)
unpack();
*p4_ = PolarLorentzVector(p4_.load()->Pt(), p4_.load()->Eta(), p4_.load()->Phi(), m);
pack();
}
void setPz(double pz) override {
unpack(); // changing px,py,pz changes also mapping between dxy,dz and x,y,z
*p4c_ = LorentzVector(p4c_.load()->Px(), p4c_.load()->Py(), pz, p4c_.load()->E());
*p4_ = PolarLorentzVector(p4c_.load()->Pt(), p4c_.load()->Eta(), p4c_.load()->Phi(), p4c_.load()->M());
pack();
}
/// vertex position
const Point& vertex() const override {
return vertex_;
} //{ if (fromPV_) return Point(0,0,0); else return Point(0,0,100); }
/// x coordinate of vertex position
double vx() const override { return vertex_.X(); } //{ return 0; }
/// y coordinate of vertex position
double vy() const override { return vertex_.Y(); } //{ return 0; }
/// z coordinate of vertex position
double vz() const override { return vertex_.Z(); } //{ if (fromPV_) return 0; else return 100; }
/// set vertex
void setVertex(const Point& vertex) override { vertex_ = vertex; }
enum PVAssoc { NoPV = 0, PVLoose = 1, PVTight = 2, PVUsedInFit = 3 };
/// dxy with respect to the PV ref
virtual float dxy() const {
unpack();
return dxy_;
}
/// dz with respect to the PV ref
virtual float dz() const {
unpack();
return dz_;
}
/// dxy with respect to another point
virtual float dxy(const Point& p) const;
/// dz with respect to another point
virtual float dz(const Point& p) const;
/// PDG identifier
int pdgId() const override { return pdgId_; }
// set PDG identifier
void setPdgId(int pdgId) override { pdgId_ = pdgId; }
/// status word
int status() const override { return 1; } /*FIXME*/
/// set status word
void setStatus(int status) override {} /*FIXME*/
/// long lived flag
static const unsigned int longLivedTag = 0; /*FIXME*/
/// set long lived flag
void setLongLived() override {} /*FIXME*/
/// is long lived?
bool longLived() const override;
/// do mass constraint flag
static const unsigned int massConstraintTag = 0; /*FIXME*/
/// set mass constraint flag
void setMassConstraint() override {} /*FIXME*/
/// do mass constraint?
bool massConstraint() const override;
/// returns a clone of the Candidate object
PackedGenParticle* clone() const override { return new PackedGenParticle(*this); }
/// chi-squares
double vertexChi2() const override;
/** Number of degrees of freedom
* Meant to be Double32_t for soft-assignment fitters:
* tracks may contribute to the vertex with fractional weights.
* The ndof is then = to the sum of the track weights.
* see e.g. CMS NOTE-2006/032, CMS NOTE-2004/002
*/
double vertexNdof() const override;
/// chi-squared divided by n.d.o.f.
double vertexNormalizedChi2() const override;
/// (i, j)-th element of error matrix, i, j = 0, ... 2
double vertexCovariance(int i, int j) const override;
/// return SMatrix
CovarianceMatrix vertexCovariance() const override {
CovarianceMatrix m;
fillVertexCovariance(m);
return m;
}
/// fill SMatrix
void fillVertexCovariance(CovarianceMatrix& v) const override;
/// returns true if this candidate has a reference to a master clone.
/// This only happens if the concrete Candidate type is ShallowCloneCandidate
bool hasMasterClone() const override;
/// returns ptr to master clone, if existing.
/// Throws an exception unless the concrete Candidate type is ShallowCloneCandidate
const reco::CandidateBaseRef& masterClone() const override;
/// returns true if this candidate has a ptr to a master clone.
/// This only happens if the concrete Candidate type is ShallowClonePtrCandidate
bool hasMasterClonePtr() const override;
/// returns ptr to master clone, if existing.
/// Throws an exception unless the concrete Candidate type is ShallowClonePtrCandidate
const reco::CandidatePtr& masterClonePtr() const override;
/// cast master clone reference to a concrete type
template <typename Ref>
Ref masterRef() const {
return masterClone().template castTo<Ref>();
}
/// get a component
bool isElectron() const override;
bool isMuon() const override;
bool isStandAloneMuon() const override;
bool isGlobalMuon() const override;
bool isTrackerMuon() const override;
bool isCaloMuon() const override;
bool isPhoton() const override;
bool isConvertedPhoton() const override;
bool isJet() const override;
const reco::GenStatusFlags& statusFlags() const { return statusFlags_; }
reco::GenStatusFlags& statusFlags() { return statusFlags_; }
/////////////////////////////////////////////////////////////////////////////
//basic set of gen status flags accessible directly here
//the rest accessible through statusFlags()
//(see GenStatusFlags.h for their meaning)
/////////////////////////////////////////////////////////////////////////////
//these are robust, generator-independent functions for categorizing
//mainly final state particles, but also intermediate hadrons/taus
//is particle prompt (not from hadron, muon, or tau decay) and final state
bool isPromptFinalState() const { return status() == 1 && statusFlags_.isPrompt(); }
//this particle is a direct decay product of a prompt tau and is final state
//(eg an electron or muon from a leptonic decay of a prompt tau)
bool isDirectPromptTauDecayProductFinalState() const {
return status() == 1 && statusFlags_.isDirectPromptTauDecayProduct();
}
/////////////////////////////////////////////////////////////////////////////
//these are generator history-dependent functions for tagging particles
//associated with the hard process
//Currently implemented for Pythia 6 and Pythia 8 status codes and history
//and may not have 100% consistent meaning across all types of processes
//Users are strongly encouraged to stick to the more robust flags above,
//as well as the expanded set available in GenStatusFlags.h
//this particle is the final state direct descendant of a hard process particle
bool fromHardProcessFinalState() const { return status() == 1 && statusFlags_.fromHardProcess(); }
//this particle is a direct decay product of a hardprocess tau and is final state
//(eg an electron or muon from a leptonic decay of a tau from the hard process)
bool isDirectHardProcessTauDecayProductFinalState() const {
return status() == 1 && statusFlags_.isDirectHardProcessTauDecayProduct();
}
protected:
uint16_t packedPt_, packedY_, packedPhi_, packedM_;
void pack(bool unpackAfterwards = true);
void unpack() const;
/// the four vector
mutable std::atomic<PolarLorentzVector*> p4_;
mutable std::atomic<LorentzVector*> p4c_;
/// vertex position
Point vertex_;
float dxy_, dz_, dphi_;
/// PDG identifier
int pdgId_;
/// Charge
int8_t charge_;
///Ref to first mother
reco::GenParticleRef mother_;
//status flags
reco::GenStatusFlags statusFlags_;
/// check overlap with another Candidate
bool overlap(const reco::Candidate&) const override;
template <typename, typename, typename>
friend struct component;
friend class ::OverlapChecker;
friend class ShallowCloneCandidate;
friend class ShallowClonePtrCandidate;
};
typedef std::vector<pat::PackedGenParticle> PackedGenParticleCollection;
typedef edm::Ref<pat::PackedGenParticleCollection> PackedGenParticleRef;
typedef edm::RefVector<pat::PackedGenParticleCollection> PackedGenParticleRefVector;
} // namespace pat
#endif
|