Class Reference for E1039 Core & Analysis Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TruthNodeMaker.cc
Go to the documentation of this file.
1 #include <iomanip>
2 #include <list>
6 #include <g4main/PHG4Hit.h>
7 #include <g4main/PHG4Particle.h>
8 #include <g4main/PHG4VtxPoint.h>
18 #include <phool/PHNodeIterator.h>
19 #include <phool/PHIODataNode.h>
20 #include <phool/getClass.h>
21 #include <geom_svc/GeomSvc.h>
22 #include <ktracker/SRecEvent.h>
23 #include <GlobalConsts.h>
24 #include "TruthNodeMaker.h"
25 using namespace std;
26 
28  : SubsysReco("TruthNodeMaker")
29  , genevtmap(nullptr)
30  , g4true(nullptr)
31  , m_vec_hit(nullptr)
32  , m_rec_evt(nullptr)
33  , m_vec_rec_trk(nullptr)
34  , m_evt(nullptr)
35  , m_mcevt(nullptr)
36  , m_vec_trk(nullptr)
37  , m_vec_dim(nullptr)
38  , m_legacy_rec_container(true)
39  , m_do_evt_header(true)
40  , m_do_truthtrk_tagging(true)
41  , m_matching_threshold(0.75)
42 {
43  for(int i = 0; i <= nChamberPlanes; ++i) {
44  m_g4hc[i] = nullptr;
45  }
46 }
47 
49 {
50  if (! m_evt ) delete m_evt;
51  if (! m_mcevt ) delete m_mcevt;
52  if (! m_vec_trk) delete m_vec_trk;
53  if (! m_vec_dim) delete m_vec_dim;
54 }
55 
57 {
59 }
60 
62 {
63  int ret = GetNodes(topNode);
64  if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
65  ret = MakeNodes(topNode);
66  if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
68 }
69 
71 {
73  if(m_do_evt_header) {
74  if (genevtmap->size() != 1) {
75  cout << "TruthNodeMaker::process_event(): size != 1 unexpectedly." << endl;
76  }
77 
78  for (PHHepMCGenEventMap::Iter iter = genevtmap->begin(); iter != genevtmap->end(); ++iter) {
79  PHHepMCGenEvent *genevt = iter->second;
80  if (! genevt) {
81  cout << "No PHHepMCGenEvent object." << endl;
82  //return Fun4AllReturnCodes::ABORTEVENT;
83  }
84  HepMC::GenEvent *evt = genevt->getEvent();
85  if (! evt) {
86  cout << "No HepMC::GenEvent object." << endl;
87  //return Fun4AllReturnCodes::ABORTEVENT;
88  }
89  m_evt->set_run_id (0);
90  m_evt->set_spill_id(0);
91  m_evt->set_event_id(evt->event_number());
92  m_mcevt->set_process_id(evt->signal_process_id());
93 
94  //HepMC::GenVertex* vtx = evt->signal_process_vertex(); // Return 0 as of 2019-11-19.
95  HepMC::GenEvent::particle_const_iterator it = evt->particles_begin();
96  it++; // Skip the 1st beam particle.
97  for (int iii = 0; iii < 4; iii++) {
98  it++;
99  const HepMC::GenParticle* par = *it;
100  const HepMC::FourVector * mom = &par->momentum();
101  TLorentzVector lvec;
102  lvec.SetPxPyPzE(mom->px(), mom->py(), mom->pz(), mom->e());
103  m_mcevt->set_particle_id(iii, par->pdg_id());
104  m_mcevt->set_particle_momentum(iii, lvec);
105  }
106  }
107  }
108 
110  m_vec_trk->clear();
111  map<int, int> trkid_idx;
112  vector<int> vec_vtx_id;
113  for (auto it = g4true->GetPrimaryParticleRange().first; it != g4true->GetPrimaryParticleRange().second; ++it) {
114  PHG4Particle* par = it->second;
115  int pid = par->get_pid();
116  if (abs(pid) != 13) continue; // not muon
117  int trk_id = par->get_track_id();
118  int vtx_id = par->get_vtx_id();
119  PHG4VtxPoint* vtx = g4true->GetVtx(vtx_id);
120 
121  SQTrack_v1 trk;
122  trk.set_track_id(trk_id);
123  trk.set_charge(pid < 0 ? +1: -1); // -13 = mu+
124  trk.set_pos_vtx(TVector3 (vtx->get_x (), vtx->get_y (), vtx->get_z ()));
125  trk.set_mom_vtx(TLorentzVector(par->get_px(), par->get_py(), par->get_pz(), par->get_e()));
126 
127  trkid_idx[trk_id] = m_vec_trk->size();
128  m_vec_trk->push_back(&trk);
129  vec_vtx_id.push_back(vtx_id);
130  }
131 
133  m_vec_dim->clear();
134  int id_dim = 0; // to be incremented
135  unsigned int n_trk = m_vec_trk->size();
136  for (unsigned int i1 = 0; i1 < n_trk; i1++) {
137  SQTrack* trk1 = m_vec_trk->at(i1);
138  if (trk1->get_charge() <= 0) continue;
139  for (unsigned int i2 = 0; i2 < n_trk; i2++) {
140  SQTrack* trk2 = m_vec_trk->at(i2);
141  if (trk2->get_charge() >= 0) continue;
142  if (vec_vtx_id[i1] != vec_vtx_id[i2]) continue;
143 
144  SQDimuon_v1 dim;
145  dim.set_dimuon_id(++id_dim);
146  //dim.set_pdg_id(par_dim->pdg_id()); // PDG ID is not accessible via PHG4Particle
147  dim.set_pos (trk1->get_pos_vtx());
148  dim.set_mom (trk1->get_mom_vtx() + trk2->get_mom_vtx());
149  dim.set_mom_pos (trk1->get_mom_vtx());
150  dim.set_mom_neg (trk2->get_mom_vtx());
151  dim.set_track_id_pos(trk1->get_track_id());
152  dim.set_track_id_neg(trk2->get_track_id());
153  m_vec_dim->push_back(&dim);
154  }
155  }
156 
158  map<int, vector<SQHit*> > trkid_hitvec;
159  int n_digihits = m_vec_hit->size();
160  for(int i = 0; i < n_digihits; ++i) {
161  SQHit* hit = m_vec_hit->at(i);
162 
163  int detid = hit->get_detector_id();
164  if(detid > nChamberPlanes || (detid >= 7 && detid <= 12)) continue;
165 
166  int trkid = hit->get_track_id();
167  if(trkid_idx.find(trkid) == trkid_idx.end()) continue;
168 
169  if(trkid_hitvec.find(trkid) == trkid_hitvec.end()) {
170  trkid_hitvec[trkid] = vector<SQHit*>();
171  }
172  trkid_hitvec[trkid].push_back(hit);
173  }
174 
176  for(unsigned int i = 0; i < n_trk; ++i) {
177  SQTrack* trk = m_vec_trk->at(i);
178 
179  int trkid = trk->get_track_id();
180  if(trkid_hitvec.find(trkid) == trkid_hitvec.end()) {
181  //this track does not have hits in detector
182  continue;
183  }
184  trk->set_num_hits(trkid_hitvec[trkid].size());
185 
186  TVector3 pos;
187  TLorentzVector mom;
188  int detIDs_st1[6] = {3, 4, 2, 5, 1, 6};
189  if(FindHitAtStation(detIDs_st1, trkid, trkid_hitvec[trkid], pos, mom)) {
190  trk->set_pos_st1(pos);
191  trk->set_mom_st1(mom);
192  }
193 
194  int detIDs_st3p[6] = {21, 22, 20, 23, 19, 24};
195  int detIDs_st3m[6] = {27, 28, 26, 29, 25, 30};
196  if(FindHitAtStation(detIDs_st3p, trkid, trkid_hitvec[trkid], pos, mom) ||
197  FindHitAtStation(detIDs_st3m, trkid, trkid_hitvec[trkid], pos, mom)) {
198  trk->set_pos_st3(pos);
199  trk->set_mom_st3(mom);
200  }
201  }
202 
204  if(!m_do_truthtrk_tagging) return Fun4AllReturnCodes::EVENT_OK;
205 
207  int n_rtrks = 0;
208  map<int, vector<int> > rtrkid_hitidvec;
209  if(m_legacy_rec_container) {
210  n_rtrks = m_rec_evt->getNTracks();
211  for(int i = 0; i < n_rtrks; i++) {
212  SRecTrack& recTrack = m_rec_evt->getTrack(i);
213  rtrkid_hitidvec[i] = vector<int>();
214 
215  int n_rhits = recTrack.getNHits();
216  for(int j = 0; j < n_rhits; ++j) {
217  rtrkid_hitidvec[i].push_back(recTrack.getHitIndex(j));
218  }
219 
220  sort(rtrkid_hitidvec[i].begin(), rtrkid_hitidvec[i].end());
221  }
222  } else {
223  n_rtrks = m_vec_rec_trk->size();
224  for(int i = 0; i < n_rtrks; ++i) {
225  SRecTrack* recTrack = dynamic_cast<SRecTrack*>(m_vec_rec_trk->at(i));
226  rtrkid_hitidvec[i] = vector<int>();
227 
228  int n_rhits = recTrack->getNHits();
229  for(int j = 0; j < n_rhits; ++j) {
230  rtrkid_hitidvec[i].push_back(recTrack->getHitIndex(j));
231  }
232 
233  sort(rtrkid_hitidvec[i].begin(), rtrkid_hitidvec[i].end());
234  }
235  }
236  if(n_rtrks <= 0) return Fun4AllReturnCodes::EVENT_OK;
237 
239  map<int, vector<int> > ttrkid_hitidvec;
240  for(auto it = trkid_hitvec.begin(); it != trkid_hitvec.end(); ++it) {
241  ttrkid_hitidvec[it->first] = vector<int>();
242  for(auto jt = it->second.begin(); jt != it->second.end(); ++jt) {
243  ttrkid_hitidvec[it->first].push_back((*jt)->get_hit_id());
244  }
245  sort(ttrkid_hitidvec[it->first].begin(), ttrkid_hitidvec[it->first].end());
246  }
247 
249  for(unsigned int i = 0; i < n_trk; ++i) {
250  SQTrack* trk = m_vec_trk->at(i);
251  int ttrkid = trk->get_track_id();
252 
253  int rtrkid = -1;
254  unsigned int n_match = 0;
255  for(auto it = rtrkid_hitidvec.begin(); it != rtrkid_hitidvec.end(); ++it) {
256  int n_match_new = FindCommonHitIDs(ttrkid_hitidvec[ttrkid], it->second);
257  if(n_match < n_match_new) {
258  n_match = n_match_new;
259  rtrkid = it->first;
260  }
261  }
262 
263  if(rtrkid >= 0 && double(n_match)/double(ttrkid_hitidvec[ttrkid].size()) > m_matching_threshold) {
264  trk->set_rec_track_id(rtrkid);
265  }
266  }
267 
269 }
270 
272 {
274 }
275 
276 int TruthNodeMaker::GetNodes(PHCompositeNode* topNode)
277 {
278  g4true = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
279  if(!g4true) {
280  cerr << Name() << ": failed locating G4TruthInfo, abort" << endl;
282  }
283 
284  m_vec_hit = findNode::getClass<SQHitVector>(topNode, "SQHitVector");
285  if(!m_vec_hit) {
286  cerr << Name() << ": failed locating the digitized hit vector, abort" << endl;
288  }
289 
290  genevtmap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
291  if(!genevtmap) {
292  m_do_evt_header = false;
293  cout << Name() << ": failed locating HepMCGenEvent, event process info will be missing" << endl;
294  }
295 
296  GeomSvc* p_geomSvc = GeomSvc::instance();
297  for(int i = 1; i <= nChamberPlanes; ++i)
298  {
299  string g4hitNodeName = "G4HIT_" + p_geomSvc->getDetectorName(i);
300  m_g4hc[i] = findNode::getClass<PHG4HitContainer>(topNode, g4hitNodeName);
301  }
302 
303  if(m_legacy_rec_container) {
304  m_rec_evt = findNode::getClass<SRecEvent>(topNode, "SRecEvent");
305  if(!m_rec_evt) {
306  m_do_truthtrk_tagging = false;
307  cout << Name() << ": failed locating rec event, no truth track tagging." << endl;
308  }
309  } else {
310  m_vec_rec_trk = findNode::getClass<SQTrackVector>(topNode, "SQRecTrackVector");
311  if(!m_vec_rec_trk) {
312  m_do_truthtrk_tagging = false;
313  cout << Name() << ": failed locating rec track vector, no truth track tagging." << endl;
314  }
315  }
316 
318 }
319 
320 int TruthNodeMaker::MakeNodes(PHCompositeNode* topNode)
321 {
322  PHNodeIterator iter(topNode);
323  PHCompositeNode* node_dst = static_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
324  if (! node_dst) {
325  cout << "No DST node!?" << endl;
327  }
328 
329  m_evt = findNode::getClass<SQEvent>(topNode, "SQEvent");
330  if (! m_evt) {
331  m_evt = new SQEvent_v1();
332  node_dst->addNode(new PHIODataNode<PHObject>(m_evt, "SQEvent", "PHObject"));
333  }
334 
335  m_mcevt = findNode::getClass<SQMCEvent>(topNode, "SQMCEvent");
336  if (! m_mcevt) {
337  m_mcevt = new SQMCEvent_v1();
338  node_dst->addNode(new PHIODataNode<PHObject>(m_mcevt, "SQMCEvent", "PHObject"));
339  }
340 
341  m_vec_trk = findNode::getClass<SQTrackVector>(topNode, "SQTruthTrackVector");
342  if (! m_vec_trk) {
343  m_vec_trk = new SQTrackVector_v1();
344  node_dst->addNode(new PHIODataNode<PHObject>(m_vec_trk, "SQTruthTrackVector", "PHObject"));
345  }
346 
347  m_vec_dim = findNode::getClass<SQDimuonVector>(topNode, "SQTruthDimuonVector");
348  if (! m_vec_dim) {
349  m_vec_dim = new SQDimuonVector_v1();
350  node_dst->addNode(new PHIODataNode<PHObject>(m_vec_dim, "SQTruthDimuonVector", "PHObject"));
351  }
352 
354 }
355 
356 bool TruthNodeMaker::FindHitAtStation(int target_detIDs[], int trkid, const vector<SQHit*>& hitvec, TVector3& pos, TLorentzVector& mom)
357 {
358  for(int i = 0; i < 6; ++i) {
359  //We try to find the wanted hit from SQHitVector first
360  for(unsigned int j = 0; j < hitvec.size(); ++j) {
361  if(hitvec[j]->get_detector_id() == target_detIDs[i]) {
362  pos.SetXYZ(hitvec[j]->get_truth_x(), hitvec[j]->get_truth_y(), hitvec[j]->get_truth_z());
363  mom.SetXYZM(hitvec[j]->get_truth_px(), hitvec[j]->get_truth_py(), hitvec[j]->get_truth_pz(), M_MU);
364  return true;
365  }
366  }
367 
368  //if failed, we resort to the default solution of G4HIT list
369  if(!m_g4hc[target_detIDs[i]]) continue;
370  PHG4HitContainer::ConstRange range = m_g4hc[target_detIDs[i]]->getHits();
371  for(PHG4HitContainer::ConstIterator it = range.first; it != range.second; it++) {
372  PHG4Hit* hit = it->second;
373  if(hit->get_trkid() == trkid) {
374  pos.SetXYZ (hit->get_x(0) , hit->get_y(0) , hit->get_z(0) );
375  mom.SetXYZM(hit->get_px(0), hit->get_py(0), hit->get_pz(0), M_MU);
376  return true;
377  }
378  }
379  }
380  return false;
381 }
382 
383 int TruthNodeMaker::FindCommonHitIDs(vector<int>& hitidvec1, vector<int>& hitidvec2)
384 {
385  //This function assumes the input vectors have been sorted
386  auto iter = hitidvec1.begin();
387  auto jter = hitidvec2.begin();
388 
389  int nCommon = 0;
390  while(iter != hitidvec1.end() && jter != hitidvec2.end()) {
391  if(*iter < *jter) {
392  ++iter;
393  } else {
394  if(!(*jter < *iter)) {
395  ++nCommon;
396  ++iter;
397  }
398  ++jter;
399  }
400  }
401 
402  return nCommon;
403 }
virtual TVector3 get_pos_vtx() const =0
Return the track position at vertex.
virtual float get_x(const int i) const
Definition: PHG4Hit.h:21
int process_event(PHCompositeNode *topNode)
Int_t getNTracks()
Get tracks.
Definition: SRecEvent.h:447
std::string getDetectorName(const int &detectorID) const
Definition: GeomSvc.h:188
virtual float get_pz(const int i) const
Definition: PHG4Hit.h:26
virtual TLorentzVector get_mom_vtx() const =0
Return the track momentum at vertex.
virtual void set_charge(const int a)
Definition: SQTrack_v1.h:22
void set_track_id_neg(const int a)
Definition: SQDimuon_v1.h:28
virtual void set_mom_st3(const TLorentzVector a)=0
virtual size_t size() const =0
size_t size() const
virtual void set_run_id(const int a)=0
virtual double get_x() const
Definition: PHG4VtxPoint.h:20
virtual void set_pos_st3(const TVector3 a)=0
virtual void set_pos_vtx(const TVector3 a)
Definition: SQTrack_v1.h:28
PHBoolean addNode(PHNode *)
virtual int get_trkid() const
Definition: PHG4Hit.h:41
ConstIter begin() const
iterator from lowest ID to highest, i.e. background to signal
virtual HepMC::GenEvent * getEvent()
int Init(PHCompositeNode *topNode)
An SQ interface class to hold one detector hit.
Definition: SQHit.h:20
virtual void set_event_id(const int a)=0
virtual double get_py() const
Definition: PHG4Particle.h:17
virtual void set_num_hits(const int a)=0
void set_track_id_pos(const int a)
Definition: SQDimuon_v1.h:25
Int_t getHitIndex(Int_t i)
Definition: SRecEvent.h:107
int End(PHCompositeNode *topNode)
Called at the end of all processing.
void set_mom(const TLorentzVector a)
Definition: SQDimuon_v1.h:34
virtual void set_mom_vtx(const TLorentzVector a)
Definition: SQTrack_v1.h:37
virtual const SQTrack * at(const size_t id) const =0
Int_t getNHits() const
Definition: SRecEvent.h:101
void set_dimuon_id(const int a)
Definition: SQDimuon_v1.h:16
std::map< int, PHHepMCGenEvent * >::iterator Iter
virtual void set_rec_track_id(const int a)=0
virtual double get_z() const
Definition: PHG4VtxPoint.h:22
virtual void push_back(const SQTrack *trk)=0
virtual const std::string Name() const
Returns the name of this module.
Definition: Fun4AllBase.h:23
virtual void clear()=0
virtual void set_pos_st1(const TVector3 a)=0
virtual void set_particle_id(const int i, const int a)=0
virtual int get_track_id() const
Return the track ID associated with this hit. Probably the value is not properly set at present...
Definition: SQHit.h:66
virtual const SQHit * at(const size_t idkey) const
Definition: SQHitVector.h:53
virtual short get_detector_id() const
Return the detector ID of this hit.
Definition: SQHit.h:42
virtual float get_y(const int i) const
Definition: PHG4Hit.h:22
virtual int get_charge() const =0
Return the charge, i.e. +1 or -1.
void set_mom_neg(const TLorentzVector a)
Definition: SQDimuon_v1.h:40
An SQ interface class to hold one true or reconstructed track.
Definition: SQTrack.h:8
int InitRun(PHCompositeNode *topNode)
virtual int get_pid() const
Definition: PHG4Particle.h:14
std::pair< ConstIterator, ConstIterator > ConstRange
virtual double get_pz() const
Definition: PHG4Particle.h:18
Definition: PHG4Hit.h:9
Map::const_iterator ConstIterator
#define M_MU
Definition: GlobalConsts.h:12
virtual void set_track_id(const int a)
Definition: SQTrack_v1.h:16
virtual void set_particle_momentum(const int i, const TLorentzVector a)=0
virtual void clear()=0
virtual double get_e() const
Definition: PHG4Particle.h:19
virtual float get_z(const int i) const
Definition: PHG4Hit.h:23
virtual int get_track_id() const
Definition: PHG4Particle.h:21
SRecTrack & getTrack(Int_t i)
Definition: SRecEvent.h:448
virtual double get_px() const
Definition: PHG4Particle.h:16
ConstIter end() const
virtual ~TruthNodeMaker()
void set_mom_pos(const TLorentzVector a)
Definition: SQDimuon_v1.h:37
virtual void set_spill_id(const int a)=0
#define nChamberPlanes
Definition: GlobalConsts.h:6
static GeomSvc * instance()
singlton instance
Definition: GeomSvc.cxx:211
virtual size_t size() const
Definition: SQHitVector.h:50
virtual float get_px(const int i) const
Definition: PHG4Hit.h:24
virtual double get_y() const
Definition: PHG4VtxPoint.h:21
virtual void set_process_id(const int a)=0
void set_pos(const TVector3 a)
Definition: SQDimuon_v1.h:31
virtual void push_back(const SQDimuon *dim)=0
virtual int get_vtx_id() const
Definition: PHG4Particle.h:22
virtual int get_track_id() const =0
Return the track ID, which is unique per event(?).
virtual void set_mom_st1(const TLorentzVector a)=0
virtual float get_py(const int i) const
Definition: PHG4Hit.h:25
PHG4VtxPoint * GetVtx(const int vtxid)