scipp / scipp/ess

Beam-center finder from I(Q) stops before converging

Open
#749 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

esssans
Dominant language
Python
Stars
1
Forks
3
Avg merge
2d 11h
Merged PRs (30d)
17

Description

beam_center_from_iofq passes its tolerance argument (default 0.1) straight to scipy.optimize.minimize as tol. For the default minimizer, Nelder-Mead, scipy maps tol onto xatol and fatol. xatol = 0.1 means 0.1 m in the search coordinates, which is larger than the region being searched, so the minimizer stops almost immediately and returns a barely-perturbed center-of-mass estimate.

Evidence

SANS2D tutorial data, against the MANTID_BEAM_CENTER reference used by the skipped tests in sans2d_reduction_test.py. Center of mass is [0.09007, -0.08264, 4], Mantid is [0.09288, -0.08195, 4].

tolerance cost evaluations result deviation from Mantid vertical shift from center of mass
0.1 (default) 14 [0.09458, -0.08264, 4] 1.83 mm 0.000 mm
0.01 20 [0.09445, -0.08184, 4] 1.57 mm 0.803 mm
0.001 39 [0.09425, -0.08234, 4] 1.42 mm 0.302 mm
0.0001 59 [0.09423, -0.08230, 4] 1.40 mm 0.336 mm

The last column is the clearest symptom: at the default tolerance the vertical coordinate comes back bit-identical to the center-of-mass estimate. That half of the refinement never runs.

Why it goes unnoticed

The center-of-mass initial guess is good, so the answer is roughly right either way, and the existing 2 mm test tolerance passes without the refinement doing anything.

There is a second, related fragility. Nelder-Mead sizes its initial simplex relative to x0, so the search step is whatever the magnitude of the initial guess happens to be rather than a deliberate choice. A beam center near the nominal axis therefore gets a much smaller search than one far from it, and an initial guess of exactly zero degenerates.

Not simply a different default

scipy maps tol per method, so no single value is correct across the minimizer argument:

  • Nelder-Mead: xatol and fatol, absolute, in metres and in cost units respectively.
  • Powell: xtol and ftol, relative.

The user guide's manual walk-through of the algorithm uses Powell with tol=0.01 and lands on a different value than the workflow does. The notebook attributes this to the different initial guess; the differing meaning of tol is plausibly also involved.

Suggested direction: set the scipy options explicitly for the chosen method, with a search scale derived from the problem (pixel size, or a fraction of the detector extent) instead of inherited from |x0|.

Notes

Present on main; found while reviewing #729 but independent of it. Not a duplicate of #401, which is about the cost of each evaluation rather than how many are performed. Resolving this looks like a prerequisite for un-skipping the beam-center tests in sans2d_reduction_test.py.

The 0.1 predates the current code: it was hard-coded when the module was first imported, and commit 74bbf8668 only turned it into an overridable BeamCenterFinderTolerance parameter. That parameter type has since been removed, so the or 0.1 fallback is now the only value, with no way to set it from the workflow.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at beam_center_from_iofq and the skipped tests in sans2d_reduction_test.py; inspect how minimizer, tolerance, and the initial guess are passed to scipy.optimize.minimize. Compare method-specific stopping options and search scale against the SANS2D/MANTID reference, then run the beam-center tests; done when refinement no longer stops at the center-of-mass estimate and the tests can be unskipped.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.