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)),
32 m_yScanner(TOPRecoManager::getYScanner(m_moduleID)),
33 m_backgroundPDF(TOPRecoManager::getBackgroundPDF(m_moduleID)),
34 m_deltaRayPDF(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
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
75 }
76
77 m_deltaRayPDF.prepare(track, hypothesis);
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 = lround(xmi / bar.A);
129 int kma = 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 = lround(xmi / bar.A);
158 int kma = 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 = lround(xmi / bar.A);
198 int kma = 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 {
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 }
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 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 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 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 fliped 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 double surf = m_yScanner->getBars().front().reflectivity;
490 double p = exp(-propLen / bulk) * pow(surf, std::abs(nx) + std::abs(ny));
491 if (type == SignalPDF::c_Reflected) p *= std::min(m_yScanner->getMirror().reflectivity, 1.0);
492 return p;
493 }
494
495 bool PDFConstructor::rangeOfX(double z, double& xmi, double& xma)
496 {
497 double maxLen = (m_maxTime - m_tof) / m_groupIndex * Const::speedOfLight; // maximal propagation length
498 if (maxLen < 0) return false;
499
500 const auto& emission = m_track.getEmissionPoint();
501 const auto& trk = emission.trackAngles;
502 const auto& cer = cerenkovAngle();
503
504 // range in x from propagation lenght limit
505
506 double dz = z - emission.position.Z();
507 double cosFicLimit = (trk.cosTh * cer.cosThc - dz / maxLen) / (trk.sinTh * cer.sinThc); // at maxLen
508 double cosLimit = (dz > 0) ? cosFicLimit : -cosFicLimit;
509 if (cosLimit < -1) return false; // photons cannot reach the plane at z within propagation lenght limit
510
511 std::vector<double> xmima;
512 double x0 = emission.position.X();
513 if (cosLimit > 1) {
514 xmima.push_back(x0 - maxLen);
515 xmima.push_back(x0 + maxLen);
516 } else {
517 double a = trk.cosTh * cer.sinThc * cosFicLimit + trk.sinTh * cer.cosThc;
518 double b = cer.sinThc * sqrt(1 - cosFicLimit * cosFicLimit);
519 xmima.push_back(x0 + maxLen * (a * trk.cosFi - b * trk.sinFi));
520 xmima.push_back(x0 + maxLen * (a * trk.cosFi + b * trk.sinFi));
521 std::sort(xmima.begin(), xmima.end());
522 }
523 xmi = xmima[0];
524 xma = xmima[1];
525
526 // range in x from minimal/maximal possible extensions in x, if they exist (d(kx/kz)/dFic = 0)
527
528 double theta = acos(trk.cosTh);
529 if (dz < 0) theta = M_PI - theta; // rotation around x by 180 deg. (z -> -z, phi -> -phi)
530 dz = std::abs(dz);
531 double thetaCer = acos(cer.cosThc);
532 if (theta - thetaCer >= M_PI / 2) return false; // photons cannot reach the plane at z
533
534 std::vector<double> dxdz;
535 double a = -cos(theta + thetaCer) * cos(theta - thetaCer);
536 double b = sin(2 * theta) * trk.cosFi;
537 double c = pow(trk.sinFi * cer.sinThc, 2) - pow(trk.cosFi, 2) * sin(theta + thetaCer) * sin(theta - thetaCer);
538 double D = b * b - 4 * a * c;
539 if (D < 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
540 if (a != 0) {
541 D = sqrt(D);
542 dxdz.push_back((-b - D) / 2 / a);
543 dxdz.push_back((-b + D) / 2 / a);
544 } else {
545 if (b == 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
546 dxdz.push_back(-c / b);
547 dxdz.push_back(copysign(INFINITY, b));
548 }
549 std::vector<double> cosFic(2, cosLimit);
550 for (int i = 0; i < 2; i++) {
551 if (std::abs(dxdz[i]) < INFINITY) {
552 double aa = (dxdz[i] * cos(theta) - trk.cosFi * sin(theta)) * cer.cosThc;
553 double bb = (dxdz[i] * sin(theta) + trk.cosFi * cos(theta)) * cer.sinThc;
554 double dd = trk.sinFi * cer.sinThc;
555 cosFic[i] = aa * bb / (bb * bb + dd * dd);
556 double kz = cos(theta) * cer.cosThc - sin(theta) * cer.sinThc * cosFic[i];
557 if (kz < 0) dxdz[i] = copysign(INFINITY, dxdz[1 - i] - dxdz[i]);
558 }
559 }
560 if (dxdz[0] > dxdz[1]) {
561 std::reverse(dxdz.begin(), dxdz.end());
562 std::reverse(cosFic.begin(), cosFic.end());
563 }
564 for (int i = 0; i < 2; i++) {
565 if (cosFic[i] < cosLimit) xmima[i] = x0 + dxdz[i] * dz;
566 }
567
568 // just to make sure xmi/xma are within the limits given by maximal propagation length
569 xmi = std::max(xmima[0], x0 - maxLen);
570 xma = std::min(xmima[1], x0 + maxLen);
571
572 return xma > xmi;
573 }
574
575
576 double PDFConstructor::derivativeOfReflectedX(double x, double xe, double ze, double zd) const
577 {
578 double z = sqrt(1 - x * x);
579 double kx = (x - xe);
580 double kz = (z - ze);
581 double s = 2 * (kx * x + kz * z);
582 double qx = kx - s * x;
583 double qz = kz - s * z;
584
585 double der_z = -x / z;
586 double der_s = 2 * (kx + der_z * kz);
587 double der_qx = (1 - s) - der_s * x;
588 double der_qz = (1 - s) * der_z - der_s * z;
589
590 return 1 - der_z * qx / qz + (zd - z) * (der_qx * qz - der_qz * qx) / (qz * qz);
591 }
592
593
594 double PDFConstructor::findReflectionExtreme(double xE, double zE, double zD, int Nxm, double A,
595 const RaytracerBase::Mirror& mirror) const
596 {
597
598 if (Nxm % 2 == 0) {
599 xE = func::unfold(xE, -Nxm, A);
600 } else {
601 xE = func::unfold(xE, Nxm, A);
602 }
603
604 double xe = (xE - mirror.xc) / mirror.R;
605 double ze = (zE - mirror.zc) / mirror.R;
606 double zd = (zD - mirror.zc) / mirror.R;
607
608 double Ah = A / 2;
609
610 double x1 = (-Ah - mirror.xc) / mirror.R;
611 double y1 = derivativeOfReflectedX(x1, xe, ze, zd);
612 if (y1 != y1 or std::abs(y1) == INFINITY) return -Ah;
613
614 double x2 = (Ah - mirror.xc) / mirror.R;
615 double y2 = derivativeOfReflectedX(x2, xe, ze, zd);
616 if (y2 != y2 or std::abs(y2) == INFINITY) return -Ah;
617
618 if (y1 * y2 > 0) return -Ah; // no minimum or maximum
619
620 for (int i = 0; i < 50; i++) {
621 double x = (x1 + x2) / 2;
622 double y = derivativeOfReflectedX(x, xe, ze, zd);
623 if (y != y or std::abs(y) == INFINITY) return -Ah;
624 if (y * y1 < 0) {
625 x2 = x;
626 } else {
627 x1 = x;
628 y1 = y;
629 }
630 }
631 double x = (x1 + x2) / 2;
632
633 return x * mirror.R + mirror.xc;
634 }
635
636 // signal PDF construction for track crossing prism --------------------------------------------------
637
639 {
640 const auto& pixelPositions = m_yScanner->getPixelPositions();
641 const auto& prism = m_inverseRaytracer->getPrism();
642 double speedOfLightQuartz = Const::speedOfLight / m_groupIndex; // average speed of light in quartz
643
644 double xE = m_track.getEmissionPoint().position.X();
645 int nxmi = (xE > 0) ? 0 : -1;
646 int nxma = (xE > 0) ? 1 : 0;
647
648 for (const auto& pixel : pixelPositions.getPixels()) {
649 if (not m_yScanner->getPixelMasks().isActive(pixel.ID)) continue;
650 double RQE = m_yScanner->getPixelEfficiencies().get(pixel.ID);
651 if (RQE == 0) continue;
652 auto& signalPDF = m_signalPDFs[pixel.ID - 1];
653 for (int Nxe = nxmi; Nxe <= nxma; Nxe++) {
654 for (size_t k = 0; k < prism.unfoldedWindows.size(); k++) {
655 const auto sol = prismSolution(pixel, k, Nxe);
656 if (sol.len == 0 or std::abs(sol.L) > m_track.getLengthInQuartz() / 2) continue;
657
658 bool ok = prismRaytrace(sol);
659 if (not ok) continue;
660 int Nye = k - prism.k0;
661 if (Nye != m_fastRaytracer->getNy() or Nxe != m_fastRaytracer->getNx()) continue;
663 const auto firstState = m_fastRaytracer->getPhotonStates().front(); // a copy of
664 const auto lastState = m_fastRaytracer->getPhotonStates().back(); // a copy of
665
666 double slope = lastState.getKy() / lastState.getKz();
667 double dz = prism.zD - prism.zFlat;
668 double y2 = std::min(pixel.yc + pixel.Dy / 2, prism.yUp + slope * dz);
669 double y1 = std::max(pixel.yc - pixel.Dy / 2, prism.yDown + slope * dz);
670 double Dy = y2 - y1;
671 if (Dy < 0) continue;
672
673 double dL = 0.1; // cm
674 for (int i = 0; i < 4; i++) {
675 ok = prismRaytrace(sol, dL);
676 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
677 if (ok) break;
678 dL = - dL / 2;
679 }
680 if (not ok) continue;
681 const auto lastState_dL = m_fastRaytracer->getPhotonStates().back(); // a copy of
682
683 double dFic = 0.01; // rad
684 for (int i = 0; i < 4; i++) {
685 ok = prismRaytrace(sol, 0, dFic);
686 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
687 if (ok) break;
688 dFic = - dFic / 2;
689 }
690 if (not ok) continue;
691 const auto lastState_dFic = m_fastRaytracer->getPhotonStates().back(); // a copy of
692
693 double de = 0.1; // eV
694 for (int i = 0; i < 4; i++) {
695 ok = prismRaytrace(sol, 0, 0, de);
696 ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
697 if (ok) break;
698 de = - de / 2;
699 }
700 if (not ok) continue;
701 const auto lastState_de = m_fastRaytracer->getPhotonStates().back(); // a copy of
702
703 double dx_dL = (lastState_dL.getX() - lastState.getX()) / dL;
704 double dy_dL = (lastState_dL.getY() - lastState.getY()) / dL;
705 double dx_dFic = (lastState_dFic.getX() - lastState.getX()) / dFic;
706 double dy_dFic = (lastState_dFic.getY() - lastState.getY()) / dFic;
707 double Jacobi = dx_dL * dy_dFic - dy_dL * dx_dFic;
708 double numPhotons = m_yScanner->getNumPhotonsPerLen() * pixel.Dx * Dy / std::abs(Jacobi) * RQE;
709
710 double dLen_de = (lastState_de.getPropagationLen() - lastState.getPropagationLen()) / de;
711 double dLen_dL = (lastState_dL.getPropagationLen() - lastState.getPropagationLen()) / dL;
712 double dLen_dFic = (lastState_dFic.getPropagationLen() - lastState.getPropagationLen()) / dFic;
713
714 double dt_de = (dLen_de + sol.len * m_groupIndexDerivative / m_groupIndex) / speedOfLightQuartz;
715 double dt_dL = dLen_dL / speedOfLightQuartz;
716 double dt_dFic = dLen_dFic / speedOfLightQuartz;
717
718 double chromatic = pow(dt_de * m_yScanner->getRMSEnergy(), 2);
719
720 double DL = (dy_dFic * pixel.Dx - dx_dFic * pixel.Dy) / Jacobi;
721 double DFic = (dx_dL * pixel.Dy - dy_dL * pixel.Dx) / Jacobi;
722 double paralax = (pow(dt_dL * DL, 2) + pow(dt_dFic * DFic, 2)) / 12;
723
724 double scattering = pow(dLen_de * m_yScanner->getSigmaScattering() / speedOfLightQuartz, 2);
725
727 peak.t0 = m_tof + sol.L / m_beta / Const::speedOfLight + sol.len / speedOfLightQuartz;
728 peak.wid = chromatic + paralax + scattering;
729 peak.nph = 1 - exp(-numPhotons); // because photons that pile-up are counted as one
730 peak.fic = atan2(sol.sinFic, sol.cosFic);
731 signalPDF.append(peak);
732
733 if (m_storeOption == c_Reduced) continue;
734
737 extra.e = m_yScanner->getMeanEnergy();
738 extra.sige = m_yScanner->getRMSEnergy();
739 extra.Nxe = Nxe;
740 extra.Nye = Nye;
741 extra.xD = lastState.getXD();
742 extra.yD = lastState.getYD();
743 extra.zD = lastState.getZD();
744 extra.kxE = firstState.getKx();
745 extra.kyE = firstState.getKy();
746 extra.kzE = firstState.getKz();
747 extra.kxD = lastState.getKx();
748 extra.kyD = lastState.getKy();
749 extra.kzD = lastState.getKz();
751 signalPDF.append(extra);
752
753 } // reflections in y (unfolded prism windows)
754 } // reflections in x
755 } // pixels
756
757 }
758
759
760 bool PDFConstructor::prismRaytrace(const PrismSolution& sol, double dL, double dFic, double de)
761 {
762 const auto& emi = m_track.getEmissionPoint(sol.L + dL);
763 const auto& trk = emi.trackAngles;
764 const auto& cer = cerenkovAngle(de);
765
766 double cosDFic = 1;
767 double sinDFic = 0;
768 if (dFic != 0) {
769 cosDFic = cos(dFic);
770 sinDFic = sin(dFic);
771 }
772 double cosFic = sol.cosFic * cosDFic - sol.sinFic * sinDFic;
773 double sinFic = sol.sinFic * cosDFic + sol.cosFic * sinDFic;
774 double a = trk.cosTh * cer.sinThc * cosFic + trk.sinTh * cer.cosThc;
775 double b = cer.sinThc * sinFic;
776 double kx = a * trk.cosFi - b * trk.sinFi;
777 double ky = a * trk.sinFi + b * trk.cosFi;
778 double kz = trk.cosTh * cer.cosThc - trk.sinTh * cer.sinThc * cosFic;
779 PhotonState photon(emi.position, kx, ky, kz);
780 m_fastRaytracer->propagate(photon);
781
783 }
784
785
787 unsigned k, int nx)
788 {
789 const auto& prism = m_inverseRaytracer->getPrism();
790 const auto& win = prism.unfoldedWindows[k];
791 double dz = std::abs(prism.zD - prism.zFlat);
792 ROOT::Math::XYZPoint rD(func::unfold(pixel.xc, nx, prism.A),
793 pixel.yc * win.sy + win.y0 + win.ny * dz,
794 pixel.yc * win.sz + win.z0 + win.nz * dz);
795
796 double L = 0;
797 for (int iter = 0; iter < 100; iter++) {
798 auto sol = prismSolution(rD, L);
799 if (std::abs(sol.L) > m_track.getLengthInQuartz() / 2) return sol;
800 if (std::abs(sol.L - L) < 0.01) return sol;
801 L = sol.L;
802 }
803 B2DEBUG(20, "TOP::PDFConstructor::prismSolution: iterations not converging");
804 return PrismSolution();
805 }
806
807
808 PDFConstructor::PrismSolution PDFConstructor::prismSolution(const ROOT::Math::XYZPoint& rD, double L)
809 {
810 const auto& emi = m_track.getEmissionPoint(L);
811
812 // transformation of detection position to system of particle
813
814 auto r = rD - emi.position;
815 const auto& trk = emi.trackAngles;
816 double xx = r.X() * trk.cosFi + r.Y() * trk.sinFi;
817 double y = -r.X() * trk.sinFi + r.Y() * trk.cosFi;
818 double x = xx * trk.cosTh - r.Z() * trk.sinTh;
819 double z = xx * trk.sinTh + r.Z() * trk.cosTh;
820
821 // solution
822
823 double rho = sqrt(x * x + y * y);
824 const auto& cer = cerenkovAngle();
825
826 PrismSolution sol;
827 sol.len = rho / cer.sinThc;
828 sol.L = L + z - sol.len * cer.cosThc;
829 sol.cosFic = x / rho;
830 sol.sinFic = y / rho;
831
832 return sol;
833 }
834
835 // log likelihood calculation ------------------------------------------------------------------------
836
838 {
839 if (not m_valid) {
840 B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
841 return LogL(0);
842 }
843
845 for (const auto& hit : m_selectedHits) {
846 if (hit.time < m_minTime or hit.time > m_maxTime) continue;
847 double f = pdfValue(hit.pixelID, hit.time, hit.timeErr);
848 if (f <= 0) {
849 auto ret = m_zeroPixels.insert(hit.pixelID);
850 if (ret.second) {
851 B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
852 << LogVar("slotID", m_moduleID)
853 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
854 }
855 continue;
856 }
857 LL.logL += log(f);
858 LL.numPhotons++;
859 LL.effectiveSignalYield += m_f0 / f;
860 }
861 return LL;
862 }
863
864
865 PDFConstructor::LogL PDFConstructor::getLogL(double t0, double minTime, double maxTime, double sigt) const
866 {
867 if (not m_valid) {
868 B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
869 return LogL(0);
870 }
871
872 LogL LL(getExpectedPhotons(minTime - t0, maxTime - t0));
873 for (const auto& hit : m_selectedHits) {
874 if (hit.time < minTime or hit.time > maxTime) continue;
875 double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
876 if (f <= 0) {
877 auto ret = m_zeroPixels.insert(hit.pixelID);
878 if (ret.second) {
879 B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
880 << LogVar("slotID", m_moduleID)
881 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
882 }
883 continue;
884 }
885 LL.logL += log(f);
886 LL.numPhotons++;
887 LL.effectiveSignalYield += m_f0 / f;
888 }
889 return LL;
890 }
891
892
893 PDFConstructor::LogL PDFConstructor::getBackgroundLogL(double minTime, double maxTime) const
894 {
895 if (not m_valid) {
896 B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): object status is invalid - cannot provide log likelihood");
897 return LogL(0);
898 }
899
900 double bkgPhotons = m_bkgPhotons * (maxTime - minTime) / (m_maxTime - m_minTime);
901
902 LogL LL(bkgPhotons);
903 for (const auto& hit : m_selectedHits) {
904 if (hit.time < minTime or hit.time > maxTime) continue;
905 double f = bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID);
906 if (f <= 0) {
907 auto ret = m_zeroPixels.insert(hit.pixelID);
908 if (ret.second) {
909 B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): PDF value is zero or negative"
910 << LogVar("slotID", m_moduleID)
911 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
912 }
913 continue;
914 }
915 LL.logL += log(f);
916 LL.numPhotons++;
917 }
918 return LL;
919 }
920
921
922 const std::vector<PDFConstructor::LogL>&
923 PDFConstructor::getPixelLogLs(double t0, double minTime, double maxTime, double sigt) const
924 {
925 if (not m_valid) {
926 B2ERROR("TOP::PDFConstructor::getPixelLogLs(): object status is invalid - cannot provide log likelihoods");
927 return m_pixelLLs;
928 }
929
930 initializePixelLogLs(minTime - t0, maxTime - t0);
931
932 for (const auto& hit : m_selectedHits) {
933 if (hit.time < minTime or hit.time > maxTime) continue;
934 double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
935 if (f <= 0) {
936 auto ret = m_zeroPixels.insert(hit.pixelID);
937 if (ret.second) {
938 B2ERROR("TOP::PDFConstructor::getPixelLogLs(): PDF value is zero or negative"
939 << LogVar("slotID", m_moduleID)
940 << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
941 }
942 continue;
943 }
944 unsigned k = hit.pixelID - 1;
945 auto& LL = m_pixelLLs[k];
946 LL.logL += log(f);
947 LL.numPhotons++;
948 LL.effectiveSignalYield += m_f0 / f;
949 }
950
951 return m_pixelLLs;
952 }
953
954 void PDFConstructor::initializePixelLogLs(double minTime, double maxTime) const
955 {
956 m_pixelLLs.clear();
957
958 double pb = (maxTime - minTime) / (m_maxTime - m_minTime);
959 double bfot = pb * m_bkgPhotons + getExpectedDeltaPhotons(minTime, maxTime);
960 for (const auto* other : m_pdfOtherTracks) bfot += other->getExpectedDeltaPhotons(minTime, maxTime);
961
962 const auto& pixelPDF = m_backgroundPDF->getPDF();
963 for (const auto& signalPDF : m_signalPDFs) {
964 unsigned k = signalPDF.getPixelID() - 1;
965 double phot = signalPDF.getIntegral(minTime, maxTime) * m_signalPhotons + bfot * pixelPDF[k];
966 for (const auto* other : m_pdfOtherTracks) {
967 const auto& otherPDFs = other->getSignalPDF();
968 phot += otherPDFs[k].getIntegral(minTime, maxTime) * other->getExpectedSignalPhotons();
969 }
970 m_pixelLLs.push_back(LogL(phot));
971 }
972 }
973
974 const std::vector<PDFConstructor::Pull>& PDFConstructor::getPulls() const
975 {
976 if (m_pulls.empty() and m_valid) {
977 for (const auto& hit : m_selectedHits) {
978 if (hit.time < m_minTime or hit.time > m_maxTime) continue;
979 appendPulls(hit);
980 }
981 }
982
983 return m_pulls;
984 }
985
987 {
988 unsigned k = hit.pixelID - 1;
989 if (k >= m_signalPDFs.size()) return;
990 const auto& signalPDF = m_signalPDFs[k];
991
993 double signalFract = m_signalPhotons / sfot;
994 double wid0 = hit.timeErr * hit.timeErr;
995 double minT0 = m_maxTime;
996 double sum = 0;
997 auto i0 = m_pulls.size();
998 for (const auto& peak : signalPDF.getPDFPeaks()) {
999 minT0 = std::min(minT0, peak.t0);
1000 for (const auto& gaus : signalPDF.getTTS()->getTTS()) {
1001 double sig2 = peak.wid + gaus.sigma * gaus.sigma + wid0; // sigma squared!
1002 double x = pow(hit.time - peak.t0 - gaus.position, 2) / sig2;
1003 if (x > 100) continue;
1004 double wt = signalFract * peak.nph * gaus.fraction / sqrt(2 * M_PI * sig2) * exp(-x / 2);
1005 sum += wt;
1006 m_pulls.push_back(Pull(hit.pixelID, hit.time, peak.t0, gaus.position, sqrt(sig2), peak.fic - M_PI, wt));
1007 }
1008 }
1009
1010 double bg = (m_deltaPhotons * m_deltaRayPDF.getPDFValue(hit.pixelID, hit.time) +
1011 m_bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID)) / sfot;
1012 sum += bg;
1013 m_pulls.push_back(Pull(hit.pixelID, hit.time, minT0, 0, 0, 0, bg));
1014
1015 if (sum == 0) return;
1016 for (size_t i = i0; i < m_pulls.size(); i++) m_pulls[i].wt /= sum;
1017 }
1018
1019
1020 } // namespace TOP
1022} // namespace Belle2
1023
1024
R E
internal precision of FFTW codelets
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:589
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
double getPDFValue(int pixelID) const
Returns PDF value for given pixel.
const std::vector< double > & getPDF() const
Returns pixel part of PDF.
Definition: BackgroundPDF.h:50
void prepare(const TOPTrack &track, const Const::ChargedStable &hypothesis)
Prepare the object.
Definition: DeltaRayPDF.cc:70
double getNumPhotons() const
Returns number of photons.
Definition: DeltaRayPDF.h:54
double getPDFValue(int pixelID, double time) const
Returns PDF value at given time and pixel.
Definition: DeltaRayPDF.cc:113
Fast photon propagation in quartz optics.
Definition: FastRaytracer.h:26
double getZD() const
Returns unfolded position in z of virtual Detector plane.
double getPropagationLen() const
Returns total propagation length since initial position.
int getNyb() const
Returns signed number of reflections in y after mirror and before prism.
const std::vector< PhotonState > & getExtraStates() const
Returns extra states.
Definition: FastRaytracer.h:62
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 getNx() const
Returns signed number of reflections in x.
double getYB() const
Returns unfolded position in y at Bar-prism-connection plane.
double getYD() const
Returns unfolded position in y at virtual Detector plane.
int getNxe() const
Returns signed number of reflections in x inside prism.
bool getTotalReflStatus(double cosTotal) const
Returns total internal reflection status.
int getNy() const
Returns signed number of reflections in y.
bool getPropagationStatus() const
Returns propagation status.
Definition: FastRaytracer.h:68
double getPropagationLenDelta() const
Returns total propagation length difference between true and flipped prism.
const std::vector< PhotonState > & getPhotonStates() const
Returns photon states (results of propagation).
Definition: FastRaytracer.h:56
int getNye() const
Returns signed number of reflections in y inside prism.
double getXD() const
Returns unfolded position in x at virtual Detector plane.
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 getStatus() const
Returns status.
std::vector< Solution > & getSolutions(unsigned i) const
Returns the solutions of inverse ray-tracing.
void clear() const
Clear the solutions to prepare for the new round.
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 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
double derivativeOfReflectedX(double x, double xe, double ze, double zd) const
Returns the derivative of reflected position at given x.
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)
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
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
double findReflectionExtreme(double xE, double zE, double zD, int Nxm, double A, const RaytracerBase::Mirror &mirror) const
Finds the position on the mirror of the extreme reflection.
EStoreOption
Options for storing signal PDF parameters.
@ c_Reduced
only PDF peak data
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
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
double get(int pixelID) const
Returns pixel relative efficinecy.
bool isActive(int pixelID) const
Checks if pixel is active.
Definition: PixelMasks.h:85
unsigned getNumPixels() const
Returns number of pixels.
const PixelData & get(int pixelID) const
Returns pixel data for given pixelID.
const Mirror & getMirror() const
Returns geometry data of spherical mirror.
const std::vector< BarSegment > & getBars() const
Returns geometry data of bar segments.
const Prism & getPrism() const
Returns geometry data of prism.
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
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
double getGroupIndexDerivative(double energy) const
Returns the derivative (dn_g/dE) of group refractive index of quartz at given photon energy.
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
double getAbsorptionLength(double energy) const
Returns bulk absorption lenght of quartz at given photon energy.
double getGroupIndex(double energy) const
Returns group refractive index of quartz at given photon energy.
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:39
double getLengthInQuartz() const
Returns track length within quartz.
Definition: TOPTrack.h:173
bool isScanRequired(unsigned col, double time, double wid) const
Checks if scan method of YScanner is needed to construct PDF for a given pixel column.
Definition: TOPTrack.cc:370
const TOPTrack::AssumedEmission & getEmissionPoint(double dL=0) const
Returns assumed photon emission position and track direction.
Definition: TOPTrack.cc:357
void prepare(double momentum, double beta, double length) const
Prepare for the PDF expansion in y for a given track mass hypothesis.
Definition: YScanner.cc:118
double getSigmaScattering() const
Returns r.m.s of multiple scattering angle in quartz converted to photon energy.
Definition: YScanner.h:353
double getNumPhotonsPerLen() const
Returns number of photons per Cerenkov azimuthal angle per track length.
Definition: YScanner.h:317
const PixelPositions & getPixelPositions() const
Returns pixel positions and their sizes.
Definition: YScanner.h:269
const PixelMasks & getPixelMasks() const
Returns pixel masks.
Definition: YScanner.h:275
double getCosTotal() const
Returns cosine of total reflection angle.
Definition: YScanner.h:293
void expand(unsigned col, double yB, double dydz, const Derivatives &D, int Ny, bool doScan) const
Performs the PDF expansion in y for a given pixel column using scan or merge methods.
Definition: YScanner.cc:238
double getSigmaAlpha() const
Returns surface roughness parameter in units of photon energy.
Definition: YScanner.h:359
double getNumPhotons() const
Returns number of photons per Cerenkov azimuthal angle.
Definition: YScanner.h:323
double getMeanEnergy() const
Returns mean photon energy.
Definition: YScanner.h:329
bool isAboveThreshold() const
Returns above Cerenkov threshold flag which is set in the prepare method.
Definition: YScanner.h:251
const PixelEfficiencies & getPixelEfficiencies() const
Returns pixel relative efficiencies.
Definition: YScanner.h:281
const std::vector< Result > & getResults() const
Returns the results of PDF expansion in y.
Definition: YScanner.h:378
double getRMSEnergy() const
Returns r.m.s of photon energy.
Definition: YScanner.h:335
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
const TOPNominalTTS & getTTS(unsigned type) const
Returns time transition spread of a given PMT type.
Definition: TOPGeometry.cc:50
double unfold(double x, int nx, double A)
unfold a coordinate.
Definition: func.h:31
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:78
double within2PI(double angle)
Returns angle within 0 and 2PI.
Definition: func.h:102
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.
Definition: RaytracerBase.h:80
double reflectivity
mirror reflectivity
Definition: RaytracerBase.h:86
double xc
center of curvature in x
Definition: RaytracerBase.h:81
double zc
center of curvature in z
Definition: RaytracerBase.h:83
std::vector< TOPGeoPrism::UnfoldedWindow > unfoldedWindows
unfolded prism exit windows
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
EPeakType type
peak type
Definition: SignalPDF.h:71
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 e
photon energy
Definition: SignalPDF.h:53
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
ROOT::Math::XYZPoint position
position
Definition: TOPTrack.h:75
TrackAngles trackAngles
sine and cosine of track polar and azimuthal angles
Definition: TOPTrack.h:76
selected photon hit from TOPDigits
Definition: TOPTrack.h:83