Parity strategy¶
magpylib_jax is a clean-room reimplementation of Magpylib, so “does it agree with Magpylib?” is a
first-class, continuously tested question — not a hope. This page explains what parity means here,
how it is enforced, the drop-in compatibility surface, and the few things that are intentionally
different.
What parity means¶
For every implemented source family, magpylib_jax reproduces upstream Magpylib’s field to within
a strict numerical tolerance, and reproduces its object/API behavior (shapes, squeeze semantics,
path handling, pixel aggregation) test-for-test.
Parity is validated in x64 (float64), because that is Magpylib’s precision. In the default
float32 mode you get the usual single-precision agreement instead — enable double precision for
bit-level comparison:
import jax
jax.config.update("jax_enable_x64", True) # required for float64 parity
import magpylib_jax as mpj
See Precision for how the dtype follows your JAX config.
The per-source workflow¶
Each source family goes through the same pipeline before it is considered at parity:
Port the kernel/object implementation to JAX.
Add parity tests against upstream Magpylib at random points and profile points.
Add mirrored upstream-file tests for object behavior.
Add physics and differentiability tests.
Gate the behavior in CI with strict parity markers and threshold checks.
Until every step lands, a family stays marked as partial and is not promoted to a hard gate.
What is covered¶
All 12 source families are implemented and exercised against Magpylib:
Namespace |
Families |
|---|---|
|
|
|
|
|
|
The full field surface — getB, getH, getJ, getM, and getFT — plus Collection, Sensor,
motion paths, and pixel aggregation is covered. See Testing and validation for the
complete taxonomy and how to run each layer.
Drop-in compatibility surface¶
Migration from Magpylib is usually a one-line import change:
import magpylib_jax as magpy # instead of: import magpylib as magpy
The following keep the same names and semantics:
Sources —
magpy.magnet.*,magpy.current.*,magpy.misc.*.Objects —
Collection(grouping and nesting) andSensor(pixel grids, handedness).Fields —
getB/getH/getJ/getMas both functions and methods, plusgetFT.Motion —
position,orientation,move,rotate,rotate_from_*, and path/edge-padding semantics.Functional & low-level — the high-level
func.*_fieldinterface and thecore.*field functions (magpylib’s capitalized names such asmagnet_cuboid_Bfieldare provided as aliases).Utilities —
show,mu_0,defaults,SUPPORTED_PLOTTING_BACKENDS, and theMagpylibBadUserInput/MagpylibMissingInputexceptions.
One difference to keep in mind
Fields come back as JAX arrays, not NumPy arrays. Wrap a call in np.asarray(...) when you need
a NumPy result (for example to hand off to pandas or Matplotlib). Everything else follows Magpylib.
What is intentionally different¶
A few upstream features are out of scope by design, so their absence is expected, not a parity gap:
Area |
Difference |
|---|---|
Display backends |
Only the Matplotlib |
|
Provided as a compatibility convenience that returns pandas objects; it is not part of the jittable field graph and cannot be traced. |
|
Takes a single |
Result dtype |
Fields are JAX arrays following your JAX precision config, not NumPy |
Where the tests live¶
tests/parity_gates— direct numeric comparison against Magpylib.tests/upstream_mirror— mirrored upstream object/API tests.The rest of the suite lives under
tests/.