Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooTemplateProxy.h
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * File: $Id: RooRealProxy.h,v 1.23 2007/07/12 20:30:28 wouter Exp $
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#ifndef ROO_TEMPLATE_PROXY
17#define ROO_TEMPLATE_PROXY
18
19#include "RooAbsReal.h"
20#include "RooArgProxy.h"
21#include "RooAbsRealLValue.h"
22#include "RooAbsCategory.h"
23#include "RooMsgService.h"
24#include <string>
25
26/**
27\class RooTemplateProxy
28\ingroup Roofitcore
29
30## Introduction
31A RooTemplateProxy is used to hold references to other RooFit objects in an expression tree.
32A `RooGaussian(..., x, mean, sigma)` can e.g. store references to `x, mean, sigma` as
33```
34RooTemplateProxy<RooAbsReal> _x;
35RooTemplateProxy<RooAbsReal> _mean;
36RooTemplateProxy<RooAbsReal> _sigma;
37```
38Now, the values of these three can be accessed, and the template argument ensures that only objects that evaluate
39to real numbers (RooAbsReal) can be stored in such a proxy. These can e.g. be variables, PDFs and functions.
40To store an object that's a `RooCategory`, one would, for example, use
41```
42RooTemplateProxy<RooCategory> _category;
43```
44
45Since %ROOT 6.22, the proxy can be used like a pointer to an instance of the template argument.
46For this, it provides `operator*` and `operator->`, e.g.
47```
48double oldValue = _x->getVal(normalisationSet);
49*_x = 17.;
50```
51
52RooTemplateProxy's base class RooArgProxy registers the proxied objects as "servers" of the object
53that holds the proxy. When the value of the proxied object is changed, the owner is
54notified, and can recalculate its own value. Renaming or exchanging objects that
55serve values to the owner of the proxy is handled automatically.
56
57## Modernisation of proxies in %ROOT 6.22
58In ROOT 6.22, the classes RooRealProxy and RooCategoryProxy were replaced by RooTemplateProxy<class T>.
59
60Two typedefs have been defined for backward compatibility:
61- `RooRealProxy = RooTemplateProxy<RooAbsReal>`. Any generic object that converts to a real value.
62- `RooCategoryProxy = RooTemplateProxy<RooAbsCategory>`. Any category object.
63
64To modernise a class, one can change the template argument of the proxy to the most appropriate type,
65and increment the class version of the owner.
66
67<table>
68<tr><th> %RooFit before %ROOT 6.22 <th> %RooFit starting with %ROOT 6.22
69<tr><td>
70~~~{.cpp}
71// In .h: Declare member
72RooRealProxy pdfProxy;
73
74ClassDef(MyPdf, 1)
75};
76
77// In .cxx: Initialise proxy in constructor
78// The proxy will accept any RooAbsArg, so the type of
79// "thePdf" has to be checked manually.
80MyPdf::MyPdf(name, title, ...) :
81 pdfProxy("pdfProxy", "Proxy holding a PDF", this, thePdf) {
82 [ Extra checking here ... ]
83}
84
85
86// In .cxx: Accessing the proxy
87RooAbsArg* absArg = pdfProxy.absArg();
88RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(absArg);
89assert(pdf); // Manual type checking ...
90pdf->fitTo(...);
91~~~
92<td>
93~~~{.cpp}
94// In .h: Declare member
95RooTemplateProxy<RooAbsPdf> pdfProxy;
96
97ClassDef(MyPdf, 2)
98};
99
100// In .cxx: Initialise proxy in constructor
101// The program will not compile if "thePdf" is not a
102// type deriving from RooAbsPdf
103MyPdf::MyPdf(name, title, ...) :
104 pdfProxy("pdfProxy", "Proxy holding a PDF", this, thePdf) {
105
106}
107
108
109// In .cxx: Accessing the proxy
110
111
112
113pdfProxy->fitTo(...);
114~~~
115</table>
116
117
118### How to modernise old code
119
1201. Choose the proper template argument for the proxy.
121 - If a PDF is stored: `RooTemplateProxy<RooAbsPdf>`.
122 - If a real-valued object is stored: `RooTemplateProxy<RooAbsReal>`.
123 - If a category is stored: `RooTemplateProxy<RooCategory>`.
124 - If a variable is stored (i.e. one wants to be able to assign values to it): `RooTemplateProxy<RooRealVar>`
125 Other template arguments are possible, as long as they derive from RooAbsArg.
1262. Increment the class version of the owning class.
1273. Make sure that the right type is passed in the constructor of the proxy.
1284. Always use `proxy->` and `*proxy` to work with the stored object. No need to cast.
1295. **Only if necessary** If errors about missing symbols connected to RooTemplateProxy appear at link time,
130 a specific template instantiation for RooTemplateProxy is not yet in ROOT's dictionaries.
131 These two lines should be added to the LinkDef.h of the project:
132 ~~~{.cpp}
133 #pragma link C++ class RooTemplateProxy<RooMultiCategory>+;
134 #pragma read sourceClass="RooCategoryProxy" targetClass="RooTemplateProxy<RooMultiCategory>"
135 ~~~
136 Replace `RooMultiCategory` by the proper type. If the proxy was holding a real-valued object, use `sourceClass="RooRealProxy"`.
137
138 The first line adds the proxy class to the dictionary, the second line enables reading a legacy
139 `RooCategoryProxy` from a file, and converting it to the new type-safe proxy. If no old proxies
140 have to be read from files, this line can be omitted.
141
142 If the template instantiation that triggered the missing symbols seems to be a very common instantiation,
143 request for it to be added to RooFit by creating a pull request for ROOT. If it is rather uncommon,
144 it is sufficient to add it to the LinkDef.h of the local project only.
145
146**/
147
148template<class T>
150public:
151
153
154 ////////////////////////////////////////////////////////////////////////////////
155 /// Constructor with owner.
156 /// \param[in] theName Name of this proxy (for printing).
157 /// \param[in] desc Description what this proxy should act as.
158 /// \param[in] owner The object that owns the proxy. This is important for tracking
159 /// of client-server dependencies.
160 /// \param[in] valueServer Notify the owner if value changes.
161 /// \param[in] shapeServer Notify the owner if shape (e.g. binning) changes.
162 /// \param[in] proxyOwnsArg Proxy will delete the payload if owning.
163 RooTemplateProxy(const char* theName, const char* desc, RooAbsArg* owner,
164 Bool_t valueServer=true, Bool_t shapeServer=false, Bool_t proxyOwnsArg=false)
165 : RooArgProxy(theName, desc, owner, valueServer, shapeServer, proxyOwnsArg) { }
166
167 ////////////////////////////////////////////////////////////////////////////////
168 /// Constructor with owner and proxied object.
169 /// \param[in] theName Name of this proxy (for printing).
170 /// \param[in] desc Description what this proxy should act as.
171 /// \param[in] owner The object that owns the proxy. This is important for tracking
172 /// of client-server dependencies.
173 /// \param[in] ref Reference to the object that the proxy should hold.
174 /// \param[in] valueServer Notify the owner if value changes.
175 /// \param[in] shapeServer Notify the owner if shape (e.g. binning) changes.
176 /// \param[in] proxyOwnsArg Proxy will delete the payload if owning.
177 RooTemplateProxy(const char* theName, const char* desc, RooAbsArg* owner, T& ref,
178 Bool_t valueServer=true, Bool_t shapeServer=false, Bool_t proxyOwnsArg=false) :
179 RooArgProxy(theName, desc, owner, const_cast<typename std::remove_const<T>::type&>(ref), valueServer, shapeServer, proxyOwnsArg) { }
180
181
182 ////////////////////////////////////////////////////////////////////////////////
183 /// Copy from an existing proxy.
184 /// It will accept any RooTemplateProxy instance, and attempt a dynamic_cast on its payload.
185 /// \param[in] theName Name of this proxy.
186 /// \param[in] owner Pointer to the owner this proxy should be registered to.
187 /// \param[in] other Instance of a differen proxy whose payload should be copied.
188 /// \param[in] allowWrongTypes Instead of throwing a std::invalid_argument, only issue an
189 /// error message when payload with wrong type is found. This is unsafe, but may be necessary
190 /// when reading back legacy types. Defaults to false.
191 /// \throw std::invalid_argument if the types of the payloads are incompatible.
192 template<typename U>
193 RooTemplateProxy(const char* theName, RooAbsArg* owner, const RooTemplateProxy<U>& other, bool allowWrongTypes = false) :
194 RooArgProxy(theName, owner, other) {
195 if (_arg && !dynamic_cast<const T*>(_arg)) {
196 if (allowWrongTypes) {
197 coutE(InputArguments) << "Error trying to copy an argument from a proxy with an incompatible payload." << std::endl;
198 } else {
199 throw std::invalid_argument("Tried to construct a RooTemplateProxy with incompatible payload.");
200 }
201 }
202 }
203
204 virtual TObject* Clone(const char* newName=0) const { return new RooTemplateProxy<T>(newName,_owner,*this); }
205
206
207 /// Return reference to the proxied object.
208 T& operator*() const {
209 return static_cast<T&>(*_arg);
210 }
211
212 /// Member access operator to proxied object.
213 T* operator->() const {
214 return static_cast<T*>(_arg);
215 }
216
217
218 /// Convert the proxy into a number.
219 /// \return A category proxy will return the index state, real proxies the result of RooAbsReal::getVal(normSet).
220 operator typename T::value_type() const {
221 return retrieveValue(arg());
222 }
223
224
225 ////////////////////////////////////////////////////////////////////////////////
226 /// Change object held in proxy into newRef
227 bool setArg(T& newRef) {
228 if (_arg) {
229 if (std::string(arg().GetName()) != newRef.GetName()) {
230 newRef.setAttribute(Form("ORIGNAME:%s", arg().GetName())) ;
231 }
232 return changePointer(RooArgSet(newRef), true);
233 } else {
234 return changePointer(RooArgSet(newRef), false, true);
235 }
236 }
237
238
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Create a new object held and owned by proxy.
241 /// Can only be done if the proxy was non-owning before.
242 template<class U, class... ConstructorArgs>
243 U& emplaceOwnedArg(ConstructorArgs&&... constructorArgs) {
244 if(_ownArg) {
245 // let's maybe not support overwriting owned args unless it becomes necessary
246 throw std::runtime_error("Error in RooTemplateProxy: emplaceOwnedArg<>() called on a proxy already owning an arg.");
247 }
248 auto ownedArg = new U{std::forward<ConstructorArgs>(constructorArgs)...};
249 setArg(*ownedArg);
250 _ownArg = true;
251 return *ownedArg;
252 }
253
254
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Move a new object held and owned by proxy.
257 /// Can only be done if the proxy was non-owning before.
258 template<class U>
259 U& putOwnedArg(std::unique_ptr<U> ownedArg) {
260 if(_ownArg) {
261 // let's maybe not support overwriting owned args unless it becomes necessary
262 throw std::runtime_error("Error in RooTemplateProxy: putOwnedArg<>() called on a proxy already owning an arg.");
263 }
264 auto argPtr = ownedArg.get();
265 setArg(*ownedArg.release());
266 _ownArg = true;
267 return *argPtr;
268 }
269
270 /// \name Legacy interface
271 /// In ROOT versions before 6.22, RooFit didn't have this typed proxy. Therefore, a number of functions
272 /// for forwarding calls to the proxied objects were necessary. The functions in this group can all be
273 /// replaced by directly accessing the proxied objects using e.g. the member access operator like
274 /// `proxy->function()` or by dereferencing like `*proxy = value`.
275 /// For this to work, choose the template argument appropriately. That is, if the
276 /// proxy stores a PDF, use `RooTemplateProxy<RooAbsPdf>`, *etc.*.
277 /// @{
278
279 /// Get the label of the current category state. This function only makes sense for category proxies.
280 const char* label() const {
281 return arg().getCurrentLabel();
282 }
283
284 /// Check if the stored object has a range with the given name.
285 bool hasRange(const char* rangeName) const {
286 return arg().hasRange(rangeName);
287 }
288
289 /// Return reference to object held in proxy.
290 const T& arg() const { return static_cast<const T&>(*_arg); }
291
292 /// Assign a new value to the object pointed to by the proxy.
293 /// This requires the payload to be assignable (RooAbsRealLValue or derived, RooAbsCategoryLValue).
294 RooTemplateProxy<T>& operator=(typename T::value_type value) {
295 lvptr(static_cast<T*>(nullptr))->operator=(value);
296 return *this;
297 }
298 /// Set a category state using its state name. This function can only work for category-type proxies.
299 RooTemplateProxy<T>& operator=(const std::string& newState) {
300 static_assert(std::is_base_of<RooAbsCategory, T>::value, "Strings can only be assigned to category proxies.");
301 lvptr(static_cast<RooAbsCategoryLValue*>(nullptr))->operator=(newState.c_str());
302 return *this;
303 }
304
305 /// Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived.
306 double min(const char* rname=0) const { return lvptr(static_cast<const T*>(nullptr))->getMin(rname) ; }
307 /// Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived.
308 double max(const char* rname=0) const { return lvptr(static_cast<const T*>(nullptr))->getMax(rname) ; }
309 /// Check if the range has a lower bound. This requires the payload to be RooAbsRealLValue or derived.
310 bool hasMin(const char* rname=0) const { return lvptr(static_cast<const T*>(nullptr))->hasMin(rname) ; }
311 /// Check if the range has a upper bound. This requires the payload to be RooAbsRealLValue or derived.
312 bool hasMax(const char* rname=0) const { return lvptr(static_cast<const T*>(nullptr))->hasMax(rname) ; }
313
314 /// @}
315
316
317private:
318 /// Are we a real-valued proxy or a category proxy?
319 using LValue_t = typename std::conditional<std::is_base_of<RooAbsReal, T>::value,
321
322 ////////////////////////////////////////////////////////////////////////////////
323 /// Return l-value pointer to contents. If the contents derive from RooAbsLValue or RooAbsCategoryLValue,
324 /// the conversion is safe, and the function directly returns the pointer using a static_cast.
325 /// If the template parameter of this proxy is not an LValue type, then
326 /// - in a debug build, a dynamic_cast with an assertion is used.
327 /// - in a release build, a static_cast is forced, irrespective of what the type of the object actually is. This
328 /// is dangerous, but equivalent to the behaviour before refactoring the RooFit proxies.
329 /// \deprecated This function is unneccessary if the template parameter is RooAbsRealLValue (+ derived types) or
330 /// RooAbsCategoryLValue (+derived types), as arg() will always return the correct type.
331 const LValue_t* lvptr(const LValue_t*) const {
332 return static_cast<const LValue_t*>(_arg);
333 }
334 /// \copydoc lvptr(const LValue_t*) const
336 return static_cast<LValue_t*>(_arg);
337 }
338 /// \copydoc lvptr(const LValue_t*) const
339 const LValue_t* lvptr(const RooAbsArg*) const
340 R__SUGGEST_ALTERNATIVE("The template argument of RooTemplateProxy needs to derive from RooAbsRealLValue or RooAbsCategoryLValue to safely call this function.") {
341#ifdef NDEBUG
342 return static_cast<const LValue_t*>(_arg);
343#else
344 auto theArg = dynamic_cast<const LValue_t*>(_arg);
345 assert(theArg);
346 return theArg;
347#endif
348 }
349 /// \copydoc lvptr(const LValue_t*) const
351 R__SUGGEST_ALTERNATIVE("The template argument of RooTemplateProxy needs to derive from RooAbsRealLValue or RooAbsCategoryLValue to safely call this function.") {
352#ifdef NDEBUG
353 return static_cast<LValue_t*>(_arg);
354#else
355 auto theArg = dynamic_cast<LValue_t*>(_arg);
356 assert(theArg);
357 return theArg;
358#endif
359 }
360
361
362 /// Retrieve index state from a category.
363 typename T::value_type retrieveValue(const RooAbsCategory& cat) const {
364 return cat.getCurrentIndex();
365 }
366
367 /// Retrieve value from a real-valued object.
368 typename T::value_type retrieveValue(const RooAbsReal& real) const {
369 return real.getVal(_nset);
370 }
371
372 ClassDef(RooTemplateProxy,1) // Proxy for a RooAbsReal object
373};
374
375#endif
#define R__SUGGEST_ALTERNATIVE(ALTERNATIVE)
Definition RConfig.hxx:524
#define coutE(a)
#define ClassDef(name, id)
Definition Rtypes.h:325
int type
Definition TGX11.cxx:121
char * Form(const char *fmt,...)
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
RooAbsCategoryLValue is the common abstract base class for objects that represent a discrete value th...
RooAbsCategory is the base class for objects that represent a discrete value with a finite number of ...
virtual value_type getCurrentIndex() const
Return index number of current state.
RooArgSet * _nset
! Normalization set to be used for evaluation of RooAbsPdf contents
Definition RooAbsProxy.h:53
RooAbsRealLValue is the common abstract base class for objects that represent a real value that may a...
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:64
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:94
RooArgProxy is the abstract interface for RooAbsArg proxy classes.
Definition RooArgProxy.h:24
RooAbsArg * _owner
Definition RooArgProxy.h:64
virtual Bool_t changePointer(const RooAbsCollection &newServerSet, Bool_t nameChange=kFALSE, Bool_t factoryInitMode=kFALSE)
Change proxied object to object of same name in given list.
RooAbsArg * owner() const
Returns the owner of this proxy.
Definition RooArgProxy.h:49
RooAbsArg * _arg
Definition RooArgProxy.h:65
Bool_t _ownArg
Definition RooArgProxy.h:70
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:35
LValue_t * lvptr(RooAbsArg *)
Return l-value pointer to contents.
bool hasMax(const char *rname=0) const
Check if the range has a upper bound. This requires the payload to be RooAbsRealLValue or derived.
bool hasRange(const char *rangeName) const
Check if the stored object has a range with the given name.
RooTemplateProxy(const char *theName, const char *desc, RooAbsArg *owner, T &ref, Bool_t valueServer=true, Bool_t shapeServer=false, Bool_t proxyOwnsArg=false)
Constructor with owner and proxied object.
T & operator*() const
Return reference to the proxied object.
T::value_type retrieveValue(const RooAbsCategory &cat) const
Retrieve index state from a category.
RooTemplateProxy(const char *theName, RooAbsArg *owner, const RooTemplateProxy< U > &other, bool allowWrongTypes=false)
Copy from an existing proxy.
RooTemplateProxy< T > & operator=(typename T::value_type value)
Assign a new value to the object pointed to by the proxy.
double min(const char *rname=0) const
Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived.
double max(const char *rname=0) const
Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived.
U & putOwnedArg(std::unique_ptr< U > ownedArg)
Move a new object held and owned by proxy.
RooTemplateProxy< T > & operator=(const std::string &newState)
Set a category state using its state name. This function can only work for category-type proxies.
const LValue_t * lvptr(const RooAbsArg *) const
Return l-value pointer to contents.
const LValue_t * lvptr(const LValue_t *) const
Return l-value pointer to contents.
bool hasMin(const char *rname=0) const
Check if the range has a lower bound. This requires the payload to be RooAbsRealLValue or derived.
virtual TObject * Clone(const char *newName=0) const
Make a clone of an object using the Streamer facility.
const char * label() const
Get the label of the current category state. This function only makes sense for category proxies.
RooTemplateProxy(const char *theName, const char *desc, RooAbsArg *owner, Bool_t valueServer=true, Bool_t shapeServer=false, Bool_t proxyOwnsArg=false)
Constructor with owner.
T * operator->() const
Member access operator to proxied object.
LValue_t * lvptr(LValue_t *)
Return l-value pointer to contents.
T::value_type retrieveValue(const RooAbsReal &real) const
Retrieve value from a real-valued object.
bool setArg(T &newRef)
Change object held in proxy into newRef.
U & emplaceOwnedArg(ConstructorArgs &&... constructorArgs)
Create a new object held and owned by proxy.
const T & arg() const
Return reference to object held in proxy.
typename std::conditional< std::is_base_of< RooAbsReal, T >::value, RooAbsRealLValue, RooAbsCategoryLValue >::type LValue_t
Are we a real-valued proxy or a category proxy?
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41