Diana Software
QTimingAnalyzer.cc
Go to the documentation of this file.
1 /*
2  * Author: Adam Bryant (adam_bryant@berkeley.edu)
3  *
4  * Class: QTimingAnalyzer
5  *
6  */
7 
8 #include "QTimingAnalyzer.hh"
9 #include <algorithm>
10 #include <cmath>
11 #include <gsl/gsl_cdf.h>
12 
13 using std::fabs;
14 using std::lower_bound;
15 using std::max_element;
16 using std::min;
17 using std::min_element;
18 using std::pow;
19 using std::vector;
20 
22  : fNeedsSort(true), fPeriod(1.0), fTolerance(1.0)
23 {
24 }
25 
27 {
28 }
29 
30 void QTimingAnalyzer::ComputeGoodnessThreshold(const double falseRate)
31 {
32  // event rate
33  double rate = 0;
34 
35  // maximum time
36  double maximum = 0;
37 
38  if (fValues.size() != 0) {
39  maximum = *( max_element(fValues.begin(), fValues.end()) );
40 
41  if (maximum > 0) {
42  rate = fValues.size() / maximum;
43  }
44  }
45 
46  // probability of event within +/- tolerance
47  double p = 1.0 - exp(-rate * (2.0 * fTolerance));
48 
49  // number of trials
50  unsigned int n
51  = fPeriod > 0
52  ? (unsigned int) (maximum / fPeriod)
53  : 0;
54 
55  unsigned int k = 0;
56  while( 1.0 - pow(gsl_cdf_binomial_P(k, p, n), 1.0 + fAdjustments.size())
57  > falseRate ) {
58  ++k;
59  }
60 
62 }
63 
65  double& closestValue)
66 {
67  double distance = 0;
68 
69  // vector should be sorted ascending
70  if (fNeedsSort) {
71  sort(fValues.begin(), fValues.end());
72  fNeedsSort = false;
73  }
74 
75  // Perform binary search for nearest elements
76  vector<double>::const_iterator position
77  = lower_bound(fValues.begin(), fValues.end(), value);
78  // returns an iterator to the first position in which 'value' can be
79  // inserted while preserving the ordering
80 
81  if (position == fValues.begin()) {
82  distance = fValues.front() - value;
83  closestValue = fValues.front();
84  }
85  else if (position == fValues.end()) {
86  distance = value - fValues.back();
87  closestValue = fValues.back();
88  }
89  else {
90  double distanceBelow = value - *(position - 1);
91  double distanceAbove = *position - value;
92  distance = min(distanceBelow, distanceAbove);
93  if (distanceBelow < distanceAbove) {
94  closestValue = *(position - 1);
95  }
96  else {
97  closestValue = *position;
98  }
99  }
100 
101  return distance;
102 }
103 
104 void QTimingAnalyzer::FindPeriod(const double uncertainty,
105  const double stepSize)
106 {
107  const double oldPeriod = fPeriod;
108  double bestPeriod = oldPeriod;
109 
110  unsigned int bestTotalGoodness = GetTotalGoodness();
111 
112  int steps = 1;
113  while ( fabs(steps * stepSize) < uncertainty ) {
114 
115  fPeriod = oldPeriod + steps * stepSize;
116  unsigned int totalGoodness = GetTotalGoodness();
117 
118  if (totalGoodness > bestTotalGoodness) {
119  bestTotalGoodness = totalGoodness;
120  bestPeriod = fPeriod;
121  }
122 
123  steps *= -1;
124  if (steps >= 0) {
125  ++steps;
126  }
127  }
128 
129  fPeriod = bestPeriod;
130 }
131 
133 {
134  unsigned int bestGoodness = 0;
135 
136  for (vector<double>::const_iterator valueIter = fValues.begin();
137  valueIter != fValues.end();
138  ++valueIter) {
139 
140  unsigned int goodness = GetGoodnessParameter(*valueIter);
141 
142  if (goodness > bestGoodness) {
143  bestGoodness = goodness;
144  }
145 
146  }
147 
148  return bestGoodness;
149 }
150 
151 unsigned int QTimingAnalyzer::GetGoodness(const double value)
152 {
153  unsigned int goodness = GetGoodnessParameter(value);
154 
155  for (vector<double>::const_iterator adjustmentIter = fAdjustments.begin();
156  adjustmentIter != fAdjustments.end();
157  ++adjustmentIter) {
158 
159  double adjustedValue = value + *adjustmentIter;
160  unsigned int goodnessWithAdjustment
161  = GetGoodnessParameter(adjustedValue);
162 
163  if (goodnessWithAdjustment > goodness) {
164  goodness = goodnessWithAdjustment;
165  }
166 
167  }
168 
169  return goodness;
170 }
171 
172 unsigned int QTimingAnalyzer::GetGoodnessParameter(const double value)
173 {
174  // Initialize the goodness parameter
175  unsigned int goodness = 0;
176 
177  if (fValues.size() != 0) {
178 
179  double maximum = *( max_element(fValues.begin(), fValues.end()) );
180  double minimum = *( min_element(fValues.begin(), fValues.end()) );
181 
182  double closestVal = 0;
183 
184  for (double val = value;
185  val < maximum + fTolerance;
186  val += fPeriod) {
187  double distance = DistanceToClosestElement(val, closestVal);
188  if (distance < fTolerance) {
189  ++goodness;
190  }
191  }
192 
193  // also step backwards in time so can start with any point in vector
194  for (double val = value - fPeriod;
195  val > minimum - fTolerance;
196  val -= fPeriod) {
197  double distance = DistanceToClosestElement(val, closestVal);
198  if (distance < fTolerance) {
199  ++goodness;
200  }
201  }
202 
203  }
204 
205  return goodness;
206 }
207 
209 {
210  unsigned int totalGoodness = 0;
211 
212  for (vector<double>::const_iterator valueIter = fValues.begin();
213  valueIter != fValues.end();
214  ++valueIter) {
215 
216  totalGoodness += GetGoodnessParameter(*valueIter);
217 
218  }
219 
220  return totalGoodness;
221 }
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
double min(const Diana::QVector &v)
Definition: QVector.cc:878
Diana::QVector exp(const Diana::QVector &v)
Definition: QVector.cc:833
std::vector< double > fValues
Time values.
double fPeriod
Period for repetition of values.
double DistanceToClosestElement(const double value, double &closestValue)
Computes distance from 'value' to closest element in fValues.
unsigned int GetGoodness(const double value)
Get goodness for a given time, using adjustments.
unsigned int fGoodnessThreshold
Goodness threshold at a certain false positive rate.
double fTolerance
Size of window in which to look for event.
QTimingAnalyzer()
Constructor.
unsigned int GetBestGoodness()
Get best goodness parameter for the values in fValues.
void ComputeGoodnessThreshold(const double falseRate)
Compute goodness threshold at given false positive rate.
unsigned int GetTotalGoodness()
Get total goodness for the values in fValues.
virtual ~QTimingAnalyzer()
Destructor.
void FindPeriod(const double uncertainty, const double stepSize=0.008)
Find period by searching within 'uncertainty' of fPeriod.
bool fNeedsSort
Whether or not vector could be out of order.
std::vector< double > fAdjustments
Adjustments.
unsigned int GetGoodnessParameter(const double value)
Get goodness for a given time value, no adjustments.