Logo ROOT  
Reference Guide
RooAddGenContext.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 RooAddGenContext.cxx
19\class RooAddGenContext
20\ingroup Roofitcore
21
22RooAddGenContext is an efficient implementation of the
23generator context specific for RooAddPdf PDFs. The strategy
24of RooAddGenContext is to defer generation of each component
25to a dedicated generator context for that component and to
26randomly choose one of those context to generate an event,
27with a probability proportional to its associated coefficient.
28**/
29
30#include "RooAddGenContext.h"
31
32#include "Riostream.h"
33#include "TClass.h"
34
35#include "RooDataSet.h"
36#include "RooRandom.h"
37
38#include <sstream>
39
40
42
43
44////////////////////////////////////////////////////////////////////////////////
45/// Constructor
46
48 const RooDataSet *prototype, const RooArgSet* auxProto,
49 bool verbose) :
50 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(false)
51{
52 cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum 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 // Constructor. Build an array of generator contexts for each product component PDF
59 _pdfSet.reset(static_cast<RooArgSet*>(RooArgSet(model).snapshot(true)));
60 _pdf = (RooAddPdf*) _pdfSet->find(model.GetName()) ;
62
63 // Fix normalization set of this RooAddPdf
64 if (prototype)
65 {
66 RooArgSet coefNSet(vars) ;
67 coefNSet.add(*prototype->get()) ;
68 _pdf->fixAddCoefNormalization(coefNSet,false) ;
69 }
70
71 _nComp = model._pdfList.getSize() ;
72 _coefThresh.resize(_nComp+1);
73 _vars.reset(static_cast<RooArgSet*>(vars.snapshot(false)));
74
75 for (const auto arg : model._pdfList) {
76 auto pdf = dynamic_cast<const RooAbsPdf *>(arg);
77 if (!pdf) {
78 coutF(Generation) << "Cannot generate events from an object that is not a PDF.\n\t"
79 << "The offending object is a " << arg->ClassName() << " named '" << arg->GetName() << "'." << std::endl;
80 throw std::invalid_argument("Trying to generate events from on object that is not a PDF.");
81 }
82
83 _gcList.emplace_back(pdf->genContext(vars,prototype,auxProto,verbose));
84 }
85
86 ((RooAddPdf*)_pdf)->getProjCache(_vars.get()) ;
88}
89
90
91
92////////////////////////////////////////////////////////////////////////////////
93/// Constructor
94
96 const RooDataSet *prototype, const RooArgSet* auxProto,
97 bool verbose) :
98 RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(true)
99{
100 cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum resolution model " << model.GetName()
101 << " for generation of observable(s) " << vars ;
102 if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
103 if (auxProto && !auxProto->empty()) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
104 ccxcoutI(Generation) << std::endl;
105
106 // Constructor. Build an array of generator contexts for each product component PDF
107 _pdfSet.reset(static_cast<RooArgSet*>(RooArgSet(model).snapshot(true)));
108 _pdf = (RooAbsPdf*) _pdfSet->find(model.GetName()) ;
109
110 _nComp = model._pdfList.getSize() ;
111 _coefThresh.resize(_nComp+1);
112 _vars.reset(static_cast<RooArgSet*>(vars.snapshot(false)));
113
114 for (const auto obj : model._pdfList) {
115 auto pdf = static_cast<RooAbsPdf*>(obj);
116 _gcList.emplace_back(pdf->genContext(vars,prototype,auxProto,verbose));
117 }
118
119 ((RooAddModel*)_pdf)->getProjCache(_vars.get()) ;
121}
122
123
124////////////////////////////////////////////////////////////////////////////////
125/// Attach given set of variables to internal p.d.f. clone
126
128{
130
131 // Forward initGenerator call to all components
132 for(auto& gc : _gcList) {
133 gc->attach(args) ;
134 }
135}
136
137
138
139////////////////////////////////////////////////////////////////////////////////
140/// One-time initialization of generator contex. Attach theEvent
141/// to internal p.d.f clone and forward initialization call to
142/// the component generators
143
145{
146 _pdf->recursiveRedirectServers(theEvent) ;
147
148 if (_isModel) {
149 RooAddModel* amod = (RooAddModel*) _pdf ;
150 _pcache = amod->getProjCache(_vars.get()) ;
151 } else {
152 RooAddPdf* apdf = (RooAddPdf*) _pdf ;
153 _pcache = apdf->getProjCache(_vars.get(),nullptr,"FULL_RANGE_ADDGENCONTEXT") ;
154 }
155
156 // Forward initGenerator call to all components
157 for(auto& gc : _gcList) {
158 gc->initGenerator(theEvent) ;
159 }
160}
161
162
163////////////////////////////////////////////////////////////////////////////////
164/// Randomly choose one of the component contexts to generate this event,
165/// with a probability proportional to its coefficient
166
168{
169 // Throw a random number to determin which component to generate
171 double rand = RooRandom::uniform() ;
172 for (Int_t i=0 ; i<_nComp ; i++) {
173 if (rand>_coefThresh[i] && rand<_coefThresh[i+1]) {
174 _gcList[i]->generateEvent(theEvent,remaining) ;
175 return ;
176 }
177 }
178}
179
180
181////////////////////////////////////////////////////////////////////////////////
182/// Update the cumulative threshold table from the current coefficient
183/// values
184
186{
187 // Templated lambda to support RooAddModel and RooAddPdf
188 auto updateThresholdsImpl = [&](auto* pdf, auto * cache) {
189 pdf->updateCoefficients(*cache,_vars.get()) ;
190
191 _coefThresh[0] = 0. ;
192 for (Int_t i=0 ; i<_nComp ; i++) {
193 double coef = pdf->_coefCache[i];
194 if(coef < 0.0) {
195 std::stringstream errMsgStream;
196 errMsgStream << "RooAddGenContext::updateThresholds(): coefficient number " << i << " of the "
197 << pdf->ClassName() << " \"" << pdf->GetName() << "\"" << " is negative!"
198 << " The current RooAddGenConext doesn't support negative coefficients."
199 << " Please recreate a new generator context with " << pdf->ClassName() << "::genContext()";
200 auto const errMsg = errMsgStream.str();
201 cxcoutE(Generation) << errMsg << std::endl;
202 throw std::runtime_error(errMsg);
203 }
204 _coefThresh[i+1] = coef + _coefThresh[i];
205 }
206 };
207
208 _isModel ? updateThresholdsImpl(static_cast<RooAddModel*>(_pdf), _pcache)
209 : updateThresholdsImpl(static_cast<RooAddPdf*>(_pdf), _pcache);
210}
211
212
213////////////////////////////////////////////////////////////////////////////////
214/// Forward the setProtoDataOrder call to the component generator contexts
215
217{
219 for(auto& gc : _gcList) {
220 gc->setProtoDataOrder(lut) ;
221 }
222}
223
224
225
226////////////////////////////////////////////////////////////////////////////////
227/// Print the details of the context
228
229void RooAddGenContext::printMultiline(std::ostream &os, Int_t content, bool verbose, TString indent) const
230{
232 os << indent << "--- RooAddGenContext ---" << std::endl;
233 os << indent << "Using PDF ";
235
236 os << indent << "List of component generators" << std::endl;
237 TString indent2(indent) ;
238 indent2.Append(" ") ;
239 for(auto& gc : _gcList) {
240 gc->printMultiline(os,content,verbose,indent2) ;
241 }
242}
#define cxcoutI(a)
Definition: RooMsgService.h:89
#define coutF(a)
Definition: RooMsgService.h:38
#define cxcoutE(a)
#define ccxcoutI(a)
Definition: RooMsgService.h:90
#define ClassImp(name)
Definition: Rtypes.h:375
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void gc
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
Definition: RooAbsArg.cxx:1165
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
Definition: RooAbsArg.cxx:1866
bool empty() const
Int_t getSize() const
Return the number of elements in the collection.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
RooAbsGenContext is the abstract base class for generator contexts of RooAbsPdf objects.
RooArgSet _theEvent
Pointer to observable event being generated.
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.
virtual void fixAddCoefNormalization(const RooArgSet &addNormSet=RooArgSet(), bool force=true)
Fix the interpretation of the coefficient of any RooAddPdf component in the expression tree headed by...
RooAddGenContext is an efficient implementation of the generator context specific for RooAddPdf PDFs.
void setProtoDataOrder(Int_t *lut) override
Forward the setProtoDataOrder call to the component generator contexts.
std::vector< double > _coefThresh
[_nComp] Array of coefficient thresholds
std::unique_ptr< RooArgSet > _pdfSet
Set owned all nodes of internal clone of p.d.f.
std::unique_ptr< RooArgSet > _vars
bool _isModel
Are we generating from a RooAddPdf or a RooAddModel.
void initGenerator(const RooArgSet &theEvent) override
One-time initialization of generator contex.
std::vector< std::unique_ptr< RooAbsGenContext > > _gcList
List of component generator contexts.
void updateThresholds()
Update the cumulative threshold table from the current coefficient values.
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Print the details of the context.
AddCacheElem * _pcache
! RooAddPdf cache element
void attach(const RooArgSet &params) override
Attach given set of variables to internal p.d.f. clone.
Int_t _nComp
Number of PDF components.
RooAddGenContext(const RooAddPdf &model, const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool _verbose=false)
Constructor.
RooAbsPdf * _pdf
Pointer to cloned p.d.f.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
Randomly choose one of the component contexts to generate this event, with a probability proportional...
RooAddModel is an efficient implementation of a sum of PDFs of the form.
Definition: RooAddModel.h:28
RooListProxy _pdfList
List of component PDFs.
Definition: RooAddModel.h:118
AddCacheElem * getProjCache(const RooArgSet *nset, const RooArgSet *iset=nullptr, const char *rangeName=nullptr) const
Retrieve cache element with for calculation of p.d.f value with normalization set nset and integrated...
RooAddPdf is an efficient implementation of a sum of PDFs of the form.
Definition: RooAddPdf.h:34
RooListProxy _pdfList
List of component PDFs.
Definition: RooAddPdf.h:128
AddCacheElem * getProjCache(const RooArgSet *nset, const RooArgSet *iset=nullptr, const char *rangeName=nullptr) const
Manager of cache with coefficient projections and transformations.
Definition: RooAddPdf.cxx:359
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition: RooArgSet.h:56
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition: RooArgSet.h:179
RooDataSet is a container class to hold unbinned data.
Definition: RooDataSet.h:55
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
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
Basic string class.
Definition: TString.h:136
TString & Append(const char *cs)
Definition: TString.h:564
@ Generation
Definition: RooGlobalFunc.h:61