Source code for autogalaxy.ellipse.plot.fit_ellipse_plots

import numpy as np
import math
from typing import List, Optional

import autoarray as aa
from autoarray.plot.utils import subplots, conf_subplot_figsize, tight_layout

from autogalaxy.ellipse.plot import fit_ellipse_plot_util
from autogalaxy.ellipse.fit_ellipse import FitEllipse
from autogalaxy.util.plot_utils import plot_array, _save_subplot
from autogalaxy.util import error_util


def _plot_data(
    fit_list: List[FitEllipse],
    output_path=None,
    output_filename="ellipse_fit",
    output_format=None,
    colormap="default",
    use_log10=False,
    disable_data_contours: bool = False,
    suffix: str = "",
    ax=None,
    title_prefix: str = None,
):
    """Plot the 2-D image data with fitted ellipse contours overlaid.

    For each :class:`~autogalaxy.ellipse.fit_ellipse.FitEllipse` in
    *fit_list* the major-axis sampling points are extracted and converted to
    ``Grid2DIrregular`` objects, which are then passed as *lines* and
    *positions* overlays to the underlying array-plot routine.

    Parameters
    ----------
    fit_list : list of FitEllipse
        The ellipse fits whose contours are to be overlaid.
    output_path : str or None
        Directory in which to save the figure.  ``None`` → ``plt.show()``.
    output_filename : str
        Stem of the output file name.
    output_format : str
        File format, e.g. ``"png"``.
    colormap : str
        Matplotlib colormap name, or ``"default"``.
    use_log10 : bool
        Apply a log₁₀ stretch to the image values.
    disable_data_contours : bool
        Reserved for future contour-suppression support (currently unused).
    suffix : str
        Optional suffix appended to *output_filename* before the extension.
    ax : matplotlib.axes.Axes or None
        Existing ``Axes`` to draw into; the caller is responsible for saving
        when this is provided.
    """
    ellipse_list = []
    for fit in fit_list:
        points = fit.points_from_major_axis_from()
        x = points[:, 1]
        y = points[:, 0] * -1.0
        ellipse_list.append(aa.Grid2DIrregular.from_yx_1d(y=y, x=x))

    lines = [np.array(e.array) for e in ellipse_list if e is not None]
    positions = lines

    _title = f"{title_prefix.rstrip()} Ellipse Fit" if title_prefix else "Ellipse Fit"
    plot_array(
        array=fit_list[0].data,
        title=_title,
        output_path=output_path,
        output_filename=f"{output_filename}{suffix}",
        output_format=output_format,
        colormap=colormap,
        use_log10=use_log10,
        lines=lines or None,
        positions=positions or None,
        ax=ax,
    )


def _plot_ellipse_residuals(
    fit_list: List[FitEllipse],
    output_path=None,
    output_format=None,
    for_subplot: bool = False,
    suffix: str = "",
    ax=None,
):
    """Plot the 1-D ellipse residuals via the low-level utility function.

    Constructs the ``autoarray`` ``Output`` object required by
    :func:`~autogalaxy.ellipse.plot.fit_ellipse_plot_util.plot_ellipse_residuals`
    and then delegates to it.

    Parameters
    ----------
    fit_list : list of FitEllipse
        The ellipse fits to summarise.
    output_path : str or None
        Directory in which to save the figure.  ``None`` → an ``Output``
        with no path is created, falling back to ``plt.show()``.
    output_format : str
        File format, e.g. ``"png"``.
    for_subplot : bool
        If ``True``, draw into subplot position ``(1, 2, 2)`` of the current
        figure.
    suffix : str
        Reserved for future filename-suffix support (currently unused).
    ax : matplotlib.axes.Axes or None
        Reserved for future direct-axes support (currently unused).
    """
    from autoarray.plot.output import Output

    output = Output(path=output_path, format=output_format) if output_path else Output()

    fit_ellipse_plot_util.plot_ellipse_residuals(
        array=fit_list[0].dataset.data.native,
        fit_list=fit_list,
        colors="k",
        output=output,
        for_subplot=for_subplot,
    )


[docs] def subplot_fit_ellipse( fit_list: List[FitEllipse], output_path=None, output_format=None, colormap="default", use_log10=False, disable_data_contours: bool = False, title_prefix: str = None, ): """Create a two-panel subplot summarising a list of ellipse fits. The left panel shows the 2-D image with fitted ellipse contours overlaid (via :func:`_plot_data`); the right panel shows the 1-D residuals as a function of position angle (via :func:`_plot_ellipse_residuals`). Parameters ---------- fit_list : list of FitEllipse The ellipse fits to visualise. output_path : str or None Directory in which to save the figure. ``None`` → ``plt.show()``. output_format : str File format, e.g. ``"png"``. colormap : str Matplotlib colormap name, or ``"default"``. use_log10 : bool Apply a log₁₀ stretch to the image values in the left panel. disable_data_contours : bool If ``True``, suppress ellipse contour overlays on the image panel. """ fig, axes = subplots(1, 2, figsize=conf_subplot_figsize(1, 2)) _plot_data( fit_list=fit_list, colormap=colormap, use_log10=use_log10, disable_data_contours=disable_data_contours, ax=axes[0], title_prefix=title_prefix, ) _plot_ellipse_residuals(fit_list=fit_list, for_subplot=True, ax=axes[1]) tight_layout() _save_subplot(fig, output_path, "fit_ellipse", output_format)
[docs] def subplot_ellipse_errors( fit_pdf_list: List[List[FitEllipse]], output_path=None, output_format=None, colormap="default", use_log10=False, sigma: Optional[float] = 3.0, ): """Create a subplot showing the median ellipse and its uncertainty region from a PDF sample. *fit_pdf_list* is a list of fit-lists — each inner list represents one posterior sample and contains one :class:`~autogalaxy.ellipse.fit_ellipse.FitEllipse` per ellipse. For each ellipse position the median contour and the ``sigma``-level confidence interval are computed in polar coordinates (via :func:`~autogalaxy.util.error_util.ellipse_median_and_error_region_in_polar`) and overlaid on the 2-D image. One panel is produced per ellipse. Parameters ---------- fit_pdf_list : list of list of FitEllipse Outer list: posterior samples. Inner list: per-ellipse fits for that sample. output_path : str or None Directory in which to save the figure. ``None`` → ``plt.show()``. output_format : str File format, e.g. ``"png"``. colormap : str Matplotlib colormap name, or ``"default"``. use_log10 : bool Apply a log₁₀ stretch to the image values. sigma : float or None Number of standard deviations defining the confidence interval (default ``3.0``). """ low_limit = (1 - math.erf(sigma / math.sqrt(2))) / 2 ellipse_centre_list = [] fit_ellipse_list = [[] for _ in range(len(fit_pdf_list[0]))] for fit_list in fit_pdf_list: ellipse_centre_list.append(fit_list[0].ellipse.centre) for i, fit in enumerate(fit_list): points = fit.points_from_major_axis_from() x = points[:, 1] y = points[:, 0] * -1.0 fit_ellipse_list[i].append(aa.Grid2DIrregular.from_yx_1d(y=y, x=x)) n = len(fit_ellipse_list) fig, axes = subplots(1, n, figsize=conf_subplot_figsize(1, n)) axes_flat = [axes] if n == 1 else list(axes.flatten()) for i in range(n): median_ellipse, [lower_ellipse, upper_ellipse] = ( error_util.ellipse_median_and_error_region_in_polar( fit_ellipse_list[i], low_limit=low_limit, center=ellipse_centre_list[i], ) ) try: median_arr = np.array( median_ellipse.array if hasattr(median_ellipse, "array") else median_ellipse ) lines = [median_arr] if median_arr.ndim == 2 else None except Exception: lines = None plot_array( array=fit_pdf_list[0][0].data, title="Ellipse Fit", colormap=colormap, use_log10=use_log10, lines=lines, ax=axes_flat[i], ) tight_layout() _save_subplot(fig, output_path, "ellipse_errors", output_format)