9#include <top/reconstruction_cpp/YScanner.h>
10#include <top/reconstruction_cpp/func.h>
11#include <top/geometry/TOPGeometryPar.h>
12#include <framework/logging/Logger.h>
29 if (sol_dx.
step == 0) B2ERROR(
"TOP::YScanner::Derivatives: step (dx) is zero");
30 if (sol_de.
step == 0) B2ERROR(
"TOP::YScanner::Derivatives: step (de) is zero");
31 if (sol_dL.
step == 0) B2ERROR(
"TOP::YScanner::Derivatives: step (dL) is zero");
53 B2FATAL(
"TOP::YScanner: N must be > 1");
60 const auto* geo = topgp->getGeometry();
61 auto qe = geo->getNominalQE();
62 qe.applyFilterTransmission(geo->getWavelengthFilter());
67 B2FATAL(
"TOP::YScanner: quantum efficiency found zero for all wavelengths");
72 const auto& tdc = geo->getNominalTDC();
73 for (
unsigned i = 0; i < N; i++) {
76 double effi = qe.getEfficiency(lambda) * tdc.getEfficiency();
87 double p = entry.y * (1 - 1 / pow(topgp->getPhaseIndex(e), 2));
129 if (beta * topgp->getPhaseIndex(
m_meanE0) < 1)
return;
134 if (area == 0)
return;
142 const double radLength = 12.3;
143 double thetaScat = 13.6e-3 / beta / momentum *
sqrt(length / 2 / radLength);
145 double n = topgp->getPhaseIndex(
m_meanE);
147 B2ERROR(
"TOP::YScanner::prepare: beta * n < 1 ==> must be a bug!");
150 double dndE = topgp->getPhaseIndexDerivative(
m_meanE);
151 double dEdTheta = n *
sqrt(pow(beta * n, 2) - 1) / dndE;
174 double p = std::max(entry.y * (1 - 1 / pow(beta * topgp->getPhaseIndex(e), 2)), 0.0);
175 double ee = entry.xsq;
181 if (s == 0)
return 0;
196 B2ERROR(
"TOP::YScanner:setQuasyEnergyDistribution: unexpectedly large size of the std::map found, map cleared");
200 int ng = lround(3 * sigma / step);
203 if (quasyEnergyDistribution.entries.empty()) {
204 std::vector<double> gaus;
205 for (
int i = 0; i <= ng; i++) {
206 double x = step * i / sigma;
207 gaus.push_back(exp(-0.5 * x * x));
213 for (
int k = -ng; k < N + ng; k++) {
217 for (
int i = -ng; i <= ng; i++) {
228 quasyEnergyDistribution.entries.push_back(
TableEntry(s, se, see));
231 for (
auto& entry : quasyEnergyDistribution.entries) entry.y /= sum;
242 if (D.dyB_de == 0)
return;
250 double dely = (std::abs(D.dyB_dL) *
m_length + std::abs(D.dyB_dx) * pixDx) / 2;
251 double y1 = yB - dely;
252 double y2 = yB + dely;
254 y1 += D.dyB_de * (minE -
m_meanE);
255 y2 += D.dyB_de * (maxE -
m_meanE);
257 y1 += D.dyB_de * (maxE -
m_meanE);
258 y2 += D.dyB_de * (minE -
m_meanE);
260 double B =
m_bars.front().B;
261 int j1 = lround(y1 / B);
262 int j2 = lround(y2 / B) + 1;
265 scan(col, yB, dydz, D, j1, j2);
268 merge(col, dydz, j1, j2);
277 std::map<int, EnergyMask*> masks;
284 std::vector<PixelProjection> projections[2];
288 if (proj[0].Dy > 0) projections[0].push_back(proj[0]);
289 proj[1].yc = -proj[1].yc;
290 if (proj[1].Dy > 0) projections[1].push_back(proj[1]);
292 if (projections[0].empty() and projections[1].empty())
continue;
294 for (
unsigned k = 0; k < 2; k++) {
295 std::sort(projections[k].begin(), projections[k].end());
296 for (
auto& projection : projections[k]) {
297 int iDy = lround(projection.Dy * 1000);
298 auto& mask = masks[iDy];
300 double Dy = projection.Dy;
304 projection.mask = mask;
309 double wid_old = 1000;
311 for (
int j = j1; j < j2; j++) {
312 double ybar = j *
m_bars.front().B - yB;
313 for (
const auto& projection : projections[std::abs(j) % 2]) {
314 double Ecp = (ybar + projection.yc) / D.dyB_de +
m_meanE;
315 double wid = projection.mask->getFullWidth();
316 if (std::abs(Ecp - Ecp_old) > (wid + wid_old) / 2 and
m_results.back().sum > 0) {
328 for (
auto& result :
m_results) result.set();
330 for (
auto& mask : masks) {
331 if (mask.second)
delete mask.second;
340 int Nodd = j2 - j1 - Neven;
353 if (proj[0].Dy > 0) Dy0 += proj[0].Dy;
354 if (proj[1].Dy > 0) Dy1 += proj[1].Dy;
356 if (Dy0 == 0 and Dy1 == 0)
continue;
358 double Dy = (Dy0 * Neven + Dy1 * Nodd) / (Neven + Nodd);
360 result.sum = Dy /
m_bars.front().B;
370 const auto& mask = energyMask->
getMask();
376 double m = energyMask->
getMask(
E - Ecp);
379 double s = entry.y * m;
381 result.e0 += entry.x * s;
382 result.sigsq += entry.xsq * s;
394 int M = mask.size() - 1;
395 int i1 = std::max(i0 - M, 0);
396 int i2 = std::min(i0 + M - 1, N);
397 for (
int i = i1; i <= i2; i++) {
399 double m = mask[std::abs(i - i0)] * (1 - fract) + mask[std::abs(i - i0 + 1)] * fract;
400 double s = entry.y * m;
402 result.e0 += entry.x * s;
403 result.sigsq += entry.xsq * s;
411 double halfSize = (k -
m_prism.
k0) % 2 == 0 ? size / 2 : -size / 2;
412 const double ypix[2] = {yc - halfSize, yc + halfSize};
413 double yproj[2][2] = {{0}};
417 double projectedY = win.y0 + win.ny * dz;
418 double projectedZ = win.z0 + win.nz * dz;
421 for (
int i = 0; i < 2; ++i) {
423 double z = ypix[i] * win.sz + projectedZ;
424 double y = ypix[i] * win.sy + projectedY;
426 yproj[0][i] = y + dy;
427 yproj[1][i] = y - dy;
430 double Bh =
m_bars.front().B / 2;
431 for (
int i = 0; i < 2; ++i) {
432 yproj[i][0] = std::max(yproj[i][0], -Bh);
433 yproj[i][1] = std::min(yproj[i][1], Bh);
434 proj[i].yc = (yproj[i][0] + yproj[i][1]) / 2;
435 proj[i].Dy = yproj[i][1] - yproj[i][0];
A mask for energy masking.
const std::vector< double > & getMask() const
Returns discrete mask (note: only half of the mask is stored)
Pixel relative efficiencies of a single module.
Pixel masks of a single module.
bool isActive(int pixelID) const
Checks if pixel is active.
Pixel positions and dimensions in module local frame.
int pixelID(unsigned row, unsigned col) const
Transforms pixel row and column to pixel ID Note: for convenience pixel row and column numbering star...
unsigned getNumPixelRows() const
Returns the number of pixel rows.
const PixelData & get(int pixelID) const
Returns pixel data for given pixelID.
Base class with geometry data.
@ c_Unified
single bar with average width and thickness
@ c_SemiLinear
semi-linear approximation
Prism m_prism
prism geometry data
std::vector< BarSegment > m_bars
geometry data of bar segments
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
static const double c_hc
Planck constant times speed of light in [eV*nm].
double m_cosTotal
cosine of total reflection angle
void prepare(double momentum, double beta, double length) const
Prepare for the PDF expansion in y for a given track mass hypothesis.
Table m_energyDistribution
photon energy distribution
PixelEfficiencies m_pixelEfficiencies
pixel relative efficiencies
double m_beta
particle beta
bool m_scanDone
true if scan performed, false if reflections just merged
Table m_efficiency
nominal photon detection efficiencies (PDE)
double m_meanE
mean photon energy
static int s_maxReflections
maximal number of reflections to perform scan
double m_rmsE
r.m.s of photon energy
bool m_aboveThreshold
true if beta is above the Cerenkov threshold
void projectPixel(double yc, double size, int k, double dydz, PixelProjection proj[2]) const
Calculates projections of a pixel to prism entrance window (going down-stream the photon).
void merge(unsigned col, double dydz, int j1, int j2) const
Performs expansion by merging all reflections.
void scan(unsigned col, double yB, double dydz, const Derivatives &D, int j1, int j2) const
Performs expansion w/ the scan over reflections.
double m_meanE0
mean photon energy for beta = 1
double m_momentum
particle momentum magnitude
Table * m_quasyEnergyDistribution
a pointer to the element in m_quasyEnergyDistributions
PixelMasks m_pixelMasks
pixel masks
void setQuasyEnergyDistribution(double sigma) const
Sets photon energy distribution convoluted with a normalized Gaussian.
void integrate(const EnergyMask *energyMask, double Ecp, Result &result) const
Integrates quasy energy distribution multiplied with energy mask.
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.
YScanner(int moduleID, unsigned N=64)
Class constructor.
std::map< int, Table > m_quasyEnergyDistributions
photon energy distributions convoluted with Gaussian of different widths
double setEnergyDistribution(double beta) const
Sets photon energy distribution and mean photon energy according to nominal PDE and particle beta.
double m_length
length of particle trajectory inside quartz
double m_rmsE0
r.m.s of photon energy for beta = 1
std::vector< Result > m_results
results of PDF expansion in y
PixelPositions m_pixelPositions
positions and sizes of pixels
void clear() const
Clear mutable variables.
double m_numPhotons
number of photons per Cerenkov azimuthal angle per track length
double m_sigmaAlpha
surface roughness parameter in photon energy units
double sqrt(double a)
sqrt for double
int getNumOfEven(int j1, int j2)
Returns number of even numbers in the range given by arguments.
Abstract base class for different kinds of events.
Solution of inverse ray-tracing.
double step
step for numerical derivative calculation
std::vector< TOPGeoPrism::UnfoldedWindow > unfoldedWindows
unfolded prism exit windows
double zFlat
z where flat continues to slanted surface
double zR
maximal z, i.e position of prism-bar joint
double zD
detector (photo-cathode) position
int k0
index of true prism in the vector 'unfoldedWindows'
static double dyB_d(const InverseRaytracer::Solution &sol0, const InverseRaytracer::Solution &sol1)
Calculates the derivative of unfolded y coordinate at prism entrance.
static double dLen_d(const InverseRaytracer::Solution &sol0, const InverseRaytracer::Solution &sol1)
Calculates the derivative of propagation length.
double dFic_de
Cerenkov azimuthal angle over photon energy.
double dLen_de
propagation length over photon energy
Derivatives()
Default constructor.
double dFic_dx
Cerenkov azimuthal angle over photon detection coordinate x.
double dFic_dL
Cerenkov azimuthal angle over running parameter of particle trajectory.
double dLen_dL
propagation length over running parameter of particle trajectory
double dyB_de
unfolded y coordinate at prism entrance over photon energy
double dLen_dx
propagation length over photon detection coordinate x
double dyB_dL
unfolded y coordinate at prism entrance over running parameter of particle trajectory
double dyB_dx
unfolded y coordinate at prism entrance over photon detection coordinate x
static double dFic_d(const InverseRaytracer::Solution &sol0, const InverseRaytracer::Solution &sol1)
Calculates the derivative of Cerenkov azimuthal angle.
Down-stream projection of a pixel to prism entrance window w/ a clip on bar exit thickness.
double getY(int i) const
Returns y for a given index.
int getIndex(double x) const
Returns index.
std::vector< TableEntry > entries
table entries
double getXmax() const
Returns x of the last entry.
double getX(int i) const
Returns x for a given index.
void clear()
Clear the content entirely.
double getXmin() const
Returns x of the first entry.
void set(double X0, double Step)
Sets the first x and the step, and clears the entries.