19#ifndef ROOT_RDFOPERATIONS
20#define ROOT_RDFOPERATIONS
75 std::vector<TBranch *> fBranches;
76 std::vector<std::string> fNames;
81 auto it = std::find(fNames.begin(), fNames.end(),
name);
82 if (it == fNames.end())
84 return fBranches[std::distance(fNames.begin(), it)];
87 void Insert(
const std::string &
name,
TBranch *address)
89 if (address ==
nullptr) {
90 throw std::logic_error(
"Trying to insert a null branch address.");
92 if (std::find(fBranches.begin(), fBranches.end(), address) != fBranches.end()) {
93 throw std::logic_error(
"Trying to insert a branch address that's already present.");
95 if (std::find(fNames.begin(), fNames.end(),
name) != fNames.end()) {
96 throw std::logic_error(
"Trying to insert a branch name that's already present.");
98 fNames.emplace_back(
name);
99 fBranches.emplace_back(address);
108 void AssertNoNullBranchAddresses()
110 std::vector<TBranch *> branchesWithNullAddress;
111 std::copy_if(fBranches.begin(), fBranches.end(), std::back_inserter(branchesWithNullAddress),
112 [](
TBranch *
b) { return b->GetAddress() == nullptr; });
114 if (branchesWithNullAddress.empty())
118 std::vector<std::string> missingBranchNames;
119 std::transform(branchesWithNullAddress.begin(), branchesWithNullAddress.end(),
120 std::back_inserter(missingBranchNames), [](
TBranch *
b) { return b->GetName(); });
121 std::string msg =
"RDataFrame::Snapshot:";
122 if (missingBranchNames.size() == 1) {
123 msg +=
" branch " + missingBranchNames[0] +
124 " is needed as it provides the size for one or more branches containing dynamically sized arrays, but "
128 for (
const auto &bName : missingBranchNames)
130 msg.resize(msg.size() - 2);
132 " are needed as they provide the size of other branches containing dynamically sized arrays, but they are";
134 msg +=
" not part of the set of branches that are being written out.";
135 throw std::runtime_error(msg);
144using Results = std::conditional_t<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>;
147class R__CLING_PTRCHECK(off) ForeachSlotHelper :
public RActionImpl<ForeachSlotHelper<F>> {
153 ForeachSlotHelper(ForeachSlotHelper &&) =
default;
154 ForeachSlotHelper(
const ForeachSlotHelper &) =
delete;
158 template <
typename... Args>
159 void Exec(
unsigned int slot, Args &&... args)
162 static_assert(std::is_same<TypeList<std::decay_t<Args>...>, ColumnTypes_t>
::value,
"");
163 fCallable(slot, std::forward<Args>(args)...);
170 std::string GetActionName() {
return "ForeachSlot"; }
173class R__CLING_PTRCHECK(off) CountHelper :
public RActionImpl<CountHelper> {
174 std::shared_ptr<ULong64_t> fResultCount;
175 Results<ULong64_t> fCounts;
179 CountHelper(
const std::shared_ptr<ULong64_t> &resultCount,
const unsigned int nSlots);
180 CountHelper(CountHelper &&) =
default;
181 CountHelper(
const CountHelper &) =
delete;
183 void Exec(
unsigned int slot);
190 return std::make_unique<RMergeableCount>(*fResultCount);
193 ULong64_t &PartialUpdate(
unsigned int slot);
195 std::string GetActionName() {
return "Count"; }
197 CountHelper MakeNew(
void *newResult)
199 auto &
result = *
static_cast<std::shared_ptr<ULong64_t> *
>(newResult);
200 return CountHelper(
result, fCounts.size());
204template <
typename RNode_t>
205class R__CLING_PTRCHECK(off) ReportHelper :
public RActionImpl<ReportHelper<RNode_t>> {
206 std::shared_ptr<RCutFlowReport> fReport;
210 bool fReturnEmptyReport;
214 ReportHelper(
const std::shared_ptr<RCutFlowReport> &report, RNode_t *node,
bool emptyRep)
215 : fReport(report), fNode(node), fReturnEmptyReport(emptyRep){};
216 ReportHelper(ReportHelper &&) =
default;
217 ReportHelper(
const ReportHelper &) =
delete;
219 void Exec(
unsigned int ) {}
223 if (!fReturnEmptyReport)
224 fNode->Report(*fReport);
227 std::string GetActionName() {
return "Report"; }
239class R__CLING_PTRCHECK(off) BufferedFillHelper :
public RActionImpl<BufferedFillHelper> {
241 static constexpr unsigned int fgTotalBufSize = 2097152;
243 using Buf_t = std::vector<BufEl_t>;
245 std::vector<Buf_t> fBuffers;
246 std::vector<Buf_t> fWBuffers;
247 std::shared_ptr<Hist_t> fResultHist;
248 unsigned int fNSlots;
249 unsigned int fBufSize;
251 Results<std::unique_ptr<Hist_t>> fPartialHists;
255 void UpdateMinMax(
unsigned int slot,
double v);
258 BufferedFillHelper(
const std::shared_ptr<Hist_t> &
h,
const unsigned int nSlots);
259 BufferedFillHelper(BufferedFillHelper &&) =
default;
260 BufferedFillHelper(
const BufferedFillHelper &) =
delete;
262 void Exec(
unsigned int slot,
double v);
263 void Exec(
unsigned int slot,
double v,
double w);
265 template <typename T, std::enable_if_t<IsDataContainer<T>::value || std::is_same<T, std::string>::value,
int> = 0>
266 void Exec(
unsigned int slot,
const T &vs)
268 auto &thisBuf = fBuffers[slot];
270 for (
auto v = vs.begin();
v != vs.end(); ++
v) {
271 UpdateMinMax(slot, *
v);
272 thisBuf.emplace_back(*
v);
276 template <typename T, typename W, std::enable_if_t<IsDataContainer<T>::value && IsDataContainer<W>::value,
int> = 0>
277 void Exec(
unsigned int slot,
const T &vs,
const W &ws)
279 auto &thisBuf = fBuffers[slot];
282 UpdateMinMax(slot,
v);
283 thisBuf.emplace_back(
v);
286 auto &thisWBuf = fWBuffers[slot];
288 thisWBuf.emplace_back(
w);
292 template <typename T, typename W, std::enable_if_t<IsDataContainer<T>::value && !IsDataContainer<W>::value,
int> = 0>
293 void Exec(
unsigned int slot,
const T &vs,
const W
w)
295 auto &thisBuf = fBuffers[slot];
297 UpdateMinMax(slot,
v);
298 thisBuf.emplace_back(
v);
301 auto &thisWBuf = fWBuffers[slot];
302 thisWBuf.insert(thisWBuf.end(), vs.size(),
w);
305 template <typename T, typename W, std::enable_if_t<IsDataContainer<W>::value && !IsDataContainer<T>::value,
int> = 0>
306 void Exec(
unsigned int slot,
const T
v,
const W &ws)
308 UpdateMinMax(slot,
v);
309 auto &thisBuf = fBuffers[slot];
310 thisBuf.insert(thisBuf.end(), ws.size(),
v);
312 auto &thisWBuf = fWBuffers[slot];
313 thisWBuf.insert(thisWBuf.end(), ws.begin(), ws.end());
316 Hist_t &PartialUpdate(
unsigned int);
325 return std::make_unique<RMergeableFill<Hist_t>>(*fResultHist);
328 std::string GetActionName()
330 return std::string(fResultHist->IsA()->GetName()) +
"\\n" + std::string(fResultHist->GetName());
333 BufferedFillHelper MakeNew(
void *newResult)
335 auto &
result = *
static_cast<std::shared_ptr<Hist_t> *
>(newResult);
337 result->SetDirectory(
nullptr);
338 return BufferedFillHelper(
result, fNSlots);
342extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<float> &);
343extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<double> &);
344extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<char> &);
345extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<int> &);
346extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
347extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<float> &,
const std::vector<float> &);
348extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<double> &,
const std::vector<double> &);
349extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<char> &,
const std::vector<char> &);
350extern template void BufferedFillHelper::Exec(
unsigned int,
const std::vector<int> &,
const std::vector<int> &);
352BufferedFillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &,
const std::vector<unsigned int> &);
356template <
typename HIST = Hist_t>
358 std::vector<HIST *> fObjects;
360 template <typename H = HIST, typename = decltype(std::declval<H>().Reset())>
361 void ResetIfPossible(
H *
h)
369 void ResetIfPossible(...)
371 throw std::runtime_error(
372 "A systematic variation was requested for a custom Fill action, but the type of the object to be filled does "
373 "not implement a Reset method, so we cannot safely re-initialize variations of the result. Aborting.");
376 void UnsetDirectoryIfPossible(
TH1 *
h) {
377 h->SetDirectory(
nullptr);
380 void UnsetDirectoryIfPossible(...) {}
383 template <typename H, typename = std::enable_if_t<std::is_base_of<TObject, H>::value,
int>>
384 auto Merge(std::vector<H *> &objs,
int )
388 for (
auto it = ++objs.begin(); it != objs.end(); ++it)
394 template <
typename H>
395 auto Merge(std::vector<H *> &objs,
double )
396 ->
decltype(objs[0]->Merge(std::vector<HIST *>{}),
void())
398 objs[0]->Merge({++objs.begin(), objs.end()});
402 template <
typename T>
405 static_assert(
sizeof(
T) < 0,
406 "The type passed to Fill does not provide a Merge(TCollection*) or Merge(const std::vector&) method.");
410 template <
typename T>
411 class ScalarConstIterator {
415 ScalarConstIterator(
const T *obj) : obj_(obj) {}
417 ScalarConstIterator<T> &operator++() {
return *
this; }
425 template <typename T, std::enable_if_t<!IsDataContainer<T>::value,
int> = 0>
426 ScalarConstIterator<T> MakeBegin(
const T &val)
428 return ScalarConstIterator<T>(&val);
432 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
433 auto MakeBegin(
const T &val)
435 return std::begin(val);
439 template <typename T, std::enable_if_t<!IsDataContainer<T>::value,
int> = 0>
440 std::size_t GetSize(
const T &)
446 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
447 std::size_t GetSize(
const T &val)
449#if __cplusplus >= 201703L
450 return std::size(val);
456 template <std::size_t ColIdx,
typename End_t,
typename... Its>
457 void ExecLoop(
unsigned int slot, End_t end, Its... its)
459 auto *thisSlotH = fObjects[slot];
462 auto nop = [](
auto &&...) {};
463 for (; GetNthElement<ColIdx>(its...) != end; nop(++its...)) {
464 thisSlotH->Fill(*its...);
469 FillHelper(FillHelper &&) =
default;
470 FillHelper(
const FillHelper &) =
delete;
472 FillHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots) : fObjects(nSlots, nullptr)
474 fObjects[0] =
h.get();
476 for (
unsigned int i = 1; i < nSlots; ++i) {
477 fObjects[i] =
new HIST(*fObjects[0]);
478 UnsetDirectoryIfPossible(fObjects[i]);
485 template <
typename... ValTypes, std::enable_if_t<!Disjunction<IsDataContainer<ValTypes>...>
::value,
int> = 0>
486 auto Exec(
unsigned int slot,
const ValTypes &...
x) ->
decltype(fObjects[slot]->Fill(
x...),
void())
488 fObjects[slot]->Fill(
x...);
492 template <
typename... Xs, std::enable_if_t<Disjunction<IsDataContainer<Xs>...>
::value,
int> = 0>
493 auto Exec(
unsigned int slot,
const Xs &...xs) ->
decltype(fObjects[slot]->Fill(*MakeBegin(xs)...),
void())
496 constexpr std::array<
bool,
sizeof...(Xs)> isContainer{IsDataContainer<Xs>::value...};
499 constexpr std::size_t colidx =
FindIdxTrue(isContainer);
501 static_assert(colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
504 auto const xrefend = std::end(GetNthElement<colidx>(xs...));
507 std::array<std::size_t,
sizeof...(xs)> sizes = {{GetSize(xs)...}};
509 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
510 if (isContainer[i] && sizes[i] != sizes[colidx]) {
511 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
515 ExecLoop<colidx>(slot, xrefend, MakeBegin(xs)...);
518 template <
typename T = HIST>
521 static_assert(
sizeof(
T) < 0,
522 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
523 "columns passed did not match the signature of the object's `Fill` method.");
530 if (fObjects.size() == 1)
536 for (
auto it = ++fObjects.begin(); it != fObjects.end(); ++it)
540 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[slot]; }
545 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
549 template <typename T = HIST, std::enable_if_t<std::is_base_of<TObject, T>::value,
int> = 0>
550 std::string GetActionName()
552 return std::string(fObjects[0]->
IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
556 template <typename T = HIST, std::enable_if_t<!std::is_base_of<TObject, T>::value,
int> = 0>
557 std::string GetActionName()
559 return "Fill custom object";
562 template <
typename H = HIST>
563 FillHelper MakeNew(
void *newResult)
565 auto &
result = *
static_cast<std::shared_ptr<H> *
>(newResult);
566 ResetIfPossible(
result.get());
567 UnsetDirectoryIfPossible(
result.get());
568 return FillHelper(
result, fObjects.size());
577 std::vector<::TGraph *> fGraphs;
580 FillTGraphHelper(FillTGraphHelper &&) =
default;
581 FillTGraphHelper(
const FillTGraphHelper &) =
delete;
583 FillTGraphHelper(
const std::shared_ptr<::TGraph> &
g,
const unsigned int nSlots) : fGraphs(nSlots, nullptr)
585 fGraphs[0] =
g.get();
587 for (
unsigned int i = 1; i < nSlots; ++i) {
588 fGraphs[i] =
new TGraph(*fGraphs[0]);
596 template <
typename X0,
typename X1,
597 std::enable_if_t<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int> = 0>
598 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
600 if (x0s.size() != x1s.size()) {
601 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
603 auto *thisSlotG = fGraphs[slot];
604 auto x0sIt = std::begin(x0s);
605 const auto x0sEnd = std::end(x0s);
606 auto x1sIt = std::begin(x1s);
607 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
608 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
613 template <
typename X0,
typename X1,
614 std::enable_if_t<!IsDataContainer<X0>::value && !IsDataContainer<X1>::value,
int> = 0>
615 void Exec(
unsigned int slot, X0 x0, X1
x1)
617 auto thisSlotG = fGraphs[slot];
618 thisSlotG->SetPoint(thisSlotG->GetN(), x0,
x1);
623 template <
typename X0,
typename X1,
typename... ExtraArgsToLowerPriority>
624 void Exec(
unsigned int, X0, X1, ExtraArgsToLowerPriority...)
626 throw std::runtime_error(
"Graph was applied to a mix of scalar values and collections. This is not supported.");
631 const auto nSlots = fGraphs.size();
632 auto resGraph = fGraphs[0];
635 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
636 l.Add(fGraphs[slot]);
644 return std::make_unique<RMergeableFill<Result_t>>(*fGraphs[0]);
647 std::string GetActionName() {
return "Graph"; }
649 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
651 FillTGraphHelper MakeNew(
void *newResult)
653 auto &
result = *
static_cast<std::shared_ptr<TGraph> *
>(newResult);
655 return FillTGraphHelper(
result, fGraphs.size());
659class R__CLING_PTRCHECK(off) FillTGraphAsymmErrorsHelper
665 std::vector<::TGraphAsymmErrors *> fGraphAsymmErrors;
668 FillTGraphAsymmErrorsHelper(FillTGraphAsymmErrorsHelper &&) =
default;
669 FillTGraphAsymmErrorsHelper(
const FillTGraphAsymmErrorsHelper &) =
delete;
671 FillTGraphAsymmErrorsHelper(
const std::shared_ptr<::TGraphAsymmErrors> &
g,
const unsigned int nSlots)
672 : fGraphAsymmErrors(nSlots, nullptr)
674 fGraphAsymmErrors[0] =
g.get();
676 for (
unsigned int i = 1; i < nSlots; ++i) {
686 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
687 std::enable_if_t<IsDataContainer<X>::value && IsDataContainer<Y>::value && IsDataContainer<EXL>::value &&
688 IsDataContainer<EXH>::value && IsDataContainer<EYL>::value && IsDataContainer<EYH>::value,
691 Exec(
unsigned int slot,
const X &xs,
const Y &ys,
const EXL &exls,
const EXH &exhs,
const EYL &eyls,
const EYH &eyhs)
693 if ((xs.size() != ys.size()) || (xs.size() != exls.size()) || (xs.size() != exhs.size()) ||
694 (xs.size() != eyls.size()) || (xs.size() != eyhs.size())) {
695 throw std::runtime_error(
"Cannot fill GraphAsymmErrors with values in containers of different sizes.");
697 auto *thisSlotG = fGraphAsymmErrors[slot];
698 auto xsIt = std::begin(xs);
699 auto ysIt = std::begin(ys);
700 auto exlsIt = std::begin(exls);
701 auto exhsIt = std::begin(exhs);
702 auto eylsIt = std::begin(eyls);
703 auto eyhsIt = std::begin(eyhs);
704 while (xsIt != std::end(xs)) {
705 const auto n = thisSlotG->GetN();
706 thisSlotG->SetPoint(
n, *xsIt++, *ysIt++);
707 thisSlotG->SetPointError(
n, *exlsIt++, *exhsIt++, *eylsIt++, *eyhsIt++);
713 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
714 std::enable_if_t<!IsDataContainer<X>::value && !IsDataContainer<Y>::value && !IsDataContainer<EXL>::value &&
715 !IsDataContainer<EXH>::value && !IsDataContainer<EYL>::value && !IsDataContainer<EYH>::value,
717 void Exec(
unsigned int slot, X
x, Y
y, EXL exl, EXH exh, EYL eyl, EYH eyh)
719 auto thisSlotG = fGraphAsymmErrors[slot];
720 const auto n = thisSlotG->GetN();
721 thisSlotG->SetPoint(
n,
x,
y);
722 thisSlotG->SetPointError(
n, exl, exh, eyl, eyh);
727 template <
typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
728 typename... ExtraArgsToLowerPriority>
729 void Exec(
unsigned int, X, Y, EXL, EXH, EYL, EYH, ExtraArgsToLowerPriority...)
731 throw std::runtime_error(
732 "GraphAsymmErrors was applied to a mix of scalar values and collections. This is not supported.");
737 const auto nSlots = fGraphAsymmErrors.size();
738 auto resGraphAsymmErrors = fGraphAsymmErrors[0];
741 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
742 l.Add(fGraphAsymmErrors[slot]);
744 resGraphAsymmErrors->Merge(&
l);
750 return std::make_unique<RMergeableFill<Result_t>>(*fGraphAsymmErrors[0]);
753 std::string GetActionName() {
return "GraphAsymmErrors"; }
755 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphAsymmErrors[slot]; }
757 FillTGraphAsymmErrorsHelper MakeNew(
void *newResult)
759 auto &
result = *
static_cast<std::shared_ptr<TGraphAsymmErrors> *
>(newResult);
761 return FillTGraphAsymmErrorsHelper(
result, fGraphAsymmErrors.size());
771template <
typename V,
typename COLL>
772void FillColl(V&&
v, COLL&
c) {
777template <
typename COLL>
778void FillColl(
bool v, COLL&
c) {
784template <
typename RealT_t,
typename T,
typename COLL>
785class R__CLING_PTRCHECK(off) TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
786 Results<std::shared_ptr<COLL>> fColls;
790 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
792 fColls.emplace_back(resultColl);
793 for (
unsigned int i = 1; i < nSlots; ++i)
794 fColls.emplace_back(std::make_shared<COLL>());
796 TakeHelper(TakeHelper &&);
797 TakeHelper(
const TakeHelper &) =
delete;
801 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
807 auto rColl = fColls[0];
808 for (
unsigned int i = 1; i < fColls.size(); ++i) {
809 const auto &coll = fColls[i];
810 const auto end = coll->end();
813 for (
auto j = coll->begin(); j != end; j++) {
814 FillColl(*j, *rColl);
819 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
821 std::string GetActionName() {
return "Take"; }
823 TakeHelper MakeNew(
void *newResult)
825 auto &
result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
827 return TakeHelper(
result, fColls.size());
833template <
typename RealT_t,
typename T>
834class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
T, std::vector<T>>
835 :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
836 Results<std::shared_ptr<std::vector<T>>> fColls;
840 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
842 fColls.emplace_back(resultColl);
843 for (
unsigned int i = 1; i < nSlots; ++i) {
844 auto v = std::make_shared<std::vector<T>>();
846 fColls.emplace_back(
v);
849 TakeHelper(TakeHelper &&);
850 TakeHelper(
const TakeHelper &) =
delete;
854 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
862 for (
auto &coll : fColls)
863 totSize += coll->
size();
864 auto rColl = fColls[0];
865 rColl->reserve(totSize);
866 for (
unsigned int i = 1; i < fColls.size(); ++i) {
867 auto &coll = fColls[i];
868 rColl->insert(rColl->end(), coll->begin(), coll->end());
872 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
874 std::string GetActionName() {
return "Take"; }
876 TakeHelper MakeNew(
void *newResult)
878 auto &
result = *
static_cast<std::shared_ptr<std::vector<T>
> *>(newResult);
880 return TakeHelper(
result, fColls.size());
886template <
typename RealT_t,
typename COLL>
887class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, COLL>
888 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
889 Results<std::shared_ptr<COLL>> fColls;
893 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
895 fColls.emplace_back(resultColl);
896 for (
unsigned int i = 1; i < nSlots; ++i)
897 fColls.emplace_back(std::make_shared<COLL>());
899 TakeHelper(TakeHelper &&);
900 TakeHelper(
const TakeHelper &) =
delete;
910 auto rColl = fColls[0];
911 for (
unsigned int i = 1; i < fColls.size(); ++i) {
912 auto &coll = fColls[i];
913 for (
auto &
v : *coll) {
914 rColl->emplace_back(
v);
919 std::string GetActionName() {
return "Take"; }
921 TakeHelper MakeNew(
void *newResult)
923 auto &
result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
925 return TakeHelper(
result, fColls.size());
931template <
typename RealT_t>
932class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>>
933 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
935 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
939 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
941 fColls.emplace_back(resultColl);
942 for (
unsigned int i = 1; i < nSlots; ++i) {
943 auto v = std::make_shared<std::vector<RealT_t>>();
945 fColls.emplace_back(
v);
948 TakeHelper(TakeHelper &&);
949 TakeHelper(
const TakeHelper &) =
delete;
961 for (
auto &coll : fColls)
962 totSize += coll->
size();
963 auto rColl = fColls[0];
964 rColl->reserve(totSize);
965 for (
unsigned int i = 1; i < fColls.size(); ++i) {
966 auto &coll = fColls[i];
967 rColl->insert(rColl->end(), coll->begin(), coll->end());
971 std::string GetActionName() {
return "Take"; }
973 TakeHelper MakeNew(
void *newResult)
975 auto &
result = *
static_cast<typename decltype(fColls)::value_type *
>(newResult);
977 return TakeHelper(
result, fColls.size());
984template <
typename RealT_t,
typename T,
typename COLL>
985TakeHelper<RealT_t, T, COLL>::TakeHelper(TakeHelper<RealT_t, T, COLL> &&) =
default;
986template <
typename RealT_t,
typename T>
987TakeHelper<RealT_t, T, std::vector<T>>::TakeHelper(TakeHelper<RealT_t, T, std::vector<T>> &&) =
default;
988template <
typename RealT_t,
typename COLL>
989TakeHelper<RealT_t, RVec<RealT_t>, COLL>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, COLL> &&) =
default;
990template <
typename RealT_t>
991TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>> &&) =
default;
995extern template class TakeHelper<bool, bool, std::vector<bool>>;
996extern template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
997extern template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
998extern template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
999extern template class TakeHelper<int, int, std::vector<int>>;
1000extern template class TakeHelper<long, long, std::vector<long>>;
1001extern template class TakeHelper<long long, long long, std::vector<long long>>;
1002extern template class TakeHelper<float, float, std::vector<float>>;
1003extern template class TakeHelper<double, double, std::vector<double>>;
1006template <
typename ResultType>
1007class R__CLING_PTRCHECK(off) MinHelper :
public RActionImpl<MinHelper<ResultType>> {
1008 std::shared_ptr<ResultType> fResultMin;
1009 Results<ResultType> fMins;
1012 MinHelper(MinHelper &&) =
default;
1013 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
1014 : fResultMin(minVPtr), fMins(nSlots, std::numeric_limits<ResultType>::max())
1018 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
1022 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1023 void Exec(
unsigned int slot,
const T &vs)
1026 fMins[slot] = std::min(static_cast<ResultType>(
v), fMins[slot]);
1033 *fResultMin = std::numeric_limits<ResultType>::max();
1034 for (
auto &
m : fMins)
1035 *fResultMin = std::min(
m, *fResultMin);
1041 return std::make_unique<RMergeableMin<ResultType>>(*fResultMin);
1044 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
1046 std::string GetActionName() {
return "Min"; }
1048 MinHelper MakeNew(
void *newResult)
1050 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1051 return MinHelper(
result, fMins.size());
1062template <
typename ResultType>
1063class R__CLING_PTRCHECK(off) MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
1064 std::shared_ptr<ResultType> fResultMax;
1065 Results<ResultType> fMaxs;
1068 MaxHelper(MaxHelper &&) =
default;
1069 MaxHelper(
const MaxHelper &) =
delete;
1070 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
1071 : fResultMax(maxVPtr), fMaxs(nSlots, std::numeric_limits<ResultType>::lowest())
1076 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
1078 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1079 void Exec(
unsigned int slot,
const T &vs)
1082 fMaxs[slot] = std::max(static_cast<ResultType>(
v), fMaxs[slot]);
1089 *fResultMax = std::numeric_limits<ResultType>::lowest();
1090 for (
auto &
m : fMaxs) {
1091 *fResultMax = std::max(
m, *fResultMax);
1098 return std::make_unique<RMergeableMax<ResultType>>(*fResultMax);
1101 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
1103 std::string GetActionName() {
return "Max"; }
1105 MaxHelper MakeNew(
void *newResult)
1107 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1108 return MaxHelper(
result, fMaxs.size());
1119template <
typename ResultType>
1120class R__CLING_PTRCHECK(off) SumHelper :
public RActionImpl<SumHelper<ResultType>> {
1121 std::shared_ptr<ResultType> fResultSum;
1122 Results<ResultType> fSums;
1123 Results<ResultType> fCompensations;
1128 template <
typename T = ResultType>
1129 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
1134 template <
typename T = ResultType,
typename Dummy =
int>
1135 ResultType NeutralElement(
const T &, Dummy)
1137 return ResultType{};
1141 SumHelper(SumHelper &&) =
default;
1142 SumHelper(
const SumHelper &) =
delete;
1143 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
1144 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1)),
1145 fCompensations(nSlots, NeutralElement(*sumVPtr, -1))
1150 void Exec(
unsigned int slot, ResultType
x)
1153 ResultType
y =
x - fCompensations[slot];
1154 ResultType t = fSums[slot] +
y;
1155 fCompensations[slot] = (t - fSums[slot]) -
y;
1159 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1160 void Exec(
unsigned int slot,
const T &vs)
1162 for (
auto &&
v : vs) {
1171 ResultType
sum(NeutralElement(ResultType{}, -1));
1172 ResultType compensation(NeutralElement(ResultType{}, -1));
1173 ResultType
y(NeutralElement(ResultType{}, -1));
1174 ResultType t(NeutralElement(ResultType{}, -1));
1175 for (
auto &
m : fSums) {
1177 y =
m - compensation;
1179 compensation = (t -
sum) -
y;
1188 return std::make_unique<RMergeableSum<ResultType>>(*fResultSum);
1191 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
1193 std::string GetActionName() {
return "Sum"; }
1195 SumHelper MakeNew(
void *newResult)
1197 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1199 return SumHelper(
result, fSums.size());
1203class R__CLING_PTRCHECK(off) MeanHelper :
public RActionImpl<MeanHelper> {
1204 std::shared_ptr<double> fResultMean;
1205 std::vector<ULong64_t> fCounts;
1206 std::vector<double> fSums;
1207 std::vector<double> fPartialMeans;
1208 std::vector<double> fCompensations;
1211 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1212 MeanHelper(MeanHelper &&) =
default;
1213 MeanHelper(
const MeanHelper &) =
delete;
1215 void Exec(
unsigned int slot,
double v);
1217 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1218 void Exec(
unsigned int slot,
const T &vs)
1220 for (
auto &&
v : vs) {
1224 double y =
v - fCompensations[slot];
1225 double t = fSums[slot] +
y;
1226 fCompensations[slot] = (t - fSums[slot]) -
y;
1238 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1239 return std::make_unique<RMergeableMean>(*fResultMean, counts);
1242 double &PartialUpdate(
unsigned int slot);
1244 std::string GetActionName() {
return "Mean"; }
1246 MeanHelper MakeNew(
void *newResult)
1248 auto &
result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1249 return MeanHelper(
result, fSums.size());
1253extern template void MeanHelper::Exec(
unsigned int,
const std::vector<float> &);
1254extern template void MeanHelper::Exec(
unsigned int,
const std::vector<double> &);
1255extern template void MeanHelper::Exec(
unsigned int,
const std::vector<char> &);
1256extern template void MeanHelper::Exec(
unsigned int,
const std::vector<int> &);
1257extern template void MeanHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
1261 unsigned int fNSlots;
1262 std::shared_ptr<double> fResultStdDev;
1264 std::vector<ULong64_t> fCounts;
1266 std::vector<double> fMeans;
1268 std::vector<double> fDistancesfromMean;
1271 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1272 StdDevHelper(StdDevHelper &&) =
default;
1273 StdDevHelper(
const StdDevHelper &) =
delete;
1275 void Exec(
unsigned int slot,
double v);
1277 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1278 void Exec(
unsigned int slot,
const T &vs)
1280 for (
auto &&
v : vs) {
1292 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1294 std::inner_product(fMeans.begin(), fMeans.end(), fCounts.begin(), 0.) /
static_cast<Double_t>(counts);
1295 return std::make_unique<RMergeableStdDev>(*fResultStdDev, counts, mean);
1298 std::string GetActionName() {
return "StdDev"; }
1300 StdDevHelper MakeNew(
void *newResult)
1302 auto &
result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1303 return StdDevHelper(
result, fCounts.size());
1307extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<float> &);
1308extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<double> &);
1309extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<char> &);
1310extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<int> &);
1311extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
1313template <
typename PrevNodeType>
1317 std::shared_ptr<Display_t> fDisplayerHelper;
1318 std::shared_ptr<PrevNodeType> fPrevNode;
1319 size_t fEntriesToProcess;
1322 DisplayHelper(
size_t nRows,
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
1323 : fDisplayerHelper(
d), fPrevNode(prevNode), fEntriesToProcess(nRows)
1326 DisplayHelper(DisplayHelper &&) =
default;
1327 DisplayHelper(
const DisplayHelper &) =
delete;
1330 template <
typename...
Columns>
1331 void Exec(
unsigned int, Columns &... columns)
1333 if (fEntriesToProcess == 0)
1336 fDisplayerHelper->AddRow(columns...);
1337 --fEntriesToProcess;
1339 if (fEntriesToProcess == 0) {
1344 fPrevNode->StopProcessing();
1352 std::string GetActionName() {
return "Display"; }
1355template <
typename T>
1361template <
typename T>
1367template <
typename T>
1368void SetBranchesHelper(
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
const std::string &
name,
1369 TBranch *&branch,
void *&branchAddress, T *address, RBranchSet &outputBranches,
1372 static TClassRef TBOClRef(
"TBranchObject");
1374 TBranch *inputBranch =
nullptr;
1376 inputBranch = inputTree->
GetBranch(inName.c_str());
1378 inputBranch = inputTree->
FindBranch(inName.c_str());
1381 auto *outputBranch = outputBranches.Get(
name);
1384 if (inputBranch && inputBranch->
IsA() == TBOClRef) {
1385 outputBranch->SetAddress(
reinterpret_cast<T **
>(inputBranch->
GetAddress()));
1387 branchAddress = address;
1388 outputBranch->SetAddress(&branchAddress);
1390 outputBranch->SetAddress(address);
1391 branchAddress = address;
1404 if (inputBranch->
IsA() == TBOClRef) {
1407 outputTree.
Branch(
name.c_str(),
reinterpret_cast<T **
>(inputBranch->
GetAddress()), bufSize, splitLevel);
1409 outputBranch = outputTree.
Branch(
name.c_str(), address, bufSize, splitLevel);
1412 outputBranch = outputTree.
Branch(
name.c_str(), address);
1414 outputBranches.Insert(
name, outputBranch);
1417 branchAddress =
nullptr;
1430template <
typename T>
1431void SetBranchesHelper(
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
const std::string &outName,
1432 TBranch *&branch,
void *&branchAddress,
RVec<T> *ab, RBranchSet &outputBranches,
bool isDefine)
1434 TBranch *inputBranch =
nullptr;
1436 inputBranch = inputTree->
GetBranch(inName.c_str());
1438 inputBranch = inputTree->
FindBranch(inName.c_str());
1440 auto *outputBranch = outputBranches.Get(outName);
1443 bool mustWriteRVec = (inputBranch ==
nullptr || isDefine);
1445 if (!mustWriteRVec && std::string_view(inputBranch->
GetClassName()) ==
"TClonesArray") {
1446 mustWriteRVec =
true;
1448 "Branch \"%s\" contains TClonesArrays but the type specified to Snapshot was RVec<T>. The branch will "
1449 "be written out as a RVec instead of a TClonesArray. Specify that the type of the branch is "
1450 "TClonesArray as a Snapshot template parameter to write out a TClonesArray instead.",
1454 if (!mustWriteRVec) {
1457 mustWriteRVec =
true;
1460 if (mustWriteRVec) {
1467 outputBranch->SetObject(ab);
1469 auto *
b = outputTree.
Branch(outName.c_str(), ab);
1470 outputBranches.Insert(outName,
b);
1476 auto dataPtr = ab->
data();
1480 branchAddress = dataPtr;
1481 outputBranch->SetAddress(&branchAddress);
1483 outputBranch->SetAddress(dataPtr);
1488 const auto bname = leaf->
GetName();
1489 auto *sizeLeaf = leaf->GetLeafCount();
1490 const auto sizeLeafName = sizeLeaf ? std::string(sizeLeaf->GetName()) : std::to_string(leaf->GetLenStatic());
1492 if (sizeLeaf && !outputBranches.Get(sizeLeafName)) {
1497 const auto sizeBufSize = sizeLeaf->GetBranch()->GetBasketSize();
1499 auto *sizeBranch = outputTree.
Branch(sizeLeafName.c_str(), (
void *)
nullptr,
1500 (sizeLeafName +
'/' + sizeTypeStr).c_str(), sizeBufSize);
1501 outputBranches.Insert(sizeLeafName, sizeBranch);
1504 const auto btype = leaf->GetTypeName();
1506 if (rootbtype ==
' ') {
1508 "RDataFrame::Snapshot: could not correctly construct a leaflist for C-style array in column %s. This "
1509 "column will not be written out.",
1512 const auto leaflist = std::string(bname) +
"[" + sizeLeafName +
"]/" + rootbtype;
1513 outputBranch = outputTree.
Branch(outName.c_str(), dataPtr, leaflist.c_str());
1515 outputBranches.Insert(outName, outputBranch);
1516 branch = outputBranch;
1517 branchAddress = ab->
data();
1525template <
typename... ColTypes>
1526class R__CLING_PTRCHECK(off) SnapshotHelper :
public RActionImpl<SnapshotHelper<ColTypes...>> {
1527 std::string fFileName;
1528 std::string fDirName;
1529 std::string fTreeName;
1531 std::unique_ptr<TFile> fOutputFile;
1532 std::unique_ptr<TTree> fOutputTree;
1533 bool fBranchAddressesNeedReset{
true};
1536 TTree *fInputTree =
nullptr;
1538 std::vector<TBranch *> fBranches;
1539 std::vector<void *> fBranchAddresses;
1540 RBranchSet fOutputBranches;
1541 std::vector<bool> fIsDefine;
1544 using ColumnTypes_t =
TypeList<ColTypes...>;
1545 SnapshotHelper(std::string_view
filename, std::string_view dirname, std::string_view treename,
1547 std::vector<bool> &&isDefine)
1548 : fFileName(
filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1550 fBranchAddresses(vbnames.
size(), nullptr), fIsDefine(std::move(isDefine))
1555 SnapshotHelper(
const SnapshotHelper &) =
delete;
1556 SnapshotHelper(SnapshotHelper &&) =
default;
1559 if (!fTreeName.empty() && !fOutputFile && fOptions.
fLazy)
1560 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1566 fInputTree =
r->GetTree();
1567 fBranchAddressesNeedReset =
true;
1570 void Exec(
unsigned int , ColTypes &... values)
1572 using ind_t = std::index_sequence_for<ColTypes...>;
1573 if (!fBranchAddressesNeedReset) {
1574 UpdateCArraysPtrs(values..., ind_t{});
1576 SetBranches(values..., ind_t{});
1577 fBranchAddressesNeedReset =
false;
1579 fOutputTree->Fill();
1582 template <std::size_t...
S>
1583 void UpdateCArraysPtrs(ColTypes &... values, std::index_sequence<S...> )
1591 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1592 ? fBranches[
S]->SetAddress(GetData(values)),
1593 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1598 template <std::size_t...
S>
1599 void SetBranches(ColTypes &... values, std::index_sequence<S...> )
1602 int expander[] = {(SetBranchesHelper(fInputTree, *fOutputTree, fInputBranchNames[S], fOutputBranchNames[S],
1603 fBranches[S], fBranchAddresses[S], &values, fOutputBranches, fIsDefine[S]),
1606 fOutputBranches.AssertNoNullBranchAddresses();
1616 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1619 if (!fDirName.empty()) {
1622 if (checkupdate ==
"update")
1623 outputDir = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
1625 outputDir = fOutputFile->
mkdir(fDirName.c_str());
1629 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, outputDir);
1632 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1637 assert(fOutputTree !=
nullptr);
1638 assert(fOutputFile !=
nullptr);
1641 fOutputTree->AutoSave(
"flushbaskets");
1643 fOutputTree.reset();
1644 fOutputFile->Close();
1647 std::string GetActionName() {
return "Snapshot"; }
1651 return [
this](
unsigned int,
const RSampleInfo &)
mutable { fBranchAddressesNeedReset =
true; };
1656template <
typename... ColTypes>
1657class R__CLING_PTRCHECK(off) SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<ColTypes...>> {
1658 unsigned int fNSlots;
1659 std::unique_ptr<ROOT::TBufferMerger> fMerger;
1660 std::vector<std::shared_ptr<ROOT::TBufferMergerFile>> fOutputFiles;
1661 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1662 std::vector<int> fBranchAddressesNeedReset;
1663 std::string fFileName;
1664 std::string fDirName;
1665 std::string fTreeName;
1669 std::vector<TTree *> fInputTrees;
1671 std::vector<std::vector<TBranch *>> fBranches;
1673 std::vector<std::vector<void *>> fBranchAddresses;
1674 std::vector<RBranchSet> fOutputBranches;
1675 std::vector<bool> fIsDefine;
1678 using ColumnTypes_t =
TypeList<ColTypes...>;
1679 SnapshotHelperMT(
const unsigned int nSlots, std::string_view
filename, std::string_view dirname,
1682 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fBranchAddressesNeedReset(fNSlots, 1),
1683 fFileName(
filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1685 fBranches(fNSlots, std::vector<
TBranch *>(vbnames.
size(), nullptr)),
1686 fBranchAddresses(fNSlots, std::vector<
void *>(vbnames.
size(), nullptr)), fOutputBranches(fNSlots),
1687 fIsDefine(std::move(isDefine))
1691 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1692 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1695 if (!fTreeName.empty() && fOptions.
fLazy &&
1696 std::all_of(fOutputFiles.begin(), fOutputFiles.end(), [](
const auto &
f) { return !f; }) )
1697 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1703 if (!fOutputFiles[slot]) {
1705 fOutputFiles[slot] = fMerger->GetFile();
1707 TDirectory *treeDirectory = fOutputFiles[slot].get();
1708 if (!fDirName.empty()) {
1710 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str(),
"",
true);
1714 fOutputTrees[slot] =
1715 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1718 fOutputTrees[slot]->SetImplicitMT(
false);
1720 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1723 fInputTrees[slot] =
r->GetTree();
1725 fBranchAddressesNeedReset[slot] = 1;
1728 void FinalizeTask(
unsigned int slot)
1730 if (fOutputTrees[slot]->GetEntries() > 0)
1731 fOutputFiles[slot]->Write();
1733 fOutputTrees[slot].reset(
nullptr);
1734 fOutputBranches[slot].Clear();
1737 void Exec(
unsigned int slot, ColTypes &... values)
1739 using ind_t = std::index_sequence_for<ColTypes...>;
1740 if (fBranchAddressesNeedReset[slot] == 0) {
1741 UpdateCArraysPtrs(slot, values..., ind_t{});
1743 SetBranches(slot, values..., ind_t{});
1744 fBranchAddressesNeedReset[slot] = 0;
1746 fOutputTrees[slot]->Fill();
1747 auto entries = fOutputTrees[slot]->GetEntries();
1748 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1749 if ((autoFlush > 0) && (entries % autoFlush == 0))
1750 fOutputFiles[slot]->Write();
1753 template <std::size_t...
S>
1754 void UpdateCArraysPtrs(
unsigned int slot, ColTypes &... values, std::index_sequence<S...> )
1762 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1763 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1764 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1769 template <std::size_t...
S>
1770 void SetBranches(
unsigned int slot, ColTypes &... values, std::index_sequence<S...> )
1773 int expander[] = {(SetBranchesHelper(fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[S],
1774 fOutputBranchNames[S], fBranches[slot][S], fBranchAddresses[slot][S],
1775 &values, fOutputBranches[slot], fIsDefine[S]),
1778 fOutputBranches[slot].AssertNoNullBranchAddresses();
1785 auto out_file =
TFile::Open(fFileName.c_str(), fOptions.
fMode.c_str(), fFileName.c_str(), cs);
1787 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1788 fMerger = std::make_unique<ROOT::TBufferMerger>(std::unique_ptr<TFile>(out_file));
1793 assert(std::any_of(fOutputFiles.begin(), fOutputFiles.end(), [](
const auto &ptr) { return ptr != nullptr; }));
1795 auto fileWritten =
false;
1796 for (
auto &
file : fOutputFiles) {
1806 "No input entries (input TTree was empty or no entry passed the Filters). Output TTree is empty.");
1810 fOutputFiles.clear();
1814 std::string GetActionName() {
return "Snapshot"; }
1818 return [
this](
unsigned int slot,
const RSampleInfo &)
mutable { fBranchAddressesNeedReset[slot] = 1; };
1822template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1823 bool MustCopyAssign = std::is_same<R, U>::value>
1824class R__CLING_PTRCHECK(off) AggregateHelper
1825 :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1828 std::shared_ptr<U> fResult;
1829 Results<U> fAggregators;
1834 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &
result,
const unsigned int nSlots)
1835 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(
result), fAggregators(nSlots, *
result)
1839 AggregateHelper(Acc &
f, Merge &
m,
const std::shared_ptr<U> &
result,
const unsigned int nSlots)
1840 : fAggregate(
f), fMerge(
m), fResult(
result), fAggregators(nSlots, *
result)
1844 AggregateHelper(AggregateHelper &&) =
default;
1845 AggregateHelper(
const AggregateHelper &) =
delete;
1849 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<MustCopyAssign_,
int> = 0>
1850 void Exec(
unsigned int slot,
const T &
value)
1852 fAggregators[slot] = fAggregate(fAggregators[slot],
value);
1855 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<!MustCopyAssign_,
int> = 0>
1856 void Exec(
unsigned int slot,
const T &
value)
1858 fAggregate(fAggregators[slot],
value);
1863 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1864 bool MergeAll = std::is_same<void, MergeRet>::value>
1865 std::enable_if_t<MergeAll, void> Finalize()
1867 fMerge(fAggregators);
1868 *fResult = fAggregators[0];
1871 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1872 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1873 std::enable_if_t<MergeTwoByTwo, void> Finalize(...)
1875 for (
const auto &acc : fAggregators)
1876 *fResult = fMerge(*fResult, acc);
1879 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1881 std::string GetActionName() {
return "Aggregate"; }
1883 AggregateHelper MakeNew(
void *newResult)
1885 auto &
result = *
static_cast<std::shared_ptr<U> *
>(newResult);
1886 return AggregateHelper(fAggregate, fMerge,
result, fAggregators.size());
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
unsigned long long ULong64_t
#define R__CLING_PTRCHECK(ONOFF)
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
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 r
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
TClass * IsA() const override
TTime operator*(const TTime &t1, const TTime &t2)
Base class for action helpers, see RInterface::Book() for more information.
iterator begin() noexcept
pointer data() noexcept
Return a pointer to the vector's buffer, even if empty().
This class is the textual representation of the content of a columnar dataset.
This type represents a sample identifier, to be used in conjunction with RDataFrame features such as ...
typename RemoveFirstParameter< T >::type RemoveFirstParameter_t
A "std::vector"-like collection of values implementing handy operation to analyse them.
A TTree is a list of TBranches.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual char * GetAddress() const
Int_t GetSplitLevel() const
TClass * IsA() const override
virtual Int_t GetBasketSize() const
TObjArray * GetListOfLeaves()
TClassRef is used to implement a permanent reference to a TClass object.
Collection abstract base class.
TDirectory::TContext keeps track and restore the current directory.
Describe directory structure in memory.
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
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.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
TObject * UncheckedAt(Int_t i) const
Statistical variable, defined by its mean and variance (RMS).
void ToLower()
Change string to lower-case.
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
A TTree represents a columnar dataset.
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
TBranch * Branch(const char *name, T *obj, Int_t bufsize=32000, Int_t splitlevel=99)
Add a new branch, and infer the data type from the type of obj being passed.
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
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 .
std::vector< std::string > ReplaceDotWithUnderscore(const std::vector< std::string > &columnNames)
Replace occurrences of '.
void ValidateSnapshotOutput(const RSnapshotOptions &opts, const std::string &treeName, const std::string &fileName)
char TypeName2ROOTTypeName(const std::string &b)
Convert type name (e.g.
constexpr std::size_t FindIdxTrue(const T &arr)
void(off) SmallVectorTemplateBase< T
std::vector< std::string > ColumnNames_t
std::function< void(unsigned int, const ROOT::RDF::RSampleInfo &)> SampleCallback_t
The type of a data-block callback, registered with a RDataFrame computation graph via e....
ROOT type_traits extensions.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
int CompressionSettings(RCompressionSetting::EAlgorithm::EValues algorithm, int compressionLevel)
RooArgSet S(Args_t &&... args)
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
void Initialize(Bool_t useTMVAStyle=kTRUE)
A collection of options to steer the creation of the dataset on file.
int fAutoFlush
AutoFlush value for output tree.
std::string fMode
Mode of creation of output file.
ECAlgo fCompressionAlgorithm
Compression algorithm of output file.
int fSplitLevel
Split level of output tree.
bool fLazy
Do not start the event loop when Snapshot is called.
int fCompressionLevel
Compression level of output file.
Lightweight storage for a collection of types.
static uint64_t sum(uint64_t i)