Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ResonanceJetTagging.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ResonanceJetTagging.cc
1 #include "ResonanceJetTagging.h"
2 
4 #include <calobase/RawCluster.h>
5 #include <calobase/RawClusterContainer.h>
6 #include <calobase/RawClusterUtility.h>
7 
9 #include <jetbase/Jet.h>
10 #include <jetbase/JetContainerv1.h>
11 #include <jetbase/Jetv2.h>
12 
16 
19 
23 
24 #include <g4main/PHG4Particle.h> // for PHG4Particle
25 #include <g4main/PHG4Particlev2.h> // for PHG4Particle
26 
27 // Particle Flow
28 #include <particleflowreco/ParticleFlowElement.h>
29 #include <particleflowreco/ParticleFlowElementContainer.h>
30 
33 
34 #include <phool/getClass.h>
35 #include <phool/PHCompositeNode.h>
36 #include <phool/phool.h>
37 
38 #include <kfparticle_sphenix/KFParticle_Container.h>
39 
40 #include <KFParticle.h>
41 
42 #include <fastjet/ClusterSequence.hh>
43 #include <fastjet/FunctionOfPseudoJet.hh>
44 #include <fastjet/JetDefinition.hh>
45 
46 #pragma GCC diagnostic push
47 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
48 #include <HepMC/GenEvent.h>
49 #include <HepMC/GenVertex.h>
50 #pragma GCC diagnostic pop
51 
53 #include <TDatabasePDG.h>
54 
56 #include <algorithm> // for max
57 #include <cassert>
58 #include <cmath>
59 #include <cstddef> // for size_t
60 #include <iostream> // for operator<<
61 #include <iterator> // for reverse_i...
62 #include <memory> // for allocator...
63 #include <set> // for set
64 #include <string>
65 
68 
79 ResonanceJetTagging::ResonanceJetTagging(const std::string &name, const TAG tag, const std::string &KFparticle_Container_name)
80  : SubsysReco(name)
81  , m_particleflow_mineta(-1.1)
82  , m_particleflow_maxeta(1.1)
83  , m_track_minpt(0.)
84  , m_track_maxpt(9999.)
85  , m_track_mineta(-1.1)
86  , m_track_maxeta(1.1)
87  , m_EMCal_cluster_minpt(0.)
88  , m_EMCal_cluster_maxpt(9999.)
89  , m_EMCal_cluster_mineta(-1.1)
90  , m_EMCal_cluster_maxeta(1.1)
91  , m_HCal_cluster_minpt(0.)
92  , m_HCal_cluster_maxpt(9999.)
93  , m_HCal_cluster_mineta(-1.1)
94  , m_HCal_cluster_maxeta(1.1)
95  , m_add_particleflow(true)
96  , m_add_tracks(false)
97  , m_add_EMCal_clusters(false)
98  , m_add_HCal_clusters(false)
99  , m_jetr(0.4)
100  , m_jetalgo(fastjet::antikt_algorithm)
101  , m_recomb_scheme(fastjet::pt_scheme)
102  , m_dorec(true)
103  , m_dotruth(false)
104  , m_nDaughters(0)
105  , m_tag_particle(tag)
106  , m_KFparticle_name(KFparticle_Container_name)
107 {
108  switch (m_tag_particle) {
109  case ResonanceJetTagging::TAG::D0:
110  m_tag_pdg = 421;
111  m_nDaughters = 2;
112  break;
113  case ResonanceJetTagging::TAG::D0TOK3PI:
114  m_tag_pdg = 421;
115  m_nDaughters = 4;
116  break;
117  case ResonanceJetTagging::TAG::DPLUS:
118  m_tag_pdg = 411;
119  m_nDaughters = 3;
120  break;
121  case ResonanceJetTagging::TAG::DSTAR:
122  m_tag_pdg = 413;
123  m_nDaughters = 0;
124  break;
125  case ResonanceJetTagging::TAG::JPSY:
126  m_tag_pdg = 433;
127  m_nDaughters = 0;
128  break;
129  case ResonanceJetTagging::TAG::K0:
130  m_tag_pdg = 311;
131  m_nDaughters = 0;
132  break;
133  case ResonanceJetTagging::TAG::GAMMA:
134  m_tag_pdg = 22;
135  m_nDaughters = 0;
136  break;
137  case ResonanceJetTagging::TAG::ELECTRON:
138  m_tag_pdg = 11;
139  m_nDaughters = 0;
140  break;
141  case ResonanceJetTagging::TAG::LAMBDAC:
142  m_tag_pdg = 4122;
143  m_nDaughters = 3;
144  break;
145  }
146 
147 }
148 
153 {
154 
155 }
156 
161 {
162  if (Verbosity() > 5)
163  {
164  std::cout << "Beginning Init in ResonanceJetTagging" << std::endl;
165  }
166 
167  createJetNode(topNode);
168 
169  return 0;
170 }
171 
177 {
178  if(m_nDaughters == 0)
179  {
180  std::cout<<"ERROR: Number of Decay Daughters Not Set, ABORTING!";
182  }
183 
184  switch (m_tag_particle) {
185  case ResonanceJetTagging::TAG::D0:
186  [[fallthrough]];
187  case ResonanceJetTagging::TAG::D0TOK3PI:
188  [[fallthrough]];
189  case ResonanceJetTagging::TAG::DPLUS:
190  [[fallthrough]];
191  case ResonanceJetTagging::TAG::LAMBDAC:
192  return tagHFHadronic(topNode);
193  break;
194  default:
195  std::cout<<"ERROR: Tag Function Not Set, ABORTING!";
197  break;
198  }
199 
201 }
202 
208 {
209  if (Verbosity() > 1)
210  {
211  std::cout << "Finished ResonanceJetTagging analysis package" << std::endl;
212  }
213 
214  return 0;
215 }
216 
218 {
219  if(m_dorec)
220  {
221  KFParticle_Container *kfContainer = findNode::getClass<KFParticle_Container>(topNode, m_KFparticle_name);
222  if(!kfContainer) return Fun4AllReturnCodes::ABORTEVENT;
223 
224  KFParticle *TagCand = nullptr;
225  PHG4Particlev2 *Cand = new PHG4Particlev2();
226  //const int nDaughters = 2; // TagCand->NDaughters() is returning 0, bug?
227  std::vector<KFParticle*> TagDaughters(m_nDaughters);
228  std::vector<PHG4Particlev2*> Daughters(m_nDaughters);
229  m_jet_id = 0;
230 
231  for (unsigned int i = 0; i < kfContainer->size(); i++)
232  {
233  TagCand = kfContainer->get(i);
234  if (std::abs(TagCand->GetPDG()) == m_tag_pdg)
235  {
236  for (int idau = 0; idau < m_nDaughters; idau++)
237  {
238  TagDaughters.at(idau) = kfContainer->get(i + idau + 1);
239  Daughters.at(idau) = new PHG4Particlev2();
240  Daughters.at(idau)->set_px(TagDaughters.at(idau)->Px());
241  Daughters.at(idau)->set_py(TagDaughters.at(idau)->Py());
242  Daughters.at(idau)->set_pz(TagDaughters.at(idau)->Pz());
243  //For daughters keep ID as the track ID, so they can be removed from the sample
244  //given to fastjet
245  Daughters.at(idau)->set_barcode(TagDaughters.at(idau)->Id());
246  }
247 
248  Cand->set_px(TagCand->Px());
249  Cand->set_py(TagCand->Py());
250  Cand->set_pz(TagCand->Pz());
251  Cand->set_e(TagCand->E());
252  //For tag particle keep ID as position in the KF Container
253  //so that later the tag particle can be recovered from jet constituent
254  Cand->set_barcode(i);
255 
256  findTaggedJets(topNode, Cand, Daughters);
257 
258  for (long unsigned int idau = 0; idau < Daughters.size(); idau++) delete Daughters.at(idau);
259 
260  m_jet_id++;
261  i += m_nDaughters; // Go to the next D meson
262  }
263  }
264  delete Cand;
265  }
266 
267  if (m_dotruth)
268  {
269  findMCTaggedJets(topNode);
270  }
271 
273 }
274 
275 void ResonanceJetTagging::findTaggedJets(PHCompositeNode *topNode, PHG4Particlev2 *Tag, const std::vector<PHG4Particlev2*> &TagDecays)
276 {
277  std::unique_ptr<fastjet::JetDefinition> jetdef(new fastjet::JetDefinition(m_jetalgo, m_jetr, m_recomb_scheme, fastjet::Best));
278  std::vector<fastjet::PseudoJet> particles;
279  Jet *taggedJet;
280  std::map<int, std::pair<Jet::SRC, int>> fjMap;
281 
282  fastjet::PseudoJet fjTag(Tag->get_px(), Tag->get_py(), Tag->get_pz(), Tag->get_e());
283  fjTag.set_user_index(0); // index 0 is the tag particle
284  particles.push_back(fjTag);
285  fjMap.insert(std::pair<int, std::pair<Jet::SRC, int>>(0, std::make_pair(Jet::SRC::VOID, Tag->get_barcode()))); // Maybe we could have a Jet::SRC::HF for HF-tagging?
286 
287  if (m_add_particleflow)
288  {
289  addParticleFlow(topNode, particles, TagDecays, fjMap);
290  }
291 
292  if (m_add_tracks)
293  {
294  addTracks(topNode, particles, TagDecays, fjMap);
295  }
296 
298  {
299  addClusters(topNode, particles, fjMap);
300  }
301 
302  fastjet::ClusterSequence jetFinder(particles, *jetdef);
303  std::vector<fastjet::PseudoJet> fastjets = jetFinder.inclusive_jets();
304 
305  taggedJet = m_taggedJetContainer->add_jet(); // add a new Jet_v2 to the JetContainer
306 
307  for (auto &fastjet : fastjets)
308  {
309  bool isTaggedJet = false;
310  std::vector<fastjet::PseudoJet> comps = fastjet.constituents();
311  for (auto &comp : comps)
312  {
313  taggedJet->insert_comp(fjMap[comp.user_index()].first, fjMap[comp.user_index()].second);
314  if (comp.user_index() == 0)
315  {
316  taggedJet->set_px(fastjet.px());
317  taggedJet->set_py(fastjet.py());
318  taggedJet->set_pz(fastjet.pz());
319  taggedJet->set_e(fastjet.e());
320  taggedJet->set_id(m_jet_id);
321  isTaggedJet = true;
322  }
323  }
324  if (isTaggedJet)
325  {
326  break;
327  }
328  else
329  {
330  taggedJet->clear_comp();
331  }
332  }
333 
334  return;
335 }
336 
337 void ResonanceJetTagging::addParticleFlow(PHCompositeNode *topNode, std::vector<fastjet::PseudoJet> &particles, const std::vector<PHG4Particlev2*> &TagDecays, std::map<int, std::pair<Jet::SRC, int>> &fjMap)
338 {
339  ParticleFlowElementContainer *pflowContainer = findNode::getClass<ParticleFlowElementContainer>(topNode, "ParticleFlowElements");
340 
341  if(!pflowContainer)
342  {
343  std::cout << PHWHERE
344  << "ParticleFlowElements node is missing, can't collect particles"
345  << std::endl;
346  return;
347  }
348 
349  SvtxTrack *track = nullptr;
350 
351  std::vector<RawCluster *> pfEMCalClusters;
352  std::vector<RawCluster *> pfHCalClusters;
353 
354  int idpart = particles.size();
355 
358  for (rtiter = begin_end.first; rtiter != begin_end.second; ++rtiter)
359  {
360  ParticleFlowElement *pflow = rtiter->second;
361 
362  if (!pflow)
363  {
364  continue;
365  }
366 
367  if (!isAcceptableParticleFlow(pflow))
368  {
369  continue;
370  }
371 
372  track = pflow->get_track();
373 
374  // Remove D0 decay daughter
375  if (track && isDecay(track, TagDecays))
376  {
377  continue;
378  }
379 
380  fastjet::PseudoJet fjPartFlow(pflow->get_px(), pflow->get_py(), pflow->get_pz(), pflow->get_e());
381 
382  fjPartFlow.set_user_index(idpart);
383  particles.push_back(fjPartFlow);
384  fjMap.insert(std::pair<int, std::pair<Jet::SRC, int>>(idpart, std::make_pair(Jet::SRC::PARTICLE, pflow->get_id())));
385  idpart++;
386  }
387 }
388 
390 {
391  // Only eta cut at this moment
392  if ((pfPart->get_eta() < m_particleflow_mineta) || (pfPart->get_eta() > m_particleflow_maxeta))
393  {
394  return false;
395  }
396 
397  return true;
398 }
399 void ResonanceJetTagging::addTracks(PHCompositeNode *topNode, std::vector<fastjet::PseudoJet> &particles, const std::vector<PHG4Particlev2*> &TagDecays, std::map<int, std::pair<Jet::SRC, int>> &fjMap)
400 {
401  SvtxTrackMap *trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
402 
403  if (!trackmap)
404  {
405  std::cout << PHWHERE
406  << "SvtxTrackMap node is missing, can't collect tracks"
407  << std::endl;
408  return;
409  }
410 
411  int idpart = particles.size();
412 
413  SvtxTrack *track = nullptr;
414 
415  for (auto &iter : *trackmap)
416  {
417  track = iter.second;
418 
419  if (!isAcceptableTrack(track))
420  {
421  continue;
422  }
423 
424  if (isDecay(track, TagDecays))
425  {
426  continue;
427  }
428 
429  fastjet::PseudoJet fjTrack(track->get_px(), track->get_py(), track->get_pz(), 0.);
430 
431  fjTrack.set_user_index(idpart);
432  particles.push_back(fjTrack);
433  fjMap.insert(std::pair<int, std::pair<Jet::SRC, int>>(idpart, std::make_pair(Jet::SRC::TRACK, track->get_id())));
434  idpart++;
435  }
436 }
437 
439 {
440  if ((track->get_pt() < m_track_minpt) || (track->get_pt() > m_track_maxpt))
441  {
442  return false;
443  }
444  if ((track->get_eta() < m_track_mineta) || (track->get_eta() > m_track_maxeta))
445  {
446  return false;
447  }
448 
449  return true;
450 }
451 
452 void ResonanceJetTagging::addClusters(PHCompositeNode *topNode, std::vector<fastjet::PseudoJet> &particles, std::map<int, std::pair<Jet::SRC, int>> &fjMap)
453 {
454  GlobalVertexMap *vertexmap = findNode::getClass<GlobalVertexMap>(topNode, "GlobalVertexMap");
455  if (!vertexmap)
456  {
457  std::cout << "ResonanceJetTagging::getEmcalClusters - Fatal Error - GlobalVertexMap node is missing. Please turn on the do_global flag in the main macro in order to reconstruct the global vertex." << std::endl;
458  assert(vertexmap); // force quit
459 
460  return;
461  }
462 
463  if (vertexmap->empty())
464  {
465  std::cout << "ResonanceJetTagging::getEmcalClusters - Fatal Error - GlobalVertexMap node is empty. Please turn on the do_global flag in the main macro in order to reconstruct the global vertex." << std::endl;
466  return;
467  }
468 
469  GlobalVertex *vtx = vertexmap->begin()->second;
470  if (vtx == nullptr)
471  {
472  return;
473  }
474 
475  // Get the current position in the particles vector
476  int idpart = particles.size();
477 
478  // EMCAL Clusters
480  {
481  RawClusterContainer *clustersEMC = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_CEMC");
482 
483  if (!clustersEMC)
484  {
485  std::cout << PHWHERE
486  << "EMCal cluster node is missing, can't collect EMCal clusters"
487  << std::endl;
488  return;
489  }
490 
491  RawClusterContainer::ConstRange begin_end_EMC = clustersEMC->getClusters();
493 
495  for (clusIter_EMC = begin_end_EMC.first;
496  clusIter_EMC != begin_end_EMC.second;
497  ++clusIter_EMC)
498  {
499  const RawCluster *cluster = clusIter_EMC->second;
500 
501  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
502  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
503 
504  if (!isAcceptableEMCalCluster(E_vec_cluster))
505  {
506  continue;
507  }
508 
509  double cluster_e = E_vec_cluster.mag();
510 
511  double cluster_pt = E_vec_cluster.perp();
512 
513  double cluster_phi = E_vec_cluster.getPhi();
514 
515  double cluster_px = cluster_pt * cos(cluster_phi);
516  double cluster_py = cluster_pt * sin(cluster_phi);
517  double cluster_pz = sqrt(cluster_e * cluster_e - cluster_px * cluster_px - cluster_py * cluster_py);
518 
519  fastjet::PseudoJet fjCluster(cluster_px, cluster_py, cluster_pz, cluster_e);
520 
521  fjCluster.set_user_index(idpart);
522  particles.push_back(fjCluster);
523  fjMap.insert(std::pair<int, std::pair<Jet::SRC, int>>(idpart, std::make_pair(Jet::SRC::CEMC_CLUSTER, cluster->get_id())));
524  idpart++;
525  }
526  }
527 
529  {
530  // HCAL Clusters
531  RawClusterContainer *clustersHCALIN = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_HCALIN");
532 
533  if (!clustersHCALIN)
534  {
535  std::cout << PHWHERE
536  << "EMCal cluster node is missing, can't collect EMCal clusters"
537  << std::endl;
538  return;
539  }
540 
541  RawClusterContainer::ConstRange begin_end_HCALIN = clustersHCALIN->getClusters();
542  RawClusterContainer::ConstIterator clusIter_HCALIN;
543 
545  for (clusIter_HCALIN = begin_end_HCALIN.first;
546  clusIter_HCALIN != begin_end_HCALIN.second;
547  ++clusIter_HCALIN)
548  {
550  const RawCluster *cluster = clusIter_HCALIN->second;
551 
552  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
553  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
554 
555  if (!isAcceptableHCalCluster(E_vec_cluster))
556  {
557  continue;
558  }
559 
560  double cluster_e = E_vec_cluster.mag();
561  double cluster_pt = E_vec_cluster.perp();
562  double cluster_phi = E_vec_cluster.getPhi();
563 
564  double cluster_px = cluster_pt * cos(cluster_phi);
565  double cluster_py = cluster_pt * sin(cluster_phi);
566  double cluster_pz = sqrt(cluster_e * cluster_e - cluster_px * cluster_px - cluster_py * cluster_py);
567 
568  fastjet::PseudoJet fjCluster(cluster_px, cluster_py, cluster_pz, cluster_e);
569 
570  fjCluster.set_user_index(idpart);
571  particles.push_back(fjCluster);
572  idpart++;
573  }
574 
575  RawClusterContainer *clustersHCALOUT = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_HCALOUT");
576 
577  if (!clustersHCALOUT)
578  {
579  std::cout << PHWHERE
580  << "EMCal cluster node is missing, can't collect EMCal clusters"
581  << std::endl;
582  return;
583  }
584 
585  RawClusterContainer::ConstRange begin_end_HCALOUT = clustersHCALOUT->getClusters();
586  RawClusterContainer::ConstIterator clusIter_HCALOUT;
587 
589  for (clusIter_HCALOUT = begin_end_HCALOUT.first;
590  clusIter_HCALOUT != begin_end_HCALOUT.second;
591  ++clusIter_HCALOUT)
592  {
594  const RawCluster *cluster = clusIter_HCALOUT->second;
595 
600  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
601  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
602 
603  if (!isAcceptableHCalCluster(E_vec_cluster))
604  {
605  continue;
606  }
607 
608  double cluster_e = E_vec_cluster.mag();
609  double cluster_pt = E_vec_cluster.perp();
610  double cluster_phi = E_vec_cluster.getPhi();
611 
612  double cluster_px = cluster_pt * cos(cluster_phi);
613  double cluster_py = cluster_pt * sin(cluster_phi);
614  double cluster_pz = sqrt(cluster_e * cluster_e - cluster_px * cluster_px - cluster_py * cluster_py);
615 
616  fastjet::PseudoJet fjCluster(cluster_px, cluster_py, cluster_pz, cluster_e);
617 
618  fjCluster.set_user_index(idpart);
619  particles.push_back(fjCluster);
620  idpart++;
621  }
622  }
623 
624 }
625 
626 bool ResonanceJetTagging::isAcceptableEMCalCluster(CLHEP::Hep3Vector &E_vec_cluster)
627 {
628  if ((E_vec_cluster.perp() < m_EMCal_cluster_minpt) || (E_vec_cluster.perp() > m_EMCal_cluster_maxpt))
629  {
630  return false;
631  }
632  if ((E_vec_cluster.pseudoRapidity() < m_EMCal_cluster_mineta) || (E_vec_cluster.pseudoRapidity() > m_EMCal_cluster_maxeta))
633  {
634  return false;
635  }
636 
637  return true;
638 }
639 
640 bool ResonanceJetTagging::isAcceptableHCalCluster(CLHEP::Hep3Vector &E_vec_cluster)
641 {
642  if ((E_vec_cluster.perp() < m_HCal_cluster_minpt) || (E_vec_cluster.perp() > m_HCal_cluster_maxpt))
643  {
644  return false;
645  }
646  if ((E_vec_cluster.pseudoRapidity() < m_HCal_cluster_mineta) || (E_vec_cluster.pseudoRapidity() > m_HCal_cluster_maxeta))
647  {
648  return false;
649  }
650 
651  return true;
652 }
653 
654 bool ResonanceJetTagging::isDecay(SvtxTrack *track, const std::vector<PHG4Particlev2*> &decays)
655 {
656  for (long unsigned int idecay = 0; idecay < decays.size(); idecay++)
657  {
658  if(int(track->get_id()) == decays.at(idecay)->get_barcode())
659  {
660  return true;
661  }
662  }
663  return false;
664 }
665 
666 bool ResonanceJetTagging::isDecay(HepMC::GenParticle *particle, const std::vector<PHG4Particlev2*> &decays)
667 {
668  for (long unsigned int idecay = 0; idecay < decays.size(); idecay++)
669  {
670  if (particle->barcode() == decays.at(idecay)->get_barcode())
671  {
672  return true;
673  }
674  }
675  return false;
676 }
677 
679 {
680  PHHepMCGenEventMap *hepmceventmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
682  if (!hepmceventmap)
683  {
684  std::cout << PHWHERE
685  << "HEPMC event map node is missing, can't collected HEPMC truth particles"
686  << std::endl;
687  return;
688  }
689 
690  PHHepMCGenEvent *hepmcevent = hepmceventmap->get(1);
691 
692  if (!hepmcevent)
693  {
694  return;
695  }
696 
697  HepMC::GenEvent *hepMCGenEvent = hepmcevent->getEvent();
698 
699  if (!hepMCGenEvent)
700  {
701  return;
702  }
703 
704  TDatabasePDG *database = TDatabasePDG::Instance();
705  TParticlePDG *partPDG = nullptr;
706 
707  PHG4TruthInfoContainer *m_truthinfo = nullptr;
708 
709  m_truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
710 
711  m_truth_jet_id = 0;
712 
713  Jet *mcTaggedJet;
714 
715  for (HepMC::GenEvent::particle_const_iterator tag = hepMCGenEvent->particles_begin(); tag != hepMCGenEvent->particles_end(); ++tag)
716  {
717  if (((*tag)->momentum().eta() < m_track_mineta) || ((*tag)->momentum().eta() > m_track_maxeta))
718  {
719  continue;
720  }
721 
722  if (std::abs((*tag)->pdg_id()) == m_tag_pdg)
723  {
724  std::vector<int> decayIDs;
725 
726  HepMC::GenVertex *TagVertex = (*tag)->end_vertex();
727  //if HEPMC vertex exists
728  if(TagVertex){
729  for (HepMC::GenVertex::particle_iterator it = TagVertex->particles_begin(HepMC::descendants); it != TagVertex->particles_end(HepMC::descendants); ++it)
730  {
731  decayIDs.push_back((*it)->barcode());
732  }
733  //if not, look into GEANT
734  }
735  else
736  {
738  for(PHG4TruthInfoContainer::ConstIterator iter = range.first; iter != range.second; ++iter)
739  {
740  PHG4Particle* g4particle = iter->second;
741  PHG4Particle* mother = nullptr;
742  if (g4particle->get_parent_id() != 0) mother = m_truthinfo->GetParticle(g4particle->get_parent_id());
743  else continue;
744  if (mother->get_barcode() == (*tag)->barcode() && mother->get_pid() == (*tag)->pdg_id())
745  {
746  decayIDs.push_back(g4particle->get_barcode());
747  }
748  }
749  }
750 
751  std::map<int, std::pair<Jet::SRC, int>> fjMapMC;
752 
753  std::vector<fastjet::PseudoJet> particles;
754  fastjet::PseudoJet fjMCParticle((*tag)->momentum().px(), (*tag)->momentum().py(), (*tag)->momentum().pz(), (*tag)->momentum().e());
755  fjMapMC.insert(std::pair<int, std::pair<Jet::SRC, int>>(0, std::make_pair(Jet::SRC::VOID, (*tag)->barcode()))); // Maybe we could have a Jet::SRC::HF for HF-tagging? Or maybe Jet::SRC::TAG? Using VOID for the tag particle
756  fjMCParticle.set_user_index(0);
757  particles.push_back(fjMCParticle);
758 
759  int idpart = particles.size();
760 
761  for (HepMC::GenEvent::particle_const_iterator p = hepMCGenEvent->particles_begin(); p != hepMCGenEvent->particles_end(); ++p)
762  {
763  if (((*p)->momentum().eta() < m_track_mineta) || ((*p)->momentum().eta() > m_track_maxeta))
764  {
765  continue;
766  }
767  if ((*p)->status() > 1)
768  {
769  continue;
770  }
771  if (std::abs((*p)->pdg_id()) == m_tag_pdg)
772  {
773  continue;
774  }
775 
776  partPDG = database->GetParticle((*p)->pdg_id());
777  double hepmcPartPt = std::sqrt(((*p)->momentum().px() * (*p)->momentum().px()) + ((*p)->momentum().py() * (*p)->momentum().py()));
778 
779  if (partPDG->Charge() != 0)
780  {
781  if ((hepmcPartPt < m_track_minpt) || (hepmcPartPt > m_track_maxpt))
782  {
783  continue;
784  }
785  }
786  else
787  {
788  if ((hepmcPartPt < m_EMCal_cluster_minpt) || (hepmcPartPt > m_EMCal_cluster_maxpt))
789  {
790  continue;
791  }
792  }
793  bool isTagDecay = false;
794  for (auto mcid : decayIDs)
795  {
796  if (mcid == (*p)->barcode())
797  {
798  isTagDecay = true;
799  }
800  }
801  if (isTagDecay)
802  {
803  continue;
804  }
805 
806  fastjet::PseudoJet fjMCParticle2((*p)->momentum().px(), (*p)->momentum().py(), (*p)->momentum().pz(), (*p)->momentum().e());
807  fjMapMC.insert(std::pair<int, std::pair<Jet::SRC, int>>(idpart, std::make_pair(Jet::SRC::PARTICLE, (*p)->barcode())));
808  fjMCParticle2.set_user_index(idpart);
809  particles.push_back(fjMCParticle2);
810  idpart++;
811  }
812 
813  std::unique_ptr<fastjet::JetDefinition> jetdef(new fastjet::JetDefinition(m_jetalgo, m_jetr, m_recomb_scheme, fastjet::Best));
814 
815  fastjet::ClusterSequence jetFinder(particles, *jetdef);
816  std::vector<fastjet::PseudoJet> mcfastjets = jetFinder.inclusive_jets();
817 
818  mcTaggedJet = m_truth_taggedJetContainer->add_jet(); // insert a new Jet_v2 and return pointer
819 
820  for (auto &mcfastjet : mcfastjets)
821  {
822  bool isTaggedJet = false;
823  std::vector<fastjet::PseudoJet> comps = mcfastjet.constituents();
824  for (auto &comp : comps)
825  {
826  mcTaggedJet->insert_comp(fjMapMC[comp.user_index()].first, fjMapMC[comp.user_index()].second);
827  if (comp.user_index() == 0)
828  {
829  mcTaggedJet->set_px(mcfastjet.px());
830  mcTaggedJet->set_py(mcfastjet.py());
831  mcTaggedJet->set_pz(mcfastjet.pz());
832  mcTaggedJet->set_e(mcfastjet.e());
833  mcTaggedJet->set_id(m_truth_jet_id);
834  isTaggedJet = true;
835  }
836  }
837  if (isTaggedJet)
838  {
839  break;
840  }
841  else
842  {
843  mcTaggedJet->clear_comp();
844  }
845  }
846  m_truth_jet_id++;
847  }
848  }
849 }
850 
851 
852 // Inspired by KFParticle_DST::createParticleNode
854 {
855  PHNodeIterator iter(topNode);
856 
857  PHCompositeNode *lowerNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
858  if (!lowerNode)
859  {
860  lowerNode = new PHCompositeNode("DST");
861  topNode->addNode(lowerNode);
862  std::cout << "DST node added" << std::endl;
863  }
864 
865  std::string baseName;
866  std::string jetNodeName;
867  std::string jetNodeNameMC;
868 
869  if (m_jetcontainer_name.empty())
870  {
871  baseName = "taggedJet";
872  }
873  else
874  {
875  baseName = m_jetcontainer_name;
876  }
877 
878  // Cant have forward slashes in DST or else you make a subdirectory on save!!!
879  std::string undrscr = "_";
880  std::string nothing = "";
881  std::map<std::string, std::string> forbiddenStrings;
882  forbiddenStrings["/"] = undrscr;
883  forbiddenStrings["("] = undrscr;
884  forbiddenStrings[")"] = nothing;
885  forbiddenStrings["+"] = "plus";
886  forbiddenStrings["-"] = "minus";
887  forbiddenStrings["*"] = "star";
888  for (auto const &[badString, goodString] : forbiddenStrings)
889  {
890  size_t pos;
891  while ((pos = baseName.find(badString)) != std::string::npos)
892  {
893  baseName.replace(pos, 1, goodString);
894  }
895  }
896 
897  jetNodeName = baseName + "_Jet_Container";
898  jetNodeNameMC = baseName + "_Truth_Jet_Container";
899 
901  PHIODataNode<PHObject> *jetNode = new PHIODataNode<PHObject>(m_taggedJetContainer, jetNodeName.c_str(), "PHObject");
902  lowerNode->addNode(jetNode);
903  std::cout << jetNodeName << " node added" << std::endl;
904 
906  PHIODataNode<PHObject> *jetNodeMC = new PHIODataNode<PHObject>(m_truth_taggedJetContainer, jetNodeNameMC.c_str(), "PHObject");
907  lowerNode->addNode(jetNodeMC);
908  std::cout << jetNodeNameMC << " node added" << std::endl;
909 
911 }