Skip to content

feat: AnalysisWeak — weak lensing modeling (weak series step 4) #579

Description

@Jammy2211

Overview

Step 4 of the weak-lensing series (PyAutoMind/z_features/weak_shear.md): add al.AnalysisWeak so a non-linear search can fit lens mass models to a WeakDataset shear catalogue, mirroring the established model API of imaging/point, plus a workspace scripts/weak/modeling.py tutorial. This is the keystone of the weak-lensing home-straight push — series steps 5 (likelihood_function), 7 (Abell 2744 real data) and 8 (combined strong+weak via summed analyses) all depend on it.

Science scope: cluster/group-scale weak shear complementing strong lensing (Niemiec et al. 2020 hybrid-Lenstool; Oguri et al. 2012 SGAS) — not cosmic shear or galaxy-galaxy lensing.

Plan

  • Add autolens/weak/model/ mirroring autolens/point/model/ (the right template — FitWeak already follows FitPoint's standalone pattern): AnalysisWeak, ResultWeak, VisualizerWeak, PlotterWeak.
  • AnalysisWeak.log_likelihood_function builds a Tracer from the model instance and returns FitWeak(dataset, tracer).log_likelihood.
  • Wire on-the-fly visualization through the existing nine weak plotters (subplot_weak_dataset, subplot_fit_weak, subplot_fit_quick), with new weak_dataset / fit_weak sections in the packaged config/visualize/plots.yaml.
  • Export al.AnalysisWeak in autolens/__init__.py; NumPy-only unit tests mirroring test_autolens/point/model/.
  • Ship library PR first; workspace follow-up adds scripts/weak/modeling.py (judgment-tier tutorial prose, style of scripts/imaging/modeling.py) and mirrors the new plots.yaml keys into workspace config.
Detailed implementation plan

Affected Repositories

  • PyAutoLens (primary — library)
  • autolens_workspace (follow-up — workspace tutorial + config mirror)

Branch Survey

Repository Current Branch Dirty?
./PyAutoLens main clean
./autolens_workspace main dirty (7 pre-existing regenerated dataset files + stray dataset.fits, unrelated to this task)

Suggested branch: feature/weak-modeling
Worktree: ~/Code/PyAutoLabs-wt/weak-modeling/
Note: autolens_workspace is currently claimed by task lenstool-example. Library work proceeds first (combined workflow); the workspace follow-up uses the parallel-worktree pattern proven twice in this series (scripts/weak/ has zero file overlap with lenstool work) if the claim still stands at ship time.

Implementation Steps

  1. autolens/weak/model/__init__.py — empty, matching point/model.
  2. autolens/weak/model/analysis.pyclass AnalysisWeak(AgAnalysis, AnalysisLens):
    • Visualizer = VisualizerWeak, Result = ResultWeak class attributes.
    • __init__(self, dataset: WeakDataset, cosmology=None, title_prefix=None, use_jax=False, **kwargs). use_jax=False default: FitWeak is NumPy (cached_property + np.asarray, no xp threading); JAX support is deliberate future work (needs pytree registration like AnalysisPoint._register_fit_point_pytrees) — do NOT bolt it on here.
    • log_likelihood_function(instance)self.fit_from(instance).log_likelihood.
    • fit_from(instance)tracer_via_instance_from(instance)FitWeak(dataset=self.dataset, tracer=tracer).
    • save_attributes(paths)ag.output_to_json(self.dataset, paths._files_path / "dataset.json") (round-trip works since the weak-dataset-from-json fix).
  3. autolens/weak/model/result.pyResultWeak(Result) mirroring ResultPoint (13 lines): fallback uniform grid property + max_log_likelihood_fit via analysis.fit_from(self.instance).
  4. autolens/weak/model/plotter.pyPlotterWeak(Plotter) mirroring PlotterPoint: dataset_weak()subplot_weak_dataset behind plot_setting(section=["weak_dataset"], ...); fit_weak(fit, quick_update=False)subplot_fit_weak / subplot_fit_quick behind plot_setting(section=["fit_weak"], ...).
  5. autolens/weak/model/visualizer.pyVisualizerWeak(af.Visualizer) mirroring VisualizerPoint (107 lines): visualize_before_fit plots the dataset; visualize plots the fit from the instance, forwarding quick_update.
  6. Config: add to autolens/config/visualize/plots.yaml (after the point_dataset/fit_point_dataset block, same comment style):
    • weak_dataset: with subplot_dataset: true
    • fit_weak: with subplot_fit: true
  7. Exports: autolens/__init__.pyfrom .weak.model.analysis import AnalysisWeak (alongside the existing weak exports at lines 128-130).
  8. Tests (NumPy-only, no JAX per repo rules): test_autolens/weak/test_analysis.py (+ plotter test if cheap) mirroring test_autolens/point/model/test_analysis_point.py:
    • log_likelihood_function(instance) == FitWeak(dataset, tracer).log_likelihood for a SimulatorShearYX(seed=1) dataset and Isothermal instance.
    • noise-free round-trip: simulator tracer fitted to its own noise-free output gives chi_squared == 0 (bit-exact, both use shear_yx_2d_via_hessian_from).
    • save_attributes writes a loadable dataset.json (al.from_json round-trip).
    • Use direct module imports in tests (the al.plot.X pytest recursion gotcha from step 2 applies).
  9. Run full python -m pytest test_autolens/ before PR.

Workspace follow-up (second PR, after library merges)

  1. autolens_workspace/scripts/weak/modeling.py — Nautilus fit of an Isothermal lens to the dataset/weak/simple dataset, prose in the style of scripts/imaging/modeling.py (judgment-tier tutorial prose per WORKFLOW.md).
  2. Mirror the new weak_dataset / fit_weak plots.yaml sections into autolens_workspace/config/visualize/plots.yaml (workspace configs override packaged defaults).

Key Files

  • autolens/point/model/{analysis,result,plotter,visualizer}.py — the template (233/13/97/107 lines).
  • autolens/weak/fit.pyFitWeak, already exposes log_likelihood.
  • autolens/weak/plot/{weak_dataset_plots,fit_weak_plots}.py — the nine existing plot helpers + subplot_fit_quick.
  • autolens/config/visualize/plots.yaml — visualization settings read by plot_setting.

Autonomy

--auto launch 2026-07-09, effective level supervised (header supervised, feature cap supervised): plan-to-issue (this issue), mechanical stretches proceed, ship sign-off parks as a batched question here, merge stays human. No Heart YELLOW acknowledgement was given at launch. Brain Feature Agent scored this too-large and suggested a 4-phase split; consolidated to the series' proven 2-PR shape (library, then workspace) — recorded here for post-hoc review.

Original Prompt

Click to expand starting prompt

We are now going to add weak lensing modeling.

First, we need to create the analysis.py module, so inspect @autolens_workspace/scripts/weak and
@PyAutoLens/autolens/imaging/model . We are basically going to make everything weak does from here a "mirror" of
the imaging model API (and also interferoter.)

The log_likelihod_function is in particular important, we already have the codw which creates the shear field
show in the @autolens_workspace/scripts/weak/simulator.py file and we can turn it into a fit in
@PyAutoLens/autolens/imaging/fit.py, so shouldnt be hard to work out the pattern and whats needed here.

I believe everything else (plotter.py, result.py, visualizer.py) should be relatively straight forward to work
out by simply copying the patterns and logic from the imaging module, but keep an eye out for unexpected tricky
parts.

Finally, read @autolens_workspace/scripts/imaging/modeling.py and then make an equivalent for
weak lensing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions