ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Seedfinder.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Seedfinder.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <cmath>
10 #include <numeric>
11 #include <type_traits>
12 
14 
15 namespace Acts {
16 
17 template <typename external_spacepoint_t>
20  : m_config(std::move(config)) {
21  // calculation of scattering using the highland formula
22  // convert pT to p once theta angle is known
23  m_config.highland = 13.6 * std::sqrt(m_config.radLengthPerSeed) *
24  (1 + 0.038 * std::log(m_config.radLengthPerSeed));
25  float maxScatteringAngle = m_config.highland / m_config.minPt;
26  m_config.maxScatteringAngle2 = maxScatteringAngle * maxScatteringAngle;
27  // helix radius in homogeneous magnetic field. Units are Kilotesla, MeV and
28  // millimeter
29  // TODO: change using ACTS units
32  std::pow(m_config.minPt * 2 / m_config.pTPerHelixRadius, 2);
35 }
36 
37 template <typename external_spacepoint_t>
38 template <typename sp_range_t>
39 std::vector<Seed<external_spacepoint_t>>
41  sp_range_t bottomSPs, sp_range_t middleSPs, sp_range_t topSPs) const {
42  std::vector<Seed<external_spacepoint_t>> outputVec;
43  for (auto spM : middleSPs) {
44  float rM = spM->radius();
45  float zM = spM->z();
46  float varianceRM = spM->varianceR();
47  float varianceZM = spM->varianceZ();
48 
49  // bottom space point
50  std::vector<const InternalSpacePoint<external_spacepoint_t>*>
51  compatBottomSP;
52 
53  for (auto bottomSP : bottomSPs) {
54  float rB = bottomSP->radius();
55  float deltaR = rM - rB;
56  // if r-distance is too big, try next SP in bin
57  if (deltaR > m_config.deltaRMax) {
58  continue;
59  }
60  // if r-distance is too small, break because bins are NOT r-sorted
61  if (deltaR < m_config.deltaRMin) {
62  continue;
63  }
64  // ratio Z/R (forward angle) of space point duplet
65  float cotTheta = (zM - bottomSP->z()) / deltaR;
66  if (std::fabs(cotTheta) > m_config.cotThetaMax) {
67  continue;
68  }
69  // check if duplet origin on z axis within collision region
70  float zOrigin = zM - rM * cotTheta;
71  if (zOrigin < m_config.collisionRegionMin ||
72  zOrigin > m_config.collisionRegionMax) {
73  continue;
74  }
75  compatBottomSP.push_back(bottomSP);
76  }
77  // no bottom SP found -> try next spM
78  if (compatBottomSP.empty()) {
79  continue;
80  }
81 
82  std::vector<const InternalSpacePoint<external_spacepoint_t>*> compatTopSP;
83 
84  for (auto topSP : topSPs) {
85  float rT = topSP->radius();
86  float deltaR = rT - rM;
87  // this condition is the opposite of the condition for bottom SP
88  if (deltaR < m_config.deltaRMin) {
89  continue;
90  }
91  if (deltaR > m_config.deltaRMax) {
92  break;
93  }
94 
95  float cotTheta = (topSP->z() - zM) / deltaR;
96  if (std::fabs(cotTheta) > m_config.cotThetaMax) {
97  continue;
98  }
99  float zOrigin = zM - rM * cotTheta;
100  if (zOrigin < m_config.collisionRegionMin ||
101  zOrigin > m_config.collisionRegionMax) {
102  continue;
103  }
104  compatTopSP.push_back(topSP);
105  }
106  if (compatTopSP.empty()) {
107  continue;
108  }
109  // contains parameters required to calculate circle with linear equation
110  // ...for bottom-middle
111  std::vector<LinCircle> linCircleBottom;
112  // ...for middle-top
113  std::vector<LinCircle> linCircleTop;
114  transformCoordinates(compatBottomSP, *spM, true, linCircleBottom);
115  transformCoordinates(compatTopSP, *spM, false, linCircleTop);
116 
117  // create vectors here to avoid reallocation in each loop
118  std::vector<const InternalSpacePoint<external_spacepoint_t>*> topSpVec;
119  std::vector<float> curvatures;
120  std::vector<float> impactParameters;
121 
122  std::vector<std::pair<
123  float, std::unique_ptr<const InternalSeed<external_spacepoint_t>>>>
124  seedsPerSpM;
125  size_t numBotSP = compatBottomSP.size();
126  size_t numTopSP = compatTopSP.size();
127 
128  for (size_t b = 0; b < numBotSP; b++) {
129  auto lb = linCircleBottom[b];
130  float Zob = lb.Zo;
131  float cotThetaB = lb.cotTheta;
132  float Vb = lb.V;
133  float Ub = lb.U;
134  float ErB = lb.Er;
135  float iDeltaRB = lb.iDeltaR;
136 
137  // 1+(cot^2(theta)) = 1/sin^2(theta)
138  float iSinTheta2 = (1. + cotThetaB * cotThetaB);
139  // calculate max scattering for min momentum at the seed's theta angle
140  // scaling scatteringAngle^2 by sin^2(theta) to convert pT^2 to p^2
141  // accurate would be taking 1/atan(thetaBottom)-1/atan(thetaTop) <
142  // scattering
143  // but to avoid trig functions we approximate cot by scaling by
144  // 1/sin^4(theta)
145  // resolving with pT to p scaling --> only divide by sin^2(theta)
146  // max approximation error for allowed scattering angles of 0.04 rad at
147  // eta=infinity: ~8.5%
148  float scatteringInRegion2 = m_config.maxScatteringAngle2 * iSinTheta2;
149  // multiply the squared sigma onto the squared scattering
150  scatteringInRegion2 *=
151  m_config.sigmaScattering * m_config.sigmaScattering;
152 
153  // clear all vectors used in each inner for loop
154  topSpVec.clear();
155  curvatures.clear();
156  impactParameters.clear();
157  for (size_t t = 0; t < numTopSP; t++) {
158  auto lt = linCircleTop[t];
159 
160  // add errors of spB-spM and spM-spT pairs and add the correlation term
161  // for errors on spM
162  float error2 = lt.Er + ErB +
163  2 * (cotThetaB * lt.cotTheta * varianceRM + varianceZM) *
164  iDeltaRB * lt.iDeltaR;
165 
166  float deltaCotTheta = cotThetaB - lt.cotTheta;
167  float deltaCotTheta2 = deltaCotTheta * deltaCotTheta;
168  float error;
169  float dCotThetaMinusError2;
170  // if the error is larger than the difference in theta, no need to
171  // compare with scattering
172  if (deltaCotTheta2 - error2 > 0) {
173  deltaCotTheta = std::abs(deltaCotTheta);
174  // if deltaTheta larger than the scattering for the lower pT cut, skip
175  error = std::sqrt(error2);
176  dCotThetaMinusError2 =
177  deltaCotTheta2 + error2 - 2 * deltaCotTheta * error;
178  // avoid taking root of scatteringInRegion
179  // if left side of ">" is positive, both sides of unequality can be
180  // squared
181  // (scattering is always positive)
182 
183  if (dCotThetaMinusError2 > scatteringInRegion2) {
184  continue;
185  }
186  }
187 
188  // protects against division by 0
189  float dU = lt.U - Ub;
190  if (dU == 0.) {
191  continue;
192  }
193  // A and B are evaluated as a function of the circumference parameters
194  // x_0 and y_0
195  float A = (lt.V - Vb) / dU;
196  float S2 = 1. + A * A;
197  float B = Vb - A * Ub;
198  float B2 = B * B;
199  // sqrt(S2)/B = 2 * helixradius
200  // calculated radius must not be smaller than minimum radius
201  if (S2 < B2 * m_config.minHelixDiameter2) {
202  continue;
203  }
204  // 1/helixradius: (B/sqrt(S2))/2 (we leave everything squared)
205  float iHelixDiameter2 = B2 / S2;
206  // calculate scattering for p(T) calculated from seed curvature
207  float pT2scatter = 4 * iHelixDiameter2 * m_config.pT2perRadius;
208  // TODO: include upper pT limit for scatter calc
209  // convert p(T) to p scaling by sin^2(theta) AND scale by 1/sin^4(theta)
210  // from rad to deltaCotTheta
211  float p2scatter = pT2scatter * iSinTheta2;
212  // if deltaTheta larger than allowed scattering for calculated pT, skip
213  if ((deltaCotTheta2 - error2 > 0) &&
214  (dCotThetaMinusError2 >
215  p2scatter * m_config.sigmaScattering * m_config.sigmaScattering)) {
216  continue;
217  }
218  // A and B allow calculation of impact params in U/V plane with linear
219  // function
220  // (in contrast to having to solve a quadratic function in x/y plane)
221  float Im = std::abs((A - B * rM) * rM);
222 
223  if (Im <= m_config.impactMax) {
224  topSpVec.push_back(compatTopSP[t]);
225  // inverse diameter is signed depending if the curvature is
226  // positive/negative in phi
227  curvatures.push_back(B / std::sqrt(S2));
228  impactParameters.push_back(Im);
229  }
230  }
231  if (!topSpVec.empty()) {
232  std::vector<std::pair<
233  float, std::unique_ptr<const InternalSeed<external_spacepoint_t>>>>
234  sameTrackSeeds;
235  sameTrackSeeds = std::move(m_config.seedFilter->filterSeeds_2SpFixed(
236  *compatBottomSP[b], *spM, topSpVec, curvatures, impactParameters,
237  Zob));
238  seedsPerSpM.insert(seedsPerSpM.end(),
239  std::make_move_iterator(sameTrackSeeds.begin()),
240  std::make_move_iterator(sameTrackSeeds.end()));
241  }
242  }
243  m_config.seedFilter->filterSeeds_1SpFixed(seedsPerSpM, outputVec);
244  }
245  return outputVec;
246 }
247 
248 template <typename external_spacepoint_t>
250  std::vector<const InternalSpacePoint<external_spacepoint_t>*>& vec,
251  const InternalSpacePoint<external_spacepoint_t>& spM, bool bottom,
252  std::vector<LinCircle>& linCircleVec) const {
253  float xM = spM.x();
254  float yM = spM.y();
255  float zM = spM.z();
256  float rM = spM.radius();
257  float varianceZM = spM.varianceZ();
258  float varianceRM = spM.varianceR();
259  float cosPhiM = xM / rM;
260  float sinPhiM = yM / rM;
261  for (auto sp : vec) {
262  float deltaX = sp->x() - xM;
263  float deltaY = sp->y() - yM;
264  float deltaZ = sp->z() - zM;
265  // calculate projection fraction of spM->sp vector pointing in same
266  // direction as
267  // vector origin->spM (x) and projection fraction of spM->sp vector pointing
268  // orthogonal to origin->spM (y)
269  float x = deltaX * cosPhiM + deltaY * sinPhiM;
270  float y = deltaY * cosPhiM - deltaX * sinPhiM;
271  // 1/(length of M -> SP)
272  float iDeltaR2 = 1. / (deltaX * deltaX + deltaY * deltaY);
273  float iDeltaR = std::sqrt(iDeltaR2);
274  //
275  int bottomFactor = 1 * (int(!bottom)) - 1 * (int(bottom));
276  // cot_theta = (deltaZ/deltaR)
277  float cot_theta = deltaZ * iDeltaR * bottomFactor;
278  // VERY frequent (SP^3) access
279  LinCircle l;
280  l.cotTheta = cot_theta;
281  // location on z-axis of this SP-duplet
282  l.Zo = zM - rM * cot_theta;
283  l.iDeltaR = iDeltaR;
284  // transformation of circle equation (x,y) into linear equation (u,v)
285  // x^2 + y^2 - 2x_0*x - 2y_0*y = 0
286  // is transformed into
287  // 1 - 2x_0*u - 2y_0*v = 0
288  // using the following m_U and m_V
289  // (u = A + B*v); A and B are created later on
290  l.U = x * iDeltaR2;
291  l.V = y * iDeltaR2;
292  // error term for sp-pair without correlation of middle space point
293  l.Er = ((varianceZM + sp->varianceZ()) +
294  (cot_theta * cot_theta) * (varianceRM + sp->varianceR())) *
295  iDeltaR2;
296  linCircleVec.push_back(l);
297  }
298 }
299 } // namespace Acts