Skip to content

Commit b0ce450

Browse files
Jammy2211claude
authored andcommitted
Plot improvements: DPI config, Delaunay aspect ratio, tick rounding, source vmax
- Add `dpi` key to `visualize/general.yaml` (default 150) so save_figure reads DPI from config rather than hardcoding 300 - Fix Delaunay source-plane aspect ratio to match rectangular: pass extent to _plot_delaunay and call ax.set_aspect(x_range/y_range, adjustable="box") - Fix tick-label 1e-16 noise: after rounding, clamp values < 1e-10 of scale to zero in _round_ticks so symmetric extents don't show scientific notation - Add vmin/vmax parameters to plot_mapper, forwarded to plot_inversion_reconstruction - In subplot_of_mapper, compute recon_vmax from the reconstructed image and pass to both source-plane panels so Zoom and No-Zoom share a colorbar scale Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a32e0de commit b0ce450

5 files changed

Lines changed: 42 additions & 9 deletions

File tree

autoarray/config/visualize/general.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
general:
22
backend: default # The matplotlib backend used for visualization. `default` uses the system default, can specify specific backend (e.g. TKAgg, Qt5Agg, WXAgg).
3+
dpi: 150 # Resolution in dots per inch used when saving figures. Lower values reduce file size (e.g. 150 gives ~50% smaller files than 300 with negligible quality loss for diagnostic subplots).
34
imshow_origin: upper # The `origin` input of `imshow`, determining if pixel values are ascending or descending on the y-axis.
45
log10_min_value: 1.0e-4 # If negative values are being plotted on a log10 scale, values below this value are rounded up to it (e.g. to remove negative values).
56
log10_max_value: 1.0e99 # If positive values are being plotted on a log10 scale, values above this value are rounded down to it.

autoarray/inversion/plot/inversion_plots.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,18 @@ def _recon_array():
116116

117117
# panels 4-5: source reconstruction zoomed / unzoomed
118118
pixel_values = inversion.reconstruction_dict[mapper]
119+
try:
120+
recon_vmax = float(np.max(np.asarray(_recon_array())))
121+
except Exception:
122+
recon_vmax = None
119123
plot_mapper(
120124
mapper,
121125
solution_vector=pixel_values,
122126
ax=axes[4],
123-
title="Source Reconstruction",
127+
title="Source Plane (Zoom)",
124128
colormap=colormap,
125129
use_log10=use_log10,
130+
vmax=recon_vmax,
126131
zoom_to_brightest=True,
127132
mesh_grid=mesh_grid,
128133
lines=lines,
@@ -131,9 +136,10 @@ def _recon_array():
131136
mapper,
132137
solution_vector=pixel_values,
133138
ax=axes[5],
134-
title="Source Reconstruction (Unzoomed)",
139+
title="Source Plane (No Zoom)",
135140
colormap=colormap,
136141
use_log10=use_log10,
142+
vmax=recon_vmax,
137143
zoom_to_brightest=False,
138144
mesh_grid=mesh_grid,
139145
lines=lines,
@@ -316,7 +322,7 @@ def subplot_mappings(
316322
mapper,
317323
solution_vector=pixel_values,
318324
ax=axes[2],
319-
title="Source Reconstruction",
325+
title="Source Plane (Zoom)",
320326
colormap=colormap,
321327
use_log10=use_log10,
322328
zoom_to_brightest=True,
@@ -327,7 +333,7 @@ def subplot_mappings(
327333
mapper,
328334
solution_vector=pixel_values,
329335
ax=axes[3],
330-
title="Source Reconstruction (Unzoomed)",
336+
title="Source Plane (No Zoom)",
331337
colormap=colormap,
332338
use_log10=use_log10,
333339
zoom_to_brightest=False,

autoarray/inversion/plot/mapper_plots.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def plot_mapper(
1818
output_format: str = "png",
1919
colormap=None,
2020
use_log10: bool = False,
21+
vmin=None,
22+
vmax=None,
2123
mesh_grid=None,
2224
lines=None,
2325
line_colors=None,
@@ -63,6 +65,8 @@ def plot_mapper(
6365
title=title,
6466
colormap=colormap,
6567
use_log10=use_log10,
68+
vmin=vmin,
69+
vmax=vmax,
6670
zoom_to_brightest=zoom_to_brightest,
6771
lines=numpy_lines(lines),
6872
line_colors=line_colors,

autoarray/plot/inversion.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def plot_inversion_reconstruction(
119119
elif isinstance(
120120
mapper.interpolator, (InterpolatorDelaunay, InterpolatorKNearestNeighbor)
121121
):
122-
_plot_delaunay(ax, pixel_values, mapper, norm, colormap, is_subplot=is_subplot)
122+
_plot_delaunay(ax, pixel_values, mapper, norm, colormap, extent, is_subplot=is_subplot)
123123

124124
# --- overlays --------------------------------------------------------------
125125
if lines is not None:
@@ -230,7 +230,7 @@ def _plot_rectangular(ax, pixel_values, mapper, norm, colormap, extent, is_subpl
230230
_apply_colorbar(im, ax, is_subplot=is_subplot)
231231

232232

233-
def _plot_delaunay(ax, pixel_values, mapper, norm, colormap, is_subplot=False):
233+
def _plot_delaunay(ax, pixel_values, mapper, norm, colormap, extent, is_subplot=False):
234234
"""Render a Delaunay or KNN pixelization reconstruction onto *ax*.
235235
236236
Uses ``ax.tripcolor`` with Gouraud shading so that the reconstructed
@@ -252,10 +252,19 @@ def _plot_delaunay(ax, pixel_values, mapper, norm, colormap, is_subplot=False):
252252
``None`` for automatic scaling.
253253
colormap
254254
Matplotlib colormap name.
255+
extent
256+
``[xmin, xmax, ymin, ymax]`` spatial extent; used to set the axes
257+
aspect ratio to match rectangular pixelization plots.
255258
is_subplot
256259
When ``True`` uses ``labelsize_subplot`` from config for the colorbar
257260
tick labels (matches the behaviour of :func:`~autoarray.plot.array.plot_array`).
258261
"""
262+
xmin, xmax, ymin, ymax = extent
263+
x_range = abs(xmax - xmin)
264+
y_range = abs(ymax - ymin)
265+
box_aspect = (x_range / y_range) if y_range > 0 else 1.0
266+
ax.set_aspect(box_aspect, adjustable="box")
267+
259268
mesh_grid = mapper.source_plane_mesh_grid
260269

261270
if hasattr(mesh_grid, "array"):

autoarray/plot/utils.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def save_figure(
419419
path: str,
420420
filename: str,
421421
format: str = "png",
422-
dpi: int = 300,
422+
dpi: Optional[int] = None,
423423
structure=None,
424424
) -> None:
425425
"""
@@ -448,6 +448,10 @@ def save_figure(
448448
of ``fig.savefig``. Callers do not need to pass this; ``plot_array``
449449
supplies it automatically from the input array.
450450
"""
451+
if dpi is None:
452+
from autoconf import conf
453+
dpi = int(conf.instance["visualize"]["general"]["general"]["dpi"])
454+
451455
if path:
452456
os.makedirs(path, exist_ok=True)
453457
formats = format if isinstance(format, (list, tuple)) else [format]
@@ -717,11 +721,20 @@ def _inward_ticks(lo: float, hi: float, factor: float, n: int) -> np.ndarray:
717721

718722

719723
def _round_ticks(values: np.ndarray, sig: int = 2) -> np.ndarray:
720-
"""Round *values* to *sig* significant figures."""
724+
"""Round *values* to *sig* significant figures.
725+
726+
After rounding, values smaller than 1e-10 of the overall tick scale are
727+
clamped to zero so that floating-point noise (e.g. 1e-16 centre ticks on
728+
symmetric extents) does not appear as scientific notation in labels.
729+
"""
721730
with np.errstate(divide="ignore", invalid="ignore"):
722731
nonzero = np.where(values != 0, np.abs(values), 1.0)
723732
mags = np.where(values != 0, 10 ** (sig - 1 - np.floor(np.log10(nonzero))), 1.0)
724-
return np.round(values * mags) / mags
733+
rounded = np.round(values * mags) / mags
734+
scale = float(np.max(np.abs(rounded))) if len(rounded) > 0 else 1.0
735+
if scale > 0:
736+
rounded[np.abs(rounded) < scale * 1e-10] = 0.0
737+
return rounded
725738

726739

727740
def _arcsec_labels(ticks) -> List[str]:

0 commit comments

Comments
 (0)