Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooSimSplitGenContext.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 RooSimSplitGenContext.cxx
19 \class RooSimSplitGenContext
20 \ingroup Roofitcore
21 
22 RooSimSplitGenContext is an efficient implementation of the generator context
23 specific for RooSimultaneous PDFs when generating more than one of the
24 component pdfs.
25 **/
26 
27 #include "RooFit.h"
28 #include "Riostream.h"
29 
30 #include "RooSimSplitGenContext.h"
31 #include "RooSimultaneous.h"
32 #include "RooRealProxy.h"
33 #include "RooDataSet.h"
34 #include "Roo1DTable.h"
35 #include "RooCategory.h"
36 #include "RooMsgService.h"
37 #include "RooRandom.h"
38 #include "RooGlobalFunc.h"
39 
40 using namespace RooFit ;
41 
42 #include <string>
43 
44 using namespace std;
45 
46 ClassImp(RooSimSplitGenContext);
47 ;
48 
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Constructor of specialized generator context for RooSimultaneous p.d.f.s. This
52 /// context creates a dedicated context for each component p.d.f.s and delegates
53 /// generation of events to the appropriate component generator context
54 
55 RooSimSplitGenContext::RooSimSplitGenContext(const RooSimultaneous &model, const RooArgSet &vars, Bool_t verbose, Bool_t autoBinned, const char* binnedTag) :
56  RooAbsGenContext(model,vars,0,0,verbose), _pdf(&model)
57 {
58  // Determine if we are requested to generate the index category
59  RooAbsCategory *idxCat = (RooAbsCategory*) model._indexCat.absArg() ;
60  RooArgSet pdfVars(vars) ;
61 
62  RooArgSet allPdfVars(pdfVars) ;
63 
64  if (!idxCat->isDerived()) {
65  pdfVars.remove(*idxCat,kTRUE,kTRUE) ;
66  Bool_t doGenIdx = allPdfVars.find(idxCat->GetName())?kTRUE:kFALSE ;
67 
68  if (!doGenIdx) {
69  oocoutE(_pdf,Generation) << "RooSimSplitGenContext::ctor(" << GetName() << ") ERROR: This context must"
70  << " generate the index category" << endl ;
71  _isValid = kFALSE ;
72  _numPdf = 0 ;
73  // coverity[UNINIT_CTOR]
74  return ;
75  }
76  } else {
77  TIterator* sIter = idxCat->serverIterator() ;
78  RooAbsArg* server ;
79  Bool_t anyServer(kFALSE), allServers(kTRUE) ;
80  while((server=(RooAbsArg*)sIter->Next())) {
81  if (vars.find(server->GetName())) {
82  anyServer=kTRUE ;
83  pdfVars.remove(*server,kTRUE,kTRUE) ;
84  } else {
85  allServers=kFALSE ;
86  }
87  }
88  delete sIter ;
89 
90  if (anyServer && !allServers) {
91  oocoutE(_pdf,Generation) << "RooSimSplitGenContext::ctor(" << GetName() << ") ERROR: This context must"
92  << " generate all components of a derived index category" << endl ;
93  _isValid = kFALSE ;
94  _numPdf = 0 ;
95  // coverity[UNINIT_CTOR]
96  return ;
97  }
98  }
99 
100  // We must extended likelihood to determine the relative fractions of the components
101  _idxCatName = idxCat->GetName() ;
102  if (!model.canBeExtended()) {
103  oocoutE(_pdf,Generation) << "RooSimSplitGenContext::RooSimSplitGenContext(" << GetName() << "): All components of the simultaneous PDF "
104  << "must be extended PDFs. Otherwise, it is impossible to calculate the number of events to be generated per component." << endl ;
105  _isValid = kFALSE ;
106  _numPdf = 0 ;
107  // coverity[UNINIT_CTOR]
108  return ;
109  }
110 
111  // Initialize fraction threshold array (used only in extended mode)
112  _numPdf = model._pdfProxyList.GetSize() ;
113  _fracThresh = new Double_t[_numPdf+1] ;
114  _fracThresh[0] = 0 ;
115 
116  // Generate index category and all registered PDFS
117  _proxyIter = model._pdfProxyList.MakeIterator() ;
118  _allVarsPdf.add(allPdfVars) ;
119  RooRealProxy* proxy ;
120  RooAbsPdf* pdf ;
121  Int_t i(1) ;
122  while((proxy=(RooRealProxy*)_proxyIter->Next())) {
123  pdf=(RooAbsPdf*)proxy->absArg() ;
124 
125  // Create generator context for this PDF
126  RooArgSet* compVars = pdf->getObservables(pdfVars) ;
127  RooAbsGenContext* cx = pdf->autoGenContext(*compVars,0,0,verbose,autoBinned,binnedTag) ;
128  delete compVars ;
129 
130  const RooCatType* state = idxCat->lookupType(proxy->name()) ;
131 
132  cx->SetName(proxy->name()) ;
133  _gcList.push_back(cx) ;
134  _gcIndex.push_back(state->getVal()) ;
135 
136  // Fill fraction threshold array
137  _fracThresh[i] = _fracThresh[i-1] + pdf->expectedEvents(&allPdfVars) ;
138  i++ ;
139  }
140 
141  for(i=0 ; i<_numPdf ; i++) {
142  _fracThresh[i] /= _fracThresh[_numPdf] ;
143  }
144 
145  // Clone the index category
146  _idxCatSet = (RooArgSet*) RooArgSet(model._indexCat.arg()).snapshot(kTRUE) ;
147  if (!_idxCatSet) {
148  oocoutE(_pdf,Generation) << "RooSimSplitGenContext::RooSimSplitGenContext(" << GetName() << ") Couldn't deep-clone index category, abort," << endl ;
149  throw std::string("RooSimSplitGenContext::RooSimSplitGenContext() Couldn't deep-clone index category, abort") ;
150  }
151 
152  _idxCat = (RooAbsCategoryLValue*) _idxCatSet->find(model._indexCat.arg().GetName()) ;
153 }
154 
155 
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Destructor. Delete all owned subgenerator contexts
159 
160 RooSimSplitGenContext::~RooSimSplitGenContext()
161 {
162  delete[] _fracThresh ;
163  delete _idxCatSet ;
164  for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
165  delete (*iter) ;
166  }
167  delete _proxyIter ;
168 }
169 
170 
171 
172 ////////////////////////////////////////////////////////////////////////////////
173 /// Attach the index category clone to the given event buffer
174 
175 void RooSimSplitGenContext::attach(const RooArgSet& args)
176 {
177  if (_idxCat->isDerived()) {
178  _idxCat->recursiveRedirectServers(args,kTRUE) ;
179  }
180 
181  // Forward initGenerator call to all components
182  for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
183  (*iter)->attach(args) ;
184  }
185 
186 }
187 
188 
189 ////////////////////////////////////////////////////////////////////////////////
190 /// Perform one-time initialization of generator context
191 
192 void RooSimSplitGenContext::initGenerator(const RooArgSet &theEvent)
193 {
194  // Attach the index category clone to the event
195  if (_idxCat->isDerived()) {
196  _idxCat->recursiveRedirectServers(theEvent,kTRUE) ;
197  } else {
198  _idxCat = (RooAbsCategoryLValue*) theEvent.find(_idxCat->GetName()) ;
199  }
200 
201  // Forward initGenerator call to all components
202  for (vector<RooAbsGenContext*>::iterator iter = _gcList.begin() ; iter!=_gcList.end() ; ++iter) {
203  (*iter)->initGenerator(theEvent) ;
204  }
205 
206 }
207 
208 
209 
210 ////////////////////////////////////////////////////////////////////////////////
211 
212 RooDataSet* RooSimSplitGenContext::generate(Double_t nEvents, Bool_t skipInit, Bool_t extendedMode)
213 {
214  if(!isValid()) {
215  coutE(Generation) << ClassName() << "::" << GetName() << ": context is not valid" << endl;
216  return 0;
217  }
218 
219 
220  // Calculate the expected number of events if necessary
221  if(nEvents <= 0) {
222  nEvents= _expectedEvents;
223  }
224  coutI(Generation) << ClassName() << "::" << GetName() << ":generate: will generate "
225  << nEvents << " events" << endl;
226 
227  if (_verbose) Print("v") ;
228 
229  // Perform any subclass implementation-specific initialization
230  // Can be skipped if this is a rerun with an identical configuration
231  if (!skipInit) {
232  initGenerator(*_theEvent);
233  }
234 
235  // Generate lookup table from expected event counts
236  vector<Double_t> nGen(_numPdf) ;
237  if (extendedMode ) {
238  _proxyIter->Reset() ;
239  RooRealProxy* proxy ;
240  Int_t i(0) ;
241  while((proxy=(RooRealProxy*)_proxyIter->Next())) {
242  RooAbsPdf* pdf=(RooAbsPdf*)proxy->absArg() ;
243  //nGen[i] = Int_t(pdf->expectedEvents(&_allVarsPdf)+0.5) ;
244  nGen[i] = pdf->expectedEvents(&_allVarsPdf) ;
245  i++ ;
246  }
247 
248  } else {
249  _proxyIter->Reset() ;
250  RooRealProxy* proxy ;
251  Int_t i(1) ;
252  _fracThresh[0] = 0 ;
253  while((proxy=(RooRealProxy*)_proxyIter->Next())) {
254  RooAbsPdf* pdf=(RooAbsPdf*)proxy->absArg() ;
255  _fracThresh[i] = _fracThresh[i-1] + pdf->expectedEvents(&_allVarsPdf) ;
256  i++ ;
257  }
258  for(i=0 ; i<_numPdf ; i++) {
259  _fracThresh[i] /= _fracThresh[_numPdf] ;
260  }
261 
262  // Determine from that total number of events to be generated for each component
263  Double_t nGenSoFar(0) ;
264  while (nGenSoFar<nEvents) {
265  Double_t rand = RooRandom::uniform() ;
266  i=0 ;
267  for (i=0 ; i<_numPdf ; i++) {
268  if (rand>_fracThresh[i] && rand<_fracThresh[i+1]) {
269  nGen[i]++ ;
270  nGenSoFar++ ;
271  break ;
272  }
273  }
274  }
275  }
276 
277 
278 
279  // Now loop over states
280  _proxyIter->Reset() ;
281  map<string,RooAbsData*> dataMap ;
282  Int_t icomp(0) ;
283  RooRealProxy* proxy ;
284  while((proxy=(RooRealProxy*)_proxyIter->Next())) {
285 
286  // Calculate number of events to generate for this state
287  if (_gcList[icomp]) {
288  dataMap[proxy->GetName()] = _gcList[icomp]->generate(nGen[icomp],skipInit,extendedMode) ;
289  }
290 
291  icomp++ ;
292  }
293 
294  // Put all datasets together in a composite-store RooDataSet that links and owns the component datasets
295  RooDataSet* hmaster = new RooDataSet("hmaster","hmaster",_allVarsPdf,RooFit::Index((RooCategory&)*_idxCat),RooFit::Link(dataMap),RooFit::OwnLinked()) ;
296  return hmaster ;
297 }
298 
299 
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Forward to components
303 
304 void RooSimSplitGenContext::setExpectedData(Bool_t flag)
305 {
306  for (vector<RooAbsGenContext*>::iterator iter=_gcList.begin() ; iter!=_gcList.end() ; ++iter) {
307  (*iter)->setExpectedData(flag) ;
308  }
309 }
310 
311 
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// this method is empty because it is not used by this context
315 
316 RooDataSet* RooSimSplitGenContext::createDataSet(const char* , const char* , const RooArgSet& )
317 {
318  return 0 ;
319 }
320 
321 
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// this method is empty because it is not used in this type of context
325 
326 void RooSimSplitGenContext::generateEvent(RooArgSet &, Int_t )
327 {
328  assert(0) ;
329 }
330 
331 
332 
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 /// this method is empty because proto datasets are not supported by this context
336 
337 void RooSimSplitGenContext::setProtoDataOrder(Int_t* )
338 {
339  assert(0) ;
340 }
341 
342 
343 ////////////////////////////////////////////////////////////////////////////////
344 /// Detailed printing interface
345 
346 void RooSimSplitGenContext::printMultiline(ostream &os, Int_t content, Bool_t verbose, TString indent) const
347 {
348  RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
349  os << indent << "--- RooSimSplitGenContext ---" << endl ;
350  os << indent << "Using PDF ";
351  _pdf->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
352 }