24#include <TEfficiency.h>
45 auto branchList =
tree->GetListOfBranches();
46 for (
const auto* branch : *branchList) {
47 totalSize +=
dynamic_cast<const TBranch*
>(branch)->GetTotalSize();
58 auto collectFromTPad = [](TPad* pad, std::vector<TObject*>&
objects,
const auto& collectFromTPad) {
62 auto* primitives = pad->GetListOfPrimitives();
63 for (
int i = 0;
i < primitives->GetSize(); ++
i) {
64 auto* primitive = primitives->At(
i);
65 if (
auto* primitivePad =
dynamic_cast<TPad*
>(primitive)) {
66 collectFromTPad(primitivePad,
objects, collectFromTPad);
73 std::vector<TObject*> collectedObjects;
74 collectFromTPad(canvas, collectedObjects, collectFromTPad);
76 return collectedObjects;
86auto matchCollectedToPairs(
const std::vector<TObject*>& targetObjects,
const std::vector<TObject*> otherObjects) -> std::vector<MatchedCollectedObjects>
88 std::vector<MatchedCollectedObjects> matchedObjects;
89 matchedObjects.reserve(std::max(targetObjects.size(), otherObjects.size()));
90 for (
const auto& targetObject : targetObjects) {
91 if (
const auto found_it = std::ranges::find_if(otherObjects, [&targetObject](
TObject* obj) {
return std::string_view(targetObject->GetName()) == std::string_view(obj->GetName()); });
92 found_it != otherObjects.end()) {
93 matchedObjects.emplace_back(targetObject, *found_it);
96 return matchedObjects;
102 Long64_t errorCode = 0;
104 TObjArray otherCollection;
105 otherCollection.SetOwner(
false);
106 otherCollection.Add(
other);
108 if (
target->InheritsFrom(TH1::Class())) {
110 auto targetTH1 =
reinterpret_cast<TH1*
>(
target);
111 if (targetTH1->TestBit(TH1::kIsAverage)) {
114 if (
auto otherTH1 =
dynamic_cast<TH1*
>(otherCollection.First())) {
115 errorCode = targetTH1->Add(otherTH1) == kFALSE ? -1 : 0;
119 errorCode = targetTH1->Merge(&otherCollection);
121 }
else if (
target->InheritsFrom(THnBase::Class())) {
123 errorCode =
reinterpret_cast<THnBase*
>(
target)->Merge(&otherCollection);
124 }
else if (
target->InheritsFrom(TTree::Class())) {
125 auto targetTree =
reinterpret_cast<TTree*
>(
target);
126 auto otherTree =
reinterpret_cast<TTree*
>(
other);
129 if (
auto totalSize = targetTreeSize + otherTreeSize; totalSize > 100000000) {
130 LOG(warn) <<
"The tree '" << targetTree->GetName() <<
"' would be larger than 100MB (" << totalSize <<
"B) after merging, skipping to let the system survive";
133 errorCode = targetTree->Merge(&otherCollection);
135 }
else if (
target->InheritsFrom(TGraph::Class())) {
136 errorCode =
reinterpret_cast<TGraph*
>(
target)->Merge(&otherCollection);
137 }
else if (
target->InheritsFrom(TEfficiency::Class())) {
138 errorCode =
reinterpret_cast<TEfficiency*
>(
target)->Merge(&otherCollection);
140 LOG(warn) <<
"Object '" + std::string(
target->GetName()) +
"' with type '" + std::string(
target->ClassName()) +
"' is not one of the mergeable types, skipping";
148 throw std::runtime_error(
"Merging target is nullptr");
150 if (
other ==
nullptr) {
151 throw std::runtime_error(
"Object to be merged in is nullptr");
154 throw std::runtime_error(
"Merging target and the other object point to the same address");
164 }
else if (
auto targetCollection =
dynamic_cast<TCollection*
>(
target)) {
166 auto otherCollection =
dynamic_cast<TCollection*
>(
other);
167 if (otherCollection ==
nullptr) {
168 throw std::runtime_error(std::string(
"The target object '") +
target->GetName() +
169 "' is a TCollection, while the other object '" +
other->GetName() +
"' is not.");
172 auto otherIterator = otherCollection->MakeIterator();
173 while (
auto otherObject = otherIterator->Next()) {
174 TObject* targetObject = targetCollection->FindObject(otherObject->GetName());
177 merge(targetObject, otherObject);
180 targetCollection->Add(otherObject->Clone());
183 delete otherIterator;
184 }
else if (
auto targetCanvas =
dynamic_cast<TCanvas*
>(
target)) {
186 auto otherCanvas =
dynamic_cast<TCanvas*
>(
other);
187 if (otherCanvas ==
nullptr) {
188 throw std::runtime_error(std::string(
"The target object '") +
target->GetName() +
189 "' is a TCanvas, while the other object '" +
other->GetName() +
"' is not.");
194 if (targetObjects.size() != otherObjects.size()) {
195 throw std::runtime_error(std::string(
"Trying to merge canvas: ") + targetCanvas->GetName() +
" and canvas " + otherObjects.size() +
"but contents are not the same");
199 if (targetObjects.size() != matched.size()) {
200 throw std::runtime_error(std::string(
"Trying to merge canvas: ") + targetCanvas->GetName() +
" and canvas " + otherObjects.size() +
"but contents are not the same");
203 for (
const auto& [targetObject, otherObject] : matched) {
204 merge(targetObject, otherObject);
210 if (errorCode == -1) {
211 LOG(error) <<
"Failed to merge the input object '" + std::string(
other->GetName()) +
"' of type '" + std::string(
other->ClassName())
212 +
" and the target object '" + std::string(
target->GetName()) +
"' of type '" + std::string(
target->ClassName()) +
"'";
218 if (errorCode == -1) {
219 LOG(error) <<
"Merging '" + std::string(
other->GetName()) +
"' and '" + std::string(
target->GetName())
220 +
"' failed again after a retry for debugging purposes. See ROOT warnings for details.";
222 LOG(warn) <<
"Merging '" + std::string(
other->GetName()) +
"' and '" + std::string(
target->GetName())
223 +
"' succeeded after retrying for debugging purposes.";
231 for (
const auto&
other : others) {
232 if (
const auto targetSameName = std::find_if(targets.begin(), targets.end(), [&
other](
const auto&
target) {
233 return std::string_view{other->GetName()} == std::string_view{target->GetName()};
235 targetSameName != targets.end()) {
246 Coll->SetOwner(
false);
247 auto ITelem = Coll->MakeIterator();
248 while (
auto*
element = ITelem->Next()) {
249 if (
auto* Coll2 =
dynamic_cast<TCollection*
>(
element)) {
250 Coll2->SetOwner(
false);
261 if (
auto* L =
dynamic_cast<TCollection*
>(obj)) {
std::vector< std::string > objects
Definition of O2 Mergers merging interface, v0.1.
Algorithms for merging objects.
Definition of ObjectStore for Mergers, v0.1.
An interface which allows to merge custom objects.
Long64_t mergeDefault(TObject *const target, TObject *const other)
void deleteRecursive(TCollection *Coll)
auto matchCollectedToPairs(const std::vector< TObject * > &targetObjects, const std::vector< TObject * > otherObjects) -> std::vector< MatchedCollectedObjects >
void merge(TObject *const target, TObject *const other)
A function which merges TObjects.
void deleteTCollections(TObject *obj)
auto collectUnderlyingObjects(TCanvas *canvas) -> std::vector< TObject * >
size_t estimateTreeSize(TTree *tree)
bool isMergeable(TObject *obj)
std::vector< TObjectPtr > VectorOfTObjectPtrs
MatchedCollectedObjects(TObject *t, TObject *o)
VectorOfTObjectPtrs other
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))