00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "RooFit.h"
00031 #include "RooMsgService.h"
00032 #include "Riostream.h"
00033
00034 #include "RooGenContext.h"
00035 #include "RooGenContext.h"
00036 #include "RooAbsPdf.h"
00037 #include "RooDataSet.h"
00038 #include "RooRealIntegral.h"
00039 #include "RooAcceptReject.h"
00040 #include "RooRealVar.h"
00041 #include "RooDataHist.h"
00042 #include "RooErrorHandler.h"
00043 #include "RooNumGenConfig.h"
00044 #include "RooNumGenFactory.h"
00045
00046 #include "TString.h"
00047 #include "TIterator.h"
00048 #include "TClass.h"
00049
00050
00051
00052 ClassImp(RooGenContext)
00053 ;
00054
00055
00056
00057
00058 RooGenContext::RooGenContext(const RooAbsPdf &model, const RooArgSet &vars,
00059 const RooDataSet *prototype, const RooArgSet* auxProto,
00060 Bool_t verbose, const RooArgSet* forceDirect) :
00061 RooAbsGenContext(model,vars,prototype,auxProto,verbose),
00062 _cloneSet(0), _pdfClone(0), _acceptRejectFunc(0), _generator(0),
00063 _maxVar(0), _uniIter(0), _updateFMaxPerEvent(0)
00064 {
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 cxcoutI(Generation) << "RooGenContext::ctor() setting up event generator context for p.d.f. " << model.GetName()
00075 << " for generation of observable(s) " << vars ;
00076 if (prototype) ccxcoutI(Generation) << " with prototype data for " << *prototype->get() ;
00077 if (auxProto && auxProto->getSize()>0) ccxcoutI(Generation) << " with auxiliary prototypes " << *auxProto ;
00078 if (forceDirect && forceDirect->getSize()>0) ccxcoutI(Generation) << " with internal generation forced for observables " << *forceDirect ;
00079 ccxcoutI(Generation) << endl ;
00080
00081
00082
00083
00084 RooArgSet nodes(model,model.GetName());
00085 _cloneSet= (RooArgSet*) nodes.snapshot(kTRUE);
00086 if (!_cloneSet) {
00087 coutE(Generation) << "RooGenContext::RooGenContext(" << GetName() << ") Couldn't deep-clone PDF, abort," << endl ;
00088 RooErrorHandler::softAbort() ;
00089 }
00090
00091
00092 _pdfClone = (RooAbsPdf*)_cloneSet->find(model.GetName());
00093
00094
00095 if (prototype&&_pdfClone->dependsOn(*prototype->get())) {
00096 RooArgSet fullNormSet(vars) ;
00097 fullNormSet.add(*prototype->get()) ;
00098 _pdfClone->fixAddCoefNormalization(fullNormSet) ;
00099 }
00100
00101
00102 _isValid= kTRUE;
00103 TIterator *iterator= vars.createIterator();
00104 TIterator *servers= _pdfClone->serverIterator();
00105 const RooAbsArg *tmp = 0;
00106 const RooAbsArg *arg = 0;
00107 while((_isValid && (tmp= (const RooAbsArg*)iterator->Next()))) {
00108
00109 if(!tmp->isFundamental()) {
00110 coutE(Generation) << "RooGenContext::ctor(): cannot generate values for derived \"" << tmp->GetName() << "\"" << endl;
00111 _isValid= kFALSE;
00112 continue;
00113 }
00114
00115 arg= (const RooAbsArg*)_cloneSet->find(tmp->GetName());
00116 if(0 == arg) {
00117 coutI(Generation) << "RooGenContext::ctor() WARNING model does not depend on \"" << tmp->GetName()
00118 << "\" which will have uniform distribution" << endl;
00119 _uniformVars.add(*tmp);
00120 }
00121 else {
00122
00123
00124
00125 const RooAbsArg *direct= arg ;
00126 if (forceDirect==0 || !forceDirect->find(direct->GetName())) {
00127 if (!_pdfClone->isDirectGenSafe(*arg)) {
00128 cxcoutD(Generation) << "RooGenContext::ctor() observable " << arg->GetName() << " has been determined to be unsafe for internal generation" << endl;
00129 direct=0 ;
00130 }
00131 }
00132
00133
00134
00135 if(direct) {
00136 _directVars.add(*arg);
00137 } else {
00138 _otherVars.add(*arg);
00139 }
00140 }
00141 }
00142 delete servers;
00143 delete iterator;
00144 if(!isValid()) {
00145 coutE(Generation) << "RooGenContext::ctor() constructor failed with errors" << endl;
00146 return;
00147 }
00148
00149
00150
00151 if (_directVars.getSize()>0) {
00152 cxcoutD(Generation) << "RooGenContext::ctor() observables " << _directVars << " are safe for internal generator (if supported by p.d.f)" << endl ;
00153 }
00154 if (_otherVars.getSize()>0) {
00155 cxcoutD(Generation) << "RooGenContext::ctor() observables " << _otherVars << " are NOT safe for internal generator (if supported by p.d.f)" << endl ;
00156 }
00157
00158
00159
00160 Bool_t staticInitOK = !_pdfClone->dependsOn(_protoVars) ;
00161 if (!staticInitOK) {
00162 cxcoutD(Generation) << "RooGenContext::ctor() Model depends on supplied protodata observables, static initialization of internal generator will not be allowed" << endl ;
00163 }
00164
00165
00166 RooArgSet generatedVars;
00167 if (_directVars.getSize()>0) {
00168 _code= _pdfClone->getGenerator(_directVars,generatedVars,staticInitOK);
00169
00170 cxcoutD(Generation) << "RooGenContext::ctor() Model indicates that it can internally generate observables "
00171 << generatedVars << " with configuration identifier " << _code << endl ;
00172 } else {
00173 _code = 0 ;
00174 }
00175
00176
00177 _directVars.remove(generatedVars);
00178 _otherVars.add(_directVars);
00179
00180
00181 _directVars.removeAll();
00182 _directVars.add(generatedVars);
00183
00184 cxcoutI(Generation) << "RooGenContext::ctor() Context will" ;
00185 if (_directVars.getSize()>0) ccxcoutI(Generation) << " let model internally generate observables " << _directVars ;
00186 if (_directVars.getSize()>0 && _otherVars.getSize()>0) ccxcoutI(Generation) << " and" ;
00187 if (_otherVars.getSize()>0) ccxcoutI(Generation) << " generate variables " << _otherVars << " with accept/reject sampling" ;
00188 if (_uniformVars.getSize()>0) ccxcoutI(Generation) << ", non-observable variables " << _uniformVars << " will be generated with flat distribution" ;
00189 ccxcoutI(Generation) << endl ;
00190
00191
00192 RooArgSet *depList= _pdfClone->getObservables(_theEvent);
00193 depList->remove(_otherVars);
00194
00195 TString nname(_pdfClone->GetName()) ;
00196 nname.Append("_AccRej") ;
00197 TString ntitle(_pdfClone->GetTitle()) ;
00198 ntitle.Append(" (Accept/Reject)") ;
00199
00200
00201 RooArgSet* protoDeps = model.getObservables(_protoVars) ;
00202
00203
00204 if (_protoVars.getSize()==0) {
00205
00206
00207
00208 if(depList->getSize()==0) {
00209
00210
00211
00212 Int_t maxFindCode = _pdfClone->getMaxVal(_otherVars) ;
00213 if (maxFindCode != 0) {
00214 coutI(Generation) << "RooGenContext::ctor() no prototype data provided, all observables are generated with numerically and "
00215 << "model supports analytical maximum findin:, can provide analytical pdf maximum to numeric generator" << endl ;
00216 Double_t maxVal = _pdfClone->maxVal(maxFindCode) / _pdfClone->getNorm(_theEvent) ;
00217 _maxVar = new RooRealVar("funcMax","function maximum",maxVal) ;
00218 cxcoutD(Generation) << "RooGenContext::ctor() maximum value returned by RooAbsPdf::maxVal() is " << maxVal << endl ;
00219 }
00220 }
00221
00222 if (_otherVars.getSize()>0) {
00223 _pdfClone->getVal(&vars) ;
00224 _acceptRejectFunc= new RooRealIntegral(nname,ntitle,*_pdfClone,*depList,&vars);
00225 cxcoutI(Generation) << "RooGenContext::ctor() accept/reject sampling function is " << _acceptRejectFunc->GetName() << endl ;
00226 } else {
00227 _acceptRejectFunc = 0 ;
00228 }
00229
00230 } else {
00231
00232
00233 depList->remove(_protoVars,kTRUE,kTRUE) ;
00234 _acceptRejectFunc= (RooRealIntegral*) _pdfClone->createIntegral(*depList,vars) ;
00235 cxcoutI(Generation) << "RooGenContext::ctor() accept/reject sampling function is " << _acceptRejectFunc->GetName() << endl ;
00236
00237 if (_directVars.getSize()==0) {
00238
00239
00240 Int_t maxFindCode = _pdfClone->getMaxVal(_otherVars) ;
00241 if (maxFindCode != 0) {
00242
00243
00244 coutI(Generation) << "RooGenContext::ctor() prototype data provided, all observables are generated numerically and "
00245 << "model supports analytical maximum finding: can provide analytical pdf maximum to numeric generator" << endl ;
00246 _maxVar = new RooRealVar("funcMax","function maximum",1) ;
00247 _updateFMaxPerEvent = maxFindCode ;
00248 cxcoutD(Generation) << "RooGenContext::ctor() maximum value must be reevaluated for each event with configuration code " << maxFindCode << endl ;
00249 }
00250 }
00251
00252 if (!_maxVar) {
00253
00254
00255 RooArgSet otherAndProto(_otherVars) ;
00256
00257 otherAndProto.add(*protoDeps) ;
00258
00259 if (_otherVars.getSize()>0) {
00260
00261 cxcoutD(Generation) << "RooGenContext::ctor() prototype data provided, observables are generated numericaly no "
00262 << "analytical estimate of maximum function value provided by model, must determine maximum value through initial sampling space "
00263 << "of accept/reject observables plus prototype observables: " << otherAndProto << endl ;
00264
00265
00266 RooAbsNumGenerator* maxFinder = RooNumGenFactory::instance().createSampler(*_acceptRejectFunc,otherAndProto,RooArgSet(_protoVars),
00267 *model.getGeneratorConfig(),_verbose) ;
00268
00269 Double_t max = maxFinder->getFuncMax() ;
00270 _maxVar = new RooRealVar("funcMax","function maximum",max) ;
00271
00272 if (max==0) {
00273 coutE(Generation) << "RooGenContext::ctor(" << model.GetName()
00274 << ") ERROR: generating conditional p.d.f. which requires prior knowledge of function maximum, "
00275 << "but chosen numeric generator (" << maxFinder->IsA()->GetName() << ") does not support maximum finding" << endl ;
00276 delete maxFinder ;
00277 throw string("RooGenContext::ctor()") ;
00278 }
00279 delete maxFinder ;
00280
00281 cxcoutD(Generation) << "RooGenContext::ctor() maximum function value found through initial sampling is " << max << endl ;
00282 }
00283 }
00284
00285 }
00286
00287 if (_acceptRejectFunc && _otherVars.getSize()>0) {
00288 _generator = RooNumGenFactory::instance().createSampler(*_acceptRejectFunc,_otherVars,RooArgSet(_protoVars),*model.getGeneratorConfig(),_verbose,_maxVar) ;
00289 cxcoutD(Generation) << "RooGenContext::ctor() creating MC sampling generator " << _generator->IsA()->GetName() << " from function for observables " << _otherVars << endl ;
00290
00291 } else {
00292 _generator = 0 ;
00293 }
00294
00295 delete protoDeps ;
00296 delete depList;
00297 _otherVars.add(_uniformVars);
00298 }
00299
00300
00301
00302 RooGenContext::~RooGenContext()
00303 {
00304
00305
00306
00307 delete _cloneSet;
00308
00309
00310 if (_generator) delete _generator;
00311 if (_acceptRejectFunc) delete _acceptRejectFunc;
00312 if (_maxVar) delete _maxVar ;
00313 if (_uniIter) delete _uniIter ;
00314 }
00315
00316
00317
00318
00319 void RooGenContext::attach(const RooArgSet& args)
00320 {
00321
00322
00323 _pdfClone->recursiveRedirectServers(args,kFALSE);
00324 if (_acceptRejectFunc) {
00325 _acceptRejectFunc->recursiveRedirectServers(args,kFALSE) ;
00326 }
00327
00328
00329 if (_generator) {
00330 _generator->attachParameters(args) ;
00331 }
00332
00333 }
00334
00335
00336
00337
00338 void RooGenContext::initGenerator(const RooArgSet &theEvent)
00339 {
00340
00341
00342 attach(theEvent) ;
00343
00344
00345 _pdfClone->resetErrorCounters();
00346
00347
00348 if (_directVars.getSize()>0) {
00349 cxcoutD(Generation) << "RooGenContext::initGenerator() initializing internal generator of model with code " << _code << endl ;
00350 _pdfClone->initGenerator(_code) ;
00351 }
00352
00353
00354 if (_uniformVars.getSize()>0) {
00355 _uniIter = _uniformVars.createIterator() ;
00356 }
00357 }
00358
00359
00360
00361 void RooGenContext::generateEvent(RooArgSet &theEvent, Int_t remaining)
00362 {
00363
00364
00365
00366 if(_otherVars.getSize() > 0) {
00367
00368
00369 if (_updateFMaxPerEvent!=0) {
00370 Double_t max = _pdfClone->maxVal(_updateFMaxPerEvent)/_pdfClone->getNorm(_otherVars) ;
00371 cxcoutD(Generation) << "RooGenContext::initGenerator() reevaluation of maximum function value is required for each event, new value is " << max << endl ;
00372 _maxVar->setVal(max) ;
00373 }
00374
00375 if (_generator) {
00376 Double_t resampleRatio(1) ;
00377 const RooArgSet *subEvent= _generator->generateEvent(remaining,resampleRatio);
00378 if (resampleRatio<1) {
00379 coutI(Generation) << "RooGenContext::generateEvent INFO: accept/reject generator requests resampling of previously produced events by factor "
00380 << resampleRatio << " due to increased maximum weight" << endl ;
00381 resampleData(resampleRatio) ;
00382 }
00383 if(0 == subEvent) {
00384 coutE(Generation) << "RooGenContext::generateEvent ERROR accept/reject generator failed" << endl ;
00385 return;
00386 }
00387 theEvent= *subEvent;
00388
00389 }
00390 }
00391
00392
00393
00394 if(_directVars.getSize() > 0) {
00395 _pdfClone->generateEvent(_code);
00396 }
00397
00398
00399 if (_uniIter) {
00400 _uniIter->Reset() ;
00401 RooAbsArg* uniVar ;
00402 while((uniVar=(RooAbsArg*)_uniIter->Next())) {
00403 RooAbsLValue* arglv = dynamic_cast<RooAbsLValue*>(uniVar) ;
00404 if (!arglv) {
00405 coutE(Generation) << "RooGenContext::generateEvent(" << GetName() << ") ERROR: uniform variable " << uniVar->GetName() << " is not an lvalue" << endl ;
00406 RooErrorHandler::softAbort() ;
00407 }
00408 arglv->randomize() ;
00409 }
00410 theEvent = _uniformVars ;
00411 }
00412
00413 }
00414
00415
00416
00417 void RooGenContext::printMultiline(ostream &os, Int_t content, Bool_t verbose, TString indent) const
00418 {
00419
00420
00421 RooAbsGenContext::printMultiline(os,content,verbose,indent);
00422 os << indent << " --- RooGenContext --- " << endl ;
00423 os << indent << "Using PDF ";
00424 _pdfClone->printStream(os,kName|kArgs|kClassName,kSingleLine,indent);
00425
00426 if(verbose) {
00427 os << indent << "Use PDF generator for " << _directVars << endl ;
00428 os << indent << "Use MC sampling generator " << (_generator ? _generator->IsA()->GetName() : "<none>") << " for " << _otherVars << endl ;
00429 if (_protoVars.getSize()>0) {
00430 os << indent << "Prototype observables are " << _protoVars << endl ;
00431 }
00432 }
00433 }