4 #include "../FdProfileReconstructorKG/OpticalHalo.h"
6 #include <fwk/CentralConfig.h>
7 #include <utl/Reader.h>
8 #include <utl/ErrorLogger.h>
9 #include <utl/PhysicalFunctions.h>
10 #include <utl/Point.h>
11 #include <utl/Integrator.h>
12 #include <utl/TabulatedFunction.h>
13 #include <det/Detector.h>
14 #include <fdet/Telescope.h>
15 #include <atm/Atmosphere.h>
16 #include <atm/ProfileResult.h>
17 #include <atm/AttenuationResult.h>
18 #include <atm/ScatteringResult.h>
19 #include <atm/InclinedAtmosphericProfile.h>
28 using namespace FdEnergyDepositFinderKG;
35 const double distanceAlongShower,
36 const double showerAge,
37 const double verticalDepth,
39 fDistanceToTelescope(distanceToTelescope),
40 fDistanceAlongShower(distanceAlongShower),
41 fShowerAge(showerAge),
42 fVerticalDepth(verticalDepth),
43 fArcLengthFunction(arcLengthFunction),
44 fSmallAngleApprox(false)
51 const double distanceRatio = fDistanceToTelescope / fDistanceAlongShower;
52 const auto& atmo = det::Detector::GetInstance().GetAtmosphere();
57 if (fSmallAngleApprox) {
59 const double theta = zeta * distanceRatio;
60 jacobian = distanceRatio;
61 pdf = atmo.AngularCherenkovPDF(theta, fVerticalDepth, fShowerAge);
65 const double cosZeta = cos(zeta);
66 const double sinZeta = sin(zeta);
67 const double tanZeta = sinZeta / cosZeta;
69 const double cosZeta2 = cosZeta * cosZeta;
70 const double sinZeta2 = sinZeta * sinZeta;
71 const double theta = atan(tanZeta * distanceRatio);
72 jacobian = 1 / (cosZeta2/distanceRatio + distanceRatio*sinZeta2);
73 pdf = atmo.AngularCherenkovPDF(theta, fVerticalDepth, fShowerAge);
77 const double arcLength = fArcLengthFunction.Y(zeta);
79 return pdf * jacobian * arcLength;
83 double fDistanceToTelescope = 0;
84 double fDistanceAlongShower = 0;
85 double fShowerAge = 0;
86 double fVerticalDepth = 0;
88 bool fSmallAngleApprox =
false;
97 const double distance,
98 const double moliereRadius,
100 fShowerAge(showerAge),
102 fMoliereRadius(moliereRadius),
103 fArcLengthFunction(arcLengthFunction),
104 fSmallAngleApprox(false)
111 const double age = fShowerAge;
112 const double d = fDistance;
113 const double rM = fMoliereRadius;
114 const double distanceRatio = d / rM;
118 if (fSmallAngleApprox) {
119 jacobian = distanceRatio;
120 pdf =
GoraPDF(zeta * distanceRatio, age);
122 const double tanZeta = tan(zeta);
123 const double rStar = distanceRatio * tanZeta;
124 jacobian = distanceRatio*(1 +
Sqr(tanZeta));
128 const double arcLength = fArcLengthFunction.Y(zeta);
130 return pdf * jacobian * arcLength;
134 double fShowerAge = 0;
135 double fDistance = 0;
136 double fMoliereRadius = 0;
138 bool fSmallAngleApprox =
false;
143 LateralLightCalculator::LateralLightCalculator() :
145 fOpticalHalo(nullptr)
162 auto lldBranch = topBranch.
GetChild(
"lateralLight");
168 fMethod = (lldOption ==
"eCircle") ?
170 (lldOption ==
"eBinByBin") ?
172 info <<
"\n\t method: " << lldOption;
175 lldBranch.GetChild(
"fluorescence").GetData(lldIsOn);
177 info <<
"\n\t lateral fluorescence is "
178 << (lldIsOn ?
"on" :
"off");
180 lldBranch.GetChild(
"directCherenkov").GetData(lldIsOn);
182 info <<
"\n\t lateral direct Cherenkov is "
183 << (lldIsOn ?
"on" :
"off");
185 lldBranch.GetChild(
"directCherenkovCorrectedGora").GetData(
fDirCherCorrGora);
186 info <<
"\n\t lateral direct Cherenkov correction for Gora is "
189 lldBranch.GetChild(
"scatteredCherenkov").GetData(lldIsOn);
192 info <<
"\n\t lateral scattered Cherenkov is "
193 << (lldIsOn ?
"on" :
"off");
195 if (lldBranch.GetChild(
"lateralWidthCorrection").Get<
bool>()) {
197 info <<
"\n\t lateralWidthCorrection in PixelIntegrated mode is "
198 "calculated in the same way as for eCircle option";
201 "only be used with eCircle option...");
204 using namespace FdProfileReconstructorKG;
207 info <<
"\n\t lateral width correction is "
220 const double cosTheta,
224 const auto sourceIter =
fLLDIsOn.find(source);
228 if (sourceIter->second) {
237 for (
unsigned int i = 0; i < emissionBin.
GetZetaPixels().size(); ++i)
243 ostringstream errMsg;
244 errMsg <<
" source " << source <<
" not implemented";
254 const double cosTheta,
262 const string errMsg =
"no bin-by-bin efficiency for fluorescence light";
267 const auto& atmo = det::Detector::GetInstance().GetAtmosphere();
269 const auto& tempProfile = atmo.EvaluateTemperatureVsHeight();
270 const auto& pressureProfile = atmo.EvaluatePressureVsHeight();
272 const double height = telData.
fHeight;
274 const double pressure = pressureProfile.Y(height);
275 const double temperature = tempProfile.Y(height);
276 const double age =
ShowerAge(xSlant, xMax);
277 const double rMoliere =
MoliereRadius(temperature, pressure, cosTheta);
281 const double showerTelDist = (meanPos - telescopePos).GetMag();
282 const double distanceToShowerAxis = tan(zeta) * showerTelDist;
284 const double rStar = distanceToShowerAxis / rMoliere;
289 return GoraCDF(rStar, age) * spotFraction;
296 for (
unsigned int i = 0; i < telData.
GetZetaPixels().size(); ++i) {
306 return fraction * spotFraction;
335 const string errMsg =
"no bin-by-bin efficiency for fluorescence light";
343 const double pathLength =
346 if (pathLength < 1*
m)
351 const double showerTelDist = (meanPos - telescopePos).GetMag();
352 const double distanceToShowerAxis = tan(zeta) * showerTelDist;
354 const auto& atmo = det::Detector::GetInstance().GetAtmosphere();
355 const auto& depthProfile = atmo.EvaluateDepthVsHeight();
356 const double height = emissionBin.
fHeight;
358 const double xVert = depthProfile.Y(height);
362 const double maxEmissionAngle = atan2(distanceToShowerAxis, pathLength);
364 atmo.AngularCherenkovCDF(maxEmissionAngle, xVert, showerAge);
367 return fraction * spotFraction;
374 integrator.GetIntegral(0., detectionBin.
GetMaxZeta());
387 const double cosTheta,
395 const string errMsg =
"no bin-by-bin efficiency for direct Cherenkov light";
410 static const double p_VA[30][6] = {
411 { 0.501418, 2.94216, -7.30234, 9.31207, -5.99745, 1.54418 },
412 { -0.00333121, 4.5624, -9.71922, 11.7979, -7.69457, 2.05705 },
413 { -0.00994375, 1.81732, 0.719025, -4.27035, 4.22282, -1.48334 },
414 { -0.00107321, 0.503863, 5.99427, -13.9105, 12.9082, -4.49541 },
415 { 0.000745283, 0.148745, 6.33147, -13.439, 12.1988, -4.23893 },
416 { 0.000709519, 0.0885937, 5.10991, -8.54954, 6.0705, -1.71655 },
417 { 0.000880354, 0.0530137, 4.34411, -5.90561, 3.24284, -0.732068 },
418 { 0.000579476, 0.0499766, 3.56326, -3.08367, -0.234635, 0.708838 },
419 { 0.000467793, 0.0390384, 3.02424, -1.45418, -1.85989, 1.25452 },
420 { 0.000499658, 0.0371965, 2.43002, 0.258876, -3.57741, 1.85539 },
421 { 0.00040399, 0.0208659, 2.08504, 1.23074, -4.54824, 2.21649 },
422 { 8.86504e-05, 0.0440711, 1.35947, 3.24868, -6.701, 3.05502 },
423 { -0.000288326, 0.055371, 0.907594, 4.31152, -7.62045, 3.35124 },
424 { -0.000158639, 0.0429035, 0.800877, 4.33574, -7.43096, 3.2566 },
425 { -0.000312911, 0.0631904, 0.162198, 6.2208, -9.62415, 4.1835 },
426 { -0.000578045, 0.0752885, 0.0811873, 5.96277, -8.99537, 3.87796 },
427 { -0.000428683, 0.0672003, -0.0811488, 6.14087, -9.08156, 3.9582 },
428 { -0.000585311, 0.083422, -0.437892, 6.90878, -9.8617, 4.30713 },
429 { -0.000603162, 0.0796437, -0.646415, 7.40142, -10.4691, 4.63569 },
430 { -0.000975556, 0.116029, -0.977511, 7.81595, -10.8033, 4.84644 },
431 { -0.00104516, 0.121701, -1.13216, 8.16602, -11.4698, 5.30535 },
432 { -0.000692655, 0.0743631, -0.839957, 7.01192, -10.029, 4.76265 },
433 { -0.000873929, 0.0974708, -1.08584, 7.59646, -11.055, 5.43051 },
434 { -0.000278001, 0.0384464, -0.475365, 5.31638, -8.13554, 4.22311 },
435 { -0.000373472, 0.0491568, -0.658973, 5.52961, -8.70434, 4.73939 },
436 { -0.000784299, 0.0923149, -1.20043, 7.06114, -10.5462, 5.52973 },
437 { -0.000272599, 0.0343134, -0.602254, 5.44353, -9.1348, 5.18153 },
438 { -0.000153735, 0.0203647, -0.445935, 4.48833, -7.8483, 4.69983 },
439 { -0.00365289, 0.175263, -2.03252, 9.50892, -14.4687, 7.745 },
440 { -0.00219899, 0.110025, -1.4529, 7.59706, -12.3696, 6.98898 }
446 const double va =
Angle(telPos - meanPos, showerDir) /
degree;
447 const double*
p = p_VA[int(round(
max(0., min(29., floor(va)))))];
449 return p[0] + x*(p[1] + x*(p[2] + x*(p[3] + x*(p[4] + x*p[5]))));
TMatrixD jacobian(TVectorD(*f)(TVectorD, const modeltype), TVectorD x, TVectorD dx, const modeltype mtype)
const TabulatedFunction & fArcLengthFunction
constexpr T Sqr(const T &x)
double GoraCDF(const double rStar, const double age)
double Angle(const double theta1, const double phi1, const double theta2, const double phi2)
double DirCherLightFraction(const TelescopeDataBin &telData, const fdet::Telescope &detTel, const double xMax, const double cosTheta, const double zeta) const
double FluoLightFraction(const TelescopeDataBin &telData, const fdet::Telescope &detTel, const double xMax, const double cosTheta, const double zeta) const
const TabulatedFunction & fArcLengthFunction
Class for integration of functions with one independent parameter.
Class to hold collection (x,y) points and provide interpolation between them.
FdProfileReconstructorKG::OpticalHalo * fOpticalHalo
#define INFO(message)
Macro for logging informational messages.
~LateralLightCalculator()
Base class for exceptions trying to access non-existing components.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double operator()(const double zeta) const
double GetMeanDepth() const
LightSource
Possible light sources.
double GetHaloFraction(const double zeta, const double age, const double dist) const
double MoliereRadius(double temperature, double pressure, const double cosTheta)
The Moliere Radius (2 radiation length above obs-level, GAP-1998-002)
constexpr double fraction
ScattCherFunctor(const double distanceToTelescope, const double distanceAlongShower, const double showerAge, const double verticalDepth, const TabulatedFunction &arcLengthFunction)
const std::vector< ZetaPixel > & GetZetaPixels() const
double operator()(const double zeta) const
double GetLightFraction(fevt::FdConstants::LightSource source, const TelescopeDataBin &emissionBin, const TelescopeDataBin &detectionBin, const fdet::Telescope &telescope, const double xMax, const double cosTheta, const double zeta) const
void GetData(bool &b) const
Overloads of the GetData member template function.
double GetMaxZeta() const
AxialVector Normalized(const AxialVector &v)
Detector description interface for Telescope-related data.
double GoraPDF(const double rStar, const double age)
FluorescenceFunctor(const double showerAge, const double distance, const double moliereRadius, const TabulatedFunction &arcLengthFunction)
double ShowerAge(const double slantDepth, const double showerMax)
General definition of shower age.
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
bool HasEfficiency(fevt::FdConstants::LightSource source) const
utl::Point GetPosition() const
ECalculationMethod fMethod
double ScattCherLightFraction(const TelescopeDataBin &emissionBin, const TelescopeDataBin &detectionBin, const fdet::Telescope &detTel, const double xMax, const double zeta) const
double GetEfficiency(fevt::FdConstants::LightSource source) const
#define ERROR(message)
Macro for logging error messages.
calculation of FD optical halo light fraction
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
const utl::TabulatedFunction & GetArcLengthFunction() const
utl::Point fMeanDepthPoint
std::map< fevt::FdConstants::LightSource, bool > fLLDIsOn