Skip to content

Commit ca82ad2

Browse files
committed
Complete plot refactor: remove all *Plotter classes, add standalone subplot functions
- Remove SubhaloPlotter from subhalo.py; replace with subplot_detection_imaging and subplot_detection_fits standalone functions in lens/plot/subhalo_plots.py - Remove SubhaloSensitivityPlotter from sensitivity.py; replace with subplot_tracer_images, subplot_sensitivity, subplot_figures_of_merit_grid standalone functions in lens/plot/sensitivity_plots.py - Delete autolens/plot/abstract_plotters.py (no longer needed) - Update autolens/plot/__init__.py: export only plot_array, plot_grid, wrap classes, and all subplot_* functions; remove all *Plotter class exports - Fix analysis/plotter_interface.py: replace aplt.Array2DPlotter usage in image_with_positions with standalone plot_array call - Add vmin/vmax params to plot_array in plot_utils.py for coordinated colormaps - Rename test files from test_*_plotters.py to test_*_plots.py - All 173 tests pass https://claude.ai/code/session_01CzJBy8KvFXiNchoNdk5i9k
1 parent e16ea95 commit ca82ad2

13 files changed

Lines changed: 311 additions & 572 deletions

File tree

autolens/analysis/plotter_interface.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77

88
import autoarray as aa
99
import autogalaxy as ag
10-
import autogalaxy.plot as aplt
1110

1211
from autogalaxy.analysis.plotter_interface import plot_setting
1312

1413
from autogalaxy.analysis.plotter_interface import PlotterInterface as AgPlotterInterface
1514

1615
from autolens.lens.tracer import Tracer
1716
from autolens.lens.plot.tracer_plots import subplot_galaxies_images
17+
from autolens.plot.plot_utils import plot_array
1818

1919

2020
class PlotterInterface(AgPlotterInterface):
@@ -145,20 +145,19 @@ def image_with_positions(self, image: aa.Array2D, positions: aa.Grid2DIrregular)
145145
def should_plot(name):
146146
return plot_setting(section=["positions"], name=name)
147147

148-
output = self.output_from()
149-
150-
if positions is not None:
148+
if positions is not None and should_plot("image_with_positions"):
151149
pos_arr = np.array(
152150
positions.array if hasattr(positions, "array") else positions
153151
)
154152

155-
image_plotter = aplt.Array2DPlotter(
153+
fmt = self.fmt
154+
if isinstance(fmt, (list, tuple)):
155+
fmt = fmt[0]
156+
157+
plot_array(
156158
array=image,
157-
output=output,
158159
positions=[pos_arr],
160+
output_path=str(self.image_path),
161+
output_filename="image_with_positions",
162+
output_format=fmt,
159163
)
160-
161-
image_plotter.set_filename("image_with_positions")
162-
163-
if should_plot("image_with_positions"):
164-
image_plotter.figure_2d()
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
"""Standalone subplot functions for subhalo sensitivity mapping visualisation."""
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
from typing import Optional
5+
6+
import autoarray as aa
7+
8+
from autolens.plot.plot_utils import plot_array, _save_subplot
9+
10+
11+
def subplot_tracer_images(
12+
mask,
13+
tracer_perturb,
14+
tracer_no_perturb,
15+
source_image,
16+
output_path: Optional[str] = None,
17+
output_format: str = "png",
18+
colormap: str = "jet",
19+
use_log10: bool = False,
20+
):
21+
"""6-panel subplot showing lensed images and residuals from a perturbed tracer."""
22+
from autolens.lens.tracer_util import critical_curves_from, caustics_from
23+
from autolens.plot.plot_utils import _to_lines
24+
25+
grid = aa.Grid2D.from_mask(mask=mask)
26+
27+
image = tracer_perturb.image_2d_from(grid=grid)
28+
lensed_source_image = tracer_perturb.image_2d_via_input_plane_image_from(
29+
grid=grid, plane_image=source_image
30+
)
31+
lensed_source_image_no_perturb = tracer_no_perturb.image_2d_via_input_plane_image_from(
32+
grid=grid, plane_image=source_image
33+
)
34+
35+
unmasked_grid = mask.derive_grid.unmasked
36+
37+
try:
38+
tan_cc_p, rad_cc_p = critical_curves_from(tracer=tracer_perturb, grid=unmasked_grid)
39+
perturb_cc_lines = _to_lines(list(tan_cc_p), list(rad_cc_p))
40+
except Exception:
41+
perturb_cc_lines = None
42+
43+
try:
44+
tan_ca_p, rad_ca_p = caustics_from(tracer=tracer_perturb, grid=unmasked_grid)
45+
perturb_ca_lines = _to_lines(list(tan_ca_p), list(rad_ca_p))
46+
except Exception:
47+
perturb_ca_lines = None
48+
49+
try:
50+
tan_cc_n, rad_cc_n = critical_curves_from(tracer=tracer_no_perturb, grid=unmasked_grid)
51+
no_perturb_cc_lines = _to_lines(list(tan_cc_n), list(rad_cc_n))
52+
except Exception:
53+
no_perturb_cc_lines = None
54+
55+
residual_map = lensed_source_image - lensed_source_image_no_perturb
56+
57+
fig, axes = plt.subplots(1, 6, figsize=(42, 7))
58+
59+
plot_array(array=image, ax=axes[0], title="Image",
60+
colormap=colormap, use_log10=use_log10)
61+
plot_array(array=lensed_source_image, ax=axes[1], title="Lensed Source Image",
62+
colormap=colormap, use_log10=use_log10, lines=perturb_cc_lines)
63+
plot_array(array=source_image, ax=axes[2], title="Source Image",
64+
colormap=colormap, use_log10=use_log10, lines=perturb_ca_lines)
65+
plot_array(array=tracer_perturb.convergence_2d_from(grid=grid), ax=axes[3],
66+
title="Convergence", colormap=colormap, use_log10=use_log10)
67+
plot_array(array=lensed_source_image, ax=axes[4],
68+
title="Lensed Source Image (No Subhalo)",
69+
colormap=colormap, use_log10=use_log10, lines=no_perturb_cc_lines)
70+
plot_array(array=residual_map, ax=axes[5],
71+
title="Residual Map (Subhalo - No Subhalo)",
72+
colormap=colormap, use_log10=use_log10, lines=no_perturb_cc_lines)
73+
74+
plt.tight_layout()
75+
_save_subplot(fig, output_path, "subplot_lensed_images", output_format)
76+
77+
78+
def subplot_sensitivity(
79+
result,
80+
data_subtracted,
81+
output_path: Optional[str] = None,
82+
output_format: str = "png",
83+
colormap: str = "jet",
84+
use_log10: bool = False,
85+
):
86+
"""8-panel sensitivity subplot: log-likelihood/evidence maps and above-threshold map."""
87+
log_likelihoods = result.figure_of_merit_array(
88+
use_log_evidences=False,
89+
remove_zeros=True,
90+
)
91+
92+
try:
93+
log_evidences = result.figure_of_merit_array(
94+
use_log_evidences=True,
95+
remove_zeros=True,
96+
)
97+
except TypeError:
98+
log_evidences = np.zeros_like(log_likelihoods)
99+
100+
above_threshold = np.where(log_likelihoods > 5.0, 1.0, 0.0)
101+
above_threshold = aa.Array2D(values=above_threshold, mask=log_likelihoods.mask)
102+
103+
fig, axes = plt.subplots(2, 4, figsize=(28, 14))
104+
axes_flat = list(axes.flatten())
105+
106+
plot_array(array=data_subtracted, ax=axes_flat[0], title="Subtracted Image",
107+
colormap=colormap, use_log10=use_log10)
108+
plot_array(array=log_evidences, ax=axes_flat[1], title="Increase in Log Evidence",
109+
colormap=colormap)
110+
plot_array(array=log_likelihoods, ax=axes_flat[2], title="Increase in Log Likelihood",
111+
colormap=colormap)
112+
plot_array(array=above_threshold, ax=axes_flat[3], title="Log Likelihood > 5.0",
113+
colormap=colormap)
114+
115+
ax_idx = 4
116+
try:
117+
log_evidences_base = result._array_2d_from(result.log_evidences_base)
118+
log_evidences_perturbed = result._array_2d_from(result.log_evidences_perturbed)
119+
120+
base_vals = np.asarray(log_evidences_base)
121+
perturb_vals = np.asarray(log_evidences_perturbed)
122+
finite_base = base_vals[np.isfinite(base_vals) & (base_vals != 0)]
123+
finite_perturb = perturb_vals[np.isfinite(perturb_vals) & (perturb_vals != 0)]
124+
if len(finite_base) > 0 and len(finite_perturb) > 0:
125+
vmin = float(np.min([np.min(finite_base), np.min(finite_perturb)]))
126+
vmax = float(np.max([np.max(finite_base), np.max(finite_perturb)]))
127+
else:
128+
vmin = vmax = None
129+
130+
plot_array(array=log_evidences_base, ax=axes_flat[ax_idx],
131+
title="Log Evidence Base", colormap=colormap, vmin=vmin, vmax=vmax)
132+
ax_idx += 1
133+
plot_array(array=log_evidences_perturbed, ax=axes_flat[ax_idx],
134+
title="Log Evidence Perturb", colormap=colormap, vmin=vmin, vmax=vmax)
135+
ax_idx += 1
136+
except (TypeError, AttributeError):
137+
pass
138+
139+
try:
140+
log_likelihoods_base = result._array_2d_from(result.log_likelihoods_base)
141+
log_likelihoods_perturbed = result._array_2d_from(result.log_likelihoods_perturbed)
142+
143+
base_vals = np.asarray(log_likelihoods_base)
144+
perturb_vals = np.asarray(log_likelihoods_perturbed)
145+
finite_base = base_vals[np.isfinite(base_vals) & (base_vals != 0)]
146+
finite_perturb = perturb_vals[np.isfinite(perturb_vals) & (perturb_vals != 0)]
147+
if len(finite_base) > 0 and len(finite_perturb) > 0:
148+
vmin = float(np.min([np.min(finite_base), np.min(finite_perturb)]))
149+
vmax = float(np.max([np.max(finite_base), np.max(finite_perturb)]))
150+
else:
151+
vmin = vmax = None
152+
153+
if ax_idx < len(axes_flat):
154+
plot_array(array=log_likelihoods_base, ax=axes_flat[ax_idx],
155+
title="Log Likelihood Base", colormap=colormap, vmin=vmin, vmax=vmax)
156+
ax_idx += 1
157+
if ax_idx < len(axes_flat):
158+
plot_array(array=log_likelihoods_perturbed, ax=axes_flat[ax_idx],
159+
title="Log Likelihood Perturb", colormap=colormap, vmin=vmin, vmax=vmax)
160+
except (TypeError, AttributeError):
161+
pass
162+
163+
plt.tight_layout()
164+
_save_subplot(fig, output_path, "subplot_sensitivity", output_format)
165+
166+
167+
def subplot_figures_of_merit_grid(
168+
result,
169+
output_path: Optional[str] = None,
170+
output_format: str = "png",
171+
colormap: str = "jet",
172+
use_log_evidences: bool = True,
173+
remove_zeros: bool = True,
174+
):
175+
"""Single-panel subplot: the figures-of-merit grid for sensitivity mapping."""
176+
figures_of_merit = result.figure_of_merit_array(
177+
use_log_evidences=use_log_evidences,
178+
remove_zeros=remove_zeros,
179+
)
180+
181+
fig, ax = plt.subplots(1, 1, figsize=(7, 7))
182+
plot_array(array=figures_of_merit, ax=ax, title="Increase in Log Evidence",
183+
colormap=colormap)
184+
plt.tight_layout()
185+
_save_subplot(fig, output_path, "sensitivity", output_format)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""Standalone subplot functions for subhalo detection visualisation."""
2+
import matplotlib.pyplot as plt
3+
from typing import Optional
4+
5+
from autolens.plot.plot_utils import plot_array, _save_subplot
6+
from autolens.imaging.plot.fit_imaging_plots import _plot_source_plane
7+
8+
9+
def subplot_detection_imaging(
10+
result,
11+
fit_imaging_with_subhalo,
12+
output_path: Optional[str] = None,
13+
output_format: str = "png",
14+
colormap: str = "jet",
15+
use_log10: bool = False,
16+
use_log_evidences: bool = True,
17+
relative_to_value: float = 0.0,
18+
remove_zeros: bool = False,
19+
):
20+
"""4-panel subplot: data, S/N map, log-evidence increase, subhalo mass grid."""
21+
fig, axes = plt.subplots(1, 4, figsize=(28, 7))
22+
23+
plot_array(
24+
array=fit_imaging_with_subhalo.data,
25+
ax=axes[0],
26+
title="Data",
27+
colormap=colormap,
28+
use_log10=use_log10,
29+
)
30+
plot_array(
31+
array=fit_imaging_with_subhalo.signal_to_noise_map,
32+
ax=axes[1],
33+
title="Signal-To-Noise Map",
34+
colormap=colormap,
35+
use_log10=use_log10,
36+
)
37+
38+
fom_array = result.figure_of_merit_array(
39+
use_log_evidences=use_log_evidences,
40+
relative_to_value=relative_to_value,
41+
remove_zeros=remove_zeros,
42+
)
43+
plot_array(
44+
array=fom_array,
45+
ax=axes[2],
46+
title="Increase in Log Evidence",
47+
colormap=colormap,
48+
)
49+
50+
mass_array = result.subhalo_mass_array
51+
plot_array(
52+
array=mass_array,
53+
ax=axes[3],
54+
title="Subhalo Mass",
55+
colormap=colormap,
56+
)
57+
58+
plt.tight_layout()
59+
_save_subplot(fig, output_path, "subplot_detection_imaging", output_format)
60+
61+
62+
def subplot_detection_fits(
63+
fit_imaging_no_subhalo,
64+
fit_imaging_with_subhalo,
65+
output_path: Optional[str] = None,
66+
output_format: str = "png",
67+
colormap: str = "jet",
68+
):
69+
"""6-panel subplot comparing fits with and without a subhalo."""
70+
fig, axes = plt.subplots(2, 3, figsize=(21, 14))
71+
72+
plot_array(
73+
array=fit_imaging_no_subhalo.normalized_residual_map,
74+
ax=axes[0][0],
75+
title="Normalized Residual Map (No Subhalo)",
76+
colormap=colormap,
77+
)
78+
plot_array(
79+
array=fit_imaging_no_subhalo.chi_squared_map,
80+
ax=axes[0][1],
81+
title="Chi-Squared Map (No Subhalo)",
82+
colormap=colormap,
83+
)
84+
_plot_source_plane(fit_imaging_no_subhalo, axes[0][2], plane_index=1,
85+
colormap=colormap)
86+
87+
plot_array(
88+
array=fit_imaging_with_subhalo.normalized_residual_map,
89+
ax=axes[1][0],
90+
title="Normalized Residual Map (With Subhalo)",
91+
colormap=colormap,
92+
)
93+
plot_array(
94+
array=fit_imaging_with_subhalo.chi_squared_map,
95+
ax=axes[1][1],
96+
title="Chi-Squared Map (With Subhalo)",
97+
colormap=colormap,
98+
)
99+
_plot_source_plane(fit_imaging_with_subhalo, axes[1][2], plane_index=1,
100+
colormap=colormap)
101+
102+
plt.tight_layout()
103+
_save_subplot(fig, output_path, "subplot_detection_fits", output_format)

0 commit comments

Comments
 (0)