Belle II Software  release-06-02-00
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 
18 using namespace std;
19 
20 namespace Belle2 {
25  namespace TOP {
26 
27  PDFConstructor::PDFConstructor(const TOPTrack& track, const Const::ChargedStable& hypothesis,
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 
42  m_valid = m_inverseRaytracer != 0 and m_fastRaytracer != 0 and m_yScanner != 0 and m_backgroundPDF != 0;
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 
74  setSignalPDF();
75  }
76 
77  m_deltaRayPDF.prepare(track, hypothesis);
79 
80  m_bkgPhotons = std::max(m_bkgRate * (m_maxTime - m_minTime), 0.1);
81  }
82 
83 
85  {
86  // construct PDF analytically
87 
88  const auto& prism = m_inverseRaytracer->getPrism();
89 
90  if (m_track.getEmissionPoint().position.Z() > prism.zR) {
93  } else {
95  }
96 
97  // count expected number of signal photons
98 
99  for (const auto& signalPDF : m_signalPDFs) {
100  m_signalPhotons += signalPDF.getSum();
101  }
102  if (m_signalPhotons == 0) return;
103 
104  // normalize PDF
105 
106  for (auto& signalPDF : m_signalPDFs) {
107  signalPDF.normalize(m_signalPhotons);
108  }
109  }
110 
111  // signal PDF construction for track crossing bar segments -------------------------------------------
112 
114  {
115  const auto& pixelPositions = m_yScanner->getPixelPositions();
116  const auto& bar = m_inverseRaytracer->getBars().front();
117  const auto& prism = m_inverseRaytracer->getPrism();
118 
119  // determine the range of number of reflections in x
120 
121  double xmi = 0, xma = 0;
122  bool ok = rangeOfX(prism.zD, xmi, xma);
123  if (not ok) return;
124  int kmi = lround(xmi / bar.A);
125  int kma = lround(xma / bar.A);
126 
127  // loop over reflections in x and over pixel columns
128 
129  for (int k = kmi; k <= kma; k++) {
130  for (unsigned col = 0; col < pixelPositions.getNumPixelColumns(); col++) {
131  const auto& pixel = pixelPositions.get(col + 1);
132  if (pixel.Dx == 0) continue;
133  double xD = func::unfold(pixel.xc, k, bar.A);
134  if (xD < xmi or xD > xma) continue;
135  InverseRaytracerDirect direct;
136  setSignalPDF(direct, col, xD, prism.zD);
137  }
138  }
139  }
140 
142  {
143  const auto& bar = m_inverseRaytracer->getBars().back();
144  const auto& prism = m_inverseRaytracer->getPrism();
145  const auto& mirror = m_inverseRaytracer->getMirror();
146  const auto& emiPoint = m_track.getEmissionPoint().position;
147 
148  // determine the range of number of reflections in x before mirror
149 
150  double xmi = 0, xma = 0;
151  bool ok = rangeOfX(mirror.zb, xmi, xma);
152  if (not ok) return;
153  int kmi = lround(xmi / bar.A);
154  int kma = lround(xma / bar.A);
155 
156  // loop over reflections in x before mirror
157 
158  double xE = emiPoint.X();
159  double zE = emiPoint.Z();
160  double Ah = bar.A / 2;
161  for (int k = kmi; k <= kma; k++) {
162  double x0 = findReflectionExtreme(xE, zE, prism.zD, k, bar.A, mirror);
163  x0 = func::clip(x0, k, bar.A, xmi, xma);
164  double xL = func::clip(-Ah, k, bar.A, xmi, xma);
165  double xR = func::clip(Ah, k, bar.A, xmi, xma);
166  if (x0 > xL) setSignalPDF_reflected(k, xL, x0);
167  if (x0 < xR) setSignalPDF_reflected(k, x0, xR);
168  }
169  }
170 
171 
172  void PDFConstructor::setSignalPDF_reflected(int Nxm, double xmMin, double xmMax)
173  {
174  const auto& pixelPositions = m_yScanner->getPixelPositions();
175  const auto& bar = m_inverseRaytracer->getBars().back();
176  const auto& prism = m_inverseRaytracer->getPrism();
177 
178  // determine the range of number of reflections in x after mirror
179 
180  std::vector<double> xDs;
181  double minLen = 1e10;
182  if (not detectionPositionX(xmMin, Nxm, xDs, minLen)) return;
183  if (not detectionPositionX(xmMax, Nxm, xDs, minLen)) return;
184  if (xDs.size() < 2) return;
185 
186  double minTime = m_tof + minLen * m_groupIndex / Const::speedOfLight;
187  if (minTime > m_maxTime) return;
188 
189  std::sort(xDs.begin(), xDs.end());
190  double xmi = xDs.front();
191  double xma = xDs.back();
192 
193  int kmi = lround(xmi / bar.A);
194  int kma = lround(xma / bar.A);
195 
196  // loop over reflections in x after mirror and over pixel columns
197 
198  for (int k = kmi; k <= kma; k++) {
199  for (unsigned col = 0; col < pixelPositions.getNumPixelColumns(); col++) {
200  const auto& pixel = pixelPositions.get(col + 1);
201  if (pixel.Dx == 0) continue;
202  double xD = func::unfold(pixel.xc, k, bar.A);
203  if (xD < xmi or xD > xma) continue;
204  InverseRaytracerReflected reflected;
205  setSignalPDF(reflected, col, xD, prism.zD, Nxm, xmMin, xmMax);
206  }
207  }
208 
209  }
210 
211 
212  bool PDFConstructor::detectionPositionX(double xM, int Nxm, std::vector<double>& xDs, double& minLen)
213  {
216  if (i0 < 0) return false;
217 
218  bool ok = false;
219  for (unsigned i = 0; i < 2; i++) {
220  if (not m_inverseRaytracer->getStatus(i)) continue;
221  const auto& solutions = m_inverseRaytracer->getSolutions(i);
222  const auto& sol = solutions[i0];
223  xDs.push_back(sol.xD);
224  minLen = std::min(minLen, sol.len);
225  ok = true;
226  }
227 
228  return ok;
229  }
230 
231 
232  bool PDFConstructor::doRaytracingCorrections(const InverseRaytracer::Solution& sol, double dFic_dx, double xD)
233  {
234  const double precision = 0.01; // [cm]
235 
236  double x1 = 0; // x is dFic
237  double y1 = deltaXD(x1, sol, xD); // y is the difference in xD
238  if (isnan(y1)) return false;
239  if (abs(y1) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
240  int n1 = m_fastRaytracer->getNxm();
241 
242  double step = -dFic_dx * y1;
243  for (int i = 1; i < 20; i++) { // search for zero-crossing interval
244  double x2 = step * i;
245  double y2 = deltaXD(x2, sol, xD);
246  if (isnan(y2)) return false;
247  int n2 = m_fastRaytracer->getNxm();
248  if (n2 != n1) { // x2 is passing the discontinuity caused by different reflection number
249  double x3 = x2;
250  x2 = x1;
251  y2 = y1;
252  for (int k = 0; k < 20; k++) { // move x2 to discontinuity using bisection
253  double x = (x2 + x3) / 2;
254  double y = deltaXD(x, sol, xD);
255  if (isnan(y)) return false;
256  int n = m_fastRaytracer->getNxm();
257  if (n == n1) {
258  x2 = x;
259  y2 = y;
260  } else {
261  x3 = x;
262  }
263  }
264  if (y2 * y1 > 0) return false; // solution does not exist
265  }
266  if (abs(y2) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
267  if (y2 * y1 < 0) { // zero-crossing interval is identified
268  for (int k = 0; k < 20; k++) { // find zero-crossing using bisection
269  double x = (x1 + x2) / 2;
270  double y = deltaXD(x, sol, xD);
271  if (isnan(y)) return false;
272  if (abs(y) < precision) return m_fastRaytracer->getTotalReflStatus(m_cosTotal);
273  if (y * y1 < 0) {
274  x2 = x;
275  } else {
276  x1 = x;
277  y1 = y;
278  }
279  }
281  }
282  x1 = x2;
283  y1 = y2;
284  }
285 
286  return false;
287  }
288 
289 
291  {
292  m_ncallsExpandPDF[type]++;
293 
294  double Len = m_fastRaytracer->getPropagationLen();
295  double speedOfLightQuartz = Const::speedOfLight / m_groupIndex; // average speed of light in quartz
296 
297  // difference of propagation times of true and fliped prism
298  double dTime = m_fastRaytracer->getPropagationLenDelta() / speedOfLightQuartz;
299 
300  // derivatives: dt/de, dt/dx, dt/dL
301  double dt_de = (D.dLen_de + Len * m_groupIndexDerivative / m_groupIndex) / speedOfLightQuartz;
302  double dt_dx = D.dLen_dx / speedOfLightQuartz;
303  double dt_dL = D.dLen_dL / speedOfLightQuartz + 1 / m_beta / Const::speedOfLight;
304 
305  // contribution of multiple scattering in quartz
306  double sigmaScat = D.dLen_de * m_yScanner->getSigmaScattering() / speedOfLightQuartz;
307 
308  const auto& pixel = m_yScanner->getPixelPositions().get(col + 1);
309  double L = m_track.getLengthInQuartz();
310 
311  // sigma squared: pixel size, parallax, propagation time difference, multiple scattering
312  double wid0 = (pow(dt_dx * pixel.Dx, 2) + pow(dt_dL * L, 2) + pow(dTime, 2)) / 12 + pow(sigmaScat, 2);
313  // sigma squared: adding chromatic contribution
314  double wid = wid0 + pow(dt_de * m_yScanner->getRMSEnergy(), 2);
315 
316  double yB = m_fastRaytracer->getYB();
317  const auto& photonStates = m_fastRaytracer->getPhotonStates();
318  const auto& atPrismEntrance = photonStates[photonStates.size() - 2];
319  double dydz = atPrismEntrance.getKy() / atPrismEntrance.getKz();
320  if (m_fastRaytracer->getNyb() % 2 != 0) dydz = -dydz;
321 
322  bool doScan = (m_PDFOption == c_Fine);
323  if (m_PDFOption == c_Optimal) {
324  double time = m_tof + Len / speedOfLightQuartz;
325  doScan = m_track.isScanRequired(col, time, wid);
326  }
327 
328  m_yScanner->expand(col, yB, dydz, D, doScan);
329 
330  double numPhotons = m_yScanner->getNumPhotons() * abs(D.dFic_dx * pixel.Dx);
331  int nx = m_fastRaytracer->getNx();
332  int ny = m_fastRaytracer->getNy();
333  for (const auto& result : m_yScanner->getResults()) {
334  double RQE = m_yScanner->getPixelEfficiencies().get(result.pixelID);
335  if (RQE == 0) continue;
336  auto& signalPDF = m_signalPDFs[result.pixelID - 1];
337  double dE = result.e0 - m_yScanner->getMeanEnergy();
338  double propLen = Len + D.dLen_de * dE;
339  double speedOfLight = Const::speedOfLight / TOPGeometryPar::Instance()->getGroupIndex(result.e0);
340 
341  SignalPDF::PDFPeak peak;
342  peak.t0 = m_tof + propLen / speedOfLight;
343  peak.wid = wid0 + dt_de * dt_de * result.sigsq;
344  peak.nph = numPhotons * result.sum * RQE * propagationLosses(result.e0, propLen, nx, ny, type);
345  peak.fic = func::within2PI(m_Fic + D.dFic_de * dE);
346  signalPDF.append(peak);
347 
348  if (m_storeOption == c_Reduced) continue;
349 
350  SignalPDF::PDFExtra extra;
351  extra.thc = acos(getCosCerenkovAngle(result.e0));
352  extra.e = result.e0;
353  extra.sige = result.sigsq;
354  extra.Nxm = m_fastRaytracer->getNxm();
355  extra.Nxb = m_fastRaytracer->getNxb();
356  extra.Nxe = m_fastRaytracer->getNxe();
357  extra.Nym = m_fastRaytracer->getNym();
358  extra.Nyb = m_fastRaytracer->getNyb();
359  extra.Nye = m_fastRaytracer->getNye();
360  extra.xD = m_fastRaytracer->getXD();
361  extra.yD = m_fastRaytracer->getYD();
362  extra.zD = m_fastRaytracer->getZD();
363  extra.yB = m_fastRaytracer->getYB();
364  const auto& firstState = photonStates.front();
365  extra.kxE = firstState.getKx();
366  extra.kyE = firstState.getKy();
367  extra.kzE = firstState.getKz();
368  const auto& lastState = photonStates.back();
369  extra.kxD = lastState.getKx();
370  extra.kyD = lastState.getKy();
371  extra.kzD = lastState.getKz();
372  extra.type = type;
373  signalPDF.append(extra);
374  }
375 
376  }
377 
378  double PDFConstructor::propagationLosses(double E, double propLen, int nx, int ny,
379  SignalPDF::EPeakType type) const
380  {
381  double bulk = TOPGeometryPar::Instance()->getAbsorptionLength(E);
382  double surf = m_yScanner->getBars().front().reflectivity;
383  double p = exp(-propLen / bulk) * pow(surf, abs(nx) + abs(ny));
384  if (type == SignalPDF::c_Reflected) p *= std::min(m_yScanner->getMirror().reflectivity, 1.0);
385  return p;
386  }
387 
388  bool PDFConstructor::rangeOfX(double z, double& xmi, double& xma)
389  {
390  double maxLen = (m_maxTime - m_tof) / m_groupIndex * Const::speedOfLight; // maximal propagation length
391  if (maxLen < 0) return false;
392 
393  const auto& emission = m_track.getEmissionPoint();
394  const auto& trk = emission.trackAngles;
395  const auto& cer = cerenkovAngle();
396 
397  // range in x from propagation lenght limit
398 
399  double dz = z - emission.position.Z();
400  double cosFicLimit = (trk.cosTh * cer.cosThc - dz / maxLen) / (trk.sinTh * cer.sinThc); // at maxLen
401  double cosLimit = (dz > 0) ? cosFicLimit : -cosFicLimit;
402  if (cosLimit < -1) return false; // photons cannot reach the plane at z within propagation lenght limit
403 
404  std::vector<double> xmima;
405  double x0 = emission.position.X();
406  if (cosLimit > 1) {
407  xmima.push_back(x0 - maxLen);
408  xmima.push_back(x0 + maxLen);
409  } else {
410  double a = trk.cosTh * cer.sinThc * cosFicLimit + trk.sinTh * cer.cosThc;
411  double b = cer.sinThc * sqrt(1 - cosFicLimit * cosFicLimit);
412  xmima.push_back(x0 + maxLen * (a * trk.cosFi - b * trk.sinFi));
413  xmima.push_back(x0 + maxLen * (a * trk.cosFi + b * trk.sinFi));
414  std::sort(xmima.begin(), xmima.end());
415  }
416  xmi = xmima[0];
417  xma = xmima[1];
418 
419  // range in x from minimal/maximal possible extensions in x, if they exist (d(kx/kz)/dFic = 0)
420 
421  double theta = acos(trk.cosTh);
422  if (dz < 0) theta = M_PI - theta; // rotation around x by 180 deg. (z -> -z, phi -> -phi)
423  dz = abs(dz);
424  double thetaCer = acos(cer.cosThc);
425  if (theta - thetaCer >= M_PI / 2) return false; // photons cannot reach the plane at z
426 
427  std::vector<double> dxdz;
428  double a = -cos(theta + thetaCer) * cos(theta - thetaCer);
429  double b = sin(2 * theta) * trk.cosFi;
430  double c = pow(trk.sinFi * cer.sinThc, 2) - pow(trk.cosFi, 2) * sin(theta + thetaCer) * sin(theta - thetaCer);
431  double D = b * b - 4 * a * c;
432  if (D < 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
433  if (a != 0) {
434  D = sqrt(D);
435  dxdz.push_back((-b - D) / 2 / a);
436  dxdz.push_back((-b + D) / 2 / a);
437  } else {
438  if (b == 0) return true; // minimum and maximum do not exist, range is given by propagation length limit
439  dxdz.push_back(-c / b);
440  dxdz.push_back(copysign(INFINITY, b));
441  }
442  std::vector<double> cosFic(2, cosLimit);
443  for (int i = 0; i < 2; i++) {
444  if (abs(dxdz[i]) < INFINITY) {
445  double aa = (dxdz[i] * cos(theta) - trk.cosFi * sin(theta)) * cer.cosThc;
446  double bb = (dxdz[i] * sin(theta) + trk.cosFi * cos(theta)) * cer.sinThc;
447  double dd = trk.sinFi * cer.sinThc;
448  cosFic[i] = aa * bb / (bb * bb + dd * dd);
449  double kz = cos(theta) * cer.cosThc - sin(theta) * cer.sinThc * cosFic[i];
450  if (kz < 0) dxdz[i] = copysign(INFINITY, dxdz[1 - i] - dxdz[i]);
451  }
452  }
453  if (dxdz[0] > dxdz[1]) {
454  std::reverse(dxdz.begin(), dxdz.end());
455  std::reverse(cosFic.begin(), cosFic.end());
456  }
457  for (int i = 0; i < 2; i++) {
458  if (cosFic[i] < cosLimit) xmima[i] = x0 + dxdz[i] * dz;
459  }
460 
461  // just to make sure xmi/xma are within the limits given by maximal propagation length
462  xmi = std::max(xmima[0], x0 - maxLen);
463  xma = std::min(xmima[1], x0 + maxLen);
464 
465  return xma > xmi;
466  }
467 
468 
469  double PDFConstructor::derivativeOfReflectedX(double x, double xe, double ze, double zd) const
470  {
471  double z = sqrt(1 - x * x);
472  double kx = (x - xe);
473  double kz = (z - ze);
474  double s = 2 * (kx * x + kz * z);
475  double qx = kx - s * x;
476  double qz = kz - s * z;
477 
478  double der_z = -x / z;
479  double der_s = 2 * (kx + der_z * kz);
480  double der_qx = (1 - s) - der_s * x;
481  double der_qz = (1 - s) * der_z - der_s * z;
482 
483  return 1 - der_z * qx / qz + (zd - z) * (der_qx * qz - der_qz * qx) / (qz * qz);
484  }
485 
486 
487  double PDFConstructor::findReflectionExtreme(double xE, double zE, double zD, int Nxm, double A,
488  const RaytracerBase::Mirror& mirror) const
489  {
490 
491  if (Nxm % 2 == 0) {
492  xE = func::unfold(xE, -Nxm, A);
493  } else {
494  xE = func::unfold(xE, Nxm, A);
495  }
496 
497  double xe = (xE - mirror.xc) / mirror.R;
498  double ze = (zE - mirror.zc) / mirror.R;
499  double zd = (zD - mirror.zc) / mirror.R;
500 
501  double Ah = A / 2;
502 
503  double x1 = (-Ah - mirror.xc) / mirror.R;
504  double y1 = derivativeOfReflectedX(x1, xe, ze, zd);
505  if (y1 != y1 or abs(y1) == INFINITY) return -Ah;
506 
507  double x2 = (Ah - mirror.xc) / mirror.R;
508  double y2 = derivativeOfReflectedX(x2, xe, ze, zd);
509  if (y2 != y2 or abs(y2) == INFINITY) return -Ah;
510 
511  if (y1 * y2 > 0) return -Ah; // no minimum or maximum
512 
513  for (int i = 0; i < 50; i++) {
514  double x = (x1 + x2) / 2;
515  double y = derivativeOfReflectedX(x, xe, ze, zd);
516  if (y != y or abs(y) == INFINITY) return -Ah;
517  if (y * y1 < 0) {
518  x2 = x;
519  } else {
520  x1 = x;
521  y1 = y;
522  }
523  }
524  double x = (x1 + x2) / 2;
525 
526  return x * mirror.R + mirror.xc;
527  }
528 
529  // signal PDF construction for track crossing prism --------------------------------------------------
530 
532  {
533  const auto& pixelPositions = m_yScanner->getPixelPositions();
534  const auto& prism = m_inverseRaytracer->getPrism();
535  double speedOfLightQuartz = Const::speedOfLight / m_groupIndex; // average speed of light in quartz
536 
537  double xE = m_track.getEmissionPoint().position.X();
538  int nxmi = (xE > 0) ? 0 : -1;
539  int nxma = (xE > 0) ? 1 : 0;
540 
541  for (const auto& pixel : pixelPositions.getPixels()) {
542  if (not m_yScanner->getPixelMasks().isActive(pixel.ID)) continue;
543  double RQE = m_yScanner->getPixelEfficiencies().get(pixel.ID);
544  if (RQE == 0) continue;
545  auto& signalPDF = m_signalPDFs[pixel.ID - 1];
546  for (int Nxe = nxmi; Nxe <= nxma; Nxe++) {
547  for (size_t k = 0; k < prism.unfoldedWindows.size(); k++) {
548  const auto sol = prismSolution(pixel, k, Nxe);
549  if (sol.len == 0 or abs(sol.L) > m_track.getLengthInQuartz() / 2) continue;
550 
551  bool ok = prismRaytrace(sol);
552  if (not ok) continue;
553  int Nye = k - prism.k0;
554  if (Nye != m_fastRaytracer->getNy() or Nxe != m_fastRaytracer->getNx()) continue;
555  if (not m_fastRaytracer->getTotalReflStatus(m_cosTotal)) continue;
556  const auto firstState = m_fastRaytracer->getPhotonStates().front(); // a copy of
557  const auto lastState = m_fastRaytracer->getPhotonStates().back(); // a copy of
558 
559  double slope = lastState.getKy() / lastState.getKz();
560  double dz = prism.zD - prism.zFlat;
561  double y2 = std::min(pixel.yc + pixel.Dy / 2, prism.yUp + slope * dz);
562  double y1 = std::max(pixel.yc - pixel.Dy / 2, prism.yDown + slope * dz);
563  double Dy = y2 - y1;
564  if (Dy < 0) continue;
565 
566  double dL = 0.1; // cm
567  for (int i = 0; i < 4; i++) {
568  ok = prismRaytrace(sol, dL);
569  ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
570  if (ok) break;
571  dL = - dL / 2;
572  }
573  if (not ok) continue;
574  const auto lastState_dL = m_fastRaytracer->getPhotonStates().back(); // a copy of
575 
576  double dFic = 0.01; // rad
577  for (int i = 0; i < 4; i++) {
578  ok = prismRaytrace(sol, 0, dFic);
579  ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
580  if (ok) break;
581  dFic = - dFic / 2;
582  }
583  if (not ok) continue;
584  const auto lastState_dFic = m_fastRaytracer->getPhotonStates().back(); // a copy of
585 
586  double de = 0.1; // eV
587  for (int i = 0; i < 4; i++) {
588  ok = prismRaytrace(sol, 0, 0, de);
589  ok = ok and Nye == m_fastRaytracer->getNy() and Nxe == m_fastRaytracer->getNx();
590  if (ok) break;
591  de = - de / 2;
592  }
593  if (not ok) continue;
594  const auto lastState_de = m_fastRaytracer->getPhotonStates().back(); // a copy of
595 
596  double dx_dL = (lastState_dL.getX() - lastState.getX()) / dL;
597  double dy_dL = (lastState_dL.getY() - lastState.getY()) / dL;
598  double dx_dFic = (lastState_dFic.getX() - lastState.getX()) / dFic;
599  double dy_dFic = (lastState_dFic.getY() - lastState.getY()) / dFic;
600  double Jacobi = dx_dL * dy_dFic - dy_dL * dx_dFic;
601  double numPhotons = m_yScanner->getNumPhotonsPerLen() * pixel.Dx * Dy / abs(Jacobi) * RQE;
602 
603  double dLen_de = (lastState_de.getPropagationLen() - lastState.getPropagationLen()) / de;
604  double dLen_dL = (lastState_dL.getPropagationLen() - lastState.getPropagationLen()) / dL;
605  double dLen_dFic = (lastState_dFic.getPropagationLen() - lastState.getPropagationLen()) / dFic;
606 
607  double dt_de = (dLen_de + sol.len * m_groupIndexDerivative / m_groupIndex) / speedOfLightQuartz;
608  double dt_dL = dLen_dL / speedOfLightQuartz;
609  double dt_dFic = dLen_dFic / speedOfLightQuartz;
610 
611  double chromatic = pow(dt_de * m_yScanner->getRMSEnergy(), 2);
612 
613  double DL = (dy_dFic * pixel.Dx - dx_dFic * pixel.Dy) / Jacobi;
614  double DFic = (dx_dL * pixel.Dy - dy_dL * pixel.Dx) / Jacobi;
615  double paralax = (pow(dt_dL * DL, 2) + pow(dt_dFic * DFic, 2)) / 12;
616 
617  double scattering = pow(dLen_de * m_yScanner->getSigmaScattering() / speedOfLightQuartz, 2);
618 
619  SignalPDF::PDFPeak peak;
620  peak.t0 = m_tof + sol.L / m_beta / Const::speedOfLight + sol.len / speedOfLightQuartz;
621  peak.wid = chromatic + paralax + scattering;
622  peak.nph = 1 - exp(-numPhotons); // because photons that pile-up are counted as one
623  peak.fic = atan2(sol.sinFic, sol.cosFic);
624  signalPDF.append(peak);
625 
626  if (m_storeOption == c_Reduced) continue;
627 
628  SignalPDF::PDFExtra extra;
630  extra.e = m_yScanner->getMeanEnergy();
631  extra.sige = m_yScanner->getRMSEnergy();
632  extra.Nxe = Nxe;
633  extra.Nye = Nye;
634  extra.xD = lastState.getXD();
635  extra.yD = lastState.getYD();
636  extra.zD = lastState.getZD();
637  extra.kxE = firstState.getKx();
638  extra.kyE = firstState.getKy();
639  extra.kzE = firstState.getKz();
640  extra.kxD = lastState.getKx();
641  extra.kyD = lastState.getKy();
642  extra.kzD = lastState.getKz();
643  extra.type = SignalPDF::c_Direct;
644  signalPDF.append(extra);
645 
646  } // reflections in y (unfolded prism windows)
647  } // reflections in x
648  } // pixels
649 
650  }
651 
652 
653  bool PDFConstructor::prismRaytrace(const PrismSolution& sol, double dL, double dFic, double de)
654  {
655  const auto& emi = m_track.getEmissionPoint(sol.L + dL);
656  const auto& trk = emi.trackAngles;
657  const auto& cer = cerenkovAngle(de);
658 
659  double cosDFic = 1;
660  double sinDFic = 0;
661  if (dFic != 0) {
662  cosDFic = cos(dFic);
663  sinDFic = sin(dFic);
664  }
665  double cosFic = sol.cosFic * cosDFic - sol.sinFic * sinDFic;
666  double sinFic = sol.sinFic * cosDFic + sol.cosFic * sinDFic;
667  double a = trk.cosTh * cer.sinThc * cosFic + trk.sinTh * cer.cosThc;
668  double b = cer.sinThc * sinFic;
669  double kx = a * trk.cosFi - b * trk.sinFi;
670  double ky = a * trk.sinFi + b * trk.cosFi;
671  double kz = trk.cosTh * cer.cosThc - trk.sinTh * cer.sinThc * cosFic;
672  PhotonState photon(emi.position, kx, ky, kz);
673  m_fastRaytracer->propagate(photon);
674 
676  }
677 
678 
680  unsigned k, int nx)
681  {
682  const auto& prism = m_inverseRaytracer->getPrism();
683  const auto& win = prism.unfoldedWindows[k];
684  double dz = abs(prism.zD - prism.zFlat);
685  TVector3 rD(func::unfold(pixel.xc, nx, prism.A),
686  pixel.yc * win.sy + win.y0 + win.ny * dz,
687  pixel.yc * win.sz + win.z0 + win.nz * dz);
688 
689  double L = 0;
690  for (int iter = 0; iter < 100; iter++) {
691  auto sol = prismSolution(rD, L);
692  if (abs(sol.L) > m_track.getLengthInQuartz() / 2) return sol;
693  if (abs(sol.L - L) < 0.01) return sol;
694  L = sol.L;
695  }
696  B2DEBUG(20, "TOP::PDFConstructor::prismSolution: iterations not converging");
697  return PrismSolution();
698  }
699 
700 
702  {
703  const auto& emi = m_track.getEmissionPoint(L);
704 
705  // transformation of detection position to system of particle
706 
707  auto r = rD - emi.position;
708  const auto& trk = emi.trackAngles;
709  double xx = r.X() * trk.cosFi + r.Y() * trk.sinFi;
710  double y = -r.X() * trk.sinFi + r.Y() * trk.cosFi;
711  double x = xx * trk.cosTh - r.Z() * trk.sinTh;
712  double z = xx * trk.sinTh + r.Z() * trk.cosTh;
713 
714  // solution
715 
716  double rho = sqrt(x * x + y * y);
717  const auto& cer = cerenkovAngle();
718 
719  PrismSolution sol;
720  sol.len = rho / cer.sinThc;
721  sol.L = L + z - sol.len * cer.cosThc;
722  sol.cosFic = x / rho;
723  sol.sinFic = y / rho;
724 
725  return sol;
726  }
727 
728  // log likelihood calculation ------------------------------------------------------------------------
729 
731  {
732  if (not m_valid) {
733  B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
734  return LogL(0);
735  }
736 
737  double expectedPhot = m_signalPhotons + m_bkgPhotons;
738  if (m_deltaPDFOn) expectedPhot += m_deltaPhotons;
739 
740  LogL LL(expectedPhot);
741  for (const auto& hit : m_selectedHits) {
742  if (hit.time < m_minTime or hit.time > m_maxTime) continue;
743  double f = pdfValue(hit.pixelID, hit.time, hit.timeErr);
744  if (f <= 0) {
745  B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
746  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
747  continue;
748  }
749  LL.logL += log(f);
750  LL.numPhotons++;
751  }
752  return LL;
753  }
754 
755 
756  PDFConstructor::LogL PDFConstructor::getLogL(double t0, double minTime, double maxTime, double sigt) const
757  {
758  if (not m_valid) {
759  B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
760  return LogL(0);
761  }
762 
763  LogL LL(expectedPhotons(minTime - t0, maxTime - t0));
764  for (const auto& hit : m_selectedHits) {
765  if (hit.time < minTime or hit.time > maxTime) continue;
766  double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
767  if (f <= 0) {
768  B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
769  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
770  continue;
771  }
772  LL.logL += log(f);
773  LL.numPhotons++;
774  }
775  return LL;
776  }
777 
778  const std::vector<PDFConstructor::LogL>&
779  PDFConstructor::getPixelLogLs(double t0, double minTime, double maxTime, double sigt) const
780  {
781  if (not m_valid) {
782  B2ERROR("TOP::PDFConstructor::getPixelLogLs(): object status is invalid - cannot provide log likelihoods");
783  return m_pixelLLs;
784  }
785 
786  initializePixelLogLs(minTime - t0, maxTime - t0);
787 
788  for (const auto& hit : m_selectedHits) {
789  if (hit.time < minTime or hit.time > maxTime) continue;
790  double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
791  if (f <= 0) {
792  B2ERROR("TOP::PDFConstructor::getPixelLogLs(): PDF value is zero or negative"
793  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
794  continue;
795  }
796  unsigned k = hit.pixelID - 1;
797  auto& LL = m_pixelLLs[k];
798  LL.logL += log(f);
799  LL.numPhotons++;
800  }
801 
802  return m_pixelLLs;
803  }
804 
805  double PDFConstructor::expectedPhotons(double minTime, double maxTime) const
806  {
807  double ps = 0;
808  for (const auto& signalPDF : m_signalPDFs) {
809  ps += signalPDF.getIntegral(minTime, maxTime);
810  }
811  double pd = m_deltaPDFOn ? m_deltaRayPDF.getIntegral(minTime, maxTime) : 0.0;
812  double pb = (maxTime - minTime) / (m_maxTime - m_minTime);
813 
814  return ps * m_signalPhotons + pd * m_deltaPhotons + pb * m_bkgPhotons;
815  }
816 
817  void PDFConstructor::initializePixelLogLs(double minTime, double maxTime) const
818  {
819  m_pixelLLs.clear();
820 
821  double pd = m_deltaPDFOn ? m_deltaRayPDF.getIntegral(minTime, maxTime) : 0.0;
822  double pb = (maxTime - minTime) / (m_maxTime - m_minTime);
823  double bfot = pd * m_deltaPhotons + pb * m_bkgPhotons;
824  const auto& pixelPDF = m_backgroundPDF->getPDF();
825  for (const auto& signalPDF : m_signalPDFs) {
826  double ps = signalPDF.getIntegral(minTime, maxTime);
827  unsigned k = signalPDF.getPixelID() - 1;
828  double phot = ps * m_signalPhotons + bfot * pixelPDF[k];
829  m_pixelLLs.push_back(LogL(phot));
830  }
831  }
832 
833  const std::vector<PDFConstructor::Pull>& PDFConstructor::getPulls() const
834  {
835  if (m_pulls.empty() and m_valid) {
836  for (const auto& hit : m_selectedHits) {
837  if (hit.time < m_minTime or hit.time > m_maxTime) continue;
838  appendPulls(hit);
839  }
840  }
841 
842  return m_pulls;
843  }
844 
846  {
847  unsigned k = hit.pixelID - 1;
848  if (k >= m_signalPDFs.size()) return;
849  const auto& signalPDF = m_signalPDFs[k];
850 
851  double sfot = m_signalPhotons + m_deltaPhotons + m_bkgPhotons;
852  double signalFract = m_signalPhotons / sfot;
853  double wid0 = hit.timeErr * hit.timeErr;
854  double minT0 = m_maxTime;
855  double sum = 0;
856  auto i0 = m_pulls.size();
857  for (const auto& peak : signalPDF.getPDFPeaks()) {
858  minT0 = std::min(minT0, peak.t0);
859  for (const auto& gaus : signalPDF.getTTS()->getTTS()) {
860  double sig2 = peak.wid + gaus.sigma * gaus.sigma + wid0; // sigma squared!
861  double x = pow(hit.time - peak.t0 - gaus.position, 2) / sig2;
862  if (x > 100) continue;
863  double wt = signalFract * peak.nph * gaus.fraction / sqrt(2 * M_PI * sig2) * exp(-x / 2);
864  sum += wt;
865  m_pulls.push_back(Pull(hit.pixelID, hit.time, peak.t0, gaus.position, sqrt(sig2), peak.fic - M_PI, wt));
866  }
867  }
868 
869  double bg = (m_deltaPhotons * m_deltaRayPDF.getPDFValue(hit.pixelID, hit.time) +
870  m_bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID)) / sfot;
871  sum += bg;
872  m_pulls.push_back(Pull(hit.pixelID, hit.time, minT0, 0, 0, 0, bg));
873 
874  if (sum == 0) return;
875  for (size_t i = i0; i < m_pulls.size(); i++) m_pulls[i].wt /= sum;
876  }
877 
878 
879  } // namespace TOP
881 } // namespace Belle2
882 
883 
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:470
static const double speedOfLight
[cm/ns]
Definition: Const.h:575
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:69
double getNumPhotons() const
Returns number of photons.
Definition: DeltaRayPDF.h:54
double getIntegral(double minTime, double maxTime) const
Returns integral of PDF from minTime to maxTime.
Definition: DeltaRayPDF.h:213
double getPDFValue(int pixelID, double time) const
Returns PDF value at given time and pixel.
Definition: DeltaRayPDF.cc:112
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.
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.
int getNye() const
Returns signed number of reflections in y inside prism.
const std::vector< PhotonState > & getPhotonStates() const
Returns photon states (results of propagation).
Definition: FastRaytracer.h:56
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.
double expectedPhotons(double minTime, double maxTime) const
Returns the expected number of photons within given time window.
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.
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
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.
double m_groupIndex
group refractive index at mean photon energy
double m_bkgPhotons
expected number of 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.
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.
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
bool m_deltaPDFOn
include/exclude delta-ray PDF in likelihood calculation
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)
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.
double m_tof
time-of-flight from IP to average photon emission position
State of the Cerenkov photon in the quartz optics.
Definition: PhotonState.h:25
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:40
double getLengthInQuartz() const
Returns track length within quartz.
Definition: TOPTrack.h:175
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:368
const TOPTrack::AssumedEmission & getEmissionPoint(double dL=0) const
Returns assumed photon emission position and track direction.
Definition: TOPTrack.cc:355
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:121
double getSigmaScattering() const
Returns r.m.s of multiple scattering angle in quartz converted to photon energy.
Definition: YScanner.h:361
void expand(unsigned col, double yB, double dydz, const Derivatives &D, bool doScan) const
Performs the PDF expansion in y for a given pixel column using scan or merge methods.
Definition: YScanner.cc:217
const PixelPositions & getPixelPositions() const
Returns pixel positions and their sizes.
Definition: YScanner.h:277
const std::vector< Result > & getResults() const
Returns the results of PDF expansion in y.
Definition: YScanner.h:379
double getNumPhotonsPerLen() const
Returns number of photons per Cerenkov azimuthal angle per track length.
Definition: YScanner.h:325
double getCosTotal() const
Returns cosine of total reflection angle.
Definition: YScanner.h:301
const PixelEfficiencies & getPixelEfficiencies() const
Returns pixel relative efficiencies.
Definition: YScanner.h:289
double getNumPhotons() const
Returns number of photons per Cerenkov azimuthal angle.
Definition: YScanner.h:331
double getMeanEnergy() const
Returns mean photon energy.
Definition: YScanner.h:337
bool isAboveThreshold() const
Returns above Cerenkov threshold flag which is set in the prepare method.
Definition: YScanner.h:260
const PixelMasks & getPixelMasks() const
Returns pixel masks.
Definition: YScanner.h:283
double getRMSEnergy() const
Returns r.m.s of photon energy.
Definition: YScanner.h:343
Class to store variables with their name which were sent to the logging service.
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:29
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:76
double within2PI(double angle)
Returns angle within 0 and 2PI.
Definition: func.h:100
Abstract base class for different kinds of events.
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.
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:79
double reflectivity
mirror reflectivity
Definition: RaytracerBase.h:85
double xc
center of curvature in x
Definition: RaytracerBase.h:80
double zc
center of curvature in z
Definition: RaytracerBase.h:82
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
TrackAngles trackAngles
sine and cosine of track polar and azimuthal angles
Definition: TOPTrack.h:77
selected photon hit from TOPDigits
Definition: TOPTrack.h:84