diff --git a/common/BraggIntegrationSettings.h b/common/BraggIntegrationSettings.h index 58327127..b3b64104 100644 --- a/common/BraggIntegrationSettings.h +++ b/common/BraggIntegrationSettings.h @@ -20,7 +20,12 @@ class BraggIntegrationSettings { IntegratorMode integrator_mode = IntegratorMode::ProfileGaussian; float r_1 = 4; float r_2 = 6; - float r_3 = 10; + // The background ring's precision is set by how many pixels it averages, not by how big the + // reflection is: the ring mean's error enters the intensity n_inner times over, so var(b)/n_B is + // a first-order term in sigma. At r3 = 10 the ring holds ~200 px against the r1 disk's ~50, and + // widening it to 13 roughly doubles that for no cost in signal - the disk is untouched, and the + // extra pixels sit further from the reflection, not closer. + float r_3 = 13; // How many times the beam's radial streak to push the r2..r3 background ring out by, per // reflection. A bandwidth streaks a spot radially by bw_sigma*Rpx, and against a fixed pixel ring // that puts the background annulus on the reflection's own tails at high resolution, where it diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index be240e67..46157b99 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,7 @@ This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use. * rugnux: The error-model **a** and **b** are reported in XDS's convention, and `_reflns.jfjoch_diffrn_ISa` now carries the whole-range `1/sqrt(a*b)` that XDS's ISa denotes; the strong-reflection asymptote moves to `_reflns.jfjoch_diffrn_ISa_asymptotic`. **A file written by an earlier version carries the asymptote under the old name.** +* Bragg integration: the background ring's outer radius default changes from 10 px to **13 px**, which roughly doubles the pixels behind each background estimate; the signal disk is unchanged. * rugnux: The background ring can be **elongated radially per reflection** for broadband data (`--integration-stencil `, default 0 = the fixed circular ring), by `k` times the beam's radial streak; the `r1` signal box stays circular. * rugnux: New **beam-stop shadow detection**, **on by default** (`--detect-beam-stop[=N|off]`), finds the beam stop and its holder in a projection of N images (default 60) and adds them to the pixel mask as bit 9, which is cleared at the start of every run. * Viewer: the detected beam-stop shadow is drawn in coral, with a "Show beam stop" switch in the side panel. diff --git a/docs/CPU_DATA_ANALYSIS.md b/docs/CPU_DATA_ANALYSIS.md index 2b792ac9..5b34550d 100644 --- a/docs/CPU_DATA_ANALYSIS.md +++ b/docs/CPU_DATA_ANALYSIS.md @@ -567,7 +567,7 @@ Pixels are classified by their squared distance $r^2=(x-x_p)^2+(y-y_p)^2$: Invalid pixels (masked/bad/saturated) are excluded from both sums. In addition, pixels lying inside the signal disk ($r`, default 0).** The three radii above are fixed pixel counts, identical for every reflection at every resolution. A reflection is not round, though: a finite bandwidth streaks it radially by $\sigma_\mathrm{bw}=\text{bandwidth}\cdot R_\mathrm{px}$. On a radially smeared spot the fixed $6\ldots10$ px ring therefore sits only $\approx1.3$–$2.2$ radial $\sigma$ from the centre — on the reflection's own tails, which it then measures as background. +**Radially elongated background ring (opt-in, `--integration-stencil `, default 0).** The three radii above are fixed pixel counts, identical for every reflection at every resolution. A reflection is not round, though: a finite bandwidth streaks it radially by $\sigma_\mathrm{bw}=\text{bandwidth}\cdot R_\mathrm{px}$. On a radially smeared spot the fixed $6\ldots13$ px ring therefore sits only $\approx1.3$–$2.2$ radial $\sigma$ from the centre — on the reflection's own tails, which it then measures as background. With $k>0$ the **background ring becomes an ellipse**, elongated along the beam→reflection direction by $k\sigma_\mathrm{bw}$. The **radial** semi-axes become $r_2+k\sigma_\mathrm{bw}$ and $r_3+k\sigma_\mathrm{bw}$; the **tangential** half-widths stay $r_2$ and $r_3$; and the growth is capped at $2r_3$, which bounds what a mis-declared bandwidth can do to the bounding box. Pixels are then classified as diff --git a/image_analysis/bragg_integration/BraggIntegrationEngine.h b/image_analysis/bragg_integration/BraggIntegrationEngine.h index 7deca572..057e5143 100644 --- a/image_analysis/bragg_integration/BraggIntegrationEngine.h +++ b/image_analysis/bragg_integration/BraggIntegrationEngine.h @@ -53,7 +53,7 @@ constexpr double C_CAPTURE = 2.5; // weak-spot radial capture term ( // Lower bound on the background term of the Kabsch fit weights (v = max(bkg, floor) + signal). It // guards the background ESTIMATE, not the detector: the r2..r3 ring mean of a high-angle reflection // can come out exactly zero, and v = 0 makes the weights P^2/v diverge. A ring of n pixels cannot -// resolve a background below ~1/n (0.005..0.02 for the default r2=6/r3=10 stencil), so that is the +// resolve a background below ~1/n (0.003..0.02 for the default r2=6/r3=13 stencil), so that is the // scale the floor has to work at. Anything larger over-regularizes: the floor multiplies the reported // variance by floor/bkg for every pixel below it, so the previous 1/12 inflated sigma by 1.3x at // 0.05 ct/px and 1.7x at 0.03 - exactly where the weakest high-resolution data live. Digitisation @@ -70,7 +70,7 @@ constexpr double WEIGHT_VARIANCE_MIN_FRACTION = 0.5; // unbounded vector and would otherwise keep trimming where the GPU had silently stopped. Note that // an elongated ring makes this a function of resolution rather than a property of the dataset - the // ring area grows with the elongation, so on a wide enough stencil the estimator changes at a fixed -// detector radius. The growth cap below keeps the default r2=6/r3=10 ring under the bound at any +// detector radius. The growth cap below keeps the default r2=6/r3=13 ring under the bound at any // bandwidth; the wider stills radii can cross it, and only ever with --background-trim, which is // off by default and kept for back compatibility. constexpr int BKG_TRIM_MAX = 512;