Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
22 RooAddGenContext is an efficient implementation of the
23 generator context specific for RooAddPdf PDFs. The strategy
24 of RooAddGenContext is to defer generation of each component
25 to a dedicated generator context for that component and to
26 randomly choose one of those context to generate an event,
27 with a probability proportional to its associated coefficient.
28 **/
29 
30 
31 #include "RooFit.h"
32 
33 #include "Riostream.h"
34 
35 
36 #include "RooMsgService.h"
37 #include "RooAddGenContext.h"
38 #include "RooAddGenContext.h"
39 #include "RooAddPdf.h"
40 #include "RooDataSet.h"
41 #include "RooRandom.h"
42 #include "RooAddModel.h"
43 
44 using namespace std;
45 
46 ClassImp(RooAddGenContext);
47 ;
48 
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Constructor
52 
53 RooAddGenContext::RooAddGenContext(const RooAddPdf &model, const RooArgSet &vars,
54  const RooDataSet *prototype, const RooArgSet* auxProto,
55  Bool_t verbose) :
56  RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(kFALSE)
57 {
58  cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum p.d.f. " << model.GetName()
59  << " for generation of observable(s) " << vars ;
60  if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
61  if (auxProto && auxProto->getSize()>0) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
62  ccxcoutI(Generation) << endl ;
63 
64  // Constructor. Build an array of generator contexts for each product component PDF
65  _pdfSet = (RooArgSet*) RooArgSet(model).snapshot(kTRUE) ;
66  _pdf = (RooAddPdf*) _pdfSet->find(model.GetName()) ;
67  _pdf->setOperMode(RooAbsArg::ADirty,kTRUE) ;
68 
69  // Fix normalization set of this RooAddPdf
70  if (prototype)
71  {
72  RooArgSet coefNSet(vars) ;
73  coefNSet.add(*prototype->get()) ;
74  _pdf->fixAddCoefNormalization(coefNSet,kFALSE) ;
75  }
76 
77  _nComp = model._pdfList.getSize() ;
78  _coefThresh = new Double_t[_nComp+1] ;
79  _vars = (RooArgSet*) vars.snapshot(kFALSE) ;
80 
81  for (const auto arg : model._pdfList) {
82  auto pdf = dynamic_cast<const RooAbsPdf *>(arg);
83  if (!pdf) {
84  coutF(Generation) << "Cannot generate events from an object that is not a PDF.\n\t"
85  << "The offending object is a " << arg->IsA()->GetName() << " named '" << arg->GetName() << "'." << std::endl;
86  throw std::invalid_argument("Trying to generate events from on object that is not a PDF.");
87  }
88 
89  RooAbsGenContext* cx = pdf->genContext(vars,prototype,auxProto,verbose) ;
90  _gcList.push_back(cx) ;
91  }
92 
93  ((RooAddPdf*)_pdf)->getProjCache(_vars) ;
94  _pdf->recursiveRedirectServers(*_theEvent) ;
95 
96  _mcache = 0 ;
97  _pcache = 0 ;
98 }
99 
100 
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// Constructor
104 
105 RooAddGenContext::RooAddGenContext(const RooAddModel &model, const RooArgSet &vars,
106  const RooDataSet *prototype, const RooArgSet* auxProto,
107  Bool_t verbose) :
108  RooAbsGenContext(model,vars,prototype,auxProto,verbose), _isModel(kTRUE)
109 {
110  cxcoutI(Generation) << "RooAddGenContext::ctor() setting up event special generator context for sum resolution model " << model.GetName()
111  << " for generation of observable(s) " << vars ;
112  if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
113  if (auxProto && auxProto->getSize()>0) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
114  ccxcoutI(Generation) << endl ;
115 
116  // Constructor. Build an array of generator contexts for each product component PDF
117  _pdfSet = (RooArgSet*) RooArgSet(model).snapshot(kTRUE) ;
118  _pdf = (RooAbsPdf*) _pdfSet->find(model.GetName()) ;
119 
120 
121  model._pdfIter->Reset() ;
122  RooAbsPdf* pdf ;
123  _nComp = model._pdfList.getSize() ;
124  _coefThresh = new Double_t[_nComp+1] ;
125  _vars = (RooArgSet*) vars.snapshot(kFALSE) ;
126 
127  while((pdf=(RooAbsPdf*)model._pdfIter->Next())) {
128  RooAbsGenContext* cx = pdf->genContext(vars,prototype,auxProto,verbose) ;
129  _gcList.push_back(cx) ;
130  }
131 
132  ((RooAddModel*)_pdf)->getProjCache(_vars) ;
133  _pdf->recursiveRedirectServers(*_theEvent) ;
134 
135  _mcache = 0 ;
136  _pcache = 0 ;
137 }
138 
139 
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// Destructor. Delete all owned subgenerator contexts
143 
144 RooAddGenContext::~RooAddGenContext()
145 {
146  delete[] _coefThresh ;
147  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
148  delete *iter ;
149  }
150  delete _vars ;
151  delete _pdfSet ;
152 }
153 
154 
155 
156 ////////////////////////////////////////////////////////////////////////////////
157 /// Attach given set of variables to internal p.d.f. clone
158 
159 void RooAddGenContext::attach(const RooArgSet& args)
160 {
161  _pdf->recursiveRedirectServers(args) ;
162 
163  // Forward initGenerator call to all components
164  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
165  (*iter)->attach(args) ;
166  }
167 }
168 
169 
170 
171 ////////////////////////////////////////////////////////////////////////////////
172 /// One-time initialization of generator contex. Attach theEvent
173 /// to internal p.d.f clone and forward initialization call to
174 /// the component generators
175 
176 void RooAddGenContext::initGenerator(const RooArgSet &theEvent)
177 {
178  _pdf->recursiveRedirectServers(theEvent) ;
179 
180  if (_isModel) {
181  RooAddModel* amod = (RooAddModel*) _pdf ;
182  _mcache = amod->getProjCache(_vars) ;
183  } else {
184  RooAddPdf* apdf = (RooAddPdf*) _pdf ;
185  _pcache = apdf->getProjCache(_vars,0,"FULL_RANGE_ADDGENCONTEXT") ;
186  }
187 
188  // Forward initGenerator call to all components
189  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
190  (*iter)->initGenerator(theEvent) ;
191  }
192 }
193 
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Randomly choose one of the component contexts to generate this event,
197 /// with a probability proportional to its coefficient
198 
199 void RooAddGenContext::generateEvent(RooArgSet &theEvent, Int_t remaining)
200 {
201  // Throw a random number to determin which component to generate
202  updateThresholds() ;
203  Double_t rand = RooRandom::uniform() ;
204  Int_t i=0 ;
205  for (i=0 ; i<_nComp ; i++) {
206  if (rand>_coefThresh[i] && rand<_coefThresh[i+1]) {
207  _gcList[i]->generateEvent(theEvent,remaining) ;
208  return ;
209  }
210  }
211 }
212 
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Update the cumulative threshold table from the current coefficient
216 /// values
217 
218 void RooAddGenContext::updateThresholds()
219 {
220  if (_isModel) {
221 
222  RooAddModel* amod = (RooAddModel*) _pdf ;
223  amod->updateCoefficients(*_mcache,_vars) ;
224 
225  _coefThresh[0] = 0. ;
226  Int_t i ;
227  for (i=0 ; i<_nComp ; i++) {
228  _coefThresh[i+1] = amod->_coefCache[i] ;
229  _coefThresh[i+1] += _coefThresh[i] ;
230  }
231 
232  } else {
233 
234  RooAddPdf* apdf = (RooAddPdf*) _pdf ;
235 
236  apdf->updateCoefficients(*_pcache,_vars) ;
237 
238  _coefThresh[0] = 0. ;
239  Int_t i ;
240  for (i=0 ; i<_nComp ; i++) {
241  _coefThresh[i+1] = apdf->_coefCache[i] ;
242  _coefThresh[i+1] += _coefThresh[i] ;
243 // cout << "RooAddGenContext::updateThresholds(" << GetName() << ") _coefThresh[" << i+1 << "] = " << _coefThresh[i+1] << endl ;
244  }
245 
246  }
247 
248 }
249 
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Forward the setProtoDataOrder call to the component generator contexts
253 
254 void RooAddGenContext::setProtoDataOrder(Int_t* lut)
255 {
256  RooAbsGenContext::setProtoDataOrder(lut) ;
257  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
258  (*iter)->setProtoDataOrder(lut) ;
259  }
260 }
261 
262 
263 
264 ////////////////////////////////////////////////////////////////////////////////
265 /// Print the details of the context
266 
267 void RooAddGenContext::printMultiline(ostream &os, Int_t content, Bool_t verbose, TString indent) const
268 {
269  RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
270  os << indent << "--- RooAddGenContext ---" << endl ;
271  os << indent << "Using PDF ";
272  _pdf->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
273 
274  os << indent << "List of component generators" << endl ;
275  TString indent2(indent) ;
276  indent2.Append(" ") ;
277  for (vector<RooAbsGenContext*>::const_iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
278  (*iter)->printMultiline(os,content,verbose,indent2) ;
279  }
280 }