WaveformCombiner.cc
1 #include "WaveformCombiner.h"
2 #include "AntennaPositions.h"
3 #include <vector>
4 #include "BasicFilters.h"
5 #include "FilteredAnitaEvent.h"
6 #include "AnitaVersion.h"
7 #include "FFTtools.h"
8 #include "ResponseManager.h"
9 #include "SystemResponse.h"
10 #include "DeltaT.h"
11 #include <dirent.h>
12 #include <sys/types.h>
13 #include <stdio.h>
14 
15  UCorrelator::WaveformCombiner::WaveformCombiner(int nantennas, int npad, bool useUnfiltered, bool deconvolve, const AnitaResponse::ResponseManager * response, bool alfa_hack)
16 : coherent(260), deconvolved(260), alfa_hack(alfa_hack)
17 {
18  setNAntennas(nantennas);
19  setNPad(npad);
20  setDeconvolve(deconvolve);
21  setUseUnfiltered(useUnfiltered);
22  setGroupDelayFlag(true);
23  setRTimeShiftFlag(true);
24  use_raw= useUnfiltered;
25  setResponseManager(response);
26  setBottomFirst(false);
27  setDelayToCenter(false);
28  extra_filters = 0;
29  extra_filters_deconvolved = 0;
30  enable_r_time_shift = true;
31  enable_simulation_time_shift = false;
32  max_vpp = 0;
33  check_vpp = 0;
34 }
35 
36 
37 
38 
39 
40 UCorrelator::WaveformCombiner::~WaveformCombiner()
41 {
42 }
43 
44 const AnalysisWaveform * UCorrelator::WaveformCombiner::getDeconvolved() const
45 {
46 
47  if (!do_deconvolution)
48  {
49  // fprintf(stderr,"WARNING! Deconvolution has not been enabled!\n");
50  return 0;
51  }
52 
53  return &deconvolved;
54 }
55 
56 
57 
58 
59 static void scaleGraph(TGraph * g, double C)
60 {
61 
62  int max = g->GetN();
63 
64  for (int i = 0; i < max; i++)
65  {
66  g->GetY()[i] *= C;
67  }
68 }
69 
70 static void addToGraph(TGraph * g, const TGraph * h)
71 {
72  int max = TMath::Min(g->GetN(), h->GetN());
73  for (int i = 0; i < max; i++)
74  {
75  g->GetY()[i] += h->GetY()[i];
76  }
77 }
78 
79 
80 const AnalysisWaveform * UCorrelator::WaveformCombiner::wf (const FilteredAnitaEvent * event, int ant, AnitaPol::AnitaPol_t pol)
81 {
82  return use_raw ? event->getRawGraph(ant, pol) : event->getFilteredGraph(ant,pol);
83 
84 
85 }
86 
87 
88 static SimplePassBandFilter alfa_filter(0,0.6);
89 
90 void UCorrelator::WaveformCombiner::combine(double phi, double theta, const FilteredAnitaEvent * event, AnitaPol::AnitaPol_t pol, ULong64_t disallowed, double t0, double t1, double * avg_of_peaks, bool use_hilbert)
91 {
92 
93  std::vector<AnalysisWaveform> padded(nant);
94  const int numDeconv = do_deconvolution ? nant : 0;
95  std::vector<AnalysisWaveform> deconv(numDeconv);
96 
97  const UCorrelator::AntennaPositions * antpos = UCorrelator::AntennaPositions::instance();
98  nant = antpos->getClosestAntennas(phi, nant, &antennas[0], disallowed);
99  double delays[nant];
100 
101  if (bottom_first) {
102  if (antennas[0] < 32) {
103  int toMove = antennas[0];
104  if (antennas[1] > 32) {
105  antennas[0] = antennas[1];
106  antennas[1] = toMove; }
107  else {
108  antennas[0] = antennas[2];
109  antennas[2] = toMove; }
110  }
111  }
112 
113  double sum_peak = 0;
114  for (int i = 0; i < nant; i++)
115  {
116  //ensure transform already calculated so we don't have to repeat when deconvolving
117  (void) wf(event,antennas[i],pol)->freq();
118  int ipol = (pol == AnitaPol::kVertical) ? 1 : 0;
119 
120  padded[i].~AnalysisWaveform();
121  new (&padded[i]) AnalysisWaveform(*wf(event,antennas[i],pol));
122  if(extra_filters)
123  {
124  for(int j = 0; j < (int) extra_filters->nOperations(); j++)
125  {
126  FilterOperation * filterOp = (FilterOperation*) extra_filters->getOperation(j);
127  filterOp->processOne(&padded[i], event->getHeader(), antennas[i], ipol);
128  //delete filterOp;
129  }
130  }
131 
132  if (i == 0)
133  {
134  const TGraphAligned *p = wf(event,antennas[0],pol)->power();
135  coherent_avg_spectrum.adopt(p);
136  }
137  else
138  {
139  addToGraph(&coherent_avg_spectrum,wf(event,antennas[0],pol)->power());
140  }
141 
142  //ALFA HACK IS HERE
143  if (alfa_hack && AnitaVersion::get() == 3 && pol == AnitaPol::kHorizontal && (antennas[i] == 4 || antennas[i] == 12))
144  {
145  alfa_filter.processOne(&padded[i]);
146  }
147 
148  if (avg_of_peaks)
149  {
150  sum_peak += (use_hilbert ? padded[i].hilbertEnvelope() : padded[i].even())->peakVal();
151  }
152 
153 
154  padded[i].padFreq(npad);
155 
156  if (do_deconvolution)
157  {
158  deconv[i].~AnalysisWaveform();
159  new (&deconv[i]) AnalysisWaveform(*wf(event,antennas[i],pol));
160  if(extra_filters_deconvolved)
161  {
162  for(int j = 0; j < (int) extra_filters_deconvolved->nOperations(); j++)
163  {
164  FilterOperation * filterOp = (FilterOperation*) extra_filters_deconvolved->getOperation(j);
165  filterOp->processOne(&deconv[i], event->getHeader(), antennas[i], ipol);
166  //delete filterOp;
167  }
168  }
169  responses->response(pol,antennas[i])->deconvolveInPlace(&deconv[i], responses->getDeconvolutionMethod(), theta ); //TODO add angle
170  if (i == 0)
171  {
172  const TGraphAligned *p =deconv[i].power();
173  deconvolved_avg_spectrum.adopt(p);
174  }
175  else
176  {
177  addToGraph(&deconvolved_avg_spectrum, deconv[i].power());
178  }
179  deconv[i].padFreq(npad);
180  }
181 
182  if (delay_to_center) delays[i] = getDeltaTtoCenter(antennas[i], phi, theta, pol, enable_group_delay, enable_r_time_shift, enable_simulation_time_shift);
183  else delays[i] = i == 0 ? 0 : getDeltaT(antennas[i], antennas[0], phi, theta, pol, enable_group_delay);
184 
185  }
186 
187  max_vpp = combineWaveforms(nant, &padded[0], delays, 0, &coherent, t0, t1, check_vpp);
188  scaleGraph(&coherent_avg_spectrum, 1./nant);
189  if (do_deconvolution)
190  {
191  combineWaveforms(nant, &deconv[0], delays, 0, &deconvolved, t0, t1, 0);
192  scaleGraph(&deconvolved_avg_spectrum, 1./nant);
193  }
194 
195  if (avg_of_peaks)
196  {
197  *avg_of_peaks = sum_peak / nant;
198  }
199 }
200 
201 
202 double UCorrelator::WaveformCombiner::combineWaveforms(int nwf, const AnalysisWaveform * wf, const double * delays, const double * scales, AnalysisWaveform * out, double min, double max, int checkvpp)
203 {
204  // we want to make the waveform as big as the entire span of all the waveforms to combine
205 
206  double dt = wf[0].deltaT();
207 
208  int N = ceil((max-min)/dt);
209  double maxvpp = 0;
210 
211  if (!out) out = new AnalysisWaveform(N);
212  TGraph * gupdate = out->updateEven();
213  gupdate->Set(N);
214 
215  for (int i = 0; i < N; i++)
216  {
217  gupdate->GetX()[i] = min + i * dt;
218 
219  double val = 0;
220  for (int j = 0; j < nwf; j++)
221  {
222  double scale = scales ? scales[j] : 1;
223  double tempvpp = 0;
224  val += wf[j].evalEven(gupdate->GetX()[i] + delays[j])/nwf*scale;
225  if(i == 0)
226  {
227  if(checkvpp == 1)
228  {
229  tempvpp = wf[j].even()->pk2pk();
230  if(maxvpp < tempvpp) maxvpp = tempvpp;
231  }
232  if(checkvpp == 2)
233  {
234  tempvpp = wf[j].even()->pk2pk()/double(nwf);
235  maxvpp += tempvpp;
236  }
237  }
238  }
239 
240  // printf("%f %f\n", gupdate->GetX()[i], val);
241  gupdate->GetY()[i] = val;
242  }
243 
244  return maxvpp;
245 }
246 
248 {
249  if(extra_filters) delete extra_filters;
250  extra_filters = extra;
251 }
252 
254 {
255  if(extra_filters_deconvolved) delete extra_filters_deconvolved;
256  extra_filters_deconvolved = extra;
257 }
258 
double evalEven(double t, EvenEvaluationType=EVAL_LINEAR) const
void setResponseManager(const AnitaResponse::ResponseManager *rm)
virtual void processOne(AnalysisWaveform *, const RawAnitaHeader *=0, int=0, int pol=0)
Definition: BasicFilters.cc:7
static double combineWaveforms(int nwf, const AnalysisWaveform *wfs, const double *delays, const double *scales=0, AnalysisWaveform *output=0, double t0=0, double t1=100, int checkvpp=0)
double getDeltaTtoCenter(int ant1, double phi, double theta, AnitaPol::AnitaPol_t pol, bool includeGroupDelay=false, bool includeTimeShift=true, bool simulationTimeShift=false)
Definition: DeltaT.h:43
TGraphAligned * updateEven()
A filter strategy defines the sets of filters that are used and provides some introspection abilities...
double getDeltaT(int ant1, int ant2, double phi, double theta, AnitaPol::AnitaPol_t pol, bool includeGroupDelay=false)
Definition: DeltaT.h:68
void combine(double phi, double theta, const FilteredAnitaEvent *event, AnitaPol::AnitaPol_t pol, ULong64_t disallowed=0, double t0=0, double t1=100, double *avg_of_peaks=0, bool use_hilbert=true)
void setExtraFilters(FilterStrategy *extra)
void setExtraFiltersDeconvolved(FilterStrategy *extra)
double deltaT() const
int getClosestAntennas(double phi, int N, int *closest, ULong64_t disallowed=0, AnitaPol::AnitaPol_t pol=AnitaPol::kHorizontal) const
Vertical Polarisation.
const TGraphAligned * even() const
Horizontal Polarisation.
This class is intended to store all the necessary data about an ANITA event for filtering and analysi...
enum AnitaPol::EAnitaPol AnitaPol_t
Polarisation enumeration.
virtual void processOne(AnalysisWaveform *awf, const RawAnitaHeader *header=0, int ant=0, int pol=0)=0
This class is intended to be the main storage vessel for ANITA waveforms. It is similar in principle ...
const RawAnitaHeader * getHeader() const