18#ifndef ROOT_RDFOPERATIONS
19#define ROOT_RDFOPERATIONS
37#include "RConfigure.h"
84using Results = std::conditional_t<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>;
98 template <
typename... Args>
99 void Exec(
unsigned int slot, Args &&... args)
102 static_assert(std::is_same<TypeList<std::decay_t<Args>...>, ColumnTypes_t>
::value,
"");
110 std::string GetActionName() {
return "ForeachSlot"; }
130 return std::make_unique<RMergeableCount>(*
fResultCount);
135 std::string GetActionName() {
return "Count"; }
144template <
typename RNode_t>
146 std::shared_ptr<RCutFlowReport>
fReport;
156 ReportHelper(ReportHelper &&) =
default;
157 ReportHelper(
const ReportHelper &) =
delete;
159 void Exec(
unsigned int ) {}
173 std::string GetActionName() {
return "Report"; }
177 auto &&
result = *
static_cast<std::shared_ptr<RCutFlowReport> *
>(
newResult);
178 return ReportHelper{
result,
179 std::static_pointer_cast<RNode_t>(fNode->GetVariedFilter(std::string(
variation))).get(),
195 using Buf_t = std::vector<BufEl_t>;
197 std::vector<Buf_t> fBuffers;
200 unsigned int fNSlots;
201 unsigned int fBufSize;
215 void Exec(
unsigned int slot,
double v,
double w);
229 void Exec(
unsigned int slot,
const T &
vs,
const W &ws)
258 void Exec(
unsigned int slot,
const T
v,
const W &ws)
268 Hist_t &PartialUpdate(
unsigned int);
277 return std::make_unique<RMergeableFill<Hist_t>>(*fResultHist);
280 std::string GetActionName()
289 result->SetDirectory(
nullptr);
300 using iterator_category = std::forward_iterator_tag;
301 using difference_type = std::ptrdiff_t;
302 using value_type = T;
304 using reference = T &;
314 if constexpr (IsDataContainer<T>::value) {
315 return std::begin(val);
323std::size_t GetSize(
const T &val)
325 if constexpr (IsDataContainer<T>::value) {
326 return std::size(val);
333template <
typename Helper>
336 template <
typename... Iterators>
337 void ExecLoop(
unsigned int slot, std::size_t elements, Iterators...
its)
339 for (std::size_t i = 0; i < elements; i++) {
341 (std::advance(
its, 1), ...);
349 if constexpr (std::disjunction_v<IsDataContainer<ColumnTypes>...>) {
350 constexpr std::array<
bool,
sizeof...(ColumnTypes)>
isContainer{IsDataContainer<ColumnTypes>::value...};
352 std::array<std::size_t,
sizeof...(columnValues)>
sizes = {{GetSize(
columnValues)...}};
353 std::size_t elements = 0;
354 for (std::size_t i = 0; i <
isContainer.size(); i++) {
358 }
else if (elements !=
sizes[i]) {
359 throw std::runtime_error(
"Cannot fill values in containers of different sizes.");
385template <
typename HIST = Hist_t>
387 std::vector<HIST *> fObjects;
391 auto Merge(std::vector<H *> &
objs,
int )
401 template <
typename H>
402 auto Merge(std::vector<H *> &
objs,
double )
403 ->
decltype(
objs[0]->Merge(std::vector<HIST *>{}),
void())
409 template <
typename T>
412 static_assert(
sizeof(T) < 0,
413 "The type passed to Fill does not provide a Merge(TCollection*) or Merge(const std::vector&) method.");
416 template <std::size_t
ColIdx,
typename End_t,
typename...
Its>
430 fObjects[0] =
h.get();
432 for (
unsigned int i = 1; i <
nSlots; ++i) {
433 fObjects[i] =
new HIST(*fObjects[0]);
441 template <
typename...
ValTypes, std::enable_if_t<!std::disjunction<IsDataContainer<ValTypes>...>
::value,
int> = 0>
444 fObjects[
slot]->Fill(
x...);
448 template <
typename...
Xs, std::enable_if_t<std::disjunction<IsDataContainer<Xs>...>
::value,
int> = 0>
452 constexpr std::array<
bool,
sizeof...(Xs)>
isContainer{IsDataContainer<Xs>::value...};
457 static_assert(
colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
463 std::array<std::size_t,
sizeof...(xs)>
sizes = {{GetSize(
xs)...}};
465 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
467 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
474 template <
typename T = HIST>
477 static_assert(
sizeof(T) < 0,
478 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
479 "columns passed did not match the signature of the object's `Fill` method.");
486 if (fObjects.size() == 1)
492 for (
auto it = ++fObjects.begin(); it != fObjects.end(); ++it)
496 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[
slot]; }
501 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
506 std::string GetActionName()
508 return std::string(fObjects[0]->IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
513 std::string GetActionName()
515 return "Fill custom object";
518 template <
typename H = HIST>
529template <
typename BinContentType,
bool WithWeight = false>
531 public ExecLoopTrait<RHistFillHelper<BinContentType, WithWeight>> {
536 std::unique_ptr<ROOT::Experimental::RHistConcurrentFiller<BinContentType>>
fFiller;
537 std::vector<std::shared_ptr<ROOT::Experimental::RHistFillContext<BinContentType>>> fContexts;
543 for (
unsigned int i = 0; i <
nSlots; i++) {
544 fContexts[i] =
fFiller->CreateFillContext();
553 std::shared_ptr<Result_t> GetResultPtr()
const {
return fFiller.GetHist(); }
558 template <
typename...
ColumnTypes,
const std::size_t... I>
565 fContexts[
slot]->Fill(args, weight);
581 for (
auto &&context : fContexts) {
593 std::string GetActionName() {
return "Hist"; }
596template <
typename BinContentType,
bool WithWeight = false>
598 :
public RActionImpl<RHistEngineFillHelper<BinContentType, WithWeight>>,
599 public ExecLoopTrait<RHistEngineFillHelper<BinContentType, WithWeight>> {
604 std::shared_ptr<Result_t> fHist;
614 std::shared_ptr<Result_t> GetResultPtr()
const {
return fHist; }
619 template <
typename...
ColumnTypes,
const std::size_t... I>
625 fHist->FillAtomic(args, weight);
648 std::string GetActionName() {
return "Hist"; }
657 std::vector<::TGraph *> fGraphs;
665 fGraphs[0] =
g.get();
667 for (
unsigned int i = 1; i <
nSlots; ++i) {
668 fGraphs[i] =
new TGraph(*fGraphs[0]);
676 template <
typename X0,
typename X1,
677 std::enable_if_t<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int> = 0>
680 if (
x0s.size() !=
x1s.size()) {
681 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
693 template <
typename X0,
typename X1,
694 std::enable_if_t<!IsDataContainer<X0>::value && !IsDataContainer<X1>::value,
int> = 0>
706 throw std::runtime_error(
"Graph was applied to a mix of scalar values and collections. This is not supported.");
711 const auto nSlots = fGraphs.size();
716 l.Add(fGraphs[
slot]);
724 return std::make_unique<RMergeableFill<Result_t>>(*fGraphs[0]);
727 std::string GetActionName() {
return "Graph"; }
729 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[
slot]; }
756 for (
unsigned int i = 1; i <
nSlots; ++i) {
766 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
767 std::enable_if_t<IsDataContainer<X>::value && IsDataContainer<Y>::value && IsDataContainer<EXL>::value &&
768 IsDataContainer<EXH>::value && IsDataContainer<EYL>::value && IsDataContainer<EYH>::value,
773 if ((
xs.size() !=
ys.size()) || (
xs.size() !=
exls.size()) || (
xs.size() !=
exhs.size()) ||
774 (
xs.size() !=
eyls.size()) || (
xs.size() !=
eyhs.size())) {
775 throw std::runtime_error(
"Cannot fill GraphAsymmErrors with values in containers of different sizes.");
778 auto xsIt = std::begin(
xs);
779 auto ysIt = std::begin(
ys);
784 while (
xsIt != std::end(
xs)) {
793 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
794 std::enable_if_t<!IsDataContainer<X>::value && !IsDataContainer<Y>::value && !IsDataContainer<EXL>::value &&
795 !IsDataContainer<EXH>::value && !IsDataContainer<EYL>::value && !IsDataContainer<EYH>::value,
807 template <
typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
811 throw std::runtime_error(
812 "GraphAsymmErrors was applied to a mix of scalar values and collections. This is not supported.");
833 std::string GetActionName() {
return "GraphAsymmErrors"; }
839 auto &
result = *
static_cast<std::shared_ptr<TGraphAsymmErrors> *
>(
newResult);
846template <
typename HIST>
848 std::vector<std::shared_ptr<HIST>> fObjects;
849 std::vector<std::unique_ptr<std::mutex>>
fMutexPtrs;
852 template <
typename T,
typename... Args>
859 template <
typename T,
typename... Args>
862 std::scoped_lock lock{mutex};
863 object.Fill(args...);
866 template <std::size_t
ColIdx,
typename End_t,
typename...
Its>
882 fObjects.front() =
h;
884 std::generate(fObjects.begin() + 1, fObjects.end(), [
h]() {
885 auto hist = std::make_shared<HIST>(*h);
886 UnsetDirectoryIfPossible(hist.get());
896 template <
typename...
ValTypes, std::enable_if_t<!std::disjunction<IsDataContainer<ValTypes>...>
::value,
int> = 0>
904 template <
typename...
Xs, std::enable_if_t<std::disjunction<IsDataContainer<Xs>...>
::value,
int> = 0>
908 constexpr std::array<
bool,
sizeof...(Xs)>
isContainer{IsDataContainer<Xs>::value...};
913 static_assert(
colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
919 std::array<std::size_t,
sizeof...(xs)>
sizes = {{GetSize(
xs)...}};
921 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
923 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
930 template <
typename T = HIST>
933 static_assert(
sizeof(T) < 0,
934 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
935 "columns passed did not match the signature of the object's `FillThreadSafe` method.");
942 if (fObjects.size() > 1) {
944 for (
auto it = fObjects.cbegin() + 1; it != fObjects.end(); ++it) {
947 fObjects[0]->Merge(&list);
957 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
962 std::string GetActionName()
964 return std::string(fObjects[0]->IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
967 template <
typename H = HIST>
983template <
typename V,
typename COLL>
989template <
typename COLL>
996template <
typename RealT_t,
typename T,
typename COLL>
1005 for (
unsigned int i = 1; i <
nSlots; ++i)
1006 fColls.emplace_back(std::make_shared<COLL>());
1020 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
1033 std::string GetActionName() {
return "Take"; }
1045template <
typename RealT_t,
typename T>
1047 :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
1055 for (
unsigned int i = 1; i <
nSlots; ++i) {
1056 auto v = std::make_shared<std::vector<T>>();
1078 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
1084 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *
fColls[
slot]; }
1086 std::string GetActionName() {
return "Take"; }
1090 auto &
result = *
static_cast<std::shared_ptr<std::vector<T>
> *>(
newResult);
1098template <
typename RealT_t,
typename COLL>
1100 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
1108 for (
unsigned int i = 1; i <
nSlots; ++i)
1109 fColls.emplace_back(std::make_shared<COLL>());
1123 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
1125 for (
auto &
v : *
coll) {
1131 std::string GetActionName() {
return "Take"; }
1143template <
typename RealT_t>
1145 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
1154 for (
unsigned int i = 1; i <
nSlots; ++i) {
1155 auto v = std::make_shared<std::vector<RealT_t>>();
1177 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
1183 std::string GetActionName() {
return "Take"; }
1196template <
typename RealT_t,
typename T,
typename COLL>
1198template <
typename RealT_t,
typename T>
1200template <
typename RealT_t,
typename COLL>
1202template <
typename RealT_t>
1218template <
typename ResultType>
1245 *
fResultMin = std::numeric_limits<ResultType>::max();
1253 return std::make_unique<RMergeableMin<ResultType>>(*fResultMin);
1258 std::string GetActionName() {
return "Min"; }
1262 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1267template <
typename ResultType>
1294 *
fResultMax = std::numeric_limits<ResultType>::lowest();
1303 return std::make_unique<RMergeableMax<ResultType>>(*fResultMax);
1308 std::string GetActionName() {
return "Max"; }
1312 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1317template <
typename ResultType>
1326 template <
typename T = ResultType>
1332 template <
typename T = ResultType,
typename Dummy =
int>
1360 for (
auto &&
v :
vs) {
1386 return std::make_unique<RMergeableSum<ResultType>>(*fResultSum);
1391 std::string GetActionName() {
return "Sum"; }
1395 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1403 std::vector<ULong64_t> fCounts;
1404 std::vector<double>
fSums;
1418 for (
auto &&
v :
vs) {
1440 double &PartialUpdate(
unsigned int slot);
1442 std::string GetActionName() {
return "Mean"; }
1453 unsigned int fNSlots;
1456 std::vector<ULong64_t> fCounts;
1458 std::vector<double> fMeans;
1472 for (
auto &&
v :
vs) {
1486 std::inner_product(fMeans.begin(), fMeans.end(), fCounts.begin(), 0.) /
static_cast<Double_t>(
counts);
1490 std::string GetActionName() {
return "StdDev"; }
1500 std::shared_ptr<double> fResult;
1501 std::vector<std::vector<double>> fBuffers;
1516 fBuffers[
slot].insert(fBuffers[
slot].end(), std::begin(
vs), std::end(
vs));
1523 std::string GetActionName() {
return "Median"; }
1525 std::shared_ptr<double> GetResultPtr()
const {
return fResult; }
1536template <
typename PrevNodeType>
1541 std::shared_ptr<PrevNodeType> fPrevNode;
1542 size_t fEntriesToProcess;
1545 DisplayHelper(
size_t nRows,
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
1549 DisplayHelper(DisplayHelper &&) =
default;
1550 DisplayHelper(
const DisplayHelper &) =
delete;
1553 template <
typename...
Columns>
1556 if (fEntriesToProcess == 0)
1560 --fEntriesToProcess;
1562 if (fEntriesToProcess == 0) {
1567 fPrevNode->StopProcessing();
1575 std::string GetActionName() {
return "Display"; }
1578template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1581 :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1584 std::shared_ptr<U> fResult;
1605 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<MustCopyAssign_,
int> = 0>
1611 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<!MustCopyAssign_,
int> = 0>
1620 bool MergeAll = std::is_same<void, MergeRet>::value>
1621 std::enable_if_t<MergeAll, void> Finalize()
1629 std::enable_if_t<MergeTwoByTwo, void> Finalize(...)
1632 *fResult = fMerge(*fResult,
acc);
1637 std::string GetActionName() {
return "Aggregate"; }
Handle_t Display_t
Display handle.
#define R(a, b, c, d, e, f, g, h, i)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Basic types used by ROOT and required by TInterpreter.
double Double_t
Double 8 bytes.
unsigned long long ULong64_t
Portable unsigned long integer 8 bytes.
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x1
TTime operator*(const TTime &t1, const TTime &t2)
Base class for action helpers, see RInterface::Book() for more information.
A histogram data structure to bin data along multiple dimensions.
A histogram for aggregation of data along multiple dimensions.
This class is the textual representation of the content of a columnar dataset.
const_iterator begin() const
const_iterator end() const
A "std::vector"-like collection of values implementing handy operation to analyse them.
Collection abstract base class.
TGraph with asymmetric error bars.
A TGraph is an object made of two arrays X and Y with npoints each.
1-D histogram with a double per channel (see TH1 documentation)
TH1 is the base class of all histogram classes in ROOT.
void Add(TObject *obj) override
Statistical variable, defined by its mean and variance (RMS).
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
RooCmdArg Columns(Int_t ncol)
CPYCPPYY_EXTERN bool Exec(const std::string &cmd)
std::unique_ptr< RMergeableVariations< T > > GetMergeableValue(ROOT::RDF::Experimental::RResultMap< T > &rmap)
Retrieve mergeable values after calling ROOT::RDF::VariationsFor .
void ResetIfPossible(TStatistic *h)
constexpr std::size_t FindIdxTrue(const T &arr)
void UnsetDirectoryIfPossible(TH1 *h)
auto FillThreadSafe(T &histo, Args... args) -> decltype(histo.FillThreadSafe(args...), void())
Entrypoint for thread-safe filling from RDataFrame.
ROOT type_traits extensions.
void Initialize(Bool_t useTMVAStyle=kTRUE)
A weight for filling histograms.
static uint64_t sum(uint64_t i)