Repository navigation
Description
Overview
al.output_to_json(obj=weak_dataset, ...) writes a WeakDataset successfully, but al.from_json(file_path=...) fails to read it back with TypeError: VectorYX2DIrregular.__init__() missing 1 required positional argument: 'values'. The bug blocks any downstream consumer wanting to load a serialised shear catalogue, and currently forces the autolens_workspace/scripts/weak/fit.py tutorial to rebuild the dataset inline rather than load it from disk. Surfaced during PR PyAutoLens #525 / workspace #188 (step 3 of the weak-lensing series).
Plan
- Add a
valuesproperty toaa.VectorYX2DIrregularin PyAutoArray returning the underlying(N, 2)ndarray, mirroring the pattern already used byGrid2DIrregular.valuesandArrayIrregular.values. This is the single root-cause fix — all consumers ofto_dict/from_dictget it for free, includingShearYX2DIrregular(which subclassesVectorYX2DIrregular). - Add a PyAutoArray-side unit test that round-trips a
VectorYX2DIrregularthroughoutput_to_json/from_json, since that's where the defective code lives and there are currently no dict round-trip tests for any irregular structure. - Add the WeakDataset regression test in PyAutoLens, exercising the full simulator → write → load path so the original failure mode is locked down.
- Once the library PRs ship, simplify
autolens_workspace/scripts/weak/fit.pyto load the dataset viaal.from_jsoninstead of rebuilding it inline.
Detailed implementation plan
Affected Repositories
- Jammy2211/PyAutoLens (primary — regression test + this issue)
- Jammy2211/PyAutoArray (the actual fix)
- Jammy2211/autolens_workspace (post-merge workspace follow-up)
Work Classification
Library work first (PyAutoArray + PyAutoLens), then workspace follow-up (autolens_workspace) after the library PRs ship.
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./PyAutoArray | main | clean |
| ./PyAutoLens | main | clean |
| ./autolens_workspace | main | dirty (pre-existing modified dataset/ binaries — unrelated to this task; not touched by this work) |
Suggested branch: feature/weak-dataset-from-json
Worktree root: ~/Code/PyAutoLabs-wt/weak-dataset-from-json/ (created later by /start_library)
Conflict check: no other active task is holding any of these three repos.
Root cause (verified by live reproduction)
autoconf/dictable.py::instance_as_dict walks the constructor signature and emits getattr(obj, arg) for each arg that satisfies hasattr(obj, arg).
VectorYX2DIrregular.__init__(self, values, grid)Grid2DIrregulardefinesvalues(→self._array) — round-trips fine.ArrayIrregulardefinesvalues(→self.array) — round-trips fine.VectorYX2DIrregulardoes NOT define avaluesproperty. Sohasattr(vec, 'values')→ False, onlygridends up in the serialized dict, andfrom_dictcallsVectorYX2DIrregular(grid=…)→TypeError: missing 1 required positional argument: 'values'.
Live reproduction confirmed:
- The exact
TypeErrorfrom the report is reproduced from a minimalaa.VectorYX2DIrregular(values=…, grid=…). - Monkey-patching
VectorYX2DIrregular.values = property(lambda self: self.array)makes the fullWeakDatasetsimulator →output_to_json→from_jsonround-trip pass, withloaded.shear_yxcoming back asShearYX2DIrregular(subclass preserved). - No
dict()method exists onAbstractNDArrayorAbstractVectorYX2Dthat would short-circuit the serialization path.
Implementation Steps
Step 1 — PyAutoArray fix. Edit autoarray/structures/vectors/irregular.py. Add the property directly under __array_finalize__, before slim:
@property
def values(self):
"""
The raw underlying ndarray of (y, x) vector components, shape [total_vectors, 2].
"""
return self.arrayMirrors Grid2DIrregular.values and ArrayIrregular.values.
Step 2 — PyAutoArray unit test. Add a tmp_path-based test in test_autoarray/structures/vectors/test_vectors_irregular.py that:
- builds
VectorYX2DIrregular(values=[[0.1, 0.2], [0.3, 0.4]], grid=[[0.0, 0.0], [1.0, 1.0]]) - runs
output_to_json(obj=vec, file_path=tmp_path / "vec.json") - runs
loaded = from_json(file_path=tmp_path / "vec.json") - asserts
isinstance(loaded, VectorYX2DIrregular)and thatloaded.arrayandloaded.grid.arraymatch the originals element-wise
Step 3 — PyAutoLens regression test. Add test_autolens/weak/test_dataset.py::test_weak_dataset_json_round_trip(tmp_path):
- build a small
WeakDatasetviaal.SimulatorShearYX(noise_sigma=0.3, seed=1).via_tracer_from(tracer=…, grid=<small aa.Grid2DIrregular>) al.output_to_json(obj=dataset, file_path=tmp_path / "dataset.json")loaded = al.from_json(file_path=tmp_path / "dataset.json")- assert
loaded.name == dataset.name - assert
np.allclose(loaded.shear_yx.array, dataset.shear_yx.array)andnp.allclose(loaded.shear_yx.grid.array, dataset.shear_yx.grid.array) - assert
np.allclose(loaded.noise_map.array, dataset.noise_map.array) - assert
isinstance(loaded.shear_yx, ShearYX2DIrregular)(subclass preserved through round-trip)
Step 4 — Workspace follow-up (after library PRs ship). In autolens_workspace/scripts/weak/fit.py, replace the inline truth_lens / truth_tracer / simulator.via_tracer_random_positions_from(...) reconstruction (and the accompanying docstring block explaining the workaround) with:
dataset = al.from_json(file_path=dataset_path / "dataset.json")Apply the same change to the matching notebook if one exists.
Key Files
PyAutoArray/autoarray/structures/vectors/irregular.py— addvaluespropertyPyAutoArray/test_autoarray/structures/vectors/test_vectors_irregular.py— round-trip unit testPyAutoLens/test_autolens/weak/test_dataset.py— WeakDataset round-trip regression testautolens_workspace/scripts/weak/fit.py— workspace follow-up (post-merge)
Out of scope
ShearYX2D/aa.VectorYX2D(regular-grid variants) — constructor also takesmask, would need separateMask2Dround-trip work, and no current code path serializes them.- Pytree registration of
WeakDatasetfor JAX compatibility — separate effort. - Reworking the simulator output format —
dataset.jsonis the right artifact; only the loader is broken.
Risk / blast radius
- Adding a
valuesproperty cannot collide with state — noself.values =setter exists anywhere inVectorYX2DIrregularor its bases. Grid2DIrregularalready has the same property and is used identically by the dictable machinery; same pattern, no surprises.
Original Prompt
Click to expand starting prompt
Fix al.from_json round-trip for WeakDataset / ShearYX2DIrregular.
The simulator script at @autolens_workspace/scripts/weak/simulator.py writes the simulated WeakDataset to
dataset/weak/simple/dataset.json via al.output_to_json, but al.from_json(file_path=...) cannot read it
back. The traceback is:
TypeError: VectorYX2DIrregular.__init__() missing 1 required positional argument: 'values'
at PyAutoFit/autofit/mapper/model_object.py:223 (return cls_(...)), called from
PyAutoConf/autoconf/dictable.py:316.
The bug surfaced when writing @autolens_workspace/scripts/weak/fit.py (PR PyAutoLens #525 / workspace #188,
step 3 of the weak-lensing series). That tutorial works around it by rebuilding the dataset inline using
SimulatorShearYX(seed=1) rather than loading from disk — but that's a real limitation: any downstream
consumer wanting to load a serialised shear catalogue is blocked.
Root cause hypothesis (inspect to confirm)
ShearYX2DIrregular inherits from aa.VectorYX2DIrregular (see @PyAutoGalaxy/autogalaxy/util/shear_field.py).
The from_dict round-trip for irregular vector fields likely needs the underlying values and grid arrays
keyed correctly in the serialised dict. The generic dictable mechanism in PyAutoConf probably doesn't
know about the values / grid constructor convention used by aa.VectorYX2DIrregular.
Suggested approach
- Look at how
aa.Grid2DIrregularround-trips (it must, sincedataset.positionsis just a property on
dataset.shear_yx.grid). IfGrid2DIrregularhas a custom__init_subclass__,to_dict, orfrom_dict
hook, mirror that pattern forVectorYX2DIrregularandShearYX2DIrregular. - Alternatively: add a custom serializer for
WeakDatasetin@PyAutoLens/autolens/weak/dataset.pythat
handles its three components (shear_yx,noise_map,name) by their public types. - Add a regression test under
@PyAutoLens/test_autolens/weak/test_dataset.py:- build a
WeakDatasetviaSimulatorShearYX al.output_to_json(obj=dataset, file_path=tmp_path / "dataset.json")loaded = al.from_json(file_path=tmp_path / "dataset.json")- assert
loaded.shear_yx == dataset.shear_yx,loaded.noise_map == dataset.noise_map,
loaded.name == dataset.name
- build a
Workspace impact
Once fixed, the @autolens_workspace/scripts/weak/fit.py tutorial can be simplified to load from disk
rather than rebuilding the dataset inline. That migration is a small workspace follow-up after the library
fix lands.
Out of scope
- Pytree registration of
WeakDatasetfor JAX compatibility — a separate effort. - Reworking the simulator output format —
dataset.jsonis the right artifact; only the loader is broken.
Activity
Jammy2211 commentedon May 28, 2026
Library PR Created — 2026-05-28
PRs
Status
Library shipped, workspace-pending. Next:
/start_workspaceto simplifyautolens_workspace/scripts/weak/fit.py(replace the inlineSimulatorShearYXreconstruction withal.from_json(file_path=dataset_path / "dataset.json")).API Changes
Added
VectorYX2DIrregular.valuesproperty returning the underlying(N, 2)ndarray. Purely additive — mirrorsGrid2DIrregular.values/ArrayIrregular.valuesand closes the missing piece that preventedto_dict/from_dictfrom round-tripping.ShearYX2DIrregularinherits the fix.Jammy2211 commentedon May 28, 2026
Smoke Test Results — 2026-05-28
All 7 smoke tests passed across autolens_workspace.
Jammy2211 commentedon May 28, 2026
Shipped — 2026-05-28
PRs
Summary
al.from_jsonforWeakDataset/ShearYX2DIrregularnow works end-to-end. Root cause was a missingvaluesproperty onaa.VectorYX2DIrregular— the dictable serializer reads constructor args viahasattr(obj, arg), so without the property onlygridwas serialized andfrom_dictcrashed. Fix mirrors the pattern already used byGrid2DIrregular.values/ArrayIrregular.values. Theautolens_workspace/scripts/weak/fit.pytutorial drops 20+ lines of inline reconstruction workaround and now loadsdataset.jsonviaal.from_jsonlike every other tutorial.Session Notes
main, not the feature branch) — anticipated and called out in the PR body. Resolved by merging the PyAutoArray PR first and re-triggering the failed unittest runs.dataset/weak/simple/dataset.jsonhad to be regenerated as part of the workspace PR — the previously-written file lacked thevaluesfield and was unreadable even by the fixed loader.dataset/weak/simple/tracer.jsonwas incidentally regenerated (autoconf added acosmologyfield and reshuffled dict-key order; numeric values identical).WeakDataset.from_dictclassmethod (suggested approach scipy.spatial.KMeans doesn't support weighted clustering #2 in the prompt). The one-line root-cause fix onVectorYX2DIrregularis strictly better — coversShearYX2DIrregularautomatically and fixes any other future consumer ofto_dict/from_dictfor vector fields.aa.VectorYX2D(regular-grid variant) has the same gap but its constructor also takesmask, which needs separateMask2Dround-trip work — and no current code path serializes it. Left alone.test: lock down WeakDataset / ShearYX2DIrregular json round-trip