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
55
56namespace {
57
58void removeConstantParameters(RooAbsCollection &coll)
59{
60 RooArgSet constSet;
61 for (auto const *myarg : static_range_cast<RooRealVar *>(coll)) {
62 if (myarg->isConstant())
63 constSet.add(*myarg);
64 }
65 coll.remove(constSet);
66}
67
68} // namespace
69
70using namespace std;
71
72namespace RooStats {
73
74////////////////////////////////////////////////////////////////////////////////
75/// Makes sensible guesses of observables, parameters of interest
76/// and nuisance parameters if one or multiple have been set by the creator of this ModelConfig.
77///
78/// Defaults:
79/// - Observables: determined from data,
80/// - Global observables: explicit obs - obs from data - constant observables
81/// - Parameters of interest: empty,
82/// - Nuisance parameters: all parameters except parameters of interest
83///
84/// We use nullptr to mean not set, so we don't want to fill
85/// with empty RooArgSets.
86
87void ModelConfig::GuessObsAndNuisance(const RooAbsData &data, bool printModelConfig)
88{
89
90 // observables
91 if (!GetObservables()) {
92 SetObservables(*std::unique_ptr<RooArgSet>{GetPdf()->getObservables(data)});
93 }
94 // global observables
95 if (!GetGlobalObservables()) {
97 co.remove(*std::unique_ptr<RooArgSet>{GetPdf()->getObservables(data)});
98 removeConstantParameters(co);
99 if (!co.empty())
101
102 // TODO BUG This does not work as observables with the same name are already in the workspace.
103 /*
104 RooArgSet o(*GetObservables());
105 o.remove(co);
106 SetObservables(o);
107 */
108 }
109
110 // parameters
111 // if (!GetParametersOfInterest()) {
112 // SetParametersOfInterest(RooArgSet());
113 // }
114 if (!GetNuisanceParameters()) {
115 RooArgSet params;
116 GetPdf()->getParameters(data.get(), params);
117 RooArgSet p(params);
118 p.remove(*GetParametersOfInterest());
119 removeConstantParameters(p);
120 if (!p.empty())
122 }
123
124 // print Modelconfig as an info message
125
126 if (printModelConfig) {
127 std::ostream &oldstream = RooPrintable::defaultPrintStream(&ccoutI(InputArguments));
128 Print();
130 }
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// print contents of Model on the default print stream
135/// It can be changed using RooPrintable
136
138{
139 ostream &os = RooPrintable::defaultPrintStream();
140
141 os << endl << "=== Using the following for " << GetName() << " ===" << endl;
142
143 // args
144 if (GetObservables()) {
145 os << "Observables: ";
146 GetObservables()->Print("");
147 }
149 os << "Parameters of Interest: ";
151 }
152 if (GetNuisanceParameters()) {
153 os << "Nuisance Parameters: ";
155 }
156 if (GetGlobalObservables()) {
157 os << "Global Observables: ";
159 }
161 os << "Constraint Parameters: ";
163 }
165 os << "Conditional Observables: ";
167 }
168 if (GetProtoData()) {
169 os << "Proto Data: ";
170 GetProtoData()->Print("");
171 }
172
173 // pdfs
174 if (GetPdf()) {
175 os << "PDF: ";
176 GetPdf()->Print("");
177 }
178 if (GetPriorPdf()) {
179 os << "Prior PDF: ";
180 GetPriorPdf()->Print("");
181 }
182
183 // snapshot
184 const RooArgSet *snapshot = GetSnapshot();
185 if (snapshot) {
186 os << "Snapshot: " << endl;
187 snapshot->Print("v");
188 delete snapshot;
189 }
190
191 os << endl;
192}
193
194////////////////////////////////////////////////////////////////////////////////
195/// If a workspace already exists in this ModelConfig, RooWorkspace::merge(ws) will be called
196/// on the existing workspace.
197
199{
200 if (!fRefWS.GetObject()) {
201 fRefWS = &ws;
202 fWSName = ws.GetName();
203 } else {
206 GetWS()->merge(ws);
208 }
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// get from TRef
213
215{
216 RooWorkspace *ws = dynamic_cast<RooWorkspace *>(fRefWS.GetObject());
217 if (!ws) {
218 coutE(ObjectHandling) << "workspace not set" << endl;
219 return nullptr;
220 }
221 return ws;
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// save snapshot in the workspace
226/// and use values passed with the set
227
229{
230 if (!GetWS())
231 return;
232
234 if (fSnapshotName.size() > 0)
235 fSnapshotName += "_";
236 fSnapshotName += set.GetName();
237 if (fSnapshotName.size() > 0)
238 fSnapshotName += "_";
239 fSnapshotName += "snapshot";
240 GetWS()->saveSnapshot(fSnapshotName.c_str(), set, true); // import also the given parameter values
241 DefineSetInWS(fSnapshotName.c_str(), set);
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Load the snapshot from ws and return the corresponding set with the snapshot values.
246/// User must delete returned RooArgSet.
247
249{
250 if (!GetWS())
251 return 0;
252 if (!fSnapshotName.length())
253 return 0;
254 // calling loadSnapshot will also copy the current parameter values in the workspaces
255 // since we do not want to change the model parameters - we restore the previous ones
256 if (!GetWS()->set(fSnapshotName.c_str()))
257 return 0;
258 RooArgSet snapshotVars(*GetWS()->set(fSnapshotName.c_str()));
259 if (snapshotVars.empty())
260 return 0;
261 // make my snapshot which will contain a copy of the snapshot variables
262 RooArgSet tempSnapshot;
263 snapshotVars.snapshot(tempSnapshot);
264 // load snapshot value from the workspace
265 if (!(GetWS()->loadSnapshot(fSnapshotName.c_str())))
266 return 0;
267 // by doing this snapshotVars will have the snapshot values - make the snapshot to return
268 const RooArgSet *modelSnapshot = dynamic_cast<const RooArgSet *>(snapshotVars.snapshot());
269 // restore now the variables of snapshot in ws to their original values
270 // need to const cast since assign is not const (but in reality in just assign values and does not change the set)
271 // and anyway the set is const
272 snapshotVars.assignFast(tempSnapshot);
273 return modelSnapshot;
274}
275
276////////////////////////////////////////////////////////////////////////////////
277/// load the snapshot from ws if it exists
278
280{
281 if (!GetWS())
282 return;
283 GetWS()->loadSnapshot(fSnapshotName.c_str());
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// helper functions to avoid code duplication
288
289void ModelConfig::DefineSetInWS(const char *name, const RooArgSet &set)
290{
291 if (!GetWS())
292 return;
293
294 const RooArgSet *prevSet = GetWS()->set(name);
295 if (prevSet) {
296 // be careful not to remove passed set in case it is the same updated
297 if (prevSet != &set)
298 GetWS()->removeSet(name);
299 }
300
301 // suppress warning when we re-define a previously defined set (when set == prevSet )
302 // and set is not removed in that case
305
306 GetWS()->defineSet(name, set, true);
307
309}
310
311////////////////////////////////////////////////////////////////////////////////
312/// internal function to import Pdf in WS
313
315{
316 if (!GetWS())
317 return;
318
319 if (!GetWS()->pdf(pdf.GetName())) {
324 }
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// internal function to import data in WS
329
331{
332 if (!GetWS())
333 return;
334
335 if (!GetWS()->data(data.GetName())) {
338 GetWS()->import(data);
340 }
341}
342
343////////////////////////////////////////////////////////////////////////////////
344
345bool ModelConfig::SetHasOnlyParameters(const RooArgSet &set, const char *errorMsgPrefix)
346{
347
348 RooArgSet nonparams;
349 for (auto const *arg : set) {
350 if (!arg->isFundamental()) {
351 nonparams.add(*arg);
352 }
353 }
354
355 if (errorMsgPrefix && !nonparams.empty()) {
356 cout << errorMsgPrefix << " ERROR: specified set contains non-parameters: " << nonparams << endl;
357 }
358 return (nonparams.empty());
359}
360
361/// Specify the external constraints.
363{
364 fExtConstraintsName = std::string(GetName()) + "_ExternalConstraints";
366}
367
368/// Specify the conditional observables.
370{
371 if (!SetHasOnlyParameters(set, "ModelConfig::SetConditionalObservables"))
372 return;
373 fConditionalObsName = std::string(GetName()) + "_ConditionalObservables";
375}
376
377/// Specify the global observables.
379{
380
381 if (!SetHasOnlyParameters(set, "ModelConfig::SetGlobalObservables"))
382 return;
383
384 // make global observables constant
385 for (auto *arg : set) {
386 arg->setAttribute("Constant", true);
387 }
388
389 fGlobalObsName = std::string(GetName()) + "_GlobalObservables";
390 DefineSetInWS(fGlobalObsName.c_str(), set);
391}
392
393namespace {
394
395std::unique_ptr<RooLinkedList>
396finalizeCmdList(ModelConfig const &modelConfig, RooLinkedList const &cmdList, std::vector<RooCmdArg> &cmdArgs)
397{
398 auto addCmdArg = [&](RooCmdArg const &cmdArg) {
399 if (cmdList.FindObject(cmdArg.GetName())) {
400 std::stringstream ss;
401 ss << "Illegal command argument \"" << cmdArg.GetName()
402 << "\" passed to ModelConfig::createNLL(). This option is retrieved from the ModelConfig itself.";
403 const std::string errorMsg = ss.str();
404 oocoutE(&modelConfig, InputArguments) << errorMsg << std::endl;
405 throw std::runtime_error(errorMsg);
406 }
407 cmdArgs.push_back(cmdArg);
408 };
409
410 if (auto args = modelConfig.GetConditionalObservables()) {
411 addCmdArg(RooFit::ConditionalObservables(*args));
412 }
413
414 if (auto args = modelConfig.GetGlobalObservables()) {
415 addCmdArg(RooFit::GlobalObservables(*args));
416 }
417
418 if (auto args = modelConfig.GetExternalConstraints()) {
419 addCmdArg(RooFit::ExternalConstraints(*args));
420 }
421
422 auto finalCmdList = std::make_unique<RooLinkedList>(cmdList);
423 for (RooCmdArg &arg : cmdArgs) {
424 finalCmdList->Add(&arg);
425 }
426
427 return finalCmdList;
428}
429
430} // namespace
431
432/// Wrapper around RooAbsPdf::createNLL(RooAbsData&, const RooLinkedList&), where
433/// the pdf and some configuration options are retrieved from the ModelConfig.
434///
435/// The options taken from the ModelConfig are:
436///
437/// * ConditionalObservables()
438/// * GlobalObservables()
439/// * ExternalConstraints()
440///
441/// Except for the options above, you can still pass all the other command
442/// arguments supported by RooAbsPdf::createNLL().
443std::unique_ptr<RooAbsReal> ModelConfig::createNLL(RooAbsData &data, const RooLinkedList &cmdList) const
444{
445 std::vector<RooCmdArg> cmdArgs;
446 auto finalCmdList = finalizeCmdList(*this, cmdList, cmdArgs);
447 return std::unique_ptr<RooAbsReal>{GetPdf()->createNLL(data, *finalCmdList)};
448}
449
450/// Wrapper around RooAbsPdf::fitTo(RooAbsData&, const RooLinkedList&), where
451/// the pdf and some configuration options are retrieved from the ModelConfig.
452///
453/// Sett ModelConfig::createNLL() for more information.
454std::unique_ptr<RooFitResult> ModelConfig::fitTo(RooAbsData &data, const RooLinkedList &cmdList)
455{
456 std::vector<RooCmdArg> cmdArgs;
457 auto finalCmdList = finalizeCmdList(*this, cmdList, 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
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
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:318
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.
RooAbsCollection is an abstract container object that can hold multiple RooAbsArg objects.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
void assignFast(const RooAbsCollection &other, bool setValDirty=true) const
Functional equivalent of assign() but assumes this and other collection have same layout.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:59
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
Definition RooAbsData.h:236
virtual RooFit::OwningPtr< RooAbsReal > createNLL(RooAbsData &data, const RooLinkedList &cmdList={})
Construct representation of -log(L) of PDF with given dataset.
virtual RooFit::OwningPtr< RooFitResult > fitTo(RooAbsData &data, const RooLinkedList &cmdList={})
Fit PDF to given dataset.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:178
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition RooCmdArg.h:26
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
TObject * FindObject(const char *name) const override
Return pointer to obejct with given name.
static RooMsgService & instance()
Return reference to singleton instance.
void setGlobalKillBelow(RooFit::MsgLevel level)
RooFit::MsgLevel globalKillBelow() const
static std::ostream & defaultPrintStream(std::ostream *os=nullptr)
Return a reference to the current default stream to use in Print().
RooRealVar represents a variable that can be changed from the outside.
Definition RooRealVar.h:40
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::unique_ptr< RooFitResult > fitTo(RooAbsData &data, const RooLinkedList &cmdList={})
Wrapper around RooAbsPdf::fitTo(RooAbsData&, const RooLinkedList&), where the pdf and some configurat...
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 > createNLL(RooAbsData &data, const RooLinkedList &cmdList={}) const
Wrapper around RooAbsPdf::createNLL(RooAbsData&, const RooLinkedList&), where the pdf and some config...
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
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)
const RooArgSet * GetExternalConstraints() const
get RooArgSet for global observables (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.
The RooWorkspace is a 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 import(const RooAbsArg &arg, const RooCmdArg &arg1=RooCmdArg(), const RooCmdArg &arg2=RooCmdArg(), const RooCmdArg &arg3=RooCmdArg(), const RooCmdArg &arg4=RooCmdArg(), const RooCmdArg &arg5=RooCmdArg(), const RooCmdArg &arg6=RooCmdArg(), const RooCmdArg &arg7=RooCmdArg(), const RooCmdArg &arg8=RooCmdArg(), const RooCmdArg &arg9=RooCmdArg())
Import a RooAbsArg object, e.g.
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.
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 Asimov.h:19