Back to home page

EIC code displayed by LXR

 
 

    


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