Jpp 20.0.0-rc.7
the software that should make you happy
Loading...
Searching...
No Matches
JPseudoExperiment.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <iomanip>
4#include <chrono>
5#include <vector>
6#include <map>
7#include <exception>
8#include <algorithm>
9
10#include "TROOT.h"
11#include "TFile.h"
12#include "TH1D.h"
13#include "TH2D.h"
14#include "TH3D.h"
15#include "TRandom3.h"
16
18#include "JAstronomy/JGarage.hh"
20
21#include "JLang/JVectorize.hh"
24#include "JROOT/JRandom.hh"
26
27#include "Jeep/JContainer.hh"
28#include "Jeep/JParser.hh"
29
30
31namespace {
32
33 /**
34 * Auxiliary data structure for experiment.
35 */
36 struct experiment_type {
37
38 JGIZMO::JRootObjectID Hs; //!< signal
39 JGIZMO::JRootObjectID Hb; //!< background
40
41 /**
42 * Read experiment from input stream.
43 *
44 * \param in input stream
45 * \param experiment experiment
46 * \return input stream
47 */
48 friend inline std::istream& operator>>(std::istream& in, experiment_type& experiment)
49 {
50 return in >> experiment.Hs
51 >> experiment.Hb;
52 }
53
54
55 /**
56 * Write experiment to output stream.
57 *
58 * \param out output stream
59 * \param experiment experiment
60 * \return output stream
61 */
62 friend inline std::ostream& operator<<(std::ostream& out, const experiment_type& experiment)
63 {
64 return out << experiment.Hs << ' '
65 << experiment.Hb;
66 }
67 };
68
69
70 /**
71 * Auxiliary data structure for printing.
72 */
73 struct printer {
74 /**
75 * Constructor.
76 *
77 * \param title title
78 * \param ps pointer to object
79 */
80 printer(const char* const title,
81 const TObject* ps) :
82 title(title),
83 ps(ps)
84 {}
85
86 /**
87 * Write printer to output stream.
88 *
89 * \param out output stream
90 * \param printer printer
91 * \return output stream
92 */
93 friend inline std::ostream& operator<<(std::ostream& out, const printer& printer)
94 {
95 using namespace std;
96 using namespace JPP;
97
98 out << setw(16) << left << printer.title << right;
99
100 if (printer.ps != NULL) {
101
102 out << ' ' << setw(16) << left << printer.ps->GetName() << right;
103
104 const TH1* h1 = dynamic_cast<const TH1*>(printer.ps);
105
106 if (h1 != NULL) {
107 out << ' ' << FIXED(10,3) << h1->GetSumOfWeights();
108 }
109 }
110
111 return out;
112 }
113
114 private:
115 const char* const title;
116 const TObject* ps;
117 };
118}
119
120
121/**
122 * \file
123 * Test application for pseudo experiment generation and likelihood ratio evaluations.
124 *
125 * \author mdejong
126 */
127int main(int argc, char **argv)
128{
129 using namespace std;
130 using namespace JPP;
131
132 typedef JAbstractHistogram<double> histogram_type;
133 typedef float data_type;
134
136
138 string outputFile;
139 size_t numberOfTests;
140 double Fs;
141 double Fb;
142 double boost;
143 size_t M;
144 double SNR;
145 histogram_type X;
146 data_type Q;
148 JRandom seed;
149 int debug;
150
151 try {
152
153 JParser<> zap;
154
155 zap['E'] = make_field(setup,
156 "douplets of signal and background histograms, "
157 << "each of which defined by <file name>:<histogram name>");
158 zap['o'] = make_field(outputFile, "output file with histograms") = "benchmark.root";
159 zap['n'] = make_field(numberOfTests, "number of tests");
160 zap['s'] = make_field(Fs, "signal strength");
161 zap['b'] = make_field(Fb, "background strength") = 1.0;
162 zap['B'] = make_field(boost, "boost livetime of experiment") = 1.0;
163 zap['M'] = make_field(M, "lookup table for CDFs") = 0;
164 zap['R'] = make_field(SNR, "signal-to-noise ratio") = 0.0;
165 zap['N'] = make_field(px.nuisance,
166 "signal and background nuisances, "
167 << "each of which defined by <type> (values), \n"
168 << "\twhere <type> can be:"
169 << get_keys(px.nuisance.signal.getDictionary())) = JPARSER::initialised();
170 zap['x'] = make_field(X, "x-axis likelihood histogram") = histogram_type(110, -10.0, +100.0);
171 zap['Q'] = make_field(Q, "minimal likelihood ratio") = 0.0;
172 zap['P'] = make_field(P, "maximal probability") = JPARSER::initialised();
173 zap['S'] = make_field(seed) = 0;
174 zap['d'] = make_field(debug) = 1;
175
176 zap(argc, argv);
177 }
178 catch(const exception& error) {
179 FATAL(error.what() << endl);
180 }
181
182
183 seed.set(gRandom);
184
185 JExperiment::setSNR(SNR);
186
187 for (const auto& i : setup) {
188
189 TObject* ps = getObject(i.Hs);
190 TObject* pb = getObject(i.Hb);
191
192 dynamic_cast<TH1*>(ps)->Scale(boost);
193 dynamic_cast<TH1*>(pb)->Scale(boost);
194
195 STATUS(printer("Signal:", ps) << endl);
196 STATUS(printer("Background:", pb) << endl);
197
198 px.add(ps, pb);
199 }
200
201 px.set(Fs, Fb);
202
203 if (M != 0) {
204 px.configure(M);
205 }
206
207 STATUS("Signal: " << FIXED(10,3) << px.getSignal() << endl);
208 STATUS("Background: " << FIXED(10,3) << px.getBackground() << endl);
209 STATUS("Number of tests: " << setw(10) << numberOfTests << endl);
210
211
212 TFile out(outputFile.c_str(), "recreate");
213
214 out << *gRandom;
215
216 TH1D hl("hl", NULL, X.getNumberOfBins(), X.getLowerLimit(), X.getUpperLimit());
217 TH1D hn("hn", NULL, 100, -15.0, +15.0);
218
219
220 if (P.size() > 1) { // special case
221
223
224 double Ps = 0.0; // total probability
225 size_t nb = px.getBackground() + 1; // start value for number of background events
226 size_t mb = 0;
227
228 {
229 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
230
231 for ( ; ; ++nb) {
232
233 const double p = poisson(nb, px.getBackground());
234 const size_t n = p * numberOfTests;
235
236 if (p > P[1]) {
237 continue;
238 }
239
240 if (n == 0) {
241 break;
242 }
243
244 if (mb == 0) {
245 mb = nb;
246
247 }
248 for (size_t i = 0; i != n; ++i) {
249 storage.put(px(nb).likelihood);
250 }
251
252 Ps += p;
253 }
254
255 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
256
257 STATUS("Total time: " << setw(8) << (t1 - t0) / chrono::milliseconds(1) << " [ms]" << endl);
258 STATUS("Average time: " << setw(6) << (t1 - t0) / chrono::nanoseconds(numberOfTests) << " [ns]" << endl);
259 }
260
261 STATUS("Poisson: " << setw(3) << mb << ' ' << SCIENTIFIC(12,3) << Ps << ' ' << setw(8) << storage.size() << endl);
262
263 storage([&hl](const data_type x) { hl.Fill(x); });
264
265 double x = 0.0;
266 double p = 0.0;
267
268 {
269 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
270
271 x = storage.getValue(P[0]/Ps);
272 p = storage.getProbability(x) * Ps;
273
274 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
275
276 STATUS("Time to result: " << setw(6) << (t1 - t0) / chrono::nanoseconds(1) << " [ns]" << endl);
277 }
278
279 cout << "Minimal likelihood ratio: " << FIXED(9,5) << x << ' ' << SCIENTIFIC(12,3) << p << endl;
280
281 } else if (P.size() > 0 && Q > 0.0) {
282
283 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
284
285 const double signal = discovery<float, 100>(px, Q, P[0], numberOfTests);
286
287 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
288
289 STATUS("Total time: " << setw(8) << (t1 - t0) / chrono::milliseconds(1) << " [ms]" << endl);
290
291 cout << "Signal strength: " << FIXED(9,5) << signal << endl;
292
293 } else if (P.size() > 0 || Q > 0.0) {
294
296
297 {
298 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
299
300 for (size_t i = 0; i != numberOfTests; ++i) {
301 storage.put(px().likelihood);
302 }
303
304 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
305
306 STATUS("Total time: " << setw(8) << (t1 - t0) / chrono::milliseconds(1) << " [ms]" << endl);
307 STATUS("Average time: " << setw(6) << (t1 - t0) / chrono::nanoseconds(numberOfTests) << " [ns]" << endl);
308 }
309
310 storage([&hl](const data_type x) { hl.Fill(x); });
311
312 double x = 0.0;
313 double p = 0.0;
314
315 {
316 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
317
318 if (P.size() == 1) { // determine minimal likelihood ratio given maximal probability
319 x = storage.getValue(P[0]);
320 p = storage.getProbability(x);
321 }
322
323 if (Q > 0.0) { // determine maximal probability given minimal likelihood ratio
324 p = storage.getProbability(Q);
325 x = storage.getValue(p);
326 }
327
328 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
329
330 STATUS("Time to result: " << setw(6) << (t1 - t0) / chrono::microseconds(1) << " [us]" << endl);
331 }
332
333 if (P.size() == 1) { cout << "Minimal likelihood ratio: " << FIXED(9,5) << x << ' ' << SCIENTIFIC(12,3) << p << endl; }
334 if (Q > 0.0) { cout << "Maximal probability: " << SCIENTIFIC(12,3) << p << ' ' << FIXED(9,5) << x << endl; }
335
336 } else {
337
338 std::vector<JPseudoExperiment::result_type> storage(numberOfTests);
339
340 const chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now();
341
342 px(storage);
343
344 const chrono::high_resolution_clock::time_point t1 = chrono::high_resolution_clock::now();
345
346 STATUS("Average time: " << setw(6) << (t1 - t0) / chrono::nanoseconds(storage.size()) << " [ns]" << endl);
347
348 for (const auto& result : storage) {
349
350 DEBUG("result: "
351 << setw(3) << result.ns << ' '
352 << setw(3) << result.nb << ' '
353 << FIXED(12,5) << result.likelihood << ' '
354 << FIXED(12,5) << result.signal << endl);
355
356 hl.Fill(result.likelihood);
357 hn.Fill(result.signal - result.ns);
358 }
359 }
360
361 out.Write();
362 out.Close();
363}
364
Container I/O.
string outputFile
std::istream & operator>>(std::istream &in, JAANET::JHead &header)
Read header from input.
Definition JHead.hh:1850
Auxiliary methods for mathematics.
#define DEBUG(A)
Message macros.
Definition JMessage.hh:62
#define STATUS(A)
Definition JMessage.hh:63
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:72
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2142
int main(int argc, char **argv)
Pseudo experiment.
Auxiliary methods to convert data members or return values of member methods of a set of objects to a...
Auxiliary class to handle file name, ROOT directory and object name.
Utility class to parse command line options.
Definition JParser.hh:1698
std::ostream & operator<<(std::ostream &stream, const CLBCommonHeader &header)
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
JWriter & operator<<(JWriter &out, const JDAQChronometer &chronometer)
Write DAQ chronometer to output.
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Auxiliary container for statistical analysis of a large number of positive (or zero) values.
Definition JGarage.hh:30
double getProbability(const T value) const
Get maximal probability corresponding given minimal value.
Definition JGarage.hh:196
T getValue(const double P) const
Get minimal value corresponding given maximal probability.
Definition JGarage.hh:154
void put(const T value)
Add value to container.
Definition JGarage.hh:105
dictionary_type & getDictionary()
Get dictionary.
Definition JNuisance.hh:372
Pseudo experiment using CDF for combined generation and likelihood evaluation.
void add(const TObject *ps, const TObject *pb)
Add objects with PDFs of signal and background.
struct JASTRONOMY::JPseudoExperiment::parameters_type nuisance
double getSignal() const
Get total signal.
virtual void set(const double fS, const double fB=1.0) override
Set scaling factors of signal and background strengths.
double getBackground() const
Get total background.
void configure(size_t N)
Configure lookup tables.
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Definition JFitK40.hh:103
Auxiliary wrapper for I/O of container with optional comment (see JComment).
Definition JContainer.hh:42
Template definition of random value generator.
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition JParser.hh:68
Simple data structure for histogram binning.
Auxiliary data structure for floating point format specification.
Definition JManip.hh:488