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;
1077template <
typename T>
1078void SetBranchesHelper(BoolArrayMap &boolArrays,
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
1079 const std::string &outName,
TBranch *&branch,
void *&branchAddress,
RVec<T> *ab)
1081 auto *
const inputBranch = inputTree ? inputTree->
GetBranch(inName.c_str()) :
nullptr;
1082 const bool isTClonesArray = inputBranch !=
nullptr && std::string(inputBranch->GetClassName()) ==
"TClonesArray";
1083 const auto mustWriteStdVec = !inputBranch || isTClonesArray ||
1086 if (mustWriteStdVec) {
1092 if (isTClonesArray) {
1094 "Branch \"%s\" contains TClonesArrays but the type specified to Snapshot was RVec<T>. The branch will "
1095 "be written out as a std::vector instead of a TClonesArray. Specify that the type of the branch is "
1096 "TClonesArray as a Snapshot template parameter to write out a TClonesArray instead.", inName.c_str());
1103 auto *
const leaf =
static_cast<TLeaf *
>(inputBranch->GetListOfLeaves()->UncheckedAt(0));
1104 const auto bname = leaf->
GetName();
1105 const auto counterStr =
1106 leaf->GetLeafCount() ? std::string(leaf->GetLeafCount()->GetName()) : std::to_string(leaf->GetLenStatic());
1107 const auto btype = leaf->GetTypeName();
1109 const auto leaflist = std::string(bname) +
"[" + counterStr +
"]/" + rootbtype;
1113 auto dataPtr = UpdateBoolArrayIfBool(boolArrays, *ab, outName);
1115 auto *
const outputBranch = outputTree.
Branch(outName.c_str(), dataPtr, leaflist.c_str());
1116 outputBranch->
SetTitle(inputBranch->GetTitle());
1119 if (!std::is_same<bool, T>::value) {
1120 branch = outputBranch;
1121 branchAddress = GetData(*ab);
1126template <
typename T>
1127void UpdateBoolArray(BoolArrayMap &,
T&,
const std::string &,
TTree &) {}
1130inline void UpdateBoolArray(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName,
TTree &t)
1132 if (
v.size() > boolArrays[outName].Size()) {
1133 boolArrays[outName] = BoolArray(
v);
1137 std::copy(
v.begin(),
v.end(), boolArrays[outName].Data());
1142template <
typename... BranchTypes>
1143class SnapshotHelper :
public RActionImpl<SnapshotHelper<BranchTypes...>> {
1144 const std::string fFileName;
1145 const std::string fDirName;
1146 const std::string fTreeName;
1148 std::unique_ptr<TFile> fOutputFile;
1149 std::unique_ptr<TTree> fOutputTree;
1150 bool fIsFirstEvent{
true};
1153 TTree *fInputTree =
nullptr;
1154 BoolArrayMap fBoolArrays;
1155 std::vector<TBranch *> fBranches;
1156 std::vector<void *> fBranchAddresses;
1159 using ColumnTypes_t =
TypeList<BranchTypes...>;
1162 : fFileName(filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1164 fBranchAddresses(vbnames.size(), nullptr)
1168 SnapshotHelper(
const SnapshotHelper &) =
delete;
1169 SnapshotHelper(SnapshotHelper &&) =
default;
1175 fInputTree =
r->GetTree();
1178 fInputTree->
AddClone(fOutputTree.get());
1181 void Exec(
unsigned int , BranchTypes &... values)
1183 using ind_t = std::index_sequence_for<BranchTypes...>;
1184 if (! fIsFirstEvent) {
1185 UpdateCArraysPtrs(values..., ind_t{});
1187 SetBranches(values..., ind_t{});
1188 fIsFirstEvent =
false;
1190 UpdateBoolArrays(values..., ind_t{});
1191 fOutputTree->Fill();
1194 template <std::size_t...
S>
1195 void UpdateCArraysPtrs(BranchTypes &... values, std::index_sequence<S...> )
1203 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1204 ? fBranches[
S]->SetAddress(GetData(values)),
1205 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1210 template <std::size_t...
S>
1211 void SetBranches(BranchTypes &... values, std::index_sequence<S...> )
1214 int expander[] = {(SetBranchesHelper(fBoolArrays, fInputTree, *fOutputTree, fInputBranchNames[
S],
1215 fOutputBranchNames[
S], fBranches[
S], fBranchAddresses[
S], &values),
1221 template <std::size_t...
S>
1222 void UpdateBoolArrays(BranchTypes &...values, std::index_sequence<S...> )
1224 int expander[] = {(UpdateBoolArray(fBoolArrays, values, fOutputBranchNames[
S], *fOutputTree), 0)..., 0};
1234 if (!fDirName.empty()) {
1235 fOutputFile->mkdir(fDirName.c_str());
1236 fOutputFile->cd(fDirName.c_str());
1240 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, fOutputFile.get());
1243 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1248 if (fOutputFile && fOutputTree) {
1250 fOutputTree->Write();
1252 fOutputTree.reset();
1253 fOutputFile->Close();
1255 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1259 std::string GetActionName() {
return "Snapshot"; }
1263template <
typename... BranchTypes>
1264class SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<BranchTypes...>> {
1265 const unsigned int fNSlots;
1266 std::unique_ptr<ROOT::Experimental::TBufferMerger> fMerger;
1267 std::vector<std::shared_ptr<ROOT::Experimental::TBufferMergerFile>> fOutputFiles;
1268 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1269 std::vector<int> fIsFirstEvent;
1270 const std::string fFileName;
1271 const std::string fDirName;
1272 const std::string fTreeName;
1276 std::vector<TTree *> fInputTrees;
1277 std::vector<BoolArrayMap> fBoolArrays;
1279 std::vector<std::vector<TBranch *>> fBranches;
1281 std::vector<std::vector<void *>> fBranchAddresses;
1284 using ColumnTypes_t =
TypeList<BranchTypes...>;
1288 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fIsFirstEvent(fNSlots, 1), fFileName(filename),
1289 fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1291 fBranches(fNSlots, std::vector<
TBranch *>(vbnames.size(), nullptr)),
1292 fBranchAddresses(fNSlots, std::vector<
void *>(vbnames.size(), nullptr))
1296 if (checkupdate ==
"update") {
1297 throw std::invalid_argument(
"Snapshot: fMode == \"update\" not supported when implicit MT is enabled");
1300 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1301 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1306 if (!fOutputFiles[slot]) {
1308 fOutputFiles[slot] = fMerger->GetFile();
1310 TDirectory *treeDirectory = fOutputFiles[slot].get();
1311 if (!fDirName.empty()) {
1313 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str(),
"",
true);
1317 fOutputTrees[slot] =
1318 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1321 fOutputTrees[slot]->SetImplicitMT(
false);
1323 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1326 fInputTrees[slot] =
r->GetTree();
1331 const auto friendsListPtr = fInputTrees[slot]->GetListOfFriends();
1332 if (friendsListPtr && friendsListPtr->GetEntries() > 0)
1333 fInputTrees[slot]->AddClone(fOutputTrees[slot].get());
1335 fIsFirstEvent[slot] = 1;
1338 void FinalizeTask(
unsigned int slot)
1340 if (fOutputTrees[slot]->GetEntries() > 0)
1341 fOutputFiles[slot]->
Write();
1343 fOutputTrees[slot].reset(
nullptr);
1346 void Exec(
unsigned int slot, BranchTypes &... values)
1348 using ind_t = std::index_sequence_for<BranchTypes...>;
1349 if (!fIsFirstEvent[slot]) {
1350 UpdateCArraysPtrs(slot, values..., ind_t{});
1352 SetBranches(slot, values..., ind_t{});
1353 fIsFirstEvent[slot] = 0;
1355 UpdateBoolArrays(slot, values..., ind_t{});
1356 fOutputTrees[slot]->Fill();
1357 auto entries = fOutputTrees[slot]->GetEntries();
1358 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1359 if ((autoFlush > 0) && (entries % autoFlush == 0))
1360 fOutputFiles[slot]->Write();
1363 template <std::size_t...
S>
1364 void UpdateCArraysPtrs(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1373 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1374 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1375 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1380 template <std::size_t...
S>
1381 void SetBranches(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1385 (SetBranchesHelper(fBoolArrays[slot], fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[
S],
1386 fOutputBranchNames[
S], fBranches[slot][
S], fBranchAddresses[slot][
S], &values),
1393 template <std::size_t...
S>
1394 void UpdateBoolArrays(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1398 (UpdateBoolArray(fBoolArrays[slot], values, fOutputBranchNames[
S], *fOutputTrees[slot]), 0)..., 0};
1405 fMerger = std::make_unique<ROOT::Experimental::TBufferMerger>(fFileName.c_str(), fOptions.
fMode.c_str(), cs);
1410 auto fileWritten =
false;
1411 for (
auto &
file : fOutputFiles) {
1420 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1424 fOutputFiles.clear();
1428 std::string GetActionName() {
return "Snapshot"; }
1431template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1432 bool MustCopyAssign = std::is_same<R, U>::value>
1433class AggregateHelper :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1436 const std::shared_ptr<U> fResult;
1437 Results<U> fAggregators;
1441 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1442 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(result), fAggregators(nSlots, *result)
1445 AggregateHelper(AggregateHelper &&) =
default;
1446 AggregateHelper(
const AggregateHelper &) =
delete;
1451 void Exec(
unsigned int slot,
const T &value)
1453 fAggregators[slot] = fAggregate(fAggregators[slot], value);
1457 void Exec(
unsigned int slot,
const T &value)
1459 fAggregate(fAggregators[slot], value);
1464 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1465 bool MergeAll = std::is_same<void, MergeRet>::value>
1468 fMerge(fAggregators);
1469 *fResult = fAggregators[0];
1472 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1473 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1476 for (
const auto &acc : fAggregators)
1477 *fResult = fMerge(*fResult, acc);
1480 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1482 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.
Small helper to keep current directory context.
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.
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 void SetTitle(const char *title="")
Set the title of the TNamed.
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.
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 * 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.
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...
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
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.
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.