Belle II Software  release-08-01-10
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  // 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;
139  InverseRaytracerDirect direct;
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;
208  InverseRaytracerReflected reflected;
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 
448  SignalPDF::PDFPeak peak;
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 
457  SignalPDF::PDFExtra extra;
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;
662  if (not m_fastRaytracer->getTotalReflStatus(m_cosTotal)) 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 
726  SignalPDF::PDFPeak peak;
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 
735  SignalPDF::PDFExtra extra;
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();
750  extra.type = SignalPDF::c_Direct;
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 
844  LogL LL(getExpectedPhotons());
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  }
860  return LL;
861  }
862 
863 
864  PDFConstructor::LogL PDFConstructor::getLogL(double t0, double minTime, double maxTime, double sigt) const
865  {
866  if (not m_valid) {
867  B2ERROR("TOP::PDFConstructor::getLogL(): object status is invalid - cannot provide log likelihood");
868  return LogL(0);
869  }
870 
871  LogL LL(getExpectedPhotons(minTime - t0, maxTime - t0));
872  for (const auto& hit : m_selectedHits) {
873  if (hit.time < minTime or hit.time > maxTime) continue;
874  double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
875  if (f <= 0) {
876  auto ret = m_zeroPixels.insert(hit.pixelID);
877  if (ret.second) {
878  B2ERROR("TOP::PDFConstructor::getLogL(): PDF value is zero or negative"
879  << LogVar("slotID", m_moduleID)
880  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
881  }
882  continue;
883  }
884  LL.logL += log(f);
885  LL.numPhotons++;
886  }
887  return LL;
888  }
889 
890 
891  PDFConstructor::LogL PDFConstructor::getBackgroundLogL(double minTime, double maxTime) const
892  {
893  if (not m_valid) {
894  B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): object status is invalid - cannot provide log likelihood");
895  return LogL(0);
896  }
897 
898  double bkgPhotons = m_bkgPhotons * (maxTime - minTime) / (m_maxTime - m_minTime);
899 
900  LogL LL(bkgPhotons);
901  for (const auto& hit : m_selectedHits) {
902  if (hit.time < minTime or hit.time > maxTime) continue;
903  double f = bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID);
904  if (f <= 0) {
905  auto ret = m_zeroPixels.insert(hit.pixelID);
906  if (ret.second) {
907  B2ERROR("TOP::PDFConstructor::getBackgroundLogL(): PDF value is zero or negative"
908  << LogVar("slotID", m_moduleID)
909  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
910  }
911  continue;
912  }
913  LL.logL += log(f);
914  LL.numPhotons++;
915  }
916  return LL;
917  }
918 
919 
920  const std::vector<PDFConstructor::LogL>&
921  PDFConstructor::getPixelLogLs(double t0, double minTime, double maxTime, double sigt) const
922  {
923  if (not m_valid) {
924  B2ERROR("TOP::PDFConstructor::getPixelLogLs(): object status is invalid - cannot provide log likelihoods");
925  return m_pixelLLs;
926  }
927 
928  initializePixelLogLs(minTime - t0, maxTime - t0);
929 
930  for (const auto& hit : m_selectedHits) {
931  if (hit.time < minTime or hit.time > maxTime) continue;
932  double f = pdfValue(hit.pixelID, hit.time - t0, hit.timeErr, sigt);
933  if (f <= 0) {
934  auto ret = m_zeroPixels.insert(hit.pixelID);
935  if (ret.second) {
936  B2ERROR("TOP::PDFConstructor::getPixelLogLs(): PDF value is zero or negative"
937  << LogVar("slotID", m_moduleID)
938  << LogVar("pixelID", hit.pixelID) << LogVar("time", hit.time) << LogVar("PDFValue", f));
939  }
940  continue;
941  }
942  unsigned k = hit.pixelID - 1;
943  auto& LL = m_pixelLLs[k];
944  LL.logL += log(f);
945  LL.numPhotons++;
946  }
947 
948  return m_pixelLLs;
949  }
950 
951  void PDFConstructor::initializePixelLogLs(double minTime, double maxTime) const
952  {
953  m_pixelLLs.clear();
954 
955  double pb = (maxTime - minTime) / (m_maxTime - m_minTime);
956  double bfot = pb * m_bkgPhotons + getExpectedDeltaPhotons(minTime, maxTime);
957  for (const auto* other : m_pdfOtherTracks) bfot += other->getExpectedDeltaPhotons(minTime, maxTime);
958 
959  const auto& pixelPDF = m_backgroundPDF->getPDF();
960  for (const auto& signalPDF : m_signalPDFs) {
961  unsigned k = signalPDF.getPixelID() - 1;
962  double phot = signalPDF.getIntegral(minTime, maxTime) * m_signalPhotons + bfot * pixelPDF[k];
963  for (const auto* other : m_pdfOtherTracks) {
964  const auto& otherPDFs = other->getSignalPDF();
965  phot += otherPDFs[k].getIntegral(minTime, maxTime) * other->getExpectedSignalPhotons();
966  }
967  m_pixelLLs.push_back(LogL(phot));
968  }
969  }
970 
971  const std::vector<PDFConstructor::Pull>& PDFConstructor::getPulls() const
972  {
973  if (m_pulls.empty() and m_valid) {
974  for (const auto& hit : m_selectedHits) {
975  if (hit.time < m_minTime or hit.time > m_maxTime) continue;
976  appendPulls(hit);
977  }
978  }
979 
980  return m_pulls;
981  }
982 
984  {
985  unsigned k = hit.pixelID - 1;
986  if (k >= m_signalPDFs.size()) return;
987  const auto& signalPDF = m_signalPDFs[k];
988 
989  double sfot = m_signalPhotons + m_deltaPhotons + m_bkgPhotons;
990  double signalFract = m_signalPhotons / sfot;
991  double wid0 = hit.timeErr * hit.timeErr;
992  double minT0 = m_maxTime;
993  double sum = 0;
994  auto i0 = m_pulls.size();
995  for (const auto& peak : signalPDF.getPDFPeaks()) {
996  minT0 = std::min(minT0, peak.t0);
997  for (const auto& gaus : signalPDF.getTTS()->getTTS()) {
998  double sig2 = peak.wid + gaus.sigma * gaus.sigma + wid0; // sigma squared!
999  double x = pow(hit.time - peak.t0 - gaus.position, 2) / sig2;
1000  if (x > 100) continue;
1001  double wt = signalFract * peak.nph * gaus.fraction / sqrt(2 * M_PI * sig2) * exp(-x / 2);
1002  sum += wt;
1003  m_pulls.push_back(Pull(hit.pixelID, hit.time, peak.t0, gaus.position, sqrt(sig2), peak.fic - M_PI, wt));
1004  }
1005  }
1006 
1007  double bg = (m_deltaPhotons * m_deltaRayPDF.getPDFValue(hit.pixelID, hit.time) +
1008  m_bkgPhotons * m_backgroundPDF->getPDFValue(hit.pixelID)) / sfot;
1009  sum += bg;
1010  m_pulls.push_back(Pull(hit.pixelID, hit.time, minT0, 0, 0, 0, bg));
1011 
1012  if (sum == 0) return;
1013  for (size_t i = i0; i < m_pulls.size(); i++) m_pulls[i].wt /= sum;
1014  }
1015 
1016 
1017  } // namespace TOP
1019 } // namespace Belle2
1020 
1021 
R E
internal precision of FFTW codelets
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:580
static const double speedOfLight
[cm/ns]
Definition: Const.h:686
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.
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 > & getExtraStates() const
Returns extra states.
Definition: FastRaytracer.h:62
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.
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_tof
time-of-flight from IP to average photon emission position
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
const PixelPositions & getPixelPositions() const
Returns pixel positions and their sizes.
Definition: YScanner.h:269
const std::vector< Result > & getResults() const
Returns the results of PDF expansion in y.
Definition: YScanner.h:378
double getNumPhotonsPerLen() const
Returns number of photons per Cerenkov azimuthal angle per track length.
Definition: YScanner.h:317
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
const PixelEfficiencies & getPixelEfficiencies() const
Returns pixel relative efficiencies.
Definition: YScanner.h:281
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 PixelMasks & getPixelMasks() const
Returns pixel masks.
Definition: YScanner.h:275
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.
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: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