8 #include <utl/ErrorLogger.h>
12 #include <fwk/CentralConfig.h>
14 #include <utl/Vector.h>
15 #include <utl/Point.h>
16 #include <utl/BasicVector.h>
17 #include <utl/GeometryUtilities.h>
18 #include <utl/RadioGeometryUtilities.h>
19 #include <utl/CoordinateSystemPtr.h>
20 #include <utl/StringCompare.h>
22 #include <evt/Event.h>
23 #include <evt/ShowerRecData.h>
24 #include <evt/ShowerSRecData.h>
25 #include <evt/ShowerRRecData.h>
26 #include <evt/ShowerFRecData.h>
27 #include <evt/ShowerSimData.h>
28 #include <evt/RadioSimulation.h>
31 #include <revt/REvent.h>
32 #include <revt/Station.h>
33 #include <revt/Header.h>
34 #include <revt/StationRecData.h>
35 #include <revt/StationRRecDataQuantities.h>
37 #include <det/Detector.h>
38 #include <rdet/RDetector.h>
41 #include "TGraph2DErrors.h"
45 #include "TFitResultPtr.h"
72 fUseSilentStations(false)
129 WARNING(
"No radio event found!");
139 ShowerRRecData& showerrrec =
event.GetRecShower().GetRRecShower();
141 TGraph2DErrors lateralDistribution2DvxB;
144 const rdet::RDetector& rDetector = det::Detector::GetInstance().GetRDetector();
152 det::Detector::GetInstance().GetReferenceCoordinateSystem();
157 const double zenith = showerAxis.
GetTheta(localCS);
161 const int nant = showerrrec.
GetParameter(revt::eNumberOfStationsWithPulseFound);
164 WARNING(
"Number of signalstations less than 3 -> doing nothing");
172 magneticField /= magneticField.
GetMag();
174 unsigned int numberOfSignalStations = 0;
175 unsigned int numberOfSilentStations = 0;
184 ++numberOfSilentStations;
186 ++numberOfSignalStations;
189 if (numberOfSignalStations < 3) {
190 WARNING(
"Number of signalstations after rejection of saturated stations < 3 -> doing nothing!");
193 double ratio_sil2sig = 1;
194 if (numberOfSilentStations > numberOfSignalStations) {
195 ratio_sil2sig = numberOfSilentStations / numberOfSignalStations;
197 double index_signal_stations[numberOfSignalStations][5];
215 sRec.
SetParameter(revt::eLDFFitStationPositionVxB, x_VxB);
216 sRec.
SetParameter(revt::eLDFFitStationPositionVxVxB, y_VxB);
217 sRec.
SetParameter(revt::eLDFFitStationPositionV, z_VxB);
219 const double integral = sRec.
GetParameter(revt::eSignalEnergyFluenceMag);
220 const double uncertainty = sRec.
GetParameterError(revt::eSignalEnergyFluenceMag);
224 sstr <<
"Signal: " << integral <<
"+/-" << uncertainty <<
"\n"
225 "Station position (reference CS): " << sPos.
GetX(referenceCS) /
utl::m <<
", "
227 "Station Position (localCS): " << sPos.
GetX(localCS) /
utl::m <<
", "
229 "core position (reference CS): " << core.
GetX(referenceCS) <<
", "
230 << core.
GetY(referenceCS) <<
", " << core.
GetZ(referenceCS) <<
"\n"
231 "showerAxis (local cs): " << showerAxis.
GetX(localCS) <<
", "
232 << showerAxis.
GetY(localCS) <<
", " << showerAxis.
GetZ(localCS) <<
"\n"
233 "magnetic field (localCS): " << magneticField.
GetX(localCS) <<
", "
234 << magneticField.
GetY(localCS) <<
", " << magneticField.
GetZ(localCS) <<
"\n"
235 "magnetic field (referenceCS): " << magneticField.
GetX(referenceCS) <<
", "
236 << magneticField.
GetY(referenceCS) <<
", " << magneticField.
GetZ(referenceCS) <<
"\n"
237 "position in vxB, vxvxB, z: " << x_VxB <<
", " << y_VxB <<
", " << z_VxB << endl;
242 lateralDistribution2DvxB.SetPoint(lateralDistribution2DvxB.GetN(), x_VxB, y_VxB, integral);
243 lateralDistribution2DvxB.SetPointError(lateralDistribution2DvxB.GetN() - 1, 0., 0.,
244 uncertainty * ratio_sil2sig);
246 lateralDistribution2DvxB.SetPoint(lateralDistribution2DvxB.GetN(), x_VxB, y_VxB, integral);
247 lateralDistribution2DvxB.SetPointError(lateralDistribution2DvxB.GetN() - 1, 0., 0.,
249 index_signal_stations[i][0] = lateralDistribution2DvxB.GetN() - 1;
250 index_signal_stations[i][1] = x_VxB;
251 index_signal_stations[i][2] = y_VxB;
252 index_signal_stations[i][3] = integral;
253 index_signal_stations[i][4] = uncertainty;
259 double sigma_max = 500;
261 double covRoot[9][9];
264 "LDF_pre_fit",
"[0]*TMath::Exp(-((x-[1])*(x-[1])/([2]*[2])+(y-[3])*(y-[3])/([2]*[2])))",
265 lateralDistribution2DvxB.GetXmin() - 100, lateralDistribution2DvxB.GetXmax() + 100,
266 lateralDistribution2DvxB.GetYmin() - 100, lateralDistribution2DvxB.GetYmax() + 100
271 "[0]*TMath::Exp(-((x-([1]+[5]))**2+(y-[2])**2)/[3]**2)-[6]*[0]*TMath::Exp(-((x-([1]+[4]))**2+(y-[2])**2)/TMath::Exp([7]+[8]*[3])**2)",
272 lateralDistribution2DvxB.GetXmin() - 100, lateralDistribution2DvxB.GetXmax() + 100,
273 lateralDistribution2DvxB.GetYmin() - 100, lateralDistribution2DvxB.GetYmax() + 100
276 ldf_pre_fit.SetParameter(0, lateralDistribution2DvxB.GetZmax());
277 ldf_pre_fit.SetParLimits(0, 1e-20 * 6.24150934 * 1e18, 1e-14 * 6.24150934 * 1e18);
278 ldf_pre_fit.SetParameter(1, 0);
279 ldf_pre_fit.SetParameter(2, 100);
280 ldf_pre_fit.SetParLimits(2, 0, 1000);
281 ldf_pre_fit.SetParameter(3, 0);
283 lateralDistribution2DvxB.Fit(&ldf_pre_fit);
285 if (gMinuit->fCstatu ==
"CONVERGED ") {
286 ldf2DFit.SetParameter(0, ldf_pre_fit.GetParameter(0));
287 ldf2DFit.SetParLimits(0, 1e-20 * 6.24150934 * 1e18, 1e-14 * 6.24150934 * 1e18);
288 ldf2DFit.SetParameter(1, ldf_pre_fit.GetParameter(1));
289 ldf2DFit.SetParameter(2, ldf_pre_fit.GetParameter(3));
290 ldf2DFit.SetParameter(3, ldf_pre_fit.GetParameter(2));
291 ldf2DFit.SetParLimits(3, 0, sigma_max);
293 ldf2DFit.SetParameter(0, lateralDistribution2DvxB.GetZmax());
294 ldf2DFit.SetParLimits(1, 1e-20 * 6.24150934 * 1e18, 1e-14 * 6.24150934 * 1e18);
295 ldf2DFit.SetParameter(1, 0);
296 ldf2DFit.SetParameter(2, 0);
297 ldf2DFit.SetParameter(3, 50);
298 ldf2DFit.SetParLimits(3, 0, sigma_max);
333 ldf2DFit.FixParameter(4, c2);
334 ldf2DFit.FixParameter(5, c1);
335 ldf2DFit.FixParameter(6, a_scale);
336 ldf2DFit.FixParameter(7,
fC3);
337 ldf2DFit.FixParameter(8,
fC4);
339 const bool fitCore = !(numberOfSignalStations < 5 ||
fFixCore ==
true);
341 ldf2DFit.FixParameter(1, 0.);
342 ldf2DFit.FixParameter(2, 0.);
345 TFitResultPtr
result = lateralDistribution2DvxB.Fit(&ldf2DFit,
"S");
346 chi2 = ldf2DFit.GetChisquare();
347 INFODebug(
"chi2 with prefit input " + to_string(chi2));
348 bool fitSucessful =
false;
349 if (gMinuit->fCstatu ==
"CONVERGED " || gMinuit->fCstatu ==
"OK " || gMinuit->fCstatu ==
"SUCCESSFUL") {
351 gMinuit->mnemat(&covRoot[0][0], 9);
355 for (
int k = 1; k < 9; ++k) {
356 ldf2DFit.SetParameter(3, k * 25);
357 TFitResultPtr result_temp = lateralDistribution2DvxB.Fit(&ldf2DFit,
"S");
358 INFODebug(
"varying sigma= " + to_string(k*25) +
"=> chi2 " + to_string(ldf2DFit.GetChisquare()));
359 if (ldf2DFit.GetChisquare() < chi2) {
360 if (gMinuit->fCstatu ==
"CONVERGED " || gMinuit->fCstatu ==
"OK " || gMinuit->fCstatu ==
"SUCCESSFUL") {
362 result = result_temp;
363 chi2 = ldf2DFit.GetChisquare();
364 gMinuit->mnemat(&covRoot[0][0], 9);
370 INFO(
"None of the fit attempts delivered a successful fit -> SKIP");
374 if (result->Parameter(3) > sigma_max - 1.) {
376 INFO(
"final reconstructed sigma at parameter limit -> SKIP");
385 ldf2DFit.SetFitResult(*result);
386 vector<double> var_A;
387 vector<double> var_sigma;
388 for (
int k = 0; k < 1000; ++k) {
389 for (
unsigned int l = 0; l < numberOfSignalStations; ++l) {
390 lateralDistribution2DvxB.SetPoint(
391 index_signal_stations[l][0], index_signal_stations[l][1], index_signal_stations[l][2],
392 r.Gaus(index_signal_stations[l][3], index_signal_stations[l][4]));
395 lateralDistribution2DvxB.Fit(&ldf2DFit,
"SV");
397 lateralDistribution2DvxB.Fit(&ldf2DFit,
"SQ");
400 if (gMinuit->fCstatu ==
"CONVERGED " ||
401 gMinuit->fCstatu ==
"OK " ||
402 gMinuit->fCstatu ==
"SUCCESSFUL") {
403 if (ldf2DFit.GetParameter(3) < sigma_max - 1.) {
404 var_A.push_back(ldf2DFit.GetParameter(0));
405 var_sigma.push_back(ldf2DFit.GetParameter(3));
410 if (var_A.size() < 500) {
412 INFO(
"less than 500 of the 1000 additional fits were successful -> SKIP!");
417 const double q_A_15_9 =
Quantile(var_A, 15.9);
418 const double q_A_50 =
Quantile(var_A, 50.);
419 const double q_A_84_1 =
Quantile(var_A, 84.1);
420 INFODebug(
"amplitude quantiles" + to_string(q_A_15_9) +
" " + to_string(q_A_50) +
421 " " + to_string(q_A_84_1));
423 const double q_sigma_15_9 =
Quantile(var_sigma, 15.9);
424 const double q_sigma_50 =
Quantile(var_sigma, 50.);
425 const double q_sigma_84_1 =
Quantile(var_sigma, 84.1);
426 INFODebug(
"sigma quantiles" + to_string(q_sigma_15_9) +
" " + to_string(q_sigma_50) +
427 " " + to_string(q_sigma_84_1));
429 bool unstableFit =
false;
430 if (q_A_50 < (result->Parameter(0) - result->ParError(0)) ||
431 q_A_50 > (result->Parameter(0) + result->ParError(0))) {
433 INFO(
"2DLDF Fit rejected, difference between mean of A-distribution and A too big!");
436 if (q_sigma_50 < (result->Parameter(3) - result->ParError(3)) ||
437 q_sigma_50 > (result->Parameter(3) + result->ParError(3))) {
439 INFO(
"2DLDF Fit rejected, difference between mean of Sigma-distribution and Sigma too big!");
442 if ((q_A_50 - q_A_15_9) / (q_A_84_1 - q_A_50) < 0.5 ||
443 (q_A_50 - q_A_15_9) / (q_A_84_1 - q_A_50) > 2) {
445 INFO(
"2DLDF Fit rejected, A-distribution too asymmetric!");
448 if ((q_sigma_50 - q_sigma_15_9) / (q_sigma_84_1 - q_sigma_50) < 0.5 ||
449 (q_sigma_50 - q_sigma_15_9) / (q_sigma_84_1 - q_sigma_50) > 2) {
451 INFO(
"2DLDF Fit rejected, Sigma-distribution too asymmetric!");
461 showerrrec.Set2dLDFFitResult(*result);
464 double y = result->Parameter(2);
472 double A = result->Parameter(0);
473 double sigma = result->Parameter(3);
474 double A_error = result->ParError(0);
475 double sigma_error = result->ParError(3);
476 double sigmaA_error = result->CovMatrix(0, 3);
477 double radiationEnergy = A * TMath::Pi()
478 * (
pow(sigma, 2) - c0 * TMath::Exp(2 *
fC3 + 2 *
fC4 * sigma));
479 double radiationEnergyError =
pow(
480 pow(TMath::Pi(), 2) *
pow(c0 * TMath::Exp(2 *
fC3 + 2 *
fC4 * sigma) -
pow(sigma, 2), 2)
482 +
pow(A, 2) *
pow(TMath::Pi(), 2)
483 *
pow((2 * c0 *
fC4 * TMath::Exp(2 *
fC4 * sigma + 2 *
fC3) - 2 * sigma), 2)
484 *
pow(sigma_error, 2)
485 - TMath::Pi() * (2 * c0 *
fC4 * TMath::Exp(2 *
fC4 * sigma + 2 *
fC3) - 2 * sigma)
489 showerrrec.
SetParameter(revt::eRadiationEnergy, radiationEnergy);
492 INFOIntermediate(
"Final result: radiation energy = " + to_string(radiationEnergy)
493 +
" +/- " + to_string(radiationEnergyError));
495 if (event.
HasSimShower() &&
event.GetSimShower().HasRadioSimulation()) {
496 const double radiationEnergySim =
497 event.GetSimShower().GetRadioSimulation().GetRadiationEnergy();
498 if (radiationEnergySim != 0.) {
499 const double Erad_resolution = (radiationEnergy - radiationEnergySim) / radiationEnergySim * 100;
500 INFOIntermediate(to_string(Erad_resolution) +
" % wrt true/simulated radiation energy");
506 sstr <<
"Final result: sigma = " << sigma <<
" +/- " << sigma_error <<
"\n"
507 <<
"Final result: x = " << result->Parameter(1) <<
" +/- " << result->ParError(1) <<
"\n"
508 <<
"Final result: y = " << result->Parameter(2) <<
" +/- " << result->ParError(2) <<
"\n";
512 const double sineAlpha =
513 RadioGeometryUtilities::GetLorentzVector(
517 const double d = 2.3137 * 1e14;
518 const double c = 0.505;
519 const double energy = d *
std::pow(radiationEnergy / (sineAlpha * sineAlpha), c);
520 const double energyError =
521 c * d *
std::pow(1 / (sineAlpha * sineAlpha), c) *
522 std::pow(radiationEnergy, c - 1) * radiationEnergyError;
523 showerrrec.
SetParameter(revt::eCosmicRayEnergy, energy);
526 double chi2signal = 0.;
527 ldf2DFit.SetFitResult(*result);
528 for (
unsigned int u = 0; u < numberOfSignalStations; ++u) {
530 (index_signal_stations[u][3] -
531 ldf2DFit.Eval(index_signal_stations[u][1], index_signal_stations[u][2]))
532 / index_signal_stations[u][4],
538 NDF = numberOfSignalStations - 2;
540 NDF = numberOfSignalStations - 4;
543 showerrrec.
SetParameter(revt::e2DLDFfitSignalChi2, chi2signal);
551 Rd2dLDFFitter::Finish()
559 Rd2dLDFFitter::Quantile(vector<double>
data,
const double percent)
562 sort(data.begin(), data.end());
563 const unsigned int length = data.size() - 1;
564 const int index_above = ceil(length * percent / 100.);
565 const int index_below = floor(length * percent / 100.);
566 if (index_above == index_below) {
567 return data[index_above];
569 const double m = data[index_above] - data[index_below];
570 const double b = data[index_above] - m * index_above;
571 return length * percent / 100. * m +
b;
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.
boost::filter_iterator< CandidateStationFilter, AllStationIterator > CandidateStationIterator
Iterator over all CandidateStations (i.e., HasSignal, HasNoSignal)
Report success to RunController.
StationRecData & GetRecData()
Get station level reconstructed data.
bool HasRecShower() const
CandidateStationIterator CandidateStationsEnd()
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.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double Quantile(std::vector< double > data, const double percent) const
double pow(const double x, const unsigned int i)
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.
class to hold data at the radio Station level.
void SetRejected(const unsigned long long int reason)
double GetX(const CoordinateSystemPtr &coordinateSystem) const
bool HasRRecShower() const
CandidateStationIterator CandidateStationsBegin()
#define WARNING(message)
Macro for logging warning messages.
void GetData(bool &b) const
Overloads of the GetData member template function.
revt::ShowerRRecDataQuantities Parameter
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.
void SetParameterError(Parameter i, double value, bool lock=true)
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 GetParameter(const Parameter i) const
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
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.