Commit Graph
2 Commits
Author SHA1 Message Date
leonarski_fandClaude Opus 5 cdb60c2916 grid scan: one cell is a crystal when that cell is decisive, and the list can be capped
The minimum patch size was a flat floor, so a crystal that covers one or two grid
points was thrown away however strong its diffraction. It is now a floor OR a piece
of evidence: a patch is reported when it has min_blob_cells cells, or when its best
cell reaches decisive_protein_score. One condition, and both halves are parameters.

The bar is the patch PEAK, not the patch mean. A two-cell patch with one strong cell
and one marginal one is the case this exists for, and the mean averages exactly that
evidence away. Over the 67 labelled rasters the two populations do not overlap: no
water raster reaches a peak of 0.15 and no ice raster reaches 0.50, while the weakest
protein raster peaks at 0.67 - so 0.6, the middle of that gap, is the default. The
peak is reported beside the mean, in the table and in the JSON, so an admission can
be checked against the number that decided it.

max_crystals caps the returned list after the sort, best first; 0, the default, is all
of them, because a crystal that was found and then dropped is information the caller
cannot get back.

The four parameters now travel as one GridScanAnalysisParameters, which is the shape
the GridScanAnalysisSettings class in common/ is to take: when it lands it replaces
this struct in the signature and nothing else changes.

On the corpus this reaches 17/17 protein loops (it was 16/17 - the miss was a crystal
covering two grid points of a 4x4 raster) with water still 0/4 and ice still 0/3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
2026-09-08 07:15:30 +02:00
leonarski_fandClaude Opus 5 21eca107fa rugnux: --mode raster reads a stored grid scan and reports the crystals in it
The offline entry point for a raster. It scores every image of a stored grid scan
- spot finding for the per-cell resolution, no indexing, because a raster answers
where the crystal is and not what its lattice is - hands the per-image protein and
ice scores to AnalyzeGridScan, and writes what came back as two files beside the
usual output: <prefix>_raster_report.txt in the idiom of the results report, and
<prefix>_raster.json with the same content typed, so a battery can aggregate a
sweep without scraping prose.

--beam-size states the beam at the sample, defaulting to the file's
incident_beam_size. It matters more than it looks: the reported crystal sizes are
measured and still contain the beam, and taking an anisotropic beam back out is a
subtraction of two covariance matrices, so a beam given as square when it is not
rotates the reported crystal axis. --raster-protein-threshold and
--raster-min-cells expose the two constants AnalyzeGridScan held at file scope, so
a sweep can vary them without a rebuild; they are now defaulted parameters with the
old values, and every existing call is unchanged.

The observer feeding the analysis reads the file's own image number
(DataMessage::original_number), not the loop's ordinal, so -s/-e/--stride cannot
silently shift the grid mapping.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
2026-09-08 00:01:39 +02:00