Repository navigation
Description
Overview
Carve-out from PyAutoFit #1279 (Phase 4 of the JAX visualization roadmap). A picklability spike found that FitImaging cannot be pickled today because AbstractMeshGeometry.__init__ stores self._xp = xp — the literal numpy or jax.numpy module — and Python can't pickle modules. This blocks sending a FitImaging over an mp.Process+Queue or ProcessPoolExecutor boundary, which is the production design for Phase 4 subprocess visualization.
Fix: replace the module-attribute pattern with the _use_jax: bool + _xp property pattern already used in Analysis._xp (PyAutoFit) and AbstractMaker._xp (PyAutoArray decorators per CLAUDE.md). Eliminates the pickle barrier at the API level instead of working around it with __getstate__/__setstate__ hooks.
Spike evidence (PyAutoFit #1279):
- Before fix:
TypeError: cannot pickle 'module' objectatinversion.linear_obj_list[0].interpolator.mesh_geometry._xp - After fix (proven via monkey-patch):
FitImaginground-trips through pickle.dumps/loads withlog_likelihooddelta0.00e+00on both numpy and JAX backends. Pickle size ~4.6 MB.
Plan
- Change
AbstractMeshGeometry.__init__to storeself._use_jax = xp is not npinstead ofself._xp = xp - Add
_xpas a@propertyderiving fromself._use_jax(returnsnporjnpon demand) - All existing call sites read
self._xp(no writes) — they continue to work transparently via the property - Add a unit test that pickles a
MeshGeometryRectangularinstance and verifies_xpround-trips to the correct module
Detailed implementation plan
Affected Repositories
- PyAutoArray (primary, library, only repo touched)
Work Classification
Library
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoArray | main | clean (canonical) — knn-barycentric task holds it via worktree, file-disjoint |
Suggested branch: feature/mesh-geometry-picklable
Worktree root: ~/Code/PyAutoLabs-wt/mesh-geometry-picklable/
Conflict resolution: File-level coexistence on PyAutoArray with knn-barycentric (#317). KNN edits inversion/mesh/interpolator/, inversion/mesh/mesh/, and plot/* — no overlap with our scope (inversion/mesh/mesh_geometry/abstract.py). Same precedent as ag-interferometer-kwargs.
Implementation Steps
autoarray/inversion/mesh/mesh_geometry/abstract.py:- In
__init__: replaceself._xp = xpwithself._use_jax = xp is not np - Add
@propertymethod_xpthat returnsjax.numpyif_use_jaxelsenumpy - Import of
jax.numpystays lazy (only when_use_jax=Trueand_xpis accessed) — matchesAnalysis._xppattern in PyAutoFit
- In
test_autoarray/inversion/pixelization/mesh_geometry/test_picklability.py(new):test_picklable_numpy_backend— construct via__new__+_use_jax=False, pickle round-trip, assertrestored._xp is nptest_picklable_jax_backend— same with_use_jax=True, assertrestored._xp is jnp(pytest.importorskip('jax'))
- Run the existing mesh_geometry tests + the new pickle tests + any pixelization tests that touch
_xpto verify no regression
Key Files
PyAutoArray/autoarray/inversion/mesh/mesh_geometry/abstract.py(line 23 + new property)PyAutoArray/test_autoarray/inversion/pixelization/mesh_geometry/test_picklability.py(new)
Out of scope
__getstate__/__setstate__workaround (Option A in the parent issue's spike) — rejected in favour of the cleaner property pattern (Option B)- Subprocess visualization itself — that's the parent task #1279
FitInterferometerNUFFT picklability — separate spike under #1279
Parent
PyAutoFit #1279 — Phase 4 subprocess visualization feasibility (carve-out of the picklability prereq)
Activity
Jammy2211 commentedon May 16, 2026
Shipped — 2026-05-16
PR
Summary
AbstractMeshGeometrynow stores_use_jax: boolinstead of_xpas a module reference, with_xpexposed as a property derived from the flag.FitImagingis now picklable end-to-end (4.6 MB / fit, bit-exact log_likelihood round-trip on both numpy and JAX backends). Unblocks PyAutoFit #1279 (Phase 4 subprocess visualization).Session Notes
mp.Process+Queue/ProcessPoolExecutorover disk-staged subprocess. Q1 measurement now focuses on which Python-native IPC is fastest under JAX, not whether they can carry a FitImaging.__getstate__/__setstate__hooks) for consistency withAnalysis._xp(PyAutoFit Phase 2) andAbstractMaker._xp(PyAutoArray decorators per CLAUDE.md). Same pattern in three places now.inversion/mesh/but on different files. Confirms the soft-conflict-guard / file-level-safety pattern fromag-interferometer-kwargsprecedent.~/Code/PyAutoLabs-wt/viz-subprocess-feasibility/) as in-progress notes for Q1/Q3/Q4 work.