← tgeo-material · part 1: the 2-point functions
CMS Phase-2 cmsSimGeom-Run4D123.root · ROOT 6.41.01 ·
9 September 2026 · follow-up to
part 1
TGeoNode::LocalToMaster, which returns the mother's frame,
not the global one. The endcap mothers sit at z = ±29.10 cm, so every
disc was 29.1 cm too close to the interaction point and the disc-to-disc
budgets were measured between the wrong planes. §5 now carries the
corrected numbers. The barrel results here and in part 1 are
unaffected — those mothers are at z = 0, which is exactly why
the mistake survived. See §5 for what changed.
Part 1 measured how much material sits between two tracker layers. That immediately raises the question of what it is and where it sits — is the budget in the layers themselves or in the gaps, is it silicon or cabling, and does the endcap behave like the barrel? This page answers those, plus a hunt for an azimuthally localised service shaft, which came back negative for an interesting reason and turned up a ROOT bug on the way.
Before any correlator, the plain question: what does the material distribution look like? Shooting one radial ray per (z, φ) cell and splitting each step exactly across r bins gives the density field ⟨1/X0⟩ per cm, of which the φ-average is the structural overview.
Tile the radius as [L1 body][gap][L2 body][gap]…[BTL body], using each layer's own envelope. Layers and gaps then add to the whole thing with nothing missing. At |z| < 15 cm:
| role class | x/X0 | share | excluding BTL |
|---|---|---|---|
| active sensor (Si + LYSO) | 0.294 | 42% | 0.047 |
| module / readout | 0.228 | 33% | 0.214 |
| support / mechanics | 0.105 | 15% | 0.044 |
| services | 0.022 | 3% | 0.022 |
| air | 0.004 | 0.5% | 0.004 |
| other | 0.041 | 6% | 0.000 |
| total | 0.694 | 0.331 |
The headline split hides the more useful fact. The BTL alone is 0.364 of the 0.626 in-layer total, and it is 58% active LYSO. Take it out and the picture inverts: in the tracker proper the sensors contribute 0.047 against 0.214 for module and readout material. Inside a single inner-tracker layer the sensor is about 8.5% of that layer's budget and the hybrid/chip mixture is about 91%. So "silicon plus carbon fibre" is not the right mental model for a tracker layer — overwhelmingly it is readout electronics.
The classification uses CMS's own composite names, which carry the role
(servicecomposite, supportcomposite,
hybridcomposite, tkLayout_SenSi), so it is their
labelling rather than ours. Two honest caveats:
hybridcomposite…ModuleSupportPlate is mechanically support
despite the prefix and is counted with the module mixture, where it is the
single largest entry; and servicecomposite is cables and cooling
blended together and cannot be separated at this level.
Part 1 anchored the correlators at each layer's mid-envelope radius. The physically right anchor is the material centroid — the x/X0-weighted mean radius within the envelope — and the two are not the same:
| layer | mid-envelope | material centroid | offset |
|---|---|---|---|
| IT1 | 3.31 | 3.06 | −0.25 |
| IT2 | 6.44 | 6.18 | −0.26 |
| IT3 | 10.77 | 10.52 | −0.25 |
| IT4 | 14.96 | 14.71 | −0.25 |
| OT1 | 25.67 | 23.57 | −2.10 |
| OT2 | 37.67 | 36.32 | −1.35 |
| OT3 | 52.84 | 51.45 | −1.39 |
| OT4 | 68.84 | 68.80 | −0.04 |
| OT5 | 86.11 | 86.07 | −0.04 |
| OT6 | 108.39 | 108.36 | −0.03 |
| BTL | 116.58 | 115.99 | −0.59 |
The inner tracker is off by a uniform 2.5 mm, which largely cancels when you take the difference between two layers. TB2S (OT4–OT6) is exact to a fraction of a millimetre. The one that matters is TBPS, and OT1 in particular, where the centroid is 2.1 cm inside the mid-envelope radius: those envelopes are 8 cm thick and the material sits in the inner part. A layer-to-layer parametrisation intended for a track fitter should be anchored to the centroid column, not the mid-envelope one.
A radial scan through the barrel at z ≈ 0 sees almost no service material — 3% of the budget. That is not because there is little of it, but because services run longitudinally and turn outward only at the ends of the barrels. Integrated over r < 125 cm:
| z [cm] | 5 | 35 | 55 | 95 | 145 | 205 | 235 | 275 |
|---|---|---|---|---|---|---|---|---|
| services x/X0 | 0.021 | 0.054 | 0.059 | 0.071 | 0.083 | 0.084 | 0.091 | 0.082 |
| share of total | 3.1% | 8.7% | 9.0% | 12.0% | 15.5% | 15.7% | 16.5% | 45% |
Four times more service material at large |z| than in the barrel core, and beyond z ≈ 255 cm — past the last sensors — services and support are essentially all that is left.
The direct analogue of the barrel correlator with r and z swapped. A path runs from a point on disc A to a point on disc B,
A = (r_A, phi_A, z_A) -> B = (r_A + dr, phi_A + dphi, z_B)
and G(rA, Δφ, Δr) is φ-averaged with rA kept as an axis, for the same reason zA is kept in the barrel: disc material varies strongly along it. Pairs are chosen clear of the barrel/endcap transition — TFPX discs 5–8 (global z = 67–140 cm), TEPX 9–12 (175–265), TEDD 3–5 (185–265).
| pair | zA → zB | r range | x/X0 | x/λI | x/X0 as first published |
|---|---|---|---|---|---|
| TFPX5 → 6 | 67 → 84 | 3.1–16.2 | 0.0371 | 0.0107 | 0.0737 |
| TFPX6 → 7 | 84 → 111 | 3.1–16.2 | 0.0375 | 0.0109 | 0.0375 |
| TFPX7 → 8 | 111 → 140 | 3.1–16.2 | 0.0375 | 0.0109 | 0.0472 |
| TEPX9 → 10 | 175 → 201 | 6.2–25.5 | 0.0491 | 0.0143 | 0.0432 |
| TEPX10 → 11 | 201 → 231 | 6.2–25.5 | 0.0492 | 0.0144 | 0.0774 |
| TEPX11 → 12 | 231 → 265 | 6.2–25.5 | 0.0494 | 0.0144 | 0.0695 |
| TEDD3 → 4 | 185 → 222 | 32–110 | 0.0430 | 0.0120 | 0.0630 |
| TEDD4 → 5 | 222 → 265 | 32–110 | 0.0432 | 0.0121 | 0.0432 |
A disc-to-disc step costs 0.037–0.049 X0: two to three times an inner-barrel layer step (0.016–0.022), and comparable to the outer barrel pairs. Per measurement, the endcap is materially the expensive place to be.
TGeoNode::LocalToMaster applies only that node's own matrix, so it
maps into the immediate mother's frame. The name suggests "master = world"; it
does not. The barrel mothers here sit at z = 0, so barrel positions came out
right by accident and the mistake was invisible for a whole page.
OTDisc3
appeared at z = 184 while the code believed that disc was at z = 156.
The tracker services have to leave the volume somewhere, and a plausible picture is a localised shaft at one azimuth. We looked for it and did not find one. The evidence:
ectkcable:, the tracker PP1 cable cone, spanning
|z| = 271–329 cm and r = 124–178 cm. It is enormously dense —
8.4 X0 traversed radially, dominated by stainless
steel — but over a 180-point azimuthal scan its max/median is
1.1. Uniform.The only genuinely narrow azimuthal features in that region are two
10-degree aluminium wedges, ectkcable:ETSU at
φ = 355°–5° and its 180-degree mirror, which are structural
spurs inside the cone and carry no budget excess relative to the cable sectors
around them.
So: a dense service cone, yes, and one that any forward track pays for heavily. A localised service chimney, no — not in this geometry. What this does not exclude is r > 350 cm, outside the tracker, where the scan is blocked by the crash described next.
TGeoPcon::DistFromInside can blow the stack.
It crosses to the next Pcon z-segment by recursion rather than
iteration (TGeoPcon.cxx:570). When the returned step is at or near
zero — a point pinned on a boundary — the point advances only by the
1E-6 nudge per level, and roughly 40 000 frames later the stack is gone.
A loop would grind slowly and return.
The trigger here is ectkcable:ETSU, the PP1 wedge, which packs
three degeneracies into one shape: a plane where
rmin == rmax, and two pairs of z-planes at identical
z — combined with a 10-degree φ wedge and a strongly flaring cone
(rmin2 = 140.5 > rmax1 = 128.3).
The φ dependence is sharp and reproducible: a radial ray at z = 290 cm survives at φ = 0 and dies at φ = 5°, exactly the wedge's phi1 + dphi. Offsetting the sampling off the 5-degree boundaries lets a full 180-point azimuthal scan run clean, which is the workaround used for the numbers above. A single ray at the failing (z, φ) does not always die, which initially made it look like accumulated state corruption; it is not, it is purely whether that ray lands on the boundary.
Suggested fix: convert both recursions in TGeoPcon::DistFromInside
to a loop with an iteration cap and return the accumulated distance when the cap
is hit. That turns an unrecoverable stack overflow into a bounded,
slightly-wrong answer — the usual TGeo failure mode for degenerate input,
and much preferable in a scanning application. It may also be worth warning at
construction about Pcon planes with rmin == rmax or
repeated z. Full writeup with a reproducer is in
BUG-TGeoPcon-DistFromInside-recursion.md alongside the code.
source ./renv.sh
root -l -b -q run_matfield.C # the density field and its projections
root -l -b -q run_endcap.C # the disc-to-disc correlators
root -l
.L mat_budget.C+
mb_init();
mb_census(15.0, 256); # the layer/gap table and centroids
mb_draw_census(15.0, 256); # the composition figure
mb_class_vs_z(0, 125, 30, 0, 300); # services vs z
mb_hunt_phi(350, 25, 40, -300, 300, 180); # the azimuthal hunt
cmsSimGeom-Run4D123.root, CMS Phase-2 Run4D123.
Analysis with ROOT 6.41.01.