You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What. Make PyUnitWizard interoperate with OpenFF's units stack, so that quantities move between OpenFF and the rest of the ecosystem (MolSysMT, OpenMM, astropy, unyt, and the serialization codec of #82) in one call, without losing or misreading a unit.
OpenFF is the open force-field ecosystem closest to MolSysMT and MolSysSuite, which makes it a natural bridge for our users. Split out of #85 at Diego's request (2026-09-24).
How OpenFF handles units (checked 2026-09-24):
openff-units is built on pint with its own registry: "a common unit registry for all OpenFF packages ... to ensure consistent unit definitions" (README). Its unit definitions come from NIST CODATA.
scalars with str() → '10.0 kcal / mol / nm ** 2', and back with the Quantity constructor;
pydantic models (openff-models, openff-interchange) as {"val": ..., "unit": "..."} (openff-models).
Distribution: conda-forge openff-units 0.4.0 (noarch; also on PyPI). It depends on numpy, openff-utilities, pint >=0.24.0,<0.26, and python >=3.12,<3.15.
convert(q, to_form="openff.units") and back, preserving arrays and dtype.
Check that unit definitions agree between the two registries, within a stated tolerance. Fail loudly if they do not; never convert silently across different definitions.
OpenMM consistency. A round trip OpenFF → PyUnitWizard → OpenMM must match openff-units' own to_openmm, and the reverse must match from_openmm, including Vec3 lists.
A {"val", "unit"} record carries no integrity guarantee. A verified record exported to OpenFF's shape must therefore be documented as leaving the verified domain, and importing one is a boundary that runs the handshake.
Optional dependency. It must be optional, loaded through DepDigest, as pyunitwizard[openff] or a conda extra. openff-units needs Python ≥ 3.12, and PyUnitWizard supports 3.11, so on 3.11 the form is unavailable with a clear diagnostic. It also pins pint <0.26, a constraint to watch against PyUnitWizard's own pint range.
Tests.
Round trips for scalars, n-D arrays and compound units (e.g. kcal/mol/nm**2).
Cross-registry arithmetic after conversion.
A deliberately altered unit definition, which must be refused.
Conformance under a non-default session policy.
Why here. PyUnitWizard is the interoperability layer (devguide/interop_future_directions.md). A bridge written separately in each consumer diverges, and divergence is where units get lost. The review in #83 found OpenFF's per-value records to be the nearest precedent to #82 in our domain.
Related: #84 (prerequisite), #85 (other forms and dialects), #82 (codec), #83 (design record and review).
What. Make PyUnitWizard interoperate with OpenFF's units stack, so that quantities move between OpenFF and the rest of the ecosystem (MolSysMT, OpenMM, astropy, unyt, and the serialization codec of #82) in one call, without losing or misreading a unit.
OpenFF is the open force-field ecosystem closest to MolSysMT and MolSysSuite, which makes it a natural bridge for our users. Split out of #85 at Diego's request (2026-09-24).
How OpenFF handles units (checked 2026-09-24):
openff.units.openmm.to_openmm/from_openmm.from_openmmturns OpenMMVec3lists into pint-wrapped numpy arrays.str()→'10.0 kcal / mol / nm ** 2', and back with theQuantityconstructor;{"val": ..., "unit": "..."}(openff-models).openff-units0.4.0 (noarch; also on PyPI). It depends onnumpy,openff-utilities,pint >=0.24.0,<0.26, andpython >=3.12,<3.15.Scope.
Prerequisite: Quantities from another pint UnitRegistry are not recognized and cannot be converted #84. Today
puw.is_quantityreturns False for a quantity from another pint registry, andconvertraises. Nothing below works until that is fixed.A form
openff.units.convert(q, to_form="openff.units")and back, preserving arrays and dtype.OpenMM consistency. A round trip OpenFF → PyUnitWizard → OpenMM must match openff-units' own
to_openmm, and the reverse must matchfrom_openmm, includingVec3lists.Serialization interop with QuantityRecord: PyUnitWizard's native inert interchange form (verified quantity records) #82. Read and write OpenFF's
{"val", "unit"}records and scalar strings, and convert them to and from the verified codec records.A
{"val", "unit"}record carries no integrity guarantee. A verified record exported to OpenFF's shape must therefore be documented as leaving the verified domain, and importing one is a boundary that runs the handshake.Optional dependency. It must be optional, loaded through DepDigest, as
pyunitwizard[openff]or a conda extra. openff-units needs Python ≥ 3.12, and PyUnitWizard supports 3.11, so on 3.11 the form is unavailable with a clear diagnostic. It also pinspint <0.26, a constraint to watch against PyUnitWizard's own pint range.Tests.
kcal/mol/nm**2).Why here. PyUnitWizard is the interoperability layer (
devguide/interop_future_directions.md). A bridge written separately in each consumer diverges, and divergence is where units get lost. The review in #83 found OpenFF's per-value records to be the nearest precedent to #82 in our domain.Related: #84 (prerequisite), #85 (other forms and dialects), #82 (codec), #83 (design record and review).