Jpp 20.0.0-rc.6
the software that should make you happy
Loading...
Searching...
No Matches
JPseudoExperiment.hh
Go to the documentation of this file.
1#ifndef __JASTRONOMY__JPSEUDOEXPERIMENT__
2#define __JASTRONOMY__JPSEUDOEXPERIMENT__
3
4#include <istream>
5#include <ostream>
6#include <vector>
7#include <algorithm>
8#include <limits>
9
10#include "TObject.h"
11#include "TH1.h"
12#include "TH2.h"
13#include "TH3.h"
14#include "TRandom3.h"
15
17#include "JAstronomy/JAspera.hh"
19
20
21/**
22 * \file
23 *
24 * Pseudo experiment.
25 * \author mdejong
26 */
27namespace JASTRONOMY {}
28namespace JPP { using namespace JASTRONOMY; }
29
30namespace JASTRONOMY {
31
32
33 /**
34 * Auxiliary interface for pseudo experiment.
35 */
37 public JExperiment
38 {
39 /**
40 * Statistics of pseudo experiment.
41 */
42 struct stats_type {
43
45 {
46 this->ns += px.ns;
47 this->nb += px.nb;
48
49 return *this;
50 }
51
52 size_t ns = 0; //!< number of generated signal events
53 size_t nb = 0; //!< number of generated background events
54 };
55
56
57 typedef JAspera::fit_type fit_type; //!< fit type
58
59
60 /**
61 * Result of combined pseudo experiment and fit.
62 */
63 struct result_type :
64 public stats_type,
65 public fit_type
66 {};
67
68
69 /**
70 * Auxiliary data structure for upper limit evaluations of background only pseudo experiments.
71 */
72 struct h0_type :
73 public std::vector<double>
74 {
75 /**
76 * Constructor.
77 *
78 * \param px pseudo experiment
79 * \param nx number of pseudo experiments
80 */
81 h0_type(const JPseudoExperiment_t& px, const size_t nx)
82 {
83 using namespace std;
84
85 for (size_t i = 0; i != nx; ++i) {
86
87 JAspera aspera;
88
89 px.run(aspera);
90
91 this->push_back(aspera(true).signal);
92 }
93
94 sort(this->begin(), this->end());
95 }
96
97
98 /**
99 * Get fraction below given upper limit of signal strength.
100 *
101 * \param ps signal strength
102 * \return fraction
103 */
104 double getFractionBelow(const double ps) const
105 {
106 using namespace std;
107
108 return (double) distance(this->begin(), lower_bound(this->begin(), this->end(), ps)) / (double) this->size();
109 }
110 };
111
112
113 /**
114 * Set scaling factors of signal and background strengths.
115 *
116 * \param fS signal strength
117 * \param fB background strength
118 */
119 virtual void set(const double fS, const double fB = 1.0) = 0;
120
121
122 /**
123 * Get fit method.
124 *
125 * \return fit
126 */
127 virtual JAspera& getAspera() = 0;
128
129
130 /**
131 * Generate pseudo experiment and transfer S/N values to fit method.
132 *
133 * \param out output
134 * \return result
135 */
136 virtual stats_type run(JAspera& out) const = 0;
137
138
139 /**
140 * Generate background only pseudo experiment and transfer S/N values to fit method.
141 *
142 * \param out output
143 * \param nb number of background events
144 * \return result
145 */
146 virtual stats_type run(JAspera& out, const size_t nb) const = 0;
147
148
149 /**
150 * Generate pseudo experiment and fit signal strength.
151 *
152 * \return result
153 */
155 {
156 JAspera& aspera = getAspera();
157
158 // reset
159
160 aspera.clear();
161 aspera.setSignal(0.0);
162
163 return { run(aspera), aspera() };
164 }
165
166
167 /**
168 * Generate background only pseudo experiment and fit signal strength.
169 *
170 * \param nb number of background events
171 * \return result
172 */
173 inline result_type operator()(const size_t nb)
174 {
175 JAspera& aspera = getAspera();
176
177 // reset
178
179 aspera.clear();
180 aspera.setSignal(0.0);
181
182 return { run(aspera, nb), aspera() };
183 }
184
185
186 /**
187 * Run pseudo experiments using given storage.
188 *
189 * \param storage storage
190 */
192 {
193 for (auto& i : storage) {
194 i = (*this)();
195 }
196 }
197
198
199 /**
200 * Run pseudo experiments using given storage.
201 *
202 * \param pm pointer to data member of result
203 * \param storage storage
204 */
205 template<class T, class JValue_t>
206 inline void operator()(JValue_t result_type::*pm, std::vector<T>& storage)
207 {
208 for (auto& i : storage) {
209 i = (*this)().*pm;
210 }
211 }
212
213
214 /**
215 * Run pseudo experiments using given storage.
216 *
217 * \param pm pointer to data member of result
218 * \param storage storage
219 */
220 template<class T, class JValue_t>
221 inline void operator()(JValue_t JAspera::fit_type::*pm, std::vector<T>& storage)
222 {
223 (*this)(static_cast<JValue_t result_type::*>(pm), storage);
224 }
225
226
227 /**
228 * Get probability for given pseudo experiment and signal strength to exceed minimal test statistic for upper limit.
229 *
230 * \param ps signal strength
231 * \param ts test statistic
232 * \param nx number of pseudo experiments
233 */
234 inline double getProbabilityForUpperLimit(const double ps,
235 const double ts,
236 const size_t nx) const
237 {
238 size_t ns = 0;
239
240 for (size_t i = 0; i != nx; ++i) {
241
242 JAspera aspera;
243
244 this->run(aspera);
245
246 if (ps <= std::numeric_limits<double>::min()) {
247
248 if (aspera().signal <= ps) {
249 ns += 1;
250 }
251
252 } else if (aspera.getTestStatisticForUpperLimit(ps) > ts) {
253 ns += 1;
254 }
255 }
256
257 return (double) ns / (double) nx;
258 }
259 };
260
261
262 /**
263 * Pseudo experiment using CDF for combined generation and likelihood evaluation.
264 */
267 {
268 using JPseudoExperiment_t::operator();
269
270 /**
271 * Default constructor.
272 */
275
276
277 /**
278 * Constructor.
279 *
280 * \param hs histogram with PDF of signal
281 * \param hb histogram with PDF of background
282 */
283 template<class H_t>
284 JPseudoExperiment(const H_t& hs,
285 const H_t& hb)
286 {
287 add(hs, hb);
288 }
289
290
291 /**
292 * Constructor.
293 *
294 * \param hS histogram with PDF for generation of signal
295 * \param hB histogram with PDF for generation of background
296 * \param hs histogram with PDF for evaluation of signal
297 * \param hb histogram with PDF for evaluation of background
298 */
299 template<class H_t>
300 JPseudoExperiment(const H_t& hS,
301 const H_t& hB,
302 const H_t& hs,
303 const H_t& hb)
304 {
305 add(hS, hB, hs, hb);
306 }
307
308
309 /**
310 * Add objects with PDFs of signal and background.
311 *
312 * \param ps pointer to object with PDF of signal
313 * \param pb pointer to object with PDF of background
314 */
315 void add(const TObject* ps,
316 const TObject* pb)
317 {
318 if (add<TH3>(ps, pb)) { return; }
319 if (add<TH2>(ps, pb)) { return; }
320 if (add<TH1>(ps, pb)) { return; }
321 }
322
323
324 /**
325 * Add objects with PDFs of signal and background.
326 *
327 * \param pS pointer to object with PDF for generation of signal
328 * \param pB pointer to object with PDF for generation of background
329 * \param ps pointer to object with PDF for evaluation of signal
330 * \param pb pointer to object with PDF for evaluation of background
331 */
332 void add(const TObject* pS,
333 const TObject* pB,
334 const TObject* ps,
335 const TObject* pb)
336 {
337 if (add<TH3>(pS, pB, ps, pb)) { return; }
338 if (add<TH2>(pS, pB, ps, pb)) { return; }
339 if (add<TH1>(pS, pB, ps, pb)) { return; }
340 }
341
342
343 /**
344 * Add histograms with PDFs of signal and background.
345 *
346 * \param hs histogram with PDF of signal
347 * \param hb histogram with PDF of background
348 */
349 void add(const TH1& hs,
350 const TH1& hb)
351 {
352 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
353 add(hs.GetBinContent(ix),
354 hb.GetBinContent(ix));
355 }
356 }
357
358
359 /**
360 * Add histograms with PDFs of signal and background.
361 *
362 * \param hS histogram with PDF for generation of signal
363 * \param hB histogram with PDF for generation of background
364 * \param hs histogram with PDF for evaluation of signal
365 * \param hb histogram with PDF for evaluation of background
366 */
367 void add(const TH1& hS,
368 const TH1& hB,
369 const TH1& hs,
370 const TH1& hb)
371 {
372 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
373 add(hS.GetBinContent(ix),
374 hB.GetBinContent(ix),
375 hs.GetBinContent(ix),
376 hb.GetBinContent(ix));
377 }
378 }
379
380
381 /**
382 * Add histograms with PDFs of signal and background.
383 *
384 * \param hs histogram with PDF of signal
385 * \param hb histogram with PDF of background
386 */
387 void add(const TH2& hs,
388 const TH2& hb)
389 {
390 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
391 for (Int_t iy = 1; iy <= hs.GetYaxis()->GetNbins(); ++iy) {
392 add(hs.GetBinContent(ix, iy),
393 hb.GetBinContent(ix, iy));
394 }
395 }
396 }
397
398
399 /**
400 * Add histograms with PDFs of signal and background.
401 *
402 * \param hS histogram with PDF for generation of signal
403 * \param hB histogram with PDF for generation of background
404 * \param hs histogram with PDF for evaluation of signal
405 * \param hb histogram with PDF for evaluation of background
406 */
407 void add(const TH2& hS,
408 const TH2& hB,
409 const TH2& hs,
410 const TH2& hb)
411 {
412 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
413 for (Int_t iy = 1; iy <= hs.GetYaxis()->GetNbins(); ++iy) {
414 add(hS.GetBinContent(ix, iy),
415 hB.GetBinContent(ix, iy),
416 hs.GetBinContent(ix, iy),
417 hb.GetBinContent(ix, iy));
418 }
419 }
420 }
421
422
423 /**
424 * Add histograms with PDFs of signal and background.
425 *
426 * \param hs histogram with PDF of signal
427 * \param hb histogram with PDF of background
428 */
429 void add(const TH3& hs,
430 const TH3& hb)
431 {
432 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
433 for (Int_t iy = 1; iy <= hs.GetYaxis()->GetNbins(); ++iy) {
434 for (Int_t iz = 1; iz <= hs.GetZaxis()->GetNbins(); ++iz) {
435 add(hs.GetBinContent(ix, iy, iz),
436 hb.GetBinContent(ix, iy, iz));
437 }
438 }
439 }
440 }
441
442
443 /**
444 * Add histograms with PDFs of signal and background.
445 *
446 * \param hS histogram with PDF for generation of signal
447 * \param hB histogram with PDF for generation of background
448 * \param hs histogram with PDF for evaluation of signal
449 * \param hb histogram with PDF for evaluation of background
450 */
451 void add(const TH3& hS,
452 const TH3& hB,
453 const TH3& hs,
454 const TH3& hb)
455 {
456 for (Int_t ix = 1; ix <= hs.GetXaxis()->GetNbins(); ++ix) {
457 for (Int_t iy = 1; iy <= hs.GetYaxis()->GetNbins(); ++iy) {
458 for (Int_t iz = 1; iz <= hs.GetZaxis()->GetNbins(); ++iz) {
459 add(hS.GetBinContent(ix, iy, iz),
460 hB.GetBinContent(ix, iy, iz),
461 hs.GetBinContent(ix, iy, iz),
462 hb.GetBinContent(ix, iy, iz));
463 }
464 }
465 }
466 }
467
468
469 /**
470 * Add signal and background.
471 *
472 * \param s signal
473 * \param b background
474 */
475 void add(const double s,
476 const double b)
477 {
478 if (check(s, b)) {
479
480 cs.put(s);
481 cb.put(b);
482
483 aspera.put(s, b);
484 }
485 }
486
487
488 /**
489 * Add signal and background.
490 *
491 * \param S signal for generation
492 * \param B background for generation
493 * \param s signal for evaluation
494 * \param b background for evaluation
495 */
496 void add(const double S,
497 const double B,
498 const double s,
499 const double b)
500 {
501 if (//check(S, B) &&
502 check(s, b)) {
503
504 cs.put(S);
505 cb.put(B);
506
507 aspera.put(s, b);
508 }
509 }
510
511
512 /**
513 * Get total signal.
514 *
515 * \return signal
516 */
517 double getSignal() const
518 {
519 return cs.back() * this->fs;
520 }
521
522
523 /**
524 * Get total background.
525 *
526 * \return background
527 */
528 double getBackground() const
529 {
530 return cb.back() * this->fb;
531 }
532
533
534 /**
535 * Set scaling factors of signal and background strengths.
536 *
537 * \param fS signal strength
538 * \param fB background strength
539 */
540 virtual void set(const double fS, const double fB = 1.0) override
541 {
542 for (auto& i : aspera) {
543 i *= fB / this->fb;
544 }
545
546 this->fs = fS;
547 this->fb = fB;
548 }
549
550
551 /**
552 * Get fit method.
553 *
554 * \return fit
555 */
556 virtual JAspera& getAspera() override
557 {
558 return this->fit;
559 }
560
561
562 /**
563 * Generate pseudo experiment and transfer values to fit method.
564 *
565 * \param out output
566 * \return result
567 */
568 virtual stats_type run(JAspera& out) const
569 {
571
572 const size_t ns = gRandom->Poisson(getSignal() * nuisance.signal ->get()); // number of signal events
573 const size_t nb = gRandom->Poisson(getBackground() * nuisance.background->get()); // number of background events
574
575 for (size_t i = ns; i != 0; --i) { out.push_back(aspera[cs.get_index(gRandom->Rndm())]); } // store distributed signal events
576 for (size_t i = nb; i != 0; --i) { out.push_back(aspera[cb.get_index(gRandom->Rndm())]); } // store distributed background events
577
578 return { ns, nb };
579 }
580
581
582 /**
583 * Generate background only pseudo experiment and transfer S/N values to fit method.
584 *
585 * \param out output
586 * \param nb number of background events
587 * \return result
588 */
589 virtual stats_type run(JAspera& out, const size_t nb) const
590 {
592
593 for (size_t i = nb; i != 0; --i) { out.push_back(aspera[cb.get_index(gRandom->Rndm())]); } // store distributed background events
594
595 return { 0, nb };
596 }
597
598
599 /**
600 * Nuisance parameters.
601 */
603
604 /**
605 * Read parameters from input stream.
606 *
607 * \param in input stream
608 * \param parameters parameters
609 * \return input stream
610 */
611 friend inline std::istream& operator>>(std::istream& in, parameters_type& parameters)
612 {
613 return in >> parameters.signal
614 >> parameters.background;
615 }
616
617
618 /**
619 * Write parameters to output stream.
620 *
621 * \param out output stream
622 * \param parameters parameters
623 * \return output stream
624 */
625 friend inline std::ostream& operator<<(std::ostream& out, const parameters_type& parameters)
626 {
627 return out << parameters.signal << ' '
628 << parameters.background;
629 }
630
633
635
636
637 /**
638 * Configure lookup tables.
639 *
640 * \param N number of bins
641 */
642 void configure(size_t N)
643 {
644 cs.configure(N);
645 cb.configure(N);
646 }
647
648 protected:
649 /**
650 * Add objects with PDF of signal and background.
651 *
652 * \param ps pointer to object with PDF of signal
653 * \param pb pointer to object with PDF of background
654 * \return true if added; else false
655 */
656 template<class H_t>
657 bool add(const TObject* ps,
658 const TObject* pb)
659 {
660 if (dynamic_cast<const H_t*>(ps) != NULL &&
661 dynamic_cast<const H_t*>(pb) != NULL) {
662
663 const H_t& hs = dynamic_cast<const H_t&>(*ps);
664 const H_t& hb = dynamic_cast<const H_t&>(*pb);
665
666 if (check(hs, hb)) {
667
668 add(hs, hb);
669
670 return true;
671 }
672 }
673
674 return false;
675 }
676
677
678 /**
679 * Add objects with PDF of signal and background.
680 *
681 * \param pS pointer to object with PDF for generation of signal
682 * \param pB pointer to object with PDF for generation of background
683 * \param ps pointer to object with PDF for evaluation of signal
684 * \param pb pointer to object with PDF for evaluation of background
685 * \return true if added; else false
686 */
687 template<class H_t>
688 bool add(const TObject* pS,
689 const TObject* pB,
690 const TObject* ps,
691 const TObject* pb)
692 {
693 if (dynamic_cast<const H_t*>(pS) != NULL &&
694 dynamic_cast<const H_t*>(pB) != NULL &&
695 dynamic_cast<const H_t*>(ps) != NULL &&
696 dynamic_cast<const H_t*>(pb) != NULL) {
697
698 const H_t& hS = dynamic_cast<const H_t&>(*pS);
699 const H_t& hB = dynamic_cast<const H_t&>(*pB);
700 const H_t& hs = dynamic_cast<const H_t&>(*ps);
701 const H_t& hb = dynamic_cast<const H_t&>(*pb);
702
703 if (check(hS, hB) && check(hB, hs) && check(hs, hb)) {
704
705 add(hS, hB, hs, hb);
706
707 return true;
708 }
709 }
710
711 return false;
712 }
713
714
715 /**
716 * Auxiliary data structure for CDF.
717 */
718 struct cdf_type :
719 public std::vector<double>
720 {
721 /**
722 * Configure lookup table.
723 *
724 * \param N number of bins
725 */
726 void configure(size_t N)
727 {
728 if (this->size() > 1) {
729
730 index.resize(N);
731
732 size_t p = 0;
733
734 for (size_t i = 0; i != N; ++i) {
735
736 const double x = this->back() * (double) i / (double) N;
737
738 while ((*this)[p+1] < x) {
739 ++p;
740 }
741
742 index[i] = p;
743 }
744 }
745 }
746
747 /**
748 * Get index corresponding to given random value.
749 *
750 * \param rv random value [0,1>
751 * \param option option
752 * \return index
753 */
754 inline size_t get_index(const double rv, const bool option = false) const
755 {
756 const double value = this->back() * rv;
757
758 if (option || index.empty()) {
759
760 size_t first = 0;
761 size_t count = this->size();
762
763 for (size_t i, step; count != 0; ) {
764
765 step = count / 2;
766 i = first + step;
767
768 if ((*this)[i] < value) {
769 first = ++i;
770 count -= step + 1;
771 } else {
772 count = step;
773 }
774 }
775
776 return first;
777
778 } else {
779
780 size_t i = index[rv * index.size()];
781
782 while (i != this->size() && (*this)[i] < value) {
783 ++i;
784 }
785
786 return i;
787 }
788 }
789
790
791 /**
792 * Put given value.
793 *
794 * \param x value
795 */
796 void put(const double x)
797 {
798 if (this->empty())
799 this->push_back(x);
800 else
801 this->push_back(this->back() + x);
802 }
803
804 private:
806 };
807
808
809 cdf_type cs; //!< CDF of signal
810 cdf_type cb; //!< CDF of background
811
812 JAspera aspera; //!< pre-computed N/S values
813
814 double fs = 1.0; //!< scaling factor signal strength
815 double fb = 1.0; //!< scaling factor background strength
816
817 JAspera fit; //!< fit
818 };
819}
820
821#endif
Per aspera ad astra.
Experiment.
Nuisance parameter.
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
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
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
Auxiliary base class for experiment.
static bool check(const double s, const double b)
Check validity of signal and background.
Helper for nuisance I/O.
Definition JNuisance.hh:349
Auxiliary data structure for CDF.
void put(const double x)
Put given value.
size_t get_index(const double rv, const bool option=false) const
Get index corresponding to given random value.
void configure(size_t N)
Configure lookup table.
friend std::ostream & operator<<(std::ostream &out, const parameters_type &parameters)
Write parameters to output stream.
friend std::istream & operator>>(std::istream &in, parameters_type &parameters)
Read parameters from input stream.
Auxiliary data structure for upper limit evaluations of background only pseudo experiments.
h0_type(const JPseudoExperiment_t &px, const size_t nx)
Constructor.
double getFractionBelow(const double ps) const
Get fraction below given upper limit of signal strength.
Result of combined pseudo experiment and fit.
size_t ns
number of generated signal events
size_t nb
number of generated background events
stats_type & operator+=(const stats_type &px)
Auxiliary interface for pseudo experiment.
result_type operator()()
Generate pseudo experiment and fit signal strength.
virtual JAspera & getAspera()=0
Get fit method.
void operator()(JValue_t JAspera::fit_type::*pm, std::vector< T > &storage)
Run pseudo experiments using given storage.
result_type operator()(const size_t nb)
Generate background only pseudo experiment and fit signal strength.
void operator()(JValue_t result_type::*pm, std::vector< T > &storage)
Run pseudo experiments using given storage.
virtual stats_type run(JAspera &out, const size_t nb) const =0
Generate background only pseudo experiment and transfer S/N values to fit method.
void operator()(std::vector< result_type > &storage)
Run pseudo experiments using given storage.
double getProbabilityForUpperLimit(const double ps, const double ts, const size_t nx) const
Get probability for given pseudo experiment and signal strength to exceed minimal test statistic for ...
virtual void set(const double fS, const double fB=1.0)=0
Set scaling factors of signal and background strengths.
virtual stats_type run(JAspera &out) const =0
Generate pseudo experiment and transfer S/N values to fit method.
JAspera::fit_type fit_type
fit type
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
virtual stats_type run(JAspera &out, const size_t nb) const
Generate background only pseudo experiment and transfer S/N values to fit method.
virtual stats_type run(JAspera &out) const
Generate pseudo experiment and transfer values to fit method.
void add(const TH3 &hS, const TH3 &hB, const TH3 &hs, const TH3 &hb)
Add histograms with PDFs of signal and background.
void add(const TH1 &hS, const TH1 &hB, const TH1 &hs, const TH1 &hb)
Add histograms with PDFs of signal and background.
bool add(const TObject *ps, const TObject *pb)
Add objects with PDF of signal and background.
virtual JAspera & getAspera() override
Get fit method.
bool add(const TObject *pS, const TObject *pB, const TObject *ps, const TObject *pb)
Add objects with PDF of signal and background.
double getSignal() const
Get total signal.
void add(const TH2 &hS, const TH2 &hB, const TH2 &hs, const TH2 &hb)
Add histograms with PDFs of signal and background.
void add(const TH3 &hs, const TH3 &hb)
Add histograms with PDFs of signal and background.
JPseudoExperiment(const H_t &hS, const H_t &hB, const H_t &hs, const H_t &hb)
Constructor.
virtual void set(const double fS, const double fB=1.0) override
Set scaling factors of signal and background strengths.
double fb
scaling factor background strength
cdf_type cb
CDF of background.
void add(const double S, const double B, const double s, const double b)
Add signal and background.
void add(const TH2 &hs, const TH2 &hb)
Add histograms with PDFs of signal and background.
JPseudoExperiment(const H_t &hs, const H_t &hb)
Constructor.
JAspera aspera
pre-computed N/S values
double getBackground() const
Get total background.
void add(const TObject *pS, const TObject *pB, const TObject *ps, const TObject *pb)
Add objects with PDFs of signal and background.
void add(const TH1 &hs, const TH1 &hb)
Add histograms with PDFs of signal and background.
double fs
scaling factor signal strength
void configure(size_t N)
Configure lookup tables.
void add(const double s, const double b)
Add signal and background.
JPseudoExperiment()
Default constructor.