RdStationPolarizationRejector.cc
Go to the documentation of this file.
2 
3 #include <fwk/CentralConfig.h>
4 #include <fwk/LocalCoordinateSystem.h>
5 #include <fwk/CoordinateSystemRegistry.h>
6 #include <fwk/MagneticFieldModel.h>
7 
8 #include <det/Detector.h>
9 #include <rdet/RDetector.h>
10 
11 #include <utl/Math.h>
12 #include <utl/MathConstants.h>
13 #include <utl/PhysicalConstants.h>
14 #include <utl/Vector.h>
15 #include <utl/CoordinateSystem.h>
16 #include <utl/AnalyticCoordinateTransformator.h>
17 
18 #include <evt/Event.h>
19 #include <evt/ShowerRecData.h>
20 #include <evt/ShowerRRecData.h>
21 
22 #include <revt/REvent.h>
23 #include <revt/Header.h>
24 #include <revt/Station.h>
25 #include <revt/StationRecData.h>
26 
27 #include <TMath.h>
28 #include <TVector3.h>
29 
30 using namespace std;
31 
33 
36  {
37  const auto topB = fwk::CentralConfig::GetInstance()->GetTopBranch("RdStationPolarizationRejector");
38  topB.GetChild("maxBeta").GetData(fMaxBeta);
39  topB.GetChild("constantChargeExcess").GetData(fConstantChargeExcess);
40  topB.GetChild("maxChargeExcess").GetData(fMaxChargeExcess);
41  topB.GetChild("minChargeExcess").GetData(fMinChargeExcess);
42  topB.GetChild("percentile").GetData(fProbability);
43  topB.GetChild("polStandardDeviations").GetData(fMaxSigmaBeta);
44  topB.GetChild("InfoLevel").GetData(fInfoLevel);
45  topB.GetChild("zenithCut").GetData(fZenithCut);
46  topB.GetChild("noiseErrorModel").GetData(fNoiseErrorModel);
47  SetProbability(GetProbability());
48  INFODebug("INIT POL REJECT");
49  return eSuccess;
50  }
51 
53  RdStationPolarizationRejector::Run(evt::Event& event)
54  {
55  INFODebug("RUN POL REJECT");
56  // nothing to do if event has no REvent
57  if (!event.HasREvent()) {
58  INFODebug("No REvent");
59  return eContinueLoop;
60  }
61 
62  // SD data is required
63  if (!event.HasRecShower()) {
64  if (fInfoLevel > 0) {
65  WARNING("Shower has to be reconstructed before RdStationPolarizationRejector is used... aborting");
66  }
67  return eBreakLoop;
68  }
69 
70  const det::Detector& det = det::Detector::GetInstance();
71  const rdet::RDetector& rdet = det.GetRDetector();
73  const utl::TimeStamp timeStamp = event.GetHeader().GetTime();
74 
75  revt::REvent& rEvent = event.GetREvent();
76  const evt::ShowerRRecData& rShower = event.GetRecShower().GetRRecShower();
77  const utl::Point corePosition = rShower.GetReferenceCorePosition(event);
79 
80  double covarianceMatrix[3];
81  GetCovarianceMatrix(event, covarianceMatrix, rShower, localCS);
82 
83  const utl::Vector showerAxis = rShower.GetReferenceAxis(event);
84  const double zenith = showerAxis.GetTheta(localCS);
85  const double azimuth = showerAxis.GetPhi(localCS);
86 
87  if (fZenithCut) {
88  if (!CheckZenith(zenith, azimuth)) {
89  stringstream sstr;
90  sstr << "Incoming direction zenith = " << zenith / utl::deg
91  << " azimuth = " << azimuth / utl::deg
92  << ". Direction does not allow for polarization rejection";
93  INFODebug(sstr.str());
94  return eSuccess;
95  }
96  }
97 
98  const fwk::MagneticFieldModel& magneticFieldModel = fwk::MagneticFieldModel::instance();
99  const utl::Vector magneticField = magneticFieldModel.GetMagneticFieldVector(corePosition, timeStamp);
100  const double angleToMagneticField = utl::Angle(magneticField, showerAxis);
101  utl::Point stationPosition;
102  const utl::RadioGeometryUtilities rdGeometryUtilities = utl::RadioGeometryUtilities(showerAxis, localCS,
103  magneticField);
105  ++sIt) {
106  revt::Station& station = *sIt;
107  stationPosition = rdet.GetStation(station).GetPosition();
108 
109  if (!station.HasSignal() || station.IsSaturated()) {
110  continue; // nothing to do here
111  }
112 
113  revt::StationRecData& stationRecData = station.GetRecData();
114  utl::Vector stationRecEfieldVector = utl::Vector(stationRecData.GetParameter(revt::eEFieldVectorEW),
115  stationRecData.GetParameter(revt::eEFieldVectorNS),
116  stationRecData.GetParameter(revt::eEFieldVectorV),
117  localCS);
118  double angleToEfieldExpectation = rdGeometryUtilities.GetAngleToEFieldExpectation(stationRecEfieldVector,
119  corePosition, showerAxis,
120  stationPosition,
121  magneticField, 0.14);
122  if (angleToEfieldExpectation > (utl::kPi / 2) * utl::radian) {
123  stationRecEfieldVector = -stationRecEfieldVector;
124  angleToEfieldExpectation = utl::kPi * utl::radian - angleToEfieldExpectation;
125  }
126 
127  stringstream sstr;
128  sstr.str("");
129  sstr << "Event: " << event.GetHeader().GetId() << " Station: " << station.GetId();
130  INFODebug(sstr.str());
131 
132  const double peakAmpMag = stationRecData.GetParameter(revt::ePeakAmplitudeMag);
133  const double noiseRmsMag = stationRecData.GetParameter(revt::eNoiseRmsMag);
134  const double snr = peakAmpMag * peakAmpMag / noiseRmsMag / noiseRmsMag;
135  const double distToShowerAxis = rdGeometryUtilities.GetDistanceToAxis(showerAxis, corePosition, stationPosition);
136  utl::Point semiMajorAxis, semiMinorAxis;
137  GetCoreErrorEllipse(semiMajorAxis, semiMinorAxis, corePosition, covarianceMatrix, localCS);
138 
139  sstr.str("");
140  sstr << "Covariance Matrix: [" << covarianceMatrix[0] << ", " << covarianceMatrix[1] << ", "
141  << covarianceMatrix[2] << "]"
142  << ", semi major axis: [" << semiMajorAxis.GetX(localCS) << ", " << semiMajorAxis.GetY(localCS) << "]"
143  << ", semi minor axis: [" << semiMinorAxis.GetX(localCS) << ", " << semiMinorAxis.GetY(localCS) << "]";
144  INFODebug(sstr.str());
145 
146  TVector3 semiMajorAxisvxBvxvxB, semiMinorAxisvxBvxvxB;
147  double rotationAngle;
148  GetCoreErrorEllipsevxBvxvxB(semiMajorAxisvxBvxvxB, semiMinorAxisvxBvxvxB, rotationAngle, semiMajorAxis,
149  semiMinorAxis, corePosition, rdGeometryUtilities);
150 
151  sstr.str("");
152  sstr << "semi minor axis vxb-vxvxb ["
153  << semiMajorAxisvxBvxvxB.X() << ", " << semiMajorAxisvxBvxvxB.Y() << "]"
154  << ", semi minor axis vxb-vxvxb ["
155  << semiMinorAxisvxBvxvxB.X() << ", " << semiMinorAxisvxBvxvxB.Y() << "]";
156  INFODebug(sstr.str());
157 
158  const double absSemiMajorAxisvxBvxvxB = sqrt(utl::Sqr(semiMajorAxisvxBvxvxB.X()) +
159  utl::Sqr(semiMajorAxisvxBvxvxB.Y()));
160 
161  const double maxChargeExcess = GetMaxChargeExcess(zenith, distToShowerAxis, absSemiMajorAxisvxBvxvxB);
162  const double minChargeExcess = GetMinChargeExcess(zenith, distToShowerAxis, absSemiMajorAxisvxBvxvxB);
163 
164  const TVector3 EfieldInShowerPlane = GetEfieldInShowerPlane(stationRecEfieldVector, localCS, rdGeometryUtilities);
165  const double noiseVxB = stationRecData.GetParameter(revt::eNoiseRmsVxB);
166  const double noiseVxVxB = stationRecData.GetParameter(revt::eNoiseRmsVxVxB);
167  const double polarizationUncertainty = GetPolAngleUncertainty(snr, EfieldInShowerPlane, noiseVxB, noiseVxVxB);
168 
169  sstr.str("");
170  sstr << "Angle to EField Expectation: " << angleToEfieldExpectation / utl::degree
171  << ", Angle tolerance based on uncertainty: " << fMaxSigmaBeta * polarizationUncertainty / utl::degree
172  << ", sin(alpha): " << sin(angleToMagneticField)
173  << ", Max charge excess: " << maxChargeExcess
174  << ", Min charge excess: " << minChargeExcess;
175  INFODebug(sstr.str());
176 
177  if ((angleToEfieldExpectation > fMaxBeta) && (sin(angleToMagneticField) > maxChargeExcess) &&
178  (angleToEfieldExpectation > fMaxSigmaBeta * polarizationUncertainty)) {
179  TVector3 stationPositionvxBvxvxB = GetStationPositionvxBvxvxB(stationPosition, corePosition,
180  rdGeometryUtilities);
181 
182  sstr.str("");
183  sstr << "pol reconstruction"
184  << stationPositionvxBvxvxB.X() << " station x"
185  << stationPositionvxBvxvxB.Y() << " station y";
186  INFODebug(sstr.str());
187 
188  double localPol1, localPol2;
189  GetLocalPolMaxima(localPol1, localPol2, angleToMagneticField, maxChargeExcess);
190 
191  const double measuredEfieldPol = atan2(EfieldInShowerPlane.Y(), -EfieldInShowerPlane.X());
192  if (IsStationInErrorEllipse(stationPositionvxBvxvxB, semiMajorAxisvxBvxvxB, semiMinorAxisvxBvxvxB,
193  rotationAngle)) {
194  const double maxPol = std::max(localPol1, localPol2);
195  const double minPol = std::min(localPol1, localPol2);
196 
197  sstr.str("");
198  sstr << "station inside ellipse: measured Efield-angle: " << measuredEfieldPol / utl::degree
199  << ", max Efield-angle: " << maxPol / utl::degree
200  << ", min Efield-angle: " << minPol / utl::degree;
201  INFODebug(sstr.str());
202 
203  if ((maxPol + fMaxSigmaBeta * polarizationUncertainty < measuredEfieldPol) ||
204  (minPol - fMaxSigmaBeta * polarizationUncertainty > measuredEfieldPol)) {
205  sstr.str("");
206  sstr << "rejecting station: " << station.GetId();
207  INFOFinal(sstr.str());
209  }
210  } else {
211  TVector3 tangentPoint1, tangentPoint2;
212  GetErrorEllipseTangentPoints(tangentPoint1, tangentPoint2, stationPositionvxBvxvxB, semiMajorAxisvxBvxvxB,
213  semiMinorAxisvxBvxvxB, rotationAngle);
214 
215  const double tangentPolMaxChargeExcess1 = GetTangentPol(stationPositionvxBvxvxB, tangentPoint1, maxChargeExcess,
216  angleToMagneticField);
217  const double tangentPolMinChargeExcess1 = GetTangentPol(stationPositionvxBvxvxB, tangentPoint1, minChargeExcess,
218  angleToMagneticField);
219  const double tangentPolMaxChargeExcess2 = GetTangentPol(stationPositionvxBvxvxB, tangentPoint2, maxChargeExcess,
220  angleToMagneticField);
221  const double tangentPolMinChargeExcess2 = GetTangentPol(stationPositionvxBvxvxB, tangentPoint2, minChargeExcess,
222  angleToMagneticField);
223 
224  double maxPol =
225  std::max(std::max(tangentPolMaxChargeExcess1, tangentPolMinChargeExcess1),
226  std::max(tangentPolMaxChargeExcess2, tangentPolMinChargeExcess2));
227  double minPol =
228  std::min(std::min(tangentPolMaxChargeExcess1, tangentPolMinChargeExcess1),
229  std::min(tangentPolMaxChargeExcess2, tangentPolMinChargeExcess2));
230 
231  const double ellipseTanAngle1 = atan2(tangentPoint1.Y() - stationPositionvxBvxvxB.Y(),
232  tangentPoint1.X() - stationPositionvxBvxvxB.X());
233  const double ellipseTanAngle2 = atan2(tangentPoint2.Y() - stationPositionvxBvxvxB.Y(),
234  tangentPoint2.X() - stationPositionvxBvxvxB.X());
235 
236  sstr.str("");
237  sstr << "station outside of ellipse. Tangent points: "
238  << "[" << tangentPoint1.X() << ", " << tangentPoint1.Y() << "]"
239  << ", [" << tangentPoint2.X() << ", " << tangentPoint2.Y() << "]"
240  << ", measured Efield-angle: " << measuredEfieldPol / utl::degree
241  << ", max Efield-angle: " << maxPol / utl::degree << "\n"
242  << ", min Efield-angle: " << minPol / utl::degree << "\n";
243  INFODebug(sstr.str());
244 
245  if ((std::max(ellipseTanAngle1, ellipseTanAngle2) > acos(maxChargeExcess / sin(angleToMagneticField))) &&
246  (std::min(ellipseTanAngle1, ellipseTanAngle2) < acos(maxChargeExcess / sin(angleToMagneticField)))) {
247  maxPol = std::max(maxPol, localPol1);
248  minPol = std::min(minPol, localPol1);
249  }
250 
251  if ((std::max(ellipseTanAngle1, ellipseTanAngle2) > -acos(maxChargeExcess / sin(angleToMagneticField))) &&
252  (std::min(ellipseTanAngle1, ellipseTanAngle2) < -acos(maxChargeExcess / sin(angleToMagneticField)))) {
253  maxPol = std::max(maxPol, localPol2);
254  minPol = std::min(minPol, localPol2);
255  }
256 
257  if ((maxPol + fMaxSigmaBeta * polarizationUncertainty < measuredEfieldPol) ||
258  (minPol - fMaxSigmaBeta * polarizationUncertainty > measuredEfieldPol)) {
259  sstr.str("");
260  sstr << "rejecting station: " << station.GetId();
261  INFOFinal(sstr.str());
263  }
264  }
265  }
266  }
267 
268  return eSuccess;
269  }
270 
271  /* Returns maximum acceptable charge excess based on zenith and distance to shower axis
272  if constantChargeExcess is set to true in steering file, the value specified there is returned */
273  double
274  RdStationPolarizationRejector::GetMaxChargeExcess(const double zenith,
275  const double distToAxis,
276  const double semiMajorAxisLength)
277  {
278  if (fConstantChargeExcess) {
279  return fMaxChargeExcess;
280  } else {
281  int minIndex = 0;
282  int maxIndex = 0;
283  double minDistToAxis = distToAxis - semiMajorAxisLength;
284  double maxDistToAxis = distToAxis + semiMajorAxisLength;
285  while (minDistToAxis > 12.5) {
286  minIndex++;
287  minDistToAxis = minDistToAxis - 25.0;
288  }
289 
290  while (maxDistToAxis > 12.5) {
291  maxIndex++;
292  maxDistToAxis = maxDistToAxis - 25.0;
293  }
294 
295  double maxChargeExcess = 0;
296  double currentChargeExcess;
297  while (minIndex <= maxIndex) {
298  if (zenith / utl::degree < 35.0) {
299  currentChargeExcess = fMaxChargeExcess30[minIndex];
300  } else if (zenith / utl::degree < 45.0) {
301  currentChargeExcess = fMaxChargeExcess40[minIndex];
302  } else if (zenith / utl::degree < 55.0) {
303  currentChargeExcess = fMaxChargeExcess50[minIndex];
304  } else if (zenith / utl::degree < 65.0) {
305  currentChargeExcess = fMaxChargeExcess60[minIndex];
306  } else {
307  return 0.25;
308  }
309 
310  if (currentChargeExcess > maxChargeExcess) {
311  maxChargeExcess = currentChargeExcess;
312  }
313 
314  minIndex++;
315  }
316 
317  return maxChargeExcess;
318  }
319  }
320 
321  // Behaves the same way as GetMaxChargeExcess but return the minimum acceptable charge excess
322  double
323  RdStationPolarizationRejector::GetMinChargeExcess(const double zenith,
324  const double distToAxis,
325  const double semiMajorAxisLength)
326  {
327  if (fConstantChargeExcess) {
328  return fMinChargeExcess;
329  } else {
330  int minIndex = 0;
331  int maxIndex = 0;
332  double minDistToAxis = distToAxis - semiMajorAxisLength;
333  double maxDistToAxis = distToAxis + semiMajorAxisLength;
334  while (minDistToAxis > 12.5) {
335  minIndex++;
336  minDistToAxis = minDistToAxis - 25.0;
337  }
338 
339  while (maxDistToAxis > 12.5) {
340  maxIndex++;
341  maxDistToAxis = maxDistToAxis - 25.0;
342  }
343 
344  double minChargeExcess = 1;
345  double currentChargeExcess;
346  while (minIndex <= maxIndex) {
347  if (zenith / utl::degree < 35.0) {
348  currentChargeExcess = fMinChargeExcess30[minIndex];
349  } else if (zenith / utl::degree < 45.0) {
350  currentChargeExcess = fMinChargeExcess40[minIndex];
351  } else if (zenith / utl::degree < 55.0) {
352  currentChargeExcess = fMinChargeExcess50[minIndex];
353  } else if (zenith / utl::degree < 65.0) {
354  currentChargeExcess = fMinChargeExcess60[minIndex];
355  } else {
356  return 0;
357  }
358 
359  if (currentChargeExcess < minChargeExcess) {
360  minChargeExcess = currentChargeExcess;
361  }
362 
363  minIndex++;
364  }
365 
366  return minChargeExcess;
367  }
368  }
369 
370  /* Checks if zenith and azimuth are within a range where polarization rejection works relaibly.
371  Returns true is pol. rejection can be performed and false otherwise */
372  bool
373  RdStationPolarizationRejector::CheckZenith(const double zenith, double azimuth)
374  {
375  int azimuth_index = 0;
376  if (azimuth < 0) {
377  azimuth = azimuth + 360. * utl::degree;
378  }
379 
380  while (azimuth > 30 * utl::degree) {
381  azimuth_index++;
382  azimuth -= 30. * utl::degree;
383  }
384 
385  if (fMaxZenith[azimuth_index] > zenith) {
386  return true;
387  } else {
388  return false;
389  }
390  }
391 
392  /* Sets the covariance matrix of the SD core position uncertainty. However,
393  since the two non-diagonal entries are equal, only one of them is saved */
394  void
395  RdStationPolarizationRejector::GetCovarianceMatrix(const evt::Event& event,
396  double covarianceMatrix[3],
397  const evt::ShowerRRecData& rShower,
398  const utl::CoordinateSystemPtr& cs)
399  {
400  const utl::Vector coreError = rShower.GetReferenceCoreError(event);
401  const double correlation = rShower.GetReferenceCoreErrorCorrelationXY(event);
402  const double sigmaX = coreError.GetX(cs);
403  const double sigmaY = coreError.GetY(cs);
404  covarianceMatrix[0] = sigmaX * sigmaX;
405  covarianceMatrix[1] = sigmaX * sigmaY * correlation;
406  covarianceMatrix[2] = sigmaY * sigmaY;
407  }
408 
409  void
410  RdStationPolarizationRejector::SetProbability(const double prob)
411  {
412  fProbability = prob;
413  fChiSquared = TMath::ChisquareQuantile(prob, 2);
414  }
415 
416  /* Returns the end points of the semi major and semi minor axis of the error ellipse of the SD core position
417  Both axes are calculated relative to the a priori SD core position */
418  void
419  RdStationPolarizationRejector::GetCoreErrorEllipse(utl::Point& semiMajorAxis,
420  utl::Point& semiMinorAxis,
421  const utl::Point& corePosition,
422  const double covarianceMatrix[3],
423  const utl::CoordinateSystemPtr& cs)
424  {
425  double coreErrorEllipseSemiMajorAxis[2];
426  double coreErrorEllipseSemiMinorAxis[2];
427  if (covarianceMatrix[1] == 0) {
428  if (abs(covarianceMatrix[0]) > abs(covarianceMatrix[2])) {
429  coreErrorEllipseSemiMajorAxis[0] = sqrt(covarianceMatrix[0] * fChiSquared);
430  coreErrorEllipseSemiMajorAxis[1] = 0;
431  coreErrorEllipseSemiMinorAxis[0] = 0;
432  coreErrorEllipseSemiMinorAxis[1] = sqrt(covarianceMatrix[2] * fChiSquared);
433  } else {
434  coreErrorEllipseSemiMinorAxis[0] = sqrt(covarianceMatrix[0] * fChiSquared);
435  coreErrorEllipseSemiMinorAxis[1] = 0;
436  coreErrorEllipseSemiMajorAxis[0] = 0;
437  coreErrorEllipseSemiMajorAxis[1] = sqrt(covarianceMatrix[2] * fChiSquared);
438  }
439  } else {
440  double trace = covarianceMatrix[0] + covarianceMatrix[2];
441  double determinant = covarianceMatrix[0] * covarianceMatrix[2] - covarianceMatrix[1] * covarianceMatrix[1];
442  double eigenValue1 = trace / 2 + sqrt(trace * trace / 4 - determinant);
443  double eigenValue2 = trace / 2 - sqrt(trace * trace / 4 - determinant);
444  if (abs(eigenValue1) > abs(eigenValue2)) {
445  double eigenVector1Norm = sqrt(
446  (eigenValue1 - covarianceMatrix[2]) * (eigenValue1 - covarianceMatrix[2]) + covarianceMatrix[1] *
447  covarianceMatrix[1]);
448  coreErrorEllipseSemiMajorAxis[0] = sqrt(eigenValue1 * fChiSquared) * (eigenValue1 - covarianceMatrix[2]) /
449  eigenVector1Norm;
450  coreErrorEllipseSemiMajorAxis[1] = sqrt(eigenValue1 * fChiSquared) * covarianceMatrix[1] / eigenVector1Norm;
451  double eigenVector2Norm = sqrt(
452  (eigenValue2 - covarianceMatrix[2]) * (eigenValue2 - covarianceMatrix[2]) + covarianceMatrix[1] *
453  covarianceMatrix[1]);
454  coreErrorEllipseSemiMinorAxis[0] = sqrt(eigenValue2 * fChiSquared) * (eigenValue2 - covarianceMatrix[2]) /
455  eigenVector2Norm;
456  coreErrorEllipseSemiMinorAxis[1] = sqrt(eigenValue2 * fChiSquared) * covarianceMatrix[1] / eigenVector2Norm;
457  } else {
458  double eigenVector1Norm = sqrt(
459  (eigenValue1 - covarianceMatrix[2]) * (eigenValue1 - covarianceMatrix[2]) + covarianceMatrix[1] *
460  covarianceMatrix[1]);
461  coreErrorEllipseSemiMinorAxis[0] = sqrt(eigenValue1 * fChiSquared) * (eigenValue1 - covarianceMatrix[2]) /
462  eigenVector1Norm;
463  coreErrorEllipseSemiMinorAxis[1] = sqrt(eigenValue1 * fChiSquared) * covarianceMatrix[1] / eigenVector1Norm;
464  double eigenVector2Norm = sqrt(
465  (eigenValue2 - covarianceMatrix[2]) * (eigenValue2 - covarianceMatrix[2]) + covarianceMatrix[1] *
466  covarianceMatrix[1]);
467  coreErrorEllipseSemiMajorAxis[0] = sqrt(eigenValue2 * fChiSquared) * (eigenValue2 - covarianceMatrix[2]) /
468  eigenVector2Norm;
469  coreErrorEllipseSemiMajorAxis[1] = sqrt(eigenValue2 * fChiSquared) * covarianceMatrix[1] / eigenVector2Norm;
470  }
471  }
472 
473  semiMajorAxis = utl::Point(coreErrorEllipseSemiMajorAxis[0] + corePosition.GetX(
474  cs), coreErrorEllipseSemiMajorAxis[1] + corePosition.GetY(cs), corePosition.GetZ(
475  cs), cs);
476  semiMinorAxis = utl::Point(coreErrorEllipseSemiMinorAxis[0] + corePosition.GetX(
477  cs), coreErrorEllipseSemiMinorAxis[1] + corePosition.GetY(cs), corePosition.GetZ(
478  cs), cs);
479  }
480 
481  /* Transforms the SD core position error ellipse into the vxB-vxvxB-system and projects it onto the shower plane
482  Returns the semi major and semi minor axis of the resulting ellipse */
483  void
484  RdStationPolarizationRejector::GetCoreErrorEllipsevxBvxvxB(TVector3& semiMajorAxisvxBvxvxB,
485  TVector3& semiMinorAxisvxBvxvxB,
486  double& rotationAngleInVxB,
487  const utl::Point& semiMajorAxis,
488  const utl::Point& semiMinorAxis,
489  const utl::Point& corePosition,
490  const utl::RadioGeometryUtilities& rdGeometryUtilities)
491  {
492  double ax, ay, az;
493  double bx, by, bz;
494  double coreX, coreY, coreZ;
495 
496  rdGeometryUtilities.GetVectorInShowerPlaneVxB(ax, ay, az, semiMajorAxis);
497  rdGeometryUtilities.GetVectorInShowerPlaneVxB(bx, by, bz, semiMinorAxis);
498  rdGeometryUtilities.GetVectorInShowerPlaneVxB(coreX, coreY, coreZ, corePosition);
499 
500  ax = ax - coreX;
501  ay = ay - coreY;
502  az = az - coreZ;
503  bx = bx - coreX;
504  by = by - coreY;
505  bz = bz - coreZ;
506 
507  double aDotB = ax * bx + ay * by;
508  if (aDotB == 0) {
509  if (ax * ax + ay * ay > bx * bx + by * by) {
510  semiMajorAxisvxBvxvxB = TVector3(ax, ay, 0);
511  semiMinorAxisvxBvxvxB = TVector3(bx, by, 0);
512  } else {
513  semiMinorAxisvxBvxvxB = TVector3(ax, ay, 0);
514  semiMajorAxisvxBvxvxB = TVector3(bx, by, 0);
515  }
516  } else {
517  const double aSquared = ax * ax + ay * ay;
518  const double bSquared = bx * bx + by * by;
519  const double tanPhi1 = -0.5 * (aSquared - bSquared) / aDotB +
520  sqrt(0.25 * ((aSquared - bSquared) * (aSquared - bSquared) / aDotB / aDotB) + 1);
521  const double tanPhi2 = -0.5 * (aSquared - bSquared) / aDotB -
522  sqrt(0.25 * ((aSquared - bSquared) * (aSquared - bSquared) / aDotB / aDotB) + 1);
523  const double phi1 = atan(tanPhi1);
524  const double phi2 = atan(tanPhi2);
525  const TVector3 axis1 = TVector3(ax * cos(phi1) + bx * sin(phi1), ay * cos(phi1) + by * sin(phi1), 0);
526  const TVector3 axis2 = TVector3(ax * cos(phi2) + bx * sin(phi2), ay * cos(phi2) + by * sin(phi2), 0);
527  if (axis1.X() * axis1.X() + axis1.Y() * axis1.Y() > axis2.X() * axis2.X() + axis2.Y() * axis2.Y()) {
528  semiMajorAxisvxBvxvxB = axis1;
529  semiMinorAxisvxBvxvxB = axis2;
530  rotationAngleInVxB = atan2(axis1.Y(), axis1.X());
531  } else {
532  semiMajorAxisvxBvxvxB = axis2;
533  semiMinorAxisvxBvxvxB = axis1;
534  rotationAngleInVxB = atan2(axis2.Y(), axis2.X());
535  }
536 
537  if (rotationAngleInVxB > utl::kPi / 2.0) {
538  rotationAngleInVxB = rotationAngleInVxB - utl::kPi;
539  } else if (rotationAngleInVxB < -utl::kPi / 2.0) {
540  rotationAngleInVxB = rotationAngleInVxB + utl::kPi;
541  }
542  }
543  }
544 
545  TVector3
546  RdStationPolarizationRejector::GetStationPositionvxBvxvxB(const utl::Point stationPosition,
547  const utl::Point& corePosition,
548  const utl::RadioGeometryUtilities& rdGeometryUtilities)
549  {
550  double x, y, z;
551  double coreX, coreY, coreZ;
552  rdGeometryUtilities.GetVectorInShowerPlaneVxB(x, y, z, stationPosition);
553  rdGeometryUtilities.GetVectorInShowerPlaneVxB(coreX, coreY, coreZ, corePosition);
554  x = x - coreX;
555  y = y - coreY;
556  z = z - coreZ;
557  return TVector3(x, y, z);
558  }
559 
560  bool
561  RdStationPolarizationRejector::IsStationInErrorEllipse(const TVector3& stationPositionvxBvxvxB,
562  const TVector3& semiMajorAxisVxB,
563  const TVector3& semiMinorAxisVxB,
564  const double rotationAngle)
565  {
566  TVector3 rotatedPosition = stationPositionvxBvxvxB;
567  rotatedPosition.RotateZ(-rotationAngle);
568  const double xStation = rotatedPosition.X();
569  const double yStation = rotatedPosition.Y();
570  if (xStation * xStation /
571  (semiMajorAxisVxB.X() * semiMajorAxisVxB.X() + semiMajorAxisVxB.Y() * semiMajorAxisVxB.Y()) + yStation *
572  yStation /
573  (semiMinorAxisVxB.X() * semiMinorAxisVxB.X() + semiMinorAxisVxB.Y() * semiMinorAxisVxB.Y()) > 1) {
574  return false;
575  } else {
576  return true;
577  }
578  }
579 
580  /* Returns the coordinates of the points where tangents of the ellipse that go through the point
581  statuibPositionvxBvxvxB touch the ellipse */
582  void
583  RdStationPolarizationRejector::GetErrorEllipseTangentPoints(TVector3& ellipseTangentPoint1,
584  TVector3& ellipseTangentPoint2,
585  const TVector3& stationPositionvxBvxvxB,
586  const TVector3& semiMajorAxisVxB,
587  const TVector3& semiMinorAxisVxB,
588  const double rotationAngle)
589  {
590  TVector3 rotatedStationPosition = stationPositionvxBvxvxB;
591  rotatedStationPosition.RotateZ(-rotationAngle);
592  const double semiMajorAxisLength2 = semiMajorAxisVxB.X() * semiMajorAxisVxB.X() + semiMajorAxisVxB.Y() *
593  semiMajorAxisVxB.Y();
594  const double semiMinorAxisLength2 = semiMinorAxisVxB.X() * semiMinorAxisVxB.X() + semiMinorAxisVxB.Y() *
595  semiMinorAxisVxB.Y();
596  const double divisor = rotatedStationPosition.Y() * rotatedStationPosition.Y() * semiMajorAxisLength2 +
597  rotatedStationPosition.X() * rotatedStationPosition.X() * semiMinorAxisLength2;
598  const double squareRootTerm = pow(
599  semiMinorAxisLength2 * semiMajorAxisLength2 * rotatedStationPosition.X() / divisor,
600  2) +
601  (pow(rotatedStationPosition.Y() * semiMajorAxisLength2,
602  2) - pow(semiMajorAxisLength2, 2) * semiMinorAxisLength2) / divisor;
603  const double x1 = semiMinorAxisLength2 * rotatedStationPosition.X() / divisor + sqrt(squareRootTerm);
604  const double x2 = semiMinorAxisLength2 * rotatedStationPosition.X() / divisor - sqrt(squareRootTerm);
605  const double y1 = semiMinorAxisLength2 / rotatedStationPosition.Y() - semiMinorAxisLength2 / semiMajorAxisLength2 *
606  x1 * rotatedStationPosition.X() / rotatedStationPosition.Y();
607  const double y2 = semiMinorAxisLength2 / rotatedStationPosition.Y() - semiMinorAxisLength2 / semiMajorAxisLength2 *
608  x2 * rotatedStationPosition.X() / rotatedStationPosition.Y();
609  ellipseTangentPoint1 = TVector3(x1, y1, 0);
610  ellipseTangentPoint1.RotateZ(rotationAngle);
611  ellipseTangentPoint2 = TVector3(x2, y2, 0);
612  ellipseTangentPoint2.RotateZ(rotationAngle);
613  }
614 
615  /* Returns the polar angles the most extreme polarization directions possible
616  if the station is inside the SD core error ellipse */
617  void
618  RdStationPolarizationRejector::GetLocalPolMaxima(double& pol1,
619  double& pol2,
620  const double angleToMagneticField,
621  double maxChargeExcess)
622  {
623  const double phi = acos(maxChargeExcess / sin(angleToMagneticField));
624  pol1 = atan2(maxChargeExcess * sin(phi), -maxChargeExcess * cos(phi) + sin(angleToMagneticField));
625  pol2 = atan2(-maxChargeExcess * sin(phi), -maxChargeExcess * cos(phi) + sin(angleToMagneticField));
626  }
627 
628  /* Returns the polar angle that the station at stationPosition vxBvxvxB would
629  measure if the SD core was at tangent point */
630  double
631  RdStationPolarizationRejector::GetTangentPol(const TVector3& stationPositionvxBvxvxB,
632  const TVector3& tangentPoint,
633  const double chargeExcess,
634  const double angleToMagneticField)
635  {
636  const TVector3 diff = TVector3(stationPositionvxBvxvxB.X() - tangentPoint.X(),
637  stationPositionvxBvxvxB.Y() - tangentPoint.Y(), 0);
638  const double absDiff = sqrt(diff.X() * diff.X() + diff.Y() * diff.Y());
639  TVector3 EFieldGeomagnetic = TVector3(-sin(angleToMagneticField), 0, 0);
640  TVector3 EFieldChargeExcess = TVector3(-chargeExcess * diff.X() / absDiff, -chargeExcess * diff.Y() / absDiff, 0);
641  TVector3 EField = EFieldGeomagnetic + EFieldChargeExcess;
642  return atan2(EField.Y(), -EField.X());
643  }
644 
645  TVector3
646  RdStationPolarizationRejector::GetEfieldInShowerPlane(const utl::Vector& efield,
647  const utl::CoordinateSystemPtr& cs,
648  const utl::RadioGeometryUtilities& rdGeometryUtilities)
649  {
650  const utl::Point stationRecEfieldVector = utl::Point(efield.GetX(cs), efield.GetY(cs), efield.GetZ(cs), cs);
651  double x;
652  double y;
653  double z;
654  rdGeometryUtilities.GetVectorInShowerPlaneVxB(x, y, z, stationRecEfieldVector);
655  return TVector3(x, y, z);
656  }
657 
658  // Returns the uncertainty of the measured polarization angle based on the signal-to-noise-ratio
659  double
660  RdStationPolarizationRejector::GetPolAngleUncertainty(const double signalToNoise,
661  const TVector3 efield,
662  const double noiseVxB,
663  const double noiseVxVxB)
664  {
665  if (fNoiseErrorModel) {
666  std::stringstream sstr;
667  sstr << "EField is [" << efield[0] << ", " << efield[1] << "]. vxB noise RMS is " << noiseVxB
668  << ", vxvxB noise RMS is " << noiseVxVxB << ".";
669  INFODebug(sstr.str());
670  double vxBError = (13.89 / pow(10., 6) + .594 * noiseVxB) * efield[1] / efield.Mag() / efield.Mag();
671  double vxvxBError = (21.14 / pow(10., 6) + .487 * noiseVxVxB) * efield[0] / efield.Mag() / efield.Mag();
672  return std::sqrt(vxBError * vxBError + vxvxBError * vxvxBError + (1. * utl::degree) * (1. * utl::degree));
673  } else {
674  const double sigma1 = (23.6 / sqrt(signalToNoise) - 4.3 / signalToNoise + 41.8 / pow(signalToNoise, 1.5)) * utl::degree;
675  const double sigma2 = 1 * utl::deg; // 1 degree alignment uncertainty
676  return sqrt(sigma1 * sigma1 + sigma2 * sigma2);
677  }
678  }
679 
681  RdStationPolarizationRejector::Finish()
682  {
683  return eSuccess;
684  }
685 
686 }
Class to access station level reconstructed data.
utl::Point GetReferenceCorePosition(const Event &event) const
Returning the reference core position depending on the corresponding flag.
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
static double GetDistanceToAxis(const utl::Vector &ShowerAxis, const utl::Point &CorePosition, const utl::Point &AntennaPosition)
computes the distance from the antenna position to the shower &quot;line&quot; defined by the core position and...
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
StationRecData & GetRecData()
Get station level reconstructed data.
bool HasRecShower() 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
Interface class to access to the RD Reconstruction of a Shower.
constexpr double radian
Definition: AugerUnits.h:130
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
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...
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
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 max(a, b)
class to hold data at the radio Station level.
static double GetAngleToEFieldExpectation(const utl::Vector &measuredEField, const utl::Point &core, const utl::Vector &showeraxis, const utl::Point &stationPosition, const utl::Vector &vMagField, const double chargeExcessStrength)
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
constexpr double kPi
Definition: MathConstants.h:24
static MagneticFieldModel & instance()
double abs(const SVector< n, T > &v)
Top of the hierarchy of the detector description interface.
Definition: Detector.h:81
bool IsSaturated() const
static utl::Vector GetMagneticFieldVector(const utl::Point &position, const utl::TimeStamp &time)
returns the magnetic field at a specific place at a specific time
constexpr double degree
#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
void SetRejectedReason(const unsigned long long int reason)
int GetId() const
Get the station Id.
#define INFODebug(y)
Definition: VModule.h:163
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
Definition: BasicVector.h:209
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
utl::CoordinateSystemPtr GetReferenceCoordinateSystem() const
Get the reference coordinate system used for analysis (usually PampaAmarilla for Auger) ...
Definition: Detector.h:141
double Angle(const Vector &left, const Vector &right)
Definition: OperationsVV.h:82
Vector object.
Definition: Vector.h:30
Get the magnetic field of the earth dependent on location and time.
utl::Vector GetReferenceAxis(const Event &event) const
Returning the referencedirection depending on the corresponding flag.
const rdet::RDetector & GetRDetector() const
Definition: Detector.cc:143
SignalStationIterator SignalStationsEnd()
Definition: REvent.h:114
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
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
boost::filter_iterator< SignalStationFilter, AllStationIterator > SignalStationIterator
Iterator over all signal stations.
Definition: REvent.h:109
bool HasSignal() const
SignalStationIterator SignalStationsBegin()
Definition: REvent.h:112

, generated on Tue Sep 26 2023.