RdStationEFieldVectorCalculator.cc
Go to the documentation of this file.
2 
3 #include <fwk/CentralConfig.h>
4 #include <fwk/LocalCoordinateSystem.h>
5 
6 #include <utl/ErrorLogger.h>
7 #include <utl/Reader.h>
8 #include <utl/config.h>
9 #include <utl/AugerUnits.h>
10 #include <utl/FFTDataContainerAlgorithm.h>
11 #include <utl/RadioGeometryUtilities.h>
12 
13 #include <evt/Event.h>
14 #include <evt/ShowerRecData.h>
15 #include <evt/ShowerRRecData.h>
16 #include <evt/ShowerSimData.h>
17 
18 #include <revt/REvent.h>
19 #include <revt/Header.h>
20 #include <revt/StationRecData.h>
21 
22 #include <det/Detector.h>
23 #include <rdet/RDetector.h>
24 
25 
26 using namespace revt;
27 using namespace fwk;
28 using namespace utl;
29 using namespace std;
30 
31 
33 
36  {
37  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdStationEFieldVectorCalculator");
38 
39  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
40  topBranch.GetChild("meanEFieldVector").GetData(fMeanEFieldVector);
41  topBranch.GetChild("trace").GetData(fTrace);
42  topBranch.GetChild("peakSearch").GetData(fPeakSearch);
43  topBranch.GetChild("peakSearchWindow").GetData(fPeakSearchWindowWidth);
44  topBranch.GetChild("ChargeExcessStrength").GetData(fChargeExcessStrength);
45 
46  return eSuccess;
47  }
48 
49 
51  RdStationEFieldVectorCalculator::Run(evt::Event& event)
52  {
53  // Check if there are events at all
54  if (!event.HasREvent()) {
55  WARNING("No radio event found!");
56  return eContinueLoop;
57  }
58 
59  // check if needed reconstructed quantities exist
60  if (!event.GetRecShower().HasRRecShower()) {
61  WARNING("Event does not have RRecShower, nothing will be done!");
62  return eSuccess;
63  }
64 
65  ostringstream info;
66 
67  REvent& rEvent = event.GetREvent();
68  auto& rRecShower = event.GetRecShower().GetRRecShower();
69  const rdet::RDetector& rDetector = det::Detector::GetInstance().GetRDetector();
70 
71  const Vector showerAxis =rRecShower.GetReferenceAxis(event);
72  const Point showerCore = rRecShower.GetReferenceCorePosition(event);
73  const CoordinateSystemPtr coordinateSystem = LocalCoordinateSystem::Create(showerCore);
74  Vector magneticFieldAxis = rRecShower.GetMagneticFieldVector();
75 
76  // use magnetic field from simulations
77  if (event.HasSimShower()) {
78  INFOFinal("Using magnetic field from simulated air shower.");
79  const double magFieldAzimuth = event.GetSimShower().GetMagneticFieldAzimuth();
80  const double magFieldZenith = event.GetSimShower().GetMagneticFieldZenith();
81  magneticFieldAxis = Vector(1, magFieldZenith, magFieldAzimuth, coordinateSystem,
82  Vector::kSpherical);
83  }
84 
85  // loop through stations
86  for (auto& station : rEvent.StationsRange()) {
87  if (!station.HasRecData()) {
88  WARNING("No RecData found");
89  return eContinueLoop;
90  }
91 
92  const Point stationPosition = rDetector.GetStation(station).GetPosition();
93 
94  // Read the time trace of this station
95  // getting a local copy of the electric field data
96  const auto& efieldData = station.GetFFTDataContainer();
97  const auto& stationtrace = efieldData.GetConstTimeSeries();
98  fPeakSearchWindow = static_cast<int>(fPeakSearchWindowWidth / stationtrace.GetBinning());
99 
100  info.str("");
101  info << "PeakSearchWindow = " << fPeakSearchWindowWidth << " ns = "
102  << fPeakSearchWindow << " bins";
103  INFOIntermediate(info);
104 
105  StationRecData& recStation = station.GetRecData();
106 
107  if (!(station.GetRecData().HasParameter(ePeakAmplitudeEW)
108  && station.GetRecData().HasParameter(ePeakAmplitudeNS)
109  && station.GetRecData().HasParameter(ePeakAmplitudeV))) {
110  WARNING("ePeakAmplitude(EW,NS,V) was not set");
111  continue;
112  }
113 
114  const array<double, 3> peakAmp = {recStation.GetParameter(ePeakAmplitudeEW),
115  recStation.GetParameter(ePeakAmplitudeNS),
116  recStation.GetParameter(ePeakAmplitudeV)
117  };
118 
119  // the polarization with the maximum amplitude or the one specified in the xml
120  unsigned int maxPol = 0;
121  if (fTrace == 3) {
122  auto iteratorOfMax = max_element(peakAmp.begin(), peakAmp.end());
123  maxPol = distance(peakAmp.begin(), iteratorOfMax);
124  }
125  else {
126  maxPol = fTrace; // use polarization defined in xml
127  }
128 
129  // determine peak position of combo envelope
130  const double tPeakTimeEnvelope =
131  (recStation.GetParameter(eSignalTime) - recStation.GetParameter(eTraceStartTime));
132  const long unsigned int tPeakPos = tPeakTimeEnvelope / stationtrace.GetBinning();
133 
134  long unsigned int peakPos = 0;
135 
136  if (fPeakSearch != 0) {
137  info.str("");
138  info << "Station " << station.GetId() << ": fPeakSearch";
139  INFOIntermediate(info);
140 
141  double tMaxAmp = 0;
142  unsigned int tMaxPos = 0;
143 
144  // search for maximum before the maximum of the combo envelope
145  if (fPeakSearch == -1) {
146  for (auto i = tPeakPos; i > (tPeakPos - fPeakSearchWindow); --i) {
147  if (fabs(stationtrace[i][maxPol]) > tMaxAmp) {
148  tMaxAmp = fabs(stationtrace[i][maxPol]);
149  tMaxPos = i;
150  }
151  }
152  peakPos = tMaxPos;
153 
154  info.str("");
155  info << "Station " << station.GetId() << ": searching " << fPeakSearchWindow
156  << "ns before the maximum of the combo hilbert envelope. MaxCombo at "
157  << tPeakPos << "ns and max of polarization " << maxPol << " at " << peakPos;
158  INFOIntermediate(info);
159  }
160 
161  // search for maximum after the maximum of the combo envelope
162  if (fPeakSearch == 1) {
163  for (auto i = tPeakPos; i < (tPeakPos + fPeakSearchWindow); ++i) {
164  if (fabs(stationtrace[i][maxPol]) > tMaxAmp) {
165  tMaxAmp = fabs(stationtrace[i][maxPol]);
166  tMaxPos = i;
167  }
168  }
169  peakPos = tMaxPos;
170 
171  info.str("");
172  info << "Station " << station.GetId() << ": searching " << fPeakSearchWindow
173  << "ns after the maximum of the combo hilbert envelope. MaxCombo at "
174  << tPeakPos << "ns and max of polarization " << maxPol << " at " << peakPos;
175  INFODebug(info);
176  }
177  }
178 
179  info.str("");
180  info << "Station " << station.GetId() << ": Found peak position at " << peakPos << " = "
181  << peakPos * stationtrace.GetBinning() << "ns in polarization " << maxPol;
182  INFOIntermediate(info);
183 
184  // set electric field vector to maximum amplitudes of each efield component.
185  // This is used as first guess in the efield vector reconstruction (averaging)
186  array<double, 3> EVector = {0, 0, 0};
187  for (unsigned int iPol = 0; iPol < 3; ++iPol) {
188  EVector[iPol] = stationtrace[peakPos][iPol];
189  }
190 
191  // values are meaningless if not fMeanEFieldVector?
192  double angleToLorentzForce = 0;
193  double angleToExpectedEField = 0;
194 
195  if (fMeanEFieldVector) {
196  // Get HilbertEnvelope of Efield Traces
197  auto efieldEnvelope = station.GetFFTDataContainer();
198  FFTDataContainerAlgorithm::HilbertEnvelope(efieldEnvelope);
199  const auto& stationEnvelope = efieldEnvelope.GetConstTimeSeries();
200 
201  // determine FWHM of HilbertEnvelope
202  const double maxSignal = recStation.GetParameter(eSignal);
203  const pair<double, double> fwhm = GetFWHM(stationEnvelope, maxSignal, tPeakPos);
204 
205  const TVector3 firstGuess(EVector[0], EVector[1], EVector[2]);
206  TVector3 meanEField = GetMeanEfieldInRange(stationtrace, fwhm, firstGuess);
207 
208  const Vector vCurrentEField =
209  Normalized(Vector(meanEField.x(), meanEField.y(), meanEField.z(), coordinateSystem));
210 
211  const double meanAngleToLorentzForce =
212  RadioGeometryUtilities::GetAngleToLorentzVector(vCurrentEField, showerAxis, magneticFieldAxis);
213 
214  const double meanAngleToExpectedEField = RadioGeometryUtilities::GetAngleToEFieldExpectation(
215  vCurrentEField, showerCore, showerAxis, stationPosition, magneticFieldAxis, fChargeExcessStrength);
216 
217  // set magnitude of the mean efield vector to the maximum of the hilbert combo trace
218  meanEField.SetMag(maxSignal);
219 
220  // save mean EFieldvector
221  EVector[0] = meanEField.x();
222  EVector[1] = meanEField.y();
223  EVector[2] = meanEField.z();
224  angleToLorentzForce = NormalizeAngle(meanAngleToLorentzForce);
225  angleToExpectedEField = NormalizeAngle(meanAngleToExpectedEField);
226  }
227 
228  info.str("");
229  info << "Station " << station.GetId() << ": Calculated EFieldvector to ("
230  << EVector[0] << ", " << EVector[1] << ", " << EVector[2] << ")";
231  INFODebug(info);
232 
233  recStation.SetParameter(eEFieldVectorEW, EVector[0]);
234  recStation.SetParameter(eEFieldVectorNS, EVector[1]);
235  recStation.SetParameter(eEFieldVectorV, EVector[2]);
236 
237  const double angleToLorentzForceError =
238  GetAngleToLorentzForceError(recStation.GetParameter(eSignalToNoise));
239 
240  recStation.SetParameter(eAngleToLorentzVector, angleToLorentzForce);
241  recStation.SetParameterError(eAngleToLorentzVector, angleToLorentzForceError);
242  recStation.SetParameter(eAngleToExpectedEFieldVector, angleToExpectedEField);
243  recStation.SetParameterError(eAngleToExpectedEFieldVector, angleToLorentzForceError);
244 
245  info.str("");
246  info << "Station " << station.GetId() << ": "
247  << "Angle to Lorentz force vector " << round(angleToLorentzForce / degree * 10.) / 10.
248  << " +/- " << round(angleToLorentzForceError / degree * 10.) / 10. << " deg, "
249  << "Angle to expected eField vector " << round(angleToExpectedEField / degree * 10.) / 10.
250  << " +/- " << round(angleToLorentzForceError / degree * 10.) / 10. << " deg "
251  << "with a charge excess strength of " << fChargeExcessStrength;
252  INFOIntermediate(info);
253  }
254 
255  return eSuccess;
256  }
257 
258 
260  RdStationEFieldVectorCalculator::Finish()
261  {
262  return eSuccess;
263  }
264 
265 
266  pair<double, double>
267  RdStationEFieldVectorCalculator::GetFWHM(const StationTimeSeries& stationEnvelope, const double maxSignal,
268  const double tPeakPos)
269  {
270  ostringstream info;
271 
272  unsigned int FWHMPosLeft = 0;
273  for (auto i = tPeakPos; i > 0; --i) {
274  if (stationEnvelope[i].GetMag() < maxSignal / 2) {
275  FWHMPosLeft = i;
276  break;
277  }
278  }
279 
280  unsigned int FWHMPosRight = 0;
281  for (auto i = tPeakPos; i < stationEnvelope.GetSize(); ++i) {
282  if (stationEnvelope[i].GetMag() < maxSignal / 2) {
283  FWHMPosRight = i;
284  break;
285  }
286  }
287 
288  info.str("");
289  info << "FWHM: " << FWHMPosLeft << " = "
290  << FWHMPosLeft * stationEnvelope.GetBinning() << "ns to " << FWHMPosRight
291  << " = " << FWHMPosRight * stationEnvelope.GetBinning() << "ns";
292  INFODebug(info);
293 
294  return std::make_pair(FWHMPosLeft, FWHMPosRight);
295  }
296 
297 
298  TVector3
299  RdStationEFieldVectorCalculator::GetMeanEfieldInRange(const StationTimeSeries& stationTrace,
300  const pair<double, double>& range,
301  const TVector3& firstGuess)
302  {
303  ostringstream info;
304 
305  // waiting for cpp17
306  double FWHMPosLeft, FWHMPosRight;
307  tie(FWHMPosLeft, FWHMPosRight) = range;
308 
309  TVector3 meanEField;
310  TVector3 currentEField;
311  double sumOfWeights = 0;
312 
313  // loop through trace from FWHMPosLeft to FWHMPosRight and compute mean EFieldvector
314  for (auto i = FWHMPosLeft; i < FWHMPosRight; ++i) {
315  currentEField = TVector3(stationTrace[i][0], stationTrace[i][1], stationTrace[i][2]);
316 
317  if (currentEField.Angle(firstGuess) > 90 * degree) {
318  info.str("");
319  info << "i = " << i << " = " << i * stationTrace.GetBinning()
320  << "ns: vector flipped";
321  INFODebug(info);
322  currentEField *= -1;
323  }
324 
325  meanEField += currentEField;
326  sumOfWeights += currentEField.Mag();
327  }
328  meanEField *= 1. / sumOfWeights;
329 
330  return meanEField;
331  }
332 
333 
334  double
335  RdStationEFieldVectorCalculator::GetAngleToLorentzForceError(double snr)
336  {
337  const double sigma1 = (23.6 / sqrt(snr) - 4.3 / snr + 41.8 / pow(snr, 1.5)) * degree;
338  const double sigma2 = 1 * deg; // 1 degree alignment uncertainty
339  return sqrt(Sqr(sigma1) + Sqr(sigma2));
340  }
341 
342 
343  double
344  RdStationEFieldVectorCalculator::NormalizeAngle(const double x)
345  {
346  return (x > kPi / 2) ? kPi - x : x;
347  }
348 
349 }
350 
Branch GetTopBranch() const
Definition: Branch.cc:63
Class to access station level reconstructed data.
void SetParameterError(Parameter i, double value, bool lock=true)
const double degree
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
ShowerRecData & GetRecShower()
bool HasSimShower() const
double GetBinning() const
size of one slot
Definition: Trace.h:138
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
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
constexpr double deg
Definition: AugerUnits.h:140
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define INFOIntermediate(y)
Definition: VModule.h:162
Class representing a document branch.
Definition: Branch.h:107
constexpr double kPi
Definition: MathConstants.h:24
bool HasRRecShower() const
SizeType GetSize() const
Definition: Trace.h:156
#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
AxialVector Normalized(const AxialVector &v)
Definition: AxialVector.h:81
#define INFODebug(y)
Definition: VModule.h:163
double GetParameter(const Parameter i) const
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
Template class for a FADC data or calibrated data container. Use the typedefs (TraceD, TraceI, etc.) defined in Trace-fwd.h.
Definition: Trace-fwd.h:19
void SetParameter(Parameter i, double value, bool lock=true)
Vector object.
Definition: Vector.h:30
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

, generated on Tue Sep 26 2023.