RdChannelNoisePowerAnalyser.cc
Go to the documentation of this file.
2 #include <utl/ErrorLogger.h>
3 
4 #include <evt/Event.h>
5 #include <revt/REvent.h>
6 #include <revt/Header.h>
7 #include <revt/Station.h>
8 #include <revt/Channel.h>
9 #include <revt/StationRecData.h>
10 #include <revt/ChannelRRecDataQuantities.h>
11 
12 #include <utl/Point.h>
13 #include <utl/Trace.h>
14 #include <utl/TraceAlgorithm.h>
15 #include <utl/ErrorLogger.h>
16 #include <utl/Reader.h>
17 #include <utl/config.h>
18 #include <utl/AugerUnits.h>
19 #include <utl/RadioGeometryUtilities.h>
20 #include <utl/TimeStamp.h>
21 #include <utl/UTCDate.h>
22 #include <fwk/CentralConfig.h>
23 
24 #include <det/Detector.h>
25 #include <rdet/RDetector.h>
26 
27 #include <math.h>
28 
29 #include "TProfile.h"
30 #include "TProfile2D.h"
31 #include "TFile.h"
32 #include "TH2D.h"
33 #include "TMath.h"
34 #include "TCanvas.h"
35 
36 #include <utl/LeapSeconds.h>
37 
38 #define INFO2(x,y) if ((x) <= fInfoLevel) INFO(y)
39 
40 using namespace std;
41 
43 
44 // function to calculate LST
45 double RdChannelNoisePowerAnalyser::GPSSecToLSTHourAuger(const unsigned long gps)
46 {
47  const double J2000 = 2451545.0;
48  const double Dtohr = 0.066666666666666;
49  const double auger_longitude = -69.6;
50 
51  // time_t utc = gps + 315964819 + 16; // GPS UTC offset, Leap Seconds have to be updated
52  time_t utc = 0;
53  utl::LeapSeconds::GetInstance().ConvertGPSToUnix(gps, utc);
54 
55  const tm* const t = gmtime(&utc);
56  int year = t->tm_year + 1900;
57  int month = t->tm_mon + 1;
58  const int day = t->tm_mday;
59  const int hour = t->tm_hour;
60  const int min = t->tm_min;
61  const int sec = t->tm_sec;
62 
63 #warning can you use the utl::ModifiedJulianDate here?
64  //Date to Julian Date
65  if (month <= 2) {
66  --year;
67  month += 12;
68  }
69  const int a = int(floor(year / 100.));
70  const int b = 2 - a + a / 4;
71  double jd = floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + b - 1524.5;
72  const double fd = double(60 * 60 * hour + 60 * min + sec) / 86400;
73  jd = jd + fd;
74 
75  static double sidereal_coeff[4] = { 280.46061837, 360.98564736629, 0.000387933, 38710000 };
76  const double dt = jd - J2000;
77  const double dt0 = dt / 36525.;
78  const double theta = sidereal_coeff[0] + dt * sidereal_coeff[1]
79  + dt0 * dt0 * (sidereal_coeff[2] - dt0 / sidereal_coeff[3]); // is in degrees
80  // original J. Meeus: longitude is positive westwards *lst = mod(theta-longitude,360.) * kSTC::Dtohr;
81  // with the new convention for longitudes (positive eastwards) :
82  const double lst = fmod(theta + (360 + auger_longitude), 360.) * Dtohr;
83  return lst;
84 }
85 
87  fInfoLevel(0),
88  fUnbinnedASCIIOutput(false),
89  fFrequencyBinWidth(1 * utl::MHz),
90  fMinFrequency(30 * utl::MHz),
91  fMaxFrequency(80 * utl::MHz),
92  fOutputPath("output"),
93  fOutputFilename("noise_amplitudes"),
94  fMinimumStationId(101),
95  fMaximumStationId(224),
96  fMinimumChannelId(1),
97  fMaximumChannelId(2),
98  fLocalSiderealDay(86164.090530833 * utl::second), // exact definition from Aoki, S., B. Guinot, G. H. Kaplan, H. Kinoshita, D. D. McCarthy and P. K. Seidelmann: "The new definition of Universal Time". Astronomy and Astrophysics 105(2), 361, 1982, see equation 19.
99  fNumberOfBinsPerDay(144),
100  fNFrequencyBins(0),
101  fReferenceTime(utl::UTCDateTime(2011, 1, 1, 0, 0, 0, 0.)), // initialize reference time to 1. Jan. 2011
102  fRootOut(0),
103  fCurrentMonth(0)
104 {
105 }
106 
108 {
109  // Initialize your module here. This method
110  // is called once at the beginning of the run.
111  // The eSuccess flag indicates the method ended
112  // successfully. For other possible return types,
113  // see the VModule documentation.
114 
115  INFO("RdChannelNoisePowerAnalyser::Init()");
117  "RdChannelNoisePowerAnalyser");
118  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
119  topBranch.GetChild("OutputPath").GetData(fOutputPath);
120  topBranch.GetChild("OutputFilename").GetData(fOutputFilename);
121  topBranch.GetChild("minStationId").GetData(fMinimumStationId);
122  topBranch.GetChild("maxStationId").GetData(fMaximumStationId);
123 
124  // initialize data structure
125  std::string outputfilename = fOutputPath;
126  if (outputfilename.substr(outputfilename.size() - 1, 1) != "/") {
127  outputfilename.append("/");
128  }
129  outputfilename.append(fOutputFilename);
130  std::string rootOutputFilename = outputfilename + ".root";
131  fRootOut = new TFile(rootOutputFilename.c_str(), "RECREATE");
132 
134  fFrequencies.reserve(fNFrequencyBins);
135  for (int i = 0; i <= fNFrequencyBins; ++i) {
137  }
138  cout << "creating data structure...";
139  for (int iStation = fMinimumStationId; iStation <= fMaximumStationId; ++iStation) {
140  cout << "." << std::flush;
141  for (int iChannel = fMinimumChannelId; iChannel <= fMaximumChannelId; ++iChannel) {
142  for (int iFrequency = 0; iFrequency < fNFrequencyBins; ++iFrequency) {
143  Key key(iStation, iChannel, iFrequency);
144 
145  // create profile histograms
146  stringstream title;
147  title << "station " << boost::get<0>(key) << ", channel " << boost::get<1>(key)
148  << ", frequency " << fFrequencies[boost::get<2>(key)] / utl::MHz << "MHz";
149  stringstream sstr;
150 // sstr.str("");
151 // sstr << "Amp_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
152 // << boost::get<2>(key);
153 // TProfile *hAmp = new TProfile(sstr.str().c_str(), title.str().c_str(), fNumberOfBinsPerDay,
154 // 0, 24);
155 // hAmp->SetDirectory(fRootOut);
156 // hAmp->GetYaxis()->SetTitle("Noise Amplitude [V/MHz]");
157 // hAmp->GetXaxis()->SetTitle("LST [h]");
158 // fProfileAmplitudeMap.insert(std::pair<Key, TProfile*>(key, hAmp));
159 // sstr.str("");
160 // sstr << "Power_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
161 // << boost::get<2>(key);
162 // TProfile *hPower = new TProfile(sstr.str().c_str(), title.str().c_str(),
163 // fNumberOfBinsPerDay, 0, 24);
164 // hPower->SetDirectory(fRootOut);
165 // hPower->GetYaxis()->SetTitle("power spectral density [W/MHz]");
166 // hPower->GetXaxis()->SetTitle("LST [h]");
167 // fProfilePowerMap.insert(std::pair<Key, TProfile*>(key, hPower));
168 
169  // initialize 2D histograms
170  sstr.str("");
171  sstr << "Power2DSparse_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
172  << boost::get<2>(key);
173 
174  Int_t bins[2] = { fNumberOfBinsPerDay, 400 };
175  Double_t xmin[2] = { 0, -14 };
176  Double_t xmax[2] = { 24, -6 };
177  THnSparseF* hs = new THnSparseF(sstr.str().c_str(), title.str().c_str(), 2, bins, xmin,
178  xmax);
179 // hs->SetDirectory(fRootOut);
180  hs->GetAxis(0)->SetTitle("LST [h]");
181  hs->GetAxis(1)->SetTitle("Log (power spectral density [W/MHz])");
182  fHistogramPowerMap.insert(std::pair<Key, THnSparseF*>(key, hs));
183 
184 
185 
186  // initialize 2D histograms linear
187  sstr.str("");
188  sstr << "Power2DSparseLinear_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
189  << boost::get<2>(key);
190 
191  Int_t bins2[2] = { fNumberOfBinsPerDay, 1000 };
192  Double_t xmin2[2] = { 0, 1e-12 };
193  Double_t xmax2[2] = { 24, 50e-12 };
194  THnSparseF* hs2 = new THnSparseF(sstr.str().c_str(), title.str().c_str(), 2, bins2, xmin2,
195  xmax2);
196  hs2->GetAxis(0)->SetTitle("LST [h]");
197  hs2->GetAxis(1)->SetTitle("power spectral density [W/MHz]");
198  fHistogramPowerMapLinear.insert(std::pair<Key, THnSparseF*>(key, hs2));
199 // TH2D *hHist2dPower = new TH2D(sstr.str().c_str(), title.str().c_str(), fNumberOfBinsPerDay,
200 // 0, fLocalSiderealDay, 500, -7, 0);
201 // hHist2dPower->SetDirectory(fRootOut);
202 // hHist2dPower->GetYaxis()->SetTitle("Log (Noise Power [V^2/MHz])");
203 // hHist2dPower->GetXaxis()->SetTitle("(time - 2011/01/01) mod LSD [ns]");
204 // fHistogramPowerMap.insert(std::pair<Key, TH2D*>(key, hHist2dPower));
205 
206  }
207  }
208  }
209  cout << endl;
210 
211  return eSuccess;
212 }
213 
214 fwk::VModule::ResultFlag RdChannelNoisePowerAnalyser::Run(evt::Event& event)
215 {
216 
217  INFO2(eDebug, "RdChannelNoisePowerAnalyser::Run()");
218  // Check if there are events at all
219  if (!event.HasREvent()) {
220  WARNING("RdChannelNoisePowerAnalyser::No radio event found!");
221  return eContinueLoop;
222  }
223  revt::REvent& revent = event.GetREvent();
224  // compute nearest neighbors
225 // const det::Detector& detector = det::Detector::GetInstance();
226 // const rdet::RDetector& rDetector = detector.GetRDetector();
227 
228  utl::TimeStamp currentTimeStamp = revent.GetHeader().GetTime();
229 
230  // initialize dynamic spectra
231  const utl::UTCDateTime date = utl::UTCDateTime(currentTimeStamp);
232  const int year = date.GetYear();
233  const int month = date.GetMonth();
234  if (fCurrentMonth != month) {
235  fCurrentMonth = month;
236  // initialize dynamic spectrum histogram
237  stringstream sstr;
238  sstr << "initializing dynamic power spectrum for month " << month << " and year " << year;
239  INFO(sstr.str());
240  for (int iStation = fMinimumStationId; iStation <= fMaximumStationId; ++iStation) {
241  for (int iChannel = fMinimumChannelId; iChannel <= fMaximumChannelId; ++iChannel) {
242  stringstream sstr;
243  sstr.str("");
244  KeyYearMonth key(iStation, iChannel, year, month);
245  sstr << "DynamicSpectrum_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
246  << boost::get<2>(key) << "_" << boost::get<3>(key);
247  stringstream title;
248  title << "station " << boost::get<0>(key) << ", channel " << boost::get<1>(key) << ", "
249  << month << " " << year;
250  utl::UTCDate tmpDateStart = utl::UTCDate(year, month, 1);
251  int nextMonth = month + 1;
252  int nextYear = year;
253  if (nextMonth > 12) {
254  nextMonth = 1;
255  nextYear += 1;
256  }
257  utl::UTCDate tmpDateStop = utl::UTCDate(nextYear, nextMonth, 1);
258  const int numberOfBins = NumberOfDaysInMonth(year, month) * 24 * 6; // every ten minutes
259  stringstream info;
260  info.str("");
261  info << "number of days per month = " << NumberOfDaysInMonth(year, month);
262  INFO(info.str());
263  TProfile2D *hHist2dPower = new TProfile2D(
264  sstr.str().c_str(), title.str().c_str(), numberOfBins,
265  utl::UTCDateTime(tmpDateStart).GetTimeStamp().GetGPSSecond(),
268  cout << "start time " << utl::UTCDateTime(tmpDateStart).GetTimeStamp().GetGPSSecond() << endl;
269  cout << "stop time " << utl::UTCDateTime(tmpDateStop).GetTimeStamp().GetGPSSecond() << endl;
270 
271  hHist2dPower->SetDirectory(fRootOut);
272  hHist2dPower->GetYaxis()->SetTitle("frequency [GHz]");
273  hHist2dPower->GetXaxis()->SetTitle("GPS seconds");
274  hHist2dPower->GetZaxis()->SetTitle("log(power spectral density [W/MHz])");
275  fDynamicPowerSpectrum.insert(std::pair<KeyYearMonth, TProfile2D*>(key, hHist2dPower));
276  info.str("");
277  info << "initializing dynamic power spectrum for month " << month << " and year " << year
278  << "station " << iStation << " and channel " << iChannel;
279  INFO(info.str());
280  }
281  }
282  }
283  // determine correct LSD bin
284  const unsigned long currentGPSSeconds = revent.GetHeader().GetTime().GetGPSSecond();
285  // const double deltaLST = fmod(currentTimeStamp - fReferenceTime.GetTimeStamp(), fLocalSiderealDay);
286  const double deltaLST = GPSSecToLSTHourAuger(currentGPSSeconds);
287  std::vector<double> LSDBinBorders;
288  LSDBinBorders.reserve(fNumberOfBinsPerDay + 1);
289  for (int i = 0; i <= fNumberOfBinsPerDay; ++i) {
290  LSDBinBorders[i] = i * 24. / (fNumberOfBinsPerDay);
291  }
292  int deltaLSTBin = -1;
293  for (int i = 0; i < fNumberOfBinsPerDay; ++i) {
294  if (deltaLST >= LSDBinBorders[i] and deltaLST < LSDBinBorders[i + 1]) {
295  deltaLSTBin = i;
296  }
297  }
298  if (deltaLSTBin == -1) {
299  cout << "delta LSTBin == -1, deltaLST = " << deltaLST << endl;
300  }
301 
302  std::map<int, std::vector<std::vector<double> > > noiseMap; // keys are [stationId][channelId][frequency] amplitudes
304  iS != revent.CandidateStationsEnd(); ++iS) {
305  // skip stations that are out of range
306  if (iS->GetId() < fMinimumStationId or iS->GetId() > fMaximumStationId) {
307  stringstream info;
308  info << "station " << iS->GetId() << " is out of range, skipping station.";
309  INFO2(eDebug, info.str());
310  continue;
311  }
312  std::vector<std::vector<double> > tmpChannels;
313  for (revt::Station::ConstChannelIterator iC = iS->ChannelsBegin(); iC != iS->ChannelsEnd();
314  ++iC) {
315  if (not iC->IsActive()) {
316  stringstream info;
317  info << "channel " << iC->GetId() << " is inactive. Skipping channel";
318  INFO2(eDebug, info.str());
319  continue;
320  }
321  // skip channels that are out of range
322  if (iC->GetId() < fMinimumChannelId or iC->GetId() > fMaximumChannelId) {
323  stringstream info;
324  info << "channel " << iC->GetId() << " is out of range, skipping channel";
325  INFO2(eDebug, info.str());
326  continue;
327  }
328 
329  const double timeBinSize = iC->GetFFTDataContainer().GetConstTimeSeries().GetBinning();
330  const double traceLength = iC->GetFFTDataContainer().GetConstTimeSeries().GetSize()
331  * timeBinSize;
332 
333  const revt::ChannelFrequencySpectrum& spectrum = iC->GetConstChannelFrequencySpectrum();
334  // double frequencyBinWidth = spectrum.GetBinning(); //unused, see below
335  // double nBins1MHz = 1 * utl::MHz / frequencyBinWidth;
336  // double nBins1MHz = 1. / frequencyBinWidth; // not used in noiseAmplitude and noisePower calc anymore since 2016-12-07 glaser commit
337  std::vector<double> noiseAmplitudes;
338  noiseAmplitudes.reserve(fNFrequencyBins);
339 
340  // debug
341 // cout << "timetrace " << endl;
342 // const revt::ChannelTimeSeries& timeseries = iC->GetChannelTimeSeries();
343 // int nn = iC->GetFFTDataContainer().GetConstTimeSeries().GetSize();
344 // cout << "timeseries = [";
345 // for (int i = 0; i < nn; ++i) {
346 // cout << timeseries[i] << ", ";
347 // }
348 // cout << "]" << endl;
349 // cout << "tracelength = " << traceLength << endl;
350  // end debug
351 
352  KeyYearMonth keyYearMonth(iS->GetId(), iC->GetId(), year, month);
353  for (int i = 0; i < fNFrequencyBins; ++i) {
354  Key key(iS->GetId(), iC->GetId(), i);
355  int binStart = iC->GetFFTDataContainer().GetBinOfFrequency(fFrequencies[i]);
356  int binStop = iC->GetFFTDataContainer().GetBinOfFrequency(fFrequencies[i + 1]);
357  double frequencyInterval = iC->GetFFTDataContainer().GetFrequencyOfBin(binStop)
358  - iC->GetFFTDataContainer().GetFrequencyOfBin(binStart);
359  double noiseAmplitude(0.);
360  double noisePower(0.);
361  // average over 1 MHz interval
362  for (int j = binStart; j < binStop; ++j) {
363  noiseAmplitude += abs(spectrum[j]);
364  noisePower += abs(spectrum[j]) * abs(spectrum[j]);
365  }
366  // normalize to number of bins (because it can be different for different frequency ranges as the samplingfrequency is not a multiple of our frequency bin width
367  noiseAmplitude *= 1. / (binStop - binStart); // average over 1 MHz interval
368  noisePower *= 1. / (binStop - binStart);
369  noisePower *= 1. / frequencyInterval * (fFrequencies[i + 1] - fFrequencies[i]); // average over 1 MHz interval
370 
371  noisePower *= 2; // because negative frequencies are omitted in real fft
372  noisePower /= traceLength; // energy -> power
373  noisePower /= (50 * utl::ohm); // V^2 -> Watts (50 ohm impedance system)
374  noisePower /= (utl::watt / utl::MHz); // convert to units W/MHz
375 
376 // stringstream sstr;
377 // sstr << "f = " << fFrequencies[i] / utl::MHz << " - " << fFrequencies[i + 1] / utl::MHz
378 // << " MHz" << " delta = " << frequencyInterval / utl::MHz << " noisepower = "
379 // << noisePower;
380 // INFO2(eDebug, sstr.str());
381 // // add info to profiles
382 // fProfileAmplitudeMap[key]->Fill(deltaLST, noiseAmplitude);
383 // fProfilePowerMap[key]->Fill(deltaLST, noisePower);
384  double x[2] = { deltaLST, TMath::Log10(noisePower) };
385  fHistogramPowerMap[key]->Fill(x);
386 
387  double x2[2] = { deltaLST, noisePower};
388  fHistogramPowerMapLinear[key]->Fill(x2);
389 
390  const double currentFrequency = 0.5 * (fFrequencies[i] + fFrequencies[i + 1]);
391  fDynamicPowerSpectrum[keyYearMonth]->Fill(currentGPSSeconds, currentFrequency,
392  TMath::Log10(noisePower));
393  }
394  tmpChannels.push_back(noiseAmplitudes);
395  }
396  }
397 
398  return eSuccess;
399 }
400 
401 fwk::VModule::ResultFlag RdChannelNoisePowerAnalyser::Finish()
402 {
403 // Put any termination or cleanup code here.
404 // This method is called once at the end of the run.
405  INFO("RdChannelNoisePowerAnalyser::Finish()");
406 
407  fRootOut->Write();
408 
409  typedef std::map<KeyYearMonth, TProfile2D*>::iterator it_type;
410  for(it_type iterator = fDynamicPowerSpectrum.begin(); iterator != fDynamicPowerSpectrum.end(); iterator++) {
411  iterator->second->Write();
412  /*
413  cout << "writing power spectrum" << endl;
414  TCanvas *c1 = new TCanvas();
415  c1->cd();
416  iterator->second->Draw("COLZ");
417  stringstream sstr;
418  sstr << iterator->second->GetName() << ".png";
419  c1->SaveAs(sstr.str().c_str());
420  */
421 
422  // iterator->first = key
423  // iterator->second = value
424  // Repeat if you also want to iterate through the second map.
425  }
426 
427  // delete all histograms from memory
428 // for (int iStation = fMinimumStationId; iStation <= fMaximumStationId; ++iStation) {
429 // for (int iChannel = fMinimumChannelId; iChannel <= fMaximumChannelId; ++iChannel) {
430 // for (int iFrequency = 0; iFrequency < fNFrequencyBins; ++iFrequency) {
431 // Key key(iStation, iChannel, iFrequency);
432 // delete fProfileAmplitudeMap[key];
433 // delete fProfilePowerMap[key];
434 // }
435 // }
436 // }
437  for (int iStation = fMinimumStationId; iStation <= fMaximumStationId; ++iStation) {
438  for (int iChannel = fMinimumChannelId; iChannel <= fMaximumChannelId; ++iChannel) {
439  for (int iFrequency = 0; iFrequency < fNFrequencyBins; ++iFrequency) {
440  Key key(iStation, iChannel, iFrequency);
441  fHistogramPowerMap[key]->Write();
442  delete fHistogramPowerMap[key];
443  fHistogramPowerMapLinear[key]->Write();
444  delete fHistogramPowerMapLinear[key];
445 // TH2D* h2 = fHistogramPowerMap[key]->Projection(1, 0);
446 // stringstream sstr;
447 // sstr << "Power2D_" << boost::get<0>(key) << "_" << boost::get<1>(key) << "_"
448 // << boost::get<2>(key);
449 // h2->SetName(sstr.str().c_str());
450 // h2->Write();
451 // delete h2;
452  }
453  }
454  }
455 
456  return eSuccess;
457 }
458 
459 }
Report success to RunController.
Definition: VModule.h:62
constexpr double MHz
Definition: AugerUnits.h:159
CandidateStationIterator CandidateStationsEnd()
Definition: REvent.h:146
boost::indirect_iterator< InternalConstChannelIterator, const Channel & > ConstChannelIterator
Iterator over station for read.
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
Skip remaining modules in the current loop and continue with next iteration of the loop...
Definition: VModule.h:68
utl::TimeStamp GetTime() const
Definition: REvent/Header.h:17
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
#define INFO2(x, y)
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
int GetYear() const
Definition: UTCDate.h:44
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
int fd
Definition: dump1090.h:233
boost::filter_iterator< CandidateStationFilter, ConstAllStationIterator > ConstCandidateStationIterator
Definition: REvent.h:142
Class representing a document branch.
Definition: Branch.h:107
static int NumberOfDaysInMonth(const int year, const int month)
double abs(const SVector< n, T > &v)
Header & GetHeader()
access to REvent Header
Definition: REvent.h:239
constexpr double ohm
Definition: AugerUnits.h:236
const double second
Definition: GalacticUnits.h:32
CandidateStationIterator CandidateStationsBegin()
Definition: REvent.h:144
boost::tuple< int, int, int > Key
#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
constexpr double watt
Definition: AugerUnits.h:204
constexpr double hour
Definition: AugerUnits.h:150
int GetMonth() const
Definition: UTCDate.h:46
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
boost::tuple< int, int, int, int > KeyYearMonth
TimeStamp GetTimeStamp() const
Definition: UTCDateTime.cc:115
constexpr double day
Definition: AugerUnits.h:151
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
const double year
Definition: GalacticUnits.h:22

, generated on Tue Sep 26 2023.