Belle II Software development
PhotonState.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/PhotonState.h>
10#include <top/reconstruction_cpp/func.h>
11#include <framework/logging/Logger.h>
12#include <cmath>
13#include <algorithm>
14
15using namespace std;
16
17namespace Belle2 {
22 namespace TOP {
23
24 double PhotonState::s_maxLen = 10000;
25
26 PhotonState::PhotonState(const ROOT::Math::XYZPoint& position, const ROOT::Math::XYZVector& direction):
27 m_x(position.X()), m_y(position.Y()), m_z(position.Z()),
28 m_kx(direction.X()), m_ky(direction.Y()), m_kz(direction.Z()),
29 m_status(true)
30 {}
31
32
33 PhotonState::PhotonState(const ROOT::Math::XYZPoint& position, double kx, double ky, double kz):
34 m_x(position.X()), m_y(position.Y()), m_z(position.Z()),
35 m_kx(kx), m_ky(ky), m_kz(kz),
36 m_status(true)
37 {}
38
39 PhotonState::PhotonState(const ROOT::Math::XYZPoint& position, const ROOT::Math::XYZVector& trackDir,
40 double thc, double fic):
41 m_x(position.X()), m_y(position.Y()), m_z(position.Z()),
42 m_status(true)
43 {
44 ROOT::Math::XYZVector dir(cos(fic) * sin(thc), sin(fic) * sin(thc), cos(thc));
45 func::rotateUz(dir, trackDir);
46 m_kx = dir.X();
47 m_ky = dir.Y();
48 m_kz = dir.Z();
49 }
50
52 {
53 if (std::abs(m_x) > bar.A / 2) return false;
54 if (std::abs(m_y) > bar.B / 2) return false;
55 if (m_z < bar.zL or m_z > bar.zR) return false;
56 return true;
57 }
58
59
61 {
62 if (std::abs(m_x) > bar.A / 2) return false;
63 if (std::abs(m_y) > bar.B / 2) return false;
64 if (m_z < bar.zL) return false;
65 double Rsq = pow(m_x - mirror.xc, 2) + pow(m_y - mirror.yc, 2) + pow(m_z - mirror.zc, 2);
66 if (Rsq > pow(mirror.R, 2)) return false;
67 return true;
68 }
69
70
72 {
73 if (std::abs(m_x) > prism.A / 2) return false;
74 if (m_z < prism.zL or m_z > prism.zR) return false;
75 if (m_y > prism.yUp or m_y < prism.yDown) return false;
76 double y = prism.yDown + (prism.yDown + prism.B / 2) / (prism.zFlat - prism.zR) * (m_z - prism.zFlat);
77 if (m_y < y) return false;
78 return true;
79 }
80
81
83 {
84 if (not m_status) return;
85
86 // local copies: stores to the data members would otherwise be assumed to alias bar
87 const double A = bar.A;
88 const double B = bar.B;
89 double x = m_x;
90 double y = m_y;
91 double kx = m_kx;
92 double ky = m_ky;
93
94 m_cosx = std::abs(kx);
95 m_cosy = std::abs(ky);
96 m_A = A;
97 m_B = B;
99
100 double z = bar.zR;
101 if (m_kz < 0) z = bar.zL;
102 if (z == m_z) return;
103
104 m_status = false;
105
106 double len = (z - m_z) / m_kz;
107 if (len < 0 or len > s_maxLen) return;
108
109 func::fold(x + len * kx, A, x, kx, m_nx);
110 func::fold(y + len * ky, B, y, ky, m_ny);
111
112 m_propLen += len;
113 m_x = x;
114 m_y = y;
115 m_kx = kx;
116 m_ky = ky;
117 m_z = z;
118
119 m_status = true;
120 }
121
122
124 {
125 if (not m_status) return;
126
127 m_cosx = std::abs(m_kx);
128 m_cosy = std::abs(m_ky);
129 m_A = bar.A;
130 m_B = bar.B;
132
133 m_status = false;
134
135 if (m_kz < 0) return;
136
137 double len = 0;
138 if (m_z < mirror.zb) {
139 len = (mirror.zb - m_z) / m_kz;
140 if (len > s_maxLen) return;
141 }
142
143 double xm = m_x + len * m_kx;
144 int nx = func::lround(xm / bar.A);
145 double ss = m_kx * m_kx + m_kz * m_kz;
146 if (ss == 0) return;
147 int i = 0;
148 while (true) {
149 double xc = func::unfold(mirror.xc, nx, bar.A);
150 double x = m_x - xc;
151 double z = m_z - mirror.zc;
152 double rdir = x * m_kx + z * m_kz;
153 double rr = x * x + z * z;
154 double D = rdir * rdir + (mirror.R * mirror.R - rr) * ss;
155 if (D < 0) return;
156 D = sqrt(D);
157 len = (D - rdir) / ss;
158 if (len < 0 or len > s_maxLen) return;
159 double xmm = m_x + len * m_kx;
160 int nxx = func::lround(xmm / bar.A);
161 if (nxx == nx) break;
162 i++;
163 if (i == 10) {
164 if (std::abs(xmm - xm) < 0.001) break;
165 B2DEBUG(20, "TOP::PhotonState::propagateSemiLinear: not converging");
166 return;
167 }
168 nx = nxx;
169 xm = xmm;
170 }
171
172 m_propLen += len;
173
174 func::fold(m_x + len * m_kx, bar.A, m_x, m_kx, m_nx);
175 func::fold(m_y + len * m_ky, bar.B, m_y, m_ky, m_ny);
176 m_y = mirror.yc;
177 m_z += len * m_kz;
178
179 double normX = (m_x - mirror.xc) / mirror.R;
180 double normZ = (m_z - mirror.zc) / mirror.R;
181 double s = 2 * (m_kx * normX + m_kz * normZ);
182 m_kx -= s * normX;
183 m_kz -= s * normZ;
184
185 m_status = true;
186 }
187
188
190 {
191 if (not m_status) return;
192
193 m_cosx = std::abs(m_kx);
194 m_cosy = std::abs(m_ky);
195 m_A = bar.A;
196 m_B = bar.B;
198
199 m_status = false;
200
201 if (m_kz < 0) return;
202
203 double len = 0;
204 if (m_z < mirror.zb) {
205 len = (mirror.zb - m_z) / m_kz;
206 if (len > s_maxLen) return;
207 }
208
209 double xm = m_x + len * m_kx;
210 int nx = func::lround(xm / bar.A);
211 double ym = m_y + len * m_ky;
212 int ny = func::lround(ym / bar.B);
213 int i = 0;
214 while (true) {
215 double xc = func::unfold(mirror.xc, nx, bar.A);
216 double yc = func::unfold(mirror.yc, ny, bar.B);
217 double x = m_x - xc;
218 double y = m_y - yc;
219 double z = m_z - mirror.zc;
220 double rdir = x * m_kx + y * m_ky + z * m_kz;
221 double rr = x * x + y * y + z * z;
222 double D = rdir * rdir + (mirror.R * mirror.R - rr);
223 if (D < 0) return;
224 D = sqrt(D);
225 len = (D - rdir);
226 if (len < 0 or len > s_maxLen) return;
227 double xmm = m_x + len * m_kx;
228 int nxx = func::lround(xmm / bar.A);
229 double ymm = m_y + len * m_ky;
230 int nyy = func::lround(ymm / bar.B);
231 if (nxx == nx and nyy == ny) break;
232 i++;
233 if (i == 10) {
234 if (std::abs(xmm - xm) < 0.001 and std::abs(ymm - ym) < 0.001) break;
235 B2DEBUG(20, "TOP::PhotonState::propagateExact: not converging");
236 return;
237 }
238 nx = nxx;
239 ny = nyy;
240 }
241
242 m_propLen += len;
243
244 func::fold(m_x + len * m_kx, bar.A, m_x, m_kx, m_nx);
245 func::fold(m_y + len * m_ky, bar.B, m_y, m_ky, m_ny);
246 m_z += len * m_kz;
247
248 double normX = (m_x - mirror.xc) / mirror.R;
249 double normY = (m_y - mirror.yc) / mirror.R;
250 double normZ = (m_z - mirror.zc) / mirror.R;
251 double s = 2 * (m_kx * normX + m_ky * normY + m_kz * normZ);
252 m_kx -= s * normX;
253 m_ky -= s * normY;
254 m_kz -= s * normZ;
255
256 m_status = true;
257 }
258
259
261 {
262 if (not m_status) return;
263
264 m_status = false;
265
266 // Work on local copies of the state and of the prism geometry. Writing to the data members
267 // inside the loop below would force the compiler to re-load the window data on every
268 // iteration (a double stored through 'this' may alias the doubles of the unfolded windows).
269
270 double x = m_x;
271 double y = m_y;
272 double z = m_z;
273 double kx = m_kx;
274 double ky = m_ky;
275 double kz = m_kz;
276 double propLen = m_propLen;
277 double cosy = m_cosy;
278
279 const double prismA = prism.A;
280 const double yUp = prism.yUp;
281 const double yDown = prism.yDown;
282 const double zR = prism.zR;
283 const double zFlat = prism.zFlat;
284 const double zDet = prism.zD;
285
286 m_cosx = std::abs(kx);
287 m_A = prismA;
288 m_B = yUp - yDown;
289 m_y0 = (yUp + yDown) / 2;
290 m_type = c_Prism;
291
292 if (kz > 0) {
293 if (z >= zR or std::abs(ky / kz) < std::abs(prism.slope)) return;
294 if (std::abs(y + ky / kz * (zR - z)) < prism.B / 2) return;
295 }
296 const double ky_in = ky;
297 const double kz_in = kz;
298
299 double yD = y;
300 double zD = z;
301
302 if (z > zFlat) {
303
304 int step = 1;
305 int ii = 0;
306 if (ky < 0) {
307 step = -1;
308 ii = 1;
309 y = std::min(y, yUp);
310 }
311
312 const auto* windows = prism.unfoldedWindows.data();
313 const unsigned numWindows = prism.unfoldedWindows.size();
314 const int k0 = prism.k0;
315
316 bool found = false;
317 unsigned k = k0;
318 while (k < numWindows) {
319 const auto& win = windows[k];
320 double s = ky * win.sz - kz * win.sy;
321 if (s != 0) {
322 double len = ((win.y0 - y) * win.sz - (win.z0 - z) * win.sy) / s;
323 yD = y + len * ky;
324 zD = z + len * kz;
325 double yu = yD - win.y0;
326 double zu = zD - win.z0;
327 double yw = yu * win.sy + zu * win.sz;
328 if (yw >= yDown and yw <= yUp) {
329 if (len < 0 or len > s_maxLen) return;
330 double kyNew = ky * win.sy + kz * win.sz;
331 double kzNew = kz * win.sy - ky * win.sz;
332 int ny = k - k0;
333 x += len * kx;
334 y = yw;
335 ky = kyNew;
336 m_ny = ny;
337 z = zFlat;
338 kz = ny % 2 == 0 ? kzNew : -kzNew;
339 propLen += len;
340 found = true;
341 break;
342 }
343 cosy = std::max(cosy, std::abs(ky_in * win.nsy[ii] + kz_in * win.nsz[ii]));
344 }
345 k += step;
346 ii ^= 1;
347 }
348
349 if (not found) {
350 B2DEBUG(20, "TOP::PhotonState::propagate: unfolded prism window not found"
351 << LogVar("yUp", prism.yUp) << LogVar("yDown", prism.yDown) << LogVar("zR", prism.zR)
352 << LogVar("y", y) << LogVar("z", z)
353 << LogVar("ky", ky_in) << LogVar("kz", kz_in));
354 return;
355 }
356 }
357
358 double len = (zDet - z) / kz;
359 if (len < 0 or len > s_maxLen) return;
360
361 func::fold(x + len * kx, prismA, x, kx, m_nx);
362 y += len * ky;
363 z = zDet;
364 propLen += len;
365 yD += len * ky_in;
366 zD += len * kz_in;
367
368 m_x = x;
369 m_y = y;
370 m_z = z;
371 m_kx = kx;
372 m_ky = ky;
373 m_kz = kz;
374 m_propLen = propLen;
375 m_yD = yD;
376 m_zD = zD;
377 m_cosy = cosy;
378
379 m_status = true;
380 }
381
382
383 } // namespace TOP
385} // namespace Belle2
386
387
double m_y0
origin in y for unfolding
EType m_type
quartz segment type at last propagation step
double m_cosy
maximal cosine of impact angle to surface in y
int m_nx
signed number of reflections in x at last propagation step
double m_zD
unfolded prism detection position in z
void propagate(const RaytracerBase::BarSegment &bar)
Propagate photon to the exit of bar segment.
double m_x
position in x
static double s_maxLen
maximal allowed propagation length
PhotonState()
Default constructor.
Definition PhotonState.h:44
double m_ky
direction in y
double m_A
width of the quartz segment (dimension in x) for unfolding
double m_cosx
maximal cosine of impact angle to surface in x
int m_ny
signed number of reflections in y at last propagation step
double m_kx
direction in x
double m_yD
unfolded prism detection position in y
double m_B
thickness of the quartz segment (dimension in y) for unfolding
bool m_status
propagation status
void propagateSemiLinear(const RaytracerBase::BarSegment &bar, const RaytracerBase::Mirror &mirror)
Propagate photon to the mirror and reflect it using semi-linear mirror optics.
double m_z
position in z
@ c_BarSegment
bar segment
Definition PhotonState.h:36
@ c_MirrorSegment
mirror segment
Definition PhotonState.h:37
double m_y
position in y
double m_propLen
propagation length since initial position
void propagateExact(const RaytracerBase::BarSegment &bar, const RaytracerBase::Mirror &mirror)
Propagate photon to the mirror and reflect it using exact mirror optics.
bool isInside(const RaytracerBase::BarSegment &bar) const
Checks if photon is inside the bar segment (including surface).
double m_kz
direction in z
Class to store variables with their name which were sent to the logging service.
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:51
void rotateUz(ROOT::Math::XYZVector &vec, const ROOT::Math::XYZVector &z_Axis)
Replacement for a function TVector3::RotateUz which is not implemented in GenVector classes.
Definition func.h:134
void fold(double xu, double A, double &x, double &kx, int &nx)
fold a coordinate (inverse of unfold).
Definition func.h:79
long lround(double x)
Rounds to the nearest integer, halfway cases away from zero.
Definition func.h:31
Abstract base class for different kinds of events.
STL namespace.
bar segment data in module local frame.
double A
width (dimension in x)
double B
thickness (dimension in y)
spherical mirror data in module local frame.
double yc
center of curvature in y
double xc
center of curvature in x
double zb
minimum of mirror surface in z
double zc
center of curvature in z
prism data in module local frame.
double A
width (dimension in x)
std::vector< TOPGeoPrism::UnfoldedWindow > unfoldedWindows
unfolded prism exit windows
double yDown
minimal y of exit window
double slope
slope of slanted surface (dy/dz)
double yUp
maximal y of exit window
double zFlat
z where flat continues to slanted surface
double zR
maximal z, i.e position of prism-bar joint
double B
thickness at bar (dimension in y)
double zD
detector (photo-cathode) position
int k0
index of true prism in the vector 'unfoldedWindows'