SdGainRatioCorrector.cc
Go to the documentation of this file.
1 #include "SdGainRatioCorrector.h"
2 #include <evt/Event.h>
3 #include <sevt/SEvent.h>
4 #include <fwk/CentralConfig.h>
5 #include <sdet/SDetector.h>
6 #include <utl/ErrorLogger.h>
7 #include <utl/zfstream.h>
8 #include <utl/split.h>
9 #include <utl/Branch.h>
10 #include <utl/LineStringTo.h>
11 #include <utl/UTCDateTime.h>
12 #include <utl/Accumulator.h>
13 #include <utl/Is.h>
14 #include <boost/range/istream_range.hpp>
15 
16 using utl::Is;
17 
18 
19 namespace SdGainRatioCorrectorKG {
20 
37 
38  public:
39  unsigned int fStationId = 0;
40  unsigned int fPmtId = 0;
41  unsigned int fYear = 0;
42  // for gain-ratio R = S_LG/S_HG these are stats on R for HG_max > 800
43  double fMedian = 0;
44  double fMean = 0;
45  double fStd = 0;
46  unsigned int fN = 0;
47  // for HG_max > 650 a fit is made with R = slope*(HG_max - 1023) + offset
48  double fSlope = 0;
49  double fSlopeError = -1;
50  double fOffset = 0;
51  double fOffsetError = -1;
52  unsigned int fNFit = 0;
53 
54  explicit operator bool() const
55  { return fStationId && fPmtId && fYear; }
56 
57  double
58  GetObservedGainRatio()
59  const
60  {
61  if (!*this)
62  return 0;
63  // these are currently the effective quality-selection criteria on the yearly data
64  {
65  const double minMe = 0.8;
66  const double maxMe = 1.2;
67  {
68  // use median of HG_max > 800 if good enough
69  const unsigned int minN = 5;
70  const unsigned int maxN = 35;
71  const double maxStd = 0.18;
72  const double maxMeDiff = 0.085;
73  if (Is(fN).InRange(minN, maxN) &&
74  Is(fMedian).InRange(minMe, maxMe) &&
75  Is(fMean).InRange(minMe, maxMe) &&
76  std::abs(fMedian - fMean) < maxMeDiff &&
77  Is(fStd).InRange(0, maxStd)) {
78  return fMedian;
79  }
80  }
81  // use fit of HG_max > 650 if good enough
82  const unsigned int minNFit = 10;
83  const unsigned int maxNFit = 50;
84  const double maxSlope = 0.4/373; // 373 = 1023 - 650
85  const double maxSlopeError = 0.5*maxSlope;
86  const double maxOffsetError = 0.4;
87  if (Is(fNFit).InRange(minNFit, maxNFit) &&
88  std::abs(fSlope) <= maxSlope &&
89  Is(fSlopeError).InRange(0, maxSlopeError) &&
90  Is(fOffsetError).InRange(0, maxOffsetError) &&
91  Is(fOffset).InRange(minMe, maxMe)) {
92  return fOffset;
93  }
94  }
95  {
96  // relaxed cut if everything agrees
97  const double minMe = 0.5;
98  const double maxMe = 1.5;
99  const unsigned int minN = 5;
100  const unsigned int maxN = 50;
101  const double maxSlope = 0.1/373;
102  const double maxStd = 0.03;
103  if (Is(fN).InRange(minN, maxN) &&
104  Is(fNFit).InRange(2*minN, maxN) &&
105  std::abs(fSlope) <= maxSlope) {
107  std(fMedian);
108  std(fMean);
109  std(fOffset);
110  const double sigma = std.GetStandardDeviation();
111  const double mean = std.GetAverage();
112  if (sigma <= maxStd && Is(mean).InRange(minMe, maxMe))
113  return mean;
114  }
115  }
116  return 0;
117  }
118 
119  friend
120  std::istream&
122  {
123  return
124  is >> std::ws >> c.fStationId
125  >> std::ws >> c.fPmtId
126  >> std::ws >> c.fYear
127  >> std::ws >> c.fMedian
128  >> std::ws >> c.fMean
129  >> std::ws >> c.fStd
130  >> std::ws >> c.fN
131  >> std::ws >> c.fSlope
132  >> std::ws >> c.fSlopeError
133  >> std::ws >> c.fOffset
134  >> std::ws >> c.fOffsetError
135  >> std::ws >> c.fNFit;
136  }
137 
138  };
139 
140 
141  bool
142  IsCommentOrEmpty(const std::string& line)
143  {
144  const auto i = line.find_first_not_of(" \t");
145  return i == std::string::npos || line[i] == '#';
146  }
147 
148 
149  template<std::size_t n>
150  inline
151  bool
153  {
154  for (std::size_t i = 0; i < n; ++i)
155  if (!c[i])
156  return false;
157  return true;
158  }
159 
160 
163  {
164  auto topB = fwk::CentralConfig::GetInstance()->GetTopBranch("SdGainRatioCorrector");
165 
166  topB.GetChild("calibrationVersion12GainFactor").GetData(fCalibrationVersion12GainFactor);
167 
168  topB.GetChild("useGainRatioCorrections").GetData(fUseGainRatioCorrections);
169 
171  return eSuccess;
172 
173  const auto filename = topB.GetChild("gainRatioCorrectionsFile").Get<std::string>();
175  if (!ifs.is_open()) {
176  std::ostringstream err;
177  err << "Cannot open file '" << filename;
178  ERROR(err);
179  return eFailure;
180  }
181 
182  for (const GainRatioCorrectionLine& gc :
183  boost::istream_range<utl::LineStringTo<GainRatioCorrectionLine>>(ifs)) {
184  const auto r = gc.GetObservedGainRatio();
185  if (r) {
186  // do not correct if R=0 returned, ie correction is effectively R=1
187  // correction is the inverse of the observed ratios, ie
188  // S_LG^new = S_LG / R => S_LG^new / S_HG = R / R == 1
189  fFactors[gc.fYear][gc.fStationId].fPMT[gc.fPmtId - 1] = 1 / r;
190  }
191  }
192 
193  if (fFactors.empty()) {
194  ERROR("The database of gain-ration correction factors is empty!");
195  return eFailure;
196  }
197  // it is safe now to get the first year
198  utl::Accumulator::MinMax<int> yearRange(fFactors.begin()->first);
199 
200  std::map<int, utl::SVector<Factors::fgNPmts, int>> stationPmtCounts;
201  for (const auto& yf : fFactors) {
202  const auto& y = yf.first;
203  yearRange(y);
204  for (const auto& sf : yf.second) {
205  const auto& s = sf.first;
206  auto& count = stationPmtCounts[s];
207  const auto& pmt = sf.second.fPMT;
208  for (int i = 0; i < Factors::fgNPmts; ++i)
209  if (pmt[i])
210  ++count[i];
211  }
212  }
213 
214  std::ostringstream info;
215  info << "For years [" << yearRange.GetMin() << ", " << yearRange.GetMax() << "] there are "
216  << stationPmtCounts.size() << " stations with gain-ratio correction factors.";
217  INFO(info);
218 
219  info.str("");
220  int incomplete = 0;
221  for (const auto& sc : stationPmtCounts) {
222  if (!HasAllCounts(sc.second)) {
223  ++incomplete;
224  if (info.str().empty())
225  info << "The following stations are missing yearly corrections for certain PMTs "
226  "(counts of years given in brackets): " << sc.first << " (" << sc.second << ')';
227  else
228  info << ", " << sc.first << " (" << sc.second << ')';
229  }
230  }
231  if (incomplete) {
232  info << "; a total of " << incomplete << " stations.";
233  INFO(info);
234  }
235 
236  return eSuccess;
237  }
238 
239 
242  {
243  if (!event.HasSEvent())
244  return eSuccess;
245  auto& sEvent = event.GetSEvent();
246 
247  const auto& sDet = det::Detector::GetInstance().GetSDetector();
248 
249  for (auto& station : sEvent.StationsRange()) {
250 
251  const bool isNotSim = !station.HasSimData();
252 
253  for (auto& pmt : station.PMTsRange(sdet::PMTConstants::eAnyType)) {
254  if (!pmt.HasCalibData() || !pmt.GetCalibData().IsTubeOk())
255  continue;
256  double gainRatio = pmt.GetCalibData().GetGainRatio();
257  if (isNotSim) {
258  const bool isLargeWCD = (pmt.GetType() == sdet::PMTConstants::eWaterCherenkovLarge);
259  if (isLargeWCD && station.GetCalibData().GetVersion() == 12)
260  gainRatio *= fCalibrationVersion12GainFactor;
261  if (!gainRatio) { // missing gain in early UUBs
262  const auto stationId = station.GetId();
263  const auto pmtId = pmt.GetId();
264  gainRatio = sDet.GetStation(stationId).GetPMT(pmtId).GetGainRatio();
265  std::ostringstream warn;
266  warn << "Gain ratio zero encountered for station " << stationId << " PMT"
267  << pmtId << ", replacing it with the nominal value " << gainRatio << "!";
268  WARNING(warn);
269  }
270  }
271  if (!pmt.HasRecData())
272  pmt.MakeRecData();
273  pmt.GetRecData().SetGainRatio(gainRatio);
274  }
275 
276  }
277 
279  return eSuccess;
280 
281  const auto& eventTime = event.GetHeader().GetTime();
282  const int year = utl::UTCDateTime(eventTime).GetYear();
283  const auto yearIt = fFactors.find(year);
284 
285  if (yearIt == fFactors.end())
286  return eSuccess;
287 
288  const auto& yearStations = yearIt->second;
289 
290  for (auto& station : sEvent.StationsRange()) {
291 
292  if (station.HasSimData() || station.IsUUB())
293  continue;
294 
295  // residual gain-ratio corrections
296  const auto stationIt = yearStations.find(station.GetId());
297  if (stationIt == yearStations.end())
298  continue;
299  const auto& pmtFactors = stationIt->second.fPMT;
300 
301  for (int i = 0; i < 3; ++i) {
302  const auto& factor = pmtFactors[i];
303  if (!factor)
304  continue;
305  const int pmtId = i + 1;
306  if (!station.HasPMT(pmtId))
307  continue;
308  auto& pmt = station.GetPMT(pmtId);
309  if (!pmt.HasCalibData() || !pmt.GetCalibData().IsTubeOk())
310  continue;
311  auto& pmtRec = pmt.GetRecData();
312  pmtRec.SetGainRatio(factor * pmtRec.GetGainRatio());
313  }
314 
315  }
316 
317  return eSuccess;
318  }
319 
320 }
fwk::VModule::ResultFlag Init() override
Initialize: invoked at beginning of run (NOT beginning of event)
friend std::istream & operator>>(std::istream &is, GainRatioCorrectionLine &c)
IsProxy< T > Is(const T &x)
Definition: Is.h:46
Report success to RunController.
Definition: VModule.h:62
bool is(const double a, const double b)
Definition: testlib.cc:113
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
int GetYear() const
Definition: UTCDate.h:44
bool HasAllCounts(const utl::SVector< n, int > &c)
constexpr double s
Definition: AugerUnits.h:163
Static (small and dense) vector class.
Definition: SVector.h:33
double abs(const SVector< n, T > &v)
#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
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.
Report failure to RunController, causing RunController to terminate execution.
Definition: VModule.h:64
Accumulates and calculates standard deviation.
char * filename
Definition: dump1090.h:266
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
bool HasSEvent() const
fwk::VModule::ResultFlag Run(evt::Event &event) override
Run: invoked once per event.
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
bool IsCommentOrEmpty(const std::string &line)
const double year
Definition: GalacticUnits.h:22

, generated on Tue Sep 26 2023.