Skip to content

fix(#278) warn when fixed_psi_* target is unreachable; add reference.natural_psi#283

Merged
prjemian merged 1 commit into
mainfrom
278-psi-horizontal-no-solutions
May 19, 2026
Merged

fix(#278) warn when fixed_psi_* target is unreachable; add reference.natural_psi#283
prjemian merged 1 commit into
mainfrom
278-psi-horizontal-no-solutions

Conversation

@prjemian

Copy link
Copy Markdown
Collaborator

Investigation

#278's "0 solutions" symptom is mathematically correct behavior under the \u03c8-validation-filter design (issue #176): for fixed (UB, hkl), every Bragg solution has the same natural \u03c8 \u2014 uniquely determined by Q_phi = UB @ hkl and the azimuthal reference. The user asked for psi=0 on reflections whose natural \u03c8 are 90\u00b0, 107\u00b0, 180\u00b0, etc., so forward() correctly returned []. The user's own Newton check in the issue confirmed these reflections aren't reachable at psi=0. The real defect was the silent empty list.

Changes

  • _solve_psi_mode now emits a UserWarning that names the natural \u03c8 and points the user at ad_hoc_diffractometer.reference.natural_psi when the target mismatches; a separate warning fires when \u03c8 is undefined (Q parallel to reference or beam).
  • New public helper reference.natural_psi(geometry, h, k, l) returns the natural \u03c8 from UB and hkl alone (None when undefined).
  • YAML comments above every fixed_psi* mode in psic, kappa6c, fourcv, fourch, kappa4cv, and kappa4ch clarify the validation-filter semantics.

Recommended workflow (now possible)

nat = ahd.reference.natural_psi(g, h, k, l)
if nat is None:
    # \u03c8 undefined for this reflection \u2014 pick another or change azimuthal_reference
    ...
for c in g.modes['fixed_psi_horizontal'].constraints:
    if isinstance(c, ahd.ReferenceConstraint) and c.name == 'psi':
        c._value = nat
sols = g.forward(h, k, l)   # now returns real solutions, no warning

QC

  • 2472 \u2192 2493 tests pass; 100% coverage maintained
  • pytest -m slow_benchmark: 3 passed
  • pre-commit, ruff, US English check all clean

Contributed by: OpenCode (argo/claudeopus47)

…natural_psi

fixed_psi_* modes silently returned [] when the user-specified ψ
target did not match the natural ψ for the requested reflection,
leaving callers without a clue why their reflection was unreachable.

Under the ψ-validation-filter design (issue #176), ψ is uniquely
determined by Q_phi = UB @ (h, k, l) and the azimuthal reference —
every Bragg solution of a reflection has the same ψ.  No motor
configuration can change it.  Returning [] on a mismatched target is
mathematically correct, but the silence was unhelpful.

Changes:

- _solve_psi_mode now emits a UserWarning that names the natural ψ
  and points the user at ad_hoc_diffractometer.reference.natural_psi
  when the target mismatches; a separate warning fires when ψ is
  undefined (Q parallel to reference or beam).
- New public helper reference.natural_psi(geometry, h, k, l) returns
  the natural ψ from UB and hkl alone (None when undefined).
- YAML comments above every fixed_psi* mode in psic, kappa6c,
  fourcv, fourch, kappa4cv, and kappa4ch clarify the validation-
  filter semantics.

Contributed by: OpenCode (argo/claudeopus47)
@prjemian prjemian merged commit 8a0de8b into main May 19, 2026
7 checks passed
@prjemian prjemian deleted the 278-psi-horizontal-no-solutions branch May 19, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

psic fixed_psi_horizontal: NoForwardSolutions for every hkl on hexagonal lattice (sibling of #275)

1 participant