Belle II Software development
PDFConstructor.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/PDFConstructor.h>
10#include <top/reconstruction_cpp/TOPRecoManager.h>
11#include <top/reconstruction_cpp/func.h>
12#include <top/geometry/TOPGeometryPar.h>
13#include <framework/logging/Logger.h>
14#include <cmath>
15#include <algorithm>
16#include <iostream>
17
18using namespace std;
19
20namespace Belle2 {
25 namespace TOP {
26
28 EPDFOption PDFOption, EStoreOption storeOption, double overrideMass):
29 m_moduleID(track.getModuleID()), m_track(track), m_hypothesis(hypothesis),
30 m_inverseRaytracer(TOPRecoManager::getInverseRaytracer(m_moduleID)),
31 m_fastRaytracer(TOPRecoManager::getFastRaytracer(m_moduleID)),
35 m_PDFOption(PDFOption), m_storeOption(storeOption)
36 {
37 if (not track.isValid()) {
38 B2ERROR("TOP::PDFConstructor: TOPTrack is not valid, cannot continue");
39 return;
40 }
41
43 if (not m_valid) {
44 B2ERROR("TOP::PDFConstructor: missing reconstruction objects, cannot continue");
45 return;
46 }
47
48 m_beta = track.getBeta(hypothesis, overrideMass);
49 m_yScanner->prepare(track.getMomentumMag(), m_beta, track.getLengthInQuartz());
50 m_tof = track.getTOF(hypothesis, 0, overrideMass);
51
52 m_groupIndex = TOPGeometryPar::Instance()->getGroupIndex(m_yScanner->getMeanEnergy());
53 m_groupIndexDerivative = TOPGeometryPar::Instance()->getGroupIndexDerivative(m_yScanner->getMeanEnergy());
54 m_cosTotal = m_yScanner->getCosTotal();
57 m_selectedHits = track.getSelectedHits();
58 m_bkgRate = track.getBkgRate();
59
60 // prepare the memory for storing signal PDF
61
62 const auto& pixelPositions = m_yScanner->getPixelPositions();
63 int numPixels = pixelPositions.getNumPixels();
64 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
65 for (int pixelID = 1; pixelID <= numPixels; pixelID++) {
66 auto pmtType = pixelPositions.get(pixelID).pmtType;
67 const auto& tts = geo->getTTS(pmtType);
68 m_signalPDFs.push_back(SignalPDF(pixelID, tts));
69 }
70
71 // construct PDF
72
73 if (m_yScanner->isAboveThreshold()) {
74 setSignalPDF();
75 }
76
77 m_deltaRayPDF.prepare(track, hypothesis);
78 m_deltaPhotons = m_deltaRayPDF.getNumPhotons();
79
80 m_bkgPhotons = std::max(m_bkgRate * (m_maxTime - m_minTime), 0.1);
81
82 // release the memory not needed anymore
83
84 m_rayTracers.clear();
85 }
86
87
89 {
90 // construct PDF analytically
91
92 const auto& prism = m_inverseRaytracer->getPrism();
93
94 if (m_track.getEmissionPoint().position.Z() > prism.zR) {
97 } else {
99 }
100
101 // count expected number of signal photons
102
103 for (const auto& signalPDF : m_signalPDFs) {
104 m_signalPhotons += signalPDF.getSum();
105 }
106 if (m_signalPhotons == 0) return;
107
108 // normalize PDF
109
110 for (auto& signalPDF : m_signalPDFs) {
111 signalPDF.normalize(m_signalPhotons);
112 }
113 }
114
115 // signal PDF construction for track crossing bar segments -------------------------------------------
116
118 {
119 const auto& pixelPositions = m_yScanner->getPixelPositions();
120 const auto& bar = m_inverseRaytracer->getBars().front();
121 const auto& prism = m_inverseRaytracer->getPrism();
122
123 // determine the range of number of reflections in x
124
125 double xmi = 0, xma = 0;
126 bool ok = rangeOfX(prism.zD, xmi, xma);
127 if (not ok) return;
128 int kmi = func::lround(xmi / bar.A);
129 int kma = func::lround(xma / bar.A);
130
131 // loop over reflections in x and over pixel columns
132
133 for (int k = kmi; k <= kma; k++) {
134 for (unsigned col = 0; col < pixelPositions.getNumPixelColumns(); col++) {
135 const auto& pixel = pixelPositions.get(col + 1);
136 if (pixel.Dx == 0) continue;
137 double xD = func::unfold(pixel.xc, k, bar.A);
138 if (xD < xmi or xD > xma) continue;
140 setSignalPDF(direct, col, xD, prism.zD);
141 }
142 }
143 }
144
146 {
147 const auto& bar = m_inverseRaytracer->getBars().back();
148 const auto& prism = m_inverseRaytracer->getPrism();
149 const auto& mirror = m_inverseRaytracer->getMirror();
150 const auto& emiPoint = m_track.getEmissionPoint().position;
151
152 // determine the range of number of reflections in x before mirror
153
154 double xmi = 0, xma = 0;
155 bool ok = rangeOfX(mirror.zb, xmi, xma);
156 if (not ok) return;
157 int kmi = func::lround(xmi / bar.A);
158 int kma = func::lround(xma / bar.A);
159
160 // loop over reflections in x before mirror
161
162 double xE = emiPoint.X();
163 double zE = emiPoint.Z();
164 double Ah = bar.A / 2;
165 for (int k = kmi; k <= kma; k++) {
166 double x0 = findReflectionExtreme(xE, zE, prism.zD, k, bar.A, mirror);
167 x0 = func::clip(x0, k, bar.A, xmi, xma);
168 double xL = func::clip(-Ah, k, bar.A, xmi, xma);
169 double xR = func::clip(Ah, k, bar.A, xmi, xma);
170 if (x0 > xL) setSignalPDF_reflected(k, xL, x0);
171 if (x0 < xR) setSignalPDF_reflected(k, x0, xR);
172 }
173 }
174
175
176 void PDFConstructor::setSignalPDF_reflected(int Nxm, double xmMin, double xmMax)
177 {
178 const auto& pixelPositions = m_yScanner->getPixelPositions();
179 const auto& bar = m_inverseRaytracer->getBars().back();
180 const auto& prism = m_inverseRaytracer->getPrism();
181
182 // determine the range of number of reflections in x after mirror
183
184 std::vector<double> xDs;
185 double minLen = 1e10;
186 if (not detectionPositionX(xmMin, Nxm, xDs, minLen)) return;
187 if (not detectionPositionX(xmMax, Nxm, xDs, minLen)) return;
188 if (xDs.size() < 2) return;
189
190 double minTime = m_tof + minLen * m_groupIndex / Const::speedOfLight;
191 if (minTime > m_maxTime) return;
192
193 std::sort(xDs.begin(), xDs.end());
194 double xmi = xDs.front();
195 double xma = xDs.back();
196
197 int kmi = func::lround(xmi / bar.A);
198 int kma = func::lround(xma / bar.A);
199
200 // loop over reflections in x after mirror and over pixel columns
201
202 for (int k = kmi; k <= kma; k++) {
203 for (unsigned col = 0; col < pixelPositions.getNumPixelColumns(); col++) {
204 const auto& pixel = pixelPositions.get(col + 1);
205 if (pixel.Dx == 0) continue;
206 double xD = func::unfold(pixel.xc, k, bar.A);
207 if (xD < xmi or xD > xma) continue;
209 setSignalPDF(reflected, col, xD, prism.zD, Nxm, xmMin, xmMax);
210 }
211 }
212
213 }
214
215
216 bool PDFConstructor::detectionPositionX(double xM, int Nxm, std::vector<double>& xDs, double& minLen)
217 {
218 m_inverseRaytracer->clear();
219 int i0 = m_inverseRaytracer->solveForReflectionPoint(xM, Nxm, m_track.getEmissionPoint(), cerenkovAngle());
220 if (i0 < 0) return false;
221
222 bool ok = false;
223 for (unsigned i = 0; i < 2; i++) {
224 if (not m_inverseRaytracer->getStatus(i)) continue;
225 const auto& solutions = m_inverseRaytracer->getSolutions(i);
226 const auto& sol = solutions[i0];
227 xDs.push_back(sol.xD);
228 minLen = std::min(minLen, sol.len);
229 ok = true;
230 }
231
232 return ok;
233 }
234
235
236 bool PDFConstructor::doRaytracingCorrections(const InverseRaytracer::Solution& sol, double dFic_dx, double xD)
237 {
238 const double precision = 0.01; // [cm]
239
240 double x1 = 0; // x is dFic
241 double y1 = deltaXD(x1, sol, xD); // y is the difference in xD
242 if (isnan(y1)) return false;
243 if (std::abs(y1) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
244 int n1 = m_fastRaytracer->getNxm();
245
246 double step = -dFic_dx * y1;
247 for (int i = 1; i < 20; i++) { // search for zero-crossing interval
248 double x2 = step * i;
249 double y2 = deltaXD(x2, sol, xD);
250 if (isnan(y2)) return false;
251 int n2 = m_fastRaytracer->getNxm();
252 if (n2 != n1) { // x2 is passing the discontinuity caused by different reflection number
253 double x3 = x2;
254 x2 = x1;
255 y2 = y1;
256 for (int k = 0; k < 20; k++) { // move x2 to discontinuity using bisection
257 double x = (x2 + x3) / 2;
258 double y = deltaXD(x, sol, xD);
259 if (isnan(y)) return false;
260 int n = m_fastRaytracer->getNxm();
261 if (n == n1) {
262 x2 = x;
263 y2 = y;
264 } else {
265 x3 = x;
266 }
267 }
268 if (y2 * y1 > 0) return false; // solution does not exist
269 }
270 if (std::abs(y2) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
271 if (y2 * y1 < 0) { // zero-crossing interval is identified
272 for (int k = 0; k < 20; k++) { // find zero-crossing using bisection
273 double x = (x1 + x2) / 2;
274 double y = deltaXD(x, sol, xD);
275 if (isnan(y)) return false;
276 if (std::abs(y) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
277 if (y * y1 < 0) {
278 x2 = x;
279 } else {
280 x1 = x;
281 y1 = y;
282 }
283 }
284 return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
285 }
286 x1 = x2;
287 y1 = y2;
288 }
289
290 return false;
291 }
292
293
294 bool PDFConstructor::setDerivatives(YScanner::Derivatives& D, double dL, double de, double dFic)
295 {
296 while (m_rayTracers.size() < 3) m_rayTracers.push_back(*m_fastRaytracer); // push back a copy of the object
297
298 bool ok = true;
299 const auto& rayTracer_dL = m_rayTracers[0];
300 for (int i = 0; i < 10; i++) {
301 ok = raytrace(rayTracer_dL, dL);
302 if (ok) break;
303 dL = - dL / 2;
304 }
305 if (not ok) return false;
306
307 const auto& rayTracer_de = m_rayTracers[1];
308 for (int i = 0; i < 10; i++) {
309 ok = raytrace(rayTracer_de, 0, de);
310 if (ok) break;
311 de = - de / 2;
312 }
313 if (not ok) return false;
314
315 const auto& rayTracer_dFic = m_rayTracers[2];
316 for (int i = 0; i < 10; i++) {
317 ok = raytrace(rayTracer_dFic, 0, 0, dFic);
318 if (ok) break;
319 dFic = - dFic / 2;
320 }
321 if (not ok) return false;
322
323 // partial derivatives on L, e and Fic
324
325 double dLen_dL = (rayTracer_dL.getPropagationLen() - m_fastRaytracer->getPropagationLen()) / dL;
326 double dLen_de = (rayTracer_de.getPropagationLen() - m_fastRaytracer->getPropagationLen()) / de;
327 double dLen_dFic = (rayTracer_dFic.getPropagationLen() - m_fastRaytracer->getPropagationLen()) / dFic;
328
329 double dyB_dL = (rayTracer_dL.getYB() - m_fastRaytracer->getYB()) / dL;
330 double dyB_de = (rayTracer_de.getYB() - m_fastRaytracer->getYB()) / de;
331 double dyB_dFic = (rayTracer_dFic.getYB() - m_fastRaytracer->getYB()) / dFic;
332
333 double dx_dL = (rayTracer_dL.getXD() - m_fastRaytracer->getXD()) / dL;
334 double dx_de = (rayTracer_de.getXD() - m_fastRaytracer->getXD()) / de;
335 double dx_dFic = (rayTracer_dFic.getXD() - m_fastRaytracer->getXD()) / dFic;
336
337 if (dx_dFic == 0) return false;
338
339 // derivatives on L, e, and x. Derivatives on L and e have to be given at constant x.
340
341 D.dLen_dx = dLen_dFic / dx_dFic;
342 D.dLen_de = dLen_de - dLen_dFic * dx_de / dx_dFic;
343 D.dLen_dL = dLen_dL - dLen_dFic * dx_dL / dx_dFic;
344
345 D.dyB_dx = dyB_dFic / dx_dFic;
346 D.dyB_de = dyB_de - dyB_dFic * dx_de / dx_dFic;
347 D.dyB_dL = dyB_dL - dyB_dFic * dx_dL / dx_dFic;
348
349 D.dFic_dx = 1 / dx_dFic;
350 D.dFic_de = - dx_de / dx_dFic;
351 D.dFic_dL = - dx_dL / dx_dFic;
352
353 return true;
354 }
355
356
357 bool PDFConstructor::raytrace(const FastRaytracer& rayTracer, double dL, double de, double dFic)
358 {
359 const auto& emi = m_track.getEmissionPoint(dL);
360 const auto& trk = emi.trackAngles;
361 const auto& cer = cerenkovAngle(de);
362
363 double fic = m_Fic + dFic;
364 double cosFic = cos(fic);
365 double sinFic = sin(fic);
366 double a = trk.cosTh * cer.sinThc * cosFic + trk.sinTh * cer.cosThc;
367 double b = cer.sinThc * sinFic;
368 double kx = a * trk.cosFi - b * trk.sinFi;
369 double ky = a * trk.sinFi + b * trk.cosFi;
370 double kz = trk.cosTh * cer.cosThc - trk.sinTh * cer.sinThc * cosFic;
371 PhotonState photon(emi.position, kx, ky, kz);
372 rayTracer.propagate(photon, true);
373 if (not rayTracer.getPropagationStatus()) return false;
374
375 if (rayTracer.getNxm() != m_fastRaytracer->getNxm()) return false;
376 if (rayTracer.getNym() != m_fastRaytracer->getNym()) return false;
377 if (rayTracer.getNxe() != m_fastRaytracer->getNxe()) return false;
378 if (rayTracer.getNye() != m_fastRaytracer->getNye()) return false;
379 if (rayTracer.getNxb() != m_fastRaytracer->getNxb()) return false;
380 if (rayTracer.getNyb() != m_fastRaytracer->getNyb()) return false;
381
382 if (rayTracer.getExtraStates().empty() or m_fastRaytracer->getExtraStates().empty()) return true;
383
384 if (rayTracer.getExtraStates().back().getNx() != m_fastRaytracer->getExtraStates().back().getNx()) return false;
385 if (rayTracer.getExtraStates().back().getNy() != m_fastRaytracer->getExtraStates().back().getNy()) return false;
386
387 return true;
388 }
389
390
392 {
393 m_ncallsExpandPDF[type]++;
394
395 double Len = m_fastRaytracer->getPropagationLen();
396 double speedOfLightQuartz = Const::speedOfLight / m_groupIndex; // average speed of light in quartz
397
398 // difference of propagation times of true and flipped prism
399 double dTime = m_fastRaytracer->getPropagationLenDelta() / speedOfLightQuartz;
400
401 // derivatives: dt/de, dt/dx, dt/dL
402 double dt_de = (D.dLen_de + Len * m_groupIndexDerivative / m_groupIndex) / speedOfLightQuartz;
403 double dt_dx = D.dLen_dx / speedOfLightQuartz;
404 double dt_dL = D.dLen_dL / speedOfLightQuartz + 1 / m_beta / Const::speedOfLight;
405
406 // contribution of multiple scattering in quartz
407 double sigmaScat = D.dLen_de * m_yScanner->getSigmaScattering() / speedOfLightQuartz;
408
409 // contribution of quartz surface roughness at single reflection and effective number of reflections
410 double sigmaAlpha = D.dLen_de * m_yScanner->getSigmaAlpha() / speedOfLightQuartz;
411 int Ny_eff = 2 * std::abs(m_fastRaytracer->getNym()) + std::abs(m_fastRaytracer->getNyb());
412
413 const auto& pixel = m_yScanner->getPixelPositions().get(col + 1);
414 double L = m_track.getLengthInQuartz();
415
416 // sigma squared: pixel size, parallax, propagation time difference, multiple scattering, surface roughness
417 double wid0 = (pow(dt_dx * pixel.Dx, 2) + pow(dt_dL * L, 2) + pow(dTime, 2)) / 12 + pow(sigmaScat, 2) +
418 pow(sigmaAlpha, 2) * Ny_eff;
419
420 // sigma squared: adding chromatic contribution
421 double wid = wid0 + pow(dt_de * m_yScanner->getRMSEnergy(), 2);
422
423 double yB = m_fastRaytracer->getYB();
424 const auto& photonStates = m_fastRaytracer->getPhotonStates();
425 const auto& atPrismEntrance = photonStates[photonStates.size() - 2];
426 double dydz = atPrismEntrance.getKy() / atPrismEntrance.getKz();
427 if (m_fastRaytracer->getNyb() % 2 != 0) dydz = -dydz;
428
429 bool doScan = (m_PDFOption == c_Fine);
430 if (m_PDFOption == c_Optimal) {
431 double time = m_tof + Len / speedOfLightQuartz;
432 doScan = m_track.isScanRequired(col, time, wid);
433 }
434
435 m_yScanner->expand(col, yB, dydz, D, Ny_eff, doScan);
436
437 double numPhotons = m_yScanner->getNumPhotons() * std::abs(D.dFic_dx * pixel.Dx);
438 int nx = m_fastRaytracer->getNx();
439 int ny = m_fastRaytracer->getNy();
440 for (const auto& result : m_yScanner->getResults()) {
441 double RQE = m_yScanner->getPixelEfficiencies().get(result.pixelID);
442 if (RQE == 0) continue;
443 auto& signalPDF = m_signalPDFs[result.pixelID - 1];
444 double dE = result.e0 - m_yScanner->getMeanEnergy();
445 double propLen = Len + D.dLen_de * dE;
446 double speedOfLight = Const::speedOfLight / TOPGeometryPar::Instance()->getGroupIndex(result.e0);
447
449 peak.t0 = m_tof + propLen / speedOfLight;
450 peak.wid = wid0 + dt_de * dt_de * result.sigsq;
451 peak.nph = numPhotons * result.sum * RQE * propagationLosses(result.e0, propLen, nx, ny, type);
452 peak.fic = func::within2PI(m_Fic + D.dFic_de * dE);
453 signalPDF.append(peak);
454
455 if (m_storeOption == c_Reduced) continue;
456
458 extra.thc = acos(getCosCerenkovAngle(result.e0));
459 extra.e = result.e0;
460 extra.sige = result.sigsq;
461 extra.Nxm = m_fastRaytracer->getNxm();
462 extra.Nxb = m_fastRaytracer->getNxb();
463 extra.Nxe = m_fastRaytracer->getNxe();
464 extra.Nym = m_fastRaytracer->getNym();
465 extra.Nyb = m_fastRaytracer->getNyb();
466 extra.Nye = m_fastRaytracer->getNye();
467 extra.xD = m_fastRaytracer->getXD();
468 extra.yD = m_fastRaytracer->getYD();
469 extra.zD = m_fastRaytracer->getZD();
470 extra.yB = m_fastRaytracer->getYB();
471 const auto& firstState = photonStates.front();
472 extra.kxE = firstState.getKx();
473 extra.kyE = firstState.getKy();
474 extra.kzE = firstState.getKz();
475 const auto& lastState = photonStates.back();
476 extra.kxD = lastState.getKx();
477 extra.kyD = lastState.getKy();
478 extra.kzD = lastState.getKz();
479 extra.type = type;
480 signalPDF.append(extra);
481 }
482
483 }
484
485 double PDFConstructor::propagationLosses(double E, double propLen, int nx, int ny,
486 SignalPDF::EPeakType type) const
487 {
489 // the surface reflectivity is a constant of the module, so its powers are tabulated
490 // once per module by the YScanner instead of being re-computed for every photon
491 double surf = m_yScanner->getSurfaceReflectivity(std::abs(nx) + std::abs(ny));
492 double p = exp(-propLen / bulk) * surf;
493 if (type == SignalPDF::c_Reflected) p *= std::min(m_yScanner->getMirror().reflectivity, 1.0);
494 return p;
495 }
496
497 bool PDFConstructor::rangeOfX(double z, double& xmi, double& xma)
498 {
499 double maxLen = (m_maxTime - m_tof) / m_groupIndex * Const::speedOfLight; // maximal propagation length
500 if (maxLen < 0) return false;
501
502 const auto& emission = m_track.getEmissionPoint();
503 const auto& trk = emission.trackAngles;
504 const auto& cer = cerenkovAngle();
505
506 // range in x from propagation length limit
507
508 double dz = z - emission.position.Z();
509 double cosFicLimit = (trk.cosTh * cer.cosThc - dz / maxLen) / (trk.sinTh * cer.sinThc); // at maxLen
510 double cosLimit = (dz > 0) ? cosFicLimit : -cosFicLimit;
511 if (cosLimit < -1) return false; // photons cannot reach the plane at z within propagation length limit
512
513 std::vector<double> xmima;
514 double x0 = emission.position.X();
515 if (cosLimit > 1) {
516 xmima.push_back(x0 - maxLen);
517 xmima.push_back(x0 + maxLen);
518 } else {
519 double a = trk.cosTh * cer.sinThc * cosFicLimit + trk.sinTh * cer.cosThc;
520 double b = cer.sinThc * sqrt(1 - cosFicLimit * cosFicLimit);
521 xmima.push_back(x0 + maxLen * (a * trk.cosFi - b * trk.sinFi));
522 xmima.push_back(x0 + maxLen * (a * trk.cosFi + b * trk.sinFi));
523 std::sort(xmima.begin(), xmima.end());
524 }
525 xmi = xmima[0];
526 xma = xmima[1];
527
528 // range in x from minimal/maximal possible extensions in x, if they exist (d(kx/kz)/dFic = 0)
529
530 double theta = acos(trk.cosTh);
531 if (dz < 0) theta = M_PI - theta; // rotation around x by 180 deg. (z -> -z, phi -> -phi)
532 dz = std::abs(dz);
533 double thetaCer = acos(cer.cosThc);
534 if (theta - thetaCer >= M_PI / 2) return false; // photons cannot reach the plane at z
535
536 std::vector<double> dxdz;
537 double a = -cos(theta + thetaCer) * cos(theta - thetaCer);
538 double b = sin(2 * theta) * trk.cosFi;
539 double c = pow(trk.sinFi * cer.sinThc, 2) - pow(trk.cosFi, 2) * sin(theta + thetaCer) * sin(theta - thetaCer);
540 double D = b * b - 4 * a * c;
541 if (D < 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
542 if (a != 0) {
543 D = sqrt(D);
544 dxdz.push_back((-b - D) / 2 / a);
545 dxdz.push_back((-b + D) / 2 / a);
546 } else {
547 if (b == 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
548 dxdz.push_back(-c / b);
549 dxdz.push_back(copysign(INFINITY, b));
550 }
551 std::vector<double> cosFic(2, cosLimit);
552 for (int i = 0; i < 2; i++) {
553 if (std::abs(dxdz[i]) < INFINITY) {
554 double aa = (dxdz[i] * cos(theta) - trk.cosFi * sin(theta)) * cer.cosThc;
555 double bb = (dxdz[i] * sin(theta) + trk.cosFi * cos(theta)) * cer.sinThc;
556 double dd = trk.sinFi * cer.sinThc;
557 cosFic[i] = aa * bb / (bb * bb + dd * dd);
558 double kz = cos(theta) * cer.cosThc - sin(theta) * cer.sinThc * cosFic[i];
559 if (kz < 0) dxdz[i] = copysign(INFINITY, dxdz[1 - i] - dxdz[i]);
560 }
561 }
562 if (dxdz[0] > dxdz[1]) {
563 std::reverse(dxdz.begin(), dxdz.end());
564 std::reverse(cosFic.begin(), cosFic.end());
565 }
566 for (int i = 0; i < 2; i++) {
567 if (cosFic[i] < cosLimit) xmima[i] = x0 + dxdz[i] * dz;
568 }
569
570 // just to make sure xmi/xma are within the limits given by maximal propagation length
571 xmi = std::max(xmima[0], x0 - maxLen);
572 xma = std::min(xmima[1], x0 + maxLen);
573
574 return xma > xmi;
575 }
576
577
578 double PDFConstructor::derivativeOfReflectedX(double x, double xe, double ze, double zd)
579 {
580 double z = sqrt(1 - x * x);
581 double kx = (x - xe);
582 double kz = (z - ze);
583 double s = 2 * (kx * x + kz * z);
584 double qx = kx - s * x;
585 double qz = kz - s * z;
586
587 double der_z = -x / z;
588 double der_s = 2 * (kx + der_z * kz);
589 double der_qx = (1 - s) - der_s * x;
590 double der_qz = (1 - s) * der_z - der_s * z;
591
592 return 1 - der_z * qx / qz + (zd - z) * (der_qx * qz - der_qz * qx) / (qz * qz);
593 }
594
595
596 double PDFConstructor::findReflectionExtreme(double xE, double zE, double zD, int Nxm, double A,
597 const RaytracerBase::Mirror& mirror)
598 {
599
600 if (Nxm % 2 == 0) {
601 xE = func::unfold(xE, -Nxm, A);
602 } else {
603 xE = func::unfold(xE, Nxm, A);
604 }
605
606 double xe = (xE - mirror.xc) / mirror.R;
607 double ze = (zE - mirror.zc) / mirror.R;
608 double zd = (zD - mirror.zc) / mirror.R;
609
610 double Ah = A / 2;
611
612 double x1 = (-Ah - mirror.xc) / mirror.R;
613 double y1 = derivativeOfReflectedX(x1, xe, ze, zd);
614 if (y1 != y1 or std::abs(y1) == INFINITY) return -Ah;
615
616 double x2 = (Ah - mirror.xc) / mirror.R;
617 double y2 = derivativeOfReflectedX(x2, xe, ze, zd);
618 if (y2 != y2 or std::abs(y2) == INFINITY) return -Ah;
619
620 if (y1 * y2 > 0) return -Ah; // no minimum or maximum
621
622 for (int i = 0; i < 50; i++) {
623 double x = (x1 + x2) / 2;
624 double y = derivativeOfReflectedX(x, xe, ze, zd);
625 if (y != y or std::abs(y) == INFINITY) return -Ah;
626 if (y * y1 < 0) {
627 x2 = x;
628 } else {
629 x1 = x;
630 y1 = y;
631 }
632 }
633 double x = (x1 + x2) / 2;
634
635 return x * mirror.R + mirror.xc;
636 }
637
638 // signal PDF construction for track crossing prism --------------------------------------------------
639
641 {
642 const auto& pixelPositions = m_yScanner->getPixelPositions();
643 const auto& prism = m_inverseRaytracer->getPrism();
644 double speedOfLightQuartz = Const::speedOfLight / m_groupIndex; // average speed of light in quartz
645
646 double xE = m_track.getEmissionPoint().position.X();
647 int nxmi = (xE > 0) ? 0 : -1;
648 int nxma = (xE > 0) ? 1 : 0;
649
650 for (const auto& pixel : pixelPositions.getPixels()) {
651 if (not m_yScanner->getPixelMasks().isActive(pixel.ID)) continue;
652 double RQE = m_yScanner->getPixelEfficiencies().get(pixel.ID);
653 if (RQE == 0) continue;
654 auto& signalPDF = m_signalPDFs[pixel.ID - 1];
655 for (int Nxe = nxmi; Nxe <= nxma; Nxe++) {
656 for (size_t k = 0; k < prism.unfoldedWindows.size(); k++) {
657 const auto sol = prismSolution(pixel, k, Nxe);
658 if (sol.len == 0 or std::abs(sol.L) > m_track.getLengthInQuartz() / 2) continue;
659
660 bool ok = prismRaytrace(sol);
661 if (not ok) continue;
662 int Nye = k - prism.k0;
663 if (Nye != m_fastRaytracer->getNy() or Nxe != m_fastRaytracer->getNx()) continue;
664 if (not m_fastRaytracer->getTotalReflStatus(m_cosTotal)) continue;
665 const auto firstState = m_fastRaytracer->getPhotonStates().front(); // a copy of
666 const auto lastState = m_fastRaytracer->getPhotonStates().back(); // a copy of
667
668 double slope = lastState.getKy() / lastState.getKz();
669 double dz = prism.zD - prism.zFlat;
670 double y2 = std::min(pixel.yc + pixel.Dy / 2, prism.yUp + slope * dz);
671 double y1 = std::max(pixel.yc - pixel.Dy / 2, prism.yDown + slope * dz);
672 double Dy = y2 - y1;
673 if (Dy < 0) continue;
674
675 double dL = 0.1; // cm
676 for (int i = 0; i < 4; i++) {
677 ok = prismRaytrace(sol, dL);
678 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
679 if (ok) break;
680 dL = - dL / 2;
681 }
682 if (not ok) continue;
683 const auto lastState_dL = m_fastRaytracer->getPhotonStates().back(); // a copy of
684
685 double dFic = 0.01; // rad
686 for (int i = 0; i < 4; i++) {
687 ok = prismRaytrace(sol, 0, dFic);
688 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
689 if (ok) break;
690 dFic = - dFic / 2;
691 }
692 if (not ok) continue;
693 const auto lastState_dFic = m_fastRaytracer->getPhotonStates().back(); // a copy of
694
695 double de = 0.1; // eV
696 for (int i = 0; i < 4; i++) {
697 ok = prismRaytrace(sol, 0, 0, de);
698 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
699 if (ok) break;
700 de = - de / 2;
701 }
702 if (not ok) continue;
703 const auto lastState_de = m_fastRaytracer->getPhotonStates().back(); // a copy of
704
705 double dx_dL = (lastState_dL.getX() - lastState.getX()) / dL;
706 double dy_dL = (lastState_dL.getY() - lastState.getY()) / dL;
707 double dx_dFic = (lastState_dFic.getX() - lastState.getX()) / dFic;
708 double dy_dFic = (lastState_dFic.getY() - lastState.getY()) / dFic;
709 double Jacobi = dx_dL * dy_dFic - dy_dL * dx_dFic;
710 double numPhotons = m_yScanner->getNumPhotonsPerLen() * pixel.Dx * Dy / std::abs(Jacobi) * RQE;
711
712 double dLen_de = (lastState_de.getPropagationLen() - lastState.getPropagationLen()) / de;
713 double dLen_dL = (lastState_dL.getPropagationLen() - lastState.getPropagationLen()) / dL;
714 double dLen_dFic = (lastState_dFic.getPropagationLen() - lastState.getPropagationLen()) / dFic;
715
716 double dt_de = (dLen_de + sol.len * m_groupIndexDerivative / m_groupIndex) / speedOfLightQuartz;
717 double dt_dL = dLen_dL / speedOfLightQuartz;
718 double dt_dFic = dLen_dFic / speedOfLightQuartz;
719
720 double chromatic = pow(dt_de * m_yScanner->getRMSEnergy(), 2);
721
722 double DL = (dy_dFic * pixel.Dx - dx_dFic * pixel.Dy) / Jacobi;
723 double DFic = (dx_dL * pixel.Dy - dy_dL * pixel.Dx) / Jacobi;
724 double paralax = (pow(dt_dL * DL, 2) + pow(dt_dFic * DFic, 2)) / 12;
725
726 double scattering = pow(dLen_de * m_yScanner->getSigmaScattering() / speedOfLightQuartz, 2);
727
729 peak.t0 = m_tof + sol.L / m_beta / Const::speedOfLight + sol.len / speedOfLightQuartz;
730 peak.wid = chromatic + paralax + scattering;
731 peak.nph = 1 - exp(-numPhotons); // because photons that pile-up are counted as one
732 peak.fic = atan2(sol.sinFic, sol.cosFic);
733 signalPDF.append(peak);
734
735 if (m_storeOption == c_Reduced) continue;
736
738 extra.thc = acos(getCosCerenkovAngle(m_yScanner->getMeanEnergy()));
739 extra.e = m_yScanner->getMeanEnergy();
740 extra.sige = m_yScanner->getRMSEnergy();
741 extra.Nxe = Nxe;
742 extra.Nye = Nye;
743 extra.xD = lastState.getXD();
744 extra.yD = lastState.getYD();
745 extra.zD = lastState.getZD();
746 extra.kxE = firstState.getKx();
747 extra.kyE = firstState.getKy();
748 extra.kzE = firstState.getKz();
749 extra.kxD = lastState.getKx();
750 extra.kyD = lastState.getKy();
751 extra.kzD = lastState.getKz();
753 signalPDF.append(extra);
754
755 } // reflections in y (unfolded prism windows)
756 } // reflections in x
757 } // pixels
758
759 }
760
761
762 bool PDFConstructor::prismRaytrace(const PrismSolution& sol, double dL, double dFic, double de)
763 {
764 const auto& emi = m_track.getEmissionPoint(sol.L + dL);
765 const auto& trk = emi.trackAngles;
766 const auto& cer = cerenkovAngle(de);
767
768 double cosDFic = 1;
769 double sinDFic = 0;
770 if (dFic != 0) {
771 cosDFic = cos(dFic);
772 sinDFic = sin(dFic);
773 }
774 double cosFic = sol.cosFic * cosDFic - sol.sinFic * sinDFic;
775 double sinFic = sol.sinFic * cosDFic + sol.cosFic * sinDFic;
776 double a = trk.cosTh * cer.sinThc * cosFic + trk.sinTh * cer.cosThc;
777 double b = cer.sinThc * sinFic;
778 double kx = a * trk.cosFi - b * trk.sinFi;
779 double ky = a * trk.sinFi + b * trk.cosFi;
780 double kz = trk.cosTh * cer.cosThc - trk.sinTh * cer.sinThc * cosFic;
781 PhotonState photon(emi.position, kx, ky, kz);
782 m_fastRaytracer->propagate(photon);
783
784 return m_fastRaytracer->getPropagationStatus();
785 }
786
787
789 unsigned k, int nx)
790 {
791 const auto& prism = m_inverseRaytracer->getPrism();
792 const auto& win = prism.unfoldedWindows[k];
793 double dz = std::abs(prism.zD - prism.zFlat);
794 ROOT::Math::XYZPoint rD(func::unfold(pixel.xc, nx, prism.A),
795 pixel.yc * win.sy + win.y0 + win.ny * dz,
796 pixel.yc * win.sz + win.z0 + win.nz * dz);
797
798 double L = 0;
799 for (int iter = 0; iter < 100; iter++) {
800 auto sol = prismSolution(rD, L);
801 if (std::abs(sol.L) > m_track.getLengthInQuartz() / 2) return sol;
802 if (std::abs(sol.L - L) < 0.01) return sol;
803 L = sol.L;
804 }
805 B2DEBUG(20, "TOP::PDFConstructor::prismSolution: iterations not converging");
806 return PrismSolution();
807 }
808
809
810 PDFConstructor::PrismSolution PDFConstructor::prismSolution(const ROOT::Math::XYZPoint& rD, double L)
811 {
812 const auto& emi = m_track.getEmissionPoint(L);
813
814 // transformation of detection position to system of particle
815
816 auto r = rD - emi.position;
817 const auto& trk = emi.trackAngles;
818 double xx = r.X() * trk.cosFi + r.Y() * trk.sinFi;
819 double y = -r.X() * trk.sinFi + r.Y() * trk.cosFi;
820 double x = xx * trk.cosTh - r.Z() * trk.sinTh;
821 double z = xx * trk.sinTh + r.Z() * trk.cosTh;
822
823 // solution
824
825 double rho = sqrt(x * x + y * y);
826 const auto& cer = cerenkovAngle();
827
828 PrismSolution sol;
829 sol.len = rho / cer.sinThc;
830 sol.L = L + z - sol.len * cer.cosThc;
831 sol.cosFic = x / rho;
832 sol.sinFic = y / rho;
833
834 return sol;
835 }
836
837 // log likelihood calculation ------------------------------------------------------------------------
838
840 {
841 if (not m_valid) {
842 B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
843 return LogL(0);
844 }
845
847 for (const auto& hit : m_selectedHits) {
848 if (hit.time < m_minTime or hit.time > m_maxTime) continue;
849 double f = pdfValue(hit.pixelID, hit.time, hit.timeErr);
850 if (f <= 0) {
851 auto ret = m_zeroPixels.insert(hit.pixelID);
852 if (ret.second) {
853 B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
854 << LogVar("slotID", m_moduleID)
855 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
856 }
857 continue;
858 }
859 LL.logL += log(f);
860 LL.numPhotons++;
861 LL.effectiveSignalYield += m_f0 / f;
862 }
863 return LL;
864 }
865
866
867 PDFConstructor::LogL PDFConstructor::getLogL(double t0, double minTime, double maxTime, double sigt) const
868 {
869 if (not m_valid) {
870 B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
871 return LogL(0);
872 }
873
874 LogL LL(getExpectedPhotons(minTime - t0, maxTime - t0));
875 for (const auto& hit : m_selectedHits) {
876 if (hit.time < minTime or hit.time > maxTime) continue;
877 double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
878 if (f <= 0) {
879 auto ret = m_zeroPixels.insert(hit.pixelID);
880 if (ret.second) {
881 B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
882 << LogVar("slotID", m_moduleID)
883 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
884 }
885 continue;
886 }
887 LL.logL += log(f);
888 LL.numPhotons++;
889 LL.effectiveSignalYield += m_f0 / f;
890 }
891 return LL;
892 }
893
894
895 PDFConstructor::LogL PDFConstructor::getBackgroundLogL(double minTime, double maxTime) const
896 {
897 if (not m_valid) {
898 B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): object status is invalid - cannot provide log likelihood");
899 return LogL(0);
900 }
901
902 double bkgPhotons = m_bkgPhotons * (maxTime - minTime) / (m_maxTime - m_minTime);
903
904 LogL LL(bkgPhotons);
905 for (const auto& hit : m_selectedHits) {
906 if (hit.time < minTime or hit.time > maxTime) continue;
907 double f = bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID);
908 if (f <= 0) {
909 auto ret = m_zeroPixels.insert(hit.pixelID);
910 if (ret.second) {
911 B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): PDF value is zero or negative"
912 << LogVar("slotID", m_moduleID)
913 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
914 }
915 continue;
916 }
917 LL.logL += log(f);
918 LL.numPhotons++;
919 }
920 return LL;
921 }
922
923
924 const std::vector<PDFConstructor::LogL>&
925 PDFConstructor::getPixelLogLs(double t0, double minTime, double maxTime, double sigt) const
926 {
927 if (not m_valid) {
928 B2ERROR("TOP::PDFConstructor::getPixelLogLs(): object status is invalid - cannot provide log likelihoods");
929 return m_pixelLLs;
930 }
931
932 initializePixelLogLs(minTime - t0, maxTime - t0);
933
934 for (const auto& hit : m_selectedHits) {
935 if (hit.time < minTime or hit.time > maxTime) continue;
936 double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
937 if (f <= 0) {
938 auto ret = m_zeroPixels.insert(hit.pixelID);
939 if (ret.second) {
940 B2ERROR("TOP::PDFConstructor::getPixelLogLs(): PDF value is zero or negative"
941 << LogVar("slotID", m_moduleID)
942 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
943 }
944 continue;
945 }
946 unsigned k = hit.pixelID - 1;
947 auto& LL = m_pixelLLs[k];
948 LL.logL += log(f);
949 LL.numPhotons++;
950 LL.effectiveSignalYield += m_f0 / f;
951 }
952
953 return m_pixelLLs;
954 }
955
956 void PDFConstructor::initializePixelLogLs(double minTime, double maxTime) const
957 {
958 m_pixelLLs.clear();
959
960 double pb = (maxTime - minTime) / (m_maxTime - m_minTime);
961 double bfot = pb * m_bkgPhotons + getExpectedDeltaPhotons(minTime, maxTime);
962 for (const auto* other : m_pdfOtherTracks) bfot += other->getExpectedDeltaPhotons(minTime, maxTime);
963
964 const auto& pixelPDF = m_backgroundPDF->getPDF();
965 for (const auto& signalPDF : m_signalPDFs) {
966 unsigned k = signalPDF.getPixelID() - 1;
967 double phot = signalPDF.getIntegral(minTime, maxTime) * m_signalPhotons + bfot * pixelPDF[k];
968 for (const auto* other : m_pdfOtherTracks) {
969 const auto& otherPDFs = other->getSignalPDF();
970 phot += otherPDFs[k].getIntegral(minTime, maxTime) * other->getExpectedSignalPhotons();
971 }
972 m_pixelLLs.push_back(LogL(phot));
973 }
974 }
975
976 const std::vector<PDFConstructor::Pull>& PDFConstructor::getPulls() const
977 {
978 if (m_pulls.empty() and m_valid) {
979 for (const auto& hit : m_selectedHits) {
980 if (hit.time < m_minTime or hit.time > m_maxTime) continue;
981 appendPulls(hit);
982 }
983 }
984
985 return m_pulls;
986 }
987
989 {
990 unsigned k = hit.pixelID - 1;
991 if (k >= m_signalPDFs.size()) return;
992 const auto& signalPDF = m_signalPDFs[k];
993
995 double signalFract = m_signalPhotons / sfot;
996 double wid0 = hit.timeErr * hit.timeErr;
997 double minT0 = m_maxTime;
998 double sum = 0;
999 auto i0 = m_pulls.size();
1000 for (const auto& peak : signalPDF.getPDFPeaks()) {
1001 minT0 = std::min(minT0, peak.t0);
1002 for (const auto& gaus : signalPDF.getTTS()->getTTS()) {
1003 double sig2 = peak.wid + gaus.sigma * gaus.sigma + wid0; // sigma squared!
1004 double x = pow(hit.time - peak.t0 - gaus.position, 2) / sig2;
1005 if (x > 100) continue;
1006 double wt = signalFract * peak.nph * gaus.fraction / sqrt(2 * M_PI * sig2) * exp(-x / 2);
1007 sum += wt;
1008 m_pulls.push_back(Pull(hit.pixelID, hit.time, peak.t0, gaus.position, sqrt(sig2), peak.fic - M_PI, wt));
1009 }
1010 }
1011
1012 double bg = (m_deltaPhotons * m_deltaRayPDF.getPDFValue(hit.pixelID, hit.time) +
1013 m_bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID)) / sfot;
1014 sum += bg;
1015 m_pulls.push_back(Pull(hit.pixelID, hit.time, minT0, 0, 0, 0, bg));
1016
1017 if (sum == 0) return;
1018 for (size_t i = i0; i < m_pulls.size(); i++) m_pulls[i].wt /= sum;
1019 }
1020
1021
1022 } // namespace TOP
1024} // namespace Belle2
1025
1026
R E
internal precision of FFTW codelets
Provides a type-safe way to pass members of the chargedStableSet set.
Definition Const.h:590
static const double speedOfLight
[cm/ns]
Definition Const.h:696
Fast photon propagation in quartz optics.
int getNyb() const
Returns signed number of reflections in y after mirror and before prism.
const std::vector< PhotonState > & getExtraStates() const
Returns extra states.
int getNxm() const
Returns signed number of reflections in x before mirror.
int getNxb() const
Returns signed number of reflections in x after mirror and before prism.
void propagate(const PhotonState &photon, bool averaging=false) const
Propagate photon to photo-detector plane.
int getNym() const
Returns signed number of reflections in y before mirror.
int getNxe() const
Returns signed number of reflections in x inside prism.
bool getPropagationStatus() const
Returns propagation status.
int getNye() const
Returns signed number of reflections in y inside prism.
double m_cosTotal
cosine of total reflection angle
void setSignalPDF_prism()
Sets signal PDF for track crossing prism.
void setSignalPDF()
Sets signal PDF.
double m_bkgRate
estimated background hit rate
double m_beta
particle hypothesis beta
const BackgroundPDF * getBackgroundPDF() const
Returns background PDF.
const InverseRaytracer::CerenkovAngle & cerenkovAngle(double dE=0)
Returns cosine and sine of cerenkov angle.
bool detectionPositionX(double xM, int Nxm, std::vector< double > &xDs, double &minLen)
Calculates unfolded detection position from known reflection position on the mirror and emission poin...
const YScanner * m_yScanner
PDF expander in y.
std::vector< SignalPDF > m_signalPDFs
parameterized signal PDF in pixels (index = pixelID - 1)
void setSignalPDF_reflected()
Sets signal PDF for reflected photons.
LogL getBackgroundLogL() const
Returns extended log likelihood for background hypothesis using default time window.
PrismSolution prismSolution(const PixelPositions::PixelData &pixel, unsigned k, int nx)
General solution of inverse raytracing in prism: iterative procedure calling basic solution.
LogL getLogL() const
Returns extended log likelihood (using the default time window)
double m_maxTime
time window upper edge
const InverseRaytracer * m_inverseRaytracer
inverse ray-tracer
double m_minTime
time window lower edge
double getExpectedDeltaPhotons() const
Returns the expected number of delta-ray photons within the default time window.
EStoreOption m_storeOption
signal PDF storing option
double m_Fic
temporary storage for Cerenkov azimuthal angle
bool setDerivatives(YScanner::Derivatives &D, double dL, double de, double dFic)
Sets the derivatives (numerically) using forward ray-tracing.
double m_groupIndex
group refractive index at mean photon energy
std::vector< const PDFConstructor * > m_pdfOtherTracks
most probable PDF's of other tracks in the module
double m_bkgPhotons
expected number of uniform background photons
const std::vector< LogL > & getPixelLogLs(double t0, double sigt=0) const
Returns extended log likelihoods in pixels for PDF shifted in time.
double propagationLosses(double E, double propLen, int nx, int ny, SignalPDF::EPeakType type) const
Returns photon propagation losses (bulk absorption, surface reflectivity, mirror reflectivity)
int getModuleID() const
Returns slot ID.
double m_deltaPhotons
expected number of delta-ray photons
const std::vector< Pull > & getPulls() const
Returns photon pulls w.r.t PDF peaks.
double getCosCerenkovAngle(double E) const
Returns cosine of Cerenkov angle at given photon energy.
double m_signalPhotons
expected number of signal photons
static double derivativeOfReflectedX(double x, double xe, double ze, double zd)
Returns the derivative of reflected position at given x.
std::map< SignalPDF::EPeakType, int > m_ncallsExpandPDF
number of calls to expandSignalPDF
void appendPulls(const TOPTrack::SelectedHit &hit) const
Appends pulls of a photon hit.
double getExpectedPhotons() const
Returns the expected number of all photons within the default time window.
bool m_valid
cross-check flag, true if track is valid and all the pointers above are valid
DeltaRayPDF m_deltaRayPDF
delta-ray PDF
double deltaXD(double dFic, const InverseRaytracer::Solution &sol, double xD)
Returns the difference in xD between ray-traced solution rotated by dFic and input argument.
bool doRaytracingCorrections(const InverseRaytracer::Solution &sol, double dFic_dx, double xD)
Corrects the solution of inverse ray-tracing with fast ray-tracing.
bool raytrace(const FastRaytracer &rayTracer, double dL=0, double de=0, double dFic=0)
Forward ray-tracing (called by setDerivatives)
std::vector< Pull > m_pulls
photon pulls w.r.t PDF peaks
const FastRaytracer * m_fastRaytracer
fast ray-tracer
EStoreOption
Options for storing signal PDF parameters.
@ c_Reduced
only PDF peak data
static double findReflectionExtreme(double xE, double zE, double zD, int Nxm, double A, const RaytracerBase::Mirror &mirror)
Finds the position on the mirror of the extreme reflection.
const TOPTrack & m_track
temporary reference to track at TOP
std::vector< LogL > m_pixelLLs
pixel log likelihoods (index = pixelID - 1)
EPDFOption m_PDFOption
signal PDF construction option
const BackgroundPDF * m_backgroundPDF
background PDF
EPDFOption
Signal PDF construction options.
@ c_Optimal
y dependent only where necessary
@ c_Fine
y dependent everywhere
double pdfValue(int pixelID, double time, double timeErr, double sigt=0) const
Returns the value of PDF normalized to the number of expected photons.
void expandSignalPDF(unsigned col, const YScanner::Derivatives &D, SignalPDF::EPeakType type)
Expands signal PDF in y (y-scan)
std::vector< FastRaytracer > m_rayTracers
copies of fast ray-tracer used to compute derivatives
const Const::ChargedStable m_hypothesis
particle hypothesis
bool prismRaytrace(const PrismSolution &sol, double dL=0, double dFic=0, double de=0)
Do forward raytracing of inverse raytracing solution in prism.
double m_groupIndexDerivative
derivative (dn_g/dE) of group refractive index at mean photon energy
void initializePixelLogLs(double minTime, double maxTime) const
Initializes pixel log likelihoods.
bool rangeOfX(double z, double &xmi, double &xma)
Estimates range of unfolded x coordinate of the hits on given plane perpendicular to z-axis.
std::vector< TOPTrack::SelectedHit > m_selectedHits
selected photon hits
void setSignalPDF_direct()
Sets signal PDF for direct photons.
std::set< int > m_zeroPixels
collection of pixelID's with zero pdfValue
double m_f0
temporary value of signal PDF
double m_tof
time-of-flight from IP to average photon emission position
PDFConstructor(const TOPTrack &track, const Const::ChargedStable &hypothesis, EPDFOption PDFOption=c_Optimal, EStoreOption storeOption=c_Reduced, double overrideMass=0)
Class constructor.
State of the Cerenkov photon in the quartz optics.
Definition PhotonState.h:27
Parametrization of signal PDF in a single pixel.
Definition SignalPDF.h:25
EPeakType
Enumerator for single PDF peak types.
Definition SignalPDF.h:32
@ c_Direct
direct photon
Definition SignalPDF.h:34
@ c_Reflected
reflected photon
Definition SignalPDF.h:35
static double getAbsorptionLength(double energy)
Returns bulk absorption length of quartz at given photon energy.
static double getGroupIndex(double energy)
Returns group refractive index of quartz at given photon energy.
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
Singleton class providing pre-constructed reconstruction objects.
static double getMaxTime()
Returns time window upper edge.
static double getMinTime()
Returns time window lower edge.
Reconstructed track at TOP.
Definition TOPTrack.h:40
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
double clip(double x, int Nx, double A, double xmi, double xma)
Performs a clip on x w.r.t xmi and xma.
Definition func.h:98
double within2PI(double angle)
Returns angle within 0 and 2PI.
Definition func.h:122
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.
Solution of inverse ray-tracing.
Structure that enables defining a template function: direct photons.
Structure that enables defining a template function: reflected photons.
Useful data type for returning the results of log likelihood calculation.
double effectiveSignalYield
effective number of signal photons in data
unsigned numPhotons
detected number of photons
double logL
extended log likelihood
Solution of inverse raytracing in prism.
double L
emission position distance along particle trajectory
double cosFic
cosine of azimuthal Cerenkov angle
double sinFic
sine of azimuthal Cerenkov angle
Data type for storing photon pull w.r.t PDF peak.
position and size of a pixel
double yc
position of center in y
double xc
position of center in x
spherical mirror data in module local frame.
double xc
center of curvature in x
double zc
center of curvature in z
Extra information about single PDF peak.
Definition SignalPDF.h:51
int Nxm
number of reflections in x before mirror
Definition SignalPDF.h:55
double yB
unfolded coordinate x at prism entrance
Definition SignalPDF.h:64
int Nye
number of reflections in y inside prism
Definition SignalPDF.h:60
double xD
unfolded detection x coordinate
Definition SignalPDF.h:61
double kxD
photon direction x at detection
Definition SignalPDF.h:68
double kyD
photon direction y at detection
Definition SignalPDF.h:69
double kzD
photon direction z at detection
Definition SignalPDF.h:70
int Nym
number of reflections in y before mirror
Definition SignalPDF.h:58
double thc
Cerenkov (polar) angle.
Definition SignalPDF.h:52
double sige
photon energy sigma squared
Definition SignalPDF.h:54
int Nxe
number of reflections in x inside prism
Definition SignalPDF.h:57
int Nyb
number of reflections in y after mirror and before prism
Definition SignalPDF.h:59
double kzE
photon direction z at emission
Definition SignalPDF.h:67
double kyE
photon direction y at emission
Definition SignalPDF.h:66
double kxE
photon direction x at emission
Definition SignalPDF.h:65
int Nxb
number of reflections in x after mirror and before prism
Definition SignalPDF.h:56
double yD
unfolded detection y coordinate
Definition SignalPDF.h:62
double zD
unfolded detection z coordinate
Definition SignalPDF.h:63
double t0
peak position [ns]
Definition SignalPDF.h:42
double fic
Cerenkov azimuthal angle.
Definition SignalPDF.h:45
double wid
peak width squared [ns^2]
Definition SignalPDF.h:43
double nph
normalized number of photons in a peak
Definition SignalPDF.h:44
selected photon hit from TOPDigits
Definition TOPTrack.h:84
double timeErr
time uncertainty
Definition TOPTrack.h:87