RdChannelSineWaveSuppressor.cc
Go to the documentation of this file.
2 #include <utl/ErrorLogger.h>
3 
4 #include <fwk/CentralConfig.h>
5 
6 #include <evt/Event.h>
7 #include <revt/REvent.h>
8 #include <evt/ShowerRecData.h>
9 #include <evt/ShowerRRecData.h>
10 #include <revt/Header.h>
11 #include <revt/Station.h>
12 #include <revt/Channel.h>
13 #include <revt/StationRecData.h>
14 
15 #include <rdet/RDetector.h>
16 #include <rdet/Channel.h>
17 
18 #include <utl/Trace.h>
19 #include <utl/TraceAlgorithm.h>
20 #include <utl/Reader.h>
21 #include <utl/config.h>
22 #include <utl/AugerUnits.h>
23 #include <utl/Math.h>
24 
25 #include <TMath.h>
26 #include <TMinuit.h>
27 
28 using namespace std;
29 using namespace utl;
30 using namespace fwk;
31 using namespace revt;
32 using namespace rdet;
33 
34 
36 
37  REvent* RdChannelSineWaveSuppressor::fgCurrentREvent;
38  int RdChannelSineWaveSuppressor::fgCurrentStation;
39  int RdChannelSineWaveSuppressor::fgCurrentChannel;
40  int RdChannelSineWaveSuppressor::fgFitWindow;
41  unsigned int RdChannelSineWaveSuppressor::fgSignalStart;
42  unsigned int RdChannelSineWaveSuppressor::fgSignalStop;
43  unsigned int RdChannelSineWaveSuppressor::fgNoiseStart;
44  unsigned int RdChannelSineWaveSuppressor::fgNoiseStop;
45 
46 
49  {
50  INFO("RdChannelSineWaveSuppressor::Init()");
51 
52  // Read in the configurations of the xml file
53  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdChannelSineWaveSuppressor");
54  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
55 
56  topBranch.GetChild("ScanWindowSize").GetData(fScanWindowSize);
57  topBranch.GetChild("NoiseInterval").GetData(fNoiseInterval);
58  topBranch.GetChild("FitWindow").GetData(fgFitWindow);
59 
60  if (fNoiseInterval >= 1.0) {
61  ERROR("<NoiseInterval> must be a fraction smaller than one");
62  return eFailure;
63  }
64 
65  if (fgFitWindow > 3) {
66  ERROR("<FitWindow> out of bounds");
67  return eFailure;
68  }
69  return eSuccess;
70  }
71 
72 
74  RdChannelSineWaveSuppressor::Run(evt::Event& event)
75  {
76  INFO("RdChannelSineWaveSuppressor::Run()");
77 
78  REvent& rEvent = event.GetREvent();
79  fgCurrentREvent = &rEvent;
80  ostringstream info;
81 
82  // Loop over all stations and channels
83  for (auto& station : rEvent.StationsRange()) {
84 
85  fgCurrentStation = station.GetId();
86 
87  for (auto& channel : station.ChannelsRange()) {
88 
89  if (!channel.IsActive())
90  continue;
91 
92  fgCurrentChannel = channel.GetId();
93 
94  const revt::ChannelFrequencySpectrum& spectrum = channel.GetChannelFrequencySpectrum();
95  double spectrumBinning = spectrum.GetBinning();
96  const rdet::RDetector& rDetector = det::Detector::GetInstance().GetRDetector();
97  const rdet::Channel& detChannel =
98  rDetector.GetStation(station.GetId()).GetChannel(channel.GetId());
99  const double lowerDesignFreq = detChannel.GetDesignLowerFreq();
100  const double upperDesignFreq = detChannel.GetDesignUpperFreq();
101  unsigned int lowerBin = (int)(lowerDesignFreq/spectrumBinning);
102  unsigned int upperBin = (int)(upperDesignFreq/spectrumBinning);
103  int WindowSize;
104 
105  if (fScanWindowSize > upperBin-lowerBin) {
106  ostringstream warn;
107  warn << "<ScanWindowSize> too big, window size set to full spectrum width ("
108  << (upperBin - lowerBin) << " bins)";
109  WARNING(warn);
110  WindowSize = upperBin - lowerBin;
111  } else
112  WindowSize = fScanWindowSize;
113 
114  const unsigned int centralBin = WindowSize/2 + 1;
115  vector<double> vSlidingWindow;
116  vector<double> vThreshold;
117  vector<double> vMaxLikelihood;
118  vector<int> vRFIBins;
119  double RFIThreshold = 0;
120  double squaredSum = 0;
121  double maxLikelihood = 0;
122 
123  // Caluclate argument of CDF on sample level assuming Rayleigh distribution of noise spectrum
124  double InvSampleProp = 1 - pow(fNoiseInterval, 1. / (upperBin - lowerBin));
125  double CDFarg = -log(InvSampleProp);
126 
127  // Move sliding window over frequency spectrum to find RFI frequencies
128  for (ChannelFrequencySpectrum::SizeType i = lowerBin; i < lowerBin+WindowSize; ++i) {
129  vSlidingWindow.push_back(abs(spectrum[i]));
130  squaredSum += Sqr(abs(spectrum[i]));
131  }
132 
133  maxLikelihood = sqrt(squaredSum / (2*WindowSize));
134  RFIThreshold = sqrt(CDFarg * 2 * Sqr(maxLikelihood));
135 
136  for (vector<double>::size_type i = 0; i <= centralBin; ++i) {
137  if (vSlidingWindow[i] > RFIThreshold) {
138  vRFIBins.push_back(lowerBin + i);
139  vThreshold.push_back(RFIThreshold);
140  vMaxLikelihood.push_back(maxLikelihood);
141  }
142  }
143 
144  for (ChannelFrequencySpectrum::SizeType i = lowerBin+WindowSize; i <= upperBin; ++i) {
145  squaredSum += Sqr(vSlidingWindow.front()) + Sqr(abs(spectrum[i]));
146  maxLikelihood = sqrt(squaredSum / (2 * WindowSize));
147  RFIThreshold = sqrt(CDFarg * 2 * Sqr(maxLikelihood));
148  vSlidingWindow.erase(vSlidingWindow.begin());
149  vSlidingWindow.push_back(abs(spectrum[i]));
150 
151  if (vSlidingWindow[centralBin] > RFIThreshold) {
152  vRFIBins.push_back(i - WindowSize + centralBin + 1);
153  vThreshold.push_back(RFIThreshold);
154  vMaxLikelihood.push_back(maxLikelihood);
155  }
156  }
157 
158  for (vector<double>::size_type i = centralBin; i < vSlidingWindow.size(); ++i) {
159  if (vSlidingWindow[i] > RFIThreshold) {
160  vRFIBins.push_back(upperBin - WindowSize + i + 1);
161  vThreshold.push_back(RFIThreshold);
162  vMaxLikelihood.push_back(maxLikelihood);
163  }
164  }
165 
166  // Just suppose nothing is above threshold, continue with next channel
167  if (vRFIBins.empty()) {
168  info << "No RFI identified in channel " << channel.GetId();
169  INFOIntermediate(info);
170  continue;
171  }
172 
173  int PeakWidth = 1;
174  int PeakBin;
175  vector<int> vFitBins;
176 
177  // Select highest bins from RFI sources wider than one bin
178  for (vector<int>::size_type i = 0; i < vRFIBins.size(); ++i) {
179  if (i < vRFIBins.size() - 1) {
180  if (vRFIBins[i+1] - vRFIBins[i] == 1)
181  ++PeakWidth;
182  else {
183  PeakBin = vRFIBins[i - PeakWidth + 1];
184  for (vector<int>::size_type j = i - PeakWidth + 1; j <= i; ++j) {
185  if (abs(spectrum[vRFIBins[j]]) > abs(spectrum[PeakBin]))
186  PeakBin = vRFIBins[j];
187  }
188  vFitBins.push_back(PeakBin);
189  PeakWidth = 1;
190  }
191  } else { // Take care of last element
192  PeakBin = vRFIBins[i - PeakWidth + 1];
193  for (vector<int>::size_type j = i - PeakWidth + 1; j <= i; ++j) {
194  if (abs(spectrum[vRFIBins[j]]) > abs(spectrum[PeakBin]))
195  PeakBin = vRFIBins[j];
196  }
197  vFitBins.push_back(PeakBin);
198  }
199  }
200 
201  // Sort RFI sources to fit strongest contribution first
202  if (vFitBins.size() > 1) {
203  RdChannelSineWaveSuppressor::RFISort(vFitBins, 0, vFitBins.size() - 1);
204  }
205 
206  info << "Identified RFI frequencies in channel " << channel.GetId()
207  << " of station " << station.GetId() << " in decreasing order of strength:";
208  INFOIntermediate(info);
209 
210  for (auto& elem : vFitBins) {
211  info << elem * spectrumBinning/MHz << " MHz ";
212  INFODebug(info);
213  }
214  INFODebug("\n");
215 
216  revt::ChannelTimeSeries& trace = channel.GetChannelTimeSeries();
217  double samplingFrequency = 1. / trace.GetBinning();
218 
219  // Set fitting globals defining windows
220  fgSignalStart = station.GetRecData().GetParameter(revt::eSignalSearchWindowStart)*samplingFrequency;
221  fgSignalStop = station.GetRecData().GetParameter(revt::eSignalSearchWindowStop)*samplingFrequency;
222  fgNoiseStart = station.GetRecData().GetParameter(revt::eNoiseWindowStart)*samplingFrequency;
223  fgNoiseStop = station.GetRecData().GetParameter(revt::eNoiseWindowStop)*samplingFrequency;
224 
225  // Loop over all RFI frequencies and perform the fit for each of them
226  for (unsigned int j = 0; j < vFitBins.size(); ++j) {
227 
228  // Set fit threshold for fitting fequency and find noise level in vicinity of RFI bin
229  double FitThreshold = 0;
230  double FitNoise = 0;
231  for (vector<int>::size_type i = 0; i < vRFIBins.size(); ++i) {
232  if (vFitBins[j] == vRFIBins[i]) {
233  FitThreshold = vThreshold[i];
234  FitNoise = vMaxLikelihood[i];
235  break;
236  }
237  }
238 
239  // Calculate fit limits and estimate fit values
240  double FitFreq = vFitBins[j] * spectrumBinning;
241  double Freqmin = FitFreq - 0.5*spectrumBinning;
242  double Freqmax = FitFreq + 0.5*spectrumBinning;
243 
244  // spectrum corrected for noise level, estimate when frequency is in middle of bin, so mimimum leakage
245  double AmpEst = (abs(spectrum[vFitBins[j]]) - FitNoise)*spectrumBinning*2.0;
246  // average of noise floor (based on Rayleigh distribution)
247  double Ampmin = FitNoise * spectrumBinning;
248  //spectrum corrected for noise level, maximum spectral leakage
249  double Ampmax = abs(spectrum[vFitBins[j]]) * spectrumBinning*TMath::Pi() - FitNoise*spectrumBinning*2.0;
250 
251  double PhaseEst = arg(spectrum[vFitBins[j]]) + FitFreq/samplingFrequency*2*TMath::Pi();
252 
253  TMinuit minuit(3);
254  double argList[10];
255  int errFlag = 0;
256  argList[0] = -1;
257 
258  if (fInfoLevel >= eInfoDebug) {
259  minuit.mnexcm("SET PRINTOUT", argList, 1, errFlag);
260  minuit.mnexcm("SET NOWARNINGS", argList, 0, errFlag);
261  }
262 
263  // Set minimization function and parameters
264  minuit.SetFCN(RdChannelSineWaveSuppressor::SineFitFnc);
265  argList[0] = 1;
266  minuit.mnexcm("SET ERRORDEF", argList, 1, errFlag);
267  minuit.mnparm(0, "amp", AmpEst, 0.00001, Ampmin, Ampmax, errFlag);
268  minuit.mnparm(1, "freq", FitFreq, 0.000001, Freqmin, Freqmax, errFlag);
269  minuit.mnparm(2, "phase", PhaseEst, 0.00001, 0, 0, errFlag);
270 
271  // Perform minimization
272  argList[0] = 5;
273  minuit.mnexcm("CALI", argList, 1, errFlag);
274  argList[0] = 500;
275  minuit.mnexcm("MINIMIZE", argList, 1, errFlag);
276 
277  // Get fit results (errors not implemented yet)
278  double amp = 0;
279  double freq = 0;
280  double phase = 0;
281  double foo = 0;
282 
283  minuit.GetParameter(0, amp, foo);
284  minuit.GetParameter(1, freq, foo);
285  minuit.GetParameter(2, phase, foo);
286 
287  // Substract fitted wave from time series if fitted amplitude large enough
288  if (amp > FitThreshold * spectrumBinning) {
289  for (ChannelTimeSeries::SizeType i = 0; i < trace.GetSize(); ++i) {
290  trace[i] = trace[i] - amp*sin(i/samplingFrequency*freq*2*TMath::Pi() + phase);
291  }
292  info << "Substracted sine wave from channel " << channel.GetId()
293  << " of station " << station.GetId() << " with frequency "
294  << freq/MHz << " MHz, amplitude " << amp*1e6
295  << " muV/m and phase " << phase/TMath::Pi() << " pi.";
296  INFODebug(info);
297  } else {
298  info << "Fit failed for RFI source from channel " << channel.GetId()
299  << " of station " << station.GetId() << " with frequency "
300  << FitFreq/MHz << " MHz. Fitted amplitude of " << amp*1e6
301  << " muV/m is lower than RFI threshold of "
302  << FitThreshold*spectrumBinning*1e6 << " muV/m.";
303  INFODebug(info);
304  }
305  }
306  }
307  }
308  return eSuccess;
309  }
310 
311 
313  RdChannelSineWaveSuppressor::Finish()
314  {
315  INFO("RdChannelSineWaveSuppressor::Finish()");
316 
317  return eSuccess;
318  }
319 
320 
321  void
322  RdChannelSineWaveSuppressor::SineFitFnc(int& /*nPar*/, double* const /*grad*/, double& value,
323  double* const par, const int /*flag*/)
324  {
325  const double& amp = par[0];
326  const double& freq = par[1];
327  const double& phase = par[2];
328  double Chi2 = 0;
329  const revt::ChannelTimeSeries& trace =
330  fgCurrentREvent->GetStation(fgCurrentStation).GetChannel(fgCurrentChannel).GetChannelTimeSeries();
331  double samplingFrequency = 1./trace.GetBinning();
332 
333  for (ChannelTimeSeries::SizeType i = 0; i < trace.GetSize(); ++i) {
334  if ((i > fgSignalStart && i < fgSignalStop && fgFitWindow > 1) ||
335  (i > fgNoiseStart && i < fgNoiseStop && fgFitWindow == 3) ||
336  (i < fgNoiseStart && i > fgNoiseStop && fgFitWindow == 1))
337  continue;
338 
339  Chi2 += (trace[i] - amp*sin(i/samplingFrequency*freq*2*TMath::Pi() + phase)) *
340  (trace[i] - amp*sin(i/samplingFrequency*freq*2*TMath::Pi() + phase));
341  }
342  value = Chi2;
343  }
344 
345  void
346  RdChannelSineWaveSuppressor::RFISort(std::vector<int> &v, int left, int right)
347  {
348  const revt::ChannelFrequencySpectrum& spectrum =
349  fgCurrentREvent->GetStation(fgCurrentStation).GetChannel(fgCurrentChannel).GetChannelFrequencySpectrum();
350  int i = left, j = right;
351  int tmp;
352  double pivot = abs(spectrum[v[(left + right) / 2]]);
353 
354  while (i <= j) {
355  while (abs(spectrum[v[i]]) > pivot)
356  ++i;
357  while (abs(spectrum[v[j]]) < pivot)
358  --j;
359  if (i <= j) {
360  tmp = v[i];
361  v[i] = v[j];
362  v[j] = tmp;
363  ++i;
364  --j;
365  }
366  }
367  if (left < j)
368  RdChannelSineWaveSuppressor::RFISort(v, left, j);
369  if (i < right)
370  RdChannelSineWaveSuppressor::RFISort(v, i, right);
371  }
372 
373 }
Branch GetTopBranch() const
Definition: Branch.cc:63
constexpr T Sqr(const T &x)
double GetDesignUpperFreq() const
Get design value of the freq-band.
constexpr double MHz
Definition: AugerUnits.h:159
int freq
Definition: dump1090.h:244
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
double GetDesignLowerFreq() const
Get design value of the freq-band.
double GetBinning() const
size of one slot
Definition: Trace.h:138
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
void Init()
Initialise the registry.
Detector description interface for Channel-related data.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double pow(const double x, const unsigned int i)
void Chi2(int &, double *const , double &value, double *const par, const int)
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
#define INFOIntermediate(y)
Definition: VModule.h:162
Class representing a document branch.
Definition: Branch.h:107
std::vector< std::complex< double > >::size_type SizeType
Definition: Trace.h:58
double abs(const SVector< n, T > &v)
SizeType GetSize() const
Definition: Trace.h:156
#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
#define INFODebug(y)
Definition: VModule.h:163
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
#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

, generated on Tue Sep 26 2023.