Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DSTEmulator.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DSTEmulator.cc
1 
6 #include "DSTEmulator.h"
7 
8 #include "DSTCompressor.h"
10 
11 #include <g4main/PHG4Hit.h>
13 #include <g4main/PHG4Particle.h>
15 
17 
18 #include <trackbase/InttDefs.h>
19 #include <trackbase/MvtxDefs.h>
20 #include <trackbase/TpcDefs.h>
24 #include <trackbase/TrkrDefs.h>
25 #include <trackbase/TrkrHit.h>
26 #include <trackbase/TrkrHitSet.h>
31 
33 
34 #include <phool/PHCompositeNode.h>
35 #include <phool/PHNodeIterator.h>
36 #include <phool/getClass.h>
37 #include <phool/recoConsts.h>
38 
41 
42 #include <TFile.h>
43 #include <TNtuple.h>
44 
45 #include <algorithm>
46 #include <bitset>
47 #include <cassert>
48 #include <iostream>
49 #include <numeric>
50 
51 //_____________________________________________________________________
52 namespace
53 {
54 
56  template <class T>
57  class range_adaptor
58  {
59  public:
60  explicit range_adaptor(const T& range)
61  : m_range(range)
62  {
63  }
64  inline const typename T::first_type& begin() { return m_range.first; }
65  inline const typename T::second_type& end() { return m_range.second; }
66 
67  private:
68  T m_range;
69  };
70 
72  template <class T>
73  inline constexpr T square(T x)
74  {
75  return x * x;
76  }
77 
79  template <class T>
80  inline constexpr T get_r(T x, T y)
81  {
82  return std::sqrt(square(x) + square(y));
83  }
84 
86  template <class T>
87  T get_pt(T px, T py)
88  {
89  return std::sqrt(square(px) + square(py));
90  }
91 
93  template <class T>
94  T get_p(T px, T py, T pz)
95  {
96  return std::sqrt(square(px) + square(py) + square(pz));
97  }
98 
100  template <class T>
101  T get_eta(T p, T pz)
102  {
103  return std::log((p + pz) / (p - pz)) / 2;
104  }
105 
106  /* //! radius
107  float get_r( PHG4Hit* hit, int i )
108  { return get_r( hit->get_x(i), hit->get_y(i) ); }
109  */
110  /*
112  template< float (PHG4Hit::*accessor)(int) const>
113  float interpolate( std::set<PHG4Hit*> hits, float rextrap )
114  {
115  // calculate all terms needed for the interpolation
116  // need to use double everywhere here due to numerical divergences
117  double sw = 0;
118  double swr = 0;
119  double swr2 = 0;
120  double swx = 0;
121  double swrx = 0;
122 
123  bool valid( false );
124  for( const auto& hit:hits )
125  {
126 
127  const double x0 = (hit->*accessor)(0);
128  const double x1 = (hit->*accessor)(1);
129  if( std::isnan( x0 ) || std::isnan( x1 ) ) continue;
130 
131  const double w = hit->get_edep();
132  if( w < 0 ) continue;
133 
134  valid = true;
135  const double r0 = get_r( hit, 0 );
136  const double r1 = get_r( hit, 1 );
137 
138  sw += w*2;
139  swr += w*(r0 + r1);
140  swr2 += w*(square(r0) + square(r1));
141  swx += w*(x0 + x1);
142  swrx += w*(r0*x0 + r1*x1);
143  }
144 
145  if( !valid ) return NAN;
146 
147  const auto alpha = (sw*swrx - swr*swx);
148  const auto beta = (swr2*swx - swr*swrx);
149  const auto denom = (sw*swr2 - square(swr));
150 
151  return ( alpha*rextrap + beta )/denom;
152  }
153  */
154  /*
156  inline int is_primary( PHG4Particle* particle )
157  { return particle->get_parent_id() == 0; }
158  */
160  int64_t get_mask(SvtxTrack* track)
161  {
162  return std::accumulate(track->begin_cluster_keys(), track->end_cluster_keys(), int64_t(0),
163  [](int64_t value, const TrkrDefs::cluskey& key)
164  {
165  return TrkrDefs::getLayer(key) < 64 ? value | (1ULL << TrkrDefs::getLayer(key)) : value;
166  });
167  }
168 
170  template <int type>
171  int get_clusters(SvtxTrack* track)
172  {
173  return std::count_if(track->begin_cluster_keys(), track->end_cluster_keys(),
174  [](const TrkrDefs::cluskey& key)
175  { return TrkrDefs::getTrkrId(key) == type; });
176  }
177 
180  {
182 
183  trackStruct.charge = track->get_charge();
184  trackStruct.nclusters = track->size_cluster_keys();
185  trackStruct.mask = get_mask(track);
186  trackStruct.nclusters_mvtx = get_clusters<TrkrDefs::mvtxId>(track);
187  trackStruct.nclusters_intt = get_clusters<TrkrDefs::inttId>(track);
188  trackStruct.nclusters_tpc = get_clusters<TrkrDefs::tpcId>(track);
189  trackStruct.nclusters_micromegas = get_clusters<TrkrDefs::micromegasId>(track);
190 
191  trackStruct.chisquare = track->get_chisq();
192  trackStruct.ndf = track->get_ndf();
193 
194  trackStruct.x = track->get_x();
195  trackStruct.y = track->get_y();
196  trackStruct.z = track->get_z();
197  trackStruct.r = get_r(trackStruct.x, trackStruct.y);
198  trackStruct.phi = std::atan2(trackStruct.y, trackStruct.x);
199 
200  trackStruct.px = track->get_px();
201  trackStruct.py = track->get_py();
202  trackStruct.pz = track->get_pz();
203  trackStruct.pt = get_pt(trackStruct.px, trackStruct.py);
204  trackStruct.p = get_p(trackStruct.px, trackStruct.py, trackStruct.pz);
205  trackStruct.eta = get_eta(trackStruct.p, trackStruct.pz);
206 
207  return trackStruct;
208  }
209 #ifdef JUNK
210 
212  {
214  cluster_struct.layer = TrkrDefs::getLayer(key);
215  cluster_struct.x = cluster->getX();
216  cluster_struct.y = cluster->getY();
217  cluster_struct.z = cluster->getZ();
218  cluster_struct.r = get_r(cluster_struct.x, cluster_struct.y);
219  cluster_struct.phi = std::atan2(cluster_struct.y, cluster_struct.x);
220  cluster_struct.phi_error = cluster->getPhiError();
221  cluster_struct.z_error = cluster->getZError();
222  std::cout << " (x|y|z|r|l) "
223  << cluster_struct.x << " | "
224  << cluster_struct.y << " | "
225  << cluster_struct.z << " | "
226  << cluster_struct.r << " | "
227  << cluster_struct.layer << " | "
228  << std::endl;
229  std::cout << " (xl|yl) "
230  << cluster->getLocalX() << " | "
231  << cluster->getLocalY()
232  << std::endl;
233  return cluster_struct;
234  }
235 
237  void add_trk_information(TrackEvaluationContainerv1::ClusterStruct& cluster, SvtxTrackState* state)
238  {
239  // need to extrapolate the track state to the right cluster radius to get proper residuals
240  const auto trk_r = get_r(state->get_x(), state->get_y());
241  const auto dr = cluster.r - trk_r;
242  const auto trk_drdt = (state->get_x() * state->get_px() + state->get_y() * state->get_py()) / trk_r;
243  const auto trk_dxdr = state->get_px() / trk_drdt;
244  const auto trk_dydr = state->get_py() / trk_drdt;
245  const auto trk_dzdr = state->get_pz() / trk_drdt;
246 
247  // store state position
248  cluster.trk_x = state->get_x() + dr * trk_dxdr;
249  cluster.trk_y = state->get_y() + dr * trk_dydr;
250  cluster.trk_z = state->get_z() + dr * trk_dzdr;
251  cluster.trk_r = get_r(cluster.trk_x, cluster.trk_y);
252  cluster.trk_phi = std::atan2(cluster.trk_y, cluster.trk_x);
253 
254  /* store local momentum information */
255  cluster.trk_px = state->get_px();
256  cluster.trk_py = state->get_py();
257  cluster.trk_pz = state->get_pz();
258 
259  /*
260  store state angles in (r,phi) and (r,z) plans
261  they are needed to study space charge distortions
262  */
263  const auto cosphi(std::cos(cluster.trk_phi));
264  const auto sinphi(std::sin(cluster.trk_phi));
265  const auto trk_pphi = -state->get_px() * sinphi + state->get_py() * cosphi;
266  const auto trk_pr = state->get_px() * cosphi + state->get_py() * sinphi;
267  const auto trk_pz = state->get_pz();
268  cluster.trk_alpha = std::atan2(trk_pphi, trk_pr);
269  cluster.trk_beta = std::atan2(trk_pz, trk_pr);
270  cluster.trk_phi_error = state->get_phi_error();
271  cluster.trk_z_error = state->get_z_error();
272  }
273 
275  void add_cluster_size(TrackEvaluationContainerv1::ClusterStruct& cluster, TrkrDefs::cluskey clus_key, TrkrClusterHitAssoc* cluster_hit_map)
276  {
277  if (!cluster_hit_map) return;
278  const auto range = cluster_hit_map->getHits(clus_key);
279 
280  // store full size
281  cluster.size = std::distance(range.first, range.second);
282 
283  const auto detId = TrkrDefs::getTrkrId(clus_key);
284  if (detId == TrkrDefs::micromegasId)
285  {
286  // for micromegas the directional cluster size depends on segmentation type
287  auto segmentation_type = MicromegasDefs::getSegmentationType(clus_key);
288  if (segmentation_type == MicromegasDefs::SegmentationType::SEGMENTATION_Z)
289  cluster.z_size = cluster.size;
290  else
291  cluster.phi_size = cluster.size;
292  }
293  else
294  {
295  // for other detectors, one must loop over the constituting hits
296  std::set<int> phibins;
297  std::set<int> zbins;
298  for (const auto& [first, hit_key] : range_adaptor(range))
299  {
300  switch (detId)
301  {
302  default:
303  break;
304  case TrkrDefs::mvtxId:
305  {
306  phibins.insert(MvtxDefs::getRow(hit_key));
307  zbins.insert(MvtxDefs::getCol(hit_key));
308  break;
309  }
310  case TrkrDefs::inttId:
311  {
312  phibins.insert(InttDefs::getRow(hit_key));
313  zbins.insert(InttDefs::getCol(hit_key));
314  break;
315  }
316  case TrkrDefs::tpcId:
317  {
318  phibins.insert(TpcDefs::getPad(hit_key));
319  zbins.insert(TpcDefs::getTBin(hit_key));
320  break;
321  }
322  }
323  }
324  cluster.phi_size = phibins.size();
325  cluster.z_size = zbins.size();
326  }
327  }
328 
330  void add_cluster_energy(TrackEvaluationContainerv1::ClusterStruct& cluster, TrkrDefs::cluskey clus_key,
331  TrkrClusterHitAssoc* cluster_hit_map,
332  TrkrHitSetContainer* hitsetcontainer)
333  {
334  // check container
335  if (!(cluster_hit_map && hitsetcontainer)) return;
336 
337  // for now this is only filled for micromegas
338  const auto detId = TrkrDefs::getTrkrId(clus_key);
339  if (detId != TrkrDefs::micromegasId) return;
340 
341  const auto hitset_key = TrkrDefs::getHitSetKeyFromClusKey(clus_key);
342  const auto hitset = hitsetcontainer->findHitSet(hitset_key);
343  if (!hitset) return;
344 
345  const auto range = cluster_hit_map->getHits(clus_key);
346  cluster.energy_max = 0;
347  cluster.energy_sum = 0;
348 
349  for (const auto& pair : range_adaptor(range))
350  {
351  const auto hit = hitset->getHit(pair.second);
352  if (hit)
353  {
354  const auto energy = hit->getEnergy();
355  cluster.energy_sum += energy;
356  if (energy > cluster.energy_max) cluster.energy_max = energy;
357  }
358  }
359  }
360 
361  // add truth information
362  void add_truth_information(TrackEvaluationContainerv1::ClusterStruct& cluster, std::set<PHG4Hit*> hits)
363  {
364  // need to extrapolate g4hits position to the cluster r
365  /* this is done by using a linear extrapolation, with a straight line going through all provided G4Hits in and out positions */
366  const auto rextrap = cluster.r;
367  cluster.truth_size = hits.size();
368  std::cout << "inter"
369  << "\n";
370 
371  cluster.truth_x = interpolate<&PHG4Hit::get_x>(hits, rextrap);
372  cluster.truth_y = interpolate<&PHG4Hit::get_y>(hits, rextrap);
373  cluster.truth_z = interpolate<&PHG4Hit::get_z>(hits, rextrap);
374  cluster.truth_r = get_r(cluster.truth_x, cluster.truth_y);
375  cluster.truth_phi = std::atan2(cluster.truth_y, cluster.truth_x);
376 
377  /* add truth momentum information */
378  cluster.truth_px = interpolate<&PHG4Hit::get_px>(hits, rextrap);
379  cluster.truth_py = interpolate<&PHG4Hit::get_py>(hits, rextrap);
380  cluster.truth_pz = interpolate<&PHG4Hit::get_pz>(hits, rextrap);
381 
382  std::cout << "inter2"
383  << "\n";
384 
385  /*
386  store state angles in (r,phi) and (r,z) plans
387  they are needed to study space charge distortions
388  */
389  const auto cosphi(std::cos(cluster.truth_phi));
390  const auto sinphi(std::sin(cluster.truth_phi));
391  const auto truth_pphi = -cluster.truth_px * sinphi + cluster.truth_py * cosphi;
392  const auto truth_pr = cluster.truth_px * cosphi + cluster.truth_py * sinphi;
393 
394  cluster.truth_alpha = std::atan2(truth_pphi, truth_pr);
395  cluster.truth_beta = std::atan2(cluster.truth_pz, truth_pr);
396  if (std::isnan(cluster.truth_alpha) || std::isnan(cluster.truth_beta))
397  {
398  // recalculate
399  double truth_alpha = 0;
400  double truth_beta = 0;
401  double sum_w = 0;
402  for (const auto& hit : hits)
403  {
404  const auto px = hit->get_x(1) - hit->get_x(0);
405  const auto py = hit->get_y(1) - hit->get_y(0);
406  const auto pz = hit->get_z(1) - hit->get_z(0);
407  const auto pphi = -px * sinphi + py * cosphi;
408  const auto pr = px * cosphi + py * sinphi;
409 
410  const auto w = hit->get_edep();
411  if (w < 0) continue;
412 
413  sum_w += w;
414  truth_alpha += w * std::atan2(pphi, pr);
415  truth_beta += w * std::atan2(pz, pr);
416  }
417  truth_alpha /= sum_w;
418  truth_beta /= sum_w;
419  cluster.truth_alpha = truth_alpha;
420  cluster.truth_beta = truth_beta;
421  }
422  }
423 
424  // ad}d truth information
425  void add_truth_information(TrackEvaluationContainerv1::TrackStruct& track, PHG4Particle* particle)
426  {
427  if (particle)
428  {
429  track.is_primary = is_primary(particle);
430  track.pid = particle->get_pid();
431  track.truth_px = particle->get_px();
432  track.truth_py = particle->get_py();
433  track.truth_pz = particle->get_pz();
434  track.truth_pt = get_pt(track.truth_px, track.truth_py);
435  track.truth_p = get_p(track.truth_px, track.truth_py, track.truth_pz);
436  track.truth_eta = get_eta(track.truth_p, track.truth_pz);
437  }
438  }
439 #endif
440 } // namespace
441 
442 //_____________________________________________________________________
444  int inSabotage, bool compress)
445  : SubsysReco(name)
446  , _filename(filename)
447  , _tfile(nullptr)
448  , nBits(inBits)
449  , sabotage(inSabotage)
450  , apply_compression(compress)
451 {
452 }
453 
454 //_____________________________________________________________________
456 {
457  if (_tfile)
458  {
459  delete _tfile;
460  }
461  _tfile = new TFile(_filename.c_str(), "RECREATE");
462 
463  _dst_data = new TNtuple("dst_data", "dst data",
464  "event:seed:"
465  "c3x:c3y:c3z:c3p:t3x:t3y:t3z:"
466  "c2x:c2y:c2r:c2l:t2x:t2y:t2r:t2l:"
467  "d2x:d2y:dr:"
468  "cmp_d2x:cmp_d2y:"
469  "pt:eta:phi:charge");
470 
471  // find DST node
472  PHNodeIterator iter(topNode);
473  auto dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
474  if (!dstNode)
475  {
476  std::cout << "DSTEmulator::Init - DST Node missing" << std::endl;
478  }
479 
480  // get EVAL node
481  iter = PHNodeIterator(dstNode);
482  auto evalNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "EVAL"));
483  if (!evalNode)
484  {
485  // create
486  std::cout << "DSTEmulator::Init - EVAL node missing - creating" << std::endl;
487  evalNode = new PHCompositeNode("EVAL");
488  dstNode->addNode(evalNode);
489  }
490 
491  auto newNode = new PHIODataNode<PHObject>(new TrackEvaluationContainerv1, "TrackEvaluationContainer", "PHObject");
492  evalNode->addNode(newNode);
493 
494  // m_compressor = new DSTCompressor(4.08407e-02,
495  // 7.46530e-02,
496  // 5.14381e-05,
497  // 2.06291e-01,
498  // with new distortion setting
499  // m_compressor = new DSTCompressor(-2.70072e-02,
500  // 2.49574e-02,
501  // 1.12803e-03,
502  // 5.91965e-02,
503  // with mininum layer 7
504  m_compressor = new DSTCompressor(6.96257e-04,
505  3.16806e-02,
506  7.32860e-05,
507  5.93230e-02,
508  nBits,
509  nBits);
511 }
512 
513 //_____________________________________________________________________
515 {
517 }
518 
519 //_____________________________________________________________________
521 {
522  // load nodes
523  auto res = load_nodes(topNode);
524  if (res != Fun4AllReturnCodes::EVENT_OK)
525  {
526  return res;
527  }
528 
529  m_tGeometry = findNode::getClass<ActsGeometry>(topNode,
530  "ActsGeometry");
531  if (!m_tGeometry)
532  {
533  std::cout << PHWHERE
534  << "ActsTrackingGeometry not found on node tree. Exiting"
535  << std::endl;
537  }
538 
539  // cleanup output container
540  if (m_container)
541  {
542  m_container->Reset();
543  }
544 
545  evaluate_tracks();
546 
547  // clear maps
548  m_g4hit_map.clear();
550 }
551 
552 //_____________________________________________________________________
554 {
555  _tfile->cd();
556  _dst_data->Write();
557  _tfile->Close();
558  delete _tfile;
560 }
561 
563 {
564  // get global position from Acts transform
565  Acts::Vector3 globalpos;
566  globalpos = m_tGeometry->getGlobalPosition(key, cluster);
567 
568  // check if TPC distortion correction are in place and apply
569  // if( m_dcc ) { globalpos = m_distortionCorrection.get_corrected_position( globalpos, m_dcc ); }
570 
571  return globalpos;
572 }
573 
574 //_____________________________________________________________________
576 {
577  // get necessary nodes
578  m_track_map = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMapTPCOnly");
579  if (m_track_map)
580  {
581  std::cout << " DSTEmulator: Using TPC Only Track Map node " << std::endl;
582  }
583  else
584  {
585  std::cout << " DSTEmulator: TPC Only Track Map node not found, using default" << std::endl;
586  m_track_map = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
587  }
588  // cluster map
589 
590  m_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "CORRECTED_TRKR_CLUSTER");
591  if (m_cluster_map)
592  {
593  if (m_cluster_map->size() > 0)
594  {
595  std::cout << " DSTEmulator: Using CORRECTED_TRKR_CLUSTER node " << std::endl;
596  }
597  else
598  {
599  std::cout << " DSTEmulator: CORRECTED_TRKR_CLUSTER node not found, using TRKR_CLUSTER" << std::endl;
600  m_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
601  }
602  }
603  else
604  {
605  std::cout << " DSTEmulator: CORRECTED_TRKR_CLUSTER node not found at all, using TRKR_CLUSTER" << std::endl;
606  m_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
607  }
608 
609  // cluster hit association map
610  m_cluster_hit_map = findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
611 
612  // cluster hit association map
613  m_hit_truth_map = findNode::getClass<TrkrHitTruthAssoc>(topNode, "TRKR_HITTRUTHASSOC");
614 
615  // local container
616  m_container = findNode::getClass<TrackEvaluationContainerv1>(topNode, "TrackEvaluationContainer");
617 
618  // hitset container
619  m_hitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
620 
621  // g4hits
622  m_g4hits_tpc = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_TPC");
623  m_g4hits_intt = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_INTT");
624  m_g4hits_mvtx = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MVTX");
625  m_g4hits_micromegas = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MICROMEGAS");
626 
627  // g4 truth info
628  m_g4truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
629 
631 }
632 
633 //_____________________________________________________________________
635 {
637  {
638  return;
639  }
640 
641  int iseed = 0;
643  if (rc->FlagExist("RANDOMSEED"))
644  {
645  iseed = rc->get_IntFlag("RANDOMSEED");
646  }
647 
648  // clear array
650 
651  for (const auto& trackpair : *m_track_map)
652  {
653  const auto track = trackpair.second;
654  auto track_struct = create_track(track);
655 
656  // truth information
657  const auto [id, contributors] = get_max_contributor(track);
658  track_struct.contributors = contributors;
659 
660  // get particle
661  auto particle = m_g4truthinfo->GetParticle(id);
662  track_struct.embed = get_embed(particle);
663  // add_truth_information(track_struct, particle);
664 
665  // running iterator over track states, used to match a given cluster to a track state
666  auto state_iter = track->begin_states();
667 
668  // loop over clusters
669  for (auto key_iter = track->begin_cluster_keys(); key_iter != track->end_cluster_keys(); ++key_iter)
670  {
671  const auto& cluster_key = *key_iter;
672  auto cluster = m_cluster_map->findCluster(cluster_key);
674 
675  if (!cluster)
676  {
677  std::cout << "DSTEmulator::evaluate_tracks - unable to find cluster for key " << cluster_key << std::endl;
678  continue;
679  }
680 
681  if (TrkrDefs::getTrkrId(cluster_key) != TrkrDefs::tpcId)
682  {
683  continue;
684  }
685 
686  // create new cluster struct
687  // auto cluster_struct = create_cluster( cluster_key, cluster );
688 
689  // find track state that is the closest to cluster
690  /* this assumes that both clusters and states are sorted along r */
691  // const auto radius( cluster_struct.r );
692  const Acts::Vector3 globalpos_d = getGlobalPosition(cluster_key, cluster);
693  float radius = get_r(globalpos_d[0], globalpos_d[1]);
694  float clu_phi = std::atan2(globalpos_d[0], globalpos_d[1]);
695  std::cout << "radius " << radius << std::endl;
696  float dr_min = -1;
697  for (auto iter = state_iter; iter != track->end_states(); ++iter)
698  {
699  const auto dr = std::abs(radius - get_r(iter->second->get_x(), iter->second->get_y()));
700  if (dr_min < 0 || dr < dr_min)
701  {
702  state_iter = iter;
703  dr_min = dr;
704  }
705  else
706  {
707  break;
708  }
709  }
710  // Got cluster and got state
711  /*
712  */
713 
714  std::cout << "NEW (xg|yg) "
715  << globalpos_d[0] << " | "
716  << globalpos_d[1]
717  << std::endl;
718  std::cout << "NEW (xl|yl) "
719  << cluster->getLocalX() << " | "
720  << cluster->getLocalY()
721  << std::endl;
722 
723  // state to local
724  // store track state in cluster struct
725  // add_trk_information( cluster_struct, state_iter->second );
726  // void add_trk_information( TrackEvaluationContainerv1::ClusterStruct& cluster, SvtxTrackState* state )
727  // need to extrapolate the track state to the right cluster radius to get proper residuals
728  const auto trk_r = get_r(state_iter->second->get_x(), state_iter->second->get_y());
729  std::cout << " trk_r " << trk_r << std::endl;
730  const auto dr = get_r(globalpos_d[0], globalpos_d[1]) - trk_r;
731  std::cout << " dr " << dr << std::endl;
732  const auto trk_drdt = (state_iter->second->get_x() * state_iter->second->get_px() + state_iter->second->get_y() * state_iter->second->get_py()) / trk_r;
733  std::cout << " trk_drdt " << trk_drdt << std::endl;
734  const auto trk_dxdr = state_iter->second->get_px() / trk_drdt;
735  std::cout << " trk_dxdr " << trk_dxdr << std::endl;
736  const auto trk_dydr = state_iter->second->get_py() / trk_drdt;
737  std::cout << " trk_dydr " << trk_dydr << std::endl;
738  const auto trk_dzdr = state_iter->second->get_pz() / trk_drdt;
739  std::cout << " trk_dzdr " << trk_dzdr << std::endl;
740 
741  // store state position
742  /* */
743  float trk_x = state_iter->second->get_x() + dr * trk_dxdr;
744  float trk_y = state_iter->second->get_y() + dr * trk_dydr;
745  float trk_z = state_iter->second->get_z() + dr * trk_dzdr;
746  std::cout << "trk_x " << state_iter->second->get_x() << "trk_y" << state_iter->second->get_y() << "trk_z " << state_iter->second->get_z() << std::endl;
747  // float trk_r = get_r( trk_x, trk_y );
748  // cluster.trk_phi = std::atan2( cluster.trk_y, cluster.trk_x );
749 
750  /* store local momentum information
751  cluster.trk_px = state->get_px();
752  cluster.trk_py = state->get_py();
753  cluster.trk_pz = state->get_pz();
754  */
755  auto layer = TrkrDefs::getLayer(cluster_key);
756  /*
757  std::cout << " track 3D (x|y|z|r|l) "
758  << trk_x << " | "
759  << trk_y << " | "
760  << trk_z << " | "
761  << trk_r << " | "
762  << layer << " | "
763  << std::endl;
764 
765  std::cout << " cluster 3D (x|y|z|r|l) "
766  << cluster->getX() << " | "
767  << cluster->getY() << " | "
768  << cluster->getZ() << " | "
769  << get_r(cluster->getX() ,cluster->getY() ) << " | "
770  << layer << " | "
771  << std::endl;
772  */
773  // Get Surface
774  Acts::Vector3 global(trk_x, trk_y, trk_z);
775  // TrkrDefs::subsurfkey subsurfkey = cluster->getSubSurfKey();
776 
777  // std::cout << " subsurfkey: " << subsurfkey << std::endl;
778  auto mapIter = m_tGeometry->maps().m_tpcSurfaceMap.find(layer);
779 
780  if (mapIter == m_tGeometry->maps().m_tpcSurfaceMap.end())
781  {
782  std::cout << PHWHERE
783  << "Error: hitsetkey not found in clusterSurfaceMap, layer = " << trk_r // layer
784  << " hitsetkey = "
785  << hitsetkey << std::endl;
786  continue; // nullptr;
787  }
788  std::cout << " g0: " << global[0] << " g1: " << global[1] << " g2:" << global[2] << std::endl;
789  // double global_phi = std::atan2(global[1], global[0]);
790  // double global_z = global[2];
791 
792  // Predict which surface index this phi and z will correspond to
793  // assumes that the vector elements are ordered positive z, -pi to pi, then negative z, -pi to pi
794  std::vector<Surface> surf_vec = mapIter->second;
795 
796  Acts::Vector3 world(globalpos_d[0], globalpos_d[1], globalpos_d[2]);
797  double world_phi = std::atan2(world[1], world[0]);
798  double world_z = world[2];
799 
800  double fraction = (world_phi + M_PI) / (2.0 * M_PI);
801  double rounded_nsurf = round((double) (surf_vec.size() / 2) * fraction - 0.5);
802  unsigned int nsurf = (unsigned int) rounded_nsurf;
803  if (world_z < 0)
804  {
805  nsurf += surf_vec.size() / 2;
806  }
807 
808  Surface surface = surf_vec[nsurf];
809 
811 
812  // no conversion needed, only used in acts
813  // Acts::Vector3 normal = surface->normal(m_tGeometry->getGeoContext());
814  double TrkRadius = std::sqrt(trk_x * trk_x + trk_y * trk_y);
815  double rTrkPhi = TrkRadius * std::atan2(trk_y, trk_x); // trkphi;
816  double surfRadius = std::sqrt(center(0) * center(0) + center(1) * center(1));
817  double surfPhiCenter = std::atan2(center[1], center[0]);
818  double surfRphiCenter = surfPhiCenter * surfRadius;
819  double surfZCenter = center[2];
820 
821  double trklocX = 0;
822  double trklocY = 0;
823  float delta_r = 0;
824 
825  delta_r = TrkRadius - surfRadius;
826  trklocX = rTrkPhi - surfRphiCenter;
827  trklocY = trk_z - surfZCenter;
828  /*
829  std::cout << " clus 2D: (xl|yl) "
830  << cluster->getLocalX() << " | "
831  << cluster->getLocalY()
832  << std::endl;
833 
834  std::cout << " trk 2D: (xl|yl) "
835  << trklocX << " | "
836  << trklocY
837  << std::endl;
838  */
839  float delta_x = trklocX - cluster->getLocalX();
840  float delta_y = trklocY - cluster->getLocalY();
841 
842  float comp_dx = compress_dx(delta_x);
843  float comp_dy = compress_dy(delta_y);
844 
845  // Sabotage the tracking by multiplying the residuals with a random number
846  if (sabotage == -1)
847  {
848  comp_dx = rnd.Uniform(-1, 1) * delta_x;
849  comp_dy = rnd.Uniform(-1, 1) * delta_y;
850  }
851  else if (sabotage == -2)
852  {
853  comp_dx = rnd.Uniform(-10, 10);
854  comp_dy = rnd.Uniform(-10, 10);
855  }
856 
857  /* "dst_data", "dst data","event:seed:"
858  "c3x:c3y:c3z:t3x:t3y:t3z:"
859  "c2x:c2y:c2r:c2l:t2x:t2y:t2r:t2l:"
860  "d2x:d2y:"
861  "cmp_d2x:cmp_d2y:"
862  "pt:eta:phi"
863  */
864  float data[] = {1,
865  (float) iseed,
866  (float) globalpos_d[0],
867  (float) globalpos_d[1],
868  (float) globalpos_d[2],
869  clu_phi,
870  trk_x,
871  trk_y,
872  trk_z,
873  cluster->getLocalX(),
874  cluster->getLocalY(),
875  get_r((float) globalpos_d[0], (float) globalpos_d[1]),
876  (float) layer,
877  (float) trklocX,
878  (float) trklocY,
879  get_r(trk_x, trk_y),
880  (float) layer,
881  delta_x,
882  delta_y,
883  delta_r,
884  comp_dx,
885  comp_dy,
886  track_struct.pt,
887  track_struct.eta,
888  track_struct.phi,
889  (float) track_struct.charge};
890  _dst_data->Fill(data);
891  std::cout << "filled"
892  << "\n";
893 
894  if (apply_compression)
895  {
896  cluster->setLocalX(trklocX - comp_dx);
897  cluster->setLocalY(trklocY - comp_dy);
898  }
899 
900 #ifdef JUNK
901  /*
902  store state angles in (r,phi) and (r,z) plans
903  they are needed to study space charge distortions
904  */
905  /*
906  const auto cosphi( std::cos( cluster.trk_phi ) );
907  const auto sinphi( std::sin( cluster.trk_phi ) );
908  const auto trk_pphi = -state->get_px()*sinphi + state->get_py()*cosphi;
909  const auto trk_pr = state->get_px()*cosphi + state->get_py()*sinphi;
910  const auto trk_pz = state->get_pz();
911  cluster.trk_alpha = std::atan2( trk_pphi, trk_pr );
912  cluster.trk_beta = std::atan2( trk_pz, trk_pr );
913  cluster.trk_phi_error = state->get_phi_error();
914  cluster.trk_z_error = state->get_z_error();
915  */
916 #endif
917  }
918  }
919 
920  std::cout << "DSTEmulator::evaluate_tracks - tracks: " << m_container->tracks().size() << std::endl;
921 }
922 
923 //_____________________________________________________________________
924 float DSTEmulator::compress_dx(float in_val)
925 {
926  unsigned short key = m_compressor->compressPhi(in_val);
927  float out_val = m_compressor->decompressPhi(key);
928  return out_val;
929 }
930 
931 //_____________________________________________________________________
932 float DSTEmulator::compress_dy(float in_val)
933 {
934  unsigned short key = m_compressor->compressZ(in_val);
935  float out_val = m_compressor->decompressZ(key);
936  return out_val;
937 }
938 
939 //_____________________________________________________________________
941 {
942  // check maps
944  {
945  return G4HitSet();
946  }
947 
948  // check if in map
949  auto map_iter = m_g4hit_map.lower_bound(cluster_key);
950  if (map_iter != m_g4hit_map.end() && cluster_key == map_iter->first)
951  {
952  return map_iter->second;
953  }
954 
955  // find hitset associated to cluster
956  G4HitSet out;
957  const auto hitset_key = TrkrDefs::getHitSetKeyFromClusKey(cluster_key);
958  for (const auto& [first, hit_key] : range_adaptor(m_cluster_hit_map->getHits(cluster_key)))
959  {
960  // store hits to g4hit associations
961  TrkrHitTruthAssoc::MMap g4hit_map;
962  m_hit_truth_map->getG4Hits(hitset_key, hit_key, g4hit_map);
963 
964  // find corresponding g4 hist
965  for (auto& truth_iter : g4hit_map)
966  {
967  const auto g4hit_key = truth_iter.second.second;
968  PHG4Hit* g4hit = nullptr;
969 
970  switch (TrkrDefs::getTrkrId(hitset_key))
971  {
972  case TrkrDefs::mvtxId:
973  if (m_g4hits_mvtx)
974  {
975  g4hit = m_g4hits_mvtx->findHit(g4hit_key);
976  }
977  break;
978 
979  case TrkrDefs::inttId:
980  if (m_g4hits_intt)
981  {
982  g4hit = m_g4hits_intt->findHit(g4hit_key);
983  }
984  break;
985 
986  case TrkrDefs::tpcId:
987  if (m_g4hits_tpc)
988  {
989  g4hit = m_g4hits_tpc->findHit(g4hit_key);
990  }
991  break;
992 
995  {
996  g4hit = m_g4hits_micromegas->findHit(g4hit_key);
997  }
998  break;
999 
1000  default:
1001  break;
1002  }
1003 
1004  if (g4hit)
1005  {
1006  out.insert(g4hit);
1007  }
1008  else
1009  {
1010  std::cout << "DSTEmulator::find_g4hits - g4hit not found " << g4hit_key << std::endl;
1011  }
1012  }
1013  }
1014 
1015  // insert in map and return
1016  return m_g4hit_map.insert(map_iter, std::make_pair(cluster_key, std::move(out)))->second;
1017 }
1018 
1019 //_____________________________________________________________________
1020 std::pair<int, int> DSTEmulator::get_max_contributor(SvtxTrack* track) const
1021 {
1023  {
1024  return {0, 0};
1025  }
1026 
1027  // maps MC track id and number of matching g4hits
1028  using IdMap = std::map<int, int>;
1029  IdMap contributor_map;
1030 
1031  // loop over clusters
1032  for (auto key_iter = track->begin_cluster_keys(); key_iter != track->end_cluster_keys(); ++key_iter)
1033  {
1034  const auto& cluster_key = *key_iter;
1035  for (const auto& hit : find_g4hits(cluster_key))
1036  {
1037  const int trkid = hit->get_trkid();
1038  auto iter = contributor_map.lower_bound(trkid);
1039  if (iter == contributor_map.end() || iter->first != trkid)
1040  {
1041  contributor_map.insert(iter, std::make_pair(trkid, 1));
1042  }
1043  else
1044  {
1045  ++iter->second;
1046  }
1047  }
1048  }
1049 
1050  if (contributor_map.empty())
1051  {
1052  return {0, 0};
1053  }
1054  else
1055  {
1056  return *std::max_element(
1057  contributor_map.cbegin(), contributor_map.cend(),
1058  [](const IdMap::value_type& first, const IdMap::value_type& second)
1059  { return first.second < second.second; });
1060  }
1061 }
1062 
1063 //_____________________________________________________________________
1065 {
1066  return (m_g4truthinfo && particle) ? m_g4truthinfo->isEmbeded(particle->get_primary_id()) : 0;
1067 }