44static_assert(std::is_nothrow_move_assignable_v<RBranchData>);
45static_assert(std::is_nothrow_move_constructible_v<RBranchData>);
49void AssertNoNullBranchAddresses(
const std::vector<RBranchData> &branches)
51 std::vector<TBranch *> branchesWithNullAddress;
52 for (
const auto &branchData : branches) {
53 if (branchData.fOutputBranch->GetAddress() ==
nullptr)
54 branchesWithNullAddress.push_back(branchData.fOutputBranch);
57 if (branchesWithNullAddress.empty())
61 std::vector<std::string> missingBranchNames;
62 std::transform(branchesWithNullAddress.begin(), branchesWithNullAddress.end(),
63 std::back_inserter(missingBranchNames), [](
TBranch *
b) { return b->GetName(); });
64 std::string msg =
"RDataFrame::Snapshot:";
65 if (missingBranchNames.size() == 1) {
66 msg +=
" branch " + missingBranchNames[0] +
67 " is needed as it provides the size for one or more branches containing dynamically sized arrays, but "
71 for (
const auto &bName : missingBranchNames)
73 msg.resize(msg.size() - 2);
74 msg +=
" are needed as they provide the size of other branches containing dynamically sized arrays, but they are";
76 msg +=
" not part of the set of branches that are being written out.";
77 throw std::runtime_error(msg);
80TBranch *SearchForBranch(
TTree *inputTree,
const std::string &branchName)
83 if (
auto *getBranchRes = inputTree->
GetBranch(branchName.c_str()))
87 if (
auto *findBranchRes = inputTree->
FindBranch(branchName.c_str()))
93std::vector<RBranchData>::iterator CreateCStyleArrayBranch(
TTree &outputTree, std::vector<RBranchData> &outputBranches,
94 std::vector<RBranchData>::iterator thisBranch,
95 TBranch *inputBranch,
int basketSize,
void *address)
106 const auto bname = leaf->GetName();
107 auto *sizeLeaf = leaf->GetLeafCount();
108 const auto sizeLeafName = sizeLeaf ? std::string(sizeLeaf->GetName()) : std::to_string(leaf->GetLenStatic());
111 if (sizeLeaf || leaf->GetLenStatic() > 1) {
116 std::find_if(outputBranches.begin(), outputBranches.end(),
117 [&sizeLeafName](
const RBranchData &bd) { return bd.fOutputBranchName == sizeLeafName; });
118 if (sizeLeafIt == outputBranches.end()) {
121 const auto indexBeforeEmplace = std::distance(outputBranches.begin(), thisBranch);
122 outputBranches.emplace_back(
"", sizeLeafName,
false,
nullptr);
123 thisBranch = outputBranches.begin() + indexBeforeEmplace;
124 sizeLeafIt = outputBranches.end() - 1;
126 if (!sizeLeafIt->fOutputBranch) {
130 const auto bufSize = (basketSize > 0) ? basketSize : sizeLeaf->GetBranch()->GetBasketSize();
133 auto *outputBranch = outputTree.
Branch(sizeLeafName.c_str(),
static_cast<void *
>(
nullptr),
134 (sizeLeafName +
'/' + sizeTypeStr).c_str(), bufSize);
135 sizeLeafIt->fOutputBranch = outputBranch;
139 const auto btype = leaf->GetTypeName();
141 if (rootbtype ==
' ') {
143 "RDataFrame::Snapshot: could not correctly construct a leaflist for C-style array in column %s. The "
144 "leaf is of type '%s'. This column will not be written out.",
149 const auto leaflist = std::string(bname) +
"[" + sizeLeafName +
"]/" + rootbtype;
151 const auto bufSize = (basketSize > 0) ? basketSize : inputBranch->GetBasketSize();
152 void *addressForBranch = [address]() ->
void * {
157 return rawRVec->
data();
161 thisBranch->fOutputBranch =
162 outputTree.
Branch(thisBranch->fOutputBranchName.c_str(), addressForBranch, leaflist.c_str(), bufSize);
163 thisBranch->fOutputBranch->SetTitle(inputBranch->
GetTitle());
164 thisBranch->fIsCArray =
true;
170void SetBranchAddress(
TBranch *inputBranch,
RBranchData &branchData,
void *valueAddress)
172 const static TClassRef TBOClRef(
"TBranchObject");
173 if (inputBranch && inputBranch->
IsA() == TBOClRef) {
180 void *correctAddress = [valueAddress, isCArray = branchData.
fIsCArray]() ->
void * {
185 return rawRVec->
data();
194void CreateFundamentalTypeBranch(
TTree &outputTree,
RBranchData &bd,
void *valueAddress,
int bufSize)
200 if (rootTypeChar ==
' ') {
202 "RDataFrame::Snapshot: could not correctly construct a leaflist for fundamental type in column %s. This "
203 "column will not be written out.",
215 const std::string &fileName)
219 if (fileMode !=
"update")
223 std::unique_ptr<TFile> outFile{
TFile::Open(fileName.c_str(),
"UPDATE_WITHOUT_GLOBALREGISTRATION")};
224 if (!outFile || outFile->IsZombie())
225 throw std::invalid_argument(
"Snapshot: cannot open file \"" + fileName +
"\" in update mode");
228 if (!outFile->GetKey(objName.c_str()))
233 if (
auto existingTree = outFile->Get<
TTree>(objName.c_str()); existingTree) {
236 existingTree->Delete(
"all");
239 outFile->Delete((objName +
";*").c_str());
242 const std::string msg =
"Snapshot: object \"" + objName +
"\" already present in file \"" + fileName +
243 "\". If you want to delete the original object and write another, please set the "
244 "'fOverwriteIfExists' option to true in RSnapshotOptions.";
245 throw std::invalid_argument(msg);
249void SetBranchesHelper(
TTree *inputTree,
TTree &outputTree,
250 std::vector<ROOT::Internal::RDF::RBranchData> &allBranchData, std::size_t currentIndex,
251 int basketSize,
void *valueAddress)
253 auto branchData = allBranchData.begin() + currentIndex;
258 SetBranchAddress(inputBranch, *branchData, valueAddress);
267 const auto bufSize = (basketSize > 0) ? basketSize : (inputBranch ? inputBranch->GetBasketSize() : 32000);
268 const auto splitLevel = inputBranch ? inputBranch->
GetSplitLevel() : 99;
271 if (
dynamic_cast<TDataType *
>(dictionary)) {
273 CreateFundamentalTypeBranch(outputTree, *branchData, valueAddress, bufSize);
283 branchData = CreateCStyleArrayBranch(outputTree, allBranchData, branchData, inputBranch, bufSize, valueAddress);
296 if (
auto *classPtr =
dynamic_cast<TClass *
>(dictionary)) {
298 if (inputBranch &&
dynamic_cast<TBranchObject *
>(inputBranch) && valueAddress)
301 inputBranch->
GetAddress(), bufSize, splitLevel);
303 else if (valueAddress)
306 valueAddress, bufSize, splitLevel);
315 throw std::logic_error(
316 "RDataFrame::Snapshot: something went wrong when creating a TTree branch, please report this as a bug.");
330 }
else if (options.
fOutputFormat == OutputFormat::kRNTuple) {
337 throw std::invalid_argument(
"RDataFrame::Snapshot: unrecognized output format");
341std::string ModeWithoutGlobalRegistration(
const std::string &
mode)
343 if (
mode.find(
"_WITHOUT_GLOBALREGISTRATION") != std::string::npos) {
346 return mode +
"_WITHOUT_GLOBALREGISTRATION";
352 const std::type_info *typeID)
353 : fInputBranchName{std::move(inputBranchName)},
354 fOutputBranchName{std::move(outputBranchName)},
355 fInputTypeID{typeID},
359 if (
auto datatype =
dynamic_cast<TDataType *
>(dictionary); datatype) {
361 }
else if (
auto tclass =
dynamic_cast<TClass *
>(dictionary); tclass) {
372 if (
auto fundamental = std::get_if<FundamentalType>(&fTypeData); fundamental) {
373 assert(!pointerToPointer);
374 return fundamental->fBytes.data();
377 auto &dynamic = std::get<EmptyDynamicType>(fTypeData);
378 if (!dynamic.fEmptyInstance) {
380 assert(
dynamic_cast<TDataType *
>(dictionary) ==
383 auto tclass =
dynamic_cast<TClass *
>(dictionary);
385 dynamic.fEmptyInstance = std::shared_ptr<void>{tclass->New(), tclass->GetDestructor()};
388 if (pointerToPointer) {
390 dynamic.fRawPtrToEmptyInstance = dynamic.fEmptyInstance.get();
391 return &dynamic.fRawPtrToEmptyInstance;
393 return dynamic.fEmptyInstance.get();
406 if (
auto fundamental = std::get_if<FundamentalType>(&fTypeData); fundamental) {
407 fundamental->fBytes.fill(std::byte{0});
410 fOutputBranch->SetAddress(EmptyInstance(
true));
415 std::string_view
filename, std::string_view dirname, std::string_view treename,
const ColumnNames_t &vbnames,
418 const std::vector<const std::type_info *> &colTypeIDs)
423 fOutputLoopManager(loopManager),
424 fInputLoopManager(inputLM)
430 for (
unsigned int i = 0; i < vbnames.size(); ++i) {
431 fBranchData.emplace_back(vbnames[i], std::move(outputBranchNames[i]), isDefine[i], colTypeIDs[i]);
443 if (!fTreeName.empty() && !fOutputFile && fOptions.fLazy) {
444 const auto fileOpenMode = [&]() {
445 TString checkupdate = fOptions.fMode;
447 return checkupdate ==
"update" ?
"updated" :
"created";
450 "A lazy Snapshot action was booked but never triggered. The tree '%s' in output file '%s' was not %s. "
451 "In case it was desired instead, remember to trigger the Snapshot operation, by storing "
452 "its result in a variable and for example calling the GetValue() method on it.",
453 fTreeName.c_str(), fFileName.c_str(), fileOpenMode);
462 fInputTree = treeDS->GetTree();
463 fBranchAddressesNeedReset =
true;
468 if (!fBranchAddressesNeedReset) {
469 UpdateCArraysPtrs(values);
472 fBranchAddressesNeedReset =
false;
484 assert(values.size() == fBranchData.size());
485 auto nValues = values.size();
486 for (
decltype(nValues) i{}; i < nValues; i++) {
487 if (fBranchData[i].fIsCArray) {
491 if (
auto *
data = rawRVec->data(); fBranchData[i].fBranchAddressForCArrays !=
data) {
492 fBranchData[i].fOutputBranch->SetAddress(
data);
493 fBranchData[i].fBranchAddressForCArrays =
data;
502 assert(fBranchData.size() == values.size());
503 for (std::size_t i = 0; i < fBranchData.size(); i++) {
504 SetBranchesHelper(fInputTree, *fOutputTree, fBranchData, i, fOptions.fBasketSize, values[i]);
506 AssertNoNullBranchAddresses(fBranchData);
511 void *dummyValueAddress{};
512 for (std::size_t i = 0; i < fBranchData.size(); i++) {
513 SetBranchesHelper(inputTree, outputTree, fBranchData, i, fOptions.fBasketSize, dummyValueAddress);
519 fOutputFile.reset(
TFile::Open(fFileName.c_str(), ModeWithoutGlobalRegistration(fOptions.fMode).c_str(),
520 "", GetSnapshotCompressionSettings(fOptions)));
522 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
525 if (!fDirName.empty()) {
526 TString checkupdate = fOptions.fMode;
528 if (checkupdate ==
"update")
529 outputDir = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
531 outputDir = fOutputFile->
mkdir(fDirName.c_str());
534 fOutputTree = std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.fSplitLevel, outputDir);
536 if (fOptions.fAutoFlush)
537 fOutputTree->SetAutoFlush(fOptions.fAutoFlush);
542 assert(fOutputTree !=
nullptr);
543 assert(fOutputFile !=
nullptr);
547 if (fOutputTree->GetEntries() == 0) {
548 SetEmptyBranches(fInputTree, *fOutputTree);
551 fOutputTree->AutoSave(
"flushbaskets");
554 fOutputFile->Close();
557 auto fullTreeName = fDirName.empty() ? fTreeName : fDirName +
'/' + fTreeName;
558 fOutputLoopManager->SetDataSource(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(fullTreeName, fFileName));
575 const std::string finalName = *
reinterpret_cast<const std::string *
>(newName);
576 std::vector<std::string> inputBranchNames;
577 std::vector<std::string> outputBranchNames;
578 std::vector<bool> isDefine;
579 std::vector<const std::type_info *> inputColumnTypeIDs;
580 for (
const auto &bd : fBranchData) {
592 std::move(inputBranchNames),
593 std::move(outputBranchNames),
602 unsigned int nSlots, std::string_view
filename, std::string_view dirname, std::string_view treename,
605 const std::vector<const std::type_info *> &colTypeIDs)
607 fOutputFiles(fNSlots),
608 fOutputTrees(fNSlots),
609 fBranchAddressesNeedReset(fNSlots, 1),
610 fInputTrees(fNSlots),
615 fOutputLoopManager(loopManager),
616 fInputLoopManager(inputLM)
622 for (
unsigned int slot = 0; slot <
fNSlots; ++slot) {
625 thisSlot.reserve(vbnames.size());
626 for (
unsigned int i = 0; i < vbnames.size(); ++i) {
627 thisSlot.emplace_back(vbnames[i], outputBranchNames[i], isDefine[i], colTypeIDs[i]);
640 if (!fTreeName.empty() && fOptions.fLazy && !fOutputFiles.empty() &&
641 std::all_of(fOutputFiles.begin(), fOutputFiles.end(), [](
const auto &
f) { return !f; }) ) {
642 const auto fileOpenMode = [&]() {
643 TString checkupdate = fOptions.fMode;
645 return checkupdate ==
"update" ?
"updated" :
"created";
648 "A lazy Snapshot action was booked but never triggered. The tree '%s' in output file '%s' was not %s. "
649 "In case it was desired instead, remember to trigger the Snapshot operation, by storing "
650 "its result in a variable and for example calling the GetValue() method on it.",
651 fTreeName.c_str(), fFileName.c_str(), fileOpenMode);
658 if (!fOutputFiles[slot]) {
660 fOutputFiles[slot] = fMerger->GetFile();
662 TDirectory *treeDirectory = fOutputFiles[slot].get();
663 if (!fDirName.empty()) {
665 treeDirectory = fOutputFiles[slot]->
mkdir(fDirName.c_str(),
"",
true);
670 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.fSplitLevel, treeDirectory);
673 fOutputTrees[slot]->SetImplicitMT(
false);
674 if (fOptions.fAutoFlush)
675 fOutputTrees[slot]->SetAutoFlush(fOptions.fAutoFlush);
678 fInputTrees[slot] =
r->GetTree();
680 fInputTrees[slot] = treeDS->GetTree();
682 fBranchAddressesNeedReset[slot] = 1;
687 if (fOutputTrees[slot]->GetEntries() > 0)
688 fOutputFiles[slot]->Write();
689 for (
auto &branchData : fBranchData[slot])
692 fOutputTrees[slot].reset(
nullptr);
697 if (fBranchAddressesNeedReset[slot] == 0) {
698 UpdateCArraysPtrs(slot, values);
700 SetBranches(slot, values);
701 fBranchAddressesNeedReset[slot] = 0;
703 fOutputTrees[slot]->Fill();
704 auto entries = fOutputTrees[slot]->GetEntries();
705 auto autoFlush = fOutputTrees[slot]->GetAutoFlush();
706 if ((autoFlush > 0) && (entries % autoFlush == 0))
707 fOutputFiles[slot]->Write();
711 const std::vector<void *> &values)
717 assert(values.size() == fBranchData[slot].size());
718 auto nValues = values.size();
719 for (
decltype(nValues) i{}; i < nValues; i++) {
720 auto &branchData = fBranchData[slot][i];
735 const std::vector<void *> &values)
738 auto &branchData = fBranchData[slot];
739 assert(branchData.size() == values.size());
740 for (std::size_t i = 0; i < branchData.size(); i++) {
741 SetBranchesHelper(fInputTrees[slot], *fOutputTrees[slot], branchData, i, fOptions.fBasketSize, values[i]);
744 AssertNoNullBranchAddresses(branchData);
749 void *dummyValueAddress{};
750 auto &branchData = fBranchData.front();
751 for (std::size_t i = 0; i < branchData.size(); i++) {
752 SetBranchesHelper(inputTree, outputTree, branchData, i, fOptions.fBasketSize, dummyValueAddress);
759 std::unique_ptr<TFile>{
TFile::Open(fFileName.c_str(), ModeWithoutGlobalRegistration(fOptions.fMode).c_str(),
760 fFileName.c_str(), GetSnapshotCompressionSettings(fOptions))};
762 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
763 fOutputFile = outFile.get();
764 fMerger = std::make_unique<ROOT::TBufferMerger>(std::move(outFile));
770 for (
auto &file : fOutputFiles) {
779 auto fullTreeName = fDirName.empty() ? fTreeName : fDirName +
'/' + fTreeName;
780 assert(fOutputFile &&
"Missing output file in Snapshot finalization.");
782 if (!fOutputFile->GetKey(fullTreeName.c_str())) {
786 if (!fDirName.empty()) {
787 treeDirectory = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
793 std::make_unique<TTree>(fTreeName.c_str(), fTreeName.c_str(), fOptions.fSplitLevel, treeDirectory);
797 SetEmptyBranches(inputTree, *outTree);
799 fOutputFile->Write();
803 fOutputFiles.clear();
807 fOutputLoopManager->SetDataSource(std::make_unique<ROOT::Internal::RDF::RTTreeDS>(fullTreeName, fFileName));
824 const std::string finalName = *
reinterpret_cast<const std::string *
>(newName);
825 std::vector<std::string> inputBranchNames;
826 std::vector<std::string> outputBranchNames;
827 std::vector<bool> isDefine;
828 std::vector<const std::type_info *> inputColumnTypeIDs;
829 for (
const auto &bd : fBranchData.front()) {
842 std::move(inputBranchNames),
843 std::move(outputBranchNames),
848 std::move(inputColumnTypeIDs)};
852 unsigned int nSlots, std::string_view
filename, std::string_view dirname, std::string_view ntuplename,
855 const std::vector<const std::type_info *> &colTypeIDs)
858 fNTupleName(ntuplename),
860 fInputLoopManager(inputLM),
861 fOutputLoopManager(outputLM),
862 fInputFieldNames(vfnames),
865 fFillContexts(nSlots),
867 fInputColumnTypeIDs(colTypeIDs)
880 if (!fNTupleName.empty() && !fOutputFile && fOptions.fLazy)
881 Warning(
"Snapshot",
"A lazy Snapshot action was booked but never triggered.");
887 auto nFields = fOutputFieldNames.size();
888 fFieldTokens.resize(nFields);
889 for (
decltype(nFields) i = 0; i < nFields; i++) {
895 fInputFieldNames[i], fOptions.fVector2RVec)
899 if (typeName.substr(0, 25) ==
"ROOT::RNTupleCardinality<") {
901 std::string cardinalityType = typeName.substr(25, typeName.size() - 26);
903 "Column \"%s\" is a read-only \"%s\" column. It will be snapshot as its inner type \"%s\" instead.",
904 fInputFieldNames[i].c_str(), typeName.c_str(), cardinalityType.c_str());
909 fFieldTokens[i] = model->GetToken(fOutputFieldNames[i]);
914 writeOptions.
SetCompression(GetSnapshotCompressionSettings(fOptions));
922 fOutputFile.reset(
TFile::Open(fFileName.c_str(), ModeWithoutGlobalRegistration(fOptions.fMode).c_str()));
924 throw std::runtime_error(
"Snapshot: could not create output file " + fFileName);
927 if (!fDirName.empty()) {
928 TString checkupdate = fOptions.fMode;
930 if (checkupdate ==
"update")
931 outputDir = fOutputFile->
mkdir(fDirName.c_str(),
"",
true);
933 outputDir = fOutputFile->
mkdir(fDirName.c_str());
943 if (!fFillContexts[slot]) {
944 fFillContexts[slot] = fWriter->CreateFillContext();
945 fEntries[slot] = fFillContexts[slot]->GetModel().CreateBareEntry();
951 auto &fillContext = fFillContexts[slot];
952 auto &outputEntry = fEntries[slot];
953 assert(values.size() == fFieldTokens.size());
954 for (
decltype(values.size()) i = 0; i < values.size(); i++) {
955 outputEntry->BindRawPtr(fFieldTokens[i], values[i]);
957 fillContext->Fill(*outputEntry);
964 fFillContexts[slot]->FlushCluster();
971 fFillContexts.clear();
976 fOutputFile->Close();
979 const auto fullNTupleName = fDirName.empty() ? fNTupleName : fDirName +
'/' + fNTupleName;
980 fOutputLoopManager->SetDataSource(std::make_unique<ROOT::RDF::RNTupleDS>(fullNTupleName, fFileName));
997 const std::string finalName = *
reinterpret_cast<const std::string *
>(newName);
999 fNSlots, finalName, fDirName, fNTupleName, fInputFieldNames,
1000 fOutputFieldNames, fOptions, fInputLoopManager, fOutputLoopManager, fInputColumnTypeIDs};
1035 (std::string{
"R_rdf_column_to_bitmask_mapping_"} +
fTree->GetName()).c_str());
1039 fTree->AutoSave(
"flushbaskets");
1042 std::string tree =
fTree->GetName();
1045 std::string file =
fFile->GetName();
1067 if (variationIndex != it->second) {
1068 throw std::logic_error(
"Branch " + branchName +
1069 " is being registered with different variation index than the expected one: " +
1070 std::to_string(variationIndex));
1076 const auto vectorIndex = variationIndex / 64u;
1077 const auto bitIndex = variationIndex % 64u;
1080 while (vectorIndex >=
fBitMasks.size()) {
1081 std::string bitmaskBranchName =
1082 std::string{
"R_rdf_mask_"} +
fTree->GetName() +
'_' + std::to_string(
fBitMasks.size());
1084 fTree->Branch(bitmaskBranchName.c_str(),
fBitMasks.back().branchBuffer.get());
1095 mask.bitset.reset();
1101 const auto vectorIndex =
index / 64;
1102 const auto bitIndex =
index % 64;
1103 fBitMasks[vectorIndex].bitset.set(bitIndex,
true);
1116 throw std::runtime_error(
"The TTree associated to the Snapshot action doesn't exist anymore.");
1119 *
mask.branchBuffer =
mask.bitset.to_ullong();
1129 std::string_view
filename, std::string_view dirname, std::string_view treename,
const ColumnNames_t &vbnames,
1132 const std::vector<const std::type_info *> &colTypeIDs)
1133 : fOptions(options), fInputLoopManager{inputLoopMgr}, fOutputLoopManager{outputLoopMgr}
1135 EnsureValidSnapshotOutput(
fOptions, std::string(treename), std::string(
filename));
1140 GetSnapshotCompressionSettings(
fOptions)));
1142 throw std::runtime_error(std::string{
"Snapshot: could not create output file "} + std::string{
filename});
1145 if (!dirname.empty()) {
1149 if (checkupdate ==
"update")
1151 fOutputHandle->fFile->mkdir(std::string{dirname}.c_str(),
"",
true);
1153 outputDir =
fOutputHandle->fFile->mkdir(std::string{dirname}.c_str());
1156 fOutputHandle->fTree = std::make_unique<TTree>(std::string{treename}.c_str(), std::string{treename}.c_str(),
1165 for (
unsigned int i = 0; i < vbnames.size(); ++i) {
1167 fBranchData.emplace_back(vbnames[i], outputBranchNames[i], isDefine[i], colTypeIDs[i]);
1182 unsigned int columnIndex,
1183 unsigned int originalColumnIndex,
1184 unsigned int variationIndex,
1185 std::string
const &variationName)
1187 if (columnIndex == originalColumnIndex) {
1190 assert(variationIndex == 0);
1191 fBranchData[columnIndex].fVariationIndex = 0;
1192 fOutputHandle->RegisterBranch(fBranchData[columnIndex].fOutputBranchName, variationIndex);
1193 }
else if (columnIndex >= fBranchData.size()) {
1195 fBranchData.resize(columnIndex + 1);
1196 auto &bd = fBranchData[columnIndex];
1197 bd = fBranchData[originalColumnIndex];
1199 std::replace(newOutputName.begin(), newOutputName.end(),
':',
'_');
1205 assert(
static_cast<unsigned int>(fBranchData[columnIndex].fVariationIndex) == variationIndex);
1215 fInputTree = treeDS->GetTree();
1218 for (std::size_t i = 0; i < fBranchData.size(); i++) {
1219 SetBranchesHelper(fInputTree, *fOutputHandle->fTree, fBranchData, i, fOptions.fBasketSize,
1220 fBranchData[i].EmptyInstance(
false));
1223 AssertNoNullBranchAddresses(fBranchData);
1229 std::vector<bool>
const &filterPassed)
1232 assert(fBranchData.size() == values.size());
1233 for (std::size_t i = 0; i < values.size(); i++) {
1234 const auto variationIndex = fBranchData[i].fVariationIndex;
1235 if (variationIndex < 0) {
1237 SetBranchesHelper(fInputTree, *fOutputHandle->fTree, fBranchData, i, fOptions.fBasketSize, values[i]);
1240 if (variationIndex == 0 || filterPassed[variationIndex]) {
1241 const bool fundamentalType = fBranchData[i].WriteValueIfFundamental(values[i]);
1242 if (!fundamentalType) {
1243 SetBranchesHelper(fInputTree, *fOutputHandle->fTree, fBranchData, i, fOptions.fBasketSize, values[i]);
1247 if (filterPassed[variationIndex]) {
1248 fOutputHandle->SetMaskBit(variationIndex);
1253 assert(!fOutputHandle->MaskEmpty());
1255 fOutputHandle->Write();
1256 fOutputHandle->ClearMaskBits();
1257 for (
auto &branchData : fBranchData) {
1264 fOutputHandle.reset();
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 data
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 mask
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 index
Option_t Option_t TPoint TPoint const char mode
The head node of a RDF computation graph.
void SetDataSource(std::unique_ptr< ROOT::RDF::RDataSource > dataSource)
std::shared_ptr< SnapshotOutputWriter > fOutputHandle
RSnapshotOptions fOptions
SnapshotHelperWithVariations(std::string_view filename, std::string_view dirname, std::string_view treename, const ColumnNames_t &, const ColumnNames_t &bnames, const RSnapshotOptions &options, std::vector< bool > &&, ROOT::Detail::RDF::RLoopManager *outputLoopMgr, ROOT::Detail::RDF::RLoopManager *inputLoopMgr, const std::vector< const std::type_info * > &colTypeIDs)
void InitTask(TTreeReader *, unsigned int slot)
Bind all output branches to RDF columns for the given slots.
std::vector< RBranchData > fBranchData
ROOT::Detail::RDF::RLoopManager * fOutputLoopManager
void Exec(unsigned int, const std::vector< void * > &values, std::vector< bool > const &filterPassed)
Connect all output fields to the values pointed to by values, fill the output dataset,...
void RegisterVariedColumn(unsigned int slot, unsigned int columnIndex, unsigned int originalColumnIndex, unsigned int varationIndex, std::string const &variationName)
Register a new column as a variation of the column at originalColumnIndex, and clone its properties.
void FinalizeTask(unsigned int slot)
RSnapshotOptions fOptions
UntypedSnapshotRNTupleHelper(unsigned int nSlots, std::string_view filename, std::string_view dirname, std::string_view ntuplename, const ColumnNames_t &vfnames, const ColumnNames_t &fnames, const RSnapshotOptions &options, ROOT::Detail::RDF::RLoopManager *inputLM, ROOT::Detail::RDF::RLoopManager *outputLM, const std::vector< const std::type_info * > &colTypeIDs)
void Exec(unsigned int slot, const std::vector< void * > &values)
UntypedSnapshotRNTupleHelper MakeNew(void *newName)
Create a new UntypedSnapshotRNTupleHelper with a different output file name.
void InitTask(TTreeReader *, unsigned int slot)
UntypedSnapshotTTreeHelperMT(unsigned int nSlots, std::string_view filename, std::string_view dirname, std::string_view treename, const ColumnNames_t &vbnames, const ColumnNames_t &bnames, const RSnapshotOptions &options, std::vector< bool > &&isDefine, ROOT::Detail::RDF::RLoopManager *loopManager, ROOT::Detail::RDF::RLoopManager *inputLM, const std::vector< const std::type_info * > &colTypeIDs)
void UpdateCArraysPtrs(unsigned int slot, const std::vector< void * > &values)
void SetEmptyBranches(TTree *inputTree, TTree &outputTree)
std::vector< std::vector< RBranchData > > fBranchData
UntypedSnapshotTTreeHelperMT MakeNew(void *newName, std::string_view="nominal")
Create a new UntypedSnapshotTTreeHelperMT with a different output file name.
RSnapshotOptions fOptions
void InitTask(TTreeReader *r, unsigned int slot)
void FinalizeTask(unsigned int slot)
void Exec(unsigned int slot, const std::vector< void * > &values)
void SetBranches(unsigned int slot, const std::vector< void * > &values)
RSnapshotOptions fOptions
std::vector< RBranchData > fBranchData
void InitTask(TTreeReader *, unsigned int)
UntypedSnapshotTTreeHelper MakeNew(void *newName, std::string_view="nominal")
Create a new UntypedSnapshotTTreeHelper with a different output file name.
void SetEmptyBranches(TTree *inputTree, TTree &outputTree)
void SetBranches(const std::vector< void * > &values)
void Exec(unsigned int, const std::vector< void * > &values)
UntypedSnapshotTTreeHelper(std::string_view filename, std::string_view dirname, std::string_view treename, const ColumnNames_t &vbnames, const ColumnNames_t &bnames, const RSnapshotOptions &options, std::vector< bool > &&isDefine, ROOT::Detail::RDF::RLoopManager *loopManager, ROOT::Detail::RDF::RLoopManager *inputLM, const std::vector< const std::type_info * > &colTypeIDs)
void UpdateCArraysPtrs(const std::vector< void * > &values)
pointer data() noexcept
Return a pointer to the vector's buffer, even if empty().
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
static std::unique_ptr< RNTupleModel > CreateBare()
Creates a "bare model", i.e. an RNTupleModel with no default entry.
static std::unique_ptr< RNTupleParallelWriter > Append(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Append an RNTuple to the existing file.
Common user-tunable settings for storing RNTuples.
void SetEnablePageChecksums(bool val)
Note that turning off page checksums will also turn off the same page merging optimization (see tunin...
void SetMaxUnzippedClusterSize(std::size_t val)
void SetMaxUnzippedPageSize(std::size_t val)
void SetInitialUnzippedPageSize(std::size_t val)
void SetEnableSamePageMerging(bool val)
void SetApproxZippedClusterSize(std::size_t val)
void SetCompression(std::uint32_t val)
A "std::vector"-like collection of values implementing handy operation to analyse them.
A Branch for the case of an object.
A TTree is a list of TBranches.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual char * GetAddress() const
Int_t GetSplitLevel() const
TClass * IsA() const override
virtual void SetAddress(void *add)
Set address of this branch.
TObjArray * GetListOfLeaves()
TClassRef is used to implement a permanent reference to a TClass object.
TClass instances represent classes, structs and namespaces in the ROOT type system.
Basic data type descriptor (datatype information is obtained from CINT).
static TDictionary * GetDictionary(const char *name)
Retrieve the type (class, fundamental type, typedef etc) named "name".
TDirectory::TContext keeps track and restore the current directory.
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/...".
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
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 TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
const char * GetTitle() const override
Returns title of object.
TObject * UncheckedAt(Int_t i) const
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 * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
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.
virtual TTree * GetTree() const
@ kEntriesReshuffled
If set, signals that this TTree is the output of the processing of another TTree, and the entries are...
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.
std::string TypeID2TypeName(const std::type_info &id)
Returns the name of a type starting from its type_info An empty string is returned in case of failure...
std::string GetTypeNameWithOpts(const ROOT::RDF::RDataSource &ds, std::string_view colName, bool vector2RVec)
char TypeID2ROOTTypeName(const std::type_info &tid)
TBranch * CallBranchImp(TTree &tree, const char *branchname, TClass *ptrClass, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
TBranch * CallBranchImpRef(TTree &tree, const char *branchname, TClass *ptrClass, EDataType datatype, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
std::vector< std::string > ColumnNames_t
int CompressionSettings(RCompressionSetting::EAlgorithm::EValues algorithm, int compressionLevel)
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...
Stores empty instances of classes, so a dummy object can be written when a systematic variation doesn...
Stores variations of a fundamental type.
Stores properties of each output branch in a Snapshot.
void * EmptyInstance(bool pointerToPointer)
Return a pointer to an empty instance of the type represented by this branch.
void ClearBranchContents()
Point the branch address to an empty instance of the type represented by this branch or write null by...
void * fBranchAddressForCArrays
std::variant< FundamentalType, EmptyDynamicType > fTypeData
std::string fOutputBranchName
void ClearBranchPointers()
std::string fInputBranchName
const std::type_info * fInputTypeID
std::unique_ptr< uint64_t > branchBuffer
An object to store an output file and a tree in one common place to share them between instances of S...
void Write() const
Write the current event and the bitmask to the output dataset.
std::unique_ptr< TTree > fTree
void ClearMaskBits()
Clear all bits, as if none of the variations passed its filter.
SnapshotOutputWriter(SnapshotOutputWriter const &)=delete
RLoopManager * fOutputLoopManager
std::string fDirectoryName
std::unordered_map< std::string, std::pair< std::string, unsigned int > > fBranchToBitmaskMapping
std::unique_ptr< TFile > fFile
void RegisterBranch(std::string const &branchName, unsigned int variationIndex)
Register a branch and corresponding systematic uncertainty.
SnapshotOutputWriter(TFile *file)
void SetMaskBit(unsigned int index)
Set a bit signalling that the variation at index passed its filter.
bool MaskEmpty() const
Test if any of the mask bits are set.
SnapshotOutputWriter & operator=(SnapshotOutputWriter const &)=delete
std::unordered_map< std::string, unsigned int > fBranchToVariationMapping
SnapshotOutputWriter(SnapshotOutputWriter &&) noexcept=delete
std::vector< Bitmask > fBitMasks
Tag to let data sources use the native data type when creating a column reader.
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
A collection of options to steer the creation of the dataset on disk through Snapshot().
int fAutoFlush
*(TTree only)* AutoFlush value for output tree
ESnapshotOutputFormat fOutputFormat
Which data format to write to.
std::string fMode
Mode of creation of output file.
ECAlgo fCompressionAlgorithm
Compression algorithm of output file.
int fSplitLevel
*(TTree only)* Split level of output tree
int fCompressionLevel
Compression level of output file.
bool fOverwriteIfExists
If fMode is "UPDATE", overwrite object in output file if it already exists.