3 #include <utl/ErrorLogger.h>
5 #include <fwk/CentralConfig.h>
7 #include <utl/Vector.h>
9 #include <utl/BasicVector.h>
10 #include <utl/GeometryUtilities.h>
11 #include <utl/RadioGeometryUtilities.h>
12 #include <utl/CoordinateSystemPtr.h>
13 #include <utl/StringCompare.h>
15 #include <evt/Event.h>
16 #include <evt/ShowerRecData.h>
17 #include <evt/ShowerSRecData.h>
18 #include <evt/ShowerRRecData.h>
19 #include <evt/ShowerFRecData.h>
20 #include <evt/ShowerSimData.h>
21 #include <evt/RadioSimulation.h>
23 #include <revt/REvent.h>
24 #include <revt/Station.h>
25 #include <revt/Header.h>
26 #include <revt/StationRecData.h>
27 #include <revt/StationRRecDataQuantities.h>
29 #include <det/Detector.h>
32 #include "TGraph2DErrors.h"
36 #include "TFitResultPtr.h"
45 #include "Minuit2/Minuit2Minimizer.h"
46 #include "Minuit2/MnUserParameters.h"
47 #include "Minuit2/MnMigrad.h"
48 #include "Minuit2/MnContours.h"
49 #include "Minuit2/FunctionMinimum.h"
50 #include "Minuit2/MinimumParameters.h"
51 #include "Minuit2/MnPrint.h"
52 #include "Minuit2/MnPlot.h"
53 #include "Minuit2/MnUserCovariance.h"
54 #include <boost/accumulators/statistics/variance.hpp>
65 namespace RdGeoCeLDFFitter {
71 const double lgE = log10(e /
utl::eV) - 19;
72 const double lnA = log(a);
74 const double p0 = 775.589 - 7.047 * lnA - 2.427 * lnA *
lnA;
75 const double p1 = 57.589 - 0.743 * lnA + 0.214 * lnA *
lnA;
76 const double p2 = -0.820 - 0.169 * lnA - 0.027 * lnA *
lnA;
78 const double xmax = p0 + p1 * lgE + p2 * lgE * lgE;
86 const Branch topBranch = CentralConfig::GetInstance()->
GetTopBranch(
"RdGeoCeLDFFitter");
88 topBranch.
GetChild(
"minNuberOfStationsForCoreFit").
GetData(fMinNuberOfStationsForCoreFit);
101 WARNING(
"No radio event found!");
114 ShowerRRecData& showerrrec =
event.GetRecShower().GetRRecShower();
116 const rdet::RDetector& rDetector = det::Detector::GetInstance().GetRDetector();
122 det::Detector::GetInstance().GetReferenceCoordinateSystem();
127 const double zenith = showerAxis.
GetTheta(localCS);
128 const double azimuth = showerAxis.
GetPhi(localCS);
132 WARNING(
"Number of signalstations less than 3 -> doing nothing");
140 MagneticField /= MagneticField.
GetMag();
143 info <<
"zenith, azimuth (rad) = " << zenith /
utl::rad <<
", " << azimuth /
utl::rad <<
"\n"
144 "zenith, azimuth (deg) = " << zenith /
utl::deg <<
", " << azimuth /
utl::deg;
147 unsigned int numberOfSignalStations = 0;
148 unsigned int numberOfSilentStations = 0;
150 for (
const auto& station : rEvent.CandidateStationsRange()) {
151 if (station.IsSaturated())
154 if (!station.HasSignal())
155 ++numberOfSilentStations;
157 ++numberOfSignalStations;
161 if (numberOfSignalStations < 3) {
162 WARNING(
"Number of signal stations after rejection of saturated stations < 3 -> doing nothing!");
166 const bool fitCore = !fFixCore && int(numberOfSignalStations) >= fMinNuberOfStationsForCoreFit;
168 info <<
"Core fit will ";
171 info <<
"be performed. The number of signal stations is " << numberOfSignalStations;
181 const double sineAlpha =
182 RadioGeometryUtilities::GetLorentzVector(
189 eventFitData.
zenith = zenith;
191 info <<
"setting zenith = " << zenith /
utl::deg <<
" sinalpha = " << sineAlpha;
194 std::vector<StationFitData> vStationFitData;
195 std::vector<StationFitData> vStationFitDataSignalStations;
198 for (
auto& station : rEvent.StationsRange()) {
209 if (station.IsSaturated())
212 if (!fUserSubThresholdStations && !station.HasSignal())
215 if (station.IsRejected())
219 tmpStationFitData.
f = sRec.
GetParameter(revt::eSignalEnergyFluenceMag);
225 tmpStationFitData.
x = X_VxB;
226 tmpStationFitData.
y = Y_VxB;
227 tmpStationFitData.
distance =
sqrt(X_VxB * X_VxB + Y_VxB * Y_VxB);
228 tmpStationFitData.
hasSignal = station.HasSignal();
234 info <<
"Station position (reference CS): " << sPos.
GetX(referenceCS) /
utl::m <<
", "
236 <<
"Station Position (localCS): " << sPos.
GetX(localCS) /
utl::m <<
", "
238 <<
"core position (reference CS): " << core.
GetX(referenceCS) <<
", "
239 << core.
GetY(referenceCS) <<
", " << core.
GetZ(referenceCS) <<
"\n"
240 <<
"showerAxis (local cs): " << showerAxis.
GetX(localCS) <<
", "
241 << showerAxis.
GetY(localCS) <<
", " << showerAxis.
GetZ(localCS) <<
"\n"
242 <<
"magnetic field (localCS): " << MagneticField.
GetX(localCS) <<
", "
243 << MagneticField.
GetY(localCS) <<
", " << MagneticField.
GetZ(localCS) <<
"\n"
244 <<
"magnetic field (referenceCS): " << MagneticField.
GetX(referenceCS) <<
", "
245 << MagneticField.
GetY(referenceCS) <<
", " << MagneticField.
GetZ(referenceCS);
266 if (station.HasSignal()) {
268 info <<
"position in vxB, vxvxB, z: " << X_VxB <<
", " << Y_VxB <<
", " << Z_VxB <<
" "
269 "f " << tmpStationFitData.
f <<
" +- "
270 << sRec.
GetParameter(revt::eNoiseEnergyFluenceMag) <<
" +- "
272 "fvB " << tmpStationFitData.
f_vB <<
" +- "
273 << sRec.
GetParameter(revt::eNoiseEnergyFluenceVxB) <<
" +- "
275 "fvvB " << tmpStationFitData.
f_vvB <<
" +- " << tmpStationFitData.
ferror_vvB;
277 vStationFitDataSignalStations.push_back(tmpStationFitData);
280 vStationFitData.push_back(tmpStationFitData);
291 double Erad_start = 10;
292 double Erad_start_error = 10;
297 CRenergy =
event.GetRecShower().GetSRecShower().GetEnergy();
298 const double CRenergyError =
event.GetRecShower().GetSRecShower().GetEnergyError() + 0.18 * CRenergy;
304 const double DXmaxEstimate =
getAtmosphere(1564) / cos(zenith) - XmaxEstimate;
307 info <<
"start values: Erad = " << Erad_start /
utl::MeV <<
" +- " << Erad_start_error /
utl::MeV
308 <<
" MeV, Dxmax = " << DXmaxEstimate;
311 ROOT::Minuit2::MnUserParameters upar;
313 upar.Add(
"dxmax", DXmaxEstimate, 50);
314 upar.Add(
"coreX", 0., 100);
315 upar.Add(
"coreY", 0., 100);
321 if (fInfoLevel < eInfoDebug){
326 gErrorIgnoreLevel = 1001;
329 ROOT::Minuit2::MnMigrad migrad_pre(fitFunction, upar);
331 ROOT::Minuit2::FunctionMinimum minimum_pre = migrad_pre();
333 info <<
"prefit: " << minimum_pre;
335 migrad_pre.Fix(
"Erad");
338 migrad_pre.Release(
"coreX");
339 migrad_pre.Release(
"coreY");
341 minimum_pre = migrad_pre();
343 info <<
"prefit: " << minimum_pre;
347 migrad_pre.Release(
"Erad");
348 migrad_pre.Release(
"dxmax");
349 migrad_pre.Fix(
"coreX");
350 migrad_pre.Fix(
"coreY");
351 minimum_pre = migrad_pre();
353 info <<
"Releasing Erad + dxmax, fixing corex, corey. prefit: " << minimum_pre;
357 migrad_pre.Release(
"coreX");
358 migrad_pre.Release(
"coreY");
362 ROOT::Minuit2::FunctionMinimum minimum = migrad_pre();
364 info <<
"minimum: " << minimum;
368 if (!minimum.IsValid()) {
370 info <<
"Geo ce LDF fit not converged. No result will be saved, returning eSuccess.";
375 ROOT::Minuit2::MnUserParameterState minUstate_tmp = minimum.UserState();
376 ROOT::Minuit2::MnUserCovariance cov = minUstate_tmp.Covariance();
382 const int number_of_trials = 100;
383 std::vector<double> radiation_energies;
384 std::vector<double> dxmaxs;
386 Double_t mu[2] = { 0, 0 };
387 Double_t sigma[2] = { 0, 0 };
388 sigma[0] = coreError.
GetX(localCS);
389 sigma[1] = coreError.
GetY(localCS);
391 CorRand rnd(mu, sigma, rho, fRandomSeed);
392 for (
int i = 0; i < number_of_trials; ++i) {
400 std::vector<StationFitData> tmpvStationFitData;
401 for (
const auto& station : rEvent.CandidateStationsRange()) {
403 const auto& sRec = station.GetRecData();
413 if (station.IsSaturated())
416 if (!fUserSubThresholdStations && !station.HasSignal())
420 tmpStationFitData.
f = sRec.GetParameter(revt::eSignalEnergyFluenceMag);
421 tmpStationFitData.
ferror = sRec.GetParameterError(revt::eSignalEnergyFluenceMag);
422 tmpStationFitData.
f_vB = sRec.GetParameter(revt::eSignalEnergyFluenceVxB);
423 tmpStationFitData.
ferror_vB = sRec.GetParameterError(revt::eSignalEnergyFluenceVxB);
424 tmpStationFitData.
f_vvB = sRec.GetParameter(revt::eSignalEnergyFluenceVxVxB);
425 tmpStationFitData.
ferror_vvB = sRec.GetParameterError(revt::eSignalEnergyFluenceVxVxB);
426 tmpStationFitData.
x = X_VxB;
427 tmpStationFitData.
y = Y_VxB;
428 tmpStationFitData.
distance =
sqrt(X_VxB * X_VxB + Y_VxB * Y_VxB);
429 tmpStationFitData.
hasSignal = station.HasSignal();
431 tmpvStationFitData.push_back(tmpStationFitData);
437 ROOT::Minuit2::MnUserParameters tmpupar;
438 tmpupar.Add(
"Erad", minUstate_tmp.Value(
"Erad"), 0.1 * minUstate_tmp.Value(
"Erad"));
439 tmpupar.Add(
"dxmax", minUstate_tmp.Value(
"dxmax"), minUstate_tmp.Value(
"dxmax") * 0.1);
440 tmpupar.Add(
"coreX", 0., 100);
441 tmpupar.Add(
"coreY", 0., 100);
443 tmpupar.Fix(
"coreX");
444 tmpupar.Fix(
"coreY");
446 ROOT::Minuit2::MnMigrad tmpmigrad(tmpfitFunction, tmpupar);
447 ROOT::Minuit2::FunctionMinimum tmpminimum = tmpmigrad();
448 ROOT::Minuit2::MnUserParameterState tmpminUstate = tmpminimum.UserState();
449 radiation_energies.push_back(tmpminUstate.Value(
"Erad"));
450 dxmaxs.push_back(tmpminUstate.Value(
"dxmax"));
453 for (
unsigned int i = 0; i < radiation_energies.size(); ++i) {
454 eradRMS +=
Sqr(radiation_energies[i] - minUstate_tmp.Value(
"Erad"));
455 dxmaxRMS +=
Sqr(dxmaxs[i] - minUstate_tmp.Value(
"dxmax"));
458 eradRMS /= radiation_energies.size();
459 dxmaxRMS /= dxmaxs.size();
460 eradRMS =
sqrt(eradRMS);
461 dxmaxRMS =
sqrt(dxmaxRMS);
464 const double radiationEnergy = minUstate_tmp.Value(
"Erad") *
utl::MeV;
465 showerrrec.
SetParameter(revt::eGeoCeLDFErad, radiationEnergy);
466 showerrrec.
SetParameter(revt::eGeoCeLDFDxmax, minUstate_tmp.Value(
"dxmax"));
468 if (fInfoLevel >= eInfoIntermediate && event.
HasSimShower() &&
event.GetSimShower().HasRadioSimulation()) {
469 const double radiationEnergySim =
event.GetSimShower().GetRadioSimulation().GetRadiationEnergy();
470 if (radiationEnergySim) {
472 info <<
" (" << (radiationEnergy - radiationEnergySim) / radiationEnergySim * 100
473 <<
"% wrt true/simulated radiation energy";
481 double x = minUstate_tmp.Value(
"coreX");
482 double y = minUstate_tmp.Value(
"coreY");
498 for (
auto& station : rEvent.StationsRange()) {
508 sRec.
SetParameter(revt::eLDFFitStationPositionVxB, X_VxB);
509 sRec.
SetParameter(revt::eLDFFitStationPositionVxVxB, Y_VxB);
510 sRec.
SetParameter(revt::eLDFFitStationPositionV, Z_VxB);
516 std::vector<double> pars = {
517 minUstate_tmp.Value(
"Erad"), minUstate_tmp.Value(
"dxmax"),
518 minUstate_tmp.Value(
"coreX"), minUstate_tmp.Value(
"coreY")
522 int ndf = numberOfSignalStations - 4;
524 ndf = numberOfSignalStations - 2;
529 info <<
"chi2/ndf = " << chi2 <<
"/" << ndf;
533 if (isnan(cov(0, 0))) {
534 WARNING(
"Cov matrix contains nan. Can not estimate uncertainties");
543 const double dxmaxError =
sqrt(
Sqr(cov(1, 1)) +
Sqr(dxmaxRMS));
561 RdGeoCeLDFFitter::Finish()
Branch GetTopBranch() const
Class to access station level reconstructed data.
void SetParameter(Parameter i, double value, bool lock=true)
utl::Point GetReferenceCorePosition(const Event &event) const
Returning the reference core position depending on the corresponding flag.
constexpr T Sqr(const T &x)
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
double GetChi2FullEnergyFluence(const std::vector< double > &pars) const
bool HasRecShower() const
Interface class to access to the Radio part of an event.
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
ShowerRecData & GetRecShower()
Interface class to access to the RD Reconstruction of a Shower.
bool HasSimShower() const
double GetParameterError(const Parameter i) const
#define INFO(message)
Macro for logging informational messages.
void Init()
Initialise the registry.
double GetXmaxGumble(const double e, const double a)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double pow(const double x, const unsigned int i)
utl::Vector GetReferenceCoreError(const Event &event) const
Returning the reference core position error depending on the corresponding flag.
double GetReferenceCoreErrorCorrelationXY(const Event &event) const
Returning the reference core position error correlation xy depending on the corresponding flag...
Detector description interface for RDetector-related data.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define INFOIntermediate(y)
utl::Point GetVectorFromShowerPlaneVxB(const double x, const double y, const double z, const bool verticalZero) const
in case of positions, the positions has to be relative to the core positions!!!
Class representing a document branch.
double GetX(const CoordinateSystemPtr &coordinateSystem) const
bool HasRRecShower() const
#define WARNING(message)
Macro for logging warning messages.
void GetData(bool &b) const
Overloads of the GetData member template function.
int GetNumberOfSignalStations() const
Get number of signal stations in the event.
double GetParameter(const Parameter i) const
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 GetY(const CoordinateSystemPtr &coordinateSystem) const
ResultFlag
Flag returned by module methods to the RunController.
double lnA(const double Rmu, const double Xmax, const double lgE, const bool realEvent)
void SetParameter(Parameter i, double value, bool lock=true)
utl::Vector GetReferenceAxis(const Event &event) const
Returning the referencedirection depending on the corresponding flag.
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
double getAtmosphere(double h)
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
utl::Vector GetMagneticFieldVector() const
returns the magnetic field vector from the components stored in the parameter storage ...
const Station & GetStation(const int stationId) const
Get station by Station Id.
bool HasSRecShower() const
void GetRnd(double *const a, double *const b)
void SetParameterCovariance(Parameter i1, Parameter i2, double value, bool lock=true)