diff --git a/autoarray/config/visualize/general.yaml b/autoarray/config/visualize/general.yaml index 36f7f1ec..3c65121e 100644 --- a/autoarray/config/visualize/general.yaml +++ b/autoarray/config/visualize/general.yaml @@ -27,20 +27,23 @@ colorbar: pad: 0.01 # Padding between colorbar and axes. labelrotation: 90 # Rotation of colorbar tick labels in degrees. labelsize: 22 # Font size of colorbar tick labels for single-panel figures. - labelsize_subplot: 22 # Font size of colorbar tick labels for subplot panels. + labelsize_subplot: 33 # Font size of colorbar tick labels for subplot panels. mat_plot: figure: figsize: (7, 7) # Default figure size. Override via aplt.Figure(figsize=(...)). + subplot_shape_to_figsize_factor: (6, 6) # Per-panel size factor for subplots. figsize = (cols*fx, rows*fy). + title: + fontsize: 24 # Default title font size for single-panel figures. + title_subplot: + fontsize: 20 # Default title font size for subplot panels. yticks: fontsize: 22 # Default y-tick font size. Override via aplt.YTicks(fontsize=...). yticks_subplot: - fontsize: 18 # Default y-tick font size for subplot panels. + fontsize: 22 # Default y-tick font size for subplot panels. xticks: fontsize: 22 # Default x-tick font size. Override via aplt.XTicks(fontsize=...). xticks_subplot: - fontsize: 18 # Default x-tick font size for subplot panels. - title: - fontsize: 24 # Default title font size. Override via aplt.Title(fontsize=...). + fontsize: 22 # Default x-tick font size for subplot panels. ylabel: fontsize: 16 # Default y-label font size. Override via aplt.YLabel(fontsize=...). xlabel: diff --git a/autoarray/dataset/plot/imaging_plots.py b/autoarray/dataset/plot/imaging_plots.py index fa0f19a4..ec680ff3 100644 --- a/autoarray/dataset/plot/imaging_plots.py +++ b/autoarray/dataset/plot/imaging_plots.py @@ -2,13 +2,13 @@ import matplotlib.pyplot as plt -from autoarray.plot.utils import subplot_save +from autoarray.plot.utils import subplot_save, conf_subplot_figsize def subplot_imaging_dataset( dataset, output_path: Optional[str] = None, - output_filename: str = "subplot_dataset", + output_filename: str = "dataset", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -51,7 +51,7 @@ def subplot_imaging_dataset( from autoarray.plot.array import plot_array - fig, axes = plt.subplots(3, 3, figsize=(21, 21)) + fig, axes = plt.subplots(3, 3, figsize=conf_subplot_figsize(3, 3)) axes = axes.flatten() plot_array( @@ -147,7 +147,7 @@ def subplot_imaging_dataset( def subplot_imaging_dataset_list( dataset_list, output_path=None, - output_filename: str = "subplot_dataset_combined", + output_filename: str = "dataset_combined", output_format="png", ): """ @@ -172,7 +172,7 @@ def subplot_imaging_dataset_list( from autoarray.plot.array import plot_array n = len(dataset_list) - fig, axes = plt.subplots(n, 3, figsize=(21, 7 * n)) + fig, axes = plt.subplots(n, 3, figsize=conf_subplot_figsize(n, 3)) if n == 1: axes = [axes] for i, dataset in enumerate(dataset_list): diff --git a/autoarray/dataset/plot/interferometer_plots.py b/autoarray/dataset/plot/interferometer_plots.py index d3cd10e8..df872e9c 100644 --- a/autoarray/dataset/plot/interferometer_plots.py +++ b/autoarray/dataset/plot/interferometer_plots.py @@ -6,14 +6,14 @@ from autoarray.plot.array import plot_array from autoarray.plot.grid import plot_grid from autoarray.plot.yx import plot_yx -from autoarray.plot.utils import subplot_save, hide_unused_axes +from autoarray.plot.utils import subplot_save, hide_unused_axes, conf_subplot_figsize from autoarray.structures.grids.irregular_2d import Grid2DIrregular def subplot_interferometer_dataset( dataset, output_path: Optional[str] = None, - output_filename: str = "subplot_dataset", + output_filename: str = "dataset", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -39,7 +39,7 @@ def subplot_interferometer_dataset( use_log10 Apply log10 normalisation to image panels. """ - fig, axes = plt.subplots(2, 3, figsize=(21, 14)) + fig, axes = plt.subplots(2, 3, figsize=conf_subplot_figsize(2, 3)) axes = axes.flatten() plot_grid(dataset.data.in_grid, ax=axes[0], title="Visibilities") @@ -92,7 +92,7 @@ def subplot_interferometer_dataset( def subplot_interferometer_dirty_images( dataset, output_path: Optional[str] = None, - output_filename: str = "subplot_dirty_images", + output_filename: str = "dirty_images", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -115,7 +115,7 @@ def subplot_interferometer_dirty_images( use_log10 Apply log10 normalisation. """ - fig, axes = plt.subplots(1, 3, figsize=(21, 7)) + fig, axes = plt.subplots(1, 3, figsize=conf_subplot_figsize(1, 3)) plot_array( dataset.dirty_image, diff --git a/autoarray/fit/plot/fit_imaging_plots.py b/autoarray/fit/plot/fit_imaging_plots.py index 0733bbc0..ce157de9 100644 --- a/autoarray/fit/plot/fit_imaging_plots.py +++ b/autoarray/fit/plot/fit_imaging_plots.py @@ -3,13 +3,13 @@ import matplotlib.pyplot as plt from autoarray.plot.array import plot_array -from autoarray.plot.utils import subplot_save, symmetric_vmin_vmax, hide_unused_axes +from autoarray.plot.utils import subplot_save, symmetric_vmin_vmax, hide_unused_axes, conf_subplot_figsize def subplot_fit_imaging( fit, output_path: Optional[str] = None, - output_filename: str = "subplot_fit", + output_filename: str = "fit", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -43,7 +43,7 @@ def subplot_fit_imaging( grid, positions, lines Optional overlays forwarded to every panel. """ - fig, axes = plt.subplots(2, 3, figsize=(21, 14)) + fig, axes = plt.subplots(2, 3, figsize=conf_subplot_figsize(2, 3)) axes = axes.flatten() plot_array( @@ -103,6 +103,7 @@ def subplot_fit_imaging( use_log10=False, vmin=vmin_n, vmax=vmax_n, + cb_unit=r"$\sigma$", grid=grid, positions=positions, lines=lines, @@ -113,6 +114,7 @@ def subplot_fit_imaging( title="Chi-Squared Map", colormap=colormap, use_log10=use_log10, + cb_unit=r"$\chi^2$", grid=grid, positions=positions, lines=lines, diff --git a/autoarray/fit/plot/fit_interferometer_plots.py b/autoarray/fit/plot/fit_interferometer_plots.py index af4312ed..11c9623b 100644 --- a/autoarray/fit/plot/fit_interferometer_plots.py +++ b/autoarray/fit/plot/fit_interferometer_plots.py @@ -5,13 +5,13 @@ from autoarray.plot.array import plot_array from autoarray.plot.yx import plot_yx -from autoarray.plot.utils import subplot_save, symmetric_vmin_vmax, hide_unused_axes +from autoarray.plot.utils import subplot_save, symmetric_vmin_vmax, hide_unused_axes, conf_subplot_figsize def subplot_fit_interferometer( fit, output_path: Optional[str] = None, - output_filename: str = "subplot_fit", + output_filename: str = "fit", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -40,7 +40,7 @@ def subplot_fit_interferometer( Not used here (UV-plane residuals are scatter plots); kept for API consistency. """ - fig, axes = plt.subplots(2, 3, figsize=(21, 14)) + fig, axes = plt.subplots(2, 3, figsize=conf_subplot_figsize(2, 3)) axes = axes.flatten() uv = fit.dataset.uv_distances / 10**3.0 @@ -106,7 +106,7 @@ def subplot_fit_interferometer( def subplot_fit_interferometer_dirty_images( fit, output_path: Optional[str] = None, - output_filename: str = "subplot_fit_dirty_images", + output_filename: str = "fit_dirty_images", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -135,7 +135,7 @@ def subplot_fit_interferometer_dirty_images( residuals_symmetric_cmap Centre residual colour scale symmetrically around zero. """ - fig, axes = plt.subplots(2, 3, figsize=(21, 14)) + fig, axes = plt.subplots(2, 3, figsize=conf_subplot_figsize(2, 3)) axes = axes.flatten() plot_array( @@ -183,6 +183,7 @@ def subplot_fit_interferometer_dirty_images( use_log10=False, vmin=vmin_n, vmax=vmax_n, + cb_unit=r"$\sigma$", ) plot_array( fit.dirty_chi_squared_map, @@ -190,6 +191,7 @@ def subplot_fit_interferometer_dirty_images( title="Dirty Chi-Squared Map", colormap=colormap, use_log10=use_log10, + cb_unit=r"$\chi^2$", ) hide_unused_axes(axes) diff --git a/autoarray/inversion/plot/inversion_plots.py b/autoarray/inversion/plot/inversion_plots.py index 6b0d30ce..d91402a3 100644 --- a/autoarray/inversion/plot/inversion_plots.py +++ b/autoarray/inversion/plot/inversion_plots.py @@ -9,7 +9,7 @@ from autoarray.inversion.mappers.abstract import Mapper from autoarray.plot.array import plot_array -from autoarray.plot.utils import numpy_grid, numpy_lines, numpy_positions, subplot_save, hide_unused_axes +from autoarray.plot.utils import numpy_grid, numpy_lines, numpy_positions, subplot_save, hide_unused_axes, conf_subplot_figsize from autoarray.inversion.plot.mapper_plots import plot_mapper from autoarray.structures.arrays.uniform_2d import Array2D @@ -20,7 +20,7 @@ def subplot_of_mapper( inversion, mapper_index: int = 0, output_path: Optional[str] = None, - output_filename: str = "subplot_inversion", + output_filename: str = "inversion", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -53,7 +53,7 @@ def subplot_of_mapper( """ mapper = inversion.cls_list_from(cls=Mapper)[mapper_index] - fig, axes = plt.subplots(3, 4, figsize=(28, 21)) + fig, axes = plt.subplots(3, 4, figsize=conf_subplot_figsize(3, 4)) axes = axes.flatten() # panel 0: data subtracted @@ -226,7 +226,7 @@ def subplot_mappings( inversion, pixelization_index: int = 0, output_path: Optional[str] = None, - output_filename: str = "subplot_mappings", + output_filename: str = "mappings", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -273,7 +273,7 @@ def subplot_mappings( ) mapper.slim_indexes_for_pix_indexes(pix_indexes=pix_indexes) - fig, axes = plt.subplots(2, 2, figsize=(14, 14)) + fig, axes = plt.subplots(2, 2, figsize=conf_subplot_figsize(2, 2)) axes = axes.flatten() # panel 0: data subtracted diff --git a/autoarray/inversion/plot/mapper_plots.py b/autoarray/inversion/plot/mapper_plots.py index 6bddd862..ccafa037 100644 --- a/autoarray/inversion/plot/mapper_plots.py +++ b/autoarray/inversion/plot/mapper_plots.py @@ -5,7 +5,7 @@ from autoarray.plot.array import plot_array from autoarray.plot.inversion import plot_inversion_reconstruction -from autoarray.plot.utils import numpy_grid, numpy_lines, subplot_save +from autoarray.plot.utils import numpy_grid, numpy_lines, subplot_save, conf_subplot_figsize logger = logging.getLogger(__name__) @@ -77,7 +77,7 @@ def subplot_image_and_mapper( mapper, image, output_path: Optional[str] = None, - output_filename: str = "subplot_image_and_mapper", + output_filename: str = "image_and_mapper", output_format: str = "png", colormap=None, use_log10: bool = False, @@ -108,7 +108,7 @@ def subplot_image_and_mapper( lines Lines to overlay on both panels. """ - fig, axes = plt.subplots(1, 2, figsize=(14, 7)) + fig, axes = plt.subplots(1, 2, figsize=conf_subplot_figsize(1, 2)) plot_array( image, diff --git a/autoarray/plot/__init__.py b/autoarray/plot/__init__.py index 5035376c..a4847c12 100644 --- a/autoarray/plot/__init__.py +++ b/autoarray/plot/__init__.py @@ -28,6 +28,7 @@ def _set_backend(): apply_extent, apply_labels, conf_figsize, + conf_subplot_figsize, conf_mat_plot_fontsize, save_figure, subplot_save, diff --git a/autoarray/plot/array.py b/autoarray/plot/array.py index 227dcdea..775e24a2 100644 --- a/autoarray/plot/array.py +++ b/autoarray/plot/array.py @@ -59,7 +59,6 @@ def plot_array( output_path: Optional[str] = None, output_filename: str = "array", output_format: str = "png", - structure=None, ) -> None: """ Plot a 2D array (image) using ``plt.imshow``. @@ -120,9 +119,8 @@ def plot_array( """ # --- autoarray extraction -------------------------------------------------- array = zoom_array(array) + structure = array try: - if structure is None: - structure = array if extent is None: extent = array.geometry.extent if mask is None: diff --git a/autoarray/plot/utils.py b/autoarray/plot/utils.py index 0c39526e..f6dd11fd 100644 --- a/autoarray/plot/utils.py +++ b/autoarray/plot/utils.py @@ -362,6 +362,25 @@ def conf_figsize(context: str = "figures") -> Tuple[int, int]: return (7, 7) if context == "figures" else (19, 16) +def conf_subplot_figsize(rows: int, cols: int) -> Tuple[int, int]: + """Compute figsize for a subplot grid from config. + + Reads ``mat_plot/figure/subplot_shape_to_figsize_factor`` from + ``visualize/general.yaml`` (default ``(6, 6)``) and returns + ``(cols * fx, rows * fy)``. + """ + try: + from autoconf import conf + + raw = conf.instance["visualize"]["general"]["mat_plot"]["figure"][ + "subplot_shape_to_figsize_factor" + ] + fx, fy = _parse_figsize(raw) + except Exception: + fx, fy = 6, 6 + return (cols * fx, rows * fy) + + def apply_labels( ax: plt.Axes, title: str = "", @@ -376,13 +395,13 @@ def apply_labels( ``*_subplot`` keys (defaulting to the single-figure values / 10 for ticks). """ if is_subplot: - title_fs = conf_mat_plot_fontsize("title_subplot", default=conf_mat_plot_fontsize("title", default=16)) + title_fs = conf_mat_plot_fontsize("title_subplot", default=20) xlabel_fs = conf_mat_plot_fontsize("xlabel_subplot", default=conf_mat_plot_fontsize("xlabel", default=14)) ylabel_fs = conf_mat_plot_fontsize("ylabel_subplot", default=conf_mat_plot_fontsize("ylabel", default=14)) xticks_fs = conf_mat_plot_fontsize("xticks_subplot", default=18) yticks_fs = conf_mat_plot_fontsize("yticks_subplot", default=18) else: - title_fs = conf_mat_plot_fontsize("title", default=16) + title_fs = conf_mat_plot_fontsize("title", default=24) xlabel_fs = conf_mat_plot_fontsize("xlabel", default=14) ylabel_fs = conf_mat_plot_fontsize("ylabel", default=14) xticks_fs = conf_mat_plot_fontsize("xticks", default=12) @@ -424,9 +443,10 @@ def save_figure( dpi Resolution in dots per inch. structure - Optional autoarray structure (e.g. ``Array2D``). Required when - *format* is ``"fits"`` — its ``output_to_fits`` method is used - instead of ``fig.savefig``. + Optional autoarray structure (e.g. ``Array2D``). When *format* includes + ``"fits"`` and the structure has ``output_to_fits``, it is used instead + of ``fig.savefig``. Callers do not need to pass this; ``plot_array`` + supplies it automatically from the input array. """ if path: os.makedirs(path, exist_ok=True) @@ -558,18 +578,20 @@ def _apply_colorbar( ticks=tick_values, ) labelsize_key = "labelsize_subplot" if is_subplot else "labelsize" - labelsize_default = 22 if is_subplot else 22 - labelsize = float(_conf_colorbar(labelsize_key, labelsize_default)) + labelsize = float(_conf_colorbar(labelsize_key, 22)) + labelrotation = float(_conf_colorbar("labelrotation", 90)) if tick_values is not None: cb.ax.set_yticklabels( _colorbar_tick_labels(tick_values, cb_unit=cb_unit), va="center", fontsize=labelsize, ) - cb.ax.tick_params( - labelrotation=float(_conf_colorbar("labelrotation", 90)), - labelsize=labelsize, - ) + # tick_params stores the setting for ticks created during draw; + # axis='y' is explicit since colorbars are vertical. + cb.ax.tick_params(axis="y", labelsize=labelsize, labelrotation=labelrotation) + # Also drive it through the yaxis object directly so it survives + # any internal colorbar redraw that recreates tick Text objects. + cb.ax.yaxis.set_tick_params(labelsize=labelsize, labelrotation=labelrotation) def _apply_contours( @@ -649,7 +671,7 @@ def _apply_contours( if include_values: try: - cs.clabel(levels=levels, inline=True, fontsize=8) + cs.clabel(levels=levels, inline=True, fontsize=10, fmt="%.2g") except (ValueError, IndexError): pass except Exception: @@ -703,8 +725,8 @@ def _round_ticks(values: np.ndarray, sig: int = 2) -> np.ndarray: def _arcsec_labels(ticks) -> List[str]: - """Format tick values as arcsecond strings, e.g. ``-1"``, ``0"``, ``1"``.""" - return [f'{v:g}"' for v in ticks] + """Format tick values as coordinate strings (no unit symbol by default).""" + return [f'{v:g}' for v in ticks] def apply_extent(