1 #include "FourierBuffer.h" 3 #include "FFTWComplex.h" 5 #include "RayleighHist.h" 7 #include "FilteredAnitaEvent.h" 8 #include "TVirtualPad.h" 11 #include "RawAnitaHeader.h" 12 #include "RootTools.h" 14 #include "AnitaDataset.h" 15 #include "FilterStrategy.h" 16 #include "ProgressBar.h" 17 #include "QualityCut.h" 18 #include "AcclaimFilters.h" 20 #include "AcclaimFilters.h" 21 #define IS_ROOT_6 (ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)) 22 #define IS_ROOT_6_06_08 (ROOT_VERSION_CODE >= ROOT_VERSION(6,6,8)) 33 doneVectorInit(false), fCurrentlyLoadingHistory(false), fForceLoadHistory(false), eventsInBuffer(0), fMinFitFreq(
Filters::
Bands::anitaHighPassGHz), fMaxFitFreq(
Filters::
Bands::anitaLowPassGHz), fNumSkipped(0){
35 bufferSize = theBufferSize <= 0 ? 1000 : theBufferSize;
40 const char* rayleighFuncText =
"([0]*x/([1]*[1]))*exp(-x*x/(2*[1]*[1]))";
41 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
42 summaryPads[ant] = NULL;
47 fRay =
new TF1(
"fRay", rayleighFuncText, 0, 1e4, TF1::EAddToList::kNo);
49 fRay =
new TF1(
"fRay", rayleighFuncText, 0, 1e4);
61 std::vector<TGraphFB>* gr,
62 int n,
double df,
double defaultVal){
67 gr[pol].reserve(NUM_SEAVEYS);
70 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
72 vec[pol][ant].resize(n, defaultVal);
76 gr[pol].push_back(
TGraphFB(
this, ant, pol, n));
77 for(
int freqBin=0; freqBin < n; freqBin++){
78 double f = df*freqBin;
79 gr[pol][ant].GetX()[freqBin] = f;
80 gr[pol][ant].GetY()[freqBin] = defaultVal;
98 initGraphAndVector(spectrumAmplitudes, grSpectrumAmplitudes, n, df, 0);
99 initGraphAndVector(chiSquares, grChiSquares, n, df, 0);
100 initGraphAndVector(chiSquaresRelativeToSpectrum, grChiSquaresRelativeToSpectrum, n, df, 0);
101 initGraphAndVector(NULL, grReducedChiSquares, n, df, 0);
102 initGraphAndVector(NULL, grReducedChiSquaresRelativeToSpectrum, n, df, 0);
103 initGraphAndVector(probs, grProbs, n, df, 0);
104 initGraphAndVector(fitAmplitudes, grAmplitudes, n, df, 0);
105 initGraphAndVector(sumPowers, NULL, n, df, 0);
106 initGraphAndVector(lastAmps, grLastAmps, n, df, 0);
107 initGraphAndVector(NULL, grNDFs, n, df, 0);
108 initGraphAndVector(chanChiSquares, NULL, n, df, 0);
113 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
114 ndfs[pol][ant].resize(n, 0);
116 hRays[pol][ant].resize(n, NULL);
117 for(
int freqBin=0; freqBin < n; freqBin++){
118 double f = df*1e3*freqBin;
119 TString name = TString::Format(
"hRayleigh_%d_%d_%d", ant, pol, freqBin);
121 int phiName = (ant%NUM_PHI)+1;
122 int ring = ant / NUM_PHI;
123 const char* ringChar = ring == 0 ?
"T" : ring == 1 ?
"M" :
"B";
124 TString title = TString::Format(
"Distribution of amplitudes %d%s%s %4.1lf MHz", phiName, ringChar, polChar, f);
125 title +=
";Amplitude (mV/MHz?); Events per bin";
127 hRays[pol][ant].at(freqBin)->SetDirectory(0);
128 hRays[pol][ant].at(freqBin)->freqMHz = df*1e3*freqBin;
136 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
141 std::vector<Acclaim::TGraphFB*> grAmpVec;
142 grAmpVec.push_back(&grLastAmps[pol][ant]);
143 grAmpVec.push_back(&grAmplitudes[pol][ant]);
144 grAmpVec.push_back(&grSpectrumAmplitudes[pol][ant]);
145 Acclaim::TGraphFB::setDrawingDependencies(grAmpVec);
147 std::vector<Acclaim::TGraphFB*> grChiSqVec;
148 grChiSqVec.push_back(&grReducedChiSquares[pol][ant]);
149 grChiSqVec.push_back(&grReducedChiSquaresRelativeToSpectrum[pol][ant]);
151 Acclaim::TGraphFB::setDrawingDependencies(grChiSqVec);
155 doneVectorInit =
true;
173 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
175 for(
unsigned i=0; i < hRays[pol][ant].size(); i++){
176 if(hRays[pol][ant].at(i)){
177 delete hRays[pol][ant].at(i);
178 hRays[pol][ant].at(i) = NULL;
184 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
185 if(summaryPads[ant]){
186 delete summaryPads[ant];
187 summaryPads[ant] = NULL;
217 df = grPower->GetX()[1] - grPower->GetX()[0];
218 initVectors(grPower->GetN(), df);
228 return eventNumbers.size();
237 if(!fForceLoadHistory){
238 return eventNumbers.size();
243 if(!fCurrentlyLoadingHistory && fForceLoadHistory){
244 automagicallyLoadHistory(fEv);
245 fForceLoadHistory =
false;
250 runs.push_back(header->
run);
252 bool anyUpdated =
false;
256 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
262 if(grPower->GetN() != (int)sumPowers[pol][ant].size()){
263 std::cerr <<
"Warning in " << __PRETTY_FUNCTION__ <<
", unexpected waveform size" << std::endl;
268 powerRingBuffers[pol][ant].push_back(std::vector<double>(0));
269 std::vector<double>& freqVec = powerRingBuffers[pol][ant].back();
270 freqVec.assign(grPower->GetY(), grPower->GetY()+grPower->GetN());
276 const double cosminPowerConversionFactor = 25000*grPower->GetN();
278 for(
int freqInd=0; freqInd < grPower->GetN(); freqInd++){
279 sumPowers[pol][ant].at(freqInd) += grPower->GetY()[freqInd];
280 double f = df*freqInd;
281 if(f >= fMinFitFreq && f < fMaxFitFreq){
283 double amp = TMath::Sqrt(grPower->GetY()[freqInd]*cosminPowerConversionFactor);
285 bool updated = hRays[pol][ant].at(freqInd)->add(amp);
286 grLastAmps[pol][ant].GetY()[freqInd] = amp;
287 lastAmps[pol][ant][freqInd] = amp;
291 hRays[pol][ant].at(freqInd)->getRayleighFitParams(fitAmplitudes[pol][ant][freqInd],
292 chiSquares[pol][ant][freqInd],
293 ndfs[pol][ant][freqInd]);
295 grChiSquares[pol][ant].GetY()[freqInd] = chiSquares[pol][ant][freqInd];
296 if(ndfs[pol][ant][freqInd] > 0){
298 grReducedChiSquares[pol][ant].GetY()[freqInd] = chiSquares[pol][ant][freqInd]/ndfs[pol][ant][freqInd];
300 grNDFs[pol][ant].GetY()[freqInd] = ndfs[pol][ant][freqInd];
301 grAmplitudes[pol][ant].GetY()[freqInd] = fitAmplitudes[pol][ant][freqInd];
305 if(spectrumAmplitudes[pol][ant][freqInd] > 0){
306 distAmp = spectrumAmplitudes[pol][ant][freqInd];
307 chiSquaresRelativeToSpectrum[pol][ant].at(freqInd) = hRays[pol][ant].at(freqInd)->getRayleighChiSquare(&spectrumAmplitudes[pol][ant][freqInd]);
311 distAmp = hRays[pol][ant].at(freqInd)->getAmplitude();
312 chiSquaresRelativeToSpectrum[pol][ant].at(freqInd) = chiSquares[pol][ant][freqInd];
314 grChiSquaresRelativeToSpectrum[pol][ant].GetY()[freqInd] = chiSquaresRelativeToSpectrum[pol][ant].at(freqInd);
316 if(ndfs[pol][ant][freqInd] > 0){
317 grReducedChiSquaresRelativeToSpectrum[pol][ant].GetY()[freqInd] = chiSquaresRelativeToSpectrum[pol][ant].at(freqInd)/ndfs[pol][ant][freqInd];
326 double prob = hRays[pol][ant].at(freqInd)->getOneMinusCDF(amp, distAmp);
328 double probVal = probVal = prob > 0 ? TMath::Log10(prob) : 0;
334 probs[pol][ant].at(freqInd) = probVal;
335 grProbs[pol][ant].GetY()[freqInd] = probVal;
339 double sumChanChiSquares = 0;
341 double sumSquaredChanChiSquares = 0;
342 for(
int freqInd=0; freqInd < grPower->GetN(); freqInd++){
343 double amp = lastAmps[pol][ant][freqInd];
345 double realAmp = fitAmplitudes[pol][ant][freqInd];
346 chanChiSquares[pol][ant][freqInd] = (amp*amp)/(realAmp*realAmp);
347 sumChanChiSquares += chanChiSquares[pol][ant][freqInd];
348 sumSquaredChanChiSquares += chanChiSquares[pol][ant][freqInd]*chanChiSquares[pol][ant][freqInd];
358 meanChanChiSquare[pol][ant] = sumChanChiSquares/n;
359 varChanChiSquare[pol][ant] = sumSquaredChanChiSquares/n - meanChanChiSquare[pol][ant]*meanChanChiSquare[pol][ant];
362 meanChanChiSquare[pol][ant] = 0;
363 varChanChiSquare[pol][ant] = 0;
381 int firstSpecInd = 0;
385 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
387 int lastSpecInd = int((isAlfaBandpassed(ant,pol) ? Filters::Bands::alfaLowPassGHz : fMaxFitFreq)/df);
388 int nf = fitAmplitudes[pol][ant].size();
392 for(
int freqInd = 0; freqInd < nf; freqInd++){
393 spectrumAmplitudes[pol][ant][freqInd] = fitAmplitudes[pol][ant][freqInd];
397 getBackgroundSpectrum(&spectrumAmplitudes[pol][ant][firstSpecInd],
398 lastSpecInd - firstSpecInd);
401 for(
int freqInd = 0; freqInd < nf; freqInd++){
402 grSpectrumAmplitudes[pol][ant].GetY()[freqInd] = spectrumAmplitudes[pol][ant][freqInd];
420 return eventNumbers.size();
445 TString hName = TString::Format(
"hChanChiSquare_%d_%d", pol, ant);
446 TH1D* h =
new TH1D(hName, hName, 8, 0, 24);
448 for(
unsigned freqInd=0; freqInd < sumPowers[pol][ant].size(); freqInd++){
449 h->Fill(chanChiSquares[pol][ant][freqInd]);
474 while((
int)eventNumbers.size() > bufferSize){
475 eventNumbers.pop_front();
480 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
481 std::vector<double>& removeThisPower = powerRingBuffers[pol][ant].front();
482 for(
unsigned int freqInd=0; freqInd < removeThisPower.size(); freqInd++){
483 sumPowers[pol][ant].at(freqInd) -= removeThisPower.at(freqInd);
485 powerRingBuffers[pol][ant].pop_front();
502 fCurrentlyLoadingHistory =
true;
503 bool loadedHistory =
false;
505 const int safetyMargin = 200;
506 const int numEventsToLoopOver = bufferSize + safetyMargin;
530 bool needToAddManually =
false;
532 std::cerr <<
"Info in " << __PRETTY_FUNCTION__ <<
": Loading history for FourierBuffer, will loop over the last " << bufferSize <<
" events plus a few." << std::endl;
535 while(!loadedHistory){
537 std::vector<AnitaDataset*> ds;
538 std::vector<Int_t> firstEntries;
539 std::vector<Int_t> lastEntries;
540 Long64_t eventsInQueue = 0;
542 while(eventsInQueue < numEventsToLoopOver){
553 UInt_t maxPossEventNumber = run == thisRun ? eventNumber : lastEventThisRun;
555 Int_t potentialEvents = maxPossEventNumber - firstEventThisRun;
557 Int_t eventsThisRun = potentialEvents > numEventsToLoopOver ? numEventsToLoopOver : potentialEvents;
559 firstEntries.push_back(potentialEvents - eventsThisRun);
560 lastEntries.push_back(potentialEvents);
561 eventsInQueue += lastEntries.back() - firstEntries.back();
568 Long64_t eventsDone = 0;
570 for(
int i = (
int)ds.size() - 1; i >= 0; i--){
574 for(
int entry = firstEntries.at(i); entry < lastEntries.at(i); entry++){
584 if(needToAddManually){
589 p.
inc(eventsDone, eventsInQueue);
596 if(eventNumbers.size() != (unsigned) bufferSize){
597 std::cerr << std::endl;
598 std::cerr <<
"Warning in " << __PRETTY_FUNCTION__ <<
", tried to load history, but only got " 599 << eventNumbers.size() <<
" events when I have a buffer size " << bufferSize << std::endl;
602 loadedHistory =
true;
604 fCurrentlyLoadingHistory =
false;
612 TGraphFB* gr = getAvePowSpec(ant, pol, lastNEvents);
623 int nEvents = eventNumbers.size();
625 TGraphFB* gr =
new TGraphFB(
this, ant, pol, sumPowers[pol][ant].size());
628 TString name = TString::Format(
"grAvePowSpec_%d_%s_%u_%u", ant, polName, eventNumbers.front(), eventNumbers.back());
629 TString title = TString::Format(
"Average Power Spectrum %d %s event %u - %u", ant, polName, eventNumbers.front(), eventNumbers.back());
630 gr->SetNameTitle(name, title);
633 for(
unsigned freqInd=0; freqInd < sumPowers[pol][ant].size(); freqInd++){
634 gr->SetPoint(freqInd, freqInd*df, sumPowers[pol][ant].at(freqInd)/nEvents);
648 return &grChiSquares[pol][ant];
649 case ReducedChisquare:
651 return &grReducedChiSquaresRelativeToSpectrum[pol][ant];
653 return &grNDFs[pol][ant];
654 case RayleighAmplitude:
656 return &grLastAmps[pol][ant];
658 return &grProbs[pol][ant];
665 TGraphFB* gr = getBackground(ant, pol, lastNEvents);
672 TGraphFB* gr = getAvePowSpec(ant, pol, lastNEvents);
674 getBackgroundSpectrum(gr->GetY(), gr->GetN());
681 void Acclaim::FourierBuffer::getBackgroundSpectrum(
double* y,
int n)
const{
684 fSpectrum =
new TSpectrum();
690 std::vector<float> tempFloats(n, 0);
691 for(
int i=0; i < n; i++){
692 tempFloats[i] = y[i];
694 float* tempPtr = &tempFloats[0];
697 const int numIter = 4;
698 fSpectrum->Background(tempPtr,n,
699 numIter,TSpectrum::kBackDecreasingWindow,
700 TSpectrum::kBackOrder4,kFALSE,
701 TSpectrum::kBackSmoothing3,kFALSE);
704 for(
int i=0; i < n; i++){
705 y[i] = tempFloats[i];
715 void Acclaim::FourierBuffer::drawSummary(TPad* pad, SummaryOption_t summaryOpt)
const{
717 if(summaryOpt == None){
724 Double_t yMax = -DBL_MAX;
725 Double_t yMin = DBL_MAX;
728 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
730 if(isAlfaBandpassed(ant, pol)){
735 const TGraphFB* gr = getSelectedGraphForSummary(summaryOpt, ant, pol);
738 for(
int i=0; i < gr->GetN(); i++){
739 double x = gr->GetX()[i];
740 if(x > fMinSpecFreq && x < fMaxFitFreq){
741 if(gr->GetY()[i] > yMax){
742 yMax = gr->GetY()[i];
744 if(gr->GetY()[i] < yMin){
745 yMin = gr->GetY()[i];
754 for(
int ant=0; ant < NUM_SEAVEYS; ant++){
756 if(!summaryPads[ant]){
757 int ring = ant/NUM_PHI;
758 int phi = ant % NUM_PHI;
763 int yBin = (2*ring + phi%2);
765 summaryPads[ant] = RootTools::makeSubPad(pad,
double(xBin)/8,
double(5 - yBin)/6,
766 double(xBin+1)/8,
double(6 - yBin)/6,
767 TString::Format(
"FourierBuffer%d", ant));
768 summaryPads[ant]->SetRightMargin(0);
769 summaryPads[ant]->SetLeftMargin(0.1 * (xBin == 0));
770 summaryPads[ant]->SetTopMargin(0.1 * (yBin == 0));
771 summaryPads[ant]->SetBottomMargin(0.1 * (yBin == 5));
774 summaryPads[ant]->SetBit(kCanDelete);
775 summaryPads[ant]->InvertBit(kCanDelete);
780 summaryPads[ant]->AppendPad();
785 summaryPads[ant]->Clear();
787 summaryPads[ant]->cd();
789 if(summaryOpt == FourierBuffer::ReducedChisquare){
793 hV->SetBit(kCanDelete);
794 hH->SetBit(kCanDelete);
795 hH->SetLineColor(kBlue);
796 hV->SetLineColor(kBlack);
808 summaryPads[ant]->cd();
810 if(summaryOpt == FourierBuffer::Prob){
818 TGraphFB* gr = getSelectedGraphForSummary(summaryOpt, ant, pol);
819 gr->SetEditable(kFALSE);
823 gr->SetLineColor(lineCol);
824 gr->SetMaximum(yMax);
825 gr->SetMinimum(yMin);
829 for(
unsigned i=0; i < gr->fDerivatives.size(); i++){
830 TGraphFB* gr2 = gr->fDerivatives[i];
832 gr2->SetLineColor(gr->GetLineColor());
833 gr2->SetLineStyle(i+1);
851 void Acclaim::TGraphFB::drawCopy()
const{
855 fDerivedFrom->drawCopy();
858 int logx = gPad->GetLogx();
859 int logy = gPad->GetLogy();
860 int logz = gPad->GetLogz();
862 TCanvas* c1 =
new TCanvas();
868 TGraphFB* gr2 =
new TGraphFB(
this);
869 gr2->SetBit(kCanDelete);
870 gr2->fDoubleClickOption = kDrawRayleigh;
871 gr2->SetTitle(TString::Format(
""));
874 for(
unsigned i=0; i < fDerivatives.size(); i++){
875 TGraphFB* grD =
new TGraphFB(fDerivatives.at(i));
876 grD->SetBit(kCanDelete);
877 grD->fDoubleClickOption = kDrawRayleigh;
878 grD->SetTitle(TString::Format(
""));
887 void Acclaim::TGraphFB::ExecuteEvent(
int event,
int x,
int y){
889 if(event == kButton1Double){
890 if(fDoubleClickOption==kDrawRayleigh){
891 drawRayleighHistNearMouse(x, y);
893 else if(fDoubleClickOption==kDrawCopy){
897 TGraphAligned::ExecuteEvent(event, x, y);
901 void Acclaim::TGraphFB::drawRayleighHistNearMouse(
int x,
int y)
const{
903 int logx = gPad->GetLogx();
904 int logy = gPad->GetLogy();
905 int selectedPoint = -1;
907 for(
int i=0; i < GetN(); i++){
908 double xVal = logx ? TMath::Log10(GetX()[i]) : GetX()[i];
909 double yVal = logy ? TMath::Log10(GetY()[i]) : GetY()[i];
910 Int_t pixelX = gPad->XtoAbsPixel(xVal);
911 Int_t pixelY = gPad->YtoAbsPixel(yVal);
916 const int closeDist = 4;
917 if(TMath::Abs(pixelX - x) < closeDist && TMath::Abs(pixelY - y) < closeDist){
918 double d2 = (pixelX - x)*(pixelX - x) + (pixelY - y)*(pixelY - y);
928 double df = GetX()[1] - GetX()[0];
930 if(selectedPoint > -1 && df > 0){
931 TCanvas* c1 =
new TCanvas();
935 RayleighHist* h = (RayleighHist*) fb->getRayleighDistribution(ant, pol, selectedPoint);
936 h->SetLineColor(GetLineColor());
946 void Acclaim::TGraphFB::setDrawingDependencies(
const std::vector<TGraphFB*> grs){
948 for(
unsigned i=1; i < grs.size(); i++){
949 grs[0]->fDerivatives.push_back(grs[i]);
950 grs[i]->fDerivedFrom = grs[0];
void initGraphAndVector(std::vector< double > vec[][NUM_SEAVEYS], std::vector< TGraphFB > *gr, int n, double df, double defaultVal)
Initialise an internal vector and TGraphFB with with an appropriate set of default values...
Hard coded frequencies in GHz which can get used in any given filter.
static Bool_t applyAll(const UsefulAnitaEvent *usefulEvent, AnitaEventSummary *sum=NULL)
Applies all the event quality cuts in succession, this should be the primary interface.
const FilterStrategy * getStrategy() const
void automagicallyLoadHistory(const FilteredAnitaEvent *fEv)
Function which loops through old events so that the FourierBuffer is filled.
const UsefulAnitaEvent * getUsefulAnitaEvent() const
int getEntry(int entryNumber)
A little class for some GUI magic (for MagicDisplay)
A filter strategy defines the sets of filters that are used and provides some introspection abilities...
void inc(Long64_t &entry, Long64_t numEntries=-1)
New primary function to move through main for loop in analysis program.
size_t add(const FilteredAnitaEvent *fEv)
Adds an event to the FourierBuffer.
Contains all my filter classes, some of which have less than obvious names.
virtual UsefulAnitaEvent * useful(bool force_reload=false)
Prints a progress bar and timer to stderr.
virtual ~FourierBuffer()
Destructor.
Int_t removeOld()
Remove data from the dequeues while their size is greater than the buffer size.
void initVectors(int n, double df)
Initialise all internal vectors.
FourierBuffer(Int_t theBufferSize=1000)
Constructor for FourierBuffer.
Adu5Pat * gps(bool force_reload=false)
const AnalysisWaveform * getFilteredGraph(UInt_t i) const
virtual RawAnitaHeader * header(bool force_reload=false)
This class is intended to store all the necessary data about an ANITA event for filtering and analysi...
TH1D * makeChanChisquareHist(AnitaPol::AnitaPol_t pol, Int_t ant, TPad *pad, const char *drawOpt) const
Histogram the event frequency bin amplitudes squared, divided by the rayleigh distribution amplitude ...
enum AnitaPol::EAnitaPol AnitaPol_t
Polarisation enumeration.
const RawAnitaHeader * getHeader() const