Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooExtendPdf.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/** \class RooExtendPdf
18RooExtendPdf is a wrapper around an existing PDF that adds a
19parameteric extended likelihood term to the PDF, optionally divided by a
20fractional term from a partial normalization of the PDF:
21\f[
22 n_\mathrm{Expected} = N \quad \text{or} \quad n_\mathrm{Expected} = N / \mathrm{frac}
23\f]
24where \f$ N \f$ is supplied as a RooAbsReal to RooExtendPdf.
25The fractional term is defined as
26\f[
27 \mathrm{frac} = \frac{\int_\mathrm{cutRegion[x]} \mathrm{pdf}(x,y) \; \mathrm{d}x \mathrm{d}y}{
28 \int_\mathrm{normRegion[x]} \mathrm{pdf}(x,y) \; \mathrm{d}x \mathrm{d}y}
29\f]
30
31where \f$ x \f$ is the set of dependents involved in the selection region and \f$ y \f$
32is the set of remaining dependents.
33
34\f$ \mathrm{cutRegion}[x] \f$ is a limited integration range that is contained in
35the nominal integration range \f$ \mathrm{normRegion}[x] \f$.
36*/
37
38#include "Riostream.h"
39
40#include "RooArgList.h"
41#include "RooConstVar.h"
42#include "RooExtendPdf.h"
43#include "RooFormulaVar.h"
44#include "RooMsgService.h"
45#include "RooNameReg.h"
46#include "RooProduct.h"
47#include "RooRatio.h"
48#include "RooRealVar.h"
49
50#include "RooFitImplHelpers.h"
51
53
54using std::endl;
55
56
57RooExtendPdf::RooExtendPdf(const char *name, const char *title, RooAbsPdf& pdf,
58 RooAbsReal& norm, const char* rangeName)
59 : RooExtendPdf{name, title, pdf, RooAbsReal::Ref{norm}, rangeName} {}
60
61/// Constructor. The ExtendPdf behaves identical to the supplied input pdf,
62/// but adds an extended likelihood term. expectedEvents() will return
63/// `norm` if `rangeName` remains empty. If `rangeName` is not empty,
64/// `norm` will refer to this range, and expectedEvents will return the
65/// total number of events over the full range of the observables.
66/// \param[in] name Name of the pdf
67/// \param[in] title Title of the pdf (for plotting)
68/// \param[in] pdf The pdf to be extended
69/// \param[in] norm Expected number of events
70/// \param[in] rangeName If given, the number of events denoted by `norm` is interpreted as
71/// the number of events in this range only
72RooExtendPdf::RooExtendPdf(const char *name, const char *title, RooAbsPdf& pdf,
73 RooAbsReal::Ref norm, const char* rangeName) :
74 RooAbsPdf(name,title),
75 _pdf("pdf", "PDF", this, pdf),
76 _n("n","Normalization",this,norm),
77 _rangeName(RooNameReg::ptr(rangeName))
78{
79
80 // Copy various setting from pdf
81 setUnit(_pdf->getUnit()) ;
83}
84
85
86
89 _pdf("pdf",this,other._pdf),
90 _n("n",this,other._n),
91 _rangeName(other._rangeName)
92{
93 // Copy constructor
94}
95
96
97/// Return the number of expected events over the full range of all variables.
98/// `norm`, the variable set as normalisation constant in the constructor,
99/// will yield the number of events in the range set in the constructor. That is, the function returns
100/// \f[
101/// N = \mathrm{norm} \; \cdot \; \frac{\int_{(x_F,y_F)} \mathrm{pdf}(x,y) }{\int_{(x_C,y_F)} \mathrm{pdf}(x,y)}
102/// \f]
103/// Where \f$ x \f$ is the set of dependents with a restricted range (defined by `rangeName` in the constructor),
104/// and \f$ y \f$ are the other dependents. \f$ x_C \f$ is the integration
105/// of \f$ x \f$ over the restricted range, and \f$ x_F \f$ is the integration of
106/// \f$ x \f$ over the full range. `norm` is the number of events given as parameter to the constructor.
107///
108/// If the nested PDF can be extended, \f$ N \f$ is further scaled by its expected number of events.
110{
111 const RooAbsPdf& pdf = *_pdf;
112
113 if (_rangeName && (!nset || nset->empty())) {
114 coutW(InputArguments) << "RooExtendPdf::expectedEvents(" << GetName() << ") WARNING: RooExtendPdf needs non-null normalization set to calculate fraction in range "
115 << _rangeName << ". Results may be nonsensical" << std::endl ;
116 }
117
118 double nExp = _n ;
119
120 // Optionally multiply with fractional normalization
121 if (_rangeName) {
122
123 double fracInt = pdf.getNormObj(nset,nset,_rangeName)->getVal();
124
125
126 if ( fracInt == 0. || _n == 0.) {
127 coutW(Eval) << "RooExtendPdf(" << GetName() << ") WARNING: nExpected = " << _n << " / "
128 << fracInt << " for nset = " << (nset?*nset:RooArgSet()) << std::endl ;
129 }
130
131 nExp /= fracInt ;
132 }
133
134 // Multiply with original Nexpected, if defined
135 if (pdf.canBeExtended()) nExp *= pdf.expectedEvents(nset) ;
136
137 return nExp ;
138}
139
140
141/// RooExtendPdf is self-normalized (selfNormalized() returns true), which means
142/// it delegates the normalization of the shape entirely to the wrapped pdf.
143/// The fractional correction of the extended term in expectedEvents() /
144/// createExpectedEventsFunc() is also evaluated from the wrapped pdf. For a
145/// likelihood over a sub-range this means the wrapped pdf must be normalized
146/// over the same range as this RooExtendPdf (the fit range), otherwise both the
147/// shape term (biasing the shape parameters) and the extended term (collapsing
148/// the yield to the fit-range count instead of reinterpreting it to the range
149/// requested in the constructor) are wrong.
150///
151/// Since the normalization range of a pdf is not automatically propagated to
152/// its servers, we propagate it explicitly to the wrapped pdf while the
153/// computation graph is compiled, mirroring what RooAddPdf does for its
154/// component pdfs. This is only done in likelihood mode: for a binned chi2, the
155/// per-bin predictions must stay normalized over the full range so that the
156/// chi2 remains additive across sub-ranges. See GitHub issue #22959.
157std::unique_ptr<RooAbsArg>
159{
160 // RAII to temporarily set the wrapped pdf's normalization range to the one
161 // of this RooExtendPdf and reset it after compilation.
162 struct NormRangeGuard {
163 NormRangeGuard(RooAbsPdf &pdf, const char *rangeName)
164 : _pdf{pdf}, _oldNormRange{pdf.normRange() ? pdf.normRange() : ""}
165 {
166 _pdf.setNormRange(rangeName);
167 }
168 ~NormRangeGuard() { _pdf.setNormRange(_oldNormRange.empty() ? nullptr : _oldNormRange.c_str()); }
169 RooAbsPdf &_pdf;
170 std::string _oldNormRange;
171 };
172
173 if (!ctx.likelihoodMode()) {
175 }
176
177 NormRangeGuard guard{*_pdf, normRange()};
179}
180
181
182std::unique_ptr<RooAbsReal> RooExtendPdf::createExpectedEventsFunc(const RooArgSet *nset) const
183{
184 const RooAbsPdf& pdf = *_pdf;
185
187 prodList.add(*_n);
188
189 // Optionally multiply with fractional normalization
190 std::unique_ptr<RooAbsReal> rangeFactor;
191 if (_rangeName) {
192 std::unique_ptr<RooAbsReal> fracInteg{pdf.createIntegral(*nset, *nset, RooNameReg::str(_rangeName))};
193 // Create one over integral term
194 auto rangeFactorName = std::string("one_over_") + fracInteg->GetName();
195 rangeFactor = std::make_unique<RooRatio>(rangeFactorName.c_str(), rangeFactorName.c_str(), RooFit::RooConst(1.0), *fracInteg);
196 rangeFactor->addOwnedComponents(std::move(fracInteg));
197 prodList.add(*rangeFactor);
198 }
199
200 // Multiply with original Nexpected, if defined
201 std::unique_ptr<RooAbsReal> pdfExpectedEvents;
202 if (pdf.canBeExtended()) {
205 }
206
207 auto name = std::string(GetName()) + "_expectedEvents";
208 if (nset) {
209 name += "[" + RooHelpers::getColonSeparatedNameString(*nset, ',') + "]";
210 }
211 auto out = std::make_unique<RooProduct>(name.c_str(), name.c_str(), prodList);
212 if(rangeFactor) {
213 out->addOwnedComponents(std::move(rangeFactor));
214 }
216 out->addOwnedComponents(std::move(pdfExpectedEvents));
217 }
218 return out;
219}
#define coutW(a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:148
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
virtual double expectedEvents(const RooArgSet *nset) const
Return expected number of events to be used in calculation of extended likelihood.
bool canBeExtended() const
If true, PDF can provide extended likelihood term.
Definition RooAbsPdf.h:214
const char * normRange() const
Definition RooAbsPdf.h:246
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,...
virtual const RooAbsReal * getNormObj(const RooArgSet *set, const RooArgSet *iset, const TNamed *rangeName=nullptr) const
Return pointer to RooAbsReal object that implements calculation of integral over observables iset in ...
A RooAbsReal::Ref can be constructed from a RooAbsReal& or a double that will be implicitly converted...
Definition RooAbsReal.h:72
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
void setUnit(const char *unit)
Definition RooAbsReal.h:153
const char * getPlotLabel() const
Get the label associated with the variable.
const Text_t * getUnit() const
Definition RooAbsReal.h:149
void setPlotLabel(const char *label)
Set the label associated with this variable.
RooFit::OwningPtr< RooAbsReal > createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create an object that represents the integral of the function over one or more observables listed in ...
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
std::unique_ptr< RooAbsReal > createExpectedEventsFunc(const RooArgSet *nset) const override
Returns an object that represents the expected number of events for a given normalization set,...
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
RooExtendPdf is self-normalized (selfNormalized() returns true), which means it delegates the normali...
RooAbsPdf const & pdf() const
RooTemplateProxy< RooAbsPdf > _pdf
Input p.d.f.
double expectedEvents(const RooArgSet *nset) const override
Return the number of expected events over the full range of all variables.
const TNamed * _rangeName
Name of subset range.
RooExtendPdf()=default
RooTemplateProxy< RooAbsReal > _n
Number of expected events.
Registry for const char* names.
Definition RooNameReg.h:26
static const char * str(const TNamed *ptr)
Return C++ string corresponding to given TNamed pointer.
Definition RooNameReg.h:39
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
RooConstVar & RooConst(double val)
std::string getColonSeparatedNameString(RooArgSet const &argSet, char delim=':')