50constexpr const char *RooNLLVarNew::weightVarName;
51constexpr const char *RooNLLVarNew::weightVarNameSumW2;
66 _observables(
"!observables",
"List of observables", this),
67 _weightVar{
"!weightVar",
"weightVar", this, weightVar, true, false}
70 _observables.add(*obs);
73 RooOffsetPdf(
const RooOffsetPdf &other,
const char *
name =
nullptr)
75 _observables(
"!servers", this, other._observables),
76 _weightVar{
"!weightVar", this, other._weightVar}
79 TObject *
clone(
const char *newname)
const override {
return new RooOffsetPdf(*
this, newname); }
84 std::size_t nEvents =
output.size();
86 std::span<const double> weights = ctx.
at(_weightVar);
94 for (std::size_t i = 0; i < nEvents; ++i) {
96 var->setVal(ctx.
at(var)[i]);
98 dataHist.
add(_observables, weights[weights.size() == 1 ? 0 : i]);
102 RooHistPdf pdf{
"offsetPdf",
"offsetPdf", _observables, dataHist};
103 for (std::size_t i = 0; i < nEvents; ++i) {
105 var->setVal(ctx.
at(var)[i]);
112 double evaluate()
const override {
return 0.0; }
127RooNLLVarNew::RooNLLVarNew(
const char *
name,
const char *title,
RooAbsPdf &pdf,
RooArgSet const &observables,
130 _pdf{
"pdf",
"pdf", this, pdf},
131 _weightVar{
"weightVar",
"weightVar", this, *dummyVar(weightVarName), true, false, true},
132 _weightSquaredVar{weightVarNameSumW2, weightVarNameSumW2, this, *dummyVar(
"weightSquardVar"), true, false, true},
133 _binnedL{pdf.getAttribute(
"BinnedLikelihoodActive")}
141 if (_binnedL && !pdf.
getAttribute(
"BinnedLikelihoodActiveYields")) {
142 fillBinWidthsFromPdfBoundaries(pdf, obs);
145 if (isExtended && !_binnedL) {
147 if (expectedEvents) {
149 std::make_unique<RooTemplateProxy<RooAbsReal>>(
"expectedEvents",
"expectedEvents",
this, *expectedEvents);
150 addOwnedComponents(std::move(expectedEvents));
154 resetWeightVarNames();
161 auto offsetPdf = std::make_unique<RooOffsetPdf>(
"_offset_pdf",
"_offset_pdf", obs, *_weightVar);
162 _offsetPdf = std::make_unique<RooTemplateProxy<RooAbsPdf>>(
"offsetPdf",
"offsetPdf",
this, *offsetPdf);
163 addOwnedComponents(std::move(offsetPdf));
167RooNLLVarNew::RooNLLVarNew(
const RooNLLVarNew &other,
const char *
name)
169 _pdf{
"pdf", this, other._pdf},
170 _weightVar{
"weightVar", this, other._weightVar},
171 _weightSquaredVar{
"weightSquaredVar", this, other._weightSquaredVar},
172 _weightSquared{other._weightSquared},
173 _binnedL{other._binnedL},
176 _prefix{other._prefix},
179 if (other._expectedEvents) {
180 _expectedEvents = std::make_unique<RooTemplateProxy<RooAbsReal>>(
"expectedEvents",
this, *other._expectedEvents);
184void RooNLLVarNew::fillBinWidthsFromPdfBoundaries(
RooAbsReal const &pdf,
RooArgSet const &observables)
187 if (!
_binw.empty()) {
191 if (observables.
size() != 1) {
192 throw std::runtime_error(
"BinnedPdf optimization only works with a 1D pdf.");
195 std::list<double> *boundaries = pdf.
binBoundaries(*var, var->getMin(), var->getMax());
196 std::list<double>::iterator biter = boundaries->begin();
197 _binw.resize(boundaries->size() - 1);
198 double lastBound = (*biter);
201 while (biter != boundaries->end()) {
202 _binw[ibin] = (*biter) - lastBound;
203 lastBound = (*biter);
211 std::span<const double> weights)
const
216 const bool predsAreYields =
_binw.empty();
218 for (std::size_t i = 0; i < preds.size(); ++i) {
221 double N = weights[i];
222 double mu = preds[i];
223 if (!predsAreYields) {
227 if (mu <= 0 && N > 0) {
229 logEvalError(
Form(
"Observed %f events in bin %lu with zero event yield",
N, (
unsigned long)i));
232 sumWeightKahanSum +=
N;
236 finalizeResult(ctx,
result, sumWeightKahanSum.Sum());
241 std::span<const double> weights = ctx.
at(_weightVar);
242 std::span<const double> weightsSumW2 = ctx.
at(_weightSquaredVar);
245 return doEvalBinnedL(ctx, ctx.
at(&*_pdf), _weightSquared ? weightsSumW2 : weights);
248 auto config = ctx.
config(
this);
252 _sumWeight = weights.size() == 1 ? weights[0] *
probas.size()
254 if (_expectedEvents && _weightSquared && _sumWeight2 == 0.0) {
255 _sumWeight2 = weights.size() == 1 ? weightsSumW2[0] *
probas.size()
262 if (nllOut.nLargeValues > 0) {
263 oocoutW(&*_pdf, Eval) <<
"RooAbsPdf::getLogVal(" << _pdf->GetName()
264 <<
") WARNING: top-level pdf has unexpectedly large values" << std::endl;
266 for (std::size_t i = 0; i < nllOut.nNonPositiveValues; ++i) {
267 _pdf->logEvalError(
"getLogVal() top-level p.d.f not greater than zero");
269 for (std::size_t i = 0; i < nllOut.nNaNValues; ++i) {
270 _pdf->logEvalError(
"getLogVal() top-level p.d.f evaluates to NaN");
273 if (_expectedEvents) {
274 std::span<const double> expected = ctx.
at(*_expectedEvents);
275 nllOut.nllSum += _pdf->extendedTerm(_sumWeight, expected[0], _weightSquared ? _sumWeight2 : 0.0,
_doBinOffset);
278 finalizeResult(ctx, {nllOut.nllSum, nllOut.nllSumCarry}, _sumWeight);
285void RooNLLVarNew::setPrefix(std::string
const &prefix)
289 resetWeightVarNames();
292void RooNLLVarNew::resetWeightVarNames()
294 _weightVar->SetName((_prefix + weightVarName).c_str());
295 _weightSquaredVar->SetName((_prefix + weightVarNameSumW2).c_str());
297 (*_offsetPdf)->SetName((_prefix +
"_offset_pdf").c_str());
303void RooNLLVarNew::applyWeightSquared(
bool flag)
305 _weightSquared = flag;
308void RooNLLVarNew::enableOffsetting(
bool flag)
336 if (_binnedL && !_pdf->getAttribute(
"BinnedLikelihoodActiveYields")) {
337 std::stringstream errorMsg;
338 errorMsg <<
"RooNLLVarNew::translate(): binned likelihood optimization is only supported when raw pdf "
339 "values can be interpreted as yields."
340 <<
" This is not the case for HistFactory models written with ROOT versions before 6.26.00";
341 coutE(InputArguments) << errorMsg.str() << std::endl;
342 throw std::runtime_error(errorMsg.str());
351 const bool needWeightSum = _expectedEvents ||
_simCount > 1;
358 std::string simCountStr = std::to_string(
static_cast<double>(
_simCount));
359 ctx.
addToCodeBody(resName +
" += " + weightSumName +
" * std::log(" + simCountStr +
");\n");
367 std::string term = ctx.
buildCall(
"RooFit::Detail::MathFuncs::nll", _pdf, _weightVar, _binnedL, 0);
370 if (_expectedEvents) {
371 std::string expected = ctx.
getResult(**_expectedEvents);
372 ctx.
addToCodeBody(resName +
" += " + expected +
" - " + weightSumName +
" * std::log(" + expected +
");\n");
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
bool _doOffset
Apply interval value offset to control numeric precision?
void enableOffsetting(bool flag) override
ROOT::Math::KahanSum< double > _offset
! Offset as KahanSum to avoid loss of precision
Int_t _simCount
Total number of component p.d.f.s in RooSimultaneous (if any)
double evaluate() const override
TObject * clone(const char *newname) const override
std::vector< double > _binw
!
std::unique_ptr< RooAbsPdf > _offsetPdf
! An optional per-bin likelihood offset
void enableBinOffsetting(bool on=true)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
The Kahan summation is a compensated summation algorithm, which significantly reduces numerical error...
Common abstract base class for objects that represent a value and a "shape" in RooFit.
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
Storage_t::size_type size() const
RooAbsArg * first() const
Abstract interface for all probability density functions.
virtual std::unique_ptr< RooAbsReal > createExpectedEventsFunc(const RooArgSet *nset) const
Returns an object that represents the expected number of events for a given normalization set,...
Abstract base class for objects that represent a real value and implements functionality common to al...
virtual std::list< double > * binBoundaries(RooAbsRealLValue &obs, double xlo, double xhi) const
Retrieve bin boundaries if this distribution is binned in obs.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Represents a constant real-valued object.
Container class to hold N-dimensional binned data.
void add(const RooArgSet &row, double wgt=1.0) override
Add wgt to the bin content enclosed by the coordinates passed in row.
A class to maintain the context for squashing of RooFit models into code.
std::string buildCall(std::string const &funcname, Args_t const &...args)
Build the code to call the function with name funcname, passing some arguments.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addToCodeBody(RooAbsArg const *klass, std::string const &in)
Adds the input string to the squashed code body.
std::string const & getResult(RooAbsArg const &arg)
Gets the result for the given node using the node name.
void addToGlobalScope(std::string const &str)
Adds the given string to the string block that will be emitted at the top of the squashed function.
std::unique_ptr< LoopScope > beginLoop(RooAbsArg const *in)
Create a RAII scope for iterating over vector observables.
std::span< const double > at(RooAbsArg const *arg, RooAbsArg const *caller=nullptr)
std::span< double > output()
RooBatchCompute::Config config(RooAbsArg const *arg) const
void setOutputWithOffset(RooAbsArg const *arg, ROOT::Math::KahanSum< double > val, ROOT::Math::KahanSum< double > const &offset)
Sets the output value with an offset.
A propability density function sampled from a multidimensional histogram.
Variable that can be changed from the outside.
Mother of all ROOT objects.
double reduceSum(Config cfg, InputArr input, size_t n)
ReduceNLLOutput reduceNLL(Config cfg, std::span< const double > probas, std::span< const double > weights, std::span< const double > offsetProbas)
double nll(double pdf, double weight, int binnedL, int doBinOffset)
std::string makeValidVarName(std::string const &in)
OffsetMode
For setting the offset mode with the Offset() command argument to RooAbsPdf::fitTo()
void probas(TString dataset, TString fin="TMVA.root", Bool_t useTMVAStyle=kTRUE)