From 188b1dce64b84f844caeb6ec4d05c782f266b0a8 Mon Sep 17 00:00:00 2001 From: Danilo Piparo <danilo.piparo@cern.ch> Date: Thu, 2 Mar 2017 14:50:22 +0100 Subject: [PATCH] [TDF] Add a Fill method to fill any object the class of which exposes a Fill method --- tree/treeplayer/inc/ROOT/TDataFrame.hxx | 30 ++++++++++- tutorials/dataframe/tdf005_fillAnyObject.C | 63 ++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tutorials/dataframe/tdf005_fillAnyObject.C diff --git a/tree/treeplayer/inc/ROOT/TDataFrame.hxx b/tree/treeplayer/inc/ROOT/TDataFrame.hxx index 622ec31fb1e..e9659e889bf 100644 --- a/tree/treeplayer/inc/ROOT/TDataFrame.hxx +++ b/tree/treeplayer/inc/ROOT/TDataFrame.hxx @@ -795,7 +795,6 @@ public: return df->MakeActionResultProxy(h); } - //////////////////////////////////////////////////////////////////////////// /// \brief Fill and return a profile (*lazy action*) /// \tparam B0 The type of the branch the values of which are used to fill the profile. @@ -916,6 +915,35 @@ public: return df->MakeActionResultProxy(h); } + + //////////////////////////////////////////////////////////////////////////// + /// \brief Fill and return any entity with a Fill method (*lazy action*) + /// \tparam BRANCHTYPES The types of the branches the values of which are used to fill the object. + /// \param[in] model The model to be considered to build the new return value. + /// \param[in] bl The name of the branches read to fill the object. + /// + /// The returned object is independent of the input one. + /// This action is *lazy*: upon invocation of this method the calculation is + /// booked but not executed. See TActionResultProxy documentation. + /// The user renounces to the ownership of the model. The value to be used is the + /// returned one. + /// It is compulsory to express the branches to be considered. + template <typename... BRANCHTYPES, typename T> + TActionResultProxy<T> Fill(T &&model, const BranchNames& bl) + { + auto h = std::make_shared<T>(model); + if (!ROOT::Internal::TDFV7Utils::Histo<T>::HasAxisLimits(*h)) { + throw std::runtime_error("The absence of axes limits is not supported yet."); + } + using Op_t = ROOT::Internal::Operations::FillTOOperation<T>; + using DFA_t = ROOT::Internal::TDataFrameAction<Op_t, Proxied, ROOT::Internal::TDFTraitsUtils::TTypeList<BRANCHTYPES...>>; + auto df = GetDataFrameChecked(); + auto nSlots = df->GetNSlots(); + df->Book(std::make_shared<DFA_t>(Op_t(h, nSlots), bl, *fProxiedPtr)); + return df->MakeActionResultProxy(h); + } + + //////////////////////////////////////////////////////////////////////////// /// \brief Return the minimum of processed branch values (*lazy action*) /// \tparam T The type of the branch. diff --git a/tutorials/dataframe/tdf005_fillAnyObject.C b/tutorials/dataframe/tdf005_fillAnyObject.C new file mode 100644 index 00000000000..b54cfb753b1 --- /dev/null +++ b/tutorials/dataframe/tdf005_fillAnyObject.C @@ -0,0 +1,63 @@ +/// \file +/// \ingroup tutorial_tdataframe +/// \notebook -nodraw +/// This tutorial shows how to fill any object the class of which exposes a +/// `Fill` method. +/// \macro_code +/// +/// \date March 2017 +/// \author Danilo Piparo + +#include "TFile.h" +#include "TH1F.h" +#include "TTree.h" + +#include "ROOT/TDataFrame.hxx" + +// A simple helper function to fill a test tree: this makes the example +// stand-alone. +void fill_tree(const char* filename, const char* treeName) { + TFile f(filename,"RECREATE"); + TTree t(treeName,treeName); + double b1; + float b2; + t.Branch("b1", &b1); + t.Branch("b2", &b2); + for(int i = 0; i < 100; ++i) { + b1 = i; + b2 = i*i; + t.Fill(); + } + t.Write(); + f.Close(); + return; +} + +int tdf005_fillAnyObject() { + + // We prepare an input tree to run on + auto fileName = "tdf005_fillAnyObject.root"; + auto treeName = "myTree"; + fill_tree(fileName,treeName); + + // We read the tree from the file and create a TDataFrame. + ROOT::Experimental::TDataFrame d(treeName, fileName); + + // ## Filling any object + // We now fill some objects which are instances of classes which expose a + // `Fill` method with some input arguments. + auto th1d = d.Fill<double>(TH1D("th1d", "th1d", 64, 0, 128), {"b1"}); + auto th1i = d.Fill<float>(TH1I("th1i", "th1i", 64, 0, 128), {"b2"}); + auto th2d = d.Fill<double, float>(TH2D("th2d", "th2d", 64, 0, 128, 64, 0, 1024), {"b1","b2"}); + + auto c1 = new TCanvas(); + th1d->DrawClone(); + + auto c2 = new TCanvas(); + th1i->DrawClone(); + + auto c3 = new TCanvas(); + th2d->DrawClone("COLZ"); + + return 0; +} -- GitLab