CMS 3D CMS Logo

GenParticleProducer.cc
Go to the documentation of this file.
1 /* \class GenParticleProducer
2  *
3  * \author Luca Lista, INFN
4  *
5  * Convert HepMC GenEvent format into a collection of type
6  * CandidateCollection containing objects of type GenParticle
7  *
8  *
9  */
18 
19 #include <vector>
20 #include <string>
21 #include <unordered_map>
22 
23 namespace edm {
24  class ParameterSet;
25 }
26 namespace HepMC {
27  class GenParticle;
28  class GenEvent;
29 } // namespace HepMC
30 
31 static constexpr int PDGCacheMax = 32768;
32 
33 namespace {
34  struct IDto3Charge {
35  IDto3Charge(HepPDT::ParticleDataTable const&, bool abortOnUnknownPDGCode);
36 
37  int chargeTimesThree(int) const;
38 
39  private:
40  std::vector<int> chargeP_, chargeM_;
41  std::unordered_map<int, int> chargeMap_;
42  bool abortOnUnknownPDGCode_;
43  };
44 
45  IDto3Charge::IDto3Charge(HepPDT::ParticleDataTable const& iTable, bool iAbortOnUnknownPDGCode)
46  : chargeP_(PDGCacheMax, 0), chargeM_(PDGCacheMax, 0), abortOnUnknownPDGCode_(iAbortOnUnknownPDGCode) {
47  for (auto const& p : iTable) {
48  const HepPDT::ParticleID& id = p.first;
49  int pdgId = id.pid(), apdgId = std::abs(pdgId);
50  int q3 = id.threeCharge();
51  if (apdgId < PDGCacheMax && pdgId > 0) {
52  chargeP_[apdgId] = q3;
53  chargeM_[apdgId] = -q3;
54  } else if (apdgId < PDGCacheMax) {
55  chargeP_[apdgId] = -q3;
56  chargeM_[apdgId] = q3;
57  } else {
58  chargeMap_.emplace(pdgId, q3);
59  chargeMap_.emplace(-pdgId, -q3);
60  }
61  }
62  }
63 
64  int IDto3Charge::chargeTimesThree(int id) const {
65  if (std::abs(id) < PDGCacheMax)
66  return id > 0 ? chargeP_[id] : chargeM_[-id];
67  auto f = chargeMap_.find(id);
68  if (f == chargeMap_.end()) {
69  if (abortOnUnknownPDGCode_)
70  throw edm::Exception(edm::errors::LogicError) << "invalid PDG id: " << id;
71  else
72  return HepPDT::ParticleID(id).threeCharge();
73  }
74  return f->second;
75  }
76 
77 } // namespace
78 
79 class GenParticleProducer : public edm::global::EDProducer<edm::RunCache<IDto3Charge>> {
80 public:
84  ~GenParticleProducer() override;
85 
87  void produce(edm::StreamID, edm::Event& e, const edm::EventSetup&) const override;
88  std::shared_ptr<IDto3Charge> globalBeginRun(const edm::Run&, const edm::EventSetup&) const override;
89  void globalEndRun(edm::Run const&, edm::EventSetup const&) const override{};
90 
91  bool convertParticle(reco::GenParticle& cand, const HepMC::GenParticle* part, const IDto3Charge& id2Charge) const;
92  bool fillDaughters(reco::GenParticleCollection& cand,
93  const HepMC::GenParticle* part,
94  reco::GenParticleRefProd const& ref,
95  size_t index,
96  std::unordered_map<int, size_t>& barcodes) const;
97  bool fillIndices(const HepMC::GenEvent* mc,
98  std::vector<const HepMC::GenParticle*>& particles,
99  std::vector<int>& barCodeVector,
100  int offset,
101  std::unordered_map<int, size_t>& barcodes) const;
102 
103 private:
106  std::vector<edm::EDGetTokenT<edm::HepMCProduct>> vectorSrcTokens_;
108 
113 
116  bool useCF_;
117 
120 };
121 
123 
124 //#include "SimDataFormats/HiGenData/interface/SubEventMap.h"
126 
135 #include <fstream>
136 #include <algorithm>
137 using namespace edm;
138 using namespace reco;
139 using namespace std;
140 using namespace HepMC;
141 
142 static const double mmToCm = 0.1;
143 static const double mmToNs = 1.0 / 299792458e-6;
144 
146  : abortOnUnknownPDGCode_(cfg.getUntrackedParameter<bool>("abortOnUnknownPDGCode", true)),
147  saveBarCodes_(cfg.getUntrackedParameter<bool>("saveBarCodes", false)),
148  doSubEvent_(cfg.getUntrackedParameter<bool>("doSubEvent", false)),
149  useCF_(cfg.getUntrackedParameter<bool>("useCrossingFrame", false)) {
150  produces<GenParticleCollection>();
151  produces<math::XYZPointF>("xyz0");
152  produces<float>("t0");
153  if (saveBarCodes_) {
154  std::string alias(cfg.getParameter<std::string>("@module_label"));
155  produces<vector<int>>().setBranchAlias(alias + "BarCodes");
156  }
157 
158  if (useCF_)
159  mixToken_ =
160  mayConsume<CrossingFrame<HepMCProduct>>(InputTag(cfg.getParameter<std::string>("mix"), "generatorSmeared"));
161  else
162  srcToken_ = mayConsume<HepMCProduct>(cfg.getParameter<InputTag>("src"));
163 }
164 
166 
167 std::shared_ptr<IDto3Charge> GenParticleProducer::globalBeginRun(const Run&, const EventSetup& es) const {
169  es.getData(pdt);
170  return std::make_shared<IDto3Charge>(*pdt, abortOnUnknownPDGCode_);
171 }
172 
174  std::unordered_map<int, size_t> barcodes;
175 
176  size_t totalSize = 0;
177  const GenEvent* mc = nullptr;
178  MixCollection<HepMCProduct>* cfhepmcprod = nullptr;
179  size_t npiles = 1;
180 
181  if (useCF_) {
183  evt.getByToken(mixToken_, cf);
184  cfhepmcprod = new MixCollection<HepMCProduct>(cf.product());
185  npiles = cfhepmcprod->size();
186  LogDebug("GenParticleProducer") << "npiles : " << npiles << endl;
187  for (unsigned int icf = 0; icf < npiles; ++icf) {
188  LogDebug("GenParticleProducer") << "subSize : " << cfhepmcprod->getObject(icf).GetEvent()->particles_size()
189  << endl;
190  totalSize += cfhepmcprod->getObject(icf).GetEvent()->particles_size();
191  }
192  LogDebug("GenParticleProducer") << "totalSize : " << totalSize << endl;
193  } else {
195  evt.getByToken(srcToken_, mcp);
196  mc = mcp->GetEvent();
197  if (mc == nullptr)
198  throw edm::Exception(edm::errors::InvalidReference) << "HepMC has null pointer to GenEvent" << endl;
199  totalSize = mc->particles_size();
200  }
201 
202  // initialise containers
203  const size_t size = totalSize;
204  vector<const HepMC::GenParticle*> particles(size);
205  auto candsPtr = std::make_unique<GenParticleCollection>(size);
206  auto barCodeVector = std::make_unique<vector<int>>(size);
207  std::unique_ptr<math::XYZPointF> xyz0Ptr(new math::XYZPointF(0., 0., 0.));
208  std::unique_ptr<float> t0Ptr(new float(0.f));
210  GenParticleCollection& cands = *candsPtr;
211  size_t offset = 0;
212  size_t suboffset = 0;
213 
214  IDto3Charge const& id2Charge = *runCache(evt.getRun().index());
216  if (doSubEvent_ || useCF_) {
217  for (size_t ipile = 0; ipile < npiles; ++ipile) {
218  LogDebug("GenParticleProducer") << "mixed object ipile : " << ipile << endl;
219  barcodes.clear();
220  if (useCF_)
221  mc = cfhepmcprod->getObject(ipile).GetEvent();
222 
223  //Look whether heavy ion/signal event
224  bool isHI = false;
225  const HepMC::HeavyIon* hi = mc->heavy_ion();
226  if (hi && hi->Ncoll_hard() > 1)
227  isHI = true;
228  size_t num_particles = mc->particles_size();
229  LogDebug("GenParticleProducer") << "num_particles : " << num_particles << endl;
230  if (ipile == 0) {
231  auto origin = (*mc->vertices_begin())->position();
232  xyz0Ptr->SetXYZ(origin.x() * mmToCm, origin.y() * mmToCm, origin.z() * mmToCm);
233  *t0Ptr = origin.t() * mmToNs;
234  }
235  fillIndices(mc, particles, *barCodeVector, offset, barcodes);
236  // fill output collection and save association
237  for (size_t ipar = offset; ipar < offset + num_particles; ++ipar) {
238  const HepMC::GenParticle* part = particles[ipar];
239  reco::GenParticle& cand = cands[ipar];
240  // convert HepMC::GenParticle to new reco::GenParticle
241  convertParticle(cand, part, id2Charge);
242  cand.resetDaughters(ref.id());
243  }
244 
245  for (size_t d = offset; d < offset + num_particles; ++d) {
246  const HepMC::GenParticle* part = particles[d];
247  const GenVertex* productionVertex = part->production_vertex();
248  int sub_id = 0;
249  if (productionVertex != nullptr) {
250  sub_id = productionVertex->id();
251  if (!isHI)
252  sub_id = 0;
253  // search barcode map and attach daughters
254  fillDaughters(cands, part, ref, d, barcodes);
255  } else {
256  const GenVertex* endVertex = part->end_vertex();
257  if (endVertex != nullptr)
258  sub_id = endVertex->id();
259  else
260  throw cms::Exception("SubEventID")
261  << "SubEvent not determined. Particle has no production and no end vertex!" << endl;
262  }
263  if (sub_id < 0)
264  sub_id = 0;
265  int new_id = sub_id + suboffset;
266  GenParticleRef dref(ref, d);
267  cands[d].setCollisionId(new_id); // For new GenParticle
268  LogDebug("VertexId") << "SubEvent offset 3 : " << suboffset;
269  }
270  int nsub = -2;
271  if (isHI) {
272  nsub = hi->Ncoll_hard() + 1;
273  suboffset += nsub;
274  } else {
275  suboffset += 1;
276  }
277  offset += num_particles;
278  }
279  } else {
280  auto origin = (*mc->vertices_begin())->position();
281  xyz0Ptr->SetXYZ(origin.x() * mmToCm, origin.y() * mmToCm, origin.z() * mmToCm);
282  *t0Ptr = origin.t() * mmToNs;
283  fillIndices(mc, particles, *barCodeVector, 0, barcodes);
284 
285  // fill output collection and save association
286  for (size_t i = 0; i < particles.size(); ++i) {
287  const HepMC::GenParticle* part = particles[i];
288  reco::GenParticle& cand = cands[i];
289  // convert HepMC::GenParticle to new reco::GenParticle
290  convertParticle(cand, part, id2Charge);
291  cand.resetDaughters(ref.id());
292  }
293 
294  // fill references to daughters
295  for (size_t d = 0; d < cands.size(); ++d) {
296  const HepMC::GenParticle* part = particles[d];
297  const GenVertex* productionVertex = part->production_vertex();
298  // search barcode map and attach daughters
299  if (productionVertex != nullptr)
300  fillDaughters(cands, part, ref, d, barcodes);
301  cands[d].setCollisionId(0);
302  }
303  }
304 
305  evt.put(std::move(candsPtr));
306  if (saveBarCodes_)
307  evt.put(std::move(barCodeVector));
308  if (cfhepmcprod)
309  delete cfhepmcprod;
310  evt.put(std::move(xyz0Ptr), "xyz0");
311  evt.put(std::move(t0Ptr), "t0");
312 }
313 
315  const HepMC::GenParticle* part,
316  IDto3Charge const& id2Charge) const {
317  Candidate::LorentzVector p4(part->momentum());
318  int pdgId = part->pdg_id();
319  cand.setThreeCharge(id2Charge.chargeTimesThree(pdgId));
320  cand.setPdgId(pdgId);
321  cand.setStatus(part->status());
322  cand.setP4(p4);
323  cand.setCollisionId(0);
324  const GenVertex* v = part->production_vertex();
325  if (v != nullptr) {
326  ThreeVector vtx = v->point3d();
327  Candidate::Point vertex(vtx.x() * mmToCm, vtx.y() * mmToCm, vtx.z() * mmToCm);
328  cand.setVertex(vertex);
329  } else {
330  cand.setVertex(Candidate::Point(0, 0, 0));
331  }
333  return true;
334 }
335 
337  const HepMC::GenParticle* part,
338  reco::GenParticleRefProd const& ref,
339  size_t index,
340  std::unordered_map<int, size_t>& barcodes) const {
341  const GenVertex* productionVertex = part->production_vertex();
342  size_t numberOfMothers = productionVertex->particles_in_size();
343  if (numberOfMothers > 0) {
344  GenVertex::particles_in_const_iterator motherIt = productionVertex->particles_in_const_begin();
345  for (; motherIt != productionVertex->particles_in_const_end(); motherIt++) {
346  const HepMC::GenParticle* mother = *motherIt;
347  size_t m = barcodes.find(mother->barcode())->second;
348  cands[m].addDaughter(GenParticleRef(ref, index));
349  cands[index].addMother(GenParticleRef(ref, m));
350  }
351  }
352 
353  return true;
354 }
355 
357  vector<const HepMC::GenParticle*>& particles,
358  vector<int>& barCodeVector,
359  int offset,
360  std::unordered_map<int, size_t>& barcodes) const {
361  size_t idx = offset;
362  HepMC::GenEvent::particle_const_iterator begin = mc->particles_begin(), end = mc->particles_end();
363  for (HepMC::GenEvent::particle_const_iterator p = begin; p != end; ++p) {
364  const HepMC::GenParticle* particle = *p;
365  size_t barCode_this_event = particle->barcode();
366  size_t barCode = barCode_this_event + offset;
367  if (barcodes.find(barCode) != barcodes.end())
368  throw cms::Exception("WrongReference") << "barcodes are duplicated! " << endl;
369  particles[idx] = particle;
370  barCodeVector[idx] = barCode;
371  barcodes.insert(make_pair(barCode_this_event, idx++));
372  }
373  return true;
374 }
375 
377 
#define LogDebug(id)
size
Write out results.
GenParticleProducer(const edm::ParameterSet &)
constructor
void produce(edm::StreamID, edm::Event &e, const edm::EventSetup &) const override
process one event
void globalEndRun(edm::Run const &, edm::EventSetup const &) const override
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
bool abortOnUnknownPDGCode_
unknown code treatment flag
MCTruthHelper< HepMC::GenParticle > mcTruthHelper_
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:131
void setCollisionId(int s)
Definition: GenParticle.h:35
static const double mmToNs
bool fillDaughters(reco::GenParticleCollection &cand, const HepMC::GenParticle *part, reco::GenParticleRefProd const &ref, size_t index, std::unordered_map< int, size_t > &barcodes) const
MCTruthHelper< reco::GenParticle > mcTruthHelperGenParts_
HepPDT::ParticleDataTable ParticleDataTable
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:525
std::vector< edm::EDGetTokenT< edm::HepMCProduct > > vectorSrcTokens_
Run const & getRun() const
Definition: Event.cc:108
edm::EDGetTokenT< CrossingFrame< edm::HepMCProduct > > mixToken_
bool fillIndices(const HepMC::GenEvent *mc, std::vector< const HepMC::GenParticle * > &particles, std::vector< int > &barCodeVector, int offset, std::unordered_map< int, size_t > &barcodes) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
edm::EDGetTokenT< edm::HepMCProduct > srcToken_
source collection name
bool convertParticle(reco::GenParticle &cand, const HepMC::GenParticle *part, const IDto3Charge &id2Charge) const
int size() const
Definition: MixCollection.h:20
void fillGenStatusFlags(const P &p, reco::GenStatusFlags &statusFlags) const
void setVertex(const Point &vertex) override
set vertex
bool getData(T &iHolder) const
Definition: EventSetup.h:113
U second(std::pair< T, U > const &p)
void resetDaughters(const edm::ProductID &id)
set daughters product ID
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
double p4[4]
Definition: TauolaWrapper.h:92
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
RunIndex index() const
Definition: Run.cc:21
double f[11][100]
static int PDGCacheMax
#define end
Definition: vmac.h:39
d
Definition: ztail.py:151
RefProd< PROD > getRefBeforePut()
Definition: Event.h:156
const GenStatusFlags & statusFlags() const
Definition: GenParticle.h:38
ProductID id() const
Accessor for product ID.
Definition: RefProd.h:124
const T & getObject(unsigned int ip) const
Definition: MixCollection.h:27
const HepMC::GenEvent * GetEvent() const
Definition: HepMCProduct.h:34
T const * product() const
Definition: Handle.h:69
void setThreeCharge(Charge qx3) final
set electric charge
static const double mmToCm
part
Definition: HCALResponse.h:20
edm::Ref< edm::HepMCProduct, HepMC::GenParticle > GenParticleRef
~GenParticleProducer() override
destructor
std::shared_ptr< IDto3Charge > globalBeginRun(const edm::Run &, const edm::EventSetup &) const override
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:37
bool doSubEvent_
input & output modes
fixed size matrix
#define begin
Definition: vmac.h:32
HLT enums.
static int position[264][3]
Definition: ReadPGInfo.cc:289
math::XYZPoint Point
point in the space
Definition: Candidate.h:41
bool saveBarCodes_
save bar-codes
void setStatus(int status) final
set status word
void setPdgId(int pdgId) final
void setP4(const LorentzVector &p4) final
set 4-momentum
def move(src, dest)
Definition: eostools.py:511
#define constexpr
Definition: Run.h:45