1
|
#include <iostream>
|
2
|
#include <cmath>
|
3
|
#include "TRolke.h"
|
4
|
#include <utilities/Statistics.hh>
|
5
|
#include <utilities/debugging.hh>
|
6
|
#include "SpectrumStats.hh"
|
7
|
|
8
|
using std::endl;
|
9
|
|
10
|
namespace Flux {
|
11
|
|
12
|
SpectrumStats::SpectrumStats()
|
13
|
: nOn(0),
|
14
|
nOff(0),
|
15
|
exposureOn(0),
|
16
|
exposureOff(0),
|
17
|
trueAreaTimeOn(0),
|
18
|
trueAreaTimeOff(0),
|
19
|
recoAreaTimeOn(0),
|
20
|
recoAreaTimeOff(0),
|
21
|
liveTime(0),
|
22
|
offLiveTime(0),
|
23
|
invRecoAreaOn(0),
|
24
|
invRecoAreaOff(0),
|
25
|
fPrintPrefix("\t")
|
26
|
{}
|
27
|
|
28
|
void SpectrumStats::Clear()
|
29
|
{
|
30
|
nOn = 0;
|
31
|
nOff = 0;
|
32
|
exposureOn = 0;
|
33
|
exposureOff = 0;
|
34
|
trueAreaTimeOn = 0;
|
35
|
trueAreaTimeOff = 0;
|
36
|
recoAreaTimeOn = 0;
|
37
|
recoAreaTimeOff = 0;
|
38
|
liveTime = 0;
|
39
|
offLiveTime = 0;
|
40
|
invRecoAreaOn = 0;
|
41
|
invRecoAreaOff = 0;
|
42
|
}
|
43
|
|
44
|
double SpectrumStats::GetField(std::string field) const
|
45
|
{
|
46
|
if(field=="nOn") return nOn;
|
47
|
else if(field=="exposureOn") return exposureOn;
|
48
|
else if(field=="nOff") return nOff;
|
49
|
else if(field=="exposureOff") return exposureOff;
|
50
|
else if(field=="trueAreaTimeOn") return trueAreaTimeOn;
|
51
|
else if(field=="trueAreaTimeOff") return trueAreaTimeOff;
|
52
|
else if(field=="recoAreaTimeOn") return recoAreaTimeOn;
|
53
|
else if(field=="recoAreaTimeOff") return recoAreaTimeOff;
|
54
|
else if(field=="liveTime") return liveTime;
|
55
|
else if(field=="offLiveTime") return offLiveTime;
|
56
|
else if(field=="invRecoAreaOn") return invRecoAreaOn;
|
57
|
else if(field=="invRecoAreaOff") return invRecoAreaOff;
|
58
|
else if(field=="Alpha") return Alpha();
|
59
|
else if(field=="Significance") return Significance();
|
60
|
else if(field=="Excess") return Excess();
|
61
|
else if(field=="ExcessError") return ExcessError();
|
62
|
else if(field=="ExcessErrorUp") return ExcessErrorUp();
|
63
|
else if(field=="ExcessErrorDown") return ExcessErrorDown();
|
64
|
else if(field=="FracError") return FracError();
|
65
|
else if(field=="FracErrorUp") return FracErrorUp();
|
66
|
else if(field=="FracErrorDown") return FracErrorDown();
|
67
|
else if(field=="Background") return Background();
|
68
|
else{
|
69
|
WARN_OUT << "Unknown field string = " << field << endl;
|
70
|
return 0;
|
71
|
}
|
72
|
}
|
73
|
|
74
|
void SpectrumStats::SetField(std::string field, double value)
|
75
|
{
|
76
|
if(field=="nOn") nOn = value;
|
77
|
else if(field=="exposureOn") exposureOn = value;
|
78
|
else if(field=="nOff") nOff = value;
|
79
|
else if(field=="exposureOff") exposureOff = value;
|
80
|
else if(field=="trueAreaTimeOn") trueAreaTimeOn = value;
|
81
|
else if(field=="trueAreaTimeOff") trueAreaTimeOff = value;
|
82
|
else if(field=="recoAreaTimeOn") recoAreaTimeOn = value;
|
83
|
else if(field=="recoAreaTimeOff") recoAreaTimeOff = value;
|
84
|
else if(field=="liveTime") liveTime = value;
|
85
|
else if(field=="offLiveTime") offLiveTime = value;
|
86
|
else if(field=="invRecoAreaOn") invRecoAreaOn = value;
|
87
|
else if(field=="invRecoAreaOff") invRecoAreaOff = value;
|
88
|
else{
|
89
|
WARN_OUT << "Unknown field string = " << field << endl;
|
90
|
return;
|
91
|
}
|
92
|
}
|
93
|
|
94
|
|
95
|
bool SpectrumStats::Compare(const SpectrumStats& rhs) const
|
96
|
{
|
97
|
if(nOn != rhs.nOn) return false;
|
98
|
if(exposureOn != rhs.exposureOn) return false;
|
99
|
if(nOff != rhs.nOff) return false;
|
100
|
if(exposureOff != rhs.exposureOff) return false;
|
101
|
if(trueAreaTimeOn != rhs.trueAreaTimeOn) return false;
|
102
|
if(trueAreaTimeOff != rhs.trueAreaTimeOff) return false;
|
103
|
if(recoAreaTimeOn != rhs.recoAreaTimeOn) return false;
|
104
|
if(recoAreaTimeOff != rhs.recoAreaTimeOff) return false;
|
105
|
if(offLiveTime != rhs.offLiveTime) return false;
|
106
|
if(invRecoAreaOn != rhs.invRecoAreaOn) return false;
|
107
|
if(invRecoAreaOff != rhs.invRecoAreaOff) return false;
|
108
|
return true;
|
109
|
}
|
110
|
|
111
|
bool SpectrumStats::operator==(const SpectrumStats& rhs) const
|
112
|
{
|
113
|
return Compare(rhs);
|
114
|
}
|
115
|
|
116
|
bool SpectrumStats::operator!=(const SpectrumStats& rhs) const
|
117
|
{
|
118
|
return !Compare(rhs);
|
119
|
}
|
120
|
|
121
|
|
122
|
void SpectrumStats::Add(const SpectrumStats& rhs)
|
123
|
{
|
124
|
nOn += rhs.nOn;
|
125
|
nOff += rhs.nOff;
|
126
|
exposureOn += rhs.exposureOn;
|
127
|
exposureOff += rhs.exposureOff;
|
128
|
|
129
|
trueAreaTimeOn += rhs.trueAreaTimeOn;
|
130
|
trueAreaTimeOff += rhs.trueAreaTimeOff;
|
131
|
|
132
|
recoAreaTimeOn += rhs.recoAreaTimeOn;
|
133
|
recoAreaTimeOff += rhs.recoAreaTimeOff;
|
134
|
|
135
|
liveTime += rhs.liveTime;
|
136
|
offLiveTime += rhs.offLiveTime;
|
137
|
invRecoAreaOn += rhs.invRecoAreaOn;
|
138
|
invRecoAreaOff += rhs.invRecoAreaOff;
|
139
|
}
|
140
|
|
141
|
|
142
|
SpectrumStats& SpectrumStats::operator+=(const SpectrumStats& rhs)
|
143
|
{
|
144
|
Add(rhs);
|
145
|
return *this;
|
146
|
}
|
147
|
|
148
|
|
149
|
|
150
|
|
151
|
SpectrumStats SpectrumStats::operator+(const SpectrumStats& rhs) const
|
152
|
{
|
153
|
SpectrumStats newstats;
|
154
|
newstats += *this;
|
155
|
newstats += rhs;
|
156
|
return newstats;
|
157
|
}
|
158
|
|
159
|
|
160
|
|
161
|
|
162
|
double SpectrumStats::Alpha() const
|
163
|
{
|
164
|
return Utilities::Statistics::Alpha(exposureOn,exposureOff);
|
165
|
}
|
166
|
|
167
|
double SpectrumStats::AlphaUnchecked() const
|
168
|
{
|
169
|
if (exposureOff>1e-10)
|
170
|
return exposureOn/exposureOff;
|
171
|
else
|
172
|
return 0;
|
173
|
}
|
174
|
|
175
|
|
176
|
|
177
|
|
178
|
double SpectrumStats::Significance() const
|
179
|
{
|
180
|
double alpha = Alpha();
|
181
|
return Utilities::Statistics::Significance(nOn, nOff, alpha);
|
182
|
}
|
183
|
|
184
|
|
185
|
|
186
|
|
187
|
double SpectrumStats::SignificanceUnchecked() const {
|
188
|
double signif=0;
|
189
|
try {
|
190
|
signif = Significance();
|
191
|
}
|
192
|
catch (Utilities::Statistics::InvalidResult &res) {
|
193
|
signif = 0;
|
194
|
}
|
195
|
return signif;
|
196
|
}
|
197
|
|
198
|
|
199
|
|
200
|
|
201
|
double SpectrumStats::Excess() const
|
202
|
{
|
203
|
double excess=0;
|
204
|
try {
|
205
|
excess = (double)nOn - Alpha()*(double)nOff;
|
206
|
}
|
207
|
catch( Utilities::Statistics::InvalidResult &res ){
|
208
|
|
209
|
}
|
210
|
return excess;
|
211
|
}
|
212
|
|
213
|
|
214
|
|
215
|
|
216
|
|
217
|
|
218
|
|
219
|
double SpectrumStats::ExcessError() const
|
220
|
{
|
221
|
double error_up
|
222
|
= Utilities::Statistics::LiMa_dExcess_Up(nOn,nOff,Alpha(),1.);
|
223
|
double error_down
|
224
|
= Utilities::Statistics::LiMa_dExcess_Down(nOn,nOff,Alpha(),1.);
|
225
|
return (error_down + error_up) / 2;
|
226
|
}
|
227
|
|
228
|
|
229
|
|
230
|
|
231
|
double SpectrumStats::ExcessErrorUp() const
|
232
|
{
|
233
|
double excesserrorup
|
234
|
= Utilities::Statistics::LiMa_dExcess_Up(nOn,nOff,Alpha(),1.);
|
235
|
if (nOff < 1e-10)
|
236
|
excesserrorup = Utilities::Statistics::ErrorUp(nOn);
|
237
|
return fabs(excesserrorup);
|
238
|
}
|
239
|
|
240
|
|
241
|
|
242
|
|
243
|
double SpectrumStats::ExcessErrorDown() const
|
244
|
{
|
245
|
double excesserrordown
|
246
|
= Utilities::Statistics::LiMa_dExcess_Down(nOn,nOff,Alpha(),1.);
|
247
|
if (nOff < 1e-10)
|
248
|
excesserrordown = Utilities::Statistics::ErrorDown(nOn);
|
249
|
return fabs(excesserrordown);
|
250
|
}
|
251
|
|
252
|
|
253
|
|
254
|
|
255
|
double SpectrumStats::FracErrorUp() const
|
256
|
{
|
257
|
return fabs(ExcessErrorUp() / Excess());
|
258
|
}
|
259
|
|
260
|
|
261
|
|
262
|
|
263
|
double SpectrumStats::FracErrorDown() const
|
264
|
{
|
265
|
return fabs(ExcessErrorDown() / Excess());
|
266
|
}
|
267
|
|
268
|
|
269
|
|
270
|
|
271
|
double SpectrumStats::FracError() const
|
272
|
{
|
273
|
return fabs(ExcessError() / Excess());
|
274
|
}
|
275
|
|
276
|
|
277
|
|
278
|
|
279
|
double SpectrumStats::ExcessSensitivity(double significance) const {
|
280
|
if( significance <= 0.0 ) return 0;
|
281
|
double result = 0;
|
282
|
try {
|
283
|
result = Utilities::Statistics::LiMa_requiredExcess(significance, nOff,
|
284
|
AlphaUnchecked());
|
285
|
} catch (Utilities::Statistics::InvalidResult error) {
|
286
|
std::cerr << error.what() << std::endl;
|
287
|
result = 0;
|
288
|
}
|
289
|
return result;
|
290
|
}
|
291
|
|
292
|
|
293
|
|
294
|
|
295
|
|
296
|
void SpectrumStats::ExcessLimits(double& excess_down, double& excess_up,
|
297
|
double cl) const
|
298
|
{
|
299
|
|
300
|
|
301
|
|
302
|
|
303
|
TRolke* rolke = new TRolke(cl / 100);
|
304
|
rolke->SetBounding(true);
|
305
|
rolke->SetPoissonBkgKnownEff(nOn, nOff, 1 / Alpha(), 1);
|
306
|
rolke->GetLimits(excess_down, excess_up);
|
307
|
delete rolke;
|
308
|
}
|
309
|
|
310
|
|
311
|
|
312
|
|
313
|
|
314
|
void SpectrumStats::ZeroExcessLimits(double& excess_down, double& excess_up,
|
315
|
double cl) const
|
316
|
{
|
317
|
|
318
|
|
319
|
|
320
|
|
321
|
TRolke* rolke = new TRolke(cl / 100);
|
322
|
rolke->SetBounding(true);
|
323
|
rolke->SetPoissonBkgKnownEff(Background(), nOff, 1 / Alpha(), 1);
|
324
|
rolke->GetLimits(excess_down, excess_up);
|
325
|
delete rolke;
|
326
|
}
|
327
|
|
328
|
double SpectrumStats::Background() const
|
329
|
{
|
330
|
return AlphaUnchecked() * nOff;
|
331
|
}
|
332
|
|
333
|
void SpectrumStats::print(std::ostream& os) const
|
334
|
{
|
335
|
try {
|
336
|
os << Form("%sN_on = %d",
|
337
|
fPrintPrefix.c_str(), nOn) << endl;
|
338
|
os << Form("%sN_off = %d",
|
339
|
fPrintPrefix.c_str(), nOff) << endl;
|
340
|
os << Form("%sExposure_on = %.1f",
|
341
|
fPrintPrefix.c_str(), exposureOn) << endl;
|
342
|
os << Form("%sExposure_off = %.1f",
|
343
|
fPrintPrefix.c_str(), exposureOff) << endl;
|
344
|
os << Form("%sAlpha = %.2f",
|
345
|
fPrintPrefix.c_str(), Alpha()) << endl;
|
346
|
os << Form("%sExcess = %.2f",
|
347
|
fPrintPrefix.c_str(), Excess()) << endl;
|
348
|
os << Form("%sSignificance = %.2f",
|
349
|
fPrintPrefix.c_str(), Significance()) << endl;
|
350
|
os << Form("%strueAT_on = %.2e cm^2 s",
|
351
|
fPrintPrefix.c_str(), trueAreaTimeOn) << endl;
|
352
|
os << Form("%strueAT_off = %.2e cm^2 s",
|
353
|
fPrintPrefix.c_str(), trueAreaTimeOff) << endl;
|
354
|
os << Form("%srecoAT_on = %.2e cm^2 s",
|
355
|
fPrintPrefix.c_str(), recoAreaTimeOn) << endl;
|
356
|
os << Form("%srecoAT_off = %.2e cm^2 s",
|
357
|
fPrintPrefix.c_str(), recoAreaTimeOff) << endl;
|
358
|
os << Form("%sLiveTime = %.2f s",
|
359
|
fPrintPrefix.c_str(), liveTime) << endl;
|
360
|
os << Form("%sLiveTime_off = %.2f s",
|
361
|
fPrintPrefix.c_str(), offLiveTime) << endl;
|
362
|
os << Form("%sinvArea_on = %.2e cm^-2",
|
363
|
fPrintPrefix.c_str(), invRecoAreaOn) << endl;
|
364
|
os << Form("%sinvArea_off = %.2e cm^-2",
|
365
|
fPrintPrefix.c_str(), invRecoAreaOff) << endl;
|
366
|
}
|
367
|
catch( Utilities::Statistics::InvalidResult &res ){
|
368
|
os << "# Couldn't calculate all statistics because: " << res.what() << endl;
|
369
|
}
|
370
|
}
|
371
|
|
372
|
}
|
373
|
|
374
|
|
375
|
std::ostream& operator<<(std::ostream& stream,
|
376
|
const Flux::SpectrumStats& stats)
|
377
|
{
|
378
|
stats.print(stream);
|
379
|
return stream;
|
380
|
}
|
381
|
|
382
|
ClassImp(Flux::SpectrumStats)
|