RdHASLDFFitter.cc
Go to the documentation of this file.
1 #include "RdHASLDFFitter.h"
2 #include "LDFFitFunction.h"
3 
4 // framework
5 #include <fwk/CentralConfig.h>
6 
7 // utilities
8 #include <utl/ErrorLogger.h>
9 #include <utl/Vector.h>
10 #include <utl/Point.h>
11 #include <utl/RadioGeometryUtilities.h>
12 #include <utl/CoordinateSystemPtr.h>
13 #include <utl/Minou.h>
14 
15 // event
16 #include <evt/Event.h>
17 #include <evt/ShowerRecData.h>
18 #include <evt/ShowerSRecData.h>
19 #include <evt/ShowerRRecData.h>
20 #include <evt/ShowerSimData.h>
21 
22 // revent
23 #include <revt/REvent.h>
24 #include <revt/Header.h>
25 #include <revt/Station.h>
26 #include <revt/StationRecData.h>
27 #include <revt/StationRRecDataQuantities.h>
28 
29 // det / rdet
30 #include <det/Detector.h>
31 #include <rdet/RDetector.h>
32 
33 // atmosphere
34 #include <atm/AerosolDB.h>
35 #include <atm/AerosolZone.h>
36 #include <atm/ProfileResult.h>
37 #include <atm/MonthlyAvgDBProfileModel.h>
38 #include <atm/InclinedAtmosphericProfile.h>
39 #include <atm/SimShowerProfileModel.h>
40 
41 #include <string>
42 #include <iostream>
43 #include <vector>
44 #include <sstream>
45 
46 
47 using namespace evt;
48 using namespace fwk;
49 using namespace std;
50 using namespace utl;
51 
52 
53 namespace RdHASLDFFitter {
54 
55  void
56  RdHASLDFFitter::RadiationDensityCorrection(
57  const double densityMax, const double densityMaxErr,
58  double& radiationDensityCorrection, double& radiationDensityCorrectionErr) const
59  {
60  /* Takes density at shower maximum in kg / m3
61  Returns correction factor for E_geo_rad / sin(alpha) ** 2*/
62 
63  const double densityAvg = fAvgDensity; // * kg/m3;
64  const double p0 = fp0;
65  const double p1 = fp1; // / (kg/m3);
66 
67  radiationDensityCorrection = pow(1 - p0 + p0 * exp(p1 * (densityMax - densityAvg)), -2);
68 
69  radiationDensityCorrectionErr =
70  abs(-2 * p0 * p1 * exp(p1 * (densityMax - densityAvg)) * densityMaxErr) /
71  pow(1 - p0 + p0 * exp(p1 * (densityMax - densityAvg)), 3);
72  }
73 
74 
75  double
77  {
78  // assumes that magnetic field is known perfectly. uncertainty of sin2(alpha). gaussian propagation without correlation
79  const ShowerRRecData& showerrrec = event.GetRecShower().GetRRecShower();
80  const utl::Point& refShowerCore = showerrrec.GetReferenceCorePosition(event);
81  const CoordinateSystemPtr refCoreCS = LocalCoordinateSystem::Create(refShowerCore);
82 
83  double zenith = 0;
84  double azimuth = 0;
85  double zenithErr = 0;
86  double azimuthErr = 0;
87 
89  const evt::ShowerSRecData& sShowerRec = event.GetRecShower().GetSRecShower();
90  const Vector sShowerAxis = sShowerRec.GetAxis();
91 
92  azimuthErr = sShowerRec.GetPhiError();
93  zenithErr = sShowerRec.GetThetaError();
94  zenith = sShowerAxis.GetTheta(refCoreCS);
95  azimuth = sShowerAxis.GetPhi(refCoreCS);
97  const Vector rShowerAxis = showerrrec.GetAxis();
98 
99  azimuthErr = showerrrec.GetAzimuthError();
100  zenithErr = showerrrec.GetZenithError();
101  zenith = rShowerAxis.GetTheta(refCoreCS);
102  azimuth = rShowerAxis.GetPhi(refCoreCS);
104  return 0;
105  } else {
106  ERROR("Selected ReferenceAxis (in RdEventInitalizer) is not supported! Return sineAlphaSquareErr = 0.");
107  return 0;
108  }
109 
110  const Vector magneticField = showerrrec.GetMagneticFieldVector();
111  const Vector magneticFieldNormalized = magneticField / magneticField.GetMag();
112  const double mx = magneticFieldNormalized.GetX(refCoreCS);
113  const double my = magneticFieldNormalized.GetY(refCoreCS);
114  const double mz = magneticFieldNormalized.GetZ(refCoreCS);
115 
116  // Derivertives are based on sin2alpha = (m x a) (m x a), with m=mag. vector and a=shower axis
117  const double dsineAlphaSquareDzenith =
118  2 * ((mz * cos(zenith) * cos(azimuth) + mx * sin(zenith)) * (-mx * cos(zenith) + mz * cos(azimuth) * sin(zenith)) +
119  cos(zenith) * sin(zenith) * Sqr(my * cos(azimuth) - mx * sin(azimuth)) -
120  (my * sin(zenith) + mz * cos(zenith) * sin(azimuth)) * (my * cos(zenith) - mz * sin(zenith) * sin(azimuth)));
121 
122  const double dsineAlphaSquareDazimuth =
123  2 * sin(zenith) * (-my * cos(azimuth) + mx * sin(azimuth)) *
124  (mz * cos(zenith) + sin(zenith) * (mx * cos(azimuth) + my * sin(azimuth)));
125 
126  const double sineAlphaSquareErr =
127  sqrt(Sqr(dsineAlphaSquareDzenith * zenithErr) + Sqr(dsineAlphaSquareDazimuth * azimuthErr));
128  return sineAlphaSquareErr;
129  }
130 
131 
132  void
133  RdHASLDFFitter::ElectromagneticEnergy(
134  const double sRad, const double sRadErr,
135  double& electromagneticEnergyRec, double& electromagneticEnergyRecErr, const double zenith) const
136  {
137  /* Takes corrected geomagnetic radiation energy in eV
138  Returns electromagnetic shower energy in eV */
139 
140  double s19 = fS19;
141  const double gamma = fGamma;
142 
143  // See explaination for this correction in XML
144  s19 = s19 / (1 + fSTEPFCCorrectionToSimulatedRadioEnergyScale);
145 
146  electromagneticEnergyRec = pow(sRad / s19, 1 / gamma) * 1e19 * eV;
147  electromagneticEnergyRecErr = pow(sRad / s19, 1 / gamma - 1) * 1e19 * eV / (s19 * gamma) * sRadErr;
148 
149  if (fApplyParametricCorrectionToElectromagneticEnergyUncertainty) {
150  // Parameterization explained in PhD Thesis Felix Schlüter Chap. 8.4.2.1.
151  // Determined with an amplitude smearing of 5% (also see XML)
152  const double correctionFactorEem =
153  1.98593279e+03 * pow(Sqr(sin(zenith)) - Sqr(sin(65 * utl::deg)), 4) + 1.44615405e+00;
154  electromagneticEnergyRecErr *= correctionFactorEem;
155  }
156 
157  }
158 
159 
160  bool
161  RdHASLDFFitter::GetXmaxEstimator(const evt::Event& event, double& xmax)
162  const
163  {
164  if (fXmaxType == "MC") {
165  if (!event.HasSimShower()) {
166  ERROR("Event has no sim shower but fXmaxType == simulation was choose.");
167  return false;
168  }
169  const evt::ShowerSimData& simShower = event.GetSimShower();
170  const auto& gh = simShower.GetGHParameters();
171  xmax = gh.GetXMax();
172  } else if (fXmaxType == "Param") {
173  if (!event.GetRecShower().HasSRecShower()) {
174  ERROR("Event has no SD rec shower. Can not estimate Xmax with utl::XmaxParam::Mean.");
175  return false;
176  }
177  const evt::ShowerSRecData& sdShower = event.GetRecShower().GetSRecShower();
178  const double crEnergy = sdShower.GetEnergy();
179  xmax = 0.5 * (XmaxParam::Mean(crEnergy, 1, fHadronicInteractionModel)
180  + XmaxParam::Mean(crEnergy, 56, fHadronicInteractionModel));
181  } else if (fXmaxType == "Average") {
182  xmax = 750 * g / cm2; // ~ 10 EeV, 50% proton, 50% iron composition
183  } else {
184  ERROR("Wrong fXmaxType choosen!");
185  return false;
186  }
187 
188  return true;
189  }
190 
191 
194  {
195  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdHASLDFFitter");
196 
197  // Read in the configurations of the xml file
198  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
199 
200  topBranch.GetChild("MinimumNumberOfStations").GetData(fMinimumNumberOfStations);
201  topBranch.GetChild("FitDistanceToXmax").GetData(fFitDistanceToXmax);
202  topBranch.GetChild("FitCore").GetData(fFitCore);
203  topBranch.GetChild("AddLowestSignalAsError").GetData(fAddLowestSignalAsError);
204  topBranch.GetChild("AddRelativeMaxSignalError").GetData(fAddRelativeMaxSignalError);
205 
206  topBranch.GetChild("XmaxEstimator").GetData(fXmaxType);
207 
208  std::string hadronicInteractionModule =
209  topBranch.GetChild("HadronicInteractionModel").Get<string>();
210  if (hadronicInteractionModule == "Sibyll2.3d")
211  fHadronicInteractionModel = utl::HadronicInteractionModel::eSibyll23d;
212  else if (hadronicInteractionModule == "EPOS-LHC")
213  fHadronicInteractionModel = utl::HadronicInteractionModel::eEPOSLHC;
214  else if (hadronicInteractionModule == "QGSJETII-04")
215  fHadronicInteractionModel = utl::HadronicInteractionModel::eQGSJETII04;
216  else {
218  "You used an invalid HadronicInteractionModel in the XML config.");
219  return eFailure;
220  }
221 
222  topBranch.GetChild("FitDirection").GetData(fFitDirection);
223  topBranch.GetChild("UseSaturatedStations").GetData(fUseSaturatedStations);
224  topBranch.GetChild("UseParametrizationToDisentanglePolarisation").GetData(
225  fUseParametrizationToDisentanglePolarisation);
226  topBranch.GetChild("UseSoftExponent").GetData(fUseSoftExponent);
227 
228  topBranch.GetChild("S19").GetData(fS19);
229  topBranch.GetChild("Gamma").GetData(fGamma);
230  topBranch.GetChild("AvgDensity").GetData(fAvgDensity);
231  topBranch.GetChild("p0").GetData(fp0);
232  topBranch.GetChild("p1").GetData(fp1);
233  topBranch.GetChild("STEPFCCorrectionToSimulatedRadioEnergyScale")
234  .GetData(fSTEPFCCorrectionToSimulatedRadioEnergyScale);
235 
236  topBranch.GetChild("ApplyParametricCorrectionToElectromagneticEnergyUncertainty")
237  .GetData(fApplyParametricCorrectionToElectromagneticEnergyUncertainty);
238 
239  ostringstream info;
240  info << "\n"
241  "\tMinimum number of required stations: " << fMinimumNumberOfStations << "\n"
242  "\tUse saturated stations: " << fUseSaturatedStations << "\n"
243  "\tFit distance to xmax / core: (" << fFitDistanceToXmax << "/" << fFitCore << ")\n"
244  "\tXmax estimator used to determine inital fit values: " << fXmaxType << "\n";
245  if (fXmaxType == "Param")
246  info << "\tUsed high-energy hadronic interaction model : " << hadronicInteractionModule << "\n";
247  info << "\tDirection used in fit: " << fFitDirection << "\n"
248  "\tUse parametrization to determine geomagnetic energy fluence: "
249  << fUseParametrizationToDisentanglePolarisation << "\n"
250  "\tUse ";
251  if (fUseSoftExponent)
252  info << "\"soft\" (default) ";
253  else
254  info << "\"hard\" (not default) ";
255  info << "exponent in geomagnetic ldf" << "\n"
256  << "\tUse correction for uncertainty: " << fApplyParametricCorrectionToElectromagneticEnergyUncertainty << "\n"
257  << "\tApply STEPFC energy scale correction factor of: " << fSTEPFCCorrectionToSimulatedRadioEnergyScale << "\n";
258  INFOFinal(info);
259 
260  return eSuccess;
261  }
262 
263 
265  RdHASLDFFitter::Run(evt::Event& event)
266  {
267  if (!event.HasREvent()) {
268  WARNING("No radio event found!");
269  return eContinueLoop;
270  }
271  revt::REvent& rEvent = event.GetREvent();
272 
273  // initialize data structures
274  if (!event.HasRecShower())
275  event.MakeRecShower();
276 
277  if (!event.GetRecShower().HasRRecShower())
278  event.GetRecShower().MakeRRecShower();
279  ShowerRRecData& showerrrec = event.GetRecShower().GetRRecShower();
280 
281  // get reference coordinate system of detector (usually PampaAmarilla)
282  const CoordinateSystemPtr referenceCS =
283  det::Detector::GetInstance().GetReferenceCoordinateSystem();
284 
285  // takes the reference geometry set in event initializer
286  const utl::Point& refShowerCore = showerrrec.GetReferenceCorePosition(event);
287  utl::Vector refShowerAxis;
288 
289  if (fFitDirection == "Reference") {
290  refShowerAxis = showerrrec.GetReferenceAxis(event);
291  } else if (fFitDirection == "Rd") {
292  if (!showerrrec.HasAxis()) {
293  INFO("Rd axis requested for reconstruction. Not available. Skip event ...");
294  return eContinueLoop;
295  }
296  refShowerAxis = showerrrec.GetAxis();
297  }
298 
299  const CoordinateSystemPtr refCoreCS = LocalCoordinateSystem::Create(refShowerCore);
300  const double zenith = refShowerAxis.GetTheta(refCoreCS);
301  const double azimuth = refShowerAxis.GetPhi(refCoreCS);
302 
303  ostringstream info;
304  info << "Use geometry:\n"
305  "\tzenith = " << zenith / utl::deg << " deg, azimuth = " << azimuth / utl::deg << " deg\n"
306  "\t" << "core in ref cs (PA): (" << refShowerCore.GetX(referenceCS) / meter << ", "
307  << refShowerCore.GetY(referenceCS) / meter << ", "
308  << refShowerCore.GetZ(referenceCS) / meter << ')';
309  INFOIntermediate(info);
310 
311  const Vector magneticField = showerrrec.GetMagneticFieldVector();
312  utl::RadioGeometryUtilities transformation = RadioGeometryUtilities(refShowerAxis, refCoreCS, magneticField);
313  const double sineAlpha = RadioGeometryUtilities::GetLorentzVector(refShowerAxis, magneticField).GetMag();
314 
315  // get detector instances
316  const det::Detector& detector = det::Detector::GetInstance();
317  const rdet::RDetector& rDetector = detector.GetRDetector();
318 
319  vector<StationFitData> vStationFitData;
320  unsigned int numberOfSignalStations = 0;
321 
322  double addErrMin = 0;
323  if (fAddLowestSignalAsError) {
324  addErrMin = 1e25;
325  // iteration over stations
326  for (const auto& station : rEvent.SignalStationsRange()) {
327  const auto& sRec = station.GetRecData();
328 
329  // skip saturated stations if it is configured
330  if (!fUseSaturatedStations && station.IsSaturated())
331  continue;
332 
333  if (addErrMin > sRec.GetParameter(revt::eSignalEnergyFluenceVxB))
334  addErrMin = sRec.GetParameter(revt::eSignalEnergyFluenceVxB);
335  }
336  }
337 
338  double addErrMax = 0;
339  if (fAddRelativeMaxSignalError) {
340  if (!event.HasSimShower()) {
342  "fAddRelativeMaxSignalError is true, requieres SimShower.");
343  }
344  const evt::ShowerSimData &simShower = event.GetSimShower();
345  const double dmaxMc = simShower.GetDistanceOfShowerMaximum();
346  const double eemMc = simShower.GetElectromagneticEnergy();
347  const double sineAlphaMC = RadioGeometryUtilities::GetLorentzVector(
348  -simShower.GetDirection(), magneticField).GetMag();
349  // simple parameterisation of f_geo_max
350  const double fGeoMax = (6.70443081e+07 * meter / dmaxMc + 1.07044401e+02) * Sqr(eemMc / EeV * sineAlphaMC);
351  addErrMax = fAddRelativeMaxSignalError * fGeoMax;
352  }
353 
354  // iteration over stations - Sofar this ldf module can not make use of NoSignal stations
355  for (auto& station : rEvent.SignalStationsRange()) {
356  auto& sRec = station.GetRecData();
357 
358  // skip saturated stations if it is configured
359  if (!fUseSaturatedStations && station.IsSaturated())
360  continue;
361 
362  if (fAddLowestSignalAsError) {
363  sRec.SetParameterError(revt::eSignalEnergyFluenceVxB,
364  sqrt(Sqr(sRec.GetParameterError(revt::eSignalEnergyFluenceVxB)) +
365  Sqr(addErrMin)));
366  }
367 
368  if (fAddRelativeMaxSignalError) {
369  sRec.SetParameterError(revt::eSignalEnergyFluenceVxB,
370  sqrt(Sqr(sRec.GetParameterError(revt::eSignalEnergyFluenceVxB)) +
371  Sqr(addErrMax)));
372  }
373 
374  StationFitData stationFitData;
375  stationFitData.fId = station.GetId();
376  stationFitData.fPosition = rDetector.GetStation(station).GetPosition();
377  stationFitData.fEnergyFluenceVxB = sRec.GetParameter(revt::eSignalEnergyFluenceVxB);
378  stationFitData.fEnergyFluenceVxBErr = sRec.GetParameterError(revt::eSignalEnergyFluenceVxB);
379  stationFitData.fEnergyFluenceVxVxB = sRec.GetParameter(revt::eSignalEnergyFluenceVxVxB);
380  stationFitData.fEnergyFluenceVxVxBErr = sRec.GetParameterError(revt::eSignalEnergyFluenceVxVxB);
381  stationFitData.fRejected = false;
382  vStationFitData.push_back(stationFitData);
383 
384  ++numberOfSignalStations;
385  }
386 
387  info.str("");
388  info << "Number of Signal Stations: " << numberOfSignalStations;
389  INFOIntermediate(info);
390 
391  if (numberOfSignalStations < fMinimumNumberOfStations) {
392  WARNING("Number of signal stations after rejection " +
393  to_string(fMinimumNumberOfStations) + " -> doing nothing!");
394  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
395  return eSuccess;
396  }
397 
398  // Estimate Xmax to estimate start value for dmax
399  double showerXmaxGuess = 0;
400  if (!GetXmaxEstimator(event, showerXmaxGuess) || showerXmaxGuess / (g/cm2) <= 1) {
401  info.str("");
402  info << "Could not get xmax estimator \"" << fXmaxType << "\": "
403  << showerXmaxGuess / (g / cm2);
404  WARNING(info);
405  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
406  return eSuccess;
407  }
408 
409  // initiate atm + tables (which model is used is decieded in the config)
410  const atm::Atmosphere& theAtm = detector.GetAtmosphere();
411  theAtm.InitSlantProfileModel(refShowerCore, refShowerAxis, 10 * g / cm2);
412  //theAtm.InitSlantProfileModel(utl::Point(0., 0., 0., referenceCS), refShowerAxis, 10.*g/cm2);
413 
414  const atm::ProfileResult& distanceFromDepth = theAtm.EvaluateDistanceVsSlantDepth();
415  const atm::ProfileResult& densityFromHeight = theAtm.EvaluateDensityVsHeight();
416  const atm::ProfileResult& heightFromDistance = theAtm.EvaluateHeightVsDistance(); // needed within fit
417  const atm::ProfileResult& refracFromHeight = theAtm.EvaluateRefractionIndexVsHeight(); // needed within fit
418 
419  // shower maximum
420  const double distanceToXmaxGuess = abs(distanceFromDepth.Y(showerXmaxGuess)); // yep, the result is negative, convention thing...
421 
422  const utl::Point showerMax = refShowerCore + refShowerAxis * distanceToXmaxGuess; // -1 * axis ???
423  info.str("");
424  info << "Position of shower maximum (estimation with \"" << fXmaxType << "\": "
425  << showerXmaxGuess / (g/cm2) << ") (for PA): (" << showerMax.GetX(refCoreCS) / meter
426  << ", " << showerMax.GetY(refCoreCS) / meter
427  << ", " << showerMax.GetZ(refCoreCS) / meter << ')';
428  INFODebug(info);
429 
430  // set shower related quantities use in the fit
431  ShowerFitData fitShowerData;
432  fitShowerData.fSineAlpha = sineAlpha;
433  fitShowerData.fZenith = zenith;
434  fitShowerData.fDistanceTo750 = abs(distanceFromDepth.Y(750 * g / cm2));
435  fitShowerData.fRefShowerAxis = refShowerAxis;
436  fitShowerData.fMagneticField = magneticField;
437  fitShowerData.fRefShowerCore = refShowerCore;
438  fitShowerData.fDensityFromHeight = densityFromHeight;
439  fitShowerData.fHeightFromDistance = heightFromDistance;
440  fitShowerData.fRefracFromHeight = refracFromHeight;
441 
442  // set config
443  FitConfig fitConfig;
444  fitConfig.fUseParam = fUseParametrizationToDisentanglePolarisation;
445  fitConfig.fUseSoftExponent = fUseSoftExponent;
446 
447  // determine if core fit is feasible
448  const bool fitDXmax = (fFitDistanceToXmax && numberOfSignalStations >= 3);
449  const bool fitCore = (fFitCore && !fFitDistanceToXmax && numberOfSignalStations >= 3) ||
450  (fFitCore && numberOfSignalStations >= 4);
451 
452  // get start shape parameter from parametrisation
453  double crEnergy;
454  if (event.GetRecShower().HasSRecShower()) {
455  crEnergy = event.GetRecShower().GetSRecShower().GetEnergy();
456  } else {
457  INFOFinal("No SD rec shower information available. "
458  "Use a cosmic ray energy 1 EeV to determine start value for radiation energy ");
459  crEnergy = 1 * EeV;
460  }
461  const double startEgeo = 26.86e6 * eV * pow(crEnergy / (1e18 * eV), 1.989) * Sqr(sineAlpha);
462 
463  info.str("");
464  info << "Attempt LDF fit: Egeo = " << startEgeo << " eV, dmax = " << distanceToXmaxGuess << " m.";
465  INFOFinal(info);
466 
467  // Initalize parameters (WARNING: Take care of correct ordering)
468  vector<utl::Minou::ParameterDef> parameters;
469 
470  // name, value, step, min, max, fixed
471  parameters.emplace_back("E_geo", startEgeo, 10, 1e3, 1e13, false);
472 
473  // distance to xmax (fixed)
474  // boundaries are strange because of table convention (see -1 in fit function)
475  const double dxmaxMin = max(-heightFromDistance.MaxX(), 0.7 * distanceToXmaxGuess / meter);
476  const double dxmaxMax = min(-heightFromDistance.MinX(), 1.5 * distanceToXmaxGuess / meter);
477  parameters.emplace_back("distance_xmax_geometric", distanceToXmaxGuess / meter, 100, dxmaxMin, dxmaxMax, true);
478 
479  // fixed core
480  parameters.emplace_back("core_x", 0, 1, -1000, 1000, true);
481  parameters.emplace_back("core_y", 0, 1, -1000, 1000, true);
482 
483  // init fitfunction
484  const double egeoCorrectionFactor = 1;
485  LDFFitFunctionGaussSigmoid fitFunction(
486  vStationFitData, fitShowerData, parameters, fitConfig, egeoCorrectionFactor
487  );
488 
489  // to store fit results
490  vector<double> tmpFitResult;
491  double chi2 = 1e99;
492  int ndf = 0;
493  vector<pair<double, double>> bestParametersAndErrors;
494  {
495  // fit
496  Minou::Minimizer<LDFFitFunction> min(fitFunction);
497  INFOIntermediate("Inital fit: only Egeo is free");
498  if (fInfoLevel >= eInfoIntermediate)
499  min.SetVerbose(true);
500 
501  if (min.Minimize(50000)) {
502  INFOFinal("Fit falied ...");
503  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
504  ++fFailedFits;
505  return eSuccess;
506  }
507 
508  // store station data
509  tmpFitResult = min.GetParameters();
510  fitFunction.GetPrediction(tmpFitResult);
511  chi2 = fitFunction.GetChi2(tmpFitResult);
512  ndf = fitFunction.GetNDF();
513  bestParametersAndErrors = min.GetParametersAndErrors();
514  }
515 
516  if (fitCore) {
517  fitFunction.SetParameterDefValues(tmpFitResult);
518 
519  // A, Dxmax coreX, coreY
520  const vector<int> fixed({0, 1, 0, 0});
521  fitFunction.SetParameterDefFixed(fixed);
522 
523  // fit
524  Minou::Minimizer<LDFFitFunction> min(fitFunction);
525  INFOIntermediate("Egeo, coreX, coreY are free");
526 
527  if (fInfoLevel >= eInfoIntermediate)
528  min.SetVerbose(true);
529 
530  if (min.Minimize(50000)) {
531  INFOFinal("Fit falied ...");
532  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
533  ++fFailedFits;
534  return eSuccess;
535  }
536 
537  // store station data
538  tmpFitResult = min.GetParameters();
539  fitFunction.GetPrediction(min.GetParameters());
540  chi2 = fitFunction.GetChi2(min.GetParameters());
541  ndf = fitFunction.GetNDF();
542  bestParametersAndErrors = min.GetParametersAndErrors();
543  }
544 
545  if (fitDXmax) {
546  fitFunction.SetParameterDefValues(tmpFitResult);
547 
548  // A, Dxmax coreX, coreY
549  const vector<int> fixed({0, 0, 1, 1});
550  fitFunction.SetParameterDefFixed(fixed);
551 
552  // fit
553  Minou::Minimizer<LDFFitFunction> min(fitFunction);
554  INFOIntermediate("Egeo, dmax are free");
555 
556  if (fInfoLevel >= eInfoIntermediate)
557  min.SetVerbose(true);
558 
559  if (min.Minimize(50000)) {
560  INFOFinal("Fit falied ...");
561  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
562  ++fFailedFits;
563  return eSuccess;
564  }
565 
566  // store station data
567  tmpFitResult = min.GetParameters();
568  fitFunction.GetPrediction(min.GetParameters());
569  chi2 = fitFunction.GetChi2(min.GetParameters());
570  ndf = fitFunction.GetNDF();
571  bestParametersAndErrors = min.GetParametersAndErrors();
572  }
573 
574  if (fitCore) {
575  fitFunction.SetParameterDefValues(tmpFitResult);
576 
577  // A, Dxmax coreX, coreY
578  const vector<int> fixed({0, !fitDXmax, 0, 0});
579  fitFunction.SetParameterDefFixed(fixed);
580 
581  // fit
582  Minou::Minimizer<LDFFitFunction> min(fitFunction);
583  if (fitDXmax) {
584  INFOIntermediate("Egeo, coreX, coreY, dmax are free");
585  } else {
586  INFOIntermediate("Egeo, coreX, coreY are free");
587  }
588 
589  if (fInfoLevel >= eInfoIntermediate)
590  min.SetVerbose(true);
591 
592  if (min.Minimize(50000)) {
593  INFOFinal("Fit falied");
594  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
595  ++fFailedFits;
596  return eSuccess;
597  }
598 
599  // store station data
600  tmpFitResult = min.GetParameters();
601  fitFunction.GetPrediction(min.GetParameters());
602  chi2 = fitFunction.GetChi2(min.GetParameters());
603  ndf = fitFunction.GetNDF();
604  bestParametersAndErrors = min.GetParametersAndErrors();
605  }
606 
607  // ------ get fit results ---------
608  const double egeo = bestParametersAndErrors.at(0).first;
609  const double egeoErr = bestParametersAndErrors.at(0).second;
610 
611  const double distanceToXmaxFit = bestParametersAndErrors.at(1).first;
612  double distanceToXmaxFitErr;
613  if (fitDXmax) {
614  distanceToXmaxFitErr = bestParametersAndErrors.at(1).second;
615  } else {
616  // error when not fitting dxmax but take the estimated from the param. Xmax (is actually not gaussian!)
617  distanceToXmaxFitErr = 0.06 * distanceToXmaxFit;
618  }
619 
620  const double coreX = bestParametersAndErrors.at(2).first;
621  const double coreXerr = bestParametersAndErrors.at(2).second;
622 
623  const double coreY = bestParametersAndErrors.at(3).first;
624  const double coreYerr = bestParametersAndErrors.at(3).second;
625 
626  double densityAtXmaxFit = 0;
627  double densityAtXmaxFitErr = 0;
628  try {
629  const double dxmax_sysdown = distanceToXmaxFit - distanceToXmaxFitErr;
630  const double dxmax_sysup = distanceToXmaxFit + distanceToXmaxFitErr;
631  // here the "-" signs are due to table convention
632  densityAtXmaxFit = densityFromHeight.Y(heightFromDistance.Y(-distanceToXmaxFit));
633  densityAtXmaxFitErr =
634  (densityFromHeight.Y(heightFromDistance.Y(-dxmax_sysdown)) -
635  densityFromHeight.Y(heightFromDistance.Y(-dxmax_sysup))) / 2;
636  } catch (const std::exception& e) {
637  INFOFinal("No proper error propagation possible, fit is discarded."
638  " distanceToXmaxFit +/- distanceToXmaxFitErr out of table range for heightFromDistance");
639  showerrrec.SetParameter(revt::eHASLDFHasFit, false);
640  ++fFailedFits;
641  return eSuccess;
642  }
643 
644  info.str("");
645  info << "LDF fit succesfull:\n"
646  "\tEgeo = " << egeo/MeV << " +- " << egeoErr / MeV << " MeV (" << egeoErr / egeo * 100 << " %)\n"
647  "\tdmax = " << distanceToXmaxFit / km << " +- " << distanceToXmaxFitErr / km << " km "
648  "(" << distanceToXmaxFitErr / distanceToXmaxFit * 100 << " %)\n"
649  "\tCoreX = " << coreX / m << " +- " << coreXerr / m << " m, CoreY = "
650  << coreY / m << " +- " << coreYerr / m << " m\n"
651  "\tchi2 / ndf = " << chi2 << " / " << ndf << " = " << chi2 / ndf;
652  INFOFinal(info);
653 
654  showerrrec.SetParameter(revt::eHASLDFHasFit, true);
655  showerrrec.SetParameter(revt::eHASLDFChi2, chi2);
656  showerrrec.SetParameter(revt::eHASLDFNDF, ndf);
657 
658  for (const auto& s : vStationFitData) {
659  revt::Station& station = rEvent.GetStation(s.fId);
660  revt::StationRecData& sRec = station.GetRecData();
661 
662  sRec.SetParameter(revt::eEarlyLateCorrectionFactor, s.fCEarlyLate);
663  sRec.SetParameter(revt::eChargeExcessFraction, s.fCeFraction);
664  sRec.SetParameter(revt::ePredictedEnergyFluenceVxB, s.fEnergyFluenceVxBPredict);
665  sRec.SetParameter(revt::eGeomagneticEnergyFluence, s.fEnergyFluenceGeomagnetic);
666  sRec.SetParameterError(revt::eGeomagneticEnergyFluence, s.fEnergyFluenceGeomagneticErr);
667  }
668 
669  // store shower data in Auger units
670  showerrrec.SetParameter(revt::eGeomagneticRadiationEnergy, egeo); // is already in eV
671  showerrrec.SetParameterError(revt::eGeomagneticRadiationEnergy, egeoErr); // is already in eV
672 
673  showerrrec.SetParameter(revt::eHASLDFDensityAtXmax, densityAtXmaxFit / (kg/m3));
674  showerrrec.SetParameterError(revt::eHASLDFDensityAtXmax, densityAtXmaxFitErr / (kg/m3));
675  showerrrec.SetParameter(revt::eHASLDFDistanceToXmaxGeometric, distanceToXmaxFit / meter); // in meter
676  showerrrec.SetParameterError(revt::eHASLDFDistanceToXmaxGeometric, distanceToXmaxFitErr / meter); // in meter
677 
678  showerrrec.SetParameter(revt::eHASLDFCoreX, coreX);
679  showerrrec.SetParameter(revt::eHASLDFCoreY, coreY);
680  showerrrec.SetParameterError(revt::eHASLDFCoreX, coreXerr);
681  showerrrec.SetParameterError(revt::eHASLDFCoreY, coreYerr);
682 
683  // original core is origin in vB system
684  utl::Point radioCore = transformation.GetVectorFromShowerPlaneVxB(coreX, coreY);
685  showerrrec.SetParameter(revt::eCoreX, radioCore.GetX(referenceCS));
686  showerrrec.SetParameter(revt::eCoreY, radioCore.GetY(referenceCS));
687  showerrrec.SetParameter(revt::eCoreZ, radioCore.GetZ(referenceCS));
688 
689  utl::RadioGeometryUtilities transformationRadioCore =
690  RadioGeometryUtilities(refShowerAxis, LocalCoordinateSystem::Create(radioCore), magneticField);
691 
692  // iteration over stations - store position in vB,vvB with final radio core
693  // we use the station iterator here to save the position in the vxB frame for all stations
694  for (auto& station : rEvent.StationsRange()) {
695  revt::StationRecData& sRec = station.GetRecData();
696  const Point sPos = rDetector.GetStation(station).GetPosition();
697 
698  // due to the choice of coordinate system the station position will be evaluated relative to the core position
699  double xvxB = 0;
700  double yvxB = 0;
701  double zvxB = 0;
702  transformationRadioCore.GetVectorInShowerPlaneVxB(xvxB, yvxB, zvxB, sPos);
703 
704  sRec.SetParameter(revt::eLDFFitStationPositionVxB, xvxB);
705  sRec.SetParameter(revt::eLDFFitStationPositionVxVxB, yvxB);
706  sRec.SetParameter(revt::eLDFFitStationPositionV, zvxB);
707  }
708 
709  // get energy reconstruction
710  double densityCorrection = 0;
711  double densityCorrectionErr = 0;
712  RadiationDensityCorrection(densityAtXmaxFit, densityAtXmaxFitErr, densityCorrection, densityCorrectionErr);
713  showerrrec.SetParameter(revt::eDensityCorrectionFactor, densityCorrection);
714  showerrrec.SetParameterError(revt::eDensityCorrectionFactor, densityCorrectionErr);
715 
716  double radioEnergyEstimator = egeo / Sqr(sineAlpha) * densityCorrection;
717 
718  const double sineAlphaSquareErr = GetSineAlphaSquareErr(event);
719  const double radioEnergyEstimatorErr =
720  radioEnergyEstimator *
721  sqrt(Sqr(egeoErr / egeo) +
722  Sqr(densityCorrectionErr / densityCorrection) +
723  Sqr(sineAlphaSquareErr / Sqr(sineAlpha)));
724 
725  showerrrec.SetParameter(revt::eCorrectedGeomagneticRadiationEnergy, radioEnergyEstimator);
726  showerrrec.SetParameterError(revt::eCorrectedGeomagneticRadiationEnergy, radioEnergyEstimatorErr);
727 
728  double electromagneticEnergyRec = 0;
729  double electromagneticEnergyRecErr = 0;
730  ElectromagneticEnergy(
731  radioEnergyEstimator, radioEnergyEstimatorErr,
732  electromagneticEnergyRec, electromagneticEnergyRecErr, zenith);
733  showerrrec.SetParameter(revt::eReconstructedElectromagneticEnergy, electromagneticEnergyRec);
734  showerrrec.SetParameterError(revt::eReconstructedElectromagneticEnergy, electromagneticEnergyRecErr);
735 
736  /* Calibration from electromagnetic to absolut shower/cosmic ray energy. See PhD Thesis from Felix Schüter Chap. 8.4.3.
737  Calibration determined with QGSJetII-04 and 4 primaries: p, He, N, Fe. Results with Sibyll2.3d were very similar */
738  const double cosmicRayEnergy = electromagneticEnergyRec * (1.14263 - 0.03279 * log10(electromagneticEnergyRec / (10 * utl::EeV)));
739  const double cosmicRayEnergyErr = electromagneticEnergyRecErr * (cosmicRayEnergy / electromagneticEnergyRec);
740  showerrrec.SetParameter(revt::eCosmicRayEnergy, cosmicRayEnergy);
741  showerrrec.SetParameterError(revt::eCosmicRayEnergy, cosmicRayEnergyErr);
742 
743  // fix or parametrized
744  const double r0 = fitFunction.CalculateR0();
745  const double sig = fitFunction.GetSig(distanceToXmaxFit);
746  const double p = fitFunction.GetP(distanceToXmaxFit);
747  const double arel = fitFunction.GetArel(distanceToXmaxFit);
748  const double r02 = fitFunction.GetR02(distanceToXmaxFit);
749 
750  showerrrec.SetParameter(revt::eHASLDFNorm, fitFunction.GetNormalization());
751 
752  showerrrec.SetParameter(revt::eHASLDFr0, r0);
753  showerrrec.SetParameter(revt::eHASLDFsig, sig);
754  showerrrec.SetParameter(revt::eHASLDFp, p);
755  showerrrec.SetParameter(revt::eHASLDFarel, arel);
756  showerrrec.SetParameter(revt::eHASLDFslope, 5);
757  showerrrec.SetParameter(revt::eHASLDFr02, r02);
758 
759  // If it reaches this point: successful fit
760  ++fSuccessfulFits;
761  return eSuccess;
762  }
763 
764 
766  RdHASLDFFitter::Finish()
767  {
768  ostringstream info;
769  const double total = fSuccessfulFits + fFailedFits; // double to prevent integer devision
770  if (total) {
771  info << "Number of successful and failed fits: " << fSuccessfulFits << " / " << fFailedFits
772  << " (" << fSuccessfulFits / total * 100 << "%, " << fFailedFits / total * 100 << "%)";
773  } else
774  info << "No radio has ldf fit was performed!";
775 
776  INFOFinal(info);
777  return eSuccess;
778  }
779 
780 }
void SetVerbose(const bool verbose)
Definition: Minou.h:234
Branch GetTopBranch() const
Definition: Branch.cc:63
const double eV
Definition: GalacticUnits.h:35
Class to access station level reconstructed data.
Top of the interface to Atmosphere information.
void SetParameter(Parameter i, double value, bool lock=true)
utl::Vector GetAxis() const
Returns vector of the shower axis.
void SetParameterError(Parameter i, double value, bool lock=true)
utl::Point GetReferenceCorePosition(const Event &event) const
Returning the reference core position depending on the corresponding flag.
double GetZenithError() const
returns the error of the zenith angle (from the wave fit)
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
constexpr double EeV
Definition: AugerUnits.h:190
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
void InitSlantProfileModel(const utl::Point &core, const utl::Vector &dir, const double deltaX) const
Interface class to access to the SD Reconstruction of a Shower.
StationRecData & GetRecData()
Get station level reconstructed data.
const evt::VGaisserHillasParameter & GetGHParameters() const
Get the Gaisser-Hillas parameters of the shower.
bool HasRecShower() const
atm::ProfileResult fDensityFromHeight
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
Base class for exceptions arising because configuration data are not valid.
ShowerRecData & GetRecShower()
Interface class to access to the RD Reconstruction of a Shower.
const atm::ProfileResult & EvaluateDensityVsHeight() const
Tabulated function giving Y=density as a function of X=height.
bool HasSimShower() const
double GetElectromagneticEnergy() const
Get the electromagnetic energy of the shower.
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
const double meter
Definition: GalacticUnits.h:29
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
double GetChi2(const std::vector< double > &pars)
void SetParameterDefFixed(const std::vector< int > &fixed)
Definition: Minou.h:134
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double pow(const double x, const unsigned int i)
bool HasREvent() const
const double EeV
Definition: GalacticUnits.h:34
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: REvent.h:190
double GetMag() const
Definition: Vector.h:58
double GetArel(const double dmax) const
double GetAzimuthError() const
returns the error of the azimuth angle (from the wave fit)
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
constexpr double deg
Definition: AugerUnits.h:140
constexpr double MeV
Definition: AugerUnits.h:184
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
const atm::Atmosphere & GetAtmosphere() const
Definition: Detector.h:113
T Get() const
Definition: Branch.h:271
atm::ProfileResult fHeightFromDistance
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define INFOIntermediate(y)
Definition: VModule.h:162
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!!!
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
double GetDistanceOfShowerMaximum() const
Get the geometrical distance of the shower maximum from the core.
class to hold data at the radio Station level.
bool HasAxis() const
Return true if all 3 axis parameter are set.
constexpr double s
Definition: AugerUnits.h:163
const utl::Vector & GetDirection() const
Get the direction of the shower axis. This is the true direction of shower movement.
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
double GetSig(const double dmax) const
double abs(const SVector< n, T > &v)
double GetSineAlphaSquareErr(const Event &event)
double GetR02(const double dmax) const
bool HasRRecShower() const
constexpr double m3
Definition: AugerUnits.h:123
Top of the hierarchy of the detector description interface.
Definition: Detector.h:81
const double km
constexpr double g
Definition: AugerUnits.h:200
double GetThetaError() const
const utl::Vector & GetAxis() const
double GetPhiError() const
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
#define INFODebug(y)
Definition: VModule.h:163
double GetEnergy() 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
Definition: BasicVector.h:209
double MinX() const
Return the minimum value for X (ordinate) stored in the profile.
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
int Minimize(const int n=500)
Definition: Minou.h:250
void SetParameterError(Parameter i, double value, bool lock=true)
void SetParameterDefValues(const std::vector< double > &vals)
Definition: Minou.h:113
void SetParameter(Parameter i, double value, bool lock=true)
Vector object.
Definition: Vector.h:30
utl::Vector GetReferenceAxis(const Event &event) const
Returning the referencedirection depending on the corresponding flag.
void GetPrediction(const std::vector< double > &pars)
atm::ProfileResult fRefracFromHeight
const rdet::RDetector & GetRDetector() const
Definition: Detector.cc:143
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
const atm::ProfileResult & EvaluateRefractionIndexVsHeight() const
Tabulated function giving Y=refraction index as a function of X=height.
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
#define INFOFinal(y)
Definition: VModule.h:161
ReferenceAxis GetReferenceAxisFlag() const
returns the flag which specify the used reference direction
utl::Vector GetMagneticFieldVector() const
returns the magnetic field vector from the components stored in the parameter storage ...
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
bool HasSRecShower() const
double GetP(const double dmax) const
double MaxX() const
Return the maximum value for X (ordinate) stored in the profile.
constexpr double kg
Definition: AugerUnits.h:199
const atm::ProfileResult & EvaluateHeightVsDistance() const
Table of height as a function of distance.
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.