Jpp 20.0.0-rc.7
the software that should make you happy
Loading...
Searching...
No Matches
JAspera.hh
Go to the documentation of this file.
1#ifndef __JASTRONOMY__JASPERA__
2#define __JASTRONOMY__JASPERA__
3
4#include <vector>
5#include <cmath>
6
7
8/**
9 * \file
10 *
11 * Per aspera ad astra.
12 * \author mdejong
13 */
14namespace JASTRONOMY {}
15namespace JPP { using namespace JASTRONOMY; }
16
17namespace JASTRONOMY {
18
19 /**
20 * Auxiliary data structure to fit signal strength using likelihood ratio.
21 */
22 struct JAspera :
23 public std::vector<double> // N/S values
24 {
25
26 static constexpr double EPSILON = 1.0e-3; //!< precision determination of signal strength
27
28
29 /**
30 * Result of fit.
31 */
32 struct fit_type {
33 double likelihood = 0.0; //!< likelihood
34 double signal = 0.0; //!< signal strength
35 };
36
37
38 /**
39 * Put signal and background to list of pre-computed N/S values.
40 *
41 * \param s signal
42 * \param b background
43 */
44 void put(const double s,
45 const double b)
46 {
47 push_back(b/s);
48
49 ws += s;
50 }
51
52
53 /**
54 * Put signal and background to list of pre-computed N/S values.
55 *
56 * \param n data
57 * \param s signal
58 * \param b background
59 */
60 void put(const size_t n,
61 const double s,
62 const double b)
63 {
64 for (size_t i = 0; i != n; ++i) {
65 push_back(b/s);
66 }
67
68 ws += s;
69 }
70
71
72 /**
73 * Get likelihood for given signal strength.
74 *
75 * \param p signal strength
76 * \return likelihood
77 */
78 double getLikelihood(const double p) const
79 {
80 double y = -p * ws;
81
82 for (const double i : static_cast<const std::vector<double>&>(*this)) {
83 y += log1p(p/i);
84 }
85
86 return y;
87 }
88
89
90 /**
91 * Get derivative of likelihood for given signal strength.
92 *
93 * \param p signal strength
94 * \return derivative of likelihood
95 */
96 double getDerivative(const double p) const
97 {
98 double y = -ws;
99
100 for (const double i : static_cast<const std::vector<double>&>(*this)) {
101 y += 1.0 / (p + i);
102 }
103
104 return y;
105 }
106
107
108 /**
109 * Fit signal strength.
110 *
111 * \param ns allow for negative signal
112 * \return result
113 */
114 fit_type operator()(const bool ns = false) const
115 {
116 using namespace std;
117
118 if (this->empty()) {
119
120 // nothing to be done
121
122 return { 0.0, 0.0 };
123 }
124
125 double x1 = 0.0;
126 double x2 = 0.0;
127
128 double f1 = getDerivative(0.0); // discriminator between positive and negative signal
129 double f2 = 0.0;
130
131 if (f1 == 0.0) {
132
133 return { 0.0, 0.0 };
134
135 } else if (f1 > 0.0) { // positive signal
136
137 x1 = 0.0; // lower limit corresponds to no signal
138 x2 = (double) this->size() / ws; // upper limit corresponds to no background (i.e. all N/S = 0)
139
140 f2 = getDerivative(x2);
141
142 } else if (ns) { // negative signal
143
144 x2 = 0.0; // upper limit corresponds to no signal
145 x1 = -(*this)[0]; // lower limit corresponds to largest negated N/S ratio
146
147 for (const double i : static_cast<const std::vector<double>&>(*this)) {
148 if (-i > x1) {
149 x1 = -i;
150 }
151 }
152
153 x1 += EPSILON; // offset
154
155 f2 = f1;
156 f1 = getDerivative(x1);
157
158 } else {
159
160 return { 0.0, 0.0 };
161 }
162
163 // Ridder's method
164
165 while (x2 - x1 > EPSILON) {
166
167 const double xm = 0.5 * (x1 + x2);
168 const double fm = getDerivative(xm);
169
170 const double s = sqrt(fm*fm - f1*f2);
171
172 if (s == 0.0) {
173 break;
174 }
175
176 const double xn = xm + (xm - x1) * fm/s;
177 const double fn = getDerivative(xn);
178
179 if (fn == 0.0) {
180 return { getLikelihood(xn), xn };
181 }
182
183 if (signbit(fn) != signbit(fm)) {
184
185 x1 = xm;
186 f1 = fm;
187 x2 = xn;
188 f2 = fn;
189
190 } else {
191
192 if (signbit(fn)) {
193
194 x2 = xn;
195 f2 = fn;
196
197 } else {
198
199 x1 = xn;
200 f1 = fn;
201 }
202 }
203 }
204
205 const double x = 0.5 * (x1 + x2);
206
207 return { getLikelihood(x), x };
208 }
209
210
211 /**
212 * Get test statistic for given signal strength.
213 * See formula 16 in this <a href="https://link.springer.com/article/10.1140/epjc/s10052-011-1554-0">reference</a>.
214 *
215 * \param ps signal strength
216 * \return test statistic
217 */
218 inline double getTestStatisticForUpperLimit(const double ps) const
219 {
220 const fit_type result = (*this)(true);
221
222 if (result.signal <= 0.0)
223 return 0.0 - this->getLikelihood(ps);
224 else if (result.signal <= ps)
225 return result.likelihood - this->getLikelihood(ps);
226 else
227 return 0.0;
228 }
229
230
231 /**
232 * Get total signal strength.
233 *
234 * \return signal strength
235 */
236 double getSignal() const
237 {
238 return ws;
239 }
240
241
242 /**
243 * Set signal strength.
244 *
245 * \param wS signal strength
246 */
247 void setSignal(const double wS)
248 {
249 ws = wS;
250 }
251
252
253 /**
254 * Add signal strength.
255 *
256 * \param wS signal strength
257 */
258 void addSignal(const double wS)
259 {
260 ws += wS;
261 }
262
263 protected:
264
265 double ws = 0.0; //!< total signal strength
266 };
267}
268
269#endif
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
double signal
signal strength
Definition JAspera.hh:34
double likelihood
likelihood
Definition JAspera.hh:33
Auxiliary data structure to fit signal strength using likelihood ratio.
Definition JAspera.hh:24
void addSignal(const double wS)
Add signal strength.
Definition JAspera.hh:258
double getSignal() const
Get total signal strength.
Definition JAspera.hh:236
double getLikelihood(const double p) const
Get likelihood for given signal strength.
Definition JAspera.hh:78
void setSignal(const double wS)
Set signal strength.
Definition JAspera.hh:247
void put(const double s, const double b)
Put signal and background to list of pre-computed N/S values.
Definition JAspera.hh:44
double getTestStatisticForUpperLimit(const double ps) const
Get test statistic for given signal strength.
Definition JAspera.hh:218
double ws
total signal strength
Definition JAspera.hh:265
static constexpr double EPSILON
precision determination of signal strength
Definition JAspera.hh:26
double getDerivative(const double p) const
Get derivative of likelihood for given signal strength.
Definition JAspera.hh:96
fit_type operator()(const bool ns=false) const
Fit signal strength.
Definition JAspera.hh:114
void put(const size_t n, const double s, const double b)
Put signal and background to list of pre-computed N/S values.
Definition JAspera.hh:60