// RooAbsGenContext is the abstract base class for generator contexts of
// RooAbsPdf objects. A generator context is an object that controls
// the generation of events from a given p.d.f in one or more sessions.
// This class defines the common interface for all such contexts and organizes
// storage of common components, such as the observables definition, the
// prototype data etc..
// END_HTML
#include "RooFit.h"
#include "TClass.h"
#include "RooAbsGenContext.h"
#include "RooAbsGenContext.h"
#include "RooAbsPdf.h"
#include "RooDataSet.h"
#include "RooMsgService.h"
#include "RooGlobalFunc.h"
#include "Riostream.h"
ClassImp(RooAbsGenContext)
;
RooAbsGenContext::RooAbsGenContext(const RooAbsPdf& model, const RooArgSet &vars,
const RooDataSet *prototype, const RooArgSet* auxProto, Bool_t verbose) :
TNamed(model),
_prototype(prototype),
_theEvent(0),
_isValid(kTRUE),
_verbose(verbose),
_protoOrder(0),
_genData(0)
{
if (model.recursiveCheckObservables(&vars)) {
coutE(Generation) << "RooAbsGenContext::ctor: Error in PDF dependents" << endl ;
_isValid = kFALSE ;
return ;
}
_theEvent= (RooArgSet*)vars.snapshot(kFALSE);
_nextProtoIndex= 0;
if(0 != _prototype) {
TIterator *protoIterator= _prototype->get()->createIterator();
const RooAbsArg *proto = 0;
while((proto= (const RooAbsArg*)protoIterator->Next())) {
if(!_theEvent->contains(*proto)) {
_protoVars.add(*proto);
_theEvent->addClone(*proto);
}
}
delete protoIterator;
}
if (auxProto) {
_protoVars.add(*auxProto) ;
_theEvent->addClone(*auxProto) ;
}
_extendMode = model.extendMode() ;
if (model.canBeExtended()) {
_expectedEvents= (Int_t)(model.expectedEvents(_theEvent) + 0.5);
} else {
_expectedEvents= 0 ;
}
if (model.normRange()) {
_normRange = model.normRange() ;
}
}
RooAbsGenContext::~RooAbsGenContext()
{
if(0 != _theEvent) delete _theEvent;
if (_protoOrder) delete[] _protoOrder ;
}
void RooAbsGenContext::attach(const RooArgSet& )
{
}
RooDataSet* RooAbsGenContext::createDataSet(const char* name, const char* title, const RooArgSet& obs)
{
return new RooDataSet(name, title, obs);
}
RooDataSet *RooAbsGenContext::generate(Int_t nEvents)
{
if(!isValid()) {
coutE(Generation) << ClassName() << "::" << GetName() << ": context is not valid" << endl;
return 0;
}
if(nEvents <= 0) {
if(_prototype) {
nEvents= (Int_t)_prototype->numEntries();
}
else {
if (_extendMode == RooAbsPdf::CanNotBeExtended) {
coutE(Generation) << ClassName() << "::" << GetName()
<< ":generate: PDF not extendable: cannot calculate expected number of events" << endl;
return 0;
}
nEvents= _expectedEvents;
}
if(nEvents <= 0) {
coutE(Generation) << ClassName() << "::" << GetName()
<< ":generate: cannot calculate expected number of events" << endl;
return 0;
}
coutI(Generation) << ClassName() << "::" << GetName() << ":generate: will generate "
<< nEvents << " events" << endl;
}
if(_prototype) {
const RooArgSet *vars= _prototype->get();
TIterator *iterator= _protoVars.createIterator();
const RooAbsArg *arg = 0;
Bool_t ok(kTRUE);
while((arg= (const RooAbsArg*)iterator->Next())) {
if(vars->contains(*arg)) continue;
coutE(InputArguments) << ClassName() << "::" << GetName() << ":generate: prototype dataset is missing \""
<< arg->GetName() << "\"" << endl;
}
delete iterator;
if(!ok) return 0;
}
if (_verbose) Print("v") ;
TString name(GetName()),title(GetTitle());
name.Append("Data");
title.Prepend("Generated From ");
_genData = createDataSet(name.Data(),title.Data(),*_theEvent) ;
initGenerator(*_theEvent);
Int_t evt(0) ;
while(_genData->numEntries()<nEvents) {
if(0 != _prototype) {
if(_nextProtoIndex >= _prototype->numEntries()) _nextProtoIndex= 0;
Int_t actualProtoIdx = _protoOrder ? _protoOrder[_nextProtoIndex] : _nextProtoIndex ;
const RooArgSet *subEvent= _prototype->get(actualProtoIdx);
_nextProtoIndex++;
if(0 != subEvent) {
*_theEvent= *subEvent;
}
else {
coutE(Generation) << ClassName() << "::" << GetName() << ":generate: cannot load event "
<< actualProtoIdx << " from prototype dataset" << endl;
return 0;
}
}
generateEvent(*_theEvent, nEvents - _genData->numEntries());
if (_normRange.Length()>0 && !_theEvent->isInRange(_normRange.Data())) {
continue ;
}
_genData->addFast(*_theEvent);
evt++ ;
}
RooDataSet* output = _genData ;
_genData = 0 ;
return output;
}
void RooAbsGenContext::initGenerator(const RooArgSet&)
{
}
void RooAbsGenContext::printName(ostream& os) const
{
os << GetName() ;
}
void RooAbsGenContext::printTitle(ostream& os) const
{
os << GetTitle() ;
}
void RooAbsGenContext::printClassName(ostream& os) const
{
os << IsA()->GetName() ;
}
void RooAbsGenContext::printArgs(ostream& os) const
{
os << "[ " ;
TIterator* iter = _theEvent->createIterator() ;
RooAbsArg* arg ;
Bool_t first(kTRUE) ;
while((arg=(RooAbsArg*)iter->Next())) {
if (first) {
first=kFALSE ;
} else {
os << "," ;
}
os << arg->GetName() ;
}
os << "]" ;
delete iter ;
}
void RooAbsGenContext::printMultiline(ostream &, Int_t , Bool_t , TString ) const
{
}
void RooAbsGenContext::setProtoDataOrder(Int_t* lut)
{
if (_protoOrder) {
delete[] _protoOrder ;
_protoOrder = 0 ;
}
if (lut && _prototype) {
Int_t n = _prototype->numEntries() ;
_protoOrder = new Int_t[n] ;
Int_t i ;
for (i=0 ; i<n ; i++) {
_protoOrder[i] = lut[i] ;
}
}
}
void RooAbsGenContext::resampleData(Double_t& ratio)
{
Int_t nOrig = _genData->numEntries() ;
Int_t nTarg = Int_t(nOrig*ratio+0.5) ;
RooDataSet* trimmedData = (RooDataSet*) _genData->reduce(RooFit::EventRange(0,nTarg)) ;
cxcoutD(Generation) << "RooGenContext::resampleData*( existing production trimmed from " << nOrig << " to " << trimmedData->numEntries() << " events" << endl ;
delete _genData ;
_genData = trimmedData ;
if (_prototype) {
_nextProtoIndex -= (nOrig-nTarg) ;
while (_nextProtoIndex<0) {
_nextProtoIndex += _prototype->numEntries() ;
}
}
}
Int_t RooAbsGenContext::defaultPrintContents(Option_t* ) const
{
return kName|kClassName|kValue ;
}
RooPrintable::StyleOption RooAbsGenContext::defaultPrintStyle(Option_t* opt) const
{
if (opt && TString(opt).Contains("v")) {
return kVerbose ;
}
return kStandard ;
}