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>;
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;
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<IsDataContainer<T>::value || std::is_same<T, std::string>::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,
197 typename std::enable_if<IsDataContainer<T>::value && IsDataContainer<W>::value,
int>
::type = 0>
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,
214 typename std::enable_if<IsDataContainer<T>::value && !IsDataContainer<W>::value,
int>
::type = 0>
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,
229 typename std::enable_if<IsDataContainer<W>::value && !IsDataContainer<T>::value,
int>
::type = 0>
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<IsDataContainer<X0>::value || std::is_same<X0, std::string>::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,
310 typename std::enable_if<IsDataContainer<X1>::value && !IsDataContainer<X0>::value,
int>
::type = 0>
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,
318 typename std::enable_if<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int>
::type = 0>
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,
334 typename std::enable_if<IsDataContainer<X0>::value && !IsDataContainer<W>::value,
int>
::type = 0>
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,
344 typename std::enable_if<IsDataContainer<X0>::value && IsDataContainer<X1>::value && IsDataContainer<X2>::value,
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,
362 typename std::enable_if<IsDataContainer<X0>::value && IsDataContainer<X1>::value && !IsDataContainer<W>::value,
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,
379 typename std::enable_if<IsDataContainer<X0>::value && IsDataContainer<X1>::value && IsDataContainer<X2>::value &&
380 IsDataContainer<X3>::value,
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,
399 typename std::enable_if<IsDataContainer<X0>::value && IsDataContainer<X1>::value && IsDataContainer<X2>::value &&
400 !IsDataContainer<W>::value,
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<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int>
::type = 0>
464 void Exec(
unsigned int slot,
const X0 &x0s,
const X1 &x1s)
466 if (x0s.size() != x1s.size()) {
467 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
469 auto thisSlotG = fGraphs[slot];
470 auto x0sIt = std::begin(x0s);
471 const auto x0sEnd = std::end(x0s);
472 auto x1sIt = std::begin(x1s);
473 for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
474 thisSlotG->SetPoint(thisSlotG->GetN(), *x0sIt, *x1sIt);
478 template <
typename X0,
typename X1>
479 void Exec(
unsigned int slot, X0 x0, X1
x1)
481 auto thisSlotG = fGraphs[slot];
482 thisSlotG->SetPoint(thisSlotG->GetN(), x0,
x1);
487 const auto nSlots = fGraphs.size();
488 auto resGraph = fGraphs[0];
491 for (
unsigned int slot = 1; slot < nSlots; ++slot) {
492 l.Add(fGraphs[slot]);
497 std::string GetActionName() {
return "Graph"; }
499 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[slot]; }
508template <
typename V,
typename COLL>
509void FillColl(V&&
v, COLL&
c) {
514template <
typename COLL>
515void FillColl(
bool v, COLL&
c) {
521template <
typename RealT_t,
typename T,
typename COLL>
522class TakeHelper :
public RActionImpl<TakeHelper<RealT_t, T, COLL>> {
523 Results<std::shared_ptr<COLL>> fColls;
527 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
529 fColls.emplace_back(resultColl);
530 for (
unsigned int i = 1; i < nSlots; ++i)
531 fColls.emplace_back(std::make_shared<COLL>());
533 TakeHelper(TakeHelper &&);
534 TakeHelper(
const TakeHelper &) =
delete;
538 void Exec(
unsigned int slot,
T &
v) { FillColl(
v, *fColls[slot]); }
544 auto rColl = fColls[0];
545 for (
unsigned int i = 1; i < fColls.size(); ++i) {
546 const auto &coll = fColls[i];
547 const auto end = coll->end();
550 for (
auto j = coll->begin(); j != end; j++) {
551 FillColl(*j, *rColl);
556 COLL &PartialUpdate(
unsigned int slot) {
return *fColls[slot].get(); }
558 std::string GetActionName() {
return "Take"; }
563template <
typename RealT_t,
typename T>
564class TakeHelper<RealT_t,
T, std::vector<T>> :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
565 Results<std::shared_ptr<std::vector<T>>> fColls;
569 TakeHelper(
const std::shared_ptr<std::vector<T>> &resultColl,
const unsigned int nSlots)
571 fColls.emplace_back(resultColl);
572 for (
unsigned int i = 1; i < nSlots; ++i) {
573 auto v = std::make_shared<std::vector<T>>();
575 fColls.emplace_back(
v);
578 TakeHelper(TakeHelper &&);
579 TakeHelper(
const TakeHelper &) =
delete;
583 void Exec(
unsigned int slot,
T &
v) { FillColl(
v, *fColls[slot]); }
591 for (
auto &coll : fColls)
592 totSize += coll->size();
593 auto rColl = fColls[0];
594 rColl->reserve(totSize);
595 for (
unsigned int i = 1; i < fColls.size(); ++i) {
596 auto &coll = fColls[i];
597 rColl->insert(rColl->end(), coll->begin(), coll->end());
601 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *fColls[slot]; }
603 std::string GetActionName() {
return "Take"; }
608template <
typename RealT_t,
typename COLL>
609class TakeHelper<RealT_t,
RVec<RealT_t>, COLL> :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
610 Results<std::shared_ptr<COLL>> fColls;
614 TakeHelper(
const std::shared_ptr<COLL> &resultColl,
const unsigned int nSlots)
616 fColls.emplace_back(resultColl);
617 for (
unsigned int i = 1; i < nSlots; ++i)
618 fColls.emplace_back(std::make_shared<COLL>());
620 TakeHelper(TakeHelper &&);
621 TakeHelper(
const TakeHelper &) =
delete;
631 auto rColl = fColls[0];
632 for (
unsigned int i = 1; i < fColls.size(); ++i) {
633 auto &coll = fColls[i];
634 for (
auto &
v : *coll) {
635 rColl->emplace_back(
v);
640 std::string GetActionName() {
return "Take"; }
645template <
typename RealT_t>
646class TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>>
647 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
649 Results<std::shared_ptr<std::vector<std::vector<RealT_t>>>> fColls;
653 TakeHelper(
const std::shared_ptr<std::vector<std::vector<RealT_t>>> &resultColl,
const unsigned int nSlots)
655 fColls.emplace_back(resultColl);
656 for (
unsigned int i = 1; i < nSlots; ++i) {
657 auto v = std::make_shared<std::vector<RealT_t>>();
659 fColls.emplace_back(
v);
662 TakeHelper(TakeHelper &&);
663 TakeHelper(
const TakeHelper &) =
delete;
675 for (
auto &coll : fColls)
676 totSize += coll->size();
677 auto rColl = fColls[0];
678 rColl->reserve(totSize);
679 for (
unsigned int i = 1; i < fColls.size(); ++i) {
680 auto &coll = fColls[i];
681 rColl->insert(rColl->end(), coll->begin(), coll->end());
685 std::string GetActionName() {
return "Take"; }
691template <
typename RealT_t,
typename T,
typename COLL>
692TakeHelper<RealT_t, T, COLL>::TakeHelper(TakeHelper<RealT_t, T, COLL> &&) =
default;
693template <
typename RealT_t,
typename T>
694TakeHelper<RealT_t, T, std::vector<T>>::TakeHelper(TakeHelper<RealT_t,
T, std::vector<T>> &&) =
default;
695template <
typename RealT_t,
typename COLL>
696TakeHelper<RealT_t, RVec<RealT_t>, COLL>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, COLL> &&) =
default;
697template <
typename RealT_t>
698TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>::TakeHelper(TakeHelper<RealT_t,
RVec<RealT_t>, std::vector<RealT_t>> &&) =
default;
702extern template class TakeHelper<bool, bool, std::vector<bool>>;
703extern template class TakeHelper<unsigned int, unsigned int, std::vector<unsigned int>>;
704extern template class TakeHelper<unsigned long, unsigned long, std::vector<unsigned long>>;
705extern template class TakeHelper<unsigned long long, unsigned long long, std::vector<unsigned long long>>;
706extern template class TakeHelper<int, int, std::vector<int>>;
707extern template class TakeHelper<long, long, std::vector<long>>;
708extern template class TakeHelper<long long, long long, std::vector<long long>>;
709extern template class TakeHelper<float, float, std::vector<float>>;
710extern template class TakeHelper<double, double, std::vector<double>>;
714template <
typename ResultType>
715class MinHelper :
public RActionImpl<MinHelper<ResultType>> {
716 const std::shared_ptr<ResultType> fResultMin;
717 Results<ResultType> fMins;
720 MinHelper(MinHelper &&) =
default;
721 MinHelper(
const std::shared_ptr<ResultType> &minVPtr,
const unsigned int nSlots)
722 : fResultMin(minVPtr), fMins(nSlots, std::numeric_limits<ResultType>::max())
726 void Exec(
unsigned int slot, ResultType
v) { fMins[slot] = std::min(
v, fMins[slot]); }
730 template <typename T, typename std::enable_if<IsDataContainer<T>::value,
int>
::type = 0>
731 void Exec(
unsigned int slot,
const T &vs)
734 fMins[slot] = std::min(
static_cast<ResultType
>(
v), fMins[slot]);
741 *fResultMin = std::numeric_limits<ResultType>::max();
742 for (
auto &
m : fMins)
743 *fResultMin = std::min(
m, *fResultMin);
746 ResultType &PartialUpdate(
unsigned int slot) {
return fMins[slot]; }
748 std::string GetActionName() {
return "Min"; }
758template <
typename ResultType>
759class MaxHelper :
public RActionImpl<MaxHelper<ResultType>> {
760 const std::shared_ptr<ResultType> fResultMax;
761 Results<ResultType> fMaxs;
764 MaxHelper(MaxHelper &&) =
default;
765 MaxHelper(
const MaxHelper &) =
delete;
766 MaxHelper(
const std::shared_ptr<ResultType> &maxVPtr,
const unsigned int nSlots)
767 : fResultMax(maxVPtr), fMaxs(nSlots, std::numeric_limits<ResultType>::lowest())
772 void Exec(
unsigned int slot, ResultType
v) { fMaxs[slot] = std::max(
v, fMaxs[slot]); }
774 template <typename T, typename std::enable_if<IsDataContainer<T>::value,
int>
::type = 0>
775 void Exec(
unsigned int slot,
const T &vs)
778 fMaxs[slot] = std::max(
static_cast<ResultType
>(
v), fMaxs[slot]);
785 *fResultMax = std::numeric_limits<ResultType>::lowest();
786 for (
auto &
m : fMaxs) {
787 *fResultMax = std::max(
m, *fResultMax);
791 ResultType &PartialUpdate(
unsigned int slot) {
return fMaxs[slot]; }
793 std::string GetActionName() {
return "Max"; }
803template <
typename ResultType>
804class SumHelper :
public RActionImpl<SumHelper<ResultType>> {
805 const std::shared_ptr<ResultType> fResultSum;
806 Results<ResultType> fSums;
811 template <
typename T = ResultType>
812 auto NeutralElement(
const T &
v,
int ) ->
decltype(
v -
v)
817 template <
typename T = ResultType,
typename Dummy =
int>
818 ResultType NeutralElement(
const T &, Dummy)
824 SumHelper(SumHelper &&) =
default;
825 SumHelper(
const SumHelper &) =
delete;
826 SumHelper(
const std::shared_ptr<ResultType> &sumVPtr,
const unsigned int nSlots)
827 : fResultSum(sumVPtr), fSums(nSlots, NeutralElement(*sumVPtr, -1))
832 void Exec(
unsigned int slot, ResultType
v) { fSums[slot] +=
v; }
834 template <typename T, typename std::enable_if<IsDataContainer<T>::value,
int>
::type = 0>
835 void Exec(
unsigned int slot,
const T &vs)
838 fSums[slot] +=
static_cast<ResultType
>(
v);
845 for (
auto &
m : fSums)
849 ResultType &PartialUpdate(
unsigned int slot) {
return fSums[slot]; }
851 std::string GetActionName() {
return "Sum"; }
854class MeanHelper :
public RActionImpl<MeanHelper> {
855 const std::shared_ptr<double> fResultMean;
856 std::vector<ULong64_t> fCounts;
857 std::vector<double> fSums;
858 std::vector<double> fPartialMeans;
861 MeanHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
862 MeanHelper(MeanHelper &&) =
default;
863 MeanHelper(
const MeanHelper &) =
delete;
865 void Exec(
unsigned int slot,
double v);
867 template <typename T, typename std::enable_if<IsDataContainer<T>::value,
int>
::type = 0>
868 void Exec(
unsigned int slot,
const T &vs)
870 for (
auto &&
v : vs) {
880 double &PartialUpdate(
unsigned int slot);
882 std::string GetActionName() {
return "Mean"; }
885extern template void MeanHelper::Exec(
unsigned int,
const std::vector<float> &);
886extern template void MeanHelper::Exec(
unsigned int,
const std::vector<double> &);
887extern template void MeanHelper::Exec(
unsigned int,
const std::vector<char> &);
888extern template void MeanHelper::Exec(
unsigned int,
const std::vector<int> &);
889extern template void MeanHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
891class StdDevHelper :
public RActionImpl<StdDevHelper> {
893 const unsigned int fNSlots;
894 const std::shared_ptr<double> fResultStdDev;
896 std::vector<ULong64_t> fCounts;
898 std::vector<double> fMeans;
900 std::vector<double> fDistancesfromMean;
903 StdDevHelper(
const std::shared_ptr<double> &meanVPtr,
const unsigned int nSlots);
904 StdDevHelper(StdDevHelper &&) =
default;
905 StdDevHelper(
const StdDevHelper &) =
delete;
907 void Exec(
unsigned int slot,
double v);
909 template <typename T, typename std::enable_if<IsDataContainer<T>::value,
int>
::type = 0>
910 void Exec(
unsigned int slot,
const T &vs)
912 for (
auto &&
v : vs) {
921 std::string GetActionName() {
return "StdDev"; }
928extern template void StdDevHelper::Exec(
unsigned int,
const std::vector<unsigned int> &);
930template <
typename PrevNodeType>
931class DisplayHelper :
public RActionImpl<DisplayHelper<PrevNodeType>> {
934 const std::shared_ptr<Display_t> fDisplayerHelper;
935 const std::shared_ptr<PrevNodeType> fPrevNode;
938 DisplayHelper(
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
939 : fDisplayerHelper(
d), fPrevNode(prevNode)
942 DisplayHelper(DisplayHelper &&) =
default;
943 DisplayHelper(
const DisplayHelper &) =
delete;
949 fDisplayerHelper->AddRow(columns...);
950 if (!fDisplayerHelper->HasNext()) {
951 fPrevNode->StopProcessing();
959 std::string GetActionName() {
return "Display"; }
969 std::size_t
fSize = 0;
970 bool *fBools =
nullptr;
975 std::copy(
v.begin(),
v.end(),
b);
979 bool *CopyArray(
bool *o, std::size_t size)
981 auto b =
new bool[size];
982 for (
auto i = 0u; i < size; ++i)
989 BoolArray() =
default;
990 template <
typename T>
991 BoolArray(
const T &) {
throw std::runtime_error(
"This constructor should never be called"); }
993 BoolArray(
const BoolArray &
b)
995 CopyArray(
b.fBools,
b.fSize);
1000 CopyArray(
b.fBools,
b.fSize);
1003 BoolArray(BoolArray &&
b)
1019 ~BoolArray() {
delete[] fBools; }
1020 std::size_t
Size()
const {
return fSize; }
1021 bool *Data() {
return fBools; }
1023using BoolArrayMap = std::map<std::string, BoolArray>;
1025inline bool *UpdateBoolArrayIfBool(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName)
1028 boolArrays[outName] = BoolArray(
v);
1029 return boolArrays[outName].Data();
1032template <
typename T>
1033T *UpdateBoolArrayIfBool(BoolArrayMap &,
RVec<T> &
v,
const std::string &)
1045template <
typename T>
1051template <
typename T>
1057template <
typename T>
1058void SetBranchesHelper(BoolArrayMap &,
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
1059 const std::string &
name,
TBranch *&branch,
void *&branchAddress,
T *address)
1061 auto *inputBranch = inputTree ? inputTree->
GetBranch(inName.c_str()) :
nullptr;
1068 const auto splitLevel = inputBranch->GetSplitLevel();
1070 static TClassRef tbo_cl(
"TBranchObject");
1071 if (inputBranch->IsA() == tbo_cl) {
1073 outputTree.
Branch(
name.c_str(), (
T **)inputBranch->GetAddress(), bufSize, splitLevel);
1075 outputTree.
Branch(
name.c_str(), address, bufSize, splitLevel);
1082 branchAddress =
nullptr;
1094template <
typename T>
1095void SetBranchesHelper(BoolArrayMap &boolArrays,
TTree *inputTree,
TTree &outputTree,
const std::string &inName,
1096 const std::string &outName,
TBranch *&branch,
void *&branchAddress,
RVec<T> *ab)
1098 auto *
const inputBranch = inputTree ? inputTree->
GetBranch(inName.c_str()) :
nullptr;
1099 const bool isTClonesArray = inputBranch !=
nullptr && std::string(inputBranch->GetClassName()) ==
"TClonesArray";
1100 const auto mustWriteStdVec = !inputBranch || isTClonesArray ||
1103 if (mustWriteStdVec) {
1109 if (isTClonesArray) {
1111 "Branch \"%s\" contains TClonesArrays but the type specified to Snapshot was RVec<T>. The branch will "
1112 "be written out as a std::vector instead of a TClonesArray. Specify that the type of the branch is "
1113 "TClonesArray as a Snapshot template parameter to write out a TClonesArray instead.", inName.c_str());
1120 auto *
const leaf =
static_cast<TLeaf *
>(inputBranch->GetListOfLeaves()->UncheckedAt(0));
1121 const auto bname = leaf->
GetName();
1122 const auto counterStr =
1123 leaf->GetLeafCount() ? std::string(leaf->GetLeafCount()->GetName()) : std::to_string(leaf->GetLenStatic());
1124 const auto btype = leaf->GetTypeName();
1126 const auto leaflist = std::string(bname) +
"[" + counterStr +
"]/" + rootbtype;
1130 auto dataPtr = UpdateBoolArrayIfBool(boolArrays, *ab, outName);
1132 auto *
const outputBranch = outputTree.
Branch(outName.c_str(), dataPtr, leaflist.c_str());
1133 outputBranch->
SetTitle(inputBranch->GetTitle());
1136 if (!std::is_same<bool, T>::value) {
1137 branch = outputBranch;
1138 branchAddress = GetData(*ab);
1143template <
typename T>
1144void UpdateBoolArray(BoolArrayMap &,
T&,
const std::string &,
TTree &) {}
1147inline void UpdateBoolArray(BoolArrayMap &boolArrays,
RVec<bool> &
v,
const std::string &outName,
TTree &t)
1150 if (boolArrays.find(outName) == boolArrays.end())
1153 if (
v.size() > boolArrays[outName].Size()) {
1154 boolArrays[outName] = BoolArray(
v);
1158 std::copy(
v.begin(),
v.end(), boolArrays[outName].Data());
1165template <
typename... BranchTypes>
1166class SnapshotHelper :
public RActionImpl<SnapshotHelper<BranchTypes...>> {
1167 const std::string fFileName;
1168 const std::string fDirName;
1169 const std::string fTreeName;
1171 std::unique_ptr<TFile> fOutputFile;
1172 std::unique_ptr<TTree> fOutputTree;
1173 bool fIsFirstEvent{
true};
1174 const ColumnNames_t fInputBranchNames;
1175 const ColumnNames_t fOutputBranchNames;
1176 TTree *fInputTree =
nullptr;
1177 BoolArrayMap fBoolArrays;
1178 std::vector<TBranch *> fBranches;
1179 std::vector<void *> fBranchAddresses;
1182 using ColumnTypes_t =
TypeList<BranchTypes...>;
1184 const ColumnNames_t &vbnames,
const ColumnNames_t &bnames,
const RSnapshotOptions &options)
1185 : fFileName(filename), fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1187 fBranchAddresses(vbnames.size(), nullptr)
1192 SnapshotHelper(
const SnapshotHelper &) =
delete;
1193 SnapshotHelper(SnapshotHelper &&) =
default;
1199 fInputTree =
r->GetTree();
1202 fInputTree->
AddClone(fOutputTree.get());
1205 void Exec(
unsigned int , BranchTypes &... values)
1207 using ind_t = std::index_sequence_for<BranchTypes...>;
1208 if (! fIsFirstEvent) {
1209 UpdateCArraysPtrs(values..., ind_t{});
1211 SetBranches(values..., ind_t{});
1212 fIsFirstEvent =
false;
1214 UpdateBoolArrays(values..., ind_t{});
1215 fOutputTree->Fill();
1218 template <std::size_t...
S>
1219 void UpdateCArraysPtrs(BranchTypes &... values, std::index_sequence<S...> )
1227 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1228 ? fBranches[
S]->SetAddress(GetData(values)),
1229 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1234 template <std::size_t...
S>
1235 void SetBranches(BranchTypes &... values, std::index_sequence<S...> )
1238 int expander[] = {(SetBranchesHelper(fBoolArrays, fInputTree, *fOutputTree, fInputBranchNames[
S],
1239 fOutputBranchNames[
S], fBranches[
S], fBranchAddresses[
S], &values),
1245 template <std::size_t...
S>
1246 void UpdateBoolArrays(BranchTypes &...values, std::index_sequence<S...> )
1248 int expander[] = {(UpdateBoolArray(fBoolArrays, values, fOutputBranchNames[
S], *fOutputTree), 0)..., 0};
1259 if (!fDirName.empty()) {
1262 if (checkupdate ==
"update")
1263 outputDir = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
1265 outputDir = fOutputFile->
mkdir(fDirName.c_str());
1269 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, outputDir);
1272 fOutputTree->SetAutoFlush(fOptions.
fAutoFlush);
1277 if (fOutputFile && fOutputTree) {
1279 fOutputTree->Write();
1281 fOutputTree.reset();
1282 fOutputFile->Close();
1284 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1288 std::string GetActionName() {
return "Snapshot"; }
1292template <
typename... BranchTypes>
1293class SnapshotHelperMT :
public RActionImpl<SnapshotHelperMT<BranchTypes...>> {
1294 const unsigned int fNSlots;
1295 std::unique_ptr<ROOT::Experimental::TBufferMerger> fMerger;
1296 std::vector<std::shared_ptr<ROOT::Experimental::TBufferMergerFile>> fOutputFiles;
1297 std::vector<std::unique_ptr<TTree>> fOutputTrees;
1298 std::vector<int> fIsFirstEvent;
1299 const std::string fFileName;
1300 const std::string fDirName;
1301 const std::string fTreeName;
1303 const ColumnNames_t fInputBranchNames;
1304 const ColumnNames_t fOutputBranchNames;
1305 std::vector<TTree *> fInputTrees;
1306 std::vector<BoolArrayMap> fBoolArrays;
1308 std::vector<std::vector<TBranch *>> fBranches;
1310 std::vector<std::vector<void *>> fBranchAddresses;
1313 using ColumnTypes_t =
TypeList<BranchTypes...>;
1315 std::string_view treename,
const ColumnNames_t &vbnames,
const ColumnNames_t &bnames,
1317 : fNSlots(nSlots), fOutputFiles(fNSlots), fOutputTrees(fNSlots), fIsFirstEvent(fNSlots, 1), fFileName(filename),
1318 fDirName(dirname), fTreeName(treename), fOptions(options), fInputBranchNames(vbnames),
1320 fBranches(fNSlots, std::vector<
TBranch *>(vbnames.size(), nullptr)),
1321 fBranchAddresses(fNSlots, std::vector<
void *>(vbnames.size(), nullptr))
1325 SnapshotHelperMT(
const SnapshotHelperMT &) =
delete;
1326 SnapshotHelperMT(SnapshotHelperMT &&) =
default;
1331 if (!fOutputFiles[slot]) {
1333 fOutputFiles[slot] = fMerger->GetFile();
1335 TDirectory *treeDirectory = fOutputFiles[slot].get();
1336 if (!fDirName.empty()) {
1338 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str(),
"",
true);
1342 fOutputTrees[slot] =
1343 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel, treeDirectory);
1346 fOutputTrees[slot]->SetImplicitMT(
false);
1348 fOutputTrees[slot]->SetAutoFlush(fOptions.
fAutoFlush);
1351 fInputTrees[slot] =
r->GetTree();
1356 const auto friendsListPtr = fInputTrees[slot]->GetListOfFriends();
1357 if (friendsListPtr && friendsListPtr->GetEntries() > 0)
1358 fInputTrees[slot]->AddClone(fOutputTrees[slot].get());
1360 fIsFirstEvent[slot] = 1;
1363 void FinalizeTask(
unsigned int slot)
1365 if (fOutputTrees[slot]->GetEntries() > 0)
1366 fOutputFiles[slot]->
Write();
1368 fOutputTrees[slot].reset(
nullptr);
1371 void Exec(
unsigned int slot, BranchTypes &... values)
1373 using ind_t = std::index_sequence_for<BranchTypes...>;
1374 if (!fIsFirstEvent[slot]) {
1375 UpdateCArraysPtrs(slot, values..., ind_t{});
1377 SetBranches(slot, values..., ind_t{});
1378 fIsFirstEvent[slot] = 0;
1380 UpdateBoolArrays(slot, values..., ind_t{});
1381 fOutputTrees[slot]->Fill();
1382 auto entries = fOutputTrees[slot]->GetEntries();
1383 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
1384 if ((autoFlush > 0) && (entries % autoFlush == 0))
1385 fOutputFiles[slot]->Write();
1388 template <std::size_t...
S>
1389 void UpdateCArraysPtrs(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1398 int expander[] = {(fBranches[slot][
S] && fBranchAddresses[slot][
S] != GetData(values)
1399 ? fBranches[slot][
S]->SetAddress(GetData(values)),
1400 fBranchAddresses[slot][
S] = GetData(values), 0 : 0, 0)...,
1405 template <std::size_t...
S>
1406 void SetBranches(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1410 (SetBranchesHelper(fBoolArrays[slot], fInputTrees[slot], *fOutputTrees[slot], fInputBranchNames[
S],
1411 fOutputBranchNames[
S], fBranches[slot][
S], fBranchAddresses[slot][
S], &values),
1418 template <std::size_t...
S>
1419 void UpdateBoolArrays(
unsigned int slot, BranchTypes &... values, std::index_sequence<S...> )
1423 (UpdateBoolArray(fBoolArrays[slot], values, fOutputBranchNames[
S], *fOutputTrees[slot]), 0)..., 0};
1430 fMerger = std::make_unique<ROOT::Experimental::TBufferMerger>(fFileName.c_str(), fOptions.
fMode.c_str(), cs);
1435 auto fileWritten =
false;
1436 for (
auto &
file : fOutputFiles) {
1445 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
1449 fOutputFiles.clear();
1453 std::string GetActionName() {
return "Snapshot"; }
1456template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1457 bool MustCopyAssign = std::is_same<R, U>::value>
1458class AggregateHelper :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1461 const std::shared_ptr<U> fResult;
1462 Results<U> fAggregators;
1466 AggregateHelper(Acc &&
f, Merge &&
m,
const std::shared_ptr<U> &result,
const unsigned int nSlots)
1467 : fAggregate(std::move(
f)), fMerge(std::move(
m)), fResult(result), fAggregators(nSlots, *result)
1470 AggregateHelper(AggregateHelper &&) =
default;
1471 AggregateHelper(
const AggregateHelper &) =
delete;
1476 void Exec(
unsigned int slot,
const T &value)
1478 fAggregators[slot] = fAggregate(fAggregators[slot], value);
1482 void Exec(
unsigned int slot,
const T &value)
1484 fAggregate(fAggregators[slot], value);
1489 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1490 bool MergeAll = std::is_same<void, MergeRet>::value>
1493 fMerge(fAggregators);
1494 *fResult = fAggregators[0];
1497 template <typename MergeRet = typename CallableTraits<Merge>::ret_type,
1498 bool MergeTwoByTwo = std::is_same<U, MergeRet>::value>
1501 for (
const auto &acc : fAggregators)
1502 *fResult = fMerge(*fResult, acc);
1505 U &PartialUpdate(
unsigned int slot) {
return fAggregators[slot]; }
1507 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.
virtual Int_t GetBasketSize() const
TClassRef is used to implement a permanent reference to a TClass object.
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 TGraph is an object made of two arrays X and Y with npoints each.
1-D histogram with a double per channel (see TH1 documentation)}
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...
RooCmdArg Columns(Int_t ncol)
basic_string_view< char > string_view
CPYCPPYY_EXTERN bool Exec(const std::string &cmd)
std::vector< std::string > ReplaceDotWithUnderscore(const std::vector< std::string > &columnNames)
Replace occurrences of '.
void ValidateSnapshotOutput(const RSnapshotOptions &opts, const std::string &treeName, const std::string &fileName)
char TypeName2ROOTTypeName(const std::string &b)
Convert type name (e.g.
ROOT type_traits extensions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
int CompressionSettings(RCompressionSetting::EAlgorithm algorithm, int compressionLevel)
RooArgSet S(const RooAbsArg &v1)
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.
Lightweight storage for a collection of types.