18#ifndef ROOT_RDFOPERATIONS
19#define ROOT_RDFOPERATIONS
34#include "RConfigure.h"
68using namespace ROOT::TypeTraits;
69using namespace ROOT::VecOps;
70using namespace ROOT::RDF;
71using namespace ROOT::Detail::RDF;
80using Results = std::conditional_t<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>;
83class R__CLING_PTRCHECK(off) ForeachSlotHelper :
public RActionImpl<ForeachSlotHelper<F>> {
87 using ColumnTypes_t = RemoveFirstParameter_t<typename CallableTraits<F>::arg_types>;
88 ForeachSlotHelper(
F &&
f) : fCallable(
f) {}
89 ForeachSlotHelper(ForeachSlotHelper &&) =
default;
90 ForeachSlotHelper(
const ForeachSlotHelper &) =
delete;
92 void InitTask(TTreeReader *,
unsigned int) {}
94 template <
typename... Args>
95 void Exec(
unsigned int slot, Args &&... args)
98 static_assert(std::is_same<TypeList<std::decay_t<Args>...>, ColumnTypes_t>::value,
"");
99 fCallable(slot, std::forward<Args>(args)...);
106 std::string GetActionName() {
return "ForeachSlot"; }
109class R__CLING_PTRCHECK(off) CountHelper :
public RActionImpl<CountHelper> {
110 std::shared_ptr<ULong64_t> fResultCount;
111 Results<ULong64_t> fCounts;
114 using ColumnTypes_t = TypeList<>;
115 CountHelper(
const std::shared_ptr<ULong64_t> &resultCount,
const unsigned int nSlots);
116 CountHelper(CountHelper &&) =
default;
117 CountHelper(
const CountHelper &) =
delete;
118 void InitTask(TTreeReader *,
unsigned int) {}
119 void Exec(
unsigned int slot);
126 return std::make_unique<RMergeableCount>(*fResultCount);
129 ULong64_t &PartialUpdate(
unsigned int slot);
131 std::string GetActionName() {
return "Count"; }
133 CountHelper MakeNew(
void *newResult, std::string_view =
"nominal")
135 auto &result = *
static_cast<std::shared_ptr<ULong64_t> *
>(newResult);
136 return CountHelper(result, fCounts.size());
140template <
typename RNode_t>
141class R__CLING_PTRCHECK(off) ReportHelper :
public RActionImpl<ReportHelper<RNode_t>> {
142 std::shared_ptr<RCutFlowReport> fReport;
146 bool fReturnEmptyReport;
149 using ColumnTypes_t = TypeList<>;
150 ReportHelper(
const std::shared_ptr<RCutFlowReport> &report, RNode_t *node,
bool emptyRep)
151 : fReport(report), fNode(node), fReturnEmptyReport(emptyRep){};
152 ReportHelper(ReportHelper &&) =
default;
153 ReportHelper(
const ReportHelper &) =
delete;
154 void InitTask(TTreeReader *,
unsigned int) {}
155 void Exec(
unsigned int ) {}
159 if (!fReturnEmptyReport)
160 fNode->Report(*fReport);
165 auto cutinfo_vec = fReport->fCutInfos;
166 return std::make_unique<RMergeableReport>(*fReport, cutinfo_vec);
169 std::string GetActionName() {
return "Report"; }
171 ReportHelper MakeNew(
void *newResult, std::string_view variation =
"nominal")
173 auto &&result = *
static_cast<std::shared_ptr<RCutFlowReport> *
>(newResult);
174 return ReportHelper{result,
175 std::static_pointer_cast<RNode_t>(fNode->GetVariedFilter(std::string(variation))).get(),
187class R__CLING_PTRCHECK(off) BufferedFillHelper :
public RActionImpl<BufferedFillHelper> {
189 static constexpr unsigned int fgTotalBufSize = 2097152;
190 using BufEl_t = double;
191 using Buf_t = std::vector<BufEl_t>;
193 std::vector<Buf_t> fBuffers;
194 std::vector<Buf_t> fWBuffers;
195 std::shared_ptr<Hist_t> fResultHist;
196 unsigned int fNSlots;
197 unsigned int fBufSize;
199 Results<std::unique_ptr<Hist_t>> fPartialHists;
203 void UpdateMinMax(
unsigned int slot,
double v);
206 BufferedFillHelper(
const std::shared_ptr<Hist_t> &
h,
const unsigned int nSlots);
207 BufferedFillHelper(BufferedFillHelper &&) =
default;
208 BufferedFillHelper(
const BufferedFillHelper &) =
delete;
209 void InitTask(TTreeReader *,
unsigned int) {}
210 void Exec(
unsigned int slot,
double v);
211 void Exec(
unsigned int slot,
double v,
double w);
213 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
214 void Exec(
unsigned int slot,
const T &vs)
216 auto &thisBuf = fBuffers[slot];
218 for (
auto v = vs.begin();
v != vs.end(); ++
v) {
219 UpdateMinMax(slot, *
v);
220 thisBuf.emplace_back(*
v);
224 template <typename T, typename W, std::enable_if_t<IsDataContainer<T>::value && IsDataContainer<W>::value,
int> = 0>
225 void Exec(
unsigned int slot,
const T &vs,
const W &ws)
227 auto &thisBuf = fBuffers[slot];
230 UpdateMinMax(slot,
v);
231 thisBuf.emplace_back(
v);
234 auto &thisWBuf = fWBuffers[slot];
236 thisWBuf.emplace_back(w);
240 template <typename T, typename W, std::enable_if_t<IsDataContainer<T>::value && !IsDataContainer<W>::value,
int> = 0>
241 void Exec(
unsigned int slot,
const T &vs,
const W w)
243 auto &thisBuf = fBuffers[slot];
245 UpdateMinMax(slot,
v);
246 thisBuf.emplace_back(
v);
249 auto &thisWBuf = fWBuffers[slot];
250 thisWBuf.insert(thisWBuf.end(), vs.size(), w);
253 template <typename T, typename W, std::enable_if_t<IsDataContainer<W>::value && !IsDataContainer<T>::value,
int> = 0>
254 void Exec(
unsigned int slot,
const T
v,
const W &ws)
256 UpdateMinMax(slot,
v);
257 auto &thisBuf = fBuffers[slot];
258 thisBuf.insert(thisBuf.end(), ws.size(),
v);
260 auto &thisWBuf = fWBuffers[slot];
261 thisWBuf.insert(thisWBuf.end(), ws.begin(), ws.end());
264 Hist_t &PartialUpdate(
unsigned int);
273 return std::make_unique<RMergeableFill<Hist_t>>(*fResultHist);
276 std::string GetActionName()
278 return std::string(fResultHist->IsA()->GetName()) +
"\\n" + std::string(fResultHist->GetName());
281 BufferedFillHelper MakeNew(
void *newResult, std::string_view =
"nominal")
283 auto &result = *
static_cast<std::shared_ptr<Hist_t> *
>(newResult);
285 result->SetDirectory(
nullptr);
286 return BufferedFillHelper(result, fNSlots);
292class ScalarConstIterator {
296 using iterator_category = std::forward_iterator_tag;
297 using difference_type = std::ptrdiff_t;
298 using value_type =
T;
300 using reference =
T &;
301 ScalarConstIterator(
const T *obj) : obj_(obj) {}
303 ScalarConstIterator<T> &operator++() {
return *
this; }
308auto MakeBegin(
const T &val)
310 if constexpr (IsDataContainer<T>::value) {
311 return std::begin(val);
313 return ScalarConstIterator<T>(&val);
319std::size_t GetSize(
const T &val)
321 if constexpr (IsDataContainer<T>::value) {
322 return std::size(val);
329template <typename H, typename = decltype(std::declval<H>().Reset())>
343template <
typename HIST = Hist_t>
344class R__CLING_PTRCHECK(off) FillHelper :
public RActionImpl<FillHelper<HIST>> {
345 std::vector<HIST *> fObjects;
348 template <typename H, typename = std::enable_if_t<std::is_base_of<TObject, H>::value,
int>>
349 auto Merge(std::vector<H *> &objs,
int )
350 ->
decltype(objs[0]->Merge((TCollection *)
nullptr),
void())
353 for (
auto it = ++objs.begin(); it != objs.end(); ++it)
359 template <
typename H>
360 auto Merge(std::vector<H *> &objs,
double )
361 ->
decltype(objs[0]->Merge(std::vector<HIST *>{}),
void())
363 objs[0]->Merge({++objs.begin(), objs.end()});
367 template <
typename T>
370 static_assert(
sizeof(
T) < 0,
371 "The type passed to Fill does not provide a Merge(TCollection*) or Merge(const std::vector&) method.");
374 template <std::size_t ColIdx,
typename End_t,
typename... Its>
375 void ExecLoop(
unsigned int slot, End_t end, Its... its)
377 for (
auto *thisSlotH = fObjects[slot]; GetNthElement<ColIdx>(its...) != end; (std::advance(its, 1), ...)) {
378 thisSlotH->Fill(*its...);
383 FillHelper(FillHelper &&) =
default;
384 FillHelper(
const FillHelper &) =
delete;
386 FillHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots) : fObjects(nSlots, nullptr)
388 fObjects[0] =
h.get();
390 for (
unsigned int i = 1; i < nSlots; ++i) {
391 fObjects[i] =
new HIST(*fObjects[0]);
396 void InitTask(TTreeReader *,
unsigned int) {}
399 template <
typename... ValTypes, std::enable_if_t<!Disjunction<IsDataContainer<ValTypes>...>::value,
int> = 0>
400 auto Exec(
unsigned int slot,
const ValTypes &...
x) ->
decltype(fObjects[slot]->Fill(
x...),
void())
402 fObjects[slot]->Fill(
x...);
406 template <
typename... Xs, std::enable_if_t<Disjunction<IsDataContainer<Xs>...>::value,
int> = 0>
407 auto Exec(
unsigned int slot,
const Xs &...xs) ->
decltype(fObjects[slot]->Fill(*MakeBegin(xs)...),
void())
410 constexpr std::array<bool,
sizeof...(Xs)> isContainer{IsDataContainer<Xs>::value...};
413 constexpr std::size_t colidx =
FindIdxTrue(isContainer);
415 static_assert(colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
418 auto const xrefend = std::end(GetNthElement<colidx>(xs...));
421 std::array<std::size_t,
sizeof...(xs)> sizes = {{GetSize(xs)...}};
423 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
424 if (isContainer[i] && sizes[i] != sizes[colidx]) {
425 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
429 ExecLoop<colidx>(slot, xrefend, MakeBegin(xs)...);
432 template <
typename T = HIST>
435 static_assert(
sizeof(
T) < 0,
436 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
437 "columns passed did not match the signature of the object's `Fill` method.");
444 if (fObjects.size() == 1)
450 for (
auto it = ++fObjects.begin(); it != fObjects.end(); ++it)
454 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[slot]; }
459 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
463 template <typename T = HIST, std::enable_if_t<std::is_base_of<TObject, T>::value,
int> = 0>
464 std::string GetActionName()
466 return std::string(fObjects[0]->
IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
470 template <typename T = HIST, std::enable_if_t<!std::is_base_of<TObject, T>::value,
int> = 0>
471 std::string GetActionName()
473 return "Fill custom object";
476 template <
typename H = HIST>
477 FillHelper MakeNew(
void *newResult, std::string_view =
"nominal")
479 auto &result = *
static_cast<std::shared_ptr<H> *
>(newResult);
482 return FillHelper(result, fObjects.size());
487template <
typename BinContentType,
bool WithWeight = false>
488class R__CLING_PTRCHECK(off) RHistFillHelper
489 :
public ROOT::Detail::RDF::RActionImpl<RHistFillHelper<BinContentType, WithWeight>> {
491 using Result_t = ROOT::Experimental::RHist<BinContentType>;
494 std::unique_ptr<ROOT::Experimental::RHistConcurrentFiller<BinContentType>> fFiller;
495 std::vector<std::shared_ptr<ROOT::Experimental::RHistFillContext<BinContentType>>> fContexts;
498 RHistFillHelper(std::shared_ptr<ROOT::Experimental::RHist<BinContentType>>
h,
unsigned int nSlots)
499 : fFiller(new ROOT::Experimental::RHistConcurrentFiller<BinContentType>(
h)), fContexts(nSlots)
501 for (
unsigned int i = 0; i < nSlots; i++) {
502 fContexts[i] = fFiller->CreateFillContext();
505 RHistFillHelper(
const RHistFillHelper &) =
delete;
506 RHistFillHelper(RHistFillHelper &&) =
default;
507 RHistFillHelper &
operator=(
const RHistFillHelper &) =
delete;
508 RHistFillHelper &
operator=(RHistFillHelper &&) =
default;
509 ~RHistFillHelper() =
default;
511 std::shared_ptr<Result_t> GetResultPtr()
const {
return fFiller.GetHist(); }
514 void InitTask(TTreeReader *,
unsigned int) {}
516 template <
typename... ColumnTypes,
const std::size_t...
I>
518 ExecWithWeight(
unsigned int slot,
const std::tuple<const ColumnTypes &...> &columnValues, std::index_sequence<I...>)
521 std::tuple<
const std::tuple_element_t<
I, std::tuple<ColumnTypes...>> &...> args(std::get<I>(columnValues)...);
522 ROOT::Experimental::RWeight weight(std::get<
sizeof...(ColumnTypes) - 1>(columnValues));
523 fContexts[slot]->Fill(args, weight);
526 template <
typename... ColumnTypes>
527 void Exec(
unsigned int slot,
const ColumnTypes &...columnValues)
529 if constexpr (WithWeight) {
530 auto t = std::forward_as_tuple(columnValues...);
531 ExecWithWeight(slot, t, std::make_index_sequence<
sizeof...(ColumnTypes) - 1>());
533 fContexts[slot]->Fill(columnValues...);
539 for (
auto &&context : fContexts) {
544 std::string GetActionName() {
return "Hist"; }
547template <
typename BinContentType,
bool WithWeight = false>
548class R__CLING_PTRCHECK(off) RHistEngineFillHelper
549 :
public ROOT::Detail::RDF::RActionImpl<RHistEngineFillHelper<BinContentType, WithWeight>> {
551 using Result_t = ROOT::Experimental::RHistEngine<BinContentType>;
554 std::shared_ptr<Result_t> fHist;
557 RHistEngineFillHelper(std::shared_ptr<ROOT::Experimental::RHistEngine<BinContentType>>
h) : fHist(
h) {}
558 RHistEngineFillHelper(
const RHistEngineFillHelper &) =
delete;
559 RHistEngineFillHelper(RHistEngineFillHelper &&) =
default;
560 RHistEngineFillHelper &
operator=(
const RHistEngineFillHelper &) =
delete;
561 RHistEngineFillHelper &
operator=(RHistEngineFillHelper &&) =
default;
562 ~RHistEngineFillHelper() =
default;
564 std::shared_ptr<Result_t> GetResultPtr()
const {
return fHist; }
567 void InitTask(TTreeReader *,
unsigned int) {}
569 template <
typename... ColumnTypes,
const std::size_t...
I>
570 void ExecWithWeight(
const std::tuple<const ColumnTypes &...> &columnValues, std::index_sequence<I...>)
573 std::tuple<
const std::tuple_element_t<
I, std::tuple<ColumnTypes...>> &...> args(std::get<I>(columnValues)...);
574 ROOT::Experimental::RWeight weight(std::get<
sizeof...(ColumnTypes) - 1>(columnValues));
575 fHist->FillAtomic(args, weight);
578 template <
typename... ColumnTypes>
579 void Exec(
unsigned int,
const ColumnTypes &...columnValues)
581 if constexpr (WithWeight) {
582 auto t = std::forward_as_tuple(columnValues...);
583 ExecWithWeight(t, std::make_index_sequence<
sizeof...(ColumnTypes) - 1>());
585 fHist->FillAtomic(columnValues...);
591 std::string GetActionName() {
return "Hist"; }
595class R__CLING_PTRCHECK(off) FillTGraphHelper :
public ROOT::Detail::RDF::RActionImpl<FillTGraphHelper> {
597 using Result_t = ::TGraph;
600 std::vector<::TGraph *> fGraphs;
603 FillTGraphHelper(FillTGraphHelper &&) =
default;
604 FillTGraphHelper(
const FillTGraphHelper &) =
delete;
606 FillTGraphHelper(
const std::shared_ptr<::TGraph> &
g,
const unsigned int nSlots) : fGraphs(nSlots, nullptr)
608 fGraphs[0] =
g.get();
610 for (
unsigned int i = 1; i < nSlots; ++i) {
611 fGraphs[i] =
new TGraph(*fGraphs[0]);
616 void InitTask(TTreeReader *,
unsigned int) {}
619 template <
typename X0,
typename X1,
620 std::enable_if_t<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int> = 0>
621 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
623 if (x0s.size() != x1s.size()) {
624 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
626 auto *thisSlotG = fGraphs[slot];
627 auto x0sIt = std::begin(x0s);
628 const auto x0sEnd = std::end(x0s);
629 auto x1sIt = std::begin(x1s);
630 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
631 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
636 template <
typename X0,
typename X1,
637 std::enable_if_t<!IsDataContainer<X0>::value && !IsDataContainer<X1>::value,
int> = 0>
638 void Exec(
unsigned int slot, X0 x0, X1 x1)
640 auto thisSlotG = fGraphs[slot];
641 thisSlotG->SetPoint(thisSlotG->GetN(), x0, x1);
646 template <
typename X0,
typename X1,
typename... ExtraArgsToLowerPriority>
647 void Exec(
unsigned int, X0, X1, ExtraArgsToLowerPriority...)
649 throw std::runtime_error(
"Graph was applied to a mix of scalar values and collections. This is not supported.");
654 const auto nSlots = fGraphs.size();
655 auto resGraph = fGraphs[0];
658 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
659 l.Add(fGraphs[slot]);
667 return std::make_unique<RMergeableFill<Result_t>>(*fGraphs[0]);
670 std::string GetActionName() {
return "Graph"; }
672 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
674 FillTGraphHelper MakeNew(
void *newResult, std::string_view =
"nominal")
676 auto &result = *
static_cast<std::shared_ptr<TGraph> *
>(newResult);
678 return FillTGraphHelper(result, fGraphs.size());
682class R__CLING_PTRCHECK(off) FillTGraphAsymmErrorsHelper
683 :
public ROOT::Detail::RDF::RActionImpl<FillTGraphAsymmErrorsHelper> {
685 using Result_t = ::TGraphAsymmErrors;
688 std::vector<::TGraphAsymmErrors *> fGraphAsymmErrors;
691 FillTGraphAsymmErrorsHelper(FillTGraphAsymmErrorsHelper &&) =
default;
692 FillTGraphAsymmErrorsHelper(
const FillTGraphAsymmErrorsHelper &) =
delete;
694 FillTGraphAsymmErrorsHelper(
const std::shared_ptr<::TGraphAsymmErrors> &
g,
const unsigned int nSlots)
695 : fGraphAsymmErrors(nSlots, nullptr)
697 fGraphAsymmErrors[0] =
g.get();
699 for (
unsigned int i = 1; i < nSlots; ++i) {
700 fGraphAsymmErrors[i] =
new TGraphAsymmErrors(*fGraphAsymmErrors[0]);
705 void InitTask(TTreeReader *,
unsigned int) {}
709 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
710 std::enable_if_t<IsDataContainer<X>::value && IsDataContainer<Y>::value && IsDataContainer<EXL>::value &&
711 IsDataContainer<EXH>::value && IsDataContainer<EYL>::value && IsDataContainer<EYH>::value,
714 Exec(
unsigned int slot,
const X &xs,
const Y &ys,
const EXL &exls,
const EXH &exhs,
const EYL &eyls,
const EYH &eyhs)
716 if ((xs.size() != ys.size()) || (xs.size() != exls.size()) || (xs.size() != exhs.size()) ||
717 (xs.size() != eyls.size()) || (xs.size() != eyhs.size())) {
718 throw std::runtime_error(
"Cannot fill GraphAsymmErrors with values in containers of different sizes.");
720 auto *thisSlotG = fGraphAsymmErrors[slot];
721 auto xsIt = std::begin(xs);
722 auto ysIt = std::begin(ys);
723 auto exlsIt = std::begin(exls);
724 auto exhsIt = std::begin(exhs);
725 auto eylsIt = std::begin(eyls);
726 auto eyhsIt = std::begin(eyhs);
727 while (xsIt != std::end(xs)) {
728 const auto n = thisSlotG->GetN();
729 thisSlotG->SetPoint(
n, *xsIt++, *ysIt++);
730 thisSlotG->SetPointError(
n, *exlsIt++, *exhsIt++, *eylsIt++, *eyhsIt++);
736 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
737 std::enable_if_t<!IsDataContainer<X>::value && !IsDataContainer<Y>::value && !IsDataContainer<EXL>::value &&
738 !IsDataContainer<EXH>::value && !IsDataContainer<EYL>::value && !IsDataContainer<EYH>::value,
740 void Exec(
unsigned int slot,
X x, Y
y, EXL exl, EXH exh, EYL eyl, EYH eyh)
742 auto thisSlotG = fGraphAsymmErrors[slot];
743 const auto n = thisSlotG->GetN();
744 thisSlotG->SetPoint(
n,
x,
y);
745 thisSlotG->SetPointError(
n, exl, exh, eyl, eyh);
750 template <
typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
751 typename... ExtraArgsToLowerPriority>
752 void Exec(
unsigned int,
X, Y, EXL, EXH, EYL, EYH, ExtraArgsToLowerPriority...)
754 throw std::runtime_error(
755 "GraphAsymmErrors was applied to a mix of scalar values and collections. This is not supported.");
760 const auto nSlots = fGraphAsymmErrors.size();
761 auto resGraphAsymmErrors = fGraphAsymmErrors[0];
764 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
765 l.Add(fGraphAsymmErrors[slot]);
767 resGraphAsymmErrors->Merge(&
l);
773 return std::make_unique<RMergeableFill<Result_t>>(*fGraphAsymmErrors[0]);
776 std::string GetActionName() {
return "GraphAsymmErrors"; }
778 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphAsymmErrors[slot]; }
780 FillTGraphAsymmErrorsHelper MakeNew(
void *newResult, std::string_view =
"nominal")
782 auto &result = *
static_cast<std::shared_ptr<TGraphAsymmErrors> *
>(newResult);
784 return FillTGraphAsymmErrorsHelper(result, fGraphAsymmErrors.size());
789template <
typename HIST>
790class R__CLING_PTRCHECK(off) ThreadSafeFillHelper :
public RActionImpl<ThreadSafeFillHelper<HIST>> {
791 std::vector<std::shared_ptr<HIST>> fObjects;
792 std::vector<std::unique_ptr<std::mutex>> fMutexPtrs;
795 template <
typename T,
typename... Args>
796 auto TryCallFillThreadSafe(T &
object, std::mutex &,
int , Args... args)
802 template <
typename T,
typename... Args>
803 auto TryCallFillThreadSafe(T &
object, std::mutex &mutex,
char , Args... args)
805 std::scoped_lock lock{mutex};
806 object.Fill(args...);
809 template <std::size_t ColIdx,
typename End_t,
typename... Its>
810 void ExecLoop(
unsigned int slot, End_t end, Its... its)
812 const auto localSlot = slot % fObjects.size();
813 for (; GetNthElement<ColIdx>(its...) != end; (std::advance(its, 1), ...)) {
814 TryCallFillThreadSafe(*fObjects[localSlot], *fMutexPtrs[localSlot], 0, *its...);
819 ThreadSafeFillHelper(ThreadSafeFillHelper &&) =
default;
820 ThreadSafeFillHelper(
const ThreadSafeFillHelper &) =
delete;
822 ThreadSafeFillHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots)
824 fObjects.resize(nSlots);
825 fObjects.front() =
h;
827 std::generate(fObjects.begin() + 1, fObjects.end(), [
h]() {
828 auto hist = std::make_shared<HIST>(*h);
829 UnsetDirectoryIfPossible(hist.get());
832 fMutexPtrs.resize(nSlots);
833 std::generate(fMutexPtrs.begin(), fMutexPtrs.end(), []() { return std::make_unique<std::mutex>(); });
836 void InitTask(TTreeReader *,
unsigned int) {}
839 template <
typename... ValTypes, std::enable_if_t<!Disjunction<IsDataContainer<ValTypes>...>::value,
int> = 0>
840 void Exec(
unsigned int slot,
const ValTypes &...
x)
842 const auto localSlot = slot % fObjects.size();
843 TryCallFillThreadSafe(*fObjects[localSlot], *fMutexPtrs[localSlot], 0,
x...);
847 template <
typename... Xs, std::enable_if_t<Disjunction<IsDataContainer<Xs>...>::value,
int> = 0>
848 void Exec(
unsigned int slot,
const Xs &...xs)
851 constexpr std::array<bool,
sizeof...(Xs)> isContainer{IsDataContainer<Xs>::value...};
854 constexpr std::size_t colidx =
FindIdxTrue(isContainer);
856 static_assert(colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
859 auto const xrefend = std::end(GetNthElement<colidx>(xs...));
862 std::array<std::size_t,
sizeof...(xs)> sizes = {{GetSize(xs)...}};
864 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
865 if (isContainer[i] && sizes[i] != sizes[colidx]) {
866 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
870 ExecLoop<colidx>(slot, xrefend, MakeBegin(xs)...);
873 template <
typename T = HIST>
876 static_assert(
sizeof(
T) < 0,
877 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
878 "columns passed did not match the signature of the object's `FillThreadSafe` method.");
885 if (fObjects.size() > 1) {
887 for (
auto it = fObjects.cbegin() + 1; it != fObjects.end(); ++it) {
890 fObjects[0]->Merge(&list);
900 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
904 template <typename T = HIST, std::enable_if_t<std::is_base_of<TObject, T>::value,
int> = 0>
905 std::string GetActionName()
907 return std::string(fObjects[0]->
IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
910 template <
typename H = HIST>
911 ThreadSafeFillHelper MakeNew(
void *newResult, std::string_view =
"nominal")
913 auto &result = *
static_cast<std::shared_ptr<H> *
>(newResult);
916 return ThreadSafeFillHelper(result, fObjects.size());
926template <
typename V,
typename COLL>
927void FillColl(V&&
v, COLL&
c) {
932template <
typename COLL>
933void FillColl(
bool v, COLL&
c) {
939template <
typename RealT_t,
typename T,
typename COLL>
940class R__CLING_PTRCHECK(off) TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
941 Results<std::shared_ptr<COLL>> fColls;
944 using ColumnTypes_t = TypeList<T>;
945 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
947 fColls.emplace_back(resultColl);
948 for (
unsigned int i = 1; i < nSlots; ++i)
949 fColls.emplace_back(std::make_shared<COLL>());
951 TakeHelper(TakeHelper &&);
952 TakeHelper(
const TakeHelper &) =
delete;
954 void InitTask(TTreeReader *,
unsigned int) {}
956 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
962 auto rColl = fColls[0];
963 for (
unsigned int i = 1; i < fColls.size(); ++i) {
964 const auto &coll = fColls[i];
965 const auto end = coll->end();
968 for (
auto j = coll->begin(); j != end; j++) {
969 FillColl(*j, *rColl);
974 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
976 std::string GetActionName() {
return "Take"; }
978 TakeHelper MakeNew(
void *newResult, std::string_view =
"nominal")
980 auto &result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
982 return TakeHelper(result, fColls.size());
988template <
typename RealT_t,
typename T>
989class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
T, std::vector<T>>
990 :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
991 Results<std::shared_ptr<std::vector<T>>> fColls;
994 using ColumnTypes_t = TypeList<T>;
995 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
997 fColls.emplace_back(resultColl);
998 for (
unsigned int i = 1; i < nSlots; ++i) {
999 auto v = std::make_shared<std::vector<T>>();
1001 fColls.emplace_back(
v);
1004 TakeHelper(TakeHelper &&);
1005 TakeHelper(
const TakeHelper &) =
delete;
1007 void InitTask(TTreeReader *,
unsigned int) {}
1009 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
1017 for (
auto &coll : fColls)
1018 totSize += coll->size();
1019 auto rColl = fColls[0];
1020 rColl->reserve(totSize);
1021 for (
unsigned int i = 1; i < fColls.size(); ++i) {
1022 auto &coll = fColls[i];
1023 rColl->insert(rColl->end(), coll->begin(), coll->end());
1027 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
1029 std::string GetActionName() {
return "Take"; }
1031 TakeHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1033 auto &result = *
static_cast<std::shared_ptr<std::vector<T>
> *>(newResult);
1035 return TakeHelper(result, fColls.size());
1041template <
typename RealT_t,
typename COLL>
1042class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, COLL>
1043 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
1044 Results<std::shared_ptr<COLL>> fColls;
1047 using ColumnTypes_t = TypeList<RVec<RealT_t>>;
1048 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
1050 fColls.emplace_back(resultColl);
1051 for (
unsigned int i = 1; i < nSlots; ++i)
1052 fColls.emplace_back(std::make_shared<COLL>());
1054 TakeHelper(TakeHelper &&);
1055 TakeHelper(
const TakeHelper &) =
delete;
1057 void InitTask(TTreeReader *,
unsigned int) {}
1059 void Exec(
unsigned int slot, RVec<RealT_t> av) { fColls[slot]->emplace_back(av.
begin(), av.
end()); }
1065 auto rColl = fColls[0];
1066 for (
unsigned int i = 1; i < fColls.size(); ++i) {
1067 auto &coll = fColls[i];
1068 for (
auto &
v : *coll) {
1069 rColl->emplace_back(
v);
1074 std::string GetActionName() {
return "Take"; }
1076 TakeHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1078 auto &result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
1080 return TakeHelper(result, fColls.size());
1086template <
typename RealT_t>
1087class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>>
1088 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
1090 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
1093 using ColumnTypes_t = TypeList<RVec<RealT_t>>;
1094 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
1096 fColls.emplace_back(resultColl);
1097 for (
unsigned int i = 1; i < nSlots; ++i) {
1098 auto v = std::make_shared<std::vector<RealT_t>>();
1100 fColls.emplace_back(
v);
1103 TakeHelper(TakeHelper &&);
1104 TakeHelper(
const TakeHelper &) =
delete;
1106 void InitTask(TTreeReader *,
unsigned int) {}
1108 void Exec(
unsigned int slot, RVec<RealT_t> av) { fColls[slot]->emplace_back(av.
begin(), av.
end()); }
1116 for (
auto &coll : fColls)
1117 totSize += coll->size();
1118 auto rColl = fColls[0];
1119 rColl->reserve(totSize);
1120 for (
unsigned int i = 1; i < fColls.size(); ++i) {
1121 auto &coll = fColls[i];
1122 rColl->insert(rColl->end(), coll->begin(), coll->end());
1126 std::string GetActionName() {
return "Take"; }
1128 TakeHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1130 auto &result = *
static_cast<typename decltype(fColls)::value_type *
>(newResult);
1132 return TakeHelper(result, fColls.size());
1139template <
typename RealT_t,
typename T,
typename COLL>
1140TakeHelper<RealT_t, T, COLL>::TakeHelper(TakeHelper<RealT_t, T, COLL> &&) =
default;
1141template <
typename RealT_t,
typename T>
1142TakeHelper<RealT_t, T, std::vector<T>>::TakeHelper(TakeHelper<RealT_t, T, std::vector<T>> &&) =
default;
1143template <
typename RealT_t,
typename COLL>
1144TakeHelper<RealT_t, RVec<RealT_t>, COLL>::TakeHelper(TakeHelper<RealT_t, RVec<RealT_t>, COLL> &&) =
default;
1145template <
typename RealT_t>
1146TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>::TakeHelper(TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>> &&) =
default;
1150extern template class TakeHelper<bool, bool, std::vector<bool>>;
1151extern template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
1152extern template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
1153extern template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
1154extern template class TakeHelper<int, int, std::vector<int>>;
1155extern template class TakeHelper<long, long, std::vector<long>>;
1156extern template class TakeHelper<long long, long long, std::vector<long long>>;
1157extern template class TakeHelper<float, float, std::vector<float>>;
1158extern template class TakeHelper<double, double, std::vector<double>>;
1161template <
typename ResultType>
1162class R__CLING_PTRCHECK(off) MinHelper :
public RActionImpl<MinHelper<ResultType>> {
1163 std::shared_ptr<ResultType> fResultMin;
1164 Results<ResultType> fMins;
1167 MinHelper(MinHelper &&) =
default;
1168 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
1169 : fResultMin(minVPtr), fMins(nSlots, std::numeric_limits<ResultType>::
max())
1173 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
1175 void InitTask(TTreeReader *,
unsigned int) {}
1177 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1178 void Exec(
unsigned int slot,
const T &vs)
1181 fMins[slot] = std::min(
static_cast<ResultType
>(
v), fMins[slot]);
1188 *fResultMin = std::numeric_limits<ResultType>::max();
1189 for (
auto &
m : fMins)
1190 *fResultMin = std::min(
m, *fResultMin);
1196 return std::make_unique<RMergeableMin<ResultType>>(*fResultMin);
1199 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
1201 std::string GetActionName() {
return "Min"; }
1203 MinHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1205 auto &result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1206 return MinHelper(result, fMins.size());
1210template <
typename ResultType>
1211class R__CLING_PTRCHECK(off) MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
1212 std::shared_ptr<ResultType> fResultMax;
1213 Results<ResultType> fMaxs;
1216 MaxHelper(MaxHelper &&) =
default;
1217 MaxHelper(
const MaxHelper &) =
delete;
1218 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
1219 : fResultMax(maxVPtr), fMaxs(nSlots, std::numeric_limits<ResultType>::lowest())
1223 void InitTask(TTreeReader *,
unsigned int) {}
1224 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
1226 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1227 void Exec(
unsigned int slot,
const T &vs)
1230 fMaxs[slot] = std::max(
static_cast<ResultType
>(
v), fMaxs[slot]);
1237 *fResultMax = std::numeric_limits<ResultType>::lowest();
1238 for (
auto &
m : fMaxs) {
1239 *fResultMax = std::max(
m, *fResultMax);
1246 return std::make_unique<RMergeableMax<ResultType>>(*fResultMax);
1249 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
1251 std::string GetActionName() {
return "Max"; }
1253 MaxHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1255 auto &result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1256 return MaxHelper(result, fMaxs.size());
1260template <
typename ResultType>
1261class R__CLING_PTRCHECK(off) SumHelper :
public RActionImpl<SumHelper<ResultType>> {
1262 std::shared_ptr<ResultType> fResultSum;
1263 Results<ResultType> fSums;
1264 Results<ResultType> fCompensations;
1269 template <
typename T = ResultType>
1270 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
1275 template <
typename T = ResultType,
typename Dummy =
int>
1276 ResultType NeutralElement(
const T &, Dummy)
1278 return ResultType{};
1282 SumHelper(SumHelper &&) =
default;
1283 SumHelper(
const SumHelper &) =
delete;
1284 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
1285 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1)),
1286 fCompensations(nSlots, NeutralElement(*sumVPtr, -1))
1289 void InitTask(TTreeReader *,
unsigned int) {}
1291 void Exec(
unsigned int slot, ResultType
x)
1294 ResultType
y =
x - fCompensations[slot];
1295 ResultType t = fSums[slot] +
y;
1296 fCompensations[slot] = (t - fSums[slot]) -
y;
1300 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1301 void Exec(
unsigned int slot,
const T &vs)
1303 for (
auto &&
v : vs) {
1312 ResultType
sum(NeutralElement(ResultType{}, -1));
1313 ResultType compensation(NeutralElement(ResultType{}, -1));
1314 ResultType
y(NeutralElement(ResultType{}, -1));
1315 ResultType t(NeutralElement(ResultType{}, -1));
1316 for (
auto &
m : fSums) {
1318 y =
m - compensation;
1320 compensation = (t -
sum) -
y;
1329 return std::make_unique<RMergeableSum<ResultType>>(*fResultSum);
1332 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
1334 std::string GetActionName() {
return "Sum"; }
1336 SumHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1338 auto &result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1339 *result = NeutralElement(*result, -1);
1340 return SumHelper(result, fSums.size());
1344class R__CLING_PTRCHECK(off) MeanHelper :
public RActionImpl<MeanHelper> {
1345 std::shared_ptr<double> fResultMean;
1346 std::vector<ULong64_t> fCounts;
1347 std::vector<double> fSums;
1348 std::vector<double> fPartialMeans;
1349 std::vector<double> fCompensations;
1352 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1353 MeanHelper(MeanHelper &&) =
default;
1354 MeanHelper(
const MeanHelper &) =
delete;
1355 void InitTask(TTreeReader *,
unsigned int) {}
1356 void Exec(
unsigned int slot,
double v);
1358 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1359 void Exec(
unsigned int slot,
const T &vs)
1361 for (
auto &&
v : vs) {
1365 double y =
v - fCompensations[slot];
1366 double t = fSums[slot] +
y;
1367 fCompensations[slot] = (t - fSums[slot]) -
y;
1379 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1380 return std::make_unique<RMergeableMean>(*fResultMean, counts);
1383 double &PartialUpdate(
unsigned int slot);
1385 std::string GetActionName() {
return "Mean"; }
1387 MeanHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1389 auto &result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1390 return MeanHelper(result, fSums.size());
1394class R__CLING_PTRCHECK(off) StdDevHelper :
public RActionImpl<StdDevHelper> {
1396 unsigned int fNSlots;
1397 std::shared_ptr<double> fResultStdDev;
1399 std::vector<ULong64_t> fCounts;
1401 std::vector<double> fMeans;
1403 std::vector<double> fDistancesfromMean;
1406 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1407 StdDevHelper(StdDevHelper &&) =
default;
1408 StdDevHelper(
const StdDevHelper &) =
delete;
1409 void InitTask(TTreeReader *,
unsigned int) {}
1410 void Exec(
unsigned int slot,
double v);
1412 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1413 void Exec(
unsigned int slot,
const T &vs)
1415 for (
auto &&
v : vs) {
1427 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1429 std::inner_product(fMeans.begin(), fMeans.end(), fCounts.begin(), 0.) /
static_cast<Double_t>(counts);
1430 return std::make_unique<RMergeableStdDev>(*fResultStdDev, counts, mean);
1433 std::string GetActionName() {
return "StdDev"; }
1435 StdDevHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1437 auto &result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1438 return StdDevHelper(result, fCounts.size());
1442template <
typename PrevNodeType>
1443class R__CLING_PTRCHECK(off) DisplayHelper :
public RActionImpl<DisplayHelper<PrevNodeType>> {
1446 std::shared_ptr<Display_t> fDisplayerHelper;
1447 std::shared_ptr<PrevNodeType> fPrevNode;
1448 size_t fEntriesToProcess;
1451 DisplayHelper(
size_t nRows,
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
1452 : fDisplayerHelper(
d), fPrevNode(prevNode), fEntriesToProcess(nRows)
1455 DisplayHelper(DisplayHelper &&) =
default;
1456 DisplayHelper(
const DisplayHelper &) =
delete;
1457 void InitTask(TTreeReader *,
unsigned int) {}
1459 template <
typename...
Columns>
1460 void Exec(
unsigned int, Columns &... columns)
1462 if (fEntriesToProcess == 0)
1465 fDisplayerHelper->AddRow(columns...);
1466 --fEntriesToProcess;
1468 if (fEntriesToProcess == 0) {
1473 fPrevNode->StopProcessing();
1481 std::string GetActionName() {
return "Display"; }
1484template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1485 bool MustCopyAssign = std::is_same<R, U>::value>
1486class R__CLING_PTRCHECK(off) AggregateHelper
1487 :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1490 std::shared_ptr<U> fResult;
1491 Results<U> fAggregators;
1494 using ColumnTypes_t = TypeList<T>;
1496 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1497 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(result), fAggregators(nSlots, *result)
1501 AggregateHelper(Acc &
f, Merge &
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1502 : fAggregate(
f), fMerge(
m), fResult(result), fAggregators(nSlots, *result)
1506 AggregateHelper(AggregateHelper &&) =
default;
1507 AggregateHelper(
const AggregateHelper &) =
delete;
1509 void InitTask(TTreeReader *,
unsigned int) {}
1511 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<MustCopyAssign_,
int> = 0>
1512 void Exec(
unsigned int slot,
const T &value)
1514 fAggregators[slot] = fAggregate(fAggregators[slot], value);
1517 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<!MustCopyAssign_,
int> = 0>
1518 void Exec(
unsigned int slot,
const T &value)
1520 fAggregate(fAggregators[slot], value);
1525 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1526 bool MergeAll = std::is_same<void, MergeRet>::value>
1527 std::enable_if_t<MergeAll, void> Finalize()
1529 fMerge(fAggregators);
1530 *fResult = fAggregators[0];
1533 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1534 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1535 std::enable_if_t<MergeTwoByTwo, void> Finalize(...)
1537 for (
const auto &acc : fAggregators)
1538 *fResult = fMerge(*fResult, acc);
1541 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1543 std::string GetActionName() {
return "Aggregate"; }
1545 AggregateHelper MakeNew(
void *newResult, std::string_view =
"nominal")
1547 auto &result = *
static_cast<std::shared_ptr<U> *
>(newResult);
1548 return AggregateHelper(fAggregate, fMerge, result, fAggregators.size());
Handle_t Display_t
Display handle.
#define R(a, b, c, d, e, f, g, h, i)
TClass * IsA() const override
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.
Binding & operator=(OUT(*fun)(void))
TTime operator*(const TTime &t1, const TTime &t2)
iterator begin() noexcept
Collection abstract base class.
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)
void(off) SmallVectorTemplateBase< T
ROOT::VecOps::RVec< T > RVec
auto FillThreadSafe(T &histo, Args... args) -> decltype(histo.FillThreadSafe(args...), void())
Entrypoint for thread-safe filling from RDataFrame.
__device__ AFloat max(AFloat x, AFloat y)
void Initialize(Bool_t useTMVAStyle=kTRUE)
static uint64_t sum(uint64_t i)