AnitaEventCalibrator.cxx
1 
9 #include "AnitaEventCalibrator.h"
10 #include "UsefulAnitaEvent.h"
11 #include "AnitaVersion.h"
12 #include "TMutex.h"
13 
14 ClassImp(AnitaEventCalibrator);
15 
16 
17 static AnitaEventCalibrator* instances[NUM_ANITAS+1] = {0};
18 
19 
20 static const char * voltageCalibFiles[] = { 0, 0, 0, "simpleVoltageCalibrationHarm.txt", "simpleVoltageCalibrationAnita4.txt" };
21 static const char * relativeCableDelayFiles[] = { 0,0,0, "relativeCableDelays.dat","relativeCableDelaysAnita4.dat"};
22 static const char * relativePhaseCenterToAmpaDelaysFiles[] = { 0,0,0, "relativePhaseCenterToAmpaDelays.dat","relativePhaseCenterToAmpaDelaysAnita4.dat"};
23 
25  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
26  // std::cerr << "AnitaEventCalibrator::AnitaEventCalibrator()" << std::endl;
27  loadCalib();
28 
29  // const Int_t bufferSize = 3600; ///< An hour of averging at 1Hz, worked for calibration
30  // clockPeriodRingBuffer = new RingBuffer(bufferSize);
31 
32  firstHitBusRcoLatchLimit = 40;
33  dtInterp = 0.01;
34  nominalDeltaT = 1./2.6;
35  fClockProblem = 0;
37 
38  for(int surf=0; surf < NUM_SURF; surf++){
39  numPointsArray[surf] = 0;
40  for(int samp=0; samp < NUM_SAMP; samp++){
41  timeArray[surf][samp] = 0;
42  scaArray[surf][samp] = 0;
43  }
44  for(int chan=0; chan < NUM_CHAN; chan++){
45  for(int samp=0; samp < NUM_SAMP; samp++){
46  voltsArray[surf][chan][samp] = 0;
47  }
48  }
49  }
50 
51 }
52 
53 
54 
55 
56 
57 AnitaEventCalibrator::~AnitaEventCalibrator(){
58  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
59  // delete clockPeriodRingBuffer;
60  deleteClockAlignmentTGraphs();
61 };
62 
63 
64 static TMutex instance_lock;
65 
66 //______________________________________________________________________________
68  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
69 
70  if (!v) v = AnitaVersion::get();
71 
72  AnitaEventCalibrator * tmp = instances[v];
73  __asm__ __volatile__ ("" ::: "memory"); //memory fence!
74 
75  if (!tmp)
76  {
77  instance_lock.Lock();
78  tmp = instances[v];
79  if (!tmp)
80  {
81  tmp = new AnitaEventCalibrator();
82  __asm__ __volatile__ ("" ::: "memory");
83  instances[v] = tmp;
84  }
85  instance_lock.UnLock();
86  }
87 
88  return instances[v];
89 }
90 
91 
92 
94  // The downside of having sensible containers
95 
96  for(Int_t surf=0; surf<NUM_SURF; surf++){
97  clockAlignment.push_back(0);
98  defaultClocksToAlign.push_back(surf);
99  grClocks.push_back(NULL);
100  grClockInterps.push_back(NULL);
101  grCorClock.push_back(NULL);
102  rcoVector.push_back(0);
103  tempFactors.push_back(1);
104 
105  measuredClockPeriods.push_back(std::vector<std::vector<Double_t> > (NUM_RCO, std::vector<Double_t>(AnitaClock::maxNumZcs, 0)));
106 
107  // const Int_t bufferSize = 3600;
108  const Int_t bufferSize = 300;
109  clockPeriodRingBuffers.push_back(std::vector<RingBuffer>(NUM_CHIP, RingBuffer(bufferSize)));
110  }
111 }
112 
113 
114 
115 
118 
119 
120  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
133 
134 
135 
136 
137 
141 
142  // Initial states for calibration flags, modified based on calType below
143  Bool_t fUnwrap = false;
144  Bool_t fBinToBinDts = false;
145  Bool_t fNominal = false;
146  Bool_t fApplyTempCorrection = true; // The only thing "on" by default
147  Bool_t fVoltage = false;
148  Bool_t fApplyTriggerJitterCorrection = false;
149  Bool_t fApplyCableDelays = false;
150  Bool_t fZeroMeanNonClockChannels = false;
151  Bool_t fFlipRcoPhase = false;
152  Bool_t fFirmwareRcoNoLatch = false;
153  Bool_t fAddPedestal = false;
154  Bool_t fApplyExtraDelayFromPhaseCenter = false;
155  Bool_t fRemoveClockSpike = false;
156 
157  switch(calType){
158  case WaveCalType::kJustRemoveClockSpike:
159  fRemoveClockSpike = true;
160  break;
161 
163  std::cerr << "Warning in " << __PRETTY_FUNCTION__ << ", calling kNotACalib will be treated as kNoCalib"
164  << std::endl;
165 
167  fApplyTempCorrection = false;
168  break;
169 
171  fRemoveClockSpike = true;
172  fBinToBinDts = true;
173  fApplyTempCorrection = true;
174  fUnwrap = true;
175  break;
176 
178  fRemoveClockSpike = true;
179  fBinToBinDts = true;
180  fApplyTempCorrection = true;
181  break;
182 
184  fUnwrap = true;
185  break;
186 
188  fRemoveClockSpike = true;
189  fUnwrap = true;
190  fBinToBinDts = true;
191  fVoltage = true;
192  fApplyTempCorrection = true;
193  break;
194 
196  fRemoveClockSpike = true;
197  fUnwrap = true;
198  fBinToBinDts = true;
199  fVoltage = true;
200  fFlipRcoPhase = true;
201  break;
202 
204  fRemoveClockSpike = true;
205  fUnwrap = true;
206  fBinToBinDts = true;
207  fVoltage = true;
208  fApplyTempCorrection = true;
209  fFirmwareRcoNoLatch = true;
210  break;
211 
213  fRemoveClockSpike = true;
214  fUnwrap = true;
215  fBinToBinDts = true;
216  fVoltage = true;
217  fFirmwareRcoNoLatch = true;
218  fFlipRcoPhase = true;
219  break;
220 
222  fRemoveClockSpike = true;
223  fUnwrap = true;
224  fBinToBinDts = true;
225  fApplyTempCorrection = true;
226  fVoltage = true;
227  fApplyTriggerJitterCorrection = true;
228  fApplyCableDelays = false;
229  fZeroMeanNonClockChannels = true;
230  break;
231 
233  fAddPedestal = true;
234  // Don't break just do full calibration but add pedestal...
235  // Not sure if this is the same as the previous implementation of this flag.
236 
237 
239  fRemoveClockSpike = true;
240  fUnwrap = true;
241  fBinToBinDts = true;
242  fApplyTempCorrection = true;
243  fApplyTriggerJitterCorrection = true;
244  fApplyCableDelays = true;
245  fZeroMeanNonClockChannels = true;
246  fApplyExtraDelayFromPhaseCenter = true;
247  break;
248 
250  fUnwrap = true;
251  fBinToBinDts = true;
252  fZeroMeanNonClockChannels = true;
253  break;
254 
255  case WaveCalType::kFull:
256  fRemoveClockSpike = true;
257  fUnwrap = true;
258  fBinToBinDts = true;
259  fApplyTempCorrection = true;
260  fVoltage = true;
261  fApplyTriggerJitterCorrection = true;
262  fApplyCableDelays = true;
263  fZeroMeanNonClockChannels = true;
264  fApplyExtraDelayFromPhaseCenter = true;
265  break;
266 
268  fRemoveClockSpike = true;
269  fUnwrap = true;
270  fBinToBinDts = true;
271  fApplyTempCorrection = false;
272  fVoltage=true;
273  fApplyTriggerJitterCorrection=false;
274  fApplyCableDelays=true;
275  fZeroMeanNonClockChannels=true;
276  fApplyExtraDelayFromPhaseCenter=true;
277 
278  // case WaveCalType::kDefault:
279  // std::cerr << "It seems like WaveCal::kDefault isn't handled by any of the options in "
280  // << __PRETTY_FUNCTION__ << std::endl;
281 
282  }
283 
285  // ! Step 2: Remove the spiky clock
287  if(fRemoveClockSpike==true){
288  // First remove spike in Surf10 chipB clock, hopefully the spiky clock in SURF10 chipB will all gone.
289  for(Int_t samp=0;samp<NUM_SAMP;samp++){
290  if((eventPtr->chipIdFlag[9*NUM_CHAN + 8]&0x03) == 0x01 and eventPtr->data[9*NUM_CHAN + 8][samp] >300 ){
291  eventPtr->data[9*NUM_CHAN + 8][samp] -= 512;
292  }
293  }
294 
295  // Loop through all Surf
296  for(Int_t surf=0; surf<NUM_SURF; surf++){
297  if(eventPtr->fFromCalibratedAnitaEvent==0){
298  //spiky clock channel
299  for(Int_t samp=0;samp<NUM_SAMP;samp++){
300  if(eventPtr->data[surf*NUM_CHAN + 8][samp] <-200 or eventPtr->data[surf*NUM_CHAN + 8][samp] > 200){
301  eventPtr->fClockSpike = 1;
302  }
303  }
304  }
305  //Handling spiky RF channel
306  for(Int_t chan=0;chan<NUM_CHAN-1;chan++){
307  for(Int_t samp=0;samp<NUM_SAMP;samp++){
308  // surf10 chipB problem
309  if(surf == 9 and (eventPtr->chipIdFlag[surf*NUM_CHAN + chan]&0x03) == 0x01 and eventPtr->data[surf*NUM_CHAN + chan][samp]>358 and eventPtr->data[surf*NUM_CHAN + chan][samp]<470){
310  eventPtr->data[surf*NUM_CHAN + chan][samp] -= 512;
311  }
312  if(eventPtr->data[surf*NUM_CHAN + chan][samp]< -470 or eventPtr->data[surf*NUM_CHAN + chan][samp]>470){
313  eventPtr->fRFSpike = 1;
314  eventPtr->SpikeyRFChannelList.push_back(surf*NUM_CHAN + chan);
315  }
316  }
317  }
318  }
319 
320 
321  }
322 
323 
324 
325 
326 
330  fClockProblem = 0;
331 
332  if(fBinToBinDts==true){
333  // If we want deltaTs then we definitely need to know what RCO phase we are in...
334 
335  if(eventPtr->fFromCalibratedAnitaEvent==0){ // Figure out the RCO if we don't have calibrated input
336  getTempFactors(eventPtr); // Get last temperature correction for this event's LAB
337  guessRco(eventPtr);
338  }
339  else{// If have calibrated anita event, then copy result and don't guess
340  for(Int_t surf=0; surf<NUM_SURF; surf++){
341  rcoVector.at(surf) = eventPtr->fRcoArray[surf];
342  }
343  fClockProblem = eventPtr->fClockProblem;
344  }
345 
346  // For calibration purposes...
347  if(fFirmwareRcoNoLatch==true){
348  for(Int_t surf=0; surf<NUM_SURF; surf++){
349  rcoVector.at(surf) = eventPtr->getRcoCorrected(surf*NUM_CHAN + 8);
350  }
351  }
352  // Also for calibration purposes...
353  if(fFlipRcoPhase==true){
354  for(Int_t surf=0; surf<NUM_SURF; surf++){
355  rcoVector.at(surf) = 1 - rcoVector.at(surf);
356  }
357  }
358 
359  // Copy to rco guessing array in UsefulAnitaEvent
360  for(Int_t surf=0; surf<NUM_SURF; surf++){
361  eventPtr->fRcoArray[surf] = rcoVector.at(surf);
362  }
363  }
364 
365 
366 
367 
368 
369 
373  if(eventPtr->fFromCalibratedAnitaEvent==0){ // Then figure it out from event information
374  if(fClockProblem!=0){
375  // std::cerr << "Clock problem found in eventNumber = " << eventPtr->eventNumber
376  // << ", skipped temperature correction" << std::endl;
377  }
378  else{
379  updateTemperatureCorrection(eventPtr);
380  }
381  getTempFactors(eventPtr);
382  for(Int_t surf=0; surf<NUM_SURF; surf++){
383  eventPtr->fTempFactorGuesses[surf] = tempFactors.at(surf);
384  }
385  }
386  else{ // If we do have a calibrated event then just copy the result into the calibrator
387  for(Int_t surf=0; surf<NUM_SURF; surf++){
388  tempFactors.at(surf) = eventPtr->fTempFactorGuesses[surf];
389  }
390  }
391 
392 
393 
397  if(fUnwrap==true){// Then we call the unwrapping function for every channel
398  for(Int_t surf = 0; surf < NUM_SURF; surf++){
399  for(Int_t chan = 0; chan < NUM_CHAN; chan++){
400  numPointsArray[surf] = unwrapChannel(eventPtr, surf, chan,
401  rcoVector.at(surf), fApplyTempCorrection, fAddPedestal,
402  voltsArray[surf][chan], timeArray[surf], scaArray[surf]);
403  }
404  }
405  }
406  else if(fUnwrap==false){// Then we fill in the volt/time arrays with linearly increasing data points
407 
408  for(Int_t surf = 0; surf < NUM_SURF; surf++){
409  Double_t tempFactor = tempFactors.at(surf);
410  numPointsArray[surf] = NUM_SAMP;
411  Int_t clockIndex = surf*NUM_CHAN + 8;
412  Int_t labChip = eventPtr->getLabChip(clockIndex);
413  Int_t rco = rcoVector.at(surf);
414  if(rco < 0 || rco > 1){
415  std::cerr << "Error in rco array!" << __FILE__ << ": " << __LINE__ << std::endl;
416  }
417  // Int_t firstHitBus = eventPtr->getFirstHitBus(clockIndex);
418 
419  Int_t earliestSample = eventPtr->getEarliestSample(clockIndex);
420  Int_t latestSample = eventPtr->getLatestSample(clockIndex);
421 
422  // i.e. is the waveform wrapped around the SCA?
423  Int_t needToFlipRco = latestSample<earliestSample ? 1 : 0;
424 
425  timeArray[surf][0] = 0;
426  for(Int_t samp=0; samp < numPointsArray[surf]-1; samp++){
427  if(samp==earliestSample && needToFlipRco){
428  rco = 1 - rco;
429  }
430  timeArray[surf][samp+1] = timeArray[surf][samp] + deltaTs[surf][labChip][rco][samp]*tempFactor;
431  }
432 
433  for(Int_t chan = 0; chan < NUM_CHAN; chan++){
434  Int_t chanIndex = surf*NUM_CHAN + chan;
435  for(Int_t samp=0; samp < numPointsArray[surf]; samp++){
436  voltsArray[surf][chan][samp] = eventPtr->data[chanIndex][samp];
437  if(fAddPedestal==true){
438  voltsArray[surf][chan][samp] += fPedStruct.thePeds[surf][labChip][chan][samp];
439  }
440  scaArray[surf][samp] = samp;
441  }
442  }
443  }
444  }
445 
449  // Actually all the bin-to-bin timings are put in the time array by default..
450  // so if they're not wanted we can take them out again.
451  if(fBinToBinDts==false){
452  Double_t timeFactor = fNominal == false ? 1 : nominalDeltaT; // If not nominal dts then use sample number
453  for(Int_t surf = 0; surf < NUM_SURF; surf++){
454  for(Int_t samp=0; samp < numPointsArray[surf]; samp++){
455  timeArray[surf][samp] = timeFactor*samp;
456  }
457  }
458  }
459 
460 
461 
462 
463 
464 
465 
466 
470  if(fVoltage==true){
471  applyVoltageCalibration(eventPtr);
472  }
473 
474 
475 
476 
477 
478 
479 
480 
481 
482 
483 
487  if(fApplyTriggerJitterCorrection==true){
488  if(eventPtr->fFromCalibratedAnitaEvent==0){
489  // If we don't have the calibration then get correction
490  getClockAlignment(eventPtr, numPointsArray, voltsArray, timeArray);
491  // And copy to relevant array
492  for(Int_t surf=0; surf<NUM_SURF; surf++){
493  // std::cout << surf << "\t" << eventPtr->fClockPhiArray[surf] << "\t" << clockAlignment.at(surf) << std::endl;
494  eventPtr->fClockPhiArray[surf] = clockAlignment.at(surf);
495  }
496  }
497  else{ // If we have the calibration then just copy the result back to the calibrator
498  for(Int_t surf=0; surf<NUM_SURF; surf++){
499  clockAlignment.at(surf) = eventPtr->fClockPhiArray[surf];
500  }
501  }
502 
503  // Apply the trigger jitter correction to the clock array.
504  for(Int_t surf=0; surf<NUM_SURF; surf++){
505  for(Int_t samp=0; samp < numPointsArray[surf]; samp++){
506  // Update time base for each SURF with the trigger jitter
507  timeArray[surf][samp] -= clockAlignment.at(surf);
508  }
509  }
510  }
511 
512 
513 
514 
515 
516 
517 
518 
522 
523  if(fZeroMeanNonClockChannels==true){
524  zeroMeanNonClockChannels();
525  }
526 
527 
528 
529 
530 
531 
532  // Combine last two steps...
537  for(Int_t surf=0; surf<NUM_SURF; surf++){
538  eventPtr->fRcoArray[surf] = rcoVector.at(surf);
539  eventPtr->fClockPhiArray[surf] = clockAlignment.at(surf);
540  for(Int_t chan=0; chan<NUM_CHAN; chan++){
541  Int_t chanIndex = surf*CHANNELS_PER_SURF + chan;
542 
543  eventPtr->fNumPoints[chanIndex] = numPointsArray[surf];
544 
545  Double_t cableDelay = 0;
546  if(fApplyCableDelays==true){
547  Int_t labChip = eventPtr->getLabChip(chanIndex);
548  cableDelay = relativeCableDelays[surf][chan][labChip];
549 
550  if(fApplyExtraDelayFromPhaseCenter==true){
551  // Defined this backwards in the phase center fitter so this gets subtracted.
552  cableDelay -= relativePhaseCenterToAmpaDelays[surf][chan];
553  }
554  }
555 
556  for(Int_t samp=0; samp<numPointsArray[surf]; samp++){
557  eventPtr->fTimes[chanIndex][samp] = timeArray[surf][samp] + cableDelay;
558  eventPtr->fVolts[chanIndex][samp] = voltsArray[surf][chan][samp];
559  eventPtr->fCapacitorNum[chanIndex][samp] = scaArray[surf][samp];
560  }
561  }
562  }
563 
564  // Finally copy some meta-data about the calibration to the tree.
565  eventPtr->fCalType = calType;
566  eventPtr->fClockProblem = fClockProblem;
567 
568 
569  // Now enjoy your calibrated event
570  return 0;
571 }
572 
573 
574 
575 
576 void AnitaEventCalibrator::applyVoltageCalibration(UsefulAnitaEvent* eventPtr){
577  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
578  for(Int_t surf=0; surf<NUM_SURF; surf++){
579  for(Int_t chan=0; chan<RFCHAN_PER_SURF; chan++){
580  Int_t chanIndex = surf*NUM_CHAN + chan;
581  Int_t labChip = eventPtr->getLabChip(chanIndex);
582  for(Int_t samp=0; samp<numPointsArray[surf]; samp++){
583  // std::cout << voltsArray[surf][chan][samp] << "\t";
584  voltsArray[surf][chan][samp]*=mvCalibVals[surf][chan][labChip];
585  // std::cout << voltsArray[surf][chan][samp] << "\tsurf=" << surf << "\tchan=" << chan
586  // << "\tchanIndex=" << chanIndex << "\tlabChip=" << labChip << "\tnumPoints="
587  // << numPointsArray[surf] << "\tRFCHAN_PER_SURF=" << RFCHAN_PER_SURF
588  // << "\tmvCalibVals[" << surf << "][" << chan << "]["<< labChip << "] = "
589  // << mvCalibVals[surf][chan][labChip] << std::endl;
590  }
591  }
592  }
593 }
594 
595 
596 
597 void AnitaEventCalibrator::zeroMeanNonClockChannels(){
598  for(Int_t surf=0; surf<NUM_SURF; surf++){
599  for(Int_t chan=0; chan<RFCHAN_PER_SURF; chan++){
600  Double_t chanMean = TMath::Mean(numPointsArray[surf], voltsArray[surf][chan]);
601  for(Int_t samp=0; samp<numPointsArray[surf]; samp++){
602  voltsArray[surf][chan][samp] -= chanMean;
603  }
604  }
605  }
606 }
607 
608 
609 std::vector<Double_t> AnitaEventCalibrator::getClockAlignment(UsefulAnitaEvent* eventPtr,
610  Int_t numPoints[NUM_SURF],
611  Double_t volts[NUM_SURF][NUM_CHAN][NUM_SAMP],
612  Double_t times[NUM_SURF][NUM_SAMP]){
613  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
614  return getClockAlignment(eventPtr, numPoints, volts, times, defaultClocksToAlign);
615 }
616 
617 
618 
619 void AnitaEventCalibrator::deleteClockAlignmentTGraphs(){
620 
621  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
622  for(Int_t surf=0; surf<NUM_SURF; surf++){
623  // std::cout << surf << std::endl;
624  clockAlignment.at(surf) = 0;
625  if(grClocks.at(surf)) {
626  delete grClocks.at(surf);
627  grClocks.at(surf) = NULL;
628  }
629  if(grClockInterps.at(surf)) {
630  delete grClockInterps.at(surf);
631  grClockInterps.at(surf) = NULL;
632  }
633  if(grCorClock.at(surf)){
634  delete grCorClock.at(surf);
635  grCorClock.at(surf) = NULL;
636  }
637  }
638 
639  // std::cout << "deleting clock0s" << std::endl;
640  for(std::map<Double_t, TGraph*>::iterator itr = grClock0s.begin(); itr != grClock0s.end(); ++itr){
641  // std::cout << itr->first << ", " << itr->second << "\t" << itr->second->GetN() << std::endl;
642 
643  delete itr->second; // delete object pointed to by current key
644  itr->second = NULL;
645  }
646 
647  // finally delete all key and pointer pairs from the map
648  grClock0s.erase(grClock0s.begin(), grClock0s.end());
649 
650  // std::cout << "finished deleting..." << std::endl;
651 }
652 
653 std::vector<Double_t> AnitaEventCalibrator::getClockAlignment(UsefulAnitaEvent* eventPtr,
654  Int_t numPoints[NUM_SURF],
655  Double_t volts[NUM_SURF][NUM_CHAN][NUM_SAMP],
656  Double_t times[NUM_SURF][NUM_SAMP],
657  std::vector<Int_t> listOfClockNums){
658  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
659 
660  // for(int surf=0; surf<NUM_SURF; surf++){
661  // std::cout << surf << "\t" << numPoints[surf] << std::endl;
662  // }
663 
664 
665 
666  // Want these to hang around in memory during calibration so I can examine them.
667  // Therefore delete previous clock alignment graphs only when this function is called.
668  deleteClockAlignmentTGraphs();
669 
670 
671 
672 #ifdef USE_FFT_TOOLS
673 
674  // is approximate and just to avoid an assertion error from inside ROOT's interpolation wrapper
675  const Int_t minNumPointsToTryInterpolation = 10; // should probs get moved to libRootFftwWrapper...
676  for(UInt_t surfInd=0; surfInd<listOfClockNums.size(); surfInd++){
677  // there is failure mode where there aren't enough points in the TGraph to interpolate
678  // here we do a very simple check for the number of points and don't even try if one clock is bad.
679 
680  if(numPoints[surfInd] <= minNumPointsToTryInterpolation){
681  // std::cerr << "Worryingly few points in clock for SURF " << surfInd << ", numPoints = "
682  // << numPoints[surfInd] << "." << std::endl;
683  // std::cerr << "Clocks for this event will be misaligned! Setting fClockProblem to 2." << std::endl;
684  eventPtr->fClockProblem = 2;
685  std::vector<Double_t> zeroClockOffsets(NUM_SURF, 0);
686  return zeroClockOffsets;
687  }
688  }
689 
690 
691 
692 
693 
694  for(UInt_t surfInd=0; surfInd<listOfClockNums.size(); surfInd++){
695  Int_t surf = listOfClockNums.at(surfInd);
696  if(surf==0){
697  continue;
698  }
699 
700  // Interpolate clock
701  // if(eventPtr->eventNumber == 31455791){
702  // std::cerr << surf << "\t" << numPoints[surf] << std::endl;
703  // }
704  grClocks.at(surf) = new TGraph(numPoints[surf], times[surf], volts[surf][8]);
705  grClockInterps.at(surf) = FFTtools::getInterpolatedGraph(grClocks.at(surf), dtInterp);
706 
707  Int_t lab = eventPtr->getLabChip(surfInd*NUM_CHAN + 8);
708  Double_t deltaClockKeepNs = clockKeepTime[surf][lab];
709 
710  TGraph* grClock0 = NULL;
711  if(grClock0s.find(deltaClockKeepNs)==grClock0s.end()){
712  // Not already made/played around with this amount of ringing
713  TGraph* grTemp0 = new TGraph(numPoints[0], times[0], volts[0][8]); // make clock
714  // if(eventPtr->eventNumber == 31455791){
715  // std::cerr << 0 << "\t" << numPoints[0] << std::endl;
716  // }
717 
718  grClock0 = FFTtools::getInterpolatedGraph(grTemp0, dtInterp);
719  delete grTemp0;
720  grClock0s[deltaClockKeepNs] = grClock0; // add key and pointer into map
721 
722  keepOnlySomeTimeAfterClockUptick(grClock0, deltaClockKeepNs); // process
723  }
724  else{
725  grClock0 = grClock0s.find(deltaClockKeepNs)->second;
726  }
727  keepOnlySomeTimeAfterClockUptick(grClockInterps.at(surf), deltaClockKeepNs);
728 
729  // Correlate clocks once they've both been processed
730  grCorClock.at(surf) = FFTtools::getCorrelationGraph(grClockInterps.at(surf),
731  grClock0);
732 
733  Double_t maxVal = -1001;
734  Double_t clockAlignmentTemp = 0;
735  for(Int_t samp=0; samp<grCorClock.at(surf)->GetN(); samp++){
736  if(TMath::Abs(grCorClock.at(surf)->GetX()[samp]) <= AnitaClock::meanPeriodNs/2){
737  if(grCorClock.at(surf)->GetY()[samp] > maxVal){
738  maxVal = grCorClock.at(surf)->GetY()[samp];
739  clockAlignmentTemp = grCorClock.at(surf)->GetX()[samp];
740  }
741  }
742  }
743  // std::cout << "Inside: " << surf << "\t" << clockAlignmentTemp << std::endl;
744  clockAlignment.at(surf) = clockAlignmentTemp;
745 
746  // not necessary but nice if printing graphs to be able to show alignment...
747  for(Int_t samp=0; samp < grClockInterps.at(surf)->GetN(); samp++){
748  grClockInterps.at(surf)->GetX()[samp] -= clockAlignment.at(surf);
749  }
750  for(Int_t samp=0; samp < grClocks.at(surf)->GetN(); samp++){
751  grClocks.at(surf)->GetX()[samp] -= clockAlignment.at(surf);
752  }
753  }
754 
755  // if(fClockProblem!=0){
756  // for(int surf=1; surf<NUM_SURF; surf++){
757  // grClockInterps.at(surf)->SetName(TString::Format("grClockInterps_%d", surf));
758  // grClockInterps.at(surf)->Write();
759 
760  // grClocks.at(surf)->SetName(TString::Format("grClocks_%d", surf));
761  // grClocks.at(surf)->Write();
762 
763  // }
764  // exit(-1);
765  // }
766 
767 #else
768  std::cerr << "FFTtools currently disabled." << std::endl;
769 #endif
770 
771  return clockAlignment;
772 }
773 
774 
775 
776 
777 
778 
779 
780 void AnitaEventCalibrator::keepOnlySomeTimeAfterClockUptick(TGraph* grClock, Double_t deltaClockKeepNs){
781  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
782 
783  if(deltaClockKeepNs > 0){ // Here 0 means don't actually do anything to the clock
784 
785  // Try only keeping things near the upgoing clock
786  // Double_t timeZeroCrossings[AnitaClock::maxNumZcs] = {0};
787  // Int_t sampZeroCrossings[AnitaClock::maxNumZcs] = {0};
788  std::vector<Double_t> timeZeroCrossings(AnitaClock::maxNumZcs, 0);
789  std::vector<Int_t> sampZeroCrossings(AnitaClock::maxNumZcs, 0);
790 
791  Int_t numZc = getTimeOfUpwardsClockTicksCrossingZero(grClock->GetN(),
792  -1,
793  grClock->GetX(),
794  grClock->GetY(),
795  timeZeroCrossings,
796  sampZeroCrossings,
797  false);
798 
799  if(fClockProblem==0){
800  Int_t thisZc = 0;
801  for(Int_t samp=0; samp<grClock->GetN(); samp++){
802 
803  if(grClock->GetX()[samp] - timeZeroCrossings[thisZc] < deltaClockKeepNs &&
804  grClock->GetX()[samp] - timeZeroCrossings[thisZc] >= 0){
805  }
806  else{
807  grClock->GetY()[samp] = 0;
808  }
809 
810  if(timeZeroCrossings[thisZc] < grClock->GetX()[samp] - deltaClockKeepNs){
811  if(thisZc < numZc-1){
812  thisZc++;
813  }
814  }
815  }
816  }
817  }
818 }
819 
820 
821 
822 
823 
824 
825 
827  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
828 
829  for(Int_t surf=0; surf<NUM_SURF; surf++){
830  Int_t lab = eventPtr->getLabChip(surf*NUM_CHAN+8);
831  Double_t oldMeanClockPeriod = clockPeriodRingBuffers.at(surf).at(lab).getMean();
832  // std::cout << surf << "\t" << lab << "\t" << oldMeanClockPeriod << std::endl;
833  Double_t tempFactor = 1;
834  if(oldMeanClockPeriod > 1e-6){ // Check we actually have a mean value
835  tempFactor = AnitaClock::meanPeriodNs/oldMeanClockPeriod;
836  }
837  tempFactors.at(surf) = tempFactor;
838  }
839 }
840 
841 
842 
843 
844 
845 
846 
847 
849  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
851 
852  if(fClockProblem==0){
853 
854  for(Int_t surf=0; surf<NUM_SURF; surf++){
855  Int_t rco = rcoVector.at(surf);
856  Int_t count = 0;
857  Double_t meanClockDt = 0;
858 
859  Double_t currentTempFactor = tempFactors.at(surf);
860  for(Int_t zc=0; zc<AnitaClock::maxNumZcs; zc++){
861  if(measuredClockPeriods.at(surf).at(rco).at(zc) > 0){
862  meanClockDt += measuredClockPeriods.at(surf).at(rco).at(zc)/currentTempFactor;
863  count++;
864  }
865  }
866 
867  meanClockDt /= count;
868  Int_t lab = eventPtr->getLabChip(surf*NUM_CHAN + 8);
869  clockPeriodRingBuffers.at(surf).at(lab).insert(meanClockDt);
870  }
871  }
872 }
873 
874 
875 
876 
877 
878 
880  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
881 
882  /*
883  This function works by unwrapping the clock channels in both RCO phases
884  and compares the upgoing clock periods to the (two) clock period(s).
885  */
886 
887  // Arrays to hold the unwrapped clock channels in both RCO phases
888  Double_t clockVolts[NUM_SURF][NUM_RCO][NUM_SAMP] = {{{0}}};
889  Double_t clockTimes[NUM_SURF][NUM_RCO][NUM_SAMP] = {{{0}}};
890  Int_t clockCapacitorNums[NUM_SURF][NUM_RCO][NUM_SAMP] = {{{0}}};
891  Int_t clockNumPoints[NUM_SURF][NUM_RCO] = {{0}};
892 
893  // Here we do the unwrapping
894  for(Int_t surf=0; surf<NUM_SURF; surf++){
895  for(Int_t rco=0; rco<NUM_RCO; rco++){
896  clockNumPoints[surf][rco] = unwrapChannel(eventPtr, surf, 8, rco, true, false,
897  clockVolts[surf][rco], clockTimes[surf][rco],
898  clockCapacitorNums[surf][rco]);
899 
900  // if(10512380==eventPtr->eventNumber){
901  // std::cout << "surf = " << surf << "\trco = " << rco << "\tnumPoints = "
902  // << clockNumPoints[surf][rco] << ":" << std::endl;
903  // for(Int_t samp=0; samp<clockNumPoints[surf][rco]; samp++){
904  // std::cout << clockVolts[surf][rco][samp] << ", ";
905  // // std::cout << clockCapacitorNums[surf][rco][samp] << ", ";
906  // }
907  // std::cout << std::endl << std::endl;
908  // for(Int_t samp=0; samp<clockNumPoints[surf][rco]; samp++){
909  // std::cout << clockTimes[surf][rco][samp] << ", ";
910  // }
911  // std::cout << std::endl << std::endl;
912  // }
913  }
914  }
915 
916  // Now we have the unwrapped clocks we need to examine their periods as measured by the SURFs.
917  // (We will use the time of the zero crossings to match them up across the SURFs later so get that too.)
918 
919  // Double_t timeZeroCrossings[NUM_SURF][NUM_RCO][AnitaClock::maxNumZcs] = {{{0}}};
920  // Int_t sampZeroCrossings[NUM_SURF][NUM_RCO][AnitaClock::maxNumZcs] = {{{0}}};
921 
922  // If you want to avoid shit like this, upgrade to ROOT v6 and start using c++11
923  std::vector<std::vector<std::vector<Double_t> > > timeZeroCrossings(NUM_SURF, std::vector<std::vector<Double_t> > (NUM_RCO, std::vector<Double_t> (AnitaClock::maxNumZcs, 0)));
924 
925  std::vector<std::vector<std::vector<Int_t> > > sampZeroCrossings(NUM_SURF, std::vector<std::vector<Int_t> > (NUM_RCO, std::vector<Int_t> (AnitaClock::maxNumZcs, 0)));
926 
927  for(Int_t surf=0; surf<NUM_SURF; surf++){
928  for(Int_t rco=0; rco<NUM_RCO; rco++){
929  for(Int_t zc=0; zc<AnitaClock::maxNumZcs; zc++){
930  measuredClockPeriods.at(surf).at(rco).at(zc) = 0;
931  }
932  }
933  }
934 
935  // std::fill(&measuredClockPeriods.at(0).at(0).at(0),
936  // &measuredClockPeriods.at(0).at(0).at(0)+sizeof(measuredClockPeriods)/sizeof(Double_t), 0);
937  // Int_t numZcs[NUM_SURF][NUM_RCO] = {{0}};
938  std::vector<std::vector<Int_t> > numZcs(NUM_SURF, std::vector<Int_t>(NUM_RCO, 0));
939 
940  for(Int_t surf=0; surf<NUM_SURF; surf++){
941  for(int rco=0; rco<NUM_RCO; rco++){
942  numZcs.at(surf).at(rco) = getTimeOfUpwardsClockTicksCrossingZero(clockNumPoints[surf][rco],
943  surf,
944  clockTimes[surf][rco],
945  clockVolts[surf][rco],
946  timeZeroCrossings.at(surf).at(rco),
947  sampZeroCrossings.at(surf).at(rco),
948  true);
949 
950  for(Int_t zc=0; zc<numZcs.at(surf).at(rco); zc++){
951  if(zc > 0){
952  measuredClockPeriods.at(surf).at(rco).at(zc-1) = (timeZeroCrossings.at(surf).at(rco).at(zc)
953  - timeZeroCrossings.at(surf).at(rco).at(zc-1));
954  }
955  }
956 
957  // if(eventPtr->eventNumber==10512383){
958  // std::cout << "Summary at start of RCO guessing " << eventPtr->eventNumber << std::endl;
959  // std::cout << "numZcs[" << surf << "][" << rco << "] = " << numZcs.at(surf).at(rco) << std::endl;
960  // for(Int_t zc=0; zc<numZcs.at(surf).at(rco); zc++){
961  // std::cout << "zc = " << zc << ", timeZc = " << timeZeroCrossings.at(surf).at(rco).at(zc) << ", sampZc = "
962  // << sampZeroCrossings.at(surf).at(rco).at(zc) << "\t" << "AnitaClock::maxNumZcs = "
963  // << AnitaClock::maxNumZcs << std::endl;
964  // }
965  // }
966  }
967  }
968 
969  // Now we have the time of (and times between) the clock upgoing zero crossings in both possible RCOs
970 
971  // Now we compare the periods implied by both RCO phase possibilities to the true clock period(s)
972  // In ANITA-3 no-one turned off the spread spectrum modulation before flight, so we compare to
973  // AnitaClock::highPeriodNs and AnitaClock::lowPeriodNs
974 
975  std::vector<std::vector<std::vector<Double_t> > > nearestClockPeriod(NUM_SURF, std::vector<std::vector<Double_t> > (NUM_RCO, std::vector<Double_t>(AnitaClock::maxNumZcs, 0)));
976 
977  std::vector<std::vector<Double_t> > differenceFromClockPeriod(NUM_SURF, std::vector<Double_t> (NUM_RCO, 0));
978 
979  // Double_t nearestClockPeriod[NUM_SURF][NUM_RCO][AnitaClock::maxNumZcs] = {{{0}}};
980  // Double_t differenceFromClockPeriod[NUM_SURF][NUM_RCO] = {{0}};
981 
982 
983  const Int_t dangerZoneStart = 170;
984  const Int_t dangerZoneEnd = 220;
985 
986  // First we use the clock period(s) to get a first pass at the RCO phase determination
987  for(Int_t surf=0; surf<NUM_SURF; surf++){
988  for(int rco=0; rco<NUM_RCO; rco++){
989  for(int zc=0; zc<numZcs.at(surf).at(rco)-1; zc++){
990 
991  // Short variable name to make the next code snippet more readable
992  Double_t dt = measuredClockPeriods.at(surf).at(rco).at(zc);
993  if(dt <= 0){
994  std::cerr << "Idiot " << __FILE__ << ": " << __LINE__ << std::endl;
995  }
996 
997  Int_t sampZc = sampZeroCrossings.at(surf).at(rco).at(zc);
998  if(sampZc < 0 || sampZc >= NUM_SAMP){
999  std::cerr << "sampZeroCrossings Array!" << __FILE__ << ": " << __LINE__ << std::endl;
1000  }
1001  Int_t capNum = clockCapacitorNums[surf][rco][sampZc];
1002  // In ANITA-3 no-one turned off the clock spread modulation... so compare to high and low periods
1003  // (We will need the nearestClockPeriods later for a second, improved period matching.)
1004 
1005  if(capNum < dangerZoneStart || capNum > dangerZoneEnd){
1006  if(TMath::Abs(dt - AnitaClock::lowPeriodNs) < TMath::Abs(dt - AnitaClock::highPeriodNs)){
1007  differenceFromClockPeriod.at(surf).at(rco) += TMath::Abs(dt - AnitaClock::lowPeriodNs);
1008  nearestClockPeriod.at(surf).at(rco).at(zc) = AnitaClock::lowPeriodNs;
1009  // std::cout << differenceFromClockPeriod.at(surf).at(rco) << "\t" << nearestClockPeriod.at(surf).at(rco).at(zc)
1010  // << std::endl;
1011  }
1012  else{
1013  differenceFromClockPeriod.at(surf).at(rco) += TMath::Abs(dt - AnitaClock::highPeriodNs);
1014  nearestClockPeriod.at(surf).at(rco).at(zc) = AnitaClock::highPeriodNs;
1015  // std::cout << differenceFromClockPeriod.at(surf).at(rco) << "\t" << nearestClockPeriod.at(surf).at(rco).at(zc)
1016  // << std::endl;
1017  }
1018  }
1019  }
1020 
1021  if(numZcs.at(surf).at(rco) > 0){
1022  differenceFromClockPeriod.at(surf).at(rco)/=numZcs.at(surf).at(rco);
1023  }
1024  else{ // If we have no zero crossings we're probably missing a clock and this won't work
1025  // std::cerr << "eventNumber " << eventPtr->eventNumber << ": Missing clock? SURF " << surf << ", RCO " << rco << ", guess 1" << std::endl;
1026  }
1027  }
1028 
1029 
1030  // May as well use firmware RCO latched value in the safe area
1031  // If the first hit bus is greater than the latch delay value defined here or the hit bus
1032  Int_t chanIndex = surf*NUM_CHAN + 8;
1033  Int_t firstHitBus = eventPtr->getFirstHitBus(chanIndex);
1034  Int_t lastHitBus = eventPtr->getLastHitBus(chanIndex);
1035  if(firstHitBus >= firstHitBusRcoLatchLimit || lastHitBus - firstHitBus > NUM_SAMP/2){
1036  rcoVector.at(surf) = eventPtr->getRcoCorrected(chanIndex);
1037  }
1038  else{
1039  // At this point we've compared the unwrapped clock periods to the closest of the
1040  // two spread modulated clock periods...
1041  // Calibration work so far indicates this is a very good guess
1042  if(differenceFromClockPeriod.at(surf).at(0) < differenceFromClockPeriod.at(surf).at(1)){
1043  rcoVector.at(surf) = 0;
1044  }
1045  else{
1046  rcoVector.at(surf) = 1;
1047  }
1048  }
1049  }
1050 
1051 
1052 
1053  // Now this is a pretty good guess, but we can do slightly better.
1054  // The clock spread modulation means is the same across all SURFs... we can use that information.
1055  // By using the time of the first upgoing zero crossings (and assuming any trigger jitter is
1056  // less than 15ns) we can match up the clock periods.
1057 
1058  // We find the offset of the clock periods relative to SURF 0.
1059 
1060  std::vector<Int_t> zeroCrossingMatchIndices;
1061  zeroCrossingMatchIndices.clear();
1062  zeroCrossingMatchIndices.assign(NUM_SURF, 0);
1063 
1064  const Double_t halfClockPeriod = 0.5*AnitaClock::meanPeriodNs;
1065  for(Int_t surf=0; surf<NUM_SURF; surf++){
1066  Int_t rco = rcoVector.at(surf);
1067 
1068  if(TMath::Abs(timeZeroCrossings.at(surf).at(rco).at(0) - timeZeroCrossings.at(0).at(rco).at(0)) < halfClockPeriod){
1069  zeroCrossingMatchIndices.at(surf) = 0; // If within half a period, there's no offset
1070  }
1071 
1072  else if(timeZeroCrossings.at(surf).at(rco).at(0) - timeZeroCrossings.at(0).at(rco).at(0) >= halfClockPeriod){
1073  // If first zero crossing in SURF[surf] is more than half a clock period later than current SURF[0]
1074  // then the timeZeroCrossing[surf][rco][0] matches up with zeroCrossing[0][rco][1]
1075  // and so the relative clock zero crossing index is -1
1076  zeroCrossingMatchIndices.at(surf) = -1;
1077  }
1078  else if(timeZeroCrossings.at(surf).at(rco).at(0) - timeZeroCrossings.at(0).at(rco).at(0) <= halfClockPeriod){
1079  // opposite of above.
1080  zeroCrossingMatchIndices.at(surf) = 1;
1081  }
1082  }
1083 
1084 
1085 
1086 
1087  // Suppose the relative SURF clock period offsets are {0, -1, 1} in a simple situation with 3 SURFs.
1088  // If we started at the sum at 0 then the third SURF would start at 1 and there would be a clock
1089  // period which didn't contribute to anything.
1090  // In that case we want the sum to start then at -1 so that the zero crossings compared will be {-1, -2, 0}
1091  // on the first loop. (Obviously we should ignore the cases when the clock indices are less than 0.)
1092  // Therefore, the start index is...
1093  Int_t startIndex = -1*TMath::MaxElement(NUM_SURF, &zeroCrossingMatchIndices[0]);
1094 
1095 
1096  // Now we need to sum over the clock indices again but with the offsets.
1097  // How many SURFs thought a period was high (AnitaClock::highPeriodNs) or low (AnitaClock::lowPeriodNs)?
1098 
1099  const Int_t maxNumOffsetZcs = AnitaClock::maxNumZcs - startIndex;
1100  std::vector<Int_t> numHigh(maxNumOffsetZcs, 0);
1101  std::vector<Int_t> numLow(maxNumOffsetZcs, 0);
1102  std::vector<Int_t> meanClockPeriod(maxNumOffsetZcs, 0);
1103  std::vector<Int_t> count(maxNumOffsetZcs, 0);
1104 
1105  Int_t alignedPeriodIndex = 0;
1106  for(Int_t zcIndex=startIndex; zcIndex < AnitaClock::maxNumZcs; zcIndex++){
1107  numHigh.at(alignedPeriodIndex)=0;
1108  numLow.at(alignedPeriodIndex)=0;
1109  for(Int_t surf=0; surf<NUM_SURF; surf++){
1110  Int_t rco = rcoVector.at(surf);
1111  Int_t zcThisSurf = zcIndex + zeroCrossingMatchIndices.at(surf);
1112  if(zcThisSurf >=0 && zcThisSurf < AnitaClock::maxNumZcs && nearestClockPeriod.at(surf).at(rco).at(zcThisSurf) > 0){
1113 
1114  meanClockPeriod.at(zcThisSurf) += measuredClockPeriods.at(surf).at(rco).at(zcThisSurf);
1115  count.at(zcThisSurf)++;
1116  // if(nearestClockPeriod.at(surf).at(rco).at(zcThisSurf)==AnitaClock::lowPeriodNs){
1117  // numLow.at(alignedPeriodIndex)++;
1118  // }
1119  // else if(nearestClockPeriod.at(surf).at(rco).at(zcThisSurf)==AnitaClock::highPeriodNs){
1120  // numHigh.at(alignedPeriodIndex)++;
1121  // }
1122  // else{
1123  // std::cerr << "How did I get here? " << __FILE__ << ": line " << __LINE__ << std::endl;
1124  // std::cerr << surf << "\t" << rco << "\t" << zcThisSurf << "\t"
1125  // << nearestClockPeriod.at(surf).at(rco).at(zcThisSurf) << std::endl;
1126  // }
1127  }
1128  }
1129 
1130  alignedPeriodIndex++;
1131  }
1132 
1133  // Now we just pick the most common answer for the clock period and compare only to that
1134  // (i.e. not to both possible (high/low) clock periods).
1135 
1136  const Int_t numAlignedPeriodIndices = alignedPeriodIndex;
1137  std::vector<Double_t> mostCommonClockPeriod;
1138  mostCommonClockPeriod.clear();
1139  mostCommonClockPeriod.assign(maxNumOffsetZcs, 0);
1140 
1141  for(Int_t alignedPeriodIndex=0; alignedPeriodIndex<numAlignedPeriodIndices; alignedPeriodIndex++){
1142 
1143  if(count.at(alignedPeriodIndex)){
1144  meanClockPeriod.at(alignedPeriodIndex)/=count.at(alignedPeriodIndex);
1145  if(TMath::Abs(meanClockPeriod.at(alignedPeriodIndex) - AnitaClock::lowPeriodNs) < TMath::Abs(meanClockPeriod.at(alignedPeriodIndex) - AnitaClock::highPeriodNs)){
1146  mostCommonClockPeriod.at(alignedPeriodIndex) = AnitaClock::lowPeriodNs;
1147  }
1148  else{
1149  mostCommonClockPeriod.at(alignedPeriodIndex) = AnitaClock::highPeriodNs;
1150  }
1151  // if the average clock period differs from 30ns by 1ns, then it has a clock problem.
1152  if(TMath::Abs(meanClockPeriod.at(alignedPeriodIndex) - 30) > 1){
1153  fClockProblem = 1;
1154  }
1155  }
1156  else{
1157  mostCommonClockPeriod.at(alignedPeriodIndex) = -1000;
1158  }
1159  // if(numLow.at(alignedPeriodIndex) > numHigh.at(alignedPeriodIndex)){
1160  // mostCommonClockPeriod.at(alignedPeriodIndex) = AnitaClock::lowPeriodNs;
1161  // }
1162  // else if(numHigh.at(alignedPeriodIndex) > numLow.at(alignedPeriodIndex)){
1163  // mostCommonClockPeriod.at(alignedPeriodIndex) = AnitaClock::highPeriodNs;
1164  // }
1165  // else{ // In the rare case that we're really not sure, let's use the mean clock period
1166  // mostCommonClockPeriod.at(alignedPeriodIndex) = AnitaClock::meanPeriodNs;
1167  // }
1168  }
1169 
1170 
1171  // Now we have our best guess at what the clock periods across all SURFs really are...
1172  // We can go through and see how far each pair of zero crossings are from the best guess across all SURFs.
1173 
1174  for(Int_t surf=0; surf<NUM_SURF; surf++){
1175  for(int rco=0; rco<NUM_RCO; rco++){
1176  Int_t alignedPeriodIndex = 0;
1177  for(int zcIndex=startIndex; zcIndex<startIndex; zcIndex++){
1178  Int_t zc = zcIndex + zeroCrossingMatchIndices.at(surf);
1179 
1180  if(zc >= 0 && zc < numZcs.at(surf).at(rco)-1 && mostCommonClockPeriod.at(alignedPeriodIndex)>0 ){
1181  // Short variable name to make the next code snippet more readable
1182  Double_t dt = measuredClockPeriods.at(surf).at(rco).at(zc);
1183 
1184  if(dt <= 0){
1185  std::cerr << "Idiot " << __FILE__ << ": " << __LINE__ << std::endl;
1186  }
1187 
1188  Int_t sampZc = sampZeroCrossings.at(surf).at(rco).at(zc);
1189  if(sampZc < 0 || sampZc >= clockNumPoints[surf][rco]){
1190  std::cerr << "sampZeroCrossings Array!" << __FILE__ << ": " << __LINE__ << std::endl;
1191  }
1192  Int_t capNum = clockCapacitorNums[surf][rco][sampZc];
1193 
1194  if(capNum < dangerZoneStart || capNum > dangerZoneEnd){
1195  differenceFromClockPeriod.at(surf).at(rco) += TMath::Abs(dt - mostCommonClockPeriod.at(alignedPeriodIndex));
1196  }
1197  }
1198  }
1199  if(numZcs.at(surf).at(rco) > 0){
1200  differenceFromClockPeriod.at(surf).at(rco)/=numZcs.at(surf).at(rco);
1201  }
1202  else{ // If we have no zero crossings we're probably missing a clock and this won't work
1203  // std::cerr << "eventNumber " << eventPtr->eventNumber << ": Missing clock? SURF " << surf << ", RCO " << rco << ", guess 2" << std::endl;
1204  }
1205  }
1206 
1207  // May as well use firmware RCO latched value in the safe area
1208  // If the first hit bus is greater than the latch delay value defined here or the hit bus
1209  Int_t chanIndex = surf*NUM_CHAN + 8;
1210  Int_t firstHitBus = eventPtr->getFirstHitBus(chanIndex);
1211  Int_t lastHitBus = eventPtr->getLastHitBus(chanIndex);
1212  if(firstHitBus >= firstHitBusRcoLatchLimit || lastHitBus - firstHitBus > NUM_SAMP/2){
1213  rcoVector.at(surf) = eventPtr->getRcoCorrected(chanIndex);
1214  }
1215  else{
1216  // At this point we've compared the unwrapped clock periods to the closest of the
1217  // two spread modulated clock periods...
1218  // Calibration work so far indicates this is a very good guess
1219  if(differenceFromClockPeriod.at(surf).at(0) < differenceFromClockPeriod.at(surf).at(1)){
1220  rcoVector.at(surf) = 0;
1221  }
1222  else{
1223  rcoVector.at(surf) = 1;
1224  }
1225  }
1226  }
1227 }
1228 
1229 
1230 
1231 
1232 
1233 Int_t AnitaEventCalibrator::getTimeOfUpwardsClockTicksCrossingZero(Int_t numPoints, Int_t surf, Double_t* times, Double_t* volts, std::vector<Double_t>& timeZeroCrossings, std::vector<Int_t>& sampZeroCrossings, bool raiseFlagIfClocksAreWeird){
1234  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
1235 
1236  std::vector<Double_t> tZcs;
1237  std::vector<Int_t> sampZcs;
1238  std::vector<Int_t> prevExtremas;
1239  std::vector<Int_t> nextExtremas;
1240 
1241  std::vector<Int_t> maximaSamps;
1242  std::vector<Int_t> minimaSamps;
1243 
1244  // See explanation below for why I find the samples of the local maxima and minima
1245  findExtremaSamples(numPoints, volts, maximaSamps, minimaSamps);
1246 
1247  Int_t numZcs = 0;
1248  for(Int_t samp=0; samp<numPoints-1; samp++){
1249  Double_t y1 = volts[samp];
1250  Double_t y2 = volts[samp+1];
1251  Double_t t1 = times[samp];
1252  Double_t t2 = times[samp+1];
1253  if(y1 <= 0 && y2 > 0){ // We have an upwards zero crossing!
1254 
1255  // Generic debug check...
1256  Double_t tzc = getTimeOfZeroCrossing(t1, y1, t2, y2);
1257  if(TMath::IsNaN(tzc)){
1258  std::cerr << "Error in " __FILE__ << ": line " << __LINE__ << std::endl;
1259  std::cerr << samp << "\t" << numPoints << "\t" << t1 << "\t"
1260  << y1 << "\t" << t2 << "\t" << y2 << std::endl;
1261  }
1262 
1263  // OK here things get a little more complicated than I would like... here's why.
1264  // There are occasionally erronious zero crossings in the clock (from crosstalk from SURF saturation?)
1265  // So to combat that I've added some extra conditions a zero crossing has to fulfill to count as
1266  // a tick.
1267  // That condition is the nearest local maxmima or minima (which ever is closer but not equal)
1268  // before and after the zero crossing sample MUST have a voltage difference above some threshold.
1269  // That threshold is defined in AnitaClock.h
1270 
1271  // At the start of this function I found the local maxima and minima...
1272  // Now I find the local maxima and minima immediately before and after the upgoing zero crossing.
1273 
1274  // First do the maxima, since we are looking for an upwards "tick" of the clock between
1275  // samp and samp+1, the current sample can't be a local maxima.
1276  Int_t nextMaxima = numPoints-1;
1277  Int_t prevMaxima = 0;
1278  for(UInt_t maxInd=0; maxInd < maximaSamps.size(); maxInd++){
1279  if(maximaSamps.at(maxInd) > samp){
1280 
1281  // So long as the next maxima isn't the sample immediately following the sample before the
1282  // minima then select the next maxima. (It could be a surf saturation cross talk!)
1283  if(maximaSamps.at(maxInd) > samp+1){
1284  nextMaxima = maximaSamps.at(maxInd);
1285  }
1286  else if(maxInd < maximaSamps.size()-1){
1287  nextMaxima = maximaSamps.at(maxInd+1);
1288  }
1289 
1290  if(maxInd > 0){
1291  // If it's not the first maxima, then the previous value can be assigned
1292  // (otherwise it stays zero).
1293  prevMaxima = maximaSamps.at(maxInd-1);
1294  }
1295  break;
1296  }
1297  }
1298 
1299  // Now we do the minima, but need to take care that we don't accidentally select the current sample
1300  // if it is indeed a minima (often the case for uninterpolated clocks)
1301  Int_t nextMinima = numPoints-1;
1302  Int_t prevMinima = 0;
1303  for(UInt_t minInd=0; minInd < minimaSamps.size(); minInd++){
1304  if(minimaSamps.at(minInd) > samp){
1305 
1306  nextMinima = minimaSamps.at(minInd);
1307 
1308  // It is possible that the value of the current sample is a local minimum
1309  // But I don't want that (downward spike from cross talk fits that condition!)
1310  if(minInd > 0 && minimaSamps.at(minInd-1) < samp){// Require the previous minima be less than samp
1311  prevMinima = minimaSamps.at(minInd-1);
1312  }
1313  else if(minInd > 1 && minimaSamps.at(minInd-2) < samp){ //If not, then use the prior one.
1314  prevMinima = minimaSamps.at(minInd-2);
1315  }
1316  // If we are very close to the start of the array then the previous minima can be 0.
1317  break;
1318  }
1319  }
1320 
1321 
1322  // Here we select the closest maxima or minima to the upwards clock tick...
1323  Int_t prevExtrema = prevMinima > prevMaxima ? prevMinima : prevMaxima;
1324  Int_t nextExtrema = nextMinima < nextMaxima ? nextMinima : nextMaxima;
1325 
1326 
1327  // std::cout << std::endl;
1328 
1329  // std::cout << "samp = " << samp << ", prevMaxima = " << prevMaxima << ", nextMaxima = " << nextMaxima
1330  // << ", prevMinima = " << prevMinima << ", nextMinima = " << nextMinima << std::endl;
1331  // std::cout << "volt = " << volts[samp] << ", prevMaxima = " << volts[prevMaxima]
1332  // << ", nextMaxima = " << volts[nextMaxima] << ", prevMinima = "
1333  // << volts[prevMinima] << ", nextMinima = " << volts[nextMinima] << std::endl;
1334  // std::cout << "nextExtrema = " << nextExtrema << " volts = " << volts[nextExtrema] << std::endl;
1335  // std::cout << "prevExtrema = " << prevExtrema << " volts = " << volts[prevExtrema] << std::endl;
1336 
1337  if(volts[nextExtrema] - volts[prevExtrema] > AnitaClock::upgoingThreshold){
1338  // Then this can count as a zero crossing.
1339 
1340  prevExtremas.push_back(prevExtrema);
1341  nextExtremas.push_back(nextExtrema);
1342 
1343  tZcs.push_back(tzc);
1344  sampZcs.push_back(samp);
1345  // std::cout << "SELECTED!" << std::endl;
1346  }
1347  // std::cout << std::endl;
1348  }
1349  }
1350 
1351  // If something has gone wrong with this whole procedure then set fClockProblem = 1.
1352  if(raiseFlagIfClocksAreWeird==true){
1353  if(tZcs.size() > (UInt_t)AnitaClock::maxNumZcs || tZcs.size() < (UInt_t)AnitaClock::minNumZcs){
1354  fClockProblem = 1;
1355  // std::cerr << "fClockProblem = " << fClockProblem << ", for surf = " << surf << std::endl;
1356  // for(UInt_t zc=0; zc<sampZcs.size(); zc++){
1357  // if(zc > 0) std::cerr << ", ";
1358  // std::cerr << "(" << sampZcs.at(zc) << ", " << volts[sampZcs.at(zc)] << ")";
1359  // if(zc==sampZcs.size()-1){
1360  // std::cerr << std::endl;
1361  // }
1362  // }
1363  }
1364  }
1365 
1366  // This guarentees we won't have any buffer overflow...
1367  // but may still have crappy zero crossings.
1368  for(Int_t zc=0; zc<AnitaClock::maxNumZcs; zc++){
1369  if(zc < (Int_t)tZcs.size()){
1370  timeZeroCrossings.at(zc) = tZcs.at(zc);
1371  sampZeroCrossings.at(zc) = sampZcs.at(zc);
1372  numZcs++;
1373  }
1374  }
1375 
1376 
1377  return numZcs;
1378 }
1379 
1380 
1381 void AnitaEventCalibrator::findExtremaSamples(Int_t length, Double_t* volts,
1382  std::vector<Int_t>& maximaSamps,
1383  std::vector<Int_t>& minimaSamps){
1384  // empty vectors
1385  maximaSamps.clear();
1386  minimaSamps.clear();
1387 
1388  for(int samp=0; samp<length; samp++){
1389  Double_t y0 = samp > 0 ? volts[samp-1] : 0;
1390  Double_t y1 = volts[samp];
1391 
1392  int posOffset = 1;
1393  Double_t y2 = samp < length-1 ? volts[samp + posOffset] : 0;
1394  while(y2==y1 && samp + posOffset < length){
1395  y2 = samp < length-1 ? volts[samp + posOffset] : 0;
1396  posOffset++;
1397  }
1398 
1399 
1400  if(y0 > y1 && y1 < y2){
1401  minimaSamps.push_back(samp);
1402  }
1403  else if(y0 < y1 && y1 > y2){
1404  maximaSamps.push_back(samp);
1405  }
1406  }
1407 }
1408 
1409 
1410 Double_t AnitaEventCalibrator::getTimeOfZeroCrossing(Double_t x1, Double_t y1, Double_t x2, Double_t y2){
1411  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
1412  // Does a linear interpolation of zero crossing between (x1,y1) and (x2, y2)
1413  Double_t m = (y1-y2)/(x1-x2);
1414  Double_t c = y1 - m*x1;
1415  return -c/m;
1416 }
1417 
1418 
1419 
1420 
1421 
1422 
1423 
1424 
1425 
1426 
1427 
1428 Int_t AnitaEventCalibrator::unwrapChannel(UsefulAnitaEvent* eventPtr, Int_t surf, Int_t chan, Int_t rco,
1429  Bool_t fApplyTempCorrection, Bool_t fAddPedestal,
1430  Double_t* mvArray,
1431  Double_t* tArray, Int_t* cArray) {
1432  // With 33 MHz clock will need to unwrap waveform to measure clock frequency and guess RCO phase.
1433  // For that reason, output array pointers are passed into function and the RCO phase to unwrap in.
1434  // The meat of this is inherited from ANITA-2 unwrapping function.
1435 
1436  // std::cout << "Just called " << __PRETTY_FUNCTION__ << std::endl;
1437 
1438  Int_t chanIndex = surf*CHANNELS_PER_SURF + chan;
1439 
1440  Int_t numExtras = 0;
1441  Int_t labChip = eventPtr->getLabChip(chanIndex);
1442  Int_t earliestSample = eventPtr->getEarliestSample(chanIndex);
1443  Int_t latestSample = eventPtr->getLatestSample(chanIndex);
1444 
1445  Double_t tempFactor = 1;
1446  if(fApplyTempCorrection==true){
1447  tempFactor = tempFactors.at(surf);
1448  }
1449 
1450  // Don't include first capacitor if it's the first sample
1451  if(earliestSample==0){
1452  earliestSample++;
1453  }
1454 
1455  // Don't include first capacitor if it's the last sample
1456  if(latestSample==0){
1457  latestSample=259;
1458  }
1459 
1460  Short_t* rawArray = eventPtr->data[chanIndex];
1461 
1462  //Now do the unwrapping
1463  Int_t index=0;
1464  Double_t time=0;
1465 
1466 
1467 
1468  if(latestSample<earliestSample) {
1469  // Then the waveform is wrapped around and we have two RCOs
1470 
1471  Int_t nextExtra=256;
1472  Double_t extraTime=0;
1473 
1474  if(earliestSample<256) {
1475  //Lets do the first segment up to the wrap around...
1476  for(Int_t samp = earliestSample;samp<256;samp++) {
1477  Int_t binRco = 1-rco;
1478  cArray[index] = samp;
1479  mvArray[index] = rawArray[samp];
1480  if(fAddPedestal==true){
1481  mvArray[index] += fPedStruct.thePeds[surf][labChip][chan][samp];
1482  }
1483  tArray[index] = time;
1484 
1485  // Need to store 255->256 differently to 255->0 in case we add data from extra capacitors
1486  if(samp == 255) {
1487  extraTime = time+(deltaTs[surf][labChip][binRco][samp])*tempFactor;
1488  }
1489  else {
1490  time += (deltaTs[surf][labChip][binRco][samp])*tempFactor;
1491  }
1492  index++;
1493  }
1494 
1495  time += epsilons[surf][labChip][rco]*tempFactor;
1496 
1497  // Ignore sample zero: add time on, but don't include value in unwrapped waveform
1498  // ***MOVED TO HERE*** (see big chunk of comments a few lines below for explanation)
1499  time += (deltaTs[surf][labChip][rco][0])*tempFactor;
1500  }
1501  else {
1502  // If first sample is inside the extra capacitors then just ignore the first couple of samples.
1503  nextExtra=260;
1504  extraTime=0;
1505  }
1506 
1507 
1508  // Chuck of explanation:
1509  // I have moved this to inside the (if earliestSample<256) statement as it led to
1510  // some waveforms starting with non-zero times when no inter-surf alignment was applied
1511  // which makes no sense at all.
1512  // Since all the deltaTs are identical across all channels (inc. the clock) in a SURF
1513  // then the non-zero start time is accounted for in the clock correction.
1514  // Moving it guarentees all channels start at t=0 (when no inter-SURF calibration is applied),
1515  // which makes it less hard to mess up calibration
1516 
1517  // Ignore sample zero: add time on, but don't include value in unwrapped waveform
1518  // time += (deltaTs[surf][labChip][rco][0])*tempFactor; // ***MOVED FROM HERE*** (see above)
1519 
1520  // Now unwrap from sample 1 to the end of the waveform
1521  for(Int_t samp=1;samp<=latestSample;samp++) {
1522  Int_t binRco = rco;
1523 
1524  if(nextExtra<260 && samp==1) {
1525 
1526  if(extraTime<time-0.22) {
1527 
1528  // Then insert the next extra capacitor
1529  binRco=1-rco;
1530  cArray[index] = nextExtra;
1531  mvArray[index] = Double_t(rawArray[nextExtra]);
1532  tArray[index] = extraTime;
1533  if(nextExtra < 259) {
1534  extraTime += (deltaTs[surf][labChip][binRco][nextExtra])*tempFactor;
1535  }
1536  nextExtra++;
1537  numExtras++;
1538  index++;
1539 
1540  // continue in loop but undo the samp variable incrementation
1541  samp--;
1542  continue;
1543  }
1544  }
1545 
1546  cArray[index] = samp;
1547  mvArray[index] = Double_t(rawArray[samp]);
1548  tArray[index] = time;
1549 
1550  if(samp<259) {
1551  time+=(deltaTs[surf][labChip][binRco][samp])*tempFactor;
1552  }
1553 
1554  index++;
1555  }
1556  }
1557  else{ // Only one rco phase, entire waveform is in order in the capacitor array
1558 
1559  time=0;
1560  for(Int_t samp=earliestSample; samp<=latestSample; samp++){
1561  Int_t binRco=rco;
1562  cArray[index] = samp;
1563  mvArray[index] = rawArray[samp];
1564  tArray[index] = time;
1565  if(samp<259) {
1566  time += (deltaTs[surf][labChip][binRco][samp])*tempFactor;
1567  }
1568  index++;
1569  }
1570  }
1571 
1572  // Here index == numPoints in unwrapped waveform
1573  return index;
1574 
1575 }
1576 
1577 
1578 void AnitaEventCalibrator::loadCalib() {
1579  char calibDir[FILENAME_MAX];
1580  char fileName[FILENAME_MAX];
1581  char *calibEnv=getenv("ANITA_CALIB_DIR");
1582  if(!calibEnv) {
1583  char *utilEnv=getenv("ANITA_UTIL_INSTALL_DIR");
1584  if(!utilEnv)
1585  sprintf(calibDir,"calib");
1586  else
1587  sprintf(calibDir,"%s/share/anitaCalib",utilEnv);
1588  }
1589  else {
1590  strncpy(calibDir,calibEnv,FILENAME_MAX);
1591  }
1592 
1593  //Set up some default numbers
1594  for(Int_t surf=0;surf<NUM_SURF;surf++) {
1595  for(Int_t chan=0;chan<NUM_CHAN;chan++) {
1596  for(Int_t chip=0;chip<NUM_CHIP;chip++) {
1597  mvCalibVals[surf][chan][chip]=1;
1598  relativeCableDelays[surf][chan][chip] = 0;
1599  }
1600  relativePhaseCenterToAmpaDelays[surf][chan] = 0;
1601  }
1602  }
1603 
1604  for(Int_t surf=0;surf<NUM_SURF;surf++) {
1605  for(Int_t chip=0;chip<NUM_CHIP;chip++) {
1606  for(Int_t rco=0;rco<NUM_RCO;rco++) {
1607  epsilons[surf][chip][rco]=1.25*(rco+1);
1608  for(Int_t samp=0;samp<NUM_SAMP;samp++)
1609  deltaTs[surf][chip][rco][samp]=1./2.6;
1610  }
1611  }
1612  }
1613 
1614 
1615 
1616 
1617  Int_t surf,chan,chip,rco,samp;
1618  Double_t calib;
1619  sprintf(fileName,"%s/%s",calibDir, voltageCalibFiles[AnitaVersion::get()]);
1620  std::ifstream CalibFile(fileName);
1621  char firstLine[180];
1622  CalibFile.getline(firstLine,179);
1623 
1624  while(CalibFile >> surf >> chan >> chip >> calib) {
1625 
1626  // std::cout << surf << "\t" << chan << "\t" << chip << "\t" << calib << std::endl;
1627  mvCalibVals[surf][chan][chip]=calib;
1628 
1629  // accounts for factor of -1 in the top ring since the seaveys are flipped
1630  Int_t ant;
1632  AnitaGeomTool::getAntPolFromSurfChan(surf,chan,ant, pol);
1633  mvCalibVals[surf][chan][chip] *= AnitaGeomTool::getAntOrientation(ant);
1634  }
1635 
1636 
1637  sprintf(fileName,"%s/justBinByBin.dat",calibDir);
1638  std::ifstream binByBinCalibFile(fileName);
1639  binByBinCalibFile.getline(firstLine,179);
1640  while(binByBinCalibFile >> surf >> chip >> rco >> samp >> calib) {
1641  deltaTs[surf][chip][rco][samp]=calib;
1642  // std::cout << "surf=" << surf << "\tchip=" << chip << "\trco=" << rco << "\tsamp=" << samp
1643  // << "\tdt=" << deltaTs[surf][chip][rco][samp] << std::endl;
1644  }
1645 
1646 
1647  sprintf(fileName,"%s/epsilonFromBenS.dat",calibDir);
1648  std::ifstream epsilonFile(fileName);
1649  epsilonFile.getline(firstLine,179);
1650  while(epsilonFile >> surf >> chip >> rco >> calib) {
1651  epsilons[surf][chip][rco]=calib;
1652  }
1653 
1654  sprintf(fileName,"%s/%s",calibDir, relativeCableDelayFiles[AnitaVersion::get()]);
1655  std::ifstream relativeCableDelayFile(fileName);
1656  relativeCableDelayFile.getline(firstLine,179);
1657  while(relativeCableDelayFile >> surf >> chan >> chip >> calib) {
1658  relativeCableDelays[surf][chan][chip]=calib;
1659  // std::cout << surf << "\t" << chan << "\t" << chip << "\t" << relativeCableDelays[surf][chan][chip] << std::endl;
1660  }
1661 
1662 
1663  sprintf(fileName,"%s/%s", calibDir, relativePhaseCenterToAmpaDelaysFiles[AnitaVersion::get()]);
1664  std::ifstream relativePhaseCenterToAmpaDelaysFile(fileName);
1665  relativePhaseCenterToAmpaDelaysFile.getline(firstLine,179);
1666  while(relativePhaseCenterToAmpaDelaysFile >> surf >> chan >> calib) {
1667  relativePhaseCenterToAmpaDelays[surf][chan]=calib;
1668  // std::cout << surf << "\t" << chan << "\t" << relativePhaseCenterToAmpaDelays[surf][chan] << std::endl;
1669  }
1670 
1671  sprintf(fileName,"%s/clockKeep.dat",calibDir);
1672  std::ifstream clockKeep(fileName);
1673  clockKeep.getline(firstLine,179);
1674  while(clockKeep >> surf >> chip >> calib) {
1675  clockKeepTime[surf][chip]=calib;
1676  }
1677 
1678  sprintf(fileName,"%s/peds.dat",calibDir);
1679  std::ifstream PedestalFile(fileName,std::ios::in | std::ios::binary);
1680  PedestalFile.read((char*)&fPedStruct,sizeof(PedestalStruct_t));
1681 
1682 
1683  sprintf(fileName,"%s/RFCalibration_BRotter.txt",calibDir);
1684  std::ifstream BRotterRfPowPeds(fileName);
1685  std::string chanName;
1686  Double_t rfYInt,ampNoise,chanGain,rfSlope;
1687  Int_t surfi,chani;
1688  BRotterRfPowPeds.getline(firstLine,179);
1689  while(BRotterRfPowPeds >> chanName >> surfi >> chani >> rfSlope >> rfYInt >> ampNoise >> chanGain) {
1690  RfPowYInt[surfi-1][chani-1]=rfYInt;
1691  RfPowSlope[surfi-1][chani-1]=rfSlope;
1692  }
1693 }
1694 
1695 
1696 Double_t AnitaEventCalibrator::convertRfPowTodBm(int surf, int chan, int adc){
1697  return (double(adc)-RfPowYInt[surf][chan])/RfPowSlope[surf][chan];
1698 }
1699 
1700 Double_t AnitaEventCalibrator::convertRfPowToKelvin(int surf, int chan, int adc){
1701  double dBm = AnitaEventCalibrator::convertRfPowTodBm(surf, chan, adc);
1702  double mW = TMath::Power(10,dBm/10.);
1703  double K = (mW/(1000.*1.38e-23*1e9));
1704  return K;
1705 }
Double_t fTempFactorGuesses[12]
A holder variable to cling on to the temperature correction factor that we are guessing at...
deltaTs, voltage, unwrap, trigger jitter, cable delay. The full monty.
Int_t numPointsArray[12]
Number of samples in each channel.
std::vector< std::vector< RingBuffer > > clockPeriodRingBuffers
Holds rolling average of temperature correction.
Inter-SURF timing (trigger jitter) without cable delay.
Int_t getRcoCorrected(int chanIndex)
Returns firmware RCO after correcting for latch delay (and factor of -1 for different definitions of ...
Pedestal utility.
Double_t clockKeepTime[12][4]
How much time after clock up-tick to keep, calib food.
All the timing of kFull, but none of the voltage calibration (Ped corrected ADC counts) ...
enum WaveCalType::EWaveCalType WaveCalType_t
The calibration enumeration type.
static AnitaEventCalibrator * Instance(int version=0)
Instance generator.
std::map< Double_t, TGraph * > grClock0s
Need to process clock 0 depending on needs of other SURF.
double fVolts[12 *9][260]
Array of unwrapped (unless kNoCalib) voltages for each channel.
static Int_t getAntPolFromSurfChan(Int_t surf, Int_t chan, Int_t &ant, AnitaPol::AnitaPol_t &pol)
Convert surf-chan to ant-pol.
Double_t epsilons[12][4][2]
Calib constants: time (ns) for write pointer to go from sample 255 -> 0 (in ANITA-2 and ANITA-3 with ...
int fNumPoints[12 *9]
Number of poins per channel.
Double_t deltaTs[12][4][2][260]
Calib constants: The time for the write pointer to travel between successove capacitors.
Double_t dtInterp
Interpolating clock for alignment step.
Useful for looping over all calibrations.
Int_t calibrateUsefulEvent(UsefulAnitaEvent *eventPtr, WaveCalType::WaveCalType_t calType)
Calibration Routine The routine that is used to calibrate the voltage time waveforms in a UsefulAnita...
TGraph * getInterpolatedGraph(const TGraph *grIn, Double_t deltaT)
Interpolation Routines that use ROOT::Math::Interpolator.
Definition: FFTtools.cxx:32
UChar_t chipIdFlag[12 *9]
chipIdFlag
Definition: RawAnitaEvent.h:47
AnitaEventCalibrator – The ANITA Event Calibrator.
std::vector< Int_t > defaultClocksToAlign
List of SURFs for getClockAlignment() (for calibration progs)
void updateTemperatureCorrection(UsefulAnitaEvent *eventPtr)
Update RingBuffer for this event.
Double_t voltsArray[12][9][260]
Channel volts in mV.
void getTempFactors(UsefulAnitaEvent *eventPtr)
Interface to RingBuffer of clock periods for temperature correction.
Int_t fClockProblem
Flag raised if more than 4 upgoing zero crossings in clock, won&#39;t update temp correction. RCO guessing may also be negatively affected by this.
Short_t data[12 *9][260]
The pedestal subtracted waveform data. Note that these arrays must be unwrapped and calibrated to bec...
Definition: RawAnitaEvent.h:67
int fCapacitorNum[12 *9][260]
Array of capacitor numbers.
std::vector< TGraph * > grClockInterps
Interpolated clocks.
Int_t getLastHitBus(Int_t chanIndex) const
Returns the lastHitbus value for the channel.
Definition: RawAnitaEvent.h:76
UsefulAnitaEvent – The Calibrated Useful Anita Event object.
For calibration: sample-to-sample dts without unwrapping (or voltage calibs)
static Int_t getAntOrientation(Int_t ant)
Some of the antennas have their orientation reversed relative to nominal. The effect of this is to sw...
The 260 samples straight from raw data.
Int_t getFirstHitBus(Int_t chanIndex) const
Returns the firstHitbus value for the channel.
Definition: RawAnitaEvent.h:73
TGraph * getCorrelationGraph(const TGraph *gr1, const TGraph *gr2, Int_t *zeroOffset=0)
Returns the correlation of two TGraphs.
Definition: FFTtools.cxx:754
void guessRco(UsefulAnitaEvent *eventPtr)
Guess RCO from clock.
Int_t getLabChip(Int_t chanIndex) const
Returns the LABRADOR number.
Definition: RawAnitaEvent.h:69
Int_t getEarliestSample(Int_t chanIndex)
Returns the earliest sample in the waveform.
Double_t relativeCableDelays[12][9][4]
From AMPA inputs to digizier delays.
Int_t unwrapChannel(UsefulAnitaEvent *eventPtr, Int_t surf, Int_t chan, Int_t rco, Bool_t fApplyTempCorrection, Bool_t fAddPedestal, Double_t *voltsArray, Double_t *timeArray, Int_t *scaArray)
Double_t nominalDeltaT
If we don&#39;t want bin-to-bin deltaTs.
Double_t relativePhaseCenterToAmpaDelays[12][9]
From phase center to AMPAs (hopefully)
For calib: opposite RCO from software algorithm.
unsigned short thePeds[12][4][9][260]
mean pedestal
Double_t timeArray[12][260]
Channel times in ns.
Int_t fRFSpike
Flag raised if the ADC value is too large or small in RF.
WaveCalType::WaveCalType_t fCalType
The calibration type requested.
The X good samples from raw data (260-hitbus)
Int_t fRcoArray[12]
An array to store the guessed at RCO values.
For calib: applies RCO from firmware (no latch delay)
Int_t fClockProblem
Flag raised if more than 4 or less than 2 upgoing zero crossings in a SURF clock. ...
Int_t scaArray[12][260]
Capacitor numbers for each sample.
Int_t fFromCalibratedAnitaEvent
Flag used in determining whether the event came from a CalibratedAnitaEvent.
For calib: 1-firmware RCO (no latch delay)
No inter-SURF timing (or zero meaning)
Double_t mvCalibVals[12][9][4]
Calib constants: converts from ADC counts to millivolts.
enum AnitaPol::EAnitaPol AnitaPol_t
Polarisation enumeration.
Faster, but no algorithm for it.
std::vector< Double_t > tempFactors
Multiplicative factor for deltaTs & epsilons accounting for temperature.
Double_t fClockPhiArray[12]
An array to store the derived clock calibration numbers (from aligning the clocks) ...
std::vector< Int_t > rcoVector
The output of AnitaEventCalibrator::guessRco() goes here.
Int_t fClockSpike
Flag raised if the ADC value is too large or small in clock.
Using mV/ADC = 1 and all dts = 1./2.6 ns.
Int_t getLatestSample(Int_t chanIndex)
Returns the latest sample in the waveform.
double fTimes[12 *9][260]
Array of unwrapped (unless kNoCalib) times for each channel.
Remove the spiky clock in early stage.