Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:27

0001 /*
0002  * Project: xRooFit
0003  * Author:
0004  *   Will Buttinger, RAL 2022
0005  *
0006  * Copyright (c) 2022, CERN
0007  *
0008  * Redistribution and use in source and binary forms,
0009  * with or without modification, are permitted according to the terms
0010  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
0011  */
0012 
0013 #include "Config.h"
0014 
0015 #ifdef XROOFIT_USE_PRAGMA_ONCE
0016 #pragma once
0017 #endif
0018 #if !defined(XROOFIT_XROONODE_H) || defined(XROOFIT_USE_PRAGMA_ONCE)
0019 #ifndef XROOFIT_USE_PRAGMA_ONCE
0020 #define XROOFIT_XROONODE_H
0021 #endif
0022 
0023 #include "TNamed.h"
0024 #include <vector>
0025 #include <functional>
0026 
0027 class RooWorkspace;
0028 class RooAbsReal;
0029 class TH1;
0030 class RooAbsLValue;
0031 class RooArgList;
0032 class RooAbsBinning;
0033 class RooFitResult;
0034 class TGraph;
0035 class TAxis;
0036 class TGListTreeItem;
0037 class TGListTree;
0038 class TVirtualPad;
0039 class TStyle;
0040 
0041 #include "xRooFit.h"
0042 #include "RooLinkedList.h"
0043 #include "RooCmdArg.h"
0044 #include "TQObject.h"
0045 #include "TMatrixDSym.h"
0046 
0047 BEGIN_XROOFIT_NAMESPACE
0048 
0049 class xRooNode;
0050 class xRooNLLVar;
0051 
0052 class xRooNode : public TNamed, public std::vector<std::shared_ptr<xRooNode>> {
0053 
0054 public:
0055    // functions of form value = f(orig,nom,nom_err)
0056    // e.g. f = ratio would be simply orig/nom
0057    // bool indicates if should be symmetrized
0058    static std::map<std::string, std::tuple<std::function<double(double, double, double)>, bool>> auxFunctions;
0059    /** @private */
0060    static void SetAuxFunction(const char *title, const std::function<double(double, double, double)> &func,
0061                               bool symmetrize = false);
0062 
0063    // this function is here because couldn't figure out how to check a null shared_ptr in pyroot
0064    /** @private */
0065    static inline bool isNull(const std::shared_ptr<xRooNode> &x) { return x == nullptr; }
0066 
0067    // name of the node needn't match the name of the component that it points to
0068    // the name of the node is how it is identified inside its parent
0069    // In c++17 for constructors with a Node2& parent, could look at using shared_from_this and if it throws except then
0070    // construct make_shared<Node2>(parent)
0071    xRooNode(const char *type, const char *name, const char *title = "");
0072 
0073    /** @private */
0074    template <typename T>
0075    xRooNode(const char *name, const char *title) : TNamed(name, title), fComp(std::make_shared<T>())
0076    {
0077       if (auto x = get<TNamed>(); x) {
0078          x->SetNameTitle(name, title);
0079       }
0080    }
0081    xRooNode(const char *name = "", const std::shared_ptr<TObject> &comp = nullptr,
0082             const std::shared_ptr<xRooNode> &parent = nullptr);
0083 
0084    /** @private */
0085    xRooNode(const char *name, const std::shared_ptr<TObject> &comp, const xRooNode &parent)
0086       : xRooNode(name, comp, std::make_shared<xRooNode>(parent))
0087    {
0088    }
0089 
0090    /** @private */
0091    xRooNode(const char *name, const TObject &comp, const std::shared_ptr<xRooNode> &parent)
0092       : xRooNode(name, std::shared_ptr<TObject>(const_cast<TObject *>(&comp), [](TObject *) {}), parent)
0093    {
0094    } // needed to ensure passing a shared_ptr<Node2> for the parent doesnt become Node2(shared_ptr<Node2>) as parent
0095      // because of Node2(shared_ptr<TObject>) constructor
0096    /** @private */
0097    xRooNode(const char *name, const TObject &comp, const xRooNode &parent)
0098       : xRooNode(name, std::shared_ptr<TObject>(const_cast<TObject *>(&comp), [](TObject *) {}), parent)
0099    {
0100    }
0101    /** @private */
0102    xRooNode(const TObject &comp, const std::shared_ptr<xRooNode> &parent = nullptr);
0103    /** @private */
0104    xRooNode(const TObject &comp, const xRooNode &parent) : xRooNode(comp, std::make_shared<xRooNode>(parent)) {}
0105    /** @private */
0106    xRooNode(const std::shared_ptr<TObject> &comp, const std::shared_ptr<xRooNode> &parent = nullptr);
0107    template <typename T>
0108    /** @private */
0109    xRooNode(const std::shared_ptr<T> &comp, const std::shared_ptr<xRooNode> &parent = nullptr)
0110       : xRooNode(std::dynamic_pointer_cast<TObject>(comp), parent)
0111    {
0112    }
0113    /** @private */
0114    template <typename T>
0115    xRooNode(const std::shared_ptr<T> &comp, const xRooNode &parent)
0116       : xRooNode(std::dynamic_pointer_cast<TObject>(comp), std::make_shared<xRooNode>(parent))
0117    {
0118    }
0119    /** @private */
0120    template <typename T>
0121    xRooNode(const std::shared_ptr<const T> &comp, const std::shared_ptr<xRooNode> &parent = nullptr)
0122       : xRooNode(std::dynamic_pointer_cast<TObject>(std::const_pointer_cast<T>(comp)), parent)
0123    {
0124    }
0125    /** @private */
0126    template <typename T>
0127    xRooNode(const std::shared_ptr<const T> &comp, const xRooNode &parent)
0128       : xRooNode(std::dynamic_pointer_cast<TObject>(std::const_pointer_cast<T>(comp)),
0129                  std::make_shared<xRooNode>(parent))
0130    {
0131    }
0132    /** @private */
0133    xRooNode(double value);
0134 
0135    ~xRooNode() override;
0136 
0137    void SetName(const char *name) override;   // *MENU*
0138    void SetTitle(const char *title) override; // *MENU*
0139 
0140    /** @private */
0141    const char *GetNodeType() const;
0142 
0143    /** @private */
0144    explicit operator bool() const { return strlen(GetName()) || get(); } // the 'null' Component is the empty string
0145 
0146    // at doesn't do an initial browse of the object, unlike [] operator
0147    const std::shared_ptr<xRooNode> &at(size_t idx, bool browseResult = true) const
0148    {
0149       IsFolder();
0150       auto &out = std::vector<std::shared_ptr<xRooNode>>::at(idx);
0151       if (browseResult && out)
0152          out->browse();
0153       return out;
0154    }
0155    std::shared_ptr<xRooNode> at(const std::string &name, bool browseResult = true) const;
0156 
0157    RooArgList argList() const;
0158 
0159    std::shared_ptr<xRooNode>
0160    find(const std::string &name, bool browseResult = true) const; // same as at but return nullptr if not found
0161    bool contains(const std::string &name) const; // doesn't trigger a browse of the found object, unlike find
0162 
0163    // most users should use these methods: will do an initial browse and will browse the returned object too
0164    std::shared_ptr<xRooNode> operator[](size_t idx) { return at(idx); }
0165    std::shared_ptr<xRooNode> operator[](const std::string &name); // will create a new node if not existing, unlike 'at'
0166 
0167    // custom iterator to ensure children are auto-browsed as we iterate through
0168    class xRooNodeIterator : public std::vector<std::shared_ptr<xRooNode>>::const_iterator {
0169    public:
0170       xRooNodeIterator(std::vector<std::shared_ptr<xRooNode>>::const_iterator itr)
0171          : std::vector<std::shared_ptr<xRooNode>>::const_iterator(itr)
0172       {
0173       }
0174       std::iterator_traits<const std::shared_ptr<xRooNode> *>::reference operator*() const
0175       {
0176          const std::shared_ptr<xRooNode> &out = std::vector<std::shared_ptr<xRooNode>>::const_iterator::operator*();
0177          if (out->get() && out->empty()) {
0178             out->browse();
0179          }
0180          return std::vector<std::shared_ptr<xRooNode>>::const_iterator::operator*();
0181       }
0182       bool operator!=(xRooNodeIterator const &b) const
0183       {
0184          const std::vector<std::shared_ptr<xRooNode>>::const_iterator &aa = (*this);
0185          const std::vector<std::shared_ptr<xRooNode>>::const_iterator &bb = b;
0186          return aa != bb;
0187       };
0188       xRooNodeIterator const &operator++()
0189       {
0190          std::vector<std::shared_ptr<xRooNode>>::const_iterator::operator++();
0191          return *this;
0192       }
0193       bool operator==(xRooNodeIterator const &b) const
0194       {
0195          const std::vector<std::shared_ptr<xRooNode>>::const_iterator &aa = (*this);
0196          const std::vector<std::shared_ptr<xRooNode>>::const_iterator &bb = b;
0197          return aa == bb;
0198       };
0199    };
0200    auto begin() const -> xRooNodeIterator { return xRooNodeIterator(std::vector<std::shared_ptr<xRooNode>>::begin()); }
0201    auto end() const -> xRooNodeIterator { return xRooNodeIterator(std::vector<std::shared_ptr<xRooNode>>::end()); }
0202 
0203    // needed in pyROOT to avoid it creating iterators that follow the 'get' to death
0204    //   auto begin() const -> decltype(std::vector<std::shared_ptr<xRooNode>>::begin())
0205    //   {
0206    //      return std::vector<std::shared_ptr<xRooNode>>::begin();
0207    //   }
0208    //   auto end() const -> decltype(std::vector<std::shared_ptr<xRooNode>>::end())
0209    //   {
0210    //      return std::vector<std::shared_ptr<xRooNode>>::end();
0211    //   }
0212 
0213    void Browse(TBrowser *b = nullptr) override; // will browse the children that aren't "null" nodes
0214    /** @private */
0215    bool IsFolder() const override;
0216    /** @private */
0217    const char *GetIconName() const override;
0218    void Inspect() const override; // *MENU*
0219 
0220    /** @private */
0221    xRooNode &browse(); // refreshes child nodes
0222 
0223    /** @private */
0224    std::string GetPath() const;
0225    void Print(Option_t *opt = "") const override; // *MENU*
0226    // void Reverse() {
0227    // std::reverse(std::vector<std::shared_ptr<Node2>>::begin(),std::vector<std::shared_ptr<Node2>>::end()); } // *MENU*
0228 
0229    xRooNode &operator=(const TObject &o);
0230 
0231    TObject *get() const { return fComp.get(); }
0232    template <typename T>
0233    T *get() const
0234    {
0235       return dynamic_cast<T *>(get());
0236    }
0237    /** @private */
0238    TObject *xget() const { return xget<TObject>(); }
0239    template <typename T>
0240    T *xget() const
0241    {
0242       for (auto &c : fBrowsables) {
0243          if (strcmp(c->GetName(), ".memory") == 0) {
0244             return c->get<T>();
0245          }
0246       }
0247       return nullptr;
0248    }
0249 
0250    TObject *operator->() const { return get(); }
0251 
0252    RooWorkspace *ws() const;
0253 
0254    /** @private */
0255    std::shared_ptr<TObject>
0256    acquire(const std::shared_ptr<TObject> &arg, bool checkFactory = false, bool mustBeNew = false);
0257    // common pattern for 'creating' an acquired object
0258    /** @private */
0259    template <typename T, typename... Args>
0260    std::shared_ptr<T> acquire(Args &&...args)
0261    {
0262       return std::dynamic_pointer_cast<T>(acquire(std::make_shared<T>(std::forward<Args>(args)...)));
0263    }
0264    /** @private */
0265    template <typename T, typename T2, typename... Args>
0266    // looser version of above ... first template type says what type to return
0267    // allows returning different type to the one requested in T2 (e.g. ok to get RooConstVar when acquire a RooRealVar)
0268    std::shared_ptr<T> acquire2(Args &&...args)
0269    {
0270       return std::dynamic_pointer_cast<T>(acquire(std::make_shared<T2>(std::forward<Args>(args)...)));
0271    }
0272    /** @private */
0273    template <typename T, typename... Args>
0274    std::shared_ptr<T> acquireNew(Args &&...args)
0275    {
0276       return std::dynamic_pointer_cast<T>(acquire(std::make_shared<T>(std::forward<Args>(args)...), false, true));
0277    }
0278    /** @private */
0279    std::shared_ptr<TObject> getObject(const std::string &name, const std::string &type = "") const;
0280    /** @private */
0281    template <typename T>
0282    std::shared_ptr<T> getObject(const std::string &name) const
0283    {
0284       return std::dynamic_pointer_cast<T>(getObject(name, T::Class_Name()));
0285    }
0286 
0287    /** @private */
0288    xRooNode shallowCopy(const std::string &name, std::shared_ptr<xRooNode> parent = nullptr);
0289    /** @private */
0290    std::shared_ptr<TObject> convertForAcquisition(xRooNode &acquirer, const char *opt = "") const;
0291 
0292    xRooNode vars() const;   // obs,pars
0293    xRooNode obs() const;    // robs and globs
0294    xRooNode robs() const;   // just the regular obs
0295    xRooNode globs() const;  // just the global obs
0296    xRooNode pars() const;   // poi, np, and pp (prespecified pars)
0297    xRooNode floats() const; // float poi or np
0298    xRooNode consts() const; // just const poi or np
0299 
0300    xRooNode poi() const; // parameters of interest
0301    xRooNode np() const;  // nuisance parameters (non-poi floatables)
0302    xRooNode pp() const;  // preset/prespecified parameters
0303 
0304    xRooNode components() const; // additive children
0305    xRooNode factors() const;    // multiplicative children
0306    xRooNode variations() const; // interpolated children (are bins a form of variation?)
0307    xRooNode coefs() const;
0308    xRooNode coords(bool setVals = true) const; // will move to the coords in the process if setVals=true
0309    xRooNode bins() const;
0310 
0311    xRooNode constraints() const; // pdfs other than the node's parent pdf where the deps of this node appear
0312    xRooNode datasets()
0313       const; // datasets corresponding to this pdf (parent nodes that do observable selections automatically applied)
0314 
0315    xRooNode Replace(const xRooNode &node); // use to replace a node in the tree at the location of this node
0316    xRooNode Remove(const xRooNode &child);
0317    xRooNode
0318    Add(const xRooNode &child,
0319        Option_t *opt =
0320           ""); // = components()[child.GetName()]=child; although need to handle case of adding same term multiple times
0321    xRooNode Multiply(const xRooNode &child, Option_t *opt = ""); // = factors()[child.GetName()]=child;
0322    xRooNode Vary(const xRooNode &child);
0323    xRooNode Constrain(const xRooNode &child);
0324 
0325    xRooNode Combine(const xRooNode &rhs); // combine rhs with this node
0326 
0327    xRooNode reduced(const std::string &range = "", bool invert = false)
0328       const; // return a node representing reduced version of this node, will use the SetRange to reduce if blank
0329 
0330    // following versions are for the menu in the GUI
0331    /** @private */
0332    void _Add_(const char *name, const char *opt); // *MENU*
0333    /** @private */
0334    xRooNode _Multiply_(const char *what) { return Multiply(what); } // *MENU*
0335    /** @private */
0336    void _Vary_(const char *what); // *MENU*
0337    /** @private */
0338    xRooNode _Constrain_(const char *what) { return Constrain(what); } // *MENU*
0339    /** @private */
0340    void _ShowVars_(bool set = true); // *TOGGLE* *GETTER=_IsShowVars_
0341    /** @private */
0342    bool _IsShowVars_() const;
0343 
0344    void SetHidden(bool set = true); // *TOGGLE* *GETTER=IsHidden
0345    bool IsHidden() const;
0346 
0347    bool SetContents(const TObject &obj)
0348    {
0349       operator=(obj);
0350       return true;
0351    } // populates the node's comp (creating if necessary)  from given object
0352    bool SetData(const TObject &obj, const xRooNode &data = "obsData");
0353 
0354    bool SetContent(double value);                                     // uses a RooConst
0355    bool SetContent(double value, const char *par, double parVal = 1); // shortcut to setting a variation content
0356    bool SetContents(const TObject &obj, const char *par, double parVal)
0357    {
0358       variations()[TString::Format("%s=%g", par, parVal).Data()]->operator=(obj);
0359       return true;
0360    }
0361    bool SetBinError(int bin, double value);
0362    bool SetBinContent(int bin, double value, const char *par = nullptr, double parVal = 1);
0363    bool SetBinData(int bin, double value, const xRooNode &data = "obsData"); // only valid for pdf nodes
0364 
0365    /** @private */
0366    void _SetContent_(double value); // *MENU*
0367    /** @private */
0368    void _SetBinContent_(int bin, double value, const char *par = "", double parVal = 1); // *MENU*
0369 
0370    bool SetXaxis(const RooAbsBinning &binning);
0371    bool SetXaxis(TAxis *ax);
0372    bool SetXaxis(const char *name, const char *title, int nbins, double low, double high);
0373    bool SetXaxis(const char *name, const char *title, int nbins, const double *bins);
0374    bool SetXaxis(const char *title, int nbins, double low, double high)
0375    {
0376       return SetXaxis("xaxis", title, nbins, low, high);
0377    }
0378    bool SetXaxis(const char *title, int nbins, const double *bins) { return SetXaxis("xaxis", title, nbins, bins); }
0379    bool SetXaxis(int nbins, double low, double high) { return SetXaxis("xaxis", "", nbins, low, high); }
0380    bool SetXaxis(int nbins, const double *bins) { return SetXaxis("xaxis", "", nbins, bins); }
0381 
0382    std::shared_ptr<TStyle> style(TObject *initObject = nullptr, bool autoCreate = true) const;
0383 
0384    TAxis *GetXaxis() const;
0385 
0386    double GetBinData(int bin, const xRooNode &data = "obsData");
0387    double GetBinContent(int bin) const { return GetBinContents(bin, bin).at(0); }
0388    std::vector<double> GetBinContents(int binStart = 1, int binEnd = 0) const; // default will get all bins
0389    double GetBinError(int bin, const xRooNode &fr = "") const;
0390    std::vector<double> GetBinErrors(int binStart = 1, int binEnd = 0, const xRooNode &fr = "") const;
0391    std::pair<double, double> IntegralAndError(const xRooNode &fr = "", const char *rangeName = nullptr) const;
0392 
0393    // methods to access default content and error
0394    double GetContent() const { return GetBinContent(fBinNumber); }
0395    double GetError(const xRooNode &fr = "") const
0396    {
0397       return (fBinNumber == -1) ? IntegralAndError(fr).second : GetBinError(fBinNumber, fr);
0398    }
0399    double GetData(const xRooNode &data = "obsData") { return GetBinData(fBinNumber, data); }
0400 
0401    // methods to access content and covariances of the CHILDREN of a node
0402    std::vector<double> contents() const;
0403    TMatrixDSym covariances(const xRooNode &fr = "") const;
0404 
0405    xRooNLLVar nll(const xRooNode &_data, std::initializer_list<RooCmdArg> nllOpts) const;
0406    xRooNLLVar nll(const xRooNode &_data, const RooLinkedList &nllOpts) const;
0407    xRooNLLVar nll(const xRooNode &_data = "") const; // uses xRooFit::createNLLOption for nllOpts
0408 
0409    xRooNode fitResult(const char *opt = "") const;      // todo: make this 'fitResults'
0410    void SetFitResult(const RooFitResult *fr = nullptr); // null means will load prefit
0411    void SetFitResult(const std::shared_ptr<const RooFitResult> &fr) { SetFitResult(fr.get()); }
0412    void SetFitResult(const xRooNode &fr);
0413 
0414    xRooNode
0415    generate(const xRooNode &fr = "", bool expected = false,
0416             int seed = 0); // generate a dataset from a pdf node using given fr - if none given will use current fit
0417 
0418    /** @private */
0419    void _fit_(const char *constParValues = ""); // *MENU*
0420    /** @private */
0421    void _generate_(const char *name = "", bool expected = false); // *MENU*
0422    /** @private */
0423    void _scan_(const char *what = "plr", double nToys = 0, const char *xvar = "", int nPointsX = 0, double lowX = 0,
0424                double highX = 0 /*, const char* yvar="", int nBinsY=0, double lowY=0, double highY=0*/,
0425                const char *constParValues = ""); // *MENU*
0426    //    xRooNode fitTo(const char* datasetName) const;
0427    //    xRooNode fitTo(const xRooNode& _data) const;
0428    //    xRooNode generate(bool expected=false) const;
0429    //    void minosScan(const char* parName); // *MENU*
0430    //    void pllScan(const char* parName, int npoints=100); // *MENU*
0431    //    void breakdown(const char* parNames, const char* groupNames); // *MENU*
0432 
0433    /*
0434    double pll(Node2& data, const char* parName, double value, const Asymptotics::PLLType& pllType =
0435    Asymptotics::TwoSided) const;
0436    // pair is obs p_sb and p_b, vector is expected -2->+2 sigma p_sb (p_b are known by construction)
0437    std::pair<std::pair<double,double>,std::vector<double>>  pValue(Node2& data, const char* parName, double value,
0438    double alt_value, const Asymptotics::PLLType& pllType); double sigma_mu(Node2& data, const char* parName, double
0439    value, double alt_value) const;
0440 */
0441 
0442    void Checked(TObject *obj, bool val);
0443    void SetChecked(bool val = true) { Checked(this, val); }
0444 
0445    /** @private */
0446    xRooNode histo(const xRooNode &vars = "x", const xRooNode &fr = "", bool content = true, bool errors = true) const;
0447    /** @private */
0448    xRooNode filter(const xRooNode &range) const;
0449 
0450    TGraph *BuildGraph(RooAbsLValue *v = nullptr, bool includeZeros = false, TVirtualPad *fromPad = nullptr) const;
0451    TH1 *BuildHistogram(RooAbsLValue *v = nullptr, bool empty = false, bool errors = false, int binStart = 1,
0452                        int binEnd = 0, const xRooNode &fr = "") const;
0453    xRooNode mainChild() const;
0454    void Draw(Option_t *opt = "") override; // *MENU*
0455 
0456    void SaveAs(const char *filename = "", Option_t *option = "") const override; // *MENU*
0457 
0458    /** @private */
0459    TGListTreeItem *GetTreeItem(TBrowser *b) const;
0460    /** @private */
0461    TGListTree *GetListTree(TBrowser *b) const;
0462 
0463    static void Interactive_PLLPlot();
0464    static void Interactive_Pull();
0465    class InteractiveObject : public TQObject {
0466    public:
0467       void Interactive_PLLPlot(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y);
0468       ClassDef(InteractiveObject, 0)
0469    };
0470    static InteractiveObject *gIntObj;
0471 
0472    mutable std::shared_ptr<TObject> fComp; //!
0473    int fTimes = 1;      // when the same comp appears multiple times in a parent node, this is increased to reflect that
0474    int fBinNumber = -1; // used by 'bin' nodes (a node that refers to a specific bin of a parent)
0475    std::shared_ptr<xRooNode> fParent; //!
0476    std::string fFolder;               // folder to put this node in when 'organising' the parent
0477 
0478    void SetRange(const char *range, double low = std::numeric_limits<double>::quiet_NaN(),
0479                  double high = std::numeric_limits<double>::quiet_NaN()); // *MENU*
0480    const char *GetRange() const;
0481    mutable std::string fRange; //! only here so can have char* GetRange return so can return nullptr for no range set
0482                                //! (required for RooCategory)
0483 
0484    mutable std::shared_ptr<TAxis>
0485       fXAxis; //! appears that if was fXaxis then dialog box for SetXaxis will take as current value
0486 
0487    mutable bool fInterrupted = false;
0488 
0489    bool fAcquirer = false; // if true, when acquiring will go into objects memory rather than pass onto parent
0490    std::shared_ptr<xRooNode> fProvider; //! like a parent but only for use by getObject
0491 
0492    std::shared_ptr<xRooNode> parentPdf() const; // find first parent that is a pdf
0493 
0494    /** @private */
0495    void sterilize() const;
0496 
0497    std::vector<std::shared_ptr<xRooNode>> fBrowsables;   // will appear in the browser tree but are not actual children
0498    std::function<xRooNode(xRooNode *)> fBrowseOperation; // a way to specify a custom browsing operation
0499 
0500    /** @private */
0501    std::shared_ptr<xRooNode> getBrowsable(const char *name) const;
0502 
0503    ClassDefOverride(xRooNode, 0)
0504 };
0505 
0506 namespace cling {
0507 std::string printValue(const xRooNode *val);
0508 }
0509 
0510 END_XROOFIT_NAMESPACE
0511 
0512 #endif // include guard