Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ConstraintHelpers.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Jonas Rembser, CERN 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13#include "ConstraintHelpers.h"
14
15#include <RooAbsData.h>
16#include <RooAbsPdf.h>
17#include <RooConstraintSum.h>
18#include <RooMsgService.h>
19
20namespace {
21
22std::unique_ptr<RooArgSet>
23getGlobalObservables(RooAbsPdf const &pdf, RooArgSet const *globalObservables, const char *globalObservablesTag)
24{
25
26 if (globalObservables && globalObservablesTag) {
27 // error!
28 std::string errMsg = "RooAbsPdf::fitTo: GlobalObservables and GlobalObservablesTag options mutually exclusive!";
29 oocoutE(&pdf, Minimization) << errMsg << std::endl;
30 throw std::invalid_argument(errMsg);
31 }
32 if (globalObservables) {
33 // pass-throught of global observables
34 return std::make_unique<RooArgSet>(*globalObservables);
35 }
36
37 if (globalObservablesTag) {
38 oocoutI(&pdf, Minimization) << "User-defined specification of global observables definition with tag named '"
39 << globalObservablesTag << "'" << std::endl;
40 } else {
41 // Neither GlobalObservables nor GlobalObservablesTag has been processed -
42 // try if a default tag is defined in the head node Check if head not
43 // specifies default global observable tag
44 if (auto defaultGlobalObservablesTag = pdf.getStringAttribute("DefaultGlobalObservablesTag")) {
45 oocoutI(&pdf, Minimization) << "p.d.f. provides built-in specification of global observables definition "
46 << "with tag named '" << defaultGlobalObservablesTag << "'" << std::endl;
47 globalObservablesTag = defaultGlobalObservablesTag;
48 }
49 }
50
51 if (globalObservablesTag) {
52 std::unique_ptr<RooArgSet> allVars{pdf.getVariables()};
53 return std::unique_ptr<RooArgSet>{static_cast<RooArgSet *>(allVars->selectByAttrib(globalObservablesTag, true))};
54 }
55
56 // no global observables specified
57 return nullptr;
58}
59
60} // namespace
61
62////////////////////////////////////////////////////////////////////////////////
63/// Create the parameter constraint sum to add to the negative log-likelihood.
64/// \return If there are constraints, returns a pointer to the constraint NLL.
65/// Returns a `nullptr` if the parameters are unconstrained.
66/// \param[in] name Name of the created RooConstraintSum object.
67/// \param[in] pdf The PDF model whose parameters should be constrained.
68/// Constraint terms will be extracted from RooProdPdf instances
69/// that are servers of the PDF (internal constraints).
70/// \param[in] data Dataset used in the fit with the constraint sum. It is
71/// used to figure out which are the observables and also to get the
72/// global observables definition and values if they are stored in
73/// the dataset.
74/// \param[in] constrainedParameters Set of parameters to constrain. If `nullptr`, all
75/// parameters will be considered.
76/// \param[in] externalConstraints Set of constraint terms that are not
77/// embedded in the PDF (external constraints).
78/// \param[in] globalObservables The normalization set for the constraint terms.
79/// If it is `nullptr`, the set of all constrained parameters will
80/// be used as the normalization set.
81/// \param[in] globalObservablesTag Alternative to define the normalization set
82/// for the constraint terms. All constrained parameters that have
83/// the attribute with the tag defined by `globalObservablesTag` are
84/// used. The `globalObservables` and `globalObservablesTag`
85/// parameters are mutually exclusive, meaning at least one of them
86/// has to be `nullptr`.
87/// \param[in] takeGlobalObservablesFromData If the dataset should be used to automatically
88/// define the set of global observables. If this is the case and the
89/// set of global observables is still defined manually with the
90/// `globalObservables` or `globalObservablesTag` parameters, the
91/// values of all global observables that are not stored in the
92/// dataset are taken from the model.
93/// \param[in] removeConstraintsPdf If true, the constraints that are extracted
94/// from the PDF are removed from the original PDF.
95std::unique_ptr<RooAbsReal> createConstraintTerm(std::string const &name, RooAbsPdf const &pdf, RooAbsData const &data,
96 RooArgSet const *constrainedParameters,
97 RooArgSet const *externalConstraints,
98 RooArgSet const *globalObservables, const char *globalObservablesTag,
99 bool takeGlobalObservablesFromData, bool removeConstraintsFromPdf)
100{
101 RooArgSet const &observables = *data.get();
102
103 bool doStripDisconnected = false;
104
105 // If no explicit list of parameters to be constrained is specified apply default algorithm
106 // All terms of RooProdPdfs that do not contain observables and share a parameters with one or more
107 // terms that do contain observables are added as constrainedParameters.
108 RooArgSet cPars;
109 if (constrainedParameters) {
110 cPars.add(*constrainedParameters);
111 } else {
112 pdf.getParameters(&observables, cPars, false);
113 doStripDisconnected = true;
114 }
115
116 // Collect internal and external constraint specifications
117 RooArgSet allConstraints;
118
119 auto observableNames = RooHelpers::getColonSeparatedNameString(observables);
120 auto constraintSetCacheName = std::string("CACHE_CONSTR_OF_PDF_") + pdf.GetName() + "_FOR_OBS_" + observableNames;
121
122 if (!cPars.empty()) {
123 std::unique_ptr<RooArgSet> internalConstraints{
124 pdf.getAllConstraints(observables, cPars, doStripDisconnected, removeConstraintsFromPdf)};
125 allConstraints.add(*internalConstraints);
126 }
127 if (externalConstraints) {
128 allConstraints.add(*externalConstraints);
129 }
130
131 if (!allConstraints.empty()) {
132
133 oocoutI(&pdf, Minimization) << " Including the following constraint terms in minimization: " << allConstraints
134 << std::endl;
135
136 // Identify global observables in the model.
137 auto glObs = getGlobalObservables(pdf, globalObservables, globalObservablesTag);
138 if (data.getGlobalObservables() && takeGlobalObservablesFromData) {
139 if (!glObs) {
140 // There were no global observables specified, but there are some in the
141 // dataset. We will just take them from the dataset.
142 oocoutI(&pdf, Minimization)
143 << "The following global observables have been automatically defined according to the dataset "
144 << "which also provides their values: " << *data.getGlobalObservables() << std::endl;
145 glObs = std::make_unique<RooArgSet>(*data.getGlobalObservables());
146 } else {
147 // There are global observables specified by the user and also some in
148 // the dataset.
149 RooArgSet globalsFromDataset;
150 data.getGlobalObservables()->selectCommon(*glObs, globalsFromDataset);
151 oocoutI(&pdf, Minimization) << "The following global observables have been defined: " << *glObs << ","
152 << " with the values of " << globalsFromDataset
153 << " obtained from the dataset and the other values from the model."
154 << std::endl;
155 }
156 } else if (glObs) {
157 oocoutI(&pdf, Minimization)
158 << "The following global observables have been defined and their values are taken from the model: "
159 << *glObs << std::endl;
160 // In this case we don't take global observables from data
161 takeGlobalObservablesFromData = false;
162 } else {
163 if (!glObs)
164 oocoutI(&pdf, Minimization)
165 << "The global observables are not defined , normalize constraints with respect to the parameters "
166 << cPars << std::endl;
167 takeGlobalObservablesFromData = false;
168 }
169
170 return std::make_unique<RooConstraintSum>(name.c_str(), "nllCons", allConstraints, glObs ? *glObs : cPars,
171 takeGlobalObservablesFromData);
172 }
173
174 // no constraints
175 return nullptr;
176}
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 removeConstraintsFromPdf)
Create the parameter constraint sum to add to the negative log-likelihood.
#define oocoutE(o, a)
#define oocoutI(o, a)
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
RooFit::OwningPtr< 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...
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:59
RooArgSet * getAllConstraints(const RooArgSet &observables, RooArgSet &constrainedParams, bool stripDisconnected=true, bool removeConstraintsFromPdf=false) const
This helper function finds and collects all constraints terms of all component p.d....
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
const char * GetName() const override
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.