Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ repos:
pass_filenames: false
always_run: true

- id: no-pre-v1.0-deprecations
name: Forbid deprecation-cycle infrastructure (pre-v1.0 policy)
language: pygrep
entry: '(REMOVE-AT-V1\.0|DeprecationWarning|_DEPRECATED_[A-Z_]+_ALIASES)'
files: ^(src/ad_hoc_diffractometer|tests)/.*\.py$
# See the "Operating directives (pre-v1.0)" section of AGENTS.md.
# Rename freely. No aliases, no DeprecationWarning emitters,
# no REMOVE-AT-V1.0 markers, no alias-map constants.

- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
Expand Down
44 changes: 44 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@ This file provides context for AI coding agents working on this project.

---

## Operating directives (pre-v1.0)

These rules apply for every issue and every PR until the project tags
v1.0. They override anything in the rest of this file or in the
agent's general training that conflicts.

### No deprecation cycles

Rename freely. Do not add forwarding aliases, `DeprecationWarning`
emitters, alias maps, `REMOVE-AT-V1.0` markers, or any other
deprecation-cycle infrastructure for any rename, signature change, or
removal. The whole package is still pre-1.0; users have no API
stability contract yet. Make the change cleanly, update every
in-tree call site, document the change in `CHANGES.md`, move on.

### Scope is the issue

The issue text defines the scope. If something falls under the
issue's title or stated motivation, it is in scope by default. Do
not unilaterally narrow the scope or split work into "follow-up"
issues. If the scope is genuinely ambiguous, ask exactly one
clarifying question, then proceed.

### No volunteered follow-up issues

Do not file new issues, propose new issues, or build "future v1.0
cleanup" tracking unless the user asks. Pre-1.0 cleanup is just
"edit the code now."

### Response length matches the request

When the user asks a brief question, answer briefly: a sentence or a
short list, no tables, no preamble, no recap. When the user asks
for analysis or a plan, longer is fine. Match the form of the
request.

### When in doubt, ask one short question

A single clarifying question is cheaper than building the wrong
thing and unwinding it. Do not stack multiple questions; ask one,
wait, then proceed.

---

## Attribution

Always sign your work. Every commit message, pull request description, and
Expand Down
21 changes: 9 additions & 12 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,21 @@ Issues](https://github.com/BCDA-APS/ad_hoc_diffractometer/issues) for the full
issue tracker. The initial project development roadmap is documented here:
[roadmap](https://github.com/BCDA-APS/ad_hoc_diffractometer/blob/main/roadmap.md).

<!--
## Unreleased

Note any unreleased items inside the comment here. Not visible until release.

### Added

- `azimuth` property and constructor kwarg as canonical name. (#298)

### Changed

- `required_reference_vector` returns `"azimuth"` instead of `"azimuthal_reference"`. (#298)

### Deprecated
- Adopt pre-v1.0 no-deprecation policy in AGENTS.md; pre-commit hook enforces. (#299)
- Rename `a_eq_b` reference constraint to `specular`. (#299)
- Rename `alpha_eq_beta_*` modes to `specular_*`. (#299)
- Rename `alpha_i` / `beta_out` reference constraints to `incidence` / `emergence`. (#299)
- Rename `azimuthal_reference` property and kwarg to `azimuth`. (#298)
- Rename `exit_angle` function to `emergence_angle`. (#299)
- Rename `fixed_alpha_i_*` / `fixed_beta_out_*` modes to `fixed_incidence_*` / `fixed_emergence_*`. (#299)
- Rename `geometry.alpha_i()` / `.alpha_f()` methods to `.incidence()` / `.emergence()`. (#299)
- Rename `surface.alpha_i()` / `.alpha_f()` functions to `.incidence()` / `.emergence()`. (#299)

- `azimuthal_reference` property and kwarg; use `azimuth` instead. (#298)

-->

## Release v0.11.1

Expand Down
4 changes: 2 additions & 2 deletions docs/source/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ reference vector n̂ (surface normal, polarization axis, etc.):
```python
from ad_hoc_diffractometer import ReferenceConstraint

ReferenceConstraint("alpha_i", 5.0) # incidence angle fixed
ReferenceConstraint("a_eq_b", True) # alpha_i = beta_out (symmetric)
ReferenceConstraint("incidence", 5.0) # incidence angle fixed
ReferenceConstraint("specular", True) # incidence = emergence (symmetric)
```

Taxonomy rules: at most one {class}`~ad_hoc_diffractometer.mode.DetectorConstraint`,
Expand Down
52 changes: 26 additions & 26 deletions docs/source/geometries/psic.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,35 +106,35 @@ The scattering plane is locked vertical by `mu = 0` and `nu = 0`;
| **Computed** | eta, phi, delta |
| **Constant during** `forward()` | chi, mu = 0, nu = 0 |

### `fixed_alpha_i_vertical`
### `fixed_incidence_vertical`

Incidence angle α_i fixed at declared value (default 0°) in the
vertical scattering plane.
Override at run time with `g.modes["fixed_alpha_i_vertical"].with_constraint_values(alpha_i=...)` — see {doc}`../howto/constraints`.
Override at run time with `g.modes["fixed_incidence_vertical"].with_constraint_values(incidence=...)` — see {doc}`../howto/constraints`.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.

| | |
|---|---|
| **Computed** | eta, chi, phi, delta |
| **Constant during** `forward()` | mu = 0, nu = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i (incidence angle), beta_out (exit angle) |
| **Extras (output)** | incidence (incidence angle), emergence (exit angle) |

### `fixed_beta_out_vertical`
### `fixed_emergence_vertical`

Exit angle β_out fixed at declared value (default 0°) in the
vertical scattering plane.
Override at run time with `g.modes["fixed_beta_out_vertical"].with_constraint_values(beta_out=...)` — see {doc}`../howto/constraints`.
Override at run time with `g.modes["fixed_emergence_vertical"].with_constraint_values(emergence=...)` — see {doc}`../howto/constraints`.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.

| | |
|---|---|
| **Computed** | eta, chi, phi, delta |
| **Constant during** `forward()` | mu = 0, nu = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `alpha_eq_beta_vertical`
### `specular_vertical`

Symmetric reflection: α_i = β_out in the vertical scattering plane.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.
Expand All @@ -144,7 +144,7 @@ Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.
| **Computed** | eta, chi, phi, delta |
| **Constant during** `forward()` | mu = 0, nu = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `fixed_psi_vertical`

Expand All @@ -167,15 +167,15 @@ validated ψ. See {doc}`../howto/surface`.
| **Extras (input)** | n̂ → set `g.azimuth = (h, k, l)`; ψ target via `with_constraint_values(psi=...)` |
| **Extras (output)** | psi (computed azimuth) |

### `fixed_alpha_i_fixed_chi_fixed_phi`
### `fixed_incidence_fixed_chi_fixed_phi`

Issue #264. Two sample stages (`chi`, `phi`) and the incidence angle
α_i are all fixed; the four remaining angles `mu`, `eta`, `nu`, `delta`
are solved jointly from the Bragg condition plus the α_i target.
This is a 4-D Newton solve that routes through the
``_solve_free_detectors`` solver (both detector stages float to lift
the detector arm out of plane as needed).
Override any of the three pinned values at run time with `g.modes["fixed_alpha_i_fixed_chi_fixed_phi"].with_constraint_values(chi=..., phi=..., alpha_i=...)` — see {doc}`../howto/constraints`.
Override any of the three pinned values at run time with `g.modes["fixed_incidence_fixed_chi_fixed_phi"].with_constraint_values(chi=..., phi=..., incidence=...)` — see {doc}`../howto/constraints`.

Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.

Expand All @@ -184,7 +184,7 @@ Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.
| **Computed** | mu, eta, nu, delta |
| **Constant during** `forward()` | chi, phi, α_i = target |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `fixed_omega_vertical`

Expand Down Expand Up @@ -296,35 +296,35 @@ is kinematically infeasible in this mode.
| **Computed** | mu, phi, nu |
| **Constant during** `forward()` | chi, eta = 0, delta = 0 |

### `fixed_alpha_i_horizontal`
### `fixed_incidence_horizontal`

Incidence angle α_i fixed at declared value (default 0°) in the
horizontal scattering plane.
Override at run time with `g.modes["fixed_alpha_i_horizontal"].with_constraint_values(alpha_i=...)` — see {doc}`../howto/constraints`.
Override at run time with `g.modes["fixed_incidence_horizontal"].with_constraint_values(incidence=...)` — see {doc}`../howto/constraints`.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.

| | |
|---|---|
| **Computed** | mu, chi, phi, nu |
| **Constant during** `forward()` | eta = 0, delta = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `fixed_beta_out_horizontal`
### `fixed_emergence_horizontal`

Exit angle β_out fixed at declared value (default 0°) in the
horizontal scattering plane.
Override at run time with `g.modes["fixed_beta_out_horizontal"].with_constraint_values(beta_out=...)` — see {doc}`../howto/constraints`.
Override at run time with `g.modes["fixed_emergence_horizontal"].with_constraint_values(emergence=...)` — see {doc}`../howto/constraints`.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.

| | |
|---|---|
| **Computed** | mu, chi, phi, nu |
| **Constant during** `forward()` | eta = 0, delta = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `alpha_eq_beta_horizontal`
### `specular_horizontal`

Symmetric reflection: α_i = β_out in the horizontal scattering plane.
Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.
Expand All @@ -334,7 +334,7 @@ Set ``g.surface_normal = (h, k, l)`` before calling ``forward()``.
| **Computed** | mu, chi, phi, nu |
| **Constant during** `forward()` | eta = 0, delta = 0 |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `fixed_psi_horizontal`

Expand Down Expand Up @@ -449,23 +449,23 @@ the Hkl/Soleil `E6C` `hkl` engine, and You (1999).
| `bisecting_vertical` | `(2,0,5,0,0)` | `bissector_vertical` | §5.1 |
| `fixed_phi_vertical` | `(2,0,4,2,0)` | `constant_phi_vertical` | §5.2 |
| `fixed_chi_vertical` | `(2,0,3,2,0)` | `constant_chi_vertical` | §5.2 |
| `fixed_alpha_i_vertical` | `(2,2,2,0,0)` | — | §6.1 |
| `fixed_beta_out_vertical` | `(2,3,2,0,0)` | — | §6.2 |
| `alpha_eq_beta_vertical` | `(2,1,2,0,0)` | — | §6.3 |
| `fixed_incidence_vertical` | `(2,2,2,0,0)` | — | §6.1 |
| `fixed_emergence_vertical` | `(2,3,2,0,0)` | — | §6.2 |
| `fixed_psi_vertical` | `(2,4,2,0,0)` | `psi_constant_vertical` | §6.4 |
| `fixed_alpha_i_fixed_chi_fixed_phi` | `(2,2,3,4,0)` ‡ | — | §6.1 |
| `fixed_incidence_fixed_chi_fixed_phi` | `(2,2,3,4,0)` ‡ | — | §6.1 |
| `fixed_omega_vertical` | `setmode d1 0 0 0` | — | §5 (Q[6]) |
| `double_diffraction_vertical` | — | `double_diffraction_vertical` | §6.5 |
| `specular_vertical` | `(2,1,2,0,0)` | — | §6.3 |
| `zone_vertical` | `setmode 5` | (TODO `HklEngine "zone"`) | §6 |
| `bisecting_horizontal` | `(1,0,6,0,0)` | `bissector_horizontal` | §5.1 |
| `fixed_phi_horizontal` | `(1,0,4,1,0)` † | — | §5.2 |
| `fixed_chi_horizontal` | `(1,0,3,1,0)` † | — | §5.2 |
| `fixed_alpha_i_horizontal` | `(1,2,1,0,0)` | — | §6.1 |
| `fixed_beta_out_horizontal` | `(1,3,1,0,0)` | — | §6.2 |
| `alpha_eq_beta_horizontal` | `(1,1,1,0,0)` | — | §6.3 |
| `fixed_incidence_horizontal` | `(1,2,1,0,0)` | — | §6.1 |
| `fixed_emergence_horizontal` | `(1,3,1,0,0)` | — | §6.2 |
| `fixed_psi_horizontal` | `(1,4,1,0,0)` | `psi_constant_horizontal` | §6.4 |
| `fixed_omega_horizontal` | `setmode d1 0 0 0` | — | §5 (Q[6]) |
| `double_diffraction_horizontal` | — | `double_diffraction_horizontal` | §6.5 |
| `specular_horizontal` | `(1,1,1,0,0)` | — | §6.3 |
| `zone_horizontal` | `setmode 5` | (TODO `HklEngine "zone"`) | §6 |
| `lifting_detector_phi` | `setmode 0 0 2 3 5` ‡ | `lifting_detector_phi` | §5.4 |
| `lifting_detector_mu` | `setmode 0 0 1 3 4` ‡ | `lifting_detector_mu` | §5.4 |
Expand Down
4 changes: 2 additions & 2 deletions docs/source/geometries/s2d2.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ Override at run time with `g.modes["fixed_mu"].with_constraint_values(mu=...)`
### `reflectivity`

{class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
symmetric reflection — incidence angle equals exit angle (alpha_i = beta_out).
symmetric reflection — incidence = emergence.
Requires ``g.surface_normal = (h, k, l)`` — see {doc}`../howto/surface`.

| | |
|---|---|
| **Computed** | mu, Z, nu, delta |
| **Constant during** `forward()` | — |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

## API reference

Expand Down
18 changes: 9 additions & 9 deletions docs/source/geometries/sixc.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,44 +105,44 @@ Override at run time with `g.modes["fixed_alpha_5c"].with_constraint_values(alph
| **Computed** | omega, chi, phi, delta, gamma |
| **Constant during** `forward()` | alpha, gamma = 0 |

### `fixed_alpha_zaxis`
### `fixed_incidence_zaxis`

{class}`~ad_hoc_diffractometer.mode.SampleConstraint` × 2 + {class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
Z-axis mode with fixed incidence angle. Requires ``g.surface_normal = (h, k, l)`` — see {doc}`../howto/surface`.
Override any of the three pinned values at run time with `g.modes["fixed_alpha_zaxis"].with_constraint_values(alpha=..., chi=..., phi=...)` — see {doc}`../howto/constraints`.
Override any of the three pinned values at run time with `g.modes["fixed_incidence_zaxis"].with_constraint_values(alpha=..., chi=..., phi=...)` — see {doc}`../howto/constraints`.

| | |
|---|---|
| **Computed** | omega, delta, gamma |
| **Constant during** `forward()` | alpha (= β_in), chi, phi |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i (incidence angle), beta_out (exit angle) |
| **Extras (output)** | incidence (incidence angle), emergence (exit angle) |

### `fixed_beta_zaxis`
### `fixed_emergence_zaxis`

{class}`~ad_hoc_diffractometer.mode.DetectorConstraint` + {class}`~ad_hoc_diffractometer.mode.SampleConstraint` + {class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
Z-axis mode with fixed exit angle. Requires ``g.surface_normal = (h, k, l)`` — see {doc}`../howto/surface`.
Override at run time with `g.modes["fixed_beta_zaxis"].with_constraint_values(gamma=..., chi=...)` — see {doc}`../howto/constraints`.
Override at run time with `g.modes["fixed_emergence_zaxis"].with_constraint_values(gamma=..., chi=...)` — see {doc}`../howto/constraints`.

| | |
|---|---|
| **Computed** | omega, delta, alpha |
| **Constant during** `forward()` | gamma (= β_out), chi |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

### `alpha_eq_beta_zaxis`
### `specular_zaxis`

{class}`~ad_hoc_diffractometer.mode.SampleConstraint` × 2 + {class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
Z-axis mode, symmetric reflection (α = γ, β_in = β_out). Requires ``g.surface_normal = (h, k, l)`` — see {doc}`../howto/surface`.
Override the chi or phi pin at run time with `g.modes["alpha_eq_beta_zaxis"].with_constraint_values(chi=..., phi=...)` — see {doc}`../howto/constraints`.
Override the chi or phi pin at run time with `g.modes["specular_zaxis"].with_constraint_values(chi=..., phi=...)` — see {doc}`../howto/constraints`.

| | |
|---|---|
| **Computed** | omega, delta, alpha, gamma |
| **Constant during** `forward()` | chi, phi |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

## API reference

Expand Down
8 changes: 4 additions & 4 deletions docs/source/geometries/zaxis.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,26 @@ See {doc}`../howto/constraints` for the extras dict pattern.
{class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
surface normal aligned with the Z-axis; alpha directly equals the incidence
angle β_in, gamma directly equals the exit angle β_out.
Override the α_i target at run time with `g.modes["zaxis"].with_constraint_values(alpha_i=...)` — see {doc}`../howto/constraints`.
Override the α_i target at run time with `g.modes["zaxis"].with_constraint_values(incidence=...)` — see {doc}`../howto/constraints`.

| | |
|---|---|
| **Computed** | Z, delta, gamma |
| **Constant during** `forward()` | — |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i (= alpha), beta_out (= gamma) |
| **Extras (output)** | incidence (= alpha), emergence (= gamma) |

### `reflectivity`

{class}`~ad_hoc_diffractometer.mode.ReferenceConstraint`:
symmetric reflection — alpha_i = beta_out (alpha = gamma).
symmetric reflection — incidence = emergence (alpha = gamma).

| | |
|---|---|
| **Computed** | Z, delta, alpha, gamma |
| **Constant during** `forward()` | — |
| **Extras (input)** | n̂ → set `g.surface_normal = (h, k, l)` |
| **Extras (output)** | alpha_i, beta_out |
| **Extras (output)** | incidence, emergence |

## API reference

Expand Down
Loading