CMS 3D CMS Logo

PhotosInterface.cc
Go to the documentation of this file.
1 #include <iostream>
6 
8 
9 #include "HepMC/GenEvent.h"
10 #include "HepMC/IO_HEPEVT.h"
11 #include "HepMC/HEPEVT_Wrapper.h"
12 
13 using namespace gen;
14 using namespace edm;
15 using namespace std;
16 
17 CLHEP::HepRandomEngine* PhotosInterface::fRandomEngine = nullptr;
18 
19 extern "C" {
20 
21 void phoini_(void);
22 void photos_(int&);
23 
24 double phoran_(int* idummy) { return PhotosInterface::flat(); }
25 
26 extern struct {
27  // bool qedrad[NMXHEP];
28  bool qedrad[4000]; // hardcoded for now...
29 } phoqed_;
30 }
31 
33  fSpecialSettings.push_back("QED-brem-off:all");
35  fIsInitialized = false;
36 }
37 
39  fSpecialSettings.push_back("QED-brem-off:all");
40  fIsInitialized = false;
41 }
42 
44 
46 
48  fOnlyPDG = ipdg;
49  // std::ostringstream command;
50  // command << "QED-brem-off:" << fOnlyPDG ;
51  fSpecialSettings.clear();
52  // fSpecialSettings.push_back( command.str() );
53 
54  return;
55 }
56 
58  if (fIsInitialized)
59  return; // do init only once
60 
61  phoini_();
62 
63  fIsInitialized = true;
64 
65  return;
66 }
67 
69  if (!fIsInitialized)
70  return evt; // conv.read_next_event();
71 
72  // loop over HepMC::GenEvent, find vertices
73 
74  // for ( int ip=0; ip<evt->particles_size(); ip++ )
75  for (int ip = 0; ip < 4000; ip++) // 4000 is the max size of the array
76  {
77  phoqed_.qedrad[ip] = true;
78  }
79 
80  //
81  // now do actual job
82  //
83 
84  for (int iv = 1; iv <= evt->vertices_size(); iv++) {
85  bool legalVtx = false;
86 
87  fSecVtxStore.clear();
88 
89  HepMC::GenVertex* vtx = evt->barcode_to_vertex(-iv);
90 
91  if (vtx->particles_in_size() != 1)
92  continue; // more complex than we need
93  if (vtx->particles_out_size() <= 1)
94  continue; // no outcoming particles
95 
96  if ((*(vtx->particles_in_const_begin()))->pdg_id() == 111)
97  continue; // pi0 decay vtx - no point to try
98 
99  if (fOnlyPDG != 1 && (*(vtx->particles_in_const_begin()))->pdg_id() != fOnlyPDG) {
100  continue;
101  } else {
102  // requested for specific PDG ID only, typically tau (15)
103  //
104  // first check if a brem vertex, where outcoming are the same pdg id and a photon
105  //
106  bool same = false;
107  for (HepMC::GenVertex::particle_iterator pitr = vtx->particles_begin(HepMC::children);
108  pitr != vtx->particles_end(HepMC::children);
109  ++pitr) {
110  if ((*pitr)->pdg_id() == fOnlyPDG) {
111  same = true;
112  break;
113  }
114  }
115  if (same)
116  continue;
117 
118  // OK, we get here if incoming fOnlyPDG and something else outcoming
119  // call it for the whole branch starting at vtx barcode iv, and go on
120  // NOTE: theoretically, it has a danger of double counting in vertices
121  // down the decay branch originating from fOnlyPDG, but in practice
122  // it's unlikely that down the branchg there'll be more fOnlyPDG's
123 
124  // cross-check printout
125  // vtx->print();
126 
127  // overprotection...
128  //
130  continue;
131 
132  applyToBranch(evt, -iv);
133  continue;
134  }
135 
136  // configured for all types of particles
137  //
138  for (HepMC::GenVertex::particle_iterator pitr = vtx->particles_begin(HepMC::children);
139  pitr != vtx->particles_end(HepMC::children);
140  ++pitr) {
141  // quark or gluon out of this vertex - no good !
142  if (abs((*pitr)->pdg_id()) >= 1 && abs((*pitr)->pdg_id()) <= 8)
143  break;
144  if (abs((*pitr)->pdg_id()) == 21)
145  break;
146 
147  if ((*pitr)->status() == 1 || (*pitr)->end_vertex()) {
148  // OK, legal already !
149  legalVtx = true;
150  break;
151  }
152  }
153 
154  if (!legalVtx)
155  continue;
156 
157  applyToVertex(evt, -iv);
158 
159  } // end of master loop
160 
161  // restore event number in HEPEVT (safety measure, somehow needed by Hw6)
162  HepMC::HEPEVT_Wrapper::set_event_number(evt->event_number());
163 
164  return evt;
165 }
166 
168  HepMC::GenVertex* vtx = evt->barcode_to_vertex(vtxbcode);
169 
171  return;
172 
173  // cross-check printout
174  //
175  // vtx->print();
176 
177  // first, flush out HEPEVT & tmp barcode storage
178  //
179  HepMC::HEPEVT_Wrapper::zero_everything();
180  fBarcodes.clear();
181 
182  // add incoming particle
183  //
184  int index = 1;
185  HepMC::HEPEVT_Wrapper::set_id(index, (*(vtx->particles_in_const_begin()))->pdg_id());
186  HepMC::FourVector vec4;
187  vec4 = (*(vtx->particles_in_const_begin()))->momentum();
188  HepMC::HEPEVT_Wrapper::set_momentum(index, vec4.x(), vec4.y(), vec4.z(), vec4.e());
189  HepMC::HEPEVT_Wrapper::set_mass(index, (*(vtx->particles_in_const_begin()))->generated_mass());
190  HepMC::HEPEVT_Wrapper::set_position(
191  index, vtx->position().x(), vtx->position().y(), vtx->position().z(), vtx->position().t());
192  HepMC::HEPEVT_Wrapper::set_status(index, (*(vtx->particles_in_const_begin()))->status());
193  HepMC::HEPEVT_Wrapper::set_parents(index, 0, 0);
194  fBarcodes.push_back((*(vtx->particles_in_const_begin()))->barcode());
195 
196  // add outcoming particles (decay products)
197  //
198  int lastDau = 1;
199  for (HepMC::GenVertex::particle_iterator pitr = vtx->particles_begin(HepMC::children);
200  pitr != vtx->particles_end(HepMC::children);
201  ++pitr) {
202  if ((*pitr)->status() == 1 || (*pitr)->end_vertex()) {
203  index++;
204  vec4 = (*pitr)->momentum();
205  HepMC::HEPEVT_Wrapper::set_id(index, (*pitr)->pdg_id());
206  HepMC::HEPEVT_Wrapper::set_momentum(index, vec4.x(), vec4.y(), vec4.z(), vec4.e());
207  HepMC::HEPEVT_Wrapper::set_mass(index, (*pitr)->generated_mass());
208  vec4 = (*pitr)->production_vertex()->position();
209  HepMC::HEPEVT_Wrapper::set_position(index, vec4.x(), vec4.y(), vec4.z(), vec4.t());
210  HepMC::HEPEVT_Wrapper::set_status(index, (*pitr)->status());
211  HepMC::HEPEVT_Wrapper::set_parents(index, 1, 1);
212  fBarcodes.push_back((*pitr)->barcode());
213  lastDau++;
214  }
215  if ((*pitr)->end_vertex()) {
216  fSecVtxStore.push_back((*pitr)->end_vertex()->barcode());
217  }
218  }
219 
220  // store, further to set NHEP in HEPEVT
221  //
222  int nentries = index;
223 
224  // reset master pointer to mother
225  index = 1;
226  HepMC::HEPEVT_Wrapper::set_children(index, 2, lastDau); // FIXME: need to check
227  // if last daughter>=2 !!!
228 
229  // finally, set number of entries (NHEP) in HEPEVT
230  //
231  HepMC::HEPEVT_Wrapper::set_number_entries(nentries);
232 
233  // cross-check printout HEPEVT
234  // HepMC::HEPEVT_Wrapper::print_hepevt();
235 
236  // OK, 1-level vertex is formed - now, call PHOTOS
237  //
238  photos_(index);
239 
240  // another cross-check printout HEPEVT - after photos
241  // HepMC::HEPEVT_Wrapper::print_hepevt();
242 
243  // now check if something has been generated
244  // and make all adjustments to underlying vtx/parts
245  //
246  attachParticles(evt, vtx, nentries);
247 
248  // ugh, done with this vertex !
249 
250  return;
251 }
252 
254  fSecVtxStore.clear();
255 
256  // 1st level vertex
257  //
258  applyToVertex(evt, vtxbcode);
259 
260  // now look down the branch for more vertices, if any
261  //
262  // Note: fSecVtxStore gets filled up in applyToVertex, if necessary
263  //
264  unsigned int vcounter = 0;
265 
266  while (vcounter < fSecVtxStore.size()) {
267  applyToVertex(evt, fSecVtxStore[vcounter]);
268  vcounter++;
269  }
270 
271  fSecVtxStore.clear();
272 
273  return;
274 }
275 
276 void PhotosInterface::attachParticles(HepMC::GenEvent* evt, HepMC::GenVertex* vtx, int nentries) {
277  if (HepMC::HEPEVT_Wrapper::number_entries() > nentries) {
278  // yes, need all corrections and adjustments -
279  // figure out how many photons and what particles in
280  // the decay branch have changes;
281  // also, follow up each one and correct accordingly;
282  // at the same time, add photon(s) to the GenVertex
283  //
284 
285  // vtx->print();
286 
287  int largestBarcode = -1;
288  int Nbcodes = fBarcodes.size();
289 
290  for (int ip = 1; ip < Nbcodes; ip++) {
291  int bcode = fBarcodes[ip];
292  HepMC::GenParticle* prt = evt->barcode_to_particle(bcode);
293  if (bcode > largestBarcode)
294  largestBarcode = bcode;
295  double px = HepMC::HEPEVT_Wrapper::px(ip + 1);
296  double py = HepMC::HEPEVT_Wrapper::py(ip + 1);
297  double pz = HepMC::HEPEVT_Wrapper::pz(ip + 1);
298  double e = HepMC::HEPEVT_Wrapper::e(ip + 1);
299  double m = HepMC::HEPEVT_Wrapper::m(ip + 1);
300 
301  if (prt->end_vertex()) {
302  HepMC::GenVertex* endVtx = prt->end_vertex();
303 
304  std::vector<int> secVtxStorage;
305  secVtxStorage.clear();
306 
307  secVtxStorage.push_back(endVtx->barcode());
308 
309  const HepMC::FourVector& mom4 = prt->momentum();
310 
311  // now rescale all descendants
312  double bet1[3], bet2[3], gam1, gam2, pb;
313  double mass = mom4.m();
314  bet1[0] = -(mom4.px() / mass);
315  bet1[1] = -(mom4.py() / mass);
316  bet1[2] = -(mom4.pz() / mass);
317  bet2[0] = px / m;
318  bet2[1] = py / m;
319  bet2[2] = pz / m;
320  gam1 = mom4.e() / mass;
321  gam2 = e / m;
322 
323  unsigned int vcounter = 0;
324 
325  while (vcounter < secVtxStorage.size()) {
326  HepMC::GenVertex* theVtx = evt->barcode_to_vertex(secVtxStorage[vcounter]);
327 
328  for (HepMC::GenVertex::particle_iterator pitr = theVtx->particles_begin(HepMC::children);
329  pitr != theVtx->particles_end(HepMC::children);
330  ++pitr) {
331  if ((*pitr)->end_vertex()) {
332  secVtxStorage.push_back((*pitr)->end_vertex()->barcode());
333  }
334 
335  if (theVtx->particles_out_size() == 1 && (*pitr)->pdg_id() == prt->pdg_id()) {
336  // carbon copy
337  (*pitr)->set_momentum(HepMC::FourVector(px, py, pz, e));
338  continue;
339  }
340 
341  HepMC::FourVector dmom4 = (*pitr)->momentum();
342 
343  // Boost vector to parent rest frame...
344  pb = bet1[0] * dmom4.px() + bet1[1] * dmom4.py() + bet1[2] * dmom4.pz();
345  double dpx = dmom4.px() + bet1[0] * (dmom4.e() + pb / (gam1 + 1.));
346  double dpy = dmom4.py() + bet1[1] * (dmom4.e() + pb / (gam1 + 1.));
347  double dpz = dmom4.pz() + bet1[2] * (dmom4.e() + pb / (gam1 + 1.));
348  double de = gam1 * dmom4.e() + pb;
349  // ...and boost back to modified parent frame
350  pb = bet2[0] * dpx + bet2[1] * dpy + bet2[2] * dpz;
351  dpx += bet2[0] * (de + pb / (gam2 + 1.));
352  dpy += bet2[1] * (de + pb / (gam2 + 1.));
353  dpz += bet2[2] * (de + pb / (gam2 + 1.));
354  de *= gam2;
355  de += pb;
356 
357  (*pitr)->set_momentum(HepMC::FourVector(dpx, dpy, dpz, de));
358  }
359  vcounter++;
360  }
361 
362  secVtxStorage.clear();
363  }
364 
365  prt->set_momentum(HepMC::FourVector(px, py, pz, e));
366 
367  } // ok, all affected particles update, but the photon(s) still not inserted
368 
369  int newlyGen = HepMC::HEPEVT_Wrapper::number_entries() - nentries;
370 
371  if (largestBarcode < evt->particles_size()) {
372  // need to adjust barcodes down from the affected vertex/particles
373  // such that we "free up" barcodes for newly generated photons
374  // in the middle of the event record
375  //
376  for (int ipp = evt->particles_size(); ipp > largestBarcode; ipp--) {
377  (evt->barcode_to_particle(ipp))->suggest_barcode(ipp + newlyGen);
378  }
379  }
380 
381  // now attach new generated photons to the vertex
382  //
383  for (int ipnw = 1; ipnw <= newlyGen; ipnw++) {
384  int nbcode = largestBarcode + ipnw;
385  int pdg_id = HepMC::HEPEVT_Wrapper::id(nentries + ipnw);
386  int status = HepMC::HEPEVT_Wrapper::status(nentries + ipnw);
387  double px = HepMC::HEPEVT_Wrapper::px(nentries + ipnw);
388  double py = HepMC::HEPEVT_Wrapper::py(nentries + ipnw);
389  double pz = HepMC::HEPEVT_Wrapper::pz(nentries + ipnw);
390  double e = HepMC::HEPEVT_Wrapper::e(nentries + ipnw);
391  double m = HepMC::HEPEVT_Wrapper::m(nentries + ipnw);
392 
393  HepMC::GenParticle* NewPart = new HepMC::GenParticle(HepMC::FourVector(px, py, pz, e), pdg_id, status);
394  NewPart->set_generated_mass(m);
395  NewPart->suggest_barcode(nbcode);
396  vtx->add_particle_out(NewPart);
397  }
398 
399  //vtx->print();
400  //std::cout << " leaving attachParticles() " << std::endl;
401 
402  } // end of global if-statement
403 
404  return;
405 }
406 
407 bool PhotosInterface::isTauLeptonicDecay(HepMC::GenVertex* vtx) {
408  if (abs((*(vtx->particles_in_const_begin()))->pdg_id()) != 15)
409  return false;
410 
411  for (HepMC::GenVertex::particle_iterator pitr = vtx->particles_begin(HepMC::children);
412  pitr != vtx->particles_end(HepMC::children);
413  ++pitr) {
414  if (abs((*pitr)->pdg_id()) == 11 || abs((*pitr)->pdg_id()) == 13) {
415  return true;
416  }
417  }
418 
419  return false;
420 }
421 
423  if (!fRandomEngine) {
424  throw cms::Exception("LogicError")
425  << "PhotosInterface::flat: Attempt to generate random number when engine pointer is null\n"
426  << "This might mean that the code was modified to generate a random number outside the\n"
427  << "event and beginLuminosityBlock methods, which is not allowed.\n";
428  }
429  return fRandomEngine->flat();
430 }
431 
void phoini_(void)
void attachParticles(HepMC::GenEvent *, HepMC::GenVertex *, int)
CLHEP::HepRandomEngine * decayRandomEngine
void init() override
void configureOnlyFor(int) override
double phoran_(int *idummy)
void setRandomEngine(CLHEP::HepRandomEngine *decayRandomEngine) override
void photos_(int &)
std::vector< int > fBarcodes
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static CLHEP::HepRandomEngine * fRandomEngine
std::vector< vec3 > vec4
Definition: HCALResponse.h:18
void applyToBranch(HepMC::GenEvent *, int)
bool qedrad[4000]
HepMC::GenEvent * apply(HepMC::GenEvent *) override
HLT enums.
std::vector< int > fSecVtxStore
void applyToVertex(HepMC::GenEvent *, int)
#define DEFINE_EDM_PLUGIN(factory, type, name)
bool isTauLeptonicDecay(HepMC::GenVertex *)
static double flat()
struct @726 phoqed_
std::vector< std::string > fSpecialSettings