QualityCut.cxx
1 #include "QualityCut.h"
2 #include "UsefulAnitaEvent.h"
3 
12 int quickFixMC(int n, const double* x){
13  // quick hack to fix this version of Linda's MC
14  double lastX = -DBL_MAX;
15  int firstBadPoint = n;
16  for(int i=0; i < n; i++){
17  double thisX = x[i];
18  if(thisX < lastX){
19  firstBadPoint = i;
20  break;
21  }
22  lastX = thisX;
23  }
24  return firstBadPoint;
25 }
26 
27 
28 ClassImp(Acclaim::QualityCut);
30 ClassImp(Acclaim::PayloadBlastCut);
31 ClassImp(Acclaim::NumPointsCut);
32 
33 
46 
48  ssc.apply(usefulEvent, sum);
49 
50  PayloadBlastCut stbc;
51  stbc.apply(usefulEvent, sum);
52 
53  NumPointsCut npc;
54  npc.apply(usefulEvent, sum);
55 
56  Bool_t isGood = (ssc.eventPassesCut && stbc.eventPassesCut && npc.eventPassesCut);
57  if(sum){
58  sum->flags.isGood = isGood;
59  }
60  return isGood;
61 }
62 
63 
64 
73 Bool_t Acclaim::QualityCut::passedAll(const AnitaEventSummary* sum, bool describe){
74 
75  Bool_t isGood = sum->flags.isGood;
76  if(describe){
77  const char* p = "passed";
78  const char* f = "failed";
79  std::cout << "Event Summary run " << sum->run << " eventNumber " << sum->eventNumber << " failed a quality cut: " << std::endl;
80  std::cout << "SURF Saturation cut = " << (sum->flags.isVarner ? f : p) << ", ";
81  std::cout << "Payload Blast cut = " << (sum->flags.isPayloadBlast ? f : p) << ", ";
82  std::cout << "Num points cut = " << (sum->flags.isVarner2 ? f : p) << std::endl;
83  }
84  return isGood;
85 }
86 
87 
94  maxLimit = 2000;
95  minLimit = -2000;
96  asymLimit = 500;
97 
98  maxVolts = 0;
99  maxVoltsAnt = -1;
100  maxVoltsPol = AnitaPol::kNotAPol;
101 
102  minVolts = 0;
103  minVoltsAnt = -1;
104  minVoltsPol = AnitaPol::kNotAPol;
105 
106  asymVolts = 0;
107  asymVoltsAnt = -1;
108  asymVoltsPol = AnitaPol::kNotAPol;
109 
110  eventPassesCut = true;
111  description = "Surf saturation cut, looks for max volts / min volts and the asymmetry between them";
112 }
113 
114 
115 
126 
127  maxVolts = 0;
128  minVolts = 0;
129  for(int pol=0; pol <AnitaPol::kNotAPol; pol++){
130  for(int ant=0; ant < NUM_SEAVEYS; ant++){
131  const int chanIndex = AnitaGeomTool::getChanIndexFromAntPol(ant, (AnitaPol::AnitaPol_t) pol);
132  const double* volts = useful->fVolts[chanIndex];
133  const int n = useful->fNumPoints[chanIndex] == NUM_SAMP ? quickFixMC(NUM_SAMP, useful->fTimes[chanIndex]) : useful->fNumPoints[chanIndex];
134 
135  double maxThisChan = TMath::MaxElement(n, volts);
136  double minThisChan = TMath::MinElement(n, volts);
137 
138  if(maxThisChan > maxVolts){
139  maxVolts = maxThisChan;
140  maxVoltsAnt = ant;
141  maxVoltsPol = (AnitaPol::AnitaPol_t) pol;
142  }
143  if(minThisChan < minVolts){
144  minVolts = minThisChan;
145  minVoltsAnt = ant;
146  minVoltsPol = (AnitaPol::AnitaPol_t) pol;
147  }
148 
149  double asymThisChan = TMath::Abs(maxVolts + minVolts);
150  if(asymThisChan > asymVolts){
151  asymVolts = asymThisChan;
152  asymVoltsAnt = ant;
153  asymVoltsPol = (AnitaPol::AnitaPol_t) pol;
154  }
155  }
156  }
157 
158  if(maxVolts > maxLimit || minVolts < minLimit || asymVolts > asymLimit){
159  eventPassesCut = false;
160  // std::cerr << "failed!:" << std::endl;
161  // std::cerr << "\t" << maxVolts << "\t" << maxVoltsAnt << "\t" << maxVoltsPol << std::endl;
162  // std::cerr << "\t" << minVolts << "\t" << minVoltsAnt << "\t" << minVoltsPol << std::endl;
163  // std::cerr << "\t" << asymVolts << "\t" << asymVoltsAnt << "\t" << asymVoltsPol << std::endl;
164  }
165  else{
166  eventPassesCut = true;
167  }
168 
169  if(sum!=NULL){
170  if(eventPassesCut){
171  sum->flags.isVarner = 0;
172  }
173  else{
174  sum->flags.isVarner = 1;
175  }
176  }
177 }
178 
179 
180 
181 
182 
183 
184 
185 
186 
187 
188 
195  ratioCutHigh = 2.8;
196  ratioCutLow = -1; // no longer used
197  maxRatio = 0;
198  maxRatioPhi = -1;
199  maxRatioPol = AnitaPol::kNotAPol;
200  eventPassesCut = true;
201  description = "Removes events with where the peak-to-peak in the top ring is significantly lower than the bottom ring channel with the largest peak-to-peak.";
202 }
203 
204 
205 
206 
207 
208 
218 
219  int anitaVersion = AnitaVersion::get();
220 
221 
222  if(sum){
223  sum->flags.nSectorsWhereBottomExceedsTop = 0;
224 
225  for(int polInd=0; polInd < AnitaPol::kNotAPol; polInd++){
226  sum->flags.maxBottomToTopRatio[polInd] = -9999;
227  sum->flags.maxBottomToTopRatioSector[polInd] = -1;
228  sum->flags.minBottomToTopRatio[polInd] = 9999;
229  sum->flags.minBottomToTopRatioSector[polInd] = -1;
230  }
231  }
232 
233  for(int pol=0; pol < AnitaPol::kNotAPol; pol++){
234 
235  Double_t peakToPeaks[AnitaRing::kNotARing][NUM_PHI];
236  Double_t maxPeakToPeak = 0;
237  Int_t maxAnt = -1;
238 
239  for(int phi=0; phi < NUM_PHI; phi++){
240 
241  // skip ALFA channels/ALFA cross talk
242  if(anitaVersion==3 && pol==AnitaPol::kVertical && phi==7){
243  continue;
244  }
245  if(anitaVersion==3 && pol==AnitaPol::kHorizontal && phi==4){
246  continue;
247  }
248 
249  for(int ring=AnitaRing::kTopRing; ring < AnitaRing::kNotARing; ring++){
250  int ant = phi + NUM_PHI*ring;
251  TGraph* gr = useful->getGraph(ant, (AnitaPol::AnitaPol_t) pol);
252 
253  // quick hack to fix this version of Linda's MC
254  const int n = gr->GetN() == NUM_SAMP ? quickFixMC(gr->GetN(), gr->GetX()) : gr->GetN();
255  while(gr->GetN() > n) gr->RemovePoint(gr->GetN()-1);
256 
257  Double_t maxY, maxX, minY, minX;
258  RootTools::getLocalMaxToMin((const TGraph*)gr, maxY, maxX, minY, minX);
259 
260  delete gr;
261 
262  Double_t p2p = maxY - minY;
263 
264  peakToPeaks[ring][phi] = p2p;
265 
266  if(ring > 0 && p2p > maxPeakToPeak){
267  maxPeakToPeak = p2p;
268  maxAnt = ant;
269 
270  if(sum && ring==AnitaRing::kBottomRing && peakToPeaks[ring][phi] > peakToPeaks[0][phi]){
271  sum->flags.nSectorsWhereBottomExceedsTop++;
272  }
273  }
274  }
275  }
276 
277  int ant = (maxAnt%NUM_PHI);
278  Double_t p2pTop = 0;
279  if(ant > -1){
280  p2pTop = peakToPeaks[ant/NUM_PHI][ant % NUM_PHI];
281  }
282 
283  Double_t ratio = p2pTop > 0 ? maxPeakToPeak/p2pTop : -1; // shouldn't be possible, but avoid division by 0
284 
285  if(sum){
286  sum->flags.maxBottomToTopRatio[pol] = ratio;
287  sum->flags.maxBottomToTopRatioSector[pol] = maxAnt;
288  sum->flags.minBottomToTopRatio[pol] = maxPeakToPeak;
289  }
290 
291  if(ratio > ratioCutHigh || ratio < ratioCutLow){
292  eventPassesCut = false;
293  }
294  else{
295  eventPassesCut = true;
296  }
297  if(sum!=NULL){
298  if(eventPassesCut){
299  sum->flags.isPayloadBlast = 0;
300  }
301  else{
302  sum->flags.isPayloadBlast = 1;
303  }
304  }
305  }
306 }
307 
308 
309 
310 
311 
312 
319  // This wasn't chosen particularly carefully
320  // I just want to stop core dumps with old root when there aren't enough points for interpolation
321  // which is < 5 points, so this is more than sufficient.
322  numPointsCutLow = 200;
323  description = "Checks there are a reasonable number of points in each waveform.";
324 }
325 
326 
327 
328 
329 
340  eventPassesCut = true;
341 
342  // yet another hacky fix for MC here, as 2017Aug MC runs < 100, fail the numPoints cut, as it's not set properly
343  // @todo remove this in the future when this is fixed in the MC...
344  if(sum->mc.weight==0){
345 
346  for(int chanIndex=0; chanIndex < NUM_CHAN*NUM_SURF; chanIndex++){
347  const int numPoints = useful->fNumPoints[chanIndex];
348  if(numPoints < numPointsCutLow){
349  eventPassesCut = false;
350  break;
351  }
352  }
353  }
354 
355  if(sum){
356  if(!eventPassesCut){
357  // silly old flag name
358  sum->flags.isVarner2 = 1;
359  }
360  else{
361  sum->flags.isVarner2 = 0;
362  }
363  }
364 }
virtual void apply(const UsefulAnitaEvent *useful, AnitaEventSummary *sum=NULL)
Definition: QualityCut.cxx:217
static Bool_t applyAll(const UsefulAnitaEvent *usefulEvent, AnitaEventSummary *sum=NULL)
Applies all the event quality cuts in succession, this should be the primary interface.
Definition: QualityCut.cxx:45
Tries to find unphysical spikes in a waveform that are characteristic of a kind of digitiser corrupti...
Definition: QualityCut.h:59
double fVolts[12 *9][260]
Array of unwrapped (unless kNoCalib) voltages for each channel.
static Int_t getChanIndexFromAntPol(Int_t ant, AnitaPol::AnitaPol_t pol)
Convert ant-pol to logical index.
int fNumPoints[12 *9]
Number of poins per channel.
virtual void apply(const UsefulAnitaEvent *useful, AnitaEventSummary *sum=NULL)
Applies the SurfSaturation cut.
Definition: QualityCut.cxx:125
virtual void apply(const UsefulAnitaEvent *useful, AnitaEventSummary *sum=NULL)
Apply the number of points cut.
Definition: QualityCut.cxx:339
USeful in for loops.
Base class from which all my quality cuts inherit.
Definition: QualityCut.h:34
TGraph * getGraph(int chanIndex) const
Returns a voltage-time waveform for given channel index.
UsefulAnitaEvent – The Calibrated Useful Anita Event object.
Tries to determine whether an event is a payload blast.
Definition: QualityCut.h:98
Removes events which have short waveforms.
Definition: QualityCut.h:126
Vertical Polarisation.
Useful in for loops.
static Bool_t passedAll(const AnitaEventSummary *sum, bool describe=false)
Reads the flags set in AnitaEventSummary, returns true if the event passed all quality cuts...
Definition: QualityCut.cxx:73
Common analysis format between UCorrelator and Acclaim.
Horizontal Polarisation.
NumPointsCut()
Constructor for the number of points cut, contains some hard coded numbers.
Definition: QualityCut.cxx:318
enum AnitaPol::EAnitaPol AnitaPol_t
Polarisation enumeration.
SurfSaturationCut()
Constructor for the SurfSaturation cut, sets some hard coded default values.
Definition: QualityCut.cxx:93
double fTimes[12 *9][260]
Array of unwrapped (unless kNoCalib) times for each channel.