Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooSimGenContext.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
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/**
18\file RooSimGenContext.cxx
19\class RooSimGenContext
20\ingroup Roofitcore
21
22RooSimGenContext is an efficient implementation of the generator context
23specific for RooSimultaneous PDFs when generating more than one of the
24component pdfs.
25It runs in two modes:
26- Proto data with category entries are given: An event from the same category as
27in the proto data is created.
28- No proto data: A category is chosen randomly.
29\note This requires that the PDFs are extended, to determine the relative probabilities
30that an event originates from a certain category.
31**/
32
33#include "RooSimGenContext.h"
34#include "RooSimultaneous.h"
35#include "RooRealProxy.h"
36#include "RooDataSet.h"
37#include "Roo1DTable.h"
38#include "RooCategory.h"
39#include "RooMsgService.h"
40#include "RooRandom.h"
41#include "RooGlobalFunc.h"
42
43using namespace RooFit;
44
45#include <iostream>
46#include <string>
47
48using namespace std;
49
51;
52
53
54////////////////////////////////////////////////////////////////////////////////
55/// Constructor of specialized generator context for RooSimultaneous p.d.f.s. This
56/// context creates a dedicated context for each component p.d.f.s and delegates
57/// generation of events to the appropriate component generator context
58
60 const RooDataSet *prototype, const RooArgSet* auxProto, bool verbose) :
61 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _pdf(&model), _protoData(nullptr)
62{
63 // Determine if we are requested to generate the index category
64 RooAbsCategoryLValue const& idxCat = model.indexCat();
65 RooArgSet pdfVars(vars) ;
66
67 RooArgSet allPdfVars(pdfVars) ;
68 if (prototype) allPdfVars.add(*prototype->get(),true) ;
69
70 RooArgSet catsAmongAllVars;
71 allPdfVars.selectCommon(model.flattenedCatList(), catsAmongAllVars);
72
73 if(catsAmongAllVars.size() != model.flattenedCatList().size()) {
74 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: This context must"
75 << " generate all components of the index category" << endl ;
76 _isValid = false ;
77 _numPdf = 0 ;
78 _haveIdxProto = false ;
79 return ;
80 }
81
82 // We must either have the prototype or extended likelihood to determined
83 // the relative fractions of the components
84 _haveIdxProto = prototype ? true : false ;
85 _idxCatName = idxCat.GetName() ;
86 if (!_haveIdxProto && !model.canBeExtended()) {
87 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: Need either extended mode"
88 << " or prototype data to calculate number of events per category" << endl ;
89 _isValid = false ;
90 _numPdf = 0 ;
91 return ;
92 }
93
94 // Initialize fraction threshold array (used only in extended mode)
95 _numPdf = model._pdfProxyList.GetSize() ;
96 _fracThresh = new double[_numPdf+1] ;
97 _fracThresh[0] = 0 ;
98
99 // Generate index category and all registered PDFS
100 _allVarsPdf.add(allPdfVars) ;
101 Int_t i(1) ;
102 for(auto * proxy : static_range_cast<RooRealProxy*>(model._pdfProxyList)) {
103 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
104
105 // Create generator context for this PDF
106 RooAbsGenContext* cx = pdf->genContext(pdfVars,prototype,auxProto,verbose) ;
107
108 // Name the context after the associated state and add to list
109 cx->SetName(proxy->name()) ;
110 _gcList.push_back(cx) ;
111 _gcIndex.push_back(idxCat.lookupIndex(proxy->name()));
112
113 // Fill fraction threshold array
114 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&allPdfVars)) ;
115 i++ ;
116 }
117
118 // Normalize fraction threshold array
119 if (!_haveIdxProto) {
120 for(i=0 ; i<_numPdf ; i++)
122 }
123
124
125 // Clone the index category
126 _idxCatSet = new RooArgSet;
127 RooArgSet(model.indexCat()).snapshot(*_idxCatSet, true);
128 if (!_idxCatSet) {
129 oocoutE(_pdf,Generation) << "RooSimGenContext::RooSimGenContext(" << GetName() << ") Couldn't deep-clone index category, abort," << endl ;
130 throw std::string("RooSimGenContext::RooSimGenContext() Couldn't deep-clone index category, abort") ;
131 }
132
133 _idxCat = static_cast<RooAbsCategoryLValue*>(_idxCatSet->find(model.indexCat().GetName()));
134}
135
136
137
138////////////////////////////////////////////////////////////////////////////////
139/// Destructor. Delete all owned subgenerator contexts
140
142{
143 delete[] _fracThresh ;
144 delete _idxCatSet ;
145 for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
146 delete (*iter) ;
147 }
148 if (_protoData) delete _protoData ;
149}
150
151
152
153////////////////////////////////////////////////////////////////////////////////
154/// Attach the index category clone to the given event buffer
155
157{
158 if (_idxCat->isDerived()) {
160 }
161
162 // Forward initGenerator call to all components
163 for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
164 (*iter)->attach(args) ;
165 }
166
167}
168
169
170////////////////////////////////////////////////////////////////////////////////
171/// Perform one-time initialization of generator context
172
174{
175 // Attach the index category clone to the event
176 if (_idxCat->isDerived()) {
178 } else {
180 }
181
182 // Update fractions reflecting possible new parameter values
184
185 // Forward initGenerator call to all components
186 for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
187 (*iter)->initGenerator(theEvent) ;
188 }
189
190}
191
192
193////////////////////////////////////////////////////////////////////////////////
194/// Create an empty dataset to hold the events that will be generated
195
196RooDataSet* RooSimGenContext::createDataSet(const char* name, const char* title, const RooArgSet& obs)
197{
198
199 // If the observables do not contain the index, make a plain dataset
200 if (!obs.contains(*_idxCat)) {
201 return new RooDataSet(name,title,obs) ;
202 }
203
204 if (!_protoData) {
205 map<string,RooAbsData*> dmap ;
206 for (const auto& nameIdx : *_idxCat) {
207 RooAbsPdf* slicePdf = _pdf->getPdf(nameIdx.first.c_str());
208 std::unique_ptr<RooArgSet> sliceObs{slicePdf->getObservables(obs)};
209 std::string sliceName = Form("%s_slice_%s", name, nameIdx.first.c_str());
210 std::string sliceTitle = Form("%s (index slice %s)", title, nameIdx.first.c_str());
211 dmap[nameIdx.first] = new RooDataSet(sliceName,sliceTitle,*sliceObs);
212 }
213 _protoData = new RooDataSet(name, title, obs, Index((RooCategory&)*_idxCat), Link(dmap), OwnLinked()) ;
214 }
215
216 RooDataSet* emptyClone = new RooDataSet(*_protoData,name) ;
217
218 return emptyClone ;
219}
220
221
222
223
224
225////////////////////////////////////////////////////////////////////////////////
226/// Generate event appropriate for current index state.
227/// The index state is taken either from the prototype
228/// or is generated from the fraction threshold table.
229
231{
232 if (_haveIdxProto) {
233
234 // Lookup pdf from selected prototype index state
235 Int_t gidx(0), cidx =_idxCat->getCurrentIndex() ;
236 for (Int_t i=0 ; i<(Int_t)_gcIndex.size() ; i++) {
237 if (_gcIndex[i]==cidx) { gidx = i ; break ; }
238 }
239 RooAbsGenContext* cx = _gcList[gidx] ;
240 if (cx) {
241 cx->generateEvent(theEvent,remaining) ;
242 } else {
243 oocoutW(_pdf,Generation) << "RooSimGenContext::generateEvent: WARNING, no PDF to generate event of type " << cidx << endl ;
244 }
245
246
247 } else {
248
249 // Throw a random number and select PDF from fraction threshold table
250 double rand = RooRandom::uniform() ;
251 Int_t i=0 ;
252 for (i=0 ; i<_numPdf ; i++) {
253 if (rand>_fracThresh[i] && rand<_fracThresh[i+1]) {
254 RooAbsGenContext* gen=_gcList[i] ;
255 gen->generateEvent(theEvent,remaining) ;
256 //Write through to sub-categories because they might be written to dataset:
258 return ;
259 }
260 }
261
262 }
263}
264
265
266
267////////////////////////////////////////////////////////////////////////////////
268/// No action needed if we have a proto index
269
271{
272 if (_haveIdxProto) return ;
273
274 // Generate index category and all registered PDFS
275 Int_t i(1) ;
276 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdf->_pdfProxyList)) {
277 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
278
279 // Fill fraction threshold array
280 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&_allVarsPdf)) ;
281 i++ ;
282 }
283
284 // Normalize fraction threshold array
285 if (!_haveIdxProto) {
286 for(i=0 ; i<_numPdf ; i++)
288 }
289
290}
291
292
293
294////////////////////////////////////////////////////////////////////////////////
295/// Set the traversal order of the prototype data to that in the
296/// given lookup table. This information is passed to all
297/// component generator contexts
298
300{
302
303 for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
304 (*iter)->setProtoDataOrder(lut) ;
305 }
306}
307
308
309////////////////////////////////////////////////////////////////////////////////
310/// Detailed printing interface
311
312void RooSimGenContext::printMultiline(ostream &os, Int_t content, bool verbose, TString indent) const
313{
314 RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
315 os << indent << "--- RooSimGenContext ---" << endl ;
316 os << indent << "Using PDF ";
318 os << indent << "List of component generators" << endl ;
319
320 TString indent2(indent) ;
321 indent2.Append(" ") ;
322
323 for (vector<RooAbsGenContext*>::const_iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
324 (*iter)->printMultiline(os,content,verbose,indent2);
325 }
326}
#define oocoutW(o, a)
#define oocoutE(o, a)
int Int_t
Definition RtypesCore.h:45
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2467
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
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.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:99
Abstract base class for objects that represent a discrete value that can be set from the outside,...
virtual bool setIndex(value_type index, bool printError=true)=0
Change category state by specifying the index code of the desired state.
virtual value_type getCurrentIndex() const
Return index number of current state.
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
bool contains(const RooAbsArg &var) const
Check if collection contains an argument with the same name as var.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
bool selectCommon(const RooAbsCollection &refColl, RooAbsCollection &outColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for generator contexts of RooAbsPdf objects.
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Interface for multi-line printing.
virtual void generateEvent(RooArgSet &theEvent, Int_t remaining)=0
bool _isValid
Is context in valid state?
virtual void setProtoDataOrder(Int_t *lut)
Set the traversal order of prototype data to that in the lookup tables passed as argument.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
bool canBeExtended() const
If true, PDF can provide extended likelihood term.
Definition RooAbsPdf.h:218
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
Object to represent discrete states.
Definition RooCategory.h:28
RooDataSet is a container class to hold unbinned data.
Definition RooDataSet.h:57
const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition RooRandom.cxx:81
RooSimGenContext is an efficient implementation of the generator context specific for RooSimultaneous...
RooAbsCategoryLValue * _idxCat
Clone of index category.
void initGenerator(const RooArgSet &theEvent) override
Perform one-time initialization of generator context.
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Detailed printing interface.
RooArgSet _allVarsPdf
All pdf variables.
double * _fracThresh
[_numPdf] Fraction threshold array
RooArgSet * _idxCatSet
Owner of index category components.
void setProtoDataOrder(Int_t *lut) override
Set the traversal order of the prototype data to that in the given lookup table.
void updateFractions()
No action needed if we have a proto index.
RooDataSet * _protoData
! Prototype dataset
const RooSimultaneous * _pdf
Original PDF.
RooSimGenContext(const RooSimultaneous &model, const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool _verbose=false)
Constructor of specialized generator context for RooSimultaneous p.d.f.s.
RooDataSet * createDataSet(const char *name, const char *title, const RooArgSet &obs) override
Create an empty dataset to hold the events that will be generated.
TString _idxCatName
Name of index category.
std::vector< RooAbsGenContext * > _gcList
List of component generator contexts.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
Generate event appropriate for current index state.
Int_t _numPdf
Number of generated PDFs.
std::vector< int > _gcIndex
Index value corresponding to component.
void attach(const RooArgSet &params) override
Attach the index category clone to the given event buffer.
~RooSimGenContext() override
Destructor. Delete all owned subgenerator contexts.
bool _haveIdxProto
Flag set if generation of index is requested.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
TList _pdfProxyList
List of PDF proxies (named after applicable category state)
RooArgSet const & flattenedCatList() const
Internal utility function to get a list of all category components for this RooSimultaneous.
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
const RooAbsCategoryLValue & indexCat() const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
Basic string class.
Definition TString.h:139
TString & Append(const char *cs)
Definition TString.h:576
RooCmdArg OwnLinked()
RooCmdArg Index(RooCategory &icat)
RooCmdArg Link(const char *state, RooAbsData &data)
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26