Skip to content

✨ feat(unitsystems): name the Planck and atomic base units - #875

Draft
nstarman wants to merge 1 commit into
GalacticDynamics:mainfrom
nstarman:claude/named-natural-units
Draft

✨ feat(unitsystems): name the Planck and atomic base units#875
nstarman wants to merge 1 commit into
GalacticDynamics:mainfrom
nstarman:claude/named-natural-units

Conversation

@nstarman

@nstarman nstarman commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Closes #868.

astropy.units has no names for the Planck or Hartree atomic base units, so
they could only be spelled as a scale times an SI unit — and to_string()
truncates past six significant figures, so that spelling neither read well nor
reparsed:

>>> planck["length"]
Unit("1.61626e-35 m")          # before — and does *not* reparse
>>> planck["length"]
Unit("l_P")                    # after

Eight units: l_P, m_P, t_P, T_P for Planck; a_0, m_e, t_au, e
for Hartree atomic.

Scope

Only these two systems get names. hep and geometrized take a free scale
(an energy and a length respectively), so their bases change with the
parameter — verified — and no fixed name would be correct:

>>> unitsystem(HEPUSysFlag)["length"]              # 1.97327e-16 m
>>> unitsystem(HEPUSysFlag, energy="TeV")["length"] # 1.97327e-19 m

Three traps, each checked rather than assumed

  • a0 and Eh are not free. astropy already parses them as
    dimensionless and as a time (E×h, hour). Either would have silently
    meant the wrong thing. Hence a_0, and no Hartree-energy unit here.
  • A unit named e does not disturb scientific notation1e5 m and
    1.5e3 kg still parse as a scale times a unit. Tested, since this was the
    main worry with the conventional name for elementary charge.
  • astropy ignores a format string identical to the unit's own name and
    then escapes the underscore, so a_0 renders $\mathrm{a\_0}$ unless the
    override differs — a_{0} fixes it.

Values track astropy

Each unit is defined from the same constant expression that already built
its unit system, not from a hard-coded number, so a CODATA revision in
astropy.constants moves these with it. A test pins that.

That also means doctests which hid these behind ... no longer need to: a
name is stable across CODATA revisions where six significant figures were not.

The registry trade-off

Registered with add_enabled_units at import, so unxt.unit("l_P") resolves
and the spelling round-trips. This mutates astropy's registry process-wide —
it is exactly why the change was kept out of #855, and the trade is
deliberate. All eight names were checked unclaimed.

Display alone would not have needed this (a def_unit knows its own name);
parsing does.

Follow-up: #876 tracks upstreaming these into astropy, which would let unxt
drop the module entirely.

Interaction with #855

#855 should rebase on top of this. Its unit-system repr routes a system whose
units have no short exact spelling to the realization's registered name
(unitsystem('planck')). With these units named, planck's bases do spell
exactly, so it will instead render unitsystem(['l_P', 'm_P', 't_P', 'T_P'])
informative and round-trippable, and quite possibly making that name-lookup
path redundant.

Verification

nox -s "pytest(package='unxt')" — 4068 passed. Every other package session
green (interop_gala, parametric, api, hypothesis, interop_xarray),
plus unxts.linalg 287. pylint 10.00/10, ruff clean.

Closes GalacticDynamics#868.

`astropy.units` has no names for these, so they could only be spelled as a
scale times an SI unit -- and `to_string()` truncates past six significant
figures, so that spelling neither read well nor reparsed:

    planck["length"]  ->  Unit("1.61626e-35 m")     # and does *not* reparse
    planck["length"]  ->  Unit("l_P")               # now

Eight units: `l_P`, `m_P`, `t_P`, `T_P` for Planck, and `a_0`, `m_e`, `t_au`,
`e` for Hartree atomic. Only these two systems get names -- `hep` and
`geometrized` take a free scale, so their bases change with the parameter and
no fixed name would be right.

Each is defined from the *same constant expression* that already built its
unit system rather than a hard-coded number, so the values track whatever
CODATA revision `astropy.constants` ships. A test pins that.

Three things the naming had to dodge, each verified rather than assumed:

- `a0` and `Eh` are **not** free. astropy already parses them as
  *dimensionless* and as a *time* (`E`×`h`, hour). Hence `a_0`, and no
  Hartree-energy unit.
- A unit named `e` does not disturb scientific notation -- `1e5 m` and
  `1.5e3 kg` still parse as a scale times a unit.
- astropy ignores a `format` string identical to the unit's own name and then
  escapes the underscore, so `a_0` needed `a_{0}` to render as `$a_{0}$`
  rather than `$\mathrm{a\_0}$`.

Registered with `add_enabled_units` at import, so `unxt.unit("l_P")` resolves
and the spelling round-trips. That mutates astropy's registry process-wide; it
is the reason this was kept out of GalacticDynamics#855, and the trade is deliberate. Upstream
issue to follow, which would let unxt drop the module entirely.

Doctests that hid these values behind `...` no longer need to: a name is
stable across CODATA revisions where six significant figures were not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 13, 2026 22:18
@nstarman nstarman added this to the v2.1.0 milestone Aug 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces explicit, parseable names for the base units of the fully-determined natural unit systems (planck and Hartree atomic) so they round-trip through astropy.units string formatting/parsing without losing precision due to to_string()’s significant-figure truncation.

Changes:

  • Add a new named_units module defining l_P, m_P, t_P, T_P, a_0, m_e, t_au, and e, and register them via astropy.units.add_enabled_units so they are parseable.
  • Switch the PlanckUSysFlag and AtomicUSysFlag realizations to use the named units (and update doctest outputs accordingly).
  • Add unit tests covering naming, round-tripping, LaTeX formatting, scientific-notation safety for e, and ensuring astropy’s pre-existing a0 meaning remains unchanged.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/unit/test_unitsystems.py Adds tests asserting named natural bases, exact reparsing, LaTeX formatting, and safety checks around e/a0.
src/unxt/_src/unitsystems/named_units.py Defines and registers the eight named units for Planck and Hartree atomic systems.
src/unxt/_src/unitsystems/flags.py Updates doctest outputs for PlanckUSysFlag / AtomicUSysFlag to show named units.
src/unxt/_src/unitsystems/core.py Uses PLANCK_UNITS / ATOMIC_UNITS instead of recomputing unnamed scaled SI units.
docs/guides/units_and_systems.md Updates documentation examples to reflect named base units.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions github-actions Bot added 📝 Add / update documentation Add or update documentation. ✅ Add / update / pass tests Add, update, or pass tests. ✨ Introduce new features Introduce new features. labels Aug 13, 2026
@nstarman
nstarman marked this pull request as draft August 13, 2026 22:36
@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.96%. Comparing base (6888db8) to head (4c03f6f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #875      +/-   ##
==========================================
+ Coverage   99.82%   99.96%   +0.13%     
==========================================
  Files          84       47      -37     
  Lines        3985     2700    -1285     
  Branches      311      162     -149     
==========================================
- Hits         3978     2699    -1279     
+ Misses          3        0       -3     
+ Partials        4        1       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📝 Add / update documentation Add or update documentation. ✅ Add / update / pass tests Add, update, or pass tests. ✨ Introduce new features Introduce new features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Named units for the natural unit systems (l_P, m_P, t_P, T_P, ...)

2 participants