23#include <TEfficiency.h>
44 auto branchList =
tree->GetListOfBranches();
45 for (
const auto* branch : *branchList) {
46 totalSize +=
dynamic_cast<const TBranch*
>(branch)->GetTotalSize();
57 auto collectFromTPad = [](TPad* pad, std::vector<TObject*>&
objects,
const auto& collectFromTPad) {
61 auto* primitives = pad->GetListOfPrimitives();
62 for (
int i = 0;
i < primitives->GetSize(); ++
i) {
63 auto* primitive = primitives->At(
i);
64 if (
auto* primitivePad =
dynamic_cast<TPad*
>(primitive)) {
65 collectFromTPad(primitivePad,
objects, collectFromTPad);
72 std::vector<TObject*> collectedObjects;
73 collectFromTPad(canvas, collectedObjects, collectFromTPad);
75 return collectedObjects;
85auto matchCollectedToPairs(
const std::vector<TObject*>& targetObjects,
const std::vector<TObject*> otherObjects) -> std::vector<MatchedCollectedObjects>
87 std::vector<MatchedCollectedObjects> matchedObjects;
88 matchedObjects.reserve(std::max(targetObjects.size(), otherObjects.size()));
89 for (
const auto& targetObject : targetObjects) {
90 if (
const auto found_it = std::ranges::find_if(otherObjects, [&targetObject](
TObject* obj) {
return std::string_view(targetObject->GetName()) == std::string_view(obj->GetName()); });
91 found_it != otherObjects.end()) {
92 matchedObjects.emplace_back(targetObject, *found_it);
95 return matchedObjects;
101 Long64_t errorCode = 0;
103 TObjArray otherCollection;
104 otherCollection.SetOwner(
false);
105 otherCollection.Add(
other);
107 if (
target->InheritsFrom(TH1::Class())) {
109 auto targetTH1 =
reinterpret_cast<TH1*
>(
target);
110 if (targetTH1->TestBit(TH1::kIsAverage)) {
113 if (
auto otherTH1 =
dynamic_cast<TH1*
>(otherCollection.First())) {
114 errorCode = targetTH1->Add(otherTH1);
118 errorCode = targetTH1->Merge(&otherCollection);
120 }
else if (
target->InheritsFrom(THnBase::Class())) {
122 errorCode =
reinterpret_cast<THnBase*
>(
target)->Merge(&otherCollection);
123 }
else if (
target->InheritsFrom(TTree::Class())) {
124 auto targetTree =
reinterpret_cast<TTree*
>(
target);
125 auto otherTree =
reinterpret_cast<TTree*
>(
other);
128 if (
auto totalSize = targetTreeSize + otherTreeSize; totalSize > 100000000) {
129 LOG(warn) <<
"The tree '" << targetTree->GetName() <<
"' would be larger than 100MB (" << totalSize <<
"B) after merging, skipping to let the system survive";
132 errorCode = targetTree->Merge(&otherCollection);
134 }
else if (
target->InheritsFrom(TGraph::Class())) {
135 errorCode =
reinterpret_cast<TGraph*
>(
target)->Merge(&otherCollection);
136 }
else if (
target->InheritsFrom(TEfficiency::Class())) {
137 errorCode =
reinterpret_cast<TEfficiency*
>(
target)->Merge(&otherCollection);
139 LOG(warn) <<
"Object '" + std::string(
target->GetName()) +
"' with type '" + std::string(
target->ClassName()) +
"' is not one of the mergeable types, skipping";
147 throw std::runtime_error(
"Merging target is nullptr");
149 if (
other ==
nullptr) {
150 throw std::runtime_error(
"Object to be merged in is nullptr");
153 throw std::runtime_error(
"Merging target and the other object point to the same address");
163 }
else if (
auto targetCollection =
dynamic_cast<TCollection*
>(
target)) {
165 auto otherCollection =
dynamic_cast<TCollection*
>(
other);
166 if (otherCollection ==
nullptr) {
167 throw std::runtime_error(std::string(
"The target object '") +
target->GetName() +
168 "' is a TCollection, while the other object '" +
other->GetName() +
"' is not.");
171 auto otherIterator = otherCollection->MakeIterator();
172 while (
auto otherObject = otherIterator->Next()) {
173 TObject* targetObject = targetCollection->FindObject(otherObject->GetName());
176 merge(targetObject, otherObject);
179 targetCollection->Add(otherObject->Clone());
182 delete otherIterator;
183 }
else if (
auto targetCanvas =
dynamic_cast<TCanvas*
>(
target)) {
185 auto otherCanvas =
dynamic_cast<TCanvas*
>(
other);
186 if (otherCanvas ==
nullptr) {
187 throw std::runtime_error(std::string(
"The target object '") +
target->GetName() +
188 "' is a TCanvas, while the other object '" +
other->GetName() +
"' is not.");
193 if (targetObjects.size() != otherObjects.size()) {
194 throw std::runtime_error(std::string(
"Trying to merge canvas: ") + targetCanvas->GetName() +
" and canvas " + otherObjects.size() +
"but contents are not the same");
198 if (targetObjects.size() != matched.size()) {
199 throw std::runtime_error(std::string(
"Trying to merge canvas: ") + targetCanvas->GetName() +
" and canvas " + otherObjects.size() +
"but contents are not the same");
202 for (
const auto& [targetObject, otherObject] : matched) {
203 merge(targetObject, otherObject);
209 if (errorCode == -1) {
210 LOG(error) <<
"Failed to merge the input object '" + std::string(
other->GetName()) +
"' of type '" + std::string(
other->ClassName())
211 +
" and the target object '" + std::string(
target->GetName()) +
"' of type '" + std::string(
target->ClassName()) +
"'";
217 if (errorCode == -1) {
218 LOG(error) <<
"Merging '" + std::string(
other->GetName()) +
"' and '" + std::string(
target->GetName())
219 +
"' failed again after a retry for debugging purposes. See ROOT warnings for details.";
221 LOG(warn) <<
"Merging '" + std::string(
other->GetName()) +
"' and '" + std::string(
target->GetName())
222 +
"' succeeded after retrying for debugging purposes.";
230 for (
const auto&
other : others) {
231 if (
const auto targetSameName = std::find_if(targets.begin(), targets.end(), [&
other](
const auto&
target) {
232 return std::string_view{other->GetName()} == std::string_view{target->GetName()};
234 targetSameName != targets.end()) {
245 Coll->SetOwner(
false);
246 auto ITelem = Coll->MakeIterator();
247 while (
auto*
element = ITelem->Next()) {
248 if (
auto* Coll2 =
dynamic_cast<TCollection*
>(
element)) {
249 Coll2->SetOwner(
false);
260 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)
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()))