External CRC benchmark, round 4: lab book

Parallax Pathology · Russell Parrish, analysis carried out with Claude (Anthropic) · 5–6 November 2026 · lab book for round 4 of the external CRC benchmark · published November 2026

Published as written at the time, apart from this header. File and folder names refer to the project record, available on request. Benchmark note · Claim ledger

Summary. Round 4 added 70 new fixed measurements (the r4 family: colour of the non-nuclear tissue, texture, nuclear form, perinuclear halo, gaps) and read them with an average of twelve readouts over six field views. Frozen and run once on the 5,380 sealed tiles (look 4), it reached 93.8% accuracy (balanced 91.0%), up from 91.6% (89.9%) at look 3; 234 tiles newly right against 120 newly wrong. The strongest new measure is the ratio of haematoxylin to eosin in the non-nuclear tissue, which separates stroma from muscle in both collections. Muscle called stroma fell from 70 to 3, but stroma itself fell from 0.72 to 0.64, and a new error appeared: 38 sealed muscle tiles called mucus. On development tiles the same error comes from muscle rendered orange-tan, a second rendering variant of the test collection.

Entry 1 · Bookkeeping

Before round 4 the sealed tiles had four logged looks (0 to 3). Same rule: develop on NCT (all) and the 1,800 development tiles only; one logged look at a frozen version (../EXTERNAL_CRC_ROUND2_20261105/LOOK_LOG.md).

Entry 2 · The r4 family

scripts/r4_axes.py: 70 fields, fixed and label-free, each a named quantity of the tile. The existing v1/v2 families separate the stains but rescale each one within the tile, which removes absolute stain amounts; r4 keeps them.

The fields are built to be rotation-invariant. On 6 test tiles rotated by 90°, one field moved by more than 5% (nuclear waviness, through the pixel grid). Speed about 0.08 s per tile. Measured with round-1 violet protection on all 100,000 NCT tiles (from the external drive, checkpointed), the 1,800 development tiles and, after the freeze, the 5,380 sealed tiles: no failures; the gate flagged 363, 103 and 75 tiles, as in every round.

Entry 3 · Do the new fields transfer?

Area under the curve of each field, NCT and development tiles (outputs/02_transfer.csv); 60 of 70 fields point the same way in both collections with |AUC − 0.5| > 0.05 for at least one of the two pairs.

Stroma vs muscleNCTDevelopmentNormal vs tumourNCTDevelopment
H/E ratio, non-nuclear tissue0.7140.863Gabor energy, 16 px0.8010.923
Haematoxylin, 10th percentile0.6020.761Lightness (L*), median0.8280.908
Chromatin texture0.4060.246Haematoxylin, 90th percentile0.2420.103
Red-green (a*), median0.2850.254DAB channel, median0.1790.106
DAB channel, median0.4160.263Chroma, median0.1540.119

AUC above 0.5 means higher in stroma (left) or normal (right). The best earlier stroma/muscle field reached about 0.79 on development tiles.

Entry 4 · The haematoxylin-to-eosin ratio

Median haematoxylin over median eosin in the non-nuclear tissue. Smooth-muscle cytoplasm takes eosin strongly; collagen and ground substance hold relatively more haematoxylin.

Median ratioMuscleStromaDebrisTumourLymphocytesNormalAdipose
NCT0.390.510.450.630.680.805.4
Development0.340.530.540.610.570.591.08

Limits: it helps the stroma/muscle boundary, not the whole picture (debris, tumour and lymphocytes sit nearby); it is unstable on tiles with little tissue (adipose); it depends on a working stain separation; and it reads orange-rendered tissue as nearly unstained (Entry 9).

Entry 5 · Development readouts

Development tilesGradient boosting (500)LogisticAverage of bothStroma (avg)
Round-3 fields (148)89.1%86.4%91.0%0.74
+ r4, all (218)90.6%86.0%91.5%0.68
+ r4, transfer-screened (208)90.0%85.3%90.3%0.66
Shift-screened, max class shift ≤ 0.5 SD (59)89.2%82.0%88.9%0.61
Shift-screened, ≤ 0.75 SD (110)90.7%85.9%91.4%0.61
Shift-screened, ≤ 1.0 SD (152)90.6%83.9%90.8%0.64

Shift screen: for each field and class, (development median − NCT median) / NCT standard deviation; fields kept if the largest absolute shift over the nine classes is within the bound. Every version gains muscle and loses stroma. Development stroma is denser and more aligned than NCT stroma (Gabor anisotropy is about 0.5 SD higher in both development stroma and development muscle, which moves stroma towards muscle), and development adipose has far less tissue per tile (tissue fraction shifted −4.3 SD), which destabilises its colour fields.

Entry 6 · Averaging over views

The six views make different mistakes. Averaging the class probabilities of all twelve readouts (six views × two readouts) gives 92.4% on development tiles. About 240 subsets of eight readouts from four of the views were also scored (best 92.6%); the rule "every view, both readouts" was taken instead of the best subset. Three views are chosen with development labels (transfer and shift screens), so a split-half check was run: screens chosen on one stratified half, ensemble scored on the other, then swapped (scripts/04_split_half.py): 92.1%.

Entry 7 · Freeze (02:35 UTC, 6 November)

FROZEN_ROUND4.md and hashes. Primary: the twelve-readout average, all fitted once on the 100,000 NCT tiles; screens recomputed at look time from NCT and the 1,800 development tiles, identical to development. Secondary, same look: round-3 fields + r4 all, gradient boosting and logistic only (no screening on development labels).

Entry 8 · Look 4 (sealed, run once)

5,380 sealed tilesAccuracy (95% tile-level)BalancedStromaMuscleNormal
Look 2: + v1/v2 extensions, gradient boosting91.5% (90.7–92.2)89.4%0.7060.8520.819
Look 3: direction-free, boosting + logistic91.6% (90.9–92.3)89.9%0.7190.8140.860
Look 4: + r4, six views averaged93.8% (93.1–94.4)91.0%0.6430.8900.915
Look 4: + r4, single view (secondary)91.6% (90.9–92.3)89.5%0.6110.8850.884

Primary recall by class: adipose 0.931, background 1.000, debris 0.914, lymphocytes 0.963, mucus 0.980, muscle 0.890, normal 0.915, stroma 0.643, tumour 0.956. 5,044 of 5,380 correct (336 errors). Tile by tile against look 3: 234 newly right, 120 newly wrong (paired sign test p ≈ 1 × 10⁻⁹).

Sealed confusionLook 3Look 4
Muscle → stroma (of 392)703
Stroma → muscle (of 221)4850
Stroma → tumour / debris5 / 015 / 8
Normal → tumour (of 541)4839
Muscle → mucus (of 392)038
Adipose → muscle (of 1,138)4052

Entry 9 · Orange-rendered muscle (development tiles)

Development muscle called mucus, muscle called correctly, and mucus
Rows: development muscle called mucus by the round-4 average (the first 8 of 17); development muscle called correctly; development mucus.

On development tiles the twelve-readout average calls 17 muscle tiles mucus (round-3 fields alone: 1). They are rendered orange-tan. The fixed stain vectors read orange as almost unstained: H/E ratio 0.06 against 0.37 for correctly called muscle, eosin median 0.011 against 0.034 (mucus 0.010). Label-free, mean red minus mean blue above 30 flags 28 development muscle tiles, 4 debris and 2 stroma, and no other class. The sealed muscle-to-mucus error was not opened; on development tiles it has this cause.

Entry 10 · Reading

Entry 11 · Note for other workstreams (H/E ratio)

Ratio of haematoxylin to eosin in non-nuclear tissue: fixed Ruifrok–Johnston deconvolution (scikit-image rgb2hed, no per-tile rescaling); nuclei masked by Otsu on haematoxylin within tissue, dilated 2 px; median H ÷ median E over the remaining tissue. Stroma vs muscle AUC 0.714 on NCT-CRC-HE-100K and 0.863 on CRC-VAL development tiles, same direction. In look 4 it is one of 70 new fields inside a six-view average that reached 93.8% on sealed tiles; its separate contribution on sealed tiles has not been isolated. Conditions: a minimum amount of non-nuclear tissue; a working stain separation (the earlier degenerate Macenko normaliser, with stain vectors 0.17° apart, would flatten it); and a rendering check, since orange-rendered tissue reads as nearly unstained. Code: EXTERNAL_CRC_ROUND4_20261105/scripts/r4_axes.py.