RooFormula.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooFormula.cxx 36230 2010-10-09 20:21:02Z 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 // RooFormula an implementation of TFormula that interfaces it to RooAbsArg
00021 // value objects. It allows to use the value of a given list of RooAbsArg objects in the formula
00022 // expression. Reference is done either by the RooAbsArgs name
00023 // or by list ordinal postion ('@0,@1,...'). State information
00024 // of RooAbsCategories can be accessed used the '::' operator,
00025 // e.g. 'tagCat::Kaon' will resolve to the numerical value of
00026 // the 'Kaon' state of the RooAbsCategory object named tagCat.
00027 // END_HTML
00028 //
00029 
00030 #include "RooFit.h"
00031 
00032 #include "Riostream.h"
00033 #include "Riostream.h"
00034 #include <stdlib.h>
00035 #include "TROOT.h"
00036 #include "TClass.h"
00037 #include "TObjString.h"
00038 #include "RooFormula.h"
00039 #include "RooAbsReal.h"
00040 #include "RooAbsCategory.h"
00041 #include "RooArgList.h"
00042 #include "RooMsgService.h"
00043 
00044 ClassImp(RooFormula)
00045 
00046 
00047 //_____________________________________________________________________________
00048 RooFormula::RooFormula() : TFormula(), _nset(0)
00049 {
00050   // Default constructor
00051   // coverity[UNINIT_CTOR]
00052 }
00053 
00054 
00055 //_____________________________________________________________________________
00056 RooFormula::RooFormula(const char* name, const char* formula, const RooArgList& list) : 
00057   TFormula(), _isOK(kTRUE), _compiled(kFALSE)
00058 {
00059   // Constructor with expression string and list of RooAbsArg variables
00060 
00061   SetName(name) ;
00062   SetTitle(formula) ;
00063 
00064   TIterator* iter = list.createIterator() ;
00065   RooAbsArg* arg ;
00066   while ((arg=(RooAbsArg*)iter->Next())) {
00067     _origList.Add(arg) ;
00068   }
00069   delete iter ;
00070 
00071   _compiled = kTRUE ;
00072   if (Compile()) {
00073     coutE(InputArguments) << "RooFormula::RooFormula(" << GetName() << "): compile error" << endl ;
00074     _isOK = kFALSE ;
00075     return ;
00076   }
00077 }
00078 
00079 
00080 
00081 //_____________________________________________________________________________
00082 RooFormula::RooFormula(const RooFormula& other, const char* name) : 
00083   TFormula(), RooPrintable(other), _isOK(other._isOK), _compiled(kFALSE) 
00084 {
00085   // Copy constructor
00086 
00087   SetName(name?name:other.GetName()) ;
00088   SetTitle(other.GetTitle()) ;
00089 
00090   TIterator* iter = other._origList.MakeIterator() ;
00091   RooAbsArg* arg ;
00092   while ((arg=(RooAbsArg*)iter->Next())) {
00093     _origList.Add(arg) ;
00094   }
00095   delete iter ;
00096   
00097   Compile() ;
00098   _compiled=kTRUE ;
00099 }
00100 
00101 
00102 
00103 //_____________________________________________________________________________
00104 Bool_t RooFormula::reCompile(const char* newFormula) 
00105 {
00106   // Recompile formula with new expression
00107 
00108   fNval=0 ;
00109   _useList.Clear() ;  
00110 
00111   TString oldFormula=GetTitle() ;
00112   if (Compile(newFormula)) {
00113     coutE(InputArguments) << "RooFormula::reCompile: new equation doesn't compile, formula unchanged" << endl ;
00114     reCompile(oldFormula) ;    
00115     return kTRUE ;
00116   }
00117 
00118   SetTitle(newFormula) ;
00119   return kFALSE ;
00120 }
00121 
00122 
00123 
00124 //_____________________________________________________________________________
00125 RooFormula::~RooFormula() 
00126 {
00127   // Destructor
00128 
00129   _labelList.Delete() ;
00130 }
00131 
00132 
00133 
00134 //_____________________________________________________________________________
00135 RooArgSet& RooFormula::actualDependents() const
00136 {
00137   // Return list of RooAbsArg dependents that is actually used by formula expression
00138 
00139   if (!_compiled) {
00140     _isOK = !((RooFormula*)this)->Compile() ;
00141     _compiled = kTRUE ;
00142   }
00143 
00144   // Return list of dependents used in formula expression
00145 
00146   _actual.removeAll();
00147   
00148   int i ;
00149   for (i=0 ; i<_useList.GetSize() ; i++) {
00150     _actual.add((RooAbsArg&)*_useList.At(i),kTRUE) ;
00151   }
00152 
00153   return _actual ;
00154 }
00155 
00156 
00157 
00158 //_____________________________________________________________________________
00159 void RooFormula::dump() 
00160 {
00161   // DEBUG: Dump state information
00162 
00163   int i ;
00164   cout << "RooFormula::dump()" << endl ;
00165   cout << "useList:" << endl ;
00166   for (i=0 ; i<_useList.GetSize() ; i++) {
00167     cout << "[" << i << "] = " << (void*) _useList.At(i) << " " << _useList.At(i)->GetName() << endl ;
00168   }
00169   cout << "labelList:" << endl ;
00170   for (i=0 ; i<_labelList.GetSize() ; i++) {
00171     cout << "[" << i << "] = " << (void*) _labelList.At(i) << " " << _labelList.At(i)->GetName() <<  endl ;
00172   }
00173   cout << "origList:" << endl ;
00174   for (i=0 ; i<_origList.GetSize() ; i++) {
00175     cout << "[" << i << "] = " << (void*) _origList.At(i)  << " " << _origList.At(i)->GetName() <<  endl ;
00176   }
00177 }
00178 
00179 
00180 
00181 //_____________________________________________________________________________
00182 Bool_t RooFormula::changeDependents(const RooAbsCollection& newDeps, Bool_t mustReplaceAll, Bool_t nameChange) 
00183 {
00184   // Change used variables to those with the same name in given list
00185   // If mustReplaceAll is true and error is generated if one of the
00186   // elements of newDeps is not found as a server
00187   
00188   //Change current servers to new servers with the same name given in list
00189   Bool_t errorStat(kFALSE) ;
00190   int i ;
00191 
00192   for (i=0 ; i<_useList.GetSize() ; i++) {
00193     RooAbsReal* replace = (RooAbsReal*) ((RooAbsArg*)_useList.At(i))->findNewServer(newDeps,nameChange) ;
00194     if (replace) {
00195       _useList.Replace(_useList.At(i),replace) ;
00196     } else if (mustReplaceAll) {
00197       coutE(LinkStateMgmt) << "RooFormula::changeDependents(1): cannot find replacement for " 
00198                            << _useList.At(i)->GetName() << endl ;
00199       errorStat = kTRUE ;
00200     }
00201   }  
00202 
00203   TIterator* iter = _origList.MakeIterator() ;
00204   RooAbsArg* arg ;
00205   while ((arg=(RooAbsArg*)iter->Next())) {
00206     RooAbsReal* replace = (RooAbsReal*) arg->findNewServer(newDeps,nameChange) ;
00207     if (replace) {
00208       _origList.Replace(arg,replace) ;
00209     } else if (mustReplaceAll) {
00210       errorStat = kTRUE ;
00211     }
00212   }
00213   delete iter ;
00214 
00215   return errorStat ;
00216 }
00217 
00218 
00219 
00220 //_____________________________________________________________________________
00221 Double_t RooFormula::eval(const RooArgSet* nset)
00222 { 
00223   // Evaluate TFormula using given normalization set to be used as
00224   // observables definition passed to RooAbsReal::getVal()
00225 
00226   if (!_compiled) {
00227     _isOK = !Compile() ;
00228     _compiled = kTRUE ;
00229   }
00230 
00231   // WVE sanity check should go here
00232   if (!_isOK) {
00233     coutE(Eval) << "RooFormula::eval(" << GetName() << "): Formula doesn't compile: " << GetTitle() << endl ;
00234     return 0. ;
00235   }
00236 
00237   // Pass current dataset pointer to DefinedValue
00238   _nset = (RooArgSet*) nset ;
00239 
00240   return EvalPar(0,0) ; 
00241 }
00242 
00243 
00244 Double_t
00245 
00246 //_____________________________________________________________________________
00247 RooFormula::DefinedValue(Int_t code) 
00248 {
00249   // Interface to TFormula, return value defined by object with id 'code'
00250   // Object ids are mapped from object names by method DefinedVariable()
00251 
00252   // Return current value for variable indicated by internal reference code
00253   if (code>=_useList.GetSize()) return 0 ;
00254   RooAbsArg* arg=(RooAbsArg*)_useList.At(code) ;
00255 
00256   const RooAbsReal *absReal= dynamic_cast<const RooAbsReal*>(arg);  
00257   if(0 != absReal) {
00258     return absReal->getVal(_nset) ;
00259   } else {
00260     const RooAbsCategory *absCat= dynamic_cast<const RooAbsCategory*>(arg);
00261     if(0 != absCat) {
00262       TString& label=((TObjString*)_labelList.At(code))->String() ;
00263       if (label.IsNull()) {
00264         return absCat->getIndex() ;
00265       } else {
00266         return absCat->lookupType(label)->getVal() ; // DK: why not call getVal(_nset) here also?
00267       }
00268     }
00269   }
00270   assert(0) ;
00271   return 0 ;
00272 }
00273 
00274 
00275 
00276 //_____________________________________________________________________________
00277 Int_t RooFormula::DefinedVariable(TString &name, int& action)
00278 {
00279   // Interface to TFormula. If name passed by TFormula is recognized
00280   // as one of our RooAbsArg servers, return a unique id integer
00281   // that represent this variable.
00282 
00283   Int_t ret = DefinedVariable(name) ;
00284   if (ret>=0) {
00285 
00286 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,0,1)
00287      action = kDefinedVariable;
00288 #else
00289      action = 0 ; // prevents compiler warning
00290 #endif
00291 
00292   }
00293   return ret ;
00294 }
00295 
00296 
00297 
00298 //_____________________________________________________________________________
00299 Int_t RooFormula::DefinedVariable(TString &name) 
00300 {
00301   // Interface to TFormula. If name passed by TFormula is recognized
00302   // as one of our RooAbsArg servers, return a unique id integer
00303   // that represent this variable.
00304 
00305   char argName[1024];
00306   strlcpy(argName,name.Data(),1024) ;
00307 
00308   // Find :: operator and split string if found
00309   char *labelName = strstr(argName,"::") ;
00310   if (labelName) {
00311     *labelName = 0 ;
00312     labelName+= 2 ;
00313   }
00314 
00315   // Defined internal reference code for given named variable 
00316   RooAbsArg *arg = 0;
00317   if (argName[0] == '@') {
00318     // Access by ordinal number
00319     Int_t index = atoi(argName+1) ;
00320     if (index>=0 && index<_origList.GetSize()) {
00321       arg = (RooAbsArg*) _origList.At(index) ;
00322     } else {
00323       coutE(Eval) << "RooFormula::DefinedVariable(" << GetName() 
00324                   << ") ERROR: ordinal variable reference " << name 
00325                   << " out of range (0 - " << _origList.GetSize()-1 << ")" << endl ;
00326     }
00327   } else {
00328     // Access by name
00329     arg= (RooAbsArg*) _origList.FindObject(argName) ;
00330   }
00331 
00332   // Check that arg exists
00333   if (!arg) return -1 ;
00334 
00335   // Check that optional label corresponds to actual category state
00336   if (labelName) {
00337     RooAbsCategory* cat = dynamic_cast<RooAbsCategory*>(arg) ;
00338     if (!cat) {
00339       coutE(Eval) << "RooFormula::DefinedVariable(" << GetName() << ") ERROR: " 
00340                   << arg->GetName() << "' is not a RooAbsCategory" << endl ;
00341       return -1 ;
00342     }
00343 
00344     if (!cat->lookupType(labelName)) {
00345       coutE(Eval) << "RooFormula::DefinedVariable(" << GetName() << ") ERROR '" 
00346                   << labelName << "' is not a state of " << arg->GetName() << endl ;
00347       return -1 ;
00348     }
00349 
00350   }
00351 
00352 
00353   // Check if already registered
00354   Int_t i ;
00355   for(i=0 ; i<_useList.GetSize() ; i++) {
00356     RooAbsArg* var = (RooAbsArg*) _useList.At(i) ;
00357     Bool_t varMatch = !TString(var->GetName()).CompareTo(arg->GetName()) ;
00358 
00359     if (varMatch) {
00360       TString& lbl= ((TObjString*) _labelList.At(i))->String() ;
00361       Bool_t lblMatch(kFALSE) ;
00362       if (!labelName && lbl.IsNull()) {
00363         lblMatch=kTRUE ;
00364       } else if (labelName && !lbl.CompareTo(labelName)) {
00365         lblMatch=kTRUE ;
00366       }
00367 
00368       if (lblMatch) {
00369         // Label and variable name match, recycle entry
00370         return i ;
00371       }
00372     }
00373   }
00374 
00375   // Register new entry ;
00376   _useList.Add(arg) ;
00377   if (!labelName) {
00378     _labelList.Add(new TObjString("")) ;
00379   } else {
00380     _labelList.Add(new TObjString(labelName)) ;
00381   }
00382 
00383    return (_useList.GetSize()-1) ;
00384 }
00385 
00386 
00387 
00388 //_____________________________________________________________________________
00389 void RooFormula::printMultiline(ostream& os, Int_t /*contents*/, Bool_t /*verbose*/, TString indent) const 
00390 {
00391   // Printing interface
00392 
00393   os << indent << "--- RooFormula ---" << endl;
00394   os << indent << "  Formula: \"" << GetTitle() << "\"" << endl;
00395   indent.Append("  ");
00396   os << indent << actualDependents() << endl ;
00397 }
00398 
00399 
00400 //_____________________________________________________________________________
00401 void RooFormula::printValue(ostream& os) const 
00402 {
00403   // Print value of formula
00404 
00405   os << const_cast<RooFormula*>(this)->eval(0) ;
00406 }
00407 
00408 
00409 //_____________________________________________________________________________
00410 void RooFormula::printName(ostream& os) const 
00411 {
00412   // Print name of formula
00413 
00414   os << GetName() ;
00415 }
00416 
00417 
00418 //_____________________________________________________________________________
00419 void RooFormula::printTitle(ostream& os) const 
00420 {
00421   // Print title of formula
00422 
00423   os << GetTitle() ;
00424 }
00425 
00426 
00427 //_____________________________________________________________________________
00428 void RooFormula::printClassName(ostream& os) const 
00429 {
00430   // Print class name of formula
00431 
00432   os << IsA()->GetName() ;
00433 }
00434 
00435 
00436 //_____________________________________________________________________________
00437 void RooFormula::printArgs(ostream& os) const 
00438 {
00439   // Print arguments of formula, i.e. dependents that are actually used
00440 
00441   os << "[ actualVars=" << _actual << " ]" ;
00442 }

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