Masks that calibrate themselves

Can the pixel masks of Skipper-CCD analyses do their job without being tuned to the particular sensor they run on?

D. Rodriguez Juiz and F. Pérez · final project, Gravitational Waves and AI-Assisted Research · repository · provenance of every result

Short answer, from simulations of three different sensors (5 independent seeds). Of the 28 cases in which a mask tuned by hand on one sensor was moved unchanged to another, 5 were worse than applying no mask at all in every seed, and 2 made no difference. The clearest was low-energy clusters on the surface laboratory sensor (tuned on deep underground): a median 0.12 of the oracle, where doing nothing scores 1.00.

The same masks written as procedures that calibrate themselves were worse than no mask in every seed in 1 of 14 cases (low-energy clusters on the surface laboratory sensor (adaptive)), and better than no mask in every seed in 12. Measured against a mask tuned with truth on the same sensor they reach a median 0.98, with a worst case of 0.38 as a median over seeds (charge-transfer trails on the surface laboratory sensor (adaptive); 0.34 in its worst seed). In 8 cases a transplanted mask beat the adaptive one in every seed: self-calibration avoids the large failures but is not free.

On the three sensors with their defects switched off, the adaptive masks fired no more often than α allows (and apparently less often; 50 runs cannot tell). The sixth mask, for muon tracks, cannot be in that test because tracks are what a real sensor cannot switch off; asked where they can be absent, in the simulator with the flux set to zero, it fired in 0 of 600 images. On the surface sensor, though, the adaptive low-energy-cluster mask keeps only 0.85–0.92 of the signal, 0.85 even in a seed with no low-energy clusters at all: it fires on charge-transfer trail electrons, a false positive that the defect-free test cannot see because it switches every defect off at once, which is why the defects were also switched on one at a time. Switching the defects on one at a time instead of all off at once shows it directly: of the 60 combinations in which the defect present is not the mask's own, 7 fire on it, the worst in 1.00 of trials while masking 0.121 of the image.

On a real sensor that nothing here was tuned for, the four exposures of the public SENSEI release, the hot-column procedure ends up flagging the 7 loudest columns of the longest exposure and nothing else, all of them inside the mask the collaboration published. The five adaptive masks together take 0.0007–0.0094 of the image, where that published mask takes 0.042–0.130.

On the 2 seeds run once after the code was frozen: 4 of 26 transplanted cases worse than no mask in every seed, 0 of 13 adaptive ones, and a median adaptive 0.98 of the oracle. The adaptive case that is worse than no mask in every development seed (low-energy clusters on the surface laboratory sensor (adaptive)) has fewer than 20 target events in the held-out seeds, so it is not counted there, although there too its figure of merit is below no mask (0.96, 0.92 of no mask).

Counted pairwise: a case is harmful only if the transplanted mask scores more than 1 % below no mask in every seed with at least 20 target events. The rule pre-registered before the re-run compared medians without a margin and gives 6 harmful transplants and 1 harmful adaptive cases; it was replaced after an independent review showed that medians differing in the third decimal were being counted as harm.

The question

A Skipper-CCD counts single electrons in millions of pixels. Before any physics is extracted, analyses discard pixels with masks, each aimed at one problem: charge left behind during transfer, hits in the serial register, hot columns and pixels, photons emitted around high-energy tracks (the halo), clusters of low-energy events, and muons. Every mask has sizes and thresholds — a radius, a trail length, a rate cut — chosen by hand for one sensor, readout and site.

The working hypothesis: what transfers between sensors is not the numbers but the procedure used to choose them. So each mask was written twice: a fixed form with hand-set constants, and an adaptive form that measures its own sizes on the images it is applied to and sets its threshold by a false-positive rate (α = 0.01, corrected for the number of tests) or by measurable physical properties of the sensor.

MaskFixed formAdaptive form
Hot columns & pixelscolumn rate above k × medianPoisson tail of each column's count against its own exposure, Bonferroni over columns, single columns before groups
Charge-transfer trailsL pixels after every bright pixeldownstream vs. upstream excess of single electrons around the same bright pixel (binomial); symmetric sources cancel
Halodisc of radius R around bright pixelseach annulus against everything outside it (conditional binomial); no far field needed
Serial-register hitsrows with n charged pixels in a window of wdensest window of each row against the image's own occupancy, at several widths
Low-energy clustersdisc around events with ≥ m neighboursneighbours within r against a Poisson count for the local valid area, at several radii
Muon trackscharge and length cutscharge of a minimum-ionising track for the measured length and this sensor's thickness; straight, piled-up or cut by the border

How it was tested

A simulator that remembers where every electron came from

Each source of charge fills its own map, so a mask can be scored against exactly the events it should remove. Three sensors differ the way real deployments do. Their geometry, noise, dark rates, background rates and muon fluxes come from public measurements (SENSEI at SNOLAB and MINOS, Oscura sensors at the surface, SNO, PDG); defect populations are not published in a transferable form and are scenario values chosen to differ between sensors.

SensorPixelsThickness (µm)Noise (e−)ExposureDark rate (e−/pix/day)Muons (cm−2 day−1)High-E (dru)Halo µm / trail px / hot cols
Deep underground3072 × 5126650.1420 h1.4 × 10-52.9 × 10-55.0 × 101100 / 30 / 4
Shallow underground3072 × 4436750.1420 h1.6 × 10-46.9 × 1003.4 × 103150 / 60 / 10
Surface laboratory1278 × 10587250.171 h3.0 × 10-21.4 × 1033.0 × 104250 / 100 / 25

Three versions of every mask were compared on an independent test stack of each sensor: the oracle (fixed form tuned with the simulator's truth on that sensor), the transplant (the oracle constants of a different sensor) and the adaptive form, calibrated without truth. The figure of merit is S/√(S+B): surviving injected signal against surviving target background.

A check against real images

Before relying on anything, the public SENSEI SNOLAB data release was read and its single-electron rate reproduced: 1.39 × 10-5 ± 1.1 × 10-6 e−/pix/day against the published 1.39 × 10-5 ± 1.1 × 10-6 (pull -0.02).

Single-electron density against exposure for four exposures of the public SENSEI release, on a straight line whose slope reproduces the published rate.
Single-electron density per exposure in the public SENSEI SNOLAB release, with the weighted straight line. The slope is the rate.
Which bit of the public mask is which (geometric check)

The release names its masks but not their bits. Each mask leaves a signature independent of its parameters; the bit order was checked against them. The noisy-row bit never appears in the active area, so it is not verified.

BitName (hypothesis)Fraction in whole columnsBright pixel upstream / only downstreamMedian distance to >100 e (px)
0x1neighbour0.060.15 / 0.06359
0x4bleeding0.051.00 / 0.00104
0x8halo0.000.20 / 0.1851
0x10crosstalk0.010.07 / 0.00752
0x40edge1.000.02 / 0.04435
0x200bad pixel0.000.04 / 0.01574
0x400bad column1.000.04 / 0.02481

Result 1 · How often the adaptive masks fire when there is nothing to find

50 independent runs of each of the three sensors with every defect the masks look for switched off, keeping what a real sensor cannot switch off: dark current, spurious charge, the injected signal, muon tracks and high-energy deposits. The stack-calibrated masks decide once per run of 2 images; the others decide per image. The test is two-sided, so a mask that is far more conservative than α is visible as well.

For each sensor and mask, the fraction of trials without the defect in which the mask fired, with 95 percent intervals, against alpha equal to 0.01.
Clopper–Pearson 95 % intervals; the vertical line is α = 0.01. Intervals are wide because 50 runs cannot resolve 0.01 from 0.03.
SensorAdaptive maskUnitFired / trialsRate95 % intervalAgainst α
Deep undergroundHot columnsper run0 / 500.000[0.000, 0.071]contains α
Deep undergroundCharge-transfer trailsper run0 / 500.000[0.000, 0.071]contains α
Deep undergroundHaloper run0 / 140.000[0.000, 0.232]contains α
Deep undergroundSerial-register hitsper image0 / 1000.000[0.000, 0.036]contains α
Deep undergroundLow-energy clustersper image1 / 1000.010[0.000, 0.054]contains α
Shallow undergroundHot columnsper run0 / 500.000[0.000, 0.071]contains α
Shallow undergroundCharge-transfer trailsper run0 / 500.000[0.000, 0.071]contains α
Shallow undergroundHaloper run0 / 500.000[0.000, 0.071]contains α
Shallow undergroundSerial-register hitsper image1 / 1000.010[0.000, 0.054]contains α
Shallow undergroundLow-energy clustersper image0 / 1000.000[0.000, 0.036]contains α
Surface laboratoryHot columnsper run0 / 500.000[0.000, 0.071]contains α
Surface laboratoryCharge-transfer trailsper run1 / 500.020[0.001, 0.106]contains α
Surface laboratoryHaloper run0 / 500.000[0.000, 0.071]contains α
Surface laboratorySerial-register hitsper image1 / 1000.010[0.000, 0.054]contains α
Surface laboratoryLow-energy clustersper image1 / 1000.010[0.000, 0.054]contains α

The muon mask is not in that table, and could not be: the five above are switched off by setting a defect rate to zero, while tracks are what a real sensor cannot switch off, and the halo is generated from their charge. Asked separately, on sensors with the tracks and the high-energy background switched off as well, it fired in 0 of 600 images (all three sensors, 200 images each), an upper limit of 0.018 at 95 %. Its threshold is physical rather than a tail probability — a cluster long enough, straight enough and carrying about the charge a minimum-ionising particle leaves crossing this sensor — so there is no α for it to match; what is measured is whether dark current can imitate a track, and at these exposures it cannot.

Result 2 · What a mask fires on when the defect present is not its own

The defect-free test above switches every defect off together, so a mask that fires on another mask's defect passes it unseen. Here each sensor is simulated with one defect at its preset value and the other four at zero, 15 configurations in all, 20 runs each, with the same chain of adaptive calibrations and the same things a real sensor cannot switch off. A mask that fires when its own defect is absent and another one is present is firing on the wrong thing.

The same question is asked of 60 mask-and-defect cells, so the bound a cell has to clear is taken at 99.92 % confidence rather than 95 %, which controls a 5 % chance of one false call over the whole grid. The hot-column row is compared with 0.02 rather than α, because it fires when either of two α-level procedures does. The 2 images of a run share the calibrations made on that run's stack, so for the two per-image masks they are not independent trials and the per-image interval is narrower than it should be. Counted one run at a time instead — a run counts as firing if either of its images did, which cannot invent a firing and throws the second image away — 6 of those 6 cells still fire. One caveat stands: a cell marked below as sitting at its detection floor fired the fewest times that could produce this verdict at all.

Of the 60 combinations in which the defect present is not the one the mask looks for, 7 fire more often than α allows and 53 are consistent with it. The largest is the low-energy clusters mask on the surface laboratory sensor when the only defect present is charge-transfer trails: it fires in 1.00 of trials and masks a median 0.121 of the image.

For each sensor, a grid of masks against the single defect switched on, with the fraction of trials in which each mask fired.
Dot area and number are the fraction of trials in which the mask fired; orange marks the cells whose lower bound, at the 99.92 % confidence corrected for the 60 cells tested, lies above the rate that mask should not exceed. Grey dots never fired; hollow circles are the diagonal, where the mask meets its own defect.
SensorOnly defect presentMask that firedUnitFired / trialsRate95 % intervalMedian fraction maskedAgainst α
Shallow undergroundCharge-transfer trailsSerial-register hitsper image5 / 400.12[0.042, 0.268]0.000fires on it (at the detection floor)
Shallow undergroundCharge-transfer trailsLow-energy clustersper image19 / 400.47[0.315, 0.639]0.000fires on it
Shallow undergroundLow-energy clustersSerial-register hitsper image6 / 400.15[0.057, 0.298]0.000fires on it
Shallow undergroundHaloLow-energy clustersper image10 / 400.25[0.127, 0.412]0.000fires on it
Surface laboratoryCharge-transfer trailsHot columnsper run9 / 200.45[0.231, 0.685]0.000fires on it
Surface laboratoryCharge-transfer trailsSerial-register hitsper image34 / 400.85[0.702, 0.943]0.001fires on it
Surface laboratoryCharge-transfer trailsLow-energy clustersper image40 / 401.00[0.912, 1.000]0.121fires on it
Every combination, including those consistent with α
SensorOnly defect presentMaskUnitFired / trialsRate95 % intervalMedian fraction maskedAgainst α
Deep undergroundHot columns & pixelsCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundHot columns & pixelsHaloper run0 / 50.00[0.000, 0.522]0.000consistent with α
Deep undergroundHot columns & pixelsSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundHot columns & pixelsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundCharge-transfer trailsHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundCharge-transfer trailsHaloper run0 / 50.00[0.000, 0.522]0.000consistent with α
Deep undergroundCharge-transfer trailsSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundCharge-transfer trailsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundSerial-register hitsHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundSerial-register hitsCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundSerial-register hitsHaloper run0 / 30.00[0.000, 0.708]0.000consistent with α
Deep undergroundSerial-register hitsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundLow-energy clustersHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundLow-energy clustersCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundLow-energy clustersHaloper run0 / 70.00[0.000, 0.410]0.000consistent with α
Deep undergroundLow-energy clustersSerial-register hitsper image4 / 400.10[0.028, 0.237]0.000consistent with α
Deep undergroundHaloHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundHaloCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Deep undergroundHaloSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Deep undergroundHaloLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Shallow undergroundHot columns & pixelsCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundHot columns & pixelsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundHot columns & pixelsSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Shallow undergroundHot columns & pixelsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Shallow undergroundCharge-transfer trailsHot columnsper run2 / 200.10[0.012, 0.317]0.000consistent with α
Shallow undergroundCharge-transfer trailsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundCharge-transfer trailsSerial-register hitsper image5 / 400.12[0.042, 0.268]0.000fires on it (at the detection floor)
Shallow undergroundCharge-transfer trailsLow-energy clustersper image19 / 400.47[0.315, 0.639]0.000fires on it
Shallow undergroundSerial-register hitsHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundSerial-register hitsCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundSerial-register hitsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundSerial-register hitsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Shallow undergroundLow-energy clustersHot columnsper run2 / 200.10[0.012, 0.317]0.000consistent with α
Shallow undergroundLow-energy clustersCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundLow-energy clustersHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundLow-energy clustersSerial-register hitsper image6 / 400.15[0.057, 0.298]0.000fires on it
Shallow undergroundHaloHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundHaloCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Shallow undergroundHaloSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Shallow undergroundHaloLow-energy clustersper image10 / 400.25[0.127, 0.412]0.000fires on it
Surface laboratoryHot columns & pixelsCharge-transfer trailsper run1 / 200.05[0.001, 0.249]0.000consistent with α
Surface laboratoryHot columns & pixelsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratoryHot columns & pixelsSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Surface laboratoryHot columns & pixelsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Surface laboratoryCharge-transfer trailsHot columnsper run9 / 200.45[0.231, 0.685]0.000fires on it
Surface laboratoryCharge-transfer trailsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratoryCharge-transfer trailsSerial-register hitsper image34 / 400.85[0.702, 0.943]0.001fires on it
Surface laboratoryCharge-transfer trailsLow-energy clustersper image40 / 401.00[0.912, 1.000]0.121fires on it
Surface laboratorySerial-register hitsHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratorySerial-register hitsCharge-transfer trailsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratorySerial-register hitsHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratorySerial-register hitsLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α
Surface laboratoryLow-energy clustersHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratoryLow-energy clustersCharge-transfer trailsper run1 / 200.05[0.001, 0.249]0.000consistent with α
Surface laboratoryLow-energy clustersHaloper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratoryLow-energy clustersSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Surface laboratoryHaloHot columnsper run0 / 200.00[0.000, 0.168]0.000consistent with α
Surface laboratoryHaloCharge-transfer trailsper run1 / 200.05[0.001, 0.249]0.000consistent with α
Surface laboratoryHaloSerial-register hitsper image0 / 400.00[0.000, 0.088]0.000consistent with α
Surface laboratoryHaloLow-energy clustersper image0 / 400.00[0.000, 0.088]0.000consistent with α

Result 3 · Transplanted constants can do harm; self-calibration avoids the large failures, at a cost

Small multiples for three sensors: figure of merit of adaptive masks and of fixed masks transplanted from other sensors, relative to the oracle.
Figure of merit relative to the oracle tuned with truth on the same sensor (vertical line). Markers are medians over 5 seeds, whiskers the range. The deep-underground sensor has few target events, so every version sits near 1 there.
Evaluated onMaskTarget eventsNo maskAdaptiveFixed, tuned on deepFixed, tuned on shallowFixed, tuned on surface
Deep undergroundHot columns & pixels590.97 (0.96–0.97)0.98 (0.98–0.99)oracle = 11.00 (1.00–1.00)0.89 (0.88–0.90)
Deep undergroundCharge-transfer trails0 too few to compare1.00 (1.00–1.00)1.00 (1.00–1.00)oracle = 11.00 (1.00–1.00)1.00 (1.00–1.00)
Deep undergroundHalo0 too few to compare1.00 (1.00–1.00)1.00 (1.00–1.00)oracle = 11.00 (1.00–1.00)1.00 (1.00–1.00)
Deep undergroundSerial-register hits3 too few to compare1.00 (0.99–1.00)1.00 (1.00–1.00)oracle = 11.00 (1.00–1.00)1.00 (1.00–1.00)
Deep undergroundLow-energy clusters250.98 (0.97–1.00)1.00 (0.99–1.00)oracle = 11.00 (0.99–1.00)0.98 (0.97–1.00)
Deep undergroundMuon tracks0 too few to compare1.00 (1.00–1.00)1.00 (1.00–1.00)oracle = 11.00 (1.00–1.00)1.00 (1.00–1.00)
Deep undergroundAll six combined810.95 (0.93–0.96)0.98 (0.98–0.99)oracle = 11.00 (0.99–1.00)0.87 (0.86–0.90)
Shallow undergroundHot columns & pixels1760.89 (0.88–0.90)0.98 (0.96–1.00)1.00 (1.00–1.00)oracle = 10.65 (0.63–0.71)
Shallow undergroundCharge-transfer trails32370.40 (0.38–0.42)0.79 (0.78–0.85)0.42 (0.39–0.42)oracle = 10.96 (0.95–0.97)
Shallow undergroundHalo2110.88 (0.88–0.88)0.97 (0.97–0.99)0.88 (0.88–1.00)oracle = 11.00 (0.99–1.00)
Shallow undergroundSerial-register hits240.99 (0.96–0.99)1.01 (1.00–1.01)0.99 (0.93–1.00)oracle = 11.00 (0.99–1.01)
Shallow undergroundLow-energy clusters1760.89 (0.76–0.93)0.98 (0.96–1.02)0.95 (0.94–0.97)oracle = 10.89 (0.76–0.93)
Shallow undergroundMuon tracks141160.19 (0.17–0.20)0.95 (0.94–0.98)1.00 (0.99–1.00)oracle = 11.00 (1.00–1.00)
Shallow undergroundAll six combined40930.40 (0.39–0.42)0.80 (0.77–0.86)0.80 (0.60–0.81)oracle = 10.55 (0.54–0.63)
Surface laboratoryHot columns & pixels16570.47 (0.47–0.53)0.99 (0.94–1.06)0.48 (0.47–0.53)0.48 (0.47–0.53)oracle = 1
Surface laboratoryCharge-transfer trails662490.27 (0.22–0.30)0.38 (0.34–0.44)0.27 (0.22–0.30)0.77 (0.67–0.85)oracle = 1
Surface laboratoryHalo20490.68 (0.66–0.70)0.68 (0.66–0.70)0.70 (0.68–0.97)1.00 (0.97–1.02)oracle = 1
Surface laboratorySerial-register hits760.94 (0.91–0.96)0.99 (0.96–1.02)0.59 (0.18–0.85)0.97 (0.94–1.00)oracle = 1
Surface laboratoryLow-energy clusters411.00 (1.00–1.01)0.96 (0.92–0.97)0.12 (0.00–0.49)0.32 (0.28–0.39)oracle = 1
Surface laboratoryMuon tracks1754940.05 (0.04–0.05)0.75 (0.67–0.81)0.86 (0.85–0.87)0.99 (0.99–1.00)oracle = 1
Surface laboratoryAll six combined700350.43 (0.40–0.54)0.59 (0.53–0.78)0.08 (0.00–0.41)0.48 (0.37–0.54)oracle = 1

Figure of merit relative to the oracle of the sensor in the first column; median, with the range over seeds in brackets.

Target removed and clean pixels kept at each working point (medians over seeds)
SensorMaskTarget eventsAdaptive: removedAdaptive: clean keptOracle: removedOracle: clean kept
Deep undergroundHot columns & pixels590.391.000.861.00
Deep undergroundCharge-transfer trails0–1.00–1.00
Deep undergroundHalo0–1.00–1.00
Deep undergroundSerial-register hits31.001.001.001.00
Deep undergroundLow-energy clusters251.000.991.001.00
Deep undergroundMuon tracks0–1.00–1.00
Shallow undergroundHot columns & pixels1760.701.000.970.97
Shallow undergroundCharge-transfer trails32370.890.941.000.86
Shallow undergroundHalo2110.670.980.910.96
Shallow undergroundSerial-register hits241.001.000.691.00
Shallow undergroundLow-energy clusters1760.930.960.960.94
Shallow undergroundMuon tracks141161.001.001.001.00
Surface laboratoryHot columns & pixels16570.940.981.000.86
Surface laboratoryCharge-transfer trails662490.860.501.000.11
Surface laboratoryHalo20490.001.000.940.51
Surface laboratorySerial-register hits760.651.000.800.98
Surface laboratoryLow-energy clusters410.330.890.001.00
Surface laboratoryMuon tracks1754941.000.951.000.97
What the adaptive masks measured on each sensor
SensorSeedTrail length h / v (px)Halo radius (px)Halo calibratedHot columns foundHot columns simulated
Deep undergroundseed_202609150 / 00yes04
Shallow undergroundseed_20260915140 / 5510yes310
Surface laboratoryseed_20260915130 / 950yes2525
Deep undergroundseed_202609160 / 00no04
Shallow undergroundseed_20260916125 / 6010yes710
Surface laboratoryseed_20260916130 / 850yes2525
Deep undergroundseed_202609170 / 00yes24
Shallow undergroundseed_20260917140 / 5010yes710
Surface laboratoryseed_20260917115 / 800yes2725
Deep undergroundseed_202609200 / 00yes14
Shallow undergroundseed_20260920140 / 5515yes1010
Surface laboratoryseed_20260920130 / 950yes2525
Deep undergroundseed_202609210 / 00yes24
Shallow undergroundseed_20260921150 / 5010yes510
Surface laboratoryseed_20260921105 / 850yes3125

Result 4 · The same procedures on a real sensor

Everything above is simulated. Here the adaptive masks run unchanged on the 4 exposures of the public SENSEI SNOLAB release: a fourth sensor, real, with a geometry none of the presets has (3072 × 16 active superpixels, each binning 32 physical rows, so a step along a column is 32 times a step along a row). Nothing about it was tuned, and the release publishes its own mask, so where the two overlap they can be compared. The pairing of one of our masks with a bit of that mask follows the hypothesis tested against the release's own geometry earlier on this page.

Given only the images, the estimator measures a readout noise of 0.141–0.142 e, where the independent fit of the rate reproduction above, on the same files, gives 0.1413–0.1420 e, and a single-electron density that grows with exposure.

What the hot-column procedure finds. It flags 2, 4, 6, 7 columns as the exposure grows, and the sets are nested: each one keeps the previous columns and adds the next loudest. At the longest exposure the 7 columns with the highest rate of charged pixels are exactly the ones it flags, and every one of them lies inside the release's own bad-column mask; the next column down (1659, at 0.019 charged pixels per pixel) is in the release's mask and is not flagged, which is the conservative direction. Each flagged column carries 102 to 1830 times the charged-pixel rate of the columns left alone.

The two directions of agreement say different things, so both are here. Of what we flag, the release also flags 0.99–1.00: we stay inside their mask. Of what they flag, we flag 0.027–0.095: they mask far more than we do, 0.042 to 0.130 of the image against our 0.0007 to 0.0094. The first number is the easy direction — a procedure that flagged one true column would score 1.00 — and it rests on 2 to 7 column decisions, not on the hundreds of pixels it is counted over.

ExposureImagesTrigger pixelsMeasured noise (e)1e density (e/pix)Trail lengths h / vHalo radiusHot columns / pixelsWe mask (union)The release masks
0 h1400.1421.34 × 10-40 / 002 / 80.00070.042
2 h14700.1421.72 × 10-40 / 004 / 80.00130.055
6 h141030.1412.95 × 10-40 / 006 / 120.00380.061
20 h138440.1416.52 × 10-40 / 0257 / 110.00940.130

The trail calibration chose length zero on every exposure, which the expectation registered in PLAN.md did not predict. The reason is in the result file: the release blinds its hits, so a whole exposure holds 0, 70, 103, 844 trigger pixels. At the longest exposure the test does see the excess on the right side — 13 single electrons within 5 superpixels downstream of a trigger against 2 upstream, p = 0.0037 — but the corrected threshold is p < 6.3e-05. Part of that strictness is an artefact: the correction counts 80 distance blocks per direction, and on an image 16 rows tall only three of them can ever be filled. Correcting for the tests that can exist would ask for about 1.7×10-3, which this p-value still does not meet, so the decision stands. The halo radius behaves the same way: 0 where there are no triggers, 25 column widths at the longest exposure.

Every mask against its counterpart in the release — the low-energy-cluster mask is not here, since the release publishes no counterpart to it, although the union above includes it
ExposureOur maskRelease bitFraction of the image we maskOf ours, also theirsOf theirs, also ours
0 hHot columns & pixelsbad column | bad pixel0.00071.000.027
0 hCharge-transfer trailsbleeding0.0000——
0 hHalohalo0.0000——
0 hSerial-register hitsnoisy row0.0000——
2 hHot columns & pixelsbad column | bad pixel0.00131.000.055
2 hCharge-transfer trailsbleeding0.0000—0.000
2 hHalohalo0.0000—0.000
2 hSerial-register hitsnoisy row0.0000——
6 hHot columns & pixelsbad column | bad pixel0.00201.000.081
6 hCharge-transfer trailsbleeding0.0000—0.000
6 hHalohalo0.0000—0.000
6 hSerial-register hitsnoisy row0.0000——
20 hHot columns & pixelsbad column | bad pixel0.00230.990.095
20 hCharge-transfer trailsbleeding0.0000—0.000
20 hHalohalo0.00711.000.119
20 hSerial-register hitsnoisy row0.0000——

What the checks caught

Every error below was found by a test or a diagnostic against the simulator's truth, fixed, and recorded.

Limitations

Reproduce

uv sync --group dev
uv run python scripts/fetch_public_data.py
uv run pytest
uv run python analysis/reproduce_release_rate.py
uv run python analysis/check_release_mask_bits.py
uv run python analysis/adaptive_masks_on_public_data.py
uv run python analysis/null_false_positive_rates.py 50
uv run python analysis/muon_mask_null_rate.py 100
uv run python analysis/cross_defect_false_positives.py 20
for seed in 20260915 20260916 20260917 20260920 20260921; do
  uv run python analysis/compare_masks_across_sensors.py 4 --seed $seed --out results/compare_masks/seed_$seed
done
uv run python analysis/figure_release_rate.py
uv run python analysis/figure_null_rates.py
uv run python analysis/figure_cross_defect.py
uv run python analysis/figure_compare_masks.py
uv run python analysis/build_report.py
uv run python scripts/make_pdf.py

Every output has a .provenance.json sidecar with the script, git commit, input hashes, parameters and seed; PROVENANCE.md says how each result was checked.

What that reproduction covered, as of 2026-09-16, written by hand unlike every number above it, because it describes runs made outside this repository. Each was re-run in a fresh clone that shares nothing with the working copy but the commit and the pinned environment, and compared at a relative tolerance of 1e-9. Identical, largest relative difference zero: the rate reproduction, the mask-bit check, the defect-free test and the real-sensor result at the current commit; the muon-mask test in a second clone; all five seeds of the transplant result at the commit that froze it, whose code has changed since only inside a docstring; and the one-defect-at-a-time result, the slowest of them at about two and a half hours, re-run in a clone that had to be resumed after something killed it six runs in. Every analysis in this repository has therefore been produced twice, the second time somewhere that shares nothing with the working copy but the commit and the pinned environment.