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, RooWorkspace::merge(ws) will be called
195/// on the existing workspace.
196
198{
199 if (!fRefWS) {
200 fRefWS = &ws;
201 } else {
202 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
203 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
204 GetWS()->merge(ws);
205 RooMsgService::instance().setGlobalKillBelow(level);
206 }
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Get workspace.
211
213{
214 if (!fRefWS) {
215 coutE(ObjectHandling) << "workspace not set" << std::endl;
216 return nullptr;
217 }
218 return fRefWS;
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// save snapshot in the workspace
223/// and use values passed with the set
224
226{
227 if (!GetWS())
228 return;
229
231 if (!fSnapshotName.empty())
232 fSnapshotName += "_";
233 fSnapshotName += set.GetName();
234 if (!fSnapshotName.empty())
235 fSnapshotName += "_";
236 fSnapshotName += "snapshot";
237 GetWS()->saveSnapshot(fSnapshotName, set, true); // import also the given parameter values
238 DefineSetInWS(fSnapshotName.c_str(), set);
239}
240
241////////////////////////////////////////////////////////////////////////////////
242/// Load the snapshot from ws and return the corresponding set with the snapshot values.
243/// User must delete returned RooArgSet.
244
246{
247 if (!GetWS())
248 return nullptr;
249 if (!fSnapshotName.length())
250 return nullptr;
251 // calling loadSnapshot will also copy the current parameter values in the workspaces
252 // since we do not want to change the model parameters - we restore the previous ones
253 if (!GetWS()->set(fSnapshotName))
254 return nullptr;
256 if (snapshotVars.empty())
257 return nullptr;
258 // make my snapshot which will contain a copy of the snapshot variables
260 snapshotVars.snapshot(tempSnapshot);
261 // load snapshot value from the workspace
262 if (!(GetWS()->loadSnapshot(fSnapshotName.c_str())))
263 return nullptr;
264 // by doing this snapshotVars will have the snapshot values - make the snapshot to return
265 const RooArgSet *modelSnapshot = dynamic_cast<const RooArgSet *>(snapshotVars.snapshot());
266 // restore now the variables of snapshot in ws to their original values
267 // need to const cast since assign is not const (but in reality in just assign values and does not change the set)
268 // and anyway the set is const
269 snapshotVars.assignFast(tempSnapshot);
270 return modelSnapshot;
271}
272
273////////////////////////////////////////////////////////////////////////////////
274/// load the snapshot from ws if it exists
275
277{
278 if (!GetWS())
279 return;
280 GetWS()->loadSnapshot(fSnapshotName.c_str());
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// helper functions to avoid code duplication
285
286void ModelConfig::DefineSetInWS(const char *name, const RooArgSet &set)
287{
288 if (!GetWS())
289 return;
290
291 const RooArgSet *prevSet = GetWS()->set(name);
292 if (prevSet) {
293 // be careful not to remove passed set in case it is the same updated
294 if (prevSet != &set)
295 GetWS()->removeSet(name);
296 }
297
298 // suppress warning when we re-define a previously defined set (when set == prevSet )
299 // and set is not removed in that case
300 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
301 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
302
303 GetWS()->defineSet(name, set, true);
304
305 RooMsgService::instance().setGlobalKillBelow(level);
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// internal function to import Pdf in WS
310
312{
313 if (!GetWS())
314 return;
315
316 if (!GetWS()->pdf(pdf.GetName())) {
317 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
318 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
320 RooMsgService::instance().setGlobalKillBelow(level);
321 }
322}
323
324////////////////////////////////////////////////////////////////////////////////
325/// internal function to import data in WS
326
328{
329 if (!GetWS())
330 return;
331
332 if (!GetWS()->data(data.GetName())) {
333 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
334 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
335 GetWS()->import(data);
336 RooMsgService::instance().setGlobalKillBelow(level);
337 }
338}
339
340////////////////////////////////////////////////////////////////////////////////
341
343{
344
346 for (auto const *arg : set) {
347 if (!arg->isFundamental()) {
348 nonparams.add(*arg);
349 }
350 }
351
352 if (errorMsgPrefix && !nonparams.empty()) {
353 std::cout << errorMsgPrefix << " ERROR: specified set contains non-parameters: " << nonparams << std::endl;
354 }
355 return (nonparams.empty());
356}
357
358/// Specify the external constraints.
360{
361 fExtConstraintsName = std::string(GetName()) + "_ExternalConstraints";
363}
364
365/// Specify the conditional observables.
367{
368 if (!SetHasOnlyParameters(set, "ModelConfig::SetConditionalObservables"))
369 return;
370 fConditionalObsName = std::string(GetName()) + "_ConditionalObservables";
372}
373
374/// Specify the global observables.
376{
377
378 if (!SetHasOnlyParameters(set, "ModelConfig::SetGlobalObservables"))
379 return;
380
381 // make global observables constant
382 for (auto *arg : set) {
383 arg->setAttribute("Constant", true);
384 }
385
386 fGlobalObsName = std::string(GetName()) + "_GlobalObservables";
387 DefineSetInWS(fGlobalObsName.c_str(), set);
388}
389
390namespace {
391
392std::unique_ptr<RooLinkedList>
393finalizeCmdList(ModelConfig const &modelConfig, RooLinkedList const &cmdList, std::vector<RooCmdArg> &cmdArgs)
394{
395 auto addCmdArg = [&](RooCmdArg const &cmdArg) {
396 if (cmdList.FindObject(cmdArg.GetName())) {
397 std::stringstream ss;
398 ss << "Illegal command argument \"" << cmdArg.GetName()
399 << "\" passed to ModelConfig::createNLL(). This option is retrieved from the ModelConfig itself.";
400 const std::string errorMsg = ss.str();
401 oocoutE(&modelConfig, InputArguments) << errorMsg << std::endl;
402 throw std::runtime_error(errorMsg);
403 }
404 cmdArgs.push_back(cmdArg);
405 };
406
407 if (auto args = modelConfig.GetConditionalObservables()) {
409 }
410
411 if (auto args = modelConfig.GetGlobalObservables()) {
413 }
414
415 if (auto args = modelConfig.GetExternalConstraints()) {
417 }
418
419 auto finalCmdList = std::make_unique<RooLinkedList>(cmdList);
420 for (RooCmdArg &arg : cmdArgs) {
421 finalCmdList->Add(&arg);
422 }
423
424 return finalCmdList;
425}
426
427} // namespace
428
429/** @fn RooStats::ModelConfig::createNLL()
430 *
431 * Wrapper around RooAbsPdf::createNLL(), where
432 * the pdf and some configuration options are retrieved from the ModelConfig.
433 *
434 * The options taken from the ModelConfig are:
435 *
436 * * ConditionalObservables()
437 * * GlobalObservables()
438 * * ExternalConstraints()
439 *
440 * Except for the options above, you can still pass all the other command
441 * arguments supported by RooAbsPdf::createNLL().
442 */
443
444std::unique_ptr<RooAbsReal> ModelConfig::createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList) const
445{
446 std::vector<RooCmdArg> cmdArgs;
448 return std::unique_ptr<RooAbsReal>{GetPdf()->createNLL(data, *finalCmdList)};
449}
450
451/** @fn RooStats::ModelConfig::fitTo()
452 *
453 * Wrapper around RooAbsPdf::fitTo(), where
454 * the pdf and some configuration options are retrieved from the ModelConfig.
455 *
456 * See ModelConfig::createNLL() for more information.
457 */
458std::unique_ptr<RooFitResult> ModelConfig::fitToImpl(RooAbsData &data, const RooLinkedList &cmdList) const
459{
460 std::vector<RooCmdArg> cmdArgs;
462 return std::unique_ptr<RooFitResult>{GetPdf()->fitTo(data, *finalCmdList)};
463}
464
465} // 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.
void merge(const RooWorkspace &)
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