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
22Efficient 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 std::endl, std::ostream;
40
41
42
43////////////////////////////////////////////////////////////////////////////////
44
46 const RooDataSet *prototype, const RooArgSet* auxProto, bool verbose) :
47 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _pdf(&model)
48{
49 // Constructor of optimization generator context for RooProdPdf objects
50
51 //Build an array of generator contexts for each product component PDF
52 cxcoutI(Generation) << "RooProdGenContext::ctor() setting up event special generator context for product p.d.f. " << model.GetName()
53 << " for generation of observable(s) " << vars ;
54 if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
55 if (auxProto && !auxProto->empty()) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
56 ccxcoutI(Generation) << std::endl ;
57
58 // Make full list of dependents (generated & proto)
59 RooArgSet deps(vars) ;
60 if (prototype) {
61 deps.remove(*std::unique_ptr<RooArgSet>{model.getObservables(*prototype->get())},true,true) ;
62 }
63
64 // Factorize product in irreducible terms
67
68 if (dologD(Generation)) {
69 cxcoutD(Generation) << "RooProdGenContext::ctor() factorizing product expression in irriducible terms " ;
70 for(auto * t : static_range_cast<RooArgSet*>(factorized.terms)) {
71 ccxcoutD(Generation) << *t ;
72 }
73 ccxcoutD(Generation) << std::endl;
74 }
75
77 // First add terms that do not import observables
78
79 bool anyAction = true ;
80 bool go=true ;
81 while(go) {
82
83 auto termIter = factorized.terms.begin();
84 auto impIter = factorized.imps.begin();
85 auto normIter = factorized.norms.begin();
86
89
90 if (factorized.terms.empty()) {
91 break ;
92 }
93
94 while(termIter != factorized.terms.end()) {
95
96 auto * term = static_cast<RooArgSet*>(*termIter);
97 auto * impDeps = static_cast<RooArgSet*>(*impIter);
98 auto * termDeps = static_cast<RooArgSet*>(*normIter);
99 if (impDeps==nullptr || termDeps==nullptr) {
100 break ;
101 }
102
103 cxcoutD(Generation) << "RooProdGenContext::ctor() analyzing product term " << *term << " with observable(s) " << *termDeps ;
104 if (!impDeps->empty()) {
105 ccxcoutD(Generation) << " which has dependence of external observable(s) " << *impDeps << " that to be generated first by other terms" ;
106 }
107 ccxcoutD(Generation) << std::endl;
108
109 // Add this term if we have no imported dependents, or imported dependents are already generated
111 neededDeps.remove(genDeps,true,true) ;
112
113 if (!neededDeps.empty()) {
114 if (!anyPrevAction) {
115 cxcoutD(Generation) << "RooProdGenContext::ctor() no convergence in single term analysis loop, terminating loop and process remainder of terms as single unit " << std::endl ;
116 go=false ;
117 break ;
118 }
119 cxcoutD(Generation) << "RooProdGenContext::ctor() skipping this term for now because it needs imported dependents that are not generated yet" << std::endl ;
120 ++termIter;
121 ++impIter;
122 ++normIter;
123 continue ;
124 }
125
126 // Check if this component has any dependents that need to be generated
127 // e.g. it can happen that there are none if all dependents of this component are prototyped
128 if (termDeps->empty()) {
129 cxcoutD(Generation) << "RooProdGenContext::ctor() term has no observables requested to be generated, removing it" << std::endl ;
130
131 // Increment the iterators first, because Removing the corresponding element
132 // would invalidate them otherwise.
133 ++termIter;
134 ++normIter;
135 ++impIter;
136 factorized.terms.Remove(term);
137 factorized.norms.Remove(termDeps);
138 factorized.imps.Remove(impDeps);
139
140 delete term ;
141 delete termDeps ;
142 delete impDeps ;
144 continue ;
145 }
146
147 if (term->size()==1) {
148 // Simple term
149
150 auto pdf = static_cast<RooAbsPdf*>((*term)[0]);
151 std::unique_ptr<RooArgSet> pdfDep{pdf->getObservables(termDeps)};
152 if (!pdfDep->empty()) {
153 coutI(Generation) << "RooProdGenContext::ctor() creating subcontext for generation of observables " << *pdfDep << " from model " << pdf->GetName() << std::endl ;
154 std::unique_ptr<RooArgSet> auxProto2{pdf->getObservables(impDeps)};
155 _gcList.emplace_back(pdf->genContext(*pdfDep,prototype,auxProto2.get(),verbose)) ;
156 }
157
158// std::cout << "adding following dependents to list of generated observables: " ; pdfDep->Print("1") ;
159 genDeps.add(*pdfDep) ;
160
161 } else {
162
163 // Composite term
164 if (!termDeps->empty()) {
165 const std::string name = model.makeRGPPName("PRODGEN_",*term,RooArgSet(),RooArgSet(),nullptr) ;
166
167 // Construct auxiliary PDF expressing product of composite terms,
168 // following Conditional component specification of input model
172 for(auto * pdf : static_range_cast<RooAbsPdf*>(*term)) {
173
174 RooArgSet* pdfnset = model.findPdfNSet(*pdf) ;
175 RooArgSet* pdfSet = new RooArgSet(*pdf) ;
176 pdfSetList.Add(pdfSet) ;
177
178 if (pdfnset && !pdfnset->empty()) {
179 // This PDF requires a Conditional() construction
181// std::cout << "Conditional " << pdf->GetName() << " " ; pdfnset->Print("1") ;
182 } else {
183 fullPdfSet.add(*pdfSet) ;
184 }
185
186 }
187 auto multiPdf = std::make_unique<RooProdPdf>(name.c_str(),name.c_str(),fullPdfSet,cmdList) ;
188 cmdList.Delete() ;
189 pdfSetList.Delete() ;
190
191 multiPdf->setOperMode(RooAbsArg::ADirty,true) ;
192 multiPdf->useDefaultGen(true) ;
193
194 coutI(Generation) << "RooProdGenContext()::ctor creating subcontext for generation of observables " << *termDeps
195 << "for irriducuble composite term using sub-product object " << multiPdf->GetName() ;
196 _gcList.emplace_back(multiPdf->genContext(*termDeps,prototype,auxProto,verbose));
198
199 genDeps.add(*termDeps) ;
200
201 }
202 }
203
204 // Increment the iterators first, because Removing the corresponding
205 // element would invalidate them otherwise.
206 ++termIter;
207 ++normIter;
208 ++impIter;
209 factorized.terms.Remove(term);
210 factorized.norms.Remove(termDeps);
211 factorized.imps.Remove(impDeps);
212 delete term ;
213 delete termDeps ;
214 delete impDeps ;
216 }
217 }
218
219 // Check if there are any left over terms that cannot be generated
220 // separately due to cross dependency of observables
221 if (!factorized.terms.empty()) {
222
223 cxcoutD(Generation) << "RooProdGenContext::ctor() there are left-over terms that need to be generated separately" << std::endl ;
224
225 // Concatenate remaining terms
226 auto normIter = factorized.norms.begin();
229 for(auto * term : static_range_cast<RooArgSet*>(factorized.terms)) {
230 auto* termDeps = static_cast<RooArgSet*>(*normIter);
231 trailerTerm.add(*term) ;
233 ++normIter;
234 }
235
236 const std::string name = model.makeRGPPName("PRODGEN_",trailerTerm,RooArgSet(),RooArgSet(),nullptr) ;
237
238 // Construct auxiliary PDF expressing product of composite terms,
239 // following Partial/Full component specification of input model
243
244 for(auto * pdf : static_range_cast<RooAbsPdf*>(trailerTerm)) {
245
246 RooArgSet* pdfnset = model.findPdfNSet(*pdf) ;
247 RooArgSet* pdfSet = new RooArgSet(*pdf) ;
248 pdfSetList.Add(pdfSet) ;
249
250 if (pdfnset && !pdfnset->empty()) {
251 // This PDF requires a Conditional() construction
253 } else {
254 fullPdfSet.add(*pdfSet) ;
255 }
256
257 }
258// cmdList.Print("v") ;
259 auto multiPdf = std::make_unique<RooProdPdf>(name.c_str(),name.c_str(),fullPdfSet,cmdList);
260 cmdList.Delete() ;
261 pdfSetList.Delete() ;
262
263 multiPdf->setOperMode(RooAbsArg::ADirty,true) ;
264 multiPdf->useDefaultGen(true) ;
265
266 cxcoutD(Generation) << "RooProdGenContext(" << model.GetName() << "): creating context for irreducible composite trailer term "
267 << multiPdf->GetName() << " that generates observables " << trailerTermDeps << std::endl ;
268 _gcList.emplace_back(multiPdf->genContext(trailerTermDeps,prototype,auxProto,verbose));
269
271 }
272
273 // Now check if the are observables in vars that are not generated by any of the above p.d.f.s
274 // If not, generate uniform distributions for these using a special context
275 _uniObs.add(vars) ;
276 _uniObs.remove(genDeps,true,true) ;
277 if (!_uniObs.empty()) {
278 coutI(Generation) << "RooProdGenContext(" << model.GetName() << "): generating uniform distribution for non-dependent observable(s) " << _uniObs << std::endl;
279 }
280}
281
282
283
284////////////////////////////////////////////////////////////////////////////////
285/// Destructor. Delete all owned subgenerator contexts
286
288
289
290////////////////////////////////////////////////////////////////////////////////
291/// Attach generator to given event buffer
292
294{
295 //Forward initGenerator call to all components
296 for (auto const& elem : _gcList) {
297 elem->attach(args) ;
298 }
299}
300
301
302////////////////////////////////////////////////////////////////////////////////
303/// One-time initialization of generator context, forward to component generators
304
306{
307 // Forward initGenerator call to all components
308 for (auto const& elem : _gcList) {
309 elem->initGenerator(theEvent) ;
310 }
311}
312
313
314
315////////////////////////////////////////////////////////////////////////////////
316/// Generate a single event of the product by generating the components
317/// of the products sequentially. The subcontext have been order such
318/// that all conditional dependencies are correctly taken into account
319/// when processed in sequential order
320
322{
323 // Loop over the component generators
324
325 for (auto const& elem : _gcList) {
326 elem->generateEvent(theEvent,remaining) ;
327 }
328
329 // Generate uniform variables (non-dependents)
330 if (!_uniObs.empty()) {
332 if (arglv) {
333 arglv->randomize() ;
334 }
335 }
336 theEvent.assign(_uniObs) ;
337 }
338}
339
340
341
342////////////////////////////////////////////////////////////////////////////////
343/// Set the traversal order of the prototype dataset by the
344/// given lookup table
345
347{
348 // Forward call to component generators
350
351 for (auto const& elem : _gcList) {
352 elem->setProtoDataOrder(lut) ;
353 }
354}
355
356
357
358////////////////////////////////////////////////////////////////////////////////
359/// Detailed printing interface
360
361void RooProdGenContext::printMultiline(ostream &os, Int_t content, bool verbose, TString indent) const
362{
364 os << indent << "--- RooProdGenContext ---" << std::endl ;
365 os << indent << "Using PDF ";
366 _pdf->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
367 os << indent << "List of component generators" << std::endl ;
368
370 indent2.Append(" ") ;
371
372 for (auto const& elem : _gcList) {
373 elem->printMultiline(os,content,verbose,indent2) ;
374 }
375}
#define coutI(a)
#define cxcoutI(a)
#define cxcoutD(a)
#define dologD(a)
#define ccxcoutD(a)
#define ccxcoutI(a)
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
const_iterator begin() const
const_iterator end() const
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.
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
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.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Container class to hold unbinned data.
Definition RooDataSet.h:34
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
std::list< std::unique_ptr< RooAbsGenContext > > _gcList
List of component generator contexts.
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.
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.
Efficient implementation of a product of PDFs of the form.
Definition RooProdPdf.h:36
void factorizeProduct(const RooArgSet &normSet, const RooArgSet &intSet, Factorized &factorized) const
Factorize product in irreducible terms for given choice of integration/normalization.
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
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)