Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooAbsArg.cxx
Go to the documentation of this file.
1 /******************************************************
2  * Project: RooFit *
3  * Package: RooFitCore *
4  * @(#)root/roofitcore:$Id$
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2005, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 //////////////////////////////////////////////////////////////////////////////
18 /** \class RooAbsArg
19  \ingroup Roofitcore
20 
21 RooAbsArg is the common abstract base class for objects that
22 represent a value (of arbitrary type) and "shape" that in general
23 depends on (is a client of) other RooAbsArg subclasses. The only
24 state information about a value that is maintained in this base
25 class consists of named attributes and flags that track when either
26 the value or the shape of this object changes. The meaning of shape
27 depends on the client implementation but could be, for example, the
28 allowed range of a value. The base class is also responsible for
29 managing client/server links and propagating value/shape changes
30 through an expression tree. RooAbsArg implements public interfaces
31 for inspecting client/server relationships and
32 setting/clearing/testing named attributes.
33 
34 */
35 
36 #include "RooFit.h"
37 #include "Riostream.h"
38 
39 #include "TBuffer.h"
40 #include "TClass.h"
41 #include "TObjString.h"
42 #include "TVirtualStreamerInfo.h"
43 // #include "TGraphStruct.h"
44 
45 #include "RooSecondMoment.h"
46 #include "RooNameSet.h"
47 #include "RooWorkspace.h"
48 
49 #include "RooMsgService.h"
50 #include "RooAbsArg.h"
51 #include "RooArgSet.h"
52 #include "RooArgProxy.h"
53 #include "RooSetProxy.h"
54 #include "RooListProxy.h"
55 #include "RooAbsData.h"
56 #include "RooAbsCategoryLValue.h"
57 #include "RooAbsRealLValue.h"
58 #include "RooTrace.h"
59 #include "RooStringVar.h"
60 #include "RooRealIntegral.h"
61 #include "RooConstVar.h"
62 #include "RooMsgService.h"
64 #include "RooAbsDataStore.h"
65 #include "RooResolutionModel.h"
66 #include "RooVectorDataStore.h"
67 #include "RooTreeDataStore.h"
68 
69 #include <sstream>
70 #include <string.h>
71 #include <algorithm>
72 
73 using namespace std ;
74 
75 #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
76 char* operator+( streampos&, char* );
77 #endif
78 
79 ClassImp(RooAbsArg);
80 ;
81 
82 Bool_t RooAbsArg::_verboseDirty(kFALSE) ;
83 Bool_t RooAbsArg::_inhibitDirty(kFALSE) ;
84 Bool_t RooAbsArg::inhibitDirty() const { return _inhibitDirty && !_localNoInhibitDirty; }
85 
86 std::map<RooAbsArg*,TRefArray*> RooAbsArg::_ioEvoList ;
87 std::stack<RooAbsArg*> RooAbsArg::_ioReadStack ;
88 
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Default constructor
92 
93 RooAbsArg::RooAbsArg()
94  : TNamed(), _deleteWatch(kFALSE), _valueDirty(kTRUE), _shapeDirty(kTRUE), _operMode(Auto), _fast(kFALSE), _ownedComponents(nullptr),
95  _prohibitServerRedirect(kFALSE), _eocache(0), _namePtr(0), _isConstant(kFALSE), _localNoInhibitDirty(kFALSE),
96  _myws(0)
97 {
98  _namePtr = (TNamed*) RooNameReg::instance().constPtr(GetName()) ;
99 
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// Create an object with the specified name and descriptive title.
104 /// The newly created object has no clients or servers and has its
105 /// dirty flags set.
106 
107 RooAbsArg::RooAbsArg(const char *name, const char *title)
108  : TNamed(name, title), _deleteWatch(kFALSE), _valueDirty(kTRUE), _shapeDirty(kTRUE), _operMode(Auto), _fast(kFALSE),
109  _ownedComponents(0), _prohibitServerRedirect(kFALSE), _eocache(0), _namePtr(0), _isConstant(kFALSE),
110  _localNoInhibitDirty(kFALSE), _myws(0)
111 {
112  if (name == nullptr || strlen(name) == 0) {
113  throw std::logic_error("Each RooFit object needs a name. "
114  "Objects representing the same entity (e.g. an observable 'x') are identified using their name.");
115  }
116  _namePtr = (TNamed*) RooNameReg::instance().constPtr(GetName()) ;
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Copy constructor transfers all boolean and string properties of the original
121 /// object. Transient properties and client-server links are not copied
122 
123 RooAbsArg::RooAbsArg(const RooAbsArg &other, const char *name)
124  : TNamed(other.GetName(), other.GetTitle()), RooPrintable(other), _boolAttrib(other._boolAttrib),
125  _stringAttrib(other._stringAttrib), _deleteWatch(other._deleteWatch), _operMode(Auto), _fast(kFALSE),
126  _ownedComponents(0), _prohibitServerRedirect(kFALSE), _eocache(other._eocache), _namePtr(other._namePtr),
127  _isConstant(other._isConstant), _localNoInhibitDirty(other._localNoInhibitDirty), _myws(0)
128 {
129  // Use name in argument, if supplied
130  if (name) {
131  TNamed::SetName(name) ;
132  _namePtr = (TNamed*) RooNameReg::instance().constPtr(name) ;
133  } else {
134  // Same name, don't recalculate name pointer (expensive)
135  TNamed::SetName(other.GetName()) ;
136  _namePtr = other._namePtr ;
137  }
138 
139  // Copy server list by hand
140  Bool_t valueProp, shapeProp ;
141  for (const auto server : other._serverList) {
142  valueProp = server->_clientListValue.containsByNamePtr(&other);
143  shapeProp = server->_clientListShape.containsByNamePtr(&other);
144  addServer(*server,valueProp,shapeProp) ;
145  }
146 
147  setValueDirty() ;
148  setShapeDirty() ;
149 
150  //setAttribute(Form("CloneOf(%08x)",&other)) ;
151  //cout << "RooAbsArg::cctor(" << this << ") #bools = " << _boolAttrib.size() << " #strings = " << _stringAttrib.size() << endl ;
152 
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Assign all boolean and string properties of the original
157 /// object. Transient properties and client-server links are not assigned.
158 RooAbsArg& RooAbsArg::operator=(const RooAbsArg& other) {
159  TNamed::operator=(other);
160  RooPrintable::operator=(other);
161  _boolAttrib = other._boolAttrib;
162  _stringAttrib = other._stringAttrib;
163  _deleteWatch = other._deleteWatch;
164  _operMode = other._operMode;
165  _fast = other._fast;
166  _ownedComponents = nullptr;
167  _prohibitServerRedirect = other._prohibitServerRedirect;
168  _eocache = other._eocache;
169  _namePtr = other._namePtr;
170  _isConstant = other._isConstant;
171  _localNoInhibitDirty = other._localNoInhibitDirty;
172  _myws = nullptr;
173 
174  bool valueProp, shapeProp;
175  for (const auto server : other._serverList) {
176  valueProp = server->_clientListValue.containsByNamePtr(&other);
177  shapeProp = server->_clientListShape.containsByNamePtr(&other);
178  addServer(*server,valueProp,shapeProp) ;
179  }
180 
181  setValueDirty();
182  setShapeDirty();
183 
184  return *this;
185 }
186 
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Destructor.
190 
191 RooAbsArg::~RooAbsArg()
192 {
193  // Notify all servers that they no longer need to serve us
194  while (!_serverList.empty()) {
195  removeServer(*_serverList.containedObjects().back(), kTRUE);
196  }
197 
198  // Notify all clients that they are in limbo
199  std::vector<RooAbsArg*> clientListTmp(_clientList.begin(), _clientList.end()); // have to copy, as we invalidate iterators
200  Bool_t first(kTRUE) ;
201  for (auto client : clientListTmp) {
202  client->setAttribute("ServerDied") ;
203  TString attr("ServerDied:");
204  attr.Append(GetName());
205  attr.Append(Form("(%lx)",(ULong_t)this)) ;
206  client->setAttribute(attr.Data());
207  client->removeServer(*this,kTRUE);
208 
209  if (_verboseDirty) {
210 
211  if (first) {
212  cxcoutD(Tracing) << "RooAbsArg::dtor(" << GetName() << "," << this << ") DeleteWatch: object is being destroyed" << endl ;
213  first = kFALSE ;
214  }
215 
216  cxcoutD(Tracing) << fName << "::" << ClassName() << ":~RooAbsArg: dependent \""
217  << client->GetName() << "\" should have been deleted first" << endl ;
218  }
219  }
220 
221  if (_ownedComponents) {
222  delete _ownedComponents ;
223  _ownedComponents = 0 ;
224  }
225 
226 }
227 
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Control global dirty inhibit mode. When set to true no value or shape dirty
231 /// flags are propagated and cache is always considered to be dirty.
232 
233 void RooAbsArg::setDirtyInhibit(Bool_t flag)
234 {
235  _inhibitDirty = flag ;
236 }
237 
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Activate verbose messaging related to dirty flag propagation
241 
242 void RooAbsArg::verboseDirty(Bool_t flag)
243 {
244  _verboseDirty = flag ;
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Check if this object was created as a clone of 'other'
249 
250 Bool_t RooAbsArg::isCloneOf(const RooAbsArg& other) const
251 {
252  return (getAttribute(Form("CloneOf(%lx)",(ULong_t)&other)) ||
253  other.getAttribute(Form("CloneOf(%lx)",(ULong_t)this))) ;
254 }
255 
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Set (default) or clear a named boolean attribute of this object.
259 
260 void RooAbsArg::setAttribute(const Text_t* name, Bool_t value)
261 {
262  // Preserve backward compatibility - any strong
263  if(string("Constant")==name) {
264  _isConstant = value ;
265  }
266 
267  if (value) {
268  _boolAttrib.insert(name) ;
269  } else {
270  set<string>::iterator iter = _boolAttrib.find(name) ;
271  if (iter != _boolAttrib.end()) {
272  _boolAttrib.erase(iter) ;
273  }
274 
275  }
276 
277 }
278 
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Check if a named attribute is set. By default, all attributes are unset.
282 
283 Bool_t RooAbsArg::getAttribute(const Text_t* name) const
284 {
285  return (_boolAttrib.find(name) != _boolAttrib.end()) ;
286 }
287 
288 
289 ////////////////////////////////////////////////////////////////////////////////
290 /// Associate string 'value' to this object under key 'key'
291 
292 void RooAbsArg::setStringAttribute(const Text_t* key, const Text_t* value)
293 {
294  if (value) {
295  _stringAttrib[key] = value ;
296  } else {
297  _stringAttrib.erase(key) ;
298  }
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// Get string attribute mapped under key 'key'. Returns null pointer
303 /// if no attribute exists under that key
304 
305 const Text_t* RooAbsArg::getStringAttribute(const Text_t* key) const
306 {
307  map<string,string>::const_iterator iter = _stringAttrib.find(key) ;
308  if (iter!=_stringAttrib.end()) {
309  return iter->second.c_str() ;
310  } else {
311  return 0 ;
312  }
313 }
314 
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Set (default) or clear a named boolean attribute of this object.
318 
319 void RooAbsArg::setTransientAttribute(const Text_t* name, Bool_t value)
320 {
321  if (value) {
322 
323  _boolAttribTransient.insert(name) ;
324 
325  } else {
326 
327  set<string>::iterator iter = _boolAttribTransient.find(name) ;
328  if (iter != _boolAttribTransient.end()) {
329  _boolAttribTransient.erase(iter) ;
330  }
331 
332  }
333 
334 }
335 
336 
337 ////////////////////////////////////////////////////////////////////////////////
338 /// Check if a named attribute is set. By default, all attributes
339 /// are unset.
340 
341 Bool_t RooAbsArg::getTransientAttribute(const Text_t* name) const
342 {
343  return (_boolAttribTransient.find(name) != _boolAttribTransient.end()) ;
344 }
345 
346 
347 
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 /// Register another RooAbsArg as a server to us, ie, declare that
351 /// we depend on it.
352 /// \param server The server to be registered.
353 /// \param valueProp In addition to the basic client-server relationship, declare dependence on the server's value.
354 /// \param valueProp In addition to the basic client-server relationship, declare dependence on the server's shape.
355 /// \param refCount Optionally add with higher reference count (if multiple components depend on it)
356 
357 void RooAbsArg::addServer(RooAbsArg& server, Bool_t valueProp, Bool_t shapeProp, std::size_t refCount)
358 {
359  if (_prohibitServerRedirect) {
360  cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName()
361  << "): PROHIBITED SERVER ADDITION REQUESTED: adding server " << server.GetName()
362  << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
363  assert(0) ;
364  }
365 
366  cxcoutD(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): adding server " << server.GetName()
367  << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
368 
369  if (server.operMode()==ADirty && operMode()!=ADirty && valueProp) {
370  setOperMode(ADirty) ;
371  }
372 
373 
374  // LM: use hash tables for larger lists
375 // if (_serverList.GetSize() > 999 && _serverList.getHashTableSize() == 0) _serverList.setHashTableSize(1000);
376 // if (server._clientList.GetSize() > 999 && server._clientList.getHashTableSize() == 0) server._clientList.setHashTableSize(1000);
377 // if (server._clientListValue.GetSize() > 999 && server._clientListValue.getHashTableSize() == 0) server._clientListValue.setHashTableSize(1000);
378 
379  // Add server link to given server
380  _serverList.Add(&server, refCount) ;
381 
382  server._clientList.Add(this, refCount);
383  if (valueProp) server._clientListValue.Add(this, refCount);
384  if (shapeProp) server._clientListShape.Add(this, refCount);
385 }
386 
387 
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Register a list of RooAbsArg as servers to us by calling
391 /// addServer() for each arg in the list
392 
393 void RooAbsArg::addServerList(RooAbsCollection& serverList, Bool_t valueProp, Bool_t shapeProp)
394 {
395  _serverList.reserve(_serverList.size() + serverList.size());
396 
397  for (const auto arg : serverList) {
398  addServer(*arg,valueProp,shapeProp) ;
399  }
400 }
401 
402 
403 
404 ////////////////////////////////////////////////////////////////////////////////
405 /// Unregister another RooAbsArg as a server to us, ie, declare that
406 /// we no longer depend on its value and shape.
407 
408 void RooAbsArg::removeServer(RooAbsArg& server, Bool_t force)
409 {
410  if (_prohibitServerRedirect) {
411  cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): PROHIBITED SERVER REMOVAL REQUESTED: removing server "
412  << server.GetName() << "(" << &server << ")" << endl ;
413  assert(0) ;
414  }
415 
416  if (_verboseDirty) {
417  cxcoutD(LinkStateMgmt) << "RooAbsArg::removeServer(" << GetName() << "): removing server "
418  << server.GetName() << "(" << &server << ")" << endl ;
419  }
420 
421  // Remove server link to given server
422  _serverList.Remove(&server, force) ;
423 
424  server._clientList.Remove(this, force) ;
425  server._clientListValue.Remove(this, force) ;
426  server._clientListShape.Remove(this, force) ;
427 }
428 
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// Replace 'oldServer' with 'newServer'
432 
433 void RooAbsArg::replaceServer(RooAbsArg& oldServer, RooAbsArg& newServer, Bool_t propValue, Bool_t propShape)
434 {
435  Int_t count = _serverList.refCount(&oldServer);
436  removeServer(oldServer, kTRUE);
437  addServer(newServer, propValue, propShape, count);
438 }
439 
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 /// Change dirty flag propagation mask for specified server
443 
444 void RooAbsArg::changeServer(RooAbsArg& server, Bool_t valueProp, Bool_t shapeProp)
445 {
446  if (!_serverList.containsByNamePtr(&server)) {
447  coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
448  << server.GetName() << " not registered" << endl ;
449  return ;
450  }
451 
452  // This condition should not happen, but check anyway
453  if (!server._clientList.containsByNamePtr(this)) {
454  coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
455  << server.GetName() << " doesn't have us registered as client" << endl ;
456  return ;
457  }
458 
459  // Remove all propagation links, then reinstall requested ones ;
460  Int_t vcount = server._clientListValue.refCount(this) ;
461  Int_t scount = server._clientListShape.refCount(this) ;
462  server._clientListValue.RemoveAll(this) ;
463  server._clientListShape.RemoveAll(this) ;
464  if (valueProp) {
465  server._clientListValue.Add(this, vcount) ;
466  }
467  if (shapeProp) {
468  server._clientListShape.Add(this, scount) ;
469  }
470 }
471 
472 
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Fill supplied list with all leaf nodes of the arg tree, starting with
476 /// ourself as top node. A leaf node is node that has no servers declared.
477 
478 void RooAbsArg::leafNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t recurseNonDerived) const
479 {
480  treeNodeServerList(list,arg,kFALSE,kTRUE,kFALSE,recurseNonDerived) ;
481 }
482 
483 
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// Fill supplied list with all branch nodes of the arg tree starting with
487 /// ourself as top node. A branch node is node that has one or more servers declared.
488 
489 void RooAbsArg::branchNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t recurseNonDerived) const
490 {
491  treeNodeServerList(list,arg,kTRUE,kFALSE,kFALSE,recurseNonDerived) ;
492 }
493 
494 
495 ////////////////////////////////////////////////////////////////////////////////
496 /// Fill supplied list with nodes of the arg tree, following all server links,
497 /// starting with ourself as top node.
498 /// \param[in] list Output list
499 /// \param[in] arg Start searching at this element of the tree.
500 /// \param[in] doBranch Add branch nodes to the list.
501 /// \param[in] doLeaf Add leaf nodes to the list.
502 /// \param[in] valueOnly Only check if an element is a value server (no shape server).
503 /// \param[in] recurseFundamental
504 
505 void RooAbsArg::treeNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, Bool_t doBranch, Bool_t doLeaf, Bool_t valueOnly, Bool_t recurseFundamental) const
506 {
507 // if (arg==0) {
508 // cout << "treeNodeServerList(" << GetName() << ") doBranch=" << (doBranch?"T":"F") << " doLeaf = " << (doLeaf?"T":"F") << " valueOnly=" << (valueOnly?"T":"F") << endl ;
509 // }
510 
511  if (!arg) {
512  list->reserve(10);
513  arg=this ;
514  }
515 
516  // Decide if to add current node
517  if ((doBranch&&doLeaf) ||
518  (doBranch&&arg->isDerived()) ||
519  (doLeaf&&arg->isFundamental()&&(!(recurseFundamental&&arg->isDerived()))) ||
520  (doLeaf && !arg->isFundamental() && !arg->isDerived())) {
521 
522  list->add(*arg,kTRUE) ;
523  }
524 
525  // Recurse if current node is derived
526  if (arg->isDerived() && (!arg->isFundamental() || recurseFundamental)) {
527  for (const auto server : arg->_serverList) {
528 
529  // Skip non-value server nodes if requested
530  Bool_t isValueSrv = server->_clientListValue.containsByNamePtr(arg);
531  if (valueOnly && !isValueSrv) {
532  continue ;
533  }
534  treeNodeServerList(list,server,doBranch,doLeaf,valueOnly,recurseFundamental) ;
535  }
536  }
537 }
538 
539 
540 ////////////////////////////////////////////////////////////////////////////////
541 /// Create a list of leaf nodes in the arg tree starting with
542 /// ourself as top node that don't match any of the names of the variable list
543 /// of the supplied data set (the dependents). The caller of this
544 /// function is responsible for deleting the returned argset.
545 /// The complement of this function is getObservables()
546 
547 RooArgSet* RooAbsArg::getParameters(const RooAbsData* set, Bool_t stripDisconnected) const
548 {
549  return getParameters(set?set->get():0,stripDisconnected) ;
550 }
551 
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 /// INTERNAL helper function for getParameters()
555 
556 void RooAbsArg::addParameters(RooArgSet& params, const RooArgSet* nset,Bool_t stripDisconnected) const
557 {
558  // INTERNAL helper function for getParameters()
559 
560  RooArgSet nodeParamServers ;
561  RooArgSet nodeBranchServers ;
562  for (const auto server : _serverList) {
563  if (server->isValueServer(*this)) {
564  if (server->isFundamental()) {
565  if (!nset || !server->dependsOn(*nset)) {
566  nodeParamServers.add(*server) ;
567  }
568  } else {
569  nodeBranchServers.add(*server) ;
570  }
571  }
572  }
573 
574  // Allow pdf to strip parameters from list before adding it
575  getParametersHook(nset,&nodeParamServers,stripDisconnected) ;
576 
577  // Add parameters of this node to the combined list
578  params.add(nodeParamServers,kTRUE) ;
579 
580  // Now recurse into branch servers
581  for (const auto server : nodeBranchServers) {
582  server->addParameters(params,nset) ;
583  }
584 }
585 
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 /// Create a list of leaf nodes in the arg tree starting with
589 /// ourself as top node that don't match any of the names the args in the
590 /// supplied argset. The caller of this function is responsible
591 /// for deleting the returned argset. The complement of this function
592 /// is getObservables()
593 
594 RooArgSet* RooAbsArg::getParameters(const RooArgSet* nset, Bool_t stripDisconnected) const
595 {
596 
597  // Check for cached parameter set
598  if (_myws) {
599  RooNameSet nsetObs(nset ? *nset : RooArgSet());
600  const RooArgSet *paramSet = _myws->set(Form("CACHE_PARAMS_OF_PDF_%s_FOR_OBS_%s", GetName(), nsetObs.content()));
601  if (paramSet) {
602  // cout << " restoring parameter cache from workspace for pdf " << IsA()->GetName() << "::" << GetName() <<
603  // endl ;
604  return new RooArgSet(*paramSet);
605  }
606  }
607 
608  RooArgSet *parList = new RooArgSet("parameters");
609 
610  addParameters(*parList, nset, stripDisconnected);
611 
612  parList->sort();
613 
614  // Cache parameter set
615  if (_myws && parList->getSize() > 10) {
616  RooNameSet nsetObs(nset ? *nset : RooArgSet());
617  _myws->defineSetInternal(Form("CACHE_PARAMS_OF_PDF_%s_FOR_OBS_%s", GetName(), nsetObs.content()), *parList);
618  // cout << " caching parameters in workspace for pdf " << IsA()->GetName() << "::" << GetName() << endl ;
619  }
620 
621  return parList;
622 }
623 
624 
625 
626 ////////////////////////////////////////////////////////////////////////////////
627 /// Create a list of leaf nodes in the arg tree starting with
628 /// ourself as top node that match any of the names of the variable list
629 /// of the supplied data set (the dependents). The caller of this
630 /// function is responsible for deleting the returned argset.
631 /// The complement of this function is getParameters().
632 
633 RooArgSet* RooAbsArg::getObservables(const RooAbsData* set) const
634 {
635  if (!set) return new RooArgSet ;
636 
637  return getObservables(set->get()) ;
638 }
639 
640 
641 ////////////////////////////////////////////////////////////////////////////////
642 /// Create a list of leaf nodes in the arg tree starting with
643 /// ourself as top node that match any of the names the args in the
644 /// supplied argset. The caller of this function is responsible
645 /// for deleting the returned argset. The complement of this function
646 /// is getParameters().
647 
648 RooArgSet* RooAbsArg::getObservables(const RooArgSet* dataList, Bool_t valueOnly) const
649 {
650  //cout << "RooAbsArg::getObservables(" << GetName() << ")" << endl ;
651 
652  RooArgSet* depList = new RooArgSet("dependents") ;
653  if (!dataList) return depList ;
654 
655  // Make iterator over tree leaf node list
656  RooArgSet leafList("leafNodeServerList") ;
657  treeNodeServerList(&leafList,0,kFALSE,kTRUE,valueOnly) ;
658 
659  if (valueOnly) {
660  for (const auto arg : leafList) {
661  if (arg->dependsOnValue(*dataList) && arg->isLValue()) {
662  depList->add(*arg) ;
663  }
664  }
665  } else {
666  for (const auto arg : leafList) {
667  if (arg->dependsOn(*dataList) && arg->isLValue()) {
668  depList->add(*arg) ;
669  }
670  }
671  }
672 
673  return depList ;
674 }
675 
676 
677 RooArgSet* RooAbsArg::getComponents() const
678 {
679  // Return a RooArgSet with all component (branch nodes) of the
680  // expression tree headed by this object
681 
682  TString name(GetName()) ;
683  name.Append("_components") ;
684 
685  RooArgSet* set = new RooArgSet(name) ;
686  branchNodeServerList(set) ;
687 
688  return set ;
689 }
690 
691 
692 
693 ////////////////////////////////////////////////////////////////////////////////
694 /// Overloadable function in which derived classes can implement
695 /// consistency checks of the variables. If this function returns
696 /// true, indicating an error, the fitter or generator will abort.
697 
698 Bool_t RooAbsArg::checkObservables(const RooArgSet*) const
699 {
700  return kFALSE ;
701 }
702 
703 
704 ////////////////////////////////////////////////////////////////////////////////
705 /// Recursively call checkObservables on all nodes in the expression tree
706 
707 Bool_t RooAbsArg::recursiveCheckObservables(const RooArgSet* nset) const
708 {
709  RooArgSet nodeList ;
710  treeNodeServerList(&nodeList) ;
711  RooFIter iter = nodeList.fwdIterator() ;
712 
713  RooAbsArg* arg ;
714  Bool_t ret(kFALSE) ;
715  while((arg=iter.next())) {
716  if (arg->getAttribute("ServerDied")) {
717  coutE(LinkStateMgmt) << "RooAbsArg::recursiveCheckObservables(" << GetName() << "): ERROR: one or more servers of node "
718  << arg->GetName() << " no longer exists!" << endl ;
719  arg->Print("v") ;
720  ret = kTRUE ;
721  }
722  ret |= arg->checkObservables(nset) ;
723  }
724 
725  return ret ;
726 }
727 
728 
729 ////////////////////////////////////////////////////////////////////////////////
730 /// Test whether we depend on (ie, are served by) any object in the
731 /// specified collection. Uses the dependsOn(RooAbsArg&) member function.
732 
733 Bool_t RooAbsArg::dependsOn(const RooAbsCollection& serverList, const RooAbsArg* ignoreArg, Bool_t valueOnly) const
734 {
735  // Test whether we depend on (ie, are served by) any object in the
736  // specified collection. Uses the dependsOn(RooAbsArg&) member function.
737 
738  for (auto server : serverList) {
739  if (dependsOn(*server,ignoreArg,valueOnly)) {
740  return kTRUE;
741  }
742  }
743  return kFALSE;
744 }
745 
746 
747 ////////////////////////////////////////////////////////////////////////////////
748 /// Test whether we depend on (ie, are served by) the specified object.
749 /// Note that RooAbsArg objects are considered equivalent if they have
750 /// the same name.
751 
752 Bool_t RooAbsArg::dependsOn(const RooAbsArg& testArg, const RooAbsArg* ignoreArg, Bool_t valueOnly) const
753 {
754  if (this==ignoreArg) return kFALSE ;
755 
756  // First check if testArg is self
757  //if (!TString(testArg.GetName()).CompareTo(GetName())) return kTRUE ;
758  if (testArg.namePtr()==namePtr()) return kTRUE ;
759 
760 
761  // Next test direct dependence
762  RooAbsArg* foundServer = findServer(testArg) ;
763  if (foundServer) {
764 
765  // Return true if valueOnly is FALSE or if server is value server, otherwise keep looking
766  if ( !valueOnly || foundServer->isValueServer(*this)) {
767  return kTRUE ;
768  }
769  }
770 
771  // If not, recurse
772  for (const auto server : _serverList) {
773  if ( !valueOnly || server->isValueServer(*this)) {
774  if (server->dependsOn(testArg,ignoreArg,valueOnly)) {
775  return kTRUE ;
776  }
777  }
778  }
779 
780  return kFALSE ;
781 }
782 
783 
784 
785 ////////////////////////////////////////////////////////////////////////////////
786 /// Test if any of the nodes of tree are shared with that of the given tree
787 
788 Bool_t RooAbsArg::overlaps(const RooAbsArg& testArg, Bool_t valueOnly) const
789 {
790  RooArgSet list("treeNodeList") ;
791  treeNodeServerList(&list) ;
792 
793  return valueOnly ? testArg.dependsOnValue(list) : testArg.dependsOn(list) ;
794 }
795 
796 
797 
798 ////////////////////////////////////////////////////////////////////////////////
799 /// Test if any of the dependents of the arg tree (as determined by getObservables)
800 /// overlaps with those of the testArg.
801 
802 Bool_t RooAbsArg::observableOverlaps(const RooAbsData* dset, const RooAbsArg& testArg) const
803 {
804  return observableOverlaps(dset->get(),testArg) ;
805 }
806 
807 
808 ////////////////////////////////////////////////////////////////////////////////
809 /// Test if any of the dependents of the arg tree (as determined by getObservables)
810 /// overlaps with those of the testArg.
811 
812 Bool_t RooAbsArg::observableOverlaps(const RooArgSet* nset, const RooAbsArg& testArg) const
813 {
814  RooArgSet* depList = getObservables(nset) ;
815  Bool_t ret = testArg.dependsOn(*depList) ;
816  delete depList ;
817  return ret ;
818 }
819 
820 
821 
822 ////////////////////////////////////////////////////////////////////////////////
823 /// Mark this object as having changed its value, and propagate this status
824 /// change to all of our clients. If the object is not in automatic dirty
825 /// state propagation mode, this call has no effect
826 
827 void RooAbsArg::setValueDirty(const RooAbsArg* source)
828 {
829  _allBatchesDirty = true;
830 
831  if (_operMode!=Auto || _inhibitDirty) return ;
832 
833  // Handle no-propagation scenarios first
834  if (_clientListValue.size() == 0) {
835  _valueDirty = kTRUE ;
836  return ;
837  }
838 
839  // Cyclical dependency interception
840  if (source==0) {
841  source=this ;
842  } else if (source==this) {
843  // Cyclical dependency, abort
844  coutE(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << GetName()
845  << "): cyclical dependency detected, source = " << source->GetName() << endl ;
846  //assert(0) ;
847  return ;
848  }
849 
850  // Propagate dirty flag to all clients if this is a down->up transition
851  if (_verboseDirty) {
852  cxcoutD(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << (source?source->GetName():"self") << "->" << GetName() << "," << this
853  << "): dirty flag " << (_valueDirty?"already ":"") << "raised" << endl ;
854  }
855 
856  _valueDirty = kTRUE ;
857 
858 
859  for (auto client : _clientListValue) {
860  client->setValueDirty(source) ;
861  }
862 
863 
864 }
865 
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// Mark this object as having changed its shape, and propagate this status
869 /// change to all of our clients.
870 
871 void RooAbsArg::setShapeDirty(const RooAbsArg* source)
872 {
873  if (_verboseDirty) {
874  cxcoutD(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
875  << "): dirty flag " << (_shapeDirty?"already ":"") << "raised" << endl ;
876  }
877 
878  if (_clientListShape.empty()) {
879  _shapeDirty = kTRUE ;
880  return ;
881  }
882 
883  // Set 'dirty' shape state for this object and propagate flag to all its clients
884  if (source==0) {
885  source=this ;
886  } else if (source==this) {
887  // Cyclical dependency, abort
888  coutE(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
889  << "): cyclical dependency detected" << endl ;
890  return ;
891  }
892 
893  // Propagate dirty flag to all clients if this is a down->up transition
894  _shapeDirty=kTRUE ;
895 
896  for (auto client : _clientListShape) {
897  client->setShapeDirty(source) ;
898  client->setValueDirty(source) ;
899  }
900 
901 }
902 
903 
904 
905 ////////////////////////////////////////////////////////////////////////////////
906 /// Substitute our servers with those listed in newSet. If nameChange is false, servers and
907 /// and substitutes are matched by name. If nameChange is true, servers are matched to args
908 /// in newSet that have the 'ORIGNAME:<servername>' attribute set. If mustReplaceAll is set,
909 /// a warning is printed and error status is returned if not all servers could be successfully
910 /// substituted.
911 
912 Bool_t RooAbsArg::redirectServers(const RooAbsCollection& newSetOrig, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t isRecursionStep)
913 {
914  // Trivial case, no servers
915  if (_serverList.empty()) return kFALSE ;
916  if (newSetOrig.getSize()==0) return kFALSE ;
917 
918  // Strip any non-matching removal nodes from newSetOrig
919  RooAbsCollection* newSet ;
920 
921  if (nameChange) {
922  newSet = new RooArgSet ;
923  for (auto arg : newSetOrig) {
924 
925  if (string("REMOVAL_DUMMY")==arg->GetName()) {
926 
927  if (arg->getAttribute("REMOVE_ALL")) {
928 // cout << "RooAbsArg::redir including remove_all node " << arg->GetName() << endl ;
929  newSet->add(*arg) ;
930  } else if (arg->getAttribute(Form("REMOVE_FROM_%s",getStringAttribute("ORIGNAME")))) {
931 // cout << "RooAbsArg::redir including remove_from_" << GetName() << " node " << arg->GetName() << endl ;
932  newSet->add(*arg) ;
933  }
934  } else {
935  newSet->add(*arg) ;
936  }
937  }
938 
939 // cout << "RooAbsArg::redirect with name change(" << GetName() << ") newSet = " << newSet << " origSet = " << newSetOrig << endl ;
940 
941  } else {
942  newSet = (RooAbsCollection*) &newSetOrig ;
943  }
944 
945  // Replace current servers with new servers with the same name from the given list
946  Bool_t ret(kFALSE) ;
947 
948  //Copy original server list to not confuse the iterator while deleting
949  std::vector<RooAbsArg*> origServerList, origServerValue, origServerShape;
950  auto origSize = _serverList.size();
951  origServerList.reserve(origSize);
952  origServerValue.reserve(origSize);
953 
954  for (const auto oldServer : _serverList) {
955  origServerList.push_back(oldServer) ;
956 
957  // Retrieve server side link state information
958  if (oldServer->_clientListValue.containsByNamePtr(this)) {
959  origServerValue.push_back(oldServer) ;
960  }
961  if (oldServer->_clientListShape.containsByNamePtr(this)) {
962  origServerShape.push_back(oldServer) ;
963  }
964  }
965 
966  // Delete all previously registered servers
967  for (auto oldServer : origServerList) {
968 
969  RooAbsArg * newServer= oldServer->findNewServer(*newSet, nameChange);
970 
971  if (newServer && _verboseDirty) {
972  cxcoutD(LinkStateMgmt) << "RooAbsArg::redirectServers(" << (void*)this << "," << GetName() << "): server " << oldServer->GetName()
973  << " redirected from " << oldServer << " to " << newServer << endl ;
974  }
975 
976  if (!newServer) {
977  if (mustReplaceAll) {
978  coutE(LinkStateMgmt) << "RooAbsArg::redirectServers(" << (void*)this << "," << GetName() << "): server " << oldServer->GetName()
979  << " (" << (void*)oldServer << ") not redirected" << (nameChange?"[nameChange]":"") << endl ;
980  ret = kTRUE ;
981  }
982  continue ;
983  }
984 
985  auto findByNamePtr = [&oldServer](const RooAbsArg * item) {
986  return oldServer->namePtr() == item->namePtr();
987  };
988  bool propValue = std::any_of(origServerValue.begin(), origServerValue.end(), findByNamePtr);
989  bool propShape = std::any_of(origServerShape.begin(), origServerShape.end(), findByNamePtr);
990  // cout << "replaceServer with name " << oldServer->GetName() << " old=" << oldServer << " new=" << newServer << endl ;
991  if (newServer != this) {
992  replaceServer(*oldServer,*newServer,propValue,propShape) ;
993  }
994  }
995 
996 
997  setValueDirty() ;
998  setShapeDirty() ;
999 
1000  // Process the proxies
1001  Bool_t allReplaced=kTRUE ;
1002  for (int i=0 ; i<numProxies() ; i++) {
1003  RooAbsProxy* p = getProxy(i) ;
1004  if (!p) continue ;
1005  Bool_t ret2 = p->changePointer(*newSet,nameChange,kFALSE) ;
1006  allReplaced &= ret2 ;
1007  }
1008 
1009  if (mustReplaceAll && !allReplaced) {
1010  coutE(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName()
1011  << "): ERROR, some proxies could not be adjusted" << endl ;
1012  ret = kTRUE ;
1013  }
1014 
1015  // Optional subclass post-processing
1016  for (Int_t i=0 ;i<numCaches() ; i++) {
1017  ret |= getCache(i)->redirectServersHook(*newSet,mustReplaceAll,nameChange,isRecursionStep) ;
1018  }
1019  ret |= redirectServersHook(*newSet,mustReplaceAll,nameChange,isRecursionStep) ;
1020 
1021  if (nameChange) {
1022  delete newSet ;
1023  }
1024 
1025  return ret ;
1026 }
1027 
1028 ////////////////////////////////////////////////////////////////////////////////
1029 /// Find the new server in the specified set that matches the old server.
1030 /// Allow a name change if nameChange is kTRUE, in which case the new
1031 /// server is selected by searching for a new server with an attribute
1032 /// of "ORIGNAME:<oldName>". Return zero if there is not a unique match.
1033 
1034 RooAbsArg *RooAbsArg::findNewServer(const RooAbsCollection &newSet, Bool_t nameChange) const
1035 {
1036  RooAbsArg *newServer = 0;
1037  if (!nameChange) {
1038  newServer = newSet.find(*this) ;
1039  }
1040  else {
1041  // Name changing server redirect:
1042  // use 'ORIGNAME:<oldName>' attribute instead of name of new server
1043  TString nameAttrib("ORIGNAME:") ;
1044  nameAttrib.Append(GetName()) ;
1045 
1046  RooArgSet* tmp = (RooArgSet*) newSet.selectByAttrib(nameAttrib,kTRUE) ;
1047  if(0 != tmp) {
1048 
1049  // Check if any match was found
1050  if (tmp->getSize()==0) {
1051  delete tmp ;
1052  return 0 ;
1053  }
1054 
1055  // Check if match is unique
1056  if(tmp->getSize()>1) {
1057  coutF(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName() << "): FATAL Error, " << tmp->getSize() << " servers with "
1058  << nameAttrib << " attribute" << endl ;
1059  tmp->Print("v") ;
1060  assert(0) ;
1061  }
1062 
1063  // use the unique element in the set
1064  newServer= tmp->first();
1065  delete tmp ;
1066  }
1067  }
1068  return newServer;
1069 }
1070 
1071 Bool_t RooAbsArg::recursiveRedirectServers(const RooAbsCollection& newSet, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t recurseInNewSet)
1072 {
1073  // Recursively redirect all servers with new server in collection 'newSet'.
1074  // Substitute our servers with those listed in newSet. If nameChange is false, servers and
1075  // and substitutes are matched by name. If nameChange is true, servers are matched to args
1076  // in newSet that have the 'ORIGNAME:<servername>' attribute set. If mustReplaceAll is set,
1077  // a warning is printed and error status is returned if not all servers could be sucessfully
1078  // substituted. If recurseInNewSet is true, the recursion algorithm also recursion into
1079  // expression trees under the arguments in the new servers (i.e. those in newset)
1080 
1081 
1082  // Cyclic recursion protection
1083  static std::set<const RooAbsArg*> callStack;
1084  {
1085  std::set<const RooAbsArg*>::iterator it = callStack.lower_bound(this);
1086  if (it != callStack.end() && this == *it) {
1087  return kFALSE;
1088  } else {
1089  callStack.insert(it, this);
1090  }
1091  }
1092 
1093  // Do not recurse into newset if not so specified
1094 // if (!recurseInNewSet && newSet.contains(*this)) {
1095 // return kFALSE ;
1096 // }
1097 
1098 
1099  // Apply the redirectServers function recursively on all branch nodes in this argument tree.
1100  Bool_t ret(kFALSE) ;
1101 
1102  cxcoutD(LinkStateMgmt) << "RooAbsArg::recursiveRedirectServers(" << this << "," << GetName() << ") newSet = " << newSet << " mustReplaceAll = "
1103  << (mustReplaceAll?"T":"F") << " nameChange = " << (nameChange?"T":"F") << " recurseInNewSet = " << (recurseInNewSet?"T":"F") << endl ;
1104 
1105  // Do redirect on self (identify operation as recursion step)
1106  ret |= redirectServers(newSet,mustReplaceAll,nameChange,kTRUE) ;
1107 
1108  // Do redirect on servers
1109  for (const auto server : _serverList){
1110  ret |= server->recursiveRedirectServers(newSet,mustReplaceAll,nameChange,recurseInNewSet) ;
1111  }
1112 
1113  callStack.erase(this);
1114  return ret ;
1115 }
1116 
1117 
1118 
1119 ////////////////////////////////////////////////////////////////////////////////
1120 /// Register an RooArgProxy in the proxy list. This function is called by owned
1121 /// proxies upon creation. After registration, this arg wil forward pointer
1122 /// changes from serverRedirects and updates in cached normalization sets
1123 /// to the proxies immediately after they occur. The proxied argument is
1124 /// also added as value and/or shape server
1125 
1126 void RooAbsArg::registerProxy(RooArgProxy& proxy)
1127 {
1128  // Every proxy can be registered only once
1129  if (_proxyList.FindObject(&proxy)) {
1130  coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1131  << proxy.GetName() << " for arg " << proxy.absArg()->GetName()
1132  << " already registered" << endl ;
1133  return ;
1134  }
1135 
1136 // cout << (void*)this << " " << GetName() << ": registering proxy "
1137 // << (void*)&proxy << " with name " << proxy.name() << " in mode "
1138 // << (proxy.isValueServer()?"V":"-") << (proxy.isShapeServer()?"S":"-") << endl ;
1139 
1140  // Register proxied object as server
1141  if (proxy.absArg()) {
1142  addServer(*proxy.absArg(),proxy.isValueServer(),proxy.isShapeServer()) ;
1143  }
1144 
1145  // Register proxy itself
1146  _proxyList.Add(&proxy) ;
1147 }
1148 
1149 
1150 ////////////////////////////////////////////////////////////////////////////////
1151 /// Remove proxy from proxy list. This functions is called by owned proxies
1152 /// upon their destruction.
1153 
1154 void RooAbsArg::unRegisterProxy(RooArgProxy& proxy)
1155 {
1156  _proxyList.Remove(&proxy) ;
1157  _proxyList.Compress() ;
1158 }
1159 
1160 
1161 
1162 ////////////////////////////////////////////////////////////////////////////////
1163 /// Register an RooSetProxy in the proxy list. This function is called by owned
1164 /// proxies upon creation. After registration, this arg wil forward pointer
1165 /// changes from serverRedirects and updates in cached normalization sets
1166 /// to the proxies immediately after they occur.
1167 
1168 void RooAbsArg::registerProxy(RooSetProxy& proxy)
1169 {
1170  // Every proxy can be registered only once
1171  if (_proxyList.FindObject(&proxy)) {
1172  coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1173  << proxy.GetName() << " already registered" << endl ;
1174  return ;
1175  }
1176 
1177  // Register proxy itself
1178  _proxyList.Add(&proxy) ;
1179 }
1180 
1181 
1182 
1183 ////////////////////////////////////////////////////////////////////////////////
1184 /// Remove proxy from proxy list. This functions is called by owned proxies
1185 /// upon their destruction.
1186 
1187 void RooAbsArg::unRegisterProxy(RooSetProxy& proxy)
1188 {
1189  _proxyList.Remove(&proxy) ;
1190  _proxyList.Compress() ;
1191 }
1192 
1193 
1194 
1195 ////////////////////////////////////////////////////////////////////////////////
1196 /// Register an RooListProxy in the proxy list. This function is called by owned
1197 /// proxies upon creation. After registration, this arg wil forward pointer
1198 /// changes from serverRedirects and updates in cached normalization sets
1199 /// to the proxies immediately after they occur.
1200 
1201 void RooAbsArg::registerProxy(RooListProxy& proxy)
1202 {
1203  // Every proxy can be registered only once
1204  if (_proxyList.FindObject(&proxy)) {
1205  coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1206  << proxy.GetName() << " already registered" << endl ;
1207  return ;
1208  }
1209 
1210  // Register proxy itself
1211  Int_t nProxyOld = _proxyList.GetEntries() ;
1212  _proxyList.Add(&proxy) ;
1213  if (_proxyList.GetEntries()!=nProxyOld+1) {
1214  cout << "RooAbsArg::registerProxy(" << GetName() << ") proxy registration failure! nold=" << nProxyOld << " nnew=" << _proxyList.GetEntries() << endl ;
1215  }
1216 }
1217 
1218 
1219 
1220 ////////////////////////////////////////////////////////////////////////////////
1221 /// Remove proxy from proxy list. This functions is called by owned proxies
1222 /// upon their destruction.
1223 
1224 void RooAbsArg::unRegisterProxy(RooListProxy& proxy)
1225 {
1226  _proxyList.Remove(&proxy) ;
1227  _proxyList.Compress() ;
1228 }
1229 
1230 
1231 
1232 ////////////////////////////////////////////////////////////////////////////////
1233 /// Return the nth proxy from the proxy list.
1234 
1235 RooAbsProxy* RooAbsArg::getProxy(Int_t index) const
1236 {
1237  // Cross cast: proxy list returns TObject base pointer, we need
1238  // a RooAbsProxy base pointer. C++ standard requires
1239  // a dynamic_cast for this.
1240  return dynamic_cast<RooAbsProxy*> (_proxyList.At(index)) ;
1241 }
1242 
1243 
1244 
1245 ////////////////////////////////////////////////////////////////////////////////
1246 /// Return the number of registered proxies.
1247 
1248 Int_t RooAbsArg::numProxies() const
1249 {
1250  return _proxyList.GetEntriesFast();
1251 }
1252 
1253 
1254 
1255 ////////////////////////////////////////////////////////////////////////////////
1256 /// Forward a change in the cached normalization argset
1257 /// to all the registered proxies.
1258 
1259 void RooAbsArg::setProxyNormSet(const RooArgSet* nset)
1260 {
1261  for (int i=0 ; i<numProxies() ; i++) {
1262  RooAbsProxy* p = getProxy(i) ;
1263  if (!p) continue ;
1264  getProxy(i)->changeNormSet(nset) ;
1265  }
1266 }
1267 
1268 
1269 
1270 ////////////////////////////////////////////////////////////////////////////////
1271 /// Overloadable function for derived classes to implement
1272 /// attachment as branch to a TTree
1273 
1274 void RooAbsArg::attachToTree(TTree& ,Int_t)
1275 {
1276  coutE(Contents) << "RooAbsArg::attachToTree(" << GetName()
1277  << "): Cannot be attached to a TTree" << endl ;
1278 }
1279 
1280 
1281 
1282 ////////////////////////////////////////////////////////////////////////////////
1283 /// WVE (08/21/01) Probably obsolete now
1284 
1285 Bool_t RooAbsArg::isValid() const
1286 {
1287  return kTRUE ;
1288 }
1289 
1290 
1291 
1292 
1293 ////////////////////////////////////////////////////////////////////////////////
1294 /// Print object name
1295 
1296 void RooAbsArg::printName(ostream& os) const
1297 {
1298  os << GetName() ;
1299 }
1300 
1301 
1302 
1303 ////////////////////////////////////////////////////////////////////////////////
1304 /// Print object title
1305 
1306 void RooAbsArg::printTitle(ostream& os) const
1307 {
1308  os << GetTitle() ;
1309 }
1310 
1311 
1312 
1313 ////////////////////////////////////////////////////////////////////////////////
1314 /// Print object class name
1315 
1316 void RooAbsArg::printClassName(ostream& os) const
1317 {
1318  os << IsA()->GetName() ;
1319 }
1320 
1321 
1322 void RooAbsArg::printAddress(ostream& os) const
1323 {
1324  // Print addrss of this RooAbsArg
1325  os << this ;
1326 }
1327 
1328 
1329 
1330 ////////////////////////////////////////////////////////////////////////////////
1331 /// Print object arguments, ie its proxies
1332 
1333 void RooAbsArg::printArgs(ostream& os) const
1334 {
1335  // Print nothing if there are no dependencies
1336  if (numProxies()==0) return ;
1337 
1338  os << "[ " ;
1339  for (Int_t i=0 ; i<numProxies() ; i++) {
1340  RooAbsProxy* p = getProxy(i) ;
1341  if (p==0) continue ;
1342  if (!TString(p->name()).BeginsWith("!")) {
1343  p->print(os) ;
1344  os << " " ;
1345  }
1346  }
1347  printMetaArgs(os) ;
1348  os << "]" ;
1349 }
1350 
1351 
1352 
1353 ////////////////////////////////////////////////////////////////////////////////
1354 /// Define default contents to print
1355 
1356 Int_t RooAbsArg::defaultPrintContents(Option_t* /*opt*/) const
1357 {
1358  return kName|kClassName|kValue|kArgs ;
1359 }
1360 
1361 
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 /// Implement multi-line detailed printing
1365 
1366 void RooAbsArg::printMultiline(ostream& os, Int_t /*contents*/, Bool_t /*verbose*/, TString indent) const
1367 {
1368  os << indent << "--- RooAbsArg ---" << endl;
1369  // dirty state flags
1370  os << indent << " Value State: " ;
1371  switch(_operMode) {
1372  case ADirty: os << "FORCED DIRTY" ; break ;
1373  case AClean: os << "FORCED clean" ; break ;
1374  case Auto: os << (isValueDirty() ? "DIRTY":"clean") ; break ;
1375  }
1376  os << endl
1377  << indent << " Shape State: " << (isShapeDirty() ? "DIRTY":"clean") << endl;
1378  // attribute list
1379  os << indent << " Attributes: " ;
1380  printAttribList(os) ;
1381  os << endl ;
1382  // our memory address (for x-referencing with client addresses of other args)
1383  os << indent << " Address: " << (void*)this << endl;
1384  // client list
1385  os << indent << " Clients: " << endl;
1386  for (const auto client : _clientList) {
1387  os << indent << " (" << (void*)client << ","
1388  << (_clientListValue.containsByNamePtr(client)?"V":"-")
1389  << (_clientListShape.containsByNamePtr(client)?"S":"-")
1390  << ") " ;
1391  client->printStream(os,kClassName|kTitle|kName,kSingleLine);
1392  }
1393 
1394  // server list
1395  os << indent << " Servers: " << endl;
1396  for (const auto server : _serverList) {
1397  os << indent << " (" << (void*)server << ","
1398  << (server->_clientListValue.containsByNamePtr(this)?"V":"-")
1399  << (server->_clientListShape.containsByNamePtr(this)?"S":"-")
1400  << ") " ;
1401  server->printStream(os,kClassName|kName|kTitle,kSingleLine);
1402  }
1403 
1404  // proxy list
1405  os << indent << " Proxies: " << endl ;
1406  for (int i=0 ; i<numProxies() ; i++) {
1407  RooAbsProxy* proxy=getProxy(i) ;
1408  if (!proxy) continue ;
1409  if (proxy->IsA()->InheritsFrom(RooArgProxy::Class())) {
1410  os << indent << " " << proxy->name() << " -> " ;
1411  RooAbsArg* parg = ((RooArgProxy*)proxy)->absArg() ;
1412  if (parg) {
1413  parg->printStream(os,kName,kSingleLine) ;
1414  } else {
1415  os << " (empty)" << endl ; ;
1416  }
1417  } else {
1418  os << indent << " " << proxy->name() << " -> " ;
1419  os << endl ;
1420  TString moreIndent(indent) ;
1421  moreIndent.Append(" ") ;
1422  ((RooSetProxy*)proxy)->printStream(os,kName,kStandard,moreIndent.Data()) ;
1423  }
1424  }
1425 }
1426 
1427 
1428 ////////////////////////////////////////////////////////////////////////////////
1429 /// Print object tree structure
1430 
1431 void RooAbsArg::printTree(ostream& os, TString /*indent*/) const
1432 {
1433  const_cast<RooAbsArg*>(this)->printCompactTree(os) ;
1434 }
1435 
1436 
1437 ////////////////////////////////////////////////////////////////////////////////
1438 /// Ostream operator
1439 
1440 ostream& operator<<(ostream& os, RooAbsArg &arg)
1441 {
1442  arg.writeToStream(os,kTRUE) ;
1443  return os ;
1444 }
1445 
1446 ////////////////////////////////////////////////////////////////////////////////
1447 /// Istream operator
1448 
1449 istream& operator>>(istream& is, RooAbsArg &arg)
1450 {
1451  arg.readFromStream(is,kTRUE,kFALSE) ;
1452  return is ;
1453 }
1454 
1455 ////////////////////////////////////////////////////////////////////////////////
1456 /// Print the attribute list
1457 
1458 void RooAbsArg::printAttribList(ostream& os) const
1459 {
1460  set<string>::const_iterator iter = _boolAttrib.begin() ;
1461  Bool_t first(kTRUE) ;
1462  while (iter != _boolAttrib.end()) {
1463  os << (first?" [":",") << *iter ;
1464  first=kFALSE ;
1465  ++iter ;
1466  }
1467  if (!first) os << "] " ;
1468 }
1469 
1470 ////////////////////////////////////////////////////////////////////////////////
1471 /// Replace server nodes with names matching the dataset variable names
1472 /// with those data set variables, making this PDF directly dependent on the dataset.
1473 
1474 void RooAbsArg::attachDataSet(const RooAbsData &data)
1475 {
1476  const RooArgSet* set = data.get() ;
1477  RooArgSet branches ;
1478  branchNodeServerList(&branches,0,kTRUE) ;
1479 
1480  RooFIter iter = branches.fwdIterator() ;
1481  RooAbsArg* branch ;
1482  while((branch=iter.next())) {
1483  branch->redirectServers(*set,kFALSE,kFALSE) ;
1484  }
1485 }
1486 
1487 
1488 
1489 ////////////////////////////////////////////////////////////////////////////////
1490 /// Replace server nodes with names matching the dataset variable names
1491 /// with those data set variables, making this PDF directly dependent on the dataset
1492 
1493 void RooAbsArg::attachDataStore(const RooAbsDataStore &dstore)
1494 {
1495  const RooArgSet* set = dstore.get() ;
1496  RooArgSet branches ;
1497  branchNodeServerList(&branches,0,kTRUE) ;
1498 
1499  RooFIter iter = branches.fwdIterator() ;
1500  RooAbsArg* branch ;
1501  while((branch=iter.next())) {
1502  branch->redirectServers(*set,kFALSE,kFALSE) ;
1503  }
1504 }
1505 
1506 
1507 
1508 ////////////////////////////////////////////////////////////////////////////////
1509 /// Utility function used by TCollection::Sort to compare contained TObjects
1510 /// We implement comparison by name, resulting in alphabetical sorting by object name.
1511 
1512 Int_t RooAbsArg::Compare(const TObject* other) const
1513 {
1514  return strcmp(GetName(),other->GetName()) ;
1515 }
1516 
1517 
1518 
1519 ////////////////////////////////////////////////////////////////////////////////
1520 /// Print information about current value dirty state information.
1521 /// If depth flag is true, information is recursively printed for
1522 /// all nodes in this arg tree.
1523 
1524 void RooAbsArg::printDirty(Bool_t depth) const
1525 {
1526  if (depth) {
1527 
1528  RooArgSet branchList ;
1529  branchNodeServerList(&branchList) ;
1530  RooFIter bIter = branchList.fwdIterator() ;
1531  RooAbsArg* branch ;
1532  while((branch=bIter.next())) {
1533  branch->printDirty(kFALSE) ;
1534  }
1535 
1536  } else {
1537  cout << GetName() << " : " ;
1538  switch (_operMode) {
1539  case AClean: cout << "FORCED clean" ; break ;
1540  case ADirty: cout << "FORCED DIRTY" ; break ;
1541  case Auto: cout << "Auto " << (isValueDirty()?"DIRTY":"clean") ;
1542  }
1543  cout << endl ;
1544  }
1545 }
1546 
1547 
1548 ////////////////////////////////////////////////////////////////////////////////
1549 /// Activate cache mode optimization with given definition of observables.
1550 /// The cache operation mode of all objects in the expression tree will
1551 /// modified such that all nodes that depend directly or indirectly on
1552 /// any of the listed observables will be set to ADirty, as they are
1553 /// expected to change every time. This save change tracking overhead for
1554 /// nodes that are a priori known to change every time
1555 
1556 void RooAbsArg::optimizeCacheMode(const RooArgSet& observables)
1557 {
1558  RooLinkedList proc;
1559  RooArgSet opt ;
1560  optimizeCacheMode(observables,opt,proc) ;
1561 
1562  coutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") nodes " << opt << " depend on observables, "
1563  << "changing cache operation mode from change tracking to unconditional evaluation" << endl ;
1564 }
1565 
1566 
1567 ////////////////////////////////////////////////////////////////////////////////
1568 /// Activate cache mode optimization with given definition of observables.
1569 /// The cache operation mode of all objects in the expression tree will
1570 /// modified such that all nodes that depend directly or indirectly on
1571 /// any of the listed observables will be set to ADirty, as they are
1572 /// expected to change every time. This save change tracking overhead for
1573 /// nodes that are a priori known to change every time
1574 
1575 void RooAbsArg::optimizeCacheMode(const RooArgSet& observables, RooArgSet& optimizedNodes, RooLinkedList& processedNodes)
1576 {
1577  // Optimization applies only to branch nodes, not to leaf nodes
1578  if (!isDerived()) {
1579  return ;
1580  }
1581 
1582 
1583  // Terminate call if this node was already processed (tree structure may be cyclical)
1584  if (processedNodes.findArg(this)) {
1585  return ;
1586  } else {
1587  processedNodes.Add(this) ;
1588  }
1589 
1590  // Set cache mode operator to 'AlwaysDirty' if we depend on any of the given observables
1591  if (dependsOnValue(observables)) {
1592 
1593  if (dynamic_cast<RooRealIntegral*>(this)) {
1594  cxcoutI(Integration) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") integral depends on value of one or more observables and will be evaluated for every event" << endl ;
1595  }
1596  optimizedNodes.add(*this,kTRUE) ;
1597  if (operMode()==AClean) {
1598  } else {
1599  setOperMode(ADirty,kTRUE) ; // WVE propagate flag recursively to top of tree
1600  }
1601  } else {
1602  }
1603  // Process any RooAbsArgs contained in any of the caches of this object
1604  for (Int_t i=0 ;i<numCaches() ; i++) {
1605  getCache(i)->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
1606  }
1607 
1608  // Forward calls to all servers
1609  for (const auto server : _serverList) {
1610  server->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
1611  }
1612 
1613 }
1614 
1615 ////////////////////////////////////////////////////////////////////////////////
1616 /// Find branch nodes with all-constant parameters, and add them to the list of
1617 /// nodes that can be cached with a dataset in a test statistic calculation
1618 
1619 Bool_t RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList)
1620 {
1621  RooLinkedList proc ;
1622  Bool_t ret = findConstantNodes(observables,cacheList,proc) ;
1623 
1624  // If node can be optimized and hasn't been identified yet, add it to the list
1625  coutI(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << "): components "
1626  << cacheList << " depend exclusively on constant parameters and will be precalculated and cached" << endl ;
1627 
1628  return ret ;
1629 }
1630 
1631 
1632 
1633 ////////////////////////////////////////////////////////////////////////////////
1634 /// Find branch nodes with all-constant parameters, and add them to the list of
1635 /// nodes that can be cached with a dataset in a test statistic calculation
1636 
1637 Bool_t RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList, RooLinkedList& processedNodes)
1638 {
1639  // Caching only applies to branch nodes
1640  if (!isDerived()) {
1641  return kFALSE;
1642  }
1643 
1644  // Terminate call if this node was already processed (tree structure may be cyclical)
1645  if (processedNodes.findArg(this)) {
1646  return kFALSE ;
1647  } else {
1648  processedNodes.Add(this) ;
1649  }
1650 
1651  // Check if node depends on any non-constant parameter
1652  Bool_t canOpt(kTRUE) ;
1653  RooArgSet* paramSet = getParameters(observables) ;
1654  RooFIter iter = paramSet->fwdIterator() ;
1655  RooAbsArg* param ;
1656  while((param = iter.next())) {
1657  if (!param->isConstant()) {
1658  canOpt=kFALSE ;
1659  break ;
1660  }
1661  }
1662  delete paramSet ;
1663 
1664 
1665  if (getAttribute("NeverConstant")) {
1666  canOpt = kFALSE ;
1667  }
1668 
1669  if (canOpt) {
1670  setAttribute("ConstantExpression") ;
1671  }
1672 
1673  // If yes, list node eligible for caching, if not test nodes one level down
1674  if (canOpt||getAttribute("CacheAndTrack")) {
1675 
1676  if (!cacheList.find(*this) && dependsOnValue(observables) && !observables.find(*this) ) {
1677 
1678  // Add to cache list
1679  cxcoutD(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << ") adding self to list of constant nodes" << endl ;
1680 
1681  if (canOpt) setAttribute("ConstantExpressionCached") ;
1682  cacheList.add(*this,kFALSE) ;
1683  }
1684  }
1685 
1686  if (!canOpt) {
1687 
1688  // If not, see if next level down can be cached
1689  for (const auto server : _serverList) {
1690  if (server->isDerived()) {
1691  server->findConstantNodes(observables,cacheList,processedNodes) ;
1692  }
1693  }
1694  }
1695 
1696  // Forward call to all cached contained in current object
1697  for (Int_t i=0 ;i<numCaches() ; i++) {
1698  getCache(i)->findConstantNodes(observables,cacheList,processedNodes) ;
1699  }
1700 
1701  return kFALSE ;
1702 }
1703 
1704 
1705 
1706 
1707 ////////////////////////////////////////////////////////////////////////////////
1708 /// Interface function signaling a request to perform constant term
1709 /// optimization. This default implementation takes no action other than to
1710 /// forward the calls to all servers
1711 
1712 void RooAbsArg::constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTrackingOpt)
1713 {
1714  for (const auto server : _serverList) {
1715  server->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt) ;
1716  }
1717 }
1718 
1719 
1720 ////////////////////////////////////////////////////////////////////////////////
1721 /// Change cache operation mode to given mode. If recurseAdirty
1722 /// is true, then a mode change to AlwaysDirty will automatically
1723 /// be propagated recursively to all client nodes
1724 
1725 void RooAbsArg::setOperMode(OperMode mode, Bool_t recurseADirty)
1726 {
1727  // Prevent recursion loops
1728  if (mode==_operMode) return ;
1729 
1730  _operMode = mode ;
1731  _fast = ((mode==AClean) || dynamic_cast<RooRealVar*>(this)!=0 || dynamic_cast<RooConstVar*>(this)!=0 ) ;
1732  for (Int_t i=0 ;i<numCaches() ; i++) {
1733  getCache(i)->operModeHook() ;
1734  }
1735  operModeHook() ;
1736 
1737  // Propagate to all clients
1738  if (mode==ADirty && recurseADirty) {
1739  for (auto clientV : _clientListValue) {
1740  clientV->setOperMode(mode) ;
1741  }
1742  }
1743 }
1744 
1745 
1746 ////////////////////////////////////////////////////////////////////////////////
1747 /// Print tree structure of expression tree on stdout, or to file if filename is specified.
1748 /// If namePat is not "*", only nodes with names matching the pattern will be printed.
1749 /// The client argument is used in recursive calls to properly display the value or shape nature
1750 /// of the client-server links. It should be zero in calls initiated by users.
1751 
1752 void RooAbsArg::printCompactTree(const char* indent, const char* filename, const char* namePat, RooAbsArg* client)
1753 {
1754  if (filename) {
1755  ofstream ofs(filename) ;
1756  printCompactTree(ofs,indent,namePat,client) ;
1757  } else {
1758  printCompactTree(cout,indent,namePat,client) ;
1759  }
1760 }
1761 
1762 
1763 ////////////////////////////////////////////////////////////////////////////////
1764 /// Print tree structure of expression tree on given ostream.
1765 /// If namePat is not "*", only nodes with names matching the pattern will be printed.
1766 /// The client argument is used in recursive calls to properly display the value or shape nature
1767 /// of the client-server links. It should be zero in calls initiated by users.
1768 
1769 void RooAbsArg::printCompactTree(ostream& os, const char* indent, const char* namePat, RooAbsArg* client)
1770 {
1771  if ( !namePat || TString(GetName()).Contains(namePat)) {
1772  os << indent << this ;
1773  if (client) {
1774  os << "/" ;
1775  if (isValueServer(*client)) os << "V" ; else os << "-" ;
1776  if (isShapeServer(*client)) os << "S" ; else os << "-" ;
1777  }
1778  os << " " ;
1779 
1780  os << IsA()->GetName() << "::" << GetName() << " = " ;
1781  printValue(os) ;
1782 
1783  if (!_serverList.empty()) {
1784  switch(operMode()) {
1785  case Auto: os << " [Auto," << (isValueDirty()?"Dirty":"Clean") << "] " ; break ;
1786  case AClean: os << " [ACLEAN] " ; break ;
1787  case ADirty: os << " [ADIRTY] " ; break ;
1788  }
1789  }
1790  os << endl ;
1791 
1792  for (Int_t i=0 ;i<numCaches() ; i++) {
1793  getCache(i)->printCompactTreeHook(os,indent) ;
1794  }
1795  printCompactTreeHook(os,indent) ;
1796  }
1797 
1798  TString indent2(indent) ;
1799  indent2 += " " ;
1800  for (const auto arg : _serverList) {
1801  arg->printCompactTree(os,indent2,namePat,this) ;
1802  }
1803 }
1804 
1805 
1806 ////////////////////////////////////////////////////////////////////////////////
1807 /// Print tree structure of expression tree on given ostream, only branch nodes are printed.
1808 /// Lead nodes (variables) will not be shown
1809 ///
1810 /// If namePat is not "*", only nodes with names matching the pattern will be printed.
1811 
1812 void RooAbsArg::printComponentTree(const char* indent, const char* namePat, Int_t nLevel)
1813 {
1814  if (nLevel==0) return ;
1815  if (isFundamental()) return ;
1816  RooResolutionModel* rmodel = dynamic_cast<RooResolutionModel*>(this) ;
1817  if (rmodel && rmodel->isConvolved()) return ;
1818  if (InheritsFrom("RooConstVar")) return ;
1819 
1820  if ( !namePat || TString(GetName()).Contains(namePat)) {
1821  cout << indent ;
1822  Print() ;
1823  }
1824 
1825  TString indent2(indent) ;
1826  indent2 += " " ;
1827  for (const auto arg : _serverList) {
1828  arg->printComponentTree(indent2.Data(),namePat,nLevel-1) ;
1829  }
1830 }
1831 
1832 
1833 ////////////////////////////////////////////////////////////////////////////////
1834 /// Construct a mangled name from the actual name that
1835 /// is free of any math symbols that might be interpreted by TTree
1836 
1837 TString RooAbsArg::cleanBranchName() const
1838 {
1839  // Check for optional alternate name of branch for this argument
1840  TString rawBranchName = GetName() ;
1841  if (getStringAttribute("BranchName")) {
1842  rawBranchName = getStringAttribute("BranchName") ;
1843  }
1844 
1845  TString cleanName(rawBranchName) ;
1846  cleanName.ReplaceAll("/","D") ;
1847  cleanName.ReplaceAll("-","M") ;
1848  cleanName.ReplaceAll("+","P") ;
1849  cleanName.ReplaceAll("*","X") ;
1850  cleanName.ReplaceAll("[","L") ;
1851  cleanName.ReplaceAll("]","R") ;
1852  cleanName.ReplaceAll("(","L") ;
1853  cleanName.ReplaceAll(")","R") ;
1854  cleanName.ReplaceAll("{","L") ;
1855  cleanName.ReplaceAll("}","R") ;
1856 
1857  return cleanName;
1858 }
1859 
1860 
1861 ////////////////////////////////////////////////////////////////////////////////
1862 /// Hook function interface for object to insert additional information
1863 /// when printed in the context of a tree structure. This default
1864 /// implementation prints nothing
1865 
1866 void RooAbsArg::printCompactTreeHook(ostream&, const char *)
1867 {
1868 }
1869 
1870 
1871 ////////////////////////////////////////////////////////////////////////////////
1872 /// Register RooAbsCache with this object. This function is called
1873 /// by RooAbsCache constructors for objects that are a datamember
1874 /// of this RooAbsArg. By registering itself the RooAbsArg is aware
1875 /// of all its cache data members and will forward server change
1876 /// and cache mode change calls to the cache objects, which in turn
1877 /// can forward them their contents
1878 
1879 void RooAbsArg::registerCache(RooAbsCache& cache)
1880 {
1881  _cacheList.push_back(&cache) ;
1882 }
1883 
1884 
1885 ////////////////////////////////////////////////////////////////////////////////
1886 /// Unregister a RooAbsCache. Called from the RooAbsCache destructor
1887 
1888 void RooAbsArg::unRegisterCache(RooAbsCache& cache)
1889 {
1890  _cacheList.erase(std::remove(_cacheList.begin(), _cacheList.end(), &cache),
1891  _cacheList.end());
1892 }
1893 
1894 
1895 ////////////////////////////////////////////////////////////////////////////////
1896 /// Return number of registered caches
1897 
1898 Int_t RooAbsArg::numCaches() const
1899 {
1900  return _cacheList.size() ;
1901 }
1902 
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 /// Return registered cache object by index
1906 
1907 RooAbsCache* RooAbsArg::getCache(Int_t index) const
1908 {
1909  return _cacheList[index] ;
1910 }
1911 
1912 
1913 ////////////////////////////////////////////////////////////////////////////////
1914 /// Return RooArgSet with all variables (tree leaf nodes of expresssion tree)
1915 
1916 RooArgSet* RooAbsArg::getVariables(Bool_t stripDisconnected) const
1917 {
1918  return getParameters(RooArgSet(),stripDisconnected) ;
1919 }
1920 
1921 
1922 ////////////////////////////////////////////////////////////////////////////////
1923 /// Return ancestors in cloning chain of this RooAbsArg. NOTE: Returned pointers
1924 /// are not guaranteed to be 'live', so do not dereference without proper caution
1925 
1926 RooLinkedList RooAbsArg::getCloningAncestors() const
1927 {
1928  RooLinkedList retVal ;
1929 
1930  set<string>::const_iterator iter= _boolAttrib.begin() ;
1931  while(iter != _boolAttrib.end()) {
1932  if (TString(*iter).BeginsWith("CloneOf(")) {
1933  char buf[128] ;
1934  strlcpy(buf,iter->c_str(),128) ;
1935  strtok(buf,"(") ;
1936  char* ptrToken = strtok(0,")") ;
1937  RooAbsArg* ptr = (RooAbsArg*) strtol(ptrToken,0,16) ;
1938  retVal.Add(ptr) ;
1939  }
1940  }
1941 
1942  return retVal ;
1943 }
1944 
1945 
1946 ////////////////////////////////////////////////////////////////////////////////
1947 /// Create a GraphViz .dot file visualizing the expression tree headed by
1948 /// this RooAbsArg object. Use the GraphViz tool suite to make e.g. a gif
1949 /// or ps file from the .dot file
1950 ///
1951 /// Based on concept developed by Kyle Cranmer
1952 
1953 void RooAbsArg::graphVizTree(const char* fileName, const char* delimiter, bool useTitle, bool useLatex)
1954 {
1955  ofstream ofs(fileName) ;
1956  if (!ofs) {
1957  coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: Cannot open graphViz output file with name " << fileName << endl ;
1958  return ;
1959  }
1960  graphVizTree(ofs, delimiter, useTitle, useLatex) ;
1961 }
1962 
1963 ////////////////////////////////////////////////////////////////////////////////
1964 /// Write the GraphViz representation of the expression tree headed by
1965 /// this RooAbsArg object to the given ostream.
1966 ///
1967 /// Based on concept developed by Kyle Cranmer
1968 
1969 void RooAbsArg::graphVizTree(ostream& os, const char* delimiter, bool useTitle, bool useLatex)
1970 {
1971  if (!os) {
1972  coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: output stream provided as input argument is in invalid state" << endl ;
1973  }
1974 
1975  // Write header
1976  os << "digraph " << GetName() << "{" << endl ;
1977 
1978  // First list all the tree nodes
1979  RooArgSet nodeSet ;
1980  treeNodeServerList(&nodeSet) ;
1981  RooFIter iter = nodeSet.fwdIterator() ;
1982  RooAbsArg* node ;
1983 
1984  // iterate over nodes
1985  while((node=iter.next())) {
1986  string nodeName = node->GetName();
1987  string nodeTitle = node->GetTitle();
1988  string nodeLabel = (useTitle && !nodeTitle.empty()) ? nodeTitle : nodeName;
1989 
1990  // if using latex, replace ROOT's # with normal latex backslash
1991  string::size_type position = nodeLabel.find("#") ;
1992  while(useLatex && position!=nodeLabel.npos){
1993  nodeLabel.replace(position, 1, "\\");
1994  }
1995 
1996  string typeFormat = "\\texttt{";
1997  string nodeType = (useLatex) ? typeFormat+node->IsA()->GetName()+"}" : node->IsA()->GetName();
1998 
1999  os << "\"" << nodeName << "\" [ color=" << (node->isFundamental()?"blue":"red")
2000  << ", label=\"" << nodeType << delimiter << nodeLabel << "\"];" << endl ;
2001 
2002  }
2003 
2004  // Get set of all server links
2005  set<pair<RooAbsArg*,RooAbsArg*> > links ;
2006  graphVizAddConnections(links) ;
2007 
2008  // And write them out
2009  set<pair<RooAbsArg*,RooAbsArg*> >::iterator liter = links.begin() ;
2010  for( ; liter != links.end() ; ++liter ) {
2011  os << "\"" << liter->first->GetName() << "\" -> \"" << liter->second->GetName() << "\";" << endl ;
2012  }
2013 
2014  // Write trailer
2015  os << "}" << endl ;
2016 
2017 }
2018 
2019 ////////////////////////////////////////////////////////////////////////////////
2020 /// Utility function that inserts all point-to-point client-server connections
2021 /// between any two RooAbsArgs in the expression tree headed by this object
2022 /// in the linkSet argument.
2023 
2024 void RooAbsArg::graphVizAddConnections(set<pair<RooAbsArg*,RooAbsArg*> >& linkSet)
2025 {
2026  for (const auto server : _serverList) {
2027  linkSet.insert(make_pair(this,server)) ;
2028  server->graphVizAddConnections(linkSet) ;
2029  }
2030 }
2031 
2032 
2033 
2034 // //_____________________________________________________________________________
2035 // TGraphStruct* RooAbsArg::graph(Bool_t useFactoryTag, Double_t textSize)
2036 // {
2037 // // Return a TGraphStruct object filled with the tree structure of the pdf object
2038 
2039 // TGraphStruct* theGraph = new TGraphStruct() ;
2040 
2041 // // First list all the tree nodes
2042 // RooArgSet nodeSet ;
2043 // treeNodeServerList(&nodeSet) ;
2044 // TIterator* iter = nodeSet.createIterator() ;
2045 // RooAbsArg* node ;
2046 
2047 
2048 // // iterate over nodes
2049 // while((node=(RooAbsArg*)iter->Next())) {
2050 
2051 // // Skip node that represent numeric constants
2052 // if (node->IsA()->InheritsFrom(RooConstVar::Class())) continue ;
2053 
2054 // string nodeName ;
2055 // if (useFactoryTag && node->getStringAttribute("factory_tag")) {
2056 // nodeName = node->getStringAttribute("factory_tag") ;
2057 // } else {
2058 // if (node->isFundamental()) {
2059 // nodeName = node->GetName();
2060 // } else {
2061 // ostringstream oss ;
2062 // node->printStream(oss,(node->defaultPrintContents(0)&(~kValue)),node->defaultPrintStyle(0)) ;
2063 // nodeName= oss.str() ;
2064 // // nodeName = Form("%s::%s",node->IsA()->GetName(),node->GetName());
2065 
2066 // }
2067 // }
2068 // if (strncmp(nodeName.c_str(),"Roo",3)==0) {
2069 // nodeName = string(nodeName.c_str()+3) ;
2070 // }
2071 // node->setStringAttribute("graph_name",nodeName.c_str()) ;
2072 
2073 // TGraphNode* gnode = theGraph->AddNode(nodeName.c_str(),nodeName.c_str()) ;
2074 // gnode->SetLineWidth(2) ;
2075 // gnode->SetTextColor(node->isFundamental()?kBlue:kRed) ;
2076 // gnode->SetTextSize(textSize) ;
2077 // }
2078 // delete iter ;
2079 
2080 // // Get set of all server links
2081 // set<pair<RooAbsArg*,RooAbsArg*> > links ;
2082 // graphVizAddConnections(links) ;
2083 
2084 // // And insert them into the graph
2085 // set<pair<RooAbsArg*,RooAbsArg*> >::iterator liter = links.begin() ;
2086 // for( ; liter != links.end() ; ++liter ) {
2087 
2088 // TGraphNode* n1 = (TGraphNode*)theGraph->GetListOfNodes()->FindObject(liter->first->getStringAttribute("graph_name")) ;
2089 // TGraphNode* n2 = (TGraphNode*)theGraph->GetListOfNodes()->FindObject(liter->second->getStringAttribute("graph_name")) ;
2090 // if (n1 && n2) {
2091 // TGraphEdge* edge = theGraph->AddEdge(n1,n2) ;
2092 // edge->SetLineWidth(2) ;
2093 // }
2094 // }
2095 
2096 // return theGraph ;
2097 // }
2098 
2099 
2100 
2101 // //_____________________________________________________________________________
2102 // Bool_t RooAbsArg::inhibitDirty()
2103 // {
2104 // // Return current status of the inhibitDirty global flag. If true
2105 // // no dirty state change tracking occurs and all caches are considered
2106 // // to be always dirty.
2107 // return _inhibitDirty ;
2108 // }
2109 
2110 
2111 ////////////////////////////////////////////////////////////////////////////////
2112 /// Take ownership of the contents of 'comps'
2113 
2114 Bool_t RooAbsArg::addOwnedComponents(const RooArgSet& comps)
2115 {
2116  if (!_ownedComponents) {
2117  _ownedComponents = new RooArgSet("owned components") ;
2118  }
2119  return _ownedComponents->addOwned(comps) ;
2120 }
2121 
2122 
2123 
2124 ////////////////////////////////////////////////////////////////////////////////
2125 /// Clone tree expression of objects. All tree nodes will be owned by
2126 /// the head node return by cloneTree()
2127 
2128 RooAbsArg* RooAbsArg::cloneTree(const char* newname) const
2129 {
2130  // Clone tree using snapshot
2131  RooArgSet* clonedNodes = (RooArgSet*) RooArgSet(*this).snapshot(kTRUE) ;
2132 
2133  // Find the head node in the cloneSet
2134  RooAbsArg* head = clonedNodes->find(*this) ;
2135  assert(head);
2136 
2137  // Remove the head node from the cloneSet
2138  // To release it from the set ownership
2139  clonedNodes->remove(*head) ;
2140 
2141  // Add the set as owned component of the head
2142  head->addOwnedComponents(*clonedNodes) ;
2143 
2144  // Delete intermediate container
2145  clonedNodes->releaseOwnership() ;
2146  delete clonedNodes ;
2147 
2148  // Adjust name of head node if requested
2149  if (newname) {
2150  head->TNamed::SetName(newname) ;
2151  head->_namePtr = (TNamed*) RooNameReg::instance().constPtr(newname) ;
2152  }
2153 
2154  // Return the head
2155  return head ;
2156 }
2157 
2158 
2159 
2160 ////////////////////////////////////////////////////////////////////////////////
2161 
2162 void RooAbsArg::attachToStore(RooAbsDataStore& store)
2163 {
2164  if (dynamic_cast<RooTreeDataStore*>(&store)) {
2165  attachToTree(((RooTreeDataStore&)store).tree()) ;
2166  } else if (dynamic_cast<RooVectorDataStore*>(&store)) {
2167  attachToVStore((RooVectorDataStore&)store) ;
2168  }
2169 }
2170 
2171 
2172 
2173 ////////////////////////////////////////////////////////////////////////////////
2174 
2175 RooExpensiveObjectCache& RooAbsArg::expensiveObjectCache() const
2176 {
2177  if (_eocache) {
2178  return *_eocache ;
2179  } else {
2180  return RooExpensiveObjectCache::instance() ;
2181  }
2182 }
2183 
2184 
2185 ////////////////////////////////////////////////////////////////////////////////
2186 
2187 const char* RooAbsArg::aggregateCacheUniqueSuffix() const
2188 {
2189  string suffix ;
2190 
2191  RooArgSet branches ;
2192  branchNodeServerList(&branches) ;
2193  RooFIter iter = branches.fwdIterator();
2194  RooAbsArg* arg ;
2195  while((arg=iter.next())) {
2196  const char* tmp = arg->cacheUniqueSuffix() ;
2197  if (tmp) suffix += tmp ;
2198  }
2199  return Form("%s",suffix.c_str()) ;
2200 }
2201 
2202 
2203 ////////////////////////////////////////////////////////////////////////////////
2204 
2205 void RooAbsArg::wireAllCaches()
2206 {
2207  RooArgSet branches ;
2208  branchNodeServerList(&branches) ;
2209  RooFIter iter = branches.fwdIterator() ;
2210  RooAbsArg* arg ;
2211  while((arg=iter.next())) {
2212 // cout << "wiring caches on node " << arg->GetName() << endl ;
2213  for (deque<RooAbsCache*>::iterator iter2 = arg->_cacheList.begin() ; iter2 != arg->_cacheList.end() ; ++iter2) {
2214  (*iter2)->wireCache() ;
2215  }
2216  }
2217 }
2218 
2219 
2220 
2221 ////////////////////////////////////////////////////////////////////////////////
2222 
2223 void RooAbsArg::SetName(const char* name)
2224 {
2225  TNamed::SetName(name) ;
2226  TNamed* newPtr = (TNamed*) RooNameReg::instance().constPtr(GetName()) ;
2227  if (newPtr != _namePtr) {
2228  //cout << "Rename '" << _namePtr->GetName() << "' to '" << name << "' (set flag in new name)" << endl;
2229  _namePtr = newPtr;
2230  _namePtr->SetBit(RooNameReg::kRenamedArg);
2231  }
2232 }
2233 
2234 
2235 
2236 
2237 ////////////////////////////////////////////////////////////////////////////////
2238 
2239 void RooAbsArg::SetNameTitle(const char *name, const char *title)
2240 {
2241  TNamed::SetNameTitle(name,title) ;
2242  TNamed* newPtr = (TNamed*) RooNameReg::instance().constPtr(GetName()) ;
2243  if (newPtr != _namePtr) {
2244  //cout << "Rename '" << _namePtr->GetName() << "' to '" << name << "' (set flag in new name)" << endl;
2245  _namePtr = newPtr;
2246  _namePtr->SetBit(RooNameReg::kRenamedArg);
2247  }
2248 }
2249 
2250 
2251 ////////////////////////////////////////////////////////////////////////////////
2252 /// Stream an object of class RooAbsArg.
2253 
2254 void RooAbsArg::Streamer(TBuffer &R__b)
2255 {
2256  if (R__b.IsReading()) {
2257  _ioReadStack.push(this) ;
2258  R__b.ReadClassBuffer(RooAbsArg::Class(),this);
2259  _ioReadStack.pop() ;
2260  _namePtr = (TNamed*) RooNameReg::instance().constPtr(GetName()) ;
2261  _isConstant = getAttribute("Constant") ;
2262  } else {
2263  R__b.WriteClassBuffer(RooAbsArg::Class(),this);
2264  }
2265 }
2266 
2267 ////////////////////////////////////////////////////////////////////////////////
2268 /// Method called by workspace container to finalize schema evolution issues
2269 /// that cannot be handled in a single ioStreamer pass.
2270 ///
2271 /// A second pass is typically needed when evolving data member of RooAbsArg-derived
2272 /// classes that are container classes with references to other members, which may
2273 /// not yet be 'live' in the first ioStreamer() evolution pass.
2274 ///
2275 /// Classes may overload this function, but must call the base method in the
2276 /// overloaded call to ensure base evolution is handled properly
2277 
2278 void RooAbsArg::ioStreamerPass2()
2279 {
2280 
2281  // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2282  map<RooAbsArg*,TRefArray*>::iterator iter = _ioEvoList.find(this) ;
2283  if (iter != _ioEvoList.end()) {
2284 
2285  // Transfer contents of saved TRefArray to RooRefArray now
2286  if (!_proxyList.GetEntriesFast())
2287  _proxyList.Expand(iter->second->GetEntriesFast());
2288  for (int i = 0; i < iter->second->GetEntriesFast(); i++) {
2289  _proxyList.Add(iter->second->At(i));
2290  }
2291  // Delete TRefArray and remove from list
2292  delete iter->second ;
2293  _ioEvoList.erase(iter) ;
2294  }
2295 }
2296 
2297 
2298 
2299 
2300 ////////////////////////////////////////////////////////////////////////////////
2301 /// Method called by workspace container to finalize schema evolution issues
2302 /// that cannot be handled in a single ioStreamer pass. This static finalize method
2303 /// is called after ioStreamerPass2() is called on each directly listed object
2304 /// in the workspace. It's purpose is to complete schema evolution of any
2305 /// objects in the workspace that are not directly listed as content elements
2306 /// (e.g. analytical convolution tokens )
2307 
2308 void RooAbsArg::ioStreamerPass2Finalize()
2309 {
2310 
2311  // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2312  map<RooAbsArg*,TRefArray*>::iterator iter = _ioEvoList.begin() ;
2313  while (iter != _ioEvoList.end()) {
2314 
2315  // Transfer contents of saved TRefArray to RooRefArray now
2316  if (!iter->first->_proxyList.GetEntriesFast())
2317  iter->first->_proxyList.Expand(iter->second->GetEntriesFast());
2318  for (int i = 0; i < iter->second->GetEntriesFast(); i++) {
2319  iter->first->_proxyList.Add(iter->second->At(i));
2320  }
2321 
2322  // Save iterator position for deletion after increment
2323  map<RooAbsArg*,TRefArray*>::iterator iter_tmp = iter ;
2324 
2325  ++iter ;
2326 
2327  // Delete TRefArray and remove from list
2328  delete iter_tmp->second ;
2329  _ioEvoList.erase(iter_tmp) ;
2330 
2331  }
2332 
2333 }
2334 
2335 RooAbsArg::RefCountListLegacyIterator_t *
2336 RooAbsArg::makeLegacyIterator(const RooAbsArg::RefCountList_t& list) const {
2337  return new RefCountListLegacyIterator_t(list.containedObjects());
2338 }
2339 
2340 ////////////////////////////////////////////////////////////////////////////////
2341 /// Stream an object of class RooRefArray.
2342 
2343 void RooRefArray::Streamer(TBuffer &R__b)
2344 {
2345  UInt_t R__s, R__c;
2346  if (R__b.IsReading()) {
2347 
2348  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
2349 
2350  // Make temporary refArray and read that from the streamer
2351  TRefArray* refArray = new TRefArray ;
2352  refArray->Streamer(R__b) ;
2353  R__b.CheckByteCount(R__s, R__c, refArray->IsA());
2354 
2355  // Schedule deferred processing of TRefArray into proxy list
2356  RooAbsArg::_ioEvoList[RooAbsArg::_ioReadStack.top()] = refArray ;
2357 
2358  } else {
2359 
2360  R__c = R__b.WriteVersion(RooRefArray::IsA(), kTRUE);
2361 
2362  // Make a temporary refArray and write that to the streamer
2363  TRefArray refArray(GetEntriesFast());
2364  TIterator* iter = MakeIterator() ;
2365  TObject* tmpObj ; while ((tmpObj = iter->Next())) {
2366  refArray.Add(tmpObj) ;
2367  }
2368  delete iter ;
2369 
2370  refArray.Streamer(R__b) ;
2371  R__b.SetByteCount(R__c, kTRUE) ;
2372 
2373  }
2374 }
2375 
2376 /// Print at the prompt
2377 namespace cling {
2378 std::string printValue(RooAbsArg *raa)
2379 {
2380  std::stringstream s;
2381  if (0 == *raa->GetName() && 0 == *raa->GetTitle()) {
2382  s << "An instance of " << raa->ClassName() << ".";
2383  return s.str();
2384  }
2385  raa->printStream(s, raa->defaultPrintContents(""), raa->defaultPrintStyle(""));
2386  return s.str();
2387 }
2388 } // namespace cling
2389