Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions autolens/config/visualize/plots.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ fit_interferometer: # Settings for plots of fits to inter

point_dataset: # Settings for plots of point source datasets (e.g. PointDatasetPlotter).
subplot_dataset: true # Plot subplot containing all dataset quantities (e.g. the data, noise-map, etc.)?
image_with_points: true # Plot the observed image (if passed to AnalysisPoint) with the observed positions over it?
image_with_points: true # Plot the observed image (if passed to AnalysisPoint) with the observed positions over it (image_with_points.png)?

fit_point_dataset: # Settings for plots of fits to point source datasets (e.g. FitPointDatasetPlotter).
image_with_points: true # Plot the observed image (if passed to AnalysisPoint) with observed and model positions over it?
fit_image_with_points: true # Plot the observed image (if passed to AnalysisPoint) with observed and model positions and critical curves over it (fit_image_with_points.png)?

weak_dataset: # Settings for plots of weak lensing shear catalogues (e.g. PlotterWeak).
subplot_dataset: true # Plot subplot containing all dataset quantities (e.g. the shear field, noise-map, etc.)?
Expand Down
13 changes: 7 additions & 6 deletions autolens/point/model/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ def image_with_points(
"""
Output an observed image of the lensed point source with the point-source positions overlaid.

Before the fit (``fit=None``) only the observed positions are drawn, controlled by the
`point_dataset: image_with_points` setting. After the fit the model positions (and critical curves,
if given) are also drawn, controlled by the `fit_point_dataset: image_with_points` setting.
Before the fit (``fit=None``) only the observed positions are drawn, output as `image_with_points.png`
and controlled by the `point_dataset: image_with_points` setting. After the fit the model positions (and
critical curves, if given) are also drawn, output as `fit_image_with_points.png` (so both figures coexist)
and controlled by the `fit_point_dataset: fit_image_with_points` setting.

Parameters
----------
Expand All @@ -62,11 +63,11 @@ def image_with_points(
Colours for each image-plane line.
"""
if fit is None:
section = ["point_dataset"]
section, name = ["point_dataset"], "image_with_points"
else:
section = ["fit", "fit_point_dataset"]
section, name = ["fit", "fit_point_dataset"], "fit_image_with_points"

if not plot_setting(section=section, name="image_with_points"):
if not plot_setting(section=section, name=name):
return

plot_image_with_points(
Expand Down
4 changes: 3 additions & 1 deletion autolens/point/model/visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def visualize_before_fit(
plotter.dataset_point(dataset=analysis.dataset)

if getattr(analysis, "image", None) is not None:
# Dataset-only figure (observed positions, no model): `image_with_points.png`.
plotter.image_with_points(image=analysis.image, dataset=analysis.dataset)

@staticmethod
Expand Down Expand Up @@ -93,7 +94,8 @@ def visualize(
source_plane_line_colors=sp_colors,
)

# Output even on `quick_update`, so the observed image with model positions updates on-the-fly.
# Output even on `quick_update`, so the observed image with model positions updates on-the-fly. Saved as
# `fit_image_with_points.png`, so the dataset-only `image_with_points.png` from before the fit is kept.
if getattr(analysis, "image", None) is not None:
plotter.image_with_points(
image=analysis.image,
Expand Down
17 changes: 14 additions & 3 deletions autolens/point/plot/fit_point_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ def plot_image_with_points(
are drawn as red crosses (image-plane fits only, as a source-plane fit's model data lies in the source
plane), and critical curves can be overlaid via ``image_plane_lines``.

The function produces two figures, depending on whether a fit is passed:

- ``fit=None`` (dataset-only): only the observed image and observed positions are drawn, saved as
``image_with_points``. Use this to display the data before lens modeling, passing no fit and no
``image_plane_lines``.
- ``fit`` given: the model positions (and critical curves, via ``image_plane_lines``) are added, the title
becomes "<name> Fit Image With Points" and the figure is saved as ``fit_image_with_points``, so it does not
overwrite the dataset-only figure.

The image is used only for visualization: it does not enter the point-source likelihood.

Parameters
Expand All @@ -113,7 +122,8 @@ def plot_image_with_points(
dataset : PointDataset
The point-source dataset whose observed positions are overlaid.
fit : FitPointDataset, optional
If given, its model positions are overlaid as red crosses.
If given, its model positions are overlaid as red crosses and the figure is saved as
``fit_image_with_points``; if ``None`` it is the dataset-only ``image_with_points``.
output_path : str, optional
Directory in which to save the figure. If ``None`` the figure is
not saved to disk.
Expand All @@ -135,7 +145,7 @@ def plot_image_with_points(
ax=ax,
lines=image_plane_lines,
line_colors=image_plane_line_colors,
title=f"{_prefix}{dataset.name} Image With Points",
title=f"{_prefix}{dataset.name} {'Image' if fit is None else 'Fit Image'} With Points",
)

# Positions are (y,x) arc-seconds: reflect them exactly as `plot_array` does its own overlays, using the
Expand Down Expand Up @@ -165,4 +175,5 @@ def _yx(grid):

ax.legend(loc="upper right", fontsize=8, framealpha=0.8)

save_figure(fig, path=output_path, filename="image_with_points", format=output_format)
filename = "image_with_points" if fit is None else "fit_image_with_points"
save_figure(fig, path=output_path, filename=filename, format=output_format)
48 changes: 42 additions & 6 deletions test_autolens/point/model/test_plotter_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,44 @@ def test__image_with_points(fit_point_dataset_x2_plane, plot_path, plot_patch):
plotter.image_with_points(image=_image(), dataset=fit_point_dataset_x2_plane.dataset)

assert str(plot_path / "image_with_points.png") in plot_patch.paths
assert str(plot_path / "fit_image_with_points.png") not in plot_patch.paths


def test__fit_image_with_points(fit_point_dataset_x2_plane, plot_path, plot_patch):
if plot_path.exists():
shutil.rmtree(plot_path)

plotter = PlotterPoint(image_path=plot_path)

plotter.image_with_points(
image=_image(),
dataset=fit_point_dataset_x2_plane.dataset,
fit=fit_point_dataset_x2_plane,
)

assert str(plot_path / "fit_image_with_points.png") in plot_patch.paths
assert str(plot_path / "image_with_points.png") not in plot_patch.paths


def test__visualizer__before_fit__only_image_with_points(
fit_point_dataset_x2_plane, plot_path, plot_patch
):
from types import SimpleNamespace

from autolens.point.model.visualizer import VisualizerPoint

if plot_path.exists():
shutil.rmtree(plot_path)

analysis = SimpleNamespace(
dataset=fit_point_dataset_x2_plane.dataset, image=_image(), title_prefix=None
)
paths = SimpleNamespace(image_path=plot_path, output_path=plot_path)

VisualizerPoint.visualize_before_fit(analysis=analysis, paths=paths, model=None)

assert plot_patch.paths.count(str(plot_path / "image_with_points.png")) == 1
assert str(plot_path / "fit_image_with_points.png") not in plot_patch.paths


@pytest.mark.parametrize("quick_update", [False, True])
Expand All @@ -91,12 +129,9 @@ def test__visualizer__image_with_points_before_and_after_fit(
quick_update=quick_update,
)

image_with_points = [
path for path in plot_patch.paths if path == str(plot_path / "image_with_points.png")
]

# Once before the fit (observed positions) and once after (with model positions).
assert len(image_with_points) == 2
# The dataset-only figure before the fit and the fit figure after it are separate files, so both coexist.
assert plot_patch.paths.count(str(plot_path / "image_with_points.png")) == 1
assert plot_patch.paths.count(str(plot_path / "fit_image_with_points.png")) == 1


def test__visualizer__no_image__no_image_with_points(
Expand All @@ -111,3 +146,4 @@ def test__visualizer__no_image__no_image_with_points(

assert str(plot_path / "fit.png") in plot_patch.paths
assert str(plot_path / "image_with_points.png") not in plot_patch.paths
assert str(plot_path / "fit_image_with_points.png") not in plot_patch.paths
46 changes: 46 additions & 0 deletions test_autolens/point/plot/test_fit_point_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,53 @@ def test__plot_image_with_points(point_dataset, fit_point_dataset_x2_plane, plot
output_path=plot_path,
output_format="png",
)
assert str(plot_path / "fit_image_with_points.png") in plot_patch.paths
assert str(plot_path / "image_with_points.png") not in plot_patch.paths


def test__plot_image_with_points__dataset_only__no_model_points_or_lines(
point_dataset, plot_path, plot_patch, monkeypatch
):
import matplotlib.axes

import autolens as al
import autogalaxy.util.plot_utils as plot_utils

from autolens.point.plot.fit_point_plots import plot_image_with_points

scatter_labels = []
scatter = matplotlib.axes.Axes.scatter

def counting_scatter(self, *args, **kwargs):
scatter_labels.append(kwargs.get("label"))
return scatter(self, *args, **kwargs)

monkeypatch.setattr(matplotlib.axes.Axes, "scatter", counting_scatter)

plot_array_kwargs = []
plot_array = plot_utils.plot_array

def recording_plot_array(*args, **kwargs):
plot_array_kwargs.append(kwargs)
return plot_array(*args, **kwargs)

monkeypatch.setattr(plot_utils, "plot_array", recording_plot_array)

plot_image_with_points(
image=al.Array2D.ones(shape_native=(20, 20), pixel_scales=0.25),
dataset=point_dataset,
output_path=plot_path,
output_format="png",
)

assert str(plot_path / "image_with_points.png") in plot_patch.paths
assert str(plot_path / "fit_image_with_points.png") not in plot_patch.paths
assert scatter_labels.count("Observed") == 1
assert "Model" not in scatter_labels
assert len(plot_array_kwargs) == 1
assert plot_array_kwargs[0]["lines"] is None
assert plot_array_kwargs[0]["title"].endswith("Image With Points")
assert "Fit Image" not in plot_array_kwargs[0]["title"]


@pytest.mark.parametrize(
Expand Down
Loading