Skip to content

Commit fd0dd5d

Browse files
committed
Fix concatenation for McCollisions indexed Trees
1 parent 30358fa commit fd0dd5d

File tree

1 file changed

+163
-1
lines changed

1 file changed

+163
-1
lines changed

MC/utils/AODBcRewriter.C

Lines changed: 163 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ static const char *findIndexBranchName(TTree *t) {
5555
return nullptr;
5656
}
5757

58+
static const char *findMcCollisionIndexBranchName(TTree *t) {
59+
if (!t)
60+
return nullptr;
61+
if (t->GetBranch("fIndexMcCollisions"))
62+
return "fIndexMcCollisions";
63+
return nullptr;
64+
}
65+
66+
static inline bool isMcCollisionTree(const char *tname) {
67+
return TString(tname).BeginsWith("O2mccollision");
68+
}
69+
5870
// Scalar type tag
5971
enum class ScalarTag {
6072
kInt,
@@ -336,6 +348,10 @@ struct BCMaps {
336348
std::vector<Int_t> indexMap;
337349
std::vector<ULong64_t> uniqueBCs;
338350
std::unordered_map<size_t, std::vector<size_t>> newIndexOrigins;
351+
352+
// McCollision scheme (populated when O2mccollision is sorted) during first stage
353+
std::vector<Long64_t> mcOldEntries;
354+
std::vector<Long64_t> mcNewEntries;
339355
};
340356

341357
static BCMaps buildBCMaps(TTree *treeBCs) {
@@ -543,7 +559,7 @@ static bool isVLA(TBranch *br) {
543559
// This is the VLA-aware rewritePayloadSorted implementation (keeps previous
544560
// tested behavior)
545561
static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut,
546-
const BCMaps &maps) {
562+
BCMaps &maps) {
547563
std::unordered_set<std::string> skipNames; // for count branches
548564
TIter it(dirIn->GetListOfKeys());
549565
while (TKey *k = (TKey *)it()) {
@@ -562,6 +578,13 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut,
562578

563579
const char *idxName = findIndexBranchName(src);
564580
if (!idxName) {
581+
// Tables indexed by McCollisions (not BCs) are forwarded to the second
582+
// stage where the sorting scheme is available.
583+
if (findMcCollisionIndexBranchName(src)) {
584+
std::cout << " [forward] " << tname
585+
<< " (McCollision-indexed) -> second stage\n";
586+
continue;
587+
}
565588
dirOut->cd();
566589
std::cout << " [copy] " << tname << " (no index) -> cloning\n";
567590
TTree *c = src->CloneTree(-1, "fast");
@@ -649,6 +672,18 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut,
649672
return a.entry < b.entry;
650673
});
651674

675+
// If this is the McCollision tree, record the sort permutation so that
676+
// tables indexed by McCollisions (fIndexMcCollisions) can be reordered consistently
677+
if (isMcCollisionTree(tname)) {
678+
maps.mcOldEntries.resize(keys.size());
679+
maps.mcNewEntries.assign(nEnt, -1);
680+
for (Long64_t j = 0; j < (Long64_t)keys.size(); ++j) {
681+
maps.mcOldEntries[j] = keys[j].entry;
682+
if (keys[j].entry >= 0)
683+
maps.mcNewEntries[keys[j].entry] = j;
684+
}
685+
}
686+
652687
// prepare output tree
653688
dirOut->cd();
654689
TTree *out = src->CloneTree(0, "fast");
@@ -889,6 +924,133 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut,
889924
out->Write();
890925
} // end while keys in dir
891926

927+
// ---- second stage: tables indexed by McCollisions using fIndexMcCollisions ----
928+
if (!maps.mcNewEntries.empty()) {
929+
TIter it2(dirIn->GetListOfKeys());
930+
while (TKey *k2 = (TKey *)it2()) {
931+
if (TString(k2->GetClassName()) != "TTree")
932+
continue;
933+
std::unique_ptr<TObject> holder2(k2->ReadObj());
934+
TTree *src2 = dynamic_cast<TTree *>(holder2.get());
935+
if (!src2)
936+
continue;
937+
const char *tname2 = src2->GetName();
938+
if (isBCtree(tname2) || isFlagsTree(tname2))
939+
continue;
940+
if (findIndexBranchName(src2))
941+
continue; // handled in first stage
942+
const char *mcIdxName = findMcCollisionIndexBranchName(src2);
943+
if (!mcIdxName) {
944+
// No BC index and no McCollision index → already handled (copied) earlier
945+
continue;
946+
}
947+
948+
std::cout << " [proc] reindex+SORT " << tname2
949+
<< " (McCollision index=" << mcIdxName << ")\n";
950+
951+
TBranch *inMcIdxBr = src2->GetBranch(mcIdxName);
952+
if (!inMcIdxBr) {
953+
std::cerr << " ERR no McCollision index branch\n";
954+
continue;
955+
}
956+
Int_t oldMcI = 0, newMcI = 0;
957+
inMcIdxBr->SetAddress(&oldMcI);
958+
959+
// Build sort keys: sort by new McCollision position.
960+
Long64_t nEnt2 = src2->GetEntries();
961+
std::vector<SortKey> keys2;
962+
keys2.reserve(nEnt2);
963+
for (Long64_t i = 0; i < nEnt2; ++i) {
964+
inMcIdxBr->GetEntry(i);
965+
Long64_t newMcPos = -1;
966+
if (oldMcI >= 0 &&
967+
(size_t)oldMcI < maps.mcNewEntries.size())
968+
newMcPos = maps.mcNewEntries[(size_t)oldMcI];
969+
keys2.push_back({i, newMcPos});
970+
}
971+
std::stable_sort(keys2.begin(), keys2.end(),
972+
[](const SortKey &a, const SortKey &b) {
973+
bool ai = (a.newBC < 0), bi = (b.newBC < 0);
974+
if (ai != bi)
975+
return !ai && bi;
976+
if (a.newBC != b.newBC)
977+
return a.newBC < b.newBC;
978+
return a.entry < b.entry;
979+
});
980+
981+
dirOut->cd();
982+
TTree *out2 = src2->CloneTree(0, "fast");
983+
984+
std::unordered_map<std::string, TBranch *> inBrs2, outBrs2;
985+
for (auto *b : *src2->GetListOfBranches())
986+
inBrs2[((TBranch *)b)->GetName()] = (TBranch *)b;
987+
for (auto *b : *out2->GetListOfBranches())
988+
outBrs2[((TBranch *)b)->GetName()] = (TBranch *)b;
989+
990+
TBranch *outMcIdxBr = out2->GetBranch(mcIdxName);
991+
outMcIdxBr->SetAddress(&newMcI);
992+
993+
std::unordered_set<std::string> skipNames2;
994+
skipNames2.insert(mcIdxName);
995+
996+
std::vector<std::unique_ptr<BufBase>> scalarBufs2;
997+
for (auto &kv : inBrs2) {
998+
if (skipNames2.count(kv.first))
999+
continue;
1000+
TBranch *inBr = kv.second;
1001+
TBranch *ouBr = outBrs2.count(kv.first) ? outBrs2[kv.first] : nullptr;
1002+
if (!ouBr)
1003+
continue;
1004+
TLeaf *leaf = (TLeaf *)inBr->GetListOfLeaves()->At(0);
1005+
if (!leaf || isVLA(inBr))
1006+
continue; // no variable-length arrays seen in McCollision-indexed tables (could be changed in the future)
1007+
ScalarTag tag = leafType(leaf);
1008+
if (tag == ScalarTag::kUnknown)
1009+
continue;
1010+
auto sb = bindScalarBranch(inBr, ouBr, tag);
1011+
if (sb)
1012+
scalarBufs2.emplace_back(std::move(sb));
1013+
}
1014+
1015+
Long64_t changed2 = 0;
1016+
for (const auto &sk : keys2) {
1017+
src2->GetEntry(sk.entry);
1018+
Int_t prev = oldMcI;
1019+
newMcI = (sk.newBC >= 0 ? (Int_t)sk.newBC : -1);
1020+
if (newMcI != prev)
1021+
++changed2;
1022+
out2->Fill();
1023+
}
1024+
std::cout << " wrote " << out2->GetEntries()
1025+
<< " rows; remapped " << changed2
1026+
<< " McCollision index values; sorted\n";
1027+
out2->Write();
1028+
}
1029+
} else {
1030+
// No mccollision permutation available: clone deferred trees as-is
1031+
TIter it2(dirIn->GetListOfKeys());
1032+
while (TKey *k2 = (TKey *)it2()) {
1033+
if (TString(k2->GetClassName()) != "TTree")
1034+
continue;
1035+
std::unique_ptr<TObject> holder2(k2->ReadObj());
1036+
TTree *src2 = dynamic_cast<TTree *>(holder2.get());
1037+
if (!src2)
1038+
continue;
1039+
if (isBCtree(src2->GetName()) || isFlagsTree(src2->GetName()))
1040+
continue;
1041+
if (findIndexBranchName(src2))
1042+
continue;
1043+
if (!findMcCollisionIndexBranchName(src2))
1044+
continue;
1045+
std::cerr << " [warn] no mccollision permutation for "
1046+
<< src2->GetName() << " -> cloning as-is\n";
1047+
dirOut->cd();
1048+
TTree *c = src2->CloneTree(-1, "fast");
1049+
c->SetDirectory(dirOut);
1050+
c->Write();
1051+
}
1052+
}
1053+
8921054
// non-tree objects: copy as-is (but for TMap use WriteTObject to preserve
8931055
// class)
8941056
it.Reset();

0 commit comments

Comments
 (0)