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,
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);
344template <
typename HIST = Hist_t>
345class R__CLING_PTRCHECK(off) FillHelper :
public RActionImpl<FillHelper<HIST>> {
346 std::vector<HIST *> fObjects;
348 template <typename H = HIST, typename = decltype(std::declval<H>().Reset())>
349 void ResetIfPossible(
H *
h)
357 void ResetIfPossible(...)
359 throw std::runtime_error(
360 "A systematic variation was requested for a custom Fill action, but the type of the object to be filled does "
361 "not implement a Reset method, so we cannot safely re-initialize variations of the result. Aborting.");
364 void UnsetDirectoryIfPossible(
TH1 *
h) {
365 h->SetDirectory(
nullptr);
368 void UnsetDirectoryIfPossible(...) {}
371 template <typename H, typename = std::enable_if_t<std::is_base_of<TObject, H>::value,
int>>
372 auto Merge(std::vector<H *> &objs,
int )
376 for (
auto it = ++objs.begin(); it != objs.end(); ++it)
382 template <
typename H>
383 auto Merge(std::vector<H *> &objs,
double )
384 ->
decltype(objs[0]->Merge(std::vector<HIST *>{}),
void())
386 objs[0]->Merge({++objs.begin(), objs.end()});
390 template <
typename T>
393 static_assert(
sizeof(
T) < 0,
394 "The type passed to Fill does not provide a Merge(TCollection*) or Merge(const std::vector&) method.");
398 template <
typename T>
399 class ScalarConstIterator {
403 ScalarConstIterator(
const T *obj) : obj_(obj) {}
405 ScalarConstIterator<T> &operator++() {
return *
this; }
413 template <typename T, std::enable_if_t<!IsDataContainer<T>::value,
int> = 0>
414 ScalarConstIterator<T> MakeBegin(
const T &val)
416 return ScalarConstIterator<T>(&val);
420 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
421 auto MakeBegin(
const T &val)
423 return std::begin(val);
427 template <typename T, std::enable_if_t<!IsDataContainer<T>::value,
int> = 0>
428 std::size_t GetSize(
const T &)
434 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
435 std::size_t GetSize(
const T &val)
437#if __cplusplus >= 201703L
438 return std::size(val);
444 template <std::size_t ColIdx,
typename End_t,
typename... Its>
445 void ExecLoop(
unsigned int slot, End_t end, Its... its)
447 auto *thisSlotH = fObjects[slot];
450 auto nop = [](
auto &&...) {};
451 for (; GetNthElement<ColIdx>(its...) !=
end; nop(++its...)) {
452 thisSlotH->Fill(*its...);
457 FillHelper(FillHelper &&) =
default;
458 FillHelper(
const FillHelper &) =
delete;
460 FillHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots) : fObjects(nSlots, nullptr)
462 fObjects[0] =
h.get();
464 for (
unsigned int i = 1; i < nSlots; ++i) {
465 fObjects[i] =
new HIST(*fObjects[0]);
466 UnsetDirectoryIfPossible(fObjects[i]);
473 template <
typename... ValTypes, std::enable_if_t<!Disjunction<IsDataContainer<ValTypes>...>
::value,
int> = 0>
474 auto Exec(
unsigned int slot,
const ValTypes &...
x) ->
decltype(fObjects[slot]->Fill(
x...),
void())
476 fObjects[slot]->Fill(
x...);
480 template <
typename... Xs, std::enable_if_t<Disjunction<IsDataContainer<Xs>...>
::value,
int> = 0>
481 auto Exec(
unsigned int slot,
const Xs &...xs) ->
decltype(fObjects[slot]->Fill(*MakeBegin(xs)...),
void())
484 constexpr std::array<
bool,
sizeof...(Xs)> isContainer{IsDataContainer<Xs>::value...};
487 constexpr std::size_t colidx =
FindIdxTrue(isContainer);
489 static_assert(colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
492 auto const xrefend = std::end(GetNthElement<colidx>(xs...));
495 std::array<std::size_t,
sizeof...(xs)> sizes = {{GetSize(xs)...}};
497 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
498 if (isContainer[i] && sizes[i] != sizes[colidx]) {
499 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
503 ExecLoop<colidx>(slot, xrefend, MakeBegin(xs)...);
506 template <
typename T = HIST>
509 static_assert(
sizeof(
T) < 0,
510 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
511 "columns passed did not match the signature of the object's `Fill` method.");
518 if (fObjects.size() == 1)
524 for (
auto it = ++fObjects.begin(); it != fObjects.end(); ++it)
528 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[slot]; }
533 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
537 template <typename T = HIST, std::enable_if_t<std::is_base_of<TObject, T>::value,
int> = 0>
538 std::string GetActionName()
540 return std::string(fObjects[0]->
IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
544 template <typename T = HIST, std::enable_if_t<!std::is_base_of<TObject, T>::value,
int> = 0>
545 std::string GetActionName()
547 return "Fill custom object";
550 template <
typename H = HIST>
551 FillHelper MakeNew(
void *newResult)
553 auto &
result = *
static_cast<std::shared_ptr<H> *
>(newResult);
554 ResetIfPossible(
result.get());
555 UnsetDirectoryIfPossible(
result.get());
556 return FillHelper(
result, fObjects.size());
565 std::vector<::TGraph *> fGraphs;
568 FillTGraphHelper(FillTGraphHelper &&) =
default;
569 FillTGraphHelper(
const FillTGraphHelper &) =
delete;
571 FillTGraphHelper(
const std::shared_ptr<::TGraph> &
g,
const unsigned int nSlots) : fGraphs(nSlots, nullptr)
573 fGraphs[0] =
g.get();
575 for (
unsigned int i = 1; i < nSlots; ++i) {
576 fGraphs[i] =
new TGraph(*fGraphs[0]);
584 template <
typename X0,
typename X1,
585 std::enable_if_t<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int> = 0>
586 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
588 if (x0s.size() != x1s.size()) {
589 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
591 auto *thisSlotG = fGraphs[slot];
592 auto x0sIt = std::begin(x0s);
593 const auto x0sEnd = std::end(x0s);
594 auto x1sIt = std::begin(x1s);
595 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
596 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
601 template <
typename X0,
typename X1,
602 std::enable_if_t<!IsDataContainer<X0>::value && !IsDataContainer<X1>::value,
int> = 0>
603 void Exec(
unsigned int slot, X0 x0, X1
x1)
605 auto thisSlotG = fGraphs[slot];
606 thisSlotG->SetPoint(thisSlotG->GetN(), x0,
x1);
611 template <
typename X0,
typename X1,
typename... ExtraArgsToLowerPriority>
612 void Exec(
unsigned int, X0, X1, ExtraArgsToLowerPriority...)
614 throw std::runtime_error(
"Graph was applied to a mix of scalar values and collections. This is not supported.");
619 const auto nSlots = fGraphs.size();
620 auto resGraph = fGraphs[0];
623 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
624 l.Add(fGraphs[slot]);
632 return std::make_unique<RMergeableFill<Result_t>>(*fGraphs[0]);
635 std::string GetActionName() {
return "Graph"; }
637 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
639 FillTGraphHelper MakeNew(
void *newResult)
641 auto &
result = *
static_cast<std::shared_ptr<TGraph> *
>(newResult);
643 return FillTGraphHelper(
result, fGraphs.size());
647class R__CLING_PTRCHECK(off) FillTGraphAsymmErrorsHelper
653 std::vector<::TGraphAsymmErrors *> fGraphAsymmErrors;
656 FillTGraphAsymmErrorsHelper(FillTGraphAsymmErrorsHelper &&) =
default;
657 FillTGraphAsymmErrorsHelper(
const FillTGraphAsymmErrorsHelper &) =
delete;
659 FillTGraphAsymmErrorsHelper(
const std::shared_ptr<::TGraphAsymmErrors> &
g,
const unsigned int nSlots)
660 : fGraphAsymmErrors(nSlots, nullptr)
662 fGraphAsymmErrors[0] =
g.get();
664 for (
unsigned int i = 1; i < nSlots; ++i) {
674 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
675 std::enable_if_t<IsDataContainer<X>::value && IsDataContainer<Y>::value && IsDataContainer<EXL>::value &&
676 IsDataContainer<EXH>::value && IsDataContainer<EYL>::value && IsDataContainer<EYH>::value,
679 Exec(
unsigned int slot,
const X &xs,
const Y &ys,
const EXL &exls,
const EXH &exhs,
const EYL &eyls,
const EYH &eyhs)
681 if ((xs.size() != ys.size()) || (xs.size() != exls.size()) || (xs.size() != exhs.size()) ||
682 (xs.size() != eyls.size()) || (xs.size() != eyhs.size())) {
683 throw std::runtime_error(
"Cannot fill GraphAsymmErrors with values in containers of different sizes.");
685 auto *thisSlotG = fGraphAsymmErrors[slot];
686 auto xsIt = std::begin(xs);
687 auto ysIt = std::begin(ys);
688 auto exlsIt = std::begin(exls);
689 auto exhsIt = std::begin(exhs);
690 auto eylsIt = std::begin(eyls);
691 auto eyhsIt = std::begin(eyhs);
692 while (xsIt != std::end(xs)) {
693 const auto n = thisSlotG->GetN();
694 thisSlotG->SetPoint(
n, *xsIt++, *ysIt++);
695 thisSlotG->SetPointError(
n, *exlsIt++, *exhsIt++, *eylsIt++, *eyhsIt++);
701 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
702 std::enable_if_t<!IsDataContainer<X>::value && !IsDataContainer<Y>::value && !IsDataContainer<EXL>::value &&
703 !IsDataContainer<EXH>::value && !IsDataContainer<EYL>::value && !IsDataContainer<EYH>::value,
705 void Exec(
unsigned int slot,
X x, Y
y, EXL exl, EXH exh, EYL eyl, EYH eyh)
707 auto thisSlotG = fGraphAsymmErrors[slot];
708 const auto n = thisSlotG->GetN();
709 thisSlotG->SetPoint(
n,
x,
y);
710 thisSlotG->SetPointError(
n, exl, exh, eyl, eyh);
715 template <
typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
716 typename... ExtraArgsToLowerPriority>
717 void Exec(
unsigned int,
X, Y, EXL, EXH, EYL, EYH, ExtraArgsToLowerPriority...)
719 throw std::runtime_error(
720 "GraphAsymmErrors was applied to a mix of scalar values and collections. This is not supported.");
725 const auto nSlots = fGraphAsymmErrors.size();
726 auto resGraphAsymmErrors = fGraphAsymmErrors[0];
729 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
730 l.Add(fGraphAsymmErrors[slot]);
732 resGraphAsymmErrors->Merge(&
l);
738 return std::make_unique<RMergeableFill<Result_t>>(*fGraphAsymmErrors[0]);
741 std::string GetActionName() {
return "GraphAsymmErrors"; }
743 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphAsymmErrors[slot]; }
745 FillTGraphAsymmErrorsHelper MakeNew(
void *newResult)
747 auto &
result = *
static_cast<std::shared_ptr<TGraphAsymmErrors> *
>(newResult);
749 return FillTGraphAsymmErrorsHelper(
result, fGraphAsymmErrors.size());
759template <
typename V,
typename COLL>
760void FillColl(V&&
v, COLL&
c) {
765template <
typename COLL>
766void FillColl(
bool v, COLL&
c) {
772template <
typename RealT_t,
typename T,
typename COLL>
773class R__CLING_PTRCHECK(off) TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
774 Results<std::shared_ptr<COLL>> fColls;
778 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
780 fColls.emplace_back(resultColl);
781 for (
unsigned int i = 1; i < nSlots; ++i)
782 fColls.emplace_back(std::make_shared<COLL>());
784 TakeHelper(TakeHelper &&);
785 TakeHelper(
const TakeHelper &) =
delete;
789 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
795 auto rColl = fColls[0];
796 for (
unsigned int i = 1; i < fColls.size(); ++i) {
797 const auto &coll = fColls[i];
798 const auto end = coll->end();
801 for (
auto j = coll->begin(); j !=
end; j++) {
802 FillColl(*j, *rColl);
807 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
809 std::string GetActionName() {
return "Take"; }
811 TakeHelper MakeNew(
void *newResult)
813 auto &
result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
815 return TakeHelper(
result, fColls.size());
821template <
typename RealT_t,
typename T>
822class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
T, std::vector<T>>
823 :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
824 Results<std::shared_ptr<std::vector<T>>> fColls;
828 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
830 fColls.emplace_back(resultColl);
831 for (
unsigned int i = 1; i < nSlots; ++i) {
832 auto v = std::make_shared<std::vector<T>>();
834 fColls.emplace_back(
v);
837 TakeHelper(TakeHelper &&);
838 TakeHelper(
const TakeHelper &) =
delete;
842 void Exec(
unsigned int slot, T &
v) { FillColl(
v, *fColls[slot]); }
850 for (
auto &coll : fColls)
851 totSize += coll->
size();
852 auto rColl = fColls[0];
853 rColl->reserve(totSize);
854 for (
unsigned int i = 1; i < fColls.size(); ++i) {
855 auto &coll = fColls[i];
856 rColl->insert(rColl->end(), coll->begin(), coll->end());
860 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
862 std::string GetActionName() {
return "Take"; }
864 TakeHelper MakeNew(
void *newResult)
866 auto &
result = *
static_cast<std::shared_ptr<std::vector<T>
> *>(newResult);
868 return TakeHelper(
result, fColls.size());
874template <
typename RealT_t,
typename COLL>
875class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, COLL>
876 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
877 Results<std::shared_ptr<COLL>> fColls;
881 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
883 fColls.emplace_back(resultColl);
884 for (
unsigned int i = 1; i < nSlots; ++i)
885 fColls.emplace_back(std::make_shared<COLL>());
887 TakeHelper(TakeHelper &&);
888 TakeHelper(
const TakeHelper &) =
delete;
898 auto rColl = fColls[0];
899 for (
unsigned int i = 1; i < fColls.size(); ++i) {
900 auto &coll = fColls[i];
901 for (
auto &
v : *coll) {
902 rColl->emplace_back(
v);
907 std::string GetActionName() {
return "Take"; }
909 TakeHelper MakeNew(
void *newResult)
911 auto &
result = *
static_cast<std::shared_ptr<COLL> *
>(newResult);
913 return TakeHelper(
result, fColls.size());
919template <
typename RealT_t>
920class R__CLING_PTRCHECK(off) TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>>
921 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
923 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
927 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
929 fColls.emplace_back(resultColl);
930 for (
unsigned int i = 1; i < nSlots; ++i) {
931 auto v = std::make_shared<std::vector<RealT_t>>();
933 fColls.emplace_back(
v);
936 TakeHelper(TakeHelper &&);
937 TakeHelper(
const TakeHelper &) =
delete;
949 for (
auto &coll : fColls)
950 totSize += coll->
size();
951 auto rColl = fColls[0];
952 rColl->reserve(totSize);
953 for (
unsigned int i = 1; i < fColls.size(); ++i) {
954 auto &coll = fColls[i];
955 rColl->insert(rColl->end(), coll->begin(), coll->end());
959 std::string GetActionName() {
return "Take"; }
961 TakeHelper MakeNew(
void *newResult)
963 auto &
result = *
static_cast<typename decltype(fColls)::value_type *
>(newResult);
965 return TakeHelper(
result, fColls.size());
972template <
typename RealT_t,
typename T,
typename COLL>
973TakeHelper<RealT_t, T, COLL>::TakeHelper(TakeHelper<RealT_t, T, COLL> &&) =
default;
974template <
typename RealT_t,
typename T>
975TakeHelper<RealT_t, T, std::vector<T>>::TakeHelper(TakeHelper<RealT_t, T, std::vector<T>> &&) =
default;
976template <
typename RealT_t,
typename COLL>
977TakeHelper<RealT_t, RVec<RealT_t>, COLL>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, COLL> &&) =
default;
978template <
typename RealT_t>
979TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>> &&) =
default;
983extern template class TakeHelper<bool, bool, std::vector<bool>>;
984extern template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
985extern template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
986extern template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
987extern template class TakeHelper<int, int, std::vector<int>>;
988extern template class TakeHelper<long, long, std::vector<long>>;
989extern template class TakeHelper<long long, long long, std::vector<long long>>;
990extern template class TakeHelper<float, float, std::vector<float>>;
991extern template class TakeHelper<double, double, std::vector<double>>;
994template <
typename ResultType>
995class R__CLING_PTRCHECK(off) MinHelper :
public RActionImpl<MinHelper<ResultType>> {
996 std::shared_ptr<ResultType> fResultMin;
997 Results<ResultType> fMins;
1000 MinHelper(MinHelper &&) =
default;
1001 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
1002 : fResultMin(minVPtr), fMins(nSlots, std::numeric_limits<ResultType>::
max())
1006 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
1010 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1011 void Exec(
unsigned int slot,
const T &vs)
1014 fMins[slot] = std::min(static_cast<ResultType>(
v), fMins[slot]);
1021 *fResultMin = std::numeric_limits<ResultType>::max();
1022 for (
auto &
m : fMins)
1023 *fResultMin = std::min(
m, *fResultMin);
1029 return std::make_unique<RMergeableMin<ResultType>>(*fResultMin);
1032 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
1034 std::string GetActionName() {
return "Min"; }
1036 MinHelper MakeNew(
void *newResult)
1038 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1039 return MinHelper(
result, fMins.size());
1050template <
typename ResultType>
1051class R__CLING_PTRCHECK(off) MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
1052 std::shared_ptr<ResultType> fResultMax;
1053 Results<ResultType> fMaxs;
1056 MaxHelper(MaxHelper &&) =
default;
1057 MaxHelper(
const MaxHelper &) =
delete;
1058 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
1059 : fResultMax(maxVPtr), fMaxs(nSlots, std::numeric_limits<ResultType>::lowest())
1064 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
1066 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1067 void Exec(
unsigned int slot,
const T &vs)
1070 fMaxs[slot] = std::
max(static_cast<ResultType>(
v), fMaxs[slot]);
1077 *fResultMax = std::numeric_limits<ResultType>::lowest();
1078 for (
auto &
m : fMaxs) {
1079 *fResultMax = std::max(
m, *fResultMax);
1086 return std::make_unique<RMergeableMax<ResultType>>(*fResultMax);
1089 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
1091 std::string GetActionName() {
return "Max"; }
1093 MaxHelper MakeNew(
void *newResult)
1095 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1096 return MaxHelper(
result, fMaxs.size());
1107template <
typename ResultType>
1108class R__CLING_PTRCHECK(off) SumHelper :
public RActionImpl<SumHelper<ResultType>> {
1109 std::shared_ptr<ResultType> fResultSum;
1110 Results<ResultType> fSums;
1111 Results<ResultType> fCompensations;
1116 template <
typename T = ResultType>
1117 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
1122 template <
typename T = ResultType,
typename Dummy =
int>
1123 ResultType NeutralElement(
const T &, Dummy)
1125 return ResultType{};
1129 SumHelper(SumHelper &&) =
default;
1130 SumHelper(
const SumHelper &) =
delete;
1131 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
1132 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1)),
1133 fCompensations(nSlots, NeutralElement(*sumVPtr, -1))
1138 void Exec(
unsigned int slot, ResultType
x)
1141 ResultType
y =
x - fCompensations[slot];
1142 ResultType t = fSums[slot] +
y;
1143 fCompensations[slot] = (t - fSums[slot]) -
y;
1147 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1148 void Exec(
unsigned int slot,
const T &vs)
1150 for (
auto &&
v : vs) {
1159 ResultType
sum(NeutralElement(ResultType{}, -1));
1160 ResultType compensation(NeutralElement(ResultType{}, -1));
1161 ResultType
y(NeutralElement(ResultType{}, -1));
1162 ResultType t(NeutralElement(ResultType{}, -1));
1163 for (
auto &
m : fSums) {
1165 y =
m - compensation;
1167 compensation = (t -
sum) -
y;
1176 return std::make_unique<RMergeableSum<ResultType>>(*fResultSum);
1179 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
1181 std::string GetActionName() {
return "Sum"; }
1183 SumHelper MakeNew(
void *newResult)
1185 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(newResult);
1187 return SumHelper(
result, fSums.size());
1191class R__CLING_PTRCHECK(off) MeanHelper :
public RActionImpl<MeanHelper> {
1192 std::shared_ptr<double> fResultMean;
1193 std::vector<ULong64_t> fCounts;
1194 std::vector<double> fSums;
1195 std::vector<double> fPartialMeans;
1196 std::vector<double> fCompensations;
1199 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1200 MeanHelper(MeanHelper &&) =
default;
1201 MeanHelper(
const MeanHelper &) =
delete;
1203 void Exec(
unsigned int slot,
double v);
1205 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1206 void Exec(
unsigned int slot,
const T &vs)
1208 for (
auto &&
v : vs) {
1212 double y =
v - fCompensations[slot];
1213 double t = fSums[slot] +
y;
1214 fCompensations[slot] = (t - fSums[slot]) -
y;
1226 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1227 return std::make_unique<RMergeableMean>(*fResultMean, counts);
1230 double &PartialUpdate(
unsigned int slot);
1232 std::string GetActionName() {
return "Mean"; }
1234 MeanHelper MakeNew(
void *newResult)
1236 auto &
result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1237 return MeanHelper(
result, fSums.size());
1241extern template void MeanHelper::Exec(
unsigned int,
const std::vector<float> &);
1242extern template void MeanHelper::Exec(
unsigned int,
const std::vector<double> &);
1243extern template void MeanHelper::Exec(
unsigned int,
const std::vector<char> &);
1244extern template void MeanHelper::Exec(
unsigned int,
const std::vector<int> &);
1245extern template void MeanHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
1249 unsigned int fNSlots;
1250 std::shared_ptr<double> fResultStdDev;
1252 std::vector<ULong64_t> fCounts;
1254 std::vector<double> fMeans;
1256 std::vector<double> fDistancesfromMean;
1259 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
1260 StdDevHelper(StdDevHelper &&) =
default;
1261 StdDevHelper(
const StdDevHelper &) =
delete;
1263 void Exec(
unsigned int slot,
double v);
1265 template <typename T, std::enable_if_t<IsDataContainer<T>::value,
int> = 0>
1266 void Exec(
unsigned int slot,
const T &vs)
1268 for (
auto &&
v : vs) {
1280 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1282 std::inner_product(fMeans.begin(), fMeans.end(), fCounts.begin(), 0.) /
static_cast<Double_t>(counts);
1283 return std::make_unique<RMergeableStdDev>(*fResultStdDev, counts, mean);
1286 std::string GetActionName() {
return "StdDev"; }
1288 StdDevHelper MakeNew(
void *newResult)
1290 auto &
result = *
static_cast<std::shared_ptr<double> *
>(newResult);
1291 return StdDevHelper(
result, fCounts.size());
1295extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<float> &);
1296extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<double> &);
1297extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<char> &);
1298extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<int> &);
1299extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
1301template <
typename PrevNodeType>
1305 std::shared_ptr<Display_t> fDisplayerHelper;
1306 std::shared_ptr<PrevNodeType> fPrevNode;
1307 size_t fEntriesToProcess;
1310 DisplayHelper(
size_t nRows,
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
1311 : fDisplayerHelper(
d), fPrevNode(prevNode), fEntriesToProcess(nRows)
1314 DisplayHelper(DisplayHelper &&) =
default;
1315 DisplayHelper(
const DisplayHelper &) =
delete;
1318 template <
typename...
Columns>
1319 void Exec(
unsigned int, Columns &... columns)
1321 if (fEntriesToProcess == 0)
1324 fDisplayerHelper->AddRow(columns...);
1325 --fEntriesToProcess;
1327 if (fEntriesToProcess == 0) {
1332 fPrevNode->StopProcessing();
1340 std::string GetActionName() {
return "Display"; }
1343template <
typename T>
1349template <
typename T>
1355template <
typename T>
1356void SetBranchesHelper(
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
const std::string &
name,
1357 TBranch *&branch,
void *&branchAddress, T *address, RBranchSet &outputBranches,
1360 static TClassRef TBOClRef(
"TBranchObject");
1362 TBranch *inputBranch =
nullptr;
1364 inputBranch = inputTree->
GetBranch(inName.c_str());
1366 inputBranch = inputTree->
FindBranch(inName.c_str());
1369 auto *outputBranch = outputBranches.Get(
name);
1372 if (inputBranch && inputBranch->
IsA() == TBOClRef) {
1373 outputBranch->SetAddress(
reinterpret_cast<T **
>(inputBranch->
GetAddress()));
1375 branchAddress = address;
1376 outputBranch->SetAddress(&branchAddress);
1378 outputBranch->SetAddress(address);
1379 branchAddress = address;
1392 if (inputBranch->
IsA() == TBOClRef) {
1395 outputTree.
Branch(
name.c_str(),
reinterpret_cast<T **
>(inputBranch->
GetAddress()), bufSize, splitLevel);
1397 outputBranch = outputTree.
Branch(
name.c_str(), address, bufSize, splitLevel);
1400 outputBranch = outputTree.
Branch(
name.c_str(), address);
1402 outputBranches.Insert(
name, outputBranch);
1405 branchAddress =
nullptr;
1418template <
typename T>
1419void SetBranchesHelper(
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
const std::string &outName,
1420 TBranch *&branch,
void *&branchAddress,
RVec<T> *ab, RBranchSet &outputBranches,
bool isDefine)
1422 TBranch *inputBranch =
nullptr;
1424 inputBranch = inputTree->
GetBranch(inName.c_str());
1426 inputBranch = inputTree->
FindBranch(inName.c_str());
1428 auto *outputBranch = outputBranches.Get(outName);
1431 bool mustWriteRVec = (inputBranch ==
nullptr || isDefine);
1433 if (!mustWriteRVec && std::string_view(inputBranch->
GetClassName()) ==
"TClonesArray") {
1434 mustWriteRVec =
true;
1436 "Branch \"%s\" contains TClonesArrays but the type specified to Snapshot was RVec<T>. The branch will "
1437 "be written out as a RVec instead of a TClonesArray. Specify that the type of the branch is "
1438 "TClonesArray as a Snapshot template parameter to write out a TClonesArray instead.",
1442 if (!mustWriteRVec) {
1445 mustWriteRVec =
true;
1448 if (mustWriteRVec) {
1455 outputBranch->SetObject(ab);
1457 auto *
b = outputTree.
Branch(outName.c_str(), ab);
1458 outputBranches.Insert(outName,
b);
1464 auto dataPtr = ab->
data();
1468 branchAddress = dataPtr;
1469 outputBranch->SetAddress(&branchAddress);
1471 outputBranch->SetAddress(dataPtr);
1476 const auto bname = leaf->
GetName();
1477 auto *sizeLeaf = leaf->GetLeafCount();
1478 const auto sizeLeafName = sizeLeaf ? std::string(sizeLeaf->GetName()) : std::to_string(leaf->GetLenStatic());
1480 if (sizeLeaf && !outputBranches.Get(sizeLeafName)) {
1485 const auto sizeBufSize = sizeLeaf->GetBranch()->GetBasketSize();
1487 auto *sizeBranch = outputTree.
Branch(sizeLeafName.c_str(), (
void *)
nullptr,
1488 (sizeLeafName +
'/' + sizeTypeStr).c_str(), sizeBufSize);
1489 outputBranches.Insert(sizeLeafName, sizeBranch);
1492 const auto btype = leaf->GetTypeName();
1494 if (rootbtype ==
' ') {
1496 "RDataFrame::Snapshot: could not correctly construct a leaflist for C-style array in column %s. This "
1497 "column will not be written out.",
1500 const auto leaflist = std::string(bname) +
"[" + sizeLeafName +
"]/" + rootbtype;
1501 outputBranch = outputTree.
Branch(outName.c_str(), dataPtr, leaflist.c_str());
1503 outputBranches.Insert(outName, outputBranch);
1504 branch = outputBranch;
1505 branchAddress = ab->
data();
1513template <
typename... ColTypes>
1514class R__CLING_PTRCHECK(off) SnapshotHelper :
public RActionImpl<SnapshotHelper<ColTypes...>> {
1515 std::string fFileName;
1516 std::string fDirName;
1517 std::string fTreeName;
1519 std::unique_ptr<TFile> fOutputFile;
1520 std::unique_ptr<TTree> fOutputTree;
1521 bool fBranchAddressesNeedReset{
true};
1524 TTree *fInputTree =
nullptr;
1526 std::vector<TBranch *> fBranches;
1527 std::vector<void *> fBranchAddresses;
1528 RBranchSet fOutputBranches;
1529 std::vector<bool> fIsDefine;
1532 using ColumnTypes_t =
TypeList<ColTypes...>;
1533 SnapshotHelper(std::string_view
filename, std::string_view dirname, std::string_view treename,
1535 std::vector<bool> &&isDefine)
1536 : fFileName(
filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1538 fBranchAddresses(vbnames.
size(), nullptr), fIsDefine(std::move(isDefine))
1543 SnapshotHelper(
const SnapshotHelper &) =
delete;
1544 SnapshotHelper(SnapshotHelper &&) =
default;
1547 if (!fTreeName.empty() && !fOutputFile && fOptions.
fLazy)
1548 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1554 fInputTree =
r->GetTree();
1555 fBranchAddressesNeedReset =
true;
1558 void Exec(
unsigned int , ColTypes &... values)
1560 using ind_t = std::index_sequence_for<ColTypes...>;
1561 if (!fBranchAddressesNeedReset) {
1562 UpdateCArraysPtrs(values..., ind_t{});
1564 SetBranches(values..., ind_t{});
1565 fBranchAddressesNeedReset =
false;
1567 fOutputTree->Fill();
1570 template <std::size_t...
S>
1571 void UpdateCArraysPtrs(ColTypes &... values, std::index_sequence<S...> )
1579 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1580 ? fBranches[
S]->SetAddress(GetData(values)),
1581 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1586 template <std::size_t...
S>
1587 void SetBranches(ColTypes &... values, std::index_sequence<S...> )
1590 int expander[] = {(SetBranchesHelper(fInputTree, *fOutputTree, fInputBranchNames[S], fOutputBranchNames[S],
1591 fBranches[S], fBranchAddresses[S], &values, fOutputBranches, fIsDefine[S]),
1594 fOutputBranches.AssertNoNullBranchAddresses();
1604 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1607 if (!fDirName.empty()) {
1610 if (checkupdate ==
"update")
1611 outputDir = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
1613 outputDir = fOutputFile->
mkdir(fDirName.c_str());
1617 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, outputDir);
1620 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1625 assert(fOutputTree !=
nullptr);
1626 assert(fOutputFile !=
nullptr);
1629 fOutputTree->AutoSave(
"flushbaskets");
1631 fOutputTree.reset();
1632 fOutputFile->Close();
1635 std::string GetActionName() {
return "Snapshot"; }
1639 return [
this](
unsigned int,
const RSampleInfo &)
mutable { fBranchAddressesNeedReset =
true; };
1653 SnapshotHelper MakeNew(
void *newName)
1655 const std::string finalName = *
reinterpret_cast<const std::string *
>(newName);
1656 return SnapshotHelper{
1657 finalName, fDirName, fTreeName, fInputBranchNames, fOutputBranchNames, fOptions, std::vector<bool>(fIsDefine)};
1662template <
typename... ColTypes>
1663class R__CLING_PTRCHECK(off) SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<ColTypes...>> {
1664 unsigned int fNSlots;
1665 std::unique_ptr<ROOT::TBufferMerger> fMerger;
1666 std::vector<std::shared_ptr<ROOT::TBufferMergerFile>> fOutputFiles;
1667 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1668 std::vector<int> fBranchAddressesNeedReset;
1669 std::string fFileName;
1670 std::string fDirName;
1671 std::string fTreeName;
1675 std::vector<TTree *> fInputTrees;
1677 std::vector<std::vector<TBranch *>> fBranches;
1679 std::vector<std::vector<void *>> fBranchAddresses;
1680 std::vector<RBranchSet> fOutputBranches;
1681 std::vector<bool> fIsDefine;
1684 using ColumnTypes_t =
TypeList<ColTypes...>;
1685 SnapshotHelperMT(
const unsigned int nSlots, std::string_view
filename, std::string_view dirname,
1688 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fBranchAddressesNeedReset(fNSlots, 1),
1689 fFileName(
filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1691 fBranches(fNSlots, std::vector<
TBranch *>(vbnames.
size(), nullptr)),
1692 fBranchAddresses(fNSlots, std::vector<
void *>(vbnames.
size(), nullptr)), fOutputBranches(fNSlots),
1693 fIsDefine(std::move(isDefine))
1697 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1698 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1701 if (!fTreeName.empty() && fOptions.
fLazy &&
1702 std::all_of(fOutputFiles.begin(), fOutputFiles.end(), [](
const auto &
f) { return !f; }) )
1703 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1709 if (!fOutputFiles[slot]) {
1711 fOutputFiles[slot] = fMerger->GetFile();
1713 TDirectory *treeDirectory = fOutputFiles[slot].get();
1714 if (!fDirName.empty()) {
1716 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str(),
"",
true);
1720 fOutputTrees[slot] =
1721 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1724 fOutputTrees[slot]->SetImplicitMT(
false);
1726 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1729 fInputTrees[slot] =
r->GetTree();
1731 fBranchAddressesNeedReset[slot] = 1;
1734 void FinalizeTask(
unsigned int slot)
1736 if (fOutputTrees[slot]->GetEntries() > 0)
1737 fOutputFiles[slot]->Write();
1739 fOutputTrees[slot].reset(
nullptr);
1740 fOutputBranches[slot].Clear();
1743 void Exec(
unsigned int slot, ColTypes &... values)
1745 using ind_t = std::index_sequence_for<ColTypes...>;
1746 if (fBranchAddressesNeedReset[slot] == 0) {
1747 UpdateCArraysPtrs(slot, values..., ind_t{});
1749 SetBranches(slot, values..., ind_t{});
1750 fBranchAddressesNeedReset[slot] = 0;
1752 fOutputTrees[slot]->Fill();
1753 auto entries = fOutputTrees[slot]->GetEntries();
1754 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1755 if ((autoFlush > 0) && (entries % autoFlush == 0))
1756 fOutputFiles[slot]->Write();
1759 template <std::size_t...
S>
1760 void UpdateCArraysPtrs(
unsigned int slot, ColTypes &... values, std::index_sequence<S...> )
1768 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1769 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1770 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1776 template <std::size_t...
S>
1777 void SetBranches(
unsigned int slot, ColTypes &... values, std::index_sequence<S...> )
1780 int expander[] = {(SetBranchesHelper(fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[S],
1781 fOutputBranchNames[S], fBranches[slot][S], fBranchAddresses[slot][S],
1782 &values, fOutputBranches[slot], fIsDefine[S]),
1785 fOutputBranches[slot].AssertNoNullBranchAddresses();
1792 auto out_file =
TFile::Open(fFileName.c_str(), fOptions.
fMode.c_str(), fFileName.c_str(), cs);
1794 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1795 fMerger = std::make_unique<ROOT::TBufferMerger>(std::unique_ptr<TFile>(out_file));
1800 assert(std::any_of(fOutputFiles.begin(), fOutputFiles.end(), [](
const auto &ptr) { return ptr != nullptr; }));
1802 auto fileWritten =
false;
1803 for (
auto &file : fOutputFiles) {
1813 "No input entries (input TTree was empty or no entry passed the Filters). Output TTree is empty.");
1817 fOutputFiles.clear();
1821 std::string GetActionName() {
return "Snapshot"; }
1825 return [
this](
unsigned int slot,
const RSampleInfo &)
mutable { fBranchAddressesNeedReset[slot] = 1; };
1839 SnapshotHelperMT MakeNew(
void *newName)
1841 const std::string finalName = *
reinterpret_cast<const std::string *
>(newName);
1842 return SnapshotHelperMT{fNSlots, finalName, fDirName, fTreeName,
1843 fInputBranchNames, fOutputBranchNames, fOptions, std::vector<bool>(fIsDefine)};
1847template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1848 bool MustCopyAssign = std::is_same<R, U>::value>
1849class R__CLING_PTRCHECK(off) AggregateHelper
1850 :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1853 std::shared_ptr<U> fResult;
1854 Results<U> fAggregators;
1859 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &
result,
const unsigned int nSlots)
1860 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(
result), fAggregators(nSlots, *
result)
1864 AggregateHelper(Acc &
f, Merge &
m,
const std::shared_ptr<U> &
result,
const unsigned int nSlots)
1865 : fAggregate(
f), fMerge(
m), fResult(
result), fAggregators(nSlots, *
result)
1869 AggregateHelper(AggregateHelper &&) =
default;
1870 AggregateHelper(
const AggregateHelper &) =
delete;
1874 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<MustCopyAssign_,
int> = 0>
1875 void Exec(
unsigned int slot,
const T &
value)
1877 fAggregators[slot] = fAggregate(fAggregators[slot],
value);
1880 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<!MustCopyAssign_,
int> = 0>
1881 void Exec(
unsigned int slot,
const T &
value)
1883 fAggregate(fAggregators[slot],
value);
1888 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1889 bool MergeAll = std::is_same<void, MergeRet>::value>
1890 std::enable_if_t<MergeAll, void> Finalize()
1892 fMerge(fAggregators);
1893 *fResult = fAggregators[0];
1896 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1897 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1898 std::enable_if_t<MergeTwoByTwo, void> Finalize(...)
1900 for (
const auto &acc : fAggregators)
1901 *fResult = fMerge(*fResult, acc);
1904 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1906 std::string GetActionName() {
return "Aggregate"; }
1908 AggregateHelper MakeNew(
void *newResult)
1910 auto &
result = *
static_cast<std::shared_ptr<U> *
>(newResult);
1911 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 an RDataFrame computation graph via e....
ROOT type_traits extensions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
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...
__device__ AFloat max(AFloat x, AFloat y)
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)