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 {
53 std::vector<double>
values(
calib->values().begin() + 1,
calib->values().end() - 1);
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;
75 if (
calib.useSplines) {
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));
82 double norm = (
calib.signal.numberOfBins() +
calib.background.numberOfBins()) / 2.0;
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;
108 double ProcLikelihood::SplinePDF::eval(
double value)
const {
110 return spline.eval(
value) * norm / spline.getArea();
113 double ProcLikelihood::SplinePDF::deriv(
double value)
const {
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,
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)
144 }
else if (
n != pdfs.size() || bias.size() > 1)
149 if (categoryIdx ==
i++)
150 iter++(Variable::FLAG_NONE);
152 iter++(Variable::FLAG_ALL);
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++)
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)
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;
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) {
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) {
322 }
else if (signalProb < 1.0
e-9 || backgroundProb < 1.0
e-9)
326 result[
result.size() -
size +
j] = signalDiff / signalProb - backgroundDiff / backgroundProb;
329 double sum = signalProb + backgroundProb;
333 (signalDiff * backgroundProb - signalProb * backgroundDiff) / (sum * sum);
334 }
else if (neverUndefined)
338 signal *= signalProb;
339 background *= backgroundProb;
340 double s = signalDiff / signalProb;
343 double b = backgroundDiff / backgroundProb;
360 }
else if (logOutput) {
361 if (signal < 1.0
e-9 && background < 1.0
e-9) {
366 }
else if (signal < 1.0
e-9 || background < 1.0
e-9)
372 double factor = signal * background / ((signal + background) * (signal + background));
373 for (std::vector<double>::iterator
p =
result.begin();
p !=
result.end(); ++
p)
constexpr bool isNotFinite(T x)