Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHSiliconTruthTrackSeeding.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHSiliconTruthTrackSeeding.cc
2 
6 
8 
12 #include <trackbase/TrkrDefs.h>
14 
15 #include <g4eval/SvtxClusterEval.h>
16 #include <g4eval/SvtxEvalStack.h>
17 #include <g4eval/SvtxEvaluator.h>
18 #include <g4eval/SvtxTrackEval.h>
19 
20 #include <g4main/PHG4Hit.h> // for PHG4Hit
21 #include <g4main/PHG4Particle.h> // for PHG4Particle
23 #include <g4main/PHG4HitDefs.h> // for keytype
25 
27 
28 #include <phool/getClass.h>
29 #include <phool/phool.h>
30 
31 #include <cstdlib> // for exit
32 #include <iostream> // for operator<<, endl
33 #include <map> // for multimap, map<>::c...
34 #include <memory>
35 #include <utility> // for pair
36 #include <cassert>
37 #include <set>
38 
39 #define LogDebug(exp) std::cout << "DEBUG: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
40 #define LogError(exp) std::cout << "ERROR: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
41 #define LogWarning(exp) std::cout << "WARNING: " << __FILE__ << ": " << __LINE__ << ": " << exp << std::endl
42 
43 class PHCompositeNode;
44 
45 namespace
46 {
47  template<class T> inline constexpr T square( const T& x ) { return x*x; }
48 }
49 
50 using namespace std;
51 
53  : PHTrackSeeding(name)
54 {
55  // we use a separate track map node for the silicon track stubs
56  // std::string track_map_node_name = {"SvtxSiliconTrackMap"};
57  // set_track_map_name(track_map_node_name);
58 }
59 
61 {
62  if(Verbosity() > 0)
63  std::cout << "Enter PHSiliconTruthTrackSeeding:: Setup" << std::endl;
64 
65  // we use a separate track map node for the silicon track stubs
66  std::string track_map_node_name = {"SvtxSiliconTrackMap"};
67  set_track_map_name(track_map_node_name);
68 
69  int ret = PHTrackSeeding::Setup(topNode);
70  if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
71 
72  // ret = GetNodes(topNode);
73  // if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
74 
76 }
77 
79 {
80  // We start with all reco clusters in the silicon layers
81  // get the associated truth g4hits and from that the g4particle
82  // make a map of <g4particle, clusters>
83  // Make an SvtxTrack in silicon from g4particle
84  // get momentum from truth
85  // get position from vertex
86  // add clusters to it
87  // Add the track to SvtxSiliconTrackMap
88 
89  using TrkrClusterSet = std::set<TrkrDefs::cluskey>;
90  using TrkClustersMap = std::map<int, TrkrClusterSet>;
91  TrkClustersMap m_trackID_clusters;
92 
93  // loop over all clusters
94  for(const auto& hitsetkey:_cluster_map->getHitSetKeys())
95  {
96  auto range = _cluster_map->getClusters(hitsetkey);
97  for( auto clusIter = range.first; clusIter != range.second; ++clusIter )
98  {
99  // TrkrCluster* cluster = clusIter->second;
100  TrkrDefs::cluskey cluskey = clusIter->first;
101  unsigned int trkrid = TrkrDefs::getTrkrId(cluskey);
102 
103  if(trkrid != TrkrDefs::mvtxId && trkrid != TrkrDefs::inttId) continue;
104 
105  unsigned int layer = TrkrDefs::getLayer(cluskey);
106  if(layer > 6)
107  std::cout << PHWHERE << " Warning: layer is screwed up - layer = " << layer << std::endl;
108 
109  if (Verbosity() >= 3)
110  {
111  std::cout << PHWHERE <<" process cluster " << cluskey << std::endl;
112  }
113 
114  // get the hits for this cluster
115  const auto hitrange = clusterhitassoc->getHits(cluskey); // returns range of pairs {cluster key, hit key} for this cluskey
116  //for (TrkrClusterHitAssoc::ConstIterator clushititer = hitrange.first; clushititer != hitrange.second; ++clushititer)
117  for (auto clushititer = hitrange.first; clushititer != hitrange.second; ++clushititer)
118  {
119  TrkrDefs::hitkey hitkey = clushititer->second;
120  // TrkrHitTruthAssoc uses a map with (hitsetkey, std::pair(hitkey, g4hitkey)) - get the hitsetkey from the cluskey
122 
123  if (Verbosity() >= 3)
124  {
125  cout << PHWHERE <<" --- process hit with hitkey " << hitkey << " hitsetkey " << hitsetkey << std::endl;
126  }
127 
128  // get all of the g4hits for this hitkey
129  std::multimap<TrkrDefs::hitsetkey, std::pair<TrkrDefs::hitkey, PHG4HitDefs::keytype> > temp_map;
130  hittruthassoc->getG4Hits(hitsetkey, hitkey, temp_map); // returns pairs (hitsetkey, std::pair(hitkey, g4hitkey)) for this hitkey only
131  for( auto htiter = temp_map.begin(); htiter != temp_map.end(); ++htiter)
132  {
133  // extract the g4 hit key here and add the hits to the set
134  PHG4HitDefs::keytype g4hitkey = htiter->second.second;
135 
136  if (Verbosity() >= 3)
137  {
138  cout << PHWHERE <<" --- process g4hit with key " << g4hitkey << std::endl;
139  }
140 
141  PHG4Hit* phg4hit = nullptr;
142  switch( trkrid )
143  {
144  case TrkrDefs::mvtxId:
145  if (phg4hits_mvtx) phg4hit = phg4hits_mvtx->findHit( g4hitkey );
146  break;
147 
148  case TrkrDefs::inttId:
149  if (phg4hits_intt) phg4hit = phg4hits_intt->findHit( g4hitkey );
150  break;
151  }
152 
153  if( !phg4hit )
154  {
155  std::cout<<PHWHERE<<" unable to find g4hit from key " << g4hitkey << std::endl;
156  continue;
157  }
158 
159  int particle_id = phg4hit->get_trkid();
160 
161  // momentum cut-off
162  if (_min_momentum>0)
163  {
165  if (!particle)
166  {
167  cout << PHWHERE <<" - validity check failed: missing truth particle with ID of "<<particle_id<<". Exiting..."<<endl;
168  exit(1);
169  }
170  const double monentum2 =
171  square( particle->get_px() )
172  + square( particle->get_py() )
173  + square( particle->get_pz() );
174 
175  if (Verbosity() >= 10)
176  {
177  cout << PHWHERE <<" --- check momentum for g4particle "<<particle_id<<" -> cluster "<<cluskey
178  <<" = "<<sqrt(monentum2)<<endl;;
179  particle->identify();
180  }
181 
182  if (monentum2 < _min_momentum * _min_momentum)
183  {
184  if (Verbosity() >= 3)
185  {
186  cout << PHWHERE <<" ignore low momentum g4particle "<<particle_id<<" -> cluster "<<cluskey<<endl;;
187  particle->identify();
188  }
189  continue;
190  }
191  }
192 
193  // add or append this particle/cluster combination to the map
194  TrkClustersMap::iterator it = m_trackID_clusters.find(particle_id);
195 
196  if (it != m_trackID_clusters.end())
197  {
198  // the clusters are stored in a set, no need to check if it is in there already
199  it->second.insert(cluskey);
200  if (Verbosity() >= 3)
201  {
202  cout << PHWHERE <<" --- appended to g4particle"<<particle_id<<" new cluster "<<cluskey<<endl;;
203  //cluster->identify();
204  }
205  }
206  else
207  {
208  m_trackID_clusters.insert(std::make_pair(particle_id, TrkrClusterSet({cluskey})));
209 
210  if (Verbosity() >= 3)
211  {
212  cout << PHWHERE <<" --- added new g4particle "<<particle_id<<" and inserted cluster "<<cluskey<<endl;;
213  //cluster->identify();
214  }
215 
216  }
217  } // loop over g4hits associated with hit
218  } // loop over hits associated with cluster
219  } // loop over clusters
220  } // loop over hitsets
221  //==================================
222  // make the tracks
223 
224  if (Verbosity() >= 2)
225  {
226  cout <<__PRETTY_FUNCTION__
227  <<" Beginning _track_map->size = "<<_track_map->size()<<endl;
228 
230  }
231 
232  // Build tracks, looping over assembled list of truth track ID's and associated reco clusters
233  for (const auto& [id, cluster_keyset] : m_trackID_clusters )
234  {
235  if( cluster_keyset.size() < _min_clusters_per_track) continue;
236 
237  // check number of layers also pass the _min_clusters_per_track cut to avoid tight loopers
238  set<uint8_t> layers;
239  for( const auto& key : cluster_keyset)
240  {
241  const uint8_t layer = TrkrDefs::getLayer(key);
242  layers.insert(layer);
243  }
244  if (Verbosity()>2)
245  {
246  cout <<__PRETTY_FUNCTION__<<" particle "<<id<<" -> "
247  <<cluster_keyset.size()<<" clusters covering "<<layers.size()<<" layers."
248  <<" Layer/clusters cuts are > "<<_min_clusters_per_track
249  <<endl;
250  }
251 
252  if (layers.size() >= _min_clusters_per_track)
253  {
254 
255  auto svtx_track = std::make_unique<TrackSeed_FastSim_v1>();
256  svtx_track->set_truth_track_id(id);
257 
258  // assign truth particle vertex ID to this silicon track stub
260  int vertexId = particle->get_vtx_id() - 1; // Geant likes to count from 1 for both vertex and g4particle ID, _vertex_map counts from 0
261  if(vertexId < 0)
262  {
263  // Secondary particle, will have the same gembed value as the corresponding primary vertex
264  int track_embed = _g4truth_container->isEmbeded(id);
265  auto vrange = _g4truth_container->GetPrimaryVtxRange();
266  for (auto iter = vrange.first; iter != vrange.second; ++iter) // all primary vertexes
267  {
268  const int point_id = iter->first;
269  int vert_embed = _g4truth_container->isEmbededVtx(point_id);
270  if(vert_embed == track_embed)
271  vertexId = point_id - 1; // Geant starts counting vertices at 1
272  if(Verbosity() > 3)
273  std::cout << " track_embed " << track_embed << " vert_embed " << vert_embed << " G4 point id " << point_id << " SvtxMap vertexId " << vertexId << std::endl;
274  }
275  }
276  if(vertexId < 0) // should not be possible
277  vertexId = 0;
278 
279  if(Verbosity() > 0)
280  std::cout << " truth track G4 point id " << particle->get_vtx_id() << " becomes SvtxMap id " << vertexId
281  << " gembed is " << _g4truth_container->isEmbeded(id) << " for truth particle " << id << std::endl;
282 
283  // set the track position to the vertex position
284  const SvtxVertex *svtxVertex = _vertex_map->get(vertexId);
285  if(!svtxVertex)
286  {
287  std::cout << PHWHERE << "Failed to get vertex with ID " << vertexId << " from _vertex_map, cannot proceed - skipping this silicon track" << std::endl;
288  continue;
289  }
290 
291  svtx_track->set_X0(svtxVertex->get_x());
292  svtx_track->set_Y0(svtxVertex->get_y());
293  svtx_track->set_Z0(svtxVertex->get_z());
294 
295  if(Verbosity() > 0)
296  {
297  std::cout << " truth track SvtxMap vertexid is " << vertexId << " for truth particle " << id << std::endl;
298  std::cout << " track position x,y,z = " << svtxVertex->get_x() << ", " << svtxVertex->get_y() << ", " << svtxVertex->get_z() << std::endl;
299  }
300 
301  // set momentum to the truth value
302 
303  float px = particle->get_px();
304  float py = particle->get_py();
305  float pz = particle->get_pz();
306  float pt = sqrt(px*px+py*py);
307  int charge = particle->get_pid() < 0 ? -1 : 1;
308  float eta = atanh(pz/sqrt(px*px+py*py+pz*pz));
309  float theta = 2*atan(exp(-1*eta));
310  svtx_track->set_qOverR(charge * 0.3*1.4/(100*pt));
311  svtx_track->set_slope(1./tan(theta));
312 
313  if(Verbosity() > 0)
314  std::cout << PHWHERE << "Truth track ID is " << svtx_track->get_truth_track_id() << " particle ID is " << particle->get_pid() << std::endl;
315 
316  // add the silicon clusters
317  for(const auto& key:cluster_keyset)
318  {
319  svtx_track->insert_cluster_key(key);
320  }
321 
322  _track_map->insert(svtx_track.get());
323 
324  if (Verbosity() >= 2)
325  {
326  cout <<__PRETTY_FUNCTION__<<" particle "<<id<<" -> "
327  <<cluster_keyset.size()<<" clusters"
328  <<" _track_map->size = "<< (_track_map->size()) <<": ";
329  _track_map->identify();
330  }
331  }
332  }
333 
334  if (Verbosity() >= 2)
335  {
336  cout << "Loop over SvtxSiliconTrackMap entries " << endl;
337  int id = 0;
339  iter != _track_map->end(); ++iter)
340  {
341  auto svtx_track = *iter;
342 
343  cout << "Track ID: " << id << ", Track pT: "
344  << svtx_track->get_pt() << ", Truth Track/Particle ID: "
345  << svtx_track->get_truth_track_id() << endl;
346  cout << " (pt, pz) = " << "("<< svtx_track->get_pt() << ", " << svtx_track->get_pz() << ")" << endl;
347  cout << " (x, y, z) = " << "("<< svtx_track->get_x() << ", " << svtx_track->get_y() << ", " << svtx_track->get_z() << ")" << endl;
348 
349  id++;
350 
351  //Print associated clusters;
353  svtx_track->begin_cluster_keys();
354  iter != svtx_track->end_cluster_keys(); ++iter)
355  {
356  TrkrDefs::cluskey cluster_key = *iter;
357  TrkrCluster* cluster = _cluster_map->findCluster(cluster_key);
358  float radius = sqrt(
359  cluster->getX() * cluster->getX() + cluster->getY() * cluster->getY());
360  cout << " cluster ID: "
361  << cluster_key << ", cluster radius: " << radius
362  << endl;
363  }
364  }
365  }
366  //==================================
367 
369 }
370 
372 {
373  /*
374  // If the _use_truth_clusters flag is set, the cluster map now points to the truth clusters
375  // in this module we want to use the reco silicon clusters instead, so we move the pointer
376  if(_use_truth_clusters)
377  _cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
378 
379  if (!_cluster_map)
380  {
381  cerr << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << endl;
382  return Fun4AllReturnCodes::ABORTEVENT;
383  }
384  */
385 
386  _g4truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
387  if (!_g4truth_container)
388  {
389  cerr << PHWHERE << " ERROR: Can't find node G4TruthInfo" << endl;
391  }
392 
393  clusterhitassoc = findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
394  if (!clusterhitassoc)
395  {
396  cout << PHWHERE << "Failed to find TRKR_CLUSTERHITASSOC node, quit!" << endl;
397  exit(1);
398  }
399 
400  hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode, "TRKR_HITTRUTHASSOC");
401  if (!hittruthassoc)
402  {
403  cout << PHWHERE << "Failed to find TRKR_HITTRUTHASSOC node, quit!" << endl;
404  exit(1);
405  }
406 
407  using nodePair = std::pair<std::string, PHG4HitContainer*&>;
408  std::initializer_list<nodePair> nodes =
409  {
410  { "G4HIT_TPC", phg4hits_tpc },
411  { "G4HIT_INTT", phg4hits_intt },
412  { "G4HIT_MVTX", phg4hits_mvtx },
413  { "G4HIT_MICROMEGAS", phg4hits_micromegas }
414  };
415 
416  for( auto&& node: nodes )
417  {
418  if( !( node.second = findNode::getClass<PHG4HitContainer>( topNode, node.first ) ) )
419  { std::cerr << PHWHERE << " PHG4HitContainer " << node.first << " not found" << std::endl; }
420  }
421 
423 }
424 
426 {
427  return 0;
428 }