Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions autogalaxy/operate/image.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
"""
Mixin classes that add image-operation methods (PSF convolution, Fourier transform) to light objects.

The three mixin classes here are arranged in a hierarchy:

- `OperateImage` — methods that operate on a **single** image from a light object
(e.g. a `LightProfile` or `Galaxy`).
- `OperateImageList` — extends `OperateImage` with methods that operate on a **list** of images,
one per light profile component.
- `OperateImageGalaxies` — extends `OperateImageList` with methods that operate on a **dict** mapping
each `Galaxy` to its image, preserving galaxy identity through the pipeline.

All three classes are mixins — they are not instantiated directly but are inherited by light objects
(`LightProfile`, `Galaxy`, `Galaxies`, `Tracer`) to expose a consistent API for blurring and Fourier
transforming images.
"""
from __future__ import annotations
import numpy as np
from typing import TYPE_CHECKING, Dict, List, Optional
Expand All @@ -24,9 +40,31 @@ class OperateImage:
def image_2d_from(
self, grid: aa.Grid2D, xp=np, operated_only: Optional[bool] = None
) -> aa.Array2D:
"""
Abstract method — return the 2D image of this light object at every coordinate on `grid`.

Subclasses (e.g. `LightProfile`, `Galaxy`) implement this method to evaluate their surface
brightness at each (y, x) coordinate.

Parameters
----------
grid
The 2D (y, x) coordinates where the image is evaluated.
operated_only
Controls which light profiles contribute. `None` (default) returns all profiles;
`True` returns only `LightProfileOperated` images; `False` excludes them.
"""
raise NotImplementedError

def has(self, cls) -> bool:
"""
Returns `True` if any attribute of this object is an instance of `cls`, else `False`.

Parameters
----------
cls
The class type to search for.
"""
raise NotImplementedError

def _blurred_image_2d_from(
Expand All @@ -36,6 +74,21 @@ def _blurred_image_2d_from(
psf: aa.Convolver,
xp=np,
) -> aa.Array2D:
"""
Convolve a 2D image with a PSF using the supplied `Convolver`.

This is the internal helper used by `blurred_image_2d_from`. It does not handle the
`LightProfileOperated` logic — the caller must do that separately.

Parameters
----------
image_2d
The 2D image of the masked pixels to be convolved.
blurring_image_2d
The 2D image of the pixels just outside the mask whose light blurs into the masked region.
psf
The PSF convolver that performs the 2D convolution.
"""

values = psf.convolved_image_from(
image=image_2d, blurring_image=blurring_image_2d, xp=xp
Expand Down
18 changes: 18 additions & 0 deletions autogalaxy/operate/lens_calc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
"""
`LensCalc` — a calculator that derives all secondary lensing quantities from a deflection callable.

Given any object that exposes `deflections_yx_2d_from` (a `MassProfile`, `Galaxy`, `Galaxies`, or
`Tracer`), `LensCalc` computes:

- **Hessian** (four components: H_yy, H_xy, H_yx, H_xx) — the matrix of second derivatives of the
lensing potential, computed by finite differences (NumPy) or automatic differentiation (JAX).
- **Convergence via Hessian** — κ = 0.5 (H_yy + H_xx), independent of the analytic profile formula.
- **Shear** — γ₁ = 0.5 (H_xx − H_yy), γ₂ = H_xy.
- **Magnification** — μ = 1 / det(I − H).
- **Critical curves** — image-plane loci where det(I − H) = 0, found via marching squares.
- **Caustics** — source-plane images of the critical curves.
- **Einstein radius** — the effective radius from the area enclosed by the tangential critical curve.
- **Fermat potential** — φ(θ) = ½|θ − β|² − ψ(θ), using the optional potential callable.

The class is constructed with `LensCalc.from_mass_obj(mass)` or `LensCalc.from_tracer(tracer)`.
"""
from functools import wraps
import logging
import numpy as np
Expand Down
Loading