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);
228 template <
typename T,
typename W,
230 void Exec(
unsigned int,
const T &,
const W &)
232 throw std::runtime_error(
233 "Cannot fill object if the type of the first column is a scalar and the one of the second a container.");
236 Hist_t &PartialUpdate(
unsigned int);
242 std::string GetActionName() {
return "Fill"; }
245extern template void FillHelper::Exec(
unsigned int,
const std::vector<float> &);
246extern template void FillHelper::Exec(
unsigned int,
const std::vector<double> &);
247extern template void FillHelper::Exec(
unsigned int,
const std::vector<char> &);
248extern template void FillHelper::Exec(
unsigned int,
const std::vector<int> &);
249extern template void FillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
250extern template void FillHelper::Exec(
unsigned int,
const std::vector<float> &,
const std::vector<float> &);
251extern template void FillHelper::Exec(
unsigned int,
const std::vector<double> &,
const std::vector<double> &);
252extern template void FillHelper::Exec(
unsigned int,
const std::vector<char> &,
const std::vector<char> &);
253extern template void FillHelper::Exec(
unsigned int,
const std::vector<int> &,
const std::vector<int> &);
255FillHelper::Exec(
unsigned int,
const std::vector<unsigned int> &,
const std::vector<unsigned int> &);
257template <
typename HIST = Hist_t>
258class FillParHelper :
public RActionImpl<FillParHelper<HIST>> {
259 std::vector<HIST *> fObjects;
262 FillParHelper(FillParHelper &&) =
default;
263 FillParHelper(
const FillParHelper &) =
delete;
265 FillParHelper(
const std::shared_ptr<HIST> &
h,
const unsigned int nSlots) : fObjects(nSlots, nullptr)
267 fObjects[0] =
h.get();
269 for (
unsigned int i = 1; i < nSlots; ++i) {
270 fObjects[i] =
new HIST(*fObjects[0]);
271 if (
auto objAsHist =
dynamic_cast<TH1*
>(fObjects[i])) {
272 objAsHist->SetDirectory(
nullptr);
279 void Exec(
unsigned int slot,
double x0)
281 fObjects[slot]->Fill(x0);
284 void Exec(
unsigned int slot,
double x0,
double x1)
286 fObjects[slot]->Fill(x0,
x1);
289 void Exec(
unsigned int slot,
double x0,
double x1,
double x2)
291 fObjects[slot]->Fill(x0,
x1,
x2);
294 void Exec(
unsigned int slot,
double x0,
double x1,
double x2,
double x3)
296 fObjects[slot]->Fill(x0,
x1,
x2,
x3);
299 template <typename X0, typename std::enable_if<IsContainer<X0>::value,
int>
::type = 0>
300 void Exec(
unsigned int slot,
const X0 &x0s)
302 auto thisSlotH = fObjects[slot];
303 for (
auto &x0 : x0s) {
309 template <
typename X0,
typename X1,
311 void Exec(
unsigned int ,
const X0 &,
const X1 &)
313 throw std::runtime_error(
314 "Cannot fill object if the type of the first column is a scalar and the one of the second a container.");
317 template <
typename X0,
typename X1,
319 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
321 auto thisSlotH = fObjects[slot];
322 if (x0s.size() != x1s.size()) {
323 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
325 auto x0sIt = std::begin(x0s);
326 const auto x0sEnd = std::end(x0s);
327 auto x1sIt = std::begin(x1s);
328 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
329 thisSlotH->Fill(*x0sIt, *x1sIt);
333 template <
typename X0,
typename W,
335 void Exec(
unsigned int slot,
const X0 &x0s,
const W w)
337 auto thisSlotH = fObjects[slot];
338 for (
auto &&
x : x0s) {
339 thisSlotH->Fill(
x, w);
343 template <
typename X0,
typename X1,
typename X2,
346 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s)
348 auto thisSlotH = fObjects[slot];
349 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size())) {
350 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
352 auto x0sIt = std::begin(x0s);
353 const auto x0sEnd = std::end(x0s);
354 auto x1sIt = std::begin(x1s);
355 auto x2sIt = std::begin(x2s);
356 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++) {
357 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt);
361 template <
typename X0,
typename X1,
typename W,
364 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const W w)
366 auto thisSlotH = fObjects[slot];
367 if (x0s.size() != x1s.size()) {
368 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
370 auto x0sIt = std::begin(x0s);
371 const auto x0sEnd = std::end(x0s);
372 auto x1sIt = std::begin(x1s);
373 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
374 thisSlotH->Fill(*x0sIt, *x1sIt, w);
378 template <
typename X0,
typename X1,
typename X2,
typename X3,
382 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s,
const X3 &x3s)
384 auto thisSlotH = fObjects[slot];
385 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size() && x1s.size() == x3s.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 auto x3sIt = std::begin(x3s);
393 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++, x3sIt++) {
394 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt, *x3sIt);
398 template <
typename X0,
typename X1,
typename X2,
typename W,
402 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s,
const X2 &x2s,
const W w)
404 auto thisSlotH = fObjects[slot];
405 if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size())) {
406 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
408 auto x0sIt = std::begin(x0s);
409 const auto x0sEnd = std::end(x0s);
410 auto x1sIt = std::begin(x1s);
411 auto x2sIt = std::begin(x2s);
412 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++) {
413 thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt, w);
421 auto resObj = fObjects[0];
422 const auto nSlots = fObjects.size();
425 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
426 l.Add(fObjects[slot]);
432 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[slot]; }
434 std::string GetActionName() {
return "FillPar"; }
437class FillTGraphHelper :
public ROOT::Detail::RDF::RActionImpl<FillTGraphHelper> {
442 std::vector<::TGraph *> fGraphs;
445 FillTGraphHelper(FillTGraphHelper &&) =
default;
446 FillTGraphHelper(
const FillTGraphHelper &) =
delete;
450 FillTGraphHelper(
const std::shared_ptr<::TGraph> &
g,
const unsigned int nSlots) : fGraphs(nSlots, nullptr)
452 fGraphs[0] =
g.get();
454 for (
unsigned int i = 1; i < nSlots; ++i) {
455 fGraphs[i] =
new TGraph(*fGraphs[0]);
462 template <
typename X0,
typename X1,
463 typename std::enable_if<
465 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
467 if (x0s.size() != x1s.size()) {
468 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
470 auto thisSlotG = fGraphs[slot];
471 auto x0sIt = std::begin(x0s);
472 const auto x0sEnd = std::end(x0s);
473 auto x1sIt = std::begin(x1s);
474 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
475 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
479 template <
typename X0,
typename X1>
480 void Exec(
unsigned int slot, X0 x0, X1
x1)
482 auto thisSlotG = fGraphs[slot];
483 thisSlotG->SetPoint(thisSlotG->GetN(), x0,
x1);
488 const auto nSlots = fGraphs.size();
489 auto resGraph = fGraphs[0];
492 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
493 l.Add(fGraphs[slot]);
498 std::string GetActionName() {
return "Graph"; }
500 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
509template <
typename V,
typename COLL>
510void FillColl(V&&
v, COLL&
c) {
515template <
typename COLL>
516void FillColl(
bool v, COLL&
c) {
522template <
typename RealT_t,
typename T,
typename COLL>
523class TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
524 Results<std::shared_ptr<COLL>> fColls;
528 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
530 fColls.emplace_back(resultColl);
531 for (
unsigned int i = 1; i < nSlots; ++i)
532 fColls.emplace_back(std::make_shared<COLL>());
534 TakeHelper(TakeHelper &&);
535 TakeHelper(
const TakeHelper &) =
delete;
539 void Exec(
unsigned int slot,
T &
v) { FillColl(
v, *fColls[slot]); }
545 auto rColl = fColls[0];
546 for (
unsigned int i = 1; i < fColls.size(); ++i) {
547 const auto &coll = fColls[i];
548 const auto end = coll->end();
551 for (
auto j = coll->begin(); j != end; j++) {
552 FillColl(*j, *rColl);
557 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
559 std::string GetActionName() {
return "Take"; }
564template <
typename RealT_t,
typename T>
565class TakeHelper<RealT_t,
T, std::vector<T>> :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
566 Results<std::shared_ptr<std::vector<T>>> fColls;
570 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
572 fColls.emplace_back(resultColl);
573 for (
unsigned int i = 1; i < nSlots; ++i) {
574 auto v = std::make_shared<std::vector<T>>();
576 fColls.emplace_back(
v);
579 TakeHelper(TakeHelper &&);
580 TakeHelper(
const TakeHelper &) =
delete;
584 void Exec(
unsigned int slot,
T &
v) { FillColl(
v, *fColls[slot]); }
592 for (
auto &coll : fColls)
593 totSize += coll->size();
594 auto rColl = fColls[0];
595 rColl->reserve(totSize);
596 for (
unsigned int i = 1; i < fColls.size(); ++i) {
597 auto &coll = fColls[i];
598 rColl->insert(rColl->end(), coll->begin(), coll->end());
602 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
604 std::string GetActionName() {
return "Take"; }
609template <
typename RealT_t,
typename COLL>
610class TakeHelper<RealT_t,
RVec<RealT_t>, COLL> :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
611 Results<std::shared_ptr<COLL>> fColls;
615 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
617 fColls.emplace_back(resultColl);
618 for (
unsigned int i = 1; i < nSlots; ++i)
619 fColls.emplace_back(std::make_shared<COLL>());
621 TakeHelper(TakeHelper &&);
622 TakeHelper(
const TakeHelper &) =
delete;
632 auto rColl = fColls[0];
633 for (
unsigned int i = 1; i < fColls.size(); ++i) {
634 auto &coll = fColls[i];
635 for (
auto &
v : *coll) {
636 rColl->emplace_back(
v);
641 std::string GetActionName() {
return "Take"; }
646template <
typename RealT_t>
647class TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>>
648 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
650 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
654 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
656 fColls.emplace_back(resultColl);
657 for (
unsigned int i = 1; i < nSlots; ++i) {
658 auto v = std::make_shared<std::vector<RealT_t>>();
660 fColls.emplace_back(
v);
663 TakeHelper(TakeHelper &&);
664 TakeHelper(
const TakeHelper &) =
delete;
676 for (
auto &coll : fColls)
677 totSize += coll->size();
678 auto rColl = fColls[0];
679 rColl->reserve(totSize);
680 for (
unsigned int i = 1; i < fColls.size(); ++i) {
681 auto &coll = fColls[i];
682 rColl->insert(rColl->end(), coll->begin(), coll->end());
686 std::string GetActionName() {
return "Take"; }
692template <
typename RealT_t,
typename T,
typename COLL>
693TakeHelper<RealT_t, T, COLL>::TakeHelper(TakeHelper<RealT_t, T, COLL> &&) =
default;
694template <
typename RealT_t,
typename T>
695TakeHelper<RealT_t, T, std::vector<T>>::TakeHelper(TakeHelper<RealT_t,
T, std::vector<T>> &&) =
default;
696template <
typename RealT_t,
typename COLL>
697TakeHelper<RealT_t, RVec<RealT_t>, COLL>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, COLL> &&) =
default;
698template <
typename RealT_t>
699TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>> &&) =
default;
703extern template class TakeHelper<bool, bool, std::vector<bool>>;
704extern template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
705extern template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
706extern template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
707extern template class TakeHelper<int, int, std::vector<int>>;
708extern template class TakeHelper<long, long, std::vector<long>>;
709extern template class TakeHelper<long long, long long, std::vector<long long>>;
710extern template class TakeHelper<float, float, std::vector<float>>;
711extern template class TakeHelper<double, double, std::vector<double>>;
715template <
typename ResultType>
716class MinHelper :
public RActionImpl<MinHelper<ResultType>> {
717 const std::shared_ptr<ResultType> fResultMin;
718 Results<ResultType> fMins;
721 MinHelper(MinHelper &&) =
default;
722 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
723 : fResultMin(minVPtr), fMins(nSlots, std::numeric_limits<ResultType>::max())
727 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
731 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
732 void Exec(
unsigned int slot,
const T &vs)
735 fMins[slot] = std::min(
v, fMins[slot]);
742 *fResultMin = std::numeric_limits<ResultType>::max();
743 for (
auto &
m : fMins)
744 *fResultMin = std::min(
m, *fResultMin);
747 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
749 std::string GetActionName() {
return "Min"; }
759template <
typename ResultType>
760class MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
761 const std::shared_ptr<ResultType> fResultMax;
762 Results<ResultType> fMaxs;
765 MaxHelper(MaxHelper &&) =
default;
766 MaxHelper(
const MaxHelper &) =
delete;
767 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
768 : fResultMax(maxVPtr), fMaxs(nSlots, std::numeric_limits<ResultType>::lowest())
773 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
775 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
776 void Exec(
unsigned int slot,
const T &vs)
779 fMaxs[slot] = std::max((ResultType)
v, fMaxs[slot]);
786 *fResultMax = std::numeric_limits<ResultType>::lowest();
787 for (
auto &
m : fMaxs) {
788 *fResultMax = std::max(
m, *fResultMax);
792 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
794 std::string GetActionName() {
return "Max"; }
804template <
typename ResultType>
805class SumHelper :
public RActionImpl<SumHelper<ResultType>> {
806 const std::shared_ptr<ResultType> fResultSum;
807 Results<ResultType> fSums;
812 template <
typename T = ResultType>
813 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
818 template <
typename T = ResultType,
typename Dummy =
int>
819 ResultType NeutralElement(
const T &, Dummy)
825 SumHelper(SumHelper &&) =
default;
826 SumHelper(
const SumHelper &) =
delete;
827 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
828 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1))
833 void Exec(
unsigned int slot, ResultType
v) { fSums[slot] +=
v; }
835 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
836 void Exec(
unsigned int slot,
const T &vs)
839 fSums[slot] +=
static_cast<ResultType
>(
v);
846 for (
auto &
m : fSums)
850 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
852 std::string GetActionName() {
return "Sum"; }
855class MeanHelper :
public RActionImpl<MeanHelper> {
856 const std::shared_ptr<double> fResultMean;
857 std::vector<ULong64_t> fCounts;
858 std::vector<double> fSums;
859 std::vector<double> fPartialMeans;
862 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
863 MeanHelper(MeanHelper &&) =
default;
864 MeanHelper(
const MeanHelper &) =
delete;
866 void Exec(
unsigned int slot,
double v);
868 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
869 void Exec(
unsigned int slot,
const T &vs)
871 for (
auto &&
v : vs) {
881 double &PartialUpdate(
unsigned int slot);
883 std::string GetActionName() {
return "Mean"; }
886extern template void MeanHelper::Exec(
unsigned int,
const std::vector<float> &);
887extern template void MeanHelper::Exec(
unsigned int,
const std::vector<double> &);
888extern template void MeanHelper::Exec(
unsigned int,
const std::vector<char> &);
889extern template void MeanHelper::Exec(
unsigned int,
const std::vector<int> &);
890extern template void MeanHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
892class StdDevHelper :
public RActionImpl<StdDevHelper> {
894 const unsigned int fNSlots;
895 const std::shared_ptr<double> fResultStdDev;
897 std::vector<ULong64_t> fCounts;
899 std::vector<double> fMeans;
901 std::vector<double> fDistancesfromMean;
904 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
905 StdDevHelper(StdDevHelper &&) =
default;
906 StdDevHelper(
const StdDevHelper &) =
delete;
908 void Exec(
unsigned int slot,
double v);
910 template <typename T, typename std::enable_if<IsContainer<T>::value,
int>
::type = 0>
911 void Exec(
unsigned int slot,
const T &vs)
913 for (
auto &&
v : vs) {
922 std::string GetActionName() {
return "StdDev"; }
925extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<float> &);
926extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<double> &);
927extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<char> &);
928extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<int> &);
929extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
931template <
typename PrevNodeType>
932class DisplayHelper :
public RActionImpl<DisplayHelper<PrevNodeType>> {
935 const std::shared_ptr<Display_t> fDisplayerHelper;
936 const std::shared_ptr<PrevNodeType> fPrevNode;
939 DisplayHelper(
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
940 : fDisplayerHelper(
d), fPrevNode(prevNode)
943 DisplayHelper(DisplayHelper &&) =
default;
944 DisplayHelper(
const DisplayHelper &) =
delete;
948 void Exec(
unsigned int,
Columns... columns)
950 fDisplayerHelper->AddRow(columns...);
951 if (!fDisplayerHelper->HasNext()) {
952 fPrevNode->StopProcessing();
960 std::string GetActionName() {
return "Display"; }
970 std::size_t fSize = 0;
971 bool *fBools =
nullptr;
975 auto b =
new bool[fSize];
976 std::copy(
v.begin(),
v.end(),
b);
980 bool *CopyArray(
bool *o, std::size_t size)
982 auto b =
new bool[size];
983 for (
auto i = 0u; i < size; ++i)
990 BoolArray() =
default;
991 template <
typename T>
992 BoolArray(
const T &) {
throw std::runtime_error(
"This constructor should never be called"); }
993 BoolArray(
const RVec<bool> &
v) : fSize(
v.size()), fBools(CopyVector(
v)) {}
994 BoolArray(
const BoolArray &
b)
996 CopyArray(
b.fBools,
b.fSize);
1001 CopyArray(
b.fBools,
b.fSize);
1004 BoolArray(BoolArray &&
b)
1020 ~BoolArray() {
delete[] fBools; }
1021 std::size_t
Size()
const {
return fSize; }
1022 bool *Data() {
return fBools; }
1024using BoolArrayMap = std::map<std::string, BoolArray>;
1026inline bool *UpdateBoolArrayIfBool(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName)
1029 boolArrays[outName] = BoolArray(
v);
1030 return boolArrays[outName].Data();
1033template <
typename T>
1034T *UpdateBoolArrayIfBool(BoolArrayMap &,
RVec<T> &
v,
const std::string &)
1046template <
typename T>
1052template <
typename T>
1059template <
typename T>
1060void SetBranchesHelper(BoolArrayMap &,
TTree * ,
TTree &outputTree,
const std::string & ,
1061 const std::string &
name,
TBranch *& branch,
void *& branchAddress,
T *address)
1065 branchAddress =
nullptr;
1075template <
typename T>
1076void SetBranchesHelper(BoolArrayMap &boolArrays,
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
1077 const std::string &outName,
TBranch *&branch,
void *&branchAddress,
RVec<T> *ab)
1079 auto *
const inputBranch = inputTree ? inputTree->
GetBranch(inName.c_str()) :
nullptr;
1080 const auto mustWriteStdVec =
1083 if (mustWriteStdVec) {
1092 auto *
const leaf =
static_cast<TLeaf *
>(inputBranch->GetListOfLeaves()->UncheckedAt(0));
1093 const auto bname = leaf->
GetName();
1094 const auto counterStr =
1095 leaf->GetLeafCount() ? std::string(leaf->GetLeafCount()->GetName()) : std::to_string(leaf->GetLenStatic());
1096 const auto btype = leaf->GetTypeName();
1098 const auto leaflist = std::string(bname) +
"[" + counterStr +
"]/" + rootbtype;
1102 auto dataPtr = UpdateBoolArrayIfBool(boolArrays, *ab, outName);
1104 auto *
const outputBranch = outputTree.
Branch(outName.c_str(), dataPtr, leaflist.c_str());
1105 outputBranch->SetTitle(inputBranch->GetTitle());
1108 if (!std::is_same<bool, T>::value) {
1109 branch = outputBranch;
1110 branchAddress = GetData(*ab);
1115template <
typename T>
1116void UpdateBoolArray(BoolArrayMap &,
T&,
const std::string &,
TTree &) {}
1119inline void UpdateBoolArray(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName,
TTree &t)
1121 if (
v.size() > boolArrays[outName].Size()) {
1122 boolArrays[outName] = BoolArray(
v);
1126 std::copy(
v.begin(),
v.end(), boolArrays[outName].Data());
1131template <
typename... BranchTypes>
1132class SnapshotHelper :
public RActionImpl<SnapshotHelper<BranchTypes...>> {
1133 const std::string fFileName;
1134 const std::string fDirName;
1135 const std::string fTreeName;
1137 std::unique_ptr<TFile> fOutputFile;
1138 std::unique_ptr<TTree> fOutputTree;
1139 bool fIsFirstEvent{
true};
1142 TTree *fInputTree =
nullptr;
1143 BoolArrayMap fBoolArrays;
1144 std::vector<TBranch *> fBranches;
1145 std::vector<void *> fBranchAddresses;
1148 using ColumnTypes_t =
TypeList<BranchTypes...>;
1151 : fFileName(filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1153 fBranchAddresses(vbnames.size(), nullptr)
1157 SnapshotHelper(
const SnapshotHelper &) =
delete;
1158 SnapshotHelper(SnapshotHelper &&) =
default;
1164 fInputTree =
r->GetTree();
1167 fInputTree->
AddClone(fOutputTree.get());
1170 void Exec(
unsigned int , BranchTypes &... values)
1172 using ind_t = std::index_sequence_for<BranchTypes...>;
1173 if (! fIsFirstEvent) {
1174 UpdateCArraysPtrs(values..., ind_t{});
1176 SetBranches(values..., ind_t{});
1177 fIsFirstEvent =
false;
1179 UpdateBoolArrays(values..., ind_t{});
1180 fOutputTree->Fill();
1183 template <std::size_t...
S>
1184 void UpdateCArraysPtrs(BranchTypes &... values, std::index_sequence<S...> )
1192 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1193 ? fBranches[
S]->SetAddress(GetData(values)),
1194 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1199 template <std::size_t...
S>
1200 void SetBranches(BranchTypes &... values, std::index_sequence<S...> )
1203 int expander[] = {(SetBranchesHelper(fBoolArrays, fInputTree, *fOutputTree, fInputBranchNames[
S],
1204 fOutputBranchNames[
S], fBranches[
S], fBranchAddresses[
S], &values),
1210 template <std::size_t...
S>
1211 void UpdateBoolArrays(BranchTypes &...values, std::index_sequence<S...> )
1213 int expander[] = {(UpdateBoolArray(fBoolArrays, values, fOutputBranchNames[
S], *fOutputTree), 0)..., 0};
1223 if (!fDirName.empty()) {
1224 fOutputFile->mkdir(fDirName.c_str());
1225 fOutputFile->cd(fDirName.c_str());
1229 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, fOutputFile.get());
1232 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1237 if (fOutputFile && fOutputTree) {
1239 fOutputTree->Write();
1241 fOutputTree.reset();
1242 fOutputFile->Close();
1244 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1248 std::string GetActionName() {
return "Snapshot"; }
1252template <
typename... BranchTypes>
1253class SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<BranchTypes...>> {
1254 const unsigned int fNSlots;
1255 std::unique_ptr<ROOT::Experimental::TBufferMerger> fMerger;
1256 std::vector<std::shared_ptr<ROOT::Experimental::TBufferMergerFile>> fOutputFiles;
1257 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1258 std::vector<int> fIsFirstEvent;
1259 const std::string fFileName;
1260 const std::string fDirName;
1261 const std::string fTreeName;
1265 std::vector<TTree *> fInputTrees;
1266 std::vector<BoolArrayMap> fBoolArrays;
1268 std::vector<std::vector<TBranch *>> fBranches;
1270 std::vector<std::vector<void *>> fBranchAddresses;
1273 using ColumnTypes_t =
TypeList<BranchTypes...>;
1277 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fIsFirstEvent(fNSlots, 1), fFileName(filename),
1278 fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1280 fBranches(fNSlots, std::vector<
TBranch *>(vbnames.size(), nullptr)),
1281 fBranchAddresses(fNSlots, std::vector<
void *>(vbnames.size(), nullptr))
1284 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1285 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1290 if (!fOutputFiles[slot]) {
1292 fOutputFiles[slot] = fMerger->GetFile();
1294 TDirectory *treeDirectory = fOutputFiles[slot].get();
1295 if (!fDirName.empty()) {
1296 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str());
1300 fOutputTrees[slot] =
1301 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1303 fOutputTrees[slot]->SetImplicitMT(
false);
1305 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1308 fInputTrees[slot] =
r->GetTree();
1313 const auto friendsListPtr = fInputTrees[slot]->GetListOfFriends();
1314 if (friendsListPtr && friendsListPtr->GetEntries() > 0)
1315 fInputTrees[slot]->AddClone(fOutputTrees[slot].get());
1317 fIsFirstEvent[slot] = 1;
1320 void FinalizeTask(
unsigned int slot)
1322 if (fOutputTrees[slot]->GetEntries() > 0)
1323 fOutputFiles[slot]->
Write();
1325 fOutputTrees[slot].reset(
nullptr);
1328 void Exec(
unsigned int slot, BranchTypes &... values)
1330 using ind_t = std::index_sequence_for<BranchTypes...>;
1331 if (!fIsFirstEvent[slot]) {
1332 UpdateCArraysPtrs(slot, values..., ind_t{});
1334 SetBranches(slot, values..., ind_t{});
1335 fIsFirstEvent[slot] = 0;
1337 UpdateBoolArrays(slot, values..., ind_t{});
1338 fOutputTrees[slot]->Fill();
1339 auto entries = fOutputTrees[slot]->GetEntries();
1340 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1341 if ((autoFlush > 0) && (entries % autoFlush == 0))
1342 fOutputFiles[slot]->Write();
1345 template <std::size_t...
S>
1346 void UpdateCArraysPtrs(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1354 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1355 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1356 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1361 template <std::size_t...
S>
1362 void SetBranches(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1366 (SetBranchesHelper(fBoolArrays[slot], fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[
S],
1367 fOutputBranchNames[
S], fBranches[slot][
S], fBranchAddresses[slot][
S], &values),
1374 template <std::size_t...
S>
1375 void UpdateBoolArrays(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1378 (UpdateBoolArray(fBoolArrays[slot], values, fOutputBranchNames[
S], *fOutputTrees[slot]), 0)..., 0};
1385 fMerger = std::make_unique<ROOT::Experimental::TBufferMerger>(fFileName.c_str(), fOptions.
fMode.c_str(), cs);
1390 auto fileWritten =
false;
1391 for (
auto &
file : fOutputFiles) {
1400 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1404 fOutputFiles.clear();
1408 std::string GetActionName() {
return "Snapshot"; }
1411template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1412 bool MustCopyAssign = std::is_same<R, U>::value>
1413class AggregateHelper :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1416 const std::shared_ptr<U> fResult;
1417 Results<U> fAggregators;
1421 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1422 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(result), fAggregators(nSlots, *result)
1425 AggregateHelper(AggregateHelper &&) =
default;
1426 AggregateHelper(
const AggregateHelper &) =
delete;
1431 void Exec(
unsigned int slot,
const T &value)
1433 fAggregators[slot] = fAggregate(fAggregators[slot], value);
1437 void Exec(
unsigned int slot,
const T &value)
1439 fAggregate(fAggregators[slot], value);
1444 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1445 bool MergeAll = std::is_same<void, MergeRet>::value>
1448 fMerge(fAggregators);
1449 *fResult = fAggregators[0];
1452 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1453 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1456 for (
const auto &acc : fAggregators)
1457 *fResult = fMerge(*fResult, acc);
1460 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1462 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 columnar datasets such as TTree,...
A TTree represents a columnar dataset.
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
basic_string_view< char > string_view
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)
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.