11#ifndef ROOT_RDFOPERATIONS
12#define ROOT_RDFOPERATIONS
52template <
typename Helper>
56 template <
typename T = Helper>
57 auto CallFinalizeTask(
unsigned int slot) ->
decltype(&T::FinalizeTask,
void())
59 static_cast<Helper *
>(
this)->FinalizeTask(slot);
62 template <
typename... Args>
63 void CallFinalizeTask(
unsigned int, Args...) {}
84using Results =
typename std::conditional<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>
::type;
87class ForeachSlotHelper :
public RActionImpl<ForeachSlotHelper<F>> {
91 using ColumnTypes_t = RemoveFirstParameter_t<typename CallableTraits<F>::arg_types>;
92 ForeachSlotHelper(
F &&
f) : fCallable(
f) {}
93 ForeachSlotHelper(ForeachSlotHelper &&) =
default;
94 ForeachSlotHelper(
const ForeachSlotHelper &) =
delete;
98 template <
typename... Args>
99 void Exec(
unsigned int slot, Args &&... args)
103 fCallable(slot, std::forward<Args>(args)...);
110 std::string GetActionName() {
return "ForeachSlot"; }
113class CountHelper :
public RActionImpl<CountHelper> {
114 const std::shared_ptr<ULong64_t> fResultCount;
115 Results<ULong64_t> fCounts;
119 CountHelper(
const std::shared_ptr<ULong64_t> &resultCount,
const unsigned int nSlots);
120 CountHelper(CountHelper &&) =
default;
121 CountHelper(
const CountHelper &) =
delete;
123 void Exec(
unsigned int slot);
126 ULong64_t &PartialUpdate(
unsigned int slot);
128 std::string GetActionName() {
return "Count"; }
131template <
typename ProxiedVal_t>
132class ReportHelper :
public RActionImpl<ReportHelper<ProxiedVal_t>> {
133 const std::shared_ptr<RCutFlowReport> fReport;
138 std::weak_ptr<ProxiedVal_t> fProxiedWPtr;
139 bool fReturnEmptyReport;
143 ReportHelper(
const std::shared_ptr<RCutFlowReport> &report,
const std::shared_ptr<ProxiedVal_t> &pp,
bool emptyRep)
144 : fReport(report), fProxiedWPtr(pp), fReturnEmptyReport(emptyRep){};
145 ReportHelper(ReportHelper &&) =
default;
146 ReportHelper(
const ReportHelper &) =
delete;
148 void Exec(
unsigned int ) {}
153 if (!fReturnEmptyReport && !fProxiedWPtr.expired())
154 fProxiedWPtr.lock()->Report(*fReport);
157 std::string GetActionName() {
return "Report"; }
160class FillHelper :
public RActionImpl<FillHelper> {
162 static constexpr unsigned int fgTotalBufSize = 2097152;
163 using BufEl_t = double;
164 using Buf_t = std::vector<BufEl_t>;
166 std::vector<Buf_t> fBuffers;
167 std::vector<Buf_t> fWBuffers;
168 const std::shared_ptr<Hist_t> fResultHist;
169 unsigned int fNSlots;
170 unsigned int fBufSize;
172 Results<std::unique_ptr<Hist_t>> fPartialHists;
176 void UpdateMinMax(
unsigned int slot,
double v);
179 FillHelper(
const std::shared_ptr<Hist_t> &
h,
const unsigned int nSlots);
180 FillHelper(FillHelper &&) =
default;
181 FillHelper(
const FillHelper &) =
delete;
183 void Exec(
unsigned int slot,
double v);
184 void Exec(
unsigned int slot,
double v,
double w);
186 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
187 void Exec(
unsigned int slot,
const T &vs)
189 auto &thisBuf = fBuffers[slot];
191 UpdateMinMax(slot,
v);
192 thisBuf.emplace_back(
v);
196 template <
typename T,
typename W,
198 void Exec(
unsigned int slot,
const T &vs,
const W &
ws)
200 auto &thisBuf = fBuffers[slot];
203 UpdateMinMax(slot,
v);
204 thisBuf.emplace_back(
v);
207 auto &thisWBuf = fWBuffers[slot];
209 thisWBuf.emplace_back(w);
213 template <
typename T,
typename W,
215 void Exec(
unsigned int slot,
const T &vs,
const W w)
217 auto &thisBuf = fBuffers[slot];
219 UpdateMinMax(slot,
v);
220 thisBuf.emplace_back(
v);
223 auto &thisWBuf = fWBuffers[slot];
224 thisWBuf.insert(thisWBuf.end(), vs.size(), w);
227 Hist_t &PartialUpdate(
unsigned int);
233 std::string GetActionName() {
return "Fill"; }
236extern template void FillHelper::Exec(
unsigned int,
const std::vector<float> &);
237extern template void FillHelper::Exec(
unsigned int,
const std::vector<double> &);
238extern template void FillHelper::Exec(
unsigned int,
const std::vector<char> &);
239extern template void FillHelper::Exec(
unsigned int,
const std::vector<int> &);
240extern template void FillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
241extern template void FillHelper::Exec(
unsigned int,
const std::vector<float> &,
const std::vector<float> &);
242extern template void FillHelper::Exec(
unsigned int,
const std::vector<double> &,
const std::vector<double> &);
243extern template void FillHelper::Exec(
unsigned int,
const std::vector<char> &,
const std::vector<char> &);
244extern template void FillHelper::Exec(
unsigned int,
const std::vector<int> &,
const std::vector<int> &);
246FillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &,
const std::vector<unsigned int> &);
248template <
typename HIST = Hist_t>
249class FillParHelper :
public RActionImpl<FillParHelper<HIST>> {
250 std::vector<HIST *> fObjects;
253 FillParHelper(FillParHelper &&) =
default;
254 FillParHelper(
const FillParHelper &) =
delete;
256 FillParHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots) : fObjects(nSlots, nullptr)
258 fObjects[0] =
h.get();
260 for (
unsigned int i = 1; i < nSlots; ++i) {
261 fObjects[i] =
new HIST(*fObjects[0]);
262 fObjects[i]->SetDirectory(
nullptr);
268 void Exec(
unsigned int slot,
double x0)
270 fObjects[slot]->Fill(x0);
273 void Exec(
unsigned int slot,
double x0,
double x1)
275 fObjects[slot]->Fill(x0,
x1);
278 void Exec(
unsigned int slot,
double x0,
double x1,
double x2)
280 fObjects[slot]->Fill(x0,
x1,
x2);
283 void Exec(
unsigned int slot,
double x0,
double x1,
double x2,
double x3)
285 fObjects[slot]->Fill(x0,
x1,
x2,
x3);
288 template <typename X0, typename std::enable_if<IsContainer<X0>::value,
int>
::type = 0>
289 void Exec(
unsigned int slot,
const X0 &x0s)
291 auto thisSlotH = fObjects[slot];
292 for (
auto &x0 : x0s) {
297 template <
typename X0,
typename X1,
299 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
301 auto thisSlotH = fObjects[slot];
302 if (x0s.size() != x1s.size()) {
303 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
305 auto x0sIt = std::begin(x0s);
306 const auto x0sEnd = std::end(x0s);
307 auto x1sIt = std::begin(x1s);
308 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
309 thisSlotH->Fill(*x0sIt, *x1sIt);
313 template <
typename X0,
typename W,
315 void Exec(
unsigned int slot,
const X0 &x0s,
const W w)
317 auto thisSlotH = fObjects[slot];
318 for (
auto &&
x : x0s) {
319 thisSlotH->Fill(
x, w);
323 template <
typename X0,
typename X1,
typename X2,
326 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s)
328 auto thisSlotH = fObjects[slot];
329 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size())) {
330 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
332 auto x0sIt = std::begin(x0s);
333 const auto x0sEnd = std::end(x0s);
334 auto x1sIt = std::begin(x1s);
335 auto x2sIt = std::begin(x2s);
336 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++) {
337 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt);
341 template <
typename X0,
typename X1,
typename W,
344 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const W w)
346 auto thisSlotH = fObjects[slot];
347 if (x0s.size() != x1s.size()) {
348 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
350 auto x0sIt = std::begin(x0s);
351 const auto x0sEnd = std::end(x0s);
352 auto x1sIt = std::begin(x1s);
353 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
354 thisSlotH->Fill(*x0sIt, *x1sIt, w);
358 template <
typename X0,
typename X1,
typename X2,
typename X3,
362 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s,
const X3 &x3s)
364 auto thisSlotH = fObjects[slot];
365 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size() && x1s.size() == x3s.size())) {
366 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
368 auto x0sIt = std::begin(x0s);
369 const auto x0sEnd = std::end(x0s);
370 auto x1sIt = std::begin(x1s);
371 auto x2sIt = std::begin(x2s);
372 auto x3sIt = std::begin(x3s);
373 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++, x3sIt++) {
374 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt, *x3sIt);
378 template <
typename X0,
typename X1,
typename X2,
typename W,
382 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s,
const W w)
384 auto thisSlotH = fObjects[slot];
385 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size())) {
386 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
388 auto x0sIt = std::begin(x0s);
389 const auto x0sEnd = std::end(x0s);
390 auto x1sIt = std::begin(x1s);
391 auto x2sIt = std::begin(x2s);
392 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++) {
393 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt, w);
401 auto resObj = fObjects[0];
402 const auto nSlots = fObjects.size();
405 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
406 l.Add(fObjects[slot]);
412 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[slot]; }
414 std::string GetActionName() {
return "FillPar"; }
417class FillTGraphHelper :
public ROOT::Detail::RDF::RActionImpl<FillTGraphHelper> {
422 std::vector<::TGraph *> fGraphs;
425 FillTGraphHelper(FillTGraphHelper &&) =
default;
426 FillTGraphHelper(
const FillTGraphHelper &) =
delete;
430 FillTGraphHelper(
const std::shared_ptr<::TGraph> &
g,
const unsigned int nSlots) : fGraphs(nSlots, nullptr)
432 fGraphs[0] =
g.get();
434 for (
unsigned int i = 1; i < nSlots; ++i) {
435 fGraphs[i] =
new TGraph(*fGraphs[0]);
442 template <
typename X0,
typename X1,
443 typename std::enable_if<
445 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
447 if (x0s.size() != x1s.size()) {
448 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
450 auto thisSlotG = fGraphs[slot];
451 auto x0sIt = std::begin(x0s);
452 const auto x0sEnd = std::end(x0s);
453 auto x1sIt = std::begin(x1s);
454 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
455 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
459 template <
typename X0,
typename X1>
460 void Exec(
unsigned int slot, X0 x0, X1
x1)
462 auto thisSlotG = fGraphs[slot];
463 thisSlotG->SetPoint(thisSlotG->GetN(), x0,
x1);
468 const auto nSlots = fGraphs.size();
469 auto resGraph = fGraphs[0];
472 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
473 l.Add(fGraphs[slot]);
478 std::string GetActionName() {
return "Graph"; }
480 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
491template <
typename RealT_t,
typename T,
typename COLL>
492class TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
493 Results<std::shared_ptr<COLL>> fColls;
497 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
499 fColls.emplace_back(resultColl);
500 for (
unsigned int i = 1; i < nSlots; ++i)
501 fColls.emplace_back(std::make_shared<COLL>());
503 TakeHelper(TakeHelper &&) =
default;
504 TakeHelper(
const TakeHelper &) =
delete;
508 void Exec(
unsigned int slot,
T &
v) { fColls[slot]->emplace_back(
v); }
514 auto rColl = fColls[0];
515 for (
unsigned int i = 1; i < fColls.size(); ++i) {
516 auto &coll = fColls[i];
518 rColl->emplace_back(
v);
523 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
525 std::string GetActionName() {
return "Take"; }
530template <
typename RealT_t,
typename T>
531class TakeHelper<RealT_t,
T,
std::vector<T>> :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
532 Results<std::shared_ptr<std::vector<T>>> fColls;
536 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
538 fColls.emplace_back(resultColl);
539 for (
unsigned int i = 1; i < nSlots; ++i) {
540 auto v = std::make_shared<std::vector<T>>();
542 fColls.emplace_back(
v);
545 TakeHelper(TakeHelper &&) =
default;
546 TakeHelper(
const TakeHelper &) =
delete;
550 void Exec(
unsigned int slot,
T &
v) { fColls[slot]->emplace_back(
v); }
558 for (
auto &coll : fColls)
559 totSize += coll->size();
560 auto rColl = fColls[0];
561 rColl->reserve(totSize);
562 for (
unsigned int i = 1; i < fColls.size(); ++i) {
563 auto &coll = fColls[i];
564 rColl->insert(rColl->end(), coll->begin(), coll->end());
568 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
570 std::string GetActionName() {
return "Take"; }
575template <
typename RealT_t,
typename COLL>
576class TakeHelper<RealT_t,
RVec<RealT_t>, COLL> :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
577 Results<std::shared_ptr<COLL>> fColls;
581 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
583 fColls.emplace_back(resultColl);
584 for (
unsigned int i = 1; i < nSlots; ++i)
585 fColls.emplace_back(std::make_shared<COLL>());
587 TakeHelper(TakeHelper &&) =
default;
588 TakeHelper(
const TakeHelper &) =
delete;
598 auto rColl = fColls[0];
599 for (
unsigned int i = 1; i < fColls.size(); ++i) {
600 auto &coll = fColls[i];
601 for (
auto &
v : *coll) {
602 rColl->emplace_back(
v);
607 std::string GetActionName() {
return "Take"; }
612template <
typename RealT_t>
613class TakeHelper<RealT_t,
RVec<RealT_t>,
std::vector<RealT_t>>
614 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
616 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
620 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
622 fColls.emplace_back(resultColl);
623 for (
unsigned int i = 1; i < nSlots; ++i) {
624 auto v = std::make_shared<std::vector<RealT_t>>();
626 fColls.emplace_back(
v);
629 TakeHelper(TakeHelper &&) =
default;
630 TakeHelper(
const TakeHelper &) =
delete;
642 for (
auto &coll : fColls)
643 totSize += coll->size();
644 auto rColl = fColls[0];
645 rColl->reserve(totSize);
646 for (
unsigned int i = 1; i < fColls.size(); ++i) {
647 auto &coll = fColls[i];
648 rColl->insert(rColl->end(), coll->begin(), coll->end());
652 std::string GetActionName() {
return "Take"; }
655template <
typename ResultType>
656class MinHelper :
public RActionImpl<MinHelper<ResultType>> {
657 const std::shared_ptr<ResultType> fResultMin;
658 Results<ResultType> fMins;
661 MinHelper(MinHelper &&) =
default;
662 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
663 : fResultMin(minVPtr), fMins(nSlots,
std::numeric_limits<ResultType>::max())
667 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
671 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
672 void Exec(
unsigned int slot,
const T &vs)
675 fMins[slot] = std::min(
v, fMins[slot]);
682 *fResultMin = std::numeric_limits<ResultType>::max();
683 for (
auto &
m : fMins)
684 *fResultMin = std::min(
m, *fResultMin);
687 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
689 std::string GetActionName() {
return "Min"; }
699template <
typename ResultType>
700class MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
701 const std::shared_ptr<ResultType> fResultMax;
702 Results<ResultType> fMaxs;
705 MaxHelper(MaxHelper &&) =
default;
706 MaxHelper(
const MaxHelper &) =
delete;
707 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
708 : fResultMax(maxVPtr), fMaxs(nSlots,
std::numeric_limits<ResultType>::lowest())
713 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
715 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
716 void Exec(
unsigned int slot,
const T &vs)
719 fMaxs[slot] = std::max((ResultType)
v, fMaxs[slot]);
726 *fResultMax = std::numeric_limits<ResultType>::lowest();
727 for (
auto &
m : fMaxs) {
728 *fResultMax = std::max(
m, *fResultMax);
732 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
734 std::string GetActionName() {
return "Max"; }
744template <
typename ResultType>
745class SumHelper :
public RActionImpl<SumHelper<ResultType>> {
746 const std::shared_ptr<ResultType> fResultSum;
747 Results<ResultType> fSums;
752 template <
typename T = ResultType>
753 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
758 template <
typename T = ResultType,
typename Dummy =
int>
759 ResultType NeutralElement(
const T &, Dummy)
765 SumHelper(SumHelper &&) =
default;
766 SumHelper(
const SumHelper &) =
delete;
767 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
768 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1))
773 void Exec(
unsigned int slot, ResultType
v) { fSums[slot] +=
v; }
775 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
776 void Exec(
unsigned int slot,
const T &vs)
779 fSums[slot] +=
static_cast<ResultType
>(
v);
786 for (
auto &
m : fSums)
790 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
792 std::string GetActionName() {
return "Sum"; }
795class MeanHelper :
public RActionImpl<MeanHelper> {
796 const std::shared_ptr<double> fResultMean;
797 std::vector<ULong64_t> fCounts;
798 std::vector<double> fSums;
799 std::vector<double> fPartialMeans;
802 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
803 MeanHelper(MeanHelper &&) =
default;
804 MeanHelper(
const MeanHelper &) =
delete;
806 void Exec(
unsigned int slot,
double v);
808 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
809 void Exec(
unsigned int slot,
const T &vs)
811 for (
auto &&
v : vs) {
821 double &PartialUpdate(
unsigned int slot);
823 std::string GetActionName() {
return "Mean"; }
826extern template void MeanHelper::Exec(
unsigned int,
const std::vector<float> &);
827extern template void MeanHelper::Exec(
unsigned int,
const std::vector<double> &);
828extern template void MeanHelper::Exec(
unsigned int,
const std::vector<char> &);
829extern template void MeanHelper::Exec(
unsigned int,
const std::vector<int> &);
830extern template void MeanHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
832class StdDevHelper :
public RActionImpl<StdDevHelper> {
834 const unsigned int fNSlots;
835 const std::shared_ptr<double> fResultStdDev;
837 std::vector<ULong64_t> fCounts;
839 std::vector<double> fMeans;
841 std::vector<double> fDistancesfromMean;
844 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
845 StdDevHelper(StdDevHelper &&) =
default;
846 StdDevHelper(
const StdDevHelper &) =
delete;
848 void Exec(
unsigned int slot,
double v);
850 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
851 void Exec(
unsigned int slot,
const T &vs)
853 for (
auto &&
v : vs) {
862 std::string GetActionName() {
return "StdDev"; }
865extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<float> &);
866extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<double> &);
867extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<char> &);
868extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<int> &);
869extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
871template <
typename PrevNodeType>
872class DisplayHelper :
public RActionImpl<DisplayHelper<PrevNodeType>> {
875 const std::shared_ptr<Display_t> fDisplayerHelper;
876 const std::shared_ptr<PrevNodeType> fPrevNode;
879 DisplayHelper(
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
880 : fDisplayerHelper(
d), fPrevNode(prevNode)
883 DisplayHelper(DisplayHelper &&) =
default;
884 DisplayHelper(
const DisplayHelper &) =
delete;
888 void Exec(
unsigned int,
Columns... columns)
890 fDisplayerHelper->AddRow(columns...);
891 if (!fDisplayerHelper->HasNext()) {
892 fPrevNode->StopProcessing();
900 std::string GetActionName() {
return "Display"; }
910 std::size_t fSize = 0;
911 bool *fBools =
nullptr;
915 auto b =
new bool[fSize];
916 std::copy(
v.begin(),
v.end(),
b);
920 bool *CopyArray(
bool *o, std::size_t size)
922 auto b =
new bool[size];
923 for (
auto i = 0u; i < size; ++i)
930 BoolArray() =
default;
931 template <
typename T>
932 BoolArray(
const T &) {
throw std::runtime_error(
"This constructor should never be called"); }
933 BoolArray(
const RVec<bool> &
v) : fSize(
v.size()), fBools(CopyVector(
v)) {}
934 BoolArray(
const BoolArray &
b)
936 CopyArray(
b.fBools,
b.fSize);
941 CopyArray(
b.fBools,
b.fSize);
944 BoolArray(BoolArray &&
b)
960 ~BoolArray() {
delete[] fBools; }
961 std::size_t
Size()
const {
return fSize; }
962 bool *Data() {
return fBools; }
964using BoolArrayMap = std::map<std::string, BoolArray>;
966inline bool *UpdateBoolArrayIfBool(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName)
969 boolArrays[outName] = BoolArray(
v);
970 return boolArrays[outName].Data();
974T *UpdateBoolArrayIfBool(BoolArrayMap &,
RVec<T> &
v,
const std::string &)
1000void SetBranchesHelper(BoolArrayMap &, TTree * , TTree &outputTree,
const std::string & ,
1001 const std::string &
name,
TBranch *& branch,
void *& branchAddress,
T *address)
1003 outputTree.Branch(
name.c_str(), address);
1005 branchAddress =
nullptr;
1015template <
typename T>
1016void SetBranchesHelper(BoolArrayMap &boolArrays, TTree *inputTree, TTree &outputTree,
const std::string &inName,
1017 const std::string &outName,
TBranch *&branch,
void *&branchAddress,
RVec<T> *ab)
1019 auto *
const inputBranch = inputTree ? inputTree->GetBranch(inName.c_str()) :
nullptr;
1020 const auto mustWriteStdVec =
1023 if (mustWriteStdVec) {
1027 outputTree.Branch(outName.c_str(), &ab->
AsVector());
1032 auto *
const leaf =
static_cast<TLeaf *
>(inputBranch->GetListOfLeaves()->UncheckedAt(0));
1033 const auto bname = leaf->
GetName();
1034 const auto counterStr =
1035 leaf->GetLeafCount() ? std::string(leaf->GetLeafCount()->GetName()) :
std::to_string(leaf->GetLenStatic());
1036 const auto btype = leaf->GetTypeName();
1038 const auto leaflist = std::string(bname) +
"[" + counterStr +
"]/" + rootbtype;
1042 auto dataPtr = UpdateBoolArrayIfBool(boolArrays, *ab, outName);
1044 auto *
const outputBranch = outputTree.Branch(outName.c_str(), dataPtr, leaflist.c_str());
1045 outputBranch->SetTitle(inputBranch->GetTitle());
1048 if (!std::is_same<bool, T>::value) {
1049 branch = outputBranch;
1050 branchAddress = GetData(*ab);
1055template <
typename T>
1056void UpdateBoolArray(BoolArrayMap &,
T&,
const std::string &, TTree &) {}
1059inline void UpdateBoolArray(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName, TTree &t)
1061 if (
v.size() > boolArrays[outName].Size()) {
1062 boolArrays[outName] = BoolArray(
v);
1063 t.SetBranchAddress(outName.c_str(), boolArrays[outName].Data());
1066 std::copy(
v.begin(),
v.end(), boolArrays[outName].Data());
1071template <
typename... BranchTypes>
1072class SnapshotHelper :
public RActionImpl<SnapshotHelper<BranchTypes...>> {
1073 const std::string fFileName;
1074 const std::string fDirName;
1075 const std::string fTreeName;
1077 std::unique_ptr<TFile> fOutputFile;
1078 std::unique_ptr<TTree> fOutputTree;
1079 bool fIsFirstEvent{
true};
1082 TTree *fInputTree =
nullptr;
1083 BoolArrayMap fBoolArrays;
1084 std::vector<TBranch *> fBranches;
1085 std::vector<void *> fBranchAddresses;
1088 using ColumnTypes_t =
TypeList<BranchTypes...>;
1091 : fFileName(filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1093 fBranchAddresses(vbnames.size(), nullptr)
1097 SnapshotHelper(
const SnapshotHelper &) =
delete;
1098 SnapshotHelper(SnapshotHelper &&) =
default;
1104 fInputTree =
r->GetTree();
1107 fInputTree->AddClone(fOutputTree.get());
1110 void Exec(
unsigned int , BranchTypes &... values)
1113 if (! fIsFirstEvent) {
1114 UpdateCArraysPtrs(values..., ind_t{});
1116 SetBranches(values..., ind_t{});
1117 fIsFirstEvent =
false;
1119 UpdateBoolArrays(values..., ind_t{});
1120 fOutputTree->Fill();
1123 template <std::size_t...
S>
1132 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1133 ? fBranches[
S]->SetAddress(GetData(values)),
1134 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1139 template <std::size_t...
S>
1143 int expander[] = {(SetBranchesHelper(fBoolArrays, fInputTree, *fOutputTree, fInputBranchNames[
S],
1144 fOutputBranchNames[
S], fBranches[
S], fBranchAddresses[
S], &values),
1150 template <std::size_t...
S>
1153 int expander[] = {(UpdateBoolArray(fBoolArrays, values, fOutputBranchNames[
S], *fOutputTree), 0)..., 0};
1163 if (!fDirName.empty()) {
1164 fOutputFile->mkdir(fDirName.c_str());
1165 fOutputFile->cd(fDirName.c_str());
1169 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, fOutputFile.get());
1172 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1177 if (fOutputFile && fOutputTree) {
1179 fOutputTree->Write();
1181 fOutputTree.reset();
1182 fOutputFile->Close();
1184 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1188 std::string GetActionName() {
return "Snapshot"; }
1192template <
typename... BranchTypes>
1193class SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<BranchTypes...>> {
1194 const unsigned int fNSlots;
1195 std::unique_ptr<ROOT::Experimental::TBufferMerger> fMerger;
1196 std::vector<std::shared_ptr<ROOT::Experimental::TBufferMergerFile>> fOutputFiles;
1197 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1198 std::vector<int> fIsFirstEvent;
1199 const std::string fFileName;
1200 const std::string fDirName;
1201 const std::string fTreeName;
1205 std::vector<TTree *> fInputTrees;
1206 std::vector<BoolArrayMap> fBoolArrays;
1208 std::vector<std::vector<TBranch *>> fBranches;
1210 std::vector<std::vector<void *>> fBranchAddresses;
1213 using ColumnTypes_t =
TypeList<BranchTypes...>;
1217 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fIsFirstEvent(fNSlots, 1), fFileName(filename),
1218 fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1220 fBranches(fNSlots,
std::vector<
TBranch *>(vbnames.size(), nullptr)),
1221 fBranchAddresses(fNSlots,
std::vector<
void *>(vbnames.size(), nullptr))
1224 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1225 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1230 if (!fOutputFiles[slot]) {
1232 fOutputFiles[slot] = fMerger->GetFile();
1234 TDirectory *treeDirectory = fOutputFiles[slot].get();
1235 if (!fDirName.empty()) {
1236 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str());
1240 fOutputTrees[slot] =
1241 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1243 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1246 fInputTrees[slot] =
r->GetTree();
1251 const auto friendsListPtr = fInputTrees[slot]->GetListOfFriends();
1252 if (friendsListPtr && friendsListPtr->GetEntries() > 0)
1253 fInputTrees[slot]->AddClone(fOutputTrees[slot].get());
1255 fIsFirstEvent[slot] = 1;
1258 void FinalizeTask(
unsigned int slot)
1260 if (fOutputTrees[slot]->GetEntries() > 0)
1261 fOutputFiles[slot]->
Write();
1263 fOutputTrees[slot].reset(
nullptr);
1266 void Exec(
unsigned int slot, BranchTypes &... values)
1269 if (!fIsFirstEvent[slot]) {
1270 UpdateCArraysPtrs(slot, values..., ind_t{});
1272 SetBranches(slot, values..., ind_t{});
1273 fIsFirstEvent[slot] = 0;
1275 UpdateBoolArrays(slot, values..., ind_t{});
1276 fOutputTrees[slot]->Fill();
1277 auto entries = fOutputTrees[slot]->GetEntries();
1278 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1279 if ((autoFlush > 0) && (entries % autoFlush == 0))
1280 fOutputFiles[slot]->Write();
1283 template <std::size_t...
S>
1292 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1293 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1294 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1299 template <std::size_t...
S>
1304 (SetBranchesHelper(fBoolArrays[slot], fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[
S],
1305 fOutputBranchNames[
S], fBranches[slot][
S], fBranchAddresses[slot][
S], &values),
1312 template <std::size_t...
S>
1316 (UpdateBoolArray(fBoolArrays[slot], values, fOutputBranchNames[
S], *fOutputTrees[slot]), 0)..., 0};
1323 fMerger = std::make_unique<ROOT::Experimental::TBufferMerger>(fFileName.c_str(), fOptions.
fMode.c_str(), cs);
1328 auto fileWritten =
false;
1329 for (
auto &
file : fOutputFiles) {
1338 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1342 fOutputFiles.clear();
1346 std::string GetActionName() {
return "Snapshot"; }
1349template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1350 bool MustCopyAssign = std::is_same<R, U>::value>
1351class AggregateHelper :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1354 const std::shared_ptr<U> fResult;
1355 Results<U> fAggregators;
1359 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1360 : fAggregate(
std::move(
f)), fMerge(
std::move(
m)), fResult(result), fAggregators(nSlots, *result)
1363 AggregateHelper(AggregateHelper &&) =
default;
1364 AggregateHelper(
const AggregateHelper &) =
delete;
1369 void Exec(
unsigned int slot,
const T &value)
1371 fAggregators[slot] = fAggregate(fAggregators[slot], value);
1375 void Exec(
unsigned int slot,
const T &value)
1377 fAggregate(fAggregators[slot], value);
1382 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1383 bool MergeAll = std::is_same<void, MergeRet>::value>
1386 fMerge(fAggregators);
1387 *fResult = fAggregators[0];
1390 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1391 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1394 for (
const auto &acc : fAggregators)
1395 *fResult = fMerge(*fResult, acc);
1398 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1400 std::string GetActionName() {
return "Aggregate"; }
#define R(a, b, c, d, e, f, g, h, i)
static const double x2[5]
static const double x1[5]
static const double x3[11]
unsigned long long ULong64_t
void Warning(const char *location, const char *msgfmt,...)
Binding & operator=(OUT(*fun)(void))
typedef void((*Func_t)())
This class is the textual representation of the content of a columnar dataset.
A "std::vector"-like collection of values implementing handy operation to analyse them.
const Impl_t & AsVector() const
iterator begin() noexcept
A TTree is a list of TBranches.
Describe directory structure in memory.
virtual TDirectory * mkdir(const char *name, const char *title="")
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::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
A Graph is a graphics object made of two arrays X and Y with npoints each.
1-D histogram with a double per channel (see TH1 documentation)}
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
virtual const char * GetName() const
Returns name of object.
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
A simple, robust and fast interface to read values from ROOT colmnar datasets such as TTree,...
std::vector< std::string > ReplaceDotWithUnderscore(const std::vector< std::string > &columnNames)
Replace occurrences of '.
char TypeName2ROOTTypeName(const std::string &b)
Convert type name (e.g.
ROOT type_traits extensions.
Namespace for new ROOT classes and functions.
ROOT::Detail::RDF::ColumnNames_t ColumnNames_t
int CompressionSettings(RCompressionSetting::EAlgorithm algorithm, int compressionLevel)
RooArgSet S(const RooAbsArg &v1)
RooCmdArg Columns(Int_t ncol)
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)
make_index_sequence< sizeof...(_Tp)> index_sequence_for
basic_string_view< char > string_view
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.
int fCompressionLevel
Compression level of output file.
Check for container traits.
Lightweight storage for a collection of types.