RdSphericalFit.cc
Go to the documentation of this file.
1 #include "RdSphericalFit.h"
2 #include "SphericalFitFunction.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 #include <utl/AnalyticCoordinateTransformator.h>
15 
16 // event
17 #include <evt/Event.h>
18 #include <evt/ShowerRecData.h>
19 #include <evt/ShowerSRecData.h>
20 #include <evt/ShowerRRecData.h>
21 #include <evt/ShowerSimData.h>
22 
23 // revent
24 #include <revt/REvent.h>
25 #include <revt/Header.h>
26 #include <revt/Station.h>
27 #include <revt/StationRecData.h>
28 #include <revt/StationRRecDataQuantities.h>
29 
30 // det / rdet
31 #include <det/Detector.h>
32 #include <rdet/RDetector.h>
33 
34 // atmosphere
35 #include <atm/AerosolDB.h>
36 #include <atm/AerosolZone.h>
37 #include <atm/ProfileResult.h>
38 #include <atm/MonthlyAvgDBProfileModel.h>
39 #include <atm/InclinedAtmosphericProfile.h>
40 #include <atm/SimShowerProfileModel.h>
41 
42 #include <TMath.h>
43 #include <TMatrixD.h>
44 
45 #include <string>
46 #include <vector>
47 
48 
49 using namespace std;
50 using namespace revt;
51 using namespace evt;
52 using namespace fwk;
53 using namespace utl;
54 
55 
56 namespace RdSphericalFit {
57 
58  vector<double>
59  GetTimeResiduals(const vector<StationFitData>& vStationFitData,
60  const Vector& showerAxis, const double tau0)
61  {
62  vector<double> expectedTimes;
63  vector<double> timeResiduals;
64 
65  for (const auto& d : vStationFitData) {
66  const double expTime = (d.antennaPos - showerAxis).GetMag() / kSpeedOfLight;
67  expectedTimes.push_back(expTime);
68  }
69 
70  const double t0 = TMath::Mean(expectedTimes.begin(), expectedTimes.end());
71 
72  for (unsigned int i = 0, n = vStationFitData.size(); i < n; ++i) {
73  const double residual = (vStationFitData[i].signalTime - tau0) - (expectedTimes[i] - t0);
74  timeResiduals.push_back(residual);
75  }
76 
77  return timeResiduals;
78  }
79 
80 
83  {
84  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdSphericalFit");
85  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
86  topBranch.GetChild("minNumberOfStations").GetData(fMinNumberOfStations);
87  topBranch.GetChild("useInitialGeometry").GetData(fUseInitialGeometry);
88  topBranch.GetChild("thetaVarC").GetData(fThetaVarC);
89  topBranch.GetChild("thetaMin").GetData(fThetaMin);
90  topBranch.GetChild("thetaMax").GetData(fThetaMax);
91  topBranch.GetChild("rMax").GetData(fRadiusMax);
92 
93  const string yesnostr = topBranch.GetChild("allowMultipleCalls").Get<string>();
94  fLockParameterStorage = (yesnostr == "no");
95 
96  return eSuccess;
97  }
98 
99 
101  RdSphericalFit::Run(Event& event)
102  {
103  // nothing to do if there is no REvent
104  if (!event.HasREvent()) {
105  INFOFinal("eContinueLoop: No REvent, so no reconstruction");
106  return eContinueLoop;
107  }
108 
109  REvent& rEvent = event.GetREvent();
110  ShowerRRecData& showerrrec = event.GetRecShower().GetRRecShower();
111  const int fNumberOfStations = rEvent.GetNumberOfSignalStations();
112 
113  const det::Detector& detector = det::Detector::GetInstance();
114  const rdet::RDetector& rDetector = detector.GetRDetector();
115 
116  ostringstream info;
117 
118  if (fNumberOfStations < fMinNumberOfStations) {
119  info.str("");
120  info << "Event contains only " << fNumberOfStations
121  << " station(s), not enough for spherical fit. Event is skipped";
122  INFOFinal(info);
123  return eContinueLoop;
124  }
125 
126  const CoordinateSystemPtr referenceCS =
127  det::Detector::GetInstance().GetReferenceCoordinateSystem();
128 
129  // get coordinate origin depending on xml settings
130  Vector initialShowerAxis;
131  Point initialCore;
132 
133  if (fUseInitialGeometry == "SD") {
134  if (!event.GetRecShower().HasSRecShower()) {
135  WARNING("Event has no SRecShower. Event is skipped");
136  return eContinueLoop;
137  }
138  initialShowerAxis = event.GetRecShower().GetSRecShower().GetAxis();
139  initialCore = event.GetRecShower().GetSRecShower().GetCorePosition();
140  } else if (fUseInitialGeometry == "MC") {
141  if (!event.HasSimShower()) {
142  WARNING("Event has no simulated shower. Event is skipped");
143  return eContinueLoop;
144  }
145  initialShowerAxis = -event.GetSimShower().GetDirection();
146  initialCore = event.GetSimShower().GetPosition();
147  } else if (fUseInitialGeometry == "RD") {
148  if (!event.GetRecShower().HasRRecShower()) {
149  WARNING("Event has no HasRRecShower. Event is skipped");
150  return eContinueLoop;
151  }
152  initialShowerAxis = showerrrec.GetAxis();
153  initialCore = showerrrec.GetCorePosition();
154  } else if (fUseInitialGeometry == "Reference") {
155  if (!event.GetRecShower().HasRRecShower()) {
156  WARNING("Event has no HasRRecShower. Event is skipped");
157  return eContinueLoop;
158  }
159  initialShowerAxis = event.GetRecShower().GetRRecShower().GetReferenceAxis(event);
160  initialCore = event.GetRecShower().GetRRecShower().GetReferenceCorePosition(event);
161  }
162 
163  const CoordinateSystemPtr localCS = LocalCoordinateSystem::Create(initialCore);
164  const double initialZenith = initialShowerAxis.GetTheta(localCS);
165  const double initialAzimuth = initialShowerAxis.GetPhi(localCS);
166 
167  // initiate atm + tables (which model is used is decieded in the config)
168  const double avgShowerXmax = 750*g/cm2;
169  const atm::Atmosphere& atmo = detector.GetAtmosphere();
170  atmo.InitSlantProfileModel(initialCore, initialShowerAxis, 10*g/cm2);
171  const atm::ProfileResult& distanceFromDepth = atmo.EvaluateDistanceVsSlantDepth();
172  // jep the result is negative, convention thing...
173  const double initialRadius = abs(distanceFromDepth.Y(avgShowerXmax));
174 
175  info.str("");
176  info << "Event has " << fNumberOfStations << " antennas, "
177  << "initial geometry is " << fUseInitialGeometry << "\n"
178  << "Zenith = " << initialZenith / deg << ", azimuth = "
179  << initialAzimuth / deg << ", radius = " << initialRadius / km;
180  INFOIntermediate(info);
181 
182  // absolute event time for both the test and measured times
183  // choosen as mean of all measured/test times
184  double tau0 = 0;
185  vector<StationFitData> vStationFitData;
186 
187  for (const auto& station : rEvent.SignalStationsRange()) {
188  const Vector sPos = rDetector.GetStation(station).GetPosition() - initialCore;
189  const StationRecData& sRec = station.GetRecData();
190  const double t = sRec.GetParameter(eSignalTime);
191  const double t_err = sRec.GetParameterError(eSignalTime);
192 
193  StationFitData stationFitData;
194  stationFitData.signalTime = t;
195  stationFitData.signalTimeErr = t_err;
196  stationFitData.antennaPos = sPos;
197  vStationFitData.push_back(stationFitData);
198 
199  tau0 += t;
200  }
201  tau0 /= vStationFitData.size();
202 
203  // Initalize parameters (WARNING: Take care of correct ordering)
204  // name, value, step, min, max, fixed
205  // min = max = 0 -> no limits
206  vector<Minou::ParameterDef> parameters;
207  parameters.emplace_back("radius", initialRadius, 100, 0, fRadiusMax, false);
208  parameters.emplace_back("zenith", initialZenith, 0.1, fThetaMin, fThetaMax, false);
209  parameters.emplace_back("azimuth", initialAzimuth, 0.01, 0, 0, false);
210  parameters.emplace_back("gamma", 1, 1e-3, 0, 0, true);
211 
212  // do the fit
213  SphericalFitFunction fitFunction(vStationFitData, parameters, localCS, tau0);
215  if (fInfoLevel >= eInfoIntermediate)
216  min.SetVerbose(true);
217 
218  if (min.Minimize(500)) {
219  INFOFinal("Fit falied, skipping event");
220  showerrrec.SetParameter(eFitSuccess, 0, fLockParameterStorage);
221  return eContinueLoop;
222  }
223 
224  // Redo fit if zenith above threshold allowing variation of speed of light, cf. GAP2011-92
225  // (Reconstruction of the Wave Front of Radio Signals at AERA)
226  // unphysical situations can arise when the signal is coming from directions close to the horizon
227  // not implemented yet.
228  /*
229  if (min.GetParameter(1) > fThetaVarC)
230  parameters.emplace_back("gamma", 1, 1e-4, 0.8, 1.2, false);
231  */
232 
233  // get fit results
234  const auto tmpFitResult = min.GetParameters();
235  const auto bestParameterError = min.GetParametersAndErrors();
236  const TMatrixD pcov = min.GetCovarianceMatrix();
237 
238  const double radius = bestParameterError.at(0).first;
239  const double theta = bestParameterError.at(1).first;
240  const double phi = bestParameterError.at(2).first;
241  const double gamma = bestParameterError.at(3).first;
242 
243  const double radiusErr = bestParameterError.at(0).second;
244  const double thetaErr = bestParameterError.at(1).second;
245  const double phiErr = bestParameterError.at(2).second;
246  const double gammaErr = bestParameterError.at(3).second;
247 
248  // the spherical wave fit can be performed with just 4 stations. The number of degrees
249  // of freedom is 0, though. To be able to compute chiSquare/NDF the NDF is set to 1.
250  const int ndf = max(fitFunction.GetNDF(), 1);
251  const double chi2 = fitFunction.GetChi2(tmpFitResult);
252 
253  info.str("");
254  info << "Spherical wavefront fit succesfull \n"
255  "\ttheta = " << theta / deg << " +/- " << thetaErr << "\n"
256  "\tphi = " << phi / deg << " +/- " << phiErr / deg << "\n"
257  "\tR = " << radius / km << " +/- " << radiusErr / km << "\n"
258  "\tchi2 / ndf = " << chi2 << " / " << ndf << " = " << chi2/ndf;
259  INFOFinal(info);
260 
261  // save results
262  const Vector axis(radius, theta, phi, localCS, Vector::kSpherical);
263  showerrrec.SetParameter(eShowerAxisX, axis.GetX(localCS), fLockParameterStorage);
264  showerrrec.SetParameter(eShowerAxisY, axis.GetY(localCS), fLockParameterStorage);
265  showerrrec.SetParameter(eShowerAxisZ, axis.GetZ(localCS), fLockParameterStorage);
266 
267  showerrrec.SetParameter(eGamma, gamma, fLockParameterStorage);
268  showerrrec.SetParameterError(eGamma, gammaErr, fLockParameterStorage);
269 
270  showerrrec.SetParameter(eFitSuccess, 1, fLockParameterStorage);
271  showerrrec.SetParameter(eWaveFitChi2, chi2, fLockParameterStorage);
272  showerrrec.SetParameter(eWaveFitNDF, ndf, fLockParameterStorage);
273 
274  double tempCov =
275  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(0, 0, radius, theta, phi,
276  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
277  showerrrec.SetParameterCovariance(eShowerAxisX, eShowerAxisX, tempCov, fLockParameterStorage);
278  tempCov =
279  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(1, 1, radius, theta, phi,
280  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
281  showerrrec.SetParameterCovariance(eShowerAxisY, eShowerAxisY, tempCov, fLockParameterStorage);
282  tempCov =
283  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(2, 2, radius, theta, phi,
284  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
285  showerrrec.SetParameterCovariance(eShowerAxisZ, eShowerAxisZ, tempCov, fLockParameterStorage);
286  tempCov =
287  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(0, 1, radius, theta, phi,
288  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
289  showerrrec.SetParameterCovariance(eShowerAxisX, eShowerAxisY, tempCov, fLockParameterStorage);
290  tempCov =
291  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(0, 2, radius, theta, phi,
292  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
293  showerrrec.SetParameterCovariance(eShowerAxisX, eShowerAxisZ, tempCov, fLockParameterStorage);
294  tempCov =
295  AnalyticCoordinateTransformator::GetCartesianCovarianceFromSpherical(1, 2, radius, theta, phi,
296  pcov(0,0), pcov(1,1), pcov(2,2), pcov(0,1), pcov(0,2), pcov(1,2));
297  showerrrec.SetParameterCovariance(eShowerAxisY, eShowerAxisZ, tempCov, fLockParameterStorage);
298 
299  // set time residuals and arrival direction of signal stations
300  const vector<double> timeResiduals = GetTimeResiduals(vStationFitData, axis, tau0);
301 
302  int iStation = 0;
303  for (auto& station : rEvent.SignalStationsRange()) {
304  StationRecData& sRec = station.GetRecData();
305 
306  sRec.SetParameter(eTimeResidual, timeResiduals[iStation], fLockParameterStorage);
307  sRec.SetParameterError(eTimeResidual, sRec.GetParameterError(eSignalTime), fLockParameterStorage);
308 
309  // for spherical wave use direction to point source aka axis
310  // therefore, emission point is transfered to local coordniate system of station
311  const CoordinateSystemPtr stationCS = rDetector.GetStation(station).GetLocalCoordinateSystem();
312  sRec.SetParameter(eSignalArrivalDirectionX, axis.GetX(stationCS), fLockParameterStorage);
313  sRec.SetParameter(eSignalArrivalDirectionY, axis.GetY(stationCS), fLockParameterStorage);
314  sRec.SetParameter(eSignalArrivalDirectionZ, axis.GetZ(stationCS), fLockParameterStorage);
315 
316  ++iStation;
317  }
318 
319  return eSuccess;
320  }
321 
322 
324  RdSphericalFit::Finish()
325  {
326  return eSuccess;
327  }
328 
329 }
void SetVerbose(const bool verbose)
Definition: Minou.h:234
Branch GetTopBranch() const
Definition: Branch.cc:63
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger reference system centered on the station.
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)
Point object.
Definition: Point.h:32
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 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
ShowerRecData & GetRecShower()
Interface class to access to the RD Reconstruction of a Shower.
bool HasSimShower() const
double GetParameterError(const Parameter i) const
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
vector< double > GetTimeResiduals(const vector< StationFitData > &vStationFitData, const Vector &showerAxis, const double tau0)
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
bool HasREvent() const
double GetChi2(const std::vector< double > &pars)
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
const atm::Atmosphere & GetAtmosphere() const
Definition: Detector.h:113
T Get() const
Definition: Branch.h:271
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define INFOIntermediate(y)
Definition: VModule.h:162
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
double abs(const SVector< n, T > &v)
bool HasRRecShower() const
Top of the hierarchy of the detector description interface.
Definition: Detector.h:81
const double km
constexpr double g
Definition: AugerUnits.h:200
#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
int GetNumberOfSignalStations() const
Get number of signal stations in the event.
Definition: REvent.h:209
double GetParameter(const Parameter i) const
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
constexpr double kSpeedOfLight
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 SetParameter(Parameter i, double value, bool lock=true)
Vector object.
Definition: Vector.h:30
utl::Point GetCorePosition() const
returns pointer of the position vector of the core in the reference coor system
const rdet::RDetector & GetRDetector() const
Definition: Detector.cc:143
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
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
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
bool HasSRecShower() const
void SetParameterCovariance(Parameter i1, Parameter i2, double value, bool lock=true)
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.