CMS 3D CMS Logo

ThirdHitPrediction.cc
Go to the documentation of this file.
12 
13 inline float sqr(float x) { return x * x; }
14 
15 using namespace std;
16 
17 /*****************************************************************************/
21  const edm::EventSetup& es,
23  double maxAngleRatio,
24  string builderName) {
25  using namespace edm;
27  es.get<IdealMagneticFieldRecord>().get(magfield);
28 
30  es.get<TransientRecHitRecord>().get(builderName, ttrhbESH);
31  theTTRecHitBuilder = ttrhbESH.product();
32 
33  Bz = fabs(magfield->inInverseGeV(GlobalPoint(0, 0, 0)).z());
34 
35  c0 = Global2DVector(region.origin().x(), region.origin().y());
36 
37  r0 = region.originRBound();
38  rm = region.ptMin() / Bz;
39 
40  g1 = inner;
41  g2 = outer;
42 
43  p1 = Global2DVector(g1.x(), g1.y());
44  p2 = Global2DVector(g2.x(), g2.y());
45 
46  dif = p1 - p2;
47 
48  // Prepare circles of minimal pt (rm) and cylinder of origin (r0)
49  keep = true;
50  arc_0m = findArcIntersection(findMinimalCircles(rm), findTouchingCircles(r0), keep);
51 
54 }
55 
56 /*****************************************************************************/
58 
59 /*****************************************************************************/
61  float s = dif.mag2() / ((c - p1).mag2() - sqr(r));
62 
63  c = p1 + (c - p1) * s;
64  r *= fabsf(s);
65 }
66 
67 /*****************************************************************************/
69  float s = dif.mag2() / (p - p1).mag2();
70 
71  p = p1 + (p - p1) * s;
72 }
73 
74 /*****************************************************************************/
75 pair<float, float> ThirdHitPrediction::findMinimalCircles(float r) {
76  pair<float, float> a(0., 0.);
77 
78  if (dif.mag2() < 2 * sqr(r))
79  a = pair<float, float>(dif.phi(), 0.5 * acos(1 - 0.5 * dif.mag2() / sqr(r)));
80 
81  return a;
82 }
83 
84 /*****************************************************************************/
85 pair<float, float> ThirdHitPrediction::findTouchingCircles(float r) {
87  invertCircle(c, r);
88 
89  pair<float, float> a(0., 0.);
90  a = pair<float, float>((c - p2).phi(), 0.5 * acos(1 - 2 * sqr(r) / (c - p2).mag2()));
91 
92  return a;
93 }
94 
95 /*****************************************************************************/
96 pair<float, float> ThirdHitPrediction::findArcIntersection(pair<float, float> a, pair<float, float> b, bool& keep) {
97  // spin closer
98  while (b.first < a.first - M_PI)
99  b.first += 2 * M_PI;
100  while (b.first > a.first + M_PI)
101  b.first -= 2 * M_PI;
102 
103  float min, max;
104 
105  if (a.first - a.second > b.first - b.second)
106  min = a.first - a.second;
107  else {
108  min = b.first - b.second;
109  keep = false;
110  }
111 
112  if (a.first + a.second < b.first + b.second)
113  max = a.first + a.second;
114  else {
115  max = b.first + b.second;
116  keep = false;
117  }
118 
119  pair<float, float> c(0., 0.);
120 
121  if (min < max) {
122  c.first = 0.5 * (max + min);
123  c.second = 0.5 * (max - min);
124  }
125 
126  return c;
127 }
128 
129 /*****************************************************************************/
130 void ThirdHitPrediction::fitParabola(const float x[3], const float y[3], float par[3]) {
131  float s2 = sqr(x[0]) * (y[1] - y[2]) + sqr(x[1]) * (y[2] - y[0]) + sqr(x[2]) * (y[0] - y[1]);
132 
133  float s1 = x[0] * (y[1] - y[2]) + x[1] * (y[2] - y[0]) + x[2] * (y[0] - y[1]);
134 
135  float s3 = (x[0] - x[1]) * (x[1] - x[2]) * (x[2] - x[0]);
136  float s4 =
137  x[0] * x[1] * y[2] * (x[0] - x[1]) + x[0] * y[1] * x[2] * (x[2] - x[0]) + y[0] * x[1] * x[2] * (x[1] - x[2]);
138 
139  par[2] = s1 / s3; // a2
140  par[1] = -s2 / s3; // a1
141  par[0] = -s4 / s3; // a0
142 }
143 
144 /*****************************************************************************/
146  const float x[3], const float y[3], const float par[3], float phi[2], float z[2]) {
147  // Initial guess
148  phi[0] = min(x[0], x[2]);
149  z[0] = min(y[0], y[2]);
150  phi[1] = max(x[0], x[2]);
151  z[1] = max(y[0], y[2]);
152 
153  // Extremum: position and value
154  float xe = -par[1] / (2 * par[2]);
155  float ye = par[0] - sqr(par[1]) / (4 * par[2]);
156 
157  // Check if extremum is inside the phi range
158  if (phi[0] < xe && xe < phi[1]) {
159  if (ye < z[0])
160  z[0] = ye;
161  if (ye > z[1])
162  z[1] = ye;
163  }
164 }
165 
166 /*****************************************************************************/
168  return a.x() * b.y() - a.y() * b.x();
169 }
170 
171 /*****************************************************************************/
173  float rad2 = (p1 - c).mag2();
174 
175  float a12 = asin(fabsf(areaParallelogram(p1 - c, p2 - c)) / rad2);
176  float a23 = asin(fabsf(areaParallelogram(p2 - c, p3 - c)) / rad2);
177 
178  return a23 / a12;
179 }
180 
181 /*****************************************************************************/
182 void ThirdHitPrediction::spinCloser(float phi[3]) {
183  while (phi[1] < phi[0] - M_PI)
184  phi[1] += 2 * M_PI;
185  while (phi[1] > phi[0] + M_PI)
186  phi[1] -= 2 * M_PI;
187 
188  while (phi[2] < phi[1] - M_PI)
189  phi[2] += 2 * M_PI;
190  while (phi[2] > phi[1] + M_PI)
191  phi[2] -= 2 * M_PI;
192 }
193 
194 /*****************************************************************************/
195 void ThirdHitPrediction::calculateRangesBarrel(float r3, float phi[2], float z[2], bool keep) {
196  pair<float, float> arc_all = findArcIntersection(arc_0m, findTouchingCircles(r3), keep);
197 
198  if (arc_all.second != 0.) {
199  Global2DVector c3(0., 0.); // barrel at r3
200  invertCircle(c3, r3); // inverted
201 
202  float angle[3]; // prepare angles
203  angle[0] = arc_all.first - arc_all.second;
204  angle[1] = arc_all.first;
205  angle[2] = arc_all.first + arc_all.second;
206 
207  float phi3[3], z3[3];
208  Global2DVector delta = c3 - p2;
209 
210  for (int i = 0; i < 3; i++) {
211  Global2DVector vec(cos(angle[i]), sin(angle[i])); // unit vector
212  float lambda = delta * vec - sqrt(sqr(delta * vec) - delta * delta + sqr(r3));
213 
214  Global2DVector p3 = p2 + lambda * vec; // inverted third hit
215  invertPoint(p3); // third hit
216  phi3[i] = p3.phi(); // phi of third hit
217 
218  float ratio;
219 
220  if (keep && i == 1) { // Straight line
221  ratio = (p2 - p3).mag() / (p1 - p2).mag();
222  } else { // Circle
223  Global2DVector c = p2 - vec * (vec * (p2 - p1)); // inverted antipodal
224  invertPoint(c); // antipodal
225  c = 0.5 * (p1 + c); // center
226 
227  ratio = angleRatio(p3, c);
228  }
229 
230  z3[i] = g2.z() + (g2.z() - g1.z()) * ratio; // z of third hit
231  }
232 
233  spinCloser(phi3);
234 
235  // Parabola on phi - z
236  float par[3];
237  fitParabola(phi3, z3, par);
238  findRectangle(phi3, z3, par, phi, z);
239  }
240 }
241 
242 /*****************************************************************************/
243 void ThirdHitPrediction::calculateRangesForward(float z3, float phi[2], float r[2], bool keep) {
244  float angle[3]; // prepare angles
245  angle[0] = arc_0m.first - arc_0m.second;
246  angle[1] = arc_0m.first;
247  angle[2] = arc_0m.first + arc_0m.second;
248 
249  float ratio = (z3 - g2.z()) / (g2.z() - g1.z());
250 
251  if (0 < ratio && ratio < maxRatio) {
252  float phi3[3], r3[3];
253 
254  for (int i = 0; i < 3; i++) {
256 
257  if (keep && i == 1) { // Straight line
258  p3 = p2 + ratio * (p2 - p1);
259  } else { // Circle
260  Global2DVector vec(cos(angle[i]), sin(angle[i])); // unit vector
261 
262  Global2DVector c = p2 - vec * (vec * (p2 - p1)); // inverted antipodal
263  invertPoint(c); // antipodal
264  c = 0.5 * (p1 + c); // center
265 
266  float rad2 = (p1 - c).mag2();
267 
268  float a12 = asin(areaParallelogram(p1 - c, p2 - c) / rad2);
269  float a23 = ratio * a12;
270 
271  p3 = c + Global2DVector((p2 - c).x() * cos(a23) - (p2 - c).y() * sin(a23),
272  (p2 - c).x() * sin(a23) + (p2 - c).y() * cos(a23));
273  }
274 
275  phi3[i] = p3.phi();
276  r3[i] = p3.mag();
277  }
278 
279  spinCloser(phi3);
280 
281  // Parabola on phi - z
282  float par[3];
283  fitParabola(phi3, r3, par);
284  findRectangle(phi3, r3, par, phi, r);
285  }
286 }
287 
288 /*****************************************************************************/
289 void ThirdHitPrediction::calculateRanges(float rz3, float phi[2], float rz[2]) {
290  // Clear
291  phi[0] = 0.;
292  rz[0] = 0.;
293  phi[1] = 0.;
294  rz[1] = 0.;
295 
296  // Calculate
297  if (theBarrel)
298  calculateRangesBarrel(rz3, phi, rz, keep);
299  else
300  calculateRangesForward(rz3, phi, rz, keep);
301 }
302 
303 /*****************************************************************************/
304 void ThirdHitPrediction::getRanges(const DetLayer* layer, float phi[], float rz[]) {
305  theLayer = layer;
306 
307  if (layer)
308  initLayer(layer);
309 
310  float phi_inner[2], rz_inner[2];
311  calculateRanges(theDetRange.min(), phi_inner, rz_inner);
312 
313  float phi_outer[2], rz_outer[2];
314  calculateRanges(theDetRange.max(), phi_outer, rz_outer);
315 
316  if ((phi_inner[0] == 0. && phi_inner[1] == 0.) || (phi_outer[0] == 0. && phi_outer[1] == 0.)) {
317  phi[0] = 0.;
318  phi[1] = 0.;
319 
320  rz[0] = 0.;
321  rz[1] = 0.;
322  } else {
323  while (phi_outer[0] > phi_inner[0] + M_PI) {
324  phi_outer[0] -= 2 * M_PI;
325  phi_outer[1] -= 2 * M_PI;
326  }
327 
328  while (phi_outer[0] < phi_inner[0] - M_PI) {
329  phi_outer[0] += 2 * M_PI;
330  phi_outer[1] += 2 * M_PI;
331  }
332 
333  phi[0] = min(phi_inner[0], phi_outer[0]);
334  phi[1] = max(phi_inner[1], phi_outer[1]);
335 
336  rz[0] = min(rz_inner[0], rz_outer[0]);
337  rz[1] = max(rz_inner[1], rz_outer[1]);
338  }
339 }
340 
341 /*****************************************************************************/
342 void ThirdHitPrediction::getRanges(float rz3, float phi[], float rz[]) { calculateRanges(rz3, phi, rz); }
343 
344 /*****************************************************************************/
346  const vector<const TrackingRecHit*>& h,
347  vector<GlobalVector>& globalDirs,
348  const edm::EventSetup& es) {
349  Global2DVector p1(g1.x(), g1.y());
350  Global2DVector p2(g2.x(), g2.y());
351  Global2DVector p3(g3.x(), g3.y());
352 
353  CircleFromThreePoints circle(g1, g2, g3);
354 
355  if (circle.curvature() != 0.) {
356  Global2DVector c(circle.center().x(), circle.center().y());
357 
358  float rad2 = (p1 - c).mag2();
359  float a12 = asin(fabsf(areaParallelogram(p1 - c, p2 - c)) / rad2);
360  float a23 = asin(fabsf(areaParallelogram(p2 - c, p3 - c)) / rad2);
361 
362  float slope = (g2.z() - g1.z()) / a12;
363 
364  float rz3 = g2.z() + slope * a23;
365  float delta_z = g3.z() - rz3;
366 
367  // Transform to tt
368  vector<TransientTrackingRecHit::RecHitPointer> th;
369  for (vector<const TrackingRecHit*>::const_iterator ih = h.begin(); ih != h.end(); ih++)
370  th.push_back(theTTRecHitBuilder->build(*ih));
371 
372  float sigma1_le2 = max(th[0]->parametersError()[0][0], th[0]->parametersError()[1][1]);
373  float sigma2_le2 = max(th[1]->parametersError()[0][0], th[1]->parametersError()[1][1]);
374 
375  float sigma_z2 = (1 + a23 / a12) * (1 + a23 / a12) * sigma2_le2 + (a23 / a12) * (a23 / a12) * sigma1_le2;
376 
377  float cotTheta = slope * circle.curvature(); // == sinhEta
378  float coshEta = sqrt(1 + sqr(cotTheta)); // == 1/sinTheta
379 
380  float pt = Bz / circle.curvature();
381  float p = pt * coshEta;
382 
383  float m_pi = 0.13957018;
384  float beta = p / sqrt(sqr(p) + sqr(m_pi));
385 
387  PixelRecoPointRZ rz2(g2.perp(), g2.z());
388 
389  float sigma_z = msp(pt, cotTheta, rz2) / beta;
390 
391  // Calculate globalDirs
392  float sinTheta = 1. / coshEta;
393  float cosTheta = cotTheta * sinTheta;
394 
395  int dir;
396  if (areaParallelogram(p1 - c, p2 - c) > 0)
397  dir = 1;
398  else
399  dir = -1;
400 
401  float curvature = circle.curvature();
402 
403  {
404  Global2DVector v = (p1 - c) * curvature * dir;
405  globalDirs.push_back(GlobalVector(-v.y() * sinTheta, v.x() * sinTheta, cosTheta));
406  }
407 
408  {
409  Global2DVector v = (p2 - c) * curvature * dir;
410  globalDirs.push_back(GlobalVector(-v.y() * sinTheta, v.x() * sinTheta, cosTheta));
411  }
412 
413  {
414  Global2DVector v = (p3 - c) * curvature * dir;
415  globalDirs.push_back(GlobalVector(-v.y() * sinTheta, v.x() * sinTheta, cosTheta));
416  }
417 
418  // Multiple scattering
419  float sigma_ms = sigma_z * coshEta;
420 
421  // Local error squared
422  float sigma_le2 = max(th[2]->parametersError()[0][0], th[2]->parametersError()[1][1]);
423 
424  return (delta_z * delta_z / (sigma_ms * sigma_ms + sigma_le2 + sigma_z2) < nSigma * nSigma);
425  }
426 
427  return false;
428 }
429 
430 /*****************************************************************************/
432  if (layer->location() == GeomDetEnumerators::barrel) {
433  theBarrel = true;
434  theForward = false;
435  const BarrelDetLayer& bl = dynamic_cast<const BarrelDetLayer&>(*layer);
436  float halfThickness = bl.surface().bounds().thickness() / 2;
437  float radius = bl.specificSurface().radius();
438  theDetRange = Range(radius - halfThickness, radius + halfThickness);
439  } else if (layer->location() == GeomDetEnumerators::endcap) {
440  theBarrel = false;
441  theForward = true;
442  const ForwardDetLayer& fl = dynamic_cast<const ForwardDetLayer&>(*layer);
443  float halfThickness = fl.surface().bounds().thickness() / 2;
444  float zLayer = fl.position().z();
445  theDetRange = Range(zLayer - halfThickness, zLayer + halfThickness);
446  }
447 }
float originRBound() const
bounds the particle vertex in the transverse plane
void findRectangle(const float x[3], const float y[3], const float par[3], float phi[2], float z[2])
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
void invertCircle(Global2DVector &c, float &r)
T y() const
Definition: PV2DBase.h:44
void initLayer(const DetLayer *layer)
GlobalPoint const & origin() const
Vector2DBase< float, GlobalTag > Global2DVector
PixelRecoRange< float > Range
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
static const double slope[3]
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
void calculateRangesForward(float z3, float phi[2], float r[2], bool keep)
virtual Location location() const =0
Which part of the detector (barrel, endcap)
T mag() const
Definition: PV2DBase.h:47
void calculateRangesBarrel(float r3, float phi[2], float z[2], bool keep)
T y() const
Definition: PV3DBase.h:60
const Bounds & bounds() const
Definition: Surface.h:89
virtual const BoundCylinder & specificSurface() const final
Extension of the interface.
float angleRatio(const Global2DVector &p3, const Global2DVector &c)
const int keep
GlobalVector inInverseGeV(const GlobalPoint &gp) const
Field value ad specified global point, in 1/Gev.
Definition: MagneticField.h:36
Geom::Phi< T > phi() const
Definition: PV2DBase.h:49
T curvature(T InversePt, const edm::EventSetup &iSetup)
susybsm::MuonSegmentRefProd msp
Definition: classes.h:34
T sqrt(T t)
Definition: SSEVec.h:19
T z() const
Definition: PV3DBase.h:61
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
float areaParallelogram(const Global2DVector &a, const Global2DVector &b)
std::pair< float, float > findMinimalCircles(float r)
T min(T a, T b)
Definition: MathUtil.h:58
double p2[4]
Definition: TauolaWrapper.h:90
#define M_PI
virtual float thickness() const =0
virtual const Surface::PositionType & position() const
Returns position of the surface.
float ptMin() const
minimal pt of interest
double b
Definition: hdecay.h:118
ThirdHitPrediction(const TrackingRegion &region, GlobalPoint inner, GlobalPoint outer, const edm::EventSetup &es, double nSigMultipleScattering, double maxAngleRatio, std::string builderName)
void spinCloser(float phi[3])
HLT enums.
const BoundSurface & surface() const final
The surface of the GeometricSearchDet.
double p1[4]
Definition: TauolaWrapper.h:89
std::pair< float, float > findArcIntersection(std::pair< float, float > a, std::pair< float, float > b, bool &keep)
double a
Definition: hdecay.h:119
T get() const
Definition: EventSetup.h:73
void invertPoint(Global2DVector &p)
void fitParabola(const float x[3], const float y[3], float par[3])
void calculateRanges(float rz3, float phi[2], float rz[2])
bool isCompatibleWithMultipleScattering(GlobalPoint g3, const std::vector< const TrackingRecHit * > &h, std::vector< GlobalVector > &localDirs, const edm::EventSetup &es)
void getRanges(const DetLayer *layer, float phi[], float rz[])
std::pair< float, float > findTouchingCircles(float r)
rm
Definition: submit.py:77
T x() const
Definition: PV2DBase.h:43
T x() const
Definition: PV3DBase.h:59
T const * product() const
Definition: ESHandle.h:86
const BoundSurface & surface() const final
GeometricSearchDet interface.
Global3DVector GlobalVector
Definition: GlobalVector.h:10
double p3[4]
Definition: TauolaWrapper.h:91
#define m_pi
Definition: RPCConst.cc:8
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11
float sqr(float x)