Skip to content

feat: Convolver convolve_over_sample_size + Imaging plumbing (phase 2a) #354

Description

@Jammy2211

Overview

Phase 2a of oversampled PSF convolution: the PyAutoArray core API. Implements the design approved in #353 (PyAutoMind/feature/autoarray/oversampling_design.md) verbatimConvolver.convolve_over_sample_size, the fine-mask machinery, Imaging plumbing and the adaptive guards, with unit tests pinned to the phase-1 numerical ground truth. Behaviour at convolve_over_sample_size=1 is byte-identical to today.

Run mode: --auto at effective level supervised (plan-to-issue, ship sign-off parks with a batched question). Phase split: 2a (this issue) → 2b inversion wiring → 2c PyAutoGalaxy consumer (queued, blocked by an unrelated PyAutoGalaxy worktree claim) → phases 3–4 (workspace, docs).

Plan

  • Add mask_2d_upscaled_from(mask, s) and the cached permutation between autoarray's per-pixel sub-block ordering and the fine mask's row-major slim ordering.
  • Extend Convolver with convolve_over_sample_size: int = 1: fine-resolution kernel semantics, fine ConvolverState from state_from, oversampled scatter → existing convolve → s×s mean bin → slim in all four convolution methods, loud shape/pixel-scale validation.
  • Extend Imaging/GridsDataset with convolve_over_sample_size_lp / convolve_over_sample_size_pixelization (int, default 1), the equality rule vs over_sample_size_*, blurring grid at over_sample_size=s, psf_setup_state fine state, ctor/from_fits/apply_* pass-through, sparse_operator + adaptive guards.
  • Add binned: bool = True pass-through to the over_sample decorator (autoarray side only).
  • Unit tests (numpy-only): s=1 strict parity, s=2 ground-truth reference values, guard raises; full suite green.
Detailed implementation plan

Affected Repositories

  • PyAutoArray (primary, only repo edited)

Branch Survey

Repository Current Branch Dirty?
./PyAutoArray main clean

Suggested branch: feature/psf-oversample-core
Worktree root: ~/Code/PyAutoLabs-wt/psf-oversample-core/

Implementation Steps

  1. Fine-mask utilsautoarray/mask/mask_2d_util.py: mask_2d_upscaled_from(mask_2d, over_sample_size) (each unmasked pixel → s×s unmasked block, pixel scale ps/s, same origin); permutation builder sub_slim_to_fine_slim_from(mask, s) mapping per-pixel sub-block slim indices to fine-mask row-major slim indices (and its inverse). Unit tests: round-trip permutation, upscaled-mask geometry, s=1 identity.
  2. ConvolverState fine geometryautoarray/operators/convolver.py: when built for s>1, construct from (kernel_fine, mask_fine); cache sub_slim_to_fine_slim, the blurring-region permutation, and bin/reshape indices alongside the existing FFT precomputes.
  3. Convolver APIconvolve_over_sample_size: int = 1 ctor param (validate plain int ≥ 1, TypeError otherwise); state_from(mask) derives the fine mask when s>1 and checks kernel.pixel_scales ≈ mask.pixel_scales / s (KernelException on mismatch); convolved_image_from, convolved_mapping_matrix_from and both _via_real_space_* variants accept over-sampled slim inputs when s>1 (length n_unmasked·s², sub-block order), raise on binned-length input, return image-resolution slim via mean bin-down. s=1 paths untouched.
  4. Imaging / GridsDatasetautoarray/dataset/imaging/dataset.py + dataset/grids.py: new ctor ints (default 1) stored + passed through from_fits / apply_mask / apply_over_sampling; equality rule (s>1 requires matching over_sample_size_* uniform int equal to it, DatasetException otherwise, checked via OverSampler.sub_is_uniform); blurring grid gets over_sample_size=s when s>1; psf_setup_state builds the fine state; raise if sparse_operator is not None and convolve_over_sample_size_pixelization > 1.
  5. Decoratorautoarray/operators/over_sampling/decorator.py: binned: bool = True kwarg; binned=False returns sub-gridded values in sub-block order (the s>1 Convolver input format). No callers change in this PR.
  6. Teststest_autoarray/: mirror the ground-truth scene (11×11, ps=1, r=3.5 circular mask, Gaussian source σ=1.2 @ (0.3,−0.4), Gaussian PSF σ=0.8, kernel radius 2.0"): s=1 parity vs existing path; s=2 == design §7 reference values (sum 2.796562184524787, slim0 3.726289901353439e-02, slim17 2.025075336159483e-01, slim36 1.090767109119494e-02); guard raises; decorator binned=False ordering.

Key Files

  • autoarray/operators/convolver.py — ConvolverState + Convolver (design §§1–2)
  • autoarray/mask/mask_2d_util.py — upscale + permutation utils
  • autoarray/dataset/imaging/dataset.py, autoarray/dataset/grids.py — plumbing + guards (design §3, §6)
  • autoarray/operators/over_sampling/decorator.pybinned kwarg (design §5)
  • PyAutoMind/feature/autoarray/oversampling_design.md — the approved design (do not re-design)
  • PyAutoMind/feature/autoarray/oversampling_ground_truth.py — reference numbers

Acceptance

  • Full PyAutoArray pytest suite green; every pre-existing test unmodified.
  • s=2 unit tests reproduce the ground-truth numbers to ≤1e-12.
  • PR body carries ## API Changes for phases 2b/2c/3.

Original Prompt

Click to expand starting prompt

See PyAutoMind/issued/oversampling_phase_2a_convolver_dataset.md (phase 2a split of oversampling_phase_2_core_api.md, itself phase 2 of oversampling.md; design approved in #353).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions