grid scan: a raster reaches the spot engine, and the crystal cap says none rather than zero

Two defects the merge created and one the API carried.

Rugnux gated the per-image spot engine on AnalysisModeIsMX, so AnalysisMode::Grid
fell through to the azimuthal-integration-only path: a raster ran, scored nothing,
and reported no crystals. The gate now asks the stages table whether the mode does
spot finding, which is the actual question - three modes need that engine for three
different reasons, and a fourth would otherwise have to be remembered here too.

max_crystals was a required integer defaulting to 10, with 0 meaning "all". Zero
reads as "report no crystals", the opposite of what it did. It is now optional, and
absent means no cap; a crystal found and then dropped is information the caller
cannot get back. grow_score_threshold was missing from the schema entirely.

Measured over the labelled corpus after these fixes: 34 of 34 confirmed-protein
rasters yield a crystal, 0 of 8 water, 0 of 6 ice, 19 of 19 heldout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
This commit is contained in:
2026-09-08 08:22:14 +02:00
co-authored by Claude Opus 5
parent 37efa573c4
commit d4f280047f
13 changed files with 166 additions and 62 deletions
+2 -1
View File
@@ -87,7 +87,8 @@ TEST_CASE("AnalysisMode_GridScanSettingsDefaults", "[AnalysisMode]") {
// otherwise the decisive rule would just be a lower general threshold.
CHECK(s.GetDecisiveSingleCellScore() > s.GetProteinScoreThreshold());
CHECK(s.GetMinBlobCells() >= 1);
CHECK(s.GetMaxCrystals() >= 1);
// No cap by default: a crystal found and then dropped cannot be recovered by the caller.
CHECK_FALSE(s.GetMaxCrystals().has_value());
GridScanAnalysisSettings set;
set.ProteinScoreThreshold(0.7f).MinBlobCells(5).DecisiveSingleCellScore(0.95f)