RdChannelBeaconTimingCalibrator.cc
Go to the documentation of this file.
1 
10 
11 #include <fwk/CentralConfig.h>
12 
13 #include <utl/ErrorLogger.h>
14 #include <utl/Reader.h>
15 #include <utl/config.h>
16 #include <utl/AugerUnits.h>
17 #include <utl/MathConstants.h>
18 #include <utl/TraceAlgorithm.h>
19 #include <utl/TimeStamp.h>
20 #include <utl/TimeInterval.h>
21 #include <utl/FFTDataContainerAlgorithm.h>
22 #include <utl/CoordinateSystem.h>
23 #include <utl/PhysicalConstants.h>
24 #include <utl/Point.h>
25 #include <utl/Vector.h>
26 
27 #include <evt/Event.h>
28 #include <revt/REvent.h>
29 #include <revt/Header.h>
30 #include <revt/Station.h>
31 #include <revt/Channel.h>
32 #include <revt/StationRecData.h>
33 
34 #include <det/Detector.h>
35 #include <rdet/RDetector.h>
36 
37 #include <rdet/Station.h>
38 #include <rdet/Channel.h>
39 
40 #include <complex>
41 #include <cmath>
42 #include <string>
43 #include <sstream>
44 #include <iostream>
45 #include <iomanip>
46 #include <fstream>
47 #include <vector>
48 #include <map>
49 #include <numeric>
50 #include <set>
51 
52 #include <CLHEP/Matrix/Matrix.h>
53 #include <CLHEP/Matrix/Vector.h>
54 
55 using namespace fwk;
56 using namespace utl;
57 using namespace revt;
58 using namespace std;
59 
60 const double speedOfLight = kSpeedOfLight / 1.00025; // for adjusting refractive index
61 
63 
66  {
67  const Branch topBranch =
68  CentralConfig::GetInstance()->GetTopBranch("RdChannelBeaconTimingCalibrator");
69 
70  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
71  topBranch.GetChild("BeaconFrequencies").GetData(fBeaconFrequencies);
72  topBranch.GetChild("ReferenceChannel").GetData(fReferenceChannel);
73  topBranch.GetChild("FixedReferenceStationID").GetData(fFixedReferenceStationID);
74  topBranch.GetChild("NoiseFilterSize").GetData(fNoiseFilterSize);
75  topBranch.GetChild("MinSNR").GetData(fMinSNR);
76  topBranch.GetChild("MaxTimeDifference").GetData(fMaxTimeDifference);
77  topBranch.GetChild("Epsilon").GetData(fEpsilon);
78  topBranch.GetChild("MinGoodFreqs").GetData(fMinGoodFreqs);
79  topBranch.GetChild("EqualizeStationTimeStamps").GetData(fEqualizeStationTimeStamps);
80  topBranch.GetChild("InputPhaseFile").GetData(fInputPhaseFile);
81  // read in the debug station list as vector, and then copy it to the set class variable
82  vector<int> dummyStationIDlist;
83  topBranch.GetChild("DebugStationIds").GetData(dummyStationIDlist);
84  fDebugStationIds = set<int>(dummyStationIDlist.begin(), dummyStationIDlist.end());
85  topBranch.GetChild("DebugOutputFile").GetData(fDebugOutputFile);
86  topBranch.GetChild("OverwriteDebugFile").GetData(fOverwriteDebugFile);
87  topBranch.GetChild("RejectIfNoRefPhaseAvailable").GetData(fRejectIfNoRefPhaseAvailable);
88  topBranch.GetChild("RejectIfCorrectionFailed").GetData(fRejectIfCorrectionFailed);
89  topBranch.GetChild("UseCrossCorrelationMethod").GetData(fUseCrossCorrelationMethod);
90  topBranch.GetChild("UseBeaconDistanceInsteadOfDatabaseValues").GetData(fUseBeaconDistanceInsteadOfDatabaseValues);
91  topBranch.GetChild("BeaconPosition").GetData(fBeaconPosition);
92  topBranch.GetChild("BeaconTimeCalibrationUncertainty").GetData(fBeaconTimeCalibrationUncertainty);
93  topBranch.GetChild("StartingDateTimeForBeaconCorrection").GetData(fStartingDateTimeForBeaconCorrection);
94 
95  //check if the beacon position has the right format
96  if(fBeaconPosition.size() < 3) {
97  ERROR("Incorrect definition of beacon position in XML file: One or more coordinates are missing!");
98  return eBreakLoop;
99  }
100 
101  return eSuccess;
102  }
103 
104 
106  RdChannelBeaconTimingCalibrator::Run(evt::Event& event)
107  {
108  // variables needed during the whole method
109 
111  std::map<int, std::map<int, double>> phases;
112 
114  std::map<int, std::map<int, double>> modPhases;
115 
117  std::map<int, std::map<int, double>> timeDiffsFreq;
118 
120  std::map<int, std::map<int, double>> SNRs;
121 
123  std::map<int, double> timeOffsets;
124 
126  std::map<int, double> timeOffsetUncertainty;
127 
128  // Check if there are events at all
129  if (!event.HasREvent()) {
130  WARNING("RdChannelBeaconTimingCalibrator::No radio event found!");
131  return eContinueLoop;
132  } else {
133  REvent& rEvent = event.GetREvent();
134  stringstream message;
135  message << "Radio event found with "
136  << rEvent.GetNumberOfStations()
137  << " stations!";
138  if (fInfoLevel >= eInfoDebug)
139  INFO(message.str());
140 
141  // Read event header and check event time
142  const Header& rHeader = rEvent.GetHeader();
143  message.str("");
144  message << "Found header with ID "
145  << rHeader.GetId()
146  << " and timestamp: "
147  << rHeader.GetTime();
148  if (fInfoLevel >= eInfoDebug)
149  INFO(message.str());
150 
151  if (rHeader.GetTime() < fStartingDateTimeForBeaconCorrection) {
152  message.str("");
153  message << "Skipped event with ID "
154  << rHeader.GetId()
155  << " because event time is before: "
156  << fStartingDateTimeForBeaconCorrection;
157  if (fInfoLevel >= eInfoFinal)
158  INFO(message.str());
159  return eSuccess;
160  }
161 
162  // add statistics of beacon successes per stationID
163  // at the beginning assume a failure and then substract it at the end, if correction was successful
164  for (REvent::ConstStationIterator sIt = rEvent.StationsBegin();
165  sIt != rEvent.StationsEnd(); ++sIt) {
166  const Station& station = *sIt;
167  // check, if station is already tracked, and if not intialize its statistics counter
168  if (fBeaconCorrectionSuccesses.find(station.GetId()) == fBeaconCorrectionSuccesses.end() )
169  fBeaconCorrectionSuccesses[station.GetId()] = 0;
170  if (fBeaconCorrectionFailures.find(station.GetId()) == fBeaconCorrectionFailures.end() )
171  fBeaconCorrectionFailures[station.GetId()] = 0;
172  // assume failure (and substract it later, if correction successful)
173  ++fBeaconCorrectionFailures[station.GetId()];
174  }
175 
176  // get Detector
177  const det::Detector& Det = det::Detector::GetInstance();
178  const rdet::RDetector& RDetector = Det.GetRDetector();
179 
180  // check if beacon frequencies have to be read from database, or are provided in XML file
181  // in the first case, fBeaconFrequencies is empty, i.e. size()==0
182  std::vector<double> beaconFrequencies(fBeaconFrequencies);
183  if(beaconFrequencies.size() < 1) {
184  try {
185  beaconFrequencies = RDetector.GetBeaconFrequencies(); // for example for 2013 returns: 0.058887 0.071191 0.068555 0.061523
186  } catch (utl::DataNotFoundInDBException& err) {
187  ERROR ("Error reading Beacon frequencies from database, skipping event!");
188  return eContinueLoop;
189  }
190  }
191 
192  // read the reference phases (from txt file or database)
193  std::vector<std::map<int, double> > referencePhases;
194  if (fInputPhaseFile != "") {
195  referencePhases = getReferencePhases(beaconFrequencies);
196  } else {
197  referencePhases = vector<map<int, double> > (beaconFrequencies.size());
198  for (REvent::ConstStationIterator sIt = rEvent.StationsBegin();
199  sIt != rEvent.StationsEnd(); ++sIt) {
200  const Station& station = *sIt;
201  const int stationId = station.GetId();
202  try {
203  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
204  referencePhases[beaconFreqN][stationId] = RDetector.GetBeaconReferencePhase(stationId, beaconFrequencies[beaconFreqN]);
205  }
206  } catch (utl::DataNotFoundInDBException& err) {
207  message.str("");
208  message << "Could not read beacon reference phases for station "
209  << station.GetId()
210  << " from database.";
211  if (fInfoLevel >= eInfoFinal)
212  WARNING(message.str());
213  }
214  }
215  }
216  // final cross check
217  if (referencePhases.size() != beaconFrequencies.size()) {
218  ERROR("Could not read reference phases correctly.");
219  return eFailure;
220  }
221 
222  // check if there are reference phases for at least two stations
223  if (referencePhases[0].size() < 2) {
224  message.str("");
225  message << "Event has only "
226  << referencePhases[0].size()
227  << " stations with available reference phases. At least 2 are needed for the beacon correction.";
228  ERROR(message.str());
229  return eContinueLoop;
230  }
231 
232  // check if fixed reference station is contained in the event
233  if (fFixedReferenceStationID > 0)
234  if (!rEvent.HasStation(fFixedReferenceStationID)) {
235  message.str("");
236  message << "Reference station with ID "
237  << fFixedReferenceStationID
238  << " is not contained in the event: No Beacon correction possible!";
239  ERROR(message.str());
240  return eContinueLoop;
241  }
242 
243  // vector for beacon frequencies acutally corresponding to the
244  vector<double> beaconFreqsInSpectrum; // attention: can change from event to event, since trace length is variable
245 
246  // loop through stations and for every station through every channel
247  // calculate the phase differences for the reference channel (default: NS, high gain = channel 2)
248  unsigned int numberOfNotRejectedStations = 0;
249  for (auto sIt = rEvent.StationsBegin(); sIt != rEvent.StationsEnd(); ++sIt) {
250  Station& station = *sIt;
251 
252  // check if all references phases are available for this station
253  bool skipStation = false;
254  for (unsigned int beaconFreqN = 0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
255  if (referencePhases[beaconFreqN].find(station.GetId()) == referencePhases[beaconFreqN].end() ) {
256  message.str("");
257  message << "No reference phase for station "
258  << station.GetId()
259  << " and frequency #"
260  << beaconFreqN+1
261  << " available!";
262  if (fRejectIfNoRefPhaseAvailable)
263  message << " Station will be rejected.\n";
264  else
265  message << ".\n";
266  if (fInfoLevel >= eInfoFinal)
267  WARNING(message.str());
268  if (fRejectIfNoRefPhaseAvailable)
270  skipStation = true;
271  break;
272  }
273 
274  // check if beacon frequencies are inside of frequency spectrum of the station
275  // (which is not the case for low frequency stations)
276  if ( (beaconFrequencies[beaconFreqN] < RDetector.GetStation(station.GetId()).GetChannel(fReferenceChannel).GetDesignLowerFreq())
277  || (beaconFrequencies[beaconFreqN] > RDetector.GetStation(station.GetId()).GetChannel(fReferenceChannel).GetDesignUpperFreq()) ) {
278  message.str("");
279  message << "Beacon frequency "
280  << beaconFrequencies[beaconFreqN]/megahertz
281  << " MHz is outside of the design frequency band of station "
282  << station.GetId()
283  << ". --> Station will be rejected.\n";
284  if (fInfoLevel >= eInfoFinal)
285  WARNING(message.str());
287  skipStation = true;
288  break;
289  }
290  }
291  if (skipStation)
292  continue;
293 
294  // Get spectrum of reference channel
295  Channel& channel = station.GetChannel(fReferenceChannel);
296 
297  message.str("");
298  message << "Calculating the phases of the beacon frequencies for channel "
299  << channel.GetId()
300  << " of station "
301  << channel.GetStationId()
302  << ".";
303  if (fInfoLevel >= eInfoDebug)
304  INFO(message.str());
305 
306  const auto spectrum = channel.GetChannelFrequencySpectrum();
307 
308  // check if spectrum has the correct length, such that the frequency bins are at the expected values
309  // for which the beacon has been optimized
310  // are more general implementation might follow in the future
311  if ( ((spectrum.GetSize()-1) % 1024) != 0 ) {
312  message.str("");
313  message << "Trace should consist of 2048 samples or an integer multiple of it! It has:"
314  << (spectrum.GetSize()-1)*2;
315  if (fInfoLevel >= eInfoFinal)
316  WARNING(message.str());
317  //return eFailure; // lets try even if frequency bins are non-optimal
318  continue; // just ignore stations with improper trace lengths (e.g., Dutch stations with 1024 samples, only)
319  }
320 
321  // get the amplitude spectrum for SNR calculation
322  Trace<double> amplitudeSpectrum;
323  for (ChannelFrequencySpectrum::SizeType i = 0; i < spectrum.GetSize(); ++i)
324  amplitudeSpectrum.PushBack(abs(spectrum[i]));
325 
326 
327  // loop through beacon frequencies, find corresponding frequency in the spectrum
328  // and store phases
329  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
330  // check if frequency is inside the range (take care that the order of the spectrum is unknown)
331  if( (beaconFrequencies[beaconFreqN] <
332  min(channel.GetFrequencyOfBin(0),channel.GetFrequencyOfBin(spectrum.GetSize()-1)))
333  || (beaconFrequencies[beaconFreqN] >
334  max(channel.GetFrequencyOfBin(0),channel.GetFrequencyOfBin(spectrum.GetSize()-1))) ) {
335  ERROR("Beacon frequency must be inside of the spectrum!");
336  return eFailure;
337  }
338  // find nearest frequency bin:
339  double bin = (beaconFrequencies[beaconFreqN]-channel.GetFrequencyOfBin(0)) * (spectrum.GetSize()-1)
340  / (channel.GetFrequencyOfBin(spectrum.GetSize()-1) - channel.GetFrequencyOfBin(0));
341 
342  // store frequencies of the spectrum bins closest to the real beacon frequencies
343  // (needed for later conversion of phase differences to time differences)
344  // only store frequencies for the first station (assuming that all stations have the same trace lengths)
345  if (beaconFreqsInSpectrum.size() < beaconFrequencies.size())
346  beaconFreqsInSpectrum.push_back( channel.GetFrequencyOfBin(round(bin)) );
347 
348  // consistency check whether frequency of the spectrum bin is still the same (within 1e-6 due to double imprecision)
349  if ( abs(beaconFreqsInSpectrum[beaconFreqN] / channel.GetFrequencyOfBin(round(bin)) - 1.) > 1e-6) {
350  message.str("");
351  message << "Frequency of bin corresponding to beacon frequency "
352  << beaconFreqN + 1
353  << " changed from "
354  << beaconFreqsInSpectrum[beaconFreqN]/megahertz << "MHz"
355  << " to "
356  << channel.GetFrequencyOfBin(round(bin))/megahertz << "MHz";
357  ERROR(message.str());
358  return eFailure;
359  }
360 
361 
362  // get the phase, amplitude and noise level of the bin
363  double phase = arg(spectrum[round(bin)]);
364  double amplitude = abs(spectrum[round(bin)]);
365 
366  // substract reference phase
367  double modPhase = phase - referencePhases[beaconFreqN][channel.GetStationId()];
368  if (modPhase > kPi) {
369  modPhase -= kTwoPi;
370  } else if (modPhase < -kPi) {
371  modPhase += kTwoPi;
372  }
373 
374  //Store original and modified phases
375  phases[beaconFreqN][station.GetId()] = phase;
376  modPhases[beaconFreqN][station.GetId()] = modPhase;
377 
378  //Calculate and store SNR
379  double noise = TraceAlgorithm::Median(amplitudeSpectrum,
380  round(bin)-trunc(fNoiseFilterSize/2.0),
381  round(bin)+ceil(fNoiseFilterSize/2.0)-1.);
382  double snr = (amplitude*amplitude)/(noise*noise) ;
383  SNRs[beaconFreqN][station.GetId()] = snr;
384 
385 
386  // store SNRs for debugging, monitoring etc.
387  if (fBeaconSNRs.find(station.GetId()) == fBeaconSNRs.end())
388  fBeaconSNRs[station.GetId()] = std::map<int,double>();
389 
390  if (fBeaconSNRs[station.GetId()].find(beaconFreqN) == fBeaconSNRs[station.GetId()].end())
391  fBeaconSNRs[station.GetId()][beaconFreqN] = snr;
392  else
393  fBeaconSNRs[station.GetId()][beaconFreqN] += snr;
394 
395  }
396  ++numberOfNotRejectedStations;
397 
398  // increase counter for SNR normalization
399  if (fBeaconSNRcounter.find(station.GetId()) == fBeaconSNRcounter.end() )
400  fBeaconSNRcounter[station.GetId()] = 1;
401  else
402  ++fBeaconSNRcounter[station.GetId()];
403  }
404 
405  // check if there are at least two not rejected stations
406  if (numberOfNotRejectedStations < 2) {
407  message.str("");
408  message << "Event has only "
409  << numberOfNotRejectedStations
410  << " stations which are not rejected. At least 2 are needed for the beacon correction.";
411  ERROR(message.str());
412  return eContinueLoop;
413  }
414 
415  // find reference station and get reference phases:
416  // Either take largest SNR in beacon frequency with lowest SNR, or use pre-defined fixed reference station
417  double bestSNR = 0;
418  int refStationID = 0;
419  double refStationTimeStamp = 0; // GPS time (relative to event time) of reference station
420  double refStationPhases[beaconFrequencies.size()];
421 
422  for (REvent::StationIterator sIt = rEvent.StationsBegin();
423  sIt != rEvent.StationsEnd(); ++sIt) {
424  Station& station = *sIt;
425 
426  if ((fFixedReferenceStationID>0) && (station.GetId()!=fFixedReferenceStationID))
427  continue;
428 
429  // skip stations without beacon reference phases
430  bool skipStation = false;
431  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
432  if ( referencePhases[beaconFreqN].find(station.GetId()) == referencePhases[beaconFreqN].end() )
433  skipStation = true;
434  }
435  if (skipStation) {
436  //cout << "Station " << station.GetId() << " skipped because of missing reference phases!" << endl;
437  continue;
438  }
439 
440  // find beacon frequency with smallest SNR
441  double smallestSNRofFreq = 1e99;
442 
443  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
444  if (SNRs[beaconFreqN][station.GetId()] < smallestSNRofFreq)
445  smallestSNRofFreq = SNRs[beaconFreqN][station.GetId()];
446  }
447 
448  // if this is the best station so far, than store reference information
449  if (smallestSNRofFreq > bestSNR) {
450  bestSNR = smallestSNRofFreq;
451  refStationID = station.GetId();
452  refStationTimeStamp = station.GetRecData().GetParameter(eTraceStartTime);
453  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN)
454  refStationPhases[beaconFreqN] = modPhases[beaconFreqN][station.GetId()];
455  }
456 
457 
458  // Message for debugging
459  message.str("");
460  message << "SNR (in power) for station "
461  << station.GetId()
462  << " : ";
463  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN)
464  message << SNRs[beaconFreqN][station.GetId()] << " \t ";
465  if (fInfoLevel >= eInfoDebug)
466  INFO(message.str());
467  }
468 
469  // Message for debugging
470  message.str("");
471  message << "Selected station "
472  << refStationID
473  << " as reference, since its SNR (power) in the worst frequency is: "
474  << bestSNR;
475  if ((fInfoLevel >= eInfoIntermediate) && (fFixedReferenceStationID>0))
476  INFO(message.str());
477 
478  // check if SNR is sufficient
479  if (bestSNR < fMinSNR) {
480  message.str("");
481  message << "The SNR (power) of the worst frequency of the reference station is insufficient: "
482  << bestSNR
483  << " (should be >= "
484  << fMinSNR
485  << ")!";
486  if (fInfoLevel >= eInfoFinal)
487  WARNING(message.str());
488  }
489 
490 
491  // get positions and expectations for delay
492  double referenceDelay = 0; // only important if expectation from distances is used instead of reference phases
493 
494  if (fUseBeaconDistanceInsteadOfDatabaseValues) {
495 
496  const Point refStationPosition(RDetector.GetStation(refStationID).GetPosition());
497 
498  const Point beaconPosition(fBeaconPosition[0], fBeaconPosition[1], fBeaconPosition[2], Det.GetReferenceCoordinateSystem());
499 
500  //calculation of the referenceDelay
501  referenceDelay = (refStationPosition - beaconPosition).GetMag() / speedOfLight;
502 
503  //cout << "\nTime to reference station: " << referenceDelay << " ns.\n" << endl;
504  }
505 
506  // calculate phase differences and time differences
507  for (REvent::StationIterator sIt = rEvent.StationsBegin();
508  sIt != rEvent.StationsEnd(); ++sIt) {
509  Station& station = *sIt;
510 
511  timeOffsets[station.GetId()] = 0; // Reset time difference of this station
512  timeOffsetUncertainty[station.GetId()] = 99.; // Reset uncertainty
513 
514  // skip stations without beacon reference phases
515  bool skipStation = false;
516  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
517  if ( referencePhases[beaconFreqN].find(station.GetId()) == referencePhases[beaconFreqN].end() )
518  skipStation = true;
519  }
520  if (skipStation) {
521  //cout << "Station " << station.GetId() << " skipped because of missing reference phases!" << endl;
522  continue;
523  }
524 
525  // only calculate time difference if at least 2 beacon frequencies with good SNR are available
526  // also check if reference phases are available for station
527  unsigned int goodSNRfreqs = 0;
528 
529  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
530  if ((SNRs[beaconFreqN][station.GetId()] > fMinSNR) && (SNRs[beaconFreqN][refStationID] > fMinSNR))
531  ++goodSNRfreqs;
532  }
533 
534  if (goodSNRfreqs < fMinGoodFreqs) {
535  message.str("");
536  message << "Station " << station.GetId() << " has " << goodSNRfreqs
537  << " beacon signals with good SNR. At least "
538  << fMinGoodFreqs << " are requiered."
539  << " No timing correction possible.";
540  if (fInfoLevel >= eInfoFinal)
541  WARNING(message.str());
542  // set time offset for this station to 0, i.e. perform no timing correction
543  timeOffsets[station.GetId()] = 0;
544  continue; // next station
545  }
546 
547  // Take possible difference of GPS time stamps into account
548  double timeStampOffsetGPS = station.GetRecData().GetParameter(eTraceStartTime) - refStationTimeStamp; // ns = Auger base unit
549 
550  // in rare cases the GPS time stamp of the station does not match the GPS time stamp of the event
551  // --> ignore those stations, if mismatch is larger than 0.01 seconds (corresponds to 3000 km light travel)
552  if (abs(timeStampOffsetGPS) > 1e7) {
553  message.str("");
554  message << "Trace start time of station "
555  << station.GetId()
556  << " is "
557  << timeStampOffsetGPS
558  << " ns larger than event time stamp! --> Station ignored!";
559  if (fInfoLevel >= eInfoFinal)
560  WARNING(message.str());
561  continue;
562  }
563 
564 
565  // semi-analytically find maximum of cross-correlation
566  // this is the shift tau, for which the following sum is maximum:
567  // sum of [freq_i * cos(phasediff_i - omega_i*tau)]
568 
569  if (fUseCrossCorrelationMethod) {
570  double expectedDelay = 0; // only important if expectation from distances is used instead of reference phases
571 
572  // get delay to station and relative to reference stationID
573  if (fUseBeaconDistanceInsteadOfDatabaseValues) {
574  const Point stationPosition(RDetector.GetStation(station.GetId()).GetPosition());
575 
576  const Point beaconPosition(fBeaconPosition[0], fBeaconPosition[1], fBeaconPosition[2], Det.GetReferenceCoordinateSystem());
577 
578  expectedDelay = (stationPosition - beaconPosition).GetMag() / speedOfLight - referenceDelay;
579  }
580  //cout << "\nExpected delay for station " << station.GetId() << " (relative to RefStation): " << expectedDelay << " ns." << endl;
581 
582  // search for maximum in different step sizes
583  const double mainstepsize = 0.5; // stepsize in ns for rough search of maxima
584  const double finestepsize = 0.01; // stepsize in ns for fine determination of maxima
585  double maxShiftValue = 0;
586  double lastSum = -1e99;
587  double secondLastSum = -1e99;
588  double currentMaxSum = -1e99;
589  for (double shift = - fMaxTimeDifference; shift <= fMaxTimeDifference; shift += mainstepsize) {
590  double currentSum = 0;
591  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
592  double phasediff = phases[beaconFreqN][station.GetId()] - phases[beaconFreqN][refStationID]
593  - timeStampOffsetGPS * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN])
594  - shift * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
595  if (fUseBeaconDistanceInsteadOfDatabaseValues)
596  phasediff += expectedDelay * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
597  else
598  phasediff += referencePhases[beaconFreqN][refStationID] - referencePhases[beaconFreqN][station.GetId()];
599 
600  // use phases calculated by distance to beacon
601  // double phasediff = phases[beaconFreqN][station.GetId()] - phases[beaconFreqN][refStationID]
602  // - timeStampOffsetGPS * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN])
603  // - (shift-expectedDelay) * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
604  // use reference phase from data base
605  // double phasediff = phases[beaconFreqN][station.GetId()] - referencePhases[beaconFreqN][station.GetId()]
606  // - phases[beaconFreqN][refStationID] + referencePhases[beaconFreqN][refStationID]
607  // - timeStampOffsetGPS * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN])
608  // - shift * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
609 
610  // frequency factor comes from analytic calculation of cross-correlation integral:
611  // --> try without this factor, to give all frequencies equal weight
612  // instead reduce weight for frequencies with small SNR (for station and reference station
613  double weight = 1.;
614  if (SNRs[beaconFreqN][station.GetId()] < fMinSNR)
615  weight *= sqrt(SNRs[beaconFreqN][station.GetId()]/fMinSNR);
616  if (SNRs[beaconFreqN][refStationID] < fMinSNR)
617  weight *= sqrt(SNRs[beaconFreqN][refStationID]/fMinSNR);
618  currentSum += weight*cos(phasediff);// * beaconFreqsInSpectrum[beaconFreqN];
619 
620  //cout << "Sum for shift of " << shift << " ns: " << currentSum << endl;
621  }
622 
623  // look if local maximum was found, then do fine search
624  if ((lastSum>currentSum)&&(lastSum>secondLastSum)) {
625  for (double fineshift = shift-2*mainstepsize; fineshift < shift; fineshift += finestepsize) {
626  double newFineSearchSum = 0;
627  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
628  double phasediff = phases[beaconFreqN][station.GetId()] - phases[beaconFreqN][refStationID]
629  - timeStampOffsetGPS * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN])
630  - fineshift * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
631  if (fUseBeaconDistanceInsteadOfDatabaseValues)
632  phasediff += expectedDelay * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
633  else
634  phasediff += referencePhases[beaconFreqN][refStationID] - referencePhases[beaconFreqN][station.GetId()];
635 
636  double weight = 1.;
637  if (SNRs[beaconFreqN][station.GetId()] < fMinSNR)
638  weight *= sqrt(SNRs[beaconFreqN][station.GetId()]/fMinSNR);
639  if (SNRs[beaconFreqN][refStationID] < fMinSNR)
640  weight *= sqrt(SNRs[beaconFreqN][refStationID]/fMinSNR);
641  newFineSearchSum += weight*cos(phasediff);
642  }
643 
644  if (newFineSearchSum > currentMaxSum) {
645  maxShiftValue = fineshift;
646  currentMaxSum = newFineSearchSum;
647  }
648  }
649  } // if ((lastSum>currentSum)&&(lastSum>secondLastSum))
650 
651  // save old values for last to steps
652  secondLastSum = lastSum;
653  lastSum = currentSum;
654  } // for (double shift = - fMaxTimeDifference; shift <= fMaxTimeDifference; shift += mainstepsize)
655  timeOffsets[station.GetId()] = maxShiftValue;
656  timeOffsetUncertainty[station.GetId()] = 0;
657 
658  } else { // if (fUseCrossCorrelationMethod)
659 
660  // Determine time difference, starting with a time offset of 0
661  double timeOffset = 0;
662 
663  // search as long as the time offset is in the allowed range
664  // while loop is quit by "break" if correct time difference is found
665  while ( abs(timeOffset) <= fMaxTimeDifference) {
666 
667  // calculate time difference for each beacon frequency
668  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
669  double phasediff = modPhases[beaconFreqN][station.GetId()] - refStationPhases[beaconFreqN]
670  - timeOffset * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN])
671  - timeStampOffsetGPS * (kTwoPi * beaconFreqsInSpectrum[beaconFreqN]);
672 
673  // due to GPS time stamp offsets, phase differences can be much larger than +/- pi
674  while (phasediff > kPi)
675  phasediff -= kTwoPi;
676  while (phasediff < -kPi)
677  phasediff += kTwoPi;
678 
679  double timediff = phasediff / ( kTwoPi * beaconFreqsInSpectrum[beaconFreqN] ) + timeOffset;
680  timeDiffsFreq[beaconFreqN][station.GetId()] = timediff;
681  }
682 
683  // put all usable time differences for this station in one vector
684  vector<double> stationTimeDiffs;
685  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN)
686  if ((SNRs[beaconFreqN][station.GetId()] > fMinSNR) && (SNRs[beaconFreqN][refStationID] > fMinSNR))
687  stationTimeDiffs.push_back(timeDiffsFreq[beaconFreqN][station.GetId()]);
688 
689 
690  // Debug output write time differences for this station
691  message.str("");
692  message << "Timediffs for station "
693  << station.GetId()
694  << " [ns]: ";
695  for (unsigned int beaconFreqN=0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN)
696  message << timeDiffsFreq[beaconFreqN][station.GetId()] << " \t";
697  if (fInfoLevel >= eInfoDebug)
698  INFO(message.str());
699 
700  // test if all time differences with valid SNR are within the acceptable range (epsilon)
701  // and calculate absolute mean deviation
702  double meanTdiff = accumulate(stationTimeDiffs.begin(), stationTimeDiffs.end(), 0.) / double(stationTimeDiffs.size());
703  double deviationFromMean = 0;
704  // message for debugging
705  message.str("");
706  message << "Mean tdiff = "
707  << meanTdiff
708  << " ns, deviations per beacon freq: ";
709 
710  bool tDiffsGood = true;
711  for (vector<double>::iterator it = stationTimeDiffs.begin();
712  it != stationTimeDiffs.end(); ++it) {
713  message << abs(*it - meanTdiff)
714  << " \t";
715  deviationFromMean += abs(*it - meanTdiff) / stationTimeDiffs.size();
716 
717  // test if all time differences agree within the allowed range (epsilon)
718  if (abs(*it - meanTdiff) > fEpsilon)
719  tDiffsGood = false;
720  }
721  if (fInfoLevel >= eInfoDebug) {
722  INFO(message.str());
723  message.str("");
724  message << "Absolute mean deviation = "
725  << deviationFromMean
726  << " ns.";
727  INFO(message.str());
728  }
729 
730  // If all time differences agree within the allowed range (epsilon), we are done
731  // if not, try a different time offset (alternating + and -), and try again, if
732  // the resulting time differences at each beacon frequency are consistent within epsilon.
733  if(tDiffsGood) {
734  timeOffsets[station.GetId()] = meanTdiff;
735  timeOffsetUncertainty[station.GetId()] = deviationFromMean;
736  break;
737  } else {
738  if (timeOffset > 0.) {
739  timeOffset *= -1.;
740  } else {
741  timeOffset *= -1.;
742  timeOffset += 12.*nanosecond;
743  // TODO: is 12 ns a useful step size, can it be larger?
744  // assumption: as long as it is shorter than the period of the highest frequency, it should be ok
745  // 80 MHz --> 12.5 ns, thus 12 ns should be ok, but probably it could be even larger
746  }
747  }
748  } // end of while
749  } // else (fUseCrossCorrelationMethod)
750  } // for (REvent::StationIterator sIt ...
751 
752 
753  // change trace start time of stations
754  for (auto sIt = rEvent.StationsBegin(); sIt != rEvent.StationsEnd(); ++sIt) {
755  Station& station = *sIt;
756 
757  // apply beacon correction only if time offset could be determined successfully
758  if (timeOffsetUncertainty[station.GetId()] < 99.) { // is set to 99 correction fails
759  // station.SetTraceStartTime(station.GetTraceStartTime() + timeOffsets[station.GetId()]);
760  station.GetRecData().SetParameter(eTraceStartTime, station.GetRecData().GetParameter(eTraceStartTime) + timeOffsets[station.GetId()], false);
761  station.GetRecData().SetParameterError(eTraceStartTime,fBeaconTimeCalibrationUncertainty, false);
762  // store value that has been added to the trace start time
763  station.GetRecData().SetParameter(eTraceStartTimeCorrectionByBeacon, timeOffsets[station.GetId()]);
764  // also change relative position of signal search window accordingly
765  station.GetRecData().SetParameter(eSignalSearchWindowStart, station.GetRecData().GetParameter(eSignalSearchWindowStart) - timeOffsets[station.GetId()], false);
766  // also change relative position of signal search window accordingly
767  station.GetRecData().SetParameter(eSignalSearchWindowStop, station.GetRecData().GetParameter(eSignalSearchWindowStop) - timeOffsets[station.GetId()], false);
768 
769  message.str("");
770  message << "Shifted trace starttime of station "
771  << station.GetId()
772  << " by "
773  << timeOffsets[station.GetId()]
774  << " ns; \tuncert. ~ "
775  << timeOffsetUncertainty[station.GetId()]
776  << " ns";
777  if (fInfoLevel >= eInfoIntermediate)
778  INFO(message.str());
779 
780  // add statistics
781  --fBeaconCorrectionFailures[station.GetId()]; // at the beginning a failure is assumed, and substracted, if this point is reached
782  ++fBeaconCorrectionSuccesses[station.GetId()];
783  } else {
784  if (fRejectIfCorrectionFailed)
786  message.str("");
787  message << "Shifted trace starttime of station "
788  << station.GetId()
789  << " by 0 ns - Beacon correction failed!";
790  if (fRejectIfCorrectionFailed)
791  message << " Station will be rejected.\n";
792  else
793  message << "\n.";
794  if (fInfoLevel >= eInfoIntermediate)
795  INFO(message.str());
796  }
797  }
798 
799  // equalize time stamps of stations (if different, and if wanted)
800  // by multiplying a phase gradient to each spectrum
801  if (fEqualizeStationTimeStamps)
802  matchStationTimeStamps(rEvent);
803 
804  // write debug output to file, if filename is given in XML file
805  if (fDebugStationIds.size() > 0)
806  if (!writeDebugFile(refStationID, timeOffsets, timeOffsetUncertainty, rEvent.GetHeader().GetTime()+ refStationTimeStamp)) {
807  message.str("");
808  message << "Error while writing debug file: "
809  << fDebugOutputFile;
810  ERROR(message.str());
811  return eFailure;
812  }
813 
814  }
815 
816  // remember that module already has been called (important for debug output)
817  fFirstModuleCall = false;
818 
819  return eSuccess;
820  }
821 
822 
824  RdChannelBeaconTimingCalibrator::Finish()
825  {
826  INFOFinal("Finish()");
827 
828  ostringstream info;
829  info << "Statistics of Beacon correction:\n"
830  "Station ID #successes #failures SNR(freq1) SNR(freq2) SNR(freq3) SNR(freq4)\n"
831  "--------------------------------------------------------------------------------------------\n";
832 
833  for (const auto& ie : fBeaconCorrectionFailures) {
834  const auto id = ie.first;
835  info << " " << id << " \t"
836  << fBeaconCorrectionSuccesses[id] << " \t "
837  << fBeaconCorrectionFailures[id] << " \t "
838  << fBeaconSNRs[id][0] / fBeaconSNRcounter[id] << " \t "
839  << fBeaconSNRs[id][1] / fBeaconSNRcounter[id] << " \t "
840  << fBeaconSNRs[id][2] / fBeaconSNRcounter[id] << " \t "
841  << fBeaconSNRs[id][3] / fBeaconSNRcounter[id] << '\n';
842  }
843 
844  info << "--------------------------------------------------------------------------------------------";
845  INFO(info);
846  return eSuccess;
847  }
848 
849 
850  std::vector<std::map<int, double> >
851  RdChannelBeaconTimingCalibrator::getReferencePhases(std::vector<double> beaconFrequencies)
852  {
853  static std::vector<std::map<int, double> > referencePhases;
854 
855  // check, if reference phases have already been read from file
856  if (referencePhases.size() > 0)
857  return referencePhases;
858 
859  // check if name of text file with reference phases is provided,
860  // otherwise read reference phase from database
861 
862  // Create file name containing frequency
863  ifstream phasefile;
864  phasefile.open(fInputPhaseFile.c_str());
865 
866  stringstream message;
867  if ((phasefile.is_open()) && (phasefile.good())) {
868  message.str("");
869  message << "Reading reference phases from file: "
870  << fInputPhaseFile;
871  if (fInfoLevel >= eInfoDebug)
872  INFO(message.str());
873  } else {
874  message.str("");
875  message << "Cannot open file for reference phases: "
876  << fInputPhaseFile;
877  ERROR(message.str());
878  return referencePhases;
879  }
880 
881  // read file header to check consistency
882  stringstream headerDummy;
883  string readString;
884  phasefile >> readString;
885 
886  if (readString != "Station") {
887  ERROR("Wrong format of file header");
888  phasefile.close();
889  return referencePhases;
890  }
891 
892  for (unsigned int beaconFreqN = 0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
893  if (!phasefile.good() ) {
894  ERROR("Wrong format of file header");
895  return referencePhases;
896  }
897  // test header content (do beacon frequencies match?)
898  phasefile >> readString;
899  headerDummy.str("");
900  headerDummy << "RefPhase[rad]_for_" << beaconFrequencies[beaconFreqN]/megahertz << "MHz";
901  if (readString != headerDummy.str()) {
902  if (fBeaconFrequencies.size() < 1)
903  ERROR("Beacon frequencies in file header do not match frequencies read from database! Maybe only the order of the frequencies is wrong.");
904  else
905  ERROR("Beacon frequencies in file header do not match XML file!");
906  phasefile.close();
907  return referencePhases;
908  }
909  }
910 
911  // loop through all lines and read the station and the reference phases
912  referencePhases = vector<map<int, double> > (beaconFrequencies.size()); // delete previous content of vector
913 
914  while (phasefile.good()) {
915  unsigned int stationID=0;
916  phasefile >> stationID;
917  // check if there is still a line in the file
918  if (!phasefile.good())
919  break;
920  for (unsigned int beaconFreqN = 0; beaconFreqN < beaconFrequencies.size(); ++beaconFreqN) {
921  double refPhase = 0;
922  phasefile >> refPhase;
923  referencePhases[beaconFreqN][stationID] = refPhase;
924  }
925  }
926 
927  phasefile.close();
928 
929  return referencePhases;
930  }
931 
932 
933  void
934  RdChannelBeaconTimingCalibrator::matchStationTimeStamps(revt::REvent& rEvent) const
935  {
936  // store time stamp of the first station as reference
937  double firstTimeStamp = rEvent.StationsBegin()->GetRecData().GetParameter(eTraceStartTime);
938  // loop through all stations:
939  // shift traces if the time stamp does not match the one of the first station
940  for (auto sIt = rEvent.StationsBegin(); sIt != rEvent.StationsEnd(); ++sIt) {
941  Station& station = *sIt;
942  double stationTimeStamp = station.GetRecData().GetParameter(eTraceStartTime);
943 
944  if (stationTimeStamp != firstTimeStamp) {
945  // correct for the difference and set new time stamp
946  for (Station::ChannelIterator cIt = station.ChannelsBegin();
947  cIt != station.ChannelsEnd(); ++cIt){
948  Channel& channel = *cIt;
949 
950  FFTDataContainerAlgorithm::ShiftTimeSeries(channel.GetFFTDataContainer(), stationTimeStamp-firstTimeStamp);
951  }
952 
953  // set trace start time, and change relative position of signal search window accordingly
954  // since the signal and the trace start time are shifted consistingly, there is no correction value stored for the trace start time
955  station.GetRecData().SetParameter(eTraceStartTime,firstTimeStamp, false);
956  station.GetRecData().SetParameter(eSignalSearchWindowStart, station.GetRecData().GetParameter(eSignalSearchWindowStart) + (stationTimeStamp-firstTimeStamp), false);
957  station.GetRecData().SetParameter(eSignalSearchWindowStop, station.GetRecData().GetParameter(eSignalSearchWindowStop) + (stationTimeStamp-firstTimeStamp), false);
958  }
959  }
960  }
961 
962 
963  bool
964  RdChannelBeaconTimingCalibrator::writeDebugFile(const int& refStationID,
965  const std::map<int,double>& timeOffsets,
966  const std::map<int,double>& timeUncertainties,
967  const utl::TimeStamp& eventGPStimeStamp) const
968  {
969  // When the beacon module is called for the first time, the file should not exist.
970  // Thus, test if file exists, and if not, create file header
971  if (fFirstModuleCall) {
972  if (!fOverwriteDebugFile) {
973  ifstream testReading;
974  testReading.open(fDebugOutputFile.c_str());
975  if (testReading.is_open()) {
976  stringstream message;
977  message << "Debug file '"
978  << fDebugOutputFile
979  << "' already exists! No debug output written!\n";
980  ERROR(message.str());
981  return false; // found error
982  }
983  testReading.close();
984  }
985 
986  // create file header
987  ofstream debugFileHeaderWriting(fDebugOutputFile.c_str());
988  debugFileHeaderWriting << "GPStime[s] \tRefStationID";
989  for (set<int>::iterator it=fDebugStationIds.begin(); it != fDebugStationIds.end(); ++it)
990  debugFileHeaderWriting << " \t" << *it << "_offset[ns] \t" << *it << "_uncert[ns]";
991  debugFileHeaderWriting << endl;
992  debugFileHeaderWriting.close();
993  }
994 
995  // append event to file
996  ofstream outputfile;
997  outputfile.open(fDebugOutputFile.c_str(), ofstream::app);
998 
999  // check if file could be opened
1000  if (!(outputfile.is_open())) {
1001  stringstream message;
1002  message << "Failed to open beacon debug file: "
1003  << fDebugOutputFile;
1004  ERROR(message.str());
1005  return false;
1006  }
1007 
1008  // time stamp and reference station ID
1009  outputfile << eventGPStimeStamp.GetGPSSecond() << "."
1010  << setfill ('0') << setw(9) << int(round(eventGPStimeStamp.GetGPSNanoSecond()))
1011  << " \t" << refStationID;
1012 
1013  // loop through station IDs and write offsets and uncertainties to file
1014  for (auto it = fDebugStationIds.begin(); it != fDebugStationIds.end(); ++it) {
1015  // check if station exists for this event
1016  if ( timeUncertainties.find(*it) != timeUncertainties.end() ) {
1017  // check if beacon correction worked
1018  if ( timeUncertainties.find(*it)->second != 99. )
1019  outputfile << " \t" << setfill (' ') << setw(7) << timeOffsets.find(*it)->second
1020  << " \t" << setfill (' ') << setw(7) << timeUncertainties.find(*it)->second;
1021  else
1022  outputfile << " \t" << " xxx " << " \t" << " xxx ";
1023  } else {
1024  outputfile << " \t" << " --- " << " \t" << " --- ";
1025  }
1026  }
1027  outputfile << endl;
1028  outputfile.close();
1029 
1030  return true; // everything ok
1031  }
1032 
1033 }
ChannelFFTDataContainer & GetFFTDataContainer()
retrieve Channel FFTDataContainer (write access)
void SetParameterError(Parameter i, double value, bool lock=true)
double GetBeaconReferencePhase(const int stationId, const double beaconFreq) const
Get beacon reference phases for one station.
Definition: RDetector.cc:197
Point object.
Definition: Point.h:32
int GetId() const
Return Id of the Channel.
StationRecData & GetRecData()
Get station level reconstructed data.
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
utl::TimeStamp GetTime() const
Definition: REvent/Header.h:17
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
StationIterator StationsEnd()
Definition: REvent.h:130
StationIterator StationsBegin()
Definition: REvent.h:128
const double speedOfLight
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
ChannelIterator ChannelsBegin()
begin Channel iterator for read/write
boost::filter_iterator< StationFilter, AllStationIterator > StationIterator
Iterator over all (non-exculded) stations.
Definition: REvent.h:125
bool HasREvent() const
int GetStationId() const
Return Id of the station to which this Channel belongs.
const std::vector< double > & GetBeaconFrequencies() const
Get vector of Beacon Frequencies for given detector-time from Manager.
Definition: RDetector.cc:183
ChannelIterator ChannelsEnd()
end Channel iterator for read/write
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
Exception to use in case requested data not found in the database with detailed printout.
class to hold data at the radio Station level.
std::vector< std::complex< double > >::size_type SizeType
Definition: Trace.h:58
constexpr double kPi
Definition: MathConstants.h:24
constexpr double nanosecond
Definition: AugerUnits.h:143
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 kTwoPi
Definition: MathConstants.h:27
int GetNumberOfStations() const
Get total number of stations in the event.
Definition: REvent.h:206
constexpr double megahertz
Definition: AugerUnits.h:155
#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)
int GetId() const
Get the station Id.
boost::filter_iterator< StationFilter, ConstAllStationIterator > ConstStationIterator
Definition: REvent.h:126
double GetParameter(const Parameter i) const
Channel & GetChannel(const int pmtId)
Retrieve a Channel by Id.
constexpr double kSpeedOfLight
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
double GetGPSNanoSecond() const
GPS nanosecond.
Definition: TimeStamp.h:127
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
Header file holding the RD Event Trigger class definition (based on SD)
Definition: REvent/Header.h:14
utl::CoordinateSystemPtr GetReferenceCoordinateSystem() const
Get the reference coordinate system used for analysis (usually PampaAmarilla for Auger) ...
Definition: Detector.h:141
ChannelFrequencySpectrum & GetChannelFrequencySpectrum()
retrieve Channel Frequency Spectrum (write access, only use this if you intend to change the data) ...
double GetFrequencyOfBin(const ChannelFrequencySpectrum::SizeType bin) const
Get the frequency corresponding to a bin of the frequency spectrum.
void SetParameter(Parameter i, double value, bool lock=true)
Class that holds the data associated to an individual radio channel.
const rdet::RDetector & GetRDetector() const
Definition: Detector.cc:143
bool HasStation(const int stationId) const
Check whether station exists.
Definition: REvent.cc:132
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
#define INFOFinal(y)
Definition: VModule.h:161
void PushBack(const T &value)
Insert a single value at the end.
Definition: Trace.h:119
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
int GetId() const
Definition: REvent/Header.h:21
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)

, generated on Tue Sep 26 2023.