Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
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(data)});
92 }
93 // global observables
94 if (!GetGlobalObservables()) {
96 co.remove(*std::unique_ptr<RooArgSet>{GetPdf()->getObservables(data)});
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(data.get(), params);
116 RooArgSet p(params);
117 p.remove(*GetParametersOfInterest());
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.GetObject()) {
200 fRefWS = &ws;
201 fWSName = ws.GetName();
202 } else {
203 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
204 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
205 GetWS()->merge(ws);
206 RooMsgService::instance().setGlobalKillBelow(level);
207 }
208}
209
210////////////////////////////////////////////////////////////////////////////////
211/// get from TRef
212
214{
215 RooWorkspace *ws = dynamic_cast<RooWorkspace *>(fRefWS.GetObject());
216 if (!ws) {
217 coutE(ObjectHandling) << "workspace not set" << std::endl;
218 return nullptr;
219 }
220 return ws;
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// save snapshot in the workspace
225/// and use values passed with the set
226
228{
229 if (!GetWS())
230 return;
231
233 if (!fSnapshotName.empty())
234 fSnapshotName += "_";
235 fSnapshotName += set.GetName();
236 if (!fSnapshotName.empty())
237 fSnapshotName += "_";
238 fSnapshotName += "snapshot";
239 GetWS()->saveSnapshot(fSnapshotName, set, true); // import also the given parameter values
240 DefineSetInWS(fSnapshotName.c_str(), set);
241}
242
243////////////////////////////////////////////////////////////////////////////////
244/// Load the snapshot from ws and return the corresponding set with the snapshot values.
245/// User must delete returned RooArgSet.
246
248{
249 if (!GetWS())
250 return nullptr;
251 if (!fSnapshotName.length())
252 return nullptr;
253 // calling loadSnapshot will also copy the current parameter values in the workspaces
254 // since we do not want to change the model parameters - we restore the previous ones
255 if (!GetWS()->set(fSnapshotName))
256 return nullptr;
258 if (snapshotVars.empty())
259 return nullptr;
260 // make my snapshot which will contain a copy of the snapshot variables
262 snapshotVars.snapshot(tempSnapshot);
263 // load snapshot value from the workspace
264 if (!(GetWS()->loadSnapshot(fSnapshotName.c_str())))
265 return nullptr;
266 // by doing this snapshotVars will have the snapshot values - make the snapshot to return
267 const RooArgSet *modelSnapshot = dynamic_cast<const RooArgSet *>(snapshotVars.snapshot());
268 // restore now the variables of snapshot in ws to their original values
269 // need to const cast since assign is not const (but in reality in just assign values and does not change the set)
270 // and anyway the set is const
271 snapshotVars.assignFast(tempSnapshot);
272 return modelSnapshot;
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// load the snapshot from ws if it exists
277
279{
280 if (!GetWS())
281 return;
282 GetWS()->loadSnapshot(fSnapshotName.c_str());
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// helper functions to avoid code duplication
287
288void ModelConfig::DefineSetInWS(const char *name, const RooArgSet &set)
289{
290 if (!GetWS())
291 return;
292
293 const RooArgSet *prevSet = GetWS()->set(name);
294 if (prevSet) {
295 // be careful not to remove passed set in case it is the same updated
296 if (prevSet != &set)
297 GetWS()->removeSet(name);
298 }
299
300 // suppress warning when we re-define a previously defined set (when set == prevSet )
301 // and set is not removed in that case
302 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
303 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
304
305 GetWS()->defineSet(name, set, true);
306
307 RooMsgService::instance().setGlobalKillBelow(level);
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// internal function to import Pdf in WS
312
314{
315 if (!GetWS())
316 return;
317
318 if (!GetWS()->pdf(pdf.GetName())) {
319 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
320 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
322 RooMsgService::instance().setGlobalKillBelow(level);
323 }
324}
325
326////////////////////////////////////////////////////////////////////////////////
327/// internal function to import data in WS
328
330{
331 if (!GetWS())
332 return;
333
334 if (!GetWS()->data(data.GetName())) {
335 RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
336 RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR);
337 GetWS()->import(data);
338 RooMsgService::instance().setGlobalKillBelow(level);
339 }
340}
341
342////////////////////////////////////////////////////////////////////////////////
343
345{
346
348 for (auto const *arg : set) {
349 if (!arg->isFundamental()) {
350 nonparams.add(*arg);
351 }
352 }
353
354 if (errorMsgPrefix && !nonparams.empty()) {
355 std::cout << errorMsgPrefix << " ERROR: specified set contains non-parameters: " << nonparams << std::endl;
356 }
357 return (nonparams.empty());
358}
359
360/// Specify the external constraints.
362{
363 fExtConstraintsName = std::string(GetName()) + "_ExternalConstraints";
365}
366
367/// Specify the conditional observables.
369{
370 if (!SetHasOnlyParameters(set, "ModelConfig::SetConditionalObservables"))
371 return;
372 fConditionalObsName = std::string(GetName()) + "_ConditionalObservables";
374}
375
376/// Specify the global observables.
378{
379
380 if (!SetHasOnlyParameters(set, "ModelConfig::SetGlobalObservables"))
381 return;
382
383 // make global observables constant
384 for (auto *arg : set) {
385 arg->setAttribute("Constant", true);
386 }
387
388 fGlobalObsName = std::string(GetName()) + "_GlobalObservables";
389 DefineSetInWS(fGlobalObsName.c_str(), set);
390}
391
392namespace {
393
394std::unique_ptr<RooLinkedList>
395finalizeCmdList(ModelConfig const &modelConfig, RooLinkedList const &cmdList, std::vector<RooCmdArg> &cmdArgs)
396{
397 auto addCmdArg = [&](RooCmdArg const &cmdArg) {
398 if (cmdList.FindObject(cmdArg.GetName())) {
399 std::stringstream ss;
400 ss << "Illegal command argument \"" << cmdArg.GetName()
401 << "\" passed to ModelConfig::createNLL(). This option is retrieved from the ModelConfig itself.";
402 const std::string errorMsg = ss.str();
403 oocoutE(&modelConfig, InputArguments) << errorMsg << std::endl;
404 throw std::runtime_error(errorMsg);
405 }
406 cmdArgs.push_back(cmdArg);
407 };
408
409 if (auto args = modelConfig.GetConditionalObservables()) {
411 }
412
413 if (auto args = modelConfig.GetGlobalObservables()) {
415 }
416
417 if (auto args = modelConfig.GetExternalConstraints()) {
419 }
420
421 auto finalCmdList = std::make_unique<RooLinkedList>(cmdList);
422 for (RooCmdArg &arg : cmdArgs) {
423 finalCmdList->Add(&arg);
424 }
425
426 return finalCmdList;
427}
428
429} // namespace
430
431/** @fn RooStats::ModelConfig::createNLL()
432 *
433 * Wrapper around RooAbsPdf::createNLL(), where
434 * the pdf and some configuration options are retrieved from the ModelConfig.
435 *
436 * The options taken from the ModelConfig are:
437 *
438 * * ConditionalObservables()
439 * * GlobalObservables()
440 * * ExternalConstraints()
441 *
442 * Except for the options above, you can still pass all the other command
443 * arguments supported by RooAbsPdf::createNLL().
444 */
445
446std::unique_ptr<RooAbsReal> ModelConfig::createNLLImpl(RooAbsData &data, const RooLinkedList &cmdList) const
447{
448 std::vector<RooCmdArg> cmdArgs;
450 return std::unique_ptr<RooAbsReal>{GetPdf()->createNLL(data, *finalCmdList)};
451}
452
453/** @fn RooStats::ModelConfig::fitTo()
454 *
455 * Wrapper around RooAbsPdf::fitTo(), where
456 * the pdf and some configuration options are retrieved from the ModelConfig.
457 *
458 * See ModelConfig::createNLL() for more information.
459 */
460std::unique_ptr<RooFitResult> ModelConfig::fitToImpl(RooAbsData &data, const RooLinkedList &cmdList) const
461{
462 std::vector<RooCmdArg> cmdArgs;
464 return std::unique_ptr<RooFitResult>{GetPdf()->fitTo(data, *finalCmdList)};
465}
466
467} // 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
Definition RtypesCore.h:66
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:263
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:40
RooFit::OwningPtr< RooAbsReal > createNLL(RooAbsData &data, CmdArgs_t const &... cmdArgs)
Construct representation of -log(L) of PDF with given dataset.
Definition RooAbsPdf.h:163
RooFit::OwningPtr< RooFitResult > fitTo(RooAbsData &data, CmdArgs_t const &... cmdArgs)
Fit PDF to given dataset.
Definition RooAbsPdf.h:157
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
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
Definition ModelConfig.h:35
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
std::string fWSName
name of the WS
const RooArgSet * GetConditionalObservables() const
get RooArgSet for conditional observables (return nullptr if not existing)
void GuessObsAndNuisance(const RooAbsData &data, bool printModelConfig=true)
Makes sensible guesses of observables, parameters of interest and nuisance parameters if one or multi...
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.
TRef 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 from TRef
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:47
TObject * GetObject() const
Return a pointer to the referenced object.
Definition TRef.cxx:377
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:58