19#ifndef ROOT_RDFOPERATIONS
20#define ROOT_RDFOPERATIONS
75 std::vector<TBranch *> fBranches;
76 std::vector<std::string> fNames;
81 auto it = std::find(fNames.begin(), fNames.end(),
name);
82 if (it == fNames.end())
84 return fBranches[std::distance(fNames.begin(), it)];
87 void Insert(
const std::string &
name,
TBranch *address)
89 if (address ==
nullptr) {
90 throw std::logic_error(
"Trying to insert a null branch address.");
92 if (std::find(fBranches.begin(), fBranches.end(), address) != fBranches.end()) {
93 throw std::logic_error(
"Trying to insert a branch address that's already present.");
95 if (std::find(fNames.begin(), fNames.end(),
name) != fNames.end()) {
96 throw std::logic_error(
"Trying to insert a branch name that's already present.");
98 fNames.emplace_back(
name);
99 fBranches.emplace_back(address);
112 [](
TBranch *
b) { return b->GetAddress() == nullptr; });
121 std::string
msg =
"RDataFrame::Snapshot:";
124 " is needed as it provides the size for one or more branches containing dynamically sized arrays, but "
130 msg.resize(
msg.size() - 2);
132 " are needed as they provide the size of other branches containing dynamically sized arrays, but they are";
134 msg +=
" not part of the set of branches that are being written out.";
135 throw std::runtime_error(
msg);
144using Results = std::conditional_t<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>;
158 template <
typename... Args>
159 void Exec(
unsigned int slot, Args &&... args)
162 static_assert(std::is_same<TypeList<std::decay_t<Args>...>, ColumnTypes_t>
::value,
"");
170 std::string GetActionName() {
return "ForeachSlot"; }
190 return std::make_unique<RMergeableCount>(*
fResultCount);
195 std::string GetActionName() {
return "Count"; }
204template <
typename RNode_t>
206 std::shared_ptr<RCutFlowReport>
fReport;
219 void Exec(
unsigned int ) {}
227 std::string GetActionName() {
return "Report"; }
231 auto &&
result = *
static_cast<std::shared_ptr<RCutFlowReport> *
>(
newResult);
233 std::static_pointer_cast<RNode_t>(fNode->GetVariedFilter(std::string(
variation))).get(),
249 using Buf_t = std::vector<BufEl_t>;
251 std::vector<Buf_t> fBuffers;
254 unsigned int fNSlots;
255 unsigned int fBufSize;
269 void Exec(
unsigned int slot,
double v,
double w);
283 void Exec(
unsigned int slot,
const T &
vs,
const W &ws)
312 void Exec(
unsigned int slot,
const T
v,
const W &ws)
322 Hist_t &PartialUpdate(
unsigned int);
331 return std::make_unique<RMergeableFill<Hist_t>>(*fResultHist);
334 std::string GetActionName()
343 result->SetDirectory(
nullptr);
350template <
typename HIST = Hist_t>
352 std::vector<HIST *> fObjects;
365 throw std::runtime_error(
366 "A systematic variation was requested for a custom Fill action, but the type of the object to be filled does "
367 "not implement a Reset method, so we cannot safely re-initialize variations of the result. Aborting.");
371 h->SetDirectory(
nullptr);
378 auto Merge(std::vector<H *> &
objs,
int )
388 template <
typename H>
389 auto Merge(std::vector<H *> &
objs,
double )
390 ->
decltype(
objs[0]->Merge(std::vector<HIST *>{}),
void())
396 template <
typename T>
399 static_assert(
sizeof(T) < 0,
400 "The type passed to Fill does not provide a Merge(TCollection*) or Merge(const std::vector&) method.");
404 template <
typename T>
429 return std::begin(val);
434 std::size_t GetSize(
const T &)
441 std::size_t GetSize(
const T &val)
443#if __cplusplus >= 201703L
444 return std::size(val);
450 template <std::size_t
ColIdx,
typename End_t,
typename...
Its>
456 auto nop = [](
auto &&...) {};
468 fObjects[0] =
h.get();
470 for (
unsigned int i = 1; i <
nSlots; ++i) {
471 fObjects[i] =
new HIST(*fObjects[0]);
479 template <
typename...
ValTypes, std::enable_if_t<!Disjunction<IsDataContainer<ValTypes>...>
::value,
int> = 0>
482 fObjects[
slot]->Fill(
x...);
486 template <
typename...
Xs, std::enable_if_t<Disjunction<IsDataContainer<Xs>...>
::value,
int> = 0>
490 constexpr std::array<
bool,
sizeof...(Xs)>
isContainer{IsDataContainer<Xs>::value...};
495 static_assert(
colidx <
sizeof...(Xs),
"Error: index of collection-type argument not found.");
501 std::array<std::size_t,
sizeof...(xs)>
sizes = {{GetSize(
xs)...}};
503 for (std::size_t i = 0; i <
sizeof...(xs); ++i) {
505 throw std::runtime_error(
"Cannot fill histogram with values in containers of different sizes.");
512 template <
typename T = HIST>
515 static_assert(
sizeof(T) < 0,
516 "When filling an object with RDataFrame (e.g. via a Fill action) the number or types of the "
517 "columns passed did not match the signature of the object's `Fill` method.");
524 if (fObjects.size() == 1)
530 for (
auto it = ++fObjects.begin(); it != fObjects.end(); ++it)
534 HIST &PartialUpdate(
unsigned int slot) {
return *fObjects[
slot]; }
539 return std::make_unique<RMergeableFill<HIST>>(*fObjects[0]);
544 std::string GetActionName()
546 return std::string(fObjects[0]->
IsA()->GetName()) +
"\\n" + std::string(fObjects[0]->GetName());
551 std::string GetActionName()
553 return "Fill custom object";
556 template <
typename H = HIST>
571 std::vector<::TGraph *> fGraphs;
579 fGraphs[0] =
g.get();
581 for (
unsigned int i = 1; i <
nSlots; ++i) {
582 fGraphs[i] =
new TGraph(*fGraphs[0]);
590 template <
typename X0,
typename X1,
591 std::enable_if_t<IsDataContainer<X0>::value && IsDataContainer<X1>::value,
int> = 0>
594 if (
x0s.size() !=
x1s.size()) {
595 throw std::runtime_error(
"Cannot fill Graph with values in containers of different sizes.");
607 template <
typename X0,
typename X1,
608 std::enable_if_t<!IsDataContainer<X0>::value && !IsDataContainer<X1>::value,
int> = 0>
620 throw std::runtime_error(
"Graph was applied to a mix of scalar values and collections. This is not supported.");
625 const auto nSlots = fGraphs.size();
630 l.Add(fGraphs[
slot]);
638 return std::make_unique<RMergeableFill<Result_t>>(*fGraphs[0]);
641 std::string GetActionName() {
return "Graph"; }
643 Result_t &PartialUpdate(
unsigned int slot) {
return *fGraphs[
slot]; }
670 for (
unsigned int i = 1; i <
nSlots; ++i) {
680 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
681 std::enable_if_t<IsDataContainer<X>::value && IsDataContainer<Y>::value && IsDataContainer<EXL>::value &&
682 IsDataContainer<EXH>::value && IsDataContainer<EYL>::value && IsDataContainer<EYH>::value,
687 if ((
xs.size() !=
ys.size()) || (
xs.size() !=
exls.size()) || (
xs.size() !=
exhs.size()) ||
688 (
xs.size() !=
eyls.size()) || (
xs.size() !=
eyhs.size())) {
689 throw std::runtime_error(
"Cannot fill GraphAsymmErrors with values in containers of different sizes.");
692 auto xsIt = std::begin(
xs);
693 auto ysIt = std::begin(
ys);
698 while (
xsIt != std::end(
xs)) {
707 typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
708 std::enable_if_t<!IsDataContainer<X>::value && !IsDataContainer<Y>::value && !IsDataContainer<EXL>::value &&
709 !IsDataContainer<EXH>::value && !IsDataContainer<EYL>::value && !IsDataContainer<EYH>::value,
721 template <
typename X,
typename Y,
typename EXL,
typename EXH,
typename EYL,
typename EYH,
725 throw std::runtime_error(
726 "GraphAsymmErrors was applied to a mix of scalar values and collections. This is not supported.");
747 std::string GetActionName() {
return "GraphAsymmErrors"; }
753 auto &
result = *
static_cast<std::shared_ptr<TGraphAsymmErrors> *
>(
newResult);
765template <
typename V,
typename COLL>
771template <
typename COLL>
778template <
typename RealT_t,
typename T,
typename COLL>
787 for (
unsigned int i = 1; i <
nSlots; ++i)
788 fColls.emplace_back(std::make_shared<COLL>());
802 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
815 std::string GetActionName() {
return "Take"; }
827template <
typename RealT_t,
typename T>
829 :
public RActionImpl<TakeHelper<RealT_t, T, std::vector<T>>> {
837 for (
unsigned int i = 1; i <
nSlots; ++i) {
838 auto v = std::make_shared<std::vector<T>>();
860 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
866 std::vector<T> &PartialUpdate(
unsigned int slot) {
return *
fColls[
slot]; }
868 std::string GetActionName() {
return "Take"; }
872 auto &
result = *
static_cast<std::shared_ptr<std::vector<T>
> *>(
newResult);
880template <
typename RealT_t,
typename COLL>
882 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, COLL>> {
890 for (
unsigned int i = 1; i <
nSlots; ++i)
891 fColls.emplace_back(std::make_shared<COLL>());
905 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
907 for (
auto &
v : *
coll) {
913 std::string GetActionName() {
return "Take"; }
925template <
typename RealT_t>
927 :
public RActionImpl<TakeHelper<RealT_t, RVec<RealT_t>, std::vector<RealT_t>>> {
936 for (
unsigned int i = 1; i <
nSlots; ++i) {
937 auto v = std::make_shared<std::vector<RealT_t>>();
959 for (
unsigned int i = 1; i <
fColls.size(); ++i) {
965 std::string GetActionName() {
return "Take"; }
978template <
typename RealT_t,
typename T,
typename COLL>
980template <
typename RealT_t,
typename T>
982template <
typename RealT_t,
typename COLL>
984template <
typename RealT_t>
1000template <
typename ResultType>
1027 *
fResultMin = std::numeric_limits<ResultType>::max();
1035 return std::make_unique<RMergeableMin<ResultType>>(*fResultMin);
1040 std::string GetActionName() {
return "Min"; }
1044 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1049template <
typename ResultType>
1076 *
fResultMax = std::numeric_limits<ResultType>::lowest();
1085 return std::make_unique<RMergeableMax<ResultType>>(*fResultMax);
1090 std::string GetActionName() {
return "Max"; }
1094 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1099template <
typename ResultType>
1108 template <
typename T = ResultType>
1114 template <
typename T = ResultType,
typename Dummy =
int>
1142 for (
auto &&
v :
vs) {
1168 return std::make_unique<RMergeableSum<ResultType>>(*fResultSum);
1173 std::string GetActionName() {
return "Sum"; }
1177 auto &
result = *
static_cast<std::shared_ptr<ResultType> *
>(
newResult);
1185 std::vector<ULong64_t> fCounts;
1186 std::vector<double>
fSums;
1200 for (
auto &&
v :
vs) {
1218 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1222 double &PartialUpdate(
unsigned int slot);
1224 std::string GetActionName() {
return "Mean"; }
1235 unsigned int fNSlots;
1238 std::vector<ULong64_t> fCounts;
1240 std::vector<double> fMeans;
1254 for (
auto &&
v :
vs) {
1266 const ULong64_t counts = std::accumulate(fCounts.begin(), fCounts.end(), 0ull);
1268 std::inner_product(fMeans.begin(), fMeans.end(), fCounts.begin(), 0.) /
static_cast<Double_t>(
counts);
1272 std::string GetActionName() {
return "StdDev"; }
1281template <
typename PrevNodeType>
1286 std::shared_ptr<PrevNodeType> fPrevNode;
1287 size_t fEntriesToProcess;
1290 DisplayHelper(
size_t nRows,
const std::shared_ptr<Display_t> &
d,
const std::shared_ptr<PrevNodeType> &prevNode)
1294 DisplayHelper(DisplayHelper &&) =
default;
1295 DisplayHelper(
const DisplayHelper &) =
delete;
1298 template <
typename...
Columns>
1301 if (fEntriesToProcess == 0)
1305 --fEntriesToProcess;
1307 if (fEntriesToProcess == 0) {
1312 fPrevNode->StopProcessing();
1320 std::string GetActionName() {
return "Display"; }
1323template <
typename T>
1329template <
typename T>
1335template <
typename T>
1398template <
typename T>
1416 "Branch \"%s\" contains TClonesArrays but the type specified to Snapshot was RVec<T>. The branch will "
1417 "be written out as a RVec instead of a TClonesArray. Specify that the type of the branch is "
1418 "TClonesArray as a Snapshot template parameter to write out a TClonesArray instead.",
1456 const auto bname =
leaf->GetName();
1472 const auto btype =
leaf->GetTypeName();
1476 "RDataFrame::Snapshot: could not correctly construct a leaflist for C-style array in column %s. This "
1477 "column will not be written out.",
1495 std::string fFileName;
1496 std::string fDirName;
1497 std::string fTreeName;
1499 std::unique_ptr<TFile> fOutputFile;
1506 std::vector<TBranch *> fBranches;
1507 std::vector<void *> fBranchAddresses;
1509 std::vector<bool> fIsDefine;
1527 if (!fTreeName.empty() && !fOutputFile && fOptions.
fLazy) {
1531 return checkupdate ==
"update" ?
"updated" :
"created";
1534 "A lazy Snapshot action was booked but never triggered. The tree '%s' in output file '%s' was not %s. "
1535 "In case it was desired instead, remember to trigger the Snapshot operation, by storing "
1536 "its result in a variable and for example calling the GetValue() method on it.",
1560 template <std::size_t...
S>
1569 int expander[] = {(fBranches[
S] && fBranchAddresses[
S] != GetData(values)
1570 ? fBranches[
S]->SetAddress(GetData(values)),
1571 fBranchAddresses[
S] = GetData(values), 0 : 0, 0)...,
1576 template <std::size_t...
S>
1581 fBranches[S], fBranchAddresses[S], &values,
fOutputBranches, fIsDefine[S]),
1594 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1597 if (!fDirName.empty()) {
1601 outputDir = fOutputFile->mkdir(fDirName.c_str(),
"",
true);
1603 outputDir = fOutputFile->mkdir(fDirName.c_str());
1607 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.
fSplitLevel,
outputDir);
1616 assert(fOutputFile !=
nullptr);
1622 fOutputFile->Close();
1625 std::string GetActionName() {
return "Snapshot"; }
1645 const std::string
finalName = *
reinterpret_cast<const std::string *
>(
newName);
1654 unsigned int fNSlots;
1655 std::unique_ptr<ROOT::TBufferMerger> fMerger;
1656 std::vector<std::shared_ptr<ROOT::TBufferMergerFile>>
fOutputFiles;
1659 std::string fFileName;
1660 std::string fDirName;
1661 std::string fTreeName;
1665 std::vector<TTree *> fInputTrees;
1667 std::vector<std::vector<TBranch *>> fBranches;
1669 std::vector<std::vector<void *>> fBranchAddresses;
1671 std::vector<bool> fIsDefine;
1696 return checkupdate ==
"update" ?
"updated" :
"created";
1699 "A lazy Snapshot action was booked but never triggered. The tree '%s' in output file '%s' was not %s. "
1700 "In case it was desired instead, remember to trigger the Snapshot operation, by storing "
1701 "its result in a variable and for example calling the GetValue() method on it.",
1714 if (!fDirName.empty()) {
1729 fInputTrees[
slot] =
r->GetTree();
1759 template <std::size_t...
S>
1768 int expander[] = {(fBranches[
slot][
S] && fBranchAddresses[
slot][
S] != GetData(values)
1769 ? fBranches[
slot][
S]->SetAddress(GetData(values)),
1770 fBranchAddresses[
slot][
S] = GetData(values), 0 : 0, 0)...,
1776 template <std::size_t...
S>
1794 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
1795 fMerger = std::make_unique<ROOT::TBufferMerger>(std::unique_ptr<TFile>(
out_file));
1813 "No input entries (input TTree was empty or no entry passed the Filters). Output TTree is empty.");
1821 std::string GetActionName() {
return "Snapshot"; }
1841 const std::string
finalName = *
reinterpret_cast<const std::string *
>(
newName);
1847template <
typename Acc,
typename Merge,
typename R,
typename T,
typename U,
1850 :
public RActionImpl<AggregateHelper<Acc, Merge, R, T, U, MustCopyAssign>> {
1853 std::shared_ptr<U> fResult;
1874 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<MustCopyAssign_,
int> = 0>
1880 template <
bool MustCopyAssign_ = MustCopyAssign, std::enable_if_t<!MustCopyAssign_,
int> = 0>
1889 bool MergeAll = std::is_same<void, MergeRet>::value>
1890 std::enable_if_t<MergeAll, void> Finalize()
1898 std::enable_if_t<MergeTwoByTwo, void> Finalize(...)
1901 *fResult = fMerge(*fResult,
acc);
1906 std::string GetActionName() {
return "Aggregate"; }
Handle_t Display_t
Display handle.
#define R(a, b, c, d, e, f, g, h, i)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned long long ULong64_t
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x1
TClass * IsA() const override
TTime operator*(const TTime &t1, const TTime &t2)
Base class for action helpers, see RInterface::Book() for more information.
This class is the textual representation of the content of a columnar dataset.
This type represents a sample identifier, to be used in conjunction with RDataFrame features such as ...
const_iterator begin() const
const_iterator end() const
A "std::vector"-like collection of values implementing handy operation to analyse them.
A TTree is a list of TBranches.
TClassRef is used to implement a permanent reference to a TClass object.
Collection abstract base class.
TDirectory::TContext keeps track and restore the current directory.
Describe directory structure in memory.
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
TGraph with asymmetric error bars.
A TGraph is an object made of two arrays X and Y with npoints each.
1-D histogram with a double per channel (see TH1 documentation)
TH1 is the base class of all histogram classes in ROOT.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Statistical variable, defined by its mean and variance (RMS).
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
A TTree represents a columnar dataset.
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
RooCmdArg Columns(Int_t ncol)
CPYCPPYY_EXTERN bool Exec(const std::string &cmd)
std::unique_ptr< RMergeableVariations< T > > GetMergeableValue(ROOT::RDF::Experimental::RResultMap< T > &rmap)
Retrieve mergeable values after calling ROOT::RDF::VariationsFor .
std::vector< std::string > ReplaceDotWithUnderscore(const std::vector< std::string > &columnNames)
Replace occurrences of '.
void ValidateSnapshotOutput(const RSnapshotOptions &opts, const std::string &treeName, const std::string &fileName)
char TypeName2ROOTTypeName(const std::string &b)
Convert type name (e.g.
constexpr std::size_t FindIdxTrue(const T &arr)
std::function< void(unsigned int, const ROOT::RDF::RSampleInfo &)> SampleCallback_t
The type of a data-block callback, registered with an RDataFrame computation graph via e....
ROOT type_traits extensions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
int CompressionSettings(RCompressionSetting::EAlgorithm::EValues algorithm, int compressionLevel)
RooArgSet S(Args_t &&... args)
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
void Initialize(Bool_t useTMVAStyle=kTRUE)
A collection of options to steer the creation of the dataset on file.
int fAutoFlush
AutoFlush value for output tree.
std::string fMode
Mode of creation of output file.
ECAlgo fCompressionAlgorithm
Compression algorithm of output file.
int fSplitLevel
Split level of output tree.
bool fLazy
Do not start the event loop when Snapshot is called.
int fCompressionLevel
Compression level of output file.
Lightweight storage for a collection of types.
static uint64_t sum(uint64_t i)