geom_refinement: stop committing refinements that did not converge
Four of the seven ceres::Solve calls in image_analysis obtained a Solver::Summary and never looked at it, so a solve that failed numerically had its parameters written back and was reported as success. StillsPartialityRefine and both PostRefine solves already gated on IsSolutionUsable(); this brings the rest to the same contract. IsSolutionUsable() is the right test rather than checking for CONVERGENCE: it accepts a solve that ran out of iterations or wall-clock time but still descended, which is exactly what the real-time callers depend on when they set max_solver_time instead of max_num_iterations. Only FAILURE and USER_FAILURE are rejected. XtalOptimizer checks before the write-back, so a failed refinement now leaves the caller's geom and latt untouched instead of half-updated. GeometryRefiner folds it into result.ok, which previously reported success from spot and frame counts alone. RingOptimizer returns a geometry by value that both callers assign straight back over their input, so it hands back the unchanged reference rather than a diverged beam centre. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,6 +174,10 @@ GeometryRefinerResult RefineGlobalGeometry(const DiffractionGeometry &nominal_ge
|
||||
return 0.3 - (0.3 - 0.1) * t;
|
||||
};
|
||||
|
||||
// Whether the last solve that ran produced a usable solution; folded into result.ok below,
|
||||
// which otherwise reports success on spot and frame counts alone.
|
||||
bool solve_usable = false;
|
||||
|
||||
for (int round = 0; round < settings.rounds; ++round) {
|
||||
EffectiveCell(system, cell_len, cell_ang, eff_len, eff_alpha, eff_beta, eff_gamma);
|
||||
|
||||
@@ -265,6 +269,7 @@ GeometryRefinerResult RefineGlobalGeometry(const DiffractionGeometry &nominal_ge
|
||||
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(options, &problem, &summary);
|
||||
solve_usable = summary.IsSolutionUsable();
|
||||
|
||||
result.frames_used = frames_used;
|
||||
result.spots_used = spots_used;
|
||||
@@ -298,7 +303,7 @@ GeometryRefinerResult RefineGlobalGeometry(const DiffractionGeometry &nominal_ge
|
||||
result.median_residual_px = residuals[residuals.size() / 2];
|
||||
}
|
||||
|
||||
result.ok = result.spots_used >= settings.min_spots_total && result.frames_used > 0;
|
||||
result.ok = solve_usable && result.spots_used >= settings.min_spots_total && result.frames_used > 0;
|
||||
result.beam_x_px = beam[0];
|
||||
result.beam_y_px = beam[1];
|
||||
result.distance_mm = distance_mm;
|
||||
|
||||
Reference in New Issue
Block a user