|
||||
Warning, file /include/root/RooTemplateProxy.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /***************************************************************************** 0002 * Project: RooFit * 0003 * Package: RooFitCore * 0004 * File: $Id: RooRealProxy.h,v 1.23 2007/07/12 20:30:28 wouter Exp $ 0005 * Authors: * 0006 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * 0007 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * 0008 * * 0009 * Copyright (c) 2000-2005, Regents of the University of California * 0010 * and Stanford University. All rights reserved. * 0011 * * 0012 * Redistribution and use in source and binary forms, * 0013 * with or without modification, are permitted according to the terms * 0014 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * 0015 *****************************************************************************/ 0016 #ifndef ROO_TEMPLATE_PROXY 0017 #define ROO_TEMPLATE_PROXY 0018 0019 #include "RooAbsReal.h" 0020 #include "RooArgProxy.h" 0021 #include "RooAbsRealLValue.h" 0022 #include "RooAbsCategory.h" 0023 #include "RooMsgService.h" 0024 #include <string> 0025 0026 /** 0027 \class RooTemplateProxy 0028 \ingroup Roofitcore 0029 0030 ## Introduction 0031 A RooTemplateProxy is used to hold references to other RooFit objects in an expression tree. 0032 A `RooGaussian(..., x, mean, sigma)` can e.g. store references to `x, mean, sigma` as 0033 ``` 0034 RooTemplateProxy<RooAbsReal> _x; 0035 RooTemplateProxy<RooAbsReal> _mean; 0036 RooTemplateProxy<RooAbsReal> _sigma; 0037 ``` 0038 Now, the values of these three can be accessed, and the template argument ensures that only objects that evaluate 0039 to real numbers (RooAbsReal) can be stored in such a proxy. These can e.g. be variables, PDFs and functions. 0040 To store an object that's a `RooCategory`, one would, for example, use 0041 ``` 0042 RooTemplateProxy<RooCategory> _category; 0043 ``` 0044 0045 Since %ROOT 6.22, the proxy can be used like a pointer to an instance of the template argument. 0046 For this, it provides `operator*` and `operator->`, e.g. 0047 ``` 0048 double oldValue = _x->getVal(normalisationSet); 0049 *_x = 17.; 0050 ``` 0051 0052 RooTemplateProxy's base class RooArgProxy registers the proxied objects as "servers" of the object 0053 that holds the proxy. When the value of the proxied object is changed, the owner is 0054 notified, and can recalculate its own value. Renaming or exchanging objects that 0055 serve values to the owner of the proxy is handled automatically. 0056 0057 ## Modernisation of proxies in ROOT 6.22 0058 In ROOT 6.22, the classes RooRealProxy and RooCategoryProxy were replaced by RooTemplateProxy<class T>. 0059 0060 Two typedefs have been defined for backward compatibility: 0061 - `RooRealProxy = RooTemplateProxy<RooAbsReal>`. Any generic object that converts to a real value. 0062 - `RooCategoryProxy = RooTemplateProxy<RooAbsCategory>`. Any category object. 0063 0064 To modernise a class, one can change the template argument of the proxy to the most appropriate type, 0065 and increment the class version of the owner. 0066 0067 <table> 0068 <tr><th> %RooFit before %ROOT 6.22 <th> %RooFit starting with %ROOT 6.22 0069 <tr><td> 0070 ~~~{.cpp} 0071 // In .h: Declare member 0072 RooRealProxy pdfProxy; 0073 0074 ClassDefOverride(MyPdf, 1) 0075 }; 0076 0077 // In .cxx: Initialise proxy in constructor 0078 // The proxy will accept any RooAbsArg, so the type of 0079 // "thePdf" has to be checked manually. 0080 MyPdf::MyPdf(name, title, ...) : 0081 pdfProxy("pdfProxy", "Proxy holding a PDF", this, thePdf) { 0082 [ Extra checking here ... ] 0083 } 0084 0085 0086 // In .cxx: Accessing the proxy 0087 RooAbsArg* absArg = pdfProxy.absArg(); 0088 RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(absArg); 0089 assert(pdf); // Manual type checking ... 0090 pdf->fitTo(...); 0091 ~~~ 0092 <td> 0093 ~~~{.cpp} 0094 // In .h: Declare member 0095 RooTemplateProxy<RooAbsPdf> pdfProxy; 0096 0097 ClassDefOverride(MyPdf, 2) 0098 }; 0099 0100 // In .cxx: Initialise proxy in constructor 0101 // The program will not compile if "thePdf" is not a 0102 // type deriving from RooAbsPdf 0103 MyPdf::MyPdf(name, title, ...) : 0104 pdfProxy("pdfProxy", "Proxy holding a PDF", this, thePdf) { 0105 0106 } 0107 0108 0109 // In .cxx: Accessing the proxy 0110 0111 0112 0113 pdfProxy->fitTo(...); 0114 ~~~ 0115 </table> 0116 0117 0118 ### How to modernise old code 0119 0120 1. Choose the proper template argument for the proxy. 0121 - If a PDF is stored: `RooTemplateProxy<RooAbsPdf>`. 0122 - If a real-valued object is stored: `RooTemplateProxy<RooAbsReal>`. 0123 - If a category is stored: `RooTemplateProxy<RooCategory>`. 0124 - If a variable is stored (i.e. one wants to be able to assign values to it): `RooTemplateProxy<RooRealVar>` 0125 Other template arguments are possible, as long as they derive from RooAbsArg. 0126 2. Increment the class version of the owning class. 0127 3. Make sure that the right type is passed in the constructor of the proxy. 0128 4. Always use `proxy->` and `*proxy` to work with the stored object. No need to cast. 0129 5. **Only if necessary** If errors about missing symbols connected to RooTemplateProxy appear at link time, 0130 a specific template instantiation for RooTemplateProxy is not yet in ROOT's dictionaries. 0131 These two lines should be added to the LinkDef.h of the project: 0132 ~~~{.cpp} 0133 #pragma link C++ class RooTemplateProxy<RooMultiCategory>+; 0134 #pragma read sourceClass="RooCategoryProxy" targetClass="RooTemplateProxy<RooMultiCategory>" 0135 ~~~ 0136 Replace `RooMultiCategory` by the proper type. If the proxy was holding a real-valued object, use `sourceClass="RooRealProxy"`. 0137 0138 The first line adds the proxy class to the dictionary, the second line enables reading a legacy 0139 `RooCategoryProxy` from a file, and converting it to the new type-safe proxy. If no old proxies 0140 have to be read from files, this line can be omitted. 0141 0142 If the template instantiation that triggered the missing symbols seems to be a very common instantiation, 0143 request for it to be added to RooFit by creating a pull request for ROOT. If it is rather uncommon, 0144 it is sufficient to add it to the LinkDef.h of the local project only. 0145 0146 **/ 0147 0148 template<class T> 0149 class RooTemplateProxy : public RooArgProxy { 0150 public: 0151 0152 RooTemplateProxy() {} ; 0153 0154 //////////////////////////////////////////////////////////////////////////////// 0155 /// Constructor with owner. 0156 /// \param[in] theName Name of this proxy (for printing). 0157 /// \param[in] desc Description what this proxy should act as. 0158 /// \param[in] owner The object that owns the proxy. This is important for tracking 0159 /// of client-server dependencies. 0160 /// \param[in] valueServer Notify the owner if value changes. 0161 /// \param[in] shapeServer Notify the owner if shape (e.g. binning) changes. 0162 /// \param[in] proxyOwnsArg Proxy will delete the payload if owning. 0163 template<typename Bool = bool, typename = std::enable_if_t<std::is_same<Bool,bool>::value>> 0164 RooTemplateProxy(const char* theName, const char* desc, RooAbsArg* owner, 0165 Bool valueServer=true, bool shapeServer=false, bool proxyOwnsArg=false) 0166 : RooArgProxy(theName, desc, owner, valueServer, shapeServer, proxyOwnsArg) { 0167 // Note for developers: the type of the first bool parameter is templated 0168 // such that implicit conversion from int or pointers to bool is disabled. 0169 // This is because there is another constructor with the signature 0170 // `RooTemplateProxy(name, title, owner, T& ref)`. It happened already more 0171 // than once that other developers accidentally used a `T*` pointer instead 0172 // of a reference, in which case it resolved to this constructor via 0173 // implicit conversion to bool. This is completely meaningless and should 0174 // not happen. 0175 } 0176 0177 //////////////////////////////////////////////////////////////////////////////// 0178 /// Constructor with owner and proxied object. 0179 /// \param[in] theName Name of this proxy (for printing). 0180 /// \param[in] desc Description what this proxy should act as. 0181 /// \param[in] owner The object that owns the proxy. This is important for tracking 0182 /// of client-server dependencies. 0183 /// \param[in] ref Reference to the object that the proxy should hold. 0184 /// \param[in] valueServer Notify the owner if value changes. 0185 /// \param[in] shapeServer Notify the owner if shape (e.g. binning) changes. 0186 /// \param[in] proxyOwnsArg Proxy will delete the payload if owning. 0187 RooTemplateProxy(const char* theName, const char* desc, RooAbsArg* owner, T& ref, 0188 bool valueServer=true, bool shapeServer=false, bool proxyOwnsArg=false) : 0189 RooArgProxy(theName, desc, owner, const_cast<typename std::remove_const<T>::type&>(ref), valueServer, shapeServer, proxyOwnsArg) { } 0190 0191 0192 //////////////////////////////////////////////////////////////////////////////// 0193 /// Copy from an existing proxy. 0194 /// It will accept any RooTemplateProxy instance, and attempt a dynamic_cast on its payload. 0195 /// \param[in] theName Name of this proxy. 0196 /// \param[in] owner Pointer to the owner this proxy should be registered to. 0197 /// \param[in] other Instance of a different proxy whose payload should be copied. 0198 /// \param[in] allowWrongTypes Instead of throwing a std::invalid_argument, only issue an 0199 /// error message when payload with wrong type is found. This is unsafe, but may be necessary 0200 /// when reading back legacy types. Defaults to false. 0201 /// \throw std::invalid_argument if the types of the payloads are incompatible. 0202 template<typename U> 0203 RooTemplateProxy(const char* theName, RooAbsArg* owner, const RooTemplateProxy<U>& other, bool allowWrongTypes = false) : 0204 RooArgProxy(theName, owner, other) { 0205 if (_arg && !dynamic_cast<const T*>(_arg)) { 0206 if (allowWrongTypes) { 0207 coutE(InputArguments) << "Error trying to copy an argument from a proxy with an incompatible payload." << std::endl; 0208 } else { 0209 throw std::invalid_argument("Tried to construct a RooTemplateProxy with incompatible payload."); 0210 } 0211 } 0212 } 0213 0214 TObject* Clone(const char* newName=nullptr) const override { return new RooTemplateProxy<T>(newName,_owner,*this); } 0215 0216 0217 /// Return reference to the proxied object. 0218 T& operator*() const { 0219 return static_cast<T&>(*_arg); 0220 } 0221 0222 /// Member access operator to proxied object. 0223 T* operator->() const { 0224 return static_cast<T*>(_arg); 0225 } 0226 0227 0228 /// Convert the proxy into a number. 0229 /// \return A category proxy will return the index state, real proxies the result of RooAbsReal::getVal(normSet). 0230 operator typename T::value_type() const { 0231 return retrieveValue(arg()); 0232 } 0233 0234 0235 //////////////////////////////////////////////////////////////////////////////// 0236 /// Change object held in proxy into newRef 0237 bool setArg(T& newRef) { 0238 if (_arg) { 0239 if (std::string(arg().GetName()) != newRef.GetName()) { 0240 newRef.setAttribute(("ORIGNAME:" + std::string(arg().GetName())).c_str()) ; 0241 } 0242 return changePointer(RooArgSet(newRef), true); 0243 } else { 0244 return changePointer(RooArgSet(newRef), false, true); 0245 } 0246 } 0247 0248 0249 //////////////////////////////////////////////////////////////////////////////// 0250 /// Create a new object held and owned by proxy. 0251 /// Can only be done if the proxy was non-owning before. 0252 template<class U, class... ConstructorArgs> 0253 U& emplaceOwnedArg(ConstructorArgs&&... constructorArgs) { 0254 if(_ownArg) { 0255 // let's maybe not support overwriting owned args unless it becomes necessary 0256 throw std::runtime_error("Error in RooTemplateProxy: emplaceOwnedArg<>() called on a proxy already owning an arg."); 0257 } 0258 auto ownedArg = new U{std::forward<ConstructorArgs>(constructorArgs)...}; 0259 setArg(*ownedArg); 0260 _ownArg = true; 0261 return *ownedArg; 0262 } 0263 0264 0265 //////////////////////////////////////////////////////////////////////////////// 0266 /// Move a new object held and owned by proxy. 0267 /// Can only be done if the proxy was non-owning before. 0268 template<class U> 0269 U& putOwnedArg(std::unique_ptr<U> ownedArg) { 0270 if(_ownArg) { 0271 // let's maybe not support overwriting owned args unless it becomes necessary 0272 throw std::runtime_error("Error in RooTemplateProxy: putOwnedArg<>() called on a proxy already owning an arg."); 0273 } 0274 auto argPtr = ownedArg.get(); 0275 setArg(*ownedArg.release()); 0276 _ownArg = true; 0277 return *argPtr; 0278 } 0279 0280 /// \name Legacy interface 0281 /// In ROOT versions before 6.22, RooFit didn't have this typed proxy. Therefore, a number of functions 0282 /// for forwarding calls to the proxied objects were necessary. The functions in this group can all be 0283 /// replaced by directly accessing the proxied objects using e.g. the member access operator like 0284 /// `proxy->function()` or by dereferencing like `*proxy = value`. 0285 /// For this to work, choose the template argument appropriately. That is, if the 0286 /// proxy stores a PDF, use `RooTemplateProxy<RooAbsPdf>`, *etc.*. 0287 /// @{ 0288 0289 /// Get the label of the current category state. This function only makes sense for category proxies. 0290 const char* label() const { 0291 return arg().getCurrentLabel(); 0292 } 0293 0294 /// Check if the stored object has a range with the given name. 0295 bool hasRange(const char* rangeName) const { 0296 return arg().hasRange(rangeName); 0297 } 0298 0299 /// Return reference to object held in proxy. 0300 const T& arg() const { return static_cast<const T&>(*_arg); } 0301 0302 /// Assign a new value to the object pointed to by the proxy. 0303 /// This requires the payload to be assignable (RooAbsRealLValue or derived, RooAbsCategoryLValue). 0304 RooTemplateProxy<T>& operator=(typename T::value_type value) { 0305 lvptr(static_cast<T*>(nullptr))->operator=(value); 0306 return *this; 0307 } 0308 /// Set a category state using its state name. This function can only work for category-type proxies. 0309 RooTemplateProxy<T>& operator=(const std::string& newState) { 0310 static_assert(std::is_base_of<RooAbsCategory, T>::value, "Strings can only be assigned to category proxies."); 0311 lvptr(static_cast<RooAbsCategoryLValue*>(nullptr))->operator=(newState.c_str()); 0312 return *this; 0313 } 0314 0315 /// Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived. 0316 double min(const char* rname=nullptr) const { return lvptr(static_cast<const T*>(nullptr))->getMin(rname) ; } 0317 /// Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived. 0318 double max(const char* rname=nullptr) const { return lvptr(static_cast<const T*>(nullptr))->getMax(rname) ; } 0319 /// Check if the range has a lower bound. This requires the payload to be RooAbsRealLValue or derived. 0320 bool hasMin(const char* rname=nullptr) const { return lvptr(static_cast<const T*>(nullptr))->hasMin(rname) ; } 0321 /// Check if the range has a upper bound. This requires the payload to be RooAbsRealLValue or derived. 0322 bool hasMax(const char* rname=nullptr) const { return lvptr(static_cast<const T*>(nullptr))->hasMax(rname) ; } 0323 0324 /// @} 0325 0326 0327 private: 0328 /// Are we a real-valued proxy or a category proxy? 0329 using LValue_t = typename std::conditional<std::is_base_of<RooAbsReal, T>::value, 0330 RooAbsRealLValue, RooAbsCategoryLValue>::type; 0331 0332 //////////////////////////////////////////////////////////////////////////////// 0333 /// Return l-value pointer to contents. If the contents derive from RooAbsLValue or RooAbsCategoryLValue, 0334 /// the conversion is safe, and the function directly returns the pointer using a static_cast. 0335 /// If the template parameter of this proxy is not an LValue type, then 0336 /// - in a debug build, a dynamic_cast with an assertion is used. 0337 /// - in a release build, a static_cast is forced, irrespective of what the type of the object actually is. This 0338 /// is dangerous, but equivalent to the behaviour before refactoring the RooFit proxies. 0339 /// \deprecated This function is unnecessary if the template parameter is RooAbsRealLValue (+ derived types) or 0340 /// RooAbsCategoryLValue (+derived types), as arg() will always return the correct type. 0341 const LValue_t* lvptr(const LValue_t*) const { 0342 return static_cast<const LValue_t*>(_arg); 0343 } 0344 /// \copydoc lvptr(const LValue_t*) const 0345 LValue_t* lvptr(LValue_t*) { 0346 return static_cast<LValue_t*>(_arg); 0347 } 0348 /// \copydoc lvptr(const LValue_t*) const 0349 const LValue_t* lvptr(const RooAbsArg*) const 0350 R__SUGGEST_ALTERNATIVE("The template argument of RooTemplateProxy needs to derive from RooAbsRealLValue or RooAbsCategoryLValue to safely call this function.") { 0351 #ifdef NDEBUG 0352 return static_cast<const LValue_t*>(_arg); 0353 #else 0354 auto theArg = dynamic_cast<const LValue_t*>(_arg); 0355 assert(theArg); 0356 return theArg; 0357 #endif 0358 } 0359 /// \copydoc lvptr(const LValue_t*) const 0360 LValue_t* lvptr(RooAbsArg*) 0361 R__SUGGEST_ALTERNATIVE("The template argument of RooTemplateProxy needs to derive from RooAbsRealLValue or RooAbsCategoryLValue to safely call this function.") { 0362 #ifdef NDEBUG 0363 return static_cast<LValue_t*>(_arg); 0364 #else 0365 auto theArg = dynamic_cast<LValue_t*>(_arg); 0366 assert(theArg); 0367 return theArg; 0368 #endif 0369 } 0370 0371 0372 /// Retrieve index state from a category. 0373 typename T::value_type retrieveValue(const RooAbsCategory& cat) const { 0374 return cat.getCurrentIndex(); 0375 } 0376 0377 /// Retrieve value from a real-valued object. 0378 typename T::value_type retrieveValue(const RooAbsReal& real) const { 0379 return real.getVal(_nset); 0380 } 0381 0382 ClassDefOverride(RooTemplateProxy,1) // Proxy for a RooAbsReal object 0383 }; 0384 0385 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |