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
22Efficient 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
43#include <iostream>
44#include <string>
45
46
47////////////////////////////////////////////////////////////////////////////////
48/// Constructor of specialized generator context for RooSimultaneous p.d.f.s. This
49/// context creates a dedicated context for each component p.d.f.s and delegates
50/// generation of events to the appropriate component generator context
51
53 const RooDataSet *prototype, const RooArgSet* auxProto, bool verbose) :
54 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _pdf(&model)
55{
56 // Determine if we are requested to generate the index category
57 RooAbsCategoryLValue const& idxCat = model.indexCat();
58 RooArgSet pdfVars(vars) ;
59
61 if (prototype) allPdfVars.add(*prototype->get(),true) ;
62
64 allPdfVars.selectCommon(model.flattenedCatList(), catsAmongAllVars);
65
66 if(catsAmongAllVars.size() != model.flattenedCatList().size()) {
67 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: This context must"
68 << " generate all components of the index category" << std::endl ;
69 _isValid = false ;
70 _numPdf = 0 ;
72 return ;
73 }
74
75 // We must either have the prototype or extended likelihood to determined
76 // the relative fractions of the components
78 _idxCatName = idxCat.GetName() ;
79 if (!_haveIdxProto && !model.canBeExtended()) {
80 oocoutE(_pdf,Generation) << "RooSimGenContext::ctor(" << GetName() << ") ERROR: Need either extended mode"
81 << " or prototype data to calculate number of events per category" << std::endl ;
82 _isValid = false ;
83 _numPdf = 0 ;
84 return ;
85 }
86
87 // Initialize fraction threshold array (used only in extended mode)
88 _numPdf = model._pdfProxyList.GetSize() ;
89 _fracThresh.resize(_numPdf+1);
90 _fracThresh[0] = 0 ;
91
92 // Generate index category and all registered PDFS
94 Int_t i(1) ;
96 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
97
98 // Name the context after the associated state and add to list
99 _gcList.emplace_back(pdf->genContext(pdfVars,prototype,auxProto,verbose)) ;
100
101 // Create generator context for this PDF
102 _gcList.back()->SetName(proxy->name()) ;
103
104 _gcIndex.push_back(idxCat.lookupIndex(proxy->name()));
105
106 // Fill fraction threshold array
107 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&allPdfVars)) ;
108 i++ ;
109 }
110
111 // Normalize fraction threshold array
112 if (!_haveIdxProto) {
113 for(i=0 ; i<_numPdf ; i++)
115 }
116
117
118 // Clone the index category
119 _idxCatSet = std::make_unique<RooArgSet>();
120 RooArgSet(model.indexCat()).snapshot(*_idxCatSet, true);
121 if (!_idxCatSet) {
122 oocoutE(_pdf,Generation) << "RooSimGenContext::RooSimGenContext(" << GetName() << ") Couldn't deep-clone index category, abort," << std::endl ;
123 throw std::string("RooSimGenContext::RooSimGenContext() Couldn't deep-clone index category, abort") ;
124 }
125
126 _idxCat = static_cast<RooAbsCategoryLValue*>(_idxCatSet->find(model.indexCat().GetName()));
127}
128
130
131////////////////////////////////////////////////////////////////////////////////
132/// Attach the index category clone to the given event buffer
133
135{
136 if (_idxCat->isDerived()) {
138 }
139
140 // Forward initGenerator call to all components
141 for(auto& item : _gcList) {
142 item->attach(args) ;
143 }
144
145}
146
147
148////////////////////////////////////////////////////////////////////////////////
149/// Perform one-time initialization of generator context
150
152{
153 // Attach the index category clone to the event
154 if (_idxCat->isDerived()) {
156 } else {
157 _idxCat = static_cast<RooAbsCategoryLValue*>(theEvent.find(_idxCat->GetName())) ;
158 }
159
160 // Update fractions reflecting possible new parameter values
162
163 // Forward initGenerator call to all components
164 for(auto& item : _gcList) {
165 item->initGenerator(theEvent) ;
166 }
167
168}
169
170
171////////////////////////////////////////////////////////////////////////////////
172/// Create an empty dataset to hold the events that will be generated
173
174RooDataSet* RooSimGenContext::createDataSet(const char* name, const char* title, const RooArgSet& obs)
175{
176
177 // If the observables do not contain the index, make a plain dataset
178 if (!obs.contains(*_idxCat)) {
179 return new RooDataSet(name,title,obs) ;
180 }
181
182 if (!_protoData) {
183 std::map<std::string,RooAbsData*> dmap ;
184 for (const auto& nameIdx : *_idxCat) {
185 RooAbsPdf* slicePdf = _pdf->getPdf(nameIdx.first.c_str());
186 std::unique_ptr<RooArgSet> sliceObs{slicePdf->getObservables(obs)};
187 std::string sliceName = name + ("_slice_" + nameIdx.first);
188 std::string sliceTitle = title + (" (index slice " + nameIdx.first + ")");
190 }
191 using namespace RooFit;
192 _protoData = std::make_unique<RooDataSet>(name, title, obs, Index(static_cast<RooCategory&>(*_idxCat)), Link(dmap), OwnLinked()) ;
193 }
194
195 return new RooDataSet(*_protoData,name) ;
196}
197
198
199
200
201
202////////////////////////////////////////////////////////////////////////////////
203/// Generate event appropriate for current index state.
204/// The index state is taken either from the prototype
205/// or is generated from the fraction threshold table.
206
208{
209 if (_haveIdxProto) {
210
211 // Lookup pdf from selected prototype index state
212 Int_t gidx(0);
214 for (Int_t i=0 ; i<(Int_t)_gcIndex.size() ; i++) {
215 if (_gcIndex[i]==cidx) { gidx = i ; break ; }
216 }
218 if (cx) {
219 cx->generateEvent(theEvent,remaining) ;
220 } else {
221 oocoutW(_pdf,Generation) << "RooSimGenContext::generateEvent: WARNING, no PDF to generate event of type " << cidx << std::endl ;
222 }
223
224
225 } else {
226
227 // Throw a random number and select PDF from fraction threshold table
228 double rand = RooRandom::uniform() ;
229 Int_t i=0 ;
230 for (i=0 ; i<_numPdf ; i++) {
231 if (rand>_fracThresh[i] && rand<_fracThresh[i+1]) {
232 RooAbsGenContext* gen=_gcList[i].get();
233 gen->generateEvent(theEvent,remaining) ;
234 //Write through to sub-categories because they might be written to dataset:
236 return ;
237 }
238 }
239
240 }
241}
242
243
244
245////////////////////////////////////////////////////////////////////////////////
246/// No action needed if we have a proto index
247
249{
250 if (_haveIdxProto) return ;
251
252 // Generate index category and all registered PDFS
253 Int_t i(1) ;
254 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdf->_pdfProxyList)) {
255 auto* pdf = static_cast<RooAbsPdf*>(proxy->absArg());
256
257 // Fill fraction threshold array
258 _fracThresh[i] = _fracThresh[i-1] + (_haveIdxProto?0:pdf->expectedEvents(&_allVarsPdf)) ;
259 i++ ;
260 }
261
262 // Normalize fraction threshold array
263 if (!_haveIdxProto) {
264 for(i=0 ; i<_numPdf ; i++)
266 }
267
268}
269
270
271
272////////////////////////////////////////////////////////////////////////////////
273/// Set the traversal order of the prototype data to that in the
274/// given lookup table. This information is passed to all
275/// component generator contexts
276
278{
280
281 for (auto& item : _gcList) {
282 item->setProtoDataOrder(lut) ;
283 }
284}
285
286
287////////////////////////////////////////////////////////////////////////////////
288/// Detailed printing interface
289
290void RooSimGenContext::printMultiline(std::ostream &os, Int_t content, bool verbose, TString indent) const
291{
293 os << indent << "--- RooSimGenContext ---" << std::endl ;
294 os << indent << "Using PDF ";
295 _pdf->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
296 os << indent << "List of component generators" << std::endl ;
297
299 indent2.Append(" ") ;
300
301 for (auto& item : _gcList) {
302 item->printMultiline(os,content,verbose,indent2);
303 }
304}
#define oocoutW(o, a)
#define oocoutE(o, a)
int Int_t
Definition RtypesCore.h:45
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:110
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:97
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.
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
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.
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:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:159
Object to represent discrete states.
Definition RooCategory.h:28
Container class to hold unbinned data.
Definition RooDataSet.h:34
static double uniform(TRandom *generator=randomGenerator())
Return a number uniformly distributed from (0,1)
Definition RooRandom.cxx:77
RooAbsCategoryLValue * _idxCat
Clone of index category.
void initGenerator(const RooArgSet &theEvent) override
Perform one-time initialization of generator context.
std::unique_ptr< RooDataSet > _protoData
! Prototype dataset
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Detailed printing interface.
std::unique_ptr< RooArgSet > _idxCatSet
Owner of index category components.
RooArgSet _allVarsPdf
All pdf variables.
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.
std::vector< std::unique_ptr< RooAbsGenContext > > _gcList
List of component generator contexts.
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.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
Generate event appropriate for current index state.
Int_t _numPdf
Number of generated PDFs.
std::vector< double > _fracThresh
[_numPdf] Fraction threshold array
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
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.
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:49
Basic string class.
Definition TString.h:139
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64