Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackSeed_v1.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrackSeed_v1.cc
1 #include "TrackSeed_v1.h"
3 
5 
6 #include <cmath>
7 
8 namespace
9 {
10 
12  template <class T>
13  inline constexpr T square(const T& x)
14  {
15  return x * x;
16  }
17 } // namespace
18 
19 TrackSeed_v1::TrackSeed_v1() = default;
20 
22 {
24 }
25 
26 // have to suppress missingMemberCopy from cppcheck, it does not
27 // go down to the CopyFrom method where things are done correctly
28 // cppcheck-suppress missingMemberCopy
30  : TrackSeed(seed)
31 {
33 }
34 
36 {
37  if (this != &seed)
38  {
39  CopyFrom(seed);
40  }
41  return *this;
42 }
43 
44 TrackSeed_v1::~TrackSeed_v1() = default;
45 
47 {
48  if (this == &seed)
49  {
50  return;
51  }
52  TrackSeed::CopyFrom(seed);
53 
54  m_qOverR = seed.get_qOverR();
55  m_X0 = seed.get_X0();
56  m_Y0 = seed.get_Y0();
57  m_slope = seed.get_slope();
58  m_Z0 = seed.get_Z0();
59  m_crossing = seed.get_crossing();
60 
61  m_cluster_keys.clear();
62  std::copy(seed.begin_cluster_keys(), seed.end_cluster_keys(),
63  std::inserter(m_cluster_keys, m_cluster_keys.begin()));
64 }
65 
66 void TrackSeed_v1::identify(std::ostream& os) const
67 {
68  os << "TrackSeed_v1 object ";
69  os << "charge " << get_charge() << std::endl;
70  os << "(pt,pz) = (" << get_pt()
71  << ", " << get_pz() << ")" << std::endl;
72  os << "(x,y,z) = (" << get_x() << ", " << get_y() << ", " << get_z()
73  << ")" << std::endl;
74  os << "(X0,Y0,Z0) = (" << m_X0 << ", " << m_Y0 << ", " << m_Z0
75  << ")" << std::endl;
76  os << "R and slope " << fabs(1. / m_qOverR) << ", " << m_slope << std::endl;
77  os << "list of cluster keys size: " << m_cluster_keys.size() << std::endl;
78  ;
79  if (m_cluster_keys.size() > 0)
80  {
82  iter != end_cluster_keys();
83  ++iter)
84  {
85  TrkrDefs::cluskey cluster_key = *iter;
86  os << cluster_key << ", ";
87  }
88  }
89 
90  os << std::endl;
91  return;
92 }
93 
96  uint8_t startLayer,
97  uint8_t endLayer)
98 {
99  std::map<TrkrDefs::cluskey, Acts::Vector3> positions;
100 
101  for (const auto& key : m_cluster_keys)
102  {
103  auto layer = TrkrDefs::getLayer(key);
104  if (layer < startLayer or layer > endLayer)
105  {
106  continue;
107  }
108 
109  auto clus = clusters->findCluster(key);
110 
111  if (clus->getEdge() > 0)
112  {
113  continue;
114  }
115  Acts::Vector3 pos = tGeometry->getGlobalPosition(
116  key, clus);
117 
118  positions.insert(std::make_pair(key, pos));
119  }
120  if (positions.size() < 3)
121  {
122  return;
123  }
124 
125  circleFitByTaubin(positions, startLayer, endLayer);
126 }
127 
130  uint8_t startLayer,
131  uint8_t endLayer)
132 {
133  std::map<TrkrDefs::cluskey, Acts::Vector3> positions;
134 
135  for (const auto& key : m_cluster_keys)
136  {
137  auto layer = TrkrDefs::getLayer(key);
138  if (layer < startLayer or layer > endLayer)
139  {
140  continue;
141  }
142 
143  Acts::Vector3 pos = tGeometry->getGlobalPosition(
144  key, clusters->findCluster(key));
145 
146  positions.insert(std::make_pair(key, pos));
147  }
148 
149  lineFit(positions, startLayer, endLayer);
150 }
151 
152 void TrackSeed_v1::circleFitByTaubin(std::map<TrkrDefs::cluskey, Acts::Vector3>& positions,
153  uint8_t startLayer,
154  uint8_t endLayer)
155 {
157  for (const auto& key : m_cluster_keys)
158  {
159  const auto layer = TrkrDefs::getLayer(key);
160  if (layer < startLayer or layer > endLayer)
161  {
162  continue;
163  }
164 
165  const auto iter = positions.find(key);
166 
168  if (iter == positions.end())
169  {
170  continue;
171  }
172 
173  // add to 2d position list
174  const Acts::Vector3& pos = iter->second;
175  positions_2d.emplace_back(pos.x(), pos.y());
176  }
177 
178  // do the fit
179  const auto [r, x0, y0] = TrackFitUtils::circle_fit_by_taubin(positions_2d);
180 
181  // assign
182  m_X0 = x0;
183  m_Y0 = y0;
184  m_qOverR = 1. / r;
185 
187  const auto& firstpos = positions_2d.at(0);
188  const auto& secondpos = positions_2d.at(1);
189 
190  const auto firstphi = atan2(firstpos.second, firstpos.first);
191  const auto secondphi = atan2(secondpos.second, secondpos.first);
192  auto dphi = secondphi - firstphi;
193  if (dphi > M_PI)
194  {
195  dphi = 2. * M_PI - dphi;
196  }
197  if (dphi < -M_PI)
198  {
199  dphi = 2 * M_PI + dphi;
200  }
201  if (dphi > 0)
202  {
203  m_qOverR *= -1;
204  }
205 }
206 
207 void TrackSeed_v1::lineFit(std::map<TrkrDefs::cluskey, Acts::Vector3>& positions,
208  uint8_t startLayer,
209  uint8_t endLayer)
210 {
212  for (const auto& key : m_cluster_keys)
213  {
214  const auto layer = TrkrDefs::getLayer(key);
215  if (layer < startLayer or layer > endLayer)
216  {
217  continue;
218  }
219 
220  const auto iter = positions.find(key);
221 
223  if (iter == positions.end())
224  {
225  continue;
226  }
227 
228  // store (r,z)
229  const Acts::Vector3& pos = iter->second;
230  positions_2d.emplace_back(std::sqrt(square(pos.x()) + square(pos.y())), pos.z());
231  }
232 
233  // do the fit
234  const auto [slope, intercept] = TrackFitUtils::line_fit(positions_2d);
235 
236  // assign
237  m_slope = slope;
238  m_Z0 = intercept;
239 }
240 
241 std::pair<float, float> TrackSeed_v1::findRoot() const
242 {
255  const float R = std::abs(1. / m_qOverR);
256  const double miny = (std::sqrt(square(m_X0) * square(R) * square(m_Y0) + square(R) * pow(m_Y0, 4)) + square(m_X0) * m_Y0 + pow(m_Y0, 3)) / (square(m_X0) + square(m_Y0));
257 
258  const double miny2 = (-std::sqrt(square(m_X0) * square(R) * square(m_Y0) + square(R) * pow(m_Y0, 4)) + square(m_X0) * m_Y0 + pow(m_Y0, 3)) / (square(m_X0) + square(m_Y0));
259 
260  const double minx = std::sqrt(square(R) - square(miny - m_Y0)) + m_X0;
261  const double minx2 = -std::sqrt(square(R) - square(miny2 - m_Y0)) + m_X0;
262 
264  const float x = (std::abs(minx) < std::abs(minx2)) ? minx : minx2;
265  const float y = (std::abs(miny) < std::abs(miny2)) ? miny : miny2;
266  return std::make_pair(x, y);
267 }
268 
269 float TrackSeed_v1::get_x() const
270 {
271  return findRoot().first;
272 }
273 
274 float TrackSeed_v1::get_y() const
275 {
276  return findRoot().second;
277 }
278 
279 float TrackSeed_v1::get_z() const
280 {
281  return get_Z0();
282 }
283 
284 float TrackSeed_v1::get_pt() const
285 {
287  return 0.3 * 1.4 / 100. * fabs(1. / m_qOverR);
288 }
289 float TrackSeed_v1::get_phi(std::map<TrkrDefs::cluskey, Acts::Vector3>& positions) const
290 {
291  const auto [x, y] = findRoot();
292  float phi = std::atan2(-1 * (m_X0 - x), (m_Y0 - y));
293  Acts::Vector3 pos0 = positions.find(*(m_cluster_keys.begin()))->second;
294  Acts::Vector3 pos1 = positions.find(*(std::next(m_cluster_keys.begin(), 1)))->second;
296  // we need to know if the track proceeds clockwise or CCW around the circle
297  double dx0 = pos0(0) - m_X0;
298  double dy0 = pos0(1) - m_Y0;
299  double phi0 = atan2(dy0, dx0);
300  double dx1 = pos1(0) - m_X0;
301  double dy1 = pos1(1) - m_Y0;
302  double phi1 = atan2(dy1, dx1);
303  double dphi = phi1 - phi0;
304 
305  // need to deal with the switch from -pi to +pi at phi = 180 degrees
306  // final phi - initial phi must be < 180 degrees for it to be a valid track
307  if (dphi > M_PI)
308  {
309  dphi -= 2.0 * M_PI;
310  }
311  if (dphi < -M_PI)
312  {
313  dphi += M_PI;
314  }
315 
316  // whether we add 180 degrees depends on the angle of the bend
317  if (dphi < 0)
318  {
319  phi += M_PI;
320  if (phi > M_PI)
321  {
322  phi -= 2. * M_PI;
323  }
324  }
325 
326  return phi;
327 }
329  ActsGeometry* tGeometry) const
330 {
331  auto clus1 = clusters->findCluster(*(m_cluster_keys.begin()));
332  auto key = *std::next(m_cluster_keys.begin(), 1);
333  auto clus2 = clusters->findCluster(key);
334  if (!clus1 or !clus2)
335  {
336  return NAN;
337  }
338 
339  Acts::Vector3 pos0 = tGeometry->getGlobalPosition(
340  *(m_cluster_keys.begin()),
341  clus1);
342 
343  Acts::Vector3 pos1 = tGeometry->getGlobalPosition(key, clus2);
344  std::map<TrkrDefs::cluskey, Acts::Vector3> positions;
345  positions.insert(std::make_pair(*(m_cluster_keys.begin()), pos0));
346  positions.insert(std::make_pair(key, pos1));
347  return get_phi(positions);
348 }
349 
351 {
352  float theta = atan(1. / m_slope);
354  if (theta < 0)
355  {
356  theta += M_PI;
357  }
358  return theta;
359 }
360 
362 {
363  return -log(tan(get_theta() / 2.));
364 }
365 
366 float TrackSeed_v1::get_p() const
367 {
368  return get_pt() * std::cosh(get_eta());
369 }
370 
372  ActsGeometry* tGeometry) const
373 {
374  return get_pt() * std::cos(get_phi(clusters, tGeometry));
375 }
376 
378  ActsGeometry* tGeometry) const
379 {
380  return get_pt() * std::sin(get_phi(clusters, tGeometry));
381 }
382 
383 float TrackSeed_v1::get_pz() const
384 {
385  return get_p() * std::cos(get_theta());
386 }
387 
389 {
390  return (m_qOverR < 0) ? -1 : 1;
391 }