Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HFFastSim.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HFFastSim.cc
1 #include "HFFastSim.h"
2 
5 #include <phool/getClass.h>
6 
8 
10 
11 #include <TDatabasePDG.h>
12 #include <TFile.h>
13 #include <TH1.h>
14 #include <TH2.h>
15 #include <TH3.h>
16 #include <TLorentzVector.h>
17 #include <TString.h>
18 #include <TTree.h>
19 #include <g4jets/Jet.h>
20 #include <g4jets/JetMap.h>
21 
22 #include <HepMC/GenEvent.h>
23 #include <HepMC/GenRanges.h>
24 #include <HepMC/GenVertex.h>
27 
28 #include <gsl/gsl_const.h>
29 
30 #include <cassert>
31 #include <cmath>
32 #include <cstddef>
33 #include <iostream>
34 
35 using namespace std;
36 
37 HFFastSim::HFFastSim(std::string filename, int flavor, int maxevent)
38  : SubsysReco("HFFastSim")
39  , _verbose(0)
40  , _ievent(0)
41  , _total_pass(0)
42  , _f(nullptr)
43  , _h2(nullptr)
44  , _h2all(nullptr)
45  , _h2_b(nullptr)
46  , _h2_c(nullptr)
47  , m_hNorm(nullptr)
48  , m_DRapidity(nullptr)
49  , m_tSingleD(nullptr)
50  , m_singleD(nullptr)
51  , m_tSingleLc(nullptr)
52  , m_singleLc(nullptr)
53  , _embedding_id(1)
54 {
56 
57  _flavor = flavor;
58 
59  _maxevent = maxevent;
60 
61  _pt_min = 0;
62  _pt_max = 100;
63 
64  _eta_min = -1.1;
65  _eta_max = +1.1;
66 
68 }
69 
71 {
72  _verbose = true;
73 
74  _ievent = 0;
75 
76  _total_pass = 0;
77 
78  _f = new TFile(_foutname.c_str(), "RECREATE");
79 
80  m_hNorm = new TH1D("hNormalization", //
81  "Normalization;Items;Summed quantity", 10, .5, 10.5);
82  int i = 1;
83  m_hNorm->GetXaxis()->SetBinLabel(i++, "IntegratedLumi");
84  m_hNorm->GetXaxis()->SetBinLabel(i++, "Event");
85  m_hNorm->GetXaxis()->SetBinLabel(i++, "D0");
86  m_hNorm->GetXaxis()->SetBinLabel(i++, "D0->PiK");
87  m_hNorm->GetXaxis()->SetBinLabel(i++, "D0-Pair");
88  m_hNorm->GetXaxis()->SetBinLabel(i++, "D0->PiK-Pair");
89  m_hNorm->GetXaxis()->SetBinLabel(i++, "Lc");
90  m_hNorm->GetXaxis()->SetBinLabel(i++, "Lc->pPiK");
91  m_hNorm->GetXaxis()->SetBinLabel(i++, "Accepted");
92 
93  m_hNorm->GetXaxis()->LabelsOption("v");
94 
95  m_DRapidity = new TH2F("hDRapidity", //
96  "hDRapidity;Rapidity of D0 meson;Accepted", 1000, -5, 5, 2, -.5, 1.5);
97 
98  _h2 = new TH2D("h2", "", 100, 0, 100.0, 40, -2, +2);
99  _h2_b = new TH2D("h2_b", "", 100, 0, 100.0, 40, -2, +2);
100  _h2_c = new TH2D("h2_c", "", 100, 0, 100.0, 40, -2, +2);
101  _h2all = new TH2D("h2all", "", 100, 0, 100.0, 40, -2, +2);
102 
103  m_tSingleD = new TTree("TSingleD", "TSingleD");
104 
105  m_singleD = new D02PiK;
106  m_tSingleD->Branch("D02PiK", "HFFastSim::D02PiK", &m_singleD);
107 
108  m_tSingleLc = new TTree("TSingleLc", "TSingleLc");
109 
110  m_singleLc = new Lc2pPiK;
111  m_tSingleLc->Branch("Lc2pPiK", "HFFastSim::Lc2pPiK", &m_singleLc);
112 
113  return 0;
114 }
115 
116 std::pair<int, TString> HFFastSim::quark_trace(const HepMC::GenParticle* p, HepMC::GenEvent* theEvent)
117 {
118  int max_abs_q_pid = 0;
119  TString chain;
120 
121  while (p)
122  {
123  int pidabs = 0;
124 
125  TParticlePDG* pdg_p = TDatabasePDG::Instance()->GetParticle((p)->pdg_id());
126  if (pdg_p)
127  {
128  chain = TString(" -> ") + TString(pdg_p->GetName()) + chain;
129 
130  if (TString(pdg_p->ParticleClass()).BeginsWith("B-"))
131  {
132  pidabs = TDatabasePDG::Instance()->GetParticle("b")->PdgCode();
133  }
134  else if (TString(pdg_p->ParticleClass()).BeginsWith("Charmed"))
135  {
136  pidabs = TDatabasePDG::Instance()->GetParticle("c")->PdgCode();
137  }
138  }
139  else
140  {
141  chain = TString(" -> ") + Form("%d", (p)->pdg_id()) + chain;
142  }
143 
144  if (pidabs > max_abs_q_pid) max_abs_q_pid = pidabs;
145 
146  const HepMC::GenVertex* vtx = p->production_vertex();
147  if (vtx)
148  {
149  if (vtx->particles_in_size() == 1)
150  {
151  //trace parent
152  p = *(vtx->particles_in_const_begin());
153  }
154  else
155  {
156  // vac, beam, or lund string
157  // vtx->print();
158 
159  break;
160  }
161  }
162  }
163 
164  return make_pair(max_abs_q_pid, chain);
165 }
166 
167 bool HFFastSim::process_D02PiK(HepMC::GenEvent* theEvent)
168 {
169  assert(theEvent);
170 
171  const double mom_factor = HepMC::Units::conversion_factor(theEvent->momentum_unit(), HepMC::Units::GEV);
172  const double length_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM);
173  // const double time_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM) / GSL_CONST_CGS_SPEED_OF_LIGHT * 1e9; // from length_unit()/c to ns
174 
175  TDatabasePDG* pdg = TDatabasePDG::Instance();
176 
177  int targetPID = std::abs(pdg->GetParticle("D0")->PdgCode());
178  int daughter1PID = std::abs(pdg->GetParticle("pi+")->PdgCode());
179  int daughter2PID = std::abs(pdg->GetParticle("K+")->PdgCode());
180 
181  unsigned int nD0(0);
182  unsigned int nD0PiK(0);
183 
184  auto range = theEvent->particle_range();
185  for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
186  {
187  const HepMC::GenParticle* p = *piter;
188  assert(p);
189 
190  if (std::abs(p->pdg_id()) == targetPID)
191  {
192  if (Verbosity() >= VERBOSITY_MORE)
193  {
194  cout << "process_D02PiK - Accept signal particle : ";
195  p->print();
196  cout << endl;
197  }
198 
199  m_hNorm->Fill("D0", 1);
200  ++nD0;
201 
203  const double rapidity = 0.5 * log((p->momentum().e() + p->momentum().z()) /
204  (p->momentum().e() - p->momentum().z()));
205 
206  m_DRapidity->Fill(rapidity, 0);
207 
208  const HepMC::GenVertex* decayVertex = p->end_vertex();
209 
210  int hasDecay1(0);
211  int hasDecay2(0);
212  int hasDecayOther(0);
213 
214  if (decayVertex) // decay
215  {
216  for (auto diter = decayVertex->particles_out_const_begin();
217  diter != decayVertex->particles_out_const_end();
218  ++diter)
219 
220  {
221  const HepMC::GenParticle* pd = *diter;
222  assert(pd);
223 
224  if (Verbosity() >= VERBOSITY_MORE)
225  {
226  cout << "process_D02PiK - Testing daughter particle: ";
227  pd->print();
228  cout << endl;
229  }
230 
231  if (std::abs(pd->pdg_id()) == daughter1PID)
232  {
233  const double eta = pd->momentum().eta();
234 
235  if (eta > _eta_min and eta < _eta_max)
236  ++hasDecay1;
237  }
238  else if (std::abs(pd->pdg_id()) == daughter2PID)
239  {
240  const double eta = pd->momentum().eta();
241 
242  if (eta > _eta_min and eta < _eta_max)
243  ++hasDecay2;
244  }
245  else
246  ++hasDecayOther;
247  } // for ...
248 
249  // found a D0->piK
250  if (hasDecay1 == 1 and hasDecay2 == 1 and hasDecayOther == 0)
251  {
252  m_hNorm->Fill("D0->PiK", 1);
253  ++nD0PiK;
254 
255  assert(m_singleD);
256  m_singleD->pid = p->pdg_id();
257  m_singleD->y = rapidity;
258  m_singleD->pt = p->momentum().perp() * mom_factor;
259 
260  m_singleD->decayL = decayVertex->point3d().r() * length_factor;
261  m_singleD->prodL = p->production_vertex()->point3d().r() * length_factor;
262 
263  auto trace = quark_trace(p, theEvent);
264  m_singleD->hadron_origion_qpid = trace.first;
265  m_singleD->decayChain = trace.second;
266 
267  if (Verbosity())
268  {
269  cout << "process_D02PiK - Found D0->piK:";
270  cout << "m_singleD->pid = " << m_singleD->pid << ", ";
271  cout << "m_singleD->y = " << m_singleD->y << ", ";
272  cout << "m_singleD->pt = " << m_singleD->pt;
273  cout << " origin " << m_singleD->decayChain << endl;
274  }
275 
277  m_tSingleD->Fill();
278  m_singleD->Clear();
279 
280  m_DRapidity->Fill(rapidity, 1);
281  }
282 
283  } // if (decayVertex)
284  else
285  {
286  cout << "process_D02PiK - Warning - target particle did not have decay vertex : ";
287  p->print();
288  cout << endl;
289  }
290 
291  } // if (std::abs(p-> pdg_id()) == targetPID)
292  } // for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
293 
294  if (nD0 >= 2)
295  {
296  if (Verbosity() >= VERBOSITY_MORE)
297  cout << "process_D02PiK - D0-Pair with nD0 = " << nD0 << endl;
298  m_hNorm->Fill("D0-Pair", nD0 * (nD0 - 1) / 2);
299  }
300  if (nD0PiK >= 2)
301  {
302  m_hNorm->Fill("D0->PiK-Pair", nD0PiK * (nD0PiK - 1) / 2);
303  }
304 
305  return nD0PiK >= 1;
306 }
307 
308 bool HFFastSim::process_Lc2pPiK(HepMC::GenEvent* theEvent)
309 {
310  assert(theEvent);
311 
312  const double mom_factor = HepMC::Units::conversion_factor(theEvent->momentum_unit(), HepMC::Units::GEV);
313  const double length_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM);
314  // const double time_factor = HepMC::Units::conversion_factor(theEvent->length_unit(), HepMC::Units::CM) / GSL_CONST_CGS_SPEED_OF_LIGHT * 1e9; // from length_unit()/c to ns
315 
316  TDatabasePDG* pdg = TDatabasePDG::Instance();
317 
318  const int targetPID = std::abs(pdg->GetParticle("Lambda_c+")->PdgCode());
319  assert(targetPID == 4122);
320  const int daughter1PID = std::abs(pdg->GetParticle("pi+")->PdgCode());
321  assert(daughter1PID == 211);
322  const int daughter2PID = std::abs(pdg->GetParticle("K+")->PdgCode());
323  assert(daughter2PID == 321);
324  const int daughter3PID = std::abs(pdg->GetParticle("proton")->PdgCode());
325  assert(daughter3PID == 2212);
326 
327  unsigned int nLc(0);
328  unsigned int nLc2pPiK(0);
329 
330  auto range = theEvent->particle_range();
331  for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
332  {
333  const HepMC::GenParticle* p = *piter;
334  assert(p);
335 
336  if (std::abs(p->pdg_id()) == targetPID)
337  {
338  if (Verbosity() >= VERBOSITY_MORE)
339  {
340  cout << "HFFastSim::process_Lc2pPiK - Accept signal particle : ";
341  p->print();
342  cout << endl;
343  }
344 
345  m_hNorm->Fill("Lc", 1);
346  ++nLc;
347 
348  const double rapidity = 0.5 * log((p->momentum().e() + p->momentum().z()) /
349  (p->momentum().e() - p->momentum().z()));
350 
351  const HepMC::GenVertex* decayVertex = p->end_vertex();
352 
353  int hasDecay1(0);
354  int hasDecay2(0);
355  int hasDecay3(0);
356  int hasDecayOther(0);
357 
358  if (decayVertex) // decay
359  {
360  for (auto diter = decayVertex->particles_out_const_begin();
361  diter != decayVertex->particles_out_const_end();
362  ++diter)
363 
364  {
365  const HepMC::GenParticle* pd = *diter;
366  assert(pd);
367 
368  if (Verbosity() >= VERBOSITY_MORE)
369  {
370  cout << "HFFastSim::process_Lc2pPiK - Testing daughter particle: ";
371  pd->print();
372  cout << endl;
373  }
374 
375  if (std::abs(pd->pdg_id()) == daughter1PID)
376  {
377  const double eta = pd->momentum().eta();
378 
379  if (eta > _eta_min and eta < _eta_max)
380  ++hasDecay1;
381  }
382  else if (std::abs(pd->pdg_id()) == daughter2PID)
383  {
384  const double eta = pd->momentum().eta();
385 
386  if (eta > _eta_min and eta < _eta_max)
387  ++hasDecay2;
388  }
389  else if (std::abs(pd->pdg_id()) == daughter3PID)
390  {
391  const double eta = pd->momentum().eta();
392 
393  if (eta > _eta_min and eta < _eta_max)
394  ++hasDecay3;
395  }
396  else
397  ++hasDecayOther;
398  } // for ...
399 
400  // found a D0->piK
401  if (hasDecay1 == 1 and hasDecay2 == 1 and hasDecay3 == 1 and hasDecayOther == 0)
402  {
403  m_hNorm->Fill("Lc->pPiK", 1);
404  ++nLc2pPiK;
405 
407  m_singleLc->pid = p->pdg_id();
408  m_singleLc->y = rapidity;
409  m_singleLc->pt = p->momentum().perp() * mom_factor;
410 
411  m_singleLc->decayL = decayVertex->point3d().r() * length_factor;
412  m_singleLc->prodL = p->production_vertex()->point3d().r() * length_factor;
413 
414  auto trace = quark_trace(p, theEvent);
415  m_singleLc->hadron_origion_qpid = trace.first;
416  m_singleLc->decayChain = trace.second;
417 
418  if (Verbosity())
419  {
420  cout << "HFFastSim::process_Lc2pPiK - Found D0->piK:";
421  cout << "m_singleLc->pid = " << m_singleLc->pid << ", ";
422  cout << "m_singleLc->y = " << m_singleLc->y << ", ";
423  cout << "m_singleLc->pt = " << m_singleLc->pt;
424  cout << " origin " << m_singleLc->decayChain << endl;
425  }
426 
428  m_tSingleLc->Fill();
429  m_singleLc->Clear();
430 
431  m_DRapidity->Fill(rapidity, 1);
432  }
433 
434  } // if (decayVertex)
435  else
436  {
437  cout << "HFFastSim::process_Lc2pPiK - Warning - target particle did not have decay vertex : ";
438  p->print();
439  cout << endl;
440  }
441 
442  } // if (std::abs(p-> pdg_id()) == targetPID)
443  } // for (HepMC::GenEvent::particle_const_iterator piter = range.begin(); piter != range.end(); ++piter)
444 
445  return nLc2pPiK >= 1;
446 }
447 
449 {
450  assert(m_hNorm);
451  m_hNorm->Fill("Event", 1);
452 
453  PHHepMCGenEventMap* geneventmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
454  if (!geneventmap)
455  {
456  std::cout << PHWHERE << " - Fatal error - missing node PHHepMCGenEventMap" << std::endl;
458  }
459 
460  PHHepMCGenEvent* genevt = geneventmap->get(_embedding_id);
461  if (!genevt)
462  {
463  std::cout << PHWHERE << " - Fatal error - node PHHepMCGenEventMap missing subevent with embedding ID " << _embedding_id;
464  std::cout << ". Print PHHepMCGenEventMap:";
465  geneventmap->identify();
467  }
468 
469  HepMC::GenEvent* theEvent = genevt->getEvent();
470  //theEvent->print();
471  assert(theEvent);
472 
473  if (Verbosity() >= VERBOSITY_MORE)
474  {
475  cout << "HFFastSim::process_event - process HepMC::GenEvent with signal_process_id = "
476  << theEvent->signal_process_id();
477  if (theEvent->signal_process_vertex())
478  {
479  cout << " and signal_process_vertex : ";
480  theEvent->signal_process_vertex()->print();
481  }
482  cout << " - Event record:" << endl;
483  theEvent->print();
484  }
485 
486  // process quarks
487  for (HepMC::GenEvent::particle_const_iterator p = theEvent->particles_begin();
488  p != theEvent->particles_end(); ++p)
489  {
490  int pidabs = abs((*p)->pdg_id());
491  if (pidabs == TDatabasePDG::Instance()->GetParticle("c")->PdgCode() //
492  or pidabs == TDatabasePDG::Instance()->GetParticle("b")->PdgCode() //
493  or pidabs == TDatabasePDG::Instance()->GetParticle("t")->PdgCode()) // handle heavy quarks only. All other favor tagged as default 0
494  {
495  if (pidabs == TDatabasePDG::Instance()->GetParticle("b")->PdgCode())
496  {
497  if (Verbosity() >= VERBOSITY_MORE)
498  std::cout << __PRETTY_FUNCTION__
499  << " --BOTTOM--> pt / eta / phi = "
500  << ((*p)->momentum().perp()) << " / "
501  << (*p)->momentum().pseudoRapidity() << " / "
502  << (*p)->momentum().phi() << std::endl;
503 
504  _h2_b->Fill((*p)->momentum().perp(), (*p)->momentum().pseudoRapidity());
505  }
506  else if (pidabs == TDatabasePDG::Instance()->GetParticle("c")->PdgCode())
507  {
508  if (Verbosity() >= VERBOSITY_MORE)
509  std::cout << __PRETTY_FUNCTION__
510  << " --CHARM --> pt / eta / phi = "
511  << (*p)->momentum().perp() << " / "
512  << (*p)->momentum().pseudoRapidity() << " / "
513  << (*p)->momentum().phi() << std::endl;
514 
515  _h2_c->Fill((*p)->momentum().perp(), (*p)->momentum().pseudoRapidity());
516  }
517  }
518 
519  } // for (HepMC::GenEvent::particle_const_iterator p =
520 
521  bool pass_event = process_D02PiK(theEvent);
522  process_Lc2pPiK(theEvent);
523 
524  if (pass_event && _total_pass >= _maxevent)
525  {
527  std::cout << __PRETTY_FUNCTION__ << " --> FAIL due to max events = "
528  << _total_pass << std::endl;
529  _ievent++;
530  return _rejection_action;
531  }
532  else if (pass_event)
533  {
534  _total_pass++;
536  std::cout << __PRETTY_FUNCTION__ << " --> PASS, total = " << _total_pass
537  << std::endl;
538  _ievent++;
539  m_hNorm->Fill("Accepted", 1);
541  }
542  else
543  {
545  std::cout << __PRETTY_FUNCTION__ << " --> FAIL " << std::endl;
546  _ievent++;
547  return _rejection_action;
548  }
549 }
550 
552 {
554  std::cout << __PRETTY_FUNCTION__ << " PASSED " << _total_pass
555  << " events" << std::endl;
556 
557  PHGenIntegral* integral_node = findNode::getClass<PHGenIntegral>(topNode, "PHGenIntegral");
558  if (integral_node)
559  {
560  integral_node->identify();
561  assert(m_hNorm);
562  m_hNorm->Fill("IntegratedLumi", integral_node->get_Integrated_Lumi());
563  }
564 
565  _f->cd();
566  _f->Write();
567  //_f->Close();
568 
569  return 0;
570 }