Deprecated/RdStationSignalReconstructorLegacy/RdStationSignalReconstructor.cc
Go to the documentation of this file.
2 
3 #include <fwk/CentralConfig.h>
4 
5 #include <utl/ErrorLogger.h>
6 #include <utl/Reader.h>
7 #include <utl/config.h>
8 #include <utl/Trace.h>
9 #include <utl/TraceAlgorithm.h>
10 #include <utl/TimeStamp.h>
11 #include <utl/TimeInterval.h>
12 #include <utl/AugerUnits.h>
13 #include <utl/PhysicalConstants.h>
14 #include <utl/AugerException.h>
15 #include <utl/FFTDataContainerAlgorithm.h>
16 #include <utl/Math.h>
17 #include <utl/RadioGeometryUtilities.h>
18 
19 #include <evt/Event.h>
20 #include <evt/ShowerRecData.h>
21 #include <evt/ShowerRRecData.h>
22 #include <evt/ShowerRRecDataQuantities.h>
23 #include <revt/REvent.h>
24 #include <revt/Header.h>
25 #include <revt/Station.h>
26 #include <revt/StationRecData.h>
27 #include <revt/StationHeader.h>
28 #include <revt/StationTriggerData.h>
29 #include <revt/Channel.h>
30 
31 #include <det/Detector.h>
32 #include <rdet/RDetector.h>
33 #include <rdet/Station.h>
34 #include <rdet/Channel.h>
35 
36 #include <TVector3.h>
37 #include "TGraph.h"
38 #include "TCanvas.h"
39 #include "Minuit2/Minuit2Minimizer.h"
40 #include "Minuit2/MnMigrad.h"
41 #include "Minuit2/FunctionMinimum.h"
42 #include "Minuit2/MinimumParameters.h"
43 #include "Minuit2/MnPrint.h"
44 
45 #include <boost/algorithm/string/case_conv.hpp>
46 
47 #include <time.h>
48 
49 #include <complex> // std::complex, std::abs
50 
51 #ifdef WITH_CUDA
52  #include <cuda_runtime_api.h>
53  #include <utl/cudaCheckErrors.h>
54 #endif
55 
56 #define OUT(x) if ((x) <= fInfoLevel) cerr << " "
57 
58 using namespace revt;
59 using namespace fwk;
60 using namespace utl;
61 using std::complex;
62 using std::stringstream;
63 using std::ostringstream;
64 using std::cerr;
65 using std::cout;
66 using std::endl;
67 using std::max;
68 using std::min;
69 
71 
73  {
74  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdStationSignalReconstructor");
75  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
76  INFODebug("");
77 
78  topBranch.GetChild("VectorialComponent").GetData(fVectorialComponent);
79  topBranch.GetChild("useEnvelope").GetData(fUseEnvelope);
80  topBranch.GetChild("NoiseSubtraction").GetData(fNoiseSubtraction);
81  topBranch.GetChild("SignalDef").GetData(fSignalDef);
82  topBranch.GetChild("SignalIntegrationWindowSize").GetData(fSignalIntegrationWindowSize);
83  topBranch.GetChild("NoiseDef").GetData(fNoiseDef);
84  topBranch.GetChild("SignalToNoiseDef").GetData(fSignalToNoiseDef);
85  topBranch.GetChild("PolarizationDef").GetData(fPolarizationDef);
86  topBranch.GetChild("AddNoiseToUncertainty").GetData(fAddNoiseToUncertainty);
87  topBranch.GetChild("MinSignal").GetData(fMinSignal);
88  topBranch.GetChild("MinSignalToNoise").GetData(fMinSignalToNoise);
89  topBranch.GetChild("SelfTriggeredSNcut").GetData(fSelfTriggeredSNcut);
90  topBranch.GetChild("AdjustSignalAmplitude").GetData(fAdjustSignalAmplitude);
91  topBranch.GetChild("AnalyticSignal").GetData(fFitAnalyticSignal);
92  topBranch.GetChild("RelativeAmplitudeUncertainty").GetData(fRelativeAmplitudeUncertainty);
93  topBranch.GetChild("DefaultAntennaUncertainty").GetData(fDefaultAntennaUncertainty);
94  topBranch.GetChild("ButterflyAntennaUncertainty").GetData(fButterflyAntennaUncertainty);
95  topBranch.GetChild("BlackSpiderAntennaUncertainty").GetData(fBlackSpiderAntennaUncertainty);
96 
97  ostringstream info;
98  info << "\n\t Vectorial component : " << fVectorialComponent
99  << "\n\t Use Envelope : " << fUseEnvelope
100  << "\n\t Signal definition (for SNR): " << fSignalDef
101  << "\n\t SNR definition : " << fSignalToNoiseDef
102  << "\n\t Min. SNR : " << fMinSignalToNoise
103  << "\n\t Subtract Noise (for peak) : " << fNoiseSubtraction
104  << "\n\t Signal inegration window : " << fSignalIntegrationWindowSize << "ns"
105  << "\n\t Add Noise to uncertainty : " << fAddNoiseToUncertainty
106  << "\n\t Rel. ampl. uncertainty / % : " << fRelativeAmplitudeUncertainty
107  << "\n\t Rel. antenna pattern uncertainty / %"
108  << "\n\t (LPDA / BF / Default): (" << fBlackSpiderAntennaUncertainty
109  << " / " << fButterflyAntennaUncertainty
110  << " / " << fDefaultAntennaUncertainty << ")\n";
111 
112  INFO(info);
113  return eSuccess;
114  }
115 
116 
117  VModule::ResultFlag RdStationSignalReconstructor::Run(evt::Event& event)
118  {
119 
120  if(fInfoLevel >= eInfoIntermediate) {
121  INFO("RdStationSignalReconstructor::Run()");
122  }
123 
124  // Check if there are events at all
125  if(!event.HasREvent()) {
126  WARNING("No radio event found!");
127  return eContinueLoop;
128  }
129 
130  ++fTotalNumberOfEvents;
131 
132  stringstream fMessage;
133 
134  REvent& rEvent = event.GetREvent();
135  //TimeStamp eventTime = rEvent.GetHeader().GetTime();
136 
137  int numberOfStationsWithPulseFound = 0;
138 
139 #ifdef WITH_CUDA
140  // calculate first HilbertEnvelope out of loop and then, in the for loop, evaluate HilbertEnvelope Result i (CPU) and calculate HilbertEnvelope i+1 (GPU) parallel
141  // cudaStream_t stream;
142  // cudaStreamCreate(&stream);
143  // cudaCheckErrors("Creating Stream failed");
144 
145  cudaStream_t streams[3];
146  for (int i = 0; i < 3; ++i)
147  cudaStreamCreate(&streams[i]);
148  cudaCheckErrors("cudaStreamCreate failed");
149 
150  //Pointers to the timeseries and transformedTimeseries on CPU pinned memory and on GPU
151  int n = rEvent.CandidateStationsBegin()->GetFFTDataContainer().GetConstTimeSeries().GetSize();
152  double* const ts = new double[3*n];
153  complex<double>* const tts = new complex<double>[3*n];
154  cudaHostRegister(ts, 3*n*sizeof(double), cudaHostRegisterPortable);
155  cudaHostRegister(tts, 3*n*sizeof(complex<double>), cudaHostRegisterPortable);
156  cudaCheckErrors("cudaHostRegister failed");
157 
158  double* d_ts = nullptr;
159  complex<double>* d_tts = nullptr;
160  cudaMalloc((void**)&d_ts, 3*n*sizeof(double));
161  cudaMalloc((void**)&d_tts, 3*n*sizeof(complex<double>));
162  cudaCheckErrors("cudaMalloc failed");
163 
165  if (fUseEnvelope) {
166  efieldData = rEvent.CandidateStationsBegin()->GetFFTDataContainer();
167  FFTDataContainerAlgorithm::HilbertEnvelope(efieldData); //transform
168  }
169  revt::StationFFTDataContainer dummyContainer;
170  double* dummyTimeseries = nullptr;
172 #endif // WITH_CUDA
173 
174  time_t timeAllStation = time(NULL);
175  // loop through candidate stations and for every station through every channel
177  sIt != rEvent.CandidateStationsEnd(); ++sIt) {
178  time_t timeStation = time(NULL);
179  Station& station = *sIt;
180 
181 #ifdef WITH_CUDA
182  next = sIt;
183  ++next;
184 #endif // WITH_CUDA
185 
186  // RRecStation event should have been generated by RdEventInitializer
187  if (!station.HasRecData()) {
188  WARNING("Station has no RecData! Please call RdEventInitializer first!");
189  return eFailure;
190  }
191  StationRecData& recStation = station.GetRecData();
192 
193  // time that is added to all times determined in a trace in ns
194  const double relTime = station.GetRecData().GetParameter(eTraceStartTime);
195 
196  ostringstream info;
197  info << "Apply pulse finder on station " << station.GetId();
198  INFOIntermediate(info);
199 
200  // Read the time trace of this station
201  // gettting a local copy of the electric field data
202 
203 #ifdef WITH_CUDA
204  // when we are using the envelope timeseries
205  if (fUseEnvelope && next != rEvent.CandidateStationsEnd()) {
206  dummyContainer = next->GetFFTDataContainer();
207  dummyTimeseries = &(dummyContainer.GetTimeSeries()[0][0]);
208  //reorder timeseries
209  for (size_t j = 0; j < 3; ++j) {
210  for (size_t i = 0; i < n; ++i) {
211  ts[j*n+i] = dummyTimeseries[i*3 + j];
212  }
213  }
214  for (int i = 0; i < 3*n; ++i) {
215  real(tts[i]) = ts[i];
216  imag(tts[i]) = 0;
217  }
218  FFTDataContainerAlgorithm::HilbertEnvelope(ts, tts, d_ts, d_tts, n, streams); //transform for the next loop;
219  }
220 #else
221  revt::StationFFTDataContainer efieldData = station.GetFFTDataContainer();
222  if (fUseEnvelope)
223  FFTDataContainerAlgorithm::HilbertEnvelope(efieldData);
224  OUT(eInfoDebug) << "size of efield trace = " << efieldData.GetConstTimeSeries().GetSize() << endl;
225 #endif // WITH_CUDA
226 
227  const StationTimeSeries& stationtrace = efieldData.GetConstTimeSeries();
228  const StationTimeSeries& stationtrace_noenvelope = station.GetFFTDataContainer().GetConstTimeSeries();
229 
230  // temporary channel trace to which the selected station data is copied
231  ChannelTimeSeries channeltrace;
232  channeltrace.SetBinning(stationtrace.GetBinning());
233 
234  ChannelTimeSeries channeltrace_noenvelope;
235  channeltrace_noenvelope.SetBinning(stationtrace_noenvelope.GetBinning());
236 
237  // noise windows are clipped when outside the trace
238  double NoiseWindowStart = recStation.GetParameter(eNoiseWindowStart);
239  double NoiseWindowStop = recStation.GetParameter(eNoiseWindowStop);
240  const double SignalSearchWindowStart = recStation.GetParameter(eSignalSearchWindowStart);
241  const double SignalSearchWindowStop = recStation.GetParameter(eSignalSearchWindowStop);
242  double SignalWindowStart = 0;
243  double SignalWindowStop = 0;
244  double SignalIntegrationWindowSize = fSignalIntegrationWindowSize;
245  recStation.SetParameter(revt::eSignalIntegrationTime, fSignalIntegrationWindowSize);
246 
247  bool PulseFound = false;
248  double MeanNoise = 0;
249  double RMSNoise = 0;
250 
251  unsigned int peak_bin = 0;
252  unsigned int sample = 0;
253 
254  double PeakAmplitude = 0;
255  double IntegratedSignal = 0;
256  double SignalTimeFWHM = 0;
257  double PeakTime = 0;
258 
259 
260  double PeakTimeError = 0;
261  double SignalToNoise = 0;
262  //double SignalToNoiseError = 0;
263 
264  // component = 0 is absolute value of vectorial sum of station vector data
265  // component = 1 is x, 2 is y, 3 is z
266  // component = 4 is xy-plane
267  // component 5-6 is vxB and vxvxB plane
268  unsigned int NumComponents = 7;
269 
270 
271  for (unsigned int iterator = 0; iterator < NumComponents; ++iterator) {
272  // loop has to start at fVectorialComponent so that start time is set correctly
273  unsigned int component = (iterator + fVectorialComponent) % NumComponents;
274  channeltrace.ClearTrace();
275  channeltrace_noenvelope.ClearTrace();
276  // fixme TH: it would be nice to reserve the appropriate space in the trace here,
277  // but utl::Trace does not offer that functionality (yet)
278 
279  if (component == 0) {
280  for (StationTimeSeries::SizeType i = 0; i < stationtrace.GetSize(); ++i) {
281  channeltrace.PushBack(stationtrace[i].GetMag());
282  if (std::isnan(stationtrace[i].GetMag())) {
283  fMessage.str("");
284  fMessage << "sample " << i << " of efield trace is nan";
285  WARNING(fMessage.str());
286  }
287  channeltrace_noenvelope.PushBack(stationtrace_noenvelope[i].GetMag());
288  if (std::isnan(stationtrace_noenvelope[i].GetMag())) {
289  fMessage.str("");
290  fMessage << "sample " << i << " of efield trace is nan";
291  WARNING(fMessage.str());
292  }
293  }
294  }
295  else if (component == 1 || component == 2 || component == 3) {
296  for (StationTimeSeries::SizeType i = 0; i < stationtrace.GetSize(); ++i) {
297  channeltrace.PushBack(fabs(stationtrace[i][component - 1]));
298  channeltrace_noenvelope.PushBack(fabs(stationtrace_noenvelope[i][component - 1]));
299  }
300  }
301  else if (component == 4) {
302  for (StationTimeSeries::SizeType i = 0; i < stationtrace.GetSize(); ++i) {
303  channeltrace.PushBack(sqrt(Sqr(stationtrace[i][0]) + Sqr(stationtrace[i][1])));
304  channeltrace_noenvelope.PushBack(sqrt(Sqr(stationtrace_noenvelope[i][0]) +
305  Sqr(stationtrace_noenvelope[i][1])));
306  }
307  }
308  else if (component == 5 || component == 6) {
309  evt::ShowerRRecData& recShower = event.GetRecShower().GetRRecShower();
310  if(!(recShower.HasReferenceCorePosition(event) && recShower.HasReferenceAxis(event))) {
311  WARNING(
312  "Reference direction or core position not set. The electric-field can not be rotated into the vxB, vx(vxB) system. The calculation will be skipped");
313  continue;
314  }
315  // rotate trace to shower xy-plane
316  const utl::CoordinateSystemPtr coreCS =
318  utl::Vector showerAxis = recShower.GetReferenceAxis(event);
320  utl::RadioGeometryUtilities(showerAxis, coreCS, recShower.GetMagneticFieldVector());
321  utl::TraceV3D traceShowerPlane = csTrans.GetTraceInShowerPlaneVxB(stationtrace);
322  utl::TraceV3D traceShowerPlane_noenvelope = csTrans.GetTraceInShowerPlaneVxB(stationtrace_noenvelope);
323  for (unsigned int i = 0; i < traceShowerPlane.GetSize(); ++i) {
324  channeltrace.PushBack(traceShowerPlane[i][component - 5]);
325  channeltrace_noenvelope.PushBack(traceShowerPlane_noenvelope[i][component - 5]);
326  }
327  }
328  else {
329  // should never reach that
330  ERROR("This component does not exist!");
331  return eFailure;
332  }
333 
334  // clip windows at trace boundaries
335  double TraceStop = (channeltrace.GetSize() - 1) * channeltrace.GetBinning();
336  NoiseWindowStart = min(max(0.0, NoiseWindowStart), TraceStop);
337  NoiseWindowStop = max(min(NoiseWindowStop, TraceStop), NoiseWindowStart);
338 
339  // calculate noise and find pulse
340  Noisefinder(channeltrace, RMSNoise, MeanNoise, NoiseWindowStart, NoiseWindowStop);
341  Pulsefinder(channeltrace, PeakAmplitude, PeakTime, PeakTimeError,
342  SignalSearchWindowStart, SignalSearchWindowStop, sample);
343 
344  if (component == fVectorialComponent)
345  peak_bin = sample;
346 
347  // calculate FWHM and integrated signal
348  PulseFWHMIntegrator(channeltrace, sample, PeakAmplitude, SignalTimeFWHM, IntegratedSignal,
349  SignalWindowStart, SignalWindowStop);
350 
351  if (fSignalDef == "IntegralFixedWindow") // overwrites IntegratedSignal
352  PulseFixedWindowIntegrator(channeltrace_noenvelope, sample, SignalIntegrationWindowSize,
353  IntegratedSignal, SignalWindowStart, SignalWindowStop, false);
354 
355  if (fSignalDef == "PowerIntegralSlidingWindow") // overwrites IntegratedSignal
356  PulseSlidingWindowIntegrator(channeltrace, SignalIntegrationWindowSize, IntegratedSignal,
357  SignalWindowStart, SignalWindowStop, SignalSearchWindowStart, SignalSearchWindowStop);
358 
359  // calculate signal energy fluence
360  double signalEnergyFluence = 0;
361  double integratedPowerFixedWidthStartTime = 0;
362  double integratedPowerFixedWidthStopTime = 0;
363  PulseFixedWindowIntegrator(channeltrace_noenvelope, peak_bin, SignalIntegrationWindowSize,
364  signalEnergyFluence, integratedPowerFixedWidthStartTime,
365  integratedPowerFixedWidthStopTime, true);
366 
367  // calculate noise energy fluence
368  double noiseEnergyFluence = 0;
369  double integratedNoisePowerFixedWidthStartTime = 0;
370  double integratedNoisePowerFixedWidthStopTime = 0;
371  double noiseWindowSize = NoiseWindowStop - NoiseWindowStart;
372  unsigned int meanNoiseSample = (NoiseWindowStart + noiseWindowSize * 0.5)
373  / channeltrace_noenvelope.GetBinning();
374  PulseFixedWindowIntegrator(channeltrace_noenvelope, meanNoiseSample, noiseWindowSize,
375  noiseEnergyFluence, integratedNoisePowerFixedWidthStartTime,
376  integratedNoisePowerFixedWidthStopTime, true);
377 
378  // normalize noise integral to size of integration window
379  noiseEnergyFluence *= SignalIntegrationWindowSize / noiseWindowSize;
380 
381  signalEnergyFluence = signalEnergyFluence - noiseEnergyFluence;
382 
383  double signalEnergyFluenceError =
384  sqrt(4 * fabs(signalEnergyFluence) * pow(RMSNoise, 2) * channeltrace_noenvelope.GetBinning() +
385  2 * SignalIntegrationWindowSize * pow(RMSNoise, 4) * channeltrace_noenvelope.GetBinning());
386 
387  signalEnergyFluence *= kConversionRadioSignalToEnergyFluence; // convert to energy fluence
388  noiseEnergyFluence *= kConversionRadioSignalToEnergyFluence; // convert to energy fluence
389  signalEnergyFluenceError *= kConversionRadioSignalToEnergyFluence; // convert to energy fluence
390 
391  double antennaToAntennaUncertainty = 0;
392  for (Station::ChannelIterator cIt = station.ChannelsBegin(); cIt != station.ChannelsEnd(); ++cIt) {
393  Channel& channel = *cIt;
394  if (boost::algorithm::to_lower_copy(
395  det::Detector::GetInstance().GetRDetector().GetStation(station)
396  .GetChannel(channel.GetId()).GetAntennaTypeName())
397  .find("butterfly") != std::string::npos ) {
398  if (antennaToAntennaUncertainty < fButterflyAntennaUncertainty)
399  antennaToAntennaUncertainty = fButterflyAntennaUncertainty;
400  } else if (boost::algorithm::to_lower_copy(
401  det::Detector::GetInstance().GetRDetector().GetStation(station)
402  .GetChannel(channel.GetId()).GetAntennaTypeName())
403  .find("blackspider") != std::string::npos ) {
404  if (antennaToAntennaUncertainty < fBlackSpiderAntennaUncertainty)
405  antennaToAntennaUncertainty = fBlackSpiderAntennaUncertainty;
406  } else {
407  if (antennaToAntennaUncertainty < fDefaultAntennaUncertainty)
408  antennaToAntennaUncertainty = fDefaultAntennaUncertainty;
409  }
410  }
411 
412  info.str("");
413  info << "Station " << station.GetId() << " component " << component << " signaltime (sample) "
414  << PeakTime << "(" << sample << ") Integrating f around sample " << peak_bin
415  << " f = " << signalEnergyFluence << " f noise = " << noiseEnergyFluence
416  << " sigma_f = " << signalEnergyFluenceError
417  << " RelativeAmplitudeUncertainty = " << fRelativeAmplitudeUncertainty
418  << " antennaToAntennaUncertainty = " << antennaToAntennaUncertainty;
419  INFODebug(info.str());
420 
421  // add relative uncertainty (a factor "2" is used because the energy fluence scales with amplitude squared)
422  signalEnergyFluenceError = sqrt(pow(signalEnergyFluenceError, 2) +
423  pow(fRelativeAmplitudeUncertainty * 2 * signalEnergyFluence, 2) +
424  pow(antennaToAntennaUncertainty * 2 * signalEnergyFluence, 2));
425 
426  // noise subtraction
427  if (fNoiseSubtraction == "Linear") {
428  if (fNoiseDef == "RMS") {
429  PeakAmplitude = PeakAmplitude - MeanNoise;
430 
431  if (fSignalDef == "IntegralFWHM")
432  IntegratedSignal -= SignalTimeFWHM / channeltrace.GetBinning() * MeanNoise;
433  if (fSignalDef == "IntegralFixedWindow" || fSignalDef == "PowerIntegralSlidingWindow")
434  IntegratedSignal -= SignalIntegrationWindowSize / channeltrace.GetBinning() * MeanNoise;
435  }
436  }
437 
438  // calculate signal to noise ratio
439  if (RMSNoise <= 0) {
440  // fixme TH: would be better not to set a signal-to-noise or at least NaN instead of -1?
441  SignalToNoise = -1;
442  } else {
443  if (fSignalDef == "Peak")
444  SignalToNoise = PeakAmplitude / RMSNoise;
445  if (fSignalDef == "IntegralFWHM")
446  SignalToNoise = IntegratedSignal / (RMSNoise * SignalTimeFWHM / channeltrace.GetBinning());
447  if (fSignalDef == "IntegralFixedWindow")
448  SignalToNoise =
449  IntegratedSignal / (RMSNoise * SignalIntegrationWindowSize / channeltrace.GetBinning());
450  if (fSignalDef == "PowerIntegralSlidingWindow")
451  SignalToNoise = pow(IntegratedSignal, 0.5) / RMSNoise;
452  }
453 
454  // fill the generic variables using the options selected in the xml file
455  if (component == fVectorialComponent) {
456  station.GetRecData().SetParameter(eSignalTime, relTime + PeakTime);
457 
458  if (fSignalDef == "Peak" && fSignalToNoiseDef == "RatioOfSquares" && fNoiseDef == "RMS") {
459  PeakTimeError = std::sqrt(Sqr(PeakTimeError) + Sqr(GetSignalTimeUncertainty(Sqr(SignalToNoise))));
460  } else {
461  WARNING("A non-standard signal or SNR definition is used. "
462  "The uncertainty of the signal time due to noise can not be set");
463  }
464  station.GetRecData().SetParameterError(eSignalTime,
465  sqrt(Sqr(PeakTimeError) +
466  Sqr(station.GetRecData().GetParameterError(revt::eTraceStartTime))));
467 
468  if (fNoiseDef == "RMS") {
469  station.GetRecData().SetParameter(eNoise, RMSNoise);
470  }
471  if (fSignalDef == "Peak") {
472  if (fAdjustSignalAmplitude) {
473  if (fSignalToNoiseDef != "RatioOfSquares" && fNoiseDef == "RMS") {
474  WARNING("A non-standard noise or SNR definition is used. "
475  "The adjustment of the signal amplitude can not be performed.");
476  } else {
477  PeakAmplitude = GetAdjustedSignalAmplitude(PeakAmplitude, Sqr(SignalToNoise));
478  }
479  }
480  station.GetRecData().SetParameter(eSignal, PeakAmplitude);
481  if (fSignalToNoiseDef != "RatioOfSquares" && fNoiseDef == "RMS") {
482  WARNING("A non-standard signal or SNR definition is used. "
483  "The uncertainty of the signal will be incorrect");
484  }
485 
486  OUT(eInfoDebug)
487  << "SNR = "
488  << Sqr(SignalToNoise)
489  << "\tsignal amplitude = "
490  << PeakAmplitude
491  << "\tUncertainty of SignalAmplitude = "
492  << GetSignalUncertainty(PeakAmplitude, Sqr(SignalToNoise))
493  << endl;
494 
495  double tempUncertainty = sqrt(
496  GetSignalUncertainty(PeakAmplitude, Sqr(SignalToNoise))
497  * GetSignalUncertainty(PeakAmplitude, Sqr(SignalToNoise))
498  + PeakAmplitude * fRelativeAmplitudeUncertainty * PeakAmplitude * fRelativeAmplitudeUncertainty
499  + PeakAmplitude * antennaToAntennaUncertainty * PeakAmplitude * antennaToAntennaUncertainty);
500  station.GetRecData().SetParameterError(eSignal, tempUncertainty);
501 
502  if (fSignalToNoiseDef == "SimpleRatio")
503  station.GetRecData().SetParameter(eSignalToNoise, SignalToNoise);
504  if (fSignalToNoiseDef == "RatioOfSquares")
505  station.GetRecData().SetParameter(eSignalToNoise, Sqr(SignalToNoise));
506  }
507 
508  if (fSignalDef == "IntegralFWHM" || fSignalDef == "IntegralFixedWindow") {
509  station.GetRecData().SetParameter(eSignal, IntegratedSignal);
510  if (fSignalToNoiseDef == "SimpleRatio")
511  station.GetRecData().SetParameter(eSignalToNoise, SignalToNoise);
512  if (fSignalToNoiseDef == "RatioOfSquares")
513  station.GetRecData().SetParameter(eSignalToNoise, Sqr(SignalToNoise));
514  }
515 
516  if (fSignalDef == "PowerIntegralSlidingWindow") {
517  station.GetRecData().SetParameter(eSignal, sqrt(IntegratedSignal));
518  if (fSignalToNoiseDef == "SimpleRatio")
519  station.GetRecData().SetParameter(eSignalToNoise, SignalToNoise);
520  if (fSignalToNoiseDef == "RatioOfSquares")
521  station.GetRecData().SetParameter(eSignalToNoise, Sqr(SignalToNoise));
522  }
523 
524  // all uncertainties have to be calculated, set them preliminary to 10%
525  // fixme TH: many uncertainties are set to a hard-coded value of 10%!
526  station.GetRecData().SetParameterError(eNoise,
527  0.1 * station.GetRecData().GetParameter(eNoise));
528  station.GetRecData().SetParameterError(eSignalToNoise,
529  0.1 * station.GetRecData().GetParameter(eSignalToNoise));
530 
531  OUT(eInfoDebug) << "Filling the primary parameters..." << endl;
532  station.GetRecData().SetParameter(eSignalWindowStart, SignalWindowStart);
533  station.GetRecData().SetParameter(eSignalWindowStop, SignalWindowStop);
534  station.GetRecData().SetParameter(eMinSignal, fMinSignal);
535  station.GetRecData().SetParameter(eMinSignalToNoise, fMinSignalToNoise);
536  }
537 
538  /* Add noise level to uncertainty. This factor is not well motivated,
539  however the uncertainty of weak signals seems underestimated otherwise.
540  Previously this has been done by the LDFFitter modules individually. */
541  if (fAddNoiseToUncertainty)
542  signalEnergyFluenceError = sqrt(pow(signalEnergyFluenceError, 2) + pow(noiseEnergyFluence, 2));
543 
544  // fill the variables
545  if (component == 0) {
546  station.GetRecData().SetParameter(ePeakAmplitudeMag, PeakAmplitude);
547  station.GetRecData().SetParameter(ePeakTimeMag, relTime + PeakTime);
548  station.GetRecData().SetParameter(eIntegratedSignalMag, IntegratedSignal);
549  station.GetRecData().SetParameter(eSignalFWHMMag, SignalTimeFWHM);
550  station.GetRecData().SetParameter(eNoiseRmsMag, RMSNoise);
551  station.GetRecData().SetParameter(eNoiseMeanMag, MeanNoise);
552  station.GetRecData().SetParameter(eSignalEnergyFluenceMag, signalEnergyFluence);
553  station.GetRecData().SetParameterError(eSignalEnergyFluenceMag, signalEnergyFluenceError);
554  station.GetRecData().SetParameter(eNoiseEnergyFluenceMag, noiseEnergyFluence);
555  } else if (component == 1) {
556  station.GetRecData().SetParameter(ePeakAmplitudeEW, PeakAmplitude);
557  station.GetRecData().SetParameter(ePeakTimeEW, relTime + PeakTime);
558  station.GetRecData().SetParameter(eIntegratedSignalEW, IntegratedSignal);
559  station.GetRecData().SetParameter(eSignalFWHMEW, SignalTimeFWHM);
560  station.GetRecData().SetParameter(eNoiseRmsEW, RMSNoise);
561  station.GetRecData().SetParameter(eNoiseMeanEW, MeanNoise);
562  station.GetRecData().SetParameter(eSignalEnergyFluenceEW, signalEnergyFluence);
563  station.GetRecData().SetParameterError(eSignalEnergyFluenceEW, signalEnergyFluenceError);
564  station.GetRecData().SetParameter(eNoiseEnergyFluenceEW, noiseEnergyFluence);
565  } else if (component == 2) {
566  station.GetRecData().SetParameter(ePeakAmplitudeNS, PeakAmplitude);
567  station.GetRecData().SetParameter(ePeakTimeNS, relTime + PeakTime);
568  station.GetRecData().SetParameter(eIntegratedSignalNS, IntegratedSignal);
569  station.GetRecData().SetParameter(eSignalFWHMNS, SignalTimeFWHM);
570  station.GetRecData().SetParameter(eNoiseRmsNS, RMSNoise);
571  station.GetRecData().SetParameter(eNoiseMeanNS, MeanNoise);
572  station.GetRecData().SetParameter(eSignalEnergyFluenceNS, signalEnergyFluence);
573  station.GetRecData().SetParameterError(eSignalEnergyFluenceNS, signalEnergyFluenceError);
574  station.GetRecData().SetParameter(eNoiseEnergyFluenceNS, noiseEnergyFluence);
575  } else if (component == 3) {
576  station.GetRecData().SetParameter(ePeakAmplitudeV, PeakAmplitude);
577  station.GetRecData().SetParameter(ePeakTimeV, relTime + PeakTime);
578  station.GetRecData().SetParameter(eIntegratedSignalV, IntegratedSignal);
579  station.GetRecData().SetParameter(eSignalFWHMV, SignalTimeFWHM);
580  station.GetRecData().SetParameter(eNoiseRmsV, RMSNoise);
581  station.GetRecData().SetParameter(eNoiseMeanV, MeanNoise);
582  station.GetRecData().SetParameter(eSignalEnergyFluenceV, signalEnergyFluence);
583  station.GetRecData().SetParameterError(eSignalEnergyFluenceV, signalEnergyFluenceError);
584  station.GetRecData().SetParameter(eNoiseEnergyFluenceV, noiseEnergyFluence);
585  } else if (component == 4) {
586  station.GetRecData().SetParameter(ePeakAmplitudeNSEWPlane, PeakAmplitude);
587  station.GetRecData().SetParameter(ePeakTimeNSEWPlane, relTime + PeakTime);
588  station.GetRecData().SetParameter(eIntegratedSignalNSEWPlane, IntegratedSignal);
589  station.GetRecData().SetParameter(eSignalFWHMNSEWPLane, SignalTimeFWHM);
590  station.GetRecData().SetParameter(eNoiseRmsNSEWPlane, RMSNoise);
591  station.GetRecData().SetParameter(eNoiseMeanNSEWPlane, MeanNoise);
592  station.GetRecData().SetParameter(eSignalEnergyFluenceNSEWPlane, signalEnergyFluence);
593  station.GetRecData().SetParameterError(eSignalEnergyFluenceNSEWPlane, signalEnergyFluenceError);
594  station.GetRecData().SetParameter(eNoiseEnergyFluenceNSEWPLane, noiseEnergyFluence);
595  } else if (component == 5) {
596  station.GetRecData().SetParameter(ePeakAmplitudeVxB, PeakAmplitude);
597  station.GetRecData().SetParameter(ePeakTimeVxB, relTime + PeakTime);
598  station.GetRecData().SetParameter(eNoiseRmsVxB, RMSNoise);
599  station.GetRecData().SetParameter(eNoiseMeanVxB, MeanNoise);
600  station.GetRecData().SetParameter(eSignalEnergyFluenceVxB, signalEnergyFluence);
601  station.GetRecData().SetParameterError(eSignalEnergyFluenceVxB, signalEnergyFluenceError);
602  station.GetRecData().SetParameter(eNoiseEnergyFluenceVxB, noiseEnergyFluence);
603  station.GetRecData().SetParameter(eSignalToNoiseVxB, SignalToNoise);
604  } else if (component == 6) {
605  station.GetRecData().SetParameter(ePeakAmplitudeVxVxB, PeakAmplitude);
606  station.GetRecData().SetParameter(ePeakTimeVxVxB, relTime + PeakTime);
607  station.GetRecData().SetParameter(eNoiseRmsVxVxB, RMSNoise);
608  station.GetRecData().SetParameter(eNoiseMeanVxVxB, MeanNoise);
609  station.GetRecData().SetParameter(eSignalEnergyFluenceVxVxB, signalEnergyFluence);
610  station.GetRecData().SetParameterError(eSignalEnergyFluenceVxVxB, signalEnergyFluenceError);
611  station.GetRecData().SetParameter(eNoiseEnergyFluenceVxVxB, noiseEnergyFluence);
612  station.GetRecData().SetParameter(eSignalToNoiseVxVxB, SignalToNoise);
613  }
614 
615  if (component == fVectorialComponent) {
616  if ((station.GetRecData().GetParameter(eSignalToNoise) > fMinSignalToNoise
618  && !fSelfTriggeredSNcut))
619  && station.GetRecData().GetParameter(eSignal) > fMinSignal) {
620  ++numberOfStationsWithPulseFound;
621  PulseFound = true;
622  } else {
623  PulseFound = false;
624  fMessage.str("");
625  fMessage << "no signal pulse found for station " << station.GetId();
626  INFODebug(fMessage.str());
627  }
628 
629  station.GetRecData().SetPulseFound(PulseFound);
630  if (PulseFound) {
631  station.SetSignal(); // mark station as signal station
632  } else {
633  station.SetNoSignal(); // remove signal attribute from station
634  }
635  }
636  } // end of component loop
637 
638  if (fFitAnalyticSignal) {
639  // fit analytic signal model
640  // fixme: check for existance of reconstructed shower or use reference direction
641  evt::ShowerRRecData& recShower = event.GetRecShower().GetRRecShower();
642 
643  // rotate trace to shower plane
644  // Point core = recShower.GetCoordinateOrigin();
645  // if (recShower.HasParameter(revt::eCoreX)) {
646  // core = recShower.GetCorePosition();
647  // }
648 
649  const utl::CoordinateSystemPtr coreCS =
651  utl::Vector showerAxis = recShower.GetReferenceAxis(event);
653  utl::RadioGeometryUtilities(showerAxis, coreCS, recShower.GetMagneticFieldVector());
654  utl::TraceV3D traceShowerPlane =
655  csTrans.GetTraceInShowerPlaneVxB(station.GetFFTDataContainer().GetConstTimeSeries());
656 
657  double energy_fluence = 0;
658  double energy_fluence2 = 0;
659  for (int polarization = 0; polarization < 2; ++polarization) {
660  ChannelTimeSeries tmpTrace;
661  tmpTrace.SetBinning(traceShowerPlane.GetBinning());
662  // unsigned int start = SignalSearchWindowStart / traceShowerPlane.GetBinning();
663  // unsigned int stop = SignalSearchWindowStop / traceShowerPlane.GetBinning();
664  // roll pulse center to the beginning/end of the trace to minimize the slope of the phase in the frequency domain (needed for unwrapping)
665  unsigned int start =
666  (station.GetRecData().GetParameter(eSignalTime) - relTime - 0.5 * fSignalIntegrationWindowSize) /
667  traceShowerPlane.GetBinning();
668  unsigned int stop =
669  (station.GetRecData().GetParameter(eSignalTime) - relTime + 0.5 * fSignalIntegrationWindowSize) /
670  traceShowerPlane.GetBinning();
671  if ((start - stop) % 2) {
672  ++stop; // even number of samples
673  }
674  unsigned int middle = (stop - start) / 2 + start;
675  for (unsigned int i = middle; i < stop; ++i) {
676  tmpTrace.PushBack(traceShowerPlane[i][polarization]);
677  }
678  for (unsigned int i = start; i < middle; ++i) {
679  tmpTrace.PushBack(traceShowerPlane[i][polarization]);
680  }
681  double phaseSlopeVxB = 0;
682  if (station.GetRecData().HasParameter(revt::eAnalyticSignalVxBPhaseP1)) {
683  phaseSlopeVxB = station.GetRecData().GetParameter(revt::eAnalyticSignalVxBPhaseP1);
684  }
685  ROOT::Minuit2::MnUserParameterState minimum =
686  FitAnalyticSignal(tmpTrace, RMSNoise, station, polarization, (polarization == 1), phaseSlopeVxB);
687  const double p0 = minimum.Parameter(0).Value();
688  const double p1 = minimum.Parameter(1).Value();
689  // const double p2 = minimum.Parameter(2).Value();
690  // const double p3 = minimum.Parameter(3).Value();
691 
692  // fixme TH: the following assumes that all channels have the same design bandwidth rate as channel 1!
693  double flow =
694  det::Detector::GetInstance().GetRDetector().GetStation(*sIt).GetChannel(1).GetDesignLowerFreq();
695  double fup =
696  det::Detector::GetInstance().GetRDetector().GetStation(*sIt).GetChannel(1).GetDesignUpperFreq();
697 
698  /* debug code
699  double timeBinning = tmpTrace.GetBinning();
700  unsigned int n = tmpTrace.GetSize(); // number of points in time domain
701  unsigned int np = n / 2 + 1; // number of points in frequency domain
702  const double frequencyBinning = 0.5 / timeBinning / (static_cast<double>(np) - 1);
703  unsigned int startBin = static_cast<int>(std::ceil(30 * utl::MHz * timeBinning * n));
704  unsigned int stopBin = static_cast<int>(std::floor(80 * utl::MHz * timeBinning * n));
705  flow = startBin / (timeBinning * n) - 0.5 * frequencyBinning;
706  fup = (stopBin) / (timeBinning * n) + 0.5 * frequencyBinning;
707  */
708 
709  double energy_fluence_tmp =
710  1. / 3. * (pow(fup, 3) - pow(flow, 3)) * p1 * p1 +
711  (fup * fup - flow * flow) * p0 * p1 + (fup - flow) * p0 * p0;
712  energy_fluence_tmp *= 2; // frequency spectrum is truncated to n/2 +1 entries, a multiplication by a factor of two is required to get the same result as in the time domain
713  energy_fluence_tmp *= kConversionRadioSignalToEnergyFluence;
714  // cout << "energy fluence pol " << polarization << " " << station.GetId() << " (" << flow << " - " << fup << "): " << energy_density_tmp << endl;
715  energy_fluence += energy_fluence_tmp;
716 
717  if (polarization == 0) {
718  station.GetRecData().SetParameter(revt::eAnalyticSignalVxBAmplitudeP0,
719  minimum.Parameter(0).Value());
720  station.GetRecData().SetParameter(revt::eAnalyticSignalVxBAmplitudeP1,
721  minimum.Parameter(1).Value());
722  station.GetRecData().SetParameter(revt::eAnalyticSignalVxBPhaseP0,
723  minimum.Parameter(2).Value());
724  station.GetRecData().SetParameter(revt::eAnalyticSignalVxBPhaseP1,
725  minimum.Parameter(3).Value());
726  station.GetRecData().SetParameter(revt::eSignalEnergyFluenceVxBFit, energy_fluence_tmp);
727  } else if (polarization == 1) {
728  station.GetRecData().SetParameter(revt::eAnalyticSignalVxVxBAmplitudeP0,
729  minimum.Parameter(0).Value());
730  station.GetRecData().SetParameter(revt::eAnalyticSignalVxVxBAmplitudeP1,
731  minimum.Parameter(1).Value());
732  station.GetRecData().SetParameter(revt::eAnalyticSignalVxVxBPhaseP0,
733  minimum.Parameter(2).Value());
734  station.GetRecData().SetParameter(revt::eAnalyticSignalVxVxBPhaseP1,
735  minimum.Parameter(3).Value());
736  station.GetRecData().SetParameter(revt::eSignalEnergyFluenceVxVxBFit, energy_fluence_tmp);
737  }
738 
739  // debug ///
740  /*
741  double* f = FFTWdouble(n); // allocate memory through fftw, making sure it is correctly aligned
742  complex<double>* g = FFTWComplex(np);
743 
744  crfft1d Backward(n, g, f); // "plan" fft^-1 through fftw
745 
746  // calculate bins of frequency 30MHz and 80MHz
747  //#warning: better get bandwidth of detector from time dependend detector description
748 
749  for (unsigned int i = 0; i < np; i++) {
750  if (i < startBin || i > stopBin) {
751  g[i] = 0;
752  } else {
753  g[i] = std::polar(p0 + p1 * i * frequencyBinning,
754  p2 + p3 * i * frequencyBinning) * frequencyBinning;
755  }
756  }
757  Backward.fft(g, f);
758 
759  // calculate signal energy density
760  double signalEnergyDensity(0.);
761  for(int i = 0; i < n; ++i) {
762  signalEnergyDensity += (f[i] * f[i]);
763  }
764  signalEnergyDensity *= (kConversionRadioSignalToEnergyFluence * timeBinning);
765  cout << "energy density pol " << polarization << " " << station.GetId()
766  << ": " << signalEnergyDensity << endl;
767  energy_density2 += signalEnergyDensity;
768  */
769  }
770 
771  station.GetRecData().SetParameter(revt::eSignalEnergyFluenceShowerPlaneFit, energy_fluence);
772  cout << "energy fluence " << station.GetId() << ": " << energy_fluence << endl;
773  cout << "energy fluence2 " << station.GetId() << ": " << energy_fluence2 << endl;
774  cout << "ratio " << station.GetId() << ": " << energy_fluence / energy_fluence2 << endl;
775  }
776 
777 
778 #ifdef WITH_CUDA
779  for (int i = 0; i < 3; ++i)
780  cudaStreamSynchronize(streams[i]);
781  cudaCheckErrors("cudaStreamSynchronize failed");
782 
783  dummyTimeseries = &(dummyContainer.GetTimeSeries()[0][0]);
784  for (size_t j = 0; j < 3; ++j) {
785  for (size_t i = 0; i < n; ++i) {
786  dummyTimeseries[i*3 + j] = ts[j*n + i];
787  }
788  }
789  efieldData = dummyContainer;
790 #endif
791 
792 
793  fMessage.str("");
794  fMessage << "needed " << difftime(time(NULL), timeStation) << " seconds for Station " << station.GetId();
795  INFODebug(fMessage.str());
796  } // end station loop
797 
798  fMessage.str("");
799  fMessage << "needed " << difftime(time(NULL), timeAllStation) << " seconds for all stations";
800  INFODebug(fMessage.str());
801 
802  if (!event.HasRecShower())
803  event.MakeRecShower();
804 
805  evt::ShowerRecData& shower = event.GetRecShower();
806  if (!shower.HasRRecShower())
807  shower.MakeRRecShower();
808 
809  evt::ShowerRRecData& rShower = shower.GetRRecShower();
810  rShower.SetParameter(revt::eNumberOfStationsWithPulseFound, numberOfStationsWithPulseFound);
811 
812  fMessage.str("");
813  fMessage << "Found " << numberOfStationsWithPulseFound << " stations with signal pulse";
814  INFOFinal(fMessage.str());
815 
816  if (numberOfStationsWithPulseFound == 1)
817  ++fNumberOfEvents1SignalStations;
818  else if (numberOfStationsWithPulseFound == 2)
819  ++fNumberOfEvents2SignalStations;
820  else if (numberOfStationsWithPulseFound == 3)
821  ++fNumberOfEvents3SignalStations;
822  else if (numberOfStationsWithPulseFound == 4)
823  ++fNumberOfEvents4SignalStations;
824  else if (numberOfStationsWithPulseFound == 5)
825  ++fNumberOfEvents5SignalStations;
826  else if (numberOfStationsWithPulseFound >= 5)
827  ++fNumberOfEvents5plusSignalStations;
828 
829 #ifdef WITH_CUDA
830  cudaHostUnregister(ts);
831  cudaHostUnregister(tts);
832  cudaCheckErrors("cudaHostUnregister failed");
833  //cudaStreamDestroy(stream);
834  for (int i = 0; i < 3; ++i)
835  cudaStreamDestroy(streams[i]);
836  cudaCheckErrors("Destroying Stream failed");
837  cudaFree(d_ts);
838  cudaFree(d_tts);
839  cudaCheckErrors("cuda mem free fail");
840  delete[] tts;
841  delete[] ts;
842 #endif
843 
844  return eSuccess;
845  }
846 
847 
849  RdStationSignalReconstructor::Finish()
850  {
851  ostringstream sstr;
852  sstr << "Event statistics:\n"
853  << "\t" << fTotalNumberOfEvents << " events\n"
854  << "\t" << fNumberOfEvents1SignalStations << " = "
855  << 100. * fNumberOfEvents1SignalStations/fTotalNumberOfEvents << "% events with 1 signal station\n"
856  << "\t" << fNumberOfEvents2SignalStations << " = "
857  << 100. * fNumberOfEvents2SignalStations/fTotalNumberOfEvents << "% events with 2 signal stations\n"
858  << "\t" << fNumberOfEvents3SignalStations << " = "
859  << 100. * fNumberOfEvents3SignalStations/fTotalNumberOfEvents << "% events with 3 signal stations\n"
860  << "\t" << fNumberOfEvents4SignalStations << " = "
861  << 100. * fNumberOfEvents4SignalStations/fTotalNumberOfEvents << "% events with 4 signal stations\n"
862  << "\t" << fNumberOfEvents5SignalStations << " = "
863  << 100. * fNumberOfEvents5SignalStations/fTotalNumberOfEvents << "% events with 5 signal stations\n"
864  << "\t" << fNumberOfEvents5plusSignalStations << " = "
865  << 100. * fNumberOfEvents5plusSignalStations/fTotalNumberOfEvents << "% events "
866  "with more than 5 signal stations\n";
867  INFO(sstr);
868  return eSuccess;
869  }
870 
871 
872  void
873  RdStationSignalReconstructor::Noisefinder(const revt::ChannelTimeSeries& channeltrace,
874  double& RMSNoise, double& MeanNoise, double NoiseWindowStart,
875  double NoiseWindowStop)
876  const
877  {
878  unsigned int start = NoiseWindowStart / channeltrace.GetBinning();
879  unsigned int stop = NoiseWindowStop / channeltrace.GetBinning();
880  RMSNoise = TraceAlgorithm::RootMeanSquare(channeltrace, start, stop);
881  MeanNoise = TraceAlgorithm::Mean(channeltrace, start, stop);
882  }
883 
884 
885  void
886  RdStationSignalReconstructor::Pulsefinder(const revt::ChannelTimeSeries& channeltrace,
887  double& PeakAmplitude, double& PeakTime, double& PeakTimeError,
888  double SignalSearchWindowStart, double SignalSearchWindowStop,
889  unsigned int& sample)
890  const
891  {
892  PeakAmplitude = 0;
893  unsigned int start = SignalSearchWindowStart / channeltrace.GetBinning();
894  unsigned int stop = SignalSearchWindowStop / channeltrace.GetBinning();
895 
896  OUT(eInfoDebug) << "Pulsefinder startsample = " << start << " lastsample = " << stop << endl;
897 
898  for (unsigned int i = start; i < stop; ++i) {
899  if (channeltrace[i] > PeakAmplitude) {
900  PeakAmplitude = channeltrace[i];
901  PeakTime = i * channeltrace.GetBinning();
902  sample = i;
903  }
904  }
905  /* Here only the uncertainty due to the finite binnig is considered,
906  * the uncertainty due to noise and from the GPS system is added later. */
907  PeakTimeError = channeltrace.GetBinning() / std::sqrt(12);
908  }
909 
910 
911  double
912  RdStationSignalReconstructor::GetAdjustedSignalAmplitude(const double signalAmpitude, const double SNR)
913  const
914  {
915  OUT(eInfoDebug) << "adjusting signal amplitude with a factor of " << 1 + 0.95 / sqrt(pow(SNR, 2.3))
916  << endl;
917  return signalAmpitude / (1 + 1.55 / sqrt(pow(SNR, 2.43)));
918  }
919 
920 
921  double
922  RdStationSignalReconstructor::GetSignalUncertainty(const double signalAmplitude, const double SNR)
923  const
924  {
925  return (0.423/sqrt(SNR) - 0.501/SNR + 3.395/pow(SNR,1.5) ) * signalAmplitude;
926  }
927 
928 
929  double
930  RdStationSignalReconstructor::GetSignalTimeUncertainty(const double SNR)
931  const
932  {
933  return 11.7 * utl::ns * std::pow(SNR, -0.71);
934  }
935 
936 
937  void
938  RdStationSignalReconstructor::PulseFWHMIntegrator(const revt::ChannelTimeSeries& channeltrace,
939  unsigned int sample, const double PeakAmplitude,
940  double& SignalTimeFWHM, double& IntegratedSignal,
941  double& SignalWindowStart, double& SignalWindowStop)
942  const
943  {
944  SignalTimeFWHM = 0;
945  IntegratedSignal = 0;
946  unsigned int tmp = sample;
947 
948  while (sample < channeltrace.GetSize() && channeltrace[sample] > 0.5 * PeakAmplitude) {
949  ++SignalTimeFWHM;
950  IntegratedSignal += channeltrace[sample];
951  ++sample;
952  }
953  SignalWindowStop = sample * channeltrace.GetBinning();
954  sample = tmp;
955 
956  while (sample > 0 && channeltrace[sample] > 0.5 * PeakAmplitude) {
957  ++SignalTimeFWHM;
958  IntegratedSignal += channeltrace[sample];
959  --sample;
960  }
961  SignalWindowStart = sample * channeltrace.GetBinning();
962  SignalTimeFWHM = SignalTimeFWHM * channeltrace.GetBinning();
963  }
964 
965 
966  void
967  RdStationSignalReconstructor::PulseFixedWindowIntegrator(const revt::ChannelTimeSeries& channeltrace,
968  unsigned int sample, double IntegrationTime,
969  double& IntegratedSignal, double& SignalWindowStart,
970  double& SignalWindowStop, const bool usePower)
971  const
972  {
973  IntegratedSignal = 0;
974  SignalWindowStart = sample * channeltrace.GetBinning() - IntegrationTime / 2;
975  SignalWindowStop = sample * channeltrace.GetBinning() + IntegrationTime / 2;
976  unsigned int start = max(0.0, sample - IntegrationTime / 2 / channeltrace.GetBinning());
977  unsigned int stop = min(channeltrace.GetSize() * 1., sample + IntegrationTime / 2 / channeltrace.GetBinning());
978  for (unsigned int i = start; i <= stop; ++i) {
979  if (usePower) {
980  IntegratedSignal += Sqr(channeltrace[i]);
981  } else {
982  IntegratedSignal += fabs(channeltrace[i]);
983  }
984  }
985  IntegratedSignal *= channeltrace.GetBinning();
986  }
987 
988 
989  void
990  RdStationSignalReconstructor::PulseSlidingWindowIntegrator(const revt::ChannelTimeSeries& channeltrace,
991  double IntegrationTime, double& IntegratedSignal,
992  double& SignalWindowStart, double& SignalWindowStop,
993  double SignalSearchWindowStart,
994  double SignalSearchWindowStop)
995  const
996  {
997  double binning = channeltrace.GetBinning();
998  IntegratedSignal = 0;
999  int count = 0;
1000  int startSample = 0;
1001  int stopSample = 0;
1002  for (int windowStartPos = SignalSearchWindowStart / binning;
1003  windowStartPos <= (SignalSearchWindowStop - IntegrationTime) / binning; ++windowStartPos) {
1004  double newIntegratedSignal = 0;
1005  count = 0;
1006  for (int integratePos = 0; integratePos < IntegrationTime / binning; ++integratePos) {
1007  newIntegratedSignal += Sqr(channeltrace[windowStartPos + integratePos]);
1008  ++count;
1009  }
1010  newIntegratedSignal /= count;
1011  if (newIntegratedSignal > IntegratedSignal) {
1012  IntegratedSignal = newIntegratedSignal;
1013  SignalWindowStart = windowStartPos * binning;
1014  startSample = windowStartPos;
1015  stopSample = windowStartPos + IntegrationTime / binning;
1016  }
1017  }
1018  SignalWindowStop = SignalWindowStart + IntegrationTime;
1019 
1020  ostringstream info;
1021  info
1022  << "RdStationSignalReconstructor::PulseSlidingWindowIntegrator():\n"
1023  << " IntegrationTime = " << IntegrationTime << " ns\n"
1024  << " SignalSearchWindowStart = " << SignalSearchWindowStart/ns << " ns\n"
1025  << " SignalSearchWindowStop = " << SignalSearchWindowStop/ns << " ns\n"
1026  << " SignalWindowStart = " << SignalWindowStart/ns << " ns\n"
1027  << " SignalWindowStop = " << SignalWindowStop/ns << " ns\n"
1028  << " startSample = " << startSample << " samples\n"
1029  << " stopSample = " << stopSample << " samples\n"
1030  << " IntegratedSignal = " << IntegratedSignal/(micro*volt/meter)/(micro*volt/meter)
1031  << "(\\mu V)^2 / m^2" << endl;
1032  INFOIntermediate(info);
1033 
1034  }
1035 
1036 
1037  ROOT::Minuit2::MnUserParameterState
1038  RdStationSignalReconstructor::FitAnalyticSignal(utl::Trace<double>& trace,
1039  const double noiseRMS,
1040  Station& /*station*/,
1041  const int /*polarization*/,
1042  const bool fixPhaseSlope,
1043  const double phaseSlope)
1044  {
1045  unsigned int nop = trace.GetSize(); // number of points in time domain
1046  if ((nop / 2) * 2 != nop) {
1047  trace.PopBack();
1048  nop = trace.GetSize();
1049  // WARNING("Warning: channel time series with uneven number of samples was clipped by one sample at the end before FFT!");
1050  }
1051  // determine start values by fit in frequency domain
1052  unsigned int n = trace.GetSize(); // number of points in time domain
1053  unsigned int np = n / 2 + 1; // number of points in frequency domain
1054 
1055  double* const f = FFTWdouble(n); // allocate memory through fftw, making sure it is correctly aligned
1056  complex<double>* const g = FFTWComplex(np);
1057  fftwpp::rcfft1d Forward(n, f, g); // "plan" fft through fftw
1058  // fill fftw array, normalising on the way - maybe implement a more efficient way through copying ("reverse adopt") in Trace
1059  TGraph gTrace = TGraph();
1060  for (unsigned int i = 0; i < n; ++i) {
1061  f[i] = trace[i] * trace.GetBinning();
1062  gTrace.SetPoint(gTrace.GetN(), i * trace.GetBinning(), trace[i]);
1063  }
1064  Forward.fft(f, g);
1065 
1066  // calculate bins of frequency 30MHz and 80MHz
1067  const double timeBinning = trace.GetBinning();
1068  //fixme: better get bandwidth of detector from time dependend detector description
1069  unsigned int startBin = static_cast<int>(std::ceil(30 * utl::MHz * timeBinning * n));
1070  unsigned int stopBin = static_cast<int>(std::floor(80 * utl::MHz * timeBinning * n));
1071  const double frequencyBinning = 0.5 / timeBinning / (static_cast<double>(np) - 1);
1072  TGraph gAmplitude;
1073  TGraph gPhase;
1074  TGraph gPhaseUnwrapped;
1075  for (unsigned int i = startBin; i <= stopBin; ++i) {
1076  gAmplitude.SetPoint(gAmplitude.GetN(), i * frequencyBinning, std::abs(g[i]));
1077  }
1078  gPhase.SetPoint(gPhase.GetN(), startBin * frequencyBinning, std::arg(g[startBin]));
1079  gPhaseUnwrapped.SetPoint(gPhaseUnwrapped.GetN(), startBin * frequencyBinning,
1080  std::arg(g[startBin]));
1081  int k = 0;
1082  const double pi = M_PI;
1083  for (unsigned int i = startBin + 1; i <= stopBin; ++i) {
1084  double previousPhase = std::arg(g[i - 1]);
1085  double phase = std::arg(g[i]);
1086  gPhase.SetPoint(gPhase.GetN(), i * frequencyBinning, phase);
1087  if ((phase - previousPhase) > pi) {
1088  --k;
1089  }
1090  if ((phase - previousPhase) < -1. * pi) {
1091  ++k;
1092  }
1093  phase += k * 2. * pi;
1094  gPhaseUnwrapped.SetPoint(gPhaseUnwrapped.GetN(), i * frequencyBinning, phase);
1095  }
1096  FFTWdelete(f/*, n*/);
1097  FFTWdelete(g/*, np*/);
1098 
1099  TFitResultPtr r_amp = gAmplitude.Fit("pol1", "S");
1100  TFitResultPtr r_phase =gPhaseUnwrapped.Fit("pol1", "S");
1101 
1102  // save debug plots
1103  // TCanvas *c1 = new TCanvas("c1", "", 1500, 800);
1104  // c1->Divide(1,3);
1105  // c1->cd(1);
1106  // gAmplitude.Draw("A*");
1107  // c1->cd(2);
1108  // gPhaseUnwrapped.SetLineColor(6);
1109  // gPhaseUnwrapped.Draw("AL");
1110  // gPhase.Draw("L");
1111  // c1->cd(3);
1112  // gTrace.Draw("AL*");
1113  // stringstream filename;
1114  // filename << "debug/station" << station.GetId() << "_" << polarization << ".png";
1115  // c1->SaveAs(filename.str().c_str());
1116  // delete c1;
1117 
1118  ROOT::Minuit2::MnUserParameters upar;
1119  upar.Add("amplitude_p0", r_amp->Parameter(0), r_amp->ParError(0));
1120  upar.Add("amplitude_p1", r_amp->Parameter(1), r_amp->ParError(1));
1121  upar.Add("phase_p0", r_phase->Parameter(0), r_phase->ParError(0));
1122  upar.Add("phase_p1", r_phase->Parameter(1), r_phase->ParError(1));
1123  if (fixPhaseSlope) {
1124  upar.SetLimits("phase_p1", phaseSlope - 0.01 / utl::MHz, phaseSlope + 0.01 / utl::MHz);
1125  }
1126 
1127  SignalObjectiveFunction fitFunction = SignalObjectiveFunction(trace, noiseRMS);
1128  ROOT::Minuit2::MnMigrad migrad(fitFunction, upar);
1129 
1130  // perform minimization
1131  ROOT::Minuit2::FunctionMinimum minimum = migrad(); // minimize calles migrad algorithm. If migrad fails it calls simplex and then migrad again.
1132  ostringstream info;
1133  info << "Result of analytic signal fit: " << minimum;
1134  INFOIntermediate(info);
1135 
1136  ROOT::Minuit2::MnUserParameterState minUstate_tmp = minimum.UserState();
1137  return minUstate_tmp;
1138  }
1139 
1140 
1141  double
1142  SignalObjectiveFunction::operator()(const std::vector<double>& pars)
1143  const
1144  {
1145  unsigned int n = fTrace.GetSize(); // number of points in time domain
1146  unsigned int np = n / 2 + 1; // number of points in frequency domain
1147 
1148  double* const f = FFTWdouble(n); // allocate memory through fftw, making sure it is correctly aligned
1149  complex<double>* const g = FFTWComplex(np);
1150 
1151  fftwpp::crfft1d Backward(n, g, f); // "plan" fft^-1 through fftw
1152 
1153  // calculate bins of frequency 30MHz and 80MHz
1154  double timeBinning = fTrace.GetBinning();
1155  //fixme: better get bandwidth of detector from time dependend detector description
1156  unsigned int startBin = static_cast<int>(std::ceil(30 * utl::MHz * timeBinning * n));
1157  unsigned int stopBin = static_cast<int>(std::floor(80 * utl::MHz * timeBinning * n));
1158  const double frequencyBinning = 0.5 / timeBinning / (static_cast<double>(np) - 1);
1159  for (unsigned int i = 0; i < np; ++i) {
1160  if (i < startBin || i > stopBin) {
1161  g[i] = 0;
1162  } else {
1163  g[i] = std::polar(pars[0] + pars[1] * i * frequencyBinning,
1164  pars[2] + pars[3] * i * frequencyBinning) * frequencyBinning;
1165  }
1166  }
1167  Backward.fft(g, f);
1168 
1169  // calculate chi2
1170  double chi2(0);
1171  for (unsigned int i = 0; i < n; ++i) {
1172  chi2 += (fTrace[i] - f[i]) * (fTrace[i] - f[i]) / (fSigma * fSigma);
1173  }
1174 
1175  FFTWdelete(f/*, n*/);
1176  FFTWdelete(g/*, np*/);
1177  return chi2 / n;
1178  }
1179 
1180 }
Branch GetTopBranch() const
Definition: Branch.cc:63
Class to access station level reconstructed data.
void SetParameter(Parameter i, double value, bool lock=true)
void SetParameterError(Parameter i, double value, bool lock=true)
utl::Point GetReferenceCorePosition(const Event &event) const
Returning the reference core position depending on the corresponding flag.
constexpr T Sqr(const T &x)
boost::filter_iterator< CandidateStationFilter, AllStationIterator > CandidateStationIterator
Iterator over all CandidateStations (i.e., HasSignal, HasNoSignal)
Definition: REvent.h:141
int GetId() const
Return Id of the Channel.
StationTriggerData & GetTriggerData()
Get Trigger data for the station.
boost::indirect_iterator< InternalChannelIterator, Channel & > ChannelIterator
Iterator over station for read/write.
constexpr double MHz
Definition: AugerUnits.h:159
void SetPulseFound(const bool pulsefound)
StationRecData & GetRecData()
Get station level reconstructed data.
Interface class to access Shower Reconstructed parameters.
Definition: ShowerRecData.h:33
bool HasRecShower() const
CandidateStationIterator CandidateStationsEnd()
Definition: REvent.h:146
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
#define FFTWdouble
Definition: fftw++.h:94
Interface class to access to the RD Reconstruction of a Shower.
double GetParameterError(const Parameter i) const
bool HasReferenceAxis(const Event &event) const
Return always true for SD and FD if RecShower exsist, asking for min. rec stage could fix this...
double GetBinning() const
size of one slot
Definition: Trace.h:138
const double meter
Definition: GalacticUnits.h:29
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
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
double pow(const double x, const unsigned int i)
bool HasREvent() const
ShowerRRecData & GetRRecShower()
ChannelIterator ChannelsEnd()
end Channel iterator for read/write
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Iterator next(Iterator it)
#define INFOIntermediate(y)
Definition: VModule.h:162
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
class to hold data at the radio Station level.
std::vector< T >::size_type SizeType
Definition: Trace.h:58
void PopBack()
Remove one value at the end of the trace.
Definition: Trace.h:129
const double ns
void fft(Complex *in, Complex *out=NULL)
Definition: fftw++.h:414
double abs(const SVector< n, T > &v)
bool HasRRecShower() const
C< T > & GetTimeSeries()
read out the time series (write access)
CandidateStationIterator CandidateStationsBegin()
Definition: REvent.h:144
constexpr double g
Definition: AugerUnits.h:200
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
int GetId() const
Get the station Id.
#define INFODebug(y)
Definition: VModule.h:163
double GetParameter(const Parameter i) const
void SetBinning(const double binning)
Definition: Trace.h:139
Template class for a data container that offers and takes both time series and corresponding frequenc...
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
bool HasParameter(const Parameter i) const
bool HasReferenceCorePosition(const Event &event) const
Return always true for SD and FD if RecShower exsist, asking for min. rec stage could fix this...
#define FFTWComplex
Definition: fftw++.h:93
const StationFFTDataContainer & GetFFTDataContainer() const
retrieve Station FFTDataContainer (read access)
Template class for a FADC data or calibrated data container. Use the typedefs (TraceD, TraceI, etc.) defined in Trace-fwd.h.
Definition: Trace-fwd.h:19
TriggerSource GetTriggerSource() const
Get the Trigger Source of the station, i.e. if it triggered itself or was triggered by the central st...
void SetParameter(Parameter i, double value, bool lock=true)
Vector object.
Definition: Vector.h:30
Class that holds the data associated to an individual radio channel.
constexpr double kConversionRadioSignalToEnergyFluence
utl::Vector GetReferenceAxis(const Event &event) const
Returning the referencedirection depending on the corresponding flag.
constexpr double micro
Definition: AugerUnits.h:65
constexpr double ns
Definition: AugerUnits.h:162
double Mean(const std::vector< double > &v)
Definition: Functions.h:31
bool HasRecData() const
Check whether station reconstructed data exists.
#define INFOFinal(y)
Definition: VModule.h:161
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
void PushBack(const T &value)
Insert a single value at the end.
Definition: Trace.h:119
utl::Vector GetMagneticFieldVector() const
returns the magnetic field vector from the components stored in the parameter storage ...
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
#define FFTWdelete
Definition: fftw++.h:95
utl::TraceV3D GetTraceInShowerPlaneVxB(const utl::TraceV3D &trace) const
const double volt
Definition: GalacticUnits.h:38

, generated on Tue Sep 26 2023.