Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
22Efficient implementation of the generator context
23specific for RooSimultaneous PDFs when generating more than one of the
24component pdfs.
25**/
26
28#include "RooSimultaneous.h"
29#include "RooRealProxy.h"
30#include "RooDataSet.h"
31#include "Roo1DTable.h"
32#include "RooCategory.h"
33#include "RooMsgService.h"
34#include "RooRandom.h"
35#include "RooGlobalFunc.h"
36
37#include <iostream>
38#include <string>
39
40
41
42////////////////////////////////////////////////////////////////////////////////
43/// Constructor of specialized generator context for RooSimultaneous p.d.f.s. This
44/// context creates a dedicated context for each component p.d.f.s and delegates
45/// generation of events to the appropriate component generator context
46
47RooSimSplitGenContext::RooSimSplitGenContext(const RooSimultaneous &model, const RooArgSet &vars, bool verbose, bool autoBinned, const char* binnedTag) :
48 RooAbsGenContext(model,vars,nullptr,nullptr,verbose), _pdf(&model)
49{
50 // Determine if we are requested to generate the index category
51 RooAbsCategoryLValue const& idxCat = model.indexCat();
52 RooArgSet pdfVars(vars) ;
53
54 RooArgSet allPdfVars(pdfVars) ;
55
56 RooArgSet catsAmongAllVars;
57 allPdfVars.selectCommon(model.flattenedCatList(), catsAmongAllVars);
58
59 if(catsAmongAllVars.size() != model.flattenedCatList().size()) {
60 oocoutE(_pdf,Generation) << "RooSimSplitGenContext::ctor(" << GetName() << ") ERROR: This context must"
61 << " generate all components of the index category" << std::endl ;
62 _isValid = false ;
63 _numPdf = 0 ;
64 // coverity[UNINIT_CTOR]
65 return ;
66 }
67
68 // We must extended likelihood to determine the relative fractions of the components
69 _idxCatName = idxCat.GetName() ;
70 if (!model.canBeExtended()) {
71 oocoutE(_pdf,Generation) << "RooSimSplitGenContext::RooSimSplitGenContext(" << GetName() << "): All components of the simultaneous PDF "
72 << "must be extended PDFs. Otherwise, it is impossible to calculate the number of events to be generated per component." << std::endl ;
73 _isValid = false ;
74 _numPdf = 0 ;
75 // coverity[UNINIT_CTOR]
76 return ;
77 }
78
79 // Initialize fraction threshold array (used only in extended mode)
80 _numPdf = model._pdfProxyList.GetSize() ;
81
82 // Generate index category and all registered PDFS
83 _allVarsPdf.add(allPdfVars) ;
84 for(auto * proxy : static_range_cast<RooRealProxy*>(model._pdfProxyList)) {
85 auto pdf = RooSimultaneous::resolveSwitchMode(static_cast<RooAbsPdf*>(proxy->absArg()), pdfVars);
86 if (!pdf) {
87 oocoutE(_pdf,Generation) << "RooSimSplitGenContext::ctor(" << GetName() << ") ERROR: the nested RooSimultaneous for the state "
88 << proxy->name() << " has no pdf for its selected state" << std::endl ;
89 _isValid = false ;
90 _numPdf = 0 ;
91 return ;
92 }
93
94 // Create generator context for this PDF
95 std::unique_ptr<RooArgSet> compVars{pdf->getObservables(pdfVars)};
96 RooAbsGenContext* cx = pdf->autoGenContext(*compVars,nullptr,nullptr,verbose,autoBinned,binnedTag) ;
97
98 const auto state = idxCat.lookupIndex(proxy->name());
99
100 cx->SetName(proxy->name()) ;
101 _gcList.push_back(cx) ;
102 _gcIndex.push_back(state);
103 }
104
105 // Clone the index category
106 if(RooArgSet(model.indexCat()).snapshot(_idxCatSet, true)) {
107 oocoutE(_pdf,Generation) << "RooSimSplitGenContext::RooSimSplitGenContext(" << GetName() << ") Couldn't deep-clone index category, abort," << std::endl ;
108 throw std::string("RooSimSplitGenContext::RooSimSplitGenContext() Couldn't deep-clone index category, abort") ;
109 }
110 _idxCat = static_cast<RooAbsCategoryLValue*>(_idxCatSet.find(model.indexCat().GetName()));
111}
112
113
114
115////////////////////////////////////////////////////////////////////////////////
116/// Destructor. Delete all owned subgenerator contexts
117
119{
120 for (RooAbsGenContext *item : _gcList) {
121 delete item;
122 }
123}
124
125
126
127////////////////////////////////////////////////////////////////////////////////
128/// Attach the index category clone to the given event buffer
129
131{
132 if (_idxCat->isDerived()) {
134 }
135
136 // Forward initGenerator call to all components
137 for (RooAbsGenContext *item : _gcList) {
138 item->attach(args) ;
139 }
140
141}
142
143
144////////////////////////////////////////////////////////////////////////////////
145/// Perform one-time initialization of generator context
146
148{
149 // Attach the index category clone to the event
150 if (_idxCat->isDerived()) {
152 } else {
153 _idxCat = static_cast<RooAbsCategoryLValue*>(theEvent.find(_idxCat->GetName())) ;
154 }
155
156 // Forward initGenerator call to all components
157 for (RooAbsGenContext *item : _gcList) {
158 item->initGenerator(theEvent) ;
159 }
160
161}
162
163
164
165////////////////////////////////////////////////////////////////////////////////
166
167RooDataSet* RooSimSplitGenContext::generate(double nEvents, bool skipInit, bool extendedMode)
168{
169 if(!isValid()) {
170 coutE(Generation) << ClassName() << "::" << GetName() << ": context is not valid" << std::endl;
171 return nullptr;
172 }
173
174
175 // Calculate the expected number of events if necessary
176 if(nEvents <= 0) {
177 nEvents= _expectedEvents;
178 }
179 coutI(Generation) << ClassName() << "::" << GetName() << ":generate: will generate "
180 << nEvents << " events" << std::endl;
181
182 if (_verbose) Print("v") ;
183
184 // Perform any subclass implementation-specific initialization
185 // Can be skipped if this is a rerun with an identical configuration
186 if (!skipInit) {
188 }
189
190 // Generate lookup table from expected event counts
191 std::vector<double> nGen(_numPdf);
192 std::vector<double> nExpected;
193 nExpected.reserve(_numPdf) ;
194 double nExpectedTotal = 0.;
195 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdf->_pdfProxyList)) {
196 RooAbsPdf* pdf=static_cast<RooAbsPdf*>(proxy->absArg()) ;
197 nExpected.push_back(pdf->expectedEvents(&_allVarsPdf));
198 nExpectedTotal += nExpected.back();
199 }
200
201 // We don't randomize events in two cases:
202 // 1. When the generation is extended, each component pdf will already
203 // randomize the expected number of events so we don't need to do it here.
204 // 2. If we want to create an expected Asimov dataset.
205 if (extendedMode || _expectedData) {
206 nGen = nExpected;
207 } else {
208 // Determine from that total number of events to be generated for each component
209 double nGenSoFar(0) ;
210 while (nGenSoFar<nEvents) {
211 double rand = RooRandom::uniform() * nExpectedTotal;
212 double cumsum = 0;
213 for (int i=0 ; i<_numPdf ; i++) {
214 if (rand >= cumsum && rand < cumsum + nExpected[i]) {
215 nGen[i]++ ;
216 nGenSoFar++ ;
217 break ;
218 }
219 cumsum += nExpected[i];
220 }
221 }
222 }
223
224
225
226 // Now loop over states
227 std::map<std::string,RooAbsData*> dataMap ;
228 Int_t icomp(0) ;
229 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdf->_pdfProxyList)) {
230
231 // Calculate number of events to generate for this state
232 if (_gcList[icomp]) {
233 dataMap[proxy->GetName()] = _gcList[icomp]->generate(nGen[icomp],skipInit,extendedMode) ;
234 }
235
236 icomp++ ;
237 }
238
239 // Put all datasets together in a composite-store RooDataSet that links and owns the component datasets
240 RooDataSet* hmaster = new RooDataSet("hmaster","hmaster",_allVarsPdf,RooFit::Index(static_cast<RooCategory&>(*_idxCat)),RooFit::Link(dataMap),RooFit::OwnLinked()) ;
241 return hmaster ;
242}
243
244
245
246////////////////////////////////////////////////////////////////////////////////
247/// Forward to components
248
250{
251 _expectedData = flag;
252 for(RooAbsGenContext *elem : _gcList) {
253 elem->setExpectedData(flag) ;
254 }
255}
256
257
258
259////////////////////////////////////////////////////////////////////////////////
260/// this method is empty because it is not used by this context
261
262RooDataSet* RooSimSplitGenContext::createDataSet(const char* , const char* , const RooArgSet& )
263{
264 return nullptr;
265}
266
267
268
269////////////////////////////////////////////////////////////////////////////////
270/// this method is empty because it is not used in this type of context
271
273{
274 assert(0) ;
275}
276
277
278
279
280////////////////////////////////////////////////////////////////////////////////
281/// this method is empty because proto datasets are not supported by this context
282
284{
285 assert(0) ;
286}
287
288
289////////////////////////////////////////////////////////////////////////////////
290/// Detailed printing interface
291
292void RooSimSplitGenContext::printMultiline(std::ostream &os, Int_t content, bool verbose, TString indent) const
293{
294 RooAbsGenContext::printMultiline(os,content,verbose,indent) ;
295 os << indent << "--- RooSimSplitGenContext ---" << std::endl ;
296 os << indent << "Using PDF ";
298}
#define coutI(a)
#define oocoutE(o, a)
#define coutE(a)
static void indent(ostringstream &buf, int indent_level)
bool recursiveRedirectServers(const RooAbsCollection &newSet, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:98
Abstract base class for objects that represent a discrete value that can be set from the outside,...
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
RooAbsArg * find(const char *name) const
Find object with given name in list.
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.
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
UInt_t _expectedEvents
Number of expected events from extended p.d.f.
bool _verbose
Verbose messaging?
bool _isValid
Is context in valid state?
bool isValid() const
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
virtual double expectedEvents(const RooArgSet *nset) const
Return expected number of events to be used in calculation of extended likelihood.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:159
RooArgSet * selectCommon(const RooAbsCollection &refColl) const
Use RooAbsCollection::selecCommon(), but return as RooArgSet.
Definition RooArgSet.h:154
Object to represent discrete states.
Definition RooCategory.h:28
Container class to hold unbinned data.
Definition RooDataSet.h:32
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:77
void setExpectedData(bool) override
Forward to components.
void generateEvent(RooArgSet &theEvent, Int_t remaining) override
this method is empty because it is not used in this type of context
std::vector< RooAbsGenContext * > _gcList
List of component generator contexts.
RooArgSet _allVarsPdf
All pdf variables.
void attach(const RooArgSet &params) override
Attach the index category clone to the given event buffer.
RooSimSplitGenContext(const RooSimultaneous &model, const RooArgSet &vars, bool _verbose=false, bool autoBinned=true, const char *binnedTag="")
Constructor of specialized generator context for RooSimultaneous p.d.f.s.
void initGenerator(const RooArgSet &theEvent) override
Perform one-time initialization of generator context.
RooDataSet * createDataSet(const char *name, const char *title, const RooArgSet &obs) override
this method is empty because it is not used by this context
Int_t _numPdf
Number of generated PDFs.
void printMultiline(std::ostream &os, Int_t content, bool verbose=false, TString indent="") const override
Detailed printing interface.
RooArgSet _idxCatSet
Owner of index category components.
const RooSimultaneous * _pdf
Original PDF.
RooDataSet * generate(double nEvents=0, bool skipInit=false, bool extendedMode=false) override
Generate the specified number of events with nEvents>0 and and return a dataset containing the genera...
std::vector< int > _gcIndex
Index value corresponding to component.
void setProtoDataOrder(Int_t *lut) override
this method is empty because proto datasets are not supported by this context
~RooSimSplitGenContext() override
Destructor. Delete all owned subgenerator contexts.
RooAbsCategoryLValue * _idxCat
Clone of index category.
TString _idxCatName
Name of index category.
Facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
TList _pdfProxyList
List of PDF proxies (named after applicable category state)
static RooAbsPdf * resolveSwitchMode(RooAbsPdf *pdf, RooArgSet const &vars)
For the generator contexts: a component that is a RooSimultaneous whose index category is not among t...
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
Basic string class.
Definition TString.h:137
RooCmdArg OwnLinked()
RooCmdArg Index(RooCategory &icat)
RooCmdArg Link(const char *state, RooAbsData &data)