Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TpcClusterMover.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TpcClusterMover.cc
1 
7 #include "TpcClusterMover.h"
8 
11 
12 #include <cmath>
13 #include <iostream>
14 #include <climits>
17 
19 {
20  // initialize layer radii
24  for(int i=0; i < 16; ++i)
25  {
27  }
28  for(int i=0; i < 16; ++i)
29  {
31  }
32  for(int i=0; i < 16; ++i)
33  {
35  }
36 }
37 
39 {
40 
41  int layer=0;
43  for (PHG4TpcCylinderGeomContainer::ConstIterator layeriter = layerrange.first;
44  layeriter != layerrange.second;
45  ++layeriter)
46  {
47  layer_radius[layer] = layeriter->second->get_radius();
48  layer++;
49  }
50 
51 }
52 
53 //____________________________________________________________________________..
54 std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> TpcClusterMover::processTrack(std::vector<std::pair<TrkrDefs::cluskey,Acts::Vector3>> global_in )
55 {
56 
57  // Get the global positions of the TPC clusters for this track, already corrected for distortions, and move them to the surfaces
58  // The input object contains all clusters for the track
59 
60  std::vector<std::pair<TrkrDefs::cluskey, Acts::Vector3>> global_moved;
61 
62  std::vector<Acts::Vector3> tpc_global_vec;
63  std::vector<TrkrDefs::cluskey> tpc_cluskey_vec;
64 
65  for(unsigned int i=0; i< global_in.size(); ++i)
66  {
67  TrkrDefs::cluskey cluskey = global_in[i].first;
68  unsigned int trkrid = TrkrDefs::getTrkrId(cluskey);
69  if(trkrid == TrkrDefs::tpcId)
70  {
71  tpc_global_vec.push_back(global_in[i].second);
72  tpc_cluskey_vec.push_back(global_in[i].first);
73  }
74  else
75  {
76  // si clusters stay where they are
77  global_moved.push_back(std::make_pair(cluskey, global_in[i].second));
78  }
79  }
80 
81  // need at least 3 clusters to fit a circle
82  if(tpc_global_vec.size() < 3)
83  {
84  if(_verbosity > 0)
85  { std::cout << " -- skip this tpc track, not enough clusters: " << tpc_global_vec.size() << std::endl; }
86  return global_in;
87  }
88 
89  // fit a circle to the TPC clusters
90  const auto [R, X0, Y0] = TrackFitUtils::circle_fit_by_taubin( tpc_global_vec );
91 
92  // get the straight line representing the z trajectory in the form of z vs radius
93  const auto [A, B] = TrackFitUtils::line_fit( tpc_global_vec );
94 
95  // Now we need to move each TPC cluster associated with this track to the readout layer radius
96  for(unsigned int i=0; i< tpc_global_vec.size(); ++i)
97  {
98  TrkrDefs::cluskey cluskey = tpc_cluskey_vec[i];
99  unsigned int layer = TrkrDefs::getLayer(cluskey);
100  Acts::Vector3 global = tpc_global_vec[i];
101 
102  // get circle position at target surface radius
103  double target_radius = layer_radius[layer-7];
104  int ret = get_circle_circle_intersection(target_radius, R, X0, Y0, global[0], global[1], _x_proj, _y_proj);
105  if(ret == Fun4AllReturnCodes::ABORTEVENT) continue; // skip to next cluster
106  // z projection is unique
107  _z_proj = B + A * target_radius;
108 
109  // get circle position at cluster radius
110  double cluster_radius = sqrt(global[0] * global[0] + global[1] * global[1]);
111  ret = get_circle_circle_intersection(cluster_radius, R, X0, Y0, global[0], global[1], _x_start, _y_start);
112  if(ret == Fun4AllReturnCodes::ABORTEVENT) continue; // skip to next cluster
113  // z projection is unique
114  _z_start = B + A * cluster_radius;
115 
116  // calculate dx, dy, dz along circle trajectory from cluster radius to surface radius
117  double xnew = global[0] - (_x_start - _x_proj);
118  double ynew = global[1] - (_y_start - _y_proj);
119  double znew = global[2] - (_z_start - _z_proj);
120 
121  // now move the cluster to the surface radius
122  // we keep the cluster key fixed, change the surface if necessary
123 
124  Acts::Vector3 global_new(xnew, ynew, znew);
125 
126  // add the new position and surface to the return object
127  global_moved.push_back(std::make_pair(cluskey, global_new));
128  }
129 
130  return global_moved;
131 }
132 
133 int TpcClusterMover::get_circle_circle_intersection(double target_radius, double R, double X0, double Y0, double xclus, double yclus, double &x, double &y)
134 {
135  // finds the intersection of the fitted circle with the cylinder having radius = target_radius
136  const auto [xplus, yplus, xminus, yminus] = TrackFitUtils::circle_circle_intersection(target_radius, R, X0, Y0 );
137 
138  // We only need to check xplus for failure, skip this TPC cluster in that case
139  if(std::isnan(xplus))
140  {
141  {
142  if(_verbosity > 1)
143  {
144  std::cout << " circle/circle intersection calculation failed, skip this cluster" << std::endl;
145  std::cout << " target_radius " << target_radius << " fitted R " << R << " fitted X0 " << X0 << " fitted Y0 " << Y0 << std::endl;
146  }
147  }
148  return Fun4AllReturnCodes::ABORTEVENT; // skip to next cluster
149  }
150 
151  // we can figure out which solution is correct based on the cluster position in the TPC
152  if(fabs(xclus - xplus) < 5.0 && fabs(yclus - yplus) < 5.0) // 5 cm, large and arbitrary
153  {
154  x = xplus;
155  y = yplus;
156  }
157  else
158  {
159  x = xminus;
160  y = yminus;
161  }
163  }