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

    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