SdSimulationCalibrator.cc
Go to the documentation of this file.
2 
3 #include <det/Detector.h>
4 
5 #include <sdet/SDetector.h>
6 #include <sdet/Station.h>
7 #include <sdet/PMTConstants.h>
8 #include <sdet/UUBDownsampleFilter.h>
9 
10 #include <evt/Event.h>
11 
12 #include <fwk/CentralConfig.h>
13 
14 #include <sevt/SEvent.h>
15 #include <sevt/Station.h>
16 #include <sevt/StationSimData.h>
17 #include <sevt/StationCalibData.h>
18 #include <sevt/PMTCalibData.h>
19 #include <sevt/PMTSimData.h>
20 #include <sevt/PMT.h>
21 
22 #include <utl/AugerUnits.h>
23 #include <utl/MathConstants.h>
24 #include <utl/Particle.h>
25 #include <utl/PhysicalConstants.h>
26 #include <utl/TimeStamp.h>
27 #include <utl/ErrorLogger.h>
28 #include <utl/Point.h>
29 #include <utl/Vector.h>
30 #include <utl/Reader.h>
31 #include <utl/TimeDistribution.h>
32 #include <utl/TimeDistributionAlgorithm.h>
33 #include <utl/TabularStream.h>
34 
35 #include <fwk/RunController.h>
36 
37 #include <sstream>
38 
39 using namespace utl;
40 using namespace sevt;
41 using namespace fwk;
42 using namespace evt;
43 using namespace det;
44 using namespace std;
45 
46 
47 namespace SdSimulationCalibratorOG {
48 
51  {
52  auto topBranch = CentralConfig::GetInstance()->GetTopBranch("SdSimulationCalibrator");
53 
54  topBranch.GetChild("singleTankId").GetData(fSingleTankId);
55 
56  const auto hardwareType = topBranch.GetChild("hardware").Get<string>();
57 
58  auto dumpTraces = topBranch.GetChild("dumpTraces").Get<bool>();
59 
60  if (hardwareType == "wcdLarge")
62  else if (hardwareType == "wcdSmall")
64  else if (hardwareType == "ssd")
65  fHardwareType = sdet::PMTConstants::eScintillator;
66  else if (hardwareType == "all")
67  fHardwareType = sdet::PMTConstants::eAnyType;
68  else {
69  ERROR("Hardware type not recognized or supported!");
70  return eFailure;
71  }
72 
73  const bool isUUB = det::Detector::GetInstance().GetSDetector().GetStation(fSingleTankId).IsUUB();
74  auto g4SimBranch = CentralConfig::GetInstance()->GetTopBranch("G4StationSimulator");
75  const auto fullTrackMode = g4SimBranch.GetChild("fullTrackMode").Get<string>();
76  const auto fastMode = g4SimBranch.GetChild("fastMode").Get<string>();
77 
78  const auto basename =
79  std::string(isUUB ? "uub" : "ub") +
80  "-hw_" + hardwareType +
81  "-full_" + fullTrackMode +
82  "-fast_" + fastMode;
83 
84  const auto chargePeakFilename = "dump_charge_peak-" + basename + ".dat";
85  fDumpFile.open(chargePeakFilename);
86  if (!fDumpFile.is_open()) {
87  ERROR("Cannot open charge/peak dump file!");
88  return eFailure;
89  }
90  fDumpFile << "# pmtId phase peak charge compatPeak\n";
91 
92  if (dumpTraces) {
93  const auto traceFilename = "dump_trace-" + basename + ".dat";
94  fDumpTraceFile = new std::ofstream(traceFilename);
95  if (!fDumpTraceFile->is_open()) {
96  ERROR("Cannot open trace dump file!");
97  return eFailure;
98  }
99  *fDumpTraceFile << "# baseline begin end num_particles <whole_trace>\n";
100  }
101 
102  return eSuccess;
103  }
104 
105 
107  SdSimulationCalibrator::Run(Event& event)
108  {
109  if (!event.HasSEvent()) {
110  ERROR("Non-existent SEvent.");
111  return eFailure;
112  }
113 
114  auto& sEvent = event.GetSEvent();
115 
116  if (!sEvent.HasStation(fSingleTankId)) {
117  ostringstream err;
118  err << "Non-existent station " << fSingleTankId;
119  ERROR(err);
120  return eFailure;
121  }
122 
123  auto& station = sEvent.GetStation(fSingleTankId);
124  const auto& dStation = Detector::GetInstance().GetSDetector().GetStation(fSingleTankId);
125 
126  fSignature = station.GetSimData().GetSimulatorSignature();
127  fIsUUB = dStation.IsUUB();
128 
129  ProcessStation(station, dStation);
130 
131  return eSuccess;
132  }
133 
134 
136  SdSimulationCalibrator::Finish()
137  {
138  TabularStream tab(" r r r | . . . | . . .");
139  tab << "PMT" << endc << "N" << endc << "NPar" << endc << "<Peak>" << endc
140  << "Err<>" << endc << "StdDev" << endc << "<Charge>" << endc << "Err<>"
141  << endc << "StdDev" << endr << hline;
142  int pmtId = 0;
143  unsigned int numRuns = 0;
144  for (const auto& peakCharge : fPeakCharge) {
145  const auto& peak = peakCharge.first;
146  if (peak.GetN()) {
147  const auto& charge = peakCharge.second;
148  tab << pmtId << endc
149  << peak.GetN() << endc
150  << fNParticles << endc
151  << peak.GetAverage() << endc
152  << peak.GetAverageError() << endc
153  << peak.GetStandardDeviation() << endc
154  << charge.GetAverage() << endc
155  << charge.GetAverageError() << endc
156  << charge.GetStandardDeviation() << endr;
157  numRuns = peak.GetN();
158  }
159  ++pmtId;
160  }
161  tab << delr;
162 
163  // Pull some info from the ParticleInjector for documentation purposes.
164  // NB this expects one to use ParticleInjectorNEU!
165  auto injB = CentralConfig::GetInstance()->GetTopBranch("ParticleInjector");
166  const double muEnergy = injB.GetChild("Energy").GetChild("Discrete").GetChild("x").Get<double>();
167 
168  ostringstream info;
169  info << "The simulated calibration constants were set as follows:\n\n"
170  << tab << "\n\n"
171  "The following XML snipped should be pasted into "
172  "Framework/SDetector/SdSimCalibrationConstants.xml.in "
173  "with the other PMT calibrations from the same simModule:\n\n"
174  " <!-- " << fSignature << " tank sim, " << numRuns << " runs, " << fNParticles << " particle(s) per run, "
175  "energy = " << muEnergy / GeV << " GeV -->\n"
176  " <simModule name='" << fSignature << "'>\n"
177  " <electronics isUUB='" << fIsUUB << "'>\n";
178 
179  for (int i = 1, n = fPeakCharge.size(); i < n; ++i) {
180  const bool isWCD = (1 <= i && i <= 3);
181  const auto& peakCharge = isWCD ? fWCDPeakCharge : fPeakCharge[i];
182  const auto& peak = peakCharge.first;
183  if (!peak.GetN())
184  continue;
185  info << " <PMT id='" << i << "'>" << (isWCD ? "<!-- note: all WCD PMTs are averaged together -->" : "") << '\n';
186  const auto& charge = peakCharge.second;
187  info << " <peak> " << peak.GetAverage() << " </peak> "
188  "<!-- err=" << peak.GetAverageError() << " std=" << peak.GetStandardDeviation();
189  if (isWCD)
190  info << " pmt" << i << '=' << fPeakCharge[i].first.GetAverage();
191  info << " -->\n"
192  " <charge> " << charge.GetAverage() << " </charge> "
193  "<!-- err=" << charge.GetAverageError() << " std=" << charge.GetStandardDeviation();
194  if (isWCD)
195  info << " pmt" << i << '=' << fPeakCharge[i].second.GetAverage();
196  info << " -->\n";
197  if (fIsUUB && isWCD) {
198  const auto& compatPeak = fWCDCompatibilityPeak;
199  const auto& peakRatio = fWCDPeakRatio;
200  info << " <compatibilityPeak> " << compatPeak.GetAverage() << " </compatibilityPeak> "
201  "<!-- err=" << compatPeak.GetAverageError() << " std=" << compatPeak.GetStandardDeviation()
202  << " pmt" << i << '=' << fCompatibilityPeak[i].GetAverage() << " -->\n"
203  " <!-- FBW/compatibility peak ratio=" << peakRatio.GetAverage() << " err=" << peakRatio.GetAverageError() << " "
204  "std=" << peakRatio.GetStandardDeviation() << " pmt" << i << '=' << fPeakRatio[i].GetAverage() << " -->\n";
205  }
206  info << " </PMT>\n";
207  }
208  info << " </electronics>\n"
209  " </simModule>\n";
210 
211  INFO(info);
212 
213  Clear();
214 
215  return eSuccess;
216  }
217 
218 
219  pair<int, int>
220  FindSignal(const TimeDistributionI& trace, const double baseline, const double threshold)
221  {
222  const double trigger = baseline + threshold;
223  const int a = trace.GetStart();
224  const int b = trace.GetStop() + 1;
225  int begin;
226  for (begin = a; begin < b; ++begin)
227  if (trace.At(begin) >= trigger)
228  break;
229  // run to the end?
230  if (begin == b)
231  return make_pair(0, 0); // not found
232  int end;
233  for (end = begin + 1; end < b; ++end)
234  if (trace.At(end) < trigger)
235  break;
236  return make_pair(begin, end);
237  }
238 
239 
240  pair<double, double>
241  ProcessTrace(const TimeDistributionI& trace, const int begin, const int end, const double baseline,
242  const int nParticles)
243  {
244  const double val = trace.At(begin) - baseline;
245  double peak = val;
246  double charge = val;
247  for (int i = begin+1; i < end; ++i) {
248  const double val = trace.At(i) - baseline;
249  charge += val;
250  if (val > peak)
251  peak = val;
252  }
253 
254  return make_pair(peak, charge / nParticles);
255  }
256 
257 
258  inline
259  void
260  DumpTrace(std::ofstream* const file,
261  const TimeDistributionI& trace, const int begin, const int end, const double baseline,
262  const int nParticles)
263  {
264  if (!file)
265  return;
266  const int start = trace.GetStart();
267  // output begin and end relative to the start of the trace dump
268  *file << baseline << ' ' << begin-start << ' ' << end-start << ' ' << nParticles;
269  for (int i = start, n = trace.GetStop()+1; i < n; ++i)
270  *file << ' ' << trace.At(i);
271  *file << '\n';
272  }
273 
274 
275  void
276  SdSimulationCalibrator::ProcessStation(const sevt::Station& station, const sdet::Station& dStation)
277  {
278  fNParticles = station.GetSimData().GetNParticles();
279 
280  if (fNParticles <= 0)
281  return;
282 
283  if (fNParticles != 1 && fHardwareType != sdet::PMTConstants::eWaterCherenkovSmall) {
284  ERROR("Simulation calibrator is throwing more than one particle. Only use with smallPMT!");
285  exit(1);
286  }
287 
288  // this tries to mimic the muon-buffer trigger
289  const double signalThreshold = 30; // adc for both
290  const int beforeSignal = fIsUUB ? 20 : 1;
291  const int afterSignal = fIsUUB ? 49 : 19;
292  const int uubTimeFactor = 3;
293 
294  for (const auto& pmt : station.PMTsRange(sdet::PMTConstants::eAnyType)) {
295 
296  if (!pmt.HasSimData())
297  continue;
298  const PMTSimData& pmtSim = pmt.GetSimData();
299 
300  if (!pmtSim.HasFADCTrace())
301  continue;
302 
303  const sdet::PMT& dPMT = dStation.GetPMT(pmt);
304  // only process desired pmt type, unless all
305  if (!(fHardwareType == sdet::PMTConstants::eAnyType || dPMT.GetType() == fHardwareType))
306  continue;
307 
308  if (!pmt.HasCalibData())
309  continue;
310  const auto& pmtCalib = pmt.GetCalibData();
311 
312  const auto index = pmt.GetId();
313 
314  const bool isWCD = (pmt.GetType() == sdet::PMTConstants::eWaterCherenkovLarge);
315 
316  const double baseline = pmtCalib.GetBaseline(sdet::PMTConstants::eHighGain);
317 
318  const auto& trace = pmtSim.GetFADCTrace();
319 
320  const auto beginEnd = FindSignal(trace, baseline, signalThreshold);
321  const auto begin = beginEnd.first;
322  const auto end = beginEnd.second;
323  if (!begin && !end)
324  continue; // no signal found
325 
326  const int signalBegin = max(begin - beforeSignal, trace.GetStart());
327  const int signalEnd = min(begin + afterSignal, trace.GetStop()+1);
328 
329  DumpTrace(fDumpTraceFile, trace, signalBegin, signalEnd, baseline, fNParticles);
330 
331  const auto peakCharge = ProcessTrace(trace, signalBegin, signalEnd, baseline, fNParticles);
332  const auto& peak = peakCharge.first;
333  const auto& charge = peakCharge.second;
334  ResizeArrays(index + 1);
335  fPeakCharge[index].first(peak);
336  fPeakCharge[index].second(charge);
337  if (isWCD) {
338  fWCDPeakCharge.first(peak);
339  fWCDPeakCharge.second(charge);
340  }
341 
342  if (!fIsUUB || !isWCD) {
343  fDumpFile << index << " -1 " << peak << ' ' << charge << " -1\n";
344  } else {
345  // this is only for UUB and WCD
346  // increase statistics by downsampling with all 3 possible phases
347  for (int phase = 0; phase < 3; ++phase) {
348  const auto compatTrace = sdet::UUBDownsampleFilter(trace, phase);
349  const auto compatPeakCharge =
350  ProcessTrace(compatTrace, signalBegin/uubTimeFactor, signalEnd/uubTimeFactor, baseline, fNParticles);
351  const auto& compatPeak = compatPeakCharge.first;
352  fCompatibilityPeak[index](compatPeak);
353  fPeakRatio[index](peak/compatPeak);
354  fWCDCompatibilityPeak(compatPeak);
355  fWCDPeakRatio(peak/compatPeak);
356  fDumpFile << index << ' ' << phase << ' ' << peak << ' ' << charge << ' ' << compatPeak << '\n';
357  }
358  }
359 
360  }
361  }
362 
363 
364  void
365  SdSimulationCalibrator::ResizeArrays(const unsigned int n)
366  {
367  if (n > fPeakCharge.size()) {
368  fPeakCharge.resize(n);
369  fCompatibilityPeak.resize(n);
370  fPeakRatio.resize(n);
371  }
372  }
373 
374 
375  void
376  SdSimulationCalibrator::Clear()
377  {
378  fPeakCharge.clear();
379  fCompatibilityPeak.clear();
380  fPeakRatio.clear();
381  fWCDPeakCharge.first.Clear();
382  fWCDPeakCharge.second.Clear();
383  fWCDCompatibilityPeak.Clear();
384  fWCDPeakRatio.Clear();
385 
386  fDumpFile.close();
387  }
388 
389 }
T At(const double time) const
int GetStart() const
First slot with data.
Detector description interface for Station-related data.
Detector description interface for PMT-related data.
Definition: SDetector/PMT.h:26
Histogram class for time distributions with suppressed empty bins.
int GetId() const
return ID of the PMT
Definition: SDetector/PMT.h:30
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
const PMT & GetPMT(const int id) const
Get specified PMT by id.
void Init()
Initialise the registry.
int exit
Definition: dump1090.h:237
bool HasFADCTrace(StationConstants::SignalComponent source=StationConstants::eTotal) const
Check if FADC trace (prior to local trigger simulation) exists.
Definition: PMTSimData.h:186
sdet::PMTConstants::PMTType GetType() const
Definition: SDetector/PMT.h:33
pair< int, int > FindSignal(const TimeDistributionI &trace, const double baseline, const double threshold)
#define max(a, b)
class to hold data at Station level
pair< double, double > ProcessTrace(const TimeDistributionI &trace, const int begin, const int end, const double baseline, const int nParticles)
utl::TraceI UUBDownsampleFilter(const utl::TraceI &trace, const int phase=1)
const EndRow endr
const int tab
Definition: SdInspector.cc:35
int GetStop() const
Last slot with data (1 less than First slot if no data)
void DumpTrace(std::ofstream *const file, const TimeDistributionI &trace, const int begin, const int end, const double baseline, const int nParticles)
class to format data in tabular form
const string file
constexpr double GeV
Definition: AugerUnits.h:187
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
const DeleteRow delr
Class to hold simulated data at PMT level.
Definition: PMTSimData.h:40
sevt::StationSimData & GetSimData()
Get simulated data at station level.
unsigned int GetNParticles() const
utl::TimeDistributionI & GetFADCTrace(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain, const StationConstants::SignalComponent source=StationConstants::eTotal)
Get FADC trace by gain and source.
Definition: PMTSimData.h:173
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
const HLine hline('-')
const EndColumn endc
bool HasSEvent() const

, generated on Tue Sep 26 2023.