Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ModelConfig.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Kyle Cranmer,
5 * Lorenzo Moneta,
6 * Gregory Schott,
7 * Wouter Verkerke,
8 * Sven Kreiss
9 *
10 * Copyright (c) 2023, CERN
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 RooStats::ModelConfig
18 \ingroup Roostats
19
20ModelConfig is a simple class that holds configuration information specifying how a model
21should be used in the context of various RooStats tools. A single model can be used
22in different ways, and this class should carry all that is needed to specify how it should be used.
23ModelConfig requires a workspace to be set.
24
25A ModelConfig holds sets of parameters of the likelihood function that have different interpretations:
26- **Parameter of interest** Parameters that are measured (*i.e.* fitted).
27- **Nuisance parameters** Parameters that are fitted, but their post-fit value is not interesting. Often,
28they might be constrained because external knowledge about them exists, *e.g.* from external measurements.
29- **Constraint parameters** No direct use in RooFit/RooStats. Can be used by the user for bookkeeping.
30- **Observables** Parameters that have been measured externally, *i.e.* they exist in a dataset. These are not fitted,
31but read during fitting from the entries of a dataset.
32- **Conditional observables** Observables that are not integrated when the normalisation of the PDF is calculated.
33See *e.g.* `rf306_condpereventerrors` in the RooFit tutorials.
34- **Global observables** Observables that to the fit look like "constant" values, *i.e.* they are not being
35fitted and they are not loaded from a dataset, but some knowledge exists that allows to set them to a
36specific value. Examples:
37-- A signal efficiency measured in a Monte Carlo study.
38-- When constraining a parameter \f$ b \f$, the target value (\f$ b_0 \f$) that this parameter is constrained to:
39\f[
40 \mathrm{Constraint}_b = \mathrm{Gauss}(b_0 \, | \, b, 0.2)
41\f]
42- **External constraints** Include given external constraints to likelihood by multiplying them with the original
43likelihood.
44*/
45
46#include <RooFit/ModelConfig.h>
47
48#include <RooFitResult.h>
49#include <RooMsgService.h>
50#include <RooRealVar.h>
51
52#include <sstream>
53
54
55namespace {
56
57void removeConstantParameters(RooAbsCollection &coll)
58{
60 for (auto const *myarg : static_range_cast<RooRealVar *>(coll)) {
61 if (myarg->isConstant())
62 constSet.add(*myarg);
63 }
64 coll.remove(constSet);
65}
66
67} // namespace
68
69using std::ostream;
70
71namespace RooStats {
72
73////////////////////////////////////////////////////////////////////////////////
74/// Makes sensible guesses of observables, parameters of interest
75/// and nuisance parameters if one or multiple have been set by the creator of this ModelConfig.
76///
77/// Defaults:
78/// - Observables: determined from data,
79/// - Global observables: explicit obs - obs from data - constant observables
80/// - Parameters of interest: empty,
81/// - Nuisance parameters: all parameters except parameters of interest
82///
83/// We use nullptr to mean not set, so we don't want to fill
84/// with empty RooArgSets.
85
87{
88
89 // observables
90 if (!GetObservables()) {
91 SetObservables(*std::unique_ptr<RooArgSet>{GetPdf()->getObservables(obsSet)});
92 }
93 // global observables
94 if (!GetGlobalObservables()) {
96 co.remove(*std::unique_ptr<RooArgSet>{GetPdf()->getObservables(obsSet)});
97 removeConstantParameters(co);
98 if (!co.empty())
100
101 // TODO BUG This does not work as observables with the same name are already in the workspace.
102 /*
103 RooArgSet o(*GetObservables());
104 o.remove(co);
105 SetObservables(o);
106 */
107 }
108
109 // parameters
110 // if (!GetParametersOfInterest()) {
111 // SetParametersOfInterest(RooArgSet());
112 // }
113 if (!GetNuisanceParameters()) {
114 RooArgSet params;
115 GetPdf()->getParameters(&obsSet, params);
116 RooArgSet p(params);
117 p.remove(*GetParametersOfInterest());
118 removeConstantParameters(p);
119 if (!p.empty())
121 }
122
123 // print Modelconfig as an info message
124
125 if (printModelConfig) {
126 std::ostream &oldstream = RooPrintable::defaultPrintStream(&ccoutI(InputArguments));
127 Print();
129 }
130}
131
132////////////////////////////////////////////////////////////////////////////////
133/// print contents of Model on the default print stream
134/// It can be changed using RooPrintable
135
137{
138 ostream &os = RooPrintable::defaultPrintStream();
139
140 os << std::endl << "=== Using the following for " << GetName() << " ===" << std::endl;
141
142 // args
143 if (GetObservables()) {
144 os << "Observables: ";
145 GetObservables()->Print("");
146 }
148 os << "Parameters of Interest: ";
149 GetParametersOfInterest()->Print("");
150 }
151 if (GetNuisanceParameters()) {
152 os << "Nuisance Parameters: ";
153 GetNuisanceParameters()->Print("");
154 }
155 if (GetGlobalObservables()) {
156 os << "Global Observables: ";
157 GetGlobalObservables()->Print("");
158 }
160 os << "Constraint Parameters: ";
161 GetConstraintParameters()->Print("");
162 }
164 os << "Conditional Observables: ";
165 GetConditionalObservables()->Print("");
166 }
167 if (GetProtoData()) {
168 os << "Proto Data: ";
169 GetProtoData()->Print("");
170 }
171
172 // pdfs
173 if (GetPdf()) {
174 os << "PDF: ";
175 GetPdf()->Print("");
176 }
177 if (GetPriorPdf()) {
178 os << "Prior PDF: ";
179 GetPriorPdf()->Print("");
180 }
181
182 // snapshot
183 const RooArgSet *snapshot = GetSnapshot();
184 if (snapshot) {
185 os << "Snapshot: " << std::endl;
186 snapshot->Print("v");
187 delete snapshot;
188 }
189
190 os << std::endl;
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// If a workspace already exists in this ModelConfig, this function will do nothing.
195
197{
198 if (!fRefWS) {
199 fRefWS = &ws;
200 } else {
201 coutE(ObjectHandling) << "ModelConfig::SetWS(): workspace already set, not doing anything" << std::endl;
202 }
203}
204
205////////////////////////////////////////////////////////////////////////////////
206/// Get workspace.
207
209{
210 if (!fRefWS) {
211 coutE(ObjectHandling) << "workspace not set" << std::endl;
212 return nullptr;
213 }
214 return fRefWS;
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// save snapshot in the workspace
219/// and use values passed with the set
220
222{
223 if (!GetWS())
224 return;
225
227 if (!fSnapshotName.empty())
228 fSnapshotName += "_";
229 fSnapshotName += set.GetName();
230 if (!fSnapshotName.empty())
231 fSnapshotName += "_";
232 fSnapshotName += "snapshot";
233 GetWS()->saveSnapshot(fSnapshotName, set, true); // import also the given parameter values
234 DefineSetInWS(fSnapshotName.c_str(), set);
235}
236
237////////////////////////////////////////////////////////////////////////////////
238/// Load the snapshot from ws and return the corresponding set with the snapshot values.
239/// User must delete returned RooArgSet.
240
242{
243 if (!GetWS())
244 return nullptr;
245 if (!fSnapshotName.length())
246 return nullptr;
247 // calling loadSnapshot will also copy the current parameter values in the workspaces
248 // since we do not want to change the model parameters - we restore the previous ones
249 if (!GetWS()->set(fSnapshotName))
250 return nullptr;
252 if (snapshotVars.empty())
253 return nullptr;
254 // make my snapshot which will contain a copy of the snapshot variables
256 snapshotVars.snapshot(tempSnapshot);
257 // load snapshot value from the workspace
258 if (!(GetWS()->loadSnapshot(fSnapshotName.c_str())))
259 return nullptr;
260 // by doing this snapshotVars will have the snapshot values - make the snapshot to return
261 const RooArgSet *modelSnapshot = dynamic_cast<const RooArgSet *>(snapshotVars.snapshot());
262 // restore now the variables of snapshot in ws to their original values
263 // need to const cast since assign is not const (but in reality in just assign values and does not change the set)
264 // and anyway the set is const
265 snapshotVars.assignFast(tempSnapshot);
266 return modelSnapshot;
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// load the snapshot from ws if it exists
271
273{
274 if (!GetWS())
275 return;
276 GetWS()->loadSnapshot(fSnapshotName.c_str());
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// helper functions to avoid code duplication
281
282void ModelConfig::DefineSetInWS(const char *name, const RooArgSet &set)
283{
284 if (!GetWS())
285 return;
286
287 const RooArgSet *prevSet = GetWS()->set(name);
288 if (prevSet) {
289 // be careful not to remove passed set in case it is the same updated
290 if (prevSet != &set)
291 GetWS()->removeSet(name);
292 }
293
294 // suppress warning when we re-define a previously defined set (when set == prevSet )
295 // and set is not removed in that case
296 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
297 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
298
299 GetWS()->defineSet(name, set, true);
300
301 RooMsgService::instance().setGlobalKillBelow(level);
302}
303
304////////////////////////////////////////////////////////////////////////////////
305/// internal function to import Pdf in WS
306
308{
309 if (!GetWS())
310 return;
311
312 if (!GetWS()->pdf(pdf.GetName())) {
313 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
314 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
316 RooMsgService::instance().setGlobalKillBelow(level);
317 }
318}
319
320////////////////////////////////////////////////////////////////////////////////
321/// internal function to import data in WS
322
324{
325 if (!GetWS())
326 return;
327
328 if (!GetWS()->data(data.GetName())) {
329 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
330 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
331 GetWS()->import(data);
332 RooMsgService::instance().setGlobalKillBelow(level);
333 }
334}
335
336////////////////////////////////////////////////////////////////////////////////
337
339{
340
342 for (auto const *arg : set) {
343 if (!arg->isFundamental()) {
344 nonparams.add(*arg);
345 }
346 }
347
348 if (errorMsgPrefix && !nonparams.empty()) {
349 std::cout << errorMsgPrefix << " ERROR: specified set contains non-parameters: " << nonparams << std::endl;
350 }
351 return (nonparams.empty());
352}
353
354/// Specify the external constraints.
356{
357 fExtConstraintsName = std::string(GetName()) + "_ExternalConstraints";
359}
360
361/// Specify the conditional observables.
363{
364 if (!SetHasOnlyParameters(set, "ModelConfig::SetConditionalObservables"))
365 return;
366 fConditionalObsName = std::string(GetName()) + "_ConditionalObservables";
368}
369
370/// Specify the global observables.
372{
373
374 if (!SetHasOnlyParameters(set, "ModelConfig::SetGlobalObservables"))
375 return;
376
377 // make global observables constant
378 for (auto *arg : set) {
379 arg->setAttribute("Constant", true);
380 }
381
382 fGlobalObsName = std::string(GetName()) + "_GlobalObservables";
383 DefineSetInWS(fGlobalObsName.c_str(), set);
384}
385
386namespace {
387
388std::unique_ptr<RooLinkedList>
389finalizeCmdList(ModelConfig const &modelConfig, RooLinkedList const &cmdList, std::vector<RooCmdArg> &cmdArgs)
390{
391 auto addCmdArg = [&](RooCmdArg const &cmdArg) {
392 if (cmdList.FindObject(cmdArg.GetName())) {
393 std::stringstream ss;
394 ss << "Illegal command argument \"" << cmdArg.GetName()
395 << "\" passed to ModelConfig::createNLL(). This option is retrieved from the ModelConfig itself.";
396 const std::string errorMsg = ss.str();
397 oocoutE(&modelConfig, InputArguments) << errorMsg << std::endl;
398 throw std::runtime_error(errorMsg);
399 }
400 cmdArgs.push_back(cmdArg);
401 };
402
403 if (auto args = modelConfig.GetConditionalObservables()) {
405 }
406
407 if (auto args = modelConfig.GetGlobalObservables()) {
409 }
410
411 if (auto args = modelConfig.GetExternalConstraints()) {
413 }
414
415 auto finalCmdList = std::make_unique<RooLinkedList>(cmdList);
416 for (RooCmdArg &arg : cmdArgs) {
417 finalCmdList->Add(&arg);
418 }
419
420 return finalCmdList;
421}
422
423} // namespace
424
425/** @fn RooStats::ModelConfig::createNLL()
426 *
427 * Wrapper around RooAbsPdf::createNLL(), where
428 * the pdf and some configuration options are retrieved from the ModelConfig.
429 *
430 * The options taken from the ModelConfig are:
431 *
432 * * ConditionalObservables()
433 * * GlobalObservables()
434 * * ExternalConstraints()
435 *
436 * Except for the options above, you can still pass all the other command
437 * arguments supported by RooAbsPdf::createNLL().
438 */
439
440std::unique_ptr<RooAbsReal> ModelConfig::createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList) const
441{
442 std::vector<RooCmdArg> cmdArgs;
444 return std::unique_ptr<RooAbsReal>{GetPdf()->createNLL(data, *finalCmdList)};
445}
446
447/** @fn RooStats::ModelConfig::fitTo()
448 *
449 * Wrapper around RooAbsPdf::fitTo(), where
450 * the pdf and some configuration options are retrieved from the ModelConfig.
451 *
452 * See ModelConfig::createNLL() for more information.
453 */
454std::unique_ptr<RooFitResult> ModelConfig::fitToImpl(RooAbsData &data, const RooLinkedList &cmdList) const
455{
456 std::vector<RooCmdArg> cmdArgs;
458 return std::unique_ptr<RooFitResult>{GetPdf()->fitTo(data, *finalCmdList)};
459}
460
461} // end namespace RooStats
ROOT::RRangeCast< T, false, Range_t > static_range_cast(Range_t &&coll)
#define oocoutE(o, a)
#define coutE(a)
#define ccoutI(a)
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
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
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:238
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...
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.
Abstract container object that can hold multiple RooAbsArg objects.
const char * GetName() const override
Returns name of object.
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
Definition RooAbsData.h:227
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
RooFit::OwningPtr< RooAbsReal > createNLL(RooAbsData &data, CmdArgs_t const &... cmdArgs)
Construct representation of -log(L) of PDF with given dataset.
Definition RooAbsPdf.h:155
RooFit::OwningPtr< RooFitResult > fitTo(RooAbsData &data, CmdArgs_t const &... cmdArgs)
Fit PDF to given dataset.
Definition RooAbsPdf.h:149
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Named container for two doubles, two integers two object points and three string pointers that can be...
Definition RooCmdArg.h:26
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
static RooMsgService & instance()
Return reference to singleton instance.
static std::ostream & defaultPrintStream(std::ostream *os=nullptr)
Return a reference to the current default stream to use in Print().
Variable that can be changed from the outside.
Definition RooRealVar.h:37
< A class that holds configuration information for a model using a workspace as a store
Definition ModelConfig.h:34
virtual void SetSnapshot(const RooArgSet &set)
Set parameter values for a particular hypothesis if using a common PDF by saving a snapshot in the wo...
virtual void SetObservables(const RooArgSet &set)
Specify the observables.
std::string fSnapshotName
name for RooArgSet that specifies a particular hypothesis
std::string fExtConstraintsName
name for RooArgSet specifying external constraints
void ImportPdfInWS(const RooAbsPdf &pdf)
internal function to import Pdf in WS
void SetExternalConstraints(const RooArgSet &set)
Specify the external constraints.
RooAbsData * GetProtoData() const
get Proto data set (return nullptr if not existing)
void DefineSetInWS(const char *name, const RooArgSet &set)
helper functions to define a set in the WS
const RooArgSet * GetConditionalObservables() const
get RooArgSet for conditional observables (return nullptr if not existing)
std::string fConditionalObsName
name for RooArgSet specifying conditional observables
const RooArgSet * GetGlobalObservables() const
get RooArgSet for global observables (return nullptr if not existing)
virtual void SetConditionalObservables(const RooArgSet &set)
Specify the conditional observables.
RooWorkspace * fRefWS
! WS reference used in the file
const RooArgSet * GetParametersOfInterest() const
get RooArgSet containing the parameter of interest (return nullptr if not existing)
const RooArgSet * GetNuisanceParameters() const
get RooArgSet containing the nuisance parameters (return nullptr if not existing)
std::unique_ptr< RooAbsReal > createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList) const
void LoadSnapshot() const
load the snapshot from ws if it exists
void Print(Option_t *option="") const override
overload the print method
std::string fGlobalObsName
name for RooArgSet specifying global observables
void ImportDataInWS(RooAbsData &data)
internal function to import data in WS
void SetWS(RooWorkspace &ws) override
Set a workspace that owns all the necessary components for the analysis.
bool SetHasOnlyParameters(const RooArgSet &set, const char *errorMsgPrefix=nullptr)
helper function to check that content of a given set is exclusively parameters
std::unique_ptr< RooFitResult > fitToImpl(RooAbsData &data, const RooLinkedList &cmdList) const
const RooArgSet * GetObservables() const
get RooArgSet for observables (return nullptr if not existing)
const RooArgSet * GetSnapshot() const
get RooArgSet for parameters for a particular hypothesis (return nullptr if not existing)
const RooArgSet * GetConstraintParameters() const
get RooArgSet containing the constraint parameters (return nullptr if not existing)
RooWorkspace * GetWS() const override
Get workspace.
void GuessObsAndNuisance(const RooArgSet &obsSet, bool printModelConfig=true)
Makes sensible guesses of observables, parameters of interest and nuisance parameters if one or multi...
RooAbsPdf * GetPdf() const
get model PDF (return nullptr if pdf has not been specified or does not exist)
virtual void SetNuisanceParameters(const RooArgSet &set)
Specify the nuisance parameters (parameters that are not POI).
RooAbsPdf * GetPriorPdf() const
get parameters prior pdf (return nullptr if not existing)
virtual void SetGlobalObservables(const RooArgSet &set)
Specify the global observables.
Persistable container for RooFit projects.
const RooArgSet * set(RooStringView name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
bool saveSnapshot(RooStringView, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
bool removeSet(const char *name)
Remove a named set from the workspace.
bool loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
bool defineSet(const char *name, const RooArgSet &aset, bool importMissing=false)
Define a named RooArgSet with given constituents.
bool import(const RooAbsArg &arg, 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 RooCmdArg &arg9={})
Import a RooAbsArg object, e.g.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
RooCmdArg RecycleConflictNodes(bool flag=true)
RooCmdArg GlobalObservables(Args_t &&... argsOrArgSet)
RooCmdArg ExternalConstraints(const RooArgSet &constraintPdfs)
RooCmdArg ConditionalObservables(Args_t &&... argsOrArgSet)
Create a RooCmdArg to declare conditional observables.
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
Namespace for the RooStats classes.
Definition CodegenImpl.h:61