Histograms of objects in roodataframes

Dear experts,

we are trying to include objects in our rdataframes code to make the code a bit cleaner. We therefore created the following class:

class Particle {
        /*
        This is a simple class that collects information of 1 particle (pt/eta/phi/mass/four-momentum)
        Serves as a baseclass for other classes like Jet have more properties

        the use case is to have a simpler interface when for example looping over the particles in a collection
        */
        public:

        Particle(): m_pt(0.), m_eta(0.), m_phi(0.), m_mass(0.){};

        Particle(
            const float& pt,
            const float& eta,
            const float& phi,
            const float& mass
        ): m_pt(pt), m_eta(eta), m_phi(phi), m_mass(mass)
        {};

        float Pt() const {return m_pt;};
        float Eta() const {return m_eta;};
        float Phi() const {return m_phi;};
        float Mass() const {return m_mass;};

        protected:
        float m_pt;
        float m_eta;
        float m_phi;
        float m_mass;
    };

This works and we can define a new column in our dataframe using this class. If we however want to create a histogram of the particles pt or eta we get an error. We are doing the following:

    self.df.Histo1D(("tau_eta0", "tau_eta0", 40, -5, 5), f"tau1___NOSYS.Eta()")

The error is the following:

File "/eos/user/c/cmo/bbtautau/hhard/dev/HHARD/python/Region.py", line 245, in testhist
    self.df.Histo1D(("tau_eta0", "tau_eta0", 40, -5, 5), f"tau1___NOSYS.Eta()")
  File "/cvmfs/sft.cern.ch/lcg/views/LCG_105/x86_64-el9-gcc11-opt/lib/ROOT/_pythonization/_rdataframe.py", line 379, in __call__
    res = self._original_method(model, *args[1:])
TypeError: Template method resolution failed:
  none of the 4 overloaded methods succeeded. Full details:
  ROOT::RDF::RResultPtr<TH1D> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Histo1D(basic_string_view<char,char_traits<char> > vName) =>
    TypeError: takes at most 1 arguments (2 given)
  ROOT::RDF::RResultPtr<TH1D> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Histo1D(const ROOT::RDF::TH1DModel& model, basic_string_view<char,char_traits<char> > vName, basic_string_view<char,char_traits<char> > wName) =>
    TypeError: takes at least 3 arguments (2 given)
  ROOT::RDF::RResultPtr<TH1D> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Histo1D(basic_string_view<char,char_traits<char> > vName, basic_string_view<char,char_traits<char> > wName) =>
    TypeError: could not convert argument 1
  ROOT::RDF::RResultPtr<TH1D> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Histo1D(const ROOT::RDF::TH1DModel& model = {"", "", 128U, 0., 0.}, basic_string_view<char,char_traits<char> > vName = "") =>
    runtime_error: Unknown column: "tau1___NOSYS.Eta()"
  Failed to instantiate "Histo1D(ROOT::RDF::TH1DModel*,std::string)"

Our question is if doing something like this is supported by RDFs, or if there is something we are doing wrong. Thanks a lot for you help.

Cheers,
Jordy

Hi Jordy,

It seems like a good idea.
If I understand the context correctly, can see two possible paths:

  1. Define a new column, e.g. tau_eta by invoking the Eta() member function
  2. Leverage the capability of ROOT of “seeing” into split branches by using as input for your Histo1D the branch name my_tau_branch.m_eta

Cheers,
Danilo

Hi Danilo,

at the moment we dont have a branch called my_tau_branch.m_eta. I tried making the member m_eta public and that also doesn’t work. (h = df.Histo1D(("tau_eta0", "tau_eta0", 40, -5, 5), f"tau.m_eta")gives the same error

We are trying to avoid using the define to create a new column as it seems to be a little redundant.

Cheers,
Jordy

Hi Jordy,

could you please share a file with a Tree of your particles? A few events (<10 even ) events are enough.

Cheers,
D