SpectrumStats.C

Deil Christoph, 05/02/2013 04:37 PM

Download (10.8 KB)

 
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
/** \return true only if all fields are equal */
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
/** Performs the operation: this = this + c1*rhs.  */
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
/** Add the rhs object to this one, return a reference to this */
142
SpectrumStats& SpectrumStats::operator+=(const SpectrumStats& rhs)
143
{
144
  Add(rhs);
145
  return *this;
146
}
147

    
148
/** Return a new SpectrumStats object which is the sum of this one
149
 * and the rhs.
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
 * Returns alpha, defined as the ratio of ON/OFF exposure.
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
 * Returns the significance (Li and Ma formula) 
177
 */
178
double SpectrumStats::Significance() const
179
{
180
  double alpha = Alpha();
181
  return Utilities::Statistics::Significance(nOn, nOff, alpha);
182
}
183

    
184
/**
185
 * Same as Significance but throws no errors (for scripts)
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
 * Returns the excess counts
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
    // do nothing - leave excess at 0 if alpha is not calculable
209
  }
210
  return excess;
211
}
212

    
213
/**
214
 * Arithmetic mean of Li & Ma up and down errors.
215
 *
216
 * Note that the nOff == 0 case is not treated separately
217
 * as in ExcessError(Down|Up)
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
 * Returns the error on the excess, using Li & Ma
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
 * Returns the error on the excess, using Li & Ma
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
 * Returns the fractional error on the excess, using Li & Ma
254
 */
255
double SpectrumStats::FracErrorUp() const
256
{
257
  return fabs(ExcessErrorUp() / Excess());
258
}
259

    
260
/**
261
 * Returns the fractional error on the excess, using Li & Ma
262
 */
263
double SpectrumStats::FracErrorDown() const
264
{
265
  return fabs(ExcessErrorDown() / Excess());
266
}
267

    
268
/**
269
 * Returns the fractional error on the excess, using Li & Ma
270
 */
271
double SpectrumStats::FracError() const
272
{
273
  return fabs(ExcessError() / Excess());
274
}
275

    
276
/**
277
 * Returns the excess sensitivity for a desired significance level.
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
 * Rolke confidence limits on the excess.
294
 * \param cl Confidence level in %
295
 */
296
void SpectrumStats::ExcessLimits(double& excess_down, double& excess_up, 
297
                                 double cl) const
298
{
299
  // \note Creating and deleting a new TRolke for every bin is inefficient,
300
  // but I don't know how else to implement it here.
301
  // Where speed is a problem you can just make a TRolke yourself instead
302
  // of calling this method for many bins.
303
  TRolke* rolke = new TRolke(cl / 100);
304
  rolke->SetBounding(true); //use method 2 of Rolke et al (2005)
305
  rolke->SetPoissonBkgKnownEff(nOn, nOff, 1 / Alpha(), 1);
306
  rolke->GetLimits(excess_down, excess_up);
307
  delete rolke;
308
}
309

    
310
/**
311
 * Rolke confidence limits on the excess.
312
 * \param cl Confidence level in %
313
 */
314
void SpectrumStats::ZeroExcessLimits(double& excess_down, double& excess_up, 
315
                                     double cl) const
316
{
317
  // \note Creating and deleting a new TRolke for every bin is inefficient,
318
  // but I don't know how else to implement it here.
319
  // Where speed is a problem you can just make a TRolke yourself instead
320
  // of calling this method for many bins.
321
  TRolke* rolke = new TRolke(cl / 100);
322
  rolke->SetBounding(true); //use method 2 of Rolke et al (2005)
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
} // end namespace Flux
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)