3 #include <utl/RadioGeometryUtilities.h>
4 #include <utl/CoordinateSystemPtr.h>
5 #include <utl/AugerUnits.h>
6 #include <utl/Integrator.h>
7 #include <utl/AxialVector.h>
9 #include <fwk/LocalCoordinateSystem.h>
23 LDFFitFunction::GeomagneticEmissionFactor(
const double ceFraction,
24 const double sineAlpha,
25 const double cosAzimuth)
32 LDFFitFunction::GeomagneticEmissionFactor(
const double ceFraction,
33 const double sineAlpha,
40 const utl::Vector coreStation = stationPosition - showerCore;
41 const utl::Vector stationInShowerPlane = coreStation - (showerAxis * coreStation) * showerAxis;
42 const double cosAzimuth =
CosAngle(vxB, stationInShowerPlane);
44 return GeomagneticEmissionFactor(ceFraction, sineAlpha, cosAzimuth);
49 LDFFitFunction::ChargeExcessFractionParamICRC19(
const double axisDistance,
50 const double distanceToXmax,
51 const double densityXmax)
55 const double a = 0.37313183;
56 const double b = 1.31124484;
57 const double p0 = 0.1889835;
58 const double p1 = 6.71403002;
59 const double densityAvg = 0.4;
61 return a * (axisDistance / distanceToXmax) *
62 std::exp(b * axisDistance / 1000) * (std::exp(p1 * (densityXmax - densityAvg)) - p0);
67 LDFFitFunction::ChargeExcessFractionParamICRC21(
const double axisDistance,
68 const double distanceToXmax,
69 const double densityXmax)
72 const double a1 = -1.17523609e-06;
73 const double a2 = 0.348154734;
74 const double b = 1.6068519502678418;
75 const double p0 = 1.66965694e+01;
76 const double p1 = 3.31954904e+00;
77 const double p2 = -5.73577715e-03;
79 const double a = a1 * distanceToXmax + a2;
80 return a * (axisDistance / distanceToXmax) *
81 std::exp(b * axisDistance / 1000) * (p0 *
std::pow(densityXmax, p1) + p2);
86 LDFFitFunction::GetChargeExcessFraction(
const double axisDistance)
93 double ceFraction = ChargeExcessFractionParamICRC21(axisDistance, fDistanceToXmax, fDensityAtXmax);
111 LDFFitFunction::FGeomagneticParam(
const double xvBvvB,
const double yvBvvB,
const double efvxB,
const double cEarlyLate)
117 const double offAxisDistance =
std::sqrt(
Sqr(xvBvvB) +
Sqr(yvBvvB)) / cEarlyLate;
119 const double polarAngle = atan2(yvBvvB, xvBvvB);
122 const double ceFraction = GetChargeExcessFraction(offAxisDistance);
125 const double cGeo = GeomagneticEmissionFactor(ceFraction, fShowerData.fSineAlpha, cos(polarAngle));
128 const double efGeoMeas = efvxB * cGeo *
Sqr(cEarlyLate);
135 LDFFitFunction::FVxBPrediction(
const double xvBvvB,
const double yvBvvB,
const double cEarlyLate)
141 const double offAxisDistance =
std::sqrt(
Sqr(xvBvvB) +
Sqr(yvBvvB)) / cEarlyLate;
143 const double polarAngle = std::atan2(yvBvvB, xvBvvB);
146 const double ceFraction = GetChargeExcessFraction(offAxisDistance);
150 const double efGeoModel = FEgeo(offAxisDistance);
153 const double cGeo = GeomagneticEmissionFactor(ceFraction, fShowerData.fSineAlpha, std::cos(polarAngle));
156 const double efvxBPredict = efGeoModel / (cGeo *
Sqr(cEarlyLate));
163 LDFFitFunction::FGeomagneticPos(
const double xvBvvB,
const double yvBvvB,
const double cEarlyLate,
const StationFitData& station)
167 const double polarAngle = std::atan2(yvBvvB, xvBvvB);
170 const double efGeoPos =
174 if (
std::abs(std::sin(polarAngle)) < 0.1)
184 LDFFitFunction::FGeomagneticPosErr(
const double xvBvvB,
const double yvBvvB,
const double efGeoPos,
const StationFitData station)
188 const double polarAngle = std::atan2(yvBvvB, xvBvvB);
199 LDFFitFunction::GetFittedRadioCoreTransformation()
203 const utl::Point radioCore = fTransformationRefCore.GetVectorFromShowerPlaneVxB(fCoreX, fCoreY);
205 fShowerData.fMagneticField);
210 LDFFitFunction::operator()(
const std::vector<double>& pars)
214 UpdateParameterParam(pars);
220 for (
const auto&
s : fStationData) {
227 const double cEarlyLate =
229 s.fCEarlyLate = cEarlyLate;
231 const double offAxisDistance =
std::sqrt(
Sqr(xvxB) +
Sqr(yvxB)) / cEarlyLate;
233 if (fFitConfig.fUseParam) {
234 const double efvxBPredict = FVxBPrediction(xvxB, yvxB, cEarlyLate);
235 const double efGeoParam = FGeomagneticParam(xvxB, yvxB,
s.fEnergyFluenceVxB, cEarlyLate);
236 const double ceFraction = GetChargeExcessFraction(offAxisDistance);
238 s.fEnergyFluenceVxBPredict = efvxBPredict;
239 s.fCeFraction = ceFraction;
240 s.fEnergyFluenceGeomagnetic = efGeoParam;
244 s.fEnergyFluenceGeomagneticErr = FGeomagneticParam(xvxB, yvxB,
s.fEnergyFluenceVxBErr, cEarlyLate);
250 loss += GetLoss(efvxBPredict,
s.fEnergyFluenceVxB,
s.fEnergyFluenceVxBErr);
252 const double efGeoPos = FGeomagneticPos(xvxB, yvxB, cEarlyLate,
s);
253 const double efGeoPosErr = FGeomagneticPosErr(xvxB, yvxB, efGeoPos,
s);
254 const double offAxisDistance =
std::sqrt(
Sqr(xvxB) +
Sqr(yvxB)) / cEarlyLate;
255 const double efGeoModel = FEgeo(offAxisDistance);
257 s.fEnergyFluenceGeomagnetic = efGeoPos;
258 s.fEnergyFluenceGeomagneticErr = efGeoPosErr;
265 loss += GetLoss(efGeoModel, efGeoPos, efGeoPosErr);
275 LDFFitFunction::GetPrediction(
const std::vector<double>& pars)
277 this->operator()(pars);
282 LDFFitFunction::GetLossLog(
const double model,
284 const double uncertainty)
287 return Sqr((std::log(model) - std::log(data)) / (uncertainty / data));
292 LDFFitFunction::GetLoss(
const double model,
294 const double uncertainty)
297 return Sqr((model - data) / uncertainty);
302 LDFFitFunction::GetChi2(
const std::vector<double>& pars)
304 return this->operator()(pars);
309 LDFFitFunction::GetNDF()
314 for (
const auto&
s : fStationData) {
320 return ndf - GetNFreeParameters();
341 LDFFitFunctionPoly3::GetNormalization()
347 const double r0 = fr0;
349 auto LDFnorm = [&B, &C, &D, &r0](
const double r)
350 {
return kTwoPi * r * FABCD(r, r0, 1, B, C, D); };
352 return MakeIntegrator(LDFnorm).GetIntegral(0, fRnorm) * fEgeoCorr;
357 LDFFitFunctionPoly3::FEgeo(
const double r)
360 return fEgeo * FABCD(r, fr0, 1, fB, fC, fD) / fNorm;
365 LDFFitFunctionPoly3::FABCD(
const double r,
const double r0,
const double a,
366 const double b,
const double c,
const double d)
368 const double x = r / r0;
369 return a * std::exp(x * (-b + x * (std::exp(c) - x * std::exp(d))));
375 LDFFitFunctionGaussSigmoid::CalculateR0()
378 const double refracIndexAtXmax = fShowerData.fRefracFromHeight.Y(fHeight);
379 const double cherenkovAngle = std::acos(1 / refracIndexAtXmax);
380 return std::tan(cherenkovAngle) * fDistanceToXmax;
385 LDFFitFunctionGaussSigmoid::GetNormalization()
388 const double r0 = fR0;
389 const double sig = fSig;
391 const double r02 = fR02;
392 const double arel = fArel;
393 const double slope = fSlope;
395 if (fFitConfig.fUseSoftExponent) {
396 auto LDFnorm = [&r0, &sig, &
p, &arel, &slope, &r02](
const double r)
397 {
return kTwoPi * r * FGaussSigmoidSoft(r, r0, sig, p, arel, slope, r02); };
399 return MakeIntegrator(LDFnorm).GetIntegral(0, fRnorm) * fEgeoCorr;
401 auto LDFnorm = [&r0, &sig, &
p, &arel, &slope, &r02](
const double r)
402 {
return kTwoPi * r * FGaussSigmoidHard(r, r0, sig, p, arel, slope, r02); };
404 return MakeIntegrator(LDFnorm).GetIntegral(0, fRnorm) * fEgeoCorr;
410 LDFFitFunctionGaussSigmoid::FEgeo(
const double r)
413 return fEgeo * FGaussSigmoid(r, fR0, fSig, fP, fArel, fSlope, fR02) / fNorm;
418 LDFFitFunctionGaussSigmoid::FGaussSigmoidSoft(
419 const double r,
const double r0,
const double sig,
double p,
420 const double arel,
const double slope,
const double r02)
422 const double pEff = (r > r0) ? 2 *
std::pow(r0 / r, p / 1000) : 2;
423 return std::exp(-
std::pow((r - r0) / sig, pEff)) + arel / (1 + std::exp(slope * (r / r0 - r02)));
427 LDFFitFunctionGaussSigmoid::FGaussSigmoidHard(
428 const double r,
const double r0,
const double sig,
double p,
429 const double arel,
const double slope,
const double r02)
431 const double pEff = (r > r0) ? p : 2;
432 return std::exp(-
std::pow((r - r0) / sig, pEff)) + arel / (1 + std::exp(slope * (r / r0 - r02)));
AxialVector Cross(const Vector &l, const Vector &r)
constexpr T Sqr(const T &x)
static double GetEarlyLateCorrectionFactor(const utl::Point &showerCore, const utl::Point &stationPosition, const utl::Point &showerMax, const utl::Vector &showerAxis)
double pow(const double x, const unsigned int i)
double fEnergyFluenceVxVxBErr
double abs(const SVector< n, T > &v)
double fEnergyFluenceVxVxB
void GetVectorInShowerPlaneVxB(double &x, double &y, double &z, const utl::Point &point) const
in case of positions, the positions has to be relative to the core positions!!!
double fEnergyFluenceVxBErr
double CosAngle(const Vector &l, const Vector &r)
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
Integrator< Functor > MakeIntegrator(Functor &f)
convenience factory