Belle II Software development
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
14namespace 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