CrossCorrelator.cxx
1 #include "CrossCorrelator.h"
2 
3 //---------------------------------------------------------------------------------------------------------
9 }
10 
11 
12 
13 
14 
15 //---------------------------------------------------------------------------------------------------------
20  for(Int_t pol = AnitaPol::kHorizontal; pol < AnitaPol::kNotAPol; pol++){
21  deleteAllWaveforms((AnitaPol::AnitaPol_t)pol);
22  }
23 }
24 
25 
26 //---------------------------------------------------------------------------------------------------------
31 
32  kDeltaPhiSect = 2;
34 
35  // Initialize with NULL otherwise very bad things will happen with gcc
36  for(Int_t pol = AnitaPol::kHorizontal; pol < AnitaPol::kNotAPol; pol++){
37  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
38  grs[pol][ant] = NULL;
39  grsResampled[pol][ant] = NULL;
40  interpRMS[pol][ant] = 0;
41  }
42  lastEventNormalized[pol] = -1;
43  eventNumber[pol] = -1;
44  }
45 
46  maxDPhiDeg = 0;
47  kOnlyThisCombo = -1;
48  kUseOffAxisDelay = 1;
49  numSamples = PAD_FACTOR*NUM_SAMPLES; // Factor of two for padding. Turns circular xcor into linear xcor.
50  numSamplesUpsampled = numSamples*UPSAMPLE_FACTOR; // For upsampling
51 
52  nominalSamplingDeltaT = NOMINAL_SAMPLING_DELTAT;
53  correlationDeltaT = nominalSamplingDeltaT/UPSAMPLE_FACTOR;
54 
56 
57  AnitaGeomTool* geom = AnitaGeomTool::Instance();
58  for(Int_t pol=0; pol < NUM_POL; pol++){
59  for(int ant=0; ant<NUM_SEAVEYS; ant++){
60  rArray[pol].push_back(geom->getAntR(ant, AnitaPol::AnitaPol_t(pol)));
61  zArray[pol].push_back(geom->getAntZ(ant, AnitaPol::AnitaPol_t(pol)));
62  phiArrayDeg[pol].push_back(geom->getAntPhiPositionRelToAftFore(ant, AnitaPol::AnitaPol_t(pol))*TMath::RadToDeg());
63  }
64  }
65  aftForeOffset = geom->aftForeOffsetAngleVertical*TMath::RadToDeg(); //phiArrayDeg[0].at(0);
66 
68 
69  for(Int_t pol=0; pol < NUM_POL; pol++){
70  for(Int_t peakInd=0; peakInd < MAX_NUM_PEAKS; peakInd++){
71  coarseMapPeakValues[pol][peakInd] = -9999;
72  coarseMapPeakPhiDegs[pol][peakInd] = -9999;
73  coarseMapPeakThetaDegs[pol][peakInd] = -9999;
74 
75  fineMapPeakValues[pol][peakInd] = -9999;
76  fineMapPeakPhiDegs[pol][peakInd] = -9999;
77  fineMapPeakThetaDegs[pol][peakInd] = -9999;
78  }
79  }
80 
81  mapModeNames[kGlobal] = "Global";
82  mapModeNames[kTriggered] = "Triggered";
83  zoomModeNames[kZoomedOut] = "";
84  zoomModeNames[kZoomedIn] = "Zoom";
85 
86  threadPol = AnitaPol::kHorizontal;
87 
88  for(Long_t threadInd=0; threadInd<NUM_THREADS; threadInd++){
89  CrossCorrelator::threadArgs threadArgVals;
90  threadArgVals.threadInd = threadInd;
91  threadArgVals.ptr = this;
92  threadArgsVec.push_back(threadArgVals);
93 
94  // Creation of fftw plans is not thread safe,
95  // so we need to create plans before doing any fftw
96  // plans inside a thread.
99  }
100 }
101 
102 
103 
104 
105 //---------------------------------------------------------------------------------------------------------
110  std::cerr << __PRETTY_FUNCTION__ << std::endl;
111  std::cerr << "\tupsample factor = " << UPSAMPLE_FACTOR << std::endl;
112  std::cerr << "\tBin size theta (deg) = " << Double_t(THETA_RANGE)/NUM_BINS_THETA << std::endl;
113  std::cerr << "\tBin size phi (deg) = " << Double_t(PHI_RANGE)/NUM_BINS_PHI << std::endl;
114  std::cerr << "\tdeltaTs array size = "
115  << sizeof(Double_t)*NUM_POL*numCombos*NUM_PHI*NUM_BINS_PHI*NUM_BINS_THETA
116  << " bytes" << std::endl;
117 }
118 
119 
120 
121 
122 //---------------------------------------------------------------------------------------------------------
129 
130  Double_t phi0 = -aftForeOffset;
131  if(phi0 < -DEGREES_IN_CIRCLE/2){
132  phi0+=DEGREES_IN_CIRCLE;
133  }
134  else if(phi0 >= DEGREES_IN_CIRCLE/2){
135  phi0-=DEGREES_IN_CIRCLE;
136  }
137  return phi0 - PHI_RANGE/2;
138 }
139 
146 
147  Double_t peakValue, peakPhiDeg, peakThetaDeg;
148  TH2D* hBlank = getMap(AnitaPol::kVertical, peakValue, peakPhiDeg, peakThetaDeg);
149 
150  const double maxDeltaAngleDeg = 45;
151  // const double maxDeltaAngleDeg = 50;
152  std::set<std::vector<Int_t> > theSet;
153 
154  Int_t newComboIndices[NUM_SEAVEYS][NUM_SEAVEYS];
155  for(int ant1=0; ant1 < NUM_SEAVEYS; ant1++){
156  for(int ant2=0; ant2 < NUM_SEAVEYS; ant2++){
157  newComboIndices[ant1][ant2] = -1;
158  }
159  }
160  std::vector<int> newComboToAnt1s;
161  std::vector<int> newComboToAnt2s;
162  // const double maxDeltaAngleDeg = 60;
163  for(int biny=0; biny <= hBlank->GetNbinsY(); biny++){
164  Double_t recoTheta = -1*hBlank->GetYaxis()->GetBinLowEdge(biny);
165  // Double_t dTheta = 0;
166  Double_t dTheta = RootTools::getDeltaAngleDeg(10, recoTheta);
167 
168  for(int binx=0; binx <= hBlank->GetNbinsX(); binx++){
169  hBlank->SetBinContent(binx, biny, 0);
170  // Int_t count = 0;
171 
172  std::vector<Int_t> theCombos;
173  Double_t recoPhi = recoPhi = hBlank->GetXaxis()->GetBinLowEdge(binx);
174 
175  for(int ant1=0; ant1 < NUM_SEAVEYS; ant1++){
176  Double_t antPhi1 = phiArrayDeg[AnitaPol::kVertical].at(ant1);
177  Double_t dPhi1 = RootTools::getDeltaAngleDeg(antPhi1, recoPhi);
178 
179  if(TMath::Sqrt(dPhi1*dPhi1 + dTheta*dTheta) < maxDeltaAngleDeg){
180  for(int ant2=ant1+1; ant2 < NUM_SEAVEYS; ant2++){
181  Double_t antPhi2 = phiArrayDeg[AnitaPol::kVertical].at(ant2);
182  Double_t dPhi2 = RootTools::getDeltaAngleDeg(antPhi2, recoPhi);
183 
184  if(TMath::Sqrt(dPhi2*dPhi2 + dTheta*dTheta) < maxDeltaAngleDeg){
185  // if(TMath::Abs(dPhi2) < maxDeltaAngleDeg){
186 
187  Int_t thisCombo = newComboIndices[ant1][ant2];
188  if(thisCombo==-1){
189  newComboIndices[ant1][ant2] = newComboToAnt1s.size();
190  newComboIndices[ant2][ant1] = newComboToAnt1s.size();
191  newComboToAnt1s.push_back(newComboToAnt1s.size());
192  newComboToAnt2s.push_back(newComboToAnt2s.size());
193  thisCombo = newComboIndices[ant1][ant2];
194  }
195  theCombos.push_back(thisCombo);
196  }
197  }
198  }
199  }
200 
201  std::pair<std::set<std::vector<int> >::iterator, bool>ret = theSet.insert(theCombos);
202  comboSetIterator[biny-1][binx-1] = ret.first;
203  hBlank->SetBinContent(binx, biny, theCombos.size());
204  // hBlank->SetBinContent(binx, biny, theSet.size());
205  }
206  }
207 
208  std::cout << "This combinatorics has " << theSet.size()
209  << ", vs. the 16 you would have in a phi-sector based method" << std::endl;
210  std::cout << "This method also gives us... " << newComboToAnt1s.size()
211  << " = " << newComboToAnt2s.size() << " combos, vs. " << NUM_COMBOS << std::endl;
212  hBlank->SetTitle("Number of antenna pairs in reconstruction; Azimuth (Degrees); Elevation (Degrees)");
213  // delete hBlank;
214  return hBlank;
215 }
216 
217 
218 
219 
220 
221 
222 //---------------------------------------------------------------------------------------------------------
233 TGraph* CrossCorrelator::interpolateWithStartTimeAndZeroMean(TGraph* grIn, Double_t startTime,
234  Double_t dt, Int_t nSamp){
235 
236  // I want to interpolate the waveform such that the mean of the post interpolation waveform is zero...
237 
238  std::vector<Double_t> newTimes = std::vector<Double_t>(nSamp, 0); // for the interp volts
239  std::vector<Double_t> newVolts = std::vector<Double_t>(nSamp, 0); // for the interp times
240  std::vector<Int_t> isPadding = std::vector<Int_t>(nSamp, 1); // whether or not the value is padding
241  Double_t thisStartTime = grIn->GetX()[0];
242  Double_t lastTime = grIn->GetX()[grIn->GetN()-1];
243 
244  // // Quantizes the start and end times so data points lie at integer multiples of nominal sampling
245  // // perhaps not really necessary if all waveforms have the same start time...
246  // startTime = dt*TMath::Nint(startTime/dt + 0.5);
247  // lastTime = dt*TMath::Nint(lastTime/dt - 0.5);
248 
249  //ROOT interpolator object constructor takes std::vector objects
250  std::vector<Double_t> tVec(grIn->GetX(), grIn->GetX() + grIn->GetN());
251  std::vector<Double_t> vVec(grIn->GetY(), grIn->GetY() + grIn->GetN());
252 
253  // This is ROOT's interpolator object
254  ROOT::Math::Interpolator chanInterp(tVec,vVec,ROOT::Math::Interpolation::kAKIMA);
255 
256  // Put new data into arrays
257  Double_t sum = 0;
258  Double_t time = startTime;
259  Int_t meanCount = 0;
260  for(Int_t samp = 0; samp < nSamp; samp++){
261  newTimes.at(samp) = time;
262  if(time >= thisStartTime && time <= lastTime){
263  Double_t V = chanInterp.Eval(time);
264  newVolts.at(samp) = V;
265  sum += V;
266  isPadding.at(samp) = 0;
267  meanCount++;
268  }
269  else{
270  newVolts.at(samp) = 0;
271  }
272  time += dt;
273  }
274 
275  // so now we have the new arrays, time to normalize these bad boys
276  Double_t mean = sum/meanCount; // the mean of the non-padded values
277  for(Int_t samp=0; samp < nSamp; samp++){
278  if(isPadding.at(samp)==0){
279  newVolts.at(samp) -= mean;
280  }
281  }
282 
283  return new TGraph(nSamp, &newTimes[0], &newVolts[0]);
284 
285 }
286 
287 
288 
289 //---------------------------------------------------------------------------------------------------------
296 void CrossCorrelator::getNormalizedInterpolatedTGraphs(UsefulAnitaEvent* usefulEvent,
297  AnitaPol::AnitaPol_t pol){
298 
299  // Delete any old waveforms (at start rather than end to leave in memory to be examined if need be)
300  deleteAllWaveforms(pol);
301 
302 
303  std::vector<Double_t> earliestStart(NUM_POL, 100); // ns
304  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
305  grs[pol][ant] = usefulEvent->getGraph(ant, (AnitaPol::AnitaPol_t)pol);
306 
307  // Find the start time of all waveforms
308  if(grs[pol][ant]->GetX()[0]<earliestStart.at(pol)){
309  earliestStart.at(pol) = grs[pol][ant]->GetX()[0];
310  }
311  }
312 
313  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
314  grsResampled[pol][ant] = interpolateWithStartTimeAndZeroMean(grs[pol][ant], earliestStart.at(pol),
316 
317  Double_t sumOfVSquared = 0;
318  for(int samp=0; samp < grsResampled[pol][ant]->GetN(); samp++){
319  Double_t V = grsResampled[pol][ant]->GetY()[samp];
320  sumOfVSquared += V*V;
321  }
322  interpRMS[pol][ant] = TMath::Sqrt(sumOfVSquared/numSamples);
323  interpRMS2[pol][ant] = TMath::Sqrt(sumOfVSquared/numSamplesUpsampled);
324  for(int samp=0; samp < grsResampled[pol][ant]->GetN(); samp++){
325  grsResampled[pol][ant]->GetY()[samp]/=interpRMS[pol][ant];
326  }
327  }
328 
329  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
330 
331  TString name, title;
332  TString name2, title2;
333  if(pol==AnitaPol::kHorizontal){
334  name = TString::Format("gr%dH_%u", ant, usefulEvent->eventNumber);
335  name2 = TString::Format("grInterp%dH_%u", ant, usefulEvent->eventNumber);
336  title = TString::Format("Antenna %d HPOL eventNumber %u", ant, usefulEvent->eventNumber);
337  title2 = TString::Format("Antenna %d HPOL eventNumber %u (evenly resampled)",
338  ant, usefulEvent->eventNumber);
339  }
340  else if(pol==AnitaPol::kVertical){
341  name = TString::Format("gr%dV_%u", ant, usefulEvent->eventNumber);
342  name2 = TString::Format("grInterp%dV_%u", ant, usefulEvent->eventNumber);
343  title = TString::Format("Antenna %d VPOL eventNumber %u", ant, usefulEvent->eventNumber);
344  title2 = TString::Format("Antenna %d VPOL eventNumber %u (evenly resampled)",
345  ant, usefulEvent->eventNumber);
346  }
347  title += "; Time (ns); Voltage (mV)";
348  grs[pol][ant]->SetName(name);
349  grsResampled[pol][ant]->SetName(name2);
350  grs[pol][ant]->SetTitle(title);
351  grsResampled[pol][ant]->SetTitle(title2);
352  }
353 
354  lastEventNormalized[pol] = usefulEvent->eventNumber;
355 }
356 
357 
358 
359 
360 //---------------------------------------------------------------------------------------------------------
367 void CrossCorrelator::doFFTs(AnitaPol::AnitaPol_t pol){
368 
369  const Double_t anitaBandLowEdge = 200; // MHz
370  const Double_t anitaBandHighEdge = 1200; // MHz
371 
372  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
373  FancyFFTs::doFFT(numSamples, grsResampled[pol][ant]->GetY(), ffts[pol][ant]);
374 
375  simpleNotch(pol, ant, 0, anitaBandLowEdge);
376  simpleNotch(pol, ant, anitaBandHighEdge, DBL_MAX);
377 
379  simple260MHzSatelliteNotch(pol, ant);
380  simple370MHzSatelliteNotch(pol, ant);
381  }
382 
383  renormalizeFourierDomain(pol, ant);
384 
386  }
387 }
388 
389 
390 
391 
392 
393 //---------------------------------------------------------------------------------------------------------
400 void CrossCorrelator::simple260MHzSatelliteNotch(AnitaPol::AnitaPol_t pol, Int_t ant){
401  simpleNotch(pol, ant, 260-26, 260+26);
402 }
403 
404 
405 
406 
407 
408 //---------------------------------------------------------------------------------------------------------
415 void CrossCorrelator::simple370MHzSatelliteNotch(AnitaPol::AnitaPol_t pol, Int_t ant){
416  simpleNotch(pol, ant, 370-20, 370+20);
417 }
418 
419 
420 
421 
422 
423 
424 //---------------------------------------------------------------------------------------------------------
433 void CrossCorrelator::simpleNotch(AnitaPol::AnitaPol_t pol, Int_t ant,
434  Double_t notchLowEdgeMHz, Double_t notchHighEdgeMHz){
435 
436  const int numFreqs = FancyFFTs::getNumFreqs(numSamples);
437  const Double_t deltaF_MHz = 1e3/(numSamples*nominalSamplingDeltaT);
438 
439  for(int freqInd=0; freqInd < numFreqs; freqInd++){
440  if(deltaF_MHz*freqInd >= notchLowEdgeMHz && deltaF_MHz*freqInd < notchHighEdgeMHz){
441  // std::cout << pol << "\t" << ant << "\t" << deltaF_MHz << "\t" << deltaF_MHz*freqInd << "\t" << notchLowEdgeMHz << "\t" << notchHighEdgeMHz << "\t" << std::endl;
442  ffts[pol][ant][freqInd].real(0);
443  ffts[pol][ant][freqInd].imag(0);
444  }
445  }
446 }
447 
448 
449 
450 
451 
452 
453 //---------------------------------------------------------------------------------------------------------
460 void CrossCorrelator::renormalizeFourierDomain(AnitaPol::AnitaPol_t pol, Int_t ant){
461 
462  const int numFreqs = FancyFFTs::getNumFreqs(numSamples);
463  Double_t sumOfVSquared = 0;
464  for(int freqInd=0; freqInd < numFreqs; freqInd++){
465  Double_t re = ffts[pol][ant][freqInd].real();
466  Double_t im = ffts[pol][ant][freqInd].imag();
467  Double_t factor = freqInd == numFreqs - 1 ? 0.5 : 1;
468  sumOfVSquared += factor*(re*re + im*im);
469  }
470 
471  Double_t timeDomainVSquared = sumOfVSquared/(numSamples*numSamples/2);
472  Double_t norm = TMath::Sqrt(timeDomainVSquared);
473 
474  for(int freqInd=0; freqInd < numFreqs; freqInd++){
475  Double_t re = ffts[pol][ant][freqInd].real();
476  Double_t im = ffts[pol][ant][freqInd].imag();
477 
478  ffts[pol][ant][freqInd].real(re/norm);
479  ffts[pol][ant][freqInd].imag(im/norm);
480  }
481 }
482 
483 
484 
485 
486 
487 
488 //---------------------------------------------------------------------------------------------------------
501 void CrossCorrelator::findPeakValues(AnitaPol::AnitaPol_t pol, Int_t numPeaks, Double_t* peakValues,
502  Double_t* phiDegs, Double_t* thetaDegs){
503 
504 
505  // You can have numPeaks less than or requal MAX_NUM_PEAKS, but not greater than.
506  if(numPeaks > MAX_NUM_PEAKS){
507  std::cerr << "Warning in "<< __PRETTY_FUNCTION__ << " in " << __FILE__
508  << ". numPeaks = " << numPeaks << ", CrossCorrelator compiled with MAX_NUM_PEAKS = "
509  << MAX_NUM_PEAKS << ", setting numPeaks = " << MAX_NUM_PEAKS << std::endl;
510  numPeaks = MAX_NUM_PEAKS;
511  }
512 
513  // Set not crazy, but still debug visible values for peak values/location
514  // Believe -DBL_MAX was causing me some while loop issues in RootTools::getDeltaAngleDeg(...)
515  // which has an unrestricted while loop inside.
516  for(Int_t peakInd=0; peakInd < numPeaks; peakInd++){
517  peakValues[peakInd] = -999;
518  phiDegs[peakInd] = -999;
519  thetaDegs[peakInd] = -999;
520  }
521 
522  Int_t allowedBins[NUM_BINS_PHI*NUM_PHI][NUM_BINS_THETA];
523  for(Int_t phiBin=0; phiBin<NUM_BINS_PHI*NUM_PHI; phiBin++){
524  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA; thetaBin++){
525  allowedBins[phiBin][thetaBin] = 1; // everything is allowed
526  }
527  }
528 
529  for(Int_t peakInd=0; peakInd < numPeaks; peakInd++){
530  for(Int_t phiBin=0; phiBin<NUM_BINS_PHI*NUM_PHI; phiBin++){
531  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA; thetaBin++){
532  if(coarseMap[pol][phiBin][thetaBin] > peakValues[peakInd]){
533  if(allowedBins[phiBin][thetaBin] > 0){
534  peakValues[peakInd] = coarseMap[pol][phiBin][thetaBin];
535  phiDegs[peakInd] = phiWaveLookup[phiBin]*TMath::RadToDeg();
536  thetaDegs[peakInd] = thetaWaves[thetaBin]*TMath::RadToDeg();
537  }
538  }
539  }
540  }
541 
542  // std::cerr << pol << "\t" << peakInd << "\t" << peakValues[peakInd] << "\t"
543  // << phiDegs[peakInd] << "\t" << thetaDegs[peakInd] << std::endl;
544  if(peakValues[peakInd]){
545  for(Int_t phiBin=0; phiBin<NUM_BINS_PHI*NUM_PHI; phiBin++){
546  Double_t phiDeg = phiWaveLookup[phiBin]*TMath::RadToDeg();
547 
548  if(RootTools::getDeltaAngleDeg(phiDegs[peakInd], phiDeg) < PEAK_PHI_DEG_RANGE){
549 
550  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA; thetaBin++){
551  Double_t thetaDeg = thetaWaves[thetaBin]*TMath::RadToDeg();
552 
553  if(RootTools::getDeltaAngleDeg(thetaDegs[peakInd], thetaDeg) < PEAK_THETA_DEG_RANGE){
554  // Now this region in phi/theta is disallowed when looking for peaks
555  allowedBins[phiBin][thetaBin] = 0;
556  }
557  }
558  }
559  }
560  }
561  }
562 }
563 
564 
565 
566 
567 //---------------------------------------------------------------------------------------------------------
577 void CrossCorrelator::reconstructEvent(UsefulAnitaEvent* usefulEvent, Int_t numFinePeaks ,Int_t numCoarsePeaks){
578 
579  for(Int_t polInd = AnitaPol::kHorizontal; polInd < AnitaPol::kNotAPol; polInd++){
580  AnitaPol::AnitaPol_t pol = (AnitaPol::AnitaPol_t)polInd;
581 
582  // now calls reconstruct inside correlate event
583  correlateEvent(usefulEvent, pol);
584 
585  findPeakValues(pol, numCoarsePeaks, coarseMapPeakValues[pol],
587 
588  if(numFinePeaks > 0 && numFinePeaks <= numCoarsePeaks){
589  for(Int_t peakInd=numFinePeaks-1; peakInd >= 0; peakInd--){
590 
591  // std::cerr << peakInd << "\t" << numFinePeaks << "\t" << numCoarsePeaks << "\t"
592  // << coarseMapPeakPhiDegs[pol][peakInd] << "\t" << coarseMapPeakThetaDegs[pol][peakInd]
593  // << std::endl;
594 
595  reconstructZoom(pol, fineMapPeakValues[pol][peakInd],
596  fineMapPeakPhiDegs[pol][peakInd], fineMapPeakThetaDegs[pol][peakInd],
597  coarseMapPeakPhiDegs[pol][peakInd], coarseMapPeakThetaDegs[pol][peakInd]);
598 
599  // std::cerr << fineMapPeakValues[pol][peakInd] << "\t" << fineMapPeakPhiDegs[pol][peakInd] << "\t"
600  // << fineMapPeakThetaDegs[pol][peakInd] << std::endl << std::endl;
601  }
602  }
603  }
604 }
605 
606 
607 
608 
609 
610 
611 
612 //---------------------------------------------------------------------------------------------------------
623 void CrossCorrelator::getCoarsePeakInfo(AnitaPol::AnitaPol_t pol, Int_t peakIndex,
624  Double_t& value, Double_t& phiDeg, Double_t& thetaDeg){
625 
626  if(peakIndex < MAX_NUM_PEAKS){
627  value = coarseMapPeakValues[pol][peakIndex];
628  phiDeg = coarseMapPeakPhiDegs[pol][peakIndex];
629  thetaDeg = coarseMapPeakThetaDegs[pol][peakIndex];
630  }
631  else{
632  std::cerr << "Warning in "<< __PRETTY_FUNCTION__ << " in " << __FILE__ << "."
633  << "Requested peak info with index too large. peakIndex = "
634  << peakIndex << ", MAX_NUM_PEAKS = " << MAX_NUM_PEAKS << "." << std::endl;
635  value = -999;
636  phiDeg = -999;
637  thetaDeg = -999;
638  }
639 }
640 
641 
642 
643 
644 
645 //---------------------------------------------------------------------------------------------------------
656 void CrossCorrelator::getFinePeakInfo(AnitaPol::AnitaPol_t pol, Int_t peakIndex,
657  Double_t& value, Double_t& phiDeg, Double_t& thetaDeg){
658 
659  if(peakIndex < MAX_NUM_PEAKS){
660  value = fineMapPeakValues[pol][peakIndex];
661  phiDeg = fineMapPeakPhiDegs[pol][peakIndex];
662  thetaDeg = fineMapPeakThetaDegs[pol][peakIndex];
663  }
664  else{
665  std::cerr << "Warning in "<< __PRETTY_FUNCTION__ << " in " << __FILE__ << "."
666  << "Requested peak info with index too large. peakIndex = "
667  << peakIndex << ", MAX_NUM_PEAKS = " << MAX_NUM_PEAKS << "." << std::endl;
668  value = -999;
669  phiDeg = -999;
670  thetaDeg = -999;
671  }
672 }
673 
674 
675 
676 
677 
678 //---------------------------------------------------------------------------------------------------------
689 void CrossCorrelator::correlateEvent(UsefulAnitaEvent* usefulEvent){
690 
691  for(Int_t pol = AnitaPol::kHorizontal; pol < AnitaPol::kNotAPol; pol++){
692  correlateEvent(usefulEvent, (AnitaPol::AnitaPol_t)pol);
693  }
694 }
695 
696 
697 
698 
699 //---------------------------------------------------------------------------------------------------------
710 void CrossCorrelator::correlateEvent(UsefulAnitaEvent* usefulEvent, AnitaPol::AnitaPol_t pol){
711 
712  // Read TGraphs from events into memory (also deletes old TGraphs)
713  getNormalizedInterpolatedTGraphs(usefulEvent, pol);
714 
715  // Generate set of ffts for cross correlation (each waveform only needs to be done once)
716  doFFTs(pol);
717 
718  // Now cross correlate those already FFT'd waveforms
720 
721  // reconstruct
723 
724  // Safety check to make sure we don't do any hard work twice.
725  eventNumber[pol] = usefulEvent->eventNumber;
726  }
727 
728 
729 
730 //---------------------------------------------------------------------------------------------------------
736 void CrossCorrelator::doAllCrossCorrelationsThreaded(AnitaPol::AnitaPol_t pol){
737 
738  // Set variable for use in threads
739  threadPol = pol;
740 
741  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
742  TString name = TString::Format("threadCorr%ld", threadInd);
743  corrThreads.push_back(new TThread(name.Data(),
745  (void*)&threadArgsVec.at(threadInd))
746  );
747  }
748 
749  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
750  corrThreads.at(threadInd)->Run();
751  }
752 
753  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
754  corrThreads.at(threadInd)->Join();
755  }
756 
757  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
758  delete corrThreads.at(threadInd);
759  }
760 
761  corrThreads.clear();
762 
763 }
764 
765 
766 
767 
768 //---------------------------------------------------------------------------------------------------------
775 
776  // Disgusting hacks to get ROOT threading to compile inside a class.
778  Long_t threadInd = args->threadInd;
779  CrossCorrelator* ptr = args->ptr;
780  AnitaPol::AnitaPol_t pol = ptr->threadPol;
781  Int_t phiSector = ptr->threadPhiSector;
782 
783  const std::vector<Int_t>* combosToUse = &ptr->combosToUseGlobal[phiSector];
784  Int_t numCombosAllThreads = combosToUse->size();
785  Int_t numCorrPerThread = numCombosAllThreads/NUM_THREADS;
786  Int_t numRemainder = numCombosAllThreads%NUM_THREADS;
787 
788  Int_t startComboInd = threadInd*numCorrPerThread;
789 
790  Double_t stash[NUM_SAMPLES*UPSAMPLE_FACTOR*PAD_FACTOR];
791 
792  for(int comboInd=startComboInd; comboInd<startComboInd+numCorrPerThread; comboInd++){
793  Int_t combo = combosToUse->at(comboInd);
794  Int_t ant1 = ptr->comboToAnt1s.at(combo);
795  Int_t ant2 = ptr->comboToAnt2s.at(combo);
796 
798  ptr->fftsPadded[pol][ant2],
799  ptr->fftsPadded[pol][ant1],
800  ptr->crossCorrelationsUpsampled[pol][combo],
801  threadInd);
802 
803  // experiment, copy negative times to behind positive times...
804  for(Int_t samp=0; samp < ptr->numSamplesUpsampled; samp++){
805  stash[samp] = ptr->crossCorrelationsUpsampled[pol][combo][samp];
806  }
807  const int offset = ptr->numSamplesUpsampled/2;
808 
809  // copies first half of original array (times >= 0) into second half of internal storage
810  for(Int_t samp=0; samp < ptr->numSamplesUpsampled/2; samp++){
811  ptr->crossCorrelationsUpsampled[pol][combo][samp+offset] = stash[samp];
812  }
813  // copies second half of original array (times < 0) into first half of internal storage
814  for(Int_t samp=ptr->numSamplesUpsampled/2; samp < ptr->numSamplesUpsampled; samp++){
815  ptr->crossCorrelationsUpsampled[pol][combo][samp-offset] = stash[samp];
816  }
817  }
818 
819  if(threadInd < numRemainder){
820  Int_t numDoneInAllThreads = NUM_THREADS*numCorrPerThread;
821  Int_t comboInd = numDoneInAllThreads + threadInd;
822  Int_t combo = combosToUse->at(comboInd);
823  Int_t ant1 = ptr->comboToAnt1s.at(combo);
824  Int_t ant2 = ptr->comboToAnt2s.at(combo);
825 
827  ptr->fftsPadded[pol][ant2],
828  ptr->fftsPadded[pol][ant1],
829  ptr->crossCorrelationsUpsampled[pol][combo],
830  threadInd);
831 
832  // experiment, copy negative times to behind positive times...
833  for(Int_t samp=0; samp < ptr->numSamplesUpsampled; samp++){
834  stash[samp] = ptr->crossCorrelationsUpsampled[pol][combo][samp];
835  }
836  const int offset = ptr->numSamplesUpsampled/2;
837 
838  // copies first half of original array (times >= 0) into second half of internal storage
839  for(Int_t samp=0; samp < ptr->numSamplesUpsampled/2; samp++){
840  ptr->crossCorrelationsUpsampled[pol][combo][samp+offset] = stash[samp];
841  }
842  // copies second half of original array (times < 0) into first half of internal storage
843  for(Int_t samp=ptr->numSamplesUpsampled/2; samp < ptr->numSamplesUpsampled; samp++){
844  ptr->crossCorrelationsUpsampled[pol][combo][samp-offset] = stash[samp];
845  }
846  }
847  return 0;
848 }
849 
850 
851 
852 
853 
854 //---------------------------------------------------------------------------------------------------------
861 
862  // Disgusting hacks to get ROOT threading to compile inside a class.
864  Long_t threadInd = args->threadInd;
865  CrossCorrelator* ptr = args->ptr;
866  AnitaPol::AnitaPol_t pol = ptr->threadPol;
867 
868  Int_t numCorrPerThread = NUM_COMBOS/NUM_THREADS;
869  Int_t startCombo = threadInd*numCorrPerThread;
870 
871  Double_t stash[NUM_SAMPLES*PAD_FACTOR];
872 
873  for(int combo=startCombo; combo<startCombo+numCorrPerThread; combo++){
874  Int_t ant1 = ptr->comboToAnt1s.at(combo);
875  Int_t ant2 = ptr->comboToAnt2s.at(combo);
877  ptr->ffts[pol][ant2],
878  ptr->ffts[pol][ant1],
879  ptr->crossCorrelations[pol][combo],
880  threadInd);
881 
882  // experiment, copy negative times to behind positive times...
883  for(Int_t samp=0; samp < ptr->numSamples; samp++){
884  stash[samp] = ptr->crossCorrelations[pol][combo][samp];
885  }
886  const int offset = ptr->numSamples/2;
887 
888  // copies first half of original array (times >= 0) into second half of internal storage
889  for(Int_t samp=0; samp < ptr->numSamples/2; samp++){
890  ptr->crossCorrelations[pol][combo][samp+offset] = stash[samp];
891  }
892  // copies second half of original array (times < 0) into first half of internal storage
893  for(Int_t samp=ptr->numSamples/2; samp < ptr->numSamples; samp++){
894  ptr->crossCorrelations[pol][combo][samp-offset] = stash[samp];
895  }
896  }
897  return 0;
898 }
899 
900 
901 
902 
903 
904 //---------------------------------------------------------------------------------------------------------
911 void CrossCorrelator::doUpsampledCrossCorrelationsThreaded(AnitaPol::AnitaPol_t pol, Int_t phiSector){
912 
913  threadPhiSector = phiSector;
914  threadPol = pol;
915 
916  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
917  TString name = TString::Format("threadUpsampledCorr%ld", threadInd);
918  upsampledCorrThreads.push_back(new TThread(name.Data(),
920  (void*)&threadArgsVec.at(threadInd))
921  );
922  }
923 
924  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
925  upsampledCorrThreads.at(threadInd)->Run();
926  }
927 
928  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
929  upsampledCorrThreads.at(threadInd)->Join();
930  }
931 
932  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
933  delete upsampledCorrThreads.at(threadInd);
934  }
935  upsampledCorrThreads.clear();
936 
937 }
938 
939 
940 
941 
942 
943 //---------------------------------------------------------------------------------------------------------
954 void CrossCorrelator::getMaxCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t combo,
955  Double_t& time, Double_t& value){
956 
957  Int_t maxInd = RootTools::getIndexOfMaximum(numSamples, crossCorrelations[pol][combo]);
958  Int_t offset = maxInd - numSamples/2;
959  value = crossCorrelations[pol][combo][maxInd];
960  time = offset*nominalSamplingDeltaT;
961 }
962 
963 
964 
965 
966 
967 //---------------------------------------------------------------------------------------------------------
977 void CrossCorrelator::getMaxCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2,
978  Double_t& time, Double_t& value){
979  Int_t combo = comboIndices[ant1][ant2];
980  getMaxCorrelationTimeValue(pol, combo, time, value);
981 }
982 
983 
984 
985 
986 
987 //---------------------------------------------------------------------------------------------------------
996 void CrossCorrelator::getMaxUpsampledCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t combo,
997  Double_t& time, Double_t& value){
998 
1000  Int_t offset = maxInd - numSamplesUpsampled/2;
1001  value = crossCorrelationsUpsampled[pol][combo][maxInd];
1002  time = offset*correlationDeltaT;
1003 }
1004 
1005 
1006 
1007 
1008 
1009 //---------------------------------------------------------------------------------------------------------
1019 void CrossCorrelator::getMaxUpsampledCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2,
1020  Double_t& time, Double_t& value){
1021  Int_t combo = comboIndices[ant1][ant2];
1022  getMaxUpsampledCorrelationTimeValue(pol, combo, time, value);
1023 }
1024 
1025 
1026 
1027 
1028 //---------------------------------------------------------------------------------------------------------
1036 Double_t CrossCorrelator::singleAntennaOffAxisDelay(Double_t deltaPhiDeg) {
1037 
1038 
1039  // These are the numbers from Linda's fits...
1040  // FCN=2014.5 FROM HESSE STATUS=NOT POSDEF 40 CALLS 407 TOTAL
1041  // EDM=5.13972e-17 STRATEGY= 1 ERR MATRIX NOT POS-DEF
1042  // EXT PARAMETER APPROXIMATE STEP FIRST
1043  // NO. NAME VALUE ERROR SIZE DERIVATIVE
1044  // 1 p0 0.00000e+00 fixed
1045  // 2 p1 0.00000e+00 fixed
1046  // 3 p2 -1.68751e-05 1.90656e-07 4.07901e-10 1.39356e-03
1047  // 4 p3 0.00000e+00 fixed
1048  // 5 p4 2.77815e-08 9.38089e-11 7.26358e-14 2.34774e+01
1049  // 6 p5 0.00000e+00 fixed
1050  // 7 p6 -8.29351e-12 1.78286e-14 7.64605e-18 -1.72486e+05
1051  // 8 p7 0.00000e+00 fixed
1052  // 9 p8 1.15064e-15 1.78092e-18 6.93019e-22 -1.31237e+09
1053  // 10 p9 0.00000e+00 fixed
1054  // 11 p10 -7.71170e-20 1.63489e-22 6.05470e-26 4.32831e+13
1055  // 12 p11 0.00000e+00 fixed
1056  // 13 p12 1.99661e-24 9.79818e-27 1.84698e-29 -6.15528e+16
1057 
1058  // ... in a const array
1059  const Int_t numPowers = 13;
1060  const Double_t params[numPowers] = {0.00000e+00, 0.00000e+00, -1.68751e-05, 0.00000e+00,
1061  2.77815e-08, 0.00000e+00, -8.29351e-12, 0.00000e+00,
1062  1.15064e-15, 0.00000e+00, -7.71170e-20, 0.00000e+00,
1063  1.99661e-24};
1064 
1065  // Sum up the powers in off boresight angle.
1066  Double_t offBoresightDelay = 0;
1067  for(int power=0; power < numPowers; power++){
1068  offBoresightDelay += params[power]*TMath::Power(deltaPhiDeg, power);
1069  }
1070 
1071  return offBoresightDelay;
1072 }
1073 
1074 
1075 
1076 
1077 
1078 //---------------------------------------------------------------------------------------------------------
1088 Double_t CrossCorrelator::relativeOffAxisDelay(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2,
1089  Double_t phiDeg) {
1090 
1091  Double_t deltaPhiDeg1 = RootTools::getDeltaAngleDeg(phiArrayDeg[pol].at(ant1), phiDeg);
1092  Double_t deltaPhiDeg2 = RootTools::getDeltaAngleDeg(phiArrayDeg[pol].at(ant2), phiDeg);
1093 
1094  // std::cout << phiDeg << "\t" << deltaPhiDeg1 << "\t" << deltaPhiDeg2 << std::endl;
1095 
1096  // Double_t leftPhi=x[0]+11.25;
1097  // Double_t rightPhi=x[0]-11.25;
1098 
1099  //leftPhi*=-1;
1100  // rightPhi*=-1;
1101  // Double_t leftDelay=singleDelayFuncMod(&leftPhi,par);
1102  // Double_t rightDelay=singleDelayFuncMod(&rightPhi,par);
1103 
1104  Double_t delay1 = singleAntennaOffAxisDelay(deltaPhiDeg1);
1105  Double_t delay2 = singleAntennaOffAxisDelay(deltaPhiDeg2);
1106 
1107  // return (leftDelay-rightDelay);
1108  return (delay1-delay2);
1109 }
1110 
1111 
1112 
1113 
1114 
1115 //---------------------------------------------------------------------------------------------------------
1126 Double_t CrossCorrelator::getDeltaTExpected(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2, Double_t phiWave, Double_t thetaWave){
1127 
1128  Double_t tanThetaW = tan(thetaWave);
1129  Double_t part1 = zArray[pol].at(ant1)*tanThetaW - rArray[pol].at(ant1)*cos(phiWave-TMath::DegToRad()*phiArrayDeg[pol].at(ant1));
1130  Double_t part2 = zArray[pol].at(ant2)*tanThetaW - rArray[pol].at(ant2)*cos(phiWave-TMath::DegToRad()*phiArrayDeg[pol].at(ant2));
1131  Double_t tdiff = 1e9*((cos(thetaWave) * (part2 - part1))/SPEED_OF_LIGHT); // Returns time in ns
1132 
1133  return tdiff;
1134 }
1135 
1136 
1137 
1138 
1139 
1140 
1141 //---------------------------------------------------------------------------------------------------------
1146  AnitaGeomTool* geom = AnitaGeomTool::Instance();
1147  geom->useKurtAnita3Numbers(1);
1148  for(Int_t pol=0; pol < NUM_POL; pol++){
1149  for(int ant=0; ant<NUM_SEAVEYS; ant++){
1150  rArray[pol].at(ant) = geom->getAntR(ant, AnitaPol::AnitaPol_t(pol));
1151  zArray[pol].at(ant) = geom->getAntZ(ant, AnitaPol::AnitaPol_t(pol));
1152  phiArrayDeg[pol].at(ant) = geom->getAntPhiPositionRelToAftFore(ant, AnitaPol::AnitaPol_t(pol))*TMath::RadToDeg();
1153  }
1154  }
1155 
1156  AnitaEventCalibrator* cal = AnitaEventCalibrator::Instance();
1157  for(int surf=0; surf < NUM_SURF; surf++){
1158  for(int chan=0; chan < NUM_CHAN; chan++){
1159  cal->relativePhaseCenterToAmpaDelays[surf][chan] = 0;
1160  }
1161  }
1162 
1163  fillDeltaTLookup();
1164  geom->useKurtAnita3Numbers(0);
1165 
1166 }
1167 
1168 
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1176 //---------------------------------------------------------------------------------------------------------
1186  // For checking later...
1187  for(Int_t ant1=0; ant1 < NUM_SEAVEYS; ant1++){
1188  for(Int_t ant2=0; ant2 < NUM_SEAVEYS; ant2++){
1189  comboIndices[ant1][ant2] = -1;
1190  }
1191  }
1192 
1193  numCombos=0;
1194  for(Int_t ant1=0; ant1<NUM_SEAVEYS; ant1++){
1195  Double_t phiSect1 = ant1%NUM_PHI;
1196  for(Int_t ant2=ant1+1; ant2<NUM_SEAVEYS; ant2++){
1197  Double_t phiSect2 = ant2%NUM_PHI;
1198 
1199  if(TMath::Abs(phiSect1 - phiSect2) <= DELTA_PHI_SECT || TMath::Abs(phiSect1 - phiSect2) >= (NUM_PHI-DELTA_PHI_SECT)){
1200  comboIndices[ant1][ant2] = numCombos;
1201  comboIndices[ant2][ant1] = numCombos;
1202  comboToAnt1s.push_back(ant1);
1203  comboToAnt2s.push_back(ant2);
1204  numCombos++;
1205  }
1206  }
1207  }
1208  if(numCombos != NUM_COMBOS){
1209  std::cerr << "Warning! in = " << __PRETTY_FUNCTION__ << std::endl;
1210  std::cerr << "\tnumCombos = " << numCombos << "." << std::endl;
1211  std::cerr << "\tNUM_COMBOS = " << NUM_COMBOS << "." << std::endl;
1212  std::cerr << "\tExpecting NUM_COMBOS == numCombos." << std::endl;
1213  std::cerr << "\tSeriously bad things are probably about to happen." << std::endl;
1214  std::cerr << "\tCheck the combinatorics!" << std::endl;
1215  }
1216 
1217  fillCombosToUse();
1218 }
1219 
1220 
1221 
1222 
1223 
1224 //---------------------------------------------------------------------------------------------------------
1229 
1230  Double_t phi0 = getBin0PhiDeg();
1231  const Double_t phiBinSize = Double_t(PHI_RANGE)/NUM_BINS_PHI;
1232  for(Int_t phiIndex=0; phiIndex < NUM_BINS_PHI*NUM_PHI; phiIndex++){
1233  Double_t phiDeg = phi0 + phiIndex*phiBinSize;
1234  Double_t phiWave = TMath::DegToRad()*phiDeg;
1235  phiWaveLookup[phiIndex] = phiWave;
1236  }
1237 
1238  const Double_t thetaBinSize = (Double_t(THETA_RANGE)/NUM_BINS_THETA);
1239  for(Int_t thetaIndex=0; thetaIndex < NUM_BINS_THETA; thetaIndex++){
1240  Double_t thetaWaveDeg = (thetaIndex-NUM_BINS_THETA/2)*thetaBinSize;
1241  Double_t thetaWave = thetaWaveDeg*TMath::DegToRad();
1242  thetaWaves[thetaIndex] = thetaWave;
1243  }
1244 
1245  for(Int_t polInd=0; polInd<NUM_POL; polInd++){
1246  AnitaPol::AnitaPol_t pol = (AnitaPol::AnitaPol_t) polInd;
1247  for(Int_t combo=0; combo<numCombos; combo++){
1248  Int_t ant1 = comboToAnt1s.at(combo);
1249  Int_t ant2 = comboToAnt2s.at(combo);
1250 
1251  for(Int_t phiSector = 0; phiSector<NUM_PHI; phiSector++){
1252  for(Int_t phiInd = 0; phiInd < NUM_BINS_PHI; phiInd++){
1253  Int_t phiBin = phiSector*NUM_BINS_PHI + phiInd;
1254  Double_t phiWave = phiWaveLookup[phiBin];
1255 
1256  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA; thetaBin++){
1257  Double_t thetaWave = thetaWaves[thetaBin];
1258  Double_t deltaT = getDeltaTExpected(pol, ant1, ant2, phiWave, thetaWave);
1259  // Int_t offset = TMath::Nint(deltaT/nominalSamplingDeltaT);
1260  // deltaTs[pol][phiBin][thetaBin][combo] = deltaT; //offset;
1261  // deltaTs[pol][combo][thetaBin][phiBin] = deltaT; //offset;
1262  Int_t offsetLow = floor(deltaT/nominalSamplingDeltaT);
1263  offsetLows[pol][combo][phiBin][thetaBin] = offsetLow;
1264  Double_t dt1 = offsetLow*nominalSamplingDeltaT;
1265  interpPreFactors[pol][combo][phiBin][thetaBin] = (deltaT - dt1)/nominalSamplingDeltaT;
1266 
1267  // Here we account for the fact that we are now time ordering the correlations
1268  offsetLows[pol][combo][phiBin][thetaBin]+=numSamples/2;
1269  }
1270  }
1271  }
1272  }
1273  }
1274 
1275  // minThetaDegZoom = -78.5;
1276  // minPhiDegZoom = -59.25; // is this a mistake!?
1277  minThetaDegZoom = -THETA_RANGE/2 - THETA_RANGE_ZOOM/2;
1278  minPhiDegZoom = getBin0PhiDeg() - PHI_RANGE_ZOOM/2;
1279 
1280  for(Int_t thetaIndex=0; thetaIndex < NUM_BINS_THETA_ZOOM_TOTAL; thetaIndex++){
1281  Double_t thetaWaveDeg = minThetaDegZoom + thetaIndex*ZOOM_BIN_SIZE_THETA;
1282  Double_t thetaWave = thetaWaveDeg*TMath::DegToRad();
1283  zoomedThetaWaves[thetaIndex] = thetaWave;
1284  zoomedTanThetaWaves[thetaIndex] = tan(thetaWave);
1285  zoomedCosThetaWaves[thetaIndex] = cos(thetaWave);
1286  }
1287 
1288  for(Int_t pol=0; pol<AnitaPol::kNotAPol; pol++){
1289  for(Int_t combo=0; combo < NUM_COMBOS; combo++){
1290  Int_t ant1 = comboToAnt1s.at(combo);
1291  Int_t ant2 = comboToAnt2s.at(combo);
1292  for(Int_t thetaIndex=0; thetaIndex < NUM_BINS_THETA_ZOOM_TOTAL; thetaIndex++){
1293  partBAsZoom[pol][combo][thetaIndex] = zoomedTanThetaWaves[thetaIndex]*(zArray[pol].at(ant2)-zArray[pol].at(ant1));
1294  }
1295  }
1296  }
1297 
1298  for(Int_t pol=0; pol<AnitaPol::kNotAPol; pol++){
1299  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
1300  for(Int_t phiIndex=0; phiIndex < NUM_BINS_PHI_ZOOM_TOTAL; phiIndex++){
1301  Double_t phiDeg = minPhiDegZoom + phiIndex*ZOOM_BIN_SIZE_PHI;
1302  Double_t phiWave = phiDeg*TMath::DegToRad();
1303  zoomedCosPartLookup[pol][ant][phiIndex] = rArray[pol].at(ant)*cos(phiWave-TMath::DegToRad()*phiArrayDeg[pol].at(ant));
1304  }
1305  }
1306 
1307  for(Int_t combo=0; combo < NUM_COMBOS; combo++){
1308  Int_t ant1 = comboToAnt1s.at(combo);
1309  Int_t ant2 = comboToAnt2s.at(combo);
1310 
1311  for(Int_t phiIndex=0; phiIndex < NUM_BINS_PHI_ZOOM_TOTAL; phiIndex++){
1312  // Double_t phiWave = TMath::DegToRad()*phiIndex*ZOOM_BIN_SIZE_PHI;
1313  Double_t phiDeg = minPhiDegZoom + phiIndex*ZOOM_BIN_SIZE_PHI;
1314  zoomedPhiWaveLookup[phiIndex] = phiIndex*ZOOM_BIN_SIZE_PHI;
1315 
1316  // Double_t offAxisDelay = getOffAxisDelay((AnitaPol::AnitaPol_t)pol, ant1, ant2, phiWave);
1317  // offAxisDelays[pol][combo][phiIndex] = offAxisDelay;
1318  Double_t offAxisDelay = relativeOffAxisDelay((AnitaPol::AnitaPol_t)pol, ant2, ant1, phiDeg);
1319  offAxisDelays[pol][combo][phiIndex] = offAxisDelay;
1320 
1321  part21sZoom[pol][combo][phiIndex] = zoomedCosPartLookup[pol][ant2][phiIndex] - zoomedCosPartLookup[pol][ant1][phiIndex];
1322 
1323  }
1324  }
1325  }
1326 }
1327 
1328 //---------------------------------------------------------------------------------------------------------
1339 Bool_t CrossCorrelator::useCombo(Int_t ant1, Int_t ant2, Int_t phiSector, Int_t deltaPhiSect){
1340 
1341  // I want to be able to choose whether or not require one of the antennas to be the phi-sector
1342  // of interest or just to have both in range of deltaPhiSect.
1343  // I'm going to use the sign of deltaPhiSect to do this.
1344  // If deltaPhiSect < 0 this implies one of the antenna pairs must be in an l3Triggered phi-sector
1345 
1346  Int_t absDeltaPhiSect = TMath::Abs(deltaPhiSect);
1347 
1348  // Require that the difference in phi-sectors be <= absDeltaPhiSect
1349  Int_t phiSectorOfAnt1 = ant1%NUM_PHI;
1350  Bool_t ant1InRange = TMath::Abs(phiSector - (phiSectorOfAnt1))<=absDeltaPhiSect;
1351 
1352  // Takes account of wrapping around payload (e.g. antennas in phi-sectors 1 and 16 are neighbours)
1353  ant1InRange = ant1InRange || TMath::Abs(phiSector - (phiSectorOfAnt1))>=(NUM_PHI-absDeltaPhiSect);
1354 
1355  Int_t phiSectorOfAnt2 = ant2%NUM_PHI;
1356  Bool_t ant2InRange = TMath::Abs(phiSector - (phiSectorOfAnt2))<=absDeltaPhiSect;
1357  ant2InRange = ant2InRange || TMath::Abs(phiSector - (phiSectorOfAnt2))>=(NUM_PHI-absDeltaPhiSect);
1358 
1359  // See rather rant above.
1360  Bool_t extraCondition = true;
1361  if(deltaPhiSect < 0){
1362  extraCondition = (phiSectorOfAnt1==phiSector || phiSectorOfAnt2==phiSector);
1363  }
1364 
1365  return (ant1InRange && ant2InRange && extraCondition);
1366 }
1367 
1368 
1369 
1370 
1371 
1372 //---------------------------------------------------------------------------------------------------------
1377 
1378  for(Int_t phiSector = 0; phiSector<NUM_PHI; phiSector++){
1379  if(combosToUseGlobal[phiSector].size() == 0){
1380  for(Int_t combo=0; combo<numCombos; combo++){
1381  Int_t ant1 = comboToAnt1s.at(combo);
1382  Int_t ant2 = comboToAnt2s.at(combo);
1383  if(useCombo(ant1, ant2, phiSector, kDeltaPhiSect)){
1384  combosToUseGlobal[phiSector].push_back(combo);
1385  }
1386  }
1387  }
1388  }
1389 }
1390 
1391 
1392 
1393 
1394 //---------------------------------------------------------------------------------------------------------
1404  Int_t combo, Double_t deltaT){
1405 
1406  Int_t offsetLow = floor(deltaT/correlationDeltaT);
1407 
1408  Double_t dt1 = offsetLow*correlationDeltaT;
1409  // Double_t dt2 = offsetHigh*ptr->correlationDeltaT;
1410 
1411  const Int_t offset = numSamplesUpsampled/2;
1412  offsetLow += offset;
1413  Int_t offsetHigh = offsetLow+1;
1414 
1415  // offsetLow = offsetLow < 0 ? offsetLow + numSamplesUpsampled : offsetLow;
1416  // offsetHigh = offsetHigh < 0 ? offsetHigh + numSamplesUpsampled : offsetHigh;
1417 
1418  Double_t c1 = crossCorrelationsUpsampled[pol][combo][offsetLow];
1419  Double_t c2 = crossCorrelationsUpsampled[pol][combo][offsetHigh];
1420 
1421  Double_t cInterp = (deltaT - dt1)*(c2 - c1)/(correlationDeltaT) + c1;
1422 
1423  return cInterp;
1424 
1425 }
1426 
1427 
1428 
1429 
1430 
1431 //---------------------------------------------------------------------------------------------------------
1442 TH2D* CrossCorrelator::getMap(AnitaPol::AnitaPol_t pol, Double_t& peakValue,
1443  Double_t& peakPhiDeg, Double_t& peakThetaDeg,
1444  UShort_t l3TrigPattern){
1445 
1446  TString name = "h";
1447  name += pol == AnitaPol::kVertical ? "ImageV" : "ImageH";
1448  name += TString::Format("%u", eventNumber[pol]);
1449 
1450  TString title = TString::Format("Event %u ", eventNumber[pol]);
1451  title += (pol == AnitaPol::kVertical ? "VPOL" : "HPOL");
1452  title += " Map";
1453 
1454  Double_t phiMin = getBin0PhiDeg();
1455  Double_t phiMax = phiMin + DEGREES_IN_CIRCLE;
1456  Double_t thetaMin = -THETA_RANGE/2;
1457  Double_t thetaMax = THETA_RANGE/2;
1458 
1459  TH2D* hImage = new TH2D(name, title,
1460  NUM_BINS_PHI*NUM_PHI, phiMin, phiMax,
1461  NUM_BINS_THETA, thetaMin, thetaMax);
1462  hImage->GetXaxis()->SetTitle("Azimuth (Degrees)");
1463  hImage->GetYaxis()->SetTitle("Elevation (Degrees)");
1464 
1465  // peakValue = -DBL_MAX;
1466  // peakPhiDeg = -DBL_MAX;
1467  // peakThetaDeg = -DBL_MAX;
1468  peakValue = -2;
1469  peakPhiDeg = -9999;
1470  peakThetaDeg = -9999;
1471 
1472  for(Int_t phiSector=0; phiSector<NUM_PHI; phiSector++){
1473  Int_t doPhiSector = RootTools::getBit(phiSector, l3TrigPattern);
1474  if(doPhiSector){
1475  for(Int_t phiBin = phiSector*NUM_BINS_PHI; phiBin < NUM_BINS_PHI*(phiSector+1); phiBin++){
1476  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA; thetaBin++){
1477  hImage->SetBinContent(phiBin+1, thetaBin+1, coarseMap[pol][phiBin][thetaBin]);
1478  if(coarseMap[pol][phiBin][thetaBin] > peakValue){
1479  peakValue = coarseMap[pol][phiBin][thetaBin];
1480  peakPhiDeg = hImage->GetXaxis()->GetBinLowEdge(phiBin+1);
1481  peakThetaDeg = hImage->GetYaxis()->GetBinLowEdge(thetaBin+1);
1482  }
1483  }
1484  }
1485  }
1486  }
1487 
1488  return hImage;
1489 }
1490 
1491 
1492 
1493 
1494 
1495 //---------------------------------------------------------------------------------------------------------
1502 TH2D* CrossCorrelator::getZoomMap(AnitaPol::AnitaPol_t pol){
1503 
1504  TString name = "hZoom";
1505  name += pol == AnitaPol::kVertical ? "ImageV" : "ImageH";
1506  name += TString::Format("%u", eventNumber[pol]);
1507 
1508  TString title = TString::Format("Event %u ", eventNumber[pol]);
1509  title += (pol == AnitaPol::kVertical ? "VPOL" : "HPOL");
1510  title += " Zoomed In";
1511  title += " Map";
1512 
1513  TH2D* hImage = new TH2D(name, title,
1514  NUM_BINS_PHI_ZOOM, zoomPhiMin, zoomPhiMin + PHI_RANGE_ZOOM,
1515  NUM_BINS_THETA_ZOOM, zoomThetaMin, zoomThetaMin + THETA_RANGE_ZOOM);
1516  hImage->GetXaxis()->SetTitle("Azimuth (Degrees)");
1517  hImage->GetYaxis()->SetTitle("Elevation (Degrees)");
1518 
1519  for(Int_t thetaBin = 0; thetaBin < NUM_BINS_THETA_ZOOM; thetaBin++){
1520  for(Int_t phiBin = 0; phiBin < NUM_BINS_PHI_ZOOM; phiBin++){
1521  hImage->SetBinContent(phiBin+1, thetaBin+1, fineMap[pol][thetaBin][phiBin]);
1522  }
1523  }
1524 
1525  return hImage;
1526 }
1527 
1528 
1529 
1530 
1531 
1532 
1533 
1534 //---------------------------------------------------------------------------------------------------------
1544 TH2D* CrossCorrelator::makeGlobalImage(AnitaPol::AnitaPol_t pol, Double_t& imagePeak, Double_t& peakPhiDeg,
1545  Double_t& peakThetaDeg){
1546 
1547  // return makeImageThreaded(pol, 0, imagePeak, peakPhiDeg, peakThetaDeg, ALL_PHI_TRIGS,
1548  // kGlobal, kZoomedOut);
1549 
1550  // std::cerr << "Global image is currently not functional: returning triggered image." << std::endl;
1551  return getMap(pol, imagePeak, peakPhiDeg, peakThetaDeg);
1552  // return makeTriggeredImage(pol, imagePeak, peakPhiDeg, peakThetaDeg, 0xffff);
1553 }
1554 
1555 
1556 
1557 
1558 //---------------------------------------------------------------------------------------------------------
1565 TH2D* CrossCorrelator::makeGlobalImage(AnitaPol::AnitaPol_t pol){
1566  Double_t imagePeak, peakPhiDeg, peakThetaDeg;
1567  return makeGlobalImage(pol, imagePeak, peakPhiDeg, peakThetaDeg);
1568 }
1569 
1570 
1571 
1572 
1573 
1574 //---------------------------------------------------------------------------------------------------------
1585 TH2D* CrossCorrelator::makeTriggeredImage(AnitaPol::AnitaPol_t pol, Double_t& imagePeak,
1586  Double_t& peakPhiDeg, Double_t& peakThetaDeg,
1587  UShort_t l3TrigPattern){
1588 
1589  // return makeImageThreaded(pol, 0, imagePeak, peakPhiDeg, peakThetaDeg,
1590  // l3TrigPattern, kTriggered, kZoomedOut);
1591 
1592  // std::cout << __PRETTY_FUNCTION__ << "\t" << l3TrigPattern << std::endl;
1593  return getMap(pol, imagePeak, peakPhiDeg, peakThetaDeg, l3TrigPattern);
1594 }
1595 
1596 
1597 
1598 
1599 
1600 //---------------------------------------------------------------------------------------------------------
1612 TH2D* CrossCorrelator::makeZoomedImage(AnitaPol::AnitaPol_t pol,
1613  Double_t& imagePeak, Double_t& peakPhiDeg, Double_t& peakThetaDeg,
1614  Double_t zoomCenterPhiDeg, Double_t zoomCenterThetaDeg){
1615 
1616  // return makeZoomImageThreaded(pol, 0, imagePeak, peakPhiDeg, peakThetaDeg, 0,
1617  // kTriggered, kZoomedIn, zoomCenterPhiDeg, zoomCenterThetaDeg);
1618 
1619  reconstructZoom(pol, imagePeak, peakPhiDeg, peakThetaDeg,
1620  zoomCenterPhiDeg, zoomCenterThetaDeg);
1621  return getZoomMap(pol);
1622 
1623 }
1624 
1625 
1626 
1627 
1628 //---------------------------------------------------------------------------------------------------------
1641 TH2D* CrossCorrelator::makeZoomedImage(AnitaPol::AnitaPol_t pol, Double_t& imagePeak, Double_t& peakPhiDeg,
1642  Double_t& peakThetaDeg, UShort_t l3TrigPattern,
1643  Double_t zoomCenterPhiDeg, Double_t zoomCenterThetaDeg){
1644 
1645  // return makeZoomImageThreaded(pol, 0, imagePeak, peakPhiDeg, peakThetaDeg, l3TrigPattern,
1646  // kTriggered, kZoomedIn, zoomCenterPhiDeg, zoomCenterThetaDeg);
1647  reconstructZoom(pol, imagePeak, peakPhiDeg, peakThetaDeg,
1648  zoomCenterPhiDeg, zoomCenterThetaDeg);
1649  return getZoomMap(pol);
1650 
1651 }
1652 
1653 
1654 
1655 
1656 
1657 //---------------------------------------------------------------------------------------------------------
1667 TH2D* CrossCorrelator::makeZoomedImage(AnitaPol::AnitaPol_t pol, UShort_t l3TrigPattern,
1668  Double_t zoomCenterPhiDeg,Double_t zoomCenterThetaDeg){
1669 
1670  Double_t imagePeak, peakPhiDeg, peakThetaDeg;
1671  // return makeZoomedImage(pol, imagePeak, peakPhiDeg, peakThetaDeg,
1672  // l3TrigPattern, zoomCenterPhiDeg, zoomCenterThetaDeg);
1673  reconstructZoom(pol, imagePeak, peakPhiDeg, peakThetaDeg,
1674  zoomCenterPhiDeg, zoomCenterThetaDeg);
1675  return getZoomMap(pol);
1676 }
1677 
1678 
1679 
1680 
1681 
1682 
1683 
1684 
1685 
1686 
1687 //---------------------------------------------------------------------------------------------------------
1698 void CrossCorrelator::reconstruct(AnitaPol::AnitaPol_t pol, Double_t& imagePeak,
1699  Double_t& peakPhiDeg, Double_t& peakThetaDeg){
1700 
1701  threadPol = pol;
1702 
1703  // LAUNCH THREADS HERE
1704  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1705  TString name = TString::Format("threadMap%ld", threadInd);
1706  mapThreads.push_back(new TThread(name.Data(),
1708  (void*)&threadArgsVec.at(threadInd))
1709  );
1710  }
1711 
1712  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1713  mapThreads.at(threadInd)->Run();
1714  }
1715 
1716  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1717  mapThreads.at(threadInd)->Join();
1718  }
1719 
1720  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1721  delete mapThreads.at(threadInd);
1722  }
1723  mapThreads.clear();
1724 
1725  // Combine peak search results from each thread.
1726  imagePeak = -DBL_MAX;
1727  for(Long_t threadInd=0; threadInd<NUM_THREADS; threadInd++){
1728  if(threadImagePeak[threadInd] > imagePeak){
1729  imagePeak = threadImagePeak[threadInd];
1730  peakPhiDeg = threadPeakPhiDeg[threadInd];
1731  peakThetaDeg = threadPeakThetaDeg[threadInd];
1732  }
1733  }
1734 
1735 
1736 }
1737 
1738 
1739 
1740 
1741 
1742 //---------------------------------------------------------------------------------------------------------
1753  // Disgusting hacks to get ROOT threading to compile inside a class.
1755  Long_t threadInd = args->threadInd;
1756  CrossCorrelator* ptr = args->ptr;
1757  AnitaPol::AnitaPol_t pol = ptr->threadPol;
1758 
1759  // const Int_t numThetaBinsPerThread = hImage->GetNbinsY()/NUM_THREADS;
1760  // const Int_t startThetaBin = threadInd*numThetaBinsPerThread;
1761  // const Int_t endThetaBin = startThetaBin+numThetaBinsPerThread;
1762  // const Int_t startPhiBin = 0;
1763  // const Int_t endPhiBin = hImage->GetNbinsX();
1764 
1765  const Int_t numPhiBinsPerThread = (NUM_BINS_PHI*NUM_PHI)/NUM_THREADS;
1766  const Int_t startThetaBin = 0;
1767  const Int_t endThetaBin = NUM_BINS_THETA;
1768  const Int_t startPhiBin = threadInd*numPhiBinsPerThread;
1769  const Int_t endPhiBin = startPhiBin+numPhiBinsPerThread;
1770 
1771  ptr->threadImagePeak[threadInd] = -DBL_MAX;
1772  Int_t peakPhiBin = -1;
1773  Int_t peakThetaBin = -1;
1774 
1775  // zero internal map
1776  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
1777  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
1778  ptr->coarseMap[pol][phiBin][thetaBin] = 0;
1779  }
1780  }
1781 
1782  Int_t phiSector = -1;
1783  std::vector<Int_t>* combosToUse = NULL;
1784  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
1785  Int_t thisPhiSector = phiBin/NUM_BINS_PHI;
1786  if(phiSector!=thisPhiSector){
1787  phiSector = thisPhiSector;
1788  combosToUse = &ptr->combosToUseGlobal[phiSector];
1789  }
1790  for(UInt_t comboInd=0; comboInd<combosToUse->size(); comboInd++){
1791  Int_t combo = combosToUse->at(comboInd);
1792  if(ptr->kOnlyThisCombo >= 0 && combo!=ptr->kOnlyThisCombo){
1793  continue;
1794  }
1795  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
1796  Int_t offsetLow = ptr->offsetLows[pol][combo][phiBin][thetaBin];
1797  Double_t c1 = ptr->crossCorrelations[pol][combo][offsetLow];
1798  Double_t c2 = ptr->crossCorrelations[pol][combo][offsetLow+1];
1799  Double_t cInterp = ptr->interpPreFactors[pol][combo][phiBin][thetaBin]*(c2 - c1) + c1;
1800  ptr->coarseMap[pol][phiBin][thetaBin] += cInterp;
1801  }
1802  }
1803  }
1804 
1805  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
1806  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
1807 
1808  if(combosToUse->size()>0 && ptr->kOnlyThisCombo < 0){
1809  ptr->coarseMap[pol][phiBin][thetaBin] /= combosToUse->size();
1810  }
1811  if(ptr->coarseMap[pol][phiBin][thetaBin] > ptr->threadImagePeak[threadInd]){
1812  ptr->threadImagePeak[threadInd] = ptr->coarseMap[pol][phiBin][thetaBin];
1813  peakPhiBin = phiBin;
1814  peakThetaBin = thetaBin;
1815  }
1816  }
1817  }
1818 
1819  ptr->threadPeakPhiDeg[threadInd] = ptr->phiWaveLookup[peakPhiBin]*TMath::RadToDeg();
1820  ptr->threadPeakThetaDeg[threadInd] = ptr->thetaWaves[peakThetaBin]*TMath::RadToDeg();
1821 
1822  return NULL;
1823 }
1824 
1825 
1826 
1827 
1828 
1829 
1830 //---------------------------------------------------------------------------------------------------------
1843 void CrossCorrelator::reconstructZoom(AnitaPol::AnitaPol_t pol, Double_t& imagePeak,
1844  Double_t& peakPhiDeg, Double_t& peakThetaDeg,
1845  Double_t zoomCenterPhiDeg,
1846  Double_t zoomCenterThetaDeg){
1847 
1848  // Some kind of sanity check here due to the unterminating while loop inside RootTools::getDeltaAngleDeg
1849  if(zoomCenterPhiDeg < -500 || zoomCenterThetaDeg < -500 ||
1850  zoomCenterPhiDeg >= 500 || zoomCenterThetaDeg >= 500){
1851 
1852  std::cerr << "Warning in "<< __PRETTY_FUNCTION__ << " in " << __FILE__ << ". zoomCenterPhiDeg = "
1853  << zoomCenterPhiDeg << " and zoomCenterThetaDeg = " << zoomCenterThetaDeg
1854  << " these values look suspicious so I'm skipping this reconstruction." << std::endl;
1855  imagePeak = -9999;
1856  peakPhiDeg = -9999;
1857  peakThetaDeg = -9999;
1858  return;
1859  }
1860 
1861  threadPol = pol;
1862  Double_t deltaPhiDegPhi0 = RootTools::getDeltaAngleDeg(zoomCenterPhiDeg, getBin0PhiDeg());
1863  deltaPhiDegPhi0 = deltaPhiDegPhi0 < 0 ? deltaPhiDegPhi0 + DEGREES_IN_CIRCLE : deltaPhiDegPhi0;
1864 
1865  Int_t phiSector = floor(deltaPhiDegPhi0)/PHI_RANGE;
1866  doUpsampledCrossCorrelationsThreaded(pol, phiSector); // sets threadPhiSector
1867 
1868  // std::cout << deltaPhiDegPhi0 << "\t" << zoomCenterPhiDeg << "\t" << phiSector << std::endl;
1869 
1870  zoomCenterPhiDeg = (TMath::Nint(zoomCenterPhiDeg/ZOOM_BIN_SIZE_PHI))*ZOOM_BIN_SIZE_PHI;
1871  zoomCenterThetaDeg = (TMath::Nint(zoomCenterThetaDeg/ZOOM_BIN_SIZE_THETA))*ZOOM_BIN_SIZE_THETA;
1872 
1873  zoomPhiMin = zoomCenterPhiDeg - PHI_RANGE_ZOOM/2;
1874  zoomThetaMin = zoomCenterThetaDeg - THETA_RANGE_ZOOM/2;
1875 
1876  // LAUNCH THREADS HERE
1877  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1878  TString name = TString::Format("threadZoomMap%ld", threadInd);
1879  mapThreads.push_back(new TThread(name.Data(),
1881  (void*)&threadArgsVec.at(threadInd))
1882  );
1883  }
1884 
1885  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1886  mapThreads.at(threadInd)->Run();
1887  }
1888 
1889  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1890  mapThreads.at(threadInd)->Join();
1891  }
1892 
1893  for(long threadInd=0; threadInd<NUM_THREADS; threadInd++){
1894  delete mapThreads.at(threadInd);
1895  }
1896  mapThreads.clear();
1897 
1898  // Combine peak search results from each thread.
1899  imagePeak = -DBL_MAX;
1900  for(Long_t threadInd=0; threadInd<NUM_THREADS; threadInd++){
1901  if(threadImagePeak[threadInd] > imagePeak){
1902  imagePeak = threadImagePeak[threadInd];
1903  peakPhiDeg = threadPeakPhiDeg[threadInd];
1904  peakThetaDeg = threadPeakThetaDeg[threadInd];
1905  }
1906  }
1907 }
1908 
1909 
1910 
1911 
1912 
1913 //---------------------------------------------------------------------------------------------------------
1923  // Disgusting hacks to get ROOT threading to compile inside a class.
1924 
1926  Long_t threadInd = args->threadInd;
1927  CrossCorrelator* ptr = args->ptr;
1928  AnitaPol::AnitaPol_t pol = ptr->threadPol;
1929 
1930  // const Int_t numThetaBinsPerThread = NUM_BINS_THETA_ZOOM/NUM_THREADS;
1931  // const Int_t startThetaBin = threadInd*numThetaBinsPerThread;
1932  // const Int_t endThetaBin = startThetaBin+numThetaBinsPerThread;
1933  // const Int_t startPhiBin = 0;
1934  // const Int_t endPhiBin = NUM_BINS_PHI_ZOOM;
1935 
1936  const Int_t numPhiBinsPerThread = NUM_BINS_PHI_ZOOM/NUM_THREADS;
1937  const Int_t startThetaBin = 0;
1938  const Int_t endThetaBin = NUM_BINS_THETA_ZOOM;
1939  const Int_t startPhiBin = threadInd*numPhiBinsPerThread;
1940  const Int_t endPhiBin = startPhiBin+numPhiBinsPerThread;
1941 
1942  // TThread::Lock();
1943  // std::cerr << threadInd << "\t" << startPhiBin << "\t" << endPhiBin << std::endl;
1944  // TThread::UnLock();
1945 
1946  ptr->threadImagePeak[threadInd] = -DBL_MAX;
1947  Int_t peakPhiBin = -1;
1948  Int_t peakThetaBin = -1;
1949 
1950  Int_t kUseOffAxisDelay = ptr->kUseOffAxisDelay;
1951 
1952  Int_t phiSector = ptr->threadPhiSector;
1953  std::vector<Int_t>* combosToUse = &ptr->combosToUseGlobal[phiSector];
1954 
1955  Int_t phiZoomBase = TMath::Nint((ptr->zoomPhiMin - ptr->minPhiDegZoom)/ZOOM_BIN_SIZE_PHI);
1956  Int_t thetaZoomBase = TMath::Nint((ptr->zoomThetaMin - ptr->minThetaDegZoom)/ZOOM_BIN_SIZE_THETA);
1957 
1958  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
1959  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
1960  ptr->fineMap[pol][thetaBin][phiBin]=0;
1961  }
1962  }
1963 
1964  const Int_t offset = ptr->numSamplesUpsampled/2;
1965  for(UInt_t comboInd=0; comboInd<combosToUse->size(); comboInd++){
1966  Int_t combo = combosToUse->at(comboInd);
1967  if(ptr->kOnlyThisCombo >= 0 && combo!=ptr->kOnlyThisCombo){
1968  continue;
1969  }
1970  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
1971  Int_t zoomThetaInd = thetaZoomBase + thetaBin;
1972  Double_t partBA = ptr->partBAsZoom[pol][combo][zoomThetaInd];
1973  Double_t dtFactor = ptr->zoomedCosThetaWaves[zoomThetaInd]/SPEED_OF_LIGHT_NS;
1974  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
1975  Int_t zoomPhiInd = phiZoomBase + phiBin;
1976  Double_t deltaT = dtFactor*(partBA - ptr->part21sZoom[pol][combo][zoomPhiInd]);
1977 
1978  if(kUseOffAxisDelay != 0){
1979  deltaT += kUseOffAxisDelay*ptr->offAxisDelays[pol][combo][zoomPhiInd];
1980  }
1981 
1982  // (int) x - (x < (int) x)
1983  // Int_t offsetLow = floor(deltaT/ptr->correlationDeltaT);
1984  // Int_t offsetLow = floor(deltaT/ptr->correlationDeltaT);
1985  Double_t offsetLowDouble = deltaT/ptr->correlationDeltaT;
1986 
1987  // hack for floor()
1988  Int_t offsetLow = (int) offsetLowDouble - (offsetLowDouble < (int) offsetLowDouble);
1989 
1990  deltaT -= offsetLow*ptr->correlationDeltaT;
1991  deltaT /= ptr->correlationDeltaT;
1992  offsetLow += offset;
1993  Double_t c1 = ptr->crossCorrelationsUpsampled[pol][combo][offsetLow];
1994  Double_t c2 = ptr->crossCorrelationsUpsampled[pol][combo][offsetLow+1];
1995  Double_t cInterp = deltaT*(c2 - c1) + c1;
1996 
1997  ptr->fineMap[pol][thetaBin][phiBin] += cInterp;
1998  }
1999  }
2000  }
2001 
2002  for(Int_t thetaBin = startThetaBin; thetaBin < endThetaBin; thetaBin++){
2003  for(Int_t phiBin = startPhiBin; phiBin < endPhiBin; phiBin++){
2004  if(combosToUse->size()>0 && ptr->kOnlyThisCombo < 0){
2005  ptr->fineMap[pol][thetaBin][phiBin] /= combosToUse->size();
2006  }
2007 
2008  if(ptr->fineMap[pol][thetaBin][phiBin] > ptr->threadImagePeak[threadInd]){
2009  ptr->threadImagePeak[threadInd] = ptr->fineMap[pol][thetaBin][phiBin];
2010  peakPhiBin = phiBin;
2011  peakThetaBin = thetaBin;
2012  }
2013  }
2014  }
2015 
2016  // ptr->threadPeakPhiDeg[threadInd] = hImage->GetXaxis()->GetBinLowEdge(peakPhiBin+1);
2017  // ptr->threadPeakThetaDeg[threadInd] = hImage->GetYaxis()->GetBinLowEdge(peakThetaBin+1);
2018  ptr->threadPeakPhiDeg[threadInd] = ptr->zoomPhiMin + peakPhiBin*ZOOM_BIN_SIZE_PHI;
2019  ptr->threadPeakThetaDeg[threadInd] = ptr->zoomThetaMin + peakThetaBin*ZOOM_BIN_SIZE_THETA;
2020 
2021  return 0;
2022 
2023 }
2024 
2025 
2026 
2027 
2028 
2029 
2030 
2031 
2032 
2033 //---------------------------------------------------------------------------------------------------------
2039 void CrossCorrelator::deleteAllWaveforms(AnitaPol::AnitaPol_t pol){
2040  for(Int_t ant=0; ant<NUM_SEAVEYS; ant++){
2041  if(grs[pol][ant]){
2042  delete grs[pol][ant];
2043  grs[pol][ant] = NULL;
2044  }
2045  if(grsResampled[pol][ant]){
2046  delete grsResampled[pol][ant];
2047  grsResampled[pol][ant] = NULL;
2048  }
2049  }
2050 }
2051 
2052 
2053 
2054 
2055 
2056 
2057 
2058 
2059 //---------------------------------------------------------------------------------------------------------
2067 Int_t CrossCorrelator::directlyInsertGeometry(TString pathToLindasFile, AnitaPol::AnitaPol_t pol){
2068 
2069  // Since I am simulataneously testing many of Linda's geometries on lots of different files
2070  // I need the help of a machine to check I'm testing the geometry I think I'm testing.
2071 
2072  AnitaGeomTool* geom = AnitaGeomTool::Instance();
2073  geom->useKurtAnita3Numbers(0); // i.e. definitely use the numbers I am inserting.
2074  AnitaEventCalibrator* cal = AnitaEventCalibrator::Instance();
2075 
2076 
2077  std::ifstream lindasNums(pathToLindasFile.Data());
2078  if(lindasNums.is_open()==0){
2079  return 1; // This is an error
2080  }
2081 
2082  Int_t ant;
2083  Double_t dr, dPhiRad, dz, dt;
2084 
2085  while(lindasNums >> ant >> dr >> dz >> dPhiRad >> dt){
2086 
2087  Int_t surf, chan, ant2;
2088  geom->getSurfChanAntFromRingPhiPol(AnitaRing::AnitaRing_t (ant/NUM_PHI), ant%NUM_PHI, pol,
2089  surf, chan, ant2);
2090 
2091  Double_t newR = geom->rPhaseCentreFromVerticalHornKurtAnita3[ant][pol] + dr;
2092  Double_t newPhi = geom->azPhaseCentreFromVerticalHornKurtAnita3[ant][pol] + dPhiRad;
2093  Double_t newZ = geom->zPhaseCentreFromVerticalHornKurtAnita3[ant][pol] + dz;
2094  Double_t newT = dt;
2095 
2096  if(newPhi >= TMath::TwoPi()){
2097  newPhi -= TMath::TwoPi();
2098  }
2099  else if(newPhi < 0){
2100  newPhi += TMath::TwoPi();
2101  }
2102 
2103  geom->rPhaseCentreFromVerticalHorn[ant][pol] = newR;
2104  geom->azPhaseCentreFromVerticalHorn[ant][pol] = newPhi;
2105  geom->zPhaseCentreFromVerticalHorn[ant][pol] = newZ;
2106  cal->relativePhaseCenterToAmpaDelays[surf][chan] = newT;
2107 
2108  // std::cout << ant << "\t" << dr << "\t" << dz << "\t" << dPhiRad << "\t" << dt << std::endl;
2109 
2110  }
2111  if(ant != NUM_SEAVEYS - 1){
2112  // then you didn't make it to the end of the file!
2113  std::cerr << "Warning in " << __PRETTY_FUNCTION__ << " in " << __FILE__ << std::endl;
2114  std::cerr << "It looks like you didn't read to the end of Linda's geometry file!" << std::endl;
2115  return 1;
2116  }
2117 
2118  return 0;
2119 }
2120 
2121 
2122 
2123 
2124 
2125 
2126 
2127 
2128 //---------------------------------------------------------------------------------------------------------
2138 TGraph* CrossCorrelator::getCrossCorrelationGraphWorker(Int_t numSamps, AnitaPol::AnitaPol_t pol,
2139  Int_t ant1, Int_t ant2){
2140  // Primarily for debugging, put cross correlations in a TGraph
2141 
2142  Int_t combo = comboIndices[ant1][ant2];
2143  if(combo < 0){
2144  return NULL;
2145  }
2146 
2147  Double_t graphDt = correlationDeltaT;
2148  Double_t* corrPtr = crossCorrelationsUpsampled[pol][combo];
2149  if(numSamps != numSamplesUpsampled){
2150  numSamps = numSamples;
2151  graphDt = nominalSamplingDeltaT;
2152  corrPtr = crossCorrelations[pol][combo];
2153  }
2154 
2155  // Could actually perform the calculation here... but I'll leave it NULL for now
2156  if(corrPtr==NULL){
2157  return NULL;
2158  }
2159 
2160  std::vector<Double_t> offsets = std::vector<Double_t>(numSamps, 0);
2161  std::vector<Double_t> corrs = std::vector<Double_t>(numSamps, 0);
2162 
2163  for(Int_t i=0; i<numSamps; i++){
2164  Int_t offset = (i - numSamps/2);
2165  offsets.at(i) = offset*graphDt;
2166  corrs.at(i) = corrPtr[i];
2167  }
2168 
2169 
2170  TGraph* gr = new TGraph(numSamps, &offsets[0], &corrs[0]);
2171  if(numSamps != numSamplesUpsampled){
2172  gr->SetName(TString::Format("grCorr_%d_%d", ant1, ant2));
2173  gr->SetTitle(TString::Format("Cross Correlation ant1 = %d, ant2 = %d", ant1, ant2));
2174  }
2175  else{
2176  gr->SetName(TString::Format("grCorrUpsampled_%d_%d", ant1, ant2));
2177  gr->SetTitle(TString::Format("Upsampled Cross Correlation ant1 = %d, ant2 = %d", ant1, ant2));
2178  }
2179 
2180  return gr;
2181 }
2182 
2183 
2184 
2185 
2186 
2187 //---------------------------------------------------------------------------------------------------------
2196 TGraph* CrossCorrelator::getCrossCorrelationGraph(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2){
2197  // Primarily for debugging, put cross correlations in a TGraph
2198  return getCrossCorrelationGraphWorker(numSamples, pol, ant1, ant2);
2199 }
2200 
2201 
2202 
2203 
2204 //---------------------------------------------------------------------------------------------------------
2213 TGraph* CrossCorrelator::getUpsampledCrossCorrelationGraph(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2){
2214  return getCrossCorrelationGraphWorker(numSamplesUpsampled, pol, ant1, ant2);
2215 }
2216 
2217 
2218 
2219 
2220 
2221 //---------------------------------------------------------------------------------------------------------
2229 Int_t CrossCorrelator::getPhiSectorOfAntennaClosestToPhiDeg(AnitaPol::AnitaPol_t pol, Double_t phiDeg){
2230  Int_t phiSectorOfPeak = -1;
2231  Double_t bestDeltaPhiOfPeakToAnt = DEGREES_IN_CIRCLE;
2232  for(int ant=0; ant < NUM_SEAVEYS; ant++){
2233  Double_t phiOfAnt = phiArrayDeg[pol].at(ant);
2234  Double_t deltaPhiOfPeakToAnt = TMath::Abs(RootTools::getDeltaAngleDeg(phiOfAnt, phiDeg));
2235  if(deltaPhiOfPeakToAnt < bestDeltaPhiOfPeakToAnt){
2236  bestDeltaPhiOfPeakToAnt = deltaPhiOfPeakToAnt;
2237  phiSectorOfPeak = (ant % NUM_PHI);
2238  }
2239  }
2240  return phiSectorOfPeak;
2241 }
2242 
2243 
2244 
2245 //---------------------------------------------------------------------------------------------------------
2255 TGraph* CrossCorrelator::makeUpsampledCoherentlySummedWaveform(AnitaPol::AnitaPol_t pol, Double_t phiDeg,
2256  Double_t thetaDeg, Int_t maxDeltaPhiSect,
2257  Double_t& snr){
2258  return makeCoherentWorker(pol, phiDeg, thetaDeg, maxDeltaPhiSect, snr, numSamplesUpsampled);
2259 }
2260 
2261 
2262 
2263 
2264 
2265 //---------------------------------------------------------------------------------------------------------
2275 TGraph* CrossCorrelator::makeCoherentlySummedWaveform(AnitaPol::AnitaPol_t pol, Double_t phiDeg,
2276  Double_t thetaDeg, Int_t maxDeltaPhiSect,
2277  Double_t& snr){
2278  return makeCoherentWorker(pol, phiDeg, thetaDeg, maxDeltaPhiSect, snr, numSamples);
2279 }
2280 
2281 
2282 
2283 
2284 
2285 //---------------------------------------------------------------------------------------------------------
2296 TGraph* CrossCorrelator::makeCoherentWorker(AnitaPol::AnitaPol_t pol, Double_t phiDeg,
2297  Double_t thetaDeg, Int_t maxDeltaPhiSect,
2298  Double_t& snr,
2299  Int_t nSamp){
2300 
2301  // std::cout << phiDeg << "\t" << thetaDeg << std::endl;
2302 
2303  Double_t theDeltaT = nSamp == numSamples ? nominalSamplingDeltaT : correlationDeltaT;
2304 
2305  Double_t phiRad = phiDeg*TMath::DegToRad();
2306  Double_t thetaRad = thetaDeg*TMath::DegToRad();
2307  Int_t numAnts = 0;
2308 
2309  Int_t centerPhiSector = getPhiSectorOfAntennaClosestToPhiDeg(pol, phiDeg);
2310 
2311  const Int_t firstAnt = centerPhiSector;
2312 
2313  std::pair<Int_t, Int_t> key(nSamp, 0);
2314  // vArray is actually internal memory managed by FancyFFTs... don't delete this!!!
2315  Double_t* vArray = FancyFFTs::getRealArray(key);
2316 
2317  if(nSamp==numSamples){
2318  FancyFFTs::doInvFFT(nSamp, ffts[pol][firstAnt], false);
2319  }
2320  else{
2321  FancyFFTs::doInvFFT(nSamp, fftsPadded[pol][firstAnt], false);
2322  }
2323 
2324  std::vector<Double_t> tArray(nSamp, 0);
2325  Double_t t0 = grsResampled[pol][firstAnt]->GetX()[0];
2326  for(Int_t samp=0; samp<nSamp; samp++){
2327  tArray.at(samp) = t0 + samp*theDeltaT;
2328  vArray[samp] *= interpRMS[pol][firstAnt]; // Undo the normalization.
2329  }
2330 
2331  // sum of rms of first few ns of each waveform
2332  Double_t rms = 0;
2333 
2334  // Factor of two here to drop the zero padding at the back of the waveform
2335  // which was used during correlations.
2336  TGraph* grCoherent = new TGraph(nSamp/2, &tArray[0], &vArray[0]);
2337 
2338  for(Int_t deltaPhiSect=-maxDeltaPhiSect; deltaPhiSect<=maxDeltaPhiSect; deltaPhiSect++){
2339 
2340  Int_t phiSector = deltaPhiSect + centerPhiSector;
2341  phiSector = phiSector < 0 ? phiSector + NUM_PHI : phiSector;
2342  phiSector = phiSector >= NUM_PHI ? phiSector - NUM_PHI : phiSector;
2343 
2344  for(Int_t ring=0; ring<NUM_RING; ring++){
2345  Int_t ant= phiSector + ring*NUM_PHI;
2346 
2347  // Here we do the inverse FFT on the padded FFTs in memory.
2348  // The output is now in the vArray
2349  if(nSamp==numSamples){
2350  FancyFFTs::doInvFFT(nSamp, ffts[pol][ant], false);
2351  }
2352  else{
2353  FancyFFTs::doInvFFT(nSamp, fftsPadded[pol][ant], false);
2354  }
2355 
2356  if(firstAnt!=ant){ // Don't do the first antenna twice
2357 
2358  // std::cout << pol << "\t" << firstAnt << "\t" << ant << "\t" << phiRad << "\t" << thetaRad << "\t" << std::endl;
2359  Double_t deltaT = getDeltaTExpected(pol, firstAnt, ant, phiRad, thetaRad);
2360 
2361  Int_t offset1 = floor(deltaT/theDeltaT);
2362  Int_t offset2 = ceil(deltaT/theDeltaT);
2363 
2364  // std::cout << deltaT << "\t" << offset1 << "\t" << offset2 << std::endl;
2365 
2366  // How far between the samples we need to interpolate.
2367  Double_t tOverDeltaT = (deltaT - theDeltaT*offset1)/theDeltaT;
2368 
2369  for(Int_t samp=0; samp<grCoherent->GetN(); samp++){
2370  Int_t samp1 = samp + offset1;
2371  Int_t samp2 = samp + offset2;
2372  if(samp1 >= 0 && samp1 < grCoherent->GetN() && samp2 >= 0 && samp2 < grCoherent->GetN()){
2373 
2374  Double_t v1 = vArray[samp1];
2375  Double_t v2 = vArray[samp2];
2376 
2377  Double_t vInterp = tOverDeltaT*(v2 - v1) + v1;
2378 
2379  grCoherent->GetY()[samp] += vInterp*interpRMS[pol][ant];
2380  }
2381  }
2382  }
2383 
2384  // Here we look at the RMS of the first few ns of the uninterpolated waveforms
2385  const Double_t timeToEvalRms = 10; // ns
2386  for(Int_t samp3=0; samp3 < grs[pol][ant]->GetN(); samp3++){
2387  if(grs[pol][ant]->GetX()[samp3] - grs[pol][ant]->GetX()[0] < timeToEvalRms){
2388  rms += grs[pol][ant]->GetY()[samp3]*grs[pol][ant]->GetY()[samp3];
2389  }
2390  }
2391  numAnts++;
2392  }
2393  }
2394 
2395  // Normalize
2396  if(numAnts > 0){
2397  TString name = nSamp == numSamples ? "grCoherent" : "grInterpCoherent";
2398  TString title;
2399  for(Int_t samp=0; samp<grCoherent->GetN(); samp++){
2400  grCoherent->GetY()[samp]/=numAnts;
2401  }
2402 
2403  if(pol==AnitaPol::kHorizontal){
2404  name += TString::Format("H_%u", eventNumber[pol]);
2405  title = "HPOL ";
2406  }
2407  else{
2408  name += TString::Format("V_%u", eventNumber[pol]);
2409  title = "VPOL ";
2410  }
2411 
2412  title += TString::Format("Coherently Summed Waveform for arrival direction elevation %4.2lf (Deg) and azimuth %4.2lf (Deg); Time (ns); Voltage (mV)", thetaDeg, phiDeg);
2413 
2414  grCoherent->SetName(name);
2415  grCoherent->SetTitle(title);
2416 
2417  rms/=numAnts;
2418  rms = TMath::Sqrt(rms);
2419 
2420  Double_t maxY = 0;
2421  Double_t maxX = 0;
2422  Double_t minY = 0;
2423  Double_t minX = 0;
2424  RootTools::getLocalMaxToMin(grCoherent, maxY, maxX, minY, minX);
2425  snr = (maxY - minY)/(2*rms);
2426  }
2427  return grCoherent;
2428 }
TH2D * makeGlobalImage(AnitaPol::AnitaPol_t pol, Double_t &imagePeak, Double_t &peakPhiDeg, Double_t &peakThetaDeg)
Creates an interferometric map using plane wave deltaTs and antenna pairs from all phi-sectors...
Double_t singleAntennaOffAxisDelay(Double_t deltaPhiDeg)
Get the off-axis delay for an off boresight angle.
Int_t numSamplesUpsampled
Number of samples in waveform after padding and up sampling.
void findPeakValues(AnitaPol::AnitaPol_t pol, Int_t numPeaks, Double_t *peakValues, Double_t *phiDegs, Double_t *thetaDegs)
Goes through the coarseMap and finds the top N values.
TString zoomModeNames[kNumZoomModes]
Maps text to the zoomMode_t enum, used for histogram names/titles.
void fillCombosToUse()
Creates vectors of antenna combo indices and puts them in the combosToUseGlobal map.
void deleteAllWaveforms(AnitaPol::AnitaPol_t pol)
Deletes the waveform TGraphs in memory and removes dangling pointers.
UInt_t lastEventNormalized[NUM_POL]
Prevents cross-correlation of the same event twice.
Double_t fineMap[NUM_POL][NUM_BINS_THETA_ZOOM][NUM_BINS_PHI_ZOOM]
Internal storage for the finely binned map.
A class to take in UsefulAnitaEvents and get interferometric maps with a single function.
Int_t comboIndices[NUM_SEAVEYS][NUM_SEAVEYS]
Array mapping ant1+ant2 to combo index.
Int_t offsetLows[NUM_POL][NUM_COMBOS][NUM_PHI *NUM_BINS_PHI][NUM_BINS_THETA]
The interpolation factor for neighbouring samples.
std::vector< TThread * > upsampledCorrThreads
TThreads for doing upsampled cross correlations.
Double_t threadImagePeak[NUM_THREADS]
Store image peaks found by different threads.
static void * doSomeCrossCorrelationsThreaded(void *voidPtrArgs)
Static member function which generates the coarsely binned set of cross correlations from the FFTs he...
TGraph * getCrossCorrelationGraphWorker(Int_t numSamps, AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2)
Called by wrapper functions. Turns internal correlation arrays into TGraphs to be seen by humans...
Int_t getIndexOfMaximum(Int_t len, Double_t *arr)
Find indices where input is not a number (for debugging).
Definition: RootTools.cxx:404
Int_t kDeltaPhiSect
Specifies how many phi-sectors around peak use in reconstruction.
TGraph * getUpsampledCrossCorrelationGraph(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2)
Turns internal upsampled correlation arrays into TGraphs to be seen by humans.
std::vector< Double_t > rArray[NUM_POL]
Vector of antenna radial positions.
std::vector< TThread * > corrThreads
TThreads for doing cross correlations.
Double_t zoomedPhiWaveLookup[NUM_BINS_PHI_ZOOM_TOTAL]
Cached phi for zoomed image.
Int_t threadPhiSector
phi-sector to use in thread functions.
TGraph * grs[NUM_POL][NUM_SEAVEYS]
Raw waveforms obtained from the UsefulAnitaEvent.
void reconstructEvent(UsefulAnitaEvent *usefulEvent, Int_t numFinePeaks=MAX_NUM_PEAKS, Int_t numCoarsePeaks=MAX_NUM_PEAKS)
Reconstruct event.
Double_t coarseMapPeakThetaDegs[NUM_POL][MAX_NUM_PEAKS]
Stores the peak theta (degrees) of the interally stored map.
Double_t coarseMap[NUM_POL][NUM_BINS_PHI *NUM_PHI][NUM_BINS_THETA]
Internal storage for the coarsely binned map.
complex< double > * zeroPadFFT(complex< double > *fft, int numSamples, int numSamplesUpsampled)
Zero padds FFTts,.
Definition: FancyFFTs.cxx:436
~CrossCorrelator()
Destructor.
double * crossCorrelate(int len, double *v1, double *v2, int threadInd=0)
Cross correlates the two input arrays.
Definition: FancyFFTs.cxx:541
TH2D * getZoomMap(AnitaPol::AnitaPol_t pol)
Gets an actual histogram of the zoomed in map.
complex< double > * doFFT(int len, double *input, bool copyOutputToNewArray, int threadInd=0)
Does a forward fast fourier transform on a real input array.
Definition: FancyFFTs.cxx:212
TGraph * grsResampled[NUM_POL][NUM_SEAVEYS]
Evenly resampled TGraphs.
void do5PhiSectorCombinatorics()
Function to index all possible antenna pairs for use in reconstuction.
TString mapModeNames[kNumMapModes]
Maps text to the mapMode_t enum, used for histogram names/titles.
TH2D * getMap(AnitaPol::AnitaPol_t pol, Double_t &peakValue, Double_t &peakPhiDeg, Double_t &peakThetaDeg, UShort_t l3TrigPattern=ALL_PHI_TRIGS)
Gets an actual histogram of the zoomed in map.
Int_t kDoSimpleSatelliteFiltering
Does a simple 52MHz wide notch at 260 if flag is greater than 0.
void printInfo()
Prints some summary information about the CrossCorrelator to stdout.
Double_t threadPeakPhiDeg[NUM_THREADS]
Store phi of image peaks found by different threads.
void correlateEvent(UsefulAnitaEvent *realEvent)
Correlate the event.
Int_t kUseOffAxisDelay
Flag for whether or not to apply off axis delay to deltaT expected.
static void * makeSomeOfZoomImageThreaded(void *voidPtrArgs)
Static member function which fills the interferometric maps.
Int_t getPhiSectorOfAntennaClosestToPhiDeg(AnitaPol::AnitaPol_t pol, Double_t phiDeg)
Finds the phi-sector closest to a particular phi direction.
Double_t part21sZoom[NUM_POL][NUM_COMBOS][NUM_BINS_PHI_ZOOM_TOTAL]
Yet more geometric caching.
Double_t interpRMS[NUM_POL][NUM_SEAVEYS]
RMS of interpolated TGraphs.
UInt_t eventNumber[NUM_POL]
For tracking event number.
void reconstruct(AnitaPol::AnitaPol_t pol, Double_t &imagePeak, Double_t &peakPhiDeg, Double_t &peakThetaDeg)
Wrapper function which launches the threaded functions, which fill the interferometric maps...
std::vector< TThread * > mapThreads
TThreads for doing interferometric map making.
std::complex< Double_t > ffts[NUM_POL][NUM_SEAVEYS][GETNUMFREQS(NUM_SAMPLES *PAD_FACTOR)]
FFTs of evenly resampled waveforms.
void getFinePeakInfo(AnitaPol::AnitaPol_t pol, Int_t peakIndex, Double_t &value, Double_t &phiDeg, Double_t &thetaDeg)
Gets the results from the fine reconstruction.
Double_t zoomedCosPartLookup[NUM_POL][NUM_SEAVEYS][NUM_BINS_PHI_ZOOM_TOTAL]
Cached part of the deltaT calculation.
std::complex< Double_t > fftsPadded[NUM_POL][NUM_SEAVEYS][GETNUMFREQS(NUM_SAMPLES *PAD_FACTOR *UPSAMPLE_FACTOR)]
FFTs of evenly resampled waveforms, padded with zeros so that the inverse fourier transform is interp...
Double_t offAxisDelays[NUM_POL][NUM_COMBOS][NUM_BINS_PHI_ZOOM_TOTAL]
Off-axis delays for fine binned images.
static void * makeSomeOfImageThreaded(void *voidPtrArgs)
Static member function which fills the interferometric maps.
CrossCorrelator()
Constructor.
Double_t crossCorrelations[NUM_POL][NUM_COMBOS][NUM_SAMPLES *PAD_FACTOR]
Cross correlations.
void renormalizeFourierDomain(AnitaPol::AnitaPol_t pol, Int_t ant)
Scales the fft such that the inverse fft would have mean=0 and rms=1. For use after notching...
Double_t zoomedThetaWaves[NUM_BINS_THETA_ZOOM_TOTAL]
Cached theta for zoomed image.
void doAllCrossCorrelationsThreaded(AnitaPol::AnitaPol_t pol)
Wrapper function which launches the threads for generating all the cross correlations.
TGraph * getCrossCorrelationGraph(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2)
Turns internal correlation arrays into TGraphs to be seen by humans.
TH2D * makeTriggeredImage(AnitaPol::AnitaPol_t pol, Double_t &imagePeak, Double_t &peakPhiDeg, Double_t &peakThetaDeg, UShort_t l3TrigPattern)
Creates an interferometric map using plane wave deltaTs and l3Triggered pairs from all phi-sectors...
CrossCorrelator * ptr
Pointer to the CrossCorrelator.
Double_t getDeltaTExpected(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2, Double_t phiWave, Double_t thetaWave)
Function to calculate the time taken by a plane wave to cross the payload.
void simple370MHzSatelliteNotch(AnitaPol::AnitaPol_t pol, Int_t ant)
Applies a 40MHz wide notch centered at 370 MHz to filter another satellite frequency.
std::vector< Int_t > combosToUseGlobal[NUM_PHI]
Depends on L3 trigger for global image.
Double_t interpRMS2[NUM_POL][NUM_SEAVEYS]
RMS of interpolated TGraphs with extra zero padding.
Double_t correlationDeltaT
nominalSamplingDeltaT/UPSAMPLE_FACTOR, deltaT of for interpolation.
Double_t partBAsZoom[NUM_POL][NUM_COMBOS][NUM_BINS_THETA_ZOOM_TOTAL]
Yet more geometric caching.
Double_t getBin0PhiDeg()
Single function to get the angle of the first bin of the interferometric histogram.
int getNumFreqs(int len)
Get the number of frequencies from the number of samples.
Definition: FancyFFTs.cxx:416
void doFFTs(AnitaPol::AnitaPol_t pol)
Takes FFTs of the normalized, evenly resampled waveforms and puts them in memory. ...
bool makeNewPlanIfNeeded(int len, int threadInd=0)
Creates new fftw plan to handle 1D transforms of length len if they haven&#39;t been allocated already...
Definition: FancyFFTs.cxx:19
Long_t threadInd
The thread index.
Double_t fineMapPeakValues[NUM_POL][MAX_NUM_PEAKS]
Stores the peak of the interally stored map.
void fillDeltaTLookup()
Fills in an array of cached deltaTs between antenna pairs as a function of arrival direction...
std::set< std::vector< int > >::iterator comboSetIterator[NUM_BINS_THETA][NUM_BINS_PHI *NUM_PHI]
Pointer to a vector of combo indices (actually an iterator over a set, but you know what I mean)...
Int_t getBit(UInt_t bitIndex, UInt_t bitMask)
For decoding bit masks.
Definition: RootTools.cxx:1242
Int_t kOnlyThisCombo
For debugging, only fill histograms with one particular antenna pair.
std::vector< Int_t > comboToAnt1s
Vector mapping combo index to ant1.
TGraph * makeCoherentlySummedWaveform(AnitaPol::AnitaPol_t pol, Double_t phiDeg, Double_t thetaDeg, Int_t maxDeltaPhiSect, Double_t &snr)
Creates the coherently summed waveform from the FFTs held in memory.
AnitaPol::AnitaPol_t threadPol
Polarization to use in thread functions.
std::vector< Double_t > zArray[NUM_POL]
Vector of antenna heights.
void getCoarsePeakInfo(AnitaPol::AnitaPol_t pol, Int_t peakIndex, Double_t &value, Double_t &phiDeg, Double_t &thetaDeg)
Gets the results from the coarse reconstruction.
std::vector< Int_t > comboToAnt2s
Vector mapping combo index to ant2.
TGraph * interpolateWithStartTimeAndZeroMean(TGraph *grIn, Double_t startTime, Double_t dt, Int_t nSamp)
Creates an interpolated TGraph with zero mean.
Double_t coarseMapPeakValues[NUM_POL][MAX_NUM_PEAKS]
Stores the peak of the interally stored map.
Int_t numSamples
Number of samples in waveform after padding.
TH2D * initializeNewCombinatorics()
static Int_t directlyInsertGeometry(TString pathToLindasFile, AnitaPol::AnitaPol_t pol)
Used to insert phase center geometry files from Linda.
Double_t relativeOffAxisDelay(AnitaPol::AnitaPol_t pol, Int_t ant1, Int_t ant2, Double_t phiDeg)
Get the relative off-axis delay between an antenna pair.
double * getRealArray(std::pair< Int_t, Int_t > key)
Get the real array of the internal fftw memory. Do not delete this!
Definition: FancyFFTs.cxx:673
TH2D * makeZoomedImage(AnitaPol::AnitaPol_t pol, UShort_t l3TrigPattern, Double_t zoomCenterPhiDeg, Double_t zoomCenterThetaDeg)
Creates an interferometric map using plane wave deltaTs centered around a particular phi/theta...
Double_t coarseMapPeakPhiDegs[NUM_POL][MAX_NUM_PEAKS]
Stores the peak phi (degrees) of the interally stored map.
void simpleNotch(AnitaPol::AnitaPol_t pol, Int_t ant, Double_t notchLowEdgeMHz, Double_t notchHighEdgeMHz)
Applies a simple notch between the given frequencies.
Container required to get threading to work inside a class, includes the thread index and the pointer...
void getLocalMaxToMin(TGraph *gr, Double_t &maxY, Double_t &maxX, Double_t &minY, Double_t &minX)
Updates input based on absolute largest local maximum to local minimum difference. For pulse finding.
Definition: RootTools.cxx:991
Int_t numCombos
Number of possible antenna pairs, counted during initialization. Should equal NUM_COMBOS.
void getNormalizedInterpolatedTGraphs(UsefulAnitaEvent *realEvent, AnitaPol::AnitaPol_t pol)
Makes evenly re-sampled, normalized waveform graphs from the UsefulAnitaEvent.
void initializeVariables()
Workhorse function to set internal variables.
void getMaxUpsampledCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t combo, Double_t &time, Double_t &value)
Get the maximum upsampled correlation time and value from a polarization and antenna combo index...
Double_t phiWaveLookup[NUM_BINS_PHI *NUM_PHI]
Cached phi for image.
static void * doSomeUpsampledCrossCorrelationsThreaded(void *voidPtrArgs)
Static member function which generates the finely binned set of cross correlations from the FFTs held...
void insertPhotogrammetryGeometry()
Inserts the photogrammetry geometry into the CrossCorrelator internals AND the AnitaEventCalibrator i...
Double_t nominalSamplingDeltaT
ANITA-3 => 1./2.6 ns, deltaT for evenly resampling.
Double_t getDeltaAngleDeg(Double_t angle1, Double_t angle2)
Do angle1-angle2 (in degrees) and +- 360 such that the result lies in -180 < deltaAngle < 180...
Definition: RootTools.cxx:267
Double_t interpPreFactors[NUM_POL][NUM_COMBOS][NUM_PHI *NUM_BINS_PHI][NUM_BINS_THETA]
The interpolation factor for neighbouring samples.
Double_t thetaWaves[NUM_BINS_THETA]
Cached theta for image.
TGraph * makeUpsampledCoherentlySummedWaveform(AnitaPol::AnitaPol_t pol, Double_t phiDeg, Double_t thetaDeg, Int_t maxDeltaPhiSect, Double_t &snr)
Creates the coherently summed waveform from the zero padded FFTs held in memory.
double * doInvFFT(int len, complex< double > *input, bool copyOutputToNewArray, int threadInd=0)
Does an inverse fast fourier transform on an array of complex<double>s.
Definition: FancyFFTs.cxx:288
void doUpsampledCrossCorrelationsThreaded(AnitaPol::AnitaPol_t pol, Int_t phiSector)
Static member function which generates the finely binned set of cross correlations from the FFTs held...
Double_t zoomedTanThetaWaves[NUM_BINS_THETA_ZOOM_TOTAL]
Cached tan(theta) for zoomed image.
Double_t maxDPhiDeg
Variable for testing how wide an off axis angle is used in reconstruction.
Double_t threadPeakThetaDeg[NUM_THREADS]
Store theta of image peaks found by different threads.
TGraph * makeCoherentWorker(AnitaPol::AnitaPol_t pol, Double_t phiDeg, Double_t thetaDeg, Int_t maxDeltaPhiSect, Double_t &snr, Int_t nSamp)
Worker function to create the coherently summed waveform from either the regular ffts or the padded f...
void getMaxCorrelationTimeValue(AnitaPol::AnitaPol_t pol, Int_t combo, Double_t &time, Double_t &value)
Get the maximum correlation time and value from a polarization and antenna combo index.
std::vector< Double_t > phiArrayDeg[NUM_POL]
Vector of antenna azimuth positions.
void reconstructZoom(AnitaPol::AnitaPol_t pol, Double_t &imagePeak, Double_t &peakPhiDeg, Double_t &peakThetaDeg, Double_t zoomCenterPhiDeg=0, Double_t zoomCenterThetaDeg=0)
Wrapper function which launches the threaded functions, which fill the zoomed maps.
void simple260MHzSatelliteNotch(AnitaPol::AnitaPol_t pol, Int_t ant)
Applies a 52MHz wide notch centered at 260 MHz to filter the most problematic satellite frequency...
Double_t crossCorrelationsUpsampled[NUM_POL][NUM_COMBOS][NUM_SAMPLES *PAD_FACTOR *UPSAMPLE_FACTOR *PAD_FACTOR]
Upsampled cross correlations.
Bool_t useCombo(Int_t ant1, Int_t ant2, Int_t phiSector, Int_t deltaPhiSect)
This function encodes whether a pair of antennas should be used in a particular phi sector...
Double_t fineMapPeakThetaDegs[NUM_POL][MAX_NUM_PEAKS]
Stores the peak theta (degrees) of the interally stored map.
Double_t getInterpolatedUpsampledCorrelationValue(AnitaPol::AnitaPol_t pol, Int_t combo, Double_t deltaT)
Linearly interpolates between upsampled correlation points.
Double_t zoomedCosThetaWaves[NUM_BINS_THETA_ZOOM_TOTAL]
Cached cos(theta) for zoomed image.
Double_t fineMapPeakPhiDegs[NUM_POL][MAX_NUM_PEAKS]
Stores the peak phi (degrees) of the interally stored map.