Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 _takeGlobalObservablesFromData{takeGlobalObservablesFromData}
54{
55 for (const auto comp : constraintSet) {
56 if (!dynamic_cast<RooAbsPdf*>(comp)) {
57 coutE(InputArguments) << "RooConstraintSum::ctor(" << GetName() << ") ERROR: component " << comp->GetName()
58 << " is not of type RooAbsPdf" << std::endl ;
60 }
61 _set1.add(*comp) ;
62 }
63
64 _paramSet.add(normSet) ;
65}
66
67
68////////////////////////////////////////////////////////////////////////////////
69/// Copy constructor.
70
72 RooAbsReal(other, name),
73 _set1("set1",this,other._set1),
74 _paramSet(other._paramSet),
75 _takeGlobalObservablesFromData{other._takeGlobalObservablesFromData}
76{
77}
78
79
80////////////////////////////////////////////////////////////////////////////////
81/// Return sum of -log of constraint p.d.f.s.
82
84{
85 Double_t sum(0);
86
87 for (const auto comp : _set1) {
88 sum -= static_cast<RooAbsPdf*>(comp)->getLogVal(&_paramSet);
89 }
90
91 return sum;
92}
93
94
95void RooConstraintSum::computeBatch(cudaStream_t *, double *output, size_t /*size*/,
96 RooFit::Detail::DataMap const &dataMap) const
97{
98 double sum(0);
99
100 for (const auto comp : _set1) {
101 sum -= std::log(dataMap.at(comp)[0]);
102 }
103
104 output[0] = sum;
105}
106
107
108std::unique_ptr<RooArgSet> RooConstraintSum::fillNormSetForServer(RooArgSet const& /*normSet*/, RooAbsArg const& /*server*/) const {
109 return std::make_unique<RooArgSet>(_paramSet);
110}
111
112
113////////////////////////////////////////////////////////////////////////////////
114/// Replace the variables in this RooConstraintSum with the global observables
115/// in the dataset if they match by name. This function will do nothing if this
116/// RooConstraintSum is configured to not use the global observables stored in
117/// datasets.
118bool RooConstraintSum::setData(RooAbsData const& data, bool /*cloneData=true*/) {
121 }
122 return true;
123}
124
125
126namespace {
127
128std::unique_ptr<RooArgSet> getGlobalObservables(
129 RooAbsPdf const& pdf, RooArgSet const* globalObservables, const char* globalObservablesTag)
130{
131
132 if(globalObservables && globalObservablesTag) {
133 // error!
134 std::string errMsg = "RooAbsPdf::fitTo: GlobalObservables and GlobalObservablesTag options mutually exclusive!";
135 oocoutE(&pdf, Minimization) << errMsg << std::endl;
136 throw std::invalid_argument(errMsg);
137 }
138 if(globalObservables) {
139 // pass-throught of global observables
140 return std::make_unique<RooArgSet>(*globalObservables);
141 }
142
143 if(globalObservablesTag) {
144 oocoutI(&pdf, Minimization) << "User-defined specification of global observables definition with tag named '"
145 << globalObservablesTag << "'" << std::endl;
146 } else {
147 // Neither GlobalObservables nor GlobalObservablesTag has been processed -
148 // try if a default tag is defined in the head node Check if head not
149 // specifies default global observable tag
150 if(auto defaultGlobalObservablesTag = pdf.getStringAttribute("DefaultGlobalObservablesTag")) {
151 oocoutI(&pdf, Minimization) << "p.d.f. provides built-in specification of global observables definition "
152 << "with tag named '" << defaultGlobalObservablesTag << "'" << std::endl;
153 globalObservablesTag = defaultGlobalObservablesTag;
154 }
155 }
156
157 if(globalObservablesTag) {
158 std::unique_ptr<RooArgSet> allVars{pdf.getVariables()} ;
159 return std::unique_ptr<RooArgSet>{static_cast<RooArgSet*>(allVars->selectByAttrib(globalObservablesTag, true))};
160 }
161
162 // no global observables specified
163 return nullptr;
164}
165
166
167RooArgSet const* tryToGetConstraintSetFromWorkspace(
168 RooAbsPdf const& pdf, RooWorkspace * workspace, std::string const& constraintSetCacheName) {
169 if(!workspace) return nullptr;
170
171 if(workspace->set(constraintSetCacheName.c_str())) {
172 // retrieve from cache
173 const RooArgSet *constr = workspace->set(constraintSetCacheName.c_str());
174 oocoutI(&pdf, Minimization)
175 << "createConstraintTerm picked up cached constraints from workspace with " << constr->size()
176 << " entries" << std::endl;
177 return constr;
178 }
179 return nullptr;
180}
181
182
183} // namespace
184
185
186////////////////////////////////////////////////////////////////////////////////
187/// Create the parameter constraint sum to add to the negative log-likelihood.
188/// \return If there are constraints, returns a pointer to the constraint NLL,
189/// where all the components are clones of the original PDF components.
190/// Returns a `nullptr` if the parameters are unconstrained.
191/// \param[in] name Name of the created RooConstraintSum object.
192/// \param[in] pdf The pdf model whose parameters should be constrained.
193/// Constraint terms will be extracted from RooProdPdf instances
194/// that are servers of the pdf (internal constraints).
195/// \param[in] data Dataset used in the fit with the constraint sum. It is
196/// used to figure out which are the observables and also to get the
197/// global observables definition and values if they are stored in
198/// the dataset.
199/// \param[in] constraints Set of parameters to constrain. If `nullptr`, all
200/// parameters will be considered.
201/// \param[in] externalConstraints Set of constraint terms that are not
202/// embedded in the pdf (external constraints).
203/// \param[in] globalObservables The normalization set for the constraint terms.
204/// If it is `nullptr`, the set of all constrained parameters will
205/// be used as the normalization set.
206/// \param[in] globalObservablesTag Alternative to define the normalization set
207/// for the constraint terms. All constrained parameters that have
208/// the attribute with the tag defined by `globalObservablesTag` are
209/// used. The `globalObservables` and `globalObservablesTag`
210/// parameters are mutually exclusive, meaning at least one of them
211/// has to be `nullptr`.
212/// \param[in] takeGlobalObservablesFromData If the dataset should be used to automatically
213/// define the set of global observables. If this is the case and the
214/// set of global observables is still defined manually with the
215/// `globalObservables` or `globalObservablesTag` parameters, the
216/// values of all global observables that are not stored in the
217/// dataset are taken from the model.
218/// \param[in] workspace RooWorkspace to cache the set of constraints.
219std::unique_ptr<RooAbsReal> RooConstraintSum::createConstraintTerm(
220 std::string const& name,
221 RooAbsPdf const& pdf,
222 RooAbsData const& data,
223 RooArgSet const* constrainedParameters,
224 RooArgSet const* externalConstraints,
225 RooArgSet const* globalObservables,
226 const char* globalObservablesTag,
227 bool takeGlobalObservablesFromData,
228 RooWorkspace * workspace)
229{
230 RooArgSet const& observables = *data.get();
231
232 bool doStripDisconnected = false ;
233
234 // If no explicit list of parameters to be constrained is specified apply default algorithm
235 // All terms of RooProdPdfs that do not contain observables and share a parameters with one or more
236 // terms that do contain observables are added as constrainedParameters.
237 RooArgSet cPars;
238 if(constrainedParameters) {
239 cPars.add(*constrainedParameters);
240 } else {
241 pdf.getParameters(&observables,cPars,false);
242 doStripDisconnected = true;
243 }
244
245 // Collect internal and external constraint specifications
246 RooArgSet allConstraints ;
247
248 auto observableNames = RooHelpers::getColonSeparatedNameString(observables);
249 auto constraintSetCacheName = std::string("CACHE_CONSTR_OF_PDF_") + pdf.GetName() + "_FOR_OBS_" + observableNames;
250
251 if (RooArgSet const* constr = tryToGetConstraintSetFromWorkspace(pdf, workspace, constraintSetCacheName)) {
252 allConstraints.add(*constr);
253 } else {
254
255 if (!cPars.empty()) {
256 std::unique_ptr<RooArgSet> internalConstraints{pdf.getAllConstraints(observables, cPars, doStripDisconnected)};
257 allConstraints.add(*internalConstraints);
258 }
259 if (externalConstraints) {
260 allConstraints.add(*externalConstraints);
261 }
262
263 // write to cache
264 if (workspace) {
265 oocoutI(&pdf, Minimization)
266 << "createConstraintTerm: caching constraint set under name "
267 << constraintSetCacheName << " with " << allConstraints.size() << " entries" << std::endl;
268 workspace->defineSetInternal(constraintSetCacheName.c_str(), allConstraints);
269 }
270 }
271
272 if (!allConstraints.empty()) {
273
274 oocoutI(&pdf, Minimization) << " Including the following constraint terms in minimization: "
275 << allConstraints << std::endl ;
276
277 // Identify global observables in the model.
278 auto glObs = getGlobalObservables(pdf, globalObservables, globalObservablesTag);
279 if(data.getGlobalObservables() && takeGlobalObservablesFromData) {
280 if(!glObs) {
281 // There were no global observables specified, but there are some in the
282 // dataset. We will just take them from the dataset.
283 oocoutI(&pdf, Minimization)
284 << "The following global observables have been automatically defined according to the dataset "
285 << "which also provides their values: " << *data.getGlobalObservables() << std::endl;
286 glObs = std::make_unique<RooArgSet>(*data.getGlobalObservables());
287 } else {
288 // There are global observables specified by the user and also some in
289 // the dataset.
290 RooArgSet globalsFromDataset;
291 data.getGlobalObservables()->selectCommon(*glObs, globalsFromDataset);
292 oocoutI(&pdf, Minimization)
293 << "The following global observables have been defined: " << *glObs
294 << "," << " with the values of " << globalsFromDataset
295 << " obtained from the dataset and the other values from the model." << std::endl;
296 }
297 } else if(glObs) {
298 oocoutI(&pdf, Minimization)
299 << "The following global observables have been defined and their values are taken from the model: "
300 << *glObs << std::endl;
301 // in this case we don;t take global observables from data
302 takeGlobalObservablesFromData = false;
303 } else {
304 if (!glObs)
305 oocoutI(&pdf, Minimization)
306 << "The global observables are not defined , normalize constraints with respect to the parameters " << cPars
307 << std::endl;
308 takeGlobalObservablesFromData = false;
309 }
310
311 // The constraint terms need to be cloned, because the global observables
312 // might be changed to have the same values as stored in data, or because
313 // the compute graph is mutated completely like in the BatchMode.
314 RooConstraintSum constraintTerm{name.c_str(), "nllCons", allConstraints, glObs ? *glObs : cPars,
315 takeGlobalObservablesFromData};
316 std::unique_ptr<RooAbsReal> constraintTermClone{static_cast<RooAbsReal *>(constraintTerm.cloneTree())};
317
318 // The parameters that are not connected to global observables from data
319 // need to be redirected to the original args to get the changes made by
320 // the minimizer. This excludes the global observables, where we take the
321 // clones with the values set to the values from the dataset if available.
322 RooArgSet allOriginalParams;
323 constraintTerm.getParameters(nullptr, allOriginalParams);
324 constraintTermClone->recursiveRedirectServers(allOriginalParams);
325
326 // Redirect the global observables to the ones from the dataset if applicable.
327 static_cast<RooConstraintSum *>(constraintTermClone.get())->setData(data, false);
328
329 // The computation graph for the constraints is very small, no need to do
330 // the tracking of clean and dirty nodes here.
331 constraintTermClone->setOperMode(RooAbsArg::ADirty);
332
333 return constraintTermClone;
334 }
335
336 // no constraints
337 return nullptr;
338}
#define oocoutE(o, a)
#define oocoutI(o, a)
#define coutE(a)
double Double_t
Definition RtypesCore.h:59
#define ClassImp(name)
Definition Rtypes.h:364
char name[80]
Definition TGX11.cxx:110
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
RooArgSet * getVariables(Bool_t stripDisconnected=kTRUE) const
Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
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...
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.
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE)
Add the specified argument to list.
Storage_t::size_type size() const
bool selectCommon(const RooAbsCollection &refColl, RooAbsCollection &outColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:82
virtual const RooArgSet * get() const
Definition RooAbsData.h:128
RooArgSet const * getGlobalObservables() const
Returns snapshot of global observables stored in this data.
Definition RooAbsData.h:315
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....
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:35
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.
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.
void computeBatch(cudaStream_t *, double *output, size_t size, RooFit::Detail::DataMap const &) const override
Base function for computing multiple values of a RooAbsReal.
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, RooWorkspace *workspace)
Create the parameter constraint sum to add to the negative log-likelihood.
RooArgSet _paramSet
Set of parameters to which constraints apply.
std::unique_ptr< RooArgSet > fillNormSetForServer(RooArgSet const &normSet, RooAbsArg const &server) const override
Fills a RooArgSet to be used as the normalization set for a server, given a normalization set for thi...
const bool _takeGlobalObservablesFromData
If the global observable values are taken from data.
static void softAbort()
auto & at(RooAbsArg const *arg, RooAbsArg const *=nullptr)
Definition DataMap.h:88
virtual Bool_t add(const RooAbsArg &var, Bool_t silent=kFALSE) override
Reimplementation of standard RooArgList::add()
The RooWorkspace is a persistable container for RooFit projects.
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...
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
std::string getColonSeparatedNameString(RooArgSet const &argSet)
Create a string with all sorted names of RooArgSet elements separated by colons.
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345
static void output(int code)
Definition gifencode.c:226