Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooProdGenContext.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 RooProdGenContext.cxx
19\class RooProdGenContext
20\ingroup Roofitcore
21
22RooProdGenContext is an efficient implementation of the generator context
23specific for RooProdPdf PDFs. The sim-context owns a list of
24component generator contexts that are used to generate the dependents
25for each component PDF sequentially.
26**/
27
28#include "Riostream.h"
29#include "RooMsgService.h"
30
31#include "RooProdGenContext.h"
32#include "RooProdPdf.h"
33#include "RooDataSet.h"
34#include "RooRealVar.h"
35#include "RooGlobalFunc.h"
36
37
38
39using namespace std;
40
42;
43
44
45////////////////////////////////////////////////////////////////////////////////
46
48 const RooDataSet *prototype, const RooArgSet* auxProto, bool verbose) :
49 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _pdf(&model)
50{
51 // Constructor of optimization generator context for RooProdPdf objects
52
53 //Build an array of generator contexts for each product component PDF
54 cxcoutI(Generation) << "RooProdGenContext::ctor() setting up event special generator context for product p.d.f. " << model.GetName()
55 << " for generation of observable(s) " << vars ;
56 if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
57 if (auxProto && !auxProto->empty()) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
58 ccxcoutI(Generation) << endl ;
59
60 // Make full list of dependents (generated & proto)
61 RooArgSet deps(vars) ;
62 if (prototype) {
63 RooArgSet protoDeps;
64 model.getObservables(prototype->get(), protoDeps);
65 deps.remove(protoDeps,true,true) ;
66 }
67
68 // Factorize product in irreducible terms
69 RooLinkedList termList,depsList,impDepList,crossDepList,intList ;
70 model.factorizeProduct(deps,RooArgSet(),termList,depsList,impDepList,crossDepList,intList) ;
71
72 if (dologD(Generation)) {
73 cxcoutD(Generation) << "RooProdGenContext::ctor() factorizing product expression in irriducible terms " ;
74 for(auto * t : static_range_cast<RooArgSet*>(termList)) {
75 ccxcoutD(Generation) << *t ;
76 }
77 ccxcoutD(Generation) << std::endl;
78 }
79
80 RooArgSet genDeps ;
81 // First add terms that do not import observables
82
83 bool anyAction = true ;
84 bool go=true ;
85 while(go) {
86
87 auto termIter = termList.begin();
88 auto impIter = impDepList.begin();
89 auto normIter = depsList.begin();
90
91 bool anyPrevAction=anyAction ;
92 anyAction=false ;
93
94 if (termList.empty()) {
95 break ;
96 }
97
98 while(termIter != termList.end()) {
99
100 auto * term = static_cast<RooArgSet*>(*termIter);
101 auto * impDeps = static_cast<RooArgSet*>(*impIter);
102 auto * termDeps = static_cast<RooArgSet*>(*normIter);
103 if (impDeps==nullptr || termDeps==nullptr) {
104 break ;
105 }
106
107 cxcoutD(Generation) << "RooProdGenContext::ctor() analyzing product term " << *term << " with observable(s) " << *termDeps ;
108 if (!impDeps->empty()) {
109 ccxcoutD(Generation) << " which has dependence of external observable(s) " << *impDeps << " that to be generated first by other terms" ;
110 }
111 ccxcoutD(Generation) << std::endl;
112
113 // Add this term if we have no imported dependents, or imported dependents are already generated
114 RooArgSet neededDeps(*impDeps) ;
115 neededDeps.remove(genDeps,true,true) ;
116
117 if (!neededDeps.empty()) {
118 if (!anyPrevAction) {
119 cxcoutD(Generation) << "RooProdGenContext::ctor() no convergence in single term analysis loop, terminating loop and process remainder of terms as single unit " << endl ;
120 go=false ;
121 break ;
122 }
123 cxcoutD(Generation) << "RooProdGenContext::ctor() skipping this term for now because it needs imported dependents that are not generated yet" << endl ;
124 ++termIter;
125 ++impIter;
126 ++normIter;
127 continue ;
128 }
129
130 // Check if this component has any dependents that need to be generated
131 // e.g. it can happen that there are none if all dependents of this component are prototyped
132 if (termDeps->empty()) {
133 cxcoutD(Generation) << "RooProdGenContext::ctor() term has no observables requested to be generated, removing it" << endl ;
134
135 // Increment the iterators first, because Removing the corresponding element
136 // would invalidate them otherwise.
137 ++termIter;
138 ++normIter;
139 ++impIter;
140 termList.Remove(term);
141 depsList.Remove(termDeps);
142 impDepList.Remove(impDeps);
143
144 delete term ;
145 delete termDeps ;
146 delete impDeps ;
147 anyAction=true ;
148 continue ;
149 }
150
151 if (term->size()==1) {
152 // Simple term
153
154 auto pdf = static_cast<RooAbsPdf*>((*term)[0]);
155 std::unique_ptr<RooArgSet> pdfDep{pdf->getObservables(termDeps)};
156 if (!pdfDep->empty()) {
157 coutI(Generation) << "RooProdGenContext::ctor() creating subcontext for generation of observables " << *pdfDep << " from model " << pdf->GetName() << endl ;
158 std::unique_ptr<RooArgSet> auxProto2{pdf->getObservables(impDeps)};
159 _gcList.push_back(pdf->genContext(*pdfDep,prototype,auxProto2.get(),verbose)) ;
160 }
161
162// cout << "adding following dependents to list of generated observables: " ; pdfDep->Print("1") ;
163 genDeps.add(*pdfDep) ;
164
165 } else {
166
167 // Composite term
168 if (!termDeps->empty()) {
169 const std::string name = model.makeRGPPName("PRODGEN_",*term,RooArgSet(),RooArgSet(),0) ;
170
171 // Construct auxiliary PDF expressing product of composite terms,
172 // following Conditional component specification of input model
173 RooLinkedList cmdList ;
174 RooLinkedList pdfSetList ;
175 RooArgSet fullPdfSet ;
176 for(auto * pdf : static_range_cast<RooAbsPdf*>(*term)) {
177
178 RooArgSet* pdfnset = model.findPdfNSet(*pdf) ;
179 RooArgSet* pdfSet = new RooArgSet(*pdf) ;
180 pdfSetList.Add(pdfSet) ;
181
182 if (pdfnset && !pdfnset->empty()) {
183 // This PDF requires a Conditional() construction
184 cmdList.Add(RooFit::Conditional(*pdfSet,*pdfnset).Clone()) ;
185// cout << "Conditional " << pdf->GetName() << " " ; pdfnset->Print("1") ;
186 } else {
187 fullPdfSet.add(*pdfSet) ;
188 }
189
190 }
191 RooProdPdf* multiPdf = new RooProdPdf(name.c_str(),name.c_str(),fullPdfSet,cmdList) ;
192 cmdList.Delete() ;
193 pdfSetList.Delete() ;
194
195 multiPdf->setOperMode(RooAbsArg::ADirty,true) ;
196 multiPdf->useDefaultGen(true) ;
197 _ownedMultiProds.addOwned(*multiPdf) ;
198
199 coutI(Generation) << "RooProdGenContext()::ctor creating subcontext for generation of observables " << *termDeps
200 << "for irriducuble composite term using sub-product object " << multiPdf->GetName() ;
201 RooAbsGenContext* cx = multiPdf->genContext(*termDeps,prototype,auxProto,verbose) ;
202 _gcList.push_back(cx) ;
203
204 genDeps.add(*termDeps) ;
205
206 }
207 }
208
209 // Increment the iterators first, because Removing the corresponding
210 // element would invalidate them otherwise.
211 ++termIter;
212 ++normIter;
213 ++impIter;
214 termList.Remove(term);
215 depsList.Remove(termDeps);
216 impDepList.Remove(impDeps);
217 delete term ;
218 delete termDeps ;
219 delete impDeps ;
220 anyAction=true ;
221 }
222 }
223
224 // Check if there are any left over terms that cannot be generated
225 // separately due to cross dependency of observables
226 if (!termList.empty()) {
227
228 cxcoutD(Generation) << "RooProdGenContext::ctor() there are left-over terms that need to be generated separately" << endl ;
229
230 // Concatenate remaining terms
231 auto normIter = depsList.begin();
232 RooArgSet trailerTerm ;
233 RooArgSet trailerTermDeps ;
234 for(auto * term : static_range_cast<RooArgSet*>(termList)) {
235 auto* termDeps = static_cast<RooArgSet*>(*normIter);
236 trailerTerm.add(*term) ;
237 trailerTermDeps.add(*termDeps) ;
238 ++normIter;
239 }
240
241 const std::string name = model.makeRGPPName("PRODGEN_",trailerTerm,RooArgSet(),RooArgSet(),0) ;
242
243 // Construct auxiliary PDF expressing product of composite terms,
244 // following Partial/Full component specification of input model
245 RooLinkedList cmdList ;
246 RooLinkedList pdfSetList ;
247 RooArgSet fullPdfSet ;
248
249 for(auto * pdf : static_range_cast<RooAbsPdf*>(trailerTerm)) {
250
251 RooArgSet* pdfnset = model.findPdfNSet(*pdf) ;
252 RooArgSet* pdfSet = new RooArgSet(*pdf) ;
253 pdfSetList.Add(pdfSet) ;
254
255 if (pdfnset && !pdfnset->empty()) {
256 // This PDF requires a Conditional() construction
257 cmdList.Add(RooFit::Conditional(*pdfSet,*pdfnset).Clone()) ;
258 } else {
259 fullPdfSet.add(*pdfSet) ;
260 }
261
262 }
263// cmdList.Print("v") ;
264 RooProdPdf* multiPdf = new RooProdPdf(name.c_str(),name.c_str(),fullPdfSet,cmdList) ;
265 cmdList.Delete() ;
266 pdfSetList.Delete() ;
267
268 multiPdf->setOperMode(RooAbsArg::ADirty,true) ;
269 multiPdf->useDefaultGen(true) ;
270 _ownedMultiProds.addOwned(*multiPdf) ;
271
272 cxcoutD(Generation) << "RooProdGenContext(" << model.GetName() << "): creating context for irreducible composite trailer term "
273 << multiPdf->GetName() << " that generates observables " << trailerTermDeps << endl ;
274 RooAbsGenContext* cx = multiPdf->genContext(trailerTermDeps,prototype,auxProto,verbose) ;
275 _gcList.push_back(cx) ;
276 }
277
278 // Now check if the are observables in vars that are not generated by any of the above p.d.f.s
279 // If not, generate uniform distributions for these using a special context
280 _uniObs.add(vars) ;
281 _uniObs.remove(genDeps,true,true) ;
282 if (!_uniObs.empty()) {
283 coutI(Generation) << "RooProdGenContext(" << model.GetName() << "): generating uniform distribution for non-dependent observable(s) " << _uniObs << std::endl;
284 }
285
286
287 // We own contents of lists filled by factorizeProduct()
288 termList.Delete() ;
289 depsList.Delete() ;
290 impDepList.Delete() ;
291 crossDepList.Delete() ;
292 intList.Delete() ;
293
294}
295
296
297
298////////////////////////////////////////////////////////////////////////////////
299/// Destructor. Delete all owned subgenerator contexts
300
302{
303 for (list<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
304 delete (*iter) ;
305 }
306}
307
308
309////////////////////////////////////////////////////////////////////////////////
310/// Attach generator to given event buffer
311
313{
314 //Forward initGenerator call to all components
315 for (list<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
316 (*iter)->attach(args) ;
317 }
318}
319
320
321////////////////////////////////////////////////////////////////////////////////
322/// One-time initialization of generator context, forward to component generators
323
325{
326 // Forward initGenerator call to all components
327 for (list<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
328 (*iter)->initGenerator(theEvent) ;
329 }
330}
331
332
333
334////////////////////////////////////////////////////////////////////////////////
335/// Generate a single event of the product by generating the components
336/// of the products sequentially. The subcontext have been order such
337/// that all conditional dependencies are correctly taken into account
338/// when processed in sequential order
339
341{
342 // Loop over the component generators
343
344 for (list<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
345 (*iter)->generateEvent(theEvent,remaining) ;
346 }
347
348 // Generate uniform variables (non-dependents)
349 if (!_uniObs.empty()) {
350 for(auto * arglv : dynamic_range_cast<RooAbsLValue*>(_uniObs)) {
351 if (arglv) {
352 arglv->randomize() ;
353 }
354 }
355 theEvent.assign(_uniObs) ;
356 }
357
358}
359
360
361
362////////////////////////////////////////////////////////////////////////////////
363/// Set the traversal order of the prototype dataset by the
364/// given lookup table
365
367{
368 // Forward call to component generators
370
371 for (list<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
372 (*iter)->setProtoDataOrder(lut) ;
373 }
374
375}
376
377
378
379////////////////////////////////////////////////////////////////////////////////
380/// Detailed printing interface
381
382void RooProdGenContext::printMultiline(ostream &os, Int_t content, bool verbose, TString indent) const
383{
384 RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
385 os << indent << "--- RooProdGenContext ---" << endl ;
386 os << indent << "Using PDF ";
388 os << indent << "List of component generators" << endl ;
389
390 TString indent2(indent) ;
391 indent2.Append(" ") ;
392
393 for (list<RooAbsGenContext*>::const_iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
394 (*iter)->printMultiline(os,content,verbose,indent2) ;
395 }
396}
#define coutI(a)
#define cxcoutI(a)
#define cxcoutD(a)
#define dologD(a)
#define ccxcoutD(a)
#define ccxcoutI(a)
#define ClassImp(name)
Definition Rtypes.h:377
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:110
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
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 remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
RooAbsGenContext is the 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 setProtoDataOrder(Int_t *lut)
Set the traversal order of prototype data to that in the lookup tables passed as argument.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
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'.
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
RooLinkedListIterImpl end() const
bool empty() const
void Delete(Option_t *o=nullptr) override
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
virtual void Add(TObject *arg)
RooLinkedListIterImpl begin() const
virtual bool Remove(TObject *arg)
Remove object from collection.
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,...
RooProdGenContext is an efficient implementation of the generator context specific for RooProdPdf PDF...
void setProtoDataOrder(Int_t *lut) override
Set the traversal order of the prototype dataset by the given lookup table.
void attach(const RooArgSet &params) override
Attach generator to given event buffer.
RooArgSet _ownedMultiProds
Owned auxiliary multi-term product PDFs.
std::list< RooAbsGenContext * > _gcList
List of component generator contexts.
const RooProdPdf * _pdf
Original PDF.
void initGenerator(const RooArgSet &theEvent) override
One-time initialization of generator context, forward to component generators.
RooArgSet _uniObs
Observable to be generated with flat distribution.
~RooProdGenContext() override
Destructor. Delete all owned subgenerator contexts.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
Generate a single event of the product by generating the components of the products sequentially.
RooProdGenContext(const RooProdPdf &model, const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool _verbose=false)
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Detailed printing interface.
RooProdPdf is an efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:33
void factorizeProduct(const RooArgSet &normSet, const RooArgSet &intSet, RooLinkedList &termList, RooLinkedList &normList, RooLinkedList &impDepList, RooLinkedList &crossDepList, RooLinkedList &intList) const
Factorize product in irreducible terms for given choice of integration/normalization.
void useDefaultGen(bool flag=true)
Definition RooProdPdf.h:180
RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false) const override
Return generator context optimized for generating events from product p.d.f.s.
std::string makeRGPPName(const char *pfx, const RooArgSet &term, const RooArgSet &iset, const RooArgSet &nset, const char *isetRangeName) const
Make an appropriate automatic name for a RooGenProdProj object in getPartIntList()
RooArgSet * findPdfNSet(RooAbsPdf const &pdf) const
Look up user specified normalization set for given input PDF component.
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Basic string class.
Definition TString.h:139
TString & Append(const char *cs)
Definition TString.h:576
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)