Back to home page

EIC code displayed by LXR

 
 

    


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