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