ValidationTests/SdCalibration/Validatrix.cc
Go to the documentation of this file.
1 #include <fwk/VModule.h>
2 #include <sdet/Station.h>
3 #include <evt/Event.h>
4 #include <sevt/SEvent.h>
5 #include <sevt/SortCriteria.h>
6 #include <sevt/Header.h>
7 #include <sevt/Station.h>
8 #include <sevt/StationRecData.h>
9 #include <sevt/PMT.h>
10 #include <sevt/PMTCalibData.h>
11 #include <sevt/PMTRecData.h>
12 #include <utl/ErrorLogger.h>
13 #include <utl/Math.h>
14 #include <utl/SVector.h>
15 
16 #include <cmath>
17 #include <vector>
18 #include <fstream>
19 
20 using namespace evt;
21 using namespace sevt;
22 using namespace utl;
23 using namespace fwk;
24 using namespace std;
25 
26 
27 namespace utl {
28 
29  template<size_t n, typename T>
30  inline
31  double
32  abs(const SVector<n, T>& v)
33  {
34  double sum2 = 0;
35  for (unsigned int i = 0; i < n; ++i)
36  sum2 += Sqr(v[i]);
37  return sqrt(sum2);
38  }
39 
40 }
41 
42 
43 namespace Validatrix {
44 
45  template<typename T>
47  public:
48  AbsoluteDifference(const double tolerance = 0)
49  : fTolerance(tolerance) { }
50 
51  static double GetDistance(const T& x, const T& y)
52  { return abs(x - y); }
53 
54  bool IsCompatible(const T& x, const T& y) const
55  { return GetDistance(x, y) <= fTolerance; }
56 
57  private:
58  double fTolerance;
59  };
60 
61 
62  template<typename T>
64  public:
65  RelativeDifference(const double tolerance = 0)
66  : fTolerance(tolerance) { }
67 
68  static
69  double
70  GetDistance(const T& x, const T& y)
71  {
72  const double avg = 0.5 * (abs(x) + abs(y));
73  const double diff = abs(x - y);
74  return avg ? diff/avg : diff;
75  }
76 
77  bool IsCompatible(const T& x, const T& y) const
78  { return GetDistance(x, y) <= fTolerance; }
79 
80  private:
81  double fTolerance;
82  };
83 
84 
85  template<typename T, template<typename> class TolerancePolicy = AbsoluteDifference>
86  class NamedType {
87  public:
88  NamedType(const string& name,
89  const TolerancePolicy<T>& tolerance = TolerancePolicy<T>(),
90  const T& value = T())
91  : fName(name), fType(value), fTolerance(tolerance) { }
92 
93  operator T&() { return fType; }
94  operator const T&() const { return fType; }
95 
96  T& operator=(const T& t) { return fType = t; }
97 
98  bool
99  IsCompatible(const NamedType& nt, const int line = 0)
100  const
101  {
102  if (!fTolerance.IsCompatible((const T&)(fType), (const T&)(nt.fType))) {
103  ostringstream err;
104  if (line)
105  err << "In line " << line << ": ";
106  err << fName << ' '
107  << (const T&)(fType) << " not compatible with " << (const T&)(nt.fType)
108  << ", distance "
109  << fTolerance.GetDistance((const T&)(fType), (const T&)(nt.fType));
110  ERROR(err);
111  return false;
112  }
113  return true;
114  }
115 
116  private:
117  const string fName;
118  T fType;
119  const TolerancePolicy<T> fTolerance;
120  };
121 
122 
123  template<class T, template<typename> class TolerancePolicy = AbsoluteDifference>
124  class NamedClass : public T {
125  public:
126  NamedClass(const string& name,
127  const TolerancePolicy<T>& tolerance = TolerancePolicy<T>(),
128  const T& value = T())
129  : T(value), fName(name), fTolerance(tolerance) { }
130 
131  bool
132  IsCompatible(const NamedClass& nc, const int line = 0)
133  const
134  {
135  if (!fTolerance.IsCompatible((const T&)(*this), (const T&)(nc))) {
136  ostringstream err;
137  if (line)
138  err << "In line " << line << ": ";
139  err << fName << ' '
140  << (const T&)(*this) << " not compatible with " << (const T&)(nc)
141  << ", distance "
142  << fTolerance.GetDistance((const T&)(*this), (const T&)(nc));
143  ERROR(err);
144  return false;
145  }
146  return true;
147  }
148 
149  private:
150  const string fName;
151  const TolerancePolicy<T> fTolerance;
152  };
153 
154 
155  const double eps = 1e-5;
156 
157 
159  private:
161 
162  public:
164  fEventId("EventId"),
165  fStationId("StationId"),
166  fHighGainSaturation("HighGainSaturation"),
167  fLowGainSaturation("LowGainSaturation"),
168  fTriggerAlgorithm("TriggerAlgorithm"),
169  fVEMCharge("VEMCharge", RelativeDifference<SVector3>(eps), SVector3(0.)),
170  fVEMPeak("VEMPeak", RelativeDifference<SVector3>(eps), SVector3(0.)),
171  fMuonChargeSlope("MuonChargeSlope", RelativeDifference<SVector3>(eps), SVector3(0.)),
172  fMuonPulseDecayTime("MuonPulseDecayTime", RelativeDifference<SVector3>(eps), SVector3(0.)),
173  fPeakAmplitude("PeakAmplitude", RelativeDifference<SVector3>(eps), SVector3(0.)),
174  fRiseTime("RiseTime", RelativeDifference<SVector3>(eps), SVector3(0.)),
175  fFallTime("FallTime", RelativeDifference<SVector3>(eps), SVector3(0.)),
176  fT50("T50", RelativeDifference<SVector3>(eps), SVector3(0.)),
177  fTotalCharge("TotalCharge", RelativeDifference<SVector3>(eps), SVector3(0.)),
178  fAreaOverPeak("AreaOverPeak", RelativeDifference<SVector3>(eps), SVector3(0.)),
179  fStationPeakAmplitude("StationPeakAmplitude", RelativeDifference<double>(eps)),
180  fSignalStartSlot("SignalStartSlot"),
181  fSignalEndSlot("SignalEndSlot"),
182  fSignalStartTime("SignalStartTime", AbsoluteDifference<SVector<2, int>>(), SVector<2, int>(0)),
183  fTotalSignal("TotalSignal", RelativeDifference<double>(eps)),
184  fShapeParameter("ShapeParameter", RelativeDifference<double>(eps)),
185  fStationRiseTime("StationRiseTime", RelativeDifference<double>(eps)),
186  fStationFallTime("StationFallTime", RelativeDifference<double>(eps)),
187  fStationT50("StationT50", RelativeDifference<double>(eps))
188  { }
189 
190  bool
191  IsCompatible(const CalibrationDigest& calib, const int line = 0)
192  const
193  {
194  return fEventId.IsCompatible(calib.fEventId, line) &&
195  fStationId.IsCompatible(calib.fStationId, line) &&
196  fHighGainSaturation.IsCompatible(calib.fHighGainSaturation, line) &&
197  fLowGainSaturation.IsCompatible(calib.fLowGainSaturation, line) &&
198  fTriggerAlgorithm.IsCompatible(calib.fTriggerAlgorithm, line) &&
199  fVEMCharge.IsCompatible(calib.fVEMCharge, line) &&
200  fVEMPeak.IsCompatible(calib.fVEMPeak, line) &&
201  fMuonChargeSlope.IsCompatible(calib.fMuonChargeSlope, line) &&
202  fMuonPulseDecayTime.IsCompatible(calib.fMuonPulseDecayTime, line) &&
203  fPeakAmplitude.IsCompatible(calib.fPeakAmplitude, line) &&
204  fRiseTime.IsCompatible(calib.fRiseTime, line) &&
205  fFallTime.IsCompatible(calib.fFallTime, line) &&
206  fT50.IsCompatible(calib.fT50, line) &&
207  fTotalCharge.IsCompatible(calib.fTotalCharge, line) &&
208  fAreaOverPeak.IsCompatible(calib.fAreaOverPeak, line) &&
209  fStationPeakAmplitude.IsCompatible(calib.fStationPeakAmplitude, line) &&
210  fSignalStartSlot.IsCompatible(calib.fSignalStartSlot, line) &&
211  fSignalEndSlot.IsCompatible(calib.fSignalEndSlot, line) &&
212  fSignalStartTime.IsCompatible(calib.fSignalStartTime, line) &&
213  fTotalSignal.IsCompatible(calib.fTotalSignal, line) &&
214  fShapeParameter.IsCompatible(calib.fShapeParameter, line) &&
215  fStationRiseTime.IsCompatible(calib.fStationRiseTime, line) &&
216  fStationFallTime.IsCompatible(calib.fStationFallTime, line) &&
217  fStationT50.IsCompatible(calib.fStationT50, line);
218  }
219 
244  };
245 
246 
247  ostream&
248  operator<<(ostream& os, const CalibrationDigest& calib)
249  {
250  return os << calib.fEventId << ' '
251  << calib.fStationId << ' '
252  << calib.fHighGainSaturation << ' '
253  << calib.fLowGainSaturation << ' '
254  << calib.fTriggerAlgorithm << ' '
255  << (const SVector<3>&)(calib.fVEMCharge) << ' '
256  << (const SVector<3>&)(calib.fVEMPeak) << ' '
257  << (const SVector<3>&)(calib.fMuonChargeSlope) << ' '
258  << (const SVector<3>&)(calib.fMuonPulseDecayTime) << ' '
259  << (const SVector<3>&)(calib.fPeakAmplitude) << ' '
260  << (const SVector<3>&)(calib.fRiseTime) << ' '
261  << (const SVector<3>&)(calib.fFallTime) << ' '
262  << (const SVector<3>&)(calib.fT50) << ' '
263  << (const SVector<3>&)(calib.fTotalCharge) << ' '
264  << (const SVector<3>&)(calib.fAreaOverPeak) << ' '
265  << calib.fStationPeakAmplitude << ' '
266  << calib.fSignalStartSlot << ' '
267  << calib.fSignalEndSlot << ' '
268  << (const SVector<2, int>&)(calib.fSignalStartTime) << ' '
269  << calib.fTotalSignal << ' '
270  << calib.fShapeParameter << ' '
271  << calib.fStationRiseTime << ' '
272  << calib.fStationFallTime << ' '
273  << calib.fStationT50;
274  }
275 
276 
277  istream&
278  operator>>(istream& is, CalibrationDigest& calib)
279  {
280  return is >> calib.fEventId
281  >> calib.fStationId
282  >> calib.fHighGainSaturation
283  >> calib.fLowGainSaturation
284  >> calib.fTriggerAlgorithm
285  >> (SVector<3>&)(calib.fVEMCharge)
286  >> (SVector<3>&)(calib.fVEMPeak)
287  >> (SVector<3>&)(calib.fMuonChargeSlope)
288  >> (SVector<3>&)(calib.fMuonPulseDecayTime)
289  >> (SVector<3>&)(calib.fPeakAmplitude)
290  >> (SVector<3>&)(calib.fRiseTime)
291  >> (SVector<3>&)(calib.fFallTime)
292  >> (SVector<3>&)(calib.fT50)
293  >> (SVector<3>&)(calib.fTotalCharge)
294  >> (SVector<3>&)(calib.fAreaOverPeak)
295  >> calib.fStationPeakAmplitude
296  >> calib.fSignalStartSlot
297  >> calib.fSignalEndSlot
298  >> (SVector<2, int>&)(calib.fSignalStartTime)
299  >> calib.fTotalSignal
300  >> calib.fShapeParameter
301  >> calib.fStationRiseTime
302  >> calib.fStationFallTime
303  >> calib.fStationT50;
304  }
305 
306 
307  template<typename T>
308  inline
309  ostream&
310  operator<<(ostream& os, const vector<T>& vec)
311  {
312  for (const auto& v : vec)
313  os << v << '\n';
314  return os;
315  }
316 
317 
318  template<typename T>
319  istream&
320  operator>>(istream& is, vector<T>& vec)
321  {
322  int lineNo = 0;
323  istringstream lineis;
324  T t;
325  string line;
326  while (getline(is, line)) {
327  ++lineNo;
328  if (line.length() && line[0] != '#') {
329  lineis.clear();
330  lineis.str(line);
331  if (lineis >> t)
332  vec.push_back(t);
333  else if (!lineis.eof()) {
334  ostringstream err;
335  err << "Read error in line " << lineNo;
336  ERROR(err);
337  }
338  }
339  }
340  return is;
341  }
342 
343 
344  template<typename T>
345  inline
346  bool
347  IsCompatible(const vector<T>& x, const vector<T>& y)
348  {
349  if (x.size() != y.size()) {
350  ERROR("Sizes do not match!");
351  return false;
352  }
353 
354  int line = 0;
355  for (typename vector<T>::const_iterator xIt = x.begin(), yIt = y.begin();
356  xIt != x.end(); ++xIt, ++yIt)
357  if (!xIt->IsCompatible(*yIt, ++line))
358  return false;
359 
360  return true;
361  }
362 
363 
364  inline
365  ostream&
366  operator<<(ostream& os, const vector<int>& vec)
367  {
368  for (const auto v : vec)
369  os << v << '\n';
370  return os;
371  }
372 
373 
383  class Validatrix : public fwk::VModule {
384  public:
385  virtual ~Validatrix() = default;
386 
387  fwk::VModule::ResultFlag Init() override;
388  fwk::VModule::ResultFlag Run(evt::Event& event) override;
389  fwk::VModule::ResultFlag Finish() override;
390 
391  private:
392  unsigned int fLineNo = 0;
393  bool fStatus = true;
394  vector<CalibrationDigest> fReferenceValues;
395  vector<CalibrationDigest> fCurrentValues;
396 
397  // set this to 'true' to get muon histograms
398  static const bool fDumpHistograms = true;
403 
404  REGISTER_MODULE("Validatrix", Validatrix);
405  };
406 
407 
410  {
411  fLineNo = 0;
412  fStatus = true;
413  fReferenceValues.clear();
414  fCurrentValues.clear();
415 
416  const string referenceFilename = "SdCalibrationValues.ref";
417  ifstream reference(referenceFilename);
418 
419  if (!reference || !reference.is_open()) {
420  ERROR("Failed to open '" + referenceFilename + "' for reading!");
421  return eFailure;
422  }
423 
424  if (!(reference >> fReferenceValues) && reference.eof()) {
425  ostringstream info;
426  info << "Read " << fReferenceValues.size() << " reference items.";
427  INFO(info);
428  } else {
429  ERROR("Error while reading '" + referenceFilename + "'...");
430  return eFailure;
431  }
432 
433  if (fDumpHistograms) {
434  fMuonBaseHistoFile.open("MuonBaseHisto.txt");
435  fMuonChargeHistoFile.open("MuonChargeHisto.txt");
436  fMuonPeakHistoFile.open("MuonPeakHisto.txt");
437  fMuonShapeHistoFile.open("MuonShapeHisto.txt");
438  }
439 
440  return eSuccess;
441  }
442 
443 
445  Validatrix::Run(Event& event)
446  {
447  if (!event.HasSEvent())
448  return eSuccess;
449 
450  event.GetSEvent().SortStations(ByIncreasingId());
451  const auto& sEvent = event.GetSEvent();
452 
453  const int firstPMT = sdet::Station::GetFirstPMTId();
454 
455  const int eventId = sEvent.GetHeader().GetId();
456 
457  for (const auto& s : sEvent.StationsRange()) {
458  CalibrationDigest calib;
459  calib.fEventId = eventId;
460  const int sId = s.GetId();
461  calib.fStationId = sId;
462  calib.fHighGainSaturation = s.IsHighGainSaturation();
463  calib.fLowGainSaturation = s.IsLowGainSaturation();
464  for (int p = 0; p < 3; ++p) {
465  const int pmtId = p + firstPMT;
466  const auto& pmt = s.GetPMT(pmtId);
467  if (!pmt.HasCalibData() && pmt.HasRecData()) {
468  ostringstream err;
469  err << "Station " << sId << ", PMT " << pmtId << " "
470  "has PMTRecData but no PMTCalibData!";
471  ERROR(err);
472  return eFailure;
473  }
474  if (fDumpHistograms && pmt.HasCalibData()) {
475  // formatted for gnuplot "index first:last" plot flag
476  fMuonBaseHistoFile << pmt.GetCalibData().GetMuonBaseHisto() << "\n\n";
477  fMuonChargeHistoFile << pmt.GetCalibData().GetMuonChargeHisto() << "\n\n";
478  fMuonPeakHistoFile << pmt.GetCalibData().GetMuonPeakHisto() << "\n\n";
479  fMuonShapeHistoFile << pmt.GetCalibData().GetMuonShapeHisto() << "\n\n";
480  }
481  if (!pmt.HasRecData())
482  calib.fVEMCharge[p] = calib.fVEMPeak[p] = -1;
483  else {
484  const PMTRecData& pmtRec = pmt.GetRecData();
485  calib.fVEMCharge[p] = pmtRec.GetVEMCharge();
486  calib.fVEMPeak[p] = pmtRec.GetVEMPeak();
487  calib.fMuonChargeSlope[p] = pmtRec.GetMuonChargeSlope();
488  calib.fMuonPulseDecayTime[p] = pmtRec.GetMuonPulseDecayTime();
489  calib.fPeakAmplitude[p] = pmtRec.GetPeakAmplitude();
490  calib.fRiseTime[p] = pmtRec.GetRiseTime();
491  calib.fFallTime[p] = pmtRec.GetFallTime();
492  calib.fT50[p] = pmtRec.GetT50();
493  calib.fTotalCharge[p] = pmtRec.GetTotalCharge();
494  calib.fAreaOverPeak[p] = pmtRec.GetAreaOverPeak();
495  }
496  }
497  if (s.HasRecData()) {
498  const StationRecData& sRec = s.GetRecData();
499  calib.fStationPeakAmplitude = sRec.GetPeakAmplitude();
500  calib.fSignalStartSlot = sRec.GetSignalStartSlot();
501  calib.fSignalEndSlot = sRec.GetSignalEndSlot();
502  calib.fSignalStartTime[0] = sRec.GetSignalStartTime().GetGPSSecond();
503  calib.fSignalStartTime[1] = sRec.GetSignalStartTime().GetGPSNanoSecond();
504  calib.fTotalSignal = sRec.GetTotalSignal();
505  calib.fShapeParameter = sRec.GetShapeParameter();
506  calib.fStationRiseTime = sRec.GetRiseTime();
507  calib.fStationFallTime = sRec.GetFallTime();
508  calib.fStationT50 = sRec.GetT50();
509  }
510 
511  if (fStatus) {
512  if (fReferenceValues.size() <= fLineNo) {
513  ERROR("Running out of reference values!");
514  fStatus = false;
515  } else
516  fStatus = fReferenceValues.at(fLineNo).IsCompatible(calib, fLineNo+1);
517  }
518 
519  ++fLineNo;
520  fCurrentValues.push_back(calib);
521  }
522 
523  return eSuccess;
524  }
525 
526 
528  Validatrix::Finish()
529  {
530  const string currentFilename = "SdCalibrationValues.ref.new";
531  ofstream currentFile(currentFilename);
532 
533  if (!currentFile || !currentFile.is_open()) {
534  ERROR("Cannot open '" + currentFilename + "' for writing!");
535  return eFailure;
536  }
537 
538  if (!(currentFile << fCurrentValues)) {
539  ERROR("Cannot write current values to '" + currentFilename + "'!");
540  return eFailure;
541  }
542 
543  if (fReferenceValues.size() != fCurrentValues.size()) {
544  ostringstream err;
545  err << "Sizes of the current (" << fCurrentValues.size() << ") "
546  "and reference (" << fReferenceValues.size() << ") values do not agree!";
547  ERROR(err);
548  return eFailure;
549  }
550 
551  if (fDumpHistograms) {
552  fMuonBaseHistoFile.close();
553  fMuonChargeHistoFile.close();
554  fMuonPeakHistoFile.close();
555  fMuonShapeHistoFile.close();
556  }
557 
558  return fStatus ? eSuccess : eFailure;
559  }
560 
561 }
void operator>>(const Event &theEvent, IoSdEvent &rawSEvent)
Class to access station level reconstructed data.
double GetPeakAmplitude() const
Amplitude of signal Peak in VEM-Peak unit,averaged over pmts.
NamedType< double, RelativeDifference > fStationRiseTime
bool IsCompatible(const vector< T > &x, const vector< T > &y)
NamedClass< SVector3, RelativeDifference > fT50
NamedClass(const string &name, const TolerancePolicy< T > &tolerance=TolerancePolicy< T >(), const T &value=T())
double GetRiseTime() const
Rise time averaged over PMTs.
NamedType< double, RelativeDifference > fStationPeakAmplitude
constexpr T Sqr(const T &x)
NamedClass< SVector3, RelativeDifference > fMuonChargeSlope
NamedClass< SVector3, RelativeDifference > fFallTime
bool is(const double a, const double b)
Definition: testlib.cc:113
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
void Init()
Initialise the registry.
NamedType< double, RelativeDifference > fShapeParameter
double GetFallTime() const
Fall time averaged over PMTs.
bool IsCompatible(const T &x, const T &y) const
NamedClass< SVector3, RelativeDifference > fPeakAmplitude
NamedType< double, RelativeDifference > fTotalSignal
NamedClass< SVector3, RelativeDifference > fMuonPulseDecayTime
NamedType< double, RelativeDifference > fStationT50
constexpr double s
Definition: AugerUnits.h:163
class to hold reconstructed data at PMT level
Definition: PMTRecData.h:38
utl::TimeStamp GetSignalStartTime() const
Start time of the signal.
void operator<<(Event &event, const IoSdEvent &rawEvent)
grabs the data of an IoSdEvent and stores it in evt::Event
Static (small and dense) vector class.
Definition: SVector.h:33
double abs(const SVector< n, T > &v)
double GetTotalSignal() const
Total integrated signal in VEM unit, averaged over pmts.
NamedClass< SVector3, RelativeDifference > fRiseTime
unsigned int GetSignalStartSlot() const
Start time of the signal in time slots from beginning of trace.
double GetShapeParameter() const
Shape parameter averaged over PMTs.
static double GetDistance(const T &x, const T &y)
double eps
unsigned int GetSignalEndSlot() const
End time of the signal in time slots from beginning of trace.
Module interface.
Definition: VModule.h:53
#define REGISTER_MODULE(_moduleName_, _ModuleType_)
Definition: VModule.h:145
NamedClass< SVector3, RelativeDifference > fVEMPeak
bool IsCompatible(const T &x, const T &y) const
NamedType(const string &name, const TolerancePolicy< T > &tolerance=TolerancePolicy< T >(), const T &value=T())
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
static unsigned int GetFirstPMTId()
Id of first pmt in station.
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
NamedClass< SVector3, RelativeDifference > fAreaOverPeak
double GetGPSNanoSecond() const
GPS nanosecond.
Definition: TimeStamp.h:127
NamedType< double, RelativeDifference > fStationFallTime
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
bool HasSEvent() const
NamedClass< SVector3, RelativeDifference > fVEMCharge
static double GetDistance(const T &x, const T &y)
NamedClass< SVector3, RelativeDifference > fTotalCharge

, generated on Tue Sep 26 2023.