RooAbsArg.cxx

Go to the documentation of this file.
00001 /******************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooAbsArg.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 // RooAbsArg is the common abstract base class for objects that
00021 // represent a value (of arbitrary type) and "shape" that in general
00022 // depends on (is a client of) other RooAbsArg subclasses. The only
00023 // state information about a value that is maintained in this base
00024 // class consists of named attributes and flags that track when either
00025 // the value or the shape of this object changes. The meaning of shape
00026 // depends on the client implementation but could be, for example, the
00027 // allowed range of a value. The base class is also responsible for
00028 // managing client/server links and propagating value/shape changes
00029 // through an expression tree. RooAbsArg implements public interfaces
00030 // for inspecting client/server relationships and
00031 // setting/clearing/testing named attributes.
00032 // END_HTML
00033 //
00034 #include "RooFit.h"
00035 #include "Riostream.h"
00036 
00037 #include "TClass.h"
00038 #include "TObjString.h"
00039 // #include "TGraphStruct.h"
00040 
00041 #include "RooMsgService.h"
00042 #include "RooAbsArg.h"
00043 #include "RooArgSet.h"
00044 #include "RooArgProxy.h"
00045 #include "RooSetProxy.h"
00046 #include "RooListProxy.h"
00047 #include "RooAbsData.h"
00048 #include "RooAbsCategoryLValue.h"
00049 #include "RooAbsRealLValue.h"
00050 #include "RooTrace.h"
00051 #include "RooStringVar.h"
00052 #include "RooRealIntegral.h"
00053 #include "RooMsgService.h"
00054 #include "RooExpensiveObjectCache.h"
00055 #include "RooAbsDataStore.h"
00056 #include "RooResolutionModel.h"
00057 
00058 #include <string.h>
00059 #include <iomanip>
00060 #include <fstream>
00061 #include <algorithm>
00062 #include <sstream>
00063 
00064 using namespace std ;
00065 
00066 #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
00067 char* operator+( streampos&, char* );
00068 #endif
00069 
00070 ClassImp(RooAbsArg)
00071 ;
00072 
00073 Bool_t RooAbsArg::_verboseDirty(kFALSE) ;
00074 Bool_t RooAbsArg::_inhibitDirty(kFALSE) ;
00075 Bool_t RooAbsArg::_flipAClean(kFALSE) ;
00076 
00077 //_____________________________________________________________________________
00078 RooAbsArg::RooAbsArg() :
00079   TNamed(),
00080   _deleteWatch(kFALSE),
00081   _operMode(Auto),
00082   _ownedComponents(0),
00083   _prohibitServerRedirect(kFALSE),
00084   _eocache(0)
00085 {
00086   // Default constructor
00087 
00088   _clientShapeIter = _clientListShape.MakeIterator() ;
00089   _clientValueIter = _clientListValue.MakeIterator() ;
00090 
00091   RooTrace::create(this) ;
00092 }
00093 
00094 //_____________________________________________________________________________
00095 RooAbsArg::RooAbsArg(const char *name, const char *title) :
00096   TNamed(name,title),
00097   _deleteWatch(kFALSE),
00098   _valueDirty(kTRUE),
00099   _shapeDirty(kTRUE),
00100   _operMode(Auto),
00101   _ownedComponents(0),
00102   _prohibitServerRedirect(kFALSE),
00103   _eocache(0)
00104 {
00105   // Create an object with the specified name and descriptive title.
00106   // The newly created object has no clients or servers and has its
00107   // dirty flags set.
00108 
00109   _clientShapeIter = _clientListShape.MakeIterator() ;
00110   _clientValueIter = _clientListValue.MakeIterator() ;
00111   RooTrace::create(this) ;
00112 
00113 }
00114 
00115 //_____________________________________________________________________________
00116 RooAbsArg::RooAbsArg(const RooAbsArg& other, const char* name)
00117   : TNamed(other.GetName(),other.GetTitle()),
00118     RooPrintable(other),
00119     _boolAttrib(other._boolAttrib),
00120     _stringAttrib(other._stringAttrib),
00121     _deleteWatch(other._deleteWatch),
00122     _operMode(Auto),
00123     _ownedComponents(0),
00124     _prohibitServerRedirect(kFALSE),
00125     _eocache(other._eocache)
00126 {
00127   // Copy constructor transfers all boolean and string properties of the original
00128   // object. Transient properties and client-server links are not copied
00129 
00130   // Use name in argument, if supplied
00131   if (name) SetName(name) ;
00132 
00133   // Copy server list by hand
00134   TIterator* sIter = other._serverList.MakeIterator() ;
00135   RooAbsArg* server ;
00136   Bool_t valueProp, shapeProp ;
00137   while ((server = (RooAbsArg*) sIter->Next())) {
00138     valueProp = server->_clientListValue.FindObject((TObject*)&other)?kTRUE:kFALSE ;
00139     shapeProp = server->_clientListShape.FindObject((TObject*)&other)?kTRUE:kFALSE ;
00140     addServer(*server,valueProp,shapeProp) ;
00141   }
00142   delete sIter ;
00143 
00144   _clientShapeIter = _clientListShape.MakeIterator() ;
00145   _clientValueIter = _clientListValue.MakeIterator() ;
00146 
00147   setValueDirty() ;
00148   setShapeDirty() ;
00149 
00150   //setAttribute(Form("CloneOf(%08x)",&other)) ;
00151   //cout << "RooAbsArg::cctor(" << this << ") #bools = " << _boolAttrib.size() << " #strings = " << _stringAttrib.size() << endl ;
00152 
00153   RooTrace::create(this) ;
00154 }
00155 
00156 
00157 //_____________________________________________________________________________
00158 RooAbsArg::~RooAbsArg()
00159 {
00160   // Destructor.
00161 
00162   // Notify all servers that they no longer need to serve us
00163   TIterator* serverIter = _serverList.MakeIterator() ;
00164   RooAbsArg* server ;
00165   while ((server=(RooAbsArg*)serverIter->Next())) {
00166     removeServer(*server,kTRUE) ;
00167   }
00168   delete serverIter ;
00169 
00170   //Notify all client that they are in limbo
00171   TIterator* clientIter = _clientList.MakeIterator() ;
00172   RooAbsArg* client = 0;
00173   Bool_t first(kTRUE) ;
00174   while ((client=(RooAbsArg*)clientIter->Next())) {
00175     client->setAttribute("ServerDied") ;
00176     TString attr("ServerDied:");
00177     attr.Append(GetName());
00178     attr.Append(Form("(%lx)",(ULong_t)this)) ;
00179     client->setAttribute(attr.Data());
00180     client->removeServer(*this,kTRUE);
00181 
00182     if (_verboseDirty) {
00183 
00184       if (first) {
00185         cxcoutD(Tracing) << "RooAbsArg::dtor(" << GetName() << "," << this << ") DeleteWatch: object is being destroyed" << endl ;
00186         first = kFALSE ;
00187       }
00188 
00189       cxcoutD(Tracing)  << fName << "::" << ClassName() << ":~RooAbsArg: dependent \""
00190                        << client->GetName() << "\" should have been deleted first" << endl ;
00191     }
00192   }
00193   delete clientIter ;
00194 
00195   delete _clientShapeIter ;
00196   delete _clientValueIter ;
00197 
00198   if (_ownedComponents) {
00199     delete _ownedComponents ;
00200     _ownedComponents = 0 ;
00201   }
00202 
00203   RooTrace::destroy(this) ;
00204 }
00205 
00206 
00207 //_____________________________________________________________________________
00208 void RooAbsArg::setDirtyInhibit(Bool_t flag)
00209 {
00210   // Control global dirty inhibit mode. When set to true no value or shape dirty
00211   // flags are propagated and cache is always considered to be dirty.
00212   _inhibitDirty = flag ;
00213 }
00214 
00215 
00216 //_____________________________________________________________________________
00217 void RooAbsArg::setACleanADirty(Bool_t flag)
00218 {
00219   // This global switch changes the cache mode of all objects marked as 'always clean'
00220   // to 'always dirty'. For internal use in RooRealIntegral
00221   _flipAClean = flag ;
00222 }
00223 
00224 //_____________________________________________________________________________
00225 void RooAbsArg::verboseDirty(Bool_t flag)
00226 {
00227   // Activate verbose messaging related to dirty flag propagation
00228   _verboseDirty = flag ;
00229 }
00230 
00231 //_____________________________________________________________________________
00232 Bool_t RooAbsArg::isCloneOf(const RooAbsArg& other) const
00233 {
00234   // Check if this object was created as a clone of 'other'
00235 
00236   return (getAttribute(Form("CloneOf(%lx)",(ULong_t)&other)) ||
00237           other.getAttribute(Form("CloneOf(%lx)",(ULong_t)this))) ;
00238 }
00239 
00240 
00241 //_____________________________________________________________________________
00242 void RooAbsArg::setAttribute(const Text_t* name, Bool_t value)
00243 {
00244   // Set (default) or clear a named boolean attribute of this object.
00245 
00246   if (value) {
00247 
00248     _boolAttrib.insert(name) ;
00249 
00250   } else {
00251 
00252     set<string>::iterator iter = _boolAttrib.find(name) ;
00253     if (iter != _boolAttrib.end()) {
00254       _boolAttrib.erase(iter) ;
00255     }
00256 
00257   }
00258 
00259 }
00260 
00261 
00262 //_____________________________________________________________________________
00263 Bool_t RooAbsArg::getAttribute(const Text_t* name) const
00264 {
00265   // Check if a named attribute is set. By default, all attributes are unset.
00266 
00267   return (_boolAttrib.find(name) != _boolAttrib.end()) ;
00268 }
00269 
00270 
00271 //_____________________________________________________________________________
00272 void RooAbsArg::setStringAttribute(const Text_t* key, const Text_t* value)
00273 {
00274   // Associate string 'value' to this object under key 'key'
00275 
00276   if (value) {
00277     _stringAttrib[key] = value ;
00278   } else {
00279     if (_stringAttrib.find(key)!=_stringAttrib.end()) {
00280       _stringAttrib.erase(key) ;
00281     }
00282   }
00283 }
00284 
00285 //_____________________________________________________________________________
00286 const Text_t* RooAbsArg::getStringAttribute(const Text_t* key) const
00287 {
00288   // Get string attribute mapped under key 'key'. Returns null pointer
00289   // if no attribute exists under that key
00290 
00291   map<string,string>::const_iterator iter = _stringAttrib.find(key) ;
00292   if (iter!=_stringAttrib.end()) {
00293     return iter->second.c_str() ;
00294   } else {
00295     return 0 ;
00296   }
00297 }
00298 
00299 
00300 //_____________________________________________________________________________
00301 void RooAbsArg::setTransientAttribute(const Text_t* name, Bool_t value)
00302 {
00303   // Set (default) or clear a named boolean attribute of this object.
00304 
00305   if (value) {
00306 
00307     _boolAttribTransient.insert(name) ;
00308 
00309   } else {
00310 
00311     set<string>::iterator iter = _boolAttribTransient.find(name) ;
00312     if (iter != _boolAttribTransient.end()) {
00313       _boolAttribTransient.erase(iter) ;
00314     }
00315 
00316   }
00317 
00318 }
00319 
00320 
00321 //_____________________________________________________________________________
00322 Bool_t RooAbsArg::getTransientAttribute(const Text_t* name) const
00323 {
00324   // Check if a named attribute is set. By default, all attributes
00325   // are unset.
00326 
00327   return (_boolAttribTransient.find(name) != _boolAttribTransient.end()) ;
00328 }
00329 
00330 
00331 
00332 
00333 //_____________________________________________________________________________
00334 void RooAbsArg::addServer(RooAbsArg& server, Bool_t valueProp, Bool_t shapeProp)
00335 {
00336   // Register another RooAbsArg as a server to us, ie, declare that
00337   // we depend on it. In addition to the basic client-server relationship,
00338   // we can declare dependence on the server's value and/or shape.
00339 
00340   if (_prohibitServerRedirect) {
00341     cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName()
00342                            << "): PROHIBITED SERVER ADDITION REQUESTED: adding server " << server.GetName()
00343                            << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
00344     assert(0) ;
00345   }
00346 
00347   cxcoutD(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): adding server " << server.GetName()
00348                          << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
00349 
00350   if (server.operMode()==ADirty && operMode()!=ADirty && valueProp) {
00351     setOperMode(ADirty) ;
00352   }
00353 
00354 
00355   // Add server link to given server
00356   _serverList.Add(&server) ;
00357 
00358   server._clientList.Add(this) ;
00359   if (valueProp) server._clientListValue.Add(this) ;
00360   if (shapeProp) server._clientListShape.Add(this) ;
00361 }
00362 
00363 
00364 
00365 //_____________________________________________________________________________
00366 void RooAbsArg::addServerList(RooAbsCollection& serverList, Bool_t valueProp, Bool_t shapeProp)
00367 {
00368   // Register a list of RooAbsArg as servers to us by calls
00369   // addServer() for each arg in the list
00370 
00371   RooAbsArg* arg ;
00372   TIterator* iter = serverList.createIterator() ;
00373   while ((arg=(RooAbsArg*)iter->Next())) {
00374     addServer(*arg,valueProp,shapeProp) ;
00375   }
00376   delete iter ;
00377 }
00378 
00379 
00380 
00381 //_____________________________________________________________________________
00382 void RooAbsArg::removeServer(RooAbsArg& server, Bool_t force)
00383 {
00384   // Unregister another RooAbsArg as a server to us, ie, declare that
00385   // we no longer depend on its value and shape.
00386 
00387   if (_prohibitServerRedirect) {
00388     cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): PROHIBITED SERVER REMOVAL REQUESTED: removing server "
00389                            << server.GetName() << "(" << &server << ")" << endl ;
00390     assert(0) ;
00391   }
00392 
00393   if (_verboseDirty) {
00394     cxcoutD(LinkStateMgmt) << "RooAbsArg::removeServer(" << GetName() << "): removing server "
00395                            << server.GetName() << "(" << &server << ")" << endl ;
00396   }
00397 
00398   // Remove server link to given server
00399   if (!force) {
00400     _serverList.Remove(&server) ;
00401 
00402     server._clientList.Remove(this) ;
00403     server._clientListValue.Remove(this) ;
00404     server._clientListShape.Remove(this) ;
00405   } else {
00406     _serverList.RemoveAll(&server) ;
00407 
00408     server._clientList.RemoveAll(this) ;
00409     server._clientListValue.RemoveAll(this) ;
00410     server._clientListShape.RemoveAll(this) ;
00411   }
00412 }
00413 
00414 
00415 //_____________________________________________________________________________
00416 void RooAbsArg::replaceServer(RooAbsArg& oldServer, RooAbsArg& newServer, Bool_t propValue, Bool_t propShape)
00417 {
00418   // Replace 'oldServer' with 'newServer'
00419 
00420   Int_t count = _serverList.refCount(&oldServer) ;
00421   removeServer(oldServer,kTRUE) ;
00422   while(count--) {
00423     addServer(newServer,propValue,propShape) ;
00424   }
00425 }
00426 
00427 
00428 //_____________________________________________________________________________
00429 void RooAbsArg::changeServer(RooAbsArg& server, Bool_t valueProp, Bool_t shapeProp)
00430 {
00431   // Change dirty flag propagation mask for specified server
00432 
00433   if (!_serverList.FindObject(&server)) {
00434     coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
00435          << server.GetName() << " not registered" << endl ;
00436     return ;
00437   }
00438 
00439   // This condition should not happen, but check anyway
00440   if (!server._clientList.FindObject(this)) {
00441     coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
00442                          << server.GetName() << " doesn't have us registered as client" << endl ;
00443     return ;
00444   }
00445 
00446   // Remove all propagation links, then reinstall requested ones ;
00447   Int_t vcount = server._clientListValue.refCount(this) ;
00448   Int_t scount = server._clientListShape.refCount(this) ;
00449   server._clientListValue.RemoveAll(this) ;
00450   server._clientListShape.RemoveAll(this) ;
00451   if (valueProp) {
00452     while (vcount--) server._clientListValue.Add(this) ;
00453   }
00454   if (shapeProp) {
00455     while(scount--) server._clientListShape.Add(this) ;
00456   }
00457 }
00458 
00459 
00460 
00461 //_____________________________________________________________________________
00462 void RooAbsArg::leafNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t recurseNonDerived) const
00463 {
00464   // Fill supplied list with all leaf nodes of the arg tree, starting with
00465   // ourself as top node. A leaf node is node that has no servers declared.
00466 
00467   treeNodeServerList(list,arg,kFALSE,kTRUE,kFALSE,recurseNonDerived) ;
00468 }
00469 
00470 
00471 
00472 //_____________________________________________________________________________
00473 void RooAbsArg::branchNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t recurseNonDerived) const
00474 {
00475   // Fill supplied list with all branch nodes of the arg tree starting with
00476   // ourself as top node. A branch node is node that has one or more servers declared.
00477 
00478   treeNodeServerList(list,arg,kTRUE,kFALSE,kFALSE,recurseNonDerived) ;
00479 }
00480 
00481 
00482 //_____________________________________________________________________________
00483 void RooAbsArg::treeNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t doBranch, Bool_t doLeaf, Bool_t valueOnly, Bool_t recurseFundamental) const
00484 {
00485   // Fill supplied list with nodes of the arg tree, following all server links,
00486   // starting with ourself as top node.
00487 
00488   if (!arg) {
00489     if (list->getHashTableSize()==0) {
00490       list->setHashTableSize(1000) ;
00491     }
00492     arg=this ;
00493   }
00494 
00495   // Decide if to add current node
00496   if ((doBranch&&doLeaf) ||
00497       (doBranch&&arg->isDerived()) ||
00498       (doLeaf&&arg->isFundamental()&&(!(recurseFundamental&&arg->isDerived()))) ) {
00499     list->add(*arg,kTRUE) ;
00500   }
00501 
00502   // Recurse if current node is derived
00503   if (arg->isDerived() && (!arg->isFundamental() || recurseFundamental)) {
00504     RooAbsArg* server ;
00505     TIterator* sIter = arg->serverIterator() ;
00506     while ((server=(RooAbsArg*)sIter->Next())) {
00507 
00508       // Skip non-value server nodes if requested
00509       Bool_t isValueSrv = server->_clientListValue.FindObject((TObject*)arg)?kTRUE:kFALSE ;
00510       if (valueOnly && !isValueSrv) {
00511         continue ;
00512       }
00513       treeNodeServerList(list,server,doBranch,doLeaf,valueOnly,recurseFundamental) ;
00514     }
00515     delete sIter ;
00516   }
00517 }
00518 
00519 
00520 //_____________________________________________________________________________
00521 RooArgSet* RooAbsArg::getParameters(const RooAbsData* set, Bool_t stripDisconnected) const
00522 {
00523   // Create a list of leaf nodes in the arg tree starting with
00524   // ourself as top node that don't match any of the names of the variable list
00525   // of the supplied data set (the dependents). The caller of this
00526   // function is responsible for deleting the returned argset.
00527   // The complement of this function is getObservables()
00528 
00529   return getParameters(set?set->get():0,stripDisconnected) ;
00530 }
00531 
00532 
00533 //_____________________________________________________________________________
00534 void RooAbsArg::addParameters(RooArgSet& params, const RooArgSet* nset,Bool_t stripDisconnected) const
00535 {
00536   // INTERNAL helper function for getParameters()
00537 
00538   RooArgSet parList("parameters") ;
00539 
00540   TIterator* siter = serverIterator() ;
00541   RooAbsArg* server ;
00542 
00543   RooArgSet nodeParamServers ;
00544   RooArgSet nodeBranchServers ;
00545   while((server=(RooAbsArg*)siter->Next())) {
00546     if (server->isValueServer(*this)) {
00547       if (server->isFundamental()) {
00548         if (!nset || !server->dependsOn(*nset)) {
00549           nodeParamServers.add(*server) ;
00550         }
00551       } else {
00552         nodeBranchServers.add(*server) ;
00553       }
00554     }
00555   }
00556   delete siter ;
00557 
00558   // Allow pdf to strip parameters from list before adding it
00559   getParametersHook(nset,&nodeParamServers,stripDisconnected) ;
00560 
00561   // Add parameters of this node to the combined list
00562   params.add(nodeParamServers,kTRUE) ;
00563 
00564   // Now recurse into branch servers
00565   TIterator* biter = nodeBranchServers.createIterator() ;
00566   while((server=(RooAbsArg*)biter->Next())) {
00567     server->addParameters(params,nset) ;
00568   }
00569   delete biter ;
00570 }
00571 
00572 
00573 //_____________________________________________________________________________
00574 RooArgSet* RooAbsArg::getParameters(const RooArgSet* nset, Bool_t stripDisconnected) const
00575 {
00576   // Create a list of leaf nodes in the arg tree starting with
00577   // ourself as top node that don't match any of the names the args in the
00578   // supplied argset. The caller of this function is responsible
00579   // for deleting the returned argset. The complement of this function
00580   // is getObservables()
00581 
00582 
00583   RooArgSet parList("parameters") ;
00584 
00585   addParameters(parList,nset,stripDisconnected) ;
00586 
00587   RooArgList tmp(parList) ;
00588   tmp.sort() ;
00589   return new RooArgSet(tmp) ;
00590 }
00591 
00592 
00593 
00594 //_____________________________________________________________________________
00595 RooArgSet* RooAbsArg::getObservables(const RooAbsData* set) const
00596 {
00597   // Create a list of leaf nodes in the arg tree starting with
00598   // ourself as top node that match any of the names of the variable list
00599   // of the supplied data set (the dependents). The caller of this
00600   // function is responsible for deleting the returned argset.
00601   // The complement of this function is getObservables()
00602 
00603   if (!set) return new RooArgSet ;
00604 
00605   return getObservables(set->get()) ;
00606 }
00607 
00608 
00609 //_____________________________________________________________________________
00610 RooArgSet* RooAbsArg::getObservables(const RooArgSet* dataList, Bool_t valueOnly) const
00611 {
00612   // Create a list of leaf nodes in the arg tree starting with
00613   // ourself as top node that match any of the names the args in the
00614   // supplied argset. The caller of this function is responsible
00615   // for deleting the returned argset. The complement of this function
00616   // is getObservables()
00617 
00618   //cout << "RooAbsArg::getObservables(" << GetName() << ")" << endl ;
00619 
00620   RooArgSet* depList = new RooArgSet("dependents") ;
00621   if (!dataList) return depList ;
00622 
00623   // Make iterator over tree leaf node list
00624   RooArgSet leafList("leafNodeServerList") ;
00625   treeNodeServerList(&leafList,0,kFALSE,kTRUE,valueOnly) ;
00626   //leafNodeServerList(&leafList) ;
00627   TIterator *sIter = leafList.createIterator() ;
00628 
00629   RooAbsArg* arg ;
00630   if (valueOnly) {
00631     while ((arg=(RooAbsArg*)sIter->Next())) {
00632       if (arg->dependsOnValue(*dataList) && arg->isLValue()) {
00633         depList->add(*arg) ;
00634       }
00635     }
00636   } else {
00637     while ((arg=(RooAbsArg*)sIter->Next())) {
00638       if (arg->dependsOn(*dataList) && arg->isLValue()) {
00639         depList->add(*arg) ;
00640       }
00641     }
00642   }
00643   delete sIter ;
00644 
00645   // Call hook function for all branch nodes
00646   RooArgSet branchList ;
00647   branchNodeServerList(&branchList) ;
00648   RooAbsArg* branch ;
00649   TIterator* bIter = branchList.createIterator() ;
00650   while((branch=(RooAbsArg*)bIter->Next())) {
00651     branch->getObservablesHook(dataList, depList) ;
00652   }
00653   delete bIter ;
00654 
00655   return depList ;
00656 }
00657 
00658 
00659 RooArgSet* RooAbsArg::getComponents() const
00660 {
00661   // Return a RooArgSet with all component (branch nodes) of the
00662   // expression tree headed by this object
00663 
00664   TString name(GetName()) ;
00665   name.Append("_components") ;
00666 
00667   RooArgSet* set = new RooArgSet(name) ;
00668   branchNodeServerList(set) ;
00669 
00670   return set ;
00671 }
00672 
00673 
00674 
00675 //_____________________________________________________________________________
00676 Bool_t RooAbsArg::checkObservables(const RooArgSet*) const
00677 {
00678   // Overloadable function in which derived classes can implement
00679   // consistency checks of the variables. If this function returns
00680   // true, indicating an error, the fitter or generator will abort.
00681 
00682   return kFALSE ;
00683 }
00684 
00685 
00686 //_____________________________________________________________________________
00687 Bool_t RooAbsArg::recursiveCheckObservables(const RooArgSet* nset) const
00688 {
00689   // Recursively call checkObservables on all nodes in the expression tree
00690 
00691   RooArgSet nodeList ;
00692   treeNodeServerList(&nodeList) ;
00693   TIterator* iter = nodeList.createIterator() ;
00694 
00695   RooAbsArg* arg ;
00696   Bool_t ret(kFALSE) ;
00697   while((arg=(RooAbsArg*)iter->Next())) {
00698     if (arg->getAttribute("ServerDied")) {
00699       coutE(LinkStateMgmt) << "RooAbsArg::recursiveCheckObservables(" << GetName() << "): ERROR: one or more servers of node "
00700                            << arg->GetName() << " no longer exists!" << endl ;
00701       arg->Print("v") ;
00702       ret = kTRUE ;
00703     }
00704     ret |= arg->checkObservables(nset) ;
00705   }
00706   delete iter ;
00707 
00708   return ret ;
00709 }
00710 
00711 
00712 //_____________________________________________________________________________
00713 Bool_t RooAbsArg::dependsOn(const RooAbsCollection& serverList, const RooAbsArg* ignoreArg, Bool_t valueOnly) const
00714 {
00715   // Test whether we depend on (ie, are served by) any object in the
00716   // specified collection. Uses the dependsOn(RooAbsArg&) member function.
00717 
00718   Bool_t result(kFALSE);
00719   TIterator* sIter = serverList.createIterator();
00720   RooAbsArg* server ;
00721   while ((!result && (server=(RooAbsArg*)sIter->Next()))) {
00722     if (dependsOn(*server,ignoreArg,valueOnly)) {
00723       result= kTRUE;
00724     }
00725   }
00726   delete sIter;
00727   return result;
00728 }
00729 
00730 
00731 //_____________________________________________________________________________
00732 Bool_t RooAbsArg::dependsOn(const RooAbsArg& testArg, const RooAbsArg* ignoreArg, Bool_t valueOnly) const
00733 {
00734   // Test whether we depend on (ie, are served by) the specified object.
00735   // Note that RooAbsArg objects are considered equivalent if they have
00736   // the same name.
00737 
00738   if (this==ignoreArg) return kFALSE ;
00739 
00740   // First check if testArg is self
00741   if (!TString(testArg.GetName()).CompareTo(GetName())) return kTRUE ;
00742 
00743 
00744   // Next test direct dependence
00745   RooAbsArg* server = findServer(testArg.GetName()) ;
00746   if (server!=0) {
00747 
00748     // Return true if valueOnly is FALSE or if server is value server, otherwise keep looking
00749     if ( !valueOnly || server->isValueServer(GetName())) {
00750       return kTRUE ;
00751     }
00752   }
00753 
00754   // If not, recurse
00755   TIterator* sIter = serverIterator() ;
00756   while ((server=(RooAbsArg*)sIter->Next())) {
00757 
00758     if ( !valueOnly || server->isValueServer(GetName())) {
00759       if (server->dependsOn(testArg,ignoreArg,valueOnly)) {
00760         delete sIter ;
00761         return kTRUE ;
00762       }
00763     }
00764   }
00765 
00766   delete sIter ;
00767   return kFALSE ;
00768 }
00769 
00770 
00771 
00772 //_____________________________________________________________________________
00773 Bool_t RooAbsArg::overlaps(const RooAbsArg& testArg, Bool_t valueOnly) const
00774 {
00775   // Test if any of the nodes of tree are shared with that of the given tree
00776 
00777   RooArgSet list("treeNodeList") ;
00778   treeNodeServerList(&list) ;
00779 
00780   return valueOnly ? testArg.dependsOnValue(list) : testArg.dependsOn(list) ;
00781 }
00782 
00783 
00784 
00785 //_____________________________________________________________________________
00786 Bool_t RooAbsArg::observableOverlaps(const RooAbsData* dset, const RooAbsArg& testArg) const
00787 {
00788   // Test if any of the dependents of the arg tree (as determined by getObservables)
00789   // overlaps with those of the testArg.
00790 
00791   return observableOverlaps(dset->get(),testArg) ;
00792 }
00793 
00794 
00795 //_____________________________________________________________________________
00796 Bool_t RooAbsArg::observableOverlaps(const RooArgSet* nset, const RooAbsArg& testArg) const
00797 {
00798   // Test if any of the dependents of the arg tree (as determined by getObservables)
00799   // overlaps with those of the testArg.
00800 
00801   RooArgSet* depList = getObservables(nset) ;
00802   Bool_t ret = testArg.dependsOn(*depList) ;
00803   delete depList ;
00804   return ret ;
00805 }
00806 
00807 
00808 
00809 //_____________________________________________________________________________
00810 void RooAbsArg::setValueDirty(const RooAbsArg* source) const
00811 {
00812   // Mark this object as having changed its value, and propagate this status
00813   // change to all of our clients. If the object is not in automatic dirty
00814   // state propagation mode, this call has no effect
00815 
00816   if (_operMode!=Auto || _inhibitDirty) return ;
00817 
00818   // Handle no-propagation scenarios first
00819   if (_clientListValue.GetSize()==0) {
00820     _valueDirty = kTRUE ;
00821     return ;
00822   }
00823 
00824   // Cyclical dependency interception
00825   if (source==0) {
00826     source=this ;
00827   } else if (source==this) {
00828     // Cyclical dependency, abort
00829     coutE(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << GetName()
00830                          << "): cyclical dependency detected, source = " << source->GetName() << endl ;
00831     //assert(0) ;
00832     return ;
00833   }
00834 
00835   // Propagate dirty flag to all clients if this is a down->up transition
00836   if (_verboseDirty) {
00837     cxcoutD(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << (source?source->GetName():"self") << "->" << GetName() << "," << this
00838                            << "): dirty flag " << (_valueDirty?"already ":"") << "raised" << endl ;
00839   }
00840 
00841   _valueDirty = kTRUE ;
00842 
00843   _clientValueIter->Reset() ;
00844   RooAbsArg* client ;
00845   while ((client=(RooAbsArg*)_clientValueIter->Next())) {
00846     client->setValueDirty(source) ;
00847   }
00848 
00849 
00850 }
00851 
00852 
00853 //_____________________________________________________________________________
00854 void RooAbsArg::setShapeDirty(const RooAbsArg* source) const
00855 {
00856   // Mark this object as having changed its shape, and propagate this status
00857   // change to all of our clients.
00858 
00859   if (_verboseDirty) {
00860     cxcoutD(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
00861                            << "): dirty flag " << (_shapeDirty?"already ":"") << "raised" << endl ;
00862   }
00863 
00864   if (_clientListShape.GetSize()==0) {
00865     _shapeDirty = kTRUE ;
00866     return ;
00867   }
00868 
00869   // Set 'dirty' shape state for this object and propagate flag to all its clients
00870   if (source==0) {
00871     source=this ;
00872   } else if (source==this) {
00873     // Cyclical dependency, abort
00874     coutE(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
00875          << "): cyclical dependency detected" << endl ;
00876     return ;
00877   }
00878 
00879   // Propagate dirty flag to all clients if this is a down->up transition
00880   _shapeDirty=kTRUE ;
00881 
00882   _clientShapeIter->Reset() ;
00883   RooAbsArg* client ;
00884   while ((client=(RooAbsArg*)_clientShapeIter->Next())) {
00885     client->setShapeDirty(source) ;
00886     client->setValueDirty(source) ;
00887   }
00888 
00889 }
00890 
00891 
00892 
00893 //_____________________________________________________________________________
00894 Bool_t RooAbsArg::redirectServers(const RooAbsCollection& newSet, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursionStep)
00895 {
00896   // Substitute our servers with those listed in newSet. If nameChange is false, servers and
00897   // and substitutes are matched by name. If nameChange is true, servers are matched to args
00898   // in newSet that have the 'ORIGNAME:<servername>' attribute set. If mustReplaceAll is set,
00899   // a warning is printed and error status is returned if not all servers could be sucessfully
00900   // substituted.
00901 
00902   // Trivial case, no servers
00903   if (!_serverList.First()) return kFALSE ;
00904   if (newSet.getSize()==0) return kFALSE ;
00905 
00906   // Replace current servers with new servers with the same name from the given list
00907   Bool_t ret(kFALSE) ;
00908 
00909   //Copy original server list to not confuse the iterator while deleting
00910   THashList origServerList, origServerValue, origServerShape ;
00911   RooAbsArg *oldServer, *newServer ;
00912   TIterator* sIter = _serverList.MakeIterator() ;
00913   while ((oldServer=(RooAbsArg*)sIter->Next())) {
00914     origServerList.Add(oldServer) ;
00915 
00916     // Retrieve server side link state information
00917     if (oldServer->_clientListValue.FindObject(this)) {
00918       origServerValue.Add(oldServer) ;
00919     }
00920     if (oldServer->_clientListShape.FindObject(this)) {
00921       origServerShape.Add(oldServer) ;
00922     }
00923   }
00924   delete sIter ;
00925 
00926   // Delete all previously registered servers
00927   sIter = origServerList.MakeIterator() ;
00928   Bool_t propValue, propShape ;
00929   while ((oldServer=(RooAbsArg*)sIter->Next())) {
00930 
00931     newServer= oldServer->findNewServer(newSet, nameChange);
00932 
00933     if (newServer && _verboseDirty) {
00934       cxcoutD(LinkStateMgmt) << "RooAbsArg::redirectServers(" << (void*)this << "," << GetName() << "): server " << oldServer->GetName()
00935                              << " redirected from " << oldServer << " to " << newServer << endl ;
00936     }
00937 
00938     if (!newServer) {
00939       if (mustReplaceAll) {
00940         cxcoutD(LinkStateMgmt) << "RooAbsArg::redirectServers(" << (void*)this << "," << GetName() << "): server " << oldServer->GetName()
00941                                << " (" << (void*)oldServer << ") not redirected" << (nameChange?"[nameChange]":"") << endl ;
00942         ret = kTRUE ;
00943       }
00944       continue ;
00945     }
00946 
00947     propValue=origServerValue.FindObject(oldServer)?kTRUE:kFALSE ;
00948     propShape=origServerShape.FindObject(oldServer)?kTRUE:kFALSE ;
00949     // cout << "replaceServer with name " << oldServer->GetName() << " old=" << oldServer << " new=" << newServer << endl ;
00950     if (newServer != this) {
00951       replaceServer(*oldServer,*newServer,propValue,propShape) ;
00952     }
00953   }
00954 
00955   delete sIter ;
00956 
00957   setValueDirty() ;
00958   setShapeDirty() ;
00959 
00960   // Take self out of newset disallowing cyclical dependencies
00961   RooAbsCollection* newSet2 = (RooAbsCollection*) newSet.clone("newSet2") ;
00962   newSet2->remove(*this,kTRUE,kTRUE) ;
00963 
00964   // Process the proxies
00965   Bool_t allReplaced=kTRUE ;
00966   for (int i=0 ; i<numProxies() ; i++) {
00967     // WVE: Need to make exception here too for newServer != this
00968     Bool_t ret2 = getProxy(i)->changePointer(*newSet2,nameChange) ;
00969     allReplaced &= ret2 ;
00970   }
00971 
00972   delete newSet2 ;
00973 
00974   if (mustReplaceAll && !allReplaced) {
00975     coutE(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName()
00976                          << "): ERROR, some proxies could not be adjusted" << endl ;
00977     ret = kTRUE ;
00978   }
00979 
00980   // Optional subclass post-processing
00981   for (Int_t i=0 ;i<numCaches() ; i++) {
00982     ret |= getCache(i)->redirectServersHook(newSet,mustReplaceAll,nameChange,isRecursionStep) ;
00983   }
00984   ret |= redirectServersHook(newSet,mustReplaceAll,nameChange,isRecursionStep) ;
00985 
00986   return ret ;
00987 }
00988 
00989 //_____________________________________________________________________________
00990 RooAbsArg *RooAbsArg::findNewServer(const RooAbsCollection &newSet, Bool_t nameChange) const
00991 {
00992   // Find the new server in the specified set that matches the old server.
00993   // Allow a name change if nameChange is kTRUE, in which case the new
00994   // server is selected by searching for a new server with an attribute
00995   // of "ORIGNAME:<oldName>". Return zero if there is not a unique match.
00996 
00997   RooAbsArg *newServer = 0;
00998   if (!nameChange) {
00999     newServer = newSet.find(GetName()) ;
01000   }
01001   else {
01002     // Name changing server redirect:
01003     // use 'ORIGNAME:<oldName>' attribute instead of name of new server
01004     TString nameAttrib("ORIGNAME:") ;
01005     nameAttrib.Append(GetName()) ;
01006 
01007     RooArgSet* tmp = (RooArgSet*) newSet.selectByAttrib(nameAttrib,kTRUE) ;
01008     if(0 != tmp) {
01009 
01010       // Check if any match was found
01011       if (tmp->getSize()==0) {
01012         delete tmp ;
01013         return 0 ;
01014       }
01015 
01016       // Check if match is unique
01017       if(tmp->getSize()>1) {
01018         coutF(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName() << "): FATAL Error, " << tmp->getSize() << " servers with "
01019                              << nameAttrib << " attribute" << endl ;
01020         tmp->Print("v") ;
01021         assert(0) ;
01022       }
01023 
01024       // use the unique element in the set
01025       newServer= tmp->first();
01026       delete tmp ;
01027     }
01028   }
01029   return newServer;
01030 }
01031 
01032 Bool_t RooAbsArg::recursiveRedirectServers(const RooAbsCollection& newSet, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t recurseInNewSet)
01033 {
01034   // Recursively redirect all servers with new server in collection 'newSet'.
01035   // Substitute our servers with those listed in newSet. If nameChange is false, servers and
01036   // and substitutes are matched by name. If nameChange is true, servers are matched to args
01037   // in newSet that have the 'ORIGNAME:<servername>' attribute set. If mustReplaceAll is set,
01038   // a warning is printed and error status is returned if not all servers could be sucessfully
01039   // substituted. If recurseInNewSet is true, the recursion algorithm also recursion into
01040   // expression trees under the arguments in the new servers (i.e. those in newset)
01041 
01042 
01043   // Cyclic recursion protection
01044   static RooLinkedList callStack ;
01045   if (callStack.FindObject(this)) {
01046     return kFALSE ;
01047   } else {
01048     callStack.Add(this) ;
01049   }
01050 
01051   // Do not recurse into newset if not so specified
01052 //   if (!recurseInNewSet && newSet.contains(*this)) {
01053 //     return kFALSE ;
01054 //   }
01055 
01056 
01057   // Apply the redirectServers function recursively on all branch nodes in this argument tree.
01058   Bool_t ret(kFALSE) ;
01059 
01060   cxcoutD(LinkStateMgmt) << "RooAbsArg::recursiveRedirectServers(" << this << "," << GetName() << ") newSet = " << newSet << " mustReplaceAll = "
01061                          << (mustReplaceAll?"T":"F") << " nameChange = " << (nameChange?"T":"F") << " recurseInNewSet = " << (recurseInNewSet?"T":"F") << endl ;
01062 
01063   // Do redirect on self (identify operation as recursion step)
01064   ret |= redirectServers(newSet,mustReplaceAll,nameChange,kTRUE) ;
01065 
01066   // Do redirect on servers
01067   TIterator* sIter = serverIterator() ;
01068   RooAbsArg* server ;
01069   while((server=(RooAbsArg*)sIter->Next())) {
01070     ret |= server->recursiveRedirectServers(newSet,mustReplaceAll,nameChange,recurseInNewSet) ;
01071   }
01072   delete sIter ;
01073 
01074   callStack.Remove(this) ;
01075   return ret ;
01076 }
01077 
01078 
01079 
01080 //_____________________________________________________________________________
01081 void RooAbsArg::registerProxy(RooArgProxy& proxy)
01082 {
01083   // Register an RooArgProxy in the proxy list. This function is called by owned
01084   // proxies upon creation. After registration, this arg wil forward pointer
01085   // changes from serverRedirects and updates in cached normalization sets
01086   // to the proxies immediately after they occur. The proxied argument is
01087   // also added as value and/or shape server
01088 
01089   // Every proxy can be registered only once
01090   if (_proxyList.FindObject(&proxy)) {
01091     coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
01092                          << proxy.GetName() << " for arg " << proxy.absArg()->GetName()
01093                          << " already registered" << endl ;
01094     return ;
01095   }
01096 
01097 //   cout << (void*)this << " " << GetName() << ": registering proxy "
01098 //        << (void*)&proxy << " with name " << proxy.name() << " in mode "
01099 //        << (proxy.isValueServer()?"V":"-") << (proxy.isShapeServer()?"S":"-") << endl ;
01100 
01101   // Register proxied object as server
01102   if (proxy.absArg()) {
01103     addServer(*proxy.absArg(),proxy.isValueServer(),proxy.isShapeServer()) ;
01104   }
01105 
01106   // Register proxy itself
01107   _proxyList.Add(&proxy) ;
01108 }
01109 
01110 
01111 //_____________________________________________________________________________
01112 void RooAbsArg::unRegisterProxy(RooArgProxy& proxy)
01113 {
01114   // Remove proxy from proxy list. This functions is called by owned proxies
01115   // upon their destruction.
01116 
01117   _proxyList.Remove(&proxy) ;
01118 }
01119 
01120 
01121 
01122 //_____________________________________________________________________________
01123 void RooAbsArg::registerProxy(RooSetProxy& proxy)
01124 {
01125   // Register an RooSetProxy in the proxy list. This function is called by owned
01126   // proxies upon creation. After registration, this arg wil forward pointer
01127   // changes from serverRedirects and updates in cached normalization sets
01128   // to the proxies immediately after they occur.
01129 
01130   // Every proxy can be registered only once
01131   if (_proxyList.FindObject(&proxy)) {
01132     coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
01133                          << proxy.GetName() << " already registered" << endl ;
01134     return ;
01135   }
01136 
01137   // Register proxy itself
01138   _proxyList.Add(&proxy) ;
01139 }
01140 
01141 
01142 
01143 //_____________________________________________________________________________
01144 void RooAbsArg::unRegisterProxy(RooSetProxy& proxy)
01145 {
01146   // Remove proxy from proxy list. This functions is called by owned proxies
01147   // upon their destruction.
01148 
01149   _proxyList.Remove(&proxy) ;
01150 }
01151 
01152 
01153 
01154 //_____________________________________________________________________________
01155 void RooAbsArg::registerProxy(RooListProxy& proxy)
01156 {
01157   // Register an RooListProxy in the proxy list. This function is called by owned
01158   // proxies upon creation. After registration, this arg wil forward pointer
01159   // changes from serverRedirects and updates in cached normalization sets
01160   // to the proxies immediately after they occur.
01161 
01162   // Every proxy can be registered only once
01163   if (_proxyList.FindObject(&proxy)) {
01164     coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
01165                          << proxy.GetName() << " already registered" << endl ;
01166     return ;
01167   }
01168 
01169   // Register proxy itself
01170   _proxyList.Add(&proxy) ;
01171 }
01172 
01173 
01174 
01175 //_____________________________________________________________________________
01176 void RooAbsArg::unRegisterProxy(RooListProxy& proxy)
01177 {
01178   // Remove proxy from proxy list. This functions is called by owned proxies
01179   // upon their destruction.
01180 
01181   _proxyList.Remove(&proxy) ;
01182 }
01183 
01184 
01185 
01186 //_____________________________________________________________________________
01187 RooAbsProxy* RooAbsArg::getProxy(Int_t index) const
01188 {
01189   // Return the nth proxy from the proxy list.
01190 
01191   // Cross cast: proxy list returns TObject base pointer, we need
01192   // a RooAbsProxy base pointer. C++ standard requires
01193   // a dynamic_cast for this.
01194   return dynamic_cast<RooAbsProxy*> (_proxyList.At(index)) ;
01195 }
01196 
01197 
01198 
01199 //_____________________________________________________________________________
01200 Int_t RooAbsArg::numProxies() const
01201 {
01202   // Return the number of registered proxies.
01203 
01204   return _proxyList.GetSize() ;
01205 }
01206 
01207 
01208 
01209 //_____________________________________________________________________________
01210 void RooAbsArg::setProxyNormSet(const RooArgSet* nset)
01211 {
01212   // Forward a change in the cached normalization argset
01213   // to all the registered proxies.
01214 
01215   for (int i=0 ; i<numProxies() ; i++) {
01216     getProxy(i)->changeNormSet(nset) ;
01217   }
01218 }
01219 
01220 
01221 
01222 //_____________________________________________________________________________
01223 void RooAbsArg::attachToTree(TTree& ,Int_t)
01224 {
01225   // Overloadable function for derived classes to implement
01226   // attachment as branch to a TTree
01227 
01228   coutE(Contents) << "RooAbsArg::attachToTree(" << GetName()
01229                   << "): Cannot be attached to a TTree" << endl ;
01230 }
01231 
01232 
01233 
01234 //_____________________________________________________________________________
01235 Bool_t RooAbsArg::isValid() const
01236 {
01237   // WVE (08/21/01) Probably obsolete now
01238   return kTRUE ;
01239 }
01240 
01241 
01242 
01243 //_____________________________________________________________________________
01244 void RooAbsArg::copyList(TList& dest, const TList& source)
01245 {
01246   // WVE (08/21/01) Probably obsolete now
01247   dest.Clear() ;
01248 
01249   TIterator* sIter = source.MakeIterator() ;
01250   TObject* obj ;
01251   while ((obj = sIter->Next())) {
01252     dest.Add(obj) ;
01253   }
01254   delete sIter ;
01255 }
01256 
01257 
01258 
01259 //_____________________________________________________________________________
01260 void RooAbsArg::printName(ostream& os) const
01261 {
01262   // Print object name
01263 
01264   os << GetName() ;
01265 }
01266 
01267 
01268 
01269 //_____________________________________________________________________________
01270 void RooAbsArg::printTitle(ostream& os) const
01271 {
01272   // Print object title
01273   os << GetTitle() ;
01274 }
01275 
01276 
01277 
01278 //_____________________________________________________________________________
01279 void RooAbsArg::printClassName(ostream& os) const
01280 {
01281   // Print object class name
01282   os << IsA()->GetName() ;
01283 }
01284 
01285 
01286 void RooAbsArg::printAddress(ostream& os) const
01287 {
01288   // Print addrss of this RooAbsArg
01289   os << this ;
01290 }
01291 
01292 
01293 
01294 //_____________________________________________________________________________
01295 void RooAbsArg::printArgs(ostream& os) const
01296 {
01297   // Print object arguments, ie its proxies
01298 
01299   // Print nothing if there are no dependencies
01300   if (numProxies()==0) return ;
01301 
01302   os << "[ " ;
01303   for (Int_t i=0 ; i<numProxies() ; i++) {
01304     RooAbsProxy* p = getProxy(i) ;
01305     if (!TString(p->name()).BeginsWith("!")) {
01306       p->print(os) ;
01307       os << " " ;
01308     }
01309   }
01310   printMetaArgs(os) ;
01311   os << "]" ;
01312 }
01313 
01314 
01315 
01316 //_____________________________________________________________________________
01317 Int_t RooAbsArg::defaultPrintContents(Option_t* /*opt*/) const
01318 {
01319   // Define default contents to print
01320   return kName|kClassName|kValue|kArgs ;
01321 }
01322 
01323 
01324 
01325 //_____________________________________________________________________________
01326 void RooAbsArg::printMultiline(ostream& os, Int_t /*contents*/, Bool_t /*verbose*/, TString indent) const
01327 {
01328   // Implement multi-line detailed printing
01329 
01330   os << indent << "--- RooAbsArg ---" << endl;
01331   // dirty state flags
01332   os << indent << "  Value State: " ;
01333   switch(_operMode) {
01334   case ADirty: os << "FORCED DIRTY" ; break ;
01335   case AClean: os << "FORCED clean" ; break ;
01336   case Auto: os << (isValueDirty() ? "DIRTY":"clean") ; break ;
01337   }
01338   os << endl
01339      << indent << "  Shape State: " << (isShapeDirty() ? "DIRTY":"clean") << endl;
01340   // attribute list
01341   os << indent << "  Attributes: " ;
01342   printAttribList(os) ;
01343   os << endl ;
01344   // our memory address (for x-referencing with client addresses of other args)
01345   os << indent << "  Address: " << (void*)this << endl;
01346   // client list
01347   os << indent << "  Clients: " << endl;
01348   TIterator *clientIter= _clientList.MakeIterator();
01349   RooAbsArg* client ;
01350   while ((client=(RooAbsArg*)clientIter->Next())) {
01351     os << indent << "    (" << (void*)client  << ","
01352        << (_clientListValue.FindObject(client)?"V":"-")
01353        << (_clientListShape.FindObject(client)?"S":"-")
01354        << ") " ;
01355     client->printStream(os,kClassName|kTitle|kName,kSingleLine);
01356   }
01357   delete clientIter;
01358 
01359   // server list
01360   os << indent << "  Servers: " << endl;
01361   TIterator *serverIter= _serverList.MakeIterator();
01362   RooAbsArg* server ;
01363   while ((server=(RooAbsArg*)serverIter->Next())) {
01364     os << indent << "    (" << (void*)server << ","
01365        << (server->_clientListValue.FindObject((TObject*)this)?"V":"-")
01366        << (server->_clientListShape.FindObject((TObject*)this)?"S":"-")
01367        << ") " ;
01368     server->printStream(os,kClassName|kName|kTitle,kSingleLine);
01369   }
01370   delete serverIter;
01371 
01372   // proxy list
01373   os << indent << "  Proxies: " << endl ;
01374   for (int i=0 ; i<numProxies() ; i++) {
01375     RooAbsProxy* proxy=getProxy(i) ;
01376 
01377     if (proxy->IsA()->InheritsFrom(RooArgProxy::Class())) {
01378       os << indent << "    " << proxy->name() << " -> " ;
01379       RooAbsArg* parg = ((RooArgProxy*)proxy)->absArg() ;
01380       if (parg) {
01381         parg->printStream(os,kName,kSingleLine) ;
01382       } else {
01383         os << " (empty)" << endl ; ;
01384       }
01385     } else {
01386       os << indent << "    " << proxy->name() << " -> " ;
01387       os << endl ;
01388       TString moreIndent(indent) ;
01389       moreIndent.Append("    ") ;
01390       ((RooSetProxy*)proxy)->printStream(os,kName,kStandard,moreIndent.Data()) ;
01391     }
01392   }
01393 }
01394 
01395 
01396 //_____________________________________________________________________________
01397 void RooAbsArg::printTree(ostream& os, TString /*indent*/) const
01398 {
01399   // Print object tree structure
01400   const_cast<RooAbsArg*>(this)->printCompactTree(os) ;
01401 }
01402 
01403 
01404 //_____________________________________________________________________________
01405 ostream& operator<<(ostream& os, RooAbsArg &arg)
01406 {
01407   // Ostream operator
01408   arg.writeToStream(os,kTRUE) ;
01409   return os ;
01410 }
01411 
01412 //_____________________________________________________________________________
01413 istream& operator>>(istream& is, RooAbsArg &arg)
01414 {
01415   // Istream operator
01416   arg.readFromStream(is,kTRUE,kFALSE) ;
01417   return is ;
01418 }
01419 
01420 //_____________________________________________________________________________
01421 void RooAbsArg::printAttribList(ostream& os) const
01422 {
01423   // Print the attribute list
01424 
01425   set<string>::const_iterator iter = _boolAttrib.begin() ;
01426   Bool_t first(kTRUE) ;
01427   while (iter != _boolAttrib.end()) {
01428     os << (first?" [":",") << *iter ;
01429     first=kFALSE ;
01430     ++iter ;
01431   }
01432   if (!first) os << "] " ;
01433 }
01434 
01435 //_____________________________________________________________________________
01436 void RooAbsArg::attachDataSet(const RooAbsData &data)
01437 {
01438   // Replace server nodes with names matching the dataset variable names
01439   // with those data set variables, making this PDF directly dependent on the dataset
01440 
01441   const RooArgSet* set = data.get() ;
01442   RooArgSet branches ;
01443   branchNodeServerList(&branches,0,kTRUE) ;
01444 
01445   TIterator* iter = branches.createIterator() ;
01446   RooAbsArg* branch ;
01447   while((branch=(RooAbsArg*)iter->Next())) {
01448     branch->redirectServers(*set,kFALSE,kFALSE) ;
01449   }
01450   delete iter ;
01451 }
01452 
01453 
01454 
01455 //_____________________________________________________________________________
01456 void RooAbsArg::attachDataStore(const RooAbsDataStore &dstore)
01457 {
01458   // Replace server nodes with names matching the dataset variable names
01459   // with those data set variables, making this PDF directly dependent on the dataset
01460 
01461   const RooArgSet* set = dstore.get() ;
01462   RooArgSet branches ;
01463   branchNodeServerList(&branches,0,kTRUE) ;
01464 
01465   TIterator* iter = branches.createIterator() ;
01466   RooAbsArg* branch ;
01467   while((branch=(RooAbsArg*)iter->Next())) {
01468     branch->redirectServers(*set,kFALSE,kFALSE) ;
01469   }
01470   delete iter ;
01471 }
01472 
01473 
01474 
01475 //_____________________________________________________________________________
01476 Int_t RooAbsArg::Compare(const TObject* other) const
01477 {
01478   // Utility function used by TCollection::Sort to compare contained TObjects
01479   // We implement comparison by name, resulting in alphabetical sorting by object name.
01480 
01481   return strcmp(GetName(),other->GetName()) ;
01482 }
01483 
01484 
01485 
01486 //_____________________________________________________________________________
01487 void RooAbsArg::printDirty(Bool_t depth) const
01488 {
01489   // Print information about current value dirty state information.
01490   // If depth flag is true, information is recursively printed for
01491   // all nodes in this arg tree.
01492 
01493   if (depth) {
01494 
01495     RooArgSet branchList ;
01496     branchNodeServerList(&branchList) ;
01497     TIterator* bIter = branchList.createIterator() ;
01498     RooAbsArg* branch ;
01499     while((branch=(RooAbsArg*)bIter->Next())) {
01500       branch->printDirty(kFALSE) ;
01501     }
01502 
01503   } else {
01504     cout << GetName() << " : " ;
01505     switch (_operMode) {
01506     case AClean: cout << "FORCED clean" ; break ;
01507     case ADirty: cout << "FORCED DIRTY" ; break ;
01508     case Auto:   cout << "Auto  " << (isValueDirty()?"DIRTY":"clean") ;
01509     }
01510     cout << endl ;
01511   }
01512 }
01513 
01514 
01515 //_____________________________________________________________________________
01516 void RooAbsArg::optimizeCacheMode(const RooArgSet& observables)
01517 {
01518   // Activate cache mode optimization with given definition of observables.
01519   // The cache operation mode of all objects in the expression tree will
01520   // modified such that all nodes that depend directly or indirectly on
01521   // any of the listed observables will be set to ADirty, as they are
01522   // expected to change every time. This save change tracking overhead for
01523   // nodes that are a priori known to change every time
01524 
01525   RooLinkedList proc;
01526   RooArgSet opt ;
01527   optimizeCacheMode(observables,opt,proc) ;
01528 
01529   coutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") nodes " << opt << " depend on observables, "
01530                         << "changing cache operation mode from change tracking to unconditional evaluation" << endl ;
01531 }
01532 
01533 
01534 //_____________________________________________________________________________
01535 void RooAbsArg::optimizeCacheMode(const RooArgSet& observables, RooArgSet& optimizedNodes, RooLinkedList& processedNodes)
01536 {
01537   // Activate cache mode optimization with given definition of observables.
01538   // The cache operation mode of all objects in the expression tree will
01539   // modified such that all nodes that depend directly or indirectly on
01540   // any of the listed observables will be set to ADirty, as they are
01541   // expected to change every time. This save change tracking overhead for
01542   // nodes that are a priori known to change every time
01543 
01544   // Optimization applies only to branch nodes, not to leaf nodes
01545   if (!isDerived()) {
01546     return ;
01547   }
01548 
01549 
01550   // Terminate call if this node was already processed (tree structure may be cyclical)
01551   if (processedNodes.FindObject(this)) {
01552     return ;
01553   } else {
01554     processedNodes.Add(this) ;
01555   }
01556 
01557   // Set cache mode operator to 'AlwaysDirty' if we depend on any of the given observables
01558   if (dependsOnValue(observables)) {
01559 
01560     if (dynamic_cast<RooRealIntegral*>(this)) {
01561       cxcoutI(Integration) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") integral depends on value of one or more observables and will be evaluated for every event" << endl ;
01562     }
01563     optimizedNodes.add(*this,kTRUE) ;
01564     if (operMode()==AClean) {
01565     } else {
01566       setOperMode(ADirty,kTRUE) ; // WVE propagate flag recursively to top of tree
01567     }
01568   } else {
01569   }
01570   // Process any RooAbsArgs contained in any of the caches of this object
01571   for (Int_t i=0 ;i<numCaches() ; i++) {
01572     getCache(i)->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
01573   }
01574 
01575   // Forward calls to all servers
01576   TIterator* sIter = serverIterator() ;
01577   RooAbsArg* server ;
01578   while((server=(RooAbsArg*)sIter->Next())) {
01579     server->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
01580   }
01581   delete sIter ;
01582 
01583 }
01584 
01585 //_____________________________________________________________________________
01586 Bool_t RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList)
01587 {
01588   // Find branch nodes with all-constant parameters, and add them to the list of
01589   // nodes that can be cached with a dataset in a test statistic calculation
01590 
01591   RooLinkedList proc ;
01592   Bool_t ret = findConstantNodes(observables,cacheList,proc) ;
01593 
01594   // If node can be optimized and hasn't been identified yet, add it to the list
01595   coutI(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << "): components "
01596                         << cacheList << " depend exclusively on constant parameters and will be precalculated and cached" << endl ;
01597 
01598   return ret ;
01599 }
01600 
01601 
01602 
01603 //_____________________________________________________________________________
01604 Bool_t RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList, RooLinkedList& processedNodes)
01605 {
01606   // Find branch nodes with all-constant parameters, and add them to the list of
01607   // nodes that can be cached with a dataset in a test statistic calculation
01608 
01609   // Caching only applies to branch nodes
01610   if (!isDerived()) {
01611     return kFALSE;
01612   }
01613 
01614   // Terminate call if this node was already processed (tree structure may be cyclical)
01615   if (processedNodes.FindObject(this)) {
01616     return kFALSE ;
01617   } else {
01618     processedNodes.Add(this) ;
01619   }
01620 
01621   // Check if node depends on any non-constant parameter
01622   Bool_t canOpt(kTRUE) ;
01623   RooArgSet* paramSet = getParameters(observables) ;
01624   TIterator* iter = paramSet->createIterator() ;
01625   RooAbsArg* param ;
01626   while((param = (RooAbsArg*)iter->Next())) {
01627     if (!param->isConstant()) {
01628       canOpt=kFALSE ;
01629       break ;
01630     }
01631   }
01632   delete iter ;
01633   delete paramSet ;
01634 
01635   // If yes, list node eligible for caching, if not test nodes one level down
01636   if (canOpt) {
01637 
01638     if (!cacheList.find(GetName()) && dependsOnValue(observables) && !observables.find(GetName()) ) {
01639 
01640       // Add to cache list
01641       cxcoutD(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << ") adding self to list of constant nodes" << endl ;
01642 
01643       cacheList.add(*this,kFALSE) ;
01644     }
01645 
01646   } else {
01647 
01648     // If not, see if next level down can be cached
01649     TIterator* sIter = serverIterator() ;
01650     RooAbsArg* server ;
01651     while((server=(RooAbsArg*)sIter->Next())) {
01652       if (server->isDerived()) {
01653         server->findConstantNodes(observables,cacheList,processedNodes) ;
01654       }
01655     }
01656     delete sIter ;
01657   }
01658 
01659   // Forward call to all cached contained in current object
01660   for (Int_t i=0 ;i<numCaches() ; i++) {
01661     getCache(i)->findConstantNodes(observables,cacheList,processedNodes) ;
01662   }
01663 
01664   return kFALSE ;
01665 }
01666 
01667 
01668 
01669 
01670 //_____________________________________________________________________________
01671 void RooAbsArg::constOptimizeTestStatistic(ConstOpCode opcode)
01672 {
01673   // Interface function signaling a request to perform constant term
01674   // optimization. This default implementation takes no action other than to
01675   // forward the calls to all servers
01676 
01677   TIterator* sIter = serverIterator() ;
01678   RooAbsArg* server ;
01679   while((server=(RooAbsArg*)sIter->Next())) {
01680     server->constOptimizeTestStatistic(opcode) ;
01681   }
01682   delete sIter ;
01683 }
01684 
01685 
01686 //_____________________________________________________________________________
01687 void RooAbsArg::setOperMode(OperMode mode, Bool_t recurseADirty)
01688 {
01689   // Change cache operation mode to given mode. If recurseAdirty
01690   // is true, then a mode change to AlwaysDirty will automatically
01691   // be propagated recursively to all client nodes
01692 
01693   // Prevent recursion loops
01694   if (mode==_operMode) return ;
01695 
01696   _operMode = mode ;
01697   for (Int_t i=0 ;i<numCaches() ; i++) {
01698     getCache(i)->operModeHook() ;
01699   }
01700   operModeHook() ;
01701 
01702   // Propagate to all clients
01703   if (mode==ADirty && recurseADirty) {
01704     TIterator* iter = valueClientIterator() ;
01705     RooAbsArg* client ;
01706     while((client=(RooAbsArg*)iter->Next())) {
01707       client->setOperMode(mode) ;
01708     }
01709     delete iter ;
01710   }
01711 }
01712 
01713 
01714 //_____________________________________________________________________________
01715 void RooAbsArg::printCompactTree(const char* indent, const char* filename, const char* namePat, RooAbsArg* client)
01716 {
01717   // Print tree structure of expression tree on stdout, or to file if filename is specified.
01718   // If namePat is not "*", only nodes with names matching the pattern will be printed.
01719   // The client argument is used in recursive calls to properly display the value or shape nature
01720   // of the client-server links. It should be zero in calls initiated by users.
01721 
01722   if (filename) {
01723     ofstream ofs(filename) ;
01724     printCompactTree(ofs,indent,namePat,client) ;
01725   } else {
01726     printCompactTree(cout,indent,namePat,client) ;
01727   }
01728 }
01729 
01730 
01731 //_____________________________________________________________________________
01732 void RooAbsArg::printCompactTree(ostream& os, const char* indent, const char* namePat, RooAbsArg* client)
01733 {
01734   // Print tree structure of expression tree on given ostream.
01735   // If namePat is not "*", only nodes with names matching the pattern will be printed.
01736   // The client argument is used in recursive calls to properly display the value or shape nature
01737   // of the client-server links. It should be zero in calls initiated by users.
01738 
01739   if ( !namePat || TString(GetName()).Contains(namePat)) {
01740     os << indent << this ;
01741     if (client) {
01742       os << "/" ;
01743       if (isValueServer(*client)) os << "V" ; else os << "-" ;
01744       if (isShapeServer(*client)) os << "S" ; else os << "-" ;
01745     }
01746     os << " " ;
01747 
01748     os << IsA()->GetName() << "::" << GetName() <<  " = " ;
01749     printValue(os) ;
01750 
01751     if (_serverList.GetSize()>0) {
01752       switch(operMode()) {
01753       case Auto:   os << " [Auto] "  ; break ;
01754       case AClean: os << " [ACLEAN] " ; break ;
01755       case ADirty: os << " [ADIRTY] " ; break ;
01756       }
01757     }
01758     os << endl ;
01759 
01760     for (Int_t i=0 ;i<numCaches() ; i++) {
01761       getCache(i)->printCompactTreeHook(os,indent) ;
01762     }
01763     printCompactTreeHook(os,indent) ;
01764   }
01765 
01766   TString indent2(indent) ;
01767   indent2 += "  " ;
01768   TIterator * iter = serverIterator() ;
01769   RooAbsArg* arg ;
01770   while((arg=(RooAbsArg*)iter->Next())) {
01771     arg->printCompactTree(os,indent2,namePat,this) ;
01772   }
01773   delete iter ;
01774 }
01775 
01776 
01777 //_____________________________________________________________________________
01778 void RooAbsArg::printComponentTree(const char* indent, const char* namePat, Int_t nLevel)
01779 {
01780   // Print tree structure of expression tree on given ostream, only branch nodes are printed.
01781   // Lead nodes (variables) will not be shown
01782   //
01783   // If namePat is not "*", only nodes with names matching the pattern will be printed.
01784 
01785   if (nLevel==0) return ;
01786   if (isFundamental()) return ;
01787   RooResolutionModel* rmodel = dynamic_cast<RooResolutionModel*>(this) ;
01788   if (rmodel && rmodel->isConvolved()) return ;
01789   if (InheritsFrom("RooConstVar")) return ;
01790 
01791   if ( !namePat || TString(GetName()).Contains(namePat)) {
01792     cout << indent ;
01793     Print() ;
01794   }
01795 
01796   TString indent2(indent) ;
01797   indent2 += "  " ;
01798   TIterator * iter = serverIterator() ;
01799   RooAbsArg* arg ;
01800   while((arg=(RooAbsArg*)iter->Next())) {
01801     arg->printComponentTree(indent2.Data(),namePat,nLevel-1) ;
01802   }
01803   delete iter ;
01804 }
01805 
01806 
01807 //_____________________________________________________________________________
01808 TString RooAbsArg::cleanBranchName() const
01809 {
01810   // Construct a mangled name from the actual name that
01811   // is free of any math symbols that might be interpreted by TTree
01812 
01813   // Check for optional alternate name of branch for this argument
01814   TString rawBranchName = GetName() ;
01815   if (getStringAttribute("BranchName")) {
01816     rawBranchName = getStringAttribute("BranchName") ;
01817   }
01818 
01819   TString cleanName(rawBranchName) ;
01820   cleanName.ReplaceAll("/","D") ;
01821   cleanName.ReplaceAll("-","M") ;
01822   cleanName.ReplaceAll("+","P") ;
01823   cleanName.ReplaceAll("*","X") ;
01824   cleanName.ReplaceAll("[","L") ;
01825   cleanName.ReplaceAll("]","R") ;
01826   cleanName.ReplaceAll("(","L") ;
01827   cleanName.ReplaceAll(")","R") ;
01828   cleanName.ReplaceAll("{","L") ;
01829   cleanName.ReplaceAll("}","R") ;
01830 
01831   if (cleanName.Length()<=60) return cleanName ;
01832 
01833   // Name is too long, truncate and include CRC32 checksum of full name in clean name
01834   static char buf[1024] ;
01835   strlcpy(buf,cleanName.Data(),1024) ;
01836   snprintf(buf+46,1024-46,"_CRC%08x",crc32(cleanName.Data())) ;
01837 
01838   return TString(buf) ;
01839 }
01840 
01841 
01842 
01843 
01844 
01845 UInt_t RooAbsArg::crc32(const char* data)
01846 {
01847   // Calculate crc32 checksum on given string
01848 
01849   // Calculate and extract length of string
01850   Int_t len = strlen(data) ;
01851   if (len<4) {
01852     oocoutE((RooAbsArg*)0,InputArguments) << "RooAbsReal::crc32 cannot calculate checksum of less than 4 bytes of data" << endl ;
01853     return 0 ;
01854   }
01855 
01856   // Initialize CRC table on first use
01857   static Bool_t init(kFALSE) ;
01858   static unsigned int crctab[256];
01859   if (!init) {
01860     int i, j;
01861     unsigned int crc;
01862     for (i = 0; i < 256; i++){
01863       crc = i << 24;
01864       for (j = 0; j < 8; j++) {
01865         if (crc & 0x80000000) {
01866           crc = (crc << 1) ^ 0x04c11db7 ;
01867         } else {
01868           crc = crc << 1;
01869         }
01870       }
01871       crctab[i] = crc;
01872     }
01873     init = kTRUE ;
01874   }
01875 
01876   unsigned int        result(0);
01877   int                 i(0);
01878 
01879   result = *data++ << 24;
01880   result |= *data++ << 16;
01881   result |= *data++ << 8;
01882   result |= *data++;
01883   result = ~ result;
01884   len -=4;
01885 
01886   for (i=0; i<len; i++) {
01887     result = (result << 8 | *data++) ^ crctab[result >> 24];
01888   }
01889 
01890   return ~result;
01891 }
01892 
01893 
01894 //_____________________________________________________________________________
01895 void RooAbsArg::printCompactTreeHook(ostream&, const char *)
01896 {
01897   // Hook function interface for object to insert additional information
01898   // when printed in the context of a tree structure. This default
01899   // implementation prints nothing
01900 }
01901 
01902 
01903 //_____________________________________________________________________________
01904 void RooAbsArg::registerCache(RooAbsCache& cache)
01905 {
01906   // Register RooAbsCache with this object. This function is called
01907   // by RooAbsCache constructors for objects that are a datamember
01908   // of this RooAbsArg. By registering itself the RooAbsArg is aware
01909   // of all its cache data members and will forward server change
01910   // and cache mode change calls to the cache objects, which in turn
01911   // can forward them their contents
01912 
01913   _cacheList.push_back(&cache) ;
01914 }
01915 
01916 
01917 //_____________________________________________________________________________
01918 void RooAbsArg::unRegisterCache(RooAbsCache& cache)
01919 {
01920   // Unregister a RooAbsCache. Called from the RooAbsCache destructor
01921   std::remove(_cacheList.begin(), _cacheList.end(), &cache);
01922 }
01923 
01924 
01925 //_____________________________________________________________________________
01926 Int_t RooAbsArg::numCaches() const
01927 {
01928   // Return number of registered caches
01929 
01930   return _cacheList.size() ;
01931 }
01932 
01933 
01934 //_____________________________________________________________________________
01935 RooAbsCache* RooAbsArg::getCache(Int_t index) const
01936 {
01937   // Return registered cache object by index
01938 
01939   return _cacheList[index] ;
01940 }
01941 
01942 
01943 //_____________________________________________________________________________
01944 RooArgSet* RooAbsArg::getVariables(Bool_t stripDisconnected) const
01945 {
01946   // Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
01947 
01948   return getParameters(RooArgSet(),stripDisconnected) ;
01949 }
01950 
01951 
01952 //_____________________________________________________________________________
01953 RooLinkedList RooAbsArg::getCloningAncestors() const
01954 {
01955   // Return ancestors in cloning chain of this RooAbsArg. NOTE: Returned pointers
01956   // are not guaranteed to be 'live', so do not dereference without proper caution
01957 
01958   RooLinkedList retVal ;
01959 
01960   set<string>::const_iterator iter= _boolAttrib.begin() ;
01961   while(iter != _boolAttrib.end()) {
01962     if (TString(*iter).BeginsWith("CloneOf(")) {
01963       char buf[128] ;
01964       strlcpy(buf,iter->c_str(),128) ;
01965       strtok(buf,"(") ;
01966       char* ptrToken = strtok(0,")") ;
01967       RooAbsArg* ptr = (RooAbsArg*) strtol(ptrToken,0,16) ;
01968       retVal.Add(ptr) ;
01969     }
01970   }
01971 
01972   return retVal ;
01973 }
01974 
01975 
01976 //_____________________________________________________________________________
01977 void RooAbsArg::graphVizTree(const char* fileName, const char* delimiter, bool useTitle, bool useLatex)
01978 {
01979   // Create a GraphViz .dot file visualizing the expression tree headed by
01980   // this RooAbsArg object. Use the GraphViz tool suite to make e.g. a gif
01981   // or ps file from the .dot file
01982   //
01983   // Based on concept developed by Kyle Cranmer
01984 
01985   ofstream ofs(fileName) ;
01986   if (!ofs) {
01987     coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: Cannot open graphViz output file with name " << fileName << endl ;
01988     return ;
01989   }
01990   graphVizTree(ofs, delimiter, useTitle, useLatex) ;
01991 }
01992 
01993 //_____________________________________________________________________________
01994 void RooAbsArg::graphVizTree(ostream& os, const char* delimiter, bool useTitle, bool useLatex)
01995 {
01996   // Write the GraphViz representation of the expression tree headed by
01997   // this RooAbsArg object to the given ostream.
01998   //
01999   // Based on concept developed by Kyle Cranmer
02000 
02001   if (!os) {
02002     coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: output stream provided as input argument is in invalid state" << endl ;
02003   }
02004 
02005   // Write header
02006   os << "digraph " << GetName() << "{" << endl ;
02007 
02008   // First list all the tree nodes
02009   RooArgSet nodeSet ;
02010   treeNodeServerList(&nodeSet) ;
02011   TIterator* iter = nodeSet.createIterator() ;
02012   RooAbsArg* node ;
02013 
02014   // iterate over nodes
02015   while((node=(RooAbsArg*)iter->Next())) {
02016     string nodeName = node->GetName();
02017     string nodeTitle = node->GetTitle();
02018     string nodeLabel = (useTitle && !nodeTitle.empty()) ? nodeTitle : nodeName;
02019 
02020     // if using latex, replace ROOT's # with normal latex backslash
02021     string::size_type position = nodeLabel.find("#") ;
02022     while(useLatex && position!=nodeLabel.npos){
02023       nodeLabel.replace(position, 1, "\\");
02024     }
02025 
02026     string typeFormat = "\\texttt{";
02027     string nodeType = (useLatex) ? typeFormat+node->IsA()->GetName()+"}" : node->IsA()->GetName();
02028 
02029     os << "\"" << nodeName << "\" [ color=" << (node->isFundamental()?"blue":"red")
02030        << ", label=\"" << nodeType << delimiter << nodeLabel << "\"];" << endl ;
02031 
02032   }
02033   delete iter ;
02034 
02035   // Get set of all server links
02036   set<pair<RooAbsArg*,RooAbsArg*> > links ;
02037   graphVizAddConnections(links) ;
02038 
02039   // And write them out
02040   set<pair<RooAbsArg*,RooAbsArg*> >::iterator liter = links.begin() ;
02041   for( ; liter != links.end() ; ++liter ) {
02042     os << "\"" << liter->first->GetName() << "\" -> \"" << liter->second->GetName() << "\";" << endl ;
02043   }
02044 
02045   // Write trailer
02046   os << "}" << endl ;
02047 
02048 }
02049 
02050 //_____________________________________________________________________________
02051 void RooAbsArg::graphVizAddConnections(set<pair<RooAbsArg*,RooAbsArg*> >& linkSet)
02052 {
02053   // Utility function that inserts all point-to-point client-server connections
02054   // between any two RooAbsArgs in the expression tree headed by this object
02055   // in the linkSet argument.
02056 
02057   TIterator* sIter = serverIterator() ;
02058   RooAbsArg* server ;
02059   while((server=(RooAbsArg*)sIter->Next())) {
02060     linkSet.insert(make_pair(this,server)) ;
02061     server->graphVizAddConnections(linkSet) ;
02062   }
02063   delete sIter ;
02064 }
02065 
02066 
02067 
02068 // //_____________________________________________________________________________
02069 // TGraphStruct* RooAbsArg::graph(Bool_t useFactoryTag, Double_t textSize)
02070 // {
02071 //   // Return a TGraphStruct object filled with the tree structure of the pdf object
02072 
02073 //   TGraphStruct* theGraph = new TGraphStruct() ;
02074 
02075 //   // First list all the tree nodes
02076 //   RooArgSet nodeSet ;
02077 //   treeNodeServerList(&nodeSet) ;
02078 //   TIterator* iter = nodeSet.createIterator() ;
02079 //   RooAbsArg* node ;
02080 
02081 
02082 //   // iterate over nodes
02083 //   while((node=(RooAbsArg*)iter->Next())) {
02084 
02085 //     // Skip node that represent numeric constants
02086 //     if (node->IsA()->InheritsFrom(RooConstVar::Class())) continue ;
02087 
02088 //     string nodeName ;
02089 //     if (useFactoryTag && node->getStringAttribute("factory_tag")) {
02090 //       nodeName  = node->getStringAttribute("factory_tag") ;
02091 //     } else {
02092 //       if (node->isFundamental()) {
02093 //      nodeName = node->GetName();
02094 //       } else {
02095 //      ostringstream oss ;
02096 //      node->printStream(oss,(node->defaultPrintContents(0)&(~kValue)),node->defaultPrintStyle(0)) ;
02097 //      nodeName= oss.str() ;
02098 // //   nodeName = Form("%s::%s",node->IsA()->GetName(),node->GetName());
02099 
02100 //       }
02101 //     }
02102 //     if (strncmp(nodeName.c_str(),"Roo",3)==0) {
02103 //       nodeName = string(nodeName.c_str()+3) ;
02104 //     }
02105 //     node->setStringAttribute("graph_name",nodeName.c_str()) ;
02106 
02107 //     TGraphNode* gnode = theGraph->AddNode(nodeName.c_str(),nodeName.c_str()) ;
02108 //     gnode->SetLineWidth(2) ;
02109 //     gnode->SetTextColor(node->isFundamental()?kBlue:kRed) ;
02110 //     gnode->SetTextSize(textSize) ;
02111 //   }
02112 //   delete iter ;
02113 
02114 //   // Get set of all server links
02115 //   set<pair<RooAbsArg*,RooAbsArg*> > links ;
02116 //   graphVizAddConnections(links) ;
02117 
02118 //   // And insert them into the graph
02119 //   set<pair<RooAbsArg*,RooAbsArg*> >::iterator liter = links.begin() ;
02120 //   for( ; liter != links.end() ; ++liter ) {
02121 
02122 //     TGraphNode* n1 = (TGraphNode*)theGraph->GetListOfNodes()->FindObject(liter->first->getStringAttribute("graph_name")) ;
02123 //     TGraphNode* n2 = (TGraphNode*)theGraph->GetListOfNodes()->FindObject(liter->second->getStringAttribute("graph_name")) ;
02124 //     if (n1 && n2) {
02125 //       TGraphEdge* edge = theGraph->AddEdge(n1,n2) ;
02126 //       edge->SetLineWidth(2) ;
02127 //     }
02128 //   }
02129 
02130 //   return theGraph ;
02131 // }
02132 
02133 
02134 
02135 //_____________________________________________________________________________
02136 Bool_t RooAbsArg::inhibitDirty()
02137 {
02138   // Return current status of the inhibitDirty global flag. If true
02139   // no dirty state change tracking occurs and all caches are considered
02140   // to be always dirty.
02141   return _inhibitDirty ;
02142 }
02143 
02144 
02145 //_____________________________________________________________________________
02146 Bool_t RooAbsArg::addOwnedComponents(const RooArgSet& comps)
02147 {
02148   // Take ownership of the contents of 'comps'
02149 
02150   if (!_ownedComponents) {
02151     _ownedComponents = new RooArgSet("owned components") ;
02152   }
02153   return _ownedComponents->addOwned(comps) ;
02154 }
02155 
02156 
02157 
02158 //_____________________________________________________________________________
02159 RooAbsArg* RooAbsArg::cloneTree(const char* newname) const
02160 {
02161   // Clone tree expression of objects. All tree nodes will be owned by
02162   // the head node return by cloneTree()
02163 
02164   // Clone tree using snapshot
02165   RooArgSet* clonedNodes = (RooArgSet*) RooArgSet(*this).snapshot(kTRUE) ;
02166 
02167   // Find the head node in the cloneSet
02168   RooAbsArg* head = clonedNodes->find(GetName()) ;
02169 
02170   // Remove the head node from the cloneSet
02171   // To release it from the set ownership
02172   clonedNodes->remove(*head) ;
02173 
02174   // Add the set as owned component of the head
02175   head->addOwnedComponents(*clonedNodes) ;
02176 
02177   // Delete intermediate container
02178   clonedNodes->releaseOwnership() ;
02179   delete clonedNodes ;
02180 
02181   // Adjust name of head node if requested
02182   if (newname) {
02183     head->SetName(newname) ;
02184   }
02185 
02186   // Return the head
02187   return head ;
02188 }
02189 
02190 
02191 
02192 //_____________________________________________________________________________
02193 RooExpensiveObjectCache& RooAbsArg::expensiveObjectCache() const
02194 {
02195   if (_eocache) {
02196     return *_eocache ;
02197   } else {
02198     return RooExpensiveObjectCache::instance() ;
02199   }
02200 }
02201 
02202 
02203 
02204 //_____________________________________________________________________________
02205 Bool_t RooAbsArg::flipAClean()
02206 {
02207   return _flipAClean ;
02208 }
02209 
02210 
02211 
02212 //_____________________________________________________________________________
02213 const char* RooAbsArg::aggregateCacheUniqueSuffix() const
02214 {
02215   string suffix ;
02216 
02217   RooArgSet branches ;
02218   branchNodeServerList(&branches) ;
02219   TIterator* iter = branches.createIterator( );
02220   RooAbsArg* arg ;
02221   while((arg=(RooAbsArg*)iter->Next())) {
02222     const char* tmp = arg->cacheUniqueSuffix() ;
02223     if (tmp) suffix += tmp ;
02224   }
02225   delete iter ;
02226   return Form("%s",suffix.c_str()) ;
02227 }

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