36 ProcLikelihood(
const char *
name,
39 ~ProcLikelihood()
override {}
41 void configure(ConfIterator iter,
unsigned int n)
override;
42 void eval(ValueIterator iter,
unsigned int n)
const override;
43 std::vector<double> deriv(
44 ValueIterator iter,
unsigned int n)
const override;
49 virtual double eval(
double value)
const = 0;
50 virtual double deriv(
double value)
const = 0;
55 struct SplinePDF :
public PDF {
60 std::vector<double>
values(
61 calib->
values().begin() + 1,
62 calib->
values().end() - 1);
66 double eval(
double value)
const override;
67 double deriv(
double value)
const override;
73 struct HistogramPDF :
public PDF {
77 double eval(
double value)
const override;
78 double deriv(
double value)
const override;
87 signal = std::auto_ptr<PDF>(
88 new SplinePDF(&calib.
signal));
89 background = std::auto_ptr<PDF>(
92 signal = std::auto_ptr<PDF>(
93 new HistogramPDF(&calib.
signal));
94 background = std::auto_ptr<PDF>(
100 background->norm = norm;
103 std::auto_ptr<PDF> signal;
104 std::auto_ptr<PDF> background;
107 int findPDFs(ValueIterator iter,
unsigned int n,
108 std::vector<SigBkg>::const_iterator &
begin,
109 std::vector<SigBkg>::const_iterator &
end)
const;
111 std::vector<SigBkg> pdfs;
112 std::vector<double> bias;
118 unsigned int nCategories;
123 double ProcLikelihood::SplinePDF::eval(
double value)
const 126 return spline.eval(value) * norm / spline.getArea();
129 double ProcLikelihood::SplinePDF::deriv(
double value)
const 132 return spline.deriv(value) * norm / spline.getArea();
135 double ProcLikelihood::HistogramPDF::eval(
double value)
const 137 return histo->normalizedValue(value) * norm;
140 double ProcLikelihood::HistogramPDF::deriv(
double value)
const 145 ProcLikelihood::ProcLikelihood(
const char *
name,
149 pdfs(calib->pdfs.
begin(), calib->pdfs.
end()),
151 categoryIdx(calib->categoryIdx), logOutput(calib->logOutput),
152 individual(calib->individual), neverUndefined(calib->neverUndefined),
153 keepEmpty(calib->keepEmpty), nCategories(1)
157 void ProcLikelihood::configure(ConfIterator iter,
unsigned int n)
159 if (categoryIdx >= 0) {
160 if ((
int)n < categoryIdx + 1)
162 nCategories = pdfs.size() / (n - 1);
163 if (nCategories * (n - 1) != pdfs.size())
165 if (!bias.empty() && bias.size() != nCategories)
167 }
else if (n != pdfs.size() || bias.size() > 1)
172 if (categoryIdx == i++)
173 iter++(Variable::FLAG_NONE);
175 iter++(Variable::FLAG_ALL);
179 for(
unsigned int i = 0; i < pdfs.size(); i += nCategories)
180 iter << (neverUndefined ? Variable::FLAG_NONE
181 : Variable::FLAG_OPTIONAL);
183 iter << (neverUndefined ? Variable::FLAG_NONE
184 : Variable::FLAG_OPTIONAL);
187 int ProcLikelihood::findPDFs(ValueIterator iter,
unsigned int n,
188 std::vector<SigBkg>::const_iterator &
begin,
189 std::vector<SigBkg>::const_iterator &
end)
const 192 if (categoryIdx >= 0) {
193 ValueIterator iter2 = iter;
194 for(
int i = 0; i < categoryIdx; i++)
198 if (cat < 0 || (
unsigned int)cat >= nCategories)
201 begin = pdfs.begin() + cat * (n - 1);
202 end = begin + (n - 1);
205 begin = pdfs.begin();
212 void ProcLikelihood::eval(ValueIterator iter,
unsigned int n)
const 214 std::vector<SigBkg>::const_iterator pdf,
last;
215 int cat = findPDFs(iter, n, pdf, last);
217 long double signal = bias.empty() ? 1.0 : bias[
cat];
218 long double background = 1.0;
222 for(
unsigned int i = 0; i <
n; i++)
229 for(
int i = 0; pdf !=
last; ++iter, i++) {
230 if (i == categoryIdx)
233 for(
double *value = iter.begin();
234 value < iter.end(); value++) {
236 std::max(0.0, pdf->signal->eval(*value));
237 double backgroundProb =
238 std::max(0.0, pdf->background->eval(*value));
239 if (!keepEmpty && !individual &&
240 signalProb + backgroundProb < 1.0
e-20)
245 signalProb *= signal;
246 backgroundProb *= background;
248 if (signalProb < 1.0
e-9 &&
249 backgroundProb < 1.0
e-9) {
253 }
else if (signalProb < 1.0
e-9)
255 else if (backgroundProb < 1.0
e-9)
262 signalProb + backgroundProb;
264 iter << (signalProb / sum);
265 else if (neverUndefined)
269 signal *= signalProb;
270 background *= backgroundProb;
280 if (!vars || signal + background <
std::exp(-7 * vars - 3)) {
282 iter(logOutput ? 0.0 : 0.5);
285 }
else if (logOutput) {
286 if (signal < 1.0
e-9 && background < 1.0
e-9) {
291 }
else if (signal < 1.0
e-9)
293 else if (background < 1.0
e-9)
298 iter(signal / (signal + background));
302 std::vector<double> ProcLikelihood::deriv(ValueIterator iter,
303 unsigned int n)
const 305 std::vector<SigBkg>::const_iterator pdf,
last;
306 int cat = findPDFs(iter, n, pdf, last);
308 long double signal = bias.empty() ? 1.0 : bias[
cat];
309 long double background = 1.0;
311 std::vector<double>
result;
315 unsigned int size = 0;
316 for(ValueIterator iter2 = iter; iter2; ++iter2)
317 size += iter2.size();
326 for(
int i = 0; pdf !=
last; ++iter, i++) {
327 if (i == categoryIdx) {
332 for(
double *value = iter.begin();
333 value < iter.end(); value++, j++) {
334 double signalProb = pdf->signal->eval(*value);
335 double signalDiff = pdf->signal->deriv(*value);
336 if (signalProb < 0.0)
337 signalProb = signalDiff = 0.0;
339 double backgroundProb = pdf->background->eval(*value);
340 double backgroundDiff = pdf->background->deriv(*value);
341 if (backgroundProb < 0.0)
342 backgroundProb = backgroundDiff = 0.0;
344 if (!keepEmpty && !individual &&
345 signalProb + backgroundProb < 1.0
e-20)
350 signalProb *= signal;
351 signalDiff *= signal;
352 backgroundProb *= background;
353 backgroundDiff *= background;
355 if (signalProb < 1.0
e-9 &&
356 backgroundProb < 1.0
e-9) {
359 result.resize(result.size() +
361 }
else if (signalProb < 1.0
e-9 ||
362 backgroundProb < 1.0
e-9)
363 result.resize(result.size() +
366 result.resize(result.size() +
368 result[result.size() -
377 signalProb + backgroundProb;
379 result.resize(result.size() +
381 result[result.size() -
388 }
else if (neverUndefined)
389 result.resize(result.size() +
393 signal *= signalProb;
394 background *= backgroundProb;
395 double s = signalDiff / signalProb;
398 double b = backgroundDiff / backgroundProb;
410 if (!vars || signal + background <
std::exp(-7 * vars - 3)) {
412 std::fill(result.begin(), result.end(), 0.0);
415 }
else if (logOutput) {
416 if (signal < 1.0
e-9 && background < 1.0
e-9) {
422 }
else if (signal < 1.0
e-9 ||
424 std::fill(result.begin(), result.end(), 0.0);
429 double factor = signal * background /
430 ((signal + background) *
431 (signal + background));
432 for(std::vector<double>::iterator
p = result.begin();
433 p != result.end(); ++
p)