Skip to content

feat(interop): COOLEST observation pixel grid + on_unsupported="skip" - #740

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/coolest-observation-grid
Sep 16, 2026
Merged

Jammy2211 merged 1 commit into
mainfrom
feature/coolest-observation-grid

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

Fixes #739.

al.interop.coolest.to_coolest() wrote every template with an empty observation.pixels block (field_of_view_x/y = (0, 0), num_pix_x/y = 0) because it built lazy.Observation() with no pixel grid. COOLEST's plotting API cannot render such a template (ModelPlotter fails with IndexError); an external reviewer found this and confirmed that setting the grid so its pixel scale matches the instrument block makes plotting work.

to_coolest now writes a real PixelatedRegularGrid from shape_native + pixel_size, or directly from a dataset= (anything with shape_native and pixel_scales, e.g. an al.Imaging). If neither is given the template is written as before (zeros) and a UserWarning says COOLEST plotting needs the grid.

It also gains on_unsupported="skip" for models COOLEST has no analytic profile for (an MGE Basis of Gaussians, a pixelized source). The supported parts (full mass model, Sersic light) still export and every omitted component is recorded under meta.skipped_profiles as {"galaxy": "galaxy_i", "profile": "Basis(GaussianSph x 30)" | "Pixelization(Delaunay)"}. The default "raise" keeps today's behaviour, so existing callers and the workspace_test round trip are unchanged. This is what the Euclid DR1 pipeline (MGE lens light + Delaunay source) needs to write COOLEST by default; converting those components to COOLEST pixel grids is a follow-up.

API Changes

  • to_coolest(...) gains keyword parameters shape_native=None, dataset=None, on_unsupported="raise" (inserted before metadata; all known callers pass metadata by keyword).
  • New UserWarning when a template is written with no observation grid.
  • Template meta may carry a skipped_profiles list when on_unsupported="skip".
    See full details below.

Test Plan

  • pytest test_autolens/interop -q — 13 passed (6 existing + 7 new: grid from shape_native/pixel_size incl. pixel-size identity with the instrument block, dataset= path, no-grid warning with zeros, default raise on MGE + pixelized galaxy, skip records both and still exports SIE + shear, invalid on_unsupported, from_coolest on a skipped template returns the mass-only tracer).
  • Hand check reproducing the report: a 100x100 / 0.1" template loads with JSONSerializer(...).load() giving num_pix_x == 100, field_of_view_x == (-5.0, 5.0), observation.check_consistency_with_instrument() passes, and coolest.api.plotting.ModelPlotter.plot_surface_brightness / plot_convergence render. The same model written without a grid reproduces the IndexError.
  • autolens_workspace/scripts/guides/coolest_interop.py runs end to end with the new grid (round-trip max deflection difference 8.9e-16); workspace PR follows behind the library-first gate.
Full API Changes (for automation & release notes)

Removed

  • none

Added

  • autolens.interop.coolest.to_coolest(galaxies, file_path, cosmology=None, mode="MAP", pixel_size=0.1, shape_native=None, dataset=None, on_unsupported="raise", metadata=None) — shape_native=(y, x) with pixel_size, or dataset=, writes the observation.pixels grid (field_of_view_x = (-x*ps/2, x*ps/2), field_of_view_y = (-y*ps/2, y*ps/2), num_pix_x = x, num_pix_y = y); on_unsupported="skip" omits unconvertible profiles and lists them in meta.skipped_profiles.

Migration

  • Before: al.interop.coolest.to_coolest(galaxies=tracer, file_path="model") → template with a zero observation grid (now warns).
  • After: al.interop.coolest.to_coolest(galaxies=tracer, file_path="model", dataset=imaging) or shape_native=(100, 100), pixel_size=0.1.
  • Models with MGE / pixelized components: add on_unsupported="skip" and read meta.skipped_profiles.

Generated by the PyAutoLabs agent workflow.

🤖 Generated with Claude Code

to_coolest wrote every template with an empty observation.pixels block
(field_of_view 0, num_pix 0) because it built lazy.Observation() with no
pixel grid; COOLEST's plotting API cannot render that. It now writes a
PixelatedRegularGrid from shape_native + pixel_size or from dataset=
(anything with shape_native and pixel_scales), and warns when neither is
given.

on_unsupported="skip" exports the full mass model and any supported
light while omitting profiles COOLEST cannot represent (an MGE Basis,
a Pixelization), recording each under meta.skipped_profiles. The default
"raise" is unchanged.

Refs #739

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Jammy2211

Copy link
Copy Markdown
Collaborator Author

Workspace follow-ups behind the library-first gate (merge this PR first): PyAutoLabs/autolens_workspace#551, PyAutoLabs/euclid_strong_lens_modeling_pipeline#82. Heart RED override authorised by the human on 2026-09-16 for PR-open only; see #739.

@Jammy2211
Jammy2211 merged commit 223132c into main Sep 16, 2026
4 checks passed
@Jammy2211
Jammy2211 deleted the feature/coolest-observation-grid branch September 16, 2026 22:40
@Jammy2211 Jammy2211 removed the pending-release PR queued for the next release build label Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(interop): COOLEST observation pixel grid, skip-and-record unsupported profiles, Euclid pipeline output

1 participant