GeometryUtilities.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // \file GeometryUtilities.cxx
3 //
4 // \brief Functions to calculate distances and angles in 3D and 2D
5 //
6 // andrzej.szelc@yale.edu
7 //
8 ////////////////////////////////////////////////////////////////////////
9 
11 #include "cetlib/pow.h"
19 
20 #include "TLorentzVector.h"
21 
22 #include <cmath>
23 
24 namespace util {
25 
27  detinfo::DetectorClocksData const& clockData,
28  detinfo::DetectorPropertiesData const& propData)
29  : fGeom{geom}, fClocks{clockData}, fDetProp{propData}
30  {
32  vertangle.resize(fNPlanes);
33  for (UInt_t ip = 0; ip < fNPlanes; ip++)
34  vertangle[ip] = fGeom.Plane(ip).Wire(0).ThetaZ(false) - TMath::Pi() / 2.; // wire angle
35 
37  fTimeTick = sampling_rate(fClocks) / 1000.;
39 
43  }
44 
45  //-----------------------------------------------------------------------------
46  // omega0 and omega1 (calculated by CPAN in degrees):
47  // angle based on distances in wires and time - rescaled to cm.
48  // tan(angle)*fMean_wire_pitch/(fTimeTick*fDriftVelocity);
49  // as those calculated with Get2Dangle
50  // writes phi and theta in degrees.
51  /////////////////////////////////////
52  Int_t
54  Int_t iplane1,
55  Double_t omega0,
56  Double_t omega1,
57  Double_t& phi,
58  Double_t& theta) const
59  {
60  // y, z, x coordinates
61  Double_t ln(0), mn(0), nn(0);
62  Double_t phis(0), thetan(0);
63 
64  // Pretend collection and induction planes.
65  // "Collection" is the plane with the vertical angle equal to zero.
66  // If both are non-zero, collection is the one with the negative angle.
67  UInt_t Cplane = 0, Iplane = 1;
68 
69  // angleC and angleI are the respective angles to vertical in C/I
70  // planes and slopeC, slopeI are the tangents of the track.
71  Double_t angleC, angleI, slopeC, slopeI, omegaC, omegaI;
72  omegaC = kINVALID_DOUBLE;
73  omegaI = kINVALID_DOUBLE;
74 
75  // Don't know how to reconstruct these yet, so exit with error.
76  // In
77  if (omega0 == 0 || omega1 == 0) {
78  phi = 0;
79  theta = -999;
80  return -1;
81  }
82 
83  //////insert check for existence of planes.
84 
85  // check if backwards going track
86  Double_t alt_backwards = 0;
87 
88  if (fabs(omega0) > (TMath::Pi() / 2.0) || fabs(omega1) > (TMath::Pi() / 2.0)) {
89  alt_backwards = 1;
90  }
91 
92  if (vertangle[iplane0] == 0) {
93  // first plane is at 0 degrees
94  Cplane = iplane0;
95  Iplane = iplane1;
96  omegaC = omega0;
97  omegaI = omega1;
98  }
99  else if (vertangle[iplane1] == 0) {
100  // second plane is at 0 degrees
101  Cplane = iplane1;
102  Iplane = iplane0;
103  omegaC = omega1;
104  omegaI = omega0;
105  }
106  else if (vertangle[iplane0] != 0 && vertangle[iplane1] != 0) {
107  // both planes are at non zero degree - find the one with deg<0
108  if (vertangle[iplane1] < vertangle[iplane0]) {
109  Cplane = iplane1;
110  Iplane = iplane0;
111  omegaC = omega1;
112  omegaI = omega0;
113  }
114  else if (vertangle[iplane1] > vertangle[iplane0]) {
115  Cplane = iplane0;
116  Iplane = iplane1;
117  omegaC = omega0;
118  omegaI = omega1;
119  }
120  else {
121  // throw error - same plane.
122  return -1;
123  }
124  }
125 
126  slopeC = tan(omegaC);
127  slopeI = tan(omegaI);
128  angleC = vertangle[Cplane];
129  angleI = vertangle[Iplane];
130 
131  // 0 -1 factor depending on if one of the planes is vertical.
132  bool nfact = !(vertangle[Cplane]);
133 
134  // ln represents y, omega is 2d angle -- in first 2 quadrants y is positive.
135  if (omegaC < TMath::Pi() && omegaC > 0)
136  ln = 1;
137  else
138  ln = -1;
139 
140  // calculate x and z using y ( ln )
141  mn = (ln / (2 * sin(angleI))) * ((cos(angleI) / (slopeC * cos(angleC))) - (1 / slopeI) +
142  nfact * (cos(angleI) / (cos(angleC) * slopeC) - 1 / slopeI));
143 
144  nn = (ln / (2 * cos(angleC))) *
145  ((1 / slopeC) + (1 / slopeI) + nfact * ((1 / slopeC) - (1 / slopeI)));
146 
147  // Direction angles
148  if (fabs(omegaC) > 0.01) // catch numeric error values
149  {
150  // phi=atan(ln/nn);
151  phis = asin(ln / TMath::Sqrt(ln * ln + nn * nn));
152 
153  if (fabs(slopeC + slopeI) < 0.001)
154  phis = 0;
155  else if (fabs(omegaI) > 0.01 && (omegaI / fabs(omegaI) == -omegaC / fabs(omegaC)) &&
156  (fabs(omegaC) < 1 * TMath::Pi() / 180 ||
157  fabs(omegaC) > 179 * TMath::Pi() / 180)) // angles have
158  phis = (fabs(omegaC) > TMath::Pi() / 2) ? TMath::Pi() : 0; // angles are
159 
160  if (nn < 0 && phis > 0 &&
161  !(!alt_backwards &&
162  fabs(phis) <
163  TMath::Pi() / 4)) // do not go back if track looks forward and phi is forward
164  phis = (TMath::Pi()) - phis;
165  else if (nn < 0 && phis < 0 && !(!alt_backwards && fabs(phis) < TMath::Pi() / 4))
166  phis = (-TMath::Pi()) - phis;
167 
168  phi = phis * 180 / TMath::Pi();
169  }
170  // If plane2 (collection), phi = 2d angle (omegaC in this case)
171  else {
172  phis = omegaC;
173  phi = omegaC;
174  }
175 
176  thetan = -asin(mn / std::hypot(ln, mn, nn));
177  theta = thetan * 180 / TMath::Pi();
178 
179  return 0;
180  }
181 
182  //////////////////////////////
183  // Calculate theta in case phi~0
184  // returns theta in angles
185  ////////////////////////////////
186  Double_t
188  Int_t iplane1,
189  Double_t dw0,
190  Double_t dw1) const
191  {
192 
193  Double_t splane, lplane; // plane in which the track is shorter and longer.
194  Double_t sdw, ldw;
195 
196  if (dw0 == 0 && dw1 == 0) return -1;
197 
198  if (dw0 >= dw1) {
199  lplane = iplane0;
200  splane = iplane1;
201  ldw = dw0;
202  sdw = dw1;
203  }
204  else {
205  lplane = iplane1;
206  splane = iplane0;
207  ldw = dw1;
208  sdw = dw0;
209  }
210 
211  Double_t top = (std::cos(vertangle[splane]) - std::cos(vertangle[lplane]) * sdw / ldw);
212  Double_t bottom = tan(vertangle[lplane] * std::cos(vertangle[splane]));
213  bottom -= tan(vertangle[splane] * std::cos(vertangle[lplane])) * sdw / ldw;
214 
215  Double_t tantheta = top / bottom;
216 
217  return atan(tantheta) * vertangle[lplane] / std::abs(vertangle[lplane]) * 180. / TMath::Pi();
218  }
219 
220  /////////////////////////////////////////////////////////
221  // Calculate 3D pitch in beam coordinates
222  //
223  /////////////////////////////////////////////////////////
224  Double_t
225  GeometryUtilities::CalculatePitch(UInt_t iplane, Double_t phi, Double_t theta) const
226  {
227 
228  Double_t pitch = -1.;
229 
230  if (fGeom.Plane(iplane).View() == geo::kUnknown || fGeom.Plane(iplane).View() == geo::k3D) {
231  mf::LogError(Form("Warning : no Pitch foreseen for view %d", fGeom.Plane(iplane).View()));
232  return pitch;
233  }
234  else {
235 
236  Double_t pi = TMath::Pi();
237  Double_t fTheta = pi / 2 - theta;
238  Double_t fPhi = -(phi + pi / 2);
239 
240  for (UInt_t i = 0; i < fGeom.Nplanes(); ++i) {
241  if (i == iplane) {
242  Double_t wirePitch = fGeom.WirePitch(i);
243  Double_t angleToVert =
244  0.5 * TMath::Pi() - fGeom.WireAngleToVertical(fGeom.Plane(i).View());
245  Double_t cosgamma =
246  TMath::Abs(TMath::Sin(angleToVert) * TMath::Cos(fTheta) +
247  TMath::Cos(angleToVert) * TMath::Sin(fTheta) * TMath::Sin(fPhi));
248 
249  if (cosgamma > 0) pitch = wirePitch / cosgamma;
250  } // end if the correct view
251  } // end loop over planes
252  } // end if a reasonable view
253 
254  return pitch;
255  }
256 
257  /////////////////////////////////////////////////////////
258  // Calculate 3D pitch in polar coordinates
259  //
260  /////////////////////////////////////////////////////////
261  Double_t
262  GeometryUtilities::CalculatePitchPolar(UInt_t iplane, Double_t phi, Double_t theta) const
263  {
264 
265  Double_t pitch = -1.;
266 
267  if (fGeom.Plane(iplane).View() == geo::kUnknown || fGeom.Plane(iplane).View() == geo::k3D) {
268  mf::LogError(Form("Warning : no Pitch foreseen for view %d", fGeom.Plane(iplane).View()));
269  return pitch;
270  }
271  else {
272 
273  Double_t fTheta = theta;
274  Double_t fPhi = phi;
275 
276  for (UInt_t i = 0; i < fGeom.Nplanes(); ++i) {
277  if (i == iplane) {
278  Double_t wirePitch = fGeom.WirePitch(i);
279  Double_t angleToVert =
280  0.5 * TMath::Pi() - fGeom.WireAngleToVertical(fGeom.Plane(i).View());
281  Double_t cosgamma =
282  TMath::Abs(TMath::Sin(angleToVert) * TMath::Cos(fTheta) +
283  TMath::Cos(angleToVert) * TMath::Sin(fTheta) * TMath::Sin(fPhi));
284 
285  if (cosgamma > 0) pitch = wirePitch / cosgamma;
286  } // end if the correct view
287  } // end loop over planes
288  } // end if a reasonable view
289 
290  return pitch;
291  }
292 
293  /////////////////////////////////////////////////////////
294  // Calculate 2D slope
295  // in "cm" "cm" coordinates
296  /////////////////////////////////////////////////////////
297  Double_t
299  Double_t wirestart,
300  Double_t timeend,
301  Double_t timestart) const
302  {
303 
304  return GeometryUtilities::Get2Dslope((wireend - wirestart) * fWiretoCm,
305  (timeend - timestart) * fTimetoCm);
306  }
307 
308  /////////////////////////////////////////////////////////
309  // Calculate 2D slope
310  // in "cm" "cm" coordinates
311  /////////////////////////////////////////////////////////
312  double
314  const util::PxPoint* startpoint) const
315  {
316  return Get2Dslope(endpoint->w - startpoint->w, endpoint->t - startpoint->t);
317  }
318 
319  /////////////////////////////////////////////////////////
320  // Calculate 2D slope
321  // in wire time coordinates coordinates
322  //
323  /////////////////////////////////////////////////////////
324  Double_t
325  GeometryUtilities::Get2Dslope(Double_t dwire, Double_t dtime) const
326  {
327  return tan(Get2Dangle(dwire, dtime)) / fWireTimetoCmCm;
328  }
329 
330  /////////////////////////////////////////////////////////
331  // Calculate 2D angle
332  // in "cm" "cm" coordinates
333  /////////////////////////////////////////////////////////
334  Double_t
336  Double_t wirestart,
337  Double_t timeend,
338  Double_t timestart) const
339  {
340 
341  return Get2Dangle((wireend - wirestart) * fWiretoCm, (timeend - timestart) * fTimetoCm);
342  }
343 
344  /////////////////////////////////////////////////////////
345  // Calculate 2D angle
346  // in "cm" "cm" coordinates, endpoint and startpoint are assumed to be in
347  // cm/cm space
348  /////////////////////////////////////////////////////////
349  Double_t
351  const util::PxPoint* startpoint) const
352  {
353  return Get2Dangle(endpoint->w - startpoint->w, endpoint->t - startpoint->t);
354  }
355 
356  ////////////////////////////
357  // Calculate 2D angle
358  // in "cm" "cm" coordinates
359  ////////////////////////////
360  Double_t
361  GeometryUtilities::Get2Dangle(Double_t dwire, Double_t dtime) const
362  {
363  Double_t BC, AC;
364  Double_t omega;
365 
366  BC = ((Double_t)dwire); // in cm
367  AC = ((Double_t)dtime); // in cm
368  omega = std::asin(AC / std::hypot(AC, BC));
369  if (BC < 0) // for the time being. Will check if it works for AC<0
370  {
371  if (AC > 0) {
372  omega = TMath::Pi() - std::abs(omega); //
373  }
374  else if (AC < 0) {
375  omega = -TMath::Pi() + std::abs(omega);
376  }
377  else {
378  omega = TMath::Pi();
379  }
380  }
381  return omega;
382  }
383 
384  // accepting phi and theta in degrees
385  // returning in radians.
386 
387  double
388  GeometryUtilities::Get2DangleFrom3D(unsigned int plane, double phi, double theta) const
389  {
390  TVector3 dummyvector(cos(theta * TMath::Pi() / 180.) * sin(phi * TMath::Pi() / 180.),
391  sin(theta * TMath::Pi() / 180.),
392  cos(theta * TMath::Pi() / 180.) * cos(phi * TMath::Pi() / 180.));
393 
394  return Get2DangleFrom3D(plane, dummyvector);
395  }
396 
397  // accepting TVector3
398  // returning in radians as is customary,
399 
400  double
401  GeometryUtilities::Get2DangleFrom3D(unsigned int plane, TVector3 dir_vector) const
402  {
403  double alpha = 0.5 * TMath::Pi() - fGeom.WireAngleToVertical(fGeom.Plane(plane).View());
404  // create dummy xyz point in middle of detector and another one in unit
405  // length. calculate correspoding points in wire-time space and use the
406  // differnces between those to return 2D a angle
407 
408  TVector3 start(fGeom.DetHalfWidth(), 0., fGeom.DetLength() / 2.);
409  TVector3 end = start + dir_vector;
410 
411  // the wire coordinate is already in cm. The time needs to be converted.
412  util::PxPoint startp(
413  plane,
414  (fGeom.DetHalfHeight() * sin(fabs(alpha)) + start[2] * cos(alpha) - start[1] * sin(alpha)),
415  start[0]);
416 
417  util::PxPoint endp(
418  plane,
419  (fGeom.DetHalfHeight() * sin(fabs(alpha)) + end[2] * cos(alpha) - end[1] * sin(alpha)),
420  end[0]);
421 
422  double angle = Get2Dangle(&endp, &startp);
423 
424  return angle;
425  }
426 
427  //////////////////////////////////////
428  // Calculate 2D distance
429  // in "cm" "cm" coordinates
430  ////////////////////////////////////////
431  Double_t
433  Double_t time1,
434  Double_t wire2,
435  Double_t time2) const
436  {
437 
438  return std::hypot((wire1 - wire2) * fWiretoCm, (time1 - time2) * fTimetoCm);
439  }
440 
441  double
443  {
444  return std::hypot(point1->w - point2->w, point1->t - point2->t);
445  }
446 
447  ////////////////////////////
448  // Calculate 2D distance, using 2D angle
449  // in "cm" "cm" coordinates
450  ////////////////////////////
451  Double_t
452  GeometryUtilities::Get2DPitchDistance(Double_t angle, Double_t inwire, Double_t wire) const
453  {
454  Double_t radangle = TMath::Pi() * angle / 180;
455  if (std::cos(radangle) == 0) return 9999;
456  return std::abs((wire - inwire) / std::cos(radangle)) * fWiretoCm;
457  }
458 
459  //----------------------------------------------------------------------------
460  Double_t
461  GeometryUtilities::Get2DPitchDistanceWSlope(Double_t slope, Double_t inwire, Double_t wire) const
462  {
463 
464  return std::abs(wire - inwire) * TMath::Sqrt(1 + slope * slope) * fWiretoCm;
465  }
466 
467  ///////////////////////////////////
468  // Calculate wire,time coordinates of the Hit projection onto a line
469  //
470  ///////////////////////////////////
471  Int_t
473  Double_t intercept,
474  Double_t wire1,
475  Double_t time1,
476  Double_t& wireout,
477  Double_t& timeout) const
478  {
479  Double_t invslope = 0;
480 
481  if (slope) { invslope = -1. / slope; }
482 
483  Double_t ort_intercept = time1 - invslope * (Double_t)wire1;
484 
485  if ((slope - invslope) != 0)
486  wireout = (ort_intercept - intercept) / (slope - invslope);
487  else
488  wireout = wire1;
489  timeout = slope * wireout + intercept;
490 
491  return 0;
492  }
493 
494  //////////////////////////////////
495  // Calculate wire,time coordinates of the Hit projection onto a line
496  // all points are assumed to be in cm/cm space.
497  ///////////////////////////////////
498  int
500  const util::PxPoint* startpoint,
501  const util::PxPoint* point1,
502  util::PxPoint& pointout) const
503  {
504 
505  double intercept = startpoint->t - slope * startpoint->w;
506 
507  return GetPointOnLine(slope, intercept, point1, pointout);
508  }
509 
510  ///////////////////////////////////
511  // Calculate wire,time coordinates of the Hit projection onto a line
512  // all points assumed to be in cm/cm space.
513  ///////////////////////////////////
514  int
516  double intercept,
517  const util::PxPoint* point1,
518  util::PxPoint& pointout) const
519  {
520  double invslope = 0;
521 
522  if (slope) { invslope = -1. / slope; }
523 
524  double ort_intercept = point1->t - invslope * point1->w;
525 
526  if ((slope - invslope) != 0)
527  pointout.w = (ort_intercept - intercept) / (slope - invslope);
528  else
529  pointout.w = point1->w;
530 
531  pointout.t = slope * pointout.w + intercept;
532 
533  return 0;
534  }
535 
536  ///////////////////////////////////
537  // Calculate wire,time coordinates of the Hit projection onto a line
538  //
539  ///////////////////////////////////
540  Int_t
542  Double_t wirestart,
543  Double_t timestart,
544  Double_t wire1,
545  Double_t time1,
546  Double_t& wireout,
547  Double_t& timeout) const
548  {
549  Double_t intercept = timestart - slope * (Double_t)wirestart;
550 
551  return GetPointOnLine(slope, intercept, wire1, time1, wireout, timeout);
552  }
553 
554  ///////////////////////////////////
555  // Calculate wire,time coordinates of the Hit projection onto a line
556  //
557  ///////////////////////////////////
558  Int_t
560  Double_t intercept,
561  Double_t ort_intercept,
562  Double_t& wireout,
563  Double_t& timeout) const
564  {
565  Double_t invslope = 0;
566 
567  if (slope) { invslope = -1. / slope; }
568 
569  invslope *= fWireTimetoCmCm * fWireTimetoCmCm;
570 
571  wireout = (ort_intercept - intercept) / (slope - invslope);
572  timeout = slope * wireout + intercept;
573 
574  wireout /= fWiretoCm;
575  timeout /= fTimetoCm;
576 
577  return 0;
578  }
579 
580  ///////////////////////////////////
581  // Calculate wire,time coordinates of the Hit projection onto a line
582  // slope should be in cm/cm space. PxPoint should be in cm/cm space.
583  ///////////////////////////////////
584  Int_t
586  double intercept,
587  double ort_intercept,
588  util::PxPoint& pointonline) const
589  {
590  Double_t invslope = 0;
591 
592  if (slope) invslope = -1. / slope;
593 
594  pointonline.w = (ort_intercept - intercept) / (slope - invslope);
595  pointonline.t = slope * pointonline.w + intercept;
596  return 0;
597  }
598 
599  //////////////////////////////////////////////////////////
600  Int_t
602  {
603 
604  // determine third plane number
605  for (UInt_t i = 0; i < fNPlanes; ++i) {
606  if (i == p0->plane || i == p1->plane) continue;
607  pN.plane = i;
608  }
609 
610  // Assuming there is no problem ( and we found the best pair that comes
611  // close in time ) we try to get the Y and Z coordinates for the start of
612  // the shower.
613  UInt_t chan1 = fGeom.PlaneWireToChannel(p0->plane, p0->w);
614  UInt_t chan2 = fGeom.PlaneWireToChannel(p1->plane, p1->w);
615  const double origin[3] = {0.};
616  Double_t pos[3] = {0.};
617  fGeom.Plane(p0->plane).LocalToWorld(origin, pos);
618  Double_t x = (p0->t - trigger_offset(fClocks)) * fTimetoCm + pos[0];
619 
620  Double_t y, z;
621  if (!fGeom.ChannelsIntersect(chan1, chan2, y, z)) return -1;
622 
623  pos[0] = x;
624  pos[1] = y;
625  pos[2] = z;
626 
627  pN = Get2DPointProjection(pos, pN.plane);
628 
629  return 0;
630  }
631 
632  //////////////////////////////////////////////////////////
633  Int_t
634  GeometryUtilities::GetYZ(const PxPoint* p0, const PxPoint* p1, Double_t* yz) const
635  {
636  Double_t y, z;
637 
638  // Force to the closest wires if not in the range
639  int z0 = p0->w / fWiretoCm;
640  int z1 = p1->w / fWiretoCm;
641  if (z0 < 0) {
642  std::cout << "\033[93mWarning\033[00m "
643  "\033[95m<<GeometryUtilities::GetYZ>>\033[00m"
644  << std::endl
645  << " 2D wire position " << p0->w << " [cm] corresponds to negative wire number."
646  << std::endl
647  << " Forcing it to wire=0..." << std::endl
648  << "\033[93mWarning ends...\033[00m" << std::endl;
649  z0 = 0;
650  }
651  else if (z0 >= (int)(fGeom.Nwires(p0->plane))) {
652  std::cout << "\033[93mWarning\033[00m "
653  "\033[95m<<GeometryUtilities::GetYZ>>\033[00m"
654  << std::endl
655  << " 2D wire position " << p0->w << " [cm] exceeds max wire number "
656  << (fGeom.Nwires(p0->plane) - 1) << std::endl
657  << " Forcing it to the max wire number..." << std::endl
658  << "\033[93mWarning ends...\033[00m" << std::endl;
659  z0 = fGeom.Nwires(p0->plane) - 1;
660  }
661  if (z1 < 0) {
662  std::cout << "\033[93mWarning\033[00m "
663  "\033[95m<<GeometryUtilities::GetYZ>>\033[00m"
664  << std::endl
665  << " 2D wire position " << p1->w << " [cm] corresponds to negative wire number."
666  << std::endl
667  << " Forcing it to wire=0..." << std::endl
668  << "\033[93mWarning ends...\033[00m" << std::endl;
669  z1 = 0;
670  }
671  if (z1 >= (int)(fGeom.Nwires(p1->plane))) {
672  std::cout << "\033[93mWarning\033[00m "
673  "\033[95m<<GeometryUtilities::GetYZ>>\033[00m"
674  << std::endl
675  << " 2D wire position " << p1->w << " [cm] exceeds max wire number "
676  << (fGeom.Nwires(p0->plane) - 1) << std::endl
677  << " Forcing it to the max wire number..." << std::endl
678  << "\033[93mWarning ends...\033[00m" << std::endl;
679  z1 = fGeom.Nwires(p1->plane) - 1;
680  }
681 
682  UInt_t chan1 = fGeom.PlaneWireToChannel(p0->plane, z0);
683  UInt_t chan2 = fGeom.PlaneWireToChannel(p1->plane, z1);
684 
685  if (!fGeom.ChannelsIntersect(chan1, chan2, y, z)) return -1;
686 
687  yz[0] = y;
688  yz[1] = z;
689 
690  return 0;
691  }
692 
693  //////////////////////////////////////////////////////////
694  Int_t
695  GeometryUtilities::GetXYZ(const PxPoint* p0, const PxPoint* p1, Double_t* xyz) const
696  {
697  const double origin[3] = {0.};
698  Double_t pos[3] = {0.};
699  fGeom.Plane(p0->plane).LocalToWorld(origin, pos);
700  Double_t x = (p0->t) - trigger_offset(fClocks) * fTimetoCm + pos[0];
701  double yz[2];
702 
703  GetYZ(p0, p1, yz);
704 
705  xyz[0] = x;
706  xyz[1] = yz[0];
707  xyz[2] = yz[1];
708 
709  return 0;
710  }
711 
712  //////////////////////////////////////////////////////////////
713 
714  PxPoint
715  GeometryUtilities::Get2DPointProjection(Double_t* xyz, Int_t plane) const
716  {
717 
718  PxPoint pN(0, 0, 0);
719  const double origin[3] = {0.};
720  Double_t pos[3];
721  fGeom.Plane(plane).LocalToWorld(origin, pos);
722  Double_t drifttick = (xyz[0] / fDriftVelocity) * (1. / fTimeTick);
723 
724  pos[1] = xyz[1];
725  pos[2] = xyz[2];
726 
727  ///\todo: this should use the cryostat and tpc as well in the NearestWire
728  /// method
729 
730  pN.w = fGeom.NearestWire(pos, plane);
731  pN.t = drifttick - (pos[0] / fDriftVelocity) * (1. / fTimeTick) + trigger_offset(fClocks);
732  pN.plane = plane;
733 
734  return pN;
735  }
736 
737  //////////////////////////////////////////////////////////////
738  // for now this returns the vlause in CM/CM space.
739  // this will become the default, but don't want to break the code that depends
740  // on the previous version. A.S. 03/26/14
741  //////////////////////////////////////
742 
743  PxPoint
744  GeometryUtilities::Get2DPointProjectionCM(std::vector<double> xyz, int plane) const
745  {
746 
747  PxPoint pN(0, 0, 0);
748 
749  Double_t pos[3]{0., xyz[1], xyz[2]};
750 
751  ///\todo: this should use the cryostat and tpc as well in the NearestWire
752  /// method
753 
754  pN.w = fGeom.NearestWire(pos, plane) * fWiretoCm;
755  pN.t = xyz[0];
756  pN.plane = plane;
757 
758  return pN;
759  }
760 
761  PxPoint
762  GeometryUtilities::Get2DPointProjectionCM(double* xyz, int plane) const
763  {
764 
765  PxPoint pN(0, 0, 0);
766 
767  Double_t pos[3]{0., xyz[1], xyz[2]};
768 
769  ///\todo: this should use the cryostat and tpc as well in the NearestWire
770  /// method
771 
772  pN.w = fGeom.NearestWire(pos, plane) * fWiretoCm;
773  pN.t = xyz[0];
774  pN.plane = plane;
775 
776  return pN;
777  }
778 
779  PxPoint
780  GeometryUtilities::Get2DPointProjectionCM(TLorentzVector* xyz, int plane) const
781  {
782  double xyznew[3] = {(*xyz)[0], (*xyz)[1], (*xyz)[2]};
783 
784  return Get2DPointProjectionCM(xyznew, plane);
785  }
786 
787  Double_t
788  GeometryUtilities::GetTimeTicks(Double_t x, Int_t plane) const
789  {
790 
791  const double origin[3] = {0.};
792  Double_t pos[3];
793  fGeom.Plane(plane).LocalToWorld(origin, pos);
794  Double_t drifttick = (x / fDriftVelocity) * (1. / fTimeTick);
795 
796  return drifttick - (pos[0] / fDriftVelocity) * (1. / fTimeTick) + trigger_offset(fClocks);
797  }
798 
799  //----------------------------------------------------------------------
800  // provide projected wire pitch for the view // copied from track.cxx and
801  // modified
802  Double_t
803  GeometryUtilities::PitchInView(UInt_t plane, Double_t phi, Double_t theta) const
804  {
805  Double_t dirs[3] = {0.};
806  GetDirectionCosines(phi, theta, dirs);
807 
808  /// \todo switch to using new Geometry::WireAngleToVertical(geo::View_t)
809  /// \todo and Geometry::WirePitch(geo::View_t) methods
810  Double_t wirePitch = 0.;
811  Double_t angleToVert = 0.;
812 
813  wirePitch = fGeom.WirePitch(plane);
814  angleToVert = fGeom.WireAngleToVertical(fGeom.Plane(plane).View()) - 0.5 * TMath::Pi();
815 
816  //(sin(angleToVert),std::cos(angleToVert)) is the direction perpendicular to
817  // wire fDir.front() is the direction of the track at the beginning of its
818  // trajectory
819  Double_t cosgamma =
820  TMath::Abs(TMath::Sin(angleToVert) * dirs[1] + TMath::Cos(angleToVert) * dirs[2]);
821 
822  if (cosgamma < 1.e-5)
823  // throw UtilException("cosgamma is basically 0, that can't be right");
824  {
825  std::cout << " returning 100" << std::endl;
826  return 100;
827  }
828 
829  return wirePitch / cosgamma;
830  }
831 
832  //////////////////////////////////////////////////
833  void
834  GeometryUtilities::GetDirectionCosines(Double_t phi, Double_t theta, Double_t* dirs) const
835  {
836  theta *= (TMath::Pi() / 180);
837  phi *= (TMath::Pi() / 180); // working on copies, it's ok.
838  dirs[0] = TMath::Cos(theta) * TMath::Sin(phi);
839  dirs[1] = TMath::Sin(theta);
840  dirs[2] = TMath::Cos(theta) * TMath::Cos(phi);
841  }
842 
843  void
844  GeometryUtilities::SelectLocalHitlist(const std::vector<util::PxHit>& hitlist,
845  std::vector<const util::PxHit*>& hitlistlocal,
846  util::PxPoint& startHit,
847  Double_t& linearlimit,
848  Double_t& ortlimit,
849  Double_t& lineslopetest) const
850  {
851  util::PxHit testHit;
853  hitlist, hitlistlocal, startHit, linearlimit, ortlimit, lineslopetest, testHit);
854  }
855 
856  //////////////////////////////////////////////////////////////////////////////////
857  ////
858  ///////////////////////////////////////////////////////////////////////////////////
859 
860  void
861  GeometryUtilities::SelectLocalHitlist(const std::vector<util::PxHit>& hitlist,
862  std::vector<const util::PxHit*>& hitlistlocal,
863  util::PxPoint& startHit,
864  Double_t& linearlimit,
865  Double_t& ortlimit,
866  Double_t& lineslopetest,
867  util::PxHit& averageHit) const
868  {
869 
870  hitlistlocal.clear();
871  std::vector<unsigned int> hitlistlocal_index;
872 
873  hitlistlocal_index.clear();
874 
876  hitlist, hitlistlocal_index, startHit, linearlimit, ortlimit, lineslopetest);
877 
878  double timesum = 0;
879  double wiresum = 0;
880  for (size_t i = 0; i < hitlistlocal_index.size(); ++i) {
881 
882  hitlistlocal.push_back((const util::PxHit*)(&(hitlist.at(hitlistlocal_index.at(i)))));
883  timesum += hitlist.at(hitlistlocal_index.at(i)).t;
884  wiresum += hitlist.at(hitlistlocal_index.at(i)).w;
885  }
886 
887  averageHit.plane = startHit.plane;
888  if (hitlistlocal.size()) {
889  averageHit.w = wiresum / (double)hitlistlocal.size();
890  averageHit.t = timesum / ((double)hitlistlocal.size());
891  }
892  }
893 
894  void
895  GeometryUtilities::SelectLocalHitlistIndex(const std::vector<util::PxHit>& hitlist,
896  std::vector<unsigned int>& hitlistlocal_index,
897  util::PxPoint& startHit,
898  Double_t& linearlimit,
899  Double_t& ortlimit,
900  Double_t& lineslopetest) const
901  {
902 
903  hitlistlocal_index.clear();
904  double locintercept = startHit.t - startHit.w * lineslopetest;
905 
906  for (size_t i = 0; i < hitlist.size(); ++i) {
907 
908  util::PxPoint hitonline;
909 
910  GetPointOnLine(lineslopetest, locintercept, (const util::PxHit*)(&hitlist.at(i)), hitonline);
911 
912  // calculate linear distance from start point and orthogonal distance from
913  // axis
914  Double_t lindist =
915  Get2DDistance((const util::PxPoint*)(&hitonline), (const util::PxPoint*)(&startHit));
916  Double_t ortdist =
917  Get2DDistance((const util::PxPoint*)(&hitlist.at(i)), (const util::PxPoint*)(&hitonline));
918 
919  if (lindist < linearlimit && ortdist < ortlimit) { hitlistlocal_index.push_back(i); }
920  }
921  }
922 
923  //////////////////////////////////////////////////////////////////
924  //////////////////////////////////////////////////////////////////
925 
926  void
927  GeometryUtilities::SelectPolygonHitList(std::vector<util::PxHit> const& hitlist,
928  std::vector<util::PxHit const*>& hitlistlocal) const
929  {
930  if (empty(hitlist)) { throw UtilException("Provided empty hit list!"); }
931 
932  hitlistlocal.clear();
933  unsigned char plane = hitlist.front().plane;
934 
935  // Define subset of hits to define polygon
936  std::map<double, const util::PxHit*> hitmap;
937  double qtotal = 0;
938  for (auto const& h : hitlist) {
939  hitmap.try_emplace(h.charge, &h);
940  qtotal += h.charge;
941  }
942  double qintegral = 0;
943  std::vector<const util::PxHit*> ordered_hits;
944  ordered_hits.reserve(hitlist.size());
945  for (auto hiter = hitmap.rbegin(); qintegral < qtotal * 0.95 && hiter != hitmap.rend();
946  ++hiter) {
947 
948  qintegral += (*hiter).first;
949  ordered_hits.push_back((*hiter).second);
950  }
951 
952  // Define container to hold found polygon corner PxHit index & distance
953  std::vector<size_t> hit_index(8, 0);
954  std::vector<double> hit_distance(8, 1e9);
955 
956  // Loop over hits and find corner points in the plane view
957  // Also fill corner edge points
958  std::vector<util::PxPoint> edges(4, PxPoint(plane, 0, 0));
959  double wire_max = fGeom.Nwires(plane) * fWiretoCm;
960  double time_max = fDetProp.NumberTimeSamples() * fTimetoCm;
961 
962  for (size_t index = 0; index < ordered_hits.size(); ++index) {
963 
964  if (ordered_hits.at(index)->t < 0 || ordered_hits.at(index)->w < 0 ||
965  ordered_hits.at(index)->t > time_max || ordered_hits.at(index)->w > wire_max) {
966 
967  throw UtilException(Form("Invalid wire/time (%g,%g) ... range is (0=>%g,0=>%g)",
968  ordered_hits.at(index)->w,
969  ordered_hits.at(index)->t,
970  wire_max,
971  time_max));
972  }
973 
974  double dist = 0;
975 
976  // Comparison w/ (Wire,0)
977  dist = ordered_hits.at(index)->t;
978  if (dist < hit_distance.at(1)) {
979  hit_distance.at(1) = dist;
980  hit_index.at(1) = index;
981  edges.at(0).t = ordered_hits.at(index)->t;
982  edges.at(1).t = ordered_hits.at(index)->t;
983  }
984 
985  // Comparison w/ (WireMax,Time)
986  dist = wire_max - ordered_hits.at(index)->w;
987  if (dist < hit_distance.at(3)) {
988  hit_distance.at(3) = dist;
989  hit_index.at(3) = index;
990  edges.at(1).w = ordered_hits.at(index)->w;
991  edges.at(2).w = ordered_hits.at(index)->w;
992  }
993 
994  // Comparison w/ (Wire,TimeMax)
995  dist = time_max - ordered_hits.at(index)->t;
996  if (dist < hit_distance.at(5)) {
997  hit_distance.at(5) = dist;
998  hit_index.at(5) = index;
999  edges.at(2).t = ordered_hits.at(index)->t;
1000  edges.at(3).t = ordered_hits.at(index)->t;
1001  }
1002 
1003  // Comparison w/ (0,Time)
1004  dist = ordered_hits.at(index)->w;
1005  if (dist < hit_distance.at(7)) {
1006  hit_distance.at(7) = dist;
1007  hit_index.at(7) = index;
1008  edges.at(0).w = ordered_hits.at(index)->w;
1009  edges.at(3).w = ordered_hits.at(index)->w;
1010  }
1011  }
1012  for (size_t index = 0; index < ordered_hits.size(); ++index) {
1013 
1014  double dist = 0;
1015  // Comparison w/ (0,0)
1016  dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(0).t,
1017  ordered_hits.at(index)->w - edges.at(0).w);
1018  if (dist < hit_distance.at(0)) {
1019  hit_distance.at(0) = dist;
1020  hit_index.at(0) = index;
1021  }
1022 
1023  // Comparison w/ (WireMax,0)
1024  dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(1).t,
1025  ordered_hits.at(index)->w - edges.at(1).w);
1026  if (dist < hit_distance.at(2)) {
1027  hit_distance.at(2) = dist;
1028  hit_index.at(2) = index;
1029  }
1030 
1031  // Comparison w/ (WireMax,TimeMax)
1032  dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(2).t,
1033  ordered_hits.at(index)->w - edges.at(2).w);
1034  if (dist < hit_distance.at(4)) {
1035  hit_distance.at(4) = dist;
1036  hit_index.at(4) = index;
1037  }
1038 
1039  // Comparison w/ (0,TimeMax)
1040  dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(3).t,
1041  ordered_hits.at(index)->w - edges.at(3).w);
1042  if (dist < hit_distance.at(6)) {
1043  hit_distance.at(6) = dist;
1044  hit_index.at(6) = index;
1045  }
1046  }
1047 
1048  // Loop over the resulting hit indexes and append unique hits to define the
1049  // polygon to the return hit list
1050  std::set<size_t> unique_index;
1051  std::vector<size_t> candidate_polygon;
1052  candidate_polygon.reserve(9);
1053  for (auto& index : hit_index) {
1054  if (unique_index.find(index) == unique_index.end()) {
1055  unique_index.insert(index);
1056  candidate_polygon.push_back(index);
1057  }
1058  }
1059  for (auto& index : hit_index) {
1060  candidate_polygon.push_back(index);
1061  break;
1062  }
1063 
1064  if (unique_index.size() > 8) throw UtilException("Size of the polygon > 8!");
1065 
1066  // Untangle Polygon
1067  candidate_polygon = PolyOverlap(ordered_hits, candidate_polygon);
1068 
1069  hitlistlocal.clear();
1070  for (unsigned int i = 0; i < (candidate_polygon.size() - 1); i++) {
1071  hitlistlocal.push_back((const util::PxHit*)(ordered_hits.at(candidate_polygon.at(i))));
1072  }
1073  // check that polygon does not have more than 8 sides
1074  if (unique_index.size() > 8) throw UtilException("Size of the polygon > 8!");
1075  }
1076 
1077  std::vector<size_t>
1078  GeometryUtilities::PolyOverlap(std::vector<const util::PxHit*> ordered_hits,
1079  std::vector<size_t> candidate_polygon) const
1080  {
1081  // loop over edges
1082  for (unsigned int i = 0; i < (candidate_polygon.size() - 1); i++) {
1083  double Ax = ordered_hits.at(candidate_polygon.at(i))->w;
1084  double Ay = ordered_hits.at(candidate_polygon.at(i))->t;
1085  double Bx = ordered_hits.at(candidate_polygon.at(i + 1))->w;
1086  double By = ordered_hits.at(candidate_polygon.at(i + 1))->t;
1087  // loop over edges that have not been checked yet...
1088  // only ones furhter down in polygon
1089  for (unsigned int j = i + 2; j < (candidate_polygon.size() - 1); j++) {
1090  // avoid consecutive segments:
1091  if (candidate_polygon.at(i) == candidate_polygon.at(j + 1))
1092  continue;
1093  else {
1094  double Cx = ordered_hits.at(candidate_polygon.at(j))->w;
1095  double Cy = ordered_hits.at(candidate_polygon.at(j))->t;
1096  double Dx = ordered_hits.at(candidate_polygon.at(j + 1))->w;
1097  double Dy = ordered_hits.at(candidate_polygon.at(j + 1))->t;
1098 
1099  if ((Clockwise(Ax, Ay, Cx, Cy, Dx, Dy) != Clockwise(Bx, By, Cx, Cy, Dx, Dy)) and
1100  (Clockwise(Ax, Ay, Bx, By, Cx, Cy) != Clockwise(Ax, Ay, Bx, By, Dx, Dy))) {
1101  size_t tmp = candidate_polygon.at(i + 1);
1102  candidate_polygon.at(i + 1) = candidate_polygon.at(j);
1103  candidate_polygon.at(j) = tmp;
1104  // check that last element is still first (to close circle...)
1105  candidate_polygon.at(candidate_polygon.size() - 1) = candidate_polygon.at(0);
1106  // swapped polygon...now do recursion to make sure
1107  return PolyOverlap(ordered_hits, candidate_polygon);
1108  } // if crossing
1109  }
1110  } // second loop
1111  } // first loop
1112  return candidate_polygon;
1113  }
1114 
1115  bool
1117  double const Ay,
1118  double const Bx,
1119  double const By,
1120  double const Cx,
1121  double const Cy) const
1122  {
1123  return (Cy - Ay) * (Bx - Ax) > (By - Ay) * (Cx - Ax);
1124  }
1125 
1126  util::PxHit
1127  GeometryUtilities::FindClosestHit(std::vector<util::PxHit> const& hitlist,
1128  unsigned int const wirein,
1129  double const timein) const
1130  {
1131  return hitlist[FindClosestHitIndex(hitlist, wirein, timein)];
1132  }
1133 
1134  unsigned int
1135  GeometryUtilities::FindClosestHitIndex(std::vector<util::PxHit> const& hitlist,
1136  unsigned int const wirein,
1137  double const timein) const
1138  {
1139  double min_length_from_start = 99999;
1140  unsigned int ret_ind = 0;
1141 
1142  for (unsigned int ii = 0; ii < hitlist.size(); ii++) {
1143  util::PxHit const& hit = hitlist[ii];
1144  double const dist_mod = Get2DDistance(wirein, timein, hit.w, hit.t);
1145  if (dist_mod < min_length_from_start) {
1146  min_length_from_start = dist_mod;
1147  ret_ind = ii;
1148  }
1149  }
1150 
1151  return ret_ind;
1152  }
1153 
1154 } // namespace
std::vector< Double_t > vertangle
detinfo::DetectorClocksData const & fClocks
Namespace for general, non-LArSoft-specific utilities.
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
Double_t Get2DDistance(Double_t wire1, Double_t time1, Double_t wire2, Double_t time2) const
std::vector< size_t > PolyOverlap(std::vector< const util::PxHit * > ordered_hits, std::vector< size_t > candidate_polygon) const
Class def header for exception classes used in GeometryUtilities.
WireGeo const & Wire(unsigned int iwire) const
Definition: PlaneGeo.cxx:506
Double_t Get2Dangle(Double_t deltawire, Double_t deltatime) const
Unknown view.
Definition: geo_types.h:136
constexpr T sum_of_squares(T x, T y)
Definition: pow.h:139
double Temperature() const
In kelvin.
bool ChannelsIntersect(raw::ChannelID_t c1, raw::ChannelID_t c2, double &y, double &z) const
Returns an intersection point of two channels.
util::PxHit FindClosestHit(std::vector< util::PxHit > const &hitlist, unsigned int wirein, double timein) const
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
Definition: WireGeo.h:250
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
Double_t PitchInView(UInt_t plane, Double_t phi, Double_t theta) const
double Efield(unsigned int planegap=0) const
kV/cm
detinfo::DetectorPropertiesData const & fDetProp
3-dimensional objects, potentially hits, clusters, prongs, etc.
Definition: geo_types.h:135
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
Double_t Get2DPitchDistance(Double_t angle, Double_t inwire, Double_t wire) const
T abs(T value)
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:184
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
const double e
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
double t
Definition: PxUtils.h:11
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
double alpha
Definition: doAna.cpp:15
geo::GeometryCore const & fGeom
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
Double_t Get3DSpecialCaseTheta(Int_t iplane0, Int_t iplane1, Double_t dw0, Double_t dw1) const
Double_t GetTimeTicks(Double_t x, Int_t plane) const
void SelectLocalHitlistIndex(const std::vector< util::PxHit > &hitlist, std::vector< unsigned int > &hitlistlocal_index, util::PxPoint &startHit, Double_t &linearlimit, Double_t &ortlimit, Double_t &lineslopetest) const
string tmp
Definition: languages.py:63
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
Description of geometry of one entire detector.
Detector simulation of raw signals on wires.
double w
Definition: PxUtils.h:10
Encapsulate the geometry of a wire.
Int_t GetPointOnLine(Double_t slope, Double_t intercept, Double_t wire1, Double_t time1, Double_t &wireout, Double_t &timeout) const
bool Clockwise(double Ax, double Ay, double Bx, double By, double Cx, double Cy) const
Double_t Get2DPitchDistanceWSlope(Double_t slope, Double_t inwire, Double_t wire) const
Int_t GetYZ(const PxPoint *p0, const PxPoint *p1, Double_t *yz) const
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double Get2DangleFrom3D(unsigned int plane, double phi, double theta) const
GeometryUtilities(geo::GeometryCore const &geom, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &propData)
Int_t GetProjectedPoint(const PxPoint *p0, const PxPoint *p1, PxPoint &pN) const
void GetDirectionCosines(Double_t phi, Double_t theta, Double_t *dirs) const
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
PxPoint Get2DPointProjection(Double_t *xyz, Int_t plane) const
int trigger_offset(DetectorClocksData const &data)
Access the description of detector geometry.
list x
Definition: train.py:276
constexpr double kINVALID_DOUBLE
unsigned int FindClosestHitIndex(std::vector< util::PxHit > const &hitlist, unsigned int wirein, double timein) const
PxPoint Get2DPointProjectionCM(std::vector< double > xyz, int plane) const
Double_t CalculatePitch(UInt_t iplane0, Double_t phi, Double_t theta) const
void SelectPolygonHitList(const std::vector< util::PxHit > &hitlist, std::vector< const util::PxHit * > &hitlistlocal) const
Int_t GetPointOnLineWSlopes(Double_t slope, Double_t intercept, Double_t ort_intercept, Double_t &wireout, Double_t &timeout) const
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
Double_t Get2Dslope(Double_t deltawire, Double_t deltatime) const
Int_t GetXYZ(const PxPoint *p0, const PxPoint *p1, Double_t *xyz) const
Int_t Get3DaxisN(Int_t iplane0, Int_t iplane1, Double_t omega0, Double_t omega1, Double_t &phi, Double_t &theta) const
void LocalToWorld(const double *plane, double *world) const
Transform point from local plane frame to world frame.
Definition: PlaneGeo.h:1343
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
unsigned int plane
Definition: PxUtils.h:12
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
QTextStream & endl(QTextStream &s)
void SelectLocalHitlist(const std::vector< util::PxHit > &hitlist, std::vector< const util::PxHit * > &hitlistlocal, util::PxPoint &startHit, Double_t &linearlimit, Double_t &ortlimit, Double_t &lineslopetest) const
Double_t CalculatePitchPolar(UInt_t iplane0, Double_t phi, Double_t theta) const