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/** \class RooAbsArg
18 \ingroup Roofitcore
19
20Common abstract base class for objects that
21represent a value and a "shape" in RooFit. Values or shapes usually depend on values
22or shapes of other RooAbsArg instances. Connecting several RooAbsArg in
23a computation graph models an expression tree that can be evaluated.
24
25### Building a computation graph of RooFit objects
26Therefore, RooAbsArg provides functionality to connect objects of type RooAbsArg into
27a computation graph to pass values between those objects.
28A value can e.g. be a real-valued number, (instances of RooAbsReal), or an integer, that is,
29category index (instances of RooAbsCategory). The third subclass of RooAbsArg is RooStringVar,
30but it is rarely used.
31
32The "shapes" that a RooAbsArg can possess can e.g. be the definition
33range of an observable, or how many states a category object has. In computations,
34values are expected to change often, while shapes remain mostly constant
35(unless e.g. a new range is set for an observable).
36
37Nodes of a computation graph are connected using instances of RooAbsProxy.
38If Node B declares a member `RooTemplateProxy<TypeOfNodeA>`, Node A will be
39registered as a server of values to Node B, and Node B will know that it is
40a client of node A. Using functions like dependsOn(), or getObservables()
41/ getParameters(), the relation of `A --> B` can be queried. Using graphVizTree(),
42one can create a visualisation of the expression tree.
43
44
45An instance of RooAbsArg can have named attributes. It also has flags
46to indicate that either its value or its shape were changed (= it is dirty).
47RooAbsArg provides functionality to manage client/server relations in
48a computation graph (\ref clientServerInterface), and helps propagating
49value/shape changes through the graph. RooAbsArg implements interfaces
50for inspecting client/server relationships (\ref clientServerInterface) and
51setting/clearing/querying named attributes.
52
53### Caching of values
54The values of nodes in the computation graph are cached in RooFit. If
55a value is used in two nodes of a graph, it doesn't need to be recomputed. If
56a node acquires a new value, it notifies its consumers ("clients") that
57their cached values are dirty. See the functions in \ref optimisationInterface
58for details.
59A node uses its isValueDirty() and isShapeDirty() functions to decide if a
60computation is necessary. Caching can be vetoed globally by setting a
61bit using setDirtyInhibit(). This will make computations slower, but all the
62nodes of the computation graph will be evaluated irrespective of whether their
63state is clean or dirty. Using setOperMode(), caching can also be enabled/disabled
64for single nodes.
65
66*/
67
68#include <RooAbsArg.h>
69
71#include <RooAbsData.h>
72#include <RooAbsDataStore.h>
73#include <RooArgProxy.h>
74#include <RooArgSet.h>
75#include <RooConstVar.h>
77#include <RooFit/Evaluator.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
99bool RooAbsArg::_verboseDirty(false);
100bool RooAbsArg::_inhibitDirty(false);
102{
104}
105
106namespace {
107
108auto &ioEvoList()
109{
110 // temporary holding list for proxies needed in schema evolution
111 static std::map<RooAbsArg *, std::unique_ptr<TRefArray>> ioEvoListInstance;
112 return ioEvoListInstance;
113}
114
115// reading stack
116auto &ioReadStack()
117{
118 static std::stack<RooAbsArg *> ioReadStackInstance;
119 return ioReadStackInstance;
120}
121
122} // namespace
123
124/// Default constructor
125
126RooAbsArg::RooAbsArg() : _namePtr(RooNameReg::instance().constPtr(GetName())) {}
127
128/// Create an object with the specified name and descriptive title.
129/// The newly created object has no clients or servers and has its
130/// dirty flags set.
131
132RooAbsArg::RooAbsArg(const char *name, const char *title) : TNamed(name, title)
133{
134 if (name == nullptr || strlen(name) == 0) {
135 throw std::logic_error(
136 "Each RooFit object needs a name. "
137 "Objects representing the same entity (e.g. an observable 'x') are identified using their name.");
138 }
139 _namePtr = RooNameReg::instance().constPtr(GetName());
140}
141
142/// Copy constructor transfers all boolean and string properties of the original
143/// object. Transient properties and client-server links are not copied
144
146 : TNamed(name ? name : other.GetName(), other.GetTitle()),
148 _boolAttrib(other._boolAttrib),
149 _stringAttrib(other._stringAttrib),
150 _deleteWatch(other._deleteWatch),
151 _namePtr(name ? RooNameReg::instance().constPtr(name) : other._namePtr),
152 _isConstant(other._isConstant),
153 _localNoInhibitDirty(other._localNoInhibitDirty)
154{
155
156 // Copy server list by hand
157 bool valueProp;
158 bool shapeProp;
159 for (const auto server : other._serverList) {
160 valueProp = server->_clientListValue.containsByNamePtr(&other);
161 shapeProp = server->_clientListShape.containsByNamePtr(&other);
163 }
164
167}
168
169/// Destructor.
170
172{
173 // If a RooFit::Evaluator still holds a data token for this arg, tell it that
174 // the arg is gone so that it doesn't reset the token in its destructor.
175 if (_evaluator) {
177 }
178
179 // Notify all servers that they no longer need to serve us
180 while (!_serverList.empty()) {
181 removeServer(*_serverList.containedObjects().back(), true);
182 }
183
184 // Notify all clients that they are in limbo
185 std::vector<RooAbsArg *> clientListTmp(_clientList.begin(),
186 _clientList.end()); // have to copy, as we invalidate iterators
187 bool first(true);
188 for (auto client : clientListTmp) {
189 client->setAttribute("ServerDied");
190 std::stringstream attr;
191 attr << "ServerDied:" << GetName() << "(" << reinterpret_cast<std::size_t>(this) << ")";
192 client->setAttribute(attr.str().c_str());
193 client->removeServer(*this, true);
194
195 if (_verboseDirty) {
196
197 if (first) {
198 cxcoutD(Tracing) << "RooAbsArg::dtor(" << GetName() << "," << this
199 << ") DeleteWatch: object is being destroyed" << std::endl;
200 first = false;
201 }
202
203 cxcoutD(Tracing) << fName << "::" << ClassName() << ":~RooAbsArg: dependent \"" << client->GetName()
204 << "\" should have been deleted first" << std::endl;
205 }
206 }
207
208 if (_ownedComponents) {
209 delete _ownedComponents;
210 _ownedComponents = nullptr;
211 }
212}
213
214/// Control global dirty inhibit mode. When set to true no value or shape dirty
215/// flags are propagated and cache is always considered to be dirty.
216
221
222/// Activate verbose messaging related to dirty flag propagation
223
225{
227}
228
229/// Set (default) or clear a named boolean attribute of this object.
230
232{
233 // Preserve backward compatibility - any strong
234 if (std::string{"Constant"} == name) {
236 }
237
238 if (value) {
239 _boolAttrib.insert(name);
240 } else {
241 std::set<std::string>::iterator iter = _boolAttrib.find(name);
242 if (iter != _boolAttrib.end()) {
243 _boolAttrib.erase(iter);
244 }
245 }
246}
247
248/// Check if a named attribute is set. By default, all attributes are unset.
249
251{
252 return _boolAttrib.find(name) != _boolAttrib.end();
253}
254
255/// Associate string 'value' to this object under key 'key'
256
258{
259 if (value) {
260 _stringAttrib[key] = value;
261 } else {
263 }
264}
265
266/// Delete a string attribute with a given key.
267
269{
270 _stringAttrib.erase(key);
271}
272
273/// Get string attribute mapped under key 'key'. Returns null pointer
274/// if no attribute exists under that key
275
277{
278 std::map<std::string, std::string>::const_iterator iter = _stringAttrib.find(key);
279 return iter != _stringAttrib.end() ? iter->second.c_str() : nullptr;
280}
281
282/// Set (default) or clear a named boolean attribute of this object.
283
285{
286 if (value) {
287
289
290 } else {
291
292 std::set<std::string>::iterator iter = _boolAttribTransient.find(name);
293 if (iter != _boolAttribTransient.end()) {
294 _boolAttribTransient.erase(iter);
295 }
296 }
297}
298
299/// Check if a named attribute is set. By default, all attributes
300/// are unset.
301
303{
304 return (_boolAttribTransient.find(name) != _boolAttribTransient.end());
305}
306
307/// Register another RooAbsArg as a server to us, ie, declare that
308/// we depend on it.
309/// \param server The server to be registered.
310/// \param valueProp In addition to the basic client-server relationship, declare dependence on the server's value.
311/// \param shapeProp In addition to the basic client-server relationship, declare dependence on the server's shape.
312/// \param refCount Optionally add with higher reference count (if multiple components depend on it)
313
314void RooAbsArg::addServer(RooAbsArg &server, bool valueProp, bool shapeProp, std::size_t refCount)
315{
317 cxcoutF(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName()
318 << "): PROHIBITED SERVER ADDITION REQUESTED: adding server " << server.GetName() << "("
319 << &server << ") for " << (valueProp ? "value " : "") << (shapeProp ? "shape" : "")
320 << std::endl;
321 throw std::logic_error("PROHIBITED SERVER ADDITION REQUESTED in RooAbsArg::addServer");
322 }
323
324 cxcoutD(LinkStateMgmt) << "RooAbsArg::addServer(" << this << "," << GetName() << "): adding server "
325 << server.GetName() << "(" << &server << ") for " << (valueProp ? "value " : "")
326 << (shapeProp ? "shape" : "") << std::endl;
327
328 if (server.operMode() == ADirty && operMode() != ADirty && valueProp) {
330 }
331
332 // LM: use hash tables for larger lists
333 // if (_serverList.GetSize() > 999 && _serverList.getHashTableSize() == 0) _serverList.setHashTableSize(1000);
334 // if (server._clientList.GetSize() > 999 && server._clientList.getHashTableSize() == 0)
335 // server._clientList.setHashTableSize(1000); if (server._clientListValue.GetSize() > 999 &&
336 // server._clientListValue.getHashTableSize() == 0) server._clientListValue.setHashTableSize(1000);
337
338 // Add server link to given server
339 _serverList.Add(&server, refCount);
340
341 server._clientList.Add(this, refCount);
342 if (valueProp)
343 server._clientListValue.Add(this, refCount);
344 if (shapeProp)
345 server._clientListShape.Add(this, refCount);
346}
347
348/// Register a list of RooAbsArg as servers to us by calling
349/// addServer() for each arg in the list
350
352{
353 _serverList.reserve(_serverList.size() + serverList.size());
354
355 for (const auto arg : serverList) {
357 }
358}
359
360/// Unregister another RooAbsArg as a server to us, ie, declare that
361/// we no longer depend on its value and shape.
362
364{
366 std::stringstream ss;
367 ss << "RooAbsArg::addServer(" << this << "," << GetName()
368 << "): PROHIBITED SERVER REMOVAL REQUESTED: removing server " << server.GetName() << "(" << &server << ")";
369 cxcoutF(LinkStateMgmt) << ss.str() << std::endl;
370 throw std::runtime_error(ss.str());
371 }
372
373 if (_verboseDirty) {
374 cxcoutD(LinkStateMgmt) << "RooAbsArg::removeServer(" << GetName() << "): removing server " << server.GetName()
375 << "(" << &server << ")" << std::endl;
376 }
377
378 // Remove server link to given server
379 _serverList.Remove(&server, force);
380
381 server._clientList.Remove(this, force);
382 server._clientListValue.Remove(this, force);
383 server._clientListShape.Remove(this, force);
384}
385
386/// Replace 'oldServer' with 'newServer', specifying whether the new server has
387/// value or shape server properties.
388///
389/// \warning This function should not be used! This method is quite unsafe for
390/// many reasons. For once, the new server will be put at the end of the server
391/// list, no matter the position of the original server. This might mess up
392/// code that expects the servers to be in a certain order. Furthermore, the
393/// proxy objects corresponding to the server are not updated, leaving the
394/// object in an invalid state where the servers are out of sync with the
395/// proxies. This can have very bad consequences. Finally, by having to
396/// manually specify the value and shape server properties, it is very easy to
397/// get them wrong.
398///
399/// If you want to safely replace a server, you should use
400/// RooAbsArg::redirectServers(), which replaces the server in-place at the
401/// same position of the server list, keeps the same value and shape server
402/// properties, and also updates the corresponding proxies.
403
405{
406 coutW(LinkStateMgmt) << "replaceServer()"
407 << " is unsafe, because the server list will be out of sync with the proxy objects!"
408 << " If you want to safely replace a server, use RooAbsArg::redirectServers()."
409 << " See the docs to replaceServers() for more info." << std::endl;
410
411 Int_t count = _serverList.refCount(&oldServer);
412 removeServer(oldServer, true);
413
415}
416
417/// Change dirty flag propagation mask for specified server
418
420{
421 if (!_serverList.containsByNamePtr(&server)) {
422 coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server " << server.GetName()
423 << " not registered" << std::endl;
424 return;
425 }
426
427 // This condition should not happen, but check anyway
428 if (!server._clientList.containsByNamePtr(this)) {
429 coutE(LinkStateMgmt) << "RooAbsArg::changeServer(" << GetName() << "): Server " << server.GetName()
430 << " doesn't have us registered as client" << std::endl;
431 return;
432 }
433
434 // Remove all propagation links, then reinstall requested ones ;
435 Int_t vcount = server._clientListValue.refCount(this);
436 Int_t scount = server._clientListShape.refCount(this);
437 server._clientListValue.RemoveAll(this);
438 server._clientListShape.RemoveAll(this);
439 if (valueProp) {
440 server._clientListValue.Add(this, vcount);
441 }
442 if (shapeProp) {
443 server._clientListShape.Add(this, scount);
444 }
445}
446
447/// Fill supplied list with all leaf nodes of the arg tree, starting with
448/// ourself as top node. A leaf node is node that has no servers declared.
449
451{
452 treeNodeServerList(list, arg, false, true, false, recurseNonDerived);
453}
454
455/// Fill supplied list with all branch nodes of the arg tree starting with
456/// ourself as top node. A branch node is node that has one or more servers declared.
457
459{
460 treeNodeServerList(list, arg, true, false, false, recurseNonDerived);
461}
462
463/// Fill supplied list with nodes of the arg tree, following all server links,
464/// starting with ourself as top node.
465/// \param[in] list Output list
466/// \param[in] arg Start searching at this element of the tree.
467/// \param[in] doBranch Add branch nodes to the list.
468/// \param[in] doLeaf Add leaf nodes to the list.
469/// \param[in] valueOnly Only check if an element is a value server (no shape server).
470/// \param[in] recurseFundamental
471
473 bool valueOnly, bool recurseFundamental) const
474{
475 // if (arg==0) {
476 // std::cout << "treeNodeServerList(" << GetName() << ") doBranch=" << (doBranch?"T":"F") << " doLeaf = " <<
477 // (doLeaf?"T":"F") << " valueOnly=" << (valueOnly?"T":"F") << std::endl ;
478 // }
479
480 if (!arg) {
481 list->reserve(10);
482 arg = this;
483 }
484
485 // Decide if to add current node
486 if ((doBranch && doLeaf) || (doBranch && arg->isDerived()) ||
487 (doLeaf && arg->isFundamental() && (!(recurseFundamental && arg->isDerived()))) ||
488 (doLeaf && !arg->isFundamental() && !arg->isDerived())) {
489
490 list->add(*arg, true);
491 }
492
493 // Recurse if current node is derived
494 if (arg->isDerived() && (!arg->isFundamental() || recurseFundamental)) {
495 for (const auto server : arg->_serverList) {
496
497 // Skip non-value server nodes if requested.
498 if (valueOnly) {
499 // The "containsByNamePtr" check is an expensive call, don't do it
500 // if "valueOnly" is false anyway!
501 if (!server->_clientListValue.containsByNamePtr(arg)) {
502 continue;
503 }
504 }
506 }
507 }
508}
509
510/// Create a list of leaf nodes in the arg tree starting with
511/// ourself as top node that don't match any of the names of the variable list
512/// of the supplied data set (the dependents). The caller of this
513/// function is responsible for deleting the returned argset.
514/// The complement of this function is getObservables()
515
517{
518 return getParameters(set ? set->get() : nullptr, stripDisconnected);
519}
520
521/// Return the parameters of this p.d.f when used in conjunction with dataset 'data'.
526
527/// Return the parameters of the p.d.f given the provided set of observables.
529{
530 return getParameters(&observables, stripDisconnected);
531}
532
533/// Create a list of leaf nodes in the arg tree starting with
534/// ourself as top node that don't match any of the names the args in the
535/// supplied argset. The caller of this function is responsible
536/// for deleting the returned argset. The complement of this function
537/// is getObservables().
538
545
546/// Add all parameters of the function and its daughters to `params`.
547/// \param[in] params Collection that stores all parameters. Add all new parameters to this.
548/// \param[in] nset Normalisation set (optional). If a value depends on this set, it's not a parameter.
549/// \param[in] stripDisconnected Passed on to getParametersHook().
550
552{
553
555 std::vector<RooAbsArg *> branchList;
556 for (const auto server : _serverList) {
557 if (server->isValueServer(*this)) {
558 if (server->isFundamental()) {
559 if (!nset || !server->dependsOn(*nset)) {
561 }
562 } else {
563 branchList.push_back(server);
564 }
565 }
566 }
567
568 // Now recurse into branch servers
569 std::sort(branchList.begin(), branchList.end());
570 const auto last = std::unique(branchList.begin(), branchList.end());
571 for (auto serverIt = branchList.begin(); serverIt < last; ++serverIt) {
572 (*serverIt)->addParameters(nodeParamServers, nset, stripDisconnected);
573 }
574
575 // Allow pdf to strip parameters from list
577
578 // Add parameters of this node to the combined list
579 params.add(nodeParamServers, true);
580}
581
582/// Fills a list with leaf nodes in the arg tree starting with
583/// ourself as top node that don't match any of the names the args in the
584/// supplied argset. Returns `true` only if something went wrong.
585/// The complement of this function is getObservables().
586/// \param[in] observables Set of leaves to ignore because they are observables and not parameters.
587/// \param[out] outputSet Output set.
588/// \param[in] stripDisconnected Allow pdf to strip parameters from list before adding it.
589
591{
592 outputSet.clear();
593 outputSet.setName("parameters");
594
596
597 outputSet.sort();
598
599 return false;
600}
601
602/// Given a set of possible observables, return the observables that this PDF depends on.
607
608/// Return the observables of this pdf given the observables defined by `data`.
613
614/// Create a list of leaf nodes in the arg tree starting with
615/// ourself as top node that match any of the names of the variable list
616/// of the supplied data set (the dependents). The caller of this
617/// function is responsible for deleting the returned argset.
618/// The complement of this function is getParameters().
619
621{
622 if (!set)
624
625 return getObservables(set->get());
626}
627
628/// Create a list of leaf nodes in the arg tree starting with
629/// ourself as top node that match any of the names the args in the
630/// supplied argset. The caller of this function is responsible
631/// for deleting the returned argset. The complement of this function
632/// is getParameters().
633
640
641/// Create a list of leaf nodes in the arg tree starting with
642/// ourself as top node that match any of the names the args in the
643/// supplied argset.
644/// Returns `true` only if something went wrong.
645/// The complement of this function is getParameters().
646/// \param[in] dataList Set of leaf nodes to match.
647/// \param[out] outputSet Output set.
648/// \param[in] valueOnly If this parameter is true, we only match leaves that
649/// depend on the value of any arg in `dataList`.
650
652{
653 outputSet.clear();
654 outputSet.setName("dependents");
655
656 if (!dataList)
657 return false;
658
659 // Make iterator over tree leaf node list
660 RooArgSet leafList("leafNodeServerList");
661 treeNodeServerList(&leafList, nullptr, false, true, valueOnly);
662
663 if (valueOnly) {
664 for (const auto arg : leafList) {
665 if (arg->dependsOnValue(*dataList) && arg->isLValue()) {
666 outputSet.add(*arg);
667 }
668 }
669 } else {
670 for (const auto arg : leafList) {
671 if (arg->dependsOn(*dataList) && arg->isLValue()) {
672 outputSet.add(*arg);
673 }
674 }
675 }
676
677 return false;
678}
679
680/// Create a RooArgSet with all components (branch nodes) of the
681/// expression tree headed by this object.
683{
684 RooArgSet *set = new RooArgSet((std::string(GetName()) + "_components").c_str());
686
688}
689
690/// Overloadable function in which derived classes can implement
691/// consistency checks of the variables. If this function returns
692/// true, indicating an error, the fitter or generator will abort.
693
695{
696 return false;
697}
698
699/// Recursively call checkObservables on all nodes in the expression tree
700
702{
705
706 bool ret(false);
707 for (RooAbsArg *arg : nodeList) {
708 if (arg->getAttribute("ServerDied")) {
709 coutE(LinkStateMgmt) << "RooAbsArg::recursiveCheckObservables(" << GetName()
710 << "): ERROR: one or more servers of node " << arg->GetName() << " no longer exists!"
711 << std::endl;
712 arg->Print("v");
713 ret = true;
714 }
715 ret |= arg->checkObservables(nset);
716 }
717
718 return ret;
719}
720
721/// Test whether we depend on (ie, are served by) any object in the
722/// specified collection. Uses the dependsOn(RooAbsArg&) member function.
723
725{
726 // Test whether we depend on (ie, are served by) any object in the
727 // specified collection. Uses the dependsOn(RooAbsArg&) member function.
728
729 for (auto server : serverList) {
731 return true;
732 }
733 }
734 return false;
735}
736
737/// Test whether we depend on (ie, are served by) an object with a specific name.
739{
740 if (this == ignoreArg)
741 return false;
742
743 // First check if testArg is self
744 if (testArgNamePtr == namePtr())
745 return true;
746
747 // Next test direct dependence
748 RooAbsArg *foundServer = _serverList.findByNamePointer(testArgNamePtr);
749 if (foundServer) {
750
751 // Return true if valueOnly is FALSE or if server is value server, otherwise keep looking
752 if (!valueOnly || foundServer->isValueServer(*this)) {
753 return true;
754 }
755 }
756
757 // If not, recurse
758 for (const auto server : _serverList) {
759 if (!valueOnly || server->isValueServer(*this)) {
760 if (server->dependsOn(testArgNamePtr, ignoreArg, valueOnly)) {
761 return true;
762 }
763 }
764 }
765
766 return false;
767}
768
769/// Test if any of the nodes of tree are shared with that of the given tree
770
772{
773 RooArgSet list("treeNodeList");
774 treeNodeServerList(&list);
775
776 return valueOnly ? testArg.dependsOnValue(list) : testArg.dependsOn(list);
777}
778
779/// Test if any of the dependents of the arg tree (as determined by getObservables)
780/// overlaps with those of the testArg.
781
783{
784 return observableOverlaps(dset->get(), testArg);
785}
786
787/// Test if any of the dependents of the arg tree (as determined by getObservables)
788/// overlaps with those of the testArg.
789
791{
792 return testArg.dependsOn(*std::unique_ptr<RooArgSet>{getObservables(nset)});
793}
794
795/// Mark this object as having changed its value, and propagate this status
796/// change to all of our clients. If the object is not in automatic dirty
797/// state propagation mode, this call has no effect.
798
800{
801 if (_operMode != Auto || _inhibitDirty)
802 return;
803
804 // Handle no-propagation scenarios first
805 if (_clientListValue.empty()) {
806 _valueDirty = true;
807 return;
808 }
809
810 // Cyclical dependency interception
811 if (source == nullptr) {
812 source = this;
813 } else if (source == this) {
814 // Cyclical dependency, abort
815 coutE(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << GetName()
816 << "): cyclical dependency detected, source = " << source->GetName() << std::endl;
817 // assert(0) ;
818 return;
819 }
820
821 // Propagate dirty flag to all clients if this is a down->up transition
822 if (_verboseDirty) {
823 cxcoutD(LinkStateMgmt) << "RooAbsArg::setValueDirty(" << (source ? source->GetName() : "self") << "->"
824 << GetName() << "," << this << "): dirty flag " << (_valueDirty ? "already " : "")
825 << "raised" << std::endl;
826 }
827
828 _valueDirty = true;
829
830 for (auto client : _clientListValue) {
831 client->setValueDirty(source);
832 }
833}
834
835/// Mark this object as having changed its shape, and propagate this status
836/// change to all of our clients.
837
839{
840 if (_verboseDirty) {
841 cxcoutD(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName() << "): dirty flag "
842 << (_shapeDirty ? "already " : "") << "raised" << std::endl;
843 }
844
845 if (_clientListShape.empty()) {
846 _shapeDirty = true;
847 return;
848 }
849
850 // Set 'dirty' shape state for this object and propagate flag to all its clients
851 if (source == nullptr) {
852 source = this;
853 } else if (source == this) {
854 // Cyclical dependency, abort
855 coutE(LinkStateMgmt) << "RooAbsArg::setShapeDirty(" << GetName() << "): cyclical dependency detected"
856 << std::endl;
857 return;
858 }
859
860 // Propagate dirty flag to all clients if this is a down->up transition
861 _shapeDirty = true;
862
863 for (auto client : _clientListShape) {
864 client->setShapeDirty(source);
865 client->setValueDirty(source);
866 }
867}
868
869/// Replace all direct servers of this object with the new servers in `newServerList`.
870/// This substitutes objects that we receive values from with new objects that have the same name.
871/// See: recursiveRedirectServers() Use recursive version if servers that are only indirectly serving this object should
872/// be replaced as well. See: redirectServers() If only the direct servers of an object need to be replaced.
873///
874/// Note that changing the types of objects is generally allowed, but can be wrong if the interface of an object
875/// changes. For example, one can reparametrise a model by substituting a variable with a function:
876/// \f[
877/// f(x\, |\, a) = a \cdot x \rightarrow f(x\, |\, b) = (2.1 \cdot b) \cdot x
878/// \f]
879/// If an object, however, expects a PDF, and this is substituted with a function that isn't normalised, wrong results
880/// might be obtained or it might even crash the program. The types of the objects being substituted are not checked.
881///
882/// \param[in] newSetOrig Set of new servers that should be used instead of the current servers.
883/// \param[in] mustReplaceAll A warning is printed and error status is returned if not all servers could be
884/// substituted successfully.
885/// \param[in] nameChange If false, an object named "x" is only replaced with an object also named "x" in `newSetOrig`.
886/// If the object in `newSet` is called differently, set `nameChange` to true and use setAttribute() on the x object:
887/// ```
888/// objectToReplaceX.setAttribute("ORIGNAME:x")
889/// ```
890/// Now, the renamed object will be selected based on the attribute "ORIGNAME:<name>".
891/// \param[in] isRecursionStep Internal switch used when called from recursiveRedirectServers().
893 bool isRecursionStep)
894{
895 // Trivial case, no servers
896 if (_serverList.empty())
897 return false;
898
899 // We don't need to do anything if there are no new servers or if the only
900 // new server is this RooAbsArg itself. And by returning early, we avoid
901 // potentially annoying side effects of the redirectServersHook.
902 if (newSetOrig.empty() || (newSetOrig.size() == 1 && newSetOrig[0] == this))
903 return false;
904
905 // Strip any non-matching removal nodes from newSetOrig
906 std::unique_ptr<RooArgSet> newSetOwned;
908
909 if (nameChange) {
910 newSetOwned = std::make_unique<RooArgSet>();
911 for (auto arg : *newSet) {
912
913 if (std::string("REMOVAL_DUMMY") == arg->GetName()) {
914
915 if (arg->getAttribute("REMOVE_ALL")) {
916 newSetOwned->add(*arg);
917 } else if (arg->getAttribute(Form("REMOVE_FROM_%s", getStringAttribute("ORIGNAME")))) {
918 newSetOwned->add(*arg);
919 }
920 } else {
921 newSetOwned->add(*arg);
922 }
923 }
924 newSet = newSetOwned.get();
925 }
926
927 // Replace current servers with new servers with the same name from the given list
928 for (auto oldServer : _serverList) {
929
930 RooAbsArg *newServer = oldServer->findNewServer(*newSet, nameChange);
931
932 if (!newServer) {
933 if (mustReplaceAll) {
934 std::stringstream ss;
935 ss << "RooAbsArg::redirectServers(" << (void *)this << "," << GetName() << "): server "
936 << oldServer->GetName() << " (" << (void *)oldServer << ") not redirected"
937 << (nameChange ? "[nameChange]" : "");
938 const std::string errorMsg = ss.str();
939 coutE(LinkStateMgmt) << errorMsg << std::endl;
940 throw std::runtime_error(errorMsg);
941 }
942 continue;
943 }
944
945 if (newServer != this) {
947 }
948 }
949
952
953 bool ret(false);
954
955 // Process the proxies
956 for (int i = 0; i < numProxies(); i++) {
957 RooAbsProxy *p = getProxy(i);
958 if (!p)
959 continue;
960 bool ret2 = p->changePointer(*newSet, nameChange, false);
961
962 if (mustReplaceAll && !ret2) {
963 auto ap = dynamic_cast<const RooArgProxy *>(p);
964 coutE(LinkStateMgmt) << "RooAbsArg::redirectServers(" << GetName() << "): ERROR, proxy '" << p->name()
965 << "' with arg '" << (ap ? ap->absArg()->GetName() : "<could not cast>")
966 << "' could not be adjusted" << std::endl;
967 ret = true;
968 }
969 }
970
971 // Optional subclass post-processing
973 return ret;
974}
975
976/// Private helper function for RooAbsArg::redirectServers().
978{
980
981 const int clientListRefCount = oldServer->_clientList.Remove(this, true);
982 const int clientListValueRefCount = oldServer->_clientListValue.Remove(this, true);
983 const int clientListShapeRefCount = oldServer->_clientListShape.Remove(this, true);
984
985 newServer->_clientList.Add(this, clientListRefCount);
986 newServer->_clientListValue.Add(this, clientListValueRefCount);
987 newServer->_clientListShape.Add(this, clientListShapeRefCount);
988
989 if (clientListValueRefCount > 0 && newServer->operMode() == ADirty && operMode() != ADirty) {
991 }
992}
993
994/// Private helper function for RooAbsArg::redirectServers().
1006
1007/// Replace some servers of this object. If there are proxies that correspond
1008/// to the replaced servers, these proxies are adjusted as well.
1009/// \param[in] replacements Map that specifies which args replace which servers.
1010bool RooAbsArg::redirectServers(std::unordered_map<RooAbsArg *, RooAbsArg *> const &replacements)
1011{
1012 bool ret(false);
1013 bool nameChange = false;
1014
1016
1017 // Replace current servers with new servers with the same name from the given list
1018 for (auto oldServer : _serverList) {
1019
1022
1023 if (!newServer || newServer == this) {
1024 continue;
1025 }
1026
1027 if (nameChange == false)
1028 nameChange = strcmp(newServerFound->first->GetName(), newServerFound->second->GetName()) != 0;
1029
1031 newList.add(*newServer);
1032 }
1033
1034 // No servers were replaced, we don't need to process proxies and call the
1035 // redirectServersHook.
1036 if (newList.empty())
1037 return ret;
1038
1039 setValueDirty();
1040 setShapeDirty();
1041
1042 // Process the proxies
1043 for (int i = 0; i < numProxies(); i++) {
1044 if (RooAbsProxy *p = getProxy(i)) {
1045 p->changePointer(replacements);
1046 }
1047 }
1048
1049 // Optional subclass post-processing
1050 ret |= callRedirectServersHook(newList, false, nameChange, false);
1051 return ret;
1052}
1053
1054/// Find the new server in the specified set that matches the old server.
1055///
1056/// \param[in] newSet Search this set by name for a new server.
1057/// \param[in] nameChange If true, search for an item with the bool attribute "ORIGNAME:<oldName>" set.
1058/// Use `<object>.setAttribute("ORIGNAME:<oldName>")` to set this attribute.
1059/// \return Pointer to the new server or `nullptr` if there's no unique match.
1061{
1062 RooAbsArg *newServer = nullptr;
1063 if (!nameChange) {
1064 newServer = newSet.find(*this);
1065 } else {
1066 // Name changing server redirect:
1067 // use 'ORIGNAME:<oldName>' attribute instead of name of new server
1068 TString nameAttrib("ORIGNAME:");
1069 nameAttrib.Append(GetName());
1070
1071 if (auto tmp = std::unique_ptr<RooAbsCollection>{newSet.selectByAttrib(nameAttrib, true)}) {
1072
1073 // Check if any match was found
1074 if (tmp->empty()) {
1075 return nullptr;
1076 }
1077
1078 // Check if match is unique
1079 if (tmp->size() > 1) {
1080 std::stringstream ss;
1081 ss << "RooAbsArg::redirectServers(" << GetName() << "): FATAL Error, " << tmp->size() << " servers with "
1082 << nameAttrib << " attribute";
1083 coutF(LinkStateMgmt) << ss.str() << std::endl;
1084 tmp->Print("v");
1085 throw std::runtime_error(ss.str());
1086 }
1087
1088 // use the unique element in the set
1089 newServer = tmp->first();
1090 }
1091 }
1092 return newServer;
1093}
1094
1095namespace {
1096
1098 bool recurseInNewSet, std::set<RooAbsArg const *> &callStack)
1099{
1100 // Cyclic recursion protection
1101 {
1102 auto it = callStack.lower_bound(arg);
1103 if (it != callStack.end() && arg == *it) {
1104 return false;
1105 }
1106 callStack.insert(it, arg);
1107 }
1108
1109 // Do not recurse into newset if not so specified
1110 // if (!recurseInNewSet && newSet.contains(*arg)) {
1111 // return false;
1112 // }
1113
1114 // Apply the redirectServers function recursively on all branch nodes in this argument tree.
1115 bool ret(false);
1116
1117 oocxcoutD(arg, LinkStateMgmt) << "RooAbsArg::recursiveRedirectServers(" << arg << "," << arg->GetName()
1118 << ") newSet = " << newSet << " mustReplaceAll = " << (mustReplaceAll ? "T" : "F")
1119 << " nameChange = " << (nameChange ? "T" : "F")
1120 << " recurseInNewSet = " << (recurseInNewSet ? "T" : "F") << std::endl;
1121
1122 // Do redirect on self (identify operation as recursion step)
1124
1125 // Do redirect on servers
1126 for (const auto server : arg->servers()) {
1128 }
1129
1130 callStack.erase(arg);
1131 return ret;
1132}
1133
1134} // namespace
1135
1136/// Recursively replace all servers with the new servers in `newSet`.
1137/// This substitutes objects that we receive values from (also indirectly
1138/// through other objects) with new objects that have the same name.
1139///
1140/// *Copied from redirectServers:*
1141///
1142/// \copydetails RooAbsArg::redirectServers
1143/// \param newSet Roo collection
1144/// \param recurseInNewSet be recursive
1146 bool recurseInNewSet)
1147{
1148 // For cyclic recursion protection
1149 std::set<const RooAbsArg *> callStack;
1150
1152}
1153
1154/// Function that is called at the end of redirectServers(). Can be overloaded
1155/// to inject some class-dependent behavior after server redirection, e.g.
1156/// resetting of caches. The return value is meant to be an error flag, so in
1157/// case something goes wrong the function should return `true`. If you
1158/// overload this function, don't forget to also call the function of the
1159/// base class.
1160///
1161/// See: redirectServers() For a detailed explanation of the function parameters.
1162///
1163// \param[in] newServerList One of the original parameters passed to redirectServers().
1164// \param[in] mustReplaceAll One of the original parameters passed to redirectServers().
1165// \param[in] nameChange One of the original parameters passed to redirectServers().
1166// \param[in] isRecursiveStep One of the original parameters passed to redirectServers().
1167bool RooAbsArg::redirectServersHook(const RooAbsCollection & /*newServerList*/, bool /*mustReplaceAll*/,
1168 bool /*nameChange*/, bool /*isRecursiveStep*/)
1169{
1170 setProxyNormSet(nullptr);
1171 return false;
1172}
1173
1174/// Register an RooArgProxy in the proxy list. This function is called by owned
1175/// proxies upon creation. After registration, this arg will forward pointer
1176/// changes from serverRedirects and updates in cached normalization sets
1177/// to the proxies immediately after they occur. The proxied argument is
1178/// also added as value and/or shape server
1179
1181{
1182 // Every proxy can be registered only once
1183 if (_proxyList.FindObject(&proxy)) {
1184 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named " << proxy.GetName()
1185 << " for arg " << proxy.absArg()->GetName() << " already registered" << std::endl;
1186 return;
1187 }
1188
1189 // std::cout << (void*)this << " " << GetName() << ": registering proxy "
1190 // << (void*)&proxy << " with name " << proxy.name() << " in mode "
1191 // << (proxy.isValueServer()?"V":"-") << (proxy.isShapeServer()?"S":"-") << std::endl ;
1192
1193 // Register proxied object as server
1194 if (proxy.absArg()) {
1195 addServer(*proxy.absArg(), proxy.isValueServer(), proxy.isShapeServer());
1196 }
1197
1198 // Register proxy itself
1200 _proxyListCache.isDirty = true;
1201}
1202
1203/// Remove proxy from proxy list. This functions is called by owned proxies
1204/// upon their destruction.
1205
1212
1213/// Register an RooSetProxy in the proxy list. This function is called by owned
1214/// proxies upon creation. After registration, this arg will forward pointer
1215/// changes from serverRedirects and updates in cached normalization sets
1216/// to the proxies immediately after they occur.
1217
1219{
1220 // Every proxy can be registered only once
1221 if (_proxyList.FindObject(&proxy)) {
1222 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named " << proxy.GetName()
1223 << " already registered" << std::endl;
1224 return;
1225 }
1226
1227 // Register proxy itself
1229 _proxyListCache.isDirty = true;
1230}
1231
1232/// Remove proxy from proxy list. This functions is called by owned proxies
1233/// upon their destruction.
1234
1241
1242/// Register an RooListProxy in the proxy list. This function is called by owned
1243/// proxies upon creation. After registration, this arg will forward pointer
1244/// changes from serverRedirects and updates in cached normalization sets
1245/// to the proxies immediately after they occur.
1246
1248{
1249 // Every proxy can be registered only once
1250 if (_proxyList.FindObject(&proxy)) {
1251 coutE(LinkStateMgmt) << "RooAbsArg::registerProxy(" << GetName() << "): proxy named " << proxy.GetName()
1252 << " already registered" << std::endl;
1253 return;
1254 }
1255
1256 // Register proxy itself
1259 _proxyListCache.isDirty = true;
1260 if (_proxyList.GetEntries() != nProxyOld + 1) {
1261 std::cout << "RooAbsArg::registerProxy(" << GetName() << ") proxy registration failure! nold=" << nProxyOld
1262 << " nnew=" << _proxyList.GetEntries() << std::endl;
1263 }
1264}
1265
1266/// Remove proxy from proxy list. This functions is called by owned proxies
1267/// upon their destruction.
1268
1275
1276/// Return the nth proxy from the proxy list.
1277
1279{
1280 // Cross cast: proxy list returns TObject base pointer, we need
1281 // a RooAbsProxy base pointer. C++ standard requires
1282 // a dynamic_cast for this.
1283 return dynamic_cast<RooAbsProxy *>(_proxyList.At(index));
1284}
1285
1286/// Return the number of registered proxies.
1287
1289{
1290 return _proxyList.GetEntriesFast();
1291}
1292
1293/// Forward a change in the cached normalization argset
1294/// to all the registered proxies. Passing `nullptr` makes this object forget
1295/// any normalization set previously passed to `getVal()`, which is required if
1296/// that set may not outlive this object (e.g. it lived on the caller's stack),
1297/// as the proxies only keep a bare pointer to it.
1298
1300{
1302 // First time we loop over proxies: cache the results to avoid future
1303 // costly dynamic_casts
1304 _proxyListCache.cache.clear();
1305 for (int i = 0; i < numProxies(); i++) {
1306 RooAbsProxy *p = getProxy(i);
1307 if (!p)
1308 continue;
1309 _proxyListCache.cache.push_back(p);
1310 }
1311 _proxyListCache.isDirty = false;
1312 }
1313
1314 for (auto &p : _proxyListCache.cache) {
1315 p->changeNormSet(nset);
1316 }
1317
1318 // If the proxy normSet changed, we also have to set our value dirty flag.
1319 // Otherwise, value for the new normalization set might not get recomputed!
1320 setValueDirty();
1321}
1322
1323/// Overloadable function for derived classes to implement
1324/// attachment as branch to a TTree
1325
1327{
1328 coutE(Contents) << "RooAbsArg::attachToTree(" << GetName() << "): Cannot be attached to a TTree" << std::endl;
1329}
1330
1331/// WVE (08/21/01) Probably obsolete now
1332
1334{
1335 return true;
1336}
1337
1338/// Print object name
1339
1340void RooAbsArg::printName(std::ostream &os) const
1341{
1342 os << GetName();
1343}
1344
1345/// Print object title
1346
1347void RooAbsArg::printTitle(std::ostream &os) const
1348{
1349 os << GetTitle();
1350}
1351
1352/// Print object class name
1353
1354void RooAbsArg::printClassName(std::ostream &os) const
1355{
1356 os << ClassName();
1357}
1358
1359/// Print address of this RooAbsArg.
1360void RooAbsArg::printAddress(std::ostream &os) const
1361{
1362 os << this;
1363}
1364
1365/// Print object arguments, ie its proxies
1366
1367void RooAbsArg::printArgs(std::ostream &os) const
1368{
1369 // Print nothing if there are no dependencies
1370 if (numProxies() == 0)
1371 return;
1372
1373 os << "[ ";
1374 for (Int_t i = 0; i < numProxies(); i++) {
1375 RooAbsProxy *p = getProxy(i);
1376 if (p == nullptr)
1377 continue;
1378 if (!TString(p->name()).BeginsWith("!")) {
1379 p->print(os);
1380 os << " ";
1381 }
1382 }
1383 printMetaArgs(os);
1384 os << "]";
1385}
1386
1387/// Define default contents to print
1388
1390{
1391 return kName | kClassName | kValue | kArgs;
1392}
1393
1394/// Implement multi-line detailed printing
1395
1396void RooAbsArg::printMultiline(std::ostream &os, Int_t /*contents*/, bool /*verbose*/, TString indent) const
1397{
1398 os << indent << "--- RooAbsArg ---" << std::endl;
1399 // dirty state flags
1400 os << indent << " Value State: ";
1401 switch (_operMode) {
1402 case ADirty: os << "FORCED DIRTY"; break;
1403 case AClean: os << "FORCED clean"; break;
1404 case Auto: os << (isValueDirty() ? "DIRTY" : "clean"); break;
1405 }
1406 os << std::endl << indent << " Shape State: " << (isShapeDirty() ? "DIRTY" : "clean") << std::endl;
1407 // attribute list
1408 os << indent << " Attributes: ";
1409 printAttribList(os);
1410 os << std::endl;
1411 // our memory address (for x-referencing with client addresses of other args)
1412 os << indent << " Address: " << (void *)this << std::endl;
1413 // client list
1414 os << indent << " Clients: " << std::endl;
1415 for (const auto client : _clientList) {
1416 os << indent << " (" << (void *)client << "," << (_clientListValue.containsByNamePtr(client) ? "V" : "-")
1417 << (_clientListShape.containsByNamePtr(client) ? "S" : "-") << ") ";
1418 client->printStream(os, kClassName | kTitle | kName, kSingleLine);
1419 }
1420
1421 // server list
1422 os << indent << " Servers: " << std::endl;
1423 for (const auto server : _serverList) {
1424 os << indent << " (" << (void *)server << "," << (server->_clientListValue.containsByNamePtr(this) ? "V" : "-")
1425 << (server->_clientListShape.containsByNamePtr(this) ? "S" : "-") << ") ";
1426 server->printStream(os, kClassName | kName | kTitle, kSingleLine);
1427 }
1428
1429 // proxy list
1430 os << indent << " Proxies: " << std::endl;
1431 for (int i = 0; i < numProxies(); i++) {
1433 if (!proxy)
1434 continue;
1435 os << indent << " " << proxy->name() << " -> ";
1436 if (auto *argProxy = dynamic_cast<RooArgProxy *>(proxy)) {
1437 if (RooAbsArg *parg = argProxy->absArg()) {
1438 parg->printStream(os, kName, kSingleLine);
1439 } else {
1440 os << " (empty)" << std::endl;
1441 }
1442 // If a RooAbsProxy is not a RooArgProxy, it is a RooSetProxy or a
1443 // RooListProxy. However, they are treated the same in this function, so
1444 // we try the dynamic cast to their common base class, RooAbsCollection.
1445 } else if (auto *collProxy = dynamic_cast<RooAbsCollection *>(proxy)) {
1446 os << std::endl;
1448 moreIndent.Append(" ");
1449 collProxy->printStream(os, kName, kStandard, moreIndent.Data());
1450 } else {
1451 throw std::runtime_error("Unsupported proxy type.");
1452 }
1453 }
1454}
1455
1456/// Print object tree structure
1457
1458void RooAbsArg::printTree(std::ostream &os, TString /*indent*/) const
1459{
1460 const_cast<RooAbsArg *>(this)->printCompactTree(os);
1461}
1462
1463/// Ostream operator
1464
1465std::ostream &operator<<(std::ostream &os, RooAbsArg const &arg)
1466{
1467 arg.writeToStream(os, true);
1468 return os;
1469}
1470
1471/// Istream operator
1472
1473std::istream &operator>>(std::istream &is, RooAbsArg &arg)
1474{
1475 arg.readFromStream(is, true, false);
1476 return is;
1477}
1478
1479/// Print the attribute list
1480
1481void RooAbsArg::printAttribList(std::ostream &os) const
1482{
1483 std::set<std::string>::const_iterator iter = _boolAttrib.begin();
1484 bool first(true);
1485 while (iter != _boolAttrib.end()) {
1486 os << (first ? " [" : ",") << *iter;
1487 first = false;
1488 ++iter;
1489 }
1490 if (!first)
1491 os << "] ";
1492}
1493
1494/// Bind this node to objects in `set`.
1495/// Search the set for objects that have the same name as our servers, and
1496/// attach ourselves to those. After this operation, this node is computing its
1497/// values based on the new servers. This can be used to e.g. read values from
1498// a dataset.
1499
1501{
1503 branchNodeServerList(&branches, nullptr, true);
1504
1505 for (auto const &branch : branches) {
1506 branch->redirectServers(set, false, false);
1507 }
1508}
1509
1510/// Replace server nodes with names matching the dataset variable names
1511/// with those data set variables, making this PDF directly dependent on the dataset.
1512
1514{
1515 attachArgs(*data.get());
1516}
1517
1518/// Replace server nodes with names matching the dataset variable names
1519/// with those data set variables, making this PDF directly dependent on the dataset
1520
1525
1526/// Utility function used by TCollection::Sort to compare contained TObjects
1527/// We implement comparison by name, resulting in alphabetical sorting by object name.
1528
1530{
1531 return strcmp(GetName(), other->GetName());
1532}
1533
1534/// Print information about current value dirty state information.
1535/// If depth flag is true, information is recursively printed for
1536/// all nodes in this arg tree.
1537
1539{
1540 if (depth) {
1541
1544 for (RooAbsArg *branch : branchList) {
1545 branch->printDirty(false);
1546 }
1547
1548 } else {
1549 std::cout << GetName() << " : ";
1550 switch (_operMode) {
1551 case AClean: std::cout << "FORCED clean"; break;
1552 case ADirty: std::cout << "FORCED DIRTY"; break;
1553 case Auto: std::cout << "Auto " << (isValueDirty() ? "DIRTY" : "clean");
1554 }
1555 std::cout << std::endl;
1556 }
1557}
1558
1559/// Activate cache mode optimization with given definition of observables.
1560/// The cache operation mode of all objects in the expression tree will
1561/// modified such that all nodes that depend directly or indirectly on
1562/// any of the listed observables will be set to ADirty, as they are
1563/// expected to change every time. This save change tracking overhead for
1564/// nodes that are a priori known to change every time
1565
1567{
1569 RooArgSet opt;
1570 optimizeCacheMode(observables, opt, proc);
1571
1572 coutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << ") nodes " << opt
1573 << " depend on observables, "
1574 << "changing cache operation mode from change tracking to unconditional evaluation" << std::endl;
1575}
1576
1577/// Activate cache mode optimization with given definition of observables.
1578/// The cache operation mode of all objects in the expression tree will
1579/// modified such that all nodes that depend directly or indirectly on
1580/// any of the listed observables will be set to ADirty, as they are
1581/// expected to change every time. This save change tracking overhead for
1582/// nodes that are a priori known to change every time
1583
1586{
1587 // Optimization applies only to branch nodes, not to leaf nodes
1588 if (!isDerived()) {
1589 return;
1590 }
1591
1592 // Terminate call if this node was already processed (tree structure may be cyclical)
1593 // LM : RooLinkedList::findArg looks by name and not but by object pointer,
1594 // should one use RooLinkedList::FindObject (look by pointer) instead of findArg when
1595 // tree contains nodes with the same name ?
1596 // Add an info message if the require node does not exist but a different node already exists with same name
1597
1598 if (processedNodes.FindObject(this))
1599 return;
1600
1601 // check if findArgs returns something different (i.e. a different node with same name) when
1602 // this node has not been processed (FindObject returns a null pointer)
1603 auto obj = processedNodes.findArg(this);
1604 assert(obj != this); // obj == this cannot happen
1605 if (obj) {
1606 // here for nodes with duplicate names
1607 cxcoutI(Optimization) << "RooAbsArg::optimizeCacheMode(" << GetName() << " node " << this << " exists already as "
1608 << obj << " but with the SAME name !" << std::endl;
1609 }
1610
1611 processedNodes.Add(this);
1612
1613 // Set cache mode operator to 'AlwaysDirty' if we depend on any of the given observables
1614 if (dependsOnValue(observables)) {
1615
1616 if (dynamic_cast<RooRealIntegral *>(this)) {
1617 cxcoutI(Integration)
1618 << "RooAbsArg::optimizeCacheMode(" << GetName()
1619 << ") integral depends on value of one or more observables and will be evaluated for every event"
1620 << std::endl;
1621 }
1622 optimizedNodes.add(*this, true);
1623 if (operMode() == AClean) {
1624 } else {
1625 setOperMode(ADirty, true); // WVE propagate flag recursively to top of tree
1626 }
1627 } else {
1628 }
1629 // Process any RooAbsArgs contained in any of the caches of this object
1630 for (Int_t i = 0; i < numCaches(); i++) {
1632 }
1633
1634 // Forward calls to all servers
1635 for (const auto server : _serverList) {
1636 server->optimizeCacheMode(observables, optimizedNodes, processedNodes);
1637 }
1638}
1639
1640/// Find branch nodes with all-constant parameters, and add them to the list of
1641/// nodes that can be cached with a dataset in a test statistic calculation
1642
1644{
1646 bool ret = findConstantNodes(observables, cacheList, proc);
1647
1648 // If node can be optimized and hasn't been identified yet, add it to the list
1649 coutI(Optimization) << "RooAbsArg::findConstantNodes(" << GetName() << "): components " << cacheList
1650 << " depend exclusively on constant parameters and will be precalculated and cached"
1651 << std::endl;
1652
1653 return ret;
1654}
1655
1656/// Find branch nodes with all-constant parameters, and add them to the list of
1657/// nodes that can be cached with a dataset in a test statistic calculation
1658
1660{
1661 // Caching only applies to branch nodes
1662 if (!isDerived()) {
1663 return false;
1664 }
1665
1666 // Terminate call if this node was already processed (tree structure may be cyclical)
1667 if (processedNodes.findArg(this)) {
1668 return false;
1669 } else {
1670 processedNodes.Add(this);
1671 }
1672
1673 // Check if node depends on any non-constant parameter
1674 bool canOpt(true);
1676 getParameters(&observables, paramSet);
1677 for (RooAbsArg *param : paramSet) {
1678 if (!param->isConstant()) {
1679 canOpt = false;
1680 break;
1681 }
1682 }
1683
1684 if (getAttribute("NeverConstant")) {
1685 canOpt = false;
1686 }
1687
1688 if (canOpt) {
1689 setAttribute("ConstantExpression");
1690 }
1691
1692 // If yes, list node eligible for caching, if not test nodes one level down
1693 if (canOpt || getAttribute("CacheAndTrack")) {
1694
1695 if (!cacheList.find(*this) && dependsOnValue(observables) && !observables.find(*this)) {
1696
1697 // Add to cache list
1698 cxcoutD(Optimization) << "RooAbsArg::findConstantNodes(" << GetName()
1699 << ") adding self to list of constant nodes" << std::endl;
1700
1701 if (canOpt)
1702 setAttribute("ConstantExpressionCached");
1703 cacheList.add(*this, false);
1704 }
1705 }
1706
1707 if (!canOpt) {
1708
1709 // If not, see if next level down can be cached
1710 for (const auto server : _serverList) {
1711 if (server->isDerived()) {
1712 server->findConstantNodes(observables, cacheList, processedNodes);
1713 }
1714 }
1715 }
1716
1717 // Forward call to all cached contained in current object
1718 for (Int_t i = 0; i < numCaches(); i++) {
1720 }
1721
1722 return false;
1723}
1724
1725/// Interface function signaling a request to perform constant term
1726/// optimization. This default implementation takes no action other than to
1727/// forward the calls to all servers
1728
1730{
1731 for (const auto server : _serverList) {
1732 server->constOptimizeTestStatistic(opcode, doAlsoTrackingOpt);
1733 }
1734}
1735
1736/// Change cache operation mode to given mode. If recurseAdirty
1737/// is true, then a mode change to AlwaysDirty will automatically
1738/// be propagated recursively to all client nodes
1739
1741{
1742 // Prevent recursion loops
1743 if (mode == _operMode)
1744 return;
1745
1746 _operMode = mode;
1747 _fast = ((mode == AClean) || dynamic_cast<RooRealVar *>(this) || dynamic_cast<RooConstVar *>(this));
1748 for (Int_t i = 0; i < numCaches(); i++) {
1749 getCache(i)->operModeHook();
1750 }
1751 operModeHook();
1752
1753 // Propagate to all clients
1754 if (mode == ADirty && recurseADirty) {
1755 for (auto clientV : _clientListValue) {
1756 clientV->setOperMode(mode);
1757 }
1758 }
1759}
1760
1761/// Print tree structure of expression tree on stdout, or to file if filename is specified.
1762/// If namePat is not "*", only nodes with names matching the pattern will be printed.
1763/// The client argument is used in recursive calls to properly display the value or shape nature
1764/// of the client-server links. It should be zero in calls initiated by users.
1765
1766void RooAbsArg::printCompactTree(const char *indent, const char *filename, const char *namePat, RooAbsArg *client)
1767{
1768 if (filename) {
1769 std::ofstream ofs(filename);
1771 } else {
1772 printCompactTree(std::cout, indent, namePat, client);
1773 }
1774}
1775
1776/// Print tree structure of expression tree on given ostream.
1777/// If namePat is not "*", only nodes with names matching the pattern will be printed.
1778/// The client argument is used in recursive calls to properly display the value or shape nature
1779/// of the client-server links. It should be zero in calls initiated by users.
1780
1781void RooAbsArg::printCompactTree(std::ostream &os, const char *indent, const char *namePat, RooAbsArg *client)
1782{
1783 if (!namePat || TString(GetName()).Contains(namePat)) {
1784 os << indent << this;
1785 if (client) {
1786 os << "/";
1787 if (isValueServer(*client))
1788 os << "V";
1789 else
1790 os << "-";
1791 if (isShapeServer(*client))
1792 os << "S";
1793 else
1794 os << "-";
1795 }
1796 os << " ";
1797
1798 os << ClassName() << "::" << GetName() << " = ";
1799 printValue(os);
1800
1801 if (!_serverList.empty()) {
1802 switch (operMode()) {
1803 case Auto: os << " [Auto," << (isValueDirty() ? "Dirty" : "Clean") << "] "; break;
1804 case AClean: os << " [ACLEAN] "; break;
1805 case ADirty: os << " [ADIRTY] "; break;
1806 }
1807 }
1808 os << std::endl;
1809
1810 for (Int_t i = 0; i < numCaches(); i++) {
1812 }
1814 }
1815
1817 indent2 += " ";
1818 for (const auto arg : _serverList) {
1819 arg->printCompactTree(os, indent2, namePat, this);
1820 }
1821}
1822
1823/// Print tree structure of expression tree on given ostream, only branch nodes are printed.
1824/// Lead nodes (variables) will not be shown
1825///
1826/// If namePat is not "*", only nodes with names matching the pattern will be printed.
1827
1829{
1830 if (nLevel == 0)
1831 return;
1832 if (isFundamental())
1833 return;
1834 auto rmodel = dynamic_cast<RooResolutionModel *>(this);
1835 if (rmodel && rmodel->isConvolved())
1836 return;
1837 if (InheritsFrom("RooConstVar"))
1838 return;
1839
1840 if (!namePat || TString(GetName()).Contains(namePat)) {
1841 std::cout << indent;
1842 Print();
1843 }
1844
1846 indent2 += " ";
1847 for (const auto arg : _serverList) {
1848 arg->printComponentTree(indent2.Data(), namePat, nLevel - 1);
1849 }
1850}
1851
1852/// Construct a mangled name from the actual name that
1853/// is free of any math symbols that might be interpreted by TTree
1854
1856{
1857 // Check for optional alternate name of branch for this argument
1859 if (getStringAttribute("BranchName")) {
1860 rawBranchName = getStringAttribute("BranchName");
1861 }
1862
1864 cleanName.ReplaceAll("/", "D");
1865 cleanName.ReplaceAll("-", "M");
1866 cleanName.ReplaceAll("+", "P");
1867 cleanName.ReplaceAll("*", "X");
1868 cleanName.ReplaceAll("[", "L");
1869 cleanName.ReplaceAll("]", "R");
1870 cleanName.ReplaceAll("(", "L");
1871 cleanName.ReplaceAll(")", "R");
1872 cleanName.ReplaceAll("{", "L");
1873 cleanName.ReplaceAll("}", "R");
1874
1875 return cleanName;
1876}
1877
1878/// Hook function interface for object to insert additional information
1879/// when printed in the context of a tree structure. This default
1880/// implementation prints nothing
1881
1882void RooAbsArg::printCompactTreeHook(std::ostream &, const char *) {}
1883
1884/// Register RooAbsCache with this object. This function is called
1885/// by RooAbsCache constructors for objects that are a datamember
1886/// of this RooAbsArg. By registering itself the RooAbsArg is aware
1887/// of all its cache data members and will forward server change
1888/// and cache mode change calls to the cache objects, which in turn
1889/// can forward them their contents
1890
1892{
1893 _cacheList.push_back(&cache);
1894}
1895
1896/// Unregister a RooAbsCache. Called from the RooAbsCache destructor
1897
1899{
1900 _cacheList.erase(std::remove(_cacheList.begin(), _cacheList.end(), &cache), _cacheList.end());
1901}
1902
1903/// Return number of registered caches
1904
1906{
1907 return _cacheList.size();
1908}
1909
1910/// Return registered cache object by index
1911
1913{
1914 return _cacheList[index];
1915}
1916
1917/// Return RooArgSet with all variables (tree leaf nodes of expression tree)
1918
1923
1924/// Create a GraphViz .dot file visualizing the expression tree headed by
1925/// this RooAbsArg object. Use the GraphViz tool suite to make e.g. a gif
1926/// or ps file from the .dot file.
1927/// If a node derives from RooAbsReal, its current (unnormalised) value is
1928/// printed as well.
1929///
1930/// Based on concept developed by Kyle Cranmer.
1931
1932void RooAbsArg::graphVizTree(const char *fileName, const char *delimiter, bool useTitle, bool useLatex)
1933{
1934 std::ofstream ofs(fileName);
1935 if (!ofs) {
1936 coutE(InputArguments) << "RooAbsArg::graphVizTree() ERROR: Cannot open graphViz output file with name "
1937 << fileName << std::endl;
1938 return;
1939 }
1941}
1942
1943/// Write the GraphViz representation of the expression tree headed by
1944/// this RooAbsArg object to the given ostream.
1945/// If a node derives from RooAbsReal, its current (unnormalised) value is
1946/// printed as well.
1947///
1948/// Based on concept developed by Kyle Cranmer.
1949
1950void RooAbsArg::graphVizTree(std::ostream &os, const char *delimiter, bool useTitle, bool useLatex)
1951{
1952 if (!os) {
1953 coutE(InputArguments)
1954 << "RooAbsArg::graphVizTree() ERROR: output stream provided as input argument is in invalid state"
1955 << std::endl;
1956 }
1957
1958 // silent warning messages coming when evaluating a RooAddPdf without a normalization set
1960
1961 // Write header
1962 os << "digraph \"" << GetName() << "\"{" << std::endl;
1963
1964 // First list all the tree nodes
1967
1968 // iterate over nodes
1969 for (RooAbsArg *node : nodeSet) {
1970 std::string nodeName = node->GetName();
1971 std::string nodeTitle = node->GetTitle();
1972 std::string nodeLabel = (useTitle && !nodeTitle.empty()) ? nodeTitle : nodeName;
1973
1974 // if using latex, replace ROOT's # with normal latex backslash
1975 std::string::size_type position = nodeLabel.find('#');
1976 while (useLatex && position != nodeLabel.npos) {
1977 nodeLabel.replace(position, 1, "\\");
1978 }
1979
1980 std::string typeFormat = "\\texttt{";
1981 std::string nodeType = (useLatex) ? typeFormat + node->ClassName() + "}" : node->ClassName();
1982
1983 os << "\"" << nodeName << "\" [ color=" << (node->isFundamental() ? "blue" : "red") << ", label=\"" << nodeType
1984 << delimiter << nodeLabel;
1985
1986 if (auto realNode = dynamic_cast<RooAbsReal *>(node)) {
1987 os << delimiter << realNode->getVal();
1988 }
1989
1990 os << "\"];" << std::endl;
1991 }
1992
1993 // Get set of all server links
1994 std::set<std::pair<RooAbsArg *, RooAbsArg *>> links;
1996
1997 // And write them out
1998 for (auto const &link : links) {
1999 os << "\"" << link.first->GetName() << "\" -> \"" << link.second->GetName() << "\";" << std::endl;
2000 }
2001
2002 // Write trailer
2003 os << "}" << std::endl;
2004}
2005
2006/// Utility function that inserts all point-to-point client-server connections
2007/// between any two RooAbsArgs in the expression tree headed by this object
2008/// in the linkSet argument.
2009
2010void RooAbsArg::graphVizAddConnections(std::set<std::pair<RooAbsArg *, RooAbsArg *>> &linkSet)
2011{
2012 for (const auto server : _serverList) {
2013 linkSet.insert(std::make_pair(this, server));
2014 server->graphVizAddConnections(linkSet);
2015 }
2016}
2017
2018/// Take ownership of the contents of 'comps'.
2019
2021{
2022 if (!_ownedComponents) {
2023 _ownedComponents = new RooArgSet("owned components");
2024 }
2026}
2027
2028/// Take ownership of the contents of 'comps'. Different from the overload that
2029/// takes the RooArgSet by `const&`, this version can also take an owning
2030/// RooArgSet without error, because the ownership will not be ambiguous afterwards.
2031
2033{
2034 if (!_ownedComponents) {
2035 _ownedComponents = new RooArgSet("owned components");
2036 }
2037 return _ownedComponents->addOwned(std::move(comps));
2038}
2039
2040/// \copydoc RooAbsArg::addOwnedComponents(RooAbsCollection&& comps)
2041
2043{
2044 return addOwnedComponents(static_cast<RooAbsCollection &&>(std::move(comps)));
2045}
2046
2047/// Clone tree expression of objects. All tree nodes will be owned by
2048/// the head node return by cloneTree()
2049
2051{
2052 // In the RooHelpers, there is a more general implementation that we will reuse here
2054
2055 // Adjust name of head node if requested
2056 if (newname) {
2057 head->SetName(newname);
2058 }
2059
2060 // Return the head
2061 return head;
2062}
2063
2065{
2066 if (dynamic_cast<RooTreeDataStore *>(&store)) {
2067 attachToTree(*static_cast<RooTreeDataStore &>(store).tree());
2068 } else if (dynamic_cast<RooVectorDataStore *>(&store)) {
2069 attachToVStore(static_cast<RooVectorDataStore &>(store));
2070 }
2071}
2072
2074{
2075 if (_eocache) {
2076 return *_eocache;
2077 } else {
2079 }
2080}
2081
2083{
2084 std::string suffix;
2085
2088 for (RooAbsArg *arg : branches) {
2089 const char *tmp = arg->cacheUniqueSuffix();
2090 if (tmp)
2091 suffix += tmp;
2092 }
2093 return Form("%s", suffix.c_str());
2094}
2095
2097{
2100 for (auto const &arg : branches) {
2101 for (auto const &arg2 : arg->_cacheList) {
2102 arg2->wireCache();
2103 }
2104 }
2105}
2106
2107void RooAbsArg::SetName(const char *name)
2108{
2110 auto newPtr = RooNameReg::instance().constPtr(GetName());
2111 if (newPtr != _namePtr) {
2112 // cout << "Rename '" << _namePtr->GetName() << "' to '" << name << "' (set flag in new name)" << std::endl;
2113 _namePtr = newPtr;
2116 }
2117}
2118
2119void RooAbsArg::SetNameTitle(const char *name, const char *title)
2120{
2121 TNamed::SetTitle(title);
2122 SetName(name);
2123}
2124
2125/// Stream an object of class RooAbsArg.
2126
2128{
2129 if (R__b.IsReading()) {
2130 ioReadStack().push(this);
2131 R__b.ReadClassBuffer(RooAbsArg::Class(), this);
2132 ioReadStack().pop();
2133 _namePtr = RooNameReg::instance().constPtr(GetName());
2134 _isConstant = getAttribute("Constant");
2135 } else {
2136 R__b.WriteClassBuffer(RooAbsArg::Class(), this);
2137 }
2138}
2139
2140void RooAbsArg::addToIoEvoList(RooAbsArg *newObj, TRefArray const &onfileProxyList)
2141{
2142 ioEvoList()[newObj] = std::make_unique<TRefArray>(onfileProxyList);
2143}
2144
2145/// Method called by workspace container to finalize schema evolution issues
2146/// that cannot be handled in a single ioStreamer pass.
2147///
2148/// A second pass is typically needed when evolving data member of RooAbsArg-derived
2149/// classes that are container classes with references to other members, which may
2150/// not yet be 'live' in the first ioStreamer() evolution pass.
2151///
2152/// Classes may overload this function, but must call the base method in the
2153/// overloaded call to ensure base evolution is handled properly
2154
2156{
2157 // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2158 auto iter = ioEvoList().find(this);
2159 if (iter != ioEvoList().end()) {
2160
2161 // Transfer contents of saved TRefArray to RooRefArray now
2163 _proxyList.Expand(iter->second->GetEntriesFast());
2164 for (int i = 0; i < iter->second->GetEntriesFast(); i++) {
2165 _proxyList.Add(iter->second->At(i));
2166 }
2167 // Delete TRefArray and remove from list
2168 ioEvoList().erase(iter);
2169 }
2170}
2171
2172/// Method called by workspace container to finalize schema evolution issues
2173/// that cannot be handled in a single ioStreamer pass. This static finalize method
2174/// is called after ioStreamerPass2() is called on each directly listed object
2175/// in the workspace. It's purpose is to complete schema evolution of any
2176/// objects in the workspace that are not directly listed as content elements
2177/// (e.g. analytical convolution tokens )
2178
2180{
2181 // Handling of v5-v6 migration (TRefArray _proxyList --> RooRefArray _proxyList)
2182 for (const auto &iter : ioEvoList()) {
2183
2184 // Transfer contents of saved TRefArray to RooRefArray now
2185 if (!iter.first->_proxyList.GetEntriesFast())
2186 iter.first->_proxyList.Expand(iter.second->GetEntriesFast());
2187 for (int i = 0; i < iter.second->GetEntriesFast(); i++) {
2188 iter.first->_proxyList.Add(iter.second->At(i));
2189 }
2190 }
2191
2192 ioEvoList().clear();
2193}
2194
2199
2200/// Stream an object of class RooRefArray.
2201
2203{
2204 UInt_t R__s;
2205 UInt_t R__c;
2206 if (R__b.IsReading()) {
2207
2208 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
2209 if (R__v) {
2210 }
2211
2212 // Make temporary refArray and read that from the streamer
2213 auto refArray = std::make_unique<TRefArray>();
2214 refArray->Streamer(R__b);
2215 R__b.CheckByteCount(R__s, R__c, refArray->IsA());
2216
2217 // Schedule deferred processing of TRefArray into proxy list. Doesn't
2218 // need to be done if there are no proxies anyway.
2219 if (!refArray->IsEmpty()) {
2220 ioEvoList()[ioReadStack().top()] = std::move(refArray);
2221 }
2222
2223 } else {
2224
2225 R__c = R__b.WriteVersion(RooRefArray::IsA(), true);
2226
2227 // Make a temporary refArray and write that to the streamer
2229 for (TObject *tmpObj : *this) {
2230 refArray.Add(tmpObj);
2231 }
2232
2233 refArray.Streamer(R__b);
2234 R__b.SetByteCount(R__c, true);
2235 }
2236}
2237
2238/// Print at the prompt
2239namespace cling {
2240std::string printValue(RooAbsArg *raa)
2241{
2242 std::stringstream s;
2243 if (0 == *raa->GetName() && 0 == *raa->GetTitle()) {
2244 s << "An instance of " << raa->ClassName() << ".";
2245 return s.str();
2246 }
2247 raa->printStream(s, raa->defaultPrintContents(""), raa->defaultPrintStyle(""));
2248 return s.str();
2249}
2250} // namespace cling
2251
2252/// Disables or enables the usage of squared weights. Needs to be overloaded in
2253/// the likelihood classes for which this is relevant.
2255{
2256 for (auto *server : servers()) {
2257 server->applyWeightSquared(flag);
2258 }
2259}
2260
2261std::unique_ptr<RooAbsArg>
2263{
2264 auto newArg = std::unique_ptr<RooAbsArg>{static_cast<RooAbsArg *>(Clone())};
2265 ctx.markAsCompiled(*newArg);
2267 return newArg;
2268}
2269
2270/// Sets the token for retrieving results in the BatchMode. For internal use only.
2271/// If an `evaluator` is passed, it is the RooFit::Evaluator that resets the
2272/// token in its destructor, and this arg will notify it if it gets deleted
2273/// before the Evaluator.
2275{
2276 if (_dataToken != index) {
2277 if (hasDataToken()) {
2278 std::stringstream errMsg;
2279 errMsg << "The data token for \"" << GetName() << "\" is already set!"
2280 << " Are you trying to evaluate the same object by multiple RooFit::Evaluator instances?"
2281 << " This is not allowed.";
2282 throw std::runtime_error(errMsg.str());
2283 }
2284 _dataToken = index;
2285 }
2286 if (evaluator) {
2288 }
2289}
std::ostream & operator<<(std::ostream &os, RooAbsArg const &arg)
Ostream operator.
std::istream & operator>>(std::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
General string (char)
Definition RtypesCore.h:76
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
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 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 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:145
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2496
const_iterator begin() const
const_iterator end() const
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.
RooRefArray _proxyList
Definition RooAbsArg.h:571
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
! Cached isConstant status
Definition RooAbsArg.h:660
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
Definition RooAbsArg.h:239
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.
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:504
std::map< std::string, std::string > _stringAttrib
Definition RooAbsArg.h:590
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
! cache of the list of proxies. Avoids type casting.
Definition RooAbsArg.h:622
bool recursiveRedirectServers(const RooAbsCollection &newSet, bool mustReplaceAll=false, bool nameChange=false, bool recurseInNewSet=true)
Recursively replace all servers with the new servers in newSet.
~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
! Set of owned component
Definition RooAbsArg.h:653
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:432
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'.
bool isShapeServer(const RooAbsArg &arg) const
Check if this is serving shape to arg.
Definition RooAbsArg.h:162
bool isShapeDirty() const
Definition RooAbsArg.h:351
static void ioStreamerPass2Finalize()
Method called by workspace container to finalize schema evolution issues that cannot be handled in a ...
bool _fast
Definition RooAbsArg.h:650
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:647
void SetName(const char *name) override
Set the name of the TNamed.
RooSTLRefCountList< RooAbsArg > RefCountList_t
Definition RooAbsArg.h:79
void setDataToken(std::size_t index, RooFit::Evaluator *evaluator=nullptr)
Sets the token for retrieving results in the BatchMode.
std::set< std::string > _boolAttrib
Definition RooAbsArg.h:589
void unRegisterCache(RooAbsCache &cache)
Unregister a RooAbsCache. Called from the RooAbsCache destructor.
RefCountList_t _clientListValue
Definition RooAbsArg.h:569
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
void printAttribList(std::ostream &os) const
Print the attribute list.
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
Definition RooAbsArg.h:625
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
! De-duplicated name pointer, equal for all objects with the same name.
Definition RooAbsArg.h:659
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:535
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:646
bool _prohibitServerRedirect
! Prohibit server redirects – Debugging tool
Definition RooAbsArg.h:655
virtual const char * cacheUniqueSuffix() const
Definition RooAbsArg.h:435
RefCountListLegacyIterator_t * makeLegacyIterator(const RefCountList_t &list) const
const RefCountList_t & servers() const
List of all servers of this object.
Definition RooAbsArg.h:146
std::size_t _dataToken
! Set by the RooFitDriver for this arg to ! retrieve its result in the run context
Definition RooAbsArg.h:666
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:105
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.
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:98
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:649
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:426
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
bool hasDataToken() const
Definition RooAbsArg.h:637
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:568
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
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.
void printName(std::ostream &os) const override
Print object name.
bool isValueDirty() const
Definition RooAbsArg.h:357
bool _localNoInhibitDirty
! Prevent 'AlwaysDirty' mode for this node
Definition RooAbsArg.h:662
virtual void printMetaArgs(std::ostream &) const
Definition RooAbsArg.h:250
virtual void applyWeightSquared(bool flag)
Disables or enables the usage of squared weights.
static bool _inhibitDirty
Definition RooAbsArg.h:626
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.
static TClass * Class()
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:567
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:566
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
! Pointer to global cache manager for expensive components.
Definition RooAbsArg.h:657
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:176
virtual bool isValid() const
WVE (08/21/01) Probably obsolete now.
std::set< std::string > _boolAttribTransient
! Transient boolean attributes (not copied in ctor)
Definition RooAbsArg.h:591
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::vector< RooAbsCache * > _cacheList
! list of caches
Definition RooAbsArg.h:573
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)
Private helper function for RooAbsArg::redirectServers().
bool getTransientAttribute(const Text_t *name) const
Check if a named attribute is set.
virtual void operModeHook()
Definition RooAbsArg.h:528
bool recursiveCheckObservables(const RooArgSet *nset) const
Recursively call checkObservables on all nodes in the expression tree.
RooFit::Evaluator * _evaluator
! The Evaluator that set the data token and resets it in its destructor
Definition RooAbsArg.h:668
bool isValueServer(const RooAbsArg &arg) const
Check if this is serving values to arg.
Definition RooAbsArg.h:158
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
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:420
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.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for a data collection.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:56
virtual const RooArgSet * get() const
Definition RooAbsData.h:100
Abstract interface for proxy classes.
Definition RooAbsProxy.h:37
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
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
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
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.
void markAsCompiled(RooAbsArg &arg) const
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
Evaluates a RooAbsReal object in other ways than recursive graph traversal.
Definition Evaluator.h:35
void unregisterNode(RooAbsArg const &arg)
Called from RooAbsArg::~RooAbsArg() when a node of the computation graph is deleted while this Evalua...
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...
Registry for const char* names.
Definition RooNameReg.h:26
@ kRenamedArg
TNamed flag to indicate that some RooAbsArg has been renamed (flag set in new name)
Definition RooNameReg.h:46
static RooNameReg & instance()
Return reference to singleton instance.
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 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.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fName
Definition TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:149
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:170
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:42
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:224
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:885
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:546
An array of references to TObjects.
Definition TRefArray.h:33
Basic string class.
Definition TString.h:138
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:632
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
A TTree represents a columnar dataset.
Definition TTree.h:89
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::vector< RooAbsProxy * > cache
Definition RooAbsArg.h:619