Releases: PyAutoLabs/PyAutoGalaxy
Release list
v2026.7.9.1
PyAutoGalaxy v2026.7.9.1
What's New
Breaking Changes
- feat: CSV API extensions from the stress-test (light variants, loud guards, table properties, flat cosmology) (#491)
- Added: qualified light-variant class names in
light.csv(linear.Sersic,operated.Gaussian,linear_operated.*— plain names stay standard);GalaxyTable.properties(extra catalogue columns load as float/string lists — nothing silently dropped) +galaxy_table_to_csv(properties=);dPIEMassLenstool(Sph)gainH0/Om0float args (Planck15-value defaults, so a Lenstool run's cosmology is CSV-able) with prior-config entries. Behaviour changed (loud guards): duplicate(galaxy, attr_name)rows and typo'd parameter columns in model CSVs now raiseValueError(both previously silent — a typo left the profile at its default value).dPIEMassLenstoolwrapper prior_count grows 9→11 (fix H0/Om0 for the old count).
- Added: qualified light-variant class names in
- feat: Lenstool-native dPIE parameterization (from_lenstool + dPIEMassLenstool) and analytic potential (#487)
- Added Lenstool-parameterized construction and fitting for the dPIE family:
from_lenstool(...)classmethods ondPIEMass/dPIEMassSph, and new model-fittable wrapper profilesdPIEMassLenstool/dPIEMassLenstoolSph(with prior configs).dPIEMass.potential_2d_fromvalues change (MGE approximation → exact analytic potential); dPIE deflections at |ell_comps| < 1e-5 change from NaN to the tiny-ellipticity limit. No removals or renames.
- Added Lenstool-parameterized construction and fitting for the dPIE family:
- feat: add Kaplinghat SIDM cored NFW profile (#471)
- Adds two public dark-matter mass profiles,
ag.mp.KaplinghatCoredNFWSphandag.mp.KaplinghatCoredNFWMCRLudlowSph, plus default prior configs. Existing profile APIs are unchanged. See full details below.
- Adds two public dark-matter mass profiles,
- Lensing potential for elliptical/spherical dark-matter profiles (NFW/gNFW) + NFWSph fix (#470)
- Adds a working
potential_2d_fromto the elliptical/spherical dark-matter profiles (via a single MGE-decomposition method ongNFW, inherited byNFW,gNFWSph, and all MCR/Virial variants). CorrectsNFWSph.potential_2d_from(it returned values a factor ofr_stoo small). No public signatures removed or renamed;MassProfile.potential_2d_fromnow acceptsxp/**kwargs(additive). Behaviour change:NFWSphpotential values are now correct (≈r_s× larger than before). See full details below.
- Adds a working
- fix(mass): convergence_func on PowerLawBroken, PowerLawMultipole, cNFW family (#467)
- Added
convergence_funcoverrides onPowerLawBroken,PowerLawBrokenSph(inherited),PowerLawMultipole, and thecNFWfamily (cNFWSph+ MCR variants inherit).PowerLawBroken._convergenceis a new private radial helper.PowerLawBroken.potential_2d_fromnow raisesNotImplementedErrorexplicitly (it was already non-functional). No signatures of existing public methods changed. See full details below.
- Added
New Features
- feat: oversampled PSF blurred images — operate/image consumer (phase 2c) (#481)
- docs: add signpost llms.txt + consolidate agent instructions into AGENTS.md (#474)
Bug Fixes
- docs: fix dead HowToGalaxy Colab links + purge stale allowlist entries (#493)
- fix: restore unconditional dataset.fits output for aggregator (save_attributes) (#479)
- fix(jax): defensive pytree dedup in imaging/interferometer analyses (#468)
Internal
- docs: document the functional plot API in plot.rst (#494)
- docs: prune stale API-doc references (#492)
- refactor: unify the blurred-image evaluate/pre-bin/convolve tail (#489)
- feat: k×s coupling call sites (blurred images, linear override, padded simulation) (#486)
- refactor: extract the oversampled-PSF evaluation-grid switch (#484)
- feat: oversampled PSF support in SimulatorImaging (phase: simulator) (#483)
- ci: call the reusable lib-tests workflow from PyAutoHeart (not PyAutoPulse) (#477)
- main.yml → thin caller to Pulse reusable lib-tests (Stage 4 Phase A) (#476)
- Remove url_check.yml: URL hygiene centralised in PyAutoPulse (#475)
- docs: consolidate agent instructions into canonical AGENTS.md (#473)
- refactor(latent): LatentGalaxy class + declare Analysis.Latent (Phase 2) (#472)
Upstream Changes
PyAutoFit
- refactor: dispatch visualize_combined per Visualizer type in FactorGraphModel (#1340)
- fix: LogUniform NumPy log-prior returns -inf for value<=0 (emcee NaN crash) (#1329)
- ci: pause routine scheduled (cron) workflow runs (#1325)
- ci: call the reusable lib-tests workflow from PyAutoHeart (not PyAutoPulse) (#1323)
- main.yml → thin caller to Pulse reusable lib-tests (Stage 4 Phase A) (#1322)
- Remove url_check.yml: URL hygiene centralised in PyAutoPulse (#1321)
- docs: add signpost llms.txt + consolidate agent instructions into AGENTS.md (#1320)
- docs: consolidate agent instructions into canonical AGENTS.md (#1319)
- refactor(latent): migrate af.ex.Analysis + cookbook docs to the Latent class (#1318)
- fix: skip latent computation without keys (#1317)
- refactor(latent): first-class Latent class + engine extraction (Phase 1) (#1315)
- fix: expand bypass-mode fake samples (#1314)
- test: skip NSS tests without optional dependency (#1312)
- fix(latent): degenerate latent edge cases (quantile n=1, latent exceptions, anti-correlated NaNs) (#1311)
- fix(latent): global masking in compute_latent_samples to prevent KeyError on per-batch NaN drops (#1310)
- feat: cross-Analysis shared per-evaluation state in FactorGraphModel (#1308)
- chore(deps): allow anesthetic>=2.9.0 to unblock jax>=0.7 / numpy>=2 resolution (#1306)
- fix(nss): chunked algo.init follow-up to #1303 (#1305)
- feat(nss): chunk_size kwarg for inversion-heavy A100 likelihoods (#1303)
- fix(jax): structural defense against cached_property pytree/dict leaks (#1302)
PyAutoArray
- refactor: qhull-only Delaunay callback, exact JAX visibility-walk point location (#368)
- feat: catalogue-size cap for PYAUTO_SMALL_DATASETS smoke mode (#366)
- refactor: vectorize k×s segment-id construction (#365)
- perf: memoize k×s segment-id construction (#364)
- feat: k×s evaluation/convolution coupling (#363)
- refactor: consolidate oversampled-PSF convolution helpers (#361)
- feat: via_image_from image_is_convolved + from_gaussian oversample kwarg (#359)
- fix: oversampled fine state when the blurring mask is padded (#358)
- feat: oversampled PSF inversion wiring — mapping formalism (phase 2b) (#357)
- feat: oversampled PSF convolution core API (convolve_over_sample_size) (#355)
- ci: call the reusable lib-tests workflow from PyAutoHeart (not PyAutoPulse) (#352)
- Arcsec ticks: consistent decimal for mixed integer/decimal ticks; centre rotated y-labels (#351)
- Add optional arcsecond double-prime tick labels (#350)
- main.yml → thin caller to Pulse reusable lib-tests (Stage 4 Phase A) (#349)
- Remove url_check.yml: URL hygiene centralised in PyAutoPulse (#348)
- docs: add signpost llms.txt + consolidate agent instructions into AGENTS.md (#347)
- docs: cons...
v2026.5.29.4
PyAutoGalaxy v2026.5.29.4
What's New
Breaking Changes
- fix(mass): convergence_func on PowerLawBroken, PowerLawMultipole, cNFW family (#467)
- Added
convergence_funcoverrides onPowerLawBroken,PowerLawBrokenSph(inherited),PowerLawMultipole, and thecNFWfamily (cNFWSph+ MCR variants inherit).PowerLawBroken._convergenceis a new private radial helper.PowerLawBroken.potential_2d_fromnow raisesNotImplementedErrorexplicitly (it was already non-functional). No signatures of existing public methods changed. See full details below.
- Added
- fix: soft-fail jax_zero_contour callers in lens_calc to NaN/[] (#465)
- Behaviour change (no signature change): when
jax_zero_contouris not installed,einstein_radius_jit_fromnow returnsfloat('nan')(was:ModuleNotFoundError), and the publictangential_critical_curve_list_via_zero_contour_from/radial_critical_curve_list_via_zero_contour_from(via the private_critical_curve_list_via_zero_contour) now return[](was:ModuleNotFoundError). Onelogger.warningper process per feature. New private helper_maybe_optional_dep_warnand module-level set_OPTIONAL_DEP_WARNED. No imports removed.
- Behaviour change (no signature change): when
- fix: raw-flux latent + soft-fail magzero-required µJy (#463)
- feat: MGE/CSE fallback for zero-returning mass profile potentials (#449)
- Added
MGEDecomposer.potential_2d_via_mge_from()— new public method computing lensing potential from MGE-decomposed convergence using the E1 exponential integral. Added helper methodsE1()(Abramowitz & Stegun approximation, JAX-compatible) andpotential_func_gaussian(). All existing zero-returning methods now return physically meaningful values instead of zeros. See full details below.
- Added
- refactor: port CSE module to support JAX via xp parameter (#447)
- Added
xp=npkeyword argument to fourMassProfileCSEmethods:convergence_cse_1d_from,deflections_via_cse_from,_convergence_2d_via_cse_from,_deflections_2d_via_cse_from. Existing callers passing noxpargument are unaffected (default isnp). The decomposition solver (_decompose_convergence_via_cse_from) stays NumPy-only — it runs before JIT tracing. See full details below.
- Added
- feat: first-class latent variable API in PyAutoGalaxy (#441)
- New public module
autogalaxy.imaging.model.latentwith helpers (ab_mag_via_flux_from,flux_mujy_via_ab_mag_from), theLATENT_FUNCTIONSregistry, thelatent_keys_enabled()reader, and one registered latent (total_galaxy_0_flux_mujy, disabled by default).AnalysisImaginggains aLATENT_KEYS@propertyand acompute_latent_variables(parameters, model)method — both new public surface. New config fileautogalaxy/config/latent.yaml. Note: autoconf lowercases yaml keys, so the latent name uses lowercasemujy(notmuJy) — this leaks through to thelatent.csvcolumn header.
- New public module
- feat: JIT-friendly Einstein radius helper + AnalysisDataset jit latent mode (#435)
- Two additions to PyAutoGalaxy: a new public method
LensCalc.einstein_radius_jit_from, and a class attribute overrideAnalysisDataset.LATENT_BATCH_MODE = "jit". No existing API surface is modified or removed.
- Two additions to PyAutoGalaxy: a new public method
- perf(lens_calc): cache (f, ZeroSolver) for zero_contour critical curves (#434)
LensCalcinstances now carry a private_zero_contour_cachedict. No public API surface changes — same method names, same signatures, same return values. Behavioural change:_critical_curve_list_via_zero_contourreuses its closure andZeroSolveracross repeat calls with the same parameters.
New Features
- perf: cache expensive @Property on Fit classes (#462)
- feat: vmapped_deflections_from for batched subhalo deflections (#455)
- docs: LaTeX docstrings for all mass profile classes (#453)
- feat: SimulatorInterferometer.via_galaxies_from auto-default xp from parent use_jax (#443)
- feat: SimulatorImaging.via_galaxies_from auto-default xp from parent use_jax (#442)
Bug Fixes
- fix(jax): defensive pytree dedup in imaging/interferometer analyses (#468)
- fix(mass): wire convergence_func on dPIE family for MGE decomposition (#466)
- fix: elliptical MGE potential via deflection line integral (#460)
- fix: use xp.sqrt in NFWSph.potential_func_sph (#458)
- fix: add xp=np to convergence_func across all mass profiles (#457)
Internal
- perf: vectorize MGE potential over components (#461)
- fix: cNFWSph deflection boundary bug and MCR validation (#451) (#454)
- refactor(model_util): replace simulator_start_here_model_from with direct random_galaxy_for_simulation_from (#438)
- refactor: archive quantity package to autolens_workspace_developer/legacy (#437)
Upstream Changes
PyAutoFit
- chore(deps): allow anesthetic>=2.9.0 to unblock jax>=0.7 / numpy>=2 resolution (#1306)
- fix(nss): chunked algo.init follow-up to #1303 (#1305)
- feat(nss): chunk_size kwarg for inversion-heavy A100 likelihoods (#1303)
- fix(jax): structural defense against cached_property pytree/dict leaks (#1302)
- fix(jax): keep parameterization cache off ModelInstance + auto-register pytrees (#1300)
- Cache model.parameterization; try interactive matplotlib backends (#1299)
- Prefer fit_quick.png in quick-update display candidates (#1298)
- Remove use_jax_for_visualization; add visualization warmup (#1297)
- fix: skip _compute_latent_samples in PYAUTO_TEST_MODE (#1294) (#1295)
- Add live_visual_update flag for opt-in on-the-fly visualization (#1293)
- fix: PYAUTO_TEST_MODE should write to a separate output dir (#1292)
- feat(quick_update): IPython.display.update_display for live Jupyter cells (#1290)
- feat(analysis): LATENT_BATCH_MODE attribute (vmap default, jit option) (#1288)
- Fix Sample.kwargs mixed string/tuple key bug (#1287)
- nss extras: strip git+https URLs to unblock PyPI uploads (#1286)
PyAutoArray
- fix(jax): exclude cached_property descriptors from pytree flatten paths (#343)
- fix: VectorYX2DIrregular from_dict round-trip (missing values property) (#342)
- perf: cache expensive @Property on Fit classes (#341)
- fix: make Array2D.native jit-traceable for JAX simulator path (#339)
- fix: raise ValueError on xp=np + jnp-backed-grid mismatch (#337)
- feat: SimulatorInterferometer(use_jax=True) + xp-aware preprocess Gaussian noise (#336)
- feat: SimulatorImaging(use_jax=True) + xp-aware preprocess noise (#335)
- TransformerNUFFT: add chunk_size knob to cap nufftax gather buffer (#330)
- interferometer: enable sparse_operator for nufftax TransformerNUFFT (#329)
Full changelog: 2026.5.21.1...2026.5.29.4
v2026.5.21.1
PyAutoGalaxy v2026.5.21.1
What's New
Breaking Changes
- fix: EllipseMultipoleScaled JAX-traceable via deferred derivation (#427)
EllipseMultipoleScaled.__init__no longer pre-computes or storesself.specific_multipole_comps; the attribute is gone.super().__init__is no longer called, soself.multipole_compsis also no longer set.get_shape_angleis now overridden (was inherited) to derive fromscaled_multipole_comps.self.major_axisis now stored as an attribute (previously it was only an__init__arg).- Numerical behaviour:
points_perturbed_fromoutput shifts by ~1e-8 relative to the old implementation. The old path storedspecific_multipole_compsto limited float precision and then re-derived(k, phi)from it, accumulating rounding error. The new direct path is cleaner. Pinning test captures the new (more accurate) values.
- fix: Basis.image_2d_from and dPIEPotential.convergence_2d_from return wrong wrapper types (#425)
- config: add prior defaults for ExternalPotential (#423)
- feat(mass): add ExternalPotential mass profile (Powell 2022 Eq 4) (#422)
- Single additive class:
ag.mp.ExternalPotential(sibling ofExternalShearinautogalaxy/profiles/mass/sheets/). Six free parameters (gamma_1/2,tau_1/2,delta_1/2) plus a freecentre(unlikeExternalShear's fixed(0, 0)— the τ and δ deflections are radial so the centre matters). Plus convenience accessorsgamma_magnitude/angle,tau_magnitude/angle,delta_magnitude/angle, and afrom_magnitudes_and_anglesclassmethod for paper-style parameterisation. - No removals, no renames, no signature changes elsewhere. See full details below.
- Single additive class:
- refactor(light): split multipole module + add ag.lp_linear variants (#421)
- Two new public classes added to
ag.lp_linear: -
ag.lp_linear.SersicMultipole— linear elliptical Sersic with m=3/m=4 multipole perturbations
- Two new public classes added to
- feat(light): add SersicMultipole and GaussianMultipole profiles (#420)
- Two new public classes added to the
ag.lpnamespace: -
ag.lp.SersicMultipole— Sersic with m=3 and m=4 Fourier perturbations on the eccentric radius
- Two new public classes added to the
- feat: AnalysisEllipse.fit_from + JAX pytree registration (keystone) (#412)
-
- Added:
use_jax: bool = TrueonAnalysisEllipse.__init__.AnalysisEllipse.fit_from(instance) -> FitEllipseSummed.FitEllipseSummedclass onautogalaxy.ellipse.fit_ellipse(sums over aList[FitEllipse]).use_jax: bool = Falsekwarg onFitEllipse.fit_list_fromso the visualizer keeps the numpy default.
- Added:
-
- Changed Behaviour:
AnalysisEllipse.log_likelihood_functionnow returnsfigure_of_merit(per-ellipse sum of-0.5 * (chi_squared + noise_normalization)) instead oflog_likelihood(per-ellipse sum of-0.5 * chi_squared). This matchesAnalysisImaging.log_likelihood_functionline 125 exactly. Existing callers see a different scalar value — differs by the per-fitnoise_normalizationsum. The workspace_test reference scripts callfit_list_fromdirectly (notlog_likelihood_function) so the prompt-2 reference numbers stay byte-stable.
- Changed Behaviour:
-
- refactor: unify FitEllipse perimeter sampling; add JAX support (#410)
FitEllipse.__init__gainsuse_jax: bool = False.FitEllipse.points_from_major_axis_fromis rewritten: the 300-iter regen-trim loop is replaced with one-shot NaN-marking. Behaviour preserved for datasets where the ellipse perimeter sits entirely inside the mask region (the common case, including prompt 2). Behaviour changes for masked-perimeter datasets:-
chi_squarednow sums overN - N_maskedperimeter terms (where N is the initial sample count) instead of always exactly N. The regen-and-trim mechanism that synthesised replacement points is gone.
- refactor: parameterise Ellipse + EllipseMultipole math on xp (#408)
- Eight methods on
Ellipse/EllipseMultipole/EllipseMultipoleScaledgain anxp=npkeyword (purely additive — existing callers unaffected). One behaviour change:EllipseMultipole.get_shape_anglepreviously wrapped angles into the open-closed interval(-period/2, period/2]via twowhileloops; thexp.modrewrite wraps into the closed-open interval[-period/2, period/2), so the single boundary valueangle == period/2.0exactly now returns-period/2.0instead of+period/2.0. A new test pins the new convention. No removals, no other behaviour changes. See full details below.
- Eight methods on
- feat: replace Ludlow16 colossus pure_callback with JAX-native impl (#403) (#406)
- The colossus
pure_callbackchain is replaced by a JAX-native port. Production no longer importscolossus. The internal mcr_util helpers (_ludlow16_cosmology_callback,ludlow16_cosmology_jax) are removed; new public entry points live inautogalaxy/profiles/mass/dark/ludlow16.py. Thexpbranches in the two callers (kappa_s_and_scale_radius_for_ludlow,kappa_s_scale_radius_and_core_radius_for_ludlow) collapse to singlexp-aware calls.colossusmoves from required to test/dev extras. See full details below.
- The colossus
- fix: register DatasetModel pytree in _register_fit_quantity_pytrees (#405)
- feat: wire ag.VisualizerQuantity through fit_for_visualization (#404)
-
- Added:
ag.AnalysisQuantity.fit_from(instance)— thin alias for the existingfit_quantity_for_instance(instance). Required so the autofit baseAnalysis.fit_for_visualizationdispatcher can find afit_frommethod on this analysis class (mirrors the imaging/interferometer pattern).
- Added:
- Strictly additive — no existing call site is affected.
fit_quantity_for_instanceretained for backwards compatibility.
-
- feat: pytree registration for FitEllipse + FitQuantity (Phase 0c) (#401)
-
ag.AnalysisEllipse.__init__andag.AnalysisQuantity.__init__gain**kwargspassthrough — strictly additive. Callers can now passuse_jax_for_visualization=True(and any other autofit-baseAnalysiskwarg) withoutTypeError.
-
- New
_register_fit_ellipse_pytreesand_register_fit_quantity_pytreesstatic methods on the respective analysis classes, invoked underif use_jax:. They registerEllipse,EllipseMultipole,FitEllipse,FitQuantity, and reuseregister_galaxies_pytree()for theGalaxiesaggregate insideFitQuantity.light_mass_obj.
- New
-
- fix: ag.AnalysisInterferometer.init kwargs passthrough (#399)
ag.AnalysisInterferometer.__init__gains a**kwargspassthrough — strictly additive. Any caller that previously worked is unaffected. New: callers can now passuse_jax_for_visualization=True(or any other kwarg accepted by the autofit baseAnalysis) withoutTypeError.
- refactor: DatasetInterp delegates to aa.interp_2d; expose xp (#398)
New Features
- feat(galaxy): named-galaxy CSV reader/writer for full model round-trips (#428)
- feat(AdaptImages): rotate cached mesh grid with DatasetModel transforms (#416)
- fix: add quick_update kwarg to VisualizerImaging.visualize_combined (#414)
Bug Fixes
- fix: handle r=0 in NFWSph deflections (#430)
- docs: audit-driven URL fixes across docs, READMEs, and docstrings (#413)
Internal
- Pin jax_zero_contour >=2.0.0,<3.0.0 in [jax] extras (#432)
- fix(lens_calc): preserve evaluation_grid extent under PYAUTO_SMALL_DATASETS=1 (#431)
- fix(csv): preserve TuplePrior on af.Model built from tuple-param rows (#429)
- ci: add live URL audit (weekly cron) + grandfather current broken URLs (#415)
- docs(research): Ludlow16 JAX concentration feasibility study (#397) (#402)
Upstream Changes
PyAutoFit
- nss extras: strip git+https URLs to unblock PyPI uploads (#1286)
- perf: direct-ndtr fast path for TruncatedGaussianPrior.value_for (#1285)
- fix: coerce figure_of_metric return to Python float for Drawer + JAX (#1283)
- ci: split NSS tests into parallel job (handley-lab blackjax fork ≠ mainline) (#1281)
- revert: default use_jax_for_visualization to False (reverts #1278) (#1280)
- feat: default use_jax_for_visualization to follow use_jax in Analysis.init (#1278)
- feat: autofit[nss] install extra (Phase 4 of nss_first_class_sampler) (#1277)
- feat: af.NSS checkpoint/resume + on-the-fly visualization (Phases 2-3) (#1274)
- feat: af.NSS NonLinearSearch wrapper for Nes...
v2026.5.14.2
PyAutoGalaxy v2026.5.14.2
What's New
Breaking Changes
- feat: replace Ludlow16 colossus pure_callback with JAX-native impl (#403) (#406)
- The colossus
pure_callbackchain is replaced by a JAX-native port. Production no longer importscolossus. The internal mcr_util helpers (_ludlow16_cosmology_callback,ludlow16_cosmology_jax) are removed; new public entry points live inautogalaxy/profiles/mass/dark/ludlow16.py. Thexpbranches in the two callers (kappa_s_and_scale_radius_for_ludlow,kappa_s_scale_radius_and_core_radius_for_ludlow) collapse to singlexp-aware calls.colossusmoves from required to test/dev extras. See full details below.
- The colossus
- fix: register DatasetModel pytree in _register_fit_quantity_pytrees (#405)
- feat: wire ag.VisualizerQuantity through fit_for_visualization (#404)
-
- Added:
ag.AnalysisQuantity.fit_from(instance)— thin alias for the existingfit_quantity_for_instance(instance). Required so the autofit baseAnalysis.fit_for_visualizationdispatcher can find afit_frommethod on this analysis class (mirrors the imaging/interferometer pattern).
- Added:
- Strictly additive — no existing call site is affected.
fit_quantity_for_instanceretained for backwards compatibility.
-
- feat: pytree registration for FitEllipse + FitQuantity (Phase 0c) (#401)
-
ag.AnalysisEllipse.__init__andag.AnalysisQuantity.__init__gain**kwargspassthrough — strictly additive. Callers can now passuse_jax_for_visualization=True(and any other autofit-baseAnalysiskwarg) withoutTypeError.
-
- New
_register_fit_ellipse_pytreesand_register_fit_quantity_pytreesstatic methods on the respective analysis classes, invoked underif use_jax:. They registerEllipse,EllipseMultipole,FitEllipse,FitQuantity, and reuseregister_galaxies_pytree()for theGalaxiesaggregate insideFitQuantity.light_mass_obj.
- New
-
- fix: ag.AnalysisInterferometer.init kwargs passthrough (#399)
ag.AnalysisInterferometer.__init__gains a**kwargspassthrough — strictly additive. Any caller that previously worked is unaffected. New: callers can now passuse_jax_for_visualization=True(or any other kwarg accepted by the autofit baseAnalysis) withoutTypeError.
- refactor: DatasetInterp delegates to aa.interp_2d; expose xp (#398)
- feat: add galaxy_table CSV reader/writer for galaxy populations (#393)
New Features
- docs: add nufftax + FINUFFT citation guidance (#396)
- test: pin FitEllipse masked-points-loop behaviour (#395)
Internal
- docs(research): Ludlow16 JAX concentration feasibility study (#397) (#402)
- feat: re-export TransformerNUFFTPyNUFFT (legacy pynufft NUFFT) (#391)
- feat: dispatch autogalaxy visualizers via fit_for_visualization (#390)
Upstream Changes
PyAutoFit
- fix: populate NUTS samples_info keys under test-mode bypass (#1260)
- fix: stop passing dataset=None to fit_cls when sensitivity Job is complete (#1259)
PyAutoArray
- feat: add aa.interp_2d (NumPy + JAX bilinear interpolation) (#308)
- perf: batched transform_mapping_matrix in TransformerNUFFT (single nufft2d2 call) (#305)
- fix(inversion): regularization_weights_mapper_dict uses correct linear_obj_list index (#304)
- feat: nufftax-backed TransformerNUFFT as default; rename pynufft variant to TransformerNUFFTPyNUFFT (#303)
- Make use_mixed_precision actually emit fp32 FFT for light profiles (#302)
- feat: honor PYAUTO_SMALL_DATASETS in Imaging.from_fits (#301)
Full changelog: 2026.5.8.2...2026.5.14.2
v2026.5.8.2
⚠️ v2026.5.8.2 is a no-op re-release of v2026.5.8.1 — same code, second release dispatched the same day to validate updated release-pipeline gates. The full set of changes shipped on 2026-05-08 follows.
PyAutoGalaxy v2026.5.8.2
What's New
Bug Fixes
- fix: xp-gate jax.scipy.special.factorial in shapelets/exponential.py (#385)
Internal
- refactor: replace os.path with pathlib (#388)
- docs: update workspace prose refs from README.rst to README.md (#387)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#386)
- test: remove jax from unit tests (moved to autogalaxy_workspace_test) (#384)
- docs: convert prose .rst files to MyST .md (#383)
Upstream Changes
PyAutoFit
- fix: populate NUTS samples_info keys under test-mode bypass (#1260)
- fix: stop passing dataset=None to fit_cls when sensitivity Job is complete (#1259)
- refactor: replace os.path with pathlib (#1258)
- feat: add BlackJAXNUTS first-class non-linear search (#1256)
- Visualizer.visualize_combined: accept quick_update kwarg (#1254)
- Fix AnalysisFactor.visualize_combined dispatch in FactorGraph (#1253)
- Refresh cached SearchUpdater when AbstractSearch.paths is reassigned (#1252)
- docs: update workspace prose refs from README.rst to README.md (#1251)
- Support fixed Array elements through the EP fitting pipeline (#1250)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#1249)
- Add EPAnalysisFactor for cavity-message injection (#1248)
- test: delete jax-using unit tests (moved to autofit_workspace_test) (#1247)
- docs: convert prose .rst files to MyST .md (#1246)
PyAutoArray
- feat: honor PYAUTO_SMALL_DATASETS in Imaging.from_fits (#301)
- refactor: replace os.path with pathlib (#300)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#298)
- Fix subplot_of_mapper crash on interferometer data_subtracted (#297)
- fix OOB read in psf_precision_value_from causing NaN sparse-CPU log_evidence (#296)
- test: remove jax-using unit tests; assertions moved to autolens_workspace_test (#295)
- docs: convert index.rst to MyST .md (#294)
Full changelog: 2026.5.1.4...2026.5.8.2
v2026.5.8.1
PyAutoGalaxy v2026.5.8.1
What's New
Bug Fixes
- fix: xp-gate jax.scipy.special.factorial in shapelets/exponential.py (#385)
Internal
- refactor: replace os.path with pathlib (#388)
- docs: update workspace prose refs from README.rst to README.md (#387)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#386)
- test: remove jax from unit tests (moved to autogalaxy_workspace_test) (#384)
- docs: convert prose .rst files to MyST .md (#383)
Upstream Changes
PyAutoFit
- fix: populate NUTS samples_info keys under test-mode bypass (#1260)
- fix: stop passing dataset=None to fit_cls when sensitivity Job is complete (#1259)
- refactor: replace os.path with pathlib (#1258)
- feat: add BlackJAXNUTS first-class non-linear search (#1256)
- Visualizer.visualize_combined: accept quick_update kwarg (#1254)
- Fix AnalysisFactor.visualize_combined dispatch in FactorGraph (#1253)
- Refresh cached SearchUpdater when AbstractSearch.paths is reassigned (#1252)
- docs: update workspace prose refs from README.rst to README.md (#1251)
- Support fixed Array elements through the EP fitting pipeline (#1250)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#1249)
- Add EPAnalysisFactor for cavity-message injection (#1248)
- test: delete jax-using unit tests (moved to autofit_workspace_test) (#1247)
- docs: convert prose .rst files to MyST .md (#1246)
PyAutoArray
- feat: honor PYAUTO_SMALL_DATASETS in Imaging.from_fits (#301)
- refactor: replace os.path with pathlib (#300)
- docs: convert remaining prose .rst to MyST .md (pass 2) (#298)
- Fix subplot_of_mapper crash on interferometer data_subtracted (#297)
- fix OOB read in psf_precision_value_from causing NaN sparse-CPU log_evidence (#296)
- test: remove jax-using unit tests; assertions moved to autolens_workspace_test (#295)
- docs: convert index.rst to MyST .md (#294)
Full changelog: 2026.5.1.4...2026.5.8.1
v2026.5.1.4
PyAutoGalaxy v2026.5.1.4
Highlights
Python 3.9–3.13 supported, 3.12 / 3.13 recommended
This release expands supported Python versions to 3.9 through 3.13 (#382). 3.12 and 3.13 are first-class recommended; 3.9, 3.10, 3.11 are supported but emit a loud (bypassable) banner on import. Silence the banner via version.python_version_check: False in your workspace's config/general.yaml. Python 3.14 is not yet supported.
Key impacts for users:
requires-python = ">=3.9"inpyproject.toml(lower floor than before)- Classifiers now cover 3.9, 3.10, 3.11, 3.12, 3.13
- JAX is now an optional extra:
pip install autogalaxy[jax], gated onpython_version >= '3.11'. Plainpip install autogalaxyno longer pulls JAX as a transitive dep.
HowToGalaxy moved to its own repo
The HowToGalaxy lecture series now lives in its own repository at PyAutoLabs/HowToGalaxy (#363). Existing URLs/prose in the library and workspace pointing at the previous location have been updated. Clone the new repo to follow the tutorial chapters.
Bug Fixes
- Mark
pytree_tokenas ephemeral in light/linear profiles via__getstate__/__setstate__(#374) — fixes pickling round-trips when JAX pytree-aware profiles are serialised - xp-gate
jax.scipy.special.factorialinshapelets/exponential.py(#385) — exponential shapelets now use the array-namespace dispatcher instead of a hard JAX import, so the module imports cleanly when JAX is not installed
Internal / Cleanup
- Remove unused
pyprojrootimport (#381) - Remove jax from unit tests (moved to
autogalaxy_workspace_test) (#384) — keeps the library's unit suite numpy-only
Upstream Changes
PyAutoConf
- Support Python 3.9–3.13, first-class 3.12/3.13 (PyAutoConf#102)
- Soften Python version check with
general.yamlbypass (PyAutoConf#96)
PyAutoArray
- Support Python 3.9–3.13 (PyAutoArray#293)
- Handle off-centre masks in convolver and blurring grid padding (PyAutoArray#274)
- Fix NaN gradients from
jaxnnlsbackward pass via Jacobi preconditioning (PyAutoArray#279) - Lower
nnls_target_kappadefault to1e-11for stable NNLS gradients (PyAutoArray#283, #284)
PyAutoFit
- Support Python 3.9–3.13 (PyAutoFit#1244)
- JAX-jitted likelihoods in Dynesty via
use_jax_jit(PyAutoFit#1243) - Skip
FitExceptionsamples incompute_latent_samples(PyAutoFit#1233)
Full changelog: 2026.4.13.6...2026.5.1.4
v2026.4.13.6
PyAutoGalaxy v2026.4.13.6
What's New
Bug Fixes
- fix: pin autofit/autoarray dependency versions and update homepage (#348)
Upstream Changes
PyAutoFit
- fix: pin autoconf dependency version and update homepage URL (#1206)
PyAutoArray
- fix: pin autoconf dependency version and update homepage URL (#273)
Full changelog: 2026.4.13.5...2026.4.13.6
v2026.4.13.5
PyAutoGalaxy v2026.4.13.5
What's New
Bug Fixes
- fix: pin autofit/autoarray dependency versions and update homepage (#348)
Upstream Changes
PyAutoFit
- fix: pin autoconf dependency version and update homepage URL (#1206)
PyAutoArray
- fix: pin autoconf dependency version and update homepage URL (#273)
Full changelog: 2026.4.13.3...2026.4.13.5
v2026.4.13.3
PyAutoGalaxy v2026.4.13.3
What's New
Breaking Changes
- refactor: rename env vars to PYAUTO_* prefix (#343)
- One env var rename. Quantity visualizer now controlled by
PYAUTO_SKIP_VISUALIZATIONinstead ofPYAUTOFIT_TEST_MODE. See full details below.
- One env var rename. Quantity visualizer now controlled by
- fix: give each basis independent ell_comps in mge_model_from (#342)
-
- New parameter:
centre_per_basis: bool = Falseonmge_model_from— when True, each basis gets independent centre priors
- New parameter:
-
- Behaviour change:
mge_model_fromwithgaussian_per_basis > 1now produces independent ell_comps per basis (was previously tied). Calls withgaussian_per_basis=1are unchanged.
- Behaviour change:
-
- refactor: merge PYAUTO_DISABLE_CRITICAL_CAUSTICS into PYAUTO_FAST_PLOTS (#340)
- Environment variable only — no Python API changes.
PYAUTO_DISABLE_CRITICAL_CAUSTICSis retired; setPYAUTO_FAST_PLOTS=1instead to skip bothtight_layout()and critical-curve/caustic overlay computation. Callers that only setPYAUTO_DISABLE_CRITICAL_CAUSTICSwill no longer skip overlays — they must migrate toPYAUTO_FAST_PLOTS=1. - Paired PyAutoBuild PR removes the retired flag from the release workflow, default env vars, and docs. A follow-up workspace sweep will remove it from the
autofit/autogalaxy/autolensworkspaceenv_vars.yaml,run_scripts.sh, and CLAUDE.md files.
- Environment variable only — no Python API changes.
- feat: reinstate title_prefix on all matplotlib subplot panel titles (#333)
- refactor: remove integral-based deflection/potential methods from mass profiles (#324)
- The following methods are removed from mass profile classes:
-
deflections_2d_via_integral_from— removed from Gaussian, Sersic, SersicGradient, NFW, gNFW, gNFWSph
-
deflection_func— removed from Gaussian, Sersic, SersicGradient, NFW, gNFW
New Features
- docs: update Python version to 3.12-3.13 (#346)
- perf: defer matplotlib imports and lazy-load plot submodule (#330)
- perf: cache cosmology distances and cap MGE gaussians for smoke tests (#329)
- feat: PYAUTO_DISABLE_CRITICAL_CAUSTICS env var to skip curve computation (#325)
Bug Fixes
- fix: re-export subplot_interferometer_dataset from autogalaxy.plot (#337)
- Fix cosmology distance cache breaking JAX JIT tracing (#334)
- fix: correct stale module paths in docs API (#319)
Internal
- build: add Python 3.13 to CI matrix (#345)
- build: raise astropy cap, update JAX Partial imports for 0.5+ compat (#344)
- Retire main_build: check out PyAutoFit main in CI (#338)
- Expose dataset_util via autogalaxy.util.dataset (#336)
- Remove Copilot dispatch workflow (#335)
- perf: remove unused astropy.modeling import from convert.py (#331)
- perf: skip savefig in _save_subplot when PYAUTO_FAST_PLOTS=1 (#328)
- refactor: import is_test_mode from autoconf (#327)
- feat: use tight_layout wrapper for PYAUTO_FAST_PLOTS support (#326)
- perf: reduce unit test runtime from 82s to 28s (#322)
- Use centralized is_test_mode() from PyAutoFit (#320)
- Add ReadTheDocs config with Python 3.12 (#318)
- Drop Python 3.9-3.11, add 3.13 (#317)
Upstream Changes
PyAutoFit
- refactor: replace search YAML config with explicit Python defaults (#1202)
- fix: guard interpolator and grid search against edge cases (#1201)
- docs: update Python version to 3.12-3.13 (#1199)
- build: add Python 3.13 support (#1198)
- build: raise scipy cap, relax threadpoolctl and SQLAlchemy pins (#1197)
- fix: bump scipy cap to <=1.15.2 (#1196)
- refactor: separate PYAUTOFIT_TEST_MODE into distinct PYAUTO_* env vars (#1195)
PyAutoArray
- fix: guard zoom_array against non-autoarray mask objects (#270)
- build: add Python 3.13 to CI matrix (#268)
- build: raise caps on scipy, astropy, scikit-image, scikit-learn (#267)
- fix: bump scipy cap to <=1.15.2 (#266)
- refactor: rename env vars to PYAUTO_* prefix (#265)
- Guarantee GaussianKernel regularization matrix is PD (#264)
- refactor: clamp brightest_coordinate_in_region_from to array bounds (#263)
- fix: add _mappings_sizes_weights_split to InterpolatorRectangular (#262)
- Add should_simulate utility for auto-simulation with small datasets (#261)
- feat: add title_prefix support to subplot_imaging_dataset (#260)
- perf: defer scipy imports to reduce import time (#259)
- perf: skip radial bins computation when PYAUTO_WORKSPACE_SMALL_DATASETS=1 (#258)
- perf: force over_sample_size=2 when PYAUTO_WORKSPACE_SMALL_DATASETS=1 (#257)
- fix: import is_test_mode from autoconf instead of autofit (#256)
- perf: skip savefig rendering in PYAUTO_FAST_PLOTS mode (#255)
- feat: add tight_layout wrapper with PYAUTO_FAST_PLOTS env var (#254)
- feat: PYAUTO_WORKSPACE_SMALL_DATASETS env var for fast smoke tests (#253)
- perf: speed up unit tests 63% by removing JAX from triangle tests (#252)
- Use centralized is_test_mode() from PyAutoFit (#250)
- Drop Python 3.9-3.11, add 3.13 (#249)
Full changelog: 2026.4.5.3...2026.4.13.3