Skip to content

Commit 0ab0fdf

Browse files
committed
Do not resort the BC table, just remove the duplicates
1 parent e882201 commit 0ab0fdf

1 file changed

Lines changed: 43 additions & 19 deletions

File tree

MC/utils/AODBcRewriter.C

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
//
1515
// This tool fixes all three problems in one pass per DF_ directory:
1616
//
17-
// Stage 0 — Sort & deduplicate the BC table. Build BC permutation map:
18-
// bcPerm[oldBCrow] = newBCrow.
17+
// Stage 0 — Deduplicate the BC table in place (order-preserving; the input
18+
// must already be globalBC-sorted). Build BC permutation map:
19+
// bcPerm[oldBCrow] = newBCrow (monotonic non-decreasing).
1920
//
2021
// Stage 1 — Process every table that carries fIndexBCs / fIndexBC.
2122
// Remap the index via bcPerm, sort rows by the new index, and
@@ -501,18 +502,31 @@ static PermMap rewriteTable(TTree *src, TDirectory *dirOut,
501502
}
502503

503504
// ============================================================================
504-
// SECTION 4 — Stage 0: BC table sort + deduplication
505+
// SECTION 4 — Stage 0: BC table deduplication (order-preserving)
505506
// ============================================================================
506507
//
507-
// Reads fGlobalBC from the BC tree, sorts rows, drops exact-duplicate BC
508-
// values, and writes the compacted table. Returns bcPerm[oldRow] = newRow.
508+
// Reads fGlobalBC from the BC tree, drops exact-duplicate BC values IN PLACE
509+
// (preserving input row order), and writes the compacted table. Returns
510+
// bcPerm[oldRow] = newRow.
511+
//
512+
// The dedup is deliberately order-preserving so that bcPerm is monotonic
513+
// non-decreasing. This matters because every BC-indexed table (collisions,
514+
// FT0/FV0/FDD/Zdc, ...) is sliced per BC and must stay sorted by its fIndexBCs,
515+
// and collisions are in turn the grouping anchor for tracks (sorted by
516+
// fIndexCollisions). A non-order-preserving BC remap would force a full reorder
517+
// cascade BC -> collisions -> tracks to keep all those groupings valid; keeping
518+
// bcPerm monotonic means none of those tables need to be reordered at all.
519+
//
520+
// This REQUIRES the input BC table to already be sorted by fGlobalBC (the
521+
// standard AO2D invariant; also asserted on the output by validateDF check #1).
522+
// We assert it loudly rather than silently emit a non-monotonic BC table.
509523

510524
struct BCStage0Result {
511-
PermMap bcPerm; // bcPerm[oldRow] = newRow in sorted/deduped BC table
525+
PermMap bcPerm; // bcPerm[oldRow] = newRow in the deduped BC table
512526
Long64_t nUnique = 0;
513527
};
514528

515-
static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) {
529+
static BCStage0Result stage0_dedupBCs(TTree *treeBCs, TDirectory *dirOut) {
516530
BCStage0Result res;
517531
Long64_t n = treeBCs->GetEntries();
518532
if (n == 0) return res;
@@ -525,19 +539,29 @@ static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) {
525539
std::vector<ULong64_t> gbcs(n);
526540
for (Long64_t i = 0; i < n; ++i) { treeBCs->GetEntry(i); gbcs[i] = gbc; }
527541

528-
// Sort row indices by fGlobalBC
529-
std::vector<Long64_t> order(n);
530-
std::iota(order.begin(), order.end(), 0);
531-
std::stable_sort(order.begin(), order.end(),
532-
[&](Long64_t a, Long64_t b){ return gbcs[a] < gbcs[b]; });
542+
// The BC table must already be sorted by fGlobalBC: the dedup below is
543+
// order-preserving (merges only adjacent equal-globalBC rows), which keeps
544+
// bcPerm monotonic and avoids a reorder cascade through collisions/tracks.
545+
// A non-monotonic input would silently break that guarantee, so abort loudly.
546+
for (Long64_t i = 1; i < n; ++i) {
547+
if (gbcs[i] < gbcs[i - 1]) {
548+
std::cerr << "FATAL: O2bc_* table is not sorted by fGlobalBC (row " << i
549+
<< " globalBC=" << gbcs[i] << " < row " << (i - 1)
550+
<< " globalBC=" << gbcs[i - 1] << ").\n"
551+
<< " AODBcRewriter requires a globalBC-sorted BC table so that\n"
552+
<< " BC deduplication is order-preserving; aborting.\n";
553+
std::abort();
554+
}
555+
}
533556

534-
// Build deduplicated row list and the permutation
557+
// Build the deduplicated row list and the (monotonic) permutation in source
558+
// row order: adjacent rows sharing a globalBC collapse onto one output row.
535559
res.bcPerm.assign(n, -1);
536560
std::vector<Long64_t> rowOrder; // source rows to keep, in output order
537-
ULong64_t prev = ULong64_t(-1);
561+
ULong64_t prev = 0;
538562
Int_t newRow = -1;
539-
for (Long64_t srcRow : order) {
540-
if (gbcs[srcRow] != prev) {
563+
for (Long64_t srcRow = 0; srcRow < n; ++srcRow) {
564+
if (newRow < 0 || gbcs[srcRow] != prev) {
541565
++newRow;
542566
prev = gbcs[srcRow];
543567
rowOrder.push_back(srcRow);
@@ -547,7 +571,7 @@ static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) {
547571
}
548572
res.nUnique = rowOrder.size();
549573

550-
std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique\n";
574+
std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique (in-place dedup)\n";
551575

552576
// Write the BC table (no index remapping needed for the table itself)
553577
rewriteTable(treeBCs, dirOut, rowOrder, /*indexBranch=*/"", /*parentPerm=*/{});
@@ -1020,10 +1044,10 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) {
10201044
return;
10211045
}
10221046

1023-
// ---- Stage 0: sort & deduplicate BCs ----
1047+
// ---- Stage 0: deduplicate BCs (order-preserving) ----
10241048
std::cout << "-- Stage 0: BCs --\n";
10251049
dirOut->cd();
1026-
BCStage0Result s0 = stage0_sortBCs(treeBCs, dirOut);
1050+
BCStage0Result s0 = stage0_dedupBCs(treeBCs, dirOut);
10271051
if (treeFlags) stage0_copyBCFlags(treeFlags, dirOut, s0.bcPerm);
10281052

10291053
// Track which tree names have been written so we don't double-write

0 commit comments

Comments
 (0)