Skip to content

Commit 09fea4d

Browse files
authored
Merge pull request #412 from Jammy2211/feature/visualization_final
Visualization final: interferometer tracer, plot consolidation
2 parents 5beb6b9 + 16dcb2e commit 09fea4d

File tree

13 files changed

+214
-76
lines changed

13 files changed

+214
-76
lines changed

CLAUDE.md

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,44 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
99
pip install -e ".[dev]"
1010
```
1111

12-
### Run Tests
13-
```bash
14-
# All tests
15-
python -m pytest test_autolens/
12+
### Run Tests
13+
```bash
14+
# All tests
15+
python -m pytest test_autolens/
1616

1717
# Single test file
1818
python -m pytest test_autolens/lens/test_tracer.py
1919

20-
# With output
21-
python -m pytest test_autolens/imaging/test_fit_imaging.py -s
22-
```
23-
24-
### Codex / sandboxed runs
25-
26-
When running Python from Codex or any restricted environment, set writable cache directories so `numba` and `matplotlib` do not fail on unwritable home or source-tree paths:
27-
28-
```bash
29-
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python -m pytest test_autolens/
30-
```
31-
32-
This workspace is often imported from `/mnt/c/...` and Codex may not be able to write to module `__pycache__` directories or `/home/jammy/.cache`, which can cause import-time `numba` caching failures without this override.
33-
34-
### Formatting
35-
```bash
36-
black autolens/
20+
# With output
21+
python -m pytest test_autolens/imaging/test_fit_imaging.py -s
22+
```
23+
24+
### Codex / sandboxed runs
25+
26+
When running Python from Codex or any restricted environment, set writable cache directories so `numba` and `matplotlib` do not fail on unwritable home or source-tree paths:
27+
28+
```bash
29+
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python -m pytest test_autolens/
30+
```
31+
32+
This workspace is often imported from `/mnt/c/...` and Codex may not be able to write to module `__pycache__` directories or `/home/jammy/.cache`, which can cause import-time `numba` caching failures without this override.
33+
34+
### Formatting
35+
```bash
36+
black autolens/
37+
```
38+
39+
### Plot Output Mode
40+
41+
Set `PYAUTOARRAY_OUTPUT_MODE=1` to capture every figure produced by a script into numbered PNG files in `./output_mode/<script_name>/`. This is useful for visually inspecting all plots from an integration test without needing a display.
42+
43+
```bash
44+
PYAUTOARRAY_OUTPUT_MODE=1 python scripts/my_script.py
45+
# -> ./output_mode/my_script/0_fit.png, 1_tracer.png, ...
3746
```
3847

48+
When this env var is set, all `save_figure`, `subplot_save`, and `_save_subplot` calls are intercepted — the normal output path is bypassed and figures are written sequentially to the output_mode directory instead.
49+
3950
## Architecture
4051

4152
**PyAutoLens** is the gravitational lensing layer built on top of PyAutoGalaxy. It adds multi-plane ray-tracing, the `Tracer` object, and lensing-specific fit classes. It depends on:

autolens/analysis/plotter.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
from autolens.lens.tracer import Tracer
1212
from autolens.lens.plot.tracer_plots import (
13-
subplot_tracer,
1413
subplot_galaxies_images,
1514
fits_tracer,
1615
fits_source_plane_images,
1716
)
18-
from autoarray.plot.array import plot_array
17+
from autogalaxy.plot.plot_utils import plot_array
1918

2019

2120
class Plotter(AgPlotter):
@@ -67,18 +66,6 @@ def should_plot(name):
6766
output_path = str(self.image_path)
6867
fmt = self.fmt
6968

70-
if should_plot("subplot_tracer"):
71-
subplot_tracer(
72-
tracer=tracer,
73-
grid=grid,
74-
output_path=output_path,
75-
output_format=fmt,
76-
image_plane_lines=image_plane_lines,
77-
image_plane_line_colors=image_plane_line_colors,
78-
source_plane_lines=source_plane_lines,
79-
source_plane_line_colors=source_plane_line_colors,
80-
)
81-
8269
if should_plot("subplot_galaxies_images"):
8370
subplot_galaxies_images(
8471
tracer=tracer,

autolens/imaging/plot/fit_imaging_plots.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import autoarray as aa
77
import autogalaxy as ag
88

9-
from autoarray.plot.array import plot_array, _zoom_array_2d
9+
from autogalaxy.plot.plot_utils import plot_array
10+
from autoarray.plot.array import _zoom_array_2d
1011
from autoarray.plot.utils import save_figure, hide_unused_axes, conf_subplot_figsize
1112
from autoarray.plot.utils import numpy_lines as _to_lines
1213
from autoarray.inversion.mappers.abstract import Mapper
@@ -42,11 +43,11 @@ def _compute_critical_curve_lines(tracer, grid):
4243
_rad_ca_lines = _to_lines(list(rad_ca) if rad_ca is not None else []) or []
4344
image_plane_lines = (_tan_cc_lines + _rad_cc_lines) or None
4445
image_plane_line_colors = (
45-
["black"] * len(_tan_cc_lines) + ["white"] * len(_rad_cc_lines)
46+
["white"] * len(_tan_cc_lines) + ["yellow"] * len(_rad_cc_lines)
4647
)
4748
source_plane_lines = (_tan_ca_lines + _rad_ca_lines) or None
4849
source_plane_line_colors = (
49-
["black"] * len(_tan_ca_lines) + ["white"] * len(_rad_ca_lines)
50+
["white"] * len(_tan_ca_lines) + ["yellow"] * len(_rad_ca_lines)
5051
)
5152
return image_plane_lines, image_plane_line_colors, source_plane_lines, source_plane_line_colors
5253
except Exception:
@@ -134,9 +135,17 @@ def _plot_source_plane(fit, ax, plane_index, zoom_to_brightest=True,
134135
"""
135136
tracer = fit.tracer_linear_light_profiles_to_light_profiles
136137
if not tracer.planes[plane_index].has(cls=aa.Pixelization):
138+
if zoom_to_brightest:
139+
grid = fit.mask.derive_grid.all_false
140+
else:
141+
zoom = aa.Zoom2D(mask=fit.mask)
142+
grid = aa.Grid2D.from_extent(
143+
extent=zoom.extent_from(buffer=0),
144+
shape_native=zoom.shape_native,
145+
)
137146
image = plane_image_from(
138147
galaxies=tracer.planes[plane_index],
139-
grid=fit.mask.derive_grid.all_false,
148+
grid=grid,
140149
zoom_to_brightest=zoom_to_brightest,
141150
)
142151
plot_array(
@@ -713,6 +722,7 @@ def subplot_tracer_from_fit(
713722
else:
714723
axes_flat[1].axis("off")
715724

725+
716726
# Panel 2: Source Plane (No Zoom) (same as subplot_fit panel 12)
717727
_plot_source_plane(fit, axes_flat[2], final_plane_index, zoom_to_brightest=False,
718728
colormap=colormap, title="Source Plane (No Zoom)",
@@ -742,17 +752,14 @@ def subplot_tracer_from_fit(
742752

743753
# Panel 6: Deflections Y
744754
plot_array(array=deflections_y, ax=axes_flat[6], title="Deflections Y",
745-
lines=image_plane_lines, line_colors=image_plane_line_colors,
746755
colormap=colormap)
747756

748757
# Panel 7: Deflections X
749758
plot_array(array=deflections_x, ax=axes_flat[7], title="Deflections X",
750-
lines=image_plane_lines, line_colors=image_plane_line_colors,
751759
colormap=colormap)
752760

753761
# Panel 8: Magnification
754762
plot_array(array=magnification, ax=axes_flat[8], title="Magnification",
755-
lines=image_plane_lines, line_colors=image_plane_line_colors,
756763
colormap=colormap)
757764

758765
plt.tight_layout()

autolens/interferometer/model/plotter.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
subplot_fit,
1515
subplot_fit_dirty_images,
1616
subplot_fit_real_space,
17+
subplot_tracer_from_fit,
1718
_compute_critical_curve_lines,
1819
)
1920
from autolens.analysis.plotter import Plotter
@@ -59,10 +60,7 @@ def should_plot(name):
5960
# Use pre-computed critical curves if provided, otherwise compute once here.
6061
if image_plane_lines is None and source_plane_lines is None:
6162
tracer = fit.tracer_linear_light_profiles_to_light_profiles
62-
_zoom = aa.Zoom2D(mask=fit.dataset.real_space_mask)
63-
_cc_grid = aa.Grid2D.from_extent(
64-
extent=_zoom.extent_from(buffer=0), shape_native=_zoom.shape_native
65-
)
63+
_cc_grid = fit.dataset.real_space_mask.derive_grid.all_false
6664
ip_lines, ip_colors, sp_lines, sp_colors = _compute_critical_curve_lines(tracer, _cc_grid)
6765
else:
6866
ip_lines, ip_colors, sp_lines, sp_colors = (
@@ -77,6 +75,13 @@ def should_plot(name):
7775
source_plane_lines=sp_lines, source_plane_line_colors=sp_colors,
7876
)
7977

78+
if plot_setting(section="tracer", name="subplot_tracer"):
79+
subplot_tracer_from_fit(
80+
fit, output_path=output_path, output_format=fmt,
81+
image_plane_lines=ip_lines, image_plane_line_colors=ip_colors,
82+
source_plane_lines=sp_lines, source_plane_line_colors=sp_colors,
83+
)
84+
8085
if should_plot("subplot_fit_dirty_images") or quick_update:
8186
subplot_fit_dirty_images(
8287
fit, output_path=output_path, output_format=fmt,

autolens/interferometer/model/visualizer.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ def visualize(
101101
)
102102

103103
# Compute grid and critical curves once for all plot functions.
104-
zoom = ag.Zoom2D(mask=fit.dataset.real_space_mask)
105-
grid = ag.Grid2D.from_extent(
106-
extent=zoom.extent_from(buffer=0), shape_native=zoom.shape_native
107-
)
104+
grid = fit.dataset.real_space_mask.derive_grid.all_false
108105
ip_lines, ip_colors, sp_lines, sp_colors = _compute_critical_curve_lines(
109106
tracer, grid
110107
)

0 commit comments

Comments
 (0)