Logo ROOT  
Reference Guide
RooConstraintSum.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/**
18\file RooConstraintSum.cxx
19\class RooConstraintSum
20\ingroup Roofitcore
21
22RooConstraintSum calculates the sum of the -(log) likelihoods of
23a set of RooAbsPfs that represent constraint functions. This class
24is used to calculate the composite -log(L) of constraints to be
25added to the regular -log(L) in RooAbsPdf::fitTo() with Constrain(..)
26arguments.
27**/
28
29
30#include "RooConstraintSum.h"
31#include "RooAbsData.h"
32#include "RooAbsReal.h"
33#include "RooAbsPdf.h"
34#include "RooErrorHandler.h"
35#include "RooArgSet.h"
36#include "RooMsgService.h"
37#include "RooHelpers.h"
38#include "RooWorkspace.h"
39#include "RooAbsRealLValue.h"
41
42#include <memory>
43
45
46
47////////////////////////////////////////////////////////////////////////////////
48/// Constructor with set of constraint p.d.f.s. All elements in constraintSet must inherit from RooAbsPdf.
49
50RooConstraintSum::RooConstraintSum(const char* name, const char* title, const RooArgSet& constraintSet, const RooArgSet& normSet, bool takeGlobalObservablesFromData) :
51 RooAbsReal(name, title),
52 _set1("set1","First set of components",this),
53 _paramSet("paramSet","Set of parameters",this),
54 _takeGlobalObservablesFromData{takeGlobalObservablesFromData}
55{
56 for (const auto comp : constraintSet) {
57 if (!dynamic_cast<RooAbsPdf*>(comp)) {
58 coutE(InputArguments) << "RooConstraintSum::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
59 << " is not of type RooAbsPdf" << std::endl ;
61 }
62 _set1.add(*comp) ;
63 }
64
65 _paramSet.add(normSet) ;
66}
67
68
69////////////////////////////////////////////////////////////////////////////////
70/// Copy constructor.
71
73 RooAbsReal(other, name),
74 _set1("set1",this,other._set1),
75 _paramSet("paramSet",this,other._paramSet),
76 _takeGlobalObservablesFromData{other._takeGlobalObservablesFromData}
77{
78}
79
80
81////////////////////////////////////////////////////////////////////////////////
82/// Return sum of -log of constraint p.d.f.s.
83
85{
86 Double_t sum(0);
87
88 for (const auto comp : _set1) {
89 sum -= static_cast<RooAbsPdf*>(comp)->getLogVal(&_paramSet);
90 }
91
92 return sum;
93}
94
95
96////////////////////////////////////////////////////////////////////////////////
97/// Replace the variables in this RooConstraintSum with the global observables
98/// in the dataset if they match by name. This function will do nothing if this
99/// RooConstraintSum is configured to not use the global observables stored in
100/// datasets.
101bool RooConstraintSum::setData(RooAbsData const& data, bool /*cloneData=true*/) {
102 if(_takeGlobalObservablesFromData && data.getGlobalObservables()) {
104 }
105 return true;
106}
107
108
109namespace {
110
111std::unique_ptr<RooArgSet> getGlobalObservables(
112 RooAbsPdf const& pdf, RooArgSet const* globalObservables, const char* globalObservablesTag)
113{
114
115 if(globalObservables && globalObservablesTag) {
116 // error!
117 std::string errMsg = "RooAbsPdf::fitTo: GlobalObservables and GlobalObservablesTag options mutually exclusive!";
118 oocoutE(&pdf, Minimization) << errMsg << std::endl;
119 throw std::invalid_argument(errMsg);
120 }
121 if(globalObservables) {
122 // pass-throught of global observables
123 return std::make_unique<RooArgSet>(*globalObservables);
124 }
125
126 if(globalObservablesTag) {
127 oocoutI(&pdf, Minimization) << "User-defined specification of global observables definition with tag named '"
128 << globalObservablesTag << "'" << std::endl;
129 } else {
130 // Neither GlobalObservables nor GlobalObservablesTag has been processed -
131 // try if a default tag is defined in the head node Check if head not
132 // specifies default global observable tag
133 if(auto defaultGlobalObservablesTag = pdf.getStringAttribute("DefaultGlobalObservablesTag")) {
134 oocoutI(&pdf, Minimization) << "p.d.f. provides built-in specification of global observables definition "
135 << "with tag named '" << defaultGlobalObservablesTag << "'" << std::endl;
136 globalObservablesTag = defaultGlobalObservablesTag;
137 }
138 }
139
140 if(globalObservablesTag) {
141 std::unique_ptr<RooArgSet> allVars{pdf.getVariables()} ;
142 return std::unique_ptr<RooArgSet>{static_cast<RooArgSet*>(allVars->selectByAttrib(globalObservablesTag, true))};
143 }
144
145 // no global observables specified
146 return nullptr;
147}
148
149
150RooArgSet const* tryToGetConstraintSetFromWorkspace(
151 RooAbsPdf const& pdf, RooWorkspace * workspace, std::string const& constraintSetCacheName) {
152 if(!workspace) return nullptr;
153
154 if(workspace->set(constraintSetCacheName.c_str())) {
155 // retrieve from cache
156 const RooArgSet *constr = workspace->set(constraintSetCacheName.c_str());
157 oocoutI(&pdf, Minimization)
158 << "createConstraintTerm picked up cached constraints from workspace with " << constr->size()
159 << " entries" << std::endl;
160 return constr;
161 }
162 return nullptr;
163}
164
165
166} // namespace
167
168
169////////////////////////////////////////////////////////////////////////////////
170/// Create the parameter constraint sum to add to the negative log-likelihood.
171/// \return a `nullptr` if the parameters are unconstrained.
172/// \param[in] name Name of the created RooConstraintSum object.
173/// \param[in] pdf The pdf model whose parameters should be constrained.
174/// Constraint terms will be extracted from RooProdPdf instances
175/// that are servers of the pdf (internal constraints).
176/// \param[in] data Dataset used in the fit with the constraint sum. It is
177/// used to figure out which are the observables and also to get the
178/// global observables definition and values if they are stored in
179/// the dataset.
180/// \param[in] constrainedParameters Set of parameters to constrain. If `nullptr`, all
181/// parameters will be considered.
182/// \param[in] externalConstraints Set of constraint terms that are not
183/// embedded in the pdf (external constraints).
184/// \param[in] globalObservables The normalization set for the constraint terms.
185/// If it is `nullptr`, the set of all constrained parameters will
186/// be used as the normalization set.
187/// \param[in] globalObservablesTag Alternative to define the normalization set
188/// for the constraint terms. All constrained parameters that have
189/// the attribute with the tag defined by `globalObservablesTag` are
190/// used. The `globalObservables` and `globalObservablesTag`
191/// parameters are mutually exclusive, meaning at least one of them
192/// has to be `nullptr`.
193/// \param[in] takeGlobalObservablesFromData If the dataset should be used to automatically
194/// define the set of global observables. If this is the case and the
195/// set of global observables is still defined manually with the
196/// `globalObservables` or `globalObservablesTag` parameters, the
197/// values of all global observables that are not stored in the
198/// dataset are taken from the model.
199/// \param[in] cloneConstraints true to clone constraints
200/// \param[in] workspace RooWorkspace to cache the set of constraints.
201std::unique_ptr<RooAbsReal> RooConstraintSum::createConstraintTerm(
202 std::string const& name,
203 RooAbsPdf const& pdf,
204 RooAbsData const& data,
205 RooArgSet const* constrainedParameters,
206 RooArgSet const* externalConstraints,
207 RooArgSet const* globalObservables,
208 const char* globalObservablesTag,
209 bool takeGlobalObservablesFromData,
210 bool cloneConstraints,
211 RooWorkspace * workspace)
212{
213 RooArgSet const& observables = *data.get();
214
215 bool doStripDisconnected = false ;
216
217 // If no explicit list of parameters to be constrained is specified apply default algorithm
218 // All terms of RooProdPdfs that do not contain observables and share a parameters with one or more
219 // terms that do contain observables are added as constrainedParameters.
220 RooArgSet cPars;
221 if(constrainedParameters) {
222 cPars.add(*constrainedParameters);
223 } else {
224 pdf.getParameters(&observables,cPars,false);
225 doStripDisconnected = true;
226 }
227
228 // Collect internal and external constraint specifications
229 RooArgSet allConstraints ;
230
231 auto observableNames = RooHelpers::getColonSeparatedNameString(observables);
232 auto constraintSetCacheName = std::string("CACHE_CONSTR_OF_PDF_") + pdf.GetName() + "_FOR_OBS_" + observableNames;
233
234 if (RooArgSet const* constr = tryToGetConstraintSetFromWorkspace(pdf, workspace, constraintSetCacheName)) {
235 allConstraints.add(*constr);
236 } else {
237
238 if (!cPars.empty()) {
239 std::unique_ptr<RooArgSet> internalConstraints{pdf.getAllConstraints(observables, cPars, doStripDisconnected)};
240 allConstraints.add(*internalConstraints);
241 }
242 if (externalConstraints) {
243 allConstraints.add(*externalConstraints);
244 }
245
246 // write to cache
247 if (workspace) {
248 oocoutI(&pdf, Minimization)
249 << "createConstraintTerm: caching constraint set under name "
250 << constraintSetCacheName << " with " << allConstraints.size() << " entries" << std::endl;
251 workspace->defineSetInternal(constraintSetCacheName.c_str(), allConstraints);
252 }
253 }
254
255 if (!allConstraints.empty()) {
256
257 oocoutI(&pdf, Minimization) << " Including the following constraint terms in minimization: "
258 << allConstraints << std::endl ;
259
260 // Identify global observables in the model.
261 auto glObs = getGlobalObservables(pdf, globalObservables, globalObservablesTag);
262 if(data.getGlobalObservables() && takeGlobalObservablesFromData) {
263 if(!glObs) {
264 // There were no global observables specified, but there are some in the
265 // dataset. We will just take them from the dataset.
266 oocoutI(&pdf, Minimization)
267 << "The following global observables have been automatically defined according to the dataset "
268 << "which also provides their values: " << *data.getGlobalObservables() << std::endl;
269 glObs = std::make_unique<RooArgSet>(*data.getGlobalObservables());
270 } else {
271 // There are global observables specified by the user and also some in
272 // the dataset.
273 RooArgSet globalsFromDataset;
274 data.getGlobalObservables()->selectCommon(*glObs, globalsFromDataset);
275 oocoutI(&pdf, Minimization)
276 << "The following global observables have been defined: " << *glObs
277 << "," << " with the values of " << globalsFromDataset
278 << " obtained from the dataset and the other values from the model." << std::endl;
279 }
280 } else if(glObs) {
281 oocoutI(&pdf, Minimization)
282 << "The following global observables have been defined and their values are taken from the model: "
283 << *glObs << std::endl;
284 // in this case we don;t take global observables from data
285 takeGlobalObservablesFromData = false;
286 } else {
287 if (!glObs)
288 oocoutI(&pdf, Minimization)
289 << "The global observables are not defined , normalize constraints with respect to the parameters " << cPars
290 << std::endl;
291 takeGlobalObservablesFromData = false;
292 }
293
294 // The constraint terms need to be cloned, because the global observables
295 // might be changed to have the same values as stored in data.
296 if (cloneConstraints) {
297 RooConstraintSum constraintTerm{name.c_str(), "nllCons", allConstraints, glObs ? *glObs : cPars,
298 takeGlobalObservablesFromData};
299 std::unique_ptr<RooAbsReal> constraintTermClone{static_cast<RooAbsReal *>(constraintTerm.cloneTree())};
300
301 // The parameters that are not connected to global observables from data
302 // need to be redirected to the original args to get the changes made by
303 // the minimizer. This excludes the global observables, where we take the
304 // clones with the values set to the values from the dataset if available.
305 RooArgSet allOriginalParams;
306 constraintTerm.getParameters(nullptr, allOriginalParams);
307 constraintTermClone->recursiveRedirectServers(allOriginalParams);
308
309 // Redirect the global observables to the ones from the dataset if applicable.
310 static_cast<RooConstraintSum *>(constraintTermClone.get())->setData(data, false);
311
312 // The computation graph for the constraints is very small, no need to do
313 // the tracking of clean and dirty nodes here.
314 constraintTermClone->setOperMode(RooAbsArg::ADirty);
315
316 return constraintTermClone;
317 }
318 // case we do not clone constraints (e.g. when using new Driver)
319 else {
320 // when we don't clone we need that global observables are not from data
321 if (takeGlobalObservablesFromData) {
322 oocoutE(&pdf, InputArguments) << "RooAbsPdf::Fit: Batch mode does not support yet GlobalObservable from data, use model as GlobalObservableSource " << std::endl;
323 throw std::invalid_argument("Invalid arguments for GlobalObservables in batch mode");
324 }
325 std::unique_ptr<RooAbsReal> constraintTerm(
326 new RooConstraintSum(name.c_str(), "nllCons", allConstraints, glObs ? *glObs : cPars, false));
327 return constraintTerm;
328 }
329 }
330
331 // no constraints
332 return nullptr;
333}
#define oocoutE(o, a)
Definition: RooMsgService.h:48
#define oocoutI(o, a)
Definition: RooMsgService.h:45
#define coutE(a)
Definition: RooMsgService.h:33
#define ClassImp(name)
Definition: Rtypes.h:375
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
char name[80]
Definition: TGX11.cxx:110
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
Definition: RooAbsArg.cxx:327
RooArgSet * getVariables(Bool_t stripDisconnected=kTRUE) const
Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
Definition: RooAbsArg.cxx:2067
RooArgSet * getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
Definition: RooAbsArg.cxx:569
Bool_t recursiveRedirectServers(const RooAbsCollection &newServerList, Bool_t mustReplaceAll=kFALSE, Bool_t nameChange=kFALSE, Bool_t recurseInNewSet=kTRUE)
Recursively replace all servers with the new servers in newSet.
Definition: RooAbsArg.cxx:1197
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
bool empty() const
Storage_t::size_type size() const
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition: RooAbsData.h:61
RooArgSet const * getGlobalObservables() const
Returns snapshot of global observables stored in this data.
Definition: RooAbsData.h:302
virtual RooArgSet * getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, Bool_t stripDisconnected=kTRUE) const
This helper function finds and collects all constraints terms of all component p.d....
Definition: RooAbsPdf.cxx:3410
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:63
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:57
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
RooConstraintSum calculates the sum of the -(log) likelihoods of a set of RooAbsPfs that represent co...
Double_t evaluate() const override
Return sum of -log of constraint p.d.f.s.
RooSetProxy _paramSet
Set of parameters to which constraints apply.
bool setData(RooAbsData const &data, bool cloneData=true)
Replace the variables in this RooConstraintSum with the global observables in the dataset if they mat...
RooListProxy _set1
Set of constraint terms.
static std::unique_ptr< RooAbsReal > createConstraintTerm(std::string const &name, RooAbsPdf const &pdf, RooAbsData const &data, RooArgSet const *constrainedParameters, RooArgSet const *externalConstraints, RooArgSet const *globalObservables, const char *globalObservablesTag, bool takeGlobalObservablesFromData, bool cloneConstraints, RooWorkspace *workspace)
Create the parameter constraint sum to add to the negative log-likelihood.
const bool _takeGlobalObservablesFromData
If the global observable values are taken from data.
static void softAbort()
Soft abort function that interrupts macro execution but doesn't kill ROOT.
The RooWorkspace is a persistable container for RooFit projects.
Definition: RooWorkspace.h:43
Bool_t defineSetInternal(const char *name, const RooArgSet &aset)
const RooArgSet * set(const char *name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
@ Minimization
Definition: RooGlobalFunc.h:63
@ InputArguments
Definition: RooGlobalFunc.h:64
std::string getColonSeparatedNameString(RooArgSet const &argSet)
Create a string with all sorted names of RooArgSet elements separated by colons.
Definition: RooHelpers.cxx:252
static uint64_t sum(uint64_t i)
Definition: Factory.cxx:2345