Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
21Common abstract base class for objects that
22represent a value and a "shape" in RooFit. Values or shapes usually depend on values
23or shapes of other RooAbsArg instances. Connecting several RooAbsArg in
24a computation graph models an expression tree that can be evaluated.
25
26### Building a computation graph of RooFit objects
27Therefore, RooAbsArg provides functionality to connect objects of type RooAbsArg into
28a computation graph to pass values between those objects.
29A value can e.g. be a real-valued number, (instances of RooAbsReal), or an integer, that is,
30category index (instances of RooAbsCategory). The third subclass of RooAbsArg is RooStringVar,
31but it is rarely used.
32
33The "shapes" that a RooAbsArg can possess can e.g. be the definition
34range of an observable, or how many states a category object has. In computations,
35values are expected to change often, while shapes remain mostly constant
36(unless e.g. a new range is set for an observable).
37
38Nodes of a computation graph are connected using instances of RooAbsProxy.
39If Node B declares a member `RooTemplateProxy<TypeOfNodeA>`, Node A will be
40registered as a server of values to Node B, and Node B will know that it is
41a client of node A. Using functions like dependsOn(), or getObservables()
42/ getParameters(), the relation of `A --> B` can be queried. Using graphVizTree(),
43one can create a visualisation of the expression tree.
44
45
46An instance of RooAbsArg can have named attributes. It also has flags
47to indicate that either its value or its shape were changed (= it is dirty).
48RooAbsArg provides functionality to manage client/server relations in
49a computation graph (\ref clientServerInterface), and helps propagating
50value/shape changes through the graph. RooAbsArg implements interfaces
51for inspecting client/server relationships (\ref clientServerInterface) and
52setting/clearing/querying named attributes.
53
54### Caching of values
55The values of nodes in the computation graph are cached in RooFit. If
56a value is used in two nodes of a graph, it doesn't need to be recomputed. If
57a node acquires a new value, it notifies its consumers ("clients") that
58their cached values are dirty. See the functions in \ref optimisationInterface
59for details.
60A node uses its isValueDirty() and isShapeDirty() functions to decide if a
61computation is necessary. Caching can be vetoed globally by setting a
62bit using setDirtyInhibit(). This will make computations slower, but all the
63nodes of the computation graph will be evaluated irrespective of whether their
64state is clean or dirty. Using setOperMode(), caching can also be enabled/disabled
65for single nodes.
66
67*/
68
69#include <RooAbsArg.h>
70
72#include <RooAbsData.h>
73#include <RooAbsDataStore.h>
74#include <RooArgProxy.h>
75#include <RooArgSet.h>
76#include <RooConstVar.h>
78#include <RooHelpers.h>
79#include "RooFitImplHelpers.h"
80#include <RooListProxy.h>
81#include <RooMsgService.h>
82#include <RooRealIntegral.h>
83#include <RooResolutionModel.h>
84#include <RooSetProxy.h>
85#include <RooTrace.h>
86#include <RooTreeDataStore.h>
87#include <RooVectorDataStore.h>
88#include <RooWorkspace.h>
89
90#include <TBuffer.h>
91#include <TClass.h>
93
94#include <algorithm>
95#include <cstring>
96#include <fstream>
97#include <sstream>
98
99using std::cout, std::endl, std::ostream, std::string, std::set, std::map, std::istream, std::pair, std::ofstream, std::make_pair;
100
102
103bool RooAbsArg::_verboseDirty(false) ;
104bool RooAbsArg::_inhibitDirty(false) ;
106
107std::map<RooAbsArg*,std::unique_ptr<TRefArray>> RooAbsArg::_ioEvoList;
108std::stack<RooAbsArg*> RooAbsArg::_ioReadStack ;
109
110
111////////////////////////////////////////////////////////////////////////////////
112/// Default constructor
113
114RooAbsArg::RooAbsArg() : _namePtr(RooNameReg::instance().constPtr(GetName())) {}
115
116////////////////////////////////////////////////////////////////////////////////
117/// Create an object with the specified name and descriptive title.
118/// The newly created object has no clients or servers and has its
119/// dirty flags set.
120
121RooAbsArg::RooAbsArg(const char *name, const char *title)
122 : TNamed(name, title)
123{
124 if (name == nullptr || strlen(name) == 0) {
125 throw std::logic_error("Each RooFit object needs a name. "
126 "Objects representing the same entity (e.g. an observable 'x') are identified using their name.");
127 }
129}
130
131////////////////////////////////////////////////////////////////////////////////
132/// Copy constructor transfers all boolean and string properties of the original
133/// object. Transient properties and client-server links are not copied
134
135RooAbsArg::RooAbsArg(const RooAbsArg &other, const char *name)
136 : TNamed(name ? name : other.GetName(), other.GetTitle()),
137 RooPrintable(other),
138 _boolAttrib(other._boolAttrib),
139 _stringAttrib(other._stringAttrib),
140 _deleteWatch(other._deleteWatch),
141 _namePtr(name ? RooNameReg::instance().constPtr(name) : other._namePtr),
142 _isConstant(other._isConstant),
143 _localNoInhibitDirty(other._localNoInhibitDirty)
144{
145
146 // Copy server list by hand
147 bool valueProp;
148 bool shapeProp;
149 for (const auto server : other._serverList) {
150 valueProp = server->_clientListValue.containsByNamePtr(&other);
151 shapeProp = server->_clientListShape.containsByNamePtr(&other);
152 addServer(*server,valueProp,shapeProp) ;
153 }
154
155 setValueDirty() ;
156 setShapeDirty() ;
157}
158
159
160////////////////////////////////////////////////////////////////////////////////
161/// Destructor.
162
164{
165 // Notify all servers that they no longer need to serve us
166 while (!_serverList.empty()) {
167 removeServer(*_serverList.containedObjects().back(), true);
168 }
169
170 // Notify all clients that they are in limbo
171 std::vector<RooAbsArg*> clientListTmp(_clientList.begin(), _clientList.end()); // have to copy, as we invalidate iterators
172 bool first(true) ;
173 for (auto client : clientListTmp) {
174 client->setAttribute("ServerDied") ;
175 std::stringstream attr;
176 attr << "ServerDied:" << GetName() << "(" << reinterpret_cast<std::size_t>(this) << ")";
177 client->setAttribute(attr.str().c_str());
178 client->removeServer(*this,true);
179
180 if (_verboseDirty) {
181
182 if (first) {
183 cxcoutD(Tracing) << "RooAbsArg::dtor(" << GetName() << "," << this << ") DeleteWatch: object is being destroyed" << endl ;
184 first = false ;
185 }
186
187 cxcoutD(Tracing) << fName << "::" << ClassName() << ":~RooAbsArg: dependent \""
188 << client->GetName() << "\" should have been deleted first" << endl ;
189 }
190 }
191
192 if (_ownedComponents) {
193 delete _ownedComponents ;
194 _ownedComponents = nullptr ;
195 }
196
197}
198
199
200////////////////////////////////////////////////////////////////////////////////
201/// Control global dirty inhibit mode. When set to true no value or shape dirty
202/// flags are propagated and cache is always considered to be dirty.
203
205{
206 _inhibitDirty = flag ;
207}
208
209
210////////////////////////////////////////////////////////////////////////////////
211/// Activate verbose messaging related to dirty flag propagation
212
214{
215 _verboseDirty = flag ;
216}
217
218
219////////////////////////////////////////////////////////////////////////////////
220/// Set (default) or clear a named boolean attribute of this object.
221
223{
224 // Preserve backward compatibility - any strong
225 if(std::string{"Constant"} == name) {
227 }
228
229 if (value) {
230 _boolAttrib.insert(name) ;
231 } else {
232 set<string>::iterator iter = _boolAttrib.find(name) ;
233 if (iter != _boolAttrib.end()) {
234 _boolAttrib.erase(iter) ;
235 }
236
237 }
238
239}
240
241
242////////////////////////////////////////////////////////////////////////////////
243/// Check if a named attribute is set. By default, all attributes are unset.
244
246{
247 return (_boolAttrib.find(name) != _boolAttrib.end()) ;
248}
249
250
251////////////////////////////////////////////////////////////////////////////////
252/// Associate string 'value' to this object under key 'key'
253
255{
256 if (value) {
257 _stringAttrib[key] = value ;
258 } else {
260 }
261}
262
263////////////////////////////////////////////////////////////////////////////////
264/// Delete a string attribute with a given key.
265
267{
268 _stringAttrib.erase(key) ;
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// Get string attribute mapped under key 'key'. Returns null pointer
273/// if no attribute exists under that key
274
276{
277 map<string,string>::const_iterator iter = _stringAttrib.find(key) ;
278 if (iter!=_stringAttrib.end()) {
279 return iter->second.c_str() ;
280 } else {
281 return nullptr ;
282 }
283}
284
285
286////////////////////////////////////////////////////////////////////////////////
287/// Set (default) or clear a named boolean attribute of this object.
288
290{
291 if (value) {
292
293 _boolAttribTransient.insert(name) ;
294
295 } else {
296
297 set<string>::iterator iter = _boolAttribTransient.find(name) ;
298 if (iter != _boolAttribTransient.end()) {
299 _boolAttribTransient.erase(iter) ;
300 }
301
302 }
303
304}
305
306
307////////////////////////////////////////////////////////////////////////////////
308/// Check if a named attribute is set. By default, all attributes
309/// are unset.
310
312{
313 return (_boolAttribTransient.find(name) != _boolAttribTransient.end()) ;
314}
315
316
317
318
319////////////////////////////////////////////////////////////////////////////////
320/// Register another RooAbsArg as a server to us, ie, declare that
321/// we depend on it.
322/// \param server The server to be registered.
323/// \param valueProp In addition to the basic client-server relationship, declare dependence on the server's value.
324/// \param shapeProp In addition to the basic client-server relationship, declare dependence on the server's shape.
325/// \param refCount Optionally add with higher reference count (if multiple components depend on it)
326
327void RooAbsArg::addServer(RooAbsArg& server, bool valueProp, bool shapeProp, std::size_t refCount)
328{
330 cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName()
331 << "): PROHIBITED SERVER ADDITION REQUESTED: adding server " << server.GetName()
332 << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
333 throw std::logic_error("PROHIBITED SERVER ADDITION REQUESTED in RooAbsArg::addServer");
334 }
335
336 cxcoutD(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): adding server " << server.GetName()
337 << "(" << &server << ") for " << (valueProp?"value ":"") << (shapeProp?"shape":"") << endl ;
338
339 if (server.operMode()==ADirty && operMode()!=ADirty && valueProp) {
341 }
342
343
344 // LM: use hash tables for larger lists
345// if (_serverList.GetSize() > 999 && _serverList.getHashTableSize() == 0) _serverList.setHashTableSize(1000);
346// if (server._clientList.GetSize() > 999 && server._clientList.getHashTableSize() == 0) server._clientList.setHashTableSize(1000);
347// if (server._clientListValue.GetSize() > 999 && server._clientListValue.getHashTableSize() == 0) server._clientListValue.setHashTableSize(1000);
348
349 // Add server link to given server
350 _serverList.Add(&server, refCount) ;
351
352 server._clientList.Add(this, refCount);
353 if (valueProp) server._clientListValue.Add(this, refCount);
354 if (shapeProp) server._clientListShape.Add(this, refCount);
355}
356
357
358
359////////////////////////////////////////////////////////////////////////////////
360/// Register a list of RooAbsArg as servers to us by calling
361/// addServer() for each arg in the list
362
363void RooAbsArg::addServerList(RooAbsCollection& serverList, bool valueProp, bool shapeProp)
364{
365 _serverList.reserve(_serverList.size() + serverList.size());
366
367 for (const auto arg : serverList) {
368 addServer(*arg,valueProp,shapeProp) ;
369 }
370}
371
372
373
374////////////////////////////////////////////////////////////////////////////////
375/// Unregister another RooAbsArg as a server to us, ie, declare that
376/// we no longer depend on its value and shape.
377
378void RooAbsArg::removeServer(RooAbsArg& server, bool force)
379{
381 std::stringstream ss;
382 ss << "RooAbsArg::addServer(" << this << "," << GetName() << "): PROHIBITED SERVER REMOVAL REQUESTED: removing server "
383 << server.GetName() << "(" << &server << ")";
384 cxcoutF(LinkStateMgmt) << ss.str() << std::endl;
385 throw std::runtime_error(ss.str());
386 }
387
388 if (_verboseDirty) {
389 cxcoutD(LinkStateMgmt) << "RooAbsArg::removeServer(" << GetName() << "): removing server "
390 << server.GetName() << "(" << &server << ")" << endl ;
391 }
392
393 // Remove server link to given server
394 _serverList.Remove(&server, force) ;
395
396 server._clientList.Remove(this, force) ;
397 server._clientListValue.Remove(this, force) ;
398 server._clientListShape.Remove(this, force) ;
399}
400
401
402////////////////////////////////////////////////////////////////////////////////
403/// Replace 'oldServer' with 'newServer', specifying whether the new server has
404/// value or shape server properties.
405///
406/// \warning This function should not be used! This method is quite unsafe for
407/// many reasons. For once, the new server will be put at the end of the server
408/// list, no matter the position of the original server. This might mess up
409/// code that expects the servers to be in a certain order. Furthermore, the
410/// proxy objects corresponding to the server are not updated, leaving the
411/// object in an invalid state where the servers are out of sync with the
412/// proxies. This can have very bad consequences. Finally, by having to
413/// manually specify the value and shape server properties, it is very easy to
414/// get them wrong.
415///
416/// If you want to safely replace a server, you should use
417/// RooAbsArg::redirectServers(), which replaces the server in-place at the
418/// same position of the server list, keeps the same value and shape server
419/// properties, and also updates the corresponding proxies.
420
421void RooAbsArg::replaceServer(RooAbsArg& oldServer, RooAbsArg& newServer, bool propValue, bool propShape)
422{
423 coutW(LinkStateMgmt) << "replaceServer()"
424 << " is unsafe, because the server list will be out of sync with the proxy objects!"
425 << " If you want to safely replace a server, use RooAbsArg::redirectServers()."
426 << " See the docs to replaceServers() for more info." << std::endl;
427
428 Int_t count = _serverList.refCount(&oldServer);
429 removeServer(oldServer, true);
430
431 addServer(newServer, propValue, propShape, count);
432}
433
434
435////////////////////////////////////////////////////////////////////////////////
436/// Change dirty flag propagation mask for specified server
437
438void RooAbsArg::changeServer(RooAbsArg& server, bool valueProp, bool shapeProp)
439{
440 if (!_serverList.containsByNamePtr(&server)) {
441 coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
442 << server.GetName() << " not registered" << endl ;
443 return ;
444 }
445
446 // This condition should not happen, but check anyway
447 if (!server._clientList.containsByNamePtr(this)) {
448 coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server "
449 << server.GetName() << " doesn't have us registered as client" << endl ;
450 return ;
451 }
452
453 // Remove all propagation links, then reinstall requested ones ;
454 Int_t vcount = server._clientListValue.refCount(this) ;
455 Int_t scount = server._clientListShape.refCount(this) ;
456 server._clientListValue.RemoveAll(this) ;
457 server._clientListShape.RemoveAll(this) ;
458 if (valueProp) {
459 server._clientListValue.Add(this, vcount) ;
460 }
461 if (shapeProp) {
462 server._clientListShape.Add(this, scount) ;
463 }
464}
465
466
467
468////////////////////////////////////////////////////////////////////////////////
469/// Fill supplied list with all leaf nodes of the arg tree, starting with
470/// ourself as top node. A leaf node is node that has no servers declared.
471
472void RooAbsArg::leafNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, bool recurseNonDerived) const
473{
474 treeNodeServerList(list,arg,false,true,false,recurseNonDerived) ;
475}
476
477
478
479////////////////////////////////////////////////////////////////////////////////
480/// Fill supplied list with all branch nodes of the arg tree starting with
481/// ourself as top node. A branch node is node that has one or more servers declared.
482
483void RooAbsArg::branchNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, bool recurseNonDerived) const
484{
485 treeNodeServerList(list,arg,true,false,false,recurseNonDerived) ;
486}
487
488
489////////////////////////////////////////////////////////////////////////////////
490/// Fill supplied list with nodes of the arg tree, following all server links,
491/// starting with ourself as top node.
492/// \param[in] list Output list
493/// \param[in] arg Start searching at this element of the tree.
494/// \param[in] doBranch Add branch nodes to the list.
495/// \param[in] doLeaf Add leaf nodes to the list.
496/// \param[in] valueOnly Only check if an element is a value server (no shape server).
497/// \param[in] recurseFundamental
498
499void RooAbsArg::treeNodeServerList(RooAbsCollection* list, const RooAbsArg* arg, bool doBranch, bool doLeaf, bool valueOnly, bool recurseFundamental) const
500{
501// if (arg==0) {
502// cout << "treeNodeServerList(" << GetName() << ") doBranch=" << (doBranch?"T":"F") << " doLeaf = " << (doLeaf?"T":"F") << " valueOnly=" << (valueOnly?"T":"F") << endl ;
503// }
504
505 if (!arg) {
506 list->reserve(10);
507 arg=this ;
508 }
509
510 // Decide if to add current node
511 if ((doBranch&&doLeaf) ||
512 (doBranch&&arg->isDerived()) ||
513 (doLeaf&&arg->isFundamental()&&(!(recurseFundamental&&arg->isDerived()))) ||
514 (doLeaf && !arg->isFundamental() && !arg->isDerived())) {
515
516 list->add(*arg,true) ;
517 }
518
519 // Recurse if current node is derived
520 if (arg->isDerived() && (!arg->isFundamental() || recurseFundamental)) {
521 for (const auto server : arg->_serverList) {
522
523 // Skip non-value server nodes if requested
524 bool isValueSrv = server->_clientListValue.containsByNamePtr(arg);
525 if (valueOnly && !isValueSrv) {
526 continue ;
527 }
528 treeNodeServerList(list,server,doBranch,doLeaf,valueOnly,recurseFundamental) ;
529 }
530 }
531}
532
533
534////////////////////////////////////////////////////////////////////////////////
535/// Create a list of leaf nodes in the arg tree starting with
536/// ourself as top node that don't match any of the names of the variable list
537/// of the supplied data set (the dependents). The caller of this
538/// function is responsible for deleting the returned argset.
539/// The complement of this function is getObservables()
540
541RooFit::OwningPtr<RooArgSet> RooAbsArg::getParameters(const RooAbsData* set, bool stripDisconnected) const
542{
543 return getParameters(set?set->get():nullptr,stripDisconnected) ;
544}
545
546
547/// Return the parameters of this p.d.f when used in conjunction with dataset 'data'.
549{
550 return getParameters(&data,stripDisconnected) ;
551}
552
553
554/// Return the parameters of the p.d.f given the provided set of observables.
555RooFit::OwningPtr<RooArgSet> RooAbsArg::getParameters(const RooArgSet& observables, bool stripDisconnected) const
556{
557 return getParameters(&observables,stripDisconnected);
558}
559
560
561////////////////////////////////////////////////////////////////////////////////
562/// Create a list of leaf nodes in the arg tree starting with
563/// ourself as top node that don't match any of the names the args in the
564/// supplied argset. The caller of this function is responsible
565/// for deleting the returned argset. The complement of this function
566/// is getObservables().
567
568RooFit::OwningPtr<RooArgSet> RooAbsArg::getParameters(const RooArgSet* observables, bool stripDisconnected) const
569{
570 auto * outputSet = new RooArgSet;
571 getParameters(observables, *outputSet, stripDisconnected);
572 return RooFit::OwningPtr<RooArgSet>{outputSet};
573}
574
575
576////////////////////////////////////////////////////////////////////////////////
577/// Add all parameters of the function and its daughters to `params`.
578/// \param[in] params Collection that stores all parameters. Add all new parameters to this.
579/// \param[in] nset Normalisation set (optional). If a value depends on this set, it's not a parameter.
580/// \param[in] stripDisconnected Passed on to getParametersHook().
581
582void RooAbsArg::addParameters(RooAbsCollection& params, const RooArgSet* nset, bool stripDisconnected) const
583{
584
585 RooArgSet nodeParamServers;
586 std::vector<RooAbsArg*> branchList;
587 for (const auto server : _serverList) {
588 if (server->isValueServer(*this)) {
589 if (server->isFundamental()) {
590 if (!nset || !server->dependsOn(*nset)) {
591 nodeParamServers.add(*server);
592 }
593 } else {
594 branchList.push_back(server);
595 }
596 }
597 }
598
599 // Allow pdf to strip parameters from list before adding it
600 getParametersHook(nset,&nodeParamServers,stripDisconnected) ;
601
602 // Add parameters of this node to the combined list
603 params.add(nodeParamServers,true) ;
604
605 // Now recurse into branch servers
606 std::sort(branchList.begin(), branchList.end());
607 const auto last = std::unique(branchList.begin(), branchList.end());
608 for (auto serverIt = branchList.begin(); serverIt < last; ++serverIt) {
609 (*serverIt)->addParameters(params, nset);
610 }
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Obtain an estimate of the number of parameters of the function and its daughters.
615/// Calling `addParameters` for large functions (NLL) can cause many reallocations of
616/// `params` due to the recursive behaviour. This utility function aims to pre-compute
617/// the total number of parameters, so that enough memory is reserved.
618/// The estimate is not fully accurate (overestimate) as there is no equivalent to `getParametersHook`.
619/// \param[in] nset Normalisation set (optional). If a value depends on this set, it's not a parameter.
620
622{
623
624 std::size_t res = 0;
625 std::vector<RooAbsArg*> branchList;
626 for (const auto server : _serverList) {
627 if (server->isValueServer(*this)) {
628 if (server->isFundamental()) {
629 if (!nset || !server->dependsOn(*nset)) {
630 res++;
631 }
632 } else {
633 branchList.push_back(server);
634 }
635 }
636 }
637
638 // Now recurse into branch servers
639 std::sort(branchList.begin(), branchList.end());
640 const auto last = std::unique(branchList.begin(), branchList.end());
641 for (auto serverIt = branchList.begin(); serverIt < last; ++serverIt) {
642 res += (*serverIt)->getParametersSizeEstimate(nset);
643 }
644
645 return res;
646}
647
648
649////////////////////////////////////////////////////////////////////////////////
650/// Fills a list with leaf nodes in the arg tree starting with
651/// ourself as top node that don't match any of the names the args in the
652/// supplied argset. Returns `true` only if something went wrong.
653/// The complement of this function is getObservables().
654/// \param[in] observables Set of leaves to ignore because they are observables and not parameters.
655/// \param[out] outputSet Output set.
656/// \param[in] stripDisconnected Allow pdf to strip parameters from list before adding it.
657
658bool RooAbsArg::getParameters(const RooArgSet* observables, RooArgSet& outputSet, bool stripDisconnected) const
659{
661
662 // Check for cached parameter set
663 if (_myws) {
664 auto nsetObs = getColonSeparatedNameString(observables ? *observables : RooArgSet());
665 const RooArgSet *paramSet = _myws->set(Form("CACHE_PARAMS_OF_PDF_%s_FOR_OBS_%s", GetName(), nsetObs.c_str()));
666 if (paramSet) {
667 outputSet.add(*paramSet);
668 return false;
669 }
670 }
671
672 outputSet.clear();
673 outputSet.setName("parameters");
674
675 RooArgList tempList;
676 // reserve all memory needed in one go
677 tempList.reserve(getParametersSizeEstimate(observables));
678
679 addParameters(tempList, observables, stripDisconnected);
680
681 // The adding from the list to the set has to be silent to not complain
682 // about duplicate parameters. After all, it's normal that parameters can
683 // appear in sifferent components of the model.
684 outputSet.add(tempList, /*silent=*/true);
685 outputSet.sort();
686
687 // Cache parameter set
688 if (_myws && outputSet.size() > 10) {
689 auto nsetObs = getColonSeparatedNameString(observables ? *observables : RooArgSet());
690 _myws->defineSetInternal(Form("CACHE_PARAMS_OF_PDF_%s_FOR_OBS_%s", GetName(), nsetObs.c_str()), outputSet);
691 }
692
693 return false;
694}
695
696
697/// Given a set of possible observables, return the observables that this PDF depends on.
699{
700 return getObservables(&set, valueOnly);
701}
702
703/// Return the observables of this pdf given the observables defined by `data`.
705{
706 return getObservables(&data);
707}
708
709
710////////////////////////////////////////////////////////////////////////////////
711/// Create a list of leaf nodes in the arg tree starting with
712/// ourself as top node that match any of the names of the variable list
713/// of the supplied data set (the dependents). The caller of this
714/// function is responsible for deleting the returned argset.
715/// The complement of this function is getParameters().
716
718{
719 if (!set) return RooFit::OwningPtr<RooArgSet>{new RooArgSet};
720
721 return getObservables(set->get()) ;
722}
723
724
725////////////////////////////////////////////////////////////////////////////////
726/// Create a list of leaf nodes in the arg tree starting with
727/// ourself as top node that match any of the names the args in the
728/// supplied argset. The caller of this function is responsible
729/// for deleting the returned argset. The complement of this function
730/// is getParameters().
731
733{
734 auto depList = new RooArgSet;
735 getObservables(dataList, *depList, valueOnly);
736 return RooFit::OwningPtr<RooArgSet>{depList};
737}
738
739
740////////////////////////////////////////////////////////////////////////////////
741/// Create a list of leaf nodes in the arg tree starting with
742/// ourself as top node that match any of the names the args in the
743/// supplied argset.
744/// Returns `true` only if something went wrong.
745/// The complement of this function is getParameters().
746/// \param[in] dataList Set of leaf nodes to match.
747/// \param[out] outputSet Output set.
748/// \param[in] valueOnly If this parameter is true, we only match leaves that
749/// depend on the value of any arg in `dataList`.
750
751bool RooAbsArg::getObservables(const RooAbsCollection* dataList, RooArgSet& outputSet, bool valueOnly) const
752{
753 outputSet.clear();
754 outputSet.setName("dependents");
755
756 if (!dataList) return false;
757
758 // Make iterator over tree leaf node list
759 RooArgSet leafList("leafNodeServerList") ;
760 treeNodeServerList(&leafList,nullptr,false,true,valueOnly) ;
761
762 if (valueOnly) {
763 for (const auto arg : leafList) {
764 if (arg->dependsOnValue(*dataList) && arg->isLValue()) {
765 outputSet.add(*arg) ;
766 }
767 }
768 } else {
769 for (const auto arg : leafList) {
770 if (arg->dependsOn(*dataList) && arg->isLValue()) {
771 outputSet.add(*arg) ;
772 }
773 }
774 }
775
776 return false;
777}
778
779
780/// \deprecated Use getObservables()
782{
783 return getObservables(set);
784}
785
786/// \deprecated Use getObservables()
788{
789 return getObservables(set);
790}
791
792/// \deprecated Use getObservables()
794{
795 return getObservables(depList);
796}
797
798
799////////////////////////////////////////////////////////////////////////////////
800/// Create a RooArgSet with all components (branch nodes) of the
801/// expression tree headed by this object.
803{
804 RooArgSet* set = new RooArgSet((std::string(GetName()) + "_components").c_str()) ;
806
808}
809
810
811
812////////////////////////////////////////////////////////////////////////////////
813/// Overloadable function in which derived classes can implement
814/// consistency checks of the variables. If this function returns
815/// true, indicating an error, the fitter or generator will abort.
816
818{
819 return false ;
820}
821
822
823////////////////////////////////////////////////////////////////////////////////
824/// Recursively call checkObservables on all nodes in the expression tree
825
827{
828 RooArgSet nodeList ;
829 treeNodeServerList(&nodeList) ;
830
831 bool ret(false) ;
832 for(RooAbsArg * arg : nodeList) {
833 if (arg->getAttribute("ServerDied")) {
834 coutE(LinkStateMgmt) << "RooAbsArg::recursiveCheckObservables(" << GetName() << "): ERROR: one or more servers of node "
835 << arg->GetName() << " no longer exists!" << endl ;
836 arg->Print("v") ;
837 ret = true ;
838 }
839 ret |= arg->checkObservables(nset) ;
840 }
841
842 return ret ;
843}
844
845
846////////////////////////////////////////////////////////////////////////////////
847/// Test whether we depend on (ie, are served by) any object in the
848/// specified collection. Uses the dependsOn(RooAbsArg&) member function.
849
850bool RooAbsArg::dependsOn(const RooAbsCollection& serverList, const RooAbsArg* ignoreArg, bool valueOnly) const
851{
852 // Test whether we depend on (ie, are served by) any object in the
853 // specified collection. Uses the dependsOn(RooAbsArg&) member function.
854
855 for (auto server : serverList) {
856 if (dependsOn(*server,ignoreArg,valueOnly)) {
857 return true;
858 }
859 }
860 return false;
861}
862
863
864////////////////////////////////////////////////////////////////////////////////
865/// Test whether we depend on (ie, are served by) an object with a specific name.
866bool RooAbsArg::dependsOn(TNamed const* testArgNamePtr, const RooAbsArg* ignoreArg, bool valueOnly) const
867{
868 if (this==ignoreArg) return false ;
869
870 // First check if testArg is self
871 if (testArgNamePtr == namePtr()) return true ;
872
873 // Next test direct dependence
874 RooAbsArg *foundServer = _serverList.findByNamePointer(testArgNamePtr);
875 if (foundServer) {
876
877 // Return true if valueOnly is FALSE or if server is value server, otherwise keep looking
878 if ( !valueOnly || foundServer->isValueServer(*this)) {
879 return true ;
880 }
881 }
882
883 // If not, recurse
884 for (const auto server : _serverList) {
885 if ( !valueOnly || server->isValueServer(*this)) {
886 if (server->dependsOn(testArgNamePtr,ignoreArg,valueOnly)) {
887 return true ;
888 }
889 }
890 }
891
892 return false ;
893}
894
895
896
897////////////////////////////////////////////////////////////////////////////////
898/// Test if any of the nodes of tree are shared with that of the given tree
899
900bool RooAbsArg::overlaps(const RooAbsArg& testArg, bool valueOnly) const
901{
902 RooArgSet list("treeNodeList") ;
903 treeNodeServerList(&list) ;
904
905 return valueOnly ? testArg.dependsOnValue(list) : testArg.dependsOn(list) ;
906}
907
908
909
910////////////////////////////////////////////////////////////////////////////////
911/// Test if any of the dependents of the arg tree (as determined by getObservables)
912/// overlaps with those of the testArg.
913
914bool RooAbsArg::observableOverlaps(const RooAbsData* dset, const RooAbsArg& testArg) const
915{
916 return observableOverlaps(dset->get(),testArg) ;
917}
918
919
920////////////////////////////////////////////////////////////////////////////////
921/// Test if any of the dependents of the arg tree (as determined by getObservables)
922/// overlaps with those of the testArg.
923
924bool RooAbsArg::observableOverlaps(const RooArgSet* nset, const RooAbsArg& testArg) const
925{
926 return testArg.dependsOn(*std::unique_ptr<RooArgSet>{getObservables(nset)});
927}
928
929
930
931////////////////////////////////////////////////////////////////////////////////
932/// Mark this object as having changed its value, and propagate this status
933/// change to all of our clients. If the object is not in automatic dirty
934/// state propagation mode, this call has no effect.
935
937{
938 if (_operMode!=Auto || _inhibitDirty) return ;
939
940 // Handle no-propagation scenarios first
941 if (_clientListValue.empty()) {
942 _valueDirty = true ;
943 return ;
944 }
945
946 // Cyclical dependency interception
947 if (source==nullptr) {
948 source=this ;
949 } else if (source==this) {
950 // Cyclical dependency, abort
951 coutE(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << GetName()
952 << "): cyclical dependency detected, source = " << source->GetName() << endl ;
953 //assert(0) ;
954 return ;
955 }
956
957 // Propagate dirty flag to all clients if this is a down->up transition
958 if (_verboseDirty) {
959 cxcoutD(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << (source?source->GetName():"self") << "->" << GetName() << "," << this
960 << "): dirty flag " << (_valueDirty?"already ":"") << "raised" << endl ;
961 }
962
963 _valueDirty = true ;
964
965
966 for (auto client : _clientListValue) {
967 client->setValueDirty(source) ;
968 }
969
970
971}
972
973
974////////////////////////////////////////////////////////////////////////////////
975/// Mark this object as having changed its shape, and propagate this status
976/// change to all of our clients.
977
979{
980 if (_verboseDirty) {
981 cxcoutD(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
982 << "): dirty flag " << (_shapeDirty?"already ":"") << "raised" << endl ;
983 }
984
985 if (_clientListShape.empty()) {
986 _shapeDirty = true ;
987 return ;
988 }
989
990 // Set 'dirty' shape state for this object and propagate flag to all its clients
991 if (source==nullptr) {
992 source=this ;
993 } else if (source==this) {
994 // Cyclical dependency, abort
995 coutE(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName()
996 << "): cyclical dependency detected" << endl ;
997 return ;
998 }
999
1000 // Propagate dirty flag to all clients if this is a down->up transition
1001 _shapeDirty=true ;
1002
1003 for (auto client : _clientListShape) {
1004 client->setShapeDirty(source) ;
1005 client->setValueDirty(source) ;
1006 }
1007
1008}
1009
1010
1011
1012////////////////////////////////////////////////////////////////////////////////
1013/// Replace all direct servers of this object with the new servers in `newServerList`.
1014/// This substitutes objects that we receive values from with new objects that have the same name.
1015/// \see recursiveRedirectServers() Use recursive version if servers that are only indirectly serving this object should be replaced as well.
1016/// \see redirectServers() If only the direct servers of an object need to be replaced.
1017///
1018/// Note that changing the types of objects is generally allowed, but can be wrong if the interface of an object changes.
1019/// For example, one can reparametrise a model by substituting a variable with a function:
1020/// \f[
1021/// f(x\, |\, a) = a \cdot x \rightarrow f(x\, |\, b) = (2.1 \cdot b) \cdot x
1022/// \f]
1023/// If an object, however, expects a PDF, and this is substituted with a function that isn't normalised, wrong results might be obtained
1024/// or it might even crash the program. The types of the objects being substituted are not checked.
1025///
1026/// \param[in] newSetOrig Set of new servers that should be used instead of the current servers.
1027/// \param[in] mustReplaceAll A warning is printed and error status is returned if not all servers could be
1028/// substituted successfully.
1029/// \param[in] nameChange If false, an object named "x" is only replaced with an object also named "x" in `newSetOrig`.
1030/// If the object in `newSet` is called differently, set `nameChange` to true and use setAttribute() on the x object:
1031/// ```
1032/// objectToReplaceX.setAttribute("ORIGNAME:x")
1033/// ```
1034/// Now, the renamed object will be selected based on the attribute "ORIGNAME:<name>".
1035/// \param[in] isRecursionStep Internal switch used when called from recursiveRedirectServers().
1036bool RooAbsArg::redirectServers(const RooAbsCollection& newSetOrig, bool mustReplaceAll, bool nameChange, bool isRecursionStep)
1037{
1038 // Trivial case, no servers
1039 if (_serverList.empty()) return false ;
1040
1041 // We don't need to do anything if there are no new servers or if the only
1042 // new server is this RooAbsArg itself. And by returning early, we avoid
1043 // potentially annoying side effects of the redirectServersHook.
1044 if (newSetOrig.empty() || (newSetOrig.size() == 1 && newSetOrig[0] == this)) return false ;
1045
1046 // Strip any non-matching removal nodes from newSetOrig
1047 std::unique_ptr<RooArgSet> newSetOwned;
1048 RooAbsCollection const* newSet = &newSetOrig;
1049
1050 if (nameChange) {
1051 newSetOwned = std::make_unique<RooArgSet>();
1052 for (auto arg : *newSet) {
1053
1054 if (string("REMOVAL_DUMMY")==arg->GetName()) {
1055
1056 if (arg->getAttribute("REMOVE_ALL")) {
1057 newSetOwned->add(*arg) ;
1058 } else if (arg->getAttribute(Form("REMOVE_FROM_%s",getStringAttribute("ORIGNAME")))) {
1059 newSetOwned->add(*arg) ;
1060 }
1061 } else {
1062 newSetOwned->add(*arg) ;
1063 }
1064 }
1065 newSet = newSetOwned.get();
1066 }
1067
1068 // Replace current servers with new servers with the same name from the given list
1069 for (auto oldServer : _serverList) {
1070
1071 RooAbsArg * newServer= oldServer->findNewServer(*newSet, nameChange);
1072
1073 if (!newServer) {
1074 if (mustReplaceAll) {
1075 std::stringstream ss;
1076 ss << "RooAbsArg::redirectServers(" << (void*)this << "," << GetName() << "): server " << oldServer->GetName()
1077 << " (" << (void*)oldServer << ") not redirected" << (nameChange?"[nameChange]":"");
1078 const std::string errorMsg = ss.str();
1079 coutE(LinkStateMgmt) << errorMsg << std::endl;
1080 throw std::runtime_error(errorMsg);
1081 }
1082 continue ;
1083 }
1084
1085 if (newServer != this) {
1086 substituteServer(oldServer, newServer);
1087 }
1088 }
1089
1090 setValueDirty() ;
1091 setShapeDirty() ;
1092
1093 bool ret(false) ;
1094
1095 // Process the proxies
1096 for (int i=0 ; i<numProxies() ; i++) {
1097 RooAbsProxy* p = getProxy(i) ;
1098 if (!p) continue ;
1099 bool ret2 = p->changePointer(*newSet,nameChange,false) ;
1100
1101 if (mustReplaceAll && !ret2) {
1102 auto ap = dynamic_cast<const RooArgProxy*>(p);
1103 coutE(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName()
1104 << "): ERROR, proxy '" << p->name()
1105 << "' with arg '" << (ap ? ap->absArg()->GetName() : "<could not cast>") << "' could not be adjusted" << endl;
1106 ret = true ;
1107 }
1108 }
1109
1110 // Optional subclass post-processing
1111 ret |= callRedirectServersHook(*newSet, mustReplaceAll, nameChange, isRecursionStep);
1112 return ret;
1113}
1114
1115/// Private helper function for RooAbsArg::redirectServers().
1117{
1118 _serverList.Replace(oldServer, newServer);
1119
1120 const int clientListRefCount = oldServer->_clientList.Remove(this, true);
1121 const int clientListValueRefCount = oldServer->_clientListValue.Remove(this, true);
1122 const int clientListShapeRefCount = oldServer->_clientListShape.Remove(this, true);
1123
1124 newServer->_clientList.Add(this, clientListRefCount);
1125 newServer->_clientListValue.Add(this, clientListValueRefCount);
1126 newServer->_clientListShape.Add(this, clientListShapeRefCount);
1127
1128 if (clientListValueRefCount > 0 && newServer->operMode() == ADirty && operMode() != ADirty) {
1130 }
1131}
1132
1133/// Private helper function for RooAbsArg::redirectServers().
1134bool RooAbsArg::callRedirectServersHook(RooAbsCollection const &newSet, bool mustReplaceAll, bool nameChange,
1135 bool isRecursionStep)
1136{
1137 bool ret = false;
1138 for (Int_t i = 0; i < numCaches(); i++) {
1139 ret |= getCache(i)->redirectServersHook(newSet, mustReplaceAll, nameChange, isRecursionStep);
1140 }
1141 ret |= redirectServersHook(newSet, mustReplaceAll, nameChange, isRecursionStep);
1142
1143 return ret;
1144}
1145
1146////////////////////////////////////////////////////////////////////////////////
1147/// Replace some servers of this object. If there are proxies that correspond
1148/// to the replaced servers, these proxies are adjusted as well.
1149/// \param[in] replacements Map that specifies which args replace which servers.
1150bool RooAbsArg::redirectServers(std::unordered_map<RooAbsArg *, RooAbsArg *> const &replacements)
1151{
1152 bool ret(false);
1153 bool nameChange = false;
1154
1155 RooArgList newList;
1156
1157 // Replace current servers with new servers with the same name from the given list
1158 for (auto oldServer : _serverList) {
1159
1160 auto newServerFound = replacements.find(oldServer);
1161 RooAbsArg *newServer = newServerFound != replacements.end() ? newServerFound->second : nullptr;
1162
1163 if (!newServer || newServer == this) {
1164 continue;
1165 }
1166
1167 if (nameChange == false)
1168 nameChange = strcmp(newServerFound->first->GetName(), newServerFound->second->GetName()) != 0;
1169
1170 substituteServer(oldServer, newServer);
1171 newList.add(*newServer);
1172 }
1173
1174 // No servers were replaced, we don't need to process proxies and call the
1175 // redirectServersHook.
1176 if (newList.empty())
1177 return ret;
1178
1179 setValueDirty();
1180 setShapeDirty();
1181
1182 // Process the proxies
1183 for (int i = 0; i < numProxies(); i++) {
1184 if (RooAbsProxy *p = getProxy(i)) {
1185 p->changePointer(replacements);
1186 }
1187 }
1188
1189 // Optional subclass post-processing
1190 ret |= callRedirectServersHook(newList, false, nameChange, false);
1191 return ret;
1192}
1193
1194////////////////////////////////////////////////////////////////////////////////
1195/// Find the new server in the specified set that matches the old server.
1196///
1197/// \param[in] newSet Search this set by name for a new server.
1198/// \param[in] nameChange If true, search for an item with the bool attribute "ORIGNAME:<oldName>" set.
1199/// Use `<object>.setAttribute("ORIGNAME:<oldName>")` to set this attribute.
1200/// \return Pointer to the new server or `nullptr` if there's no unique match.
1201RooAbsArg *RooAbsArg::findNewServer(const RooAbsCollection &newSet, bool nameChange) const
1202{
1203 RooAbsArg *newServer = nullptr;
1204 if (!nameChange) {
1205 newServer = newSet.find(*this) ;
1206 }
1207 else {
1208 // Name changing server redirect:
1209 // use 'ORIGNAME:<oldName>' attribute instead of name of new server
1210 TString nameAttrib("ORIGNAME:") ;
1211 nameAttrib.Append(GetName()) ;
1212
1213 if (auto tmp = std::unique_ptr<RooAbsCollection>{newSet.selectByAttrib(nameAttrib,true)}) {
1214
1215 // Check if any match was found
1216 if (tmp->empty()) {
1217 return nullptr;
1218 }
1219
1220 // Check if match is unique
1221 if(tmp->size()>1) {
1222 std::stringstream ss;
1223 ss << "RooAbsArg::redirectServers(" << GetName() << "): FATAL Error, " << tmp->size() << " servers with "
1224 << nameAttrib << " attribute";
1225 coutF(LinkStateMgmt) << ss.str() << std::endl;
1226 tmp->Print("v") ;
1227 throw std::runtime_error(ss.str());
1228 }
1229
1230 // use the unique element in the set
1231 newServer= tmp->first();
1232 }
1233 }
1234 return newServer;
1235}
1236
1237
1238namespace {
1239
1240bool recursiveRedirectServersImpl(RooAbsArg *arg, RooAbsCollection const &newSet, bool mustReplaceAll, bool nameChange,
1241 bool recurseInNewSet, std::set<RooAbsArg const *> &callStack)
1242{
1243 // Cyclic recursion protection
1244 {
1245 auto it = callStack.lower_bound(arg);
1246 if (it != callStack.end() && arg == *it) {
1247 return false;
1248 }
1249 callStack.insert(it, arg);
1250 }
1251
1252 // Do not recurse into newset if not so specified
1253 // if (!recurseInNewSet && newSet.contains(*arg)) {
1254 // return false;
1255 // }
1256
1257 // Apply the redirectServers function recursively on all branch nodes in this argument tree.
1258 bool ret(false);
1259
1260 oocxcoutD(arg, LinkStateMgmt) << "RooAbsArg::recursiveRedirectServers(" << arg << "," << arg->GetName()
1261 << ") newSet = " << newSet << " mustReplaceAll = " << (mustReplaceAll ? "T" : "F")
1262 << " nameChange = " << (nameChange ? "T" : "F")
1263 << " recurseInNewSet = " << (recurseInNewSet ? "T" : "F") << endl;
1264
1265 // Do redirect on self (identify operation as recursion step)
1266 ret |= arg->redirectServers(newSet, mustReplaceAll, nameChange, true);
1267
1268 // Do redirect on servers
1269 for (const auto server : arg->servers()) {
1270 ret |= recursiveRedirectServersImpl(server, newSet, mustReplaceAll, nameChange, recurseInNewSet, callStack);
1271 }
1272
1273 callStack.erase(arg);
1274 return ret;
1275}
1276
1277} // namespace
1278
1279////////////////////////////////////////////////////////////////////////////////
1280/// Recursively replace all servers with the new servers in `newSet`.
1281/// This substitutes objects that we receive values from (also indirectly
1282/// through other objects) with new objects that have the same name.
1283///
1284/// *Copied from redirectServers:*
1285///
1286/// \copydetails RooAbsArg::redirectServers
1287/// \param newSet Roo collection
1288/// \param recurseInNewSet be recursive
1289bool RooAbsArg::recursiveRedirectServers(RooAbsCollection const &newSet, bool mustReplaceAll, bool nameChange,
1290 bool recurseInNewSet)
1291{
1292 // For cyclic recursion protection
1293 std::set<const RooAbsArg *> callStack;
1294
1295 return recursiveRedirectServersImpl(this, newSet, mustReplaceAll, nameChange, recurseInNewSet, callStack);
1296}
1297
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Function that is called at the end of redirectServers(). Can be overloaded
1301/// to inject some class-dependent behavior after server redirection, e.g.
1302/// resetting of caches. The return value is meant to be an error flag, so in
1303/// case something goes wrong the function should return `true`. If you
1304/// overload this function, don't forget to also call the function of the
1305/// base class.
1306///
1307/// \see redirectServers() For a detailed explanation of the function parameters.
1308///
1309// \param[in] newServerList One of the original parameters passed to redirectServers().
1310// \param[in] mustReplaceAll One of the original parameters passed to redirectServers().
1311// \param[in] nameChange One of the original parameters passed to redirectServers().
1312// \param[in] isRecursiveStep One of the original parameters passed to redirectServers().
1313bool RooAbsArg::redirectServersHook(const RooAbsCollection & /*newServerList*/, bool /*mustReplaceAll*/,
1314 bool /*nameChange*/, bool /*isRecursiveStep*/)
1315{
1316 setProxyNormSet(nullptr);
1317 return false;
1318}
1319
1320
1321
1322////////////////////////////////////////////////////////////////////////////////
1323/// Register an RooArgProxy in the proxy list. This function is called by owned
1324/// proxies upon creation. After registration, this arg will forward pointer
1325/// changes from serverRedirects and updates in cached normalization sets
1326/// to the proxies immediately after they occur. The proxied argument is
1327/// also added as value and/or shape server
1328
1330{
1331 // Every proxy can be registered only once
1332 if (_proxyList.FindObject(&proxy)) {
1333 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1334 << proxy.GetName() << " for arg " << proxy.absArg()->GetName()
1335 << " already registered" << endl ;
1336 return ;
1337 }
1338
1339// cout << (void*)this << " " << GetName() << ": registering proxy "
1340// << (void*)&proxy << " with name " << proxy.name() << " in mode "
1341// << (proxy.isValueServer()?"V":"-") << (proxy.isShapeServer()?"S":"-") << endl ;
1342
1343 // Register proxied object as server
1344 if (proxy.absArg()) {
1345 addServer(*proxy.absArg(),proxy.isValueServer(),proxy.isShapeServer()) ;
1346 }
1347
1348 // Register proxy itself
1349 _proxyList.Add(&proxy) ;
1350 _proxyListCache.isDirty = true;
1351}
1352
1353
1354////////////////////////////////////////////////////////////////////////////////
1355/// Remove proxy from proxy list. This functions is called by owned proxies
1356/// upon their destruction.
1357
1359{
1360 _proxyList.Remove(&proxy) ;
1362 _proxyListCache.isDirty = true;
1363}
1364
1365
1366
1367////////////////////////////////////////////////////////////////////////////////
1368/// Register an RooSetProxy in the proxy list. This function is called by owned
1369/// proxies upon creation. After registration, this arg will forward pointer
1370/// changes from serverRedirects and updates in cached normalization sets
1371/// to the proxies immediately after they occur.
1372
1374{
1375 // Every proxy can be registered only once
1376 if (_proxyList.FindObject(&proxy)) {
1377 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1378 << proxy.GetName() << " already registered" << endl ;
1379 return ;
1380 }
1381
1382 // Register proxy itself
1383 _proxyList.Add(&proxy) ;
1384 _proxyListCache.isDirty = true;
1385}
1386
1387
1388
1389////////////////////////////////////////////////////////////////////////////////
1390/// Remove proxy from proxy list. This functions is called by owned proxies
1391/// upon their destruction.
1392
1394{
1395 _proxyList.Remove(&proxy) ;
1397 _proxyListCache.isDirty = true;
1398}
1399
1400
1401
1402////////////////////////////////////////////////////////////////////////////////
1403/// Register an RooListProxy in the proxy list. This function is called by owned
1404/// proxies upon creation. After registration, this arg will forward pointer
1405/// changes from serverRedirects and updates in cached normalization sets
1406/// to the proxies immediately after they occur.
1407
1409{
1410 // Every proxy can be registered only once
1411 if (_proxyList.FindObject(&proxy)) {
1412 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named "
1413 << proxy.GetName() << " already registered" << endl ;
1414 return ;
1415 }
1416
1417 // Register proxy itself
1418 Int_t nProxyOld = _proxyList.GetEntries() ;
1419 _proxyList.Add(&proxy) ;
1420 _proxyListCache.isDirty = true;
1421 if (_proxyList.GetEntries()!=nProxyOld+1) {
1422 cout << "RooAbsArg::registerProxy(" << GetName() << ") proxy registration failure! nold=" << nProxyOld << " nnew=" << _proxyList.GetEntries() << endl ;
1423 }
1424}
1425
1426
1427
1428////////////////////////////////////////////////////////////////////////////////
1429/// Remove proxy from proxy list. This functions is called by owned proxies
1430/// upon their destruction.
1431
1433{
1434 _proxyList.Remove(&proxy) ;
1436 _proxyListCache.isDirty = true;
1437}
1438
1439
1440
1441////////////////////////////////////////////////////////////////////////////////
1442/// Return the nth proxy from the proxy list.
1443
1445{
1446 // Cross cast: proxy list returns TObject base pointer, we need
1447 // a RooAbsProxy base pointer. C++ standard requires
1448 // a dynamic_cast for this.
1449 return dynamic_cast<RooAbsProxy*> (_proxyList.At(index)) ;
1450}
1451
1452
1453
1454////////////////////////////////////////////////////////////////////////////////
1455/// Return the number of registered proxies.
1456
1458{
1459 return _proxyList.GetEntriesFast();
1460}
1461
1462
1463
1464////////////////////////////////////////////////////////////////////////////////
1465/// Forward a change in the cached normalization argset
1466/// to all the registered proxies.
1467
1469{
1471 // First time we loop over proxies: cache the results to avoid future
1472 // costly dynamic_casts
1473 _proxyListCache.cache.clear();
1474 for (int i=0 ; i<numProxies() ; i++) {
1475 RooAbsProxy* p = getProxy(i) ;
1476 if (!p) continue ;
1477 _proxyListCache.cache.push_back(p);
1478 }
1479 _proxyListCache.isDirty = false;
1480 }
1481
1482 for ( auto& p : _proxyListCache.cache ) {
1483 p->changeNormSet(nset);
1484 }
1485
1486 // If the proxy normSet changed, we also have to set our value dirty flag.
1487 // Otherwise, value for the new normalization set might not get recomputed!
1488 setValueDirty();
1489}
1490
1491
1492
1493////////////////////////////////////////////////////////////////////////////////
1494/// Overloadable function for derived classes to implement
1495/// attachment as branch to a TTree
1496
1498{
1499 coutE(Contents) << "RooAbsArg::attachToTree(" << GetName()
1500 << "): Cannot be attached to a TTree" << endl ;
1501}
1502
1503
1504
1505////////////////////////////////////////////////////////////////////////////////
1506/// WVE (08/21/01) Probably obsolete now
1507
1509{
1510 return true ;
1511}
1512
1513
1514
1515
1516////////////////////////////////////////////////////////////////////////////////
1517/// Print object name
1518
1519void RooAbsArg::printName(ostream& os) const
1520{
1521 os << GetName() ;
1522}
1523
1524
1525
1526////////////////////////////////////////////////////////////////////////////////
1527/// Print object title
1528
1529void RooAbsArg::printTitle(ostream& os) const
1530{
1531 os << GetTitle() ;
1532}
1533
1534
1535
1536////////////////////////////////////////////////////////////////////////////////
1537/// Print object class name
1538
1539void RooAbsArg::printClassName(ostream& os) const
1540{
1541 os << ClassName() ;
1542}
1543
1544
1545/// Print address of this RooAbsArg.
1546void RooAbsArg::printAddress(ostream& os) const
1547{
1548 os << this ;
1549}
1550
1551
1552
1553////////////////////////////////////////////////////////////////////////////////
1554/// Print object arguments, ie its proxies
1555
1556void RooAbsArg::printArgs(ostream& os) const
1557{
1558 // Print nothing if there are no dependencies
1559 if (numProxies()==0) return ;
1560
1561 os << "[ " ;
1562 for (Int_t i=0 ; i<numProxies() ; i++) {
1563 RooAbsProxy* p = getProxy(i) ;
1564 if (p==nullptr) continue ;
1565 if (!TString(p->name()).BeginsWith("!")) {
1566 p->print(os) ;
1567 os << " " ;
1568 }
1569 }
1570 printMetaArgs(os) ;
1571 os << "]" ;
1572}
1573
1574
1575
1576////////////////////////////////////////////////////////////////////////////////
1577/// Define default contents to print
1578
1580{
1581 return kName|kClassName|kValue|kArgs ;
1582}
1583
1584
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Implement multi-line detailed printing
1588
1589void RooAbsArg::printMultiline(ostream& os, Int_t /*contents*/, bool /*verbose*/, TString indent) const
1590{
1591 os << indent << "--- RooAbsArg ---" << endl;
1592 // dirty state flags
1593 os << indent << " Value State: " ;
1594 switch(_operMode) {
1595 case ADirty: os << "FORCED DIRTY" ; break ;
1596 case AClean: os << "FORCED clean" ; break ;
1597 case Auto: os << (isValueDirty() ? "DIRTY":"clean") ; break ;
1598 }
1599 os << endl
1600 << indent << " Shape State: " << (isShapeDirty() ? "DIRTY":"clean") << endl;
1601 // attribute list
1602 os << indent << " Attributes: " ;
1603 printAttribList(os) ;
1604 os << endl ;
1605 // our memory address (for x-referencing with client addresses of other args)
1606 os << indent << " Address: " << (void*)this << endl;
1607 // client list
1608 os << indent << " Clients: " << endl;
1609 for (const auto client : _clientList) {
1610 os << indent << " (" << (void*)client << ","
1611 << (_clientListValue.containsByNamePtr(client)?"V":"-")
1612 << (_clientListShape.containsByNamePtr(client)?"S":"-")
1613 << ") " ;
1614 client->printStream(os,kClassName|kTitle|kName,kSingleLine);
1615 }
1616
1617 // server list
1618 os << indent << " Servers: " << endl;
1619 for (const auto server : _serverList) {
1620 os << indent << " (" << (void*)server << ","
1621 << (server->_clientListValue.containsByNamePtr(this)?"V":"-")
1622 << (server->_clientListShape.containsByNamePtr(this)?"S":"-")
1623 << ") " ;
1624 server->printStream(os,kClassName|kName|kTitle,kSingleLine);
1625 }
1626
1627 // proxy list
1628 os << indent << " Proxies: " << std::endl;
1629 for (int i=0 ; i<numProxies() ; i++) {
1630 RooAbsProxy* proxy=getProxy(i) ;
1631 if (!proxy) continue ;
1632 os << indent << " " << proxy->name() << " -> " ;
1633 if(auto * argProxy = dynamic_cast<RooArgProxy*>(proxy)) {
1634 if (RooAbsArg* parg = argProxy->absArg()) {
1635 parg->printStream(os,kName,kSingleLine) ;
1636 } else {
1637 os << " (empty)" << std::endl;
1638 }
1639 // If a RooAbsProxy is not a RooArgProxy, it is a RooSetProxy or a
1640 // RooListProxy. However, they are treated the same in this function, so
1641 // we try the dynamic cast to their common base class, RooAbsCollection.
1642 } else if(auto * collProxy = dynamic_cast<RooAbsCollection*>(proxy)) {
1643 os << std::endl;
1644 TString moreIndent(indent) ;
1645 moreIndent.Append(" ") ;
1646 collProxy->printStream(os,kName,kStandard,moreIndent.Data());
1647 } else {
1648 throw std::runtime_error("Unsupported proxy type.");
1649 }
1650 }
1651}
1652
1653
1654////////////////////////////////////////////////////////////////////////////////
1655/// Print object tree structure
1656
1657void RooAbsArg::printTree(ostream& os, TString /*indent*/) const
1658{
1659 const_cast<RooAbsArg*>(this)->printCompactTree(os) ;
1660}
1661
1662
1663////////////////////////////////////////////////////////////////////////////////
1664/// Ostream operator
1665
1666ostream& operator<<(ostream& os, RooAbsArg const& arg)
1667{
1668 arg.writeToStream(os,true) ;
1669 return os ;
1670}
1671
1672////////////////////////////////////////////////////////////////////////////////
1673/// Istream operator
1674
1675istream& operator>>(istream& is, RooAbsArg &arg)
1676{
1677 arg.readFromStream(is,true,false) ;
1678 return is ;
1679}
1680
1681////////////////////////////////////////////////////////////////////////////////
1682/// Print the attribute list
1683
1684void RooAbsArg::printAttribList(ostream& os) const
1685{
1686 set<string>::const_iterator iter = _boolAttrib.begin() ;
1687 bool first(true) ;
1688 while (iter != _boolAttrib.end()) {
1689 os << (first?" [":",") << *iter ;
1690 first=false ;
1691 ++iter ;
1692 }
1693 if (!first) os << "] " ;
1694}
1695
1696
1697////////////////////////////////////////////////////////////////////////////////
1698/// Bind this node to objects in `set`.
1699/// Search the set for objects that have the same name as our servers, and
1700/// attach ourselves to those. After this operation, this node is computing its
1701/// values based on the new servers. This can be used to e.g. read values from
1702// a dataset.
1703
1704
1706{
1707 RooArgSet branches;
1708 branchNodeServerList(&branches,nullptr,true);
1709
1710 for(auto const& branch : branches) {
1711 branch->redirectServers(set,false,false);
1712 }
1713}
1714
1715
1716////////////////////////////////////////////////////////////////////////////////
1717/// Replace server nodes with names matching the dataset variable names
1718/// with those data set variables, making this PDF directly dependent on the dataset.
1719
1721{
1722 attachArgs(*data.get());
1723}
1724
1725
1726////////////////////////////////////////////////////////////////////////////////
1727/// Replace server nodes with names matching the dataset variable names
1728/// with those data set variables, making this PDF directly dependent on the dataset
1729
1731{
1732 attachArgs(*dstore.get());
1733}
1734
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Utility function used by TCollection::Sort to compare contained TObjects
1738/// We implement comparison by name, resulting in alphabetical sorting by object name.
1739
1741{
1742 return strcmp(GetName(),other->GetName()) ;
1743}
1744
1745
1746
1747////////////////////////////////////////////////////////////////////////////////
1748/// Print information about current value dirty state information.
1749/// If depth flag is true, information is recursively printed for
1750/// all nodes in this arg tree.
1751
1752void RooAbsArg::printDirty(bool depth) const
1753{
1754 if (depth) {
1755
1756 RooArgSet branchList ;
1757 branchNodeServerList(&branchList) ;
1758 for(RooAbsArg * branch : branchList) {
1759 branch->printDirty(false) ;
1760 }
1761
1762 } else {
1763 cout << GetName() << " : " ;
1764 switch (_operMode) {
1765 case AClean: cout << "FORCED clean" ; break ;
1766 case ADirty: cout << "FORCED DIRTY" ; break ;
1767 case Auto: cout << "Auto " << (isValueDirty()?"DIRTY":"clean") ;
1768 }
1769 cout << endl ;
1770 }
1771}
1772
1773
1774////////////////////////////////////////////////////////////////////////////////
1775/// Activate cache mode optimization with given definition of observables.
1776/// The cache operation mode of all objects in the expression tree will
1777/// modified such that all nodes that depend directly or indirectly on
1778/// any of the listed observables will be set to ADirty, as they are
1779/// expected to change every time. This save change tracking overhead for
1780/// nodes that are a priori known to change every time
1781
1783{
1784 RooLinkedList proc;
1785 RooArgSet opt ;
1786 optimizeCacheMode(observables,opt,proc) ;
1787
1788 coutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") nodes " << opt << " depend on observables, "
1789 << "changing cache operation mode from change tracking to unconditional evaluation" << endl ;
1790}
1791
1792
1793////////////////////////////////////////////////////////////////////////////////
1794/// Activate cache mode optimization with given definition of observables.
1795/// The cache operation mode of all objects in the expression tree will
1796/// modified such that all nodes that depend directly or indirectly on
1797/// any of the listed observables will be set to ADirty, as they are
1798/// expected to change every time. This save change tracking overhead for
1799/// nodes that are a priori known to change every time
1800
1801void RooAbsArg::optimizeCacheMode(const RooArgSet& observables, RooArgSet& optimizedNodes, RooLinkedList& processedNodes)
1802{
1803 // Optimization applies only to branch nodes, not to leaf nodes
1804 if (!isDerived()) {
1805 return ;
1806 }
1807
1808
1809 // Terminate call if this node was already processed (tree structure may be cyclical)
1810 // LM : RooLinkedList::findArg looks by name and not but by object pointer,
1811 // should one use RooLinkedList::FindObject (look byt pointer) instead of findArg when
1812 // tree contains nodes with the same name ?
1813 // Add an info message if the require node does not exist but a different node already exists with same name
1814
1815 if (processedNodes.FindObject(this))
1816 return;
1817
1818 // check if findArgs returns something different (i.e. a different node with same name) when
1819 // this node has not been processed (FindObject returns a null pointer)
1820 auto obj = processedNodes.findArg(this);
1821 assert(obj != this); // obj == this cannot happen
1822 if (obj) {
1823 // here for nodes with duplicate names
1824 cxcoutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << " node " << this << " exists already as "
1825 << obj << " but with the SAME name !" << endl;
1826 }
1827
1828 processedNodes.Add(this);
1829
1830 // Set cache mode operator to 'AlwaysDirty' if we depend on any of the given observables
1831 if (dependsOnValue(observables)) {
1832
1833 if (dynamic_cast<RooRealIntegral*>(this)) {
1834 cxcoutI(Integration) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") integral depends on value of one or more observables and will be evaluated for every event" << endl ;
1835 }
1836 optimizedNodes.add(*this,true) ;
1837 if (operMode()==AClean) {
1838 } else {
1839 setOperMode(ADirty,true) ; // WVE propagate flag recursively to top of tree
1840 }
1841 } else {
1842 }
1843 // Process any RooAbsArgs contained in any of the caches of this object
1844 for (Int_t i=0 ;i<numCaches() ; i++) {
1845 getCache(i)->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
1846 }
1847
1848 // Forward calls to all servers
1849 for (const auto server : _serverList) {
1850 server->optimizeCacheMode(observables,optimizedNodes,processedNodes) ;
1851 }
1852
1853}
1854
1855////////////////////////////////////////////////////////////////////////////////
1856/// Find branch nodes with all-constant parameters, and add them to the list of
1857/// nodes that can be cached with a dataset in a test statistic calculation
1858
1859bool RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList)
1860{
1861 RooLinkedList proc ;
1862 bool ret = findConstantNodes(observables,cacheList,proc) ;
1863
1864 // If node can be optimized and hasn't been identified yet, add it to the list
1865 coutI(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << "): components "
1866 << cacheList << " depend exclusively on constant parameters and will be precalculated and cached" << endl ;
1867
1868 return ret ;
1869}
1870
1871
1872
1873////////////////////////////////////////////////////////////////////////////////
1874/// Find branch nodes with all-constant parameters, and add them to the list of
1875/// nodes that can be cached with a dataset in a test statistic calculation
1876
1877bool RooAbsArg::findConstantNodes(const RooArgSet& observables, RooArgSet& cacheList, RooLinkedList& processedNodes)
1878{
1879 // Caching only applies to branch nodes
1880 if (!isDerived()) {
1881 return false;
1882 }
1883
1884 // Terminate call if this node was already processed (tree structure may be cyclical)
1885 if (processedNodes.findArg(this)) {
1886 return false ;
1887 } else {
1888 processedNodes.Add(this) ;
1889 }
1890
1891 // Check if node depends on any non-constant parameter
1892 bool canOpt(true) ;
1893 RooArgSet paramSet;
1894 getParameters(&observables, paramSet);
1895 for(RooAbsArg * param : paramSet) {
1896 if (!param->isConstant()) {
1897 canOpt=false ;
1898 break ;
1899 }
1900 }
1901
1902
1903 if (getAttribute("NeverConstant")) {
1904 canOpt = false ;
1905 }
1906
1907 if (canOpt) {
1908 setAttribute("ConstantExpression") ;
1909 }
1910
1911 // If yes, list node eligible for caching, if not test nodes one level down
1912 if (canOpt||getAttribute("CacheAndTrack")) {
1913
1914 if (!cacheList.find(*this) && dependsOnValue(observables) && !observables.find(*this) ) {
1915
1916 // Add to cache list
1917 cxcoutD(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << ") adding self to list of constant nodes" << endl ;
1918
1919 if (canOpt) setAttribute("ConstantExpressionCached") ;
1920 cacheList.add(*this,false) ;
1921 }
1922 }
1923
1924 if (!canOpt) {
1925
1926 // If not, see if next level down can be cached
1927 for (const auto server : _serverList) {
1928 if (server->isDerived()) {
1929 server->findConstantNodes(observables,cacheList,processedNodes) ;
1930 }
1931 }
1932 }
1933
1934 // Forward call to all cached contained in current object
1935 for (Int_t i=0 ;i<numCaches() ; i++) {
1936 getCache(i)->findConstantNodes(observables,cacheList,processedNodes) ;
1937 }
1938
1939 return false ;
1940}
1941
1942
1943
1944
1945////////////////////////////////////////////////////////////////////////////////
1946/// Interface function signaling a request to perform constant term
1947/// optimization. This default implementation takes no action other than to
1948/// forward the calls to all servers
1949
1950void RooAbsArg::constOptimizeTestStatistic(ConstOpCode opcode, bool doAlsoTrackingOpt)
1951{
1952 for (const auto server : _serverList) {
1953 server->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt) ;
1954 }
1955}
1956
1957
1958////////////////////////////////////////////////////////////////////////////////
1959/// Change cache operation mode to given mode. If recurseAdirty
1960/// is true, then a mode change to AlwaysDirty will automatically
1961/// be propagated recursively to all client nodes
1962
1963void RooAbsArg::setOperMode(OperMode mode, bool recurseADirty)
1964{
1965 // Prevent recursion loops
1966 if (mode==_operMode) return ;
1967
1968 _operMode = mode ;
1969 _fast = ((mode==AClean) || dynamic_cast<RooRealVar*>(this) || dynamic_cast<RooConstVar*>(this) ) ;
1970 for (Int_t i=0 ;i<numCaches() ; i++) {
1971 getCache(i)->operModeHook() ;
1972 }
1973 operModeHook() ;
1974
1975 // Propagate to all clients
1976 if (mode==ADirty && recurseADirty) {
1977 for (auto clientV : _clientListValue) {
1978 clientV->setOperMode(mode) ;
1979 }
1980 }
1981}
1982
1983
1984////////////////////////////////////////////////////////////////////////////////
1985/// Print tree structure of expression tree on stdout, or to file if filename is specified.
1986/// If namePat is not "*", only nodes with names matching the pattern will be printed.
1987/// The client argument is used in recursive calls to properly display the value or shape nature
1988/// of the client-server links. It should be zero in calls initiated by users.
1989
1990void RooAbsArg::printCompactTree(const char* indent, const char* filename, const char* namePat, RooAbsArg* client)
1991{
1992 if (filename) {
1993 ofstream ofs(filename) ;
1994 printCompactTree(ofs,indent,namePat,client) ;
1995 } else {
1996 printCompactTree(cout,indent,namePat,client) ;
1997 }
1998}
1999
2000
2001////////////////////////////////////////////////////////////////////////////////
2002/// Print tree structure of expression tree on given ostream.
2003/// If namePat is not "*", only nodes with names matching the pattern will be printed.
2004/// The client argument is used in recursive calls to properly display the value or shape nature
2005/// of the client-server links. It should be zero in calls initiated by users.
2006
2007void RooAbsArg::printCompactTree(ostream& os, const char* indent, const char* namePat, RooAbsArg* client)
2008{
2009 if ( !namePat || TString(GetName()).Contains(namePat)) {
2010 os << indent << this ;
2011 if (client) {
2012 os << "/" ;
2013 if (isValueServer(*client)) os << "V" ; else os << "-" ;
2014 if (isShapeServer(*client)) os << "S" ; else os << "-" ;
2015 }
2016 os << " " ;
2017
2018 os << ClassName() << "::" << GetName() << " = " ;
2019 printValue(os) ;
2020
2021 if (!_serverList.empty()) {
2022 switch(operMode()) {
2023 case Auto: os << " [Auto," << (isValueDirty()?"Dirty":"Clean") << "] " ; break ;
2024 case AClean: os << " [ACLEAN] " ; break ;
2025 case ADirty: os << " [ADIRTY] " ; break ;
2026 }
2027 }
2028 os << endl ;
2029
2030 for (Int_t i=0 ;i<numCaches() ; i++) {
2032 }
2034 }
2035
2036 TString indent2(indent) ;
2037 indent2 += " " ;
2038 for (const auto arg : _serverList) {
2039 arg->printCompactTree(os,indent2,namePat,this) ;
2040 }
2041}
2042
2043
2044////////////////////////////////////////////////////////////////////////////////
2045/// Print tree structure of expression tree on given ostream, only branch nodes are printed.
2046/// Lead nodes (variables) will not be shown
2047///
2048/// If namePat is not "*", only nodes with names matching the pattern will be printed.
2049
2050void RooAbsArg::printComponentTree(const char* indent, const char* namePat, Int_t nLevel)
2051{
2052 if (nLevel==0) return ;
2053 if (isFundamental()) return ;
2054 auto rmodel = dynamic_cast<RooResolutionModel*>(this) ;
2055 if (rmodel && rmodel->isConvolved()) return ;
2056 if (InheritsFrom("RooConstVar")) return ;
2057
2058 if ( !namePat || TString(GetName()).Contains(namePat)) {
2059 cout << indent ;
2060 Print() ;
2061 }
2062
2063 TString indent2(indent) ;
2064 indent2 += " " ;
2065 for (const auto arg : _serverList) {
2066 arg->printComponentTree(indent2.Data(),namePat,nLevel-1) ;
2067 }
2068}
2069
2070
2071////////////////////////////////////////////////////////////////////////////////
2072/// Construct a mangled name from the actual name that
2073/// is free of any math symbols that might be interpreted by TTree
2074
2076{
2077 // Check for optional alternate name of branch for this argument
2078 TString rawBranchName = GetName() ;
2079 if (getStringAttribute("BranchName")) {
2080 rawBranchName = getStringAttribute("BranchName") ;
2081 }
2082
2083 TString cleanName(rawBranchName) ;
2084 cleanName.ReplaceAll("/","D") ;
2085 cleanName.ReplaceAll("-","M") ;
2086 cleanName.ReplaceAll("+","P") ;
2087 cleanName.ReplaceAll("*","X") ;
2088 cleanName.ReplaceAll("[","L") ;
2089 cleanName.ReplaceAll("]","R") ;
2090 cleanName.ReplaceAll("(","L") ;
2091 cleanName.ReplaceAll(")","R") ;
2092 cleanName.ReplaceAll("{","L") ;
2093 cleanName.ReplaceAll("}","R") ;
2094
2095 return cleanName;
2096}
2097
2098
2099////////////////////////////////////////////////////////////////////////////////
2100/// Hook function interface for object to insert additional information
2101/// when printed in the context of a tree structure. This default
2102/// implementation prints nothing
2103
2104void RooAbsArg::printCompactTreeHook(ostream&, const char *)
2105{
2106}
2107
2108
2109////////////////////////////////////////////////////////////////////////////////
2110/// Register RooAbsCache with this object. This function is called
2111/// by RooAbsCache constructors for objects that are a datamember
2112/// of this RooAbsArg. By registering itself the RooAbsArg is aware
2113/// of all its cache data members and will forward server change
2114/// and cache mode change calls to the cache objects, which in turn
2115/// can forward them their contents
2116
2118{
2119 _cacheList.push_back(&cache) ;
2120}
2121
2122
2123////////////////////////////////////////////////////////////////////////////////
2124/// Unregister a RooAbsCache. Called from the RooAbsCache destructor
2125
2127{
2128 _cacheList.erase(std::remove(_cacheList.begin(), _cacheList.end(), &cache),
2129 _cacheList.end());
2130}
2131
2132
2133////////////////////////////////////////////////////////////////////////////////
2134/// Return number of registered caches
2135
2137{
2138 return _cacheList.size() ;
2139}
2140
2141
2142////////////////////////////////////////////////////////////////////////////////
2143/// Return registered cache object by index
2144
2146{
2147 return _cacheList[index] ;
2148}
2149
2150
2151////////////////////////////////////////////////////////////////////////////////
2152/// Return RooArgSet with all variables (tree leaf nodes of expression tree)
2153
2155{
2156 return getParameters(RooArgSet(),stripDisconnected) ;
2157}
2158
2159
2160////////////////////////////////////////////////////////////////////////////////
2161/// Create a GraphViz .dot file visualizing the expression tree headed by
2162/// this RooAbsArg object. Use the GraphViz tool suite to make e.g. a gif
2163/// or ps file from the .dot file.
2164/// If a node derives from RooAbsReal, its current (unnormalised) value is
2165/// printed as well.
2166///
2167/// Based on concept developed by Kyle Cranmer.
2168
2169void RooAbsArg::graphVizTree(const char* fileName, const char* delimiter, bool useTitle, bool useLatex)
2170{
2171 ofstream ofs(fileName) ;
2172 if (!ofs) {
2173 coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: Cannot open graphViz output file with name " << fileName << endl ;
2174 return ;
2175 }
2176 graphVizTree(ofs, delimiter, useTitle, useLatex) ;
2177}
2178
2179////////////////////////////////////////////////////////////////////////////////
2180/// Write the GraphViz representation of the expression tree headed by
2181/// this RooAbsArg object to the given ostream.
2182/// If a node derives from RooAbsReal, its current (unnormalised) value is
2183/// printed as well.
2184///
2185/// Based on concept developed by Kyle Cranmer.
2186
2187void RooAbsArg::graphVizTree(ostream& os, const char* delimiter, bool useTitle, bool useLatex)
2188{
2189 if (!os) {
2190 coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: output stream provided as input argument is in invalid state" << endl ;
2191 }
2192
2193 // silent warning messages coming when evaluating a RooAddPdf without a normalization set
2195
2196 // Write header
2197 os << "digraph \"" << GetName() << "\"{" << endl ;
2198
2199 // First list all the tree nodes
2200 RooArgSet nodeSet ;
2201 treeNodeServerList(&nodeSet) ;
2202
2203 // iterate over nodes
2204 for(RooAbsArg * node : nodeSet) {
2205 string nodeName = node->GetName();
2206 string nodeTitle = node->GetTitle();
2207 string nodeLabel = (useTitle && !nodeTitle.empty()) ? nodeTitle : nodeName;
2208
2209 // if using latex, replace ROOT's # with normal latex backslash
2210 string::size_type position = nodeLabel.find('#') ;
2211 while(useLatex && position!=nodeLabel.npos){
2212 nodeLabel.replace(position, 1, "\\");
2213 }
2214
2215 string typeFormat = "\\texttt{";
2216 string nodeType = (useLatex) ? typeFormat+node->ClassName()+"}" : node->ClassName();
2217
2218 if (auto realNode = dynamic_cast<RooAbsReal*>(node)) {
2219 nodeLabel += delimiter + std::to_string(realNode->getVal());
2220 }
2221
2222 os << "\"" << nodeName << "\" [ color=" << (node->isFundamental()?"blue":"red")
2223 << ", label=\"" << nodeType << delimiter << nodeLabel << "\"];" << endl ;
2224
2225 }
2226
2227 // Get set of all server links
2228 set<pair<RooAbsArg*,RooAbsArg*> > links ;
2229 graphVizAddConnections(links) ;
2230
2231 // And write them out
2232 for(auto const& link : links) {
2233 os << "\"" << link.first->GetName() << "\" -> \"" << link.second->GetName() << "\";" << endl ;
2234 }
2235
2236 // Write trailer
2237 os << "}" << endl ;
2238
2239}
2240
2241////////////////////////////////////////////////////////////////////////////////
2242/// Utility function that inserts all point-to-point client-server connections
2243/// between any two RooAbsArgs in the expression tree headed by this object
2244/// in the linkSet argument.
2245
2246void RooAbsArg::graphVizAddConnections(set<pair<RooAbsArg*,RooAbsArg*> >& linkSet)
2247{
2248 for (const auto server : _serverList) {
2249 linkSet.insert(make_pair(this,server)) ;
2250 server->graphVizAddConnections(linkSet) ;
2251 }
2252}
2253
2254
2255////////////////////////////////////////////////////////////////////////////////
2256/// Take ownership of the contents of 'comps'.
2257
2259{
2260 if (!_ownedComponents) {
2261 _ownedComponents = new RooArgSet("owned components") ;
2262 }
2263 return _ownedComponents->addOwned(comps) ;
2264}
2265
2266
2267////////////////////////////////////////////////////////////////////////////////
2268/// Take ownership of the contents of 'comps'. Different from the overload that
2269/// taked the RooArgSet by `const&`, this version can also take an owning
2270/// RooArgSet without error, because the ownership will not be ambiguous afterwards.
2271
2273{
2274 if (!_ownedComponents) {
2275 _ownedComponents = new RooArgSet("owned components") ;
2276 }
2277 return _ownedComponents->addOwned(std::move(comps)) ;
2278}
2279
2280
2281////////////////////////////////////////////////////////////////////////////////
2282/// \copydoc RooAbsArg::addOwnedComponents(RooAbsCollection&& comps)
2283
2285 return addOwnedComponents(static_cast<RooAbsCollection&&>(std::move(comps)));
2286}
2287
2288
2289////////////////////////////////////////////////////////////////////////////////
2290/// Clone tree expression of objects. All tree nodes will be owned by
2291/// the head node return by cloneTree()
2292
2293RooAbsArg* RooAbsArg::cloneTree(const char* newname) const
2294{
2295 // In the RooHelpers, there is a more general implementation that we will reuse here
2297
2298 // Adjust name of head node if requested
2299 if (newname) {
2300 head->SetName(newname) ;
2301 }
2302
2303 // Return the head
2304 return head ;
2305}
2306
2307
2308
2309////////////////////////////////////////////////////////////////////////////////
2310
2312{
2313 if (dynamic_cast<RooTreeDataStore*>(&store)) {
2314 attachToTree((static_cast<RooTreeDataStore&>(store)).tree()) ;
2315 } else if (dynamic_cast<RooVectorDataStore*>(&store)) {
2316 attachToVStore(static_cast<RooVectorDataStore&>(store)) ;
2317 }
2318}
2319
2320
2321
2322////////////////////////////////////////////////////////////////////////////////
2323
2325{
2326 if (_eocache) {
2327 return *_eocache ;
2328 } else {
2330 }
2331}
2332
2333
2334////////////////////////////////////////////////////////////////////////////////
2335
2337{
2338 string suffix ;
2339
2340 RooArgSet branches ;
2341 branchNodeServerList(&branches) ;
2342 for(RooAbsArg * arg : branches) {
2343 const char* tmp = arg->cacheUniqueSuffix() ;
2344 if (tmp) suffix += tmp ;
2345 }
2346 return Form("%s",suffix.c_str()) ;
2347}
2348
2349
2350////////////////////////////////////////////////////////////////////////////////
2351
2353{
2354 RooArgSet branches ;
2355 branchNodeServerList(&branches) ;
2356 for(auto const& arg : branches) {
2357 for (auto const& arg2 : arg->_cacheList) {
2358 arg2->wireCache() ;
2359 }
2360 }
2361}
2362
2363
2364
2365////////////////////////////////////////////////////////////////////////////////
2366
2367void RooAbsArg::SetName(const char* name)
2368{
2370 auto newPtr = RooNameReg::instance().constPtr(GetName()) ;
2371 if (newPtr != _namePtr) {
2372 //cout << "Rename '" << _namePtr->GetName() << "' to '" << name << "' (set flag in new name)" << endl;
2373 _namePtr = newPtr;
2376 }
2377}
2378
2379
2380
2381
2382////////////////////////////////////////////////////////////////////////////////
2383
2384void RooAbsArg::SetNameTitle(const char *name, const char *title)
2385{
2386 TNamed::SetTitle(title) ;
2387 SetName(name);
2388}
2389
2390
2391////////////////////////////////////////////////////////////////////////////////
2392/// Stream an object of class RooAbsArg.
2393
2394void RooAbsArg::Streamer(TBuffer &R__b)
2395{
2396 if (R__b.IsReading()) {
2397 _ioReadStack.push(this) ;
2398 R__b.ReadClassBuffer(RooAbsArg::Class(),this);
2399 _ioReadStack.pop() ;
2401 _isConstant = getAttribute("Constant") ;
2402 } else {
2404 }
2405}
2406
2407////////////////////////////////////////////////////////////////////////////////
2408/// Method called by workspace container to finalize schema evolution issues
2409/// that cannot be handled in a single ioStreamer pass.
2410///
2411/// A second pass is typically needed when evolving data member of RooAbsArg-derived
2412/// classes that are container classes with references to other members, which may
2413/// not yet be 'live' in the first ioStreamer() evolution pass.
2414///
2415/// Classes may overload this function, but must call the base method in the
2416/// overloaded call to ensure base evolution is handled properly
2417
2419{
2420 // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2421 auto iter = _ioEvoList.find(this);
2422 if (iter != _ioEvoList.end()) {
2423
2424 // Transfer contents of saved TRefArray to RooRefArray now
2426 _proxyList.Expand(iter->second->GetEntriesFast());
2427 for (int i = 0; i < iter->second->GetEntriesFast(); i++) {
2428 _proxyList.Add(iter->second->At(i));
2429 }
2430 // Delete TRefArray and remove from list
2431 _ioEvoList.erase(iter);
2432 }
2433}
2434
2435
2436
2437
2438////////////////////////////////////////////////////////////////////////////////
2439/// Method called by workspace container to finalize schema evolution issues
2440/// that cannot be handled in a single ioStreamer pass. This static finalize method
2441/// is called after ioStreamerPass2() is called on each directly listed object
2442/// in the workspace. It's purpose is to complete schema evolution of any
2443/// objects in the workspace that are not directly listed as content elements
2444/// (e.g. analytical convolution tokens )
2445
2447{
2448 // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2449 for (const auto& iter : _ioEvoList) {
2450
2451 // Transfer contents of saved TRefArray to RooRefArray now
2452 if (!iter.first->_proxyList.GetEntriesFast())
2453 iter.first->_proxyList.Expand(iter.second->GetEntriesFast());
2454 for (int i = 0; i < iter.second->GetEntriesFast(); i++) {
2455 iter.first->_proxyList.Add(iter.second->At(i));
2456 }
2457 }
2458
2459 _ioEvoList.clear();
2460}
2461
2462
2465 return new RefCountListLegacyIterator_t(list.containedObjects());
2466}
2467
2468////////////////////////////////////////////////////////////////////////////////
2469/// Stream an object of class RooRefArray.
2470
2472{
2473 UInt_t R__s;
2474 UInt_t R__c;
2475 if (R__b.IsReading()) {
2476
2477 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2478 if (R__v) {
2479 }
2480
2481 // Make temporary refArray and read that from the streamer
2482 auto refArray = std::make_unique<TRefArray>();
2483 refArray->Streamer(R__b);
2484 R__b.CheckByteCount(R__s, R__c, refArray->IsA());
2485
2486 // Schedule deferred processing of TRefArray into proxy list
2487 RooAbsArg::_ioEvoList[RooAbsArg::_ioReadStack.top()] = std::move(refArray);
2488
2489 } else {
2490
2491 R__c = R__b.WriteVersion(RooRefArray::IsA(), true);
2492
2493 // Make a temporary refArray and write that to the streamer
2494 TRefArray refArray;
2495 for (TObject *tmpObj : *this) {
2496 refArray.Add(tmpObj);
2497 }
2498
2499 refArray.Streamer(R__b);
2500 R__b.SetByteCount(R__c, true);
2501 }
2502}
2503
2504/// Print at the prompt
2505namespace cling {
2506std::string printValue(RooAbsArg *raa)
2507{
2508 std::stringstream s;
2509 if (0 == *raa->GetName() && 0 == *raa->GetTitle()) {
2510 s << "An instance of " << raa->ClassName() << ".";
2511 return s.str();
2512 }
2513 raa->printStream(s, raa->defaultPrintContents(""), raa->defaultPrintStyle(""));
2514 return s.str();
2515}
2516} // namespace cling
2517
2518
2519/// Disables or enables the usage of squared weights. Needs to be overloaded in
2520/// the likelihood classes for which this is relevant.
2522 for(auto * server : servers()) {
2523 server->applyWeightSquared(flag);
2524 }
2525}
2526
2527
2528std::unique_ptr<RooAbsArg> RooAbsArg::compileForNormSet(RooArgSet const & normSet, RooFit::Detail::CompileContext & ctx) const
2529{
2530 auto newArg = std::unique_ptr<RooAbsArg>{static_cast<RooAbsArg *>(Clone())};
2531 ctx.markAsCompiled(*newArg);
2532 ctx.compileServers(*newArg, normSet);
2533 return newArg;
2534}
2535
2536
2537////////////////////////////////////////////////////////////////////////////////
2538/// This function defines a translation for each RooAbsReal based object that can be used
2539/// to express the class as simple C++ code. The function adds the code represented by
2540/// each class as an std::string (that is later concatenated with code strings from translate calls)
2541/// to form the C++ code that AD tools can understand. Any class that wants to support AD, has to
2542/// implement this function.
2543///
2544/// \param[in] ctx An object to manage auxiliary information for code-squashing. Also takes the
2545/// code string that this class outputs into the squashed code through the 'addToCodeBody' function.
2547{
2548 std::stringstream errorMsg;
2549 errorMsg << "Translate function for class \"" << ClassName() << "\" has not yet been implemented.";
2550 coutE(Minimization) << errorMsg.str() << std::endl;
2551 throw std::runtime_error(errorMsg.str().c_str());
2552}
2553
2554/// Sets the token for retrieving results in the BatchMode. For internal use only.
2556{
2557 if (_dataToken == index) {
2558 return;
2559 }
2560 if (_dataToken != std::numeric_limits<std::size_t>::max()) {
2561 std::stringstream errMsg;
2562 errMsg << "The data token for \"" << GetName() << "\" is already set!"
2563 << " Are you trying to evaluate the same object by multiple RooFit::Evaluator instances?"
2564 << " This is not allowed.";
2565 throw std::runtime_error(errMsg.str());
2566 }
2567 _dataToken = index;
2568}
istream & operator>>(istream &is, RooAbsArg &arg)
Istream operator.
static Roo_reg_AGKInteg1D instance
#define coutI(a)
#define cxcoutI(a)
#define cxcoutD(a)
#define oocxcoutD(o, a)
#define coutW(a)
#define coutF(a)
#define coutE(a)
#define cxcoutF(a)
char Text_t
Definition RtypesCore.h:62
short Version_t
Definition RtypesCore.h:65
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition TBuffer.h:397
static void indent(ostringstream &buf, int indent_level)
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
RooExpensiveObjectCache & expensiveObjectCache() const
bool overlaps(const RooAbsArg &testArg, bool valueOnly=false) const
Test if any of the nodes of tree are shared with that of the given tree.
TIterator Use servers() and begin()
RooRefArray _proxyList
Definition RooAbsArg.h:637
void replaceServer(RooAbsArg &oldServer, RooAbsArg &newServer, bool valueProp, bool shapeProp)
Replace 'oldServer' with 'newServer', specifying whether the new server has value or shape server pro...
bool _isConstant
De-duplicated name pointer. This will be equal for all objects with the same name.
Definition RooAbsArg.h:725
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:320
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
void attachToStore(RooAbsDataStore &store)
Attach this argument to the data store such that it reads data from there.
bool recursiveRedirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:561
const char * aggregateCacheUniqueSuffix() const
void printArgs(std::ostream &os) const override
Print object arguments, ie its proxies.
void printClassName(std::ostream &os) const override
Print object class name.
ProxyListCache _proxyListCache
Definition RooAbsArg.h:690
RooWorkspace * _myws
Prevent 'AlwaysDirty' mode for this node.
Definition RooAbsArg.h:732
~RooAbsArg() override
Destructor.
void attachDataStore(const RooAbsDataStore &set)
Replace server nodes with names matching the dataset variable names with those data set variables,...
RooArgSet * _ownedComponents
Definition RooAbsArg.h:718
void printAddress(std::ostream &os) const override
Print address of this RooAbsArg.
void setShapeDirty()
Notify that a shape-like property (e.g. binning) has changed.
Definition RooAbsArg.h:493
void setDataToken(std::size_t index)
Sets the token for retrieving results in the BatchMode. For internal use only.
void registerProxy(RooArgProxy &proxy)
Register an RooArgProxy in the proxy list.
void setOperMode(OperMode mode, bool recurseADirty=true)
Set the operation mode of this node.
bool callRedirectServersHook(RooAbsCollection const &newSet, bool mustReplaceAll, bool nameChange, bool isRecursionStep)
Private helper function for RooAbsArg::redirectServers().
void attachArgs(const RooAbsCollection &set)
Bind this node to objects in set.
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
RooFit::OwningPtr< RooArgSet > getDependents(const RooArgSet &set) const
bool isShapeServer(const RooAbsArg &arg) const
Check if this is serving shape to arg.
Definition RooAbsArg.h:231
bool isShapeDirty() const
Definition RooAbsArg.h:414
static void ioStreamerPass2Finalize()
Method called by workspace container to finalize schema evolution issues that cannot be handled in a ...
bool _fast
Definition RooAbsArg.h:715
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
void addParameters(RooAbsCollection &params, const RooArgSet *nset=nullptr, bool stripDisconnected=true) const
Add all parameters of the function and its daughters to params.
void removeServer(RooAbsArg &server, bool force=false)
Unregister another RooAbsArg as a server to us, ie, declare that we no longer depend on its value and...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
void setTransientAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
void graphVizAddConnections(std::set< std::pair< RooAbsArg *, RooAbsArg * > > &)
Utility function that inserts all point-to-point client-server connections between any two RooAbsArgs...
void unRegisterProxy(RooArgProxy &proxy)
Remove proxy from proxy list.
bool _shapeDirty
Definition RooAbsArg.h:712
void SetName(const char *name) override
Set the name of the TNamed.
std::set< std::string > _boolAttrib
Definition RooAbsArg.h:657
void unRegisterCache(RooAbsCache &cache)
Unregister a RooAbsCache. Called from the RooAbsCache destructor.
RefCountList_t _clientListValue
Definition RooAbsArg.h:635
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
void printAttribList(std::ostream &os) const
Transient boolean attributes (not copied in ctor)
void printTree(std::ostream &os, TString indent="") const override
Print object tree structure.
void SetNameTitle(const char *name, const char *title) override
Set all the TNamed parameters (name and title).
friend void RooRefArray::Streamer(TBuffer &)
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
bool findConstantNodes(const RooArgSet &observables, RooArgSet &cacheList)
Find branch nodes with all-constant parameters, and add them to the list of nodes that can be cached ...
static bool _verboseDirty
cache of the list of proxies. Avoids type casting.
Definition RooAbsArg.h:693
void addServerList(RooAbsCollection &serverList, bool valueProp=true, bool shapeProp=false)
Register a list of RooAbsArg as servers to us by calling addServer() for each arg in the list.
virtual bool readFromStream(std::istream &is, bool compact, bool verbose=false)=0
bool redirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool isRecursionStep=false)
Replace all direct servers of this object with the new servers in newServerList.
static void setDirtyInhibit(bool flag)
Control global dirty inhibit mode.
virtual void printCompactTreeHook(std::ostream &os, const char *ind="")
Hook function interface for object to insert additional information when printed in the context of a ...
const TNamed * _namePtr
Pointer to global cache manager for any expensive components created by this object.
Definition RooAbsArg.h:724
void printCompactTree(const char *indent="", const char *fileName=nullptr, const char *namePat=nullptr, RooAbsArg *client=nullptr)
Print tree structure of expression tree on stdout, or to file if filename is specified.
virtual std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const
virtual void getParametersHook(const RooArgSet *, RooArgSet *, bool) const
Definition RooAbsArg.h:594
virtual void ioStreamerPass2()
Method called by workspace container to finalize schema evolution issues that cannot be handled in a ...
RooFit::OwningPtr< RooArgSet > getComponents() const
Create a RooArgSet with all components (branch nodes) of the expression tree headed by this object.
void wireAllCaches()
bool _valueDirty
Definition RooAbsArg.h:711
bool _prohibitServerRedirect
Set of owned component.
Definition RooAbsArg.h:720
virtual const char * cacheUniqueSuffix() const
Definition RooAbsArg.h:496
RefCountListLegacyIterator_t * makeLegacyIterator(const RefCountList_t &list) const
std::size_t _dataToken
In which workspace do I live, if any.
Definition RooAbsArg.h:734
bool dependsOnValue(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr) const
Check whether this object depends on values from an element in the serverList.
Definition RooAbsArg.h:106
void addServer(RooAbsArg &server, bool valueProp=true, bool shapeProp=false, std::size_t refCount=1)
Register another RooAbsArg as a server to us, ie, declare that we depend on it.
virtual void translate(RooFit::Detail::CodeSquashContext &ctx) const
This function defines a translation for each RooAbsReal based object that can be used to express the ...
void removeStringAttribute(const Text_t *key)
Delete a string attribute with a given key.
Int_t Compare(const TObject *other) const override
Utility function used by TCollection::Sort to compare contained TObjects We implement comparison by n...
Int_t defaultPrintContents(Option_t *opt) const override
Define default contents to print.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:97
virtual void attachToTree(TTree &t, Int_t bufSize=32000)=0
Overloadable function for derived classes to implement attachment as branch to a TTree.
void printComponentTree(const char *indent="", const char *namePat=nullptr, Int_t nLevel=999)
Print tree structure of expression tree on given ostream, only branch nodes are printed.
OperMode _operMode
Definition RooAbsArg.h:714
virtual void constOptimizeTestStatistic(ConstOpCode opcode, bool doAlsoTrackingOpt=true)
Interface function signaling a request to perform constant term optimization.
void setValueDirty()
Mark the element dirty. This forces a re-evaluation when a value is requested.
Definition RooAbsArg.h:488
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
static void verboseDirty(bool flag)
Activate verbose messaging related to dirty flag propagation.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
RooAbsCache * getCache(Int_t index) const
Return registered cache object by index.
virtual void writeToStream(std::ostream &os, bool compact) const =0
void printMultiline(std::ostream &os, Int_t contents, bool verbose=false, TString indent="") const override
Implement multi-line detailed printing.
virtual RooAbsArg * cloneTree(const char *newname=nullptr) const
Clone tree expression of objects.
void registerCache(RooAbsCache &cache)
Register RooAbsCache with this object.
virtual void optimizeCacheMode(const RooArgSet &observables)
Activate cache mode optimization with given definition of observables.
RefCountList_t _clientListShape
Definition RooAbsArg.h:634
virtual void attachToVStore(RooVectorDataStore &vstore)=0
TString cleanBranchName() const
Construct a mangled name from the actual name that is free of any math symbols that might be interpre...
bool inhibitDirty() const
Delete watch flag.
bool observableOverlaps(const RooAbsData *dset, const RooAbsArg &testArg) const
Test if any of the dependents of the arg tree (as determined by getObservables) overlaps with those o...
void changeServer(RooAbsArg &server, bool valueProp, bool shapeProp)
Change dirty flag propagation mask for specified server.
Int_t numProxies() const
Return the number of registered proxies.
TIterator Use end() or range-based loops.")
Definition RooAbsArg.h:136
void printName(std::ostream &os) const override
Print object name.
bool isValueDirty() const
Definition RooAbsArg.h:419
bool _localNoInhibitDirty
Cached isConstant status.
Definition RooAbsArg.h:727
virtual void printMetaArgs(std::ostream &) const
Definition RooAbsArg.h:330
virtual void applyWeightSquared(bool flag)
Disables or enables the usage of squared weights.
static bool _inhibitDirty
Definition RooAbsArg.h:694
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
void setProxyNormSet(const RooArgSet *nset)
Forward a change in the cached normalization argset to all the registered proxies.
void branchNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all branch nodes of the arg tree starting with ourself as top node.
RefCountList_t _clientList
Definition RooAbsArg.h:633
void printDirty(bool depth=true) const
Print information about current value dirty state information.
RooAbsProxy * getProxy(Int_t index) const
Return the nth proxy from the proxy list.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:89
RefCountList_t _serverList
Definition RooAbsArg.h:632
void leafNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool recurseNonDerived=false) const
Fill supplied list with all leaf nodes of the arg tree, starting with ourself as top node.
RooExpensiveObjectCache * _eocache
Prohibit server redirects – Debugging tool.
Definition RooAbsArg.h:722
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:249
virtual bool isValid() const
WVE (08/21/01) Probably obsolete now.
std::set< std::string > _boolAttribTransient
Definition RooAbsArg.h:659
void printTitle(std::ostream &os) const override
Print object title.
virtual bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep)
Function that is called at the end of redirectServers().
std::size_t getParametersSizeEstimate(const RooArgSet *nset=nullptr) const
Obtain an estimate of the number of parameters of the function and its daughters.
void graphVizTree(const char *fileName, const char *delimiter="\n", bool useTitle=false, bool useLatex=false)
Create a GraphViz .dot file visualizing the expression tree headed by this RooAbsArg object.
void substituteServer(RooAbsArg *oldServer, RooAbsArg *newServer)
Set by the RooFitDriver for this arg to retrieve its result in the run context.
bool getTransientAttribute(const Text_t *name) const
Check if a named attribute is set.
virtual void operModeHook()
Definition RooAbsArg.h:588
bool recursiveCheckObservables(const RooArgSet *nset) const
Recursively call checkObservables on all nodes in the expression tree.
bool isValueServer(const RooAbsArg &arg) const
Check if this is serving values to arg.
Definition RooAbsArg.h:223
std::map< std::string, std::string > _stringAttrib
Definition RooAbsArg.h:658
Int_t numCaches() const
Return number of registered caches.
virtual bool checkObservables(const RooArgSet *nset) const
Overloadable function in which derived classes can implement consistency checks of the variables.
RooAbsArg()
Default constructor.
void attachDataSet(const RooAbsData &set)
Replace server nodes with names matching the dataset variable names with those data set variables,...
TIteratorToSTLInterface< RefCountList_t::Container_t > RefCountListLegacyIterator_t
Definition RooAbsArg.h:80
std::vector< RooAbsCache * > _cacheList
Definition RooAbsArg.h:639
void treeNodeServerList(RooAbsCollection *list, const RooAbsArg *arg=nullptr, bool doBranch=true, bool doLeaf=true, bool valueOnly=false, bool recurseNonDerived=false) const
Fill supplied list with nodes of the arg tree, following all server links, starting with ourself as t...
RooAbsArg * findNewServer(const RooAbsCollection &newSet, bool nameChange) const
Find the new server in the specified set that matches the old server.
OperMode operMode() const
Query the operation mode of this node.
Definition RooAbsArg.h:482
Abstract base class for data members of RooAbsArgs that cache other (composite) RooAbsArg expressions...
Definition RooAbsCache.h:27
virtual void operModeHook()
Interface for operation mode changes.
Definition RooAbsCache.h:46
virtual void findConstantNodes(const RooArgSet &, RooArgSet &, RooLinkedList &)
Interface for constant term node finding calls.
Definition RooAbsCache.h:52
virtual void printCompactTreeHook(std::ostream &, const char *)
Interface for printing of cache guts in tree mode printing.
Definition RooAbsCache.h:55
virtual bool redirectServersHook(const RooAbsCollection &, bool, bool, bool)
Interface for server redirect calls.
Definition RooAbsCache.h:40
virtual void optimizeCacheMode(const RooArgSet &, RooArgSet &, RooLinkedList &)
Interface for processing of cache mode optimization calls.
Definition RooAbsCache.h:49
Abstract container object that can hold multiple RooAbsArg objects.
RooAbsCollection * selectByAttrib(const char *name, bool value) const
Create a subset of the current collection, consisting only of those elements with the specified attri...
Storage_t const & get() const
Const access to the underlying stl container.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
void reserve(Storage_t::size_type count)
void clear()
Clear contents. If the collection is owning, it will also delete the contents.
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
void sort(bool reverse=false)
Sort collection using std::sort and name comparison.
void setName(const char *name)
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for a data collection.
virtual const RooArgSet * get(Int_t index) const =0
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
virtual const RooArgSet * get() const
Definition RooAbsData.h:101
Abstract interface for proxy classes.
Definition RooAbsProxy.h:37
virtual const char * name() const
Definition RooAbsProxy.h:47
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
Abstract interface for RooAbsArg proxy classes.
Definition RooArgProxy.h:24
bool isShapeServer() const
Returns true if contents is shape server of owner.
Definition RooArgProxy.h:64
RooAbsArg * absArg() const
Return pointer to contained argument.
Definition RooArgProxy.h:46
bool isValueServer() const
Returns true of contents is value server of owner.
Definition RooArgProxy.h:60
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
Represents a constant real-valued object.
Definition RooConstVar.h:23
Singleton class that serves as repository for objects that are expensive to calculate.
static RooExpensiveObjectCache & instance()
Return reference to singleton instance.
A class to maintain the context for squashing of RooFit models into code.
void markAsCompiled(RooAbsArg &arg) const
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
Switches the message service to a different level while the instance is alive.
Definition RooHelpers.h:37
Collection class for internal use, storing a collection of RooAbsArg pointers in a doubly linked list...
RooAbsArg * findArg(const RooAbsArg *) const
Return pointer to object with given name in collection.
virtual void Add(TObject *arg)
TObject * FindObject(const char *name) const override
Return pointer to object with given name.
Registry for const char* names.
Definition RooNameReg.h:26
const TNamed * constPtr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
static RooNameReg & instance()
Return reference to singleton instance.
@ kRenamedArg
TNamed flag to indicate that some RooAbsArg has been renamed (flag set in new name)
Definition RooNameReg.h:46
static void incrementRenameCounter()
The renaming counter has to be incremented every time a RooAbsArg is renamed.
A 'mix-in' base class that define the standard RooFit plotting and printing methods.
virtual StyleOption defaultPrintStyle(Option_t *opt) const
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
virtual void printValue(std::ostream &os) const
Interface to print value of object.
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
Variable that can be changed from the outside.
Definition RooRealVar.h:37
TClass * IsA() const override
Definition RooAbsArg.h:68
void Streamer(TBuffer &) override
Stream an object of class RooRefArray.
RooResolutionModel is the base class for PDFs that represent a resolution model that can be convolute...
TTree-backed data storage.
Uses std::vector to store data columns.
const RooArgSet * set(RooStringView name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
bool defineSetInternal(const char *name, const RooArgSet &aset)
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
TIterator and GenericRooFIter front end with STL back end.
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
TString fName
Definition TNamed.h:32
static TClass * Class()
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
Int_t GetEntriesFast() const
Definition TObjArray.h:58
virtual void Expand(Int_t newSize)
Expand or shrink the array to newSize elements.
virtual void Compress()
Remove empty slots from array.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * Remove(TObject *obj) override
Remove object from array.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
An array of references to TObjects.
Definition TRefArray.h:33
void Add(TObject *obj) override
Definition TRefArray.h:74
void Streamer(TBuffer &) override
Stream all objects in the array to or from the I/O buffer.
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Append(const char *cs)
Definition TString.h:572
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
A TTree represents a columnar dataset.
Definition TTree.h:79
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35
RooAbsArg * cloneTreeWithSameParametersImpl(RooAbsArg const &arg, RooArgSet const *observables)
std::string getColonSeparatedNameString(RooArgSet const &argSet, char delim=':')
std::vector< RooAbsProxy * > cache
Definition RooAbsArg.h:687