RdTopDownStationSelector.cc
Go to the documentation of this file.
2 
3 #include <fwk/CentralConfig.h>
4 
5 #include <det/Detector.h>
6 #include <rdet/RDetector.h>
7 
8 #include <utl/Branch.h>
9 #include <utl/RadioGeometryUtilities.h>
10 #include <utl/PhysicalConstants.h>
11 #include <utl/Vector.h>
12 #include <utl/Point.h>
13 
14 #include <evt/Event.h>
15 #include <evt/Header.h>
16 #include <evt/ShowerRecData.h>
17 #include <evt/ShowerRRecData.h>
18 
19 #include <revt/REvent.h>
20 #include <revt/Header.h>
21 #include <revt/StationConstants.h>
22 #include <revt/StationRecData.h>
23 
24 #include "TMath.h"
25 
26 
27 using namespace std;
28 using namespace fwk;
29 
30 
32 
35  {
36  utl::Branch topB = CentralConfig::GetInstance()->GetTopBranch("RdTopDownStationSelector");
37  topB.GetChild("InfoLevel").GetData(fInfoLevel);
38  topB.GetChild("maxNumberOfStations").GetData(fMaxNumberOfStations);
39  topB.GetChild("minNumberOfStations").GetData(fInitialNumberOfSignalStations);
40  topB.GetChild("stopAtFirstStation").GetData(fStopAtFirstStation);
41  topB.GetChild("chiSquareProbabilityCutValue").GetData(fChiSquareProbabilityCutValue);
42  topB.GetChild("initialSDCheck").GetData(fInitialSDCheck);
43  topB.GetChild("maxIncomingDirectionDifference").GetData(fMaxIncomingDirectionDifference);
44  topB.GetChild("additionalSystematicError").GetData(fAdditionalSystematicError);
45 
46  return eSuccess;
47  }
48 
49 
50  bool
51  ComparePair(const std::pair<int, double>& a, const std::pair<int, double>& b)
52  {
53  return a.second < b.second;
54  }
55 
56 
58  RdTopDownStationSelector::Run(evt::Event& event)
59  {
60  if (!event.HasREvent()) {
61  WARNING("No REvent");
62  return eBreakLoop;
63  }
64 
65  ostringstream info;
66  info << "RUN in iteration " << fIteration;
67  INFODebug(info);
68 
69  revt::REvent& rEvent = event.GetREvent();
70  evt::ShowerRRecData& rShower = event.GetRecShower().GetRRecShower();
71 
72  const det::Detector& detector = det::Detector::GetInstance();
73  const rdet::RDetector& rDetector = detector.GetRDetector();
74 
75  const utl::Vector showerAxis = rShower.GetReferenceAxis(event);
76  const utl::Point showerCore = rShower.GetReferenceCorePosition(event);
77 
78  const int runId = rEvent.GetHeader().GetRunNumber();
79  const int eventId = rEvent.GetHeader().GetId();
80  const string headerId = event.GetHeader().GetId();
81 
82  // check if new event comes in and reset count variables
83  if ((fCurrentRunId != runId) || (fCurrentEventId != eventId) || (fCurrentHeaderId != headerId)) {
84  fIteration = 0;
85  fCurrentRunId = runId;
86  fCurrentEventId = eventId;
87  fCurrentHeaderId = headerId;
88  fChiSquaredNDF = 1;
89  fCurrentNumberOfStations = fInitialNumberOfSignalStations;
90  INFOIntermediate("A new event comes in, setting fIteration = 0.");
91  }
92 
93  // check if last added station should stay in signal station list
94  if (fIteration > 0) {
95  if (fCurrentNumberOfStations >= 4) {
96  if (!rShower.HasParameter(revt::eFitSuccess)){
97  WARNING("Event has no eFitSuccess parameter. Since this is not the first iteration"
98  " (at least I think so) it should! This can happen if events with identical IDs are"
99  " reconstructed, e.g. using the Offline file format and <loop numTimes='>1'...");
100  }
101 
102  if (rShower.GetParameter(revt::eFitSuccess) == 0) {
103  rEvent.GetStation(fLastAddedStationId).SetRejectedReason(revt::eLargeTimeResidual);
104  info.str("");
105  info << "Wave fit was not successful with station " << fLastAddedStationId
106  << ". Station will be rejected permanently.";
107  INFOIntermediate(info);
108 
109  if (fStopAtFirstStation) {
110  return eBreakLoop;
111  }
112  } else {
113  // calculate chi2 again with additional uncertainty per station to account
114  // for model uncertainties (e.g. the true shower front is not a plane wave
115  double chi2 = 0;
116  INFODebug("calculating chi2 manually: ");
117  for (const auto& station : rEvent.SignalStationsRange()) {
118  const double timeResidual = station.GetRecData().GetParameter(revt::eTimeResidual);
119  const double timeResidualError = station.GetRecData().GetParameterError(revt::eTimeResidual);
120  const double sigma_t2 = utl::Sqr(fAdditionalSystematicError) + utl::Sqr(timeResidualError);
121  chi2 += utl::Sqr(timeResidual) / sigma_t2;
122 
123  info << "tres = " << timeResidual / utl::ns << "ns, error = "
124  << std::sqrt(sigma_t2) / utl::ns << "ns" << std::endl;
125  INFODebug(info);
126  }
127  const double ndf = max(rShower.GetParameter(revt::eWaveFitNDF), 1.);
128  const double chi2ndf = chi2 / ndf;
129  info << "chi2 = " << chi2 << "/" << ndf << " = " << chi2ndf << std::endl;
130  INFODebug(info);
131 
132  // if chi2 per ndf is considerable larger than without last added station, remove last added station
133  if ((chi2ndf > 2 * fChiSquaredNDF) && (chi2ndf > 1)) {
134  info.str("");
135  info << "This condition is not used, but for your information: Adding Station "
136  << fLastAddedStationId << " to the fit results in a chi2/ndf = " << chi2ndf
137  << ". Previously it was " << fChiSquaredNDF
138  << ". Station will be rejected permanently.";
139  INFODebug(info);
140  }
141 
142  bool rejectChi2Prob = false;
143  const double chi2prob = TMath::Prob(chi2, ndf);
144 
145  if (chi2prob < fChiSquareProbabilityCutValue) {
146  rejectChi2Prob = true;
147  info.str("");
148  info << "Adding Station " << fLastAddedStationId
149  << " to the fit results in a chi2probability = " << chi2prob
150  << ". This is smaller than the allowed probability of "
151  << fChiSquareProbabilityCutValue << ". Station will be rejected permanently.";
152  INFOIntermediate(info);
153  }
154 
155  // cut using preferred algorithm (currently chi2prob)
156  if (rejectChi2Prob) {
157  rEvent.GetStation(fLastAddedStationId).SetRejectedReason(revt::eLargeTimeResidual);
158  if (fStopAtFirstStation) {
159  return eBreakLoop;
160  }
161  } else {
162  fCurrentNumberOfStations++;
163  fChiSquaredNDF = chi2ndf;
164  info.str("");
165  info << "Adding Station " << fLastAddedStationId
166  << " does not increase chi2ndf significantly (chi2probability = " << chi2prob
167  << "). Station will be kept. In the next step " << fCurrentNumberOfStations
168  << " stations will be considered.";
169  INFOIntermediate(info);
170  }
171  }
172  } else if (fInitialSDCheck && (fCurrentNumberOfStations == 3)) {
173  // to make sure that none of the closest 3 stations is a noise pulse, we check if the
174  // incoming direction reconstructed from them roughly agrees with SD
175  if (fCurrentNumberOfStations == 3) {
176  // this variable is set to true if we find a reason to suspect that one of the stations is faulty
177  bool faultyStationPresent = false;
178  if (rShower.GetParameter(revt::eFitSuccess) == 0) {
179  faultyStationPresent = true;
180  info.str("");
181  info << "Fit was not successful, suggesting that there is something wrong with one of the 3 stations"
182  " closest to the axis. Need to investigate further...";
183  INFOIntermediate(info);
184  } else {
185  const utl::Vector referenceAxis = rShower.GetReferenceAxis(event);
186  const double dotProduct = showerAxis * referenceAxis;
187  const double angularDifference = acos(dotProduct / showerAxis.GetMag() / referenceAxis.GetMag());
188 
189  if (angularDifference > fMaxIncomingDirectionDifference) {
190  faultyStationPresent = true;
191  info.str("");
192  info << "SD and RD reconstruction differ by "
193  << fMaxIncomingDirectionDifference / utl::degree
194  << " degrees. Need to investigate further...";
195  INFOIntermediate(info);
196  }
197  }
198 
199  if (faultyStationPresent) {
200  // One of the stations if faulty. We now compare measured signal time with the expectation
201  // from SD to find out which one
202  const utl::Point& referencePosition = rShower.GetReferenceCorePosition(event);
203  const utl::Vector& referenceAxis = rShower.GetReferenceAxis(event);
204 
205  std::vector<double> expectedSignalTime;
206  std::vector<double> measuredSignalTime;
207  std::vector<int> stationIds;
208 
209  for (auto& station : rEvent.SignalStationsRange()) {
210  measuredSignalTime.push_back(station.GetRecData().GetParameter(revt::eSignalTime));
211  const int stationId = station.GetId();
212  const utl::Vector stationPosition = rDetector.GetStation(stationId).GetPosition() -
213  referencePosition;
214  expectedSignalTime.push_back(-(referenceAxis * stationPosition / utl::kSpeedOfLight));
215  stationIds.push_back(stationId);
216  }
217 
218  const double avgExpectedSignalTime = TMath::Mean(expectedSignalTime.begin(),
219  expectedSignalTime.end());
220  const double avgMeasuredSignalTime = TMath::Mean(measuredSignalTime.begin(),
221  measuredSignalTime.end());
222  int faultyStation = 0;
223  double maxTimeResidual = 0;
224  for (unsigned int i = 0; i < measuredSignalTime.size(); i++) {
225  const double timeResidual = abs(measuredSignalTime[i] - avgMeasuredSignalTime -
226  expectedSignalTime[i] + avgExpectedSignalTime);
227  if (timeResidual > maxTimeResidual) {
228  maxTimeResidual = timeResidual;
229  faultyStation = stationIds[i];
230  }
231  }
233  } else {
234  ++fCurrentNumberOfStations;
235  }
236  }
237  }
238  }
239 
240  // break loop if the maximum number of signal stations is reached
241  if (fMaxNumberOfStations < fCurrentNumberOfStations) {
242  info.str("");
243  info << "Maximum number of signal stations reached, breaking loop... ("
244  << "current number of signal stations is " << fCurrentNumberOfStations
245  << " and maximum number of stations is " << fMaxNumberOfStations << ")";
246  INFOIntermediate(info);
247  return eBreakLoop;
248  }
249 
250  // fill distances of all suitable stations into std::vector
251  // (suitable means: a signal station or a ONLY TopDown deselcted station)
252  // Here all temporarily rejected stations are reseted, so vIdDistance contains all possible signal stations
253  // (i.e. all signal stations that have not been rejected permanently)
254  // at the end of the Main() method of the module, stations get rejected temporarily again.
255  std::vector<std::pair<int, double> > vIdDistance;
256 
257  info.str("");
258  info << "List of suitable stations:";
259  for (auto& station : rEvent.StationsRange()) {
260  // select station only if it has a signal (and therefore is not rejected)
261  // or if the only rejection reason is eTopDownDeselected
262  if (station.HasSignal() || station.GetRejectedReason() == revt::eTopDownDeselected){
263  info << " " << station.GetId() << endl;
264 
265  // set all stations back to signal stations
266  // (it just removes the eTopDownDeselected status from the station)
267  station.SetSignal();
268  station.ClearRejectedReason();
269 
270  const utl::Point stationPosition = rDetector.GetStation(station).GetPosition();
271  const double distance = utl::RadioGeometryUtilities::GetDistanceToAxis(showerAxis, showerCore,
272  stationPosition);
273  vIdDistance.emplace_back(station.GetId(), distance);
274  }
275  }
276  INFODebug(info);
277  sort(vIdDistance.begin(), vIdDistance.end(), ComparePair); // sort: increasing distances to shower axis
278 
279  // break selection process if all available stations are considered
280  if (fCurrentNumberOfStations > vIdDistance.size()) {
281  info.str("");
282  info << "Number of available signal stations is " << vIdDistance.size()
283  << " and current number of used stations is " << fCurrentNumberOfStations;
284  INFOIntermediate(info);
285  INFO("All available stations are considered, breaking loop.");
286  return eBreakLoop;
287  }
288 
289  // use only the N (fCurrentNumberOfStations) nearest stations to the shower axis
290  // reject all stations temporarily but the nearest fCurrentNumberOfStations stations.
291  // (This counting variable will be increased if the added station does not decrease fit quality)
292  for (unsigned int i = fCurrentNumberOfStations; i < vIdDistance.size(); ++i) {
293  const int stationId = vIdDistance[i].first;
295  info.str("");
296  info << "station " << stationId << " is temporarily rejected (distance to shower axis = "
297  << vIdDistance[i].second / utl::m << "m)";
298  INFODebug(info);
299  }
300  fLastAddedStationId = vIdDistance[fCurrentNumberOfStations - 1].first;
301  fIteration++;
302 
303  return eSuccess;
304  }
305 
306 
308  RdTopDownStationSelector::Finish()
309  {
310  return eSuccess;
311  }
312 
313 }
Branch GetTopBranch() const
Definition: Branch.cc:63
bool HasParameter(const Parameter i) const
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...
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
Interface class to access to the RD Reconstruction of a Shower.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
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
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
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
#define INFOIntermediate(y)
Definition: VModule.h:162
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
double abs(const SVector< n, T > &v)
Header & GetHeader()
access to REvent Header
Definition: REvent.h:239
Top of the hierarchy of the detector description interface.
Definition: Detector.h:81
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)
#define INFODebug(y)
Definition: VModule.h:163
constexpr double kSpeedOfLight
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
int GetRunNumber() const
Event id in the run (Start at zero at the beginning of each run) /provided by the daq...
Definition: REvent/Header.h:22
Vector object.
Definition: Vector.h:30
utl::Vector GetReferenceAxis(const Event &event) const
Returning the referencedirection depending on the corresponding flag.
constexpr double ns
Definition: AugerUnits.h:162
const rdet::RDetector & GetRDetector() const
Definition: Detector.cc:143
double GetParameter(const Parameter i) const
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
constexpr double m
Definition: AugerUnits.h:121
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
int GetId() const
Definition: REvent/Header.h:21
bool ComparePair(const std::pair< int, double > &a, const std::pair< int, double > &b)

, generated on Tue Sep 26 2023.