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