Jpp 20.0.0-27-g39925593c-D
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 } else if (this->size() == 1 ) {
125
126 // analytical solution
127
128 const double x = 1.0/ws - (*this)[0];
129
130 if (x > 0.0 || ns)
131 return { getLikelihood(x), x };
132 else
133 return { 0.0, 0.0 };
134 }
135
136 double x1 = 0.0;
137 double x2 = 0.0;
138
139 double f1 = getDerivative(0.0); // discriminator between positive and negative signal
140 double f2 = 0.0;
141
142 if (f1 == 0.0) {
143
144 return { 0.0, 0.0 };
145
146 } else if (f1 > 0.0) { // positive signal
147
148 x1 = 0.0; // lower limit corresponds to no signal
149 x2 = (double) this->size() / ws; // upper limit corresponds to no background (i.e. all N/S = 0)
150
151 f2 = getDerivative(x2);
152
153 } else if (ns) { // negative signal
154
155 x2 = 0.0; // upper limit corresponds to no signal
156 x1 = -(*this)[0]; // lower limit corresponds to largest negated N/S ratio
157
158 for (const double i : static_cast<const std::vector<double>&>(*this)) {
159 if (-i > x1) {
160 x1 = -i;
161 }
162 }
163
164 x1 += EPSILON; // offset
165
166 f2 = f1;
167 f1 = getDerivative(x1);
168
169 } else {
170
171 return { 0.0, 0.0 };
172 }
173
174 // Ridder's method
175
176 while (x2 - x1 > EPSILON) {
177
178 const double xm = 0.5 * (x1 + x2);
179 const double fm = getDerivative(xm);
180
181 const double s = sqrt(fm*fm - f1*f2);
182
183 if (s == 0.0) {
184 break;
185 }
186
187 const double xn = xm + (xm - x1) * fm/s;
188 const double fn = getDerivative(xn);
189
190 if (fn == 0.0) {
191 return { getLikelihood(xn), xn };
192 }
193
194 if (signbit(fn) != signbit(fm)) {
195
196 x1 = xm;
197 f1 = fm;
198 x2 = xn;
199 f2 = fn;
200
201 } else {
202
203 if (signbit(fn)) {
204
205 x2 = xn;
206 f2 = fn;
207
208 } else {
209
210 x1 = xn;
211 f1 = fn;
212 }
213 }
214 }
215
216 const double x = 0.5 * (x1 + x2);
217
218 return { getLikelihood(x), x };
219 }
220
221
222 /**
223 * Get test statistic for given signal strength.
224 * See formula 16 in this <a href="https://link.springer.com/article/10.1140/epjc/s10052-011-1554-0">reference</a>.
225 *
226 * \param ps signal strength
227 * \return test statistic
228 */
229 inline double getTestStatisticForUpperLimit(const double ps) const
230 {
231 const fit_type result = (*this)(true);
232
233 if (result.signal <= 0.0)
234 return 0.0 - this->getLikelihood(ps);
235 else if (result.signal <= ps)
236 return result.likelihood - this->getLikelihood(ps);
237 else
238 return 0.0;
239 }
240
241
242 /**
243 * Get total signal strength.
244 *
245 * \return signal strength
246 */
247 double getSignal() const
248 {
249 return ws;
250 }
251
252
253 /**
254 * Set signal strength.
255 *
256 * \param wS signal strength
257 */
258 void setSignal(const double wS)
259 {
260 ws = wS;
261 }
262
263
264 /**
265 * Add signal strength.
266 *
267 * \param wS signal strength
268 */
269 void addSignal(const double wS)
270 {
271 ws += wS;
272 }
273
274 protected:
275
276 double ws = 0.0; //!< total signal strength
277 };
278}
279
280#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:269
double getSignal() const
Get total signal strength.
Definition JAspera.hh:247
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:258
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:229
double ws
total signal strength
Definition JAspera.hh:276
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