Belle II Software  release-08-01-10
InverseRaytracer.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <top/reconstruction_cpp/InverseRaytracer.h>
10 #include <top/reconstruction_cpp/func.h>
11 #include <framework/logging/Logger.h>
12 #include <cmath>
13 
14 namespace Belle2 {
19  namespace TOP {
20 
21  double InverseRaytracer::s_maxLen = 10000;
22 
24  cosThc(cosTheta), sinThc(sqrt(1 - cosTheta * cosTheta))
25  {}
26 
27 
28  InverseRaytracer::Solution::Solution(double cfi, double sfi):
29  cosFic(cfi), sinFic(sfi)
30  {}
31 
32 
34  {
35  double a = trk.cosTh * cer.sinThc * cosFic + trk.sinTh * cer.cosThc;
36  double b = cer.sinThc * sinFic;
37  kx = a * trk.cosFi - b * trk.sinFi;
38  ky = a * trk.sinFi + b * trk.cosFi;
39  kz = trk.cosTh * cer.cosThc - trk.sinTh * cer.sinThc * cosFic;
40  }
41 
42  void InverseRaytracer::Solution::setTotalReflStatus(double A, double B, double cosTotal)
43  {
44  totRefl = (std::abs(kx) < cosTotal or std::abs(xD) < A / 2) and (std::abs(ky) < cosTotal or std::abs(yB) < B / 2);
45  }
46 
47  void InverseRaytracer::Solution::setTotalReflStatus(double A, double B, double cosTotal, double Kx, double Ky)
48  {
49  bool beforeMirror = (std::abs(kx) < cosTotal or Nxm == 0) and (std::abs(ky) < cosTotal or Nym == 0);
50  bool afterMirror = (std::abs(Kx) < cosTotal or std::abs(xD) < A / 2) and (std::abs(Ky) < cosTotal or std::abs(yB) < B / 2);
51  totRefl = beforeMirror and afterMirror;
52  }
53 
55  {
56  return (len > 0 and len < s_maxLen and totRefl);
57  }
58 
60  {
61  m_solutions[0].clear();
62  m_solutions[1].clear();
63  m_ok[0] = false;
64  m_ok[1] = false;
65  }
66 
67  int InverseRaytracer::solveDirect(double xD, double zD,
68  const TOPTrack::AssumedEmission& assumedEmission,
69  const CerenkovAngle& cer, double step) const
70  {
71  const auto& emiPoint = assumedEmission.position;
72  const auto& trk = assumedEmission.trackAngles;
73  bool first = m_solutions[0].empty();
74  if (first) {
75  m_emiPoint = emiPoint;
76  m_cer = cer;
77  m_trk = trk;
78  }
79 
80  double dx = xD - emiPoint.X();
81  double dz = zD - emiPoint.Z();
82 
83  double dxdz = dx / dz;
84  if (not solve(dxdz, cer, trk)) return c_NoEquationSolution;
85 
86  for (int i = 0; i < 2; i++) {
87  auto& sol = m_solutions[i].back();
88  sol.xD = xD;
89  sol.zD = zD;
90  sol.step = step;
91  sol.len = dz / sol.kz;
92  double dydz = sol.ky / sol.kz;
93  sol.yD = emiPoint.Y() + dydz * dz;
94  sol.yB = emiPoint.Y() + dydz * (m_prism.zR - emiPoint.Z());
95  if (first) {
96  m_ok[i] = true;
97  sol.setTotalReflStatus(m_bars[0].A, m_bars[0].B, m_cosTotal);
98  }
99  if (not sol.getStatus()) m_ok[i] = false;
100  }
101 
102  if (not(m_ok[0] or m_ok[1])) return c_NoPhysicsSolution;
103 
104  return m_solutions[0].size() - 1;
105  }
106 
107 
108  int InverseRaytracer::solveReflected(double xD, double zD, int Nxm, double xmMin, double xmMax,
109  const TOPTrack::AssumedEmission& assumedEmission,
110  const CerenkovAngle& cer, double step) const
111  {
112  const auto& emiPoint = assumedEmission.position;
113  const auto& trk = assumedEmission.trackAngles;
114  bool first = m_solutions[0].empty();
115  if (first) {
116  m_emiPoint = emiPoint;
117  m_cer = cer;
118  m_trk = trk;
119  }
120 
121  double A = m_bars[0].A;
122  double B = m_bars[0].B;
123 
124  double xM = 0;
125  double zM = 0;
126  double dxdz = 0;
127  if (Nxm % 2 == 0) {
128  double xE = func::unfold(emiPoint.X(), -Nxm, A);
129  double zE = emiPoint.Z();
130  bool ok = findReflectionPoint(xE, zE, xD, zD, xmMin, xmMax, xM, zM, dxdz);
131  if (not ok) return c_NoReflectionPoint;
132  } else {
133  double xE = func::unfold(emiPoint.X(), Nxm, A);
134  double zE = emiPoint.Z();
135  bool ok = findReflectionPoint(xE, zE, xD, zD, xmMin, xmMax, xM, zM, dxdz);
136  if (not ok) return c_NoReflectionPoint;
137  dxdz = -dxdz;
138  }
139 
140  bool ok = solve(dxdz, cer, trk);
141  if (not ok) return c_NoEquationSolution;
142 
143  double normX = (xM - m_mirror.xc) / m_mirror.R;
144  double normZ = (zM - m_mirror.zc) / m_mirror.R;
145 
146  for (int i = 0; i < 2; i++) {
147  auto& sol = m_solutions[i].back();
148  sol.xD = xD;
149  sol.zD = zD;
150  sol.step = step;
151  sol.Nxm = Nxm;
152 
153  double len = (zM - emiPoint.Z()) / sol.kz;
154  if (len < 0) {
155  m_ok[i] = false;
156  continue;
157  }
158  sol.len = len;
159  int Nym = lround((emiPoint.Y() + len * sol.ky) / B);
160 
161  double kx = func::unfold(sol.kx, Nxm);
162  double ky = func::unfold(sol.ky, Nym);
163  double kz = sol.kz;
164  double s = 2 * (kx * normX + kz * normZ);
165  kx -= s * normX;
166  kz -= s * normZ;
167 
168  len = (zD - zM) / kz;
169  if (len < 0) {
170  m_ok[i] = false;
171  continue;
172  }
173  sol.len += len;
174 
175  sol.yD = m_mirror.yc + len * ky;
176  sol.yB = m_mirror.yc + (m_prism.zR - zM) / kz * ky;
177  sol.Nym = Nym;
178 
179  if (first) {
180  m_ok[i] = true;
181  sol.setTotalReflStatus(A, B, m_cosTotal, kx, ky);
182  }
183  if (not sol.getStatus()) m_ok[i] = false;
184  }
185 
186  if (not(m_ok[0] or m_ok[1])) return c_NoPhysicsSolution;
187 
188  return m_solutions[0].size() - 1;
189  }
190 
191 
193  const TOPTrack::AssumedEmission& assumedEmission,
194  const CerenkovAngle& cer) const
195  {
196  const auto& emiPoint = assumedEmission.position;
197  const auto& trk = assumedEmission.trackAngles;
198  bool first = m_solutions[0].empty();
199  if (first) {
200  m_emiPoint = emiPoint;
201  m_cer = cer;
202  m_trk = trk;
203  }
204 
205  double A = m_bars[0].A;
206  double B = m_bars[0].B;
207 
208  double zM = m_mirror.zc + sqrt(pow(m_mirror.R, 2) - pow(xM - m_mirror.xc, 2));
209  double dx = func::unfold(xM, Nxm, A) - emiPoint.X();
210  double dz = zM - emiPoint.Z();
211  double dxdz = dx / dz;
212 
213  bool ok = solve(dxdz, cer, trk);
214  if (not ok) return c_NoEquationSolution;
215 
216  double normX = (xM - m_mirror.xc) / m_mirror.R;
217  double normZ = (zM - m_mirror.zc) / m_mirror.R;
218  double zD = m_prism.zD;
219 
220  for (int i = 0; i < 2; i++) {
221  auto& sol = m_solutions[i].back();
222  sol.zD = zD;
223  sol.Nxm = Nxm;
224 
225  double len = (zM - emiPoint.Z()) / sol.kz;
226  if (len < 0) {
227  m_ok[i] = false;
228  continue;
229  }
230  sol.len = len;
231  int Nym = lround((emiPoint.Y() + len * sol.ky) / B);
232 
233  double kx = func::unfold(sol.kx, Nxm);
234  double ky = func::unfold(sol.ky, Nym);
235  double kz = sol.kz;
236  double s = 2 * (kx * normX + kz * normZ);
237  kx -= s * normX;
238  kz -= s * normZ;
239 
240  len = (zD - zM) / kz;
241  if (len < 0) {
242  m_ok[i] = false;
243  continue;
244  }
245  sol.len += len;
246 
247  sol.xD = xM + len * kx;
248  sol.yD = m_mirror.yc + len * ky;
249  sol.yB = m_mirror.yc + (m_prism.zR - zM) / kz * ky;
250  sol.Nym = Nym;
251  m_ok[i] = sol.getStatus();
252  }
253 
254  if (not(m_ok[0] or m_ok[1])) return c_NoPhysicsSolution;
255 
256  return m_solutions[0].size() - 1;
257  }
258 
260  {
261  for (int i = 0; i < 2; i++) {
262  const auto& solutions = m_solutions[i];
263  if (m_ok[i] and solutions.back().Nym != solutions.front().Nym) return true;
264  }
265  return false;
266  }
267 
268  bool InverseRaytracer::solve(double dxdz, const CerenkovAngle& cer, const TOPTrack::TrackAngles& trk) const
269  {
270  double a = (dxdz * trk.cosTh - trk.cosFi * trk.sinTh) * cer.cosThc;
271  double b = (dxdz * trk.sinTh + trk.cosFi * trk.cosTh) * cer.sinThc;
272  double d = trk.sinFi * cer.sinThc;
273 
274  double B = b * b + d * d;
275  if (B == 0) return false;
276 
277  if (d == 0) {
278  double cfic = a / b;
279  if (std::abs(cfic) > 1) return false;
280  double sfic = sqrt(1 - cfic * cfic);
281  m_solutions[0].push_back(Solution(cfic, sfic));
282  m_solutions[1].push_back(Solution(cfic, -sfic));
283  } else {
284  double D = B - a * a;
285  if (D < 0) return false;
286  D = d * sqrt(D);
287  double ab = a * b;
288  double cfic = (ab + D) / B;
289  m_solutions[0].push_back(Solution(cfic, (b * cfic - a) / d));
290  cfic = (ab - D) / B;
291  m_solutions[1].push_back(Solution(cfic, (b * cfic - a) / d));
292  }
293  m_solutions[0].back().setDirection(cer, trk);
294  m_solutions[1].back().setDirection(cer, trk);
295 
296  return true;
297  }
298 
299 
300  double InverseRaytracer::getDeltaXE(double x, double xe, double ze, double xd, double zd) const
301  {
302  double z = sqrt(1 - x * x);
303  double kx = (x - xd);
304  double kz = (z - zd);
305  double s = 2 * (kx * x + kz * z);
306  kx -= s * x;
307  kz -= s * z;
308 
309  return x + (ze - z) * kx / kz - xe;
310  }
311 
312 
313  bool InverseRaytracer::findReflectionPoint(double xE, double zE, double xD, double zD,
314  double xmMin, double xmMax,
315  double& xM, double& zM, double& dxdz) const
316  {
317  double xe = (xE - m_mirror.xc) / m_mirror.R;
318  double ze = (zE - m_mirror.zc) / m_mirror.R;
319  double xd = (xD - m_mirror.xc) / m_mirror.R;
320  double zd = (zD - m_mirror.zc) / m_mirror.R;
321 
322  double x1 = (xmMin - m_mirror.xc) / m_mirror.R;
323  double y1 = getDeltaXE(x1, xe, ze, xd, zd);
324 
325  double x2 = (xmMax - m_mirror.xc) / m_mirror.R;
326  double y2 = getDeltaXE(x2, xe, ze, xd, zd);
327 
328  if (y1 * y2 > 0) return false; // no (single) solution
329 
330  for (int i = 0; i < 20; i++) {
331  double x = (x1 + x2) / 2;
332  double y = getDeltaXE(x, xe, ze, xd, zd);
333  if (y * y1 < 0) {
334  x2 = x;
335  } else {
336  x1 = x;
337  y1 = y;
338  }
339  }
340  double x = (x1 + x2) / 2;
341  double z = sqrt(1 - x * x);
342  xM = x * m_mirror.R + m_mirror.xc;
343  zM = z * m_mirror.R + m_mirror.zc;
344 
345  double kx = (x - xd);
346  double kz = (z - zd);
347  double s = 2 * (kx * x + kz * z);
348  kx -= s * x;
349  kz -= s * z;
350  dxdz = kx / kz;
351 
352  return true;
353  }
354 
355 
357  {
358  if (DFic == 0) {
359  return PhotonState(m_emiPoint, sol.kx, sol.ky, sol.kz);
360  } else {
361  double cosDFic = cos(DFic);
362  double sinDFic = sin(DFic);
363  double cosFic = sol.cosFic * cosDFic - sol.sinFic * sinDFic;
364  double sinFic = sol.sinFic * cosDFic + sol.cosFic * sinDFic;
365  double a = m_trk.cosTh * m_cer.sinThc * cosFic + m_trk.sinTh * m_cer.cosThc;
366  double b = m_cer.sinThc * sinFic;
367  double kx = a * m_trk.cosFi - b * m_trk.sinFi;
368  double ky = a * m_trk.sinFi + b * m_trk.cosFi;
369  double kz = m_trk.cosTh * m_cer.cosThc - m_trk.sinTh * m_cer.sinThc * cosFic;
370  return PhotonState(m_emiPoint, kx, ky, kz);
371  }
372  }
373 
374 
375  } //TOP
377 } //Belle2
378 
double m_cosTotal
cosine of total reflection angle
int solveReflected(double xD, double zD, int Nxm, double xmMin, double xmMax, const TOPTrack::AssumedEmission &assumedEmission, const CerenkovAngle &cer, double step=0) const
Solve inverse ray-tracing for reflected photon.
PhotonState getReconstructedPhoton(const Solution &sol, double DFic=0) const
Returns reconstructed photon at emission for a given solution of inverse raytracing.
int solveForReflectionPoint(double xM, int Nxm, const TOPTrack::AssumedEmission &assumedEmission, const CerenkovAngle &cer) const
Solve inverse ray-tracing for a given reflection point on the mirror.
bool solve(double dxdz, const CerenkovAngle &cer, const TOPTrack::TrackAngles &trk) const
Solve inverse ray-tracing for unknown azimuthal Cerenkov angle.
@ c_NoEquationSolution
no solution of equation
@ c_NoReflectionPoint
position on the mirror not found
@ c_NoPhysicsSolution
no physics solution
double getDeltaXE(double x, double xe, double ze, double xd, double zd) const
Returns the difference between input xe and the reflected position at given x.
bool findReflectionPoint(double xE, double zE, double xD, double zD, double xmMin, double xmMax, double &xM, double &zM, double &dxdz) const
Finds reflection point on the mirror using semi-linear optics approximation.
bool isNymDifferent() const
Checks if Nym differs between solutions front and back in at least one of the vectors.
ROOT::Math::XYZPoint m_emiPoint
temporary storage of emission point
static double s_maxLen
maximal allowed propagation length
CerenkovAngle m_cer
temporary storage of Cerenkov angle
int solveDirect(double xD, double zD, const TOPTrack::AssumedEmission &assumedEmission, const CerenkovAngle &cer, double step=0) const
Solve inverse ray-tracing for direct photon.
std::vector< Solution > m_solutions[2]
storage for the two solutions
void clear() const
Clear the solutions to prepare for the new round.
bool m_ok[2]
status of solutions
TOPTrack::TrackAngles m_trk
temporary storage of track polar and azimuthal angles
State of the Cerenkov photon in the quartz optics.
Definition: PhotonState.h:27
Mirror m_mirror
spherical mirror geometry data
Prism m_prism
prism geometry data
std::vector< BarSegment > m_bars
geometry data of bar segments
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
double unfold(double x, int nx, double A)
unfold a coordinate.
Definition: func.h:31
Abstract base class for different kinds of events.
Sine and cosine of Cerenkov angle.
double cosThc
cosine of Cerenkov angle
Solution of inverse ray-tracing.
void setDirection(const CerenkovAngle &cer, const TOPTrack::TrackAngles &trk)
Sets photon direction.
bool getStatus() const
Returns status.
Solution(double cfi, double sfi)
constructor
double cosFic
cosine of azimuthal Cerenkov angle
double ky
photon direction in y at emission
void setTotalReflStatus(double A, double B, double cosTotal)
Sets total reflection status for direct photon.
double sinFic
sine of azimuthal Cerenkov angle
double kz
photon direction in z at emission
double kx
photon direction in x at emission
double yc
center of curvature in y
Definition: RaytracerBase.h:82
double xc
center of curvature in x
Definition: RaytracerBase.h:81
double zc
center of curvature in z
Definition: RaytracerBase.h:83
double zR
maximal z, i.e position of prism-bar joint
double zD
detector (photo-cathode) position
assumed photon emission point in local frame
Definition: TOPTrack.h:74
ROOT::Math::XYZPoint position
position
Definition: TOPTrack.h:75
TrackAngles trackAngles
sine and cosine of track polar and azimuthal angles
Definition: TOPTrack.h:76
Sine and cosine of track polar and azimuthal angles at assumed photon emission.
Definition: TOPTrack.h:46
double sinFi
sine of azimuthal angle
Definition: TOPTrack.h:50
double cosFi
cosine of azimuthal angle
Definition: TOPTrack.h:49
double cosTh
cosine of polar angle
Definition: TOPTrack.h:47
double sinTh
sine of polar angle
Definition: TOPTrack.h:48