27 using namespace PhysicsTools;
36 ~ProcLikelihood()
override {}
38 void configure(ConfIterator iter,
unsigned int n)
override;
39 void eval(ValueIterator iter,
unsigned int n)
const override;
40 std::vector<double> deriv(ValueIterator iter,
unsigned int n)
const override;
45 virtual double eval(
double value)
const = 0;
46 virtual double deriv(
double value)
const = 0;
51 struct SplinePDF :
public PDF {
57 double eval(
double value)
const override;
58 double deriv(
double value)
const override;
64 struct HistogramPDF :
public PDF {
67 double eval(
double value)
const override;
68 double deriv(
double value)
const override;
76 signal = std::unique_ptr<PDF>(
new SplinePDF(&calib.
signal));
77 background = std::unique_ptr<PDF>(
new SplinePDF(&calib.
background));
79 signal = std::unique_ptr<PDF>(
new HistogramPDF(&calib.
signal));
80 background = std::unique_ptr<PDF>(
new HistogramPDF(&calib.
background));
84 background->norm = norm;
87 std::unique_ptr<PDF> signal;
88 std::unique_ptr<PDF> background;
91 int findPDFs(ValueIterator iter,
93 std::vector<SigBkg>::const_iterator &
begin,
94 std::vector<SigBkg>::const_iterator &
end)
const;
96 std::vector<SigBkg> pdfs;
97 std::vector<double> bias;
103 unsigned int nCategories;
108 double ProcLikelihood::SplinePDF::eval(
double value)
const {
109 value = (value -
min) / width;
110 return spline.eval(value) * norm / spline.getArea();
113 double ProcLikelihood::SplinePDF::deriv(
double value)
const {
114 value = (value -
min) / width;
115 return spline.deriv(value) * norm / spline.getArea();
118 double ProcLikelihood::HistogramPDF::eval(
double value)
const {
return histo->normalizedValue(value) * norm; }
120 double ProcLikelihood::HistogramPDF::deriv(
double value)
const {
return 0; }
122 ProcLikelihood::ProcLikelihood(
const char *
name,
126 pdfs(calib->pdfs.
begin(), calib->pdfs.
end()),
128 categoryIdx(calib->categoryIdx),
129 logOutput(calib->logOutput),
130 individual(calib->individual),
131 neverUndefined(calib->neverUndefined),
132 keepEmpty(calib->keepEmpty),
135 void ProcLikelihood::configure(ConfIterator iter,
unsigned int n) {
136 if (categoryIdx >= 0) {
137 if ((
int)n < categoryIdx + 1)
139 nCategories = pdfs.size() / (n - 1);
140 if (nCategories * (n - 1) != pdfs.size())
142 if (!bias.empty() && bias.size() != nCategories)
144 }
else if (n != pdfs.size() || bias.size() > 1)
149 if (categoryIdx == i++)
150 iter++(Variable::FLAG_NONE);
152 iter++(Variable::FLAG_ALL);
156 for (
unsigned int i = 0; i < pdfs.size(); i += nCategories)
157 iter << (neverUndefined ? Variable::FLAG_NONE : Variable::FLAG_OPTIONAL);
159 iter << (neverUndefined ? Variable::FLAG_NONE : Variable::FLAG_OPTIONAL);
162 int ProcLikelihood::findPDFs(ValueIterator iter,
164 std::vector<SigBkg>::const_iterator &
begin,
165 std::vector<SigBkg>::const_iterator &
end)
const {
167 if (categoryIdx >= 0) {
168 ValueIterator iter2 = iter;
169 for (
int i = 0; i < categoryIdx; i++)
173 if (cat < 0 || (
unsigned int)cat >= nCategories)
176 begin = pdfs.begin() + cat * (n - 1);
177 end = begin + (n - 1);
180 begin = pdfs.begin();
187 void ProcLikelihood::eval(ValueIterator iter,
unsigned int n)
const {
188 std::vector<SigBkg>::const_iterator pdf,
last;
189 int cat = findPDFs(iter, n, pdf, last);
191 long double signal = bias.empty() ? 1.0 : bias[
cat];
192 long double background = 1.0;
196 for (
unsigned int i = 0; i <
n; i++)
203 for (
int i = 0; pdf !=
last; ++iter, i++) {
204 if (i == categoryIdx)
207 for (
double *value = iter.begin(); value < iter.end(); value++) {
208 double signalProb =
std::max(0.0, pdf->signal->eval(*value));
209 double backgroundProb =
std::max(0.0, pdf->background->eval(*value));
210 if (!keepEmpty && !individual && signalProb + backgroundProb < 1.0
e-20)
215 signalProb *= signal;
216 backgroundProb *= background;
218 if (signalProb < 1.0
e-9 && backgroundProb < 1.0
e-9) {
222 }
else if (signalProb < 1.0
e-9)
224 else if (backgroundProb < 1.0
e-9)
229 double sum = signalProb + backgroundProb;
231 iter << (signalProb / sum);
232 else if (neverUndefined)
236 signal *= signalProb;
237 background *= backgroundProb;
247 if (!vars || signal + background <
std::exp(-7 * vars - 3)) {
249 iter(logOutput ? 0.0 : 0.5);
252 }
else if (logOutput) {
253 if (signal < 1.0
e-9 && background < 1.0
e-9) {
258 }
else if (signal < 1.0
e-9)
260 else if (background < 1.0
e-9)
265 iter(signal / (signal + background));
269 std::vector<double> ProcLikelihood::deriv(ValueIterator iter,
unsigned int n)
const {
270 std::vector<SigBkg>::const_iterator pdf,
last;
271 int cat = findPDFs(iter, n, pdf, last);
273 long double signal = bias.empty() ? 1.0 : bias[
cat];
274 long double background = 1.0;
276 std::vector<double>
result;
280 unsigned int size = 0;
281 for (ValueIterator iter2 = iter; iter2; ++iter2)
282 size += iter2.size();
291 for (
int i = 0; pdf !=
last; ++iter, i++) {
292 if (i == categoryIdx) {
297 for (
double *value = iter.begin(); value < iter.end(); value++, j++) {
298 double signalProb = pdf->signal->eval(*value);
299 double signalDiff = pdf->signal->deriv(*value);
300 if (signalProb < 0.0)
301 signalProb = signalDiff = 0.0;
303 double backgroundProb = pdf->background->eval(*value);
304 double backgroundDiff = pdf->background->deriv(*value);
305 if (backgroundProb < 0.0)
306 backgroundProb = backgroundDiff = 0.0;
308 if (!keepEmpty && !individual && signalProb + backgroundProb < 1.0
e-20)
313 signalProb *= signal;
314 signalDiff *= signal;
315 backgroundProb *= background;
316 backgroundDiff *= background;
318 if (signalProb < 1.0
e-9 && backgroundProb < 1.0
e-9) {
321 result.resize(result.size() +
size);
322 }
else if (signalProb < 1.0
e-9 || backgroundProb < 1.0
e-9)
323 result.resize(result.size() +
size);
325 result.resize(result.size() +
size);
326 result[result.size() - size +
j] = signalDiff / signalProb - backgroundDiff / backgroundProb;
329 double sum = signalProb + backgroundProb;
331 result.resize(result.size() +
size);
332 result[result.size() - size +
j] =
333 (signalDiff * backgroundProb - signalProb * backgroundDiff) / (sum * sum);
334 }
else if (neverUndefined)
335 result.resize(result.size() +
size);
338 signal *= signalProb;
339 background *= backgroundProb;
340 double s = signalDiff / signalProb;
343 double b = backgroundDiff / backgroundProb;
355 if (!vars || signal + background <
std::exp(-7 * vars - 3)) {
357 std::fill(result.begin(), result.end(), 0.0);
360 }
else if (logOutput) {
361 if (signal < 1.0
e-9 && background < 1.0
e-9) {
363 std::fill(result.begin(), result.end(), 0.0);
366 }
else if (signal < 1.0
e-9 || background < 1.0
e-9)
367 std::fill(result.begin(), result.end(), 0.0);
372 double factor = signal * background / ((signal + background) * (signal + background));
373 for (std::vector<double>::iterator
p = result.begin();
p != result.end(); ++
p)
static std::vector< std::string > checklist log
constexpr bool isNotFinite(T x)
Exp< T >::type exp(const T &t)
const uint16_t range(const Frame &aFrame)
void fill(std::map< std::string, TH1 * > &h, const std::string &s, double x)
tuple size
Write out results.