RooAbsGenContext.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooAbsGenContext.cxx 36210 2010-10-08 21:59:38Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 // 
00019 // BEGIN_HTML
00020 // RooAbsGenContext is the abstract base class for generator contexts of 
00021 // RooAbsPdf objects. A generator context is an object that controls
00022 // the generation of events from a given p.d.f in one or more sessions.
00023 // This class defines the common interface for all such contexts and organizes
00024 // storage of common components, such as the observables definition, the 
00025 // prototype data etc..
00026 // END_HTML
00027 //
00028 //
00029 
00030 #include "RooFit.h"
00031 
00032 #include "TClass.h"
00033 
00034 #include "RooAbsGenContext.h"
00035 #include "RooAbsGenContext.h"
00036 #include "RooAbsPdf.h"
00037 #include "RooDataSet.h"
00038 #include "RooMsgService.h"
00039 #include "RooGlobalFunc.h"
00040 
00041 #include "Riostream.h"
00042 
00043 
00044 ClassImp(RooAbsGenContext)
00045 ;
00046 
00047 
00048 //_____________________________________________________________________________
00049 RooAbsGenContext::RooAbsGenContext(const RooAbsPdf& model, const RooArgSet &vars,
00050                                    const RooDataSet *prototype, const RooArgSet* auxProto, Bool_t verbose) :
00051   TNamed(model), 
00052   _prototype(prototype), 
00053   _theEvent(0), 
00054   _isValid(kTRUE),
00055   _verbose(verbose),
00056   _protoOrder(0),
00057   _genData(0)
00058 {
00059   // Constructor
00060 
00061   // Check PDF dependents 
00062   if (model.recursiveCheckObservables(&vars)) {
00063     coutE(Generation) << "RooAbsGenContext::ctor: Error in PDF dependents" << endl ;
00064     _isValid = kFALSE ;
00065     return ;
00066   }
00067 
00068   // Make a snapshot of the generated variables that we can overwrite.
00069   _theEvent= (RooArgSet*)vars.snapshot(kFALSE);
00070 
00071   // Analyze the prototype dataset, if one is specified
00072   _nextProtoIndex= 0;
00073   if(0 != _prototype) {
00074     TIterator *protoIterator= _prototype->get()->createIterator();
00075     const RooAbsArg *proto = 0;
00076     while((proto= (const RooAbsArg*)protoIterator->Next())) {
00077       // is this variable being generated or taken from the prototype?
00078       if(!_theEvent->contains(*proto)) {
00079         _protoVars.add(*proto);
00080         _theEvent->addClone(*proto);
00081       }
00082     }
00083     delete protoIterator;
00084   }
00085 
00086   // Add auxiliary protovars to _protoVars, if provided
00087   if (auxProto) {
00088     _protoVars.add(*auxProto) ;
00089     _theEvent->addClone(*auxProto) ; 
00090   }
00091 
00092   // Remember the default number of events to generate when no prototype dataset is provided.
00093   _extendMode = model.extendMode() ;
00094   if (model.canBeExtended()) {
00095     _expectedEvents= (Int_t)(model.expectedEvents(_theEvent) + 0.5);
00096   } else {
00097     _expectedEvents= 0 ;
00098   }
00099 
00100   // Save normalization range
00101   if (model.normRange()) {
00102     _normRange = model.normRange() ;
00103   }
00104 }
00105 
00106 
00107 
00108 //_____________________________________________________________________________
00109 RooAbsGenContext::~RooAbsGenContext()
00110 {
00111   // Destructor
00112 
00113   if(0 != _theEvent) delete _theEvent;
00114   if (_protoOrder) delete[] _protoOrder ;
00115 }
00116 
00117 
00118 
00119 //_____________________________________________________________________________
00120 void RooAbsGenContext::attach(const RooArgSet& /*params*/) 
00121 {
00122   // Interface to attach given parameters to object in this context
00123 }
00124 
00125 
00126 
00127 //_____________________________________________________________________________
00128 RooDataSet *RooAbsGenContext::generate(Int_t nEvents) 
00129 {
00130   // Generate the specified number of events with nEvents>0 and
00131   // and return a dataset containing the generated events. With nEvents<=0,
00132   // generate the number of events in the prototype dataset, if available,
00133   // or else the expected number of events, if non-zero. The returned
00134   // dataset belongs to the caller. Return zero in case of an error.
00135   // Generation of individual events is delegated to a virtual generateEvent()
00136   // method. A virtual initGenerator() method is also called just before the
00137   // first call to generateEvent().
00138   
00139   if(!isValid()) {
00140     coutE(Generation) << ClassName() << "::" << GetName() << ": context is not valid" << endl;
00141     return 0;
00142   }
00143 
00144   // Calculate the expected number of events if necessary
00145   if(nEvents <= 0) {
00146     if(_prototype) {
00147       nEvents= (Int_t)_prototype->numEntries();
00148     }
00149     else {
00150       if (_extendMode == RooAbsPdf::CanNotBeExtended) {
00151         coutE(Generation) << ClassName() << "::" << GetName()
00152              << ":generate: PDF not extendable: cannot calculate expected number of events" << endl;
00153         return 0;       
00154       }
00155       nEvents= _expectedEvents;
00156     }
00157     if(nEvents <= 0) {
00158       coutE(Generation) << ClassName() << "::" << GetName()
00159                         << ":generate: cannot calculate expected number of events" << endl;
00160       return 0;
00161     }
00162     coutI(Generation) << ClassName() << "::" << GetName() << ":generate: will generate "
00163                       << nEvents << " events" << endl;
00164   }
00165 
00166   // check that any prototype dataset still defines the variables we need
00167   // (this is necessary since we never make a private clone, for efficiency)
00168   if(_prototype) {
00169     const RooArgSet *vars= _prototype->get();
00170     TIterator *iterator= _protoVars.createIterator();
00171     const RooAbsArg *arg = 0;
00172     Bool_t ok(kTRUE);
00173     while((arg= (const RooAbsArg*)iterator->Next())) {
00174       if(vars->contains(*arg)) continue;
00175       coutE(InputArguments) << ClassName() << "::" << GetName() << ":generate: prototype dataset is missing \""
00176                             << arg->GetName() << "\"" << endl;
00177 
00178       // WVE disable this for the moment
00179       // ok= kFALSE;
00180     }
00181     delete iterator;
00182     // coverity[DEADCODE]
00183     if(!ok) return 0;
00184   }
00185 
00186   if (_verbose) Print("v") ;
00187 
00188   // create a new dataset
00189   TString name(GetName()),title(GetTitle());
00190   name.Append("Data");
00191   title.Prepend("Generated From ");
00192   
00193   _genData = new RooDataSet(name.Data(), title.Data(), *_theEvent);
00194 
00195   // Perform any subclass implementation-specific initialization
00196   initGenerator(*_theEvent);
00197   
00198   // Loop over the events to generate
00199   Int_t evt(0) ;
00200   while(_genData->numEntries()<nEvents) {
00201     
00202     // first, load values from the prototype dataset, if one was provided
00203     if(0 != _prototype) {
00204       if(_nextProtoIndex >= _prototype->numEntries()) _nextProtoIndex= 0;
00205 
00206       Int_t actualProtoIdx = _protoOrder ? _protoOrder[_nextProtoIndex] : _nextProtoIndex ;
00207 
00208       const RooArgSet *subEvent= _prototype->get(actualProtoIdx);
00209       _nextProtoIndex++;
00210       if(0 != subEvent) {
00211         *_theEvent= *subEvent;
00212       }
00213       else {
00214         coutE(Generation) << ClassName() << "::" << GetName() << ":generate: cannot load event "
00215                           << actualProtoIdx << " from prototype dataset" << endl;
00216         return 0;
00217       }
00218     }
00219 
00220     // delegate the generation of the rest of this event to our subclass implementation
00221     generateEvent(*_theEvent, nEvents - _genData->numEntries());
00222 
00223 
00224     // WVE add check that event is in normRange
00225     if (_normRange.Length()>0 && !_theEvent->isInRange(_normRange.Data())) {
00226       continue ;
00227     }      
00228 
00229     _genData->addFast(*_theEvent);
00230     evt++ ;
00231   }
00232 
00233   RooDataSet* output = _genData ;
00234   _genData = 0 ;
00235 
00236   return output;
00237 }
00238 
00239 
00240 
00241 //_____________________________________________________________________________
00242 void RooAbsGenContext::initGenerator(const RooArgSet&) 
00243 {
00244   // Interface function to initialize context for generation for given
00245   // set of observables
00246 }
00247 
00248 
00249 
00250 //_____________________________________________________________________________
00251 void RooAbsGenContext::printName(ostream& os) const 
00252 {
00253   // Print name of context
00254 
00255   os << GetName() ;
00256 }
00257 
00258 
00259 
00260 //_____________________________________________________________________________
00261 void RooAbsGenContext::printTitle(ostream& os) const 
00262 {
00263   // Print title of context
00264 
00265   os << GetTitle() ;
00266 }
00267 
00268 
00269 
00270 //_____________________________________________________________________________
00271 void RooAbsGenContext::printClassName(ostream& os) const 
00272 {
00273   // Print class name of context
00274 
00275   os << IsA()->GetName() ;
00276 }
00277 
00278 
00279 
00280 //_____________________________________________________________________________
00281 void RooAbsGenContext::printArgs(ostream& os) const 
00282 {
00283   // Print arguments of context, i.e. the observables being generated in this context
00284 
00285   os << "[ " ;    
00286   TIterator* iter = _theEvent->createIterator() ;
00287   RooAbsArg* arg ;
00288   Bool_t first(kTRUE) ;
00289   while((arg=(RooAbsArg*)iter->Next())) {
00290     if (first) {
00291       first=kFALSE ;
00292     } else {
00293       os << "," ;
00294     }
00295     os << arg->GetName() ;
00296   }    
00297   os << "]" ;
00298   delete iter ;
00299 }
00300 
00301 
00302 
00303 //_____________________________________________________________________________
00304 void RooAbsGenContext::printMultiline(ostream &/*os*/, Int_t /*contents*/, Bool_t /*verbose*/, TString /*indent*/) const
00305 {
00306   // Interface for multi-line printing
00307 }
00308 
00309 
00310 
00311 
00312 //_____________________________________________________________________________
00313 void RooAbsGenContext::setProtoDataOrder(Int_t* lut)
00314 {
00315   // Set the traversal order of prototype data to that in the lookup tables
00316   // passed as argument. The LUT must be an array of integers with the same
00317   // size as the number of entries in the prototype dataset and must contain
00318   // integer values in the range [0,Nevt-1]
00319 
00320   // Delete any previous lookup table
00321   if (_protoOrder) {
00322     delete[] _protoOrder ;
00323     _protoOrder = 0 ;
00324   }
00325   
00326   // Copy new lookup table if provided and needed
00327   if (lut && _prototype) {
00328     Int_t n = _prototype->numEntries() ;
00329     _protoOrder = new Int_t[n] ;
00330     Int_t i ;
00331     for (i=0 ; i<n ; i++) {
00332       _protoOrder[i] = lut[i] ;
00333     }
00334   }
00335 }
00336 
00337 
00338 
00339 
00340 //_____________________________________________________________________________
00341 void RooAbsGenContext::resampleData(Double_t& ratio) 
00342 {
00343   // Rescale existing output buffer with given ratio
00344 
00345 
00346   Int_t nOrig = _genData->numEntries() ;
00347   Int_t nTarg = Int_t(nOrig*ratio+0.5) ;
00348   RooDataSet* trimmedData = (RooDataSet*) _genData->reduce(RooFit::EventRange(0,nTarg)) ;
00349 
00350   cxcoutD(Generation) << "RooGenContext::resampleData*( existing production trimmed from " << nOrig << " to " << trimmedData->numEntries() << " events" << endl ;
00351 
00352   delete _genData ;
00353   _genData = trimmedData ;
00354 
00355   if (_prototype) {
00356     // Push back proto index by trimmed amount to force recycling of the
00357     // proto entries that were trimmed away
00358     _nextProtoIndex -= (nOrig-nTarg) ;
00359     while (_nextProtoIndex<0) {
00360       _nextProtoIndex += _prototype->numEntries() ;
00361     }
00362   }  
00363 
00364 }
00365 
00366 
00367 
00368 
00369 //_____________________________________________________________________________
00370 Int_t RooAbsGenContext::defaultPrintContents(Option_t* /*opt*/) const 
00371 {
00372   // Define default contents when printing
00373   return kName|kClassName|kValue ;
00374 }
00375 
00376 
00377 
00378 //_____________________________________________________________________________
00379 RooPrintable::StyleOption RooAbsGenContext::defaultPrintStyle(Option_t* opt) const 
00380 {
00381   // Define default print style 
00382   if (opt && TString(opt).Contains("v")) {
00383     return kVerbose ;
00384   } 
00385   return kStandard ;
00386 }

Generated on Tue Jul 5 15:05:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1