From af862c36a01542b543cf63c1fdd8fd8f8121192a Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Wed, 25 Mar 2026 19:53:07 +0000 Subject: [PATCH 1/4] Refactor unit tests for granularity, clarity and parametrize coverage - Split omnibus tests into focused single-scenario tests throughout test_fit_imaging.py, test_tracer.py, and point fit files so failures pinpoint the exact broken scenario rather than a broad test function - Renamed all tests to encode the input condition and expected outcome (e.g. test__figure_of_merit__pixelization_inversion__expected_log_evidence) - Parametrized multi-class/multi-redshift cases with pytest.mark.parametrize: FitPointDataset position fitting classes, plane_index_via_redshift_from, extract_plane_index_of_profile, and upper_plane_index_with_light_profile - Added coverage for new plotting functions lacking any tests: subplot_fit_x1_plane, subplot_fit_log10_x1_plane, subplot_tracer_from_fit, subplot_fit_combined, subplot_fit_combined_log10, save_tracer_fits, save_source_plane_images_fits - All numerical assertions preserved exactly unchanged Co-Authored-By: Claude Sonnet 4.6 --- .../imaging/plot/test_fit_imaging_plots.py | 92 +- test_autolens/imaging/test_fit_imaging.py | 2010 +++++++++-------- test_autolens/lens/plot/test_tracer_plots.py | 32 +- test_autolens/lens/test_tracer.py | 1971 ++++++++-------- .../fit/positions/image/test_abstract.py | 133 +- .../point/fit/positions/image/test_pair.py | 54 +- .../fit/positions/image/test_pair_all.py | 228 +- .../fit/positions/image/test_pair_repeat.py | 89 +- .../fit/positions/source/test_separations.py | 155 +- test_autolens/point/fit/test_fit_dataset.py | 235 +- test_autolens/point/fit/test_fluxes.py | 102 +- 11 files changed, 2783 insertions(+), 2318 deletions(-) diff --git a/test_autolens/imaging/plot/test_fit_imaging_plots.py b/test_autolens/imaging/plot/test_fit_imaging_plots.py index ae8df649f..71db64582 100644 --- a/test_autolens/imaging/plot/test_fit_imaging_plots.py +++ b/test_autolens/imaging/plot/test_fit_imaging_plots.py @@ -5,7 +5,12 @@ from autolens.imaging.plot.fit_imaging_plots import ( subplot_fit, subplot_fit_log10, + subplot_fit_x1_plane, + subplot_fit_log10_x1_plane, subplot_of_planes, + subplot_tracer_from_fit, + subplot_fit_combined, + subplot_fit_combined_log10, ) directory = path.dirname(path.realpath(__file__)) @@ -18,7 +23,7 @@ def make_fit_imaging_plotter_setup(): ) -def test_subplot_fit_is_output( +def test__subplot_fit__two_plane_tracer__output_file_created( fit_imaging_x2_plane_7x7, plot_path, plot_patch ): subplot_fit( @@ -29,7 +34,29 @@ def test_subplot_fit_is_output( assert path.join(plot_path, "subplot_fit.png") in plot_patch.paths -def test_subplot_fit_log10_is_output( +def test__subplot_fit__single_plane_tracer__delegates_to_x1_plane_and_creates_file( + fit_imaging_x1_plane_7x7, plot_path, plot_patch +): + subplot_fit( + fit=fit_imaging_x1_plane_7x7, + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_fit_x1_plane.png") in plot_patch.paths + + +def test__subplot_fit_x1_plane__single_plane_tracer__output_file_created( + fit_imaging_x1_plane_7x7, plot_path, plot_patch +): + subplot_fit_x1_plane( + fit=fit_imaging_x1_plane_7x7, + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_fit_x1_plane.png") in plot_patch.paths + + +def test__subplot_fit_log10__two_plane_tracer__output_file_created( fit_imaging_x2_plane_7x7, plot_path, plot_patch ): subplot_fit_log10( @@ -40,7 +67,29 @@ def test_subplot_fit_log10_is_output( assert path.join(plot_path, "subplot_fit_log10.png") in plot_patch.paths -def test__subplot_of_planes( +def test__subplot_fit_log10__single_plane_tracer__delegates_to_x1_plane_and_creates_file( + fit_imaging_x1_plane_7x7, plot_path, plot_patch +): + subplot_fit_log10( + fit=fit_imaging_x1_plane_7x7, + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_fit_log10.png") in plot_patch.paths + + +def test__subplot_fit_log10_x1_plane__single_plane_tracer__output_file_created( + fit_imaging_x1_plane_7x7, plot_path, plot_patch +): + subplot_fit_log10_x1_plane( + fit=fit_imaging_x1_plane_7x7, + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_fit_log10.png") in plot_patch.paths + + +def test__subplot_of_planes__no_plane_index_specified__all_plane_files_created( fit_imaging_x2_plane_7x7, plot_path, plot_patch ): subplot_of_planes( @@ -52,8 +101,10 @@ def test__subplot_of_planes( assert path.join(plot_path, "subplot_of_plane_0.png") in plot_patch.paths assert path.join(plot_path, "subplot_of_plane_1.png") in plot_patch.paths - plot_patch.paths = [] +def test__subplot_of_planes__plane_index_0_specified__only_plane_0_file_created( + fit_imaging_x2_plane_7x7, plot_path, plot_patch +): subplot_of_planes( fit=fit_imaging_x2_plane_7x7, output_path=plot_path, @@ -63,3 +114,36 @@ def test__subplot_of_planes( assert path.join(plot_path, "subplot_of_plane_0.png") in plot_patch.paths assert path.join(plot_path, "subplot_of_plane_1.png") not in plot_patch.paths + + +def test__subplot_tracer_from_fit__two_plane_tracer__output_file_created( + fit_imaging_x2_plane_7x7, plot_path, plot_patch +): + subplot_tracer_from_fit( + fit=fit_imaging_x2_plane_7x7, + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_tracer.png") in plot_patch.paths + + +def test__subplot_fit_combined__list_of_two_fits__output_file_created( + fit_imaging_x1_plane_7x7, fit_imaging_x2_plane_7x7, plot_path, plot_patch +): + subplot_fit_combined( + fit_list=[fit_imaging_x1_plane_7x7, fit_imaging_x2_plane_7x7], + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "subplot_fit_combined.png") in plot_patch.paths + + +def test__subplot_fit_combined_log10__list_of_two_fits__output_file_created( + fit_imaging_x1_plane_7x7, fit_imaging_x2_plane_7x7, plot_path, plot_patch +): + subplot_fit_combined_log10( + fit_list=[fit_imaging_x1_plane_7x7, fit_imaging_x2_plane_7x7], + output_path=plot_path, + output_format="png", + ) + assert path.join(plot_path, "fit_combined_log10.png") in plot_patch.paths diff --git a/test_autolens/imaging/test_fit_imaging.py b/test_autolens/imaging/test_fit_imaging.py index 118632baf..9544b7183 100644 --- a/test_autolens/imaging/test_fit_imaging.py +++ b/test_autolens/imaging/test_fit_imaging.py @@ -1,902 +1,1108 @@ -import copy -import numpy as np -import pytest - -import autolens as al - - -def test__model_image__with_and_without_psf_blurring( - masked_imaging_7x7_no_blur, masked_imaging_7x7 -): - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.m.MockLightProfile(image_2d_value=1.0, image_2d_first_value=2.0), - ) - tracer = al.Tracer(galaxies=[g0]) - - fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) - - assert fit.model_data.slim == pytest.approx( - np.array([2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]), 1.0e-4 - ) - assert fit.log_likelihood == pytest.approx(-14.6337, 1.0e-4) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.model_data.slim == pytest.approx( - np.array([1.33, 1.16, 1.0, 1.16, 1.0, 1.0, 1.0, 1.0, 1.0]), 1.0e-1 - ) - assert fit.log_likelihood == pytest.approx(-14.52960, 1.0e-4) - - - -def test__fit_figure_of_merit(masked_imaging_7x7, masked_imaging_covariance_7x7): - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-648.4814555620, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), - ] - ) - - g0 = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0) - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-648.4814555620, 1.0e-4) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - g0 = al.Galaxy(redshift=0.5, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), g0]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-22.9122020414322, 1.0e-4) - - galaxy_light = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[galaxy_light, galaxy_pix]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-29.2344033729098, 1.0e-4) - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), - disk=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - tracer = al.Tracer(galaxies=[g0_linear, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-16.9731347648, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), - al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), - ] - ) - - g0_linear = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0) - ) - - tracer = al.Tracer(galaxies=[g0_linear, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-16.97313476, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), - al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), - ], - regularization=al.reg.Constant(coefficient=1.0), - ) - - g0_basis = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) - ) - - tracer = al.Tracer(galaxies=[g0_basis, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-51.0835080747, 1.0e-4) - - tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-22.801816971, 1.0e-4) - - g0_operated = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1_operated = al.Galaxy(redshift=1.0, bulge=al.lp_operated.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0_operated, g1_operated]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-745.25961066, 1.0e-4) - - g0_linear_operated = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear_operated.Sersic(centre=(0.05, 0.05), sersic_index=1.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1_linear_operated = al.Galaxy( - redshift=1.0, bulge=al.lp_linear_operated.Sersic(centre=(0.05, 0.05), sersic_index=4.0) - ) - - tracer = al.Tracer(galaxies=[g0_linear_operated, g1_linear_operated]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-14.933306470, 1.0e-4) - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_covariance_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-775.003133428, 1.0e-4) - - -def test__fit_figure_of_merit__sub_2(image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7, masked_imaging_covariance_7x7): - - dataset = al.Imaging( - data=image_7x7, - psf=psf_3x3, - noise_map=noise_map_7x7, - over_sample_size_lp=2, - ) - - masked_imaging_7x7 = dataset.apply_mask( - mask=mask_2d_7x7 - ) - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - disk=al.lp.Sersic(intensity=2.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-41.60614104506, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp.Sersic(intensity=1.0), - al.lp.Sersic(intensity=2.0), - ] - ) - - g0 = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-41.60614104506277, 1.0e-4) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - g0 = al.Galaxy(redshift=0.5, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), g0]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-22.912202041432, 1.0e-4) - - galaxy_light = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[galaxy_light, galaxy_pix]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-23.040374194334518, 1.0e-4) - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(sersic_index=1.0), - disk=al.lp_linear.Sersic(sersic_index=4.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - tracer = al.Tracer(galaxies=[g0_linear, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-18.47282483, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp_linear.Sersic(sersic_index=1.0), - al.lp_linear.Sersic(sersic_index=4.0), - ] - ) - - g0_linear = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) - ) - - tracer = al.Tracer(galaxies=[g0_linear, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-18.4728248395, 1.0e-4) - - basis = al.lp_basis.Basis( - profile_list=[ - al.lp_linear.Sersic(sersic_index=1.0), - al.lp_linear.Sersic(sersic_index=4.0), - ], - regularization=al.reg.Constant(coefficient=1.0), - ) - - g0_basis = al.Galaxy( - redshift=0.5, bulge=basis, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) - ) - - tracer = al.Tracer(galaxies=[g0_basis, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-27.8563999226980, 1.0e-4) - - tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx( -22.8051006673, 1.0e-4) - - g0_operated = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - g1_operated = al.Galaxy(redshift=1.0, bulge=al.lp_operated.Sersic(intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0_operated, g1_operated]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-51.32884812, 1.0e-4) - - g0_linear_operated = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear_operated.Sersic(sersic_index=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - g1_linear_operated = al.Galaxy( - redshift=1.0, bulge=al.lp_linear_operated.Sersic(sersic_index=4.0) - ) - - tracer = al.Tracer(galaxies=[g0_linear_operated, g1_linear_operated]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.perform_inversion is True - assert fit.figure_of_merit == pytest.approx(-14.532352248, 1.0e-4) - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_covariance_7x7, tracer=tracer) - - assert fit.perform_inversion is False - assert fit.figure_of_merit == pytest.approx(-775.0031334280, 1.0e-4) - - -def test__fit__sky___handles_special_behaviour(masked_imaging_7x7): - masked_imaging_7x7 = copy.copy(masked_imaging_7x7) - - masked_imaging_7x7.data -= 100.0 - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging( - dataset=masked_imaging_7x7, tracer=tracer, dataset_model=al.DatasetModel(background_sky_level=5.0) - ) - - assert fit.figure_of_merit == pytest.approx(-18050.8847818, 1.0e-4) - - -def test__fit__model_dataset__grid_offset__handles_special_behaviour(masked_imaging_7x7): - - # Numerical value changes slightly due to prevision in grid values - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(-1.05, -2.05), intensity=1.0), - disk=al.lp.Sersic(centre=(-1.05, -2.05), intensity=2.0), - mass_profile=al.mp.IsothermalSph(centre=(-1.05, -2.05), einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, - bulge=al.lp.Sersic(centre=(-1.05, -2.05), intensity=1.0) - ) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging( - dataset=masked_imaging_7x7, - tracer=tracer, - dataset_model=al.DatasetModel(grid_offset=(1.0, 2.0)) - ) - - assert fit.figure_of_merit == pytest.approx(-648.48145556, 1.0e-4) - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(centre=(-1.0, -2.0), sersic_index=1.0), - disk=al.lp_linear.Sersic(centre=(-1.0, -2.0), sersic_index=4.0), - mass_profile=al.mp.IsothermalSph(centre=(-1.0, -2.0), einstein_radius=1.0), - ) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer, - dataset_model=al.DatasetModel(grid_offset=(1.0, 2.0)) - ) - assert fit.figure_of_merit == pytest.approx(-22.8051006, 1.0e-4) - - -def test__galaxy_image_dict(masked_imaging_7x7): - - # Normal Light Profiles Only - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - g2 = al.Galaxy(redshift=1.0) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - image_2d_list = tracer.image_2d_list_from( - grid=masked_imaging_7x7.grids.lp, - ) - - assert fit.galaxy_image_dict[g0] == pytest.approx( - image_2d_list[0].array, 1.0e-4 - ) - assert fit.galaxy_image_dict[g1] == pytest.approx( - image_2d_list[1].array, 1.0e-4 - ) - assert (fit.galaxy_image_dict[g2] == np.zeros(9)).all() - - # Normal light + Linear Light PRofiles + Pixelization + Regularizaiton - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer( - galaxies=[g0, g0_linear, g2, galaxy_pix_0, galaxy_pix_1] - ) - - masked_imaging_7x7.data[0] = 3.0 - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.galaxy_image_dict[g0] == pytest.approx( - image_2d_list[0].array, 1.0e-4 - ) - - assert fit.galaxy_image_dict[g0_linear][4] == pytest.approx( - -27.926926, 1.0e-4 - ) - - assert fit.galaxy_image_dict[galaxy_pix_0][4] == pytest.approx( - 0.94954435552, 1.0e-4 - ) - assert fit.galaxy_image_dict[galaxy_pix_1][4] == pytest.approx( - 0.94954436798, 1.0e-4 - ) - assert (fit.galaxy_image_dict[g2] == np.zeros(9)).all() - - -def test__galaxy_model_image_dict(masked_imaging_7x7): - - # Normal Light Profiles Only - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - g2 = al.Galaxy(redshift=1.0) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - blurred_image_2d_list = tracer.blurred_image_2d_list_from( - grid=masked_imaging_7x7.grids.lp, - psf=masked_imaging_7x7.psf, - blurring_grid=masked_imaging_7x7.grids.blurring, - ) - - assert fit.galaxy_model_image_dict[g0] == pytest.approx( - blurred_image_2d_list[0].array, 1.0e-4 - ) - assert fit.galaxy_model_image_dict[g1] == pytest.approx( - blurred_image_2d_list[1].array, 1.0e-4 - ) - assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() - - assert fit.model_data.native == pytest.approx( - fit.galaxy_model_image_dict[g0].native.array + fit.galaxy_model_image_dict[g1].native.array, - 1.0e-4, - ) - - # Linear Light Profiles Only - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - g1_linear = al.Galaxy(redshift=1.0, bulge=al.lp_linear.Sersic()) - - tracer = al.Tracer(galaxies=[g0_linear, g1_linear, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.galaxy_model_image_dict[g0_linear][4] == pytest.approx( - -4.99645959e-01, 1.0e-2 - ) - assert fit.galaxy_model_image_dict[g1_linear][4] == pytest.approx( - 1.9986499980, 1.0e-2 - ) - assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() - - assert fit.model_data == pytest.approx( - fit.galaxy_model_image_dict[g0_linear].array + fit.galaxy_model_image_dict[g1_linear].array, - 1.0e-4, - ) - - # Pixelization + Regularizaiton only - - g0_no_light = al.Galaxy( - redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) - ) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[g0_no_light, galaxy_pix_0]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert (fit.galaxy_model_image_dict[g0_no_light].array == np.zeros(9)).all() - assert fit.galaxy_model_image_dict[galaxy_pix_0].array[4] == pytest.approx( - 1.259965886, 1.0e-4 - ) - - assert fit.model_data == pytest.approx( - fit.galaxy_model_image_dict[galaxy_pix_0].array, 1.0e-4 - ) - - # Normal light + Linear Light PRofiles + Pixelization + Regularizaiton - - galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer( - galaxies=[g0, g0_linear, g2, galaxy_pix_0, galaxy_pix_1] - ) - - masked_imaging_7x7.data[0] = 3.0 - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.galaxy_model_image_dict[g0] == pytest.approx( - blurred_image_2d_list[0].array, 1.0e-4 - ) - - assert fit.galaxy_model_image_dict[g0_linear][4] == pytest.approx( - -9.31143037, 1.0e-4 - ) - - assert fit.galaxy_model_image_dict[galaxy_pix_0][4] == pytest.approx( - 0.94918443, 1.0e-4 - ) - assert fit.galaxy_model_image_dict[galaxy_pix_1][4] == pytest.approx( - 0.94918442, 1.0e-4 - ) - assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() - - -def test__subtracted_image_of_galaxies_dict(masked_imaging_7x7): - - # 2 Planes with Summed Galaxies - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - ) - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) - g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - g0_image = g0.blurred_image_2d_from( - grid=masked_imaging_7x7.grids.lp, - blurring_grid=masked_imaging_7x7.grids.blurring, - psf=masked_imaging_7x7.psf - ) - - g1_image = g1.blurred_image_2d_from( - grid=masked_imaging_7x7.grids.lp, - blurring_grid=masked_imaging_7x7.grids.blurring, - psf=masked_imaging_7x7.psf - ) - - g2_image = g2.blurred_image_2d_from( - grid=masked_imaging_7x7.grids.lp, - blurring_grid=masked_imaging_7x7.grids.blurring, - psf=masked_imaging_7x7.psf - ) - - assert fit.subtracted_images_of_galaxies_dict[g0] == pytest.approx( - masked_imaging_7x7.data.array - g1_image.array - g2_image.array, 1.0e-4 - ) - assert fit.subtracted_images_of_galaxies_dict[g1] == pytest.approx( - masked_imaging_7x7.data.array - g0_image.array - g2_image.array, 1.0e-4 - ) - assert fit.subtracted_images_of_galaxies_dict[g2] == pytest.approx( - masked_imaging_7x7.data.array - g0_image.array - g1_image.array, 1.0e-4 - ) - - # 3 Planes - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) - g2 = al.Galaxy(redshift=2.0, bulge=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - blurred_image_2d_list = tracer.blurred_image_2d_list_from( - grid=masked_imaging_7x7.grids.lp, - psf=masked_imaging_7x7.psf, - blurring_grid=masked_imaging_7x7.grids.blurring, - ) - - assert fit.subtracted_images_of_galaxies_dict[g0] == pytest.approx( - masked_imaging_7x7.data.array - blurred_image_2d_list[1].array - blurred_image_2d_list[2].array, 1.0e-4 - ) - assert fit.subtracted_images_of_galaxies_dict[g1] == pytest.approx( - masked_imaging_7x7.data.array - blurred_image_2d_list[0].array - blurred_image_2d_list[2].array, 1.0e-4 - ) - assert fit.subtracted_images_of_galaxies_dict[g2] == pytest.approx( - masked_imaging_7x7.data.array - blurred_image_2d_list[0].array - blurred_image_2d_list[1].array, 1.0e-4 - ) - - -def test__model_images_of_planes_list(masked_imaging_7x7_sub_2): - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - g1_linear = al.Galaxy(redshift=0.75, bulge=al.lp_linear.Sersic()) - - pixelization = al.Pixelization( - mesh=al.mesh.RectangularUniform(shape=(3, 3)), - regularization=al.reg.Constant(coefficient=1.0), - ) - - galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) - galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - tracer = al.Tracer( - galaxies=[g0, g1_linear, galaxy_pix_0, galaxy_pix_1] - ) - - fit = al.FitImaging(dataset=masked_imaging_7x7_sub_2, tracer=tracer) - - assert fit.model_images_of_planes_list[0] == pytest.approx( - fit.galaxy_model_image_dict[g0].array, 1.0e-4 - ) - assert fit.model_images_of_planes_list[1] == pytest.approx( - fit.galaxy_model_image_dict[g1_linear].array, 1.0e-4 - ) - assert fit.model_images_of_planes_list[2] == pytest.approx( - fit.galaxy_model_image_dict[galaxy_pix_0].array - + fit.galaxy_model_image_dict[galaxy_pix_1].array, - 1.0e-4, - ) - - assert fit.model_images_of_planes_list[2][0] == pytest.approx(1.5614163282, 1.0e-4) - - -def test__subtracted_images_of_planes_list(masked_imaging_7x7_no_blur, masked_imaging_7x7_no_blur_sub_2): - - g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) - - g1 = al.Galaxy(redshift=0.75, bulge=al.lp.Sersic(intensity=2.0)) - - g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) - - assert fit.subtracted_images_of_planes_list[0].slim[0] == pytest.approx(0.200638, 1.0e-4) - assert fit.subtracted_images_of_planes_list[1].slim[0] == pytest.approx(0.360511, 1.0e-4) - assert fit.subtracted_images_of_planes_list[2].slim[0] == pytest.approx(0.520383, 1.0e-4) - - fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur_sub_2, tracer=tracer) - - assert fit.subtracted_images_of_planes_list[2].slim[0] == pytest.approx(0.475542485138, 1.0e-4) - - g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) - - g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) - - assert fit.subtracted_images_of_planes_list[0].slim[0] == pytest.approx(0.200638, 1.0e-4) - assert fit.subtracted_images_of_planes_list[1].slim[0] == pytest.approx(0.840127, 1.0e-4) - - -def test___unmasked_blurred_images(masked_imaging_7x7): - - g0 = al.Galaxy( - redshift=0.5, - bulge=al.lp.Sersic(intensity=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - - g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - blurred_images_of_planes = tracer.blurred_image_2d_list_from( - grid=masked_imaging_7x7.grids.lp, - psf=masked_imaging_7x7.psf, - blurring_grid=masked_imaging_7x7.grids.blurring, - ) - - unmasked_blurred_image = tracer.unmasked_blurred_image_2d_from( - grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf - ) - - assert (fit.unmasked_blurred_image == unmasked_blurred_image).all() - - unmasked_blurred_image_of_planes_list = tracer.unmasked_blurred_image_2d_list_from( - grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf - ) - - assert ( - unmasked_blurred_image_of_planes_list[0] - == fit.unmasked_blurred_image_of_planes_list[0] - ).all() - assert ( - unmasked_blurred_image_of_planes_list[1] - == fit.unmasked_blurred_image_of_planes_list[1] - ).all() - - -def test__tracer_linear_light_profiles_to_light_profiles(masked_imaging_7x7): - - g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) - - g0_linear = al.Galaxy( - redshift=0.5, - bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), - mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), - ) - - g1_linear = al.Galaxy(redshift=1.0, bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0)) - - - tracer = al.Tracer(galaxies=[g0, g0_linear, g1_linear]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.tracer.galaxies[0].bulge.intensity == pytest.approx(1.0, 1.0e-4) - - tracer = fit.tracer_linear_light_profiles_to_light_profiles - - assert tracer.galaxies[0].bulge.intensity == pytest.approx(1.0, 1.0e-4) - assert tracer.galaxies[1].bulge.intensity == pytest.approx(-5.830442986, 1.0e-4) - assert tracer.galaxies[2].bulge.intensity == pytest.approx(0.135755913, 1.0e-4) - - - -def test__total_mappers(masked_imaging_7x7): - - g0 = al.Galaxy(redshift=0.5) - - g1 = al.Galaxy(redshift=1.0) - - g2 = al.Galaxy(redshift=2.0) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.total_mappers == 0 - - pixelization = al.Pixelization(mesh=al.mesh.RectangularUniform()) - - g2 = al.Galaxy(redshift=2.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) - - assert fit.total_mappers == 1 - - g0 = al.Galaxy(redshift=0.5, pixelization=pixelization) - - g1 = al.Galaxy(redshift=1.0, pixelization=pixelization) - - g2 = al.Galaxy(redshift=2.0, pixelization=pixelization) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - fit = al.FitImaging( - dataset=masked_imaging_7x7, - tracer=tracer, - ) - - assert fit.total_mappers == 3 +import copy +import numpy as np +import pytest + +import autolens as al + + +def test__model_image__without_psf_blurring__slim_values_and_log_likelihood_correct( + masked_imaging_7x7_no_blur, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.m.MockLightProfile(image_2d_value=1.0, image_2d_first_value=2.0), + ) + tracer = al.Tracer(galaxies=[g0]) + + fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) + + assert fit.model_data.slim == pytest.approx( + np.array([2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]), 1.0e-4 + ) + assert fit.log_likelihood == pytest.approx(-14.6337, 1.0e-4) + + +def test__model_image__with_psf_blurring__blurred_slim_values_and_log_likelihood_correct( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.m.MockLightProfile(image_2d_value=1.0, image_2d_first_value=2.0), + ) + tracer = al.Tracer(galaxies=[g0]) + + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.model_data.slim == pytest.approx( + np.array([1.33, 1.16, 1.0, 1.16, 1.0, 1.0, 1.0, 1.0, 1.0]), 1.0e-1 + ) + assert fit.log_likelihood == pytest.approx(-14.52960, 1.0e-4) + + +def test__figure_of_merit__two_sersic_light_profiles__no_inversion(masked_imaging_7x7): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-648.4814555620, 1.0e-4) + + +def test__figure_of_merit__basis_profiles_no_inversion__same_result_as_standard_profiles( + masked_imaging_7x7, +): + basis = al.lp_basis.Basis( + profile_list=[ + al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), + ] + ) + g0 = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-648.4814555620, 1.0e-4) + + +def test__figure_of_merit__pixelization_inversion__expected_log_evidence( + masked_imaging_7x7, +): + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + g0 = al.Galaxy(redshift=0.5, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), g0]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-22.9122020414322, 1.0e-4) + + +def test__figure_of_merit__light_profile_with_pixelization_inversion__expected_log_evidence( + masked_imaging_7x7, +): + galaxy_light = al.Galaxy( + redshift=0.5, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0) + ) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[galaxy_light, galaxy_pix]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-29.2344033729098, 1.0e-4) + + +def test__figure_of_merit__linear_light_profiles__inversion__expected_log_evidence( + masked_imaging_7x7, +): + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + disk=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_linear, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-16.9731347648, 1.0e-4) + + +def test__figure_of_merit__linear_basis_profiles__inversion__expected_log_evidence( + masked_imaging_7x7, +): + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + ] + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_linear, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-16.97313476, 1.0e-4) + + +def test__figure_of_merit__linear_basis_with_regularization__inversion__expected_log_evidence( + masked_imaging_7x7, +): + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + ], + regularization=al.reg.Constant(coefficient=1.0), + ) + g0_basis = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_basis, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-51.0835080747, 1.0e-4) + + +def test__figure_of_merit__linear_profiles_with_pixelization__inversion__expected_log_evidence( + masked_imaging_7x7, +): + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + ] + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-22.801816971, 1.0e-4) + + +def test__figure_of_merit__operated_light_profiles__no_inversion__expected_log_likelihood( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy( + redshift=1.0, + bulge=al.lp_operated.Sersic(centre=(0.05, 0.05), intensity=1.0), + ) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-745.25961066, 1.0e-4) + + +def test__figure_of_merit__linear_operated_light_profiles__inversion__expected_log_evidence( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear_operated.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy( + redshift=1.0, + bulge=al.lp_linear_operated.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + ) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-14.933306470, 1.0e-4) + + +def test__figure_of_merit__covariance_noise_matrix__expected_log_likelihood( + masked_imaging_covariance_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_covariance_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-775.003133428, 1.0e-4) + + +# --- sub_2 oversampling variants --- + + +def test__figure_of_merit__sub_2_oversampling__two_sersic_profiles__no_inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(intensity=1.0), + disk=al.lp.Sersic(intensity=2.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-41.60614104506, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__basis_profiles__no_inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + basis = al.lp_basis.Basis( + profile_list=[ + al.lp.Sersic(intensity=1.0), + al.lp.Sersic(intensity=2.0), + ] + ) + g0 = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-41.60614104506277, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__pixelization_inversion__expected_log_evidence( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + g0 = al.Galaxy(redshift=0.5, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), g0]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-22.912202041432, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__light_with_pixelization__expected_log_evidence( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + galaxy_light = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[galaxy_light, galaxy_pix]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-23.040374194334518, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__linear_light_profiles__inversion__expected_log_evidence( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(sersic_index=1.0), + disk=al.lp_linear.Sersic(sersic_index=4.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_linear, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-18.47282483, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__linear_basis_profiles__inversion__expected_log_evidence( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(sersic_index=1.0), + al.lp_linear.Sersic(sersic_index=4.0), + ] + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_linear, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-18.4728248395, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__linear_basis_with_regularization__inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(sersic_index=1.0), + al.lp_linear.Sersic(sersic_index=4.0), + ], + regularization=al.reg.Constant(coefficient=1.0), + ) + g0_basis = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0_basis, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-27.8563999226980, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__linear_profiles_with_pixelization__inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + basis = al.lp_basis.Basis( + profile_list=[ + al.lp_linear.Sersic(sersic_index=1.0), + al.lp_linear.Sersic(sersic_index=4.0), + ] + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=basis, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-22.8051006673, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__operated_light_profiles__no_inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(intensity=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp_operated.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-51.32884812, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__linear_operated_profiles__inversion( + image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear_operated.Sersic(sersic_index=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy( + redshift=1.0, bulge=al.lp_linear_operated.Sersic(sersic_index=4.0) + ) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.perform_inversion is True + assert fit.figure_of_merit == pytest.approx(-14.532352248, 1.0e-4) + + +def test__figure_of_merit__sub_2_oversampling__covariance_noise_matrix__expected_log_likelihood( + masked_imaging_covariance_7x7, image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 +): + dataset = al.Imaging( + data=image_7x7, + psf=psf_3x3, + noise_map=noise_map_7x7, + over_sample_size_lp=2, + ) + masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) + + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_covariance_7x7, tracer=tracer) + + assert fit.perform_inversion is False + assert fit.figure_of_merit == pytest.approx(-775.0031334280, 1.0e-4) + + +def test__fit__sky__background_sky_level_subtracted_from_data__expected_log_likelihood( + masked_imaging_7x7, +): + masked_imaging_7x7 = copy.copy(masked_imaging_7x7) + masked_imaging_7x7.data -= 100.0 + + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + disk=al.lp.Sersic(centre=(0.05, 0.05), intensity=2.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging( + dataset=masked_imaging_7x7, + tracer=tracer, + dataset_model=al.DatasetModel(background_sky_level=5.0), + ) + + assert fit.figure_of_merit == pytest.approx(-18050.8847818, 1.0e-4) + + +def test__fit__grid_offset__shifts_model_to_match_offset_galaxy_positions__expected_log_likelihood( + masked_imaging_7x7, +): + # Numerical value changes slightly due to precision in grid values + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(-1.05, -2.05), intensity=1.0), + disk=al.lp.Sersic(centre=(-1.05, -2.05), intensity=2.0), + mass_profile=al.mp.IsothermalSph(centre=(-1.05, -2.05), einstein_radius=1.0), + ) + g1 = al.Galaxy( + redshift=1.0, bulge=al.lp.Sersic(centre=(-1.05, -2.05), intensity=1.0) + ) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging( + dataset=masked_imaging_7x7, + tracer=tracer, + dataset_model=al.DatasetModel(grid_offset=(1.0, 2.0)), + ) + + assert fit.figure_of_merit == pytest.approx(-648.48145556, 1.0e-4) + + +def test__fit__grid_offset__with_linear_profiles_and_pixelization__expected_log_evidence( + masked_imaging_7x7, +): + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(centre=(-1.0, -2.0), sersic_index=1.0), + disk=al.lp_linear.Sersic(centre=(-1.0, -2.0), sersic_index=4.0), + mass_profile=al.mp.IsothermalSph(centre=(-1.0, -2.0), einstein_radius=1.0), + ) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0_linear, galaxy_pix]) + fit = al.FitImaging( + dataset=masked_imaging_7x7, + tracer=tracer, + dataset_model=al.DatasetModel(grid_offset=(1.0, 2.0)), + ) + + assert fit.figure_of_merit == pytest.approx(-22.8051006, 1.0e-4) + + +def test__galaxy_image_dict__normal_light_profiles__images_match_individual_galaxy_images( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + g2 = al.Galaxy(redshift=1.0) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + image_2d_list = tracer.image_2d_list_from(grid=masked_imaging_7x7.grids.lp) + + assert fit.galaxy_image_dict[g0] == pytest.approx(image_2d_list[0].array, 1.0e-4) + assert fit.galaxy_image_dict[g1] == pytest.approx(image_2d_list[1].array, 1.0e-4) + assert (fit.galaxy_image_dict[g2] == np.zeros(9)).all() + + +def test__galaxy_image_dict__mixed_linear_and_pixelization__image_values_correct( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g2 = al.Galaxy(redshift=1.0) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) + galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0, g0_linear, g2, galaxy_pix_0, galaxy_pix_1]) + masked_imaging_7x7.data[0] = 3.0 + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + image_2d_list = al.Tracer( + galaxies=[ + al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ), + al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)), + al.Galaxy(redshift=1.0), + ] + ).image_2d_list_from(grid=masked_imaging_7x7.grids.lp) + + assert fit.galaxy_image_dict[g0] == pytest.approx(image_2d_list[0].array, 1.0e-4) + assert fit.galaxy_image_dict[g0_linear][4] == pytest.approx(-27.926926, 1.0e-4) + assert fit.galaxy_image_dict[galaxy_pix_0][4] == pytest.approx(0.94954435552, 1.0e-4) + assert fit.galaxy_image_dict[galaxy_pix_1][4] == pytest.approx(0.94954436798, 1.0e-4) + assert (fit.galaxy_image_dict[g2] == np.zeros(9)).all() + + +def test__galaxy_model_image_dict__normal_light_profiles__model_images_match_blurred_images( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)) + g2 = al.Galaxy(redshift=1.0) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + blurred_image_2d_list = tracer.blurred_image_2d_list_from( + grid=masked_imaging_7x7.grids.lp, + psf=masked_imaging_7x7.psf, + blurring_grid=masked_imaging_7x7.grids.blurring, + ) + + assert fit.galaxy_model_image_dict[g0] == pytest.approx( + blurred_image_2d_list[0].array, 1.0e-4 + ) + assert fit.galaxy_model_image_dict[g1] == pytest.approx( + blurred_image_2d_list[1].array, 1.0e-4 + ) + assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() + assert fit.model_data.native == pytest.approx( + fit.galaxy_model_image_dict[g0].native.array + + fit.galaxy_model_image_dict[g1].native.array, + 1.0e-4, + ) + + +def test__galaxy_model_image_dict__linear_light_profiles__model_images_sum_to_model_data( + masked_imaging_7x7, +): + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1_linear = al.Galaxy(redshift=1.0, bulge=al.lp_linear.Sersic()) + g2 = al.Galaxy(redshift=1.0) + + tracer = al.Tracer(galaxies=[g0_linear, g1_linear, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.galaxy_model_image_dict[g0_linear][4] == pytest.approx( + -4.99645959e-01, 1.0e-2 + ) + assert fit.galaxy_model_image_dict[g1_linear][4] == pytest.approx( + 1.9986499980, 1.0e-2 + ) + assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() + assert fit.model_data == pytest.approx( + fit.galaxy_model_image_dict[g0_linear].array + + fit.galaxy_model_image_dict[g1_linear].array, + 1.0e-4, + ) + + +def test__galaxy_model_image_dict__pixelization_only__reconstruction_image_sums_to_model_data( + masked_imaging_7x7, +): + g0_no_light = al.Galaxy( + redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0) + ) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0_no_light, galaxy_pix_0]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert (fit.galaxy_model_image_dict[g0_no_light].array == np.zeros(9)).all() + assert fit.galaxy_model_image_dict[galaxy_pix_0].array[4] == pytest.approx( + 1.259965886, 1.0e-4 + ) + assert fit.model_data == pytest.approx( + fit.galaxy_model_image_dict[galaxy_pix_0].array, 1.0e-4 + ) + + +def test__galaxy_model_image_dict__mixed_linear_and_pixelization__all_contributions_correct( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g2 = al.Galaxy(redshift=1.0) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) + galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0, g0_linear, g2, galaxy_pix_0, galaxy_pix_1]) + masked_imaging_7x7.data[0] = 3.0 + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + blurred_image_2d_list = al.Tracer( + galaxies=[ + al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ), + al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0)), + al.Galaxy(redshift=1.0), + ] + ).blurred_image_2d_list_from( + grid=masked_imaging_7x7.grids.lp, + psf=masked_imaging_7x7.psf, + blurring_grid=masked_imaging_7x7.grids.blurring, + ) + + assert fit.galaxy_model_image_dict[g0] == pytest.approx( + blurred_image_2d_list[0].array, 1.0e-4 + ) + assert fit.galaxy_model_image_dict[g0_linear][4] == pytest.approx(-9.31143037, 1.0e-4) + assert fit.galaxy_model_image_dict[galaxy_pix_0][4] == pytest.approx(0.94918443, 1.0e-4) + assert fit.galaxy_model_image_dict[galaxy_pix_1][4] == pytest.approx(0.94918442, 1.0e-4) + assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all() + + +def test__subtracted_image_of_galaxies_dict__single_plane_with_multiple_galaxies__each_subtraction_correct( + masked_imaging_7x7, +): + g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + g0_image = g0.blurred_image_2d_from( + grid=masked_imaging_7x7.grids.lp, + blurring_grid=masked_imaging_7x7.grids.blurring, + psf=masked_imaging_7x7.psf, + ) + g1_image = g1.blurred_image_2d_from( + grid=masked_imaging_7x7.grids.lp, + blurring_grid=masked_imaging_7x7.grids.blurring, + psf=masked_imaging_7x7.psf, + ) + g2_image = g2.blurred_image_2d_from( + grid=masked_imaging_7x7.grids.lp, + blurring_grid=masked_imaging_7x7.grids.blurring, + psf=masked_imaging_7x7.psf, + ) + + assert fit.subtracted_images_of_galaxies_dict[g0] == pytest.approx( + masked_imaging_7x7.data.array - g1_image.array - g2_image.array, 1.0e-4 + ) + assert fit.subtracted_images_of_galaxies_dict[g1] == pytest.approx( + masked_imaging_7x7.data.array - g0_image.array - g2_image.array, 1.0e-4 + ) + assert fit.subtracted_images_of_galaxies_dict[g2] == pytest.approx( + masked_imaging_7x7.data.array - g0_image.array - g1_image.array, 1.0e-4 + ) + + +def test__subtracted_image_of_galaxies_dict__three_planes_with_lensing__each_subtraction_correct( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(intensity=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=2.0, bulge=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + blurred_image_2d_list = tracer.blurred_image_2d_list_from( + grid=masked_imaging_7x7.grids.lp, + psf=masked_imaging_7x7.psf, + blurring_grid=masked_imaging_7x7.grids.blurring, + ) + + assert fit.subtracted_images_of_galaxies_dict[g0] == pytest.approx( + masked_imaging_7x7.data.array + - blurred_image_2d_list[1].array + - blurred_image_2d_list[2].array, + 1.0e-4, + ) + assert fit.subtracted_images_of_galaxies_dict[g1] == pytest.approx( + masked_imaging_7x7.data.array + - blurred_image_2d_list[0].array + - blurred_image_2d_list[2].array, + 1.0e-4, + ) + assert fit.subtracted_images_of_galaxies_dict[g2] == pytest.approx( + masked_imaging_7x7.data.array + - blurred_image_2d_list[0].array + - blurred_image_2d_list[1].array, + 1.0e-4, + ) + + +def test__model_images_of_planes_list__mixed_profiles__each_plane_image_matches_galaxy_contributions( + masked_imaging_7x7_sub_2, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(intensity=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1_linear = al.Galaxy(redshift=0.75, bulge=al.lp_linear.Sersic()) + pixelization = al.Pixelization( + mesh=al.mesh.RectangularUniform(shape=(3, 3)), + regularization=al.reg.Constant(coefficient=1.0), + ) + galaxy_pix_0 = al.Galaxy(redshift=1.0, pixelization=pixelization) + galaxy_pix_1 = al.Galaxy(redshift=1.0, pixelization=pixelization) + + tracer = al.Tracer(galaxies=[g0, g1_linear, galaxy_pix_0, galaxy_pix_1]) + fit = al.FitImaging(dataset=masked_imaging_7x7_sub_2, tracer=tracer) + + assert fit.model_images_of_planes_list[0] == pytest.approx( + fit.galaxy_model_image_dict[g0].array, 1.0e-4 + ) + assert fit.model_images_of_planes_list[1] == pytest.approx( + fit.galaxy_model_image_dict[g1_linear].array, 1.0e-4 + ) + assert fit.model_images_of_planes_list[2] == pytest.approx( + fit.galaxy_model_image_dict[galaxy_pix_0].array + + fit.galaxy_model_image_dict[galaxy_pix_1].array, + 1.0e-4, + ) + assert fit.model_images_of_planes_list[2][0] == pytest.approx(1.5614163282, 1.0e-4) + + +def test__subtracted_images_of_planes_list__three_distinct_redshift_planes__each_plane_subtraction_correct( + masked_imaging_7x7_no_blur, +): + g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy(redshift=0.75, bulge=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) + + assert fit.subtracted_images_of_planes_list[0].slim[0] == pytest.approx(0.200638, 1.0e-4) + assert fit.subtracted_images_of_planes_list[1].slim[0] == pytest.approx(0.360511, 1.0e-4) + assert fit.subtracted_images_of_planes_list[2].slim[0] == pytest.approx(0.520383, 1.0e-4) + + +def test__subtracted_images_of_planes_list__three_planes__sub_2_oversampling__subtraction_correct( + masked_imaging_7x7_no_blur_sub_2, +): + g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy(redshift=0.75, bulge=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur_sub_2, tracer=tracer) + + assert fit.subtracted_images_of_planes_list[2].slim[0] == pytest.approx( + 0.475542485138, 1.0e-4 + ) + + +def test__subtracted_images_of_planes_list__two_galaxies_at_same_redshift__subtraction_correct( + masked_imaging_7x7_no_blur, +): + g0 = al.Galaxy(redshift=0.5, bulge=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + fit = al.FitImaging(dataset=masked_imaging_7x7_no_blur, tracer=tracer) + + assert fit.subtracted_images_of_planes_list[0].slim[0] == pytest.approx(0.200638, 1.0e-4) + assert fit.subtracted_images_of_planes_list[1].slim[0] == pytest.approx(0.840127, 1.0e-4) + + +def test__unmasked_blurred_images__two_plane_tracer__unmasked_images_match_tracer_output( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, + bulge=al.lp.Sersic(intensity=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, bulge=al.lp.Sersic(intensity=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + unmasked_blurred_image = tracer.unmasked_blurred_image_2d_from( + grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf + ) + assert (fit.unmasked_blurred_image == unmasked_blurred_image).all() + + unmasked_blurred_image_of_planes_list = tracer.unmasked_blurred_image_2d_list_from( + grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf + ) + assert ( + unmasked_blurred_image_of_planes_list[0] + == fit.unmasked_blurred_image_of_planes_list[0] + ).all() + assert ( + unmasked_blurred_image_of_planes_list[1] + == fit.unmasked_blurred_image_of_planes_list[1] + ).all() + + +def test__tracer_linear_light_profiles_to_light_profiles__solved_intensities_replace_linear_profiles( + masked_imaging_7x7, +): + g0 = al.Galaxy( + redshift=0.5, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0) + ) + g0_linear = al.Galaxy( + redshift=0.5, + bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=1.0), + mass_profile=al.mp.IsothermalSph(centre=(0.05, 0.05), einstein_radius=1.0), + ) + g1_linear = al.Galaxy( + redshift=1.0, + bulge=al.lp_linear.Sersic(centre=(0.05, 0.05), sersic_index=4.0), + ) + + tracer = al.Tracer(galaxies=[g0, g0_linear, g1_linear]) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.tracer.galaxies[0].bulge.intensity == pytest.approx(1.0, 1.0e-4) + + tracer_converted = fit.tracer_linear_light_profiles_to_light_profiles + + assert tracer_converted.galaxies[0].bulge.intensity == pytest.approx(1.0, 1.0e-4) + assert tracer_converted.galaxies[1].bulge.intensity == pytest.approx( + -5.830442986, 1.0e-4 + ) + assert tracer_converted.galaxies[2].bulge.intensity == pytest.approx( + 0.135755913, 1.0e-4 + ) + + +def test__total_mappers__no_pixelization__returns_zero(masked_imaging_7x7): + tracer = al.Tracer( + galaxies=[ + al.Galaxy(redshift=0.5), + al.Galaxy(redshift=1.0), + al.Galaxy(redshift=2.0), + ] + ) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.total_mappers == 0 + + +def test__total_mappers__one_pixelization__returns_one(masked_imaging_7x7): + pixelization = al.Pixelization(mesh=al.mesh.RectangularUniform()) + tracer = al.Tracer( + galaxies=[ + al.Galaxy(redshift=0.5), + al.Galaxy(redshift=1.0), + al.Galaxy(redshift=2.0, pixelization=pixelization), + ] + ) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.total_mappers == 1 + + +def test__total_mappers__three_pixelizations_across_planes__returns_three( + masked_imaging_7x7, +): + pixelization = al.Pixelization(mesh=al.mesh.RectangularUniform()) + tracer = al.Tracer( + galaxies=[ + al.Galaxy(redshift=0.5, pixelization=pixelization), + al.Galaxy(redshift=1.0, pixelization=pixelization), + al.Galaxy(redshift=2.0, pixelization=pixelization), + ] + ) + fit = al.FitImaging(dataset=masked_imaging_7x7, tracer=tracer) + + assert fit.total_mappers == 3 diff --git a/test_autolens/lens/plot/test_tracer_plots.py b/test_autolens/lens/plot/test_tracer_plots.py index 9cd6ba2b3..cfa4cf9da 100644 --- a/test_autolens/lens/plot/test_tracer_plots.py +++ b/test_autolens/lens/plot/test_tracer_plots.py @@ -7,6 +7,8 @@ subplot_tracer, subplot_lensed_images, subplot_galaxies_images, + save_tracer_fits, + save_source_plane_images_fits, ) directory = path.dirname(path.realpath(__file__)) @@ -22,7 +24,9 @@ def make_tracer_plotter_setup(): ) -def test__subplot_tracer(tracer_x2_plane_7x7, grid_2d_7x7, plot_path, plot_patch): +def test__subplot_tracer__two_plane_tracer__output_file_created( + tracer_x2_plane_7x7, grid_2d_7x7, plot_path, plot_patch +): subplot_tracer( tracer=tracer_x2_plane_7x7, grid=grid_2d_7x7, @@ -32,7 +36,7 @@ def test__subplot_tracer(tracer_x2_plane_7x7, grid_2d_7x7, plot_path, plot_patch assert path.join(plot_path, "subplot_tracer.png") in plot_patch.paths -def test__subplot_galaxies_images( +def test__subplot_galaxies_images__two_plane_tracer__output_file_created( tracer_x2_plane_7x7, grid_2d_7x7, plot_path, plot_patch ): subplot_galaxies_images( @@ -44,7 +48,7 @@ def test__subplot_galaxies_images( assert path.join(plot_path, "subplot_galaxies_images.png") in plot_patch.paths -def test__subplot_lensed_images( +def test__subplot_lensed_images__two_plane_tracer__output_file_created( tracer_x2_plane_7x7, grid_2d_7x7, plot_path, plot_patch ): subplot_lensed_images( @@ -54,3 +58,25 @@ def test__subplot_lensed_images( output_format="png", ) assert path.join(plot_path, "subplot_lensed_images.png") in plot_patch.paths + + +def test__save_tracer_fits__two_plane_tracer__tracer_fits_file_written( + tracer_x2_plane_7x7, grid_2d_7x7, tmp_path +): + save_tracer_fits( + tracer=tracer_x2_plane_7x7, + grid=grid_2d_7x7, + output_path=tmp_path, + ) + assert (tmp_path / "tracer.fits").exists() + + +def test__save_source_plane_images_fits__two_plane_tracer__source_plane_fits_file_written( + tracer_x2_plane_7x7, grid_2d_7x7, tmp_path +): + save_source_plane_images_fits( + tracer=tracer_x2_plane_7x7, + grid=grid_2d_7x7, + output_path=tmp_path, + ) + assert (tmp_path / "source_plane_images.fits").exists() diff --git a/test_autolens/lens/test_tracer.py b/test_autolens/lens/test_tracer.py index 47f4de731..abca8c570 100644 --- a/test_autolens/lens/test_tracer.py +++ b/test_autolens/lens/test_tracer.py @@ -1,908 +1,1063 @@ -import numpy as np -import pytest -from os import path - -from autoconf.dictable import from_json, output_to_json -import autofit as af -import autolens as al - - -grid_simple = al.Grid2DIrregular(values=[(1.0, 2.0)]) - - -def test__has(): - gal_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) - gal_mp = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph()) - - tracer = al.Tracer(galaxies=[gal_mp, gal_mp]) - - assert tracer.has(cls=al.LightProfile) is False - - tracer = al.Tracer(galaxies=[gal_lp, gal_lp]) - - assert tracer.has(cls=al.LightProfile) is True - - tracer = al.Tracer(galaxies=[gal_lp, gal_mp]) - - assert tracer.has(cls=al.LightProfile) is True - - -def test__galaxies_ascending_redshift(grid_2d_7x7): - g0 = al.Galaxy(redshift=0.5) - g1 = al.Galaxy(redshift=0.5) - - tracer = al.Tracer(galaxies=[g0, g1]) - - assert tracer.galaxies_ascending_redshift == [g0, g1] - - g2 = al.Galaxy(redshift=1.0) - g3 = al.Galaxy(redshift=1.0) - - tracer = al.Tracer(galaxies=[g0, g1, g2, g3]) - - assert tracer.galaxies_ascending_redshift == [g0, g1, g2, g3] - - g4 = al.Galaxy(redshift=0.75) - g5 = al.Galaxy(redshift=1.5) - - tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5]) - - assert tracer.galaxies_ascending_redshift == [g0, g1, g4, g2, g3, g5] - - -def test__plane_redshifts(): - g1 = al.Galaxy(redshift=1) - g2 = al.Galaxy(redshift=2) - g3 = al.Galaxy(redshift=3) - - tracer = al.Tracer(galaxies=[g1, g2]) - - assert tracer.plane_redshifts == [1, 2] - - tracer = al.Tracer(galaxies=[g2, g2, g3, g1, g1]) - - assert tracer.plane_redshifts == [1, 2, 3] - - -def test__planes(): - g1 = al.Galaxy(redshift=1) - g2 = al.Galaxy(redshift=2) - g3 = al.Galaxy(redshift=3) - - tracer = al.Tracer(galaxies=[g1, g2]) - - assert tracer.planes == [[g1], [g2]] - - tracer = al.Tracer(galaxies=[g2, g2, g3, g1, g1]) - - assert tracer.planes == [[g1, g1], [g2, g2], [g3]] - - -def test__plane_index_via_redshift_from(): - - g1 = al.Galaxy(redshift=1) - g2 = al.Galaxy(redshift=2) - g3 = al.Galaxy(redshift=3) - - tracer = al.Tracer(galaxies=[g1, g2, g3]) - - assert tracer.plane_index_via_redshift_from(redshift=2.0) == 1 - assert tracer.plane_index_via_redshift_from(redshift=3.0) == 2 - assert tracer.plane_index_via_redshift_from(redshift=3.001) == None - - -def test__upper_plane_index_with_light_profile(): - g0 = al.Galaxy(redshift=0.5) - g1 = al.Galaxy(redshift=1.0) - g2 = al.Galaxy(redshift=2.0) - g3 = al.Galaxy(redshift=3.0) - - g0_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) - g1_lp = al.Galaxy(redshift=1.0, light_profile=al.LightProfile()) - g2_lp = al.Galaxy(redshift=2.0, light_profile=al.LightProfile()) - g3_lp = al.Galaxy(redshift=3.0, light_profile=al.LightProfile()) - - tracer = al.Tracer(galaxies=[g1_lp]) - - assert tracer.upper_plane_index_with_light_profile == 0 - - tracer = al.Tracer(galaxies=[g0, g1_lp]) - - assert tracer.upper_plane_index_with_light_profile == 1 - - tracer = al.Tracer(galaxies=[g0_lp, g1_lp, g2_lp]) - - assert tracer.upper_plane_index_with_light_profile == 2 - - tracer = al.Tracer(galaxies=[g0_lp, g1, g2, g3_lp]) - - assert tracer.upper_plane_index_with_light_profile == 3 - - tracer = al.Tracer(galaxies=[g0_lp, g1, g2_lp, g3]) - - assert tracer.upper_plane_index_with_light_profile == 2 - - -def test__traced_grid_2d_list_from(grid_2d_7x7, grid_2d_7x7_simple): - g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - - galaxies = [g0, g1, g2, g3, g4, g5] - - tracer = al.Tracer(galaxies=galaxies, cosmology=al.cosmo.Planck15()) - - traced_grid_list = tracer.traced_grid_2d_list_from( - grid=grid_simple, - ) - - assert traced_grid_list[0][0] == pytest.approx((1.0, 2.0), 1.0e-4) - assert traced_grid_list[1][0] == pytest.approx((0.58194284, 1.16388568), 1.0e-4) - assert traced_grid_list[2][0] == pytest.approx((0.22277247, 0.4455449), 1.0e-4) - assert traced_grid_list[3][0] == pytest.approx((-0.78885438, -1.57770876), 1.0e-4) - assert len(traced_grid_list) == 4 - - traced_grid_list = tracer.traced_grid_2d_list_from( - grid=grid_simple, plane_index_limit=1 - ) - - assert traced_grid_list[0][0] == pytest.approx((1.0, 2.0), 1.0e-4) - assert traced_grid_list[-1][0] == pytest.approx((0.58194284, 1.16388568), 1.0e-4) - assert len(traced_grid_list) == 2 - - -def test__grid_2d_at_redshift_from(grid_2d_7x7): - g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - - galaxies = [g0, g1, g2, g3, g4, g5] - - tracer = al.Tracer(galaxies=galaxies, cosmology=al.cosmo.Planck15()) - - galaxies_plus_extra = [g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=0.5)] - tracer_plus_extra = al.Tracer( - galaxies=galaxies_plus_extra, cosmology=al.cosmo.Planck15() - ) - grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) - - grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=0.5) - - assert grid_2d_list_from[1] == pytest.approx(grid_at_redshift.array, 1.0e-4) - assert grid_at_redshift[0] == pytest.approx((0.6273814, 1.2547628), 1.0e-4) - - galaxies_plus_extra = [g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=1.75)] - tracer_plus_extra = al.Tracer( - galaxies=galaxies_plus_extra, cosmology=al.cosmo.Planck15() - ) - grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) - - grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=1.75) - - assert grid_2d_list_from[2] == pytest.approx(grid_at_redshift.array, 1.0e-4) - assert grid_at_redshift[0] == pytest.approx((0.27331481161, 0.5466296232), 1.0e-4) - - galaxies_plus_extra = [g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=2.0)] - tracer_plus_extra = al.Tracer( - galaxies=galaxies_plus_extra, cosmology=al.cosmo.Planck15() - ) - grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) - - grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=2.0) - - assert grid_2d_list_from[2] == pytest.approx(grid_at_redshift.array, 1.0e-4) - assert grid_at_redshift[0] == pytest.approx((0.222772465, 0.445544931), 1.0e-4) - - -def test__image_2d_list_from(): - g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) - g1 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=2.0)) - g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - image_list = tracer.image_2d_list_from(grid=grid_simple) - - assert image_list[0][0] == pytest.approx(0.30276535, 1.0e-4) - assert len(image_list) == 1 - - g0 = al.Galaxy( - redshift=0.5, - light_profile=al.lp.Sersic(intensity=1.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - ) - g1 = al.Galaxy( - redshift=1.0, - light_profile=al.lp.Sersic(intensity=2.0), - mass_profile=al.mp.IsothermalSph(einstein_radius=2.0), - ) - g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - image_list = tracer.image_2d_list_from(grid=grid_simple) - - assert image_list[0][0] == pytest.approx(0.0504608, 1.0e-4) - assert image_list[1][0] == pytest.approx(0.2517025, 1.0e-4) - assert image_list[2][0] == pytest.approx(1.8611933, 1.0e-4) - assert len(image_list) == 3 - - -def test__image_2d_list_from__plane_without_light_profile_is_zeros( - grid_2d_7x7, -): - # Planes without light profiles give zeros - - g0 = al.Galaxy(redshift=0.1, light_profile=al.lp.Sersic(intensity=0.1)) - g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) - g2 = al.Galaxy(redshift=2.0) - - tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=al.cosmo.Planck15()) - - tracer_image_of_planes = tracer.image_2d_list_from(grid=grid_2d_7x7) - - assert tracer_image_of_planes[2].shape_native == (7, 7) - assert (tracer_image_of_planes[2].native == np.zeros((7, 7))).all() - - -def test__image_2d_from__operated_only_input(grid_2d_7x7, lp_0, lp_operated_0, mp_0): - galaxy_0 = al.Galaxy( - redshift=0.5, light=lp_0, light_operated=lp_operated_0, mass=mp_0 - ) - - galaxy_1 = al.Galaxy( - redshift=1.0, light_operated_0=lp_operated_0, light_operated_1=lp_operated_0 - ) - galaxy_2 = al.Galaxy(redshift=2.0) - - tracer = al.Tracer(galaxies=[galaxy_0, galaxy_1, galaxy_2]) - - image = tracer.image_2d_from(grid=grid_2d_7x7, operated_only=False) - - assert image[0] == pytest.approx(1.79362512, 1.0e-4) - assert image[1] == pytest.approx(2.93152589, 1.0e-4) - - -def test__image_2d_from__sum_of_individual_images(mask_2d_7x7): - grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) - - g0 = al.Galaxy( - redshift=0.1, - light_profile=al.lp.Sersic(intensity=0.1), - mass=al.mp.IsothermalSph(einstein_radius=1.0), - ) - g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) - - tracer = al.Tracer(galaxies=[g0, g1], cosmology=al.cosmo.Planck15()) - - traced_grid_2d_list = tracer.traced_grid_2d_list_from( - grid=al.Grid2DIrregular(grid_2d_7x7.over_sampled) - ) - - image = g0.image_2d_from(grid=traced_grid_2d_list[0]) + g1.image_2d_from( - grid=traced_grid_2d_list[1] - ) - - image = grid_2d_7x7.over_sampler.binned_array_2d_from(array=image) - - image_tracer = tracer.image_2d_from(grid=grid_2d_7x7) - - assert image.shape_native == (7, 7) - assert image == pytest.approx(image_tracer.array, 1.0e-4) - - -def test__image_2d_via_input_plane_image_from__with_foreground_planes(grid_2d_7x7): - plane_grid = al.Grid2D.uniform( - shape_native=(40, 40), pixel_scales=0.3, over_sample_size=1 - ) - - g0 = al.Galaxy( - redshift=0.5, - light_profile=al.lp.Sersic(intensity=1.0), - mass=al.mp.IsothermalSph(einstein_radius=0.2), - ) - g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=2.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - image_via_light_profile = tracer.image_2d_from(grid=grid_2d_7x7) - - plane_image = g1.image_2d_from(grid=plane_grid) - - image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( - grid=grid_2d_7x7, - plane_image=plane_image, - plane_index=-1, - include_other_planes=True, - ) - - assert image_via_light_profile[0] == pytest.approx( - image_via_input_plane_image[0], 1.0e-2 - ) - - -def test__image_2d_via_input_plane_image_from__without_foreground_planes( - grid_2d_7x7, -): - grid_2d_7x7 = al.Grid2D( - values=grid_2d_7x7, - mask=grid_2d_7x7.mask, - over_sample_size=2, - ) - - g0 = al.Galaxy( - redshift=0.5, - mass=al.mp.IsothermalSph(einstein_radius=0.2), - light_profile=al.lp.Sersic(intensity=1.0), - ) - g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=2.0)) - - tracer = al.Tracer(galaxies=[g0, g1]) - - image_via_light_profile = tracer.image_2d_list_from(grid=grid_2d_7x7)[-1] - - plane_grid = al.Grid2D.uniform(shape_native=(80, 80), pixel_scales=0.125) - - plane_image = g1.image_2d_from( - grid=plane_grid, - ) - - image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( - grid=grid_2d_7x7, - plane_image=plane_image, - plane_index=-1, - include_other_planes=False, - ) - - assert image_via_light_profile[0] == pytest.approx( - image_via_input_plane_image[0], 1.0e-2 - ) - - -def test__image_2d_via_input_plane_image_from__with_foreground_planes__multi_plane( - grid_2d_7x7, -): - plane_grid = al.Grid2D.uniform( - shape_native=(40, 40), pixel_scales=0.3, over_sample_size=1 - ) - - g0 = al.Galaxy( - redshift=0.5, - light_profile=al.lp.Sersic(intensity=1.0), - mass=al.mp.IsothermalSph(einstein_radius=0.2), - ) - g1 = al.Galaxy( - redshift=1.0, - light_profile=al.lp.Sersic(intensity=2.0), - mass=al.mp.IsothermalSph(einstein_radius=0.2), - ) - g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - image_via_light_profile = tracer.image_2d_from(grid=grid_2d_7x7) - - plane_image = g2.image_2d_from(grid=plane_grid) - - image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( - grid=grid_2d_7x7, - plane_image=plane_image, - plane_index=-1, - include_other_planes=True, - ) - - assert image_via_light_profile[0] == pytest.approx( - image_via_input_plane_image[0], 1.0e-2 - ) - - plane_image = g1.image_2d_from(grid=plane_grid) - - image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( - grid=grid_2d_7x7, - plane_image=plane_image, - plane_index=1, - include_other_planes=True, - ) - - assert image_via_light_profile[0] == pytest.approx( - image_via_input_plane_image[0], 1.0e-2 - ) - - -def test__padded_image_2d_from(grid_2d_7x7): - padded_grid = grid_2d_7x7.padded_grid_from(kernel_shape_native=(3, 3)) - - g0 = al.Galaxy(redshift=0.1, light_profile=al.lp.Sersic(intensity=0.1)) - g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) - g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=0.3)) - - padded_g0_image = g0.image_2d_from(grid=padded_grid) - - padded_g1_image = g1.image_2d_from(grid=padded_grid) - - padded_g2_image = g2.image_2d_from(grid=padded_grid) - - tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=al.cosmo.Planck15()) - - padded_tracer_image = tracer.padded_image_2d_from( - grid=grid_2d_7x7, psf_shape_2d=(3, 3) - ) - - assert padded_tracer_image.shape_native == (9, 9) - assert padded_tracer_image == pytest.approx( - padded_g0_image.array + padded_g1_image.array + padded_g2_image.array, 1.0e-4 - ) - - -def test__light_profile_snr__signal_to_noise_via_simulator_correct(): - background_sky_level = 10.0 - exposure_time = 300.0 - - grid = al.Grid2D.uniform(shape_native=(3, 3), pixel_scales=1.0) - - mass = al.mp.IsothermalSph(einstein_radius=1.0) - - sersic = al.lp_snr.Sersic(signal_to_noise_ratio=10.0, effective_radius=0.01) - - tracer = al.Tracer( - galaxies=[ - al.Galaxy(redshift=0.5, mass=mass), - al.Galaxy(redshift=1.0, light=sersic), - ] - ) - - kernel = al.Array2D.no_mask(values=[[1.0]], pixel_scales=1.0) - psf = al.Convolver(kernel=kernel) - - simulator = al.SimulatorImaging( - psf=psf, - exposure_time=exposure_time, - noise_seed=1, - background_sky_level=background_sky_level, - ) - - dataset = simulator.via_tracer_from(tracer=tracer, grid=grid) - - assert 8.0 < dataset.signal_to_noise_map.native[0, 1] < 12.0 - assert 8.0 < dataset.signal_to_noise_map.native[1, 0] < 12.0 - assert 8.0 < dataset.signal_to_noise_map.native[1, 2] < 12.0 - assert 8.0 < dataset.signal_to_noise_map.native[2, 1] < 12.0 - - -def test__galaxy_image_2d_dict_from(grid_2d_7x7, mask_2d_7x7): - grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) - - g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) - g1 = al.Galaxy( - redshift=0.5, - mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), - light_profile=al.lp.Sersic(intensity=2.0), - ) - - g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) - - g3 = al.Galaxy(redshift=1.0, light_profile=al.lp_operated.Gaussian(intensity=5.0)) - - g0_image = g0.image_2d_from(grid=grid_2d_7x7) - g1_image = g1.image_2d_from(grid=grid_2d_7x7) - g2_image = g2.image_2d_from(grid=grid_2d_7x7) - - tracer = al.Tracer(galaxies=[g3, g1, g0, g2], cosmology=al.cosmo.Planck15()) - - galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from(grid=grid_2d_7x7) - - assert (galaxy_image_2d_dict[g0] == g0_image).all() - assert (galaxy_image_2d_dict[g1] == g1_image).all() - assert (galaxy_image_2d_dict[g2] == g2_image).all() - assert galaxy_image_2d_dict[g3][0] == pytest.approx(4.429962294298565, 1.0e-4) - - galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from( - grid=grid_2d_7x7, operated_only=True - ) - - assert (galaxy_image_2d_dict[g0] == np.zeros(shape=(9,))).all() - assert (galaxy_image_2d_dict[g1] == np.zeros(shape=(9,))).all() - assert (galaxy_image_2d_dict[g2] == np.zeros(shape=(9,))).all() - assert galaxy_image_2d_dict[g3][0] == pytest.approx(4.429962294298565, 1.0e-4) - - galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from( - grid=grid_2d_7x7, operated_only=False - ) - - assert (galaxy_image_2d_dict[g0] == g0_image).all() - assert (galaxy_image_2d_dict[g1] == g1_image).all() - assert (galaxy_image_2d_dict[g2] == g2_image).all() - assert (galaxy_image_2d_dict[g3] == np.zeros(shape=(9,))).all() - assert galaxy_image_2d_dict[g2][0] == pytest.approx(0.5244575148617125, 1.0e-4) - - -def test__convergence_2d_from(grid_2d_7x7): - g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) - g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - convergence = tracer.convergence_2d_from(grid=grid_simple) - - assert convergence == pytest.approx(1.34164079, 1.0e-4) - - # No Galaxy with mass profile - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) - - assert ( - tracer.convergence_2d_from(grid=grid_2d_7x7).native == np.zeros(shape=(7, 7)) - ).all() - - -def test__potential_2d_from(grid_2d_7x7): - g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) - g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - potential = tracer.potential_2d_from(grid=grid_simple) - - assert potential == pytest.approx(13.4164078, 1.0e-4) - - # No Galaxy with mass profile - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) - - assert ( - tracer.potential_2d_from(grid=grid_2d_7x7).native == np.zeros(shape=(7, 7)) - ).all() - - -def test__time_delays_from(): - - grid = al.Grid2DIrregular(values=[(0.7, 0.5), (1.0, 1.0)]) - - mp = al.mp.Isothermal( - centre=(0.0, 0.0), ell_comps=(0.0, -0.111111), einstein_radius=2.0 - ) - - g0 = al.Galaxy(redshift=0.2, mass=mp) - g1 = al.Galaxy(redshift=0.7) - - tracer = al.Tracer(galaxies=[g0, g1]) - - time_delay = tracer.time_delays_from(grid=grid) - - assert time_delay == pytest.approx(np.array([8.52966247, -29.0176387]), 1.0e-4) - - -def test__deflections_of_planes_summed_from(grid_2d_7x7): - g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) - g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - deflections = tracer.deflections_of_planes_summed_from(grid=grid_simple) - - assert deflections[0] == pytest.approx((2.68328157, 5.36656315), 1.0e-4) - - # Single plane case - - g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - - tracer = al.Tracer(galaxies=[g0]) - - deflections = tracer.deflections_of_planes_summed_from(grid=grid_simple) - - assert deflections[0] == pytest.approx((0.4472135954999, 0.8944271909), 1.0e-4) - - # No Galaxy With Mass Profile - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) - - tracer_deflections = tracer.deflections_of_planes_summed_from(grid=grid_2d_7x7) - - assert (tracer_deflections.native[:, :, 0] == np.zeros(shape=(7, 7))).all() - assert (tracer_deflections.native[:, :, 1] == np.zeros(shape=(7, 7))).all() - - -def test__extract_attribute(): - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) - - values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") - - assert values == None - - g0 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0)) - ) - g1 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0)) - ) - - tracer = al.Tracer(galaxies=[g0, g1]) - - values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") - - assert values.in_list == [0.9, 0.8] - - values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value1") - - assert values.in_list == [(1.0, 1.0), (2.0, 2.0)] - - g2 = al.Galaxy( - redshift=0.5, - mp_0=al.m.MockMassProfile(value=0.7), - mp_1=al.m.MockMassProfile(value=0.6), - ) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") - - assert values.in_list == [0.9, 0.8, 0.7, 0.6] - - tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="incorrect_value") - - -def test__extract_attributes_of_plane(): - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) - - values = tracer.extract_attributes_of_planes( - cls=al.mp.MassProfile, attr_name="value" - ) - - assert values == [None, None] - - g0 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0)) - ) - g1 = al.Galaxy( - redshift=0.75, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0)) - ) - g2 = al.Galaxy( - redshift=1.0, - mp_0=al.m.MockMassProfile(value=0.7), - mp_1=al.m.MockMassProfile(value=0.6), - ) - - tracer = al.Tracer(galaxies=[g0, g1]) - - values = tracer.extract_attributes_of_planes( - cls=al.mp.MassProfile, attr_name="value" - ) - - print(values) - - assert values[0].in_list == [0.9] - assert values[1].in_list == [0.8] - - values = tracer.extract_attributes_of_planes( - cls=al.mp.MassProfile, attr_name="value1" - ) - - assert values[0].in_list == [(1.0, 1.0)] - assert values[1].in_list == [(2.0, 2.0)] - - tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.25), g2]) - - values = tracer.extract_attributes_of_planes( - cls=al.mp.MassProfile, attr_name="value", filter_nones=False - ) - - assert values[0] == None - assert values[1] == 0.9 - assert values[2] == 0.8 - assert values[3].in_list == [0.7, 0.6] - - values = tracer.extract_attributes_of_planes( - cls=al.mp.MassProfile, attr_name="value", filter_nones=True - ) - - assert values[0] == 0.9 - assert values[1] == 0.8 - assert values[2].in_list == [0.7, 0.6] - - tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="incorrect_value") - - -def test__extract_attributes_of_galaxies(): - g0 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0)) - ) - g1 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0)) - ) - g2 = al.Galaxy( - redshift=0.5, - mp_0=al.m.MockMassProfile(value=0.7), - mp_1=al.m.MockMassProfile(value=0.6), - ) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) - - values = tracer.extract_attributes_of_galaxies( - cls=al.mp.MassProfile, attr_name="value" - ) - - assert values == [None, None] - - tracer = al.Tracer(galaxies=[g0, g1]) - - values = tracer.extract_attributes_of_galaxies( - cls=al.mp.MassProfile, attr_name="value" - ) - - assert values[0].in_list == [0.9] - assert values[1].in_list == [0.8] - - values = tracer.extract_attributes_of_galaxies( - cls=al.mp.MassProfile, attr_name="value1" - ) - - assert values[0].in_list == [(1.0, 1.0)] - assert values[1].in_list == [(2.0, 2.0)] - - tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.5), g2]) - - values = tracer.extract_attributes_of_galaxies( - cls=al.mp.MassProfile, attr_name="value", filter_nones=False - ) - - assert values[0].in_list == [0.9] - assert values[1].in_list == [0.8] - assert values[2] == None - assert values[3].in_list == [0.7, 0.6] - - values = tracer.extract_attributes_of_galaxies( - cls=al.mp.MassProfile, attr_name="value", filter_nones=True - ) - - assert values[0].in_list == [0.9] - assert values[1].in_list == [0.8] - assert values[2].in_list == [0.7, 0.6] - - tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="incorrect_value") - - -def test__extract_profile(): - g0 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0)) - ) - g1 = al.Galaxy( - redshift=0.5, mp_1=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0)) - ) - g2 = al.Galaxy( - redshift=1.0, - mp_2=al.m.MockMassProfile(value=0.7), - mp_3=al.m.MockMassProfile(value=0.6), - ) - - tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=None) - - profile = tracer.extract_profile(profile_name="mp_0") - - assert profile.value == 0.9 - - profile = tracer.extract_profile(profile_name="mp_3") - - assert profile.value == 0.6 - - -def test__extract_plane_index_of_profile(): - g0 = al.Galaxy( - redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0)) - ) - g1 = al.Galaxy( - redshift=0.75, mp_1=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0)) - ) - g2 = al.Galaxy( - redshift=1.0, - mp_2=al.m.MockMassProfile(value=0.7), - mp_3=al.m.MockMassProfile(value=0.6), - ) - - tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=None) - - plane_index = tracer.extract_plane_index_of_profile(profile_name="mp_0") - - assert plane_index == 0 - - plane_index = tracer.extract_plane_index_of_profile(profile_name="mp_1") - - assert plane_index == 1 - - plane_index = tracer.extract_plane_index_of_profile(profile_name="mp_3") - - assert plane_index == 2 - - -def test__sliced_tracer_from(grid_2d_7x7, grid_2d_7x7_simple): - lens_g0 = al.Galaxy(redshift=0.5) - source_g0 = al.Galaxy(redshift=2.0) - los_g0 = al.Galaxy(redshift=0.1) - los_g1 = al.Galaxy(redshift=0.2) - los_g2 = al.Galaxy(redshift=0.4) - los_g3 = al.Galaxy(redshift=0.6) - - tracer = al.Tracer.sliced_tracer_from( - lens_galaxies=[lens_g0], - line_of_sight_galaxies=[los_g0, los_g1, los_g2, los_g3], - source_galaxies=[source_g0], - planes_between_lenses=[1, 1], - cosmology=al.cosmo.Planck15(), - ) - - assert tracer.planes[0] == [los_g0, los_g1] - assert tracer.planes[1] == [lens_g0, los_g2, los_g3] - assert tracer.planes[2] == [source_g0] - - -def test__regression__centre_of_profile_in_right_place(): - grid = al.Grid2D.uniform(shape_native=(7, 7), pixel_scales=1.0) - - g0 = al.Galaxy( - redshift=0.5, - mass=al.mp.Isothermal(centre=(1.9999, 0.9999), einstein_radius=1.0), - ) - - tracer = al.Tracer(galaxies=[g0, al.Galaxy(redshift=1.0)]) - - convergence = tracer.convergence_2d_from(grid=grid) - max_indexes = np.unravel_index( - convergence.native.argmax(), convergence.shape_native - ) - assert max_indexes == (1, 4) - - potential = tracer.potential_2d_from(grid=grid) - max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) - assert max_indexes == (1, 4) - - deflections = tracer.deflections_yx_2d_from(grid=grid) - assert deflections.native[1, 4, 0] > 0 - assert deflections.native[2, 4, 0] < 0 - assert deflections.native[1, 4, 1] > 0 - assert deflections.native[1, 3, 1] < 0 - - -def test__instance_into_tracer__retains_dictionary_access(): - model = af.Collection( - galaxies=af.Collection( - lens=al.Galaxy( - redshift=0.5, - light=al.lp.SersicSph(intensity=2.0), - mass=al.mp.IsothermalSph(centre=(0.0, 0.0), einstein_radius=1.0), - ), - source=al.Galaxy(redshift=1.0), - ) - ) - - instance = model.instance_from_prior_medians() - - tracer = al.Tracer(galaxies=instance.galaxies) - - assert tracer.galaxies.lens.light.intensity == 2.0 - - -def test__output_to_and_load_from_json(): - json_file = path.join( - "{}".format(path.dirname(path.realpath(__file__))), "files", "tracer.json" - ) - - g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=1.0) - - tracer = al.Tracer(galaxies=[g0, g1], cosmology=al.cosmo.Planck15()) - - output_to_json(tracer, file_path=json_file) - - tracer_from_json = from_json(file_path=json_file) - - assert tracer_from_json.galaxies[0].redshift == 0.5 - assert tracer_from_json.galaxies[1].redshift == 1.0 - assert tracer_from_json.galaxies[0].mass_profile.einstein_radius == 1.0 +import numpy as np +import pytest +from os import path + +from autoconf.dictable import from_json, output_to_json +import autofit as af +import autolens as al + + +grid_simple = al.Grid2DIrregular(values=[(1.0, 2.0)]) + + +# ── has() ───────────────────────────────────────────────────────────────────── + + +def test__has__all_galaxies_have_only_mass_profiles__returns_false(): + gal_mp = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph()) + tracer = al.Tracer(galaxies=[gal_mp, gal_mp]) + assert tracer.has(cls=al.LightProfile) is False + + +def test__has__all_galaxies_have_light_profiles__returns_true(): + gal_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) + tracer = al.Tracer(galaxies=[gal_lp, gal_lp]) + assert tracer.has(cls=al.LightProfile) is True + + +def test__has__one_galaxy_has_light_profile__returns_true(): + gal_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) + gal_mp = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph()) + tracer = al.Tracer(galaxies=[gal_lp, gal_mp]) + assert tracer.has(cls=al.LightProfile) is True + + +# ── galaxies_ascending_redshift ─────────────────────────────────────────────── + + +def test__galaxies_ascending_redshift__two_galaxies_same_redshift__order_preserved( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5) + g1 = al.Galaxy(redshift=0.5) + tracer = al.Tracer(galaxies=[g0, g1]) + assert tracer.galaxies_ascending_redshift == [g0, g1] + + +def test__galaxies_ascending_redshift__four_galaxies_at_two_redshifts__sorted_correctly( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5) + g1 = al.Galaxy(redshift=0.5) + g2 = al.Galaxy(redshift=1.0) + g3 = al.Galaxy(redshift=1.0) + tracer = al.Tracer(galaxies=[g0, g1, g2, g3]) + assert tracer.galaxies_ascending_redshift == [g0, g1, g2, g3] + + +def test__galaxies_ascending_redshift__six_galaxies_at_mixed_redshifts__sorted_correctly( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5) + g1 = al.Galaxy(redshift=0.5) + g2 = al.Galaxy(redshift=1.0) + g3 = al.Galaxy(redshift=1.0) + g4 = al.Galaxy(redshift=0.75) + g5 = al.Galaxy(redshift=1.5) + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5]) + assert tracer.galaxies_ascending_redshift == [g0, g1, g4, g2, g3, g5] + + +# ── plane_redshifts ─────────────────────────────────────────────────────────── + + +def test__plane_redshifts__two_distinct_redshifts__returns_both(): + g1 = al.Galaxy(redshift=1) + g2 = al.Galaxy(redshift=2) + tracer = al.Tracer(galaxies=[g1, g2]) + assert tracer.plane_redshifts == [1, 2] + + +def test__plane_redshifts__duplicate_redshifts_across_galaxies__deduplicates_correctly(): + g1 = al.Galaxy(redshift=1) + g2 = al.Galaxy(redshift=2) + g3 = al.Galaxy(redshift=3) + tracer = al.Tracer(galaxies=[g2, g2, g3, g1, g1]) + assert tracer.plane_redshifts == [1, 2, 3] + + +# ── planes ──────────────────────────────────────────────────────────────────── + + +def test__planes__two_distinct_redshifts__one_galaxy_per_plane(): + g1 = al.Galaxy(redshift=1) + g2 = al.Galaxy(redshift=2) + tracer = al.Tracer(galaxies=[g1, g2]) + assert tracer.planes == [[g1], [g2]] + + +def test__planes__duplicate_and_multiple_redshifts__grouped_correctly(): + g1 = al.Galaxy(redshift=1) + g2 = al.Galaxy(redshift=2) + g3 = al.Galaxy(redshift=3) + tracer = al.Tracer(galaxies=[g2, g2, g3, g1, g1]) + assert tracer.planes == [[g1, g1], [g2, g2], [g3]] + + +# ── plane_index_via_redshift_from ───────────────────────────────────────────── + + +@pytest.mark.parametrize("redshift,expected_index", [ + (2.0, 1), + (3.0, 2), + (3.001, None), +]) +def test__plane_index_via_redshift_from__various_redshifts__returns_correct_index_or_none( + redshift, expected_index +): + g1 = al.Galaxy(redshift=1) + g2 = al.Galaxy(redshift=2) + g3 = al.Galaxy(redshift=3) + tracer = al.Tracer(galaxies=[g1, g2, g3]) + assert tracer.plane_index_via_redshift_from(redshift=redshift) == expected_index + + +# ── upper_plane_index_with_light_profile ───────────────────────────────────── + + +def test__upper_plane_index_with_light_profile__single_plane_with_light__returns_0(): + g1_lp = al.Galaxy(redshift=1.0, light_profile=al.LightProfile()) + tracer = al.Tracer(galaxies=[g1_lp]) + assert tracer.upper_plane_index_with_light_profile == 0 + + +def test__upper_plane_index_with_light_profile__two_planes_light_on_second__returns_1(): + g0 = al.Galaxy(redshift=0.5) + g1_lp = al.Galaxy(redshift=1.0, light_profile=al.LightProfile()) + tracer = al.Tracer(galaxies=[g0, g1_lp]) + assert tracer.upper_plane_index_with_light_profile == 1 + + +def test__upper_plane_index_with_light_profile__three_planes_all_have_light__returns_2(): + g0_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) + g1_lp = al.Galaxy(redshift=1.0, light_profile=al.LightProfile()) + g2_lp = al.Galaxy(redshift=2.0, light_profile=al.LightProfile()) + tracer = al.Tracer(galaxies=[g0_lp, g1_lp, g2_lp]) + assert tracer.upper_plane_index_with_light_profile == 2 + + +def test__upper_plane_index_with_light_profile__four_planes_first_and_last_have_light__returns_3(): + g0_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) + g1 = al.Galaxy(redshift=1.0) + g2 = al.Galaxy(redshift=2.0) + g3_lp = al.Galaxy(redshift=3.0, light_profile=al.LightProfile()) + tracer = al.Tracer(galaxies=[g0_lp, g1, g2, g3_lp]) + assert tracer.upper_plane_index_with_light_profile == 3 + + +def test__upper_plane_index_with_light_profile__four_planes_light_on_first_and_third__returns_2(): + g0_lp = al.Galaxy(redshift=0.5, light_profile=al.LightProfile()) + g1 = al.Galaxy(redshift=1.0) + g2_lp = al.Galaxy(redshift=2.0, light_profile=al.LightProfile()) + g3 = al.Galaxy(redshift=3.0) + tracer = al.Tracer(galaxies=[g0_lp, g1, g2_lp, g3]) + assert tracer.upper_plane_index_with_light_profile == 2 + + +# ── traced_grid_2d_list_from ────────────────────────────────────────────────── + + +def test__traced_grid_2d_list_from__full_trace__all_planes_have_correct_grid_values( + grid_2d_7x7, grid_2d_7x7_simple +): + g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5], cosmology=al.cosmo.Planck15()) + traced_grid_list = tracer.traced_grid_2d_list_from(grid=grid_simple) + + assert traced_grid_list[0][0] == pytest.approx((1.0, 2.0), 1.0e-4) + assert traced_grid_list[1][0] == pytest.approx((0.58194284, 1.16388568), 1.0e-4) + assert traced_grid_list[2][0] == pytest.approx((0.22277247, 0.4455449), 1.0e-4) + assert traced_grid_list[3][0] == pytest.approx((-0.78885438, -1.57770876), 1.0e-4) + assert len(traced_grid_list) == 4 + + +def test__traced_grid_2d_list_from__plane_index_limit__only_traces_up_to_specified_plane( + grid_2d_7x7, grid_2d_7x7_simple +): + g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5], cosmology=al.cosmo.Planck15()) + traced_grid_list = tracer.traced_grid_2d_list_from(grid=grid_simple, plane_index_limit=1) + + assert traced_grid_list[0][0] == pytest.approx((1.0, 2.0), 1.0e-4) + assert traced_grid_list[-1][0] == pytest.approx((0.58194284, 1.16388568), 1.0e-4) + assert len(traced_grid_list) == 2 + + +# ── grid_2d_at_redshift_from ────────────────────────────────────────────────── + + +def test__grid_2d_at_redshift_from__redshift_0p5__grid_interpolated_correctly( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5], cosmology=al.cosmo.Planck15()) + tracer_plus_extra = al.Tracer( + galaxies=[g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=0.5)], + cosmology=al.cosmo.Planck15(), + ) + grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) + + grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=0.5) + + assert grid_2d_list_from[1] == pytest.approx(grid_at_redshift.array, 1.0e-4) + assert grid_at_redshift[0] == pytest.approx((0.6273814, 1.2547628), 1.0e-4) + + +def test__grid_2d_at_redshift_from__redshift_1p75__grid_interpolated_correctly( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5], cosmology=al.cosmo.Planck15()) + tracer_plus_extra = al.Tracer( + galaxies=[g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=1.75)], + cosmology=al.cosmo.Planck15(), + ) + grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) + + grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=1.75) + + assert grid_2d_list_from[2] == pytest.approx(grid_at_redshift.array, 1.0e-4) + assert grid_at_redshift[0] == pytest.approx((0.27331481161, 0.5466296232), 1.0e-4) + + +def test__grid_2d_at_redshift_from__redshift_2p0__grid_interpolated_correctly( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=2.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g2 = al.Galaxy(redshift=0.1, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g3 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g4 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g5 = al.Galaxy(redshift=3.0, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2, g3, g4, g5], cosmology=al.cosmo.Planck15()) + tracer_plus_extra = al.Tracer( + galaxies=[g0, g1, g2, g3, g4, g5, al.Galaxy(redshift=2.0)], + cosmology=al.cosmo.Planck15(), + ) + grid_2d_list_from = tracer_plus_extra.traced_grid_2d_list_from(grid=grid_simple) + + grid_at_redshift = tracer.grid_2d_at_redshift_from(grid=grid_simple, redshift=2.0) + + assert grid_2d_list_from[2] == pytest.approx(grid_at_redshift.array, 1.0e-4) + assert grid_at_redshift[0] == pytest.approx((0.222772465, 0.445544931), 1.0e-4) + + +# ── image_2d_list_from ──────────────────────────────────────────────────────── + + +def test__image_2d_list_from__single_plane_multiple_galaxies__one_combined_image_returned(): + g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=2.0)) + g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + image_list = tracer.image_2d_list_from(grid=grid_simple) + + assert image_list[0][0] == pytest.approx(0.30276535, 1.0e-4) + assert len(image_list) == 1 + + +def test__image_2d_list_from__multi_plane_with_lensing__each_plane_image_lensed_correctly(): + g0 = al.Galaxy( + redshift=0.5, + light_profile=al.lp.Sersic(intensity=1.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy( + redshift=1.0, + light_profile=al.lp.Sersic(intensity=2.0), + mass_profile=al.mp.IsothermalSph(einstein_radius=2.0), + ) + g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + image_list = tracer.image_2d_list_from(grid=grid_simple) + + assert image_list[0][0] == pytest.approx(0.0504608, 1.0e-4) + assert image_list[1][0] == pytest.approx(0.2517025, 1.0e-4) + assert image_list[2][0] == pytest.approx(1.8611933, 1.0e-4) + assert len(image_list) == 3 + + +def test__image_2d_list_from__plane_without_light_profile_is_zeros( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.1, light_profile=al.lp.Sersic(intensity=0.1)) + g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) + g2 = al.Galaxy(redshift=2.0) + + tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=al.cosmo.Planck15()) + tracer_image_of_planes = tracer.image_2d_list_from(grid=grid_2d_7x7) + + assert tracer_image_of_planes[2].shape_native == (7, 7) + assert (tracer_image_of_planes[2].native == np.zeros((7, 7))).all() + + +# ── image_2d_from ───────────────────────────────────────────────────────────── + + +def test__image_2d_from__operated_only_input(grid_2d_7x7, lp_0, lp_operated_0, mp_0): + galaxy_0 = al.Galaxy( + redshift=0.5, light=lp_0, light_operated=lp_operated_0, mass=mp_0 + ) + galaxy_1 = al.Galaxy( + redshift=1.0, light_operated_0=lp_operated_0, light_operated_1=lp_operated_0 + ) + galaxy_2 = al.Galaxy(redshift=2.0) + + tracer = al.Tracer(galaxies=[galaxy_0, galaxy_1, galaxy_2]) + image = tracer.image_2d_from(grid=grid_2d_7x7, operated_only=False) + + assert image[0] == pytest.approx(1.79362512, 1.0e-4) + assert image[1] == pytest.approx(2.93152589, 1.0e-4) + + +def test__image_2d_from__sum_of_individual_images(mask_2d_7x7): + grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) + + g0 = al.Galaxy( + redshift=0.1, + light_profile=al.lp.Sersic(intensity=0.1), + mass=al.mp.IsothermalSph(einstein_radius=1.0), + ) + g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) + + tracer = al.Tracer(galaxies=[g0, g1], cosmology=al.cosmo.Planck15()) + + traced_grid_2d_list = tracer.traced_grid_2d_list_from( + grid=al.Grid2DIrregular(grid_2d_7x7.over_sampled) + ) + + image = g0.image_2d_from(grid=traced_grid_2d_list[0]) + g1.image_2d_from( + grid=traced_grid_2d_list[1] + ) + image = grid_2d_7x7.over_sampler.binned_array_2d_from(array=image) + image_tracer = tracer.image_2d_from(grid=grid_2d_7x7) + + assert image.shape_native == (7, 7) + assert image == pytest.approx(image_tracer.array, 1.0e-4) + + +# ── image_2d_via_input_plane_image_from ─────────────────────────────────────── + + +def test__image_2d_via_input_plane_image_from__with_foreground_planes(grid_2d_7x7): + plane_grid = al.Grid2D.uniform( + shape_native=(40, 40), pixel_scales=0.3, over_sample_size=1 + ) + + g0 = al.Galaxy( + redshift=0.5, + light_profile=al.lp.Sersic(intensity=1.0), + mass=al.mp.IsothermalSph(einstein_radius=0.2), + ) + g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=2.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + image_via_light_profile = tracer.image_2d_from(grid=grid_2d_7x7) + plane_image = g1.image_2d_from(grid=plane_grid) + + image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( + grid=grid_2d_7x7, + plane_image=plane_image, + plane_index=-1, + include_other_planes=True, + ) + + assert image_via_light_profile[0] == pytest.approx( + image_via_input_plane_image[0], 1.0e-2 + ) + + +def test__image_2d_via_input_plane_image_from__without_foreground_planes( + grid_2d_7x7, +): + grid_2d_7x7 = al.Grid2D( + values=grid_2d_7x7, + mask=grid_2d_7x7.mask, + over_sample_size=2, + ) + + g0 = al.Galaxy( + redshift=0.5, + mass=al.mp.IsothermalSph(einstein_radius=0.2), + light_profile=al.lp.Sersic(intensity=1.0), + ) + g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=2.0)) + + tracer = al.Tracer(galaxies=[g0, g1]) + image_via_light_profile = tracer.image_2d_list_from(grid=grid_2d_7x7)[-1] + + plane_grid = al.Grid2D.uniform(shape_native=(80, 80), pixel_scales=0.125) + plane_image = g1.image_2d_from(grid=plane_grid) + + image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( + grid=grid_2d_7x7, + plane_image=plane_image, + plane_index=-1, + include_other_planes=False, + ) + + assert image_via_light_profile[0] == pytest.approx( + image_via_input_plane_image[0], 1.0e-2 + ) + + +def test__image_2d_via_input_plane_image_from__multi_plane__final_source_plane_image_correct( + grid_2d_7x7, +): + plane_grid = al.Grid2D.uniform( + shape_native=(40, 40), pixel_scales=0.3, over_sample_size=1 + ) + + g0 = al.Galaxy( + redshift=0.5, + light_profile=al.lp.Sersic(intensity=1.0), + mass=al.mp.IsothermalSph(einstein_radius=0.2), + ) + g1 = al.Galaxy( + redshift=1.0, + light_profile=al.lp.Sersic(intensity=2.0), + mass=al.mp.IsothermalSph(einstein_radius=0.2), + ) + g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + image_via_light_profile = tracer.image_2d_from(grid=grid_2d_7x7) + + plane_image = g2.image_2d_from(grid=plane_grid) + image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( + grid=grid_2d_7x7, + plane_image=plane_image, + plane_index=-1, + include_other_planes=True, + ) + + assert image_via_light_profile[0] == pytest.approx( + image_via_input_plane_image[0], 1.0e-2 + ) + + +def test__image_2d_via_input_plane_image_from__multi_plane__intermediate_plane_index_correct( + grid_2d_7x7, +): + plane_grid = al.Grid2D.uniform( + shape_native=(40, 40), pixel_scales=0.3, over_sample_size=1 + ) + + g0 = al.Galaxy( + redshift=0.5, + light_profile=al.lp.Sersic(intensity=1.0), + mass=al.mp.IsothermalSph(einstein_radius=0.2), + ) + g1 = al.Galaxy( + redshift=1.0, + light_profile=al.lp.Sersic(intensity=2.0), + mass=al.mp.IsothermalSph(einstein_radius=0.2), + ) + g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + image_via_light_profile = tracer.image_2d_from(grid=grid_2d_7x7) + + plane_image = g1.image_2d_from(grid=plane_grid) + image_via_input_plane_image = tracer.image_2d_via_input_plane_image_from( + grid=grid_2d_7x7, + plane_image=plane_image, + plane_index=1, + include_other_planes=True, + ) + + assert image_via_light_profile[0] == pytest.approx( + image_via_input_plane_image[0], 1.0e-2 + ) + + +# ── padded_image_2d_from ────────────────────────────────────────────────────── + + +def test__padded_image_2d_from(grid_2d_7x7): + padded_grid = grid_2d_7x7.padded_grid_from(kernel_shape_native=(3, 3)) + + g0 = al.Galaxy(redshift=0.1, light_profile=al.lp.Sersic(intensity=0.1)) + g1 = al.Galaxy(redshift=1.0, light_profile=al.lp.Sersic(intensity=0.2)) + g2 = al.Galaxy(redshift=2.0, light_profile=al.lp.Sersic(intensity=0.3)) + + padded_g0_image = g0.image_2d_from(grid=padded_grid) + padded_g1_image = g1.image_2d_from(grid=padded_grid) + padded_g2_image = g2.image_2d_from(grid=padded_grid) + + tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=al.cosmo.Planck15()) + padded_tracer_image = tracer.padded_image_2d_from( + grid=grid_2d_7x7, psf_shape_2d=(3, 3) + ) + + assert padded_tracer_image.shape_native == (9, 9) + assert padded_tracer_image == pytest.approx( + padded_g0_image.array + padded_g1_image.array + padded_g2_image.array, 1.0e-4 + ) + + +# ── light_profile_snr ───────────────────────────────────────────────────────── + + +def test__light_profile_snr__signal_to_noise_via_simulator_correct(): + background_sky_level = 10.0 + exposure_time = 300.0 + + grid = al.Grid2D.uniform(shape_native=(3, 3), pixel_scales=1.0) + mass = al.mp.IsothermalSph(einstein_radius=1.0) + sersic = al.lp_snr.Sersic(signal_to_noise_ratio=10.0, effective_radius=0.01) + + tracer = al.Tracer( + galaxies=[ + al.Galaxy(redshift=0.5, mass=mass), + al.Galaxy(redshift=1.0, light=sersic), + ] + ) + + kernel = al.Array2D.no_mask(values=[[1.0]], pixel_scales=1.0) + psf = al.Convolver(kernel=kernel) + + simulator = al.SimulatorImaging( + psf=psf, + exposure_time=exposure_time, + noise_seed=1, + background_sky_level=background_sky_level, + ) + + dataset = simulator.via_tracer_from(tracer=tracer, grid=grid) + + assert 8.0 < dataset.signal_to_noise_map.native[0, 1] < 12.0 + assert 8.0 < dataset.signal_to_noise_map.native[1, 0] < 12.0 + assert 8.0 < dataset.signal_to_noise_map.native[1, 2] < 12.0 + assert 8.0 < dataset.signal_to_noise_map.native[2, 1] < 12.0 + + +# ── galaxy_image_2d_dict_from ───────────────────────────────────────────────── + + +def test__galaxy_image_2d_dict_from__default_operated_only__standard_and_operated_images_returned( + grid_2d_7x7, mask_2d_7x7 +): + grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) + + g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy( + redshift=0.5, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + light_profile=al.lp.Sersic(intensity=2.0), + ) + g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) + g3 = al.Galaxy(redshift=1.0, light_profile=al.lp_operated.Gaussian(intensity=5.0)) + + tracer = al.Tracer(galaxies=[g3, g1, g0, g2], cosmology=al.cosmo.Planck15()) + galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from(grid=grid_2d_7x7) + + assert (galaxy_image_2d_dict[g0] == g0.image_2d_from(grid=grid_2d_7x7)).all() + assert (galaxy_image_2d_dict[g1] == g1.image_2d_from(grid=grid_2d_7x7)).all() + assert (galaxy_image_2d_dict[g2] == g2.image_2d_from(grid=grid_2d_7x7)).all() + assert galaxy_image_2d_dict[g3][0] == pytest.approx(4.429962294298565, 1.0e-4) + + +def test__galaxy_image_2d_dict_from__operated_only_true__only_operated_profiles_contribute( + grid_2d_7x7, mask_2d_7x7 +): + grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) + + g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy( + redshift=0.5, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + light_profile=al.lp.Sersic(intensity=2.0), + ) + g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) + g3 = al.Galaxy(redshift=1.0, light_profile=al.lp_operated.Gaussian(intensity=5.0)) + + tracer = al.Tracer(galaxies=[g3, g1, g0, g2], cosmology=al.cosmo.Planck15()) + galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from( + grid=grid_2d_7x7, operated_only=True + ) + + assert (galaxy_image_2d_dict[g0] == np.zeros(shape=(9,))).all() + assert (galaxy_image_2d_dict[g1] == np.zeros(shape=(9,))).all() + assert (galaxy_image_2d_dict[g2] == np.zeros(shape=(9,))).all() + assert galaxy_image_2d_dict[g3][0] == pytest.approx(4.429962294298565, 1.0e-4) + + +def test__galaxy_image_2d_dict_from__operated_only_false__only_standard_profiles_contribute( + grid_2d_7x7, mask_2d_7x7 +): + grid_2d_7x7 = al.Grid2D.from_mask(mask=mask_2d_7x7, over_sample_size=2) + + g0 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=1.0)) + g1 = al.Galaxy( + redshift=0.5, + mass_profile=al.mp.IsothermalSph(einstein_radius=1.0), + light_profile=al.lp.Sersic(intensity=2.0), + ) + g2 = al.Galaxy(redshift=0.5, light_profile=al.lp.Sersic(intensity=3.0)) + g3 = al.Galaxy(redshift=1.0, light_profile=al.lp_operated.Gaussian(intensity=5.0)) + + tracer = al.Tracer(galaxies=[g3, g1, g0, g2], cosmology=al.cosmo.Planck15()) + galaxy_image_2d_dict = tracer.galaxy_image_2d_dict_from( + grid=grid_2d_7x7, operated_only=False + ) + + assert (galaxy_image_2d_dict[g0] == g0.image_2d_from(grid=grid_2d_7x7)).all() + assert (galaxy_image_2d_dict[g1] == g1.image_2d_from(grid=grid_2d_7x7)).all() + assert (galaxy_image_2d_dict[g2] == g2.image_2d_from(grid=grid_2d_7x7)).all() + assert (galaxy_image_2d_dict[g3] == np.zeros(shape=(9,))).all() + assert galaxy_image_2d_dict[g2][0] == pytest.approx(0.5244575148617125, 1.0e-4) + + +# ── convergence_2d_from ─────────────────────────────────────────────────────── + + +def test__convergence_2d_from__multiple_mass_profiles__summed_convergence_correct( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) + g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + convergence = tracer.convergence_2d_from(grid=grid_simple) + + assert convergence == pytest.approx(1.34164079, 1.0e-4) + + +def test__convergence_2d_from__no_mass_profiles__returns_zeros(grid_2d_7x7): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) + + assert ( + tracer.convergence_2d_from(grid=grid_2d_7x7).native == np.zeros(shape=(7, 7)) + ).all() + + +# ── potential_2d_from ───────────────────────────────────────────────────────── + + +def test__potential_2d_from__multiple_mass_profiles__summed_potential_correct( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) + g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + potential = tracer.potential_2d_from(grid=grid_simple) + + assert potential == pytest.approx(13.4164078, 1.0e-4) + + +def test__potential_2d_from__no_mass_profiles__returns_zeros(grid_2d_7x7): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) + + assert ( + tracer.potential_2d_from(grid=grid_2d_7x7).native == np.zeros(shape=(7, 7)) + ).all() + + +# ── time_delays_from ────────────────────────────────────────────────────────── + + +def test__time_delays_from__isothermal_mass_profile__expected_time_delays_correct(): + grid = al.Grid2DIrregular(values=[(0.7, 0.5), (1.0, 1.0)]) + mp = al.mp.Isothermal( + centre=(0.0, 0.0), ell_comps=(0.0, -0.111111), einstein_radius=2.0 + ) + g0 = al.Galaxy(redshift=0.2, mass=mp) + g1 = al.Galaxy(redshift=0.7) + + tracer = al.Tracer(galaxies=[g0, g1]) + time_delay = tracer.time_delays_from(grid=grid) + + assert time_delay == pytest.approx(np.array([8.52966247, -29.0176387]), 1.0e-4) + + +# ── deflections_of_planes_summed_from ──────────────────────────────────────── + + +def test__deflections_of_planes_summed_from__multiple_mass_profiles__summed_deflections_correct( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=2.0)) + g2 = al.Galaxy(redshift=1.0, mass_profile=al.mp.IsothermalSph(einstein_radius=3.0)) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + deflections = tracer.deflections_of_planes_summed_from(grid=grid_simple) + + assert deflections[0] == pytest.approx((2.68328157, 5.36656315), 1.0e-4) + + +def test__deflections_of_planes_summed_from__single_plane__deflections_correct( + grid_2d_7x7, +): + g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + tracer = al.Tracer(galaxies=[g0]) + deflections = tracer.deflections_of_planes_summed_from(grid=grid_simple) + + assert deflections[0] == pytest.approx((0.4472135954999, 0.8944271909), 1.0e-4) + + +def test__deflections_of_planes_summed_from__no_mass_profiles__returns_zeros( + grid_2d_7x7, +): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=0.5)]) + tracer_deflections = tracer.deflections_of_planes_summed_from(grid=grid_2d_7x7) + + assert (tracer_deflections.native[:, :, 0] == np.zeros(shape=(7, 7))).all() + assert (tracer_deflections.native[:, :, 1] == np.zeros(shape=(7, 7))).all() + + +# ── extract_attribute ───────────────────────────────────────────────────────── + + +def test__extract_attribute__no_mass_profiles__returns_none(): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) + values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") + assert values is None + + +def test__extract_attribute__two_galaxies_one_profile_each__returns_both_values(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + + tracer = al.Tracer(galaxies=[g0, g1]) + values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") + assert values.in_list == [0.9, 0.8] + + values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value1") + assert values.in_list == [(1.0, 1.0), (2.0, 2.0)] + + +def test__extract_attribute__three_galaxies_multiple_profiles__returns_all_values(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=0.5, + mp_0=al.m.MockMassProfile(value=0.7), + mp_1=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + values = tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="value") + assert values.in_list == [0.9, 0.8, 0.7, 0.6] + + +def test__extract_attribute__incorrect_attr_name__does_not_raise(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + tracer = al.Tracer(galaxies=[g0]) + tracer.extract_attribute(cls=al.mp.MassProfile, attr_name="incorrect_value") + + +# ── extract_attributes_of_plane ─────────────────────────────────────────────── + + +def test__extract_attributes_of_plane__no_mass_profiles__returns_list_of_nones(): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) + values = tracer.extract_attributes_of_planes(cls=al.mp.MassProfile, attr_name="value") + assert values == [None, None] + + +def test__extract_attributes_of_plane__two_planes_one_profile_each__returns_per_plane_values(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.75, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + + tracer = al.Tracer(galaxies=[g0, g1]) + + values = tracer.extract_attributes_of_planes(cls=al.mp.MassProfile, attr_name="value") + assert values[0].in_list == [0.9] + assert values[1].in_list == [0.8] + + values = tracer.extract_attributes_of_planes(cls=al.mp.MassProfile, attr_name="value1") + assert values[0].in_list == [(1.0, 1.0)] + assert values[1].in_list == [(2.0, 2.0)] + + +def test__extract_attributes_of_plane__filter_nones_false__includes_none_entries(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.75, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=1.0, + mp_0=al.m.MockMassProfile(value=0.7), + mp_1=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.25), g2]) + values = tracer.extract_attributes_of_planes( + cls=al.mp.MassProfile, attr_name="value", filter_nones=False + ) + + assert values[0] is None + assert values[1] == 0.9 + assert values[2] == 0.8 + assert values[3].in_list == [0.7, 0.6] + + +def test__extract_attributes_of_plane__filter_nones_true__excludes_none_entries(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.75, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=1.0, + mp_0=al.m.MockMassProfile(value=0.7), + mp_1=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.25), g2]) + values = tracer.extract_attributes_of_planes( + cls=al.mp.MassProfile, attr_name="value", filter_nones=True + ) + + assert values[0] == 0.9 + assert values[1] == 0.8 + assert values[2].in_list == [0.7, 0.6] + + +# ── extract_attributes_of_galaxies ─────────────────────────────────────────── + + +def test__extract_attributes_of_galaxies__no_mass_profiles__returns_list_of_nones(): + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), al.Galaxy(redshift=1.0)]) + values = tracer.extract_attributes_of_galaxies( + cls=al.mp.MassProfile, attr_name="value" + ) + assert values == [None, None] + + +def test__extract_attributes_of_galaxies__two_galaxies__returns_per_galaxy_values(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + + tracer = al.Tracer(galaxies=[g0, g1]) + values = tracer.extract_attributes_of_galaxies( + cls=al.mp.MassProfile, attr_name="value" + ) + assert values[0].in_list == [0.9] + assert values[1].in_list == [0.8] + + values = tracer.extract_attributes_of_galaxies( + cls=al.mp.MassProfile, attr_name="value1" + ) + assert values[0].in_list == [(1.0, 1.0)] + assert values[1].in_list == [(2.0, 2.0)] + + +def test__extract_attributes_of_galaxies__filter_nones_false__includes_none_entries(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=0.5, + mp_0=al.m.MockMassProfile(value=0.7), + mp_1=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.5), g2]) + values = tracer.extract_attributes_of_galaxies( + cls=al.mp.MassProfile, attr_name="value", filter_nones=False + ) + + assert values[0].in_list == [0.9] + assert values[1].in_list == [0.8] + assert values[2] is None + assert values[3].in_list == [0.7, 0.6] + + +def test__extract_attributes_of_galaxies__filter_nones_true__excludes_none_entries(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=0.5, + mp_0=al.m.MockMassProfile(value=0.7), + mp_1=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, al.Galaxy(redshift=0.5), g2]) + values = tracer.extract_attributes_of_galaxies( + cls=al.mp.MassProfile, attr_name="value", filter_nones=True + ) + + assert values[0].in_list == [0.9] + assert values[1].in_list == [0.8] + assert values[2].in_list == [0.7, 0.6] + + +# ── extract_profile ─────────────────────────────────────────────────────────── + + +def test__extract_profile__profile_name_matches_first_galaxy__returns_correct_profile(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_1=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=1.0, + mp_2=al.m.MockMassProfile(value=0.7), + mp_3=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=None) + profile = tracer.extract_profile(profile_name="mp_0") + assert profile.value == 0.9 + + +def test__extract_profile__profile_name_matches_second_plane__returns_correct_profile(): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.5, mp_1=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=1.0, + mp_2=al.m.MockMassProfile(value=0.7), + mp_3=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=None) + profile = tracer.extract_profile(profile_name="mp_3") + assert profile.value == 0.6 + + +# ── extract_plane_index_of_profile ─────────────────────────────────────────── + + +@pytest.mark.parametrize("profile_name,expected_plane_index", [ + ("mp_0", 0), + ("mp_1", 1), + ("mp_3", 2), +]) +def test__extract_plane_index_of_profile__various_profiles__returns_correct_plane_index( + profile_name, expected_plane_index +): + g0 = al.Galaxy(redshift=0.5, mp_0=al.m.MockMassProfile(value=0.9, value1=(1.0, 1.0))) + g1 = al.Galaxy(redshift=0.75, mp_1=al.m.MockMassProfile(value=0.8, value1=(2.0, 2.0))) + g2 = al.Galaxy( + redshift=1.0, + mp_2=al.m.MockMassProfile(value=0.7), + mp_3=al.m.MockMassProfile(value=0.6), + ) + + tracer = al.Tracer(galaxies=[g0, g1, g2], cosmology=None) + assert tracer.extract_plane_index_of_profile(profile_name=profile_name) == expected_plane_index + + +# ── sliced_tracer_from ──────────────────────────────────────────────────────── + + +def test__sliced_tracer_from(grid_2d_7x7, grid_2d_7x7_simple): + lens_g0 = al.Galaxy(redshift=0.5) + source_g0 = al.Galaxy(redshift=2.0) + los_g0 = al.Galaxy(redshift=0.1) + los_g1 = al.Galaxy(redshift=0.2) + los_g2 = al.Galaxy(redshift=0.4) + los_g3 = al.Galaxy(redshift=0.6) + + tracer = al.Tracer.sliced_tracer_from( + lens_galaxies=[lens_g0], + line_of_sight_galaxies=[los_g0, los_g1, los_g2, los_g3], + source_galaxies=[source_g0], + planes_between_lenses=[1, 1], + cosmology=al.cosmo.Planck15(), + ) + + assert tracer.planes[0] == [los_g0, los_g1] + assert tracer.planes[1] == [lens_g0, los_g2, los_g3] + assert tracer.planes[2] == [source_g0] + + +# ── regression ──────────────────────────────────────────────────────────────── + + +def test__regression__centre_of_profile_in_right_place(): + grid = al.Grid2D.uniform(shape_native=(7, 7), pixel_scales=1.0) + + g0 = al.Galaxy( + redshift=0.5, + mass=al.mp.Isothermal(centre=(1.9999, 0.9999), einstein_radius=1.0), + ) + + tracer = al.Tracer(galaxies=[g0, al.Galaxy(redshift=1.0)]) + + convergence = tracer.convergence_2d_from(grid=grid) + max_indexes = np.unravel_index( + convergence.native.argmax(), convergence.shape_native + ) + assert max_indexes == (1, 4) + + potential = tracer.potential_2d_from(grid=grid) + max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) + assert max_indexes == (1, 4) + + deflections = tracer.deflections_yx_2d_from(grid=grid) + assert deflections.native[1, 4, 0] > 0 + assert deflections.native[2, 4, 0] < 0 + assert deflections.native[1, 4, 1] > 0 + assert deflections.native[1, 3, 1] < 0 + + +def test__instance_into_tracer__retains_dictionary_access(): + model = af.Collection( + galaxies=af.Collection( + lens=al.Galaxy( + redshift=0.5, + light=al.lp.SersicSph(intensity=2.0), + mass=al.mp.IsothermalSph(centre=(0.0, 0.0), einstein_radius=1.0), + ), + source=al.Galaxy(redshift=1.0), + ) + ) + + instance = model.instance_from_prior_medians() + tracer = al.Tracer(galaxies=instance.galaxies) + + assert tracer.galaxies.lens.light.intensity == 2.0 + + +def test__output_to_and_load_from_json(): + json_file = path.join( + "{}".format(path.dirname(path.realpath(__file__))), "files", "tracer.json" + ) + + g0 = al.Galaxy(redshift=0.5, mass_profile=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=1.0) + + tracer = al.Tracer(galaxies=[g0, g1], cosmology=al.cosmo.Planck15()) + output_to_json(tracer, file_path=json_file) + + tracer_from_json = from_json(file_path=json_file) + + assert tracer_from_json.galaxies[0].redshift == 0.5 + assert tracer_from_json.galaxies[1].redshift == 1.0 + assert tracer_from_json.galaxies[0].mass_profile.einstein_radius == 1.0 diff --git a/test_autolens/point/fit/positions/image/test_abstract.py b/test_autolens/point/fit/positions/image/test_abstract.py index 4ad50e2ac..e57328399 100644 --- a/test_autolens/point/fit/positions/image/test_abstract.py +++ b/test_autolens/point/fit/positions/image/test_abstract.py @@ -1,87 +1,46 @@ -import numpy as np -import pytest - -import autolens as al - - -def test__two_sets_of_positions__residuals_likelihood_correct(): - point = al.ps.Point(centre=(0.1, 0.1)) - galaxy = al.Galaxy(redshift=1.0, point_0=point) - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) - - data = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_data = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) - - solver = al.m.MockPointSolver(model_positions=model_data) - - # Uses FitPositionsImagePairRepeat to produce residual_map but test is focused on all attributes - - fit = al.FitPositionsImagePairRepeat( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=solver, - ) - - assert fit.model_data.in_list == [(3.0, 1.0), (2.0, 3.0)] - assert fit.noise_map.in_list == [0.5, 1.0] - - assert fit.residual_map.in_list == [np.sqrt(10.0), np.sqrt(2.0)] - assert fit.normalized_residual_map.in_list == [ - np.sqrt(10.0) / 0.5, - np.sqrt(2.0) / 1.0, - ] - assert fit.chi_squared_map.in_list == [ - (np.sqrt(10.0) / 0.5) ** 2, - np.sqrt(2.0) ** 2.0, - ] - assert fit.chi_squared == pytest.approx(42.0, 1.0e-4) - assert fit.noise_normalization == pytest.approx(2.28945, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-22.14472, 1.0e-4) - - -def test__multi_plane_position_solving(): - grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) - - g0 = al.Galaxy(redshift=0.5, mass=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=1.0, point_0=al.ps.Point(centre=(0.1, 0.1))) - g2 = al.Galaxy(redshift=2.0, point_1=al.ps.Point(centre=(0.1, 0.1))) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - dataset = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - - solver = al.PointSolver.for_grid(grid=grid, pixel_scale_precision=0.01) - - fit_0 = al.AbstractFitPositionsImagePair( - name="point_0", - data=dataset, - noise_map=noise_map, - tracer=tracer, - solver=solver, - ) - - fit_1 = al.AbstractFitPositionsImagePair( - name="point_1", - data=dataset, - noise_map=noise_map, # - tracer=tracer, - solver=solver, - ) - - scaling_factor = tracer.cosmology.scaling_factor_between_redshifts_from( - redshift_0=0.5, redshift_1=1.0, redshift_final=2.0 - ) - - print(fit_0.model_data) - print(fit_1.model_data.array) - - assert fit_0.model_data[0, :] == pytest.approx( - scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 - ) - assert fit_0.model_data[0, :] == pytest.approx( - scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 - ) +import numpy as np +import pytest + +import autolens as al + + +def test__abstract_fit_positions_image_pair__multi_plane_tracer__model_positions_scale_with_cosmology(): + grid = al.Grid2D.uniform(shape_native=(100, 100), pixel_scales=0.05) + + g0 = al.Galaxy(redshift=0.5, mass=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=1.0, point_0=al.ps.Point(centre=(0.1, 0.1))) + g2 = al.Galaxy(redshift=2.0, point_1=al.ps.Point(centre=(0.1, 0.1))) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + + dataset = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + + solver = al.PointSolver.for_grid(grid=grid, pixel_scale_precision=0.01) + + fit_0 = al.AbstractFitPositionsImagePair( + name="point_0", + data=dataset, + noise_map=noise_map, + tracer=tracer, + solver=solver, + ) + + fit_1 = al.AbstractFitPositionsImagePair( + name="point_1", + data=dataset, + noise_map=noise_map, + tracer=tracer, + solver=solver, + ) + + scaling_factor = tracer.cosmology.scaling_factor_between_redshifts_from( + redshift_0=0.5, redshift_1=1.0, redshift_final=2.0 + ) + + assert fit_0.model_data[0, :] == pytest.approx( + scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 + ) + assert fit_0.model_data[0, :] == pytest.approx( + scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 + ) diff --git a/test_autolens/point/fit/positions/image/test_pair.py b/test_autolens/point/fit/positions/image/test_pair.py index 240074e4b..cd92e5531 100644 --- a/test_autolens/point/fit/positions/image/test_pair.py +++ b/test_autolens/point/fit/positions/image/test_pair.py @@ -1,27 +1,27 @@ -import numpy as np -import pytest - -import autolens as al - - -def test__three_sets_of_positions__model_is_repeated__does_not_double_count(): - point = al.ps.Point(centre=(0.1, 0.1)) - galaxy = al.Galaxy(redshift=1.0, point_0=point) - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) - - data = al.Grid2DIrregular([(2.0, 0.0), (1.0, 0.0), (0.0, 0.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_data = al.Grid2DIrregular([(4.0, 0.0), (3.0, 0.0), (0.0, 0.0)]) - - solver = al.m.MockPointSolver(model_positions=model_data) - - fit = al.FitPositionsImagePair( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=solver, - ) - - assert fit.model_data.in_list == [(4.0, 0.0), (3.0, 0.0), (0.0, 0.0)] - assert fit.residual_map.in_list == [1.0, 3.0, 0.0] +import numpy as np +import pytest + +import autolens as al + + +def test__fit_positions_image_pair__three_observed_positions__model_not_repeated__residuals_correct(): + point = al.ps.Point(centre=(0.1, 0.1)) + galaxy = al.Galaxy(redshift=1.0, point_0=point) + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) + + data = al.Grid2DIrregular([(2.0, 0.0), (1.0, 0.0), (0.0, 0.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + model_data = al.Grid2DIrregular([(4.0, 0.0), (3.0, 0.0), (0.0, 0.0)]) + + solver = al.m.MockPointSolver(model_positions=model_data) + + fit = al.FitPositionsImagePair( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=solver, + ) + + assert fit.model_data.in_list == [(4.0, 0.0), (3.0, 0.0), (0.0, 0.0)] + assert fit.residual_map.in_list == [1.0, 3.0, 0.0] diff --git a/test_autolens/point/fit/positions/image/test_pair_all.py b/test_autolens/point/fit/positions/image/test_pair_all.py index c5bbb2b55..890a6b856 100644 --- a/test_autolens/point/fit/positions/image/test_pair_all.py +++ b/test_autolens/point/fit/positions/image/test_pair_all.py @@ -1,116 +1,112 @@ -try: - import jax - - JAX_INSTALLED = True -except ImportError: - JAX_INSTALLED = False - -import numpy as np -import pytest - -import autolens as al - -point = al.ps.Point(centre=(0.1, 0.1)) -galaxy = al.Galaxy(redshift=1.0, point_0=point) -tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) - - -@pytest.fixture -def data(): - return np.array([(0.0, 0.0), (1.0, 0.0)]) - - -@pytest.fixture -def noise_map(): - return np.array([1.0, 1.0]) - - -@pytest.fixture -def fit(data, noise_map): - model_positions = al.Grid2DIrregular( - [ - (-1.0749, -1.1), - (1.19117, 1.175), - ] - ) - - return al.FitPositionsImagePairAll( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=al.mock.MockPointSolver(model_positions), - ) - - -def test_andrew_implementation(fit): - assert np.allclose( - fit.all_permutations_log_likelihoods(), - [ - -1.51114426, - -1.50631469, - ], - ) - assert fit.chi_squared == -2.0 * -4.40375330990644 - - -# @pytest.mark.skipif(not JAX_INSTALLED, reason="JAX is not installed") -# def test_jax(fit): -# assert jax.jit(fit.log_likelihood)() == -4.40375330990644 - - -def test_inf_model_positions( - data, - noise_map, -): - model_positions = al.Grid2DIrregular( - [ - (-1.0749, -1.1), - (1.19117, 1.175), - (np.inf, np.inf), - ] - ) - fit = al.FitPositionsImagePairAll( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=al.mock.MockPointSolver(model_positions), - ) - - print(fit.all_permutations_log_likelihoods()) - - assert np.allclose( - fit.all_permutations_log_likelihoods(), - [ - -1.51114426, - -1.50631469, - ], - ) - assert fit.chi_squared == -2.0 * -4.40375330990644 - - -def test_duplicate_model_position( - data, - noise_map, -): - model_positions = al.Grid2DIrregular( - [ - (-1.0749, -1.1), - (1.19117, 1.175), - (1.19117, 1.175), - ] - ) - fit = al.FitPositionsImagePairAll( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=al.mock.MockPointSolver(model_positions), - ) - - assert np.allclose( - fit.all_permutations_log_likelihoods(), - [-1.14237812, -0.87193683], - ) - assert fit.chi_squared == -2.0 * -4.211539531047171 +try: + import jax + + JAX_INSTALLED = True +except ImportError: + JAX_INSTALLED = False + +import numpy as np +import pytest + +import autolens as al + + +point = al.ps.Point(centre=(0.1, 0.1)) +galaxy = al.Galaxy(redshift=1.0, point_0=point) +tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) + + +@pytest.fixture +def data(): + return np.array([(0.0, 0.0), (1.0, 0.0)]) + + +@pytest.fixture +def noise_map(): + return np.array([1.0, 1.0]) + + +@pytest.fixture +def fit(data, noise_map): + model_positions = al.Grid2DIrregular( + [ + (-1.0749, -1.1), + (1.19117, 1.175), + ] + ) + + return al.FitPositionsImagePairAll( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=al.mock.MockPointSolver(model_positions), + ) + + +def test__fit_positions_image_pair_all__two_model_positions__per_permutation_likelihoods_and_chi_squared_correct( + fit, +): + assert np.allclose( + fit.all_permutations_log_likelihoods(), + [ + -1.51114426, + -1.50631469, + ], + ) + assert fit.chi_squared == -2.0 * -4.40375330990644 + + +def test__fit_positions_image_pair_all__model_has_inf_position__inf_excluded_from_permutations( + data, + noise_map, +): + model_positions = al.Grid2DIrregular( + [ + (-1.0749, -1.1), + (1.19117, 1.175), + (np.inf, np.inf), + ] + ) + fit = al.FitPositionsImagePairAll( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=al.mock.MockPointSolver(model_positions), + ) + + assert np.allclose( + fit.all_permutations_log_likelihoods(), + [ + -1.51114426, + -1.50631469, + ], + ) + assert fit.chi_squared == -2.0 * -4.40375330990644 + + +def test__fit_positions_image_pair_all__model_has_duplicate_position__duplicate_permutations_handled( + data, + noise_map, +): + model_positions = al.Grid2DIrregular( + [ + (-1.0749, -1.1), + (1.19117, 1.175), + (1.19117, 1.175), + ] + ) + fit = al.FitPositionsImagePairAll( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=al.mock.MockPointSolver(model_positions), + ) + + assert np.allclose( + fit.all_permutations_log_likelihoods(), + [-1.14237812, -0.87193683], + ) + assert fit.chi_squared == -2.0 * -4.211539531047171 diff --git a/test_autolens/point/fit/positions/image/test_pair_repeat.py b/test_autolens/point/fit/positions/image/test_pair_repeat.py index f92e0ad7e..1d652b52c 100644 --- a/test_autolens/point/fit/positions/image/test_pair_repeat.py +++ b/test_autolens/point/fit/positions/image/test_pair_repeat.py @@ -1,27 +1,62 @@ -import numpy as np -import pytest - -import autolens as al - - -def test__three_sets_of_positions__model_is_repeat_allocated(): - point = al.ps.Point(centre=(0.1, 0.1)) - galaxy = al.Galaxy(redshift=1.0, point_0=point) - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) - - data = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_data = al.Grid2DIrregular([(3.0, 1.0), (3.0, 4.0)]) - - solver = al.m.MockPointSolver(model_positions=model_data) - - fit = al.FitPositionsImagePairRepeat( - name="point_0", - data=data, - noise_map=noise_map, - tracer=tracer, - solver=solver, - ) - - assert fit.model_data.in_list == [(3.0, 1.0), (3.0, 4.0)] - assert fit.residual_map.in_list == [np.sqrt(10.0), 0.0, 0.0] +import numpy as np +import pytest + +import autolens as al + + +def test__fit_positions_image_pair_repeat__two_residuals_and_all_fit_quantities_correct(): + point = al.ps.Point(centre=(0.1, 0.1)) + galaxy = al.Galaxy(redshift=1.0, point_0=point) + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) + + data = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + model_data = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) + + solver = al.m.MockPointSolver(model_positions=model_data) + + fit = al.FitPositionsImagePairRepeat( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=solver, + ) + + assert fit.model_data.in_list == [(3.0, 1.0), (2.0, 3.0)] + assert fit.noise_map.in_list == [0.5, 1.0] + assert fit.residual_map.in_list == [np.sqrt(10.0), np.sqrt(2.0)] + assert fit.normalized_residual_map.in_list == [ + np.sqrt(10.0) / 0.5, + np.sqrt(2.0) / 1.0, + ] + assert fit.chi_squared_map.in_list == [ + (np.sqrt(10.0) / 0.5) ** 2, + np.sqrt(2.0) ** 2.0, + ] + assert fit.chi_squared == pytest.approx(42.0, 1.0e-4) + assert fit.noise_normalization == pytest.approx(2.28945, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-22.14472, 1.0e-4) + + +def test__fit_positions_image_pair_repeat__three_observed_positions__model_allocated_by_repeat(): + point = al.ps.Point(centre=(0.1, 0.1)) + galaxy = al.Galaxy(redshift=1.0, point_0=point) + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy]) + + data = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0), (3.0, 4.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + model_data = al.Grid2DIrregular([(3.0, 1.0), (3.0, 4.0)]) + + solver = al.m.MockPointSolver(model_positions=model_data) + + fit = al.FitPositionsImagePairRepeat( + name="point_0", + data=data, + noise_map=noise_map, + tracer=tracer, + solver=solver, + ) + + assert fit.model_data.in_list == [(3.0, 1.0), (3.0, 4.0)] + assert fit.residual_map.in_list == [np.sqrt(10.0), 0.0, 0.0] diff --git a/test_autolens/point/fit/positions/source/test_separations.py b/test_autolens/point/fit/positions/source/test_separations.py index 760981394..1ac96058f 100644 --- a/test_autolens/point/fit/positions/source/test_separations.py +++ b/test_autolens/point/fit/positions/source/test_separations.py @@ -1,76 +1,79 @@ -import pytest - -import autolens as al - - -def test__two_sets_of_positions__residuals_likelihood_correct(): - point_source = al.ps.Point(centre=(0.0, 0.0)) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) - - positions = al.Grid2DIrregular([(0.0, 1.0), (0.0, 2.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - - fit = al.FitPositionsSource( - name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None - ) - - assert fit.model_data.in_list == [(0.0, 1.0), (0.0, 2.0)] - assert fit.noise_map.in_list == [0.5, 1.0] - assert fit.residual_map.in_list == [1.0, 2.0] - assert fit.normalized_residual_map.in_list == [1.0 / 0.5, 2.0 / 1.0] - assert fit.chi_squared_map.in_list == [(1.0 / 0.5) ** 2.0, 2.0**2.0] - assert fit.chi_squared == pytest.approx(8.0, 1.0e-4) - assert fit.noise_normalization == pytest.approx(2.28945, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-5.14472988, 1.0e-4) - - # Inclusion of mass model below means there are nonzero magnifications at each position, which get factored into - # chi-squared calculation. - - galaxy_mass = al.Galaxy( - redshift=0.5, mass=al.mp.IsothermalSph(centre=(0.0, 0.0), einstein_radius=0.1) - ) - - tracer = al.Tracer(galaxies=[galaxy_mass, galaxy_point_source]) - - fit = al.FitPositionsSource( - name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None - ) - - assert fit.magnifications_at_positions.in_list == pytest.approx( - [1.1111049387688177, 1.0526308864400329], 1.0e-4 - ) - assert fit.model_data.in_list == [(0.0, 0.9), (0.0, 1.9)] - - assert fit.chi_squared_map.in_list == pytest.approx( - [3.9999555592589244, 3.9999947369459807], 1.0e-4 - ) - assert fit.log_likelihood == pytest.approx(-4.98805743691215, 1.0e-4) - - -def test__multi_plane_position_solving(): - g0 = al.Galaxy(redshift=0.5, mass=al.mp.IsothermalSph(einstein_radius=1.0)) - g1 = al.Galaxy(redshift=1.0, point_0=al.ps.Point(centre=(0.1, 0.1))) - g2 = al.Galaxy(redshift=2.0, point_1=al.ps.Point(centre=(0.1, 0.1))) - - tracer = al.Tracer(galaxies=[g0, g1, g2]) - - positions = al.Grid2DIrregular([(0.0, 1.0), (0.0, 2.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - - traced_grids = tracer.traced_grid_2d_list_from(grid=positions) - - fit_0 = al.FitPositionsSource( - name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None - ) - - assert fit_0.model_data[0, 1] == pytest.approx(0.326054, 1.0e-1) - assert fit_0.model_data[1, 1] == pytest.approx(1.326054, 1.0e-1) - - assert (fit_0.model_data == traced_grids[1]).all() - - fit_1 = al.FitPositionsSource( - name="point_1", data=positions, noise_map=noise_map, tracer=tracer, solver=None - ) - - assert (fit_1.model_data == traced_grids[2]).all() +import pytest + +import autolens as al + + +def test__fit_positions_source__all_residual_quantities_correct_without_mass_profile(): + point_source = al.ps.Point(centre=(0.0, 0.0)) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) + + positions = al.Grid2DIrregular([(0.0, 1.0), (0.0, 2.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + + fit = al.FitPositionsSource( + name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None + ) + + assert fit.model_data.in_list == [(0.0, 1.0), (0.0, 2.0)] + assert fit.noise_map.in_list == [0.5, 1.0] + assert fit.residual_map.in_list == [1.0, 2.0] + assert fit.normalized_residual_map.in_list == [1.0 / 0.5, 2.0 / 1.0] + assert fit.chi_squared_map.in_list == [(1.0 / 0.5) ** 2.0, 2.0 ** 2.0] + assert fit.chi_squared == pytest.approx(8.0, 1.0e-4) + assert fit.noise_normalization == pytest.approx(2.28945, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-5.14472988, 1.0e-4) + + +def test__fit_positions_source__with_isothermal_mass_profile__magnification_reduces_source_positions(): + # Inclusion of mass model means nonzero magnifications at each position, which + # reduce the reconstructed source-plane separation. + point_source = al.ps.Point(centre=(0.0, 0.0)) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + galaxy_mass = al.Galaxy( + redshift=0.5, mass=al.mp.IsothermalSph(centre=(0.0, 0.0), einstein_radius=0.1) + ) + + tracer = al.Tracer(galaxies=[galaxy_mass, galaxy_point_source]) + + positions = al.Grid2DIrregular([(0.0, 1.0), (0.0, 2.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + + fit = al.FitPositionsSource( + name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None + ) + + assert fit.magnifications_at_positions.in_list == pytest.approx( + [1.1111049387688177, 1.0526308864400329], 1.0e-4 + ) + assert fit.model_data.in_list == [(0.0, 0.9), (0.0, 1.9)] + assert fit.chi_squared_map.in_list == pytest.approx( + [3.9999555592589244, 3.9999947369459807], 1.0e-4 + ) + assert fit.log_likelihood == pytest.approx(-4.98805743691215, 1.0e-4) + + +def test__fit_positions_source__multi_plane_tracer__model_data_traces_to_correct_source_plane(): + g0 = al.Galaxy(redshift=0.5, mass=al.mp.IsothermalSph(einstein_radius=1.0)) + g1 = al.Galaxy(redshift=1.0, point_0=al.ps.Point(centre=(0.1, 0.1))) + g2 = al.Galaxy(redshift=2.0, point_1=al.ps.Point(centre=(0.1, 0.1))) + + tracer = al.Tracer(galaxies=[g0, g1, g2]) + + positions = al.Grid2DIrregular([(0.0, 1.0), (0.0, 2.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + traced_grids = tracer.traced_grid_2d_list_from(grid=positions) + + fit_0 = al.FitPositionsSource( + name="point_0", data=positions, noise_map=noise_map, tracer=tracer, solver=None + ) + + assert fit_0.model_data[0, 1] == pytest.approx(0.326054, 1.0e-1) + assert fit_0.model_data[1, 1] == pytest.approx(1.326054, 1.0e-1) + assert (fit_0.model_data == traced_grids[1]).all() + + fit_1 = al.FitPositionsSource( + name="point_1", data=positions, noise_map=noise_map, tracer=tracer, solver=None + ) + + assert (fit_1.model_data == traced_grids[2]).all() diff --git a/test_autolens/point/fit/test_fit_dataset.py b/test_autolens/point/fit/test_fit_dataset.py index 36bea90db..e0bab3106 100644 --- a/test_autolens/point/fit/test_fit_dataset.py +++ b/test_autolens/point/fit/test_fit_dataset.py @@ -1,118 +1,117 @@ -import pytest - -import autolens as al - - -def test__fit_dataset__positions_only(): - point_source = al.ps.Point(centre=(0.1, 0.1)) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) - - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_positions = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) - - solver = al.m.MockPointSolver(model_positions=model_positions) - - dataset_0 = al.PointDataset( - name="point_0", positions=positions, positions_noise_map=noise_map - ) - - fit = al.FitPointDataset(dataset=dataset_0, tracer=tracer, solver=solver) - - assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) - assert fit.flux == None - - dataset_1 = al.PointDataset( - name="point_1", positions=positions, positions_noise_map=noise_map - ) - - fit = al.FitPointDataset(dataset=dataset_1, tracer=tracer, solver=solver) - - assert fit.flux == None - assert fit.positions == None - assert fit.flux == None - - -def test__fit_dataset__all_positions_classes(): - point_source = al.ps.Point(centre=(0.1, 0.1)) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) - - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_positions = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) - - solver = al.m.MockPointSolver(model_positions=model_positions) - - dataset_0 = al.PointDataset( - name="point_0", positions=positions, positions_noise_map=noise_map - ) - - fit = al.FitPointDataset( - dataset=dataset_0, - tracer=tracer, - solver=solver, - fit_positions_cls=al.FitPositionsImagePair, - ) - - assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) - - fit = al.FitPointDataset( - dataset=dataset_0, - tracer=tracer, - solver=solver, - fit_positions_cls=al.FitPositionsImagePairRepeat, - ) - - assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) - - fit = al.FitPointDataset( - dataset=dataset_0, - tracer=tracer, - solver=solver, - fit_positions_cls=al.FitPositionsImagePairAll, - ) - - assert fit.positions.log_likelihood == pytest.approx(-24.6435280294, 1.0e-4) - - fit = al.FitPointDataset( - dataset=dataset_0, - tracer=tracer, - solver=solver, - fit_positions_cls=al.FitPositionsSource, - ) - - assert fit.positions.log_likelihood == pytest.approx(-12.9947298, 1.0e-4) - - -def test__fit_dataset__positions_and_flux(): - point_source = al.ps.PointFlux(centre=(0.1, 0.1), flux=2.0) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - - tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) - - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - noise_map = al.ArrayIrregular([0.5, 1.0]) - model_positions = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) - - fluxes = al.ArrayIrregular([1.0, 2.0]) - flux_noise_map = al.ArrayIrregular([3.0, 1.0]) - - solver = al.m.MockPointSolver(model_positions=model_positions) - - dataset_0 = al.PointDataset( - name="point_0", - positions=positions, - positions_noise_map=noise_map, - fluxes=fluxes, - fluxes_noise_map=flux_noise_map, - ) - - fit = al.FitPointDataset(dataset=dataset_0, tracer=tracer, solver=solver) - - assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) - assert fit.flux.log_likelihood == pytest.approx(-2.9920449, 1.0e-4) - assert fit.log_likelihood == fit.positions.log_likelihood + fit.flux.log_likelihood +import pytest + +import autolens as al + + +@pytest.fixture +def point_source_tracer(): + point_source = al.ps.Point(centre=(0.1, 0.1)) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + return al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) + + +@pytest.fixture +def positions_and_noise(): + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + return positions, noise_map + + +@pytest.fixture +def mock_solver(): + model_positions = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) + return al.m.MockPointSolver(model_positions=model_positions) + + +def test__fit_dataset__matching_point_name__positions_log_likelihood_correct( + point_source_tracer, positions_and_noise, mock_solver +): + positions, noise_map = positions_and_noise + dataset = al.PointDataset( + name="point_0", positions=positions, positions_noise_map=noise_map + ) + + fit = al.FitPointDataset( + dataset=dataset, tracer=point_source_tracer, solver=mock_solver + ) + + assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) + assert fit.flux is None + + +def test__fit_dataset__nonmatching_point_name__positions_and_flux_are_none( + point_source_tracer, positions_and_noise, mock_solver +): + positions, noise_map = positions_and_noise + dataset = al.PointDataset( + name="point_1", positions=positions, positions_noise_map=noise_map + ) + + fit = al.FitPointDataset( + dataset=dataset, tracer=point_source_tracer, solver=mock_solver + ) + + assert fit.positions is None + assert fit.flux is None + + +@pytest.mark.parametrize( + "fit_positions_cls, expected_log_likelihood", + [ + (al.FitPositionsImagePair, -22.14472), + (al.FitPositionsImagePairRepeat, -22.14472), + (al.FitPositionsImagePairAll, -24.6435280294), + (al.FitPositionsSource, -12.9947298), + ], + ids=[ + "FitPositionsImagePair", + "FitPositionsImagePairRepeat", + "FitPositionsImagePairAll", + "FitPositionsSource", + ], +) +def test__fit_dataset__log_likelihood_correct_for_each_position_fitting_class( + point_source_tracer, positions_and_noise, mock_solver, + fit_positions_cls, expected_log_likelihood, +): + positions, noise_map = positions_and_noise + dataset = al.PointDataset( + name="point_0", positions=positions, positions_noise_map=noise_map + ) + + fit = al.FitPointDataset( + dataset=dataset, + tracer=point_source_tracer, + solver=mock_solver, + fit_positions_cls=fit_positions_cls, + ) + + assert fit.positions.log_likelihood == pytest.approx(expected_log_likelihood, 1.0e-4) + + +def test__fit_dataset__positions_and_flux__both_log_likelihoods_correct_and_sum(): + point_source = al.ps.PointFlux(centre=(0.1, 0.1), flux=2.0) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + tracer = al.Tracer(galaxies=[al.Galaxy(redshift=0.5), galaxy_point_source]) + + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + noise_map = al.ArrayIrregular([0.5, 1.0]) + model_positions = al.Grid2DIrregular([(3.0, 1.0), (2.0, 3.0)]) + fluxes = al.ArrayIrregular([1.0, 2.0]) + flux_noise_map = al.ArrayIrregular([3.0, 1.0]) + + solver = al.m.MockPointSolver(model_positions=model_positions) + + dataset = al.PointDataset( + name="point_0", + positions=positions, + positions_noise_map=noise_map, + fluxes=fluxes, + fluxes_noise_map=flux_noise_map, + ) + + fit = al.FitPointDataset(dataset=dataset, tracer=tracer, solver=solver) + + assert fit.positions.log_likelihood == pytest.approx(-22.14472, 1.0e-4) + assert fit.flux.log_likelihood == pytest.approx(-2.9920449, 1.0e-4) + assert fit.log_likelihood == fit.positions.log_likelihood + fit.flux.log_likelihood diff --git a/test_autolens/point/fit/test_fluxes.py b/test_autolens/point/fit/test_fluxes.py index 703b8c340..5141d1fef 100644 --- a/test_autolens/point/fit/test_fluxes.py +++ b/test_autolens/point/fit/test_fluxes.py @@ -1,50 +1,52 @@ -import pytest - -import autolens as al - - -def test__one_set_of_fluxes__residuals_likelihood_correct(): - tracer = al.m.MockTracerPoint(profile=al.ps.PointFlux(flux=2.0)) - - data = al.ArrayIrregular([1.0, 2.0]) - noise_map = al.ArrayIrregular([3.0, 1.0]) - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - - fit = al.FitFluxes( - name="point_0", - data=data, - noise_map=noise_map, - positions=positions, - tracer=tracer, - ) - - assert fit.data.in_list == [1.0, 2.0] - assert fit.noise_map.in_list == [3.0, 1.0] - assert fit.model_fluxes.in_list == [2.0, 2.0] - assert fit.residual_map.in_list == [-1.0, -0.0] - assert fit.normalized_residual_map.in_list == [-1.0 / 3.0, -0.0] - assert fit.chi_squared_map.in_list == [1.0 / 9.0, 0.0] - assert fit.chi_squared == pytest.approx(1.0 / 9.0, 1.0e-4) - assert fit.noise_normalization == pytest.approx(5.87297, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-2.992044910633, 1.0e-4) - - -def test__use_real_tracer(gal_x1_mp): - point_source = al.ps.PointFlux(centre=(0.1, 0.1), flux=2.0) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - tracer = al.Tracer(galaxies=[gal_x1_mp, galaxy_point_source]) - - data = al.ArrayIrregular([1.0, 2.0]) - noise_map = al.ArrayIrregular([3.0, 1.0]) - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - - fit = al.FitFluxes( - name="point_0", - data=data, - noise_map=noise_map, - positions=positions, - tracer=tracer, - ) - - assert fit.model_fluxes.in_list[1] == pytest.approx(2.5, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-3.11702, 1.0e-4) +import pytest + +import autolens as al + + +def test__fit_fluxes__all_residual_quantities_computed_correctly_with_mock_tracer(): + tracer = al.m.MockTracerPoint(profile=al.ps.PointFlux(flux=2.0)) + + data = al.ArrayIrregular([1.0, 2.0]) + noise_map = al.ArrayIrregular([3.0, 1.0]) + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + + fit = al.FitFluxes( + name="point_0", + data=data, + noise_map=noise_map, + positions=positions, + tracer=tracer, + ) + + assert fit.data.in_list == [1.0, 2.0] + assert fit.noise_map.in_list == [3.0, 1.0] + assert fit.model_fluxes.in_list == [2.0, 2.0] + assert fit.residual_map.in_list == [-1.0, -0.0] + assert fit.normalized_residual_map.in_list == [-1.0 / 3.0, -0.0] + assert fit.chi_squared_map.in_list == [1.0 / 9.0, 0.0] + assert fit.chi_squared == pytest.approx(1.0 / 9.0, 1.0e-4) + assert fit.noise_normalization == pytest.approx(5.87297, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-2.992044910633, 1.0e-4) + + +def test__fit_fluxes__model_flux_magnified_correctly_with_real_isothermal_tracer( + gal_x1_mp, +): + point_source = al.ps.PointFlux(centre=(0.1, 0.1), flux=2.0) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + tracer = al.Tracer(galaxies=[gal_x1_mp, galaxy_point_source]) + + data = al.ArrayIrregular([1.0, 2.0]) + noise_map = al.ArrayIrregular([3.0, 1.0]) + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + + fit = al.FitFluxes( + name="point_0", + data=data, + noise_map=noise_map, + positions=positions, + tracer=tracer, + ) + + assert fit.model_fluxes.in_list[1] == pytest.approx(2.5, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-3.11702, 1.0e-4) From d5cbe62b892d07ede812d914b96d31ccb11c8671 Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Wed, 25 Mar 2026 19:57:18 +0000 Subject: [PATCH 2/4] Rename test_time_delays.py tests for clarity Consistent with test_fluxes.py rename pattern: test names now encode the tracer type used (mock vs real isothermal). Co-Authored-By: Claude Sonnet 4.6 --- test_autolens/point/fit/test_time_delays.py | 113 ++++++++++---------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/test_autolens/point/fit/test_time_delays.py b/test_autolens/point/fit/test_time_delays.py index d42b94b6a..0f5f468b3 100644 --- a/test_autolens/point/fit/test_time_delays.py +++ b/test_autolens/point/fit/test_time_delays.py @@ -1,57 +1,56 @@ -import numpy as np -import pytest - -import autolens as al - - -def test__one_set_of_time_delays__residuals_likelihood_correct(): - # Mock tracer returns fixed time delays (like magnifications in original) - tracer = al.m.MockTracerPoint( - profile=al.ps.Point(), - time_delays=al.ArrayIrregular([2.0, 2.0]), # Mock time delays for two positions - ) - - data = al.ArrayIrregular([1.0, 2.0]) # observed time delays - noise_map = al.ArrayIrregular([3.0, 1.0]) - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - - fit = al.FitTimeDelays( - name="point_0", - data=data, - noise_map=noise_map, - positions=positions, - tracer=tracer, - ) - - assert fit.data.in_list == [1.0, 2.0] - assert fit.noise_map.in_list == [3.0, 1.0] - assert fit.model_time_delays.in_list == [2.0, 2.0] - assert fit.residual_map.in_list == [0.0, 1.0] - assert fit.normalized_residual_map.in_list == [0.0, 1.0] - assert fit.chi_squared_map.in_list == [0.0, 1.0] - assert fit.chi_squared == pytest.approx(1.0, 1.0e-4) - assert fit.noise_normalization == pytest.approx(5.87297, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-3.43648935, 1.0e-4) - - -def test__use_real_tracer(gal_x1_mp): - - point_source = al.ps.Point(centre=(0.1, 0.1)) - galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) - tracer = al.Tracer(galaxies=[gal_x1_mp, galaxy_point_source]) - - data = al.ArrayIrregular([1.0, 2.0]) # observed time delays - noise_map = al.ArrayIrregular([3.0, 1.0]) - positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) - - fit = al.FitTimeDelays( - name="point_0", - data=data, - noise_map=noise_map, - positions=positions, - tracer=tracer, - ) - - # Replace 2.5 with expected model time delay from your tracer - assert fit.model_time_delays.in_list[1] == pytest.approx(-573.994580905, 1.0e-4) - assert fit.log_likelihood == pytest.approx(-22600.81488747, 1.0e-4) +import numpy as np +import pytest + +import autolens as al + + +def test__fit_time_delays__all_residual_quantities_computed_correctly_with_mock_tracer(): + tracer = al.m.MockTracerPoint( + profile=al.ps.Point(), + time_delays=al.ArrayIrregular([2.0, 2.0]), + ) + + data = al.ArrayIrregular([1.0, 2.0]) + noise_map = al.ArrayIrregular([3.0, 1.0]) + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + + fit = al.FitTimeDelays( + name="point_0", + data=data, + noise_map=noise_map, + positions=positions, + tracer=tracer, + ) + + assert fit.data.in_list == [1.0, 2.0] + assert fit.noise_map.in_list == [3.0, 1.0] + assert fit.model_time_delays.in_list == [2.0, 2.0] + assert fit.residual_map.in_list == [0.0, 1.0] + assert fit.normalized_residual_map.in_list == [0.0, 1.0] + assert fit.chi_squared_map.in_list == [0.0, 1.0] + assert fit.chi_squared == pytest.approx(1.0, 1.0e-4) + assert fit.noise_normalization == pytest.approx(5.87297, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-3.43648935, 1.0e-4) + + +def test__fit_time_delays__model_time_delays_correct_with_real_isothermal_tracer( + gal_x1_mp, +): + point_source = al.ps.Point(centre=(0.1, 0.1)) + galaxy_point_source = al.Galaxy(redshift=1.0, point_0=point_source) + tracer = al.Tracer(galaxies=[gal_x1_mp, galaxy_point_source]) + + data = al.ArrayIrregular([1.0, 2.0]) + noise_map = al.ArrayIrregular([3.0, 1.0]) + positions = al.Grid2DIrregular([(0.0, 0.0), (3.0, 4.0)]) + + fit = al.FitTimeDelays( + name="point_0", + data=data, + noise_map=noise_map, + positions=positions, + tracer=tracer, + ) + + assert fit.model_time_delays.in_list[1] == pytest.approx(-573.994580905, 1.0e-4) + assert fit.log_likelihood == pytest.approx(-22600.81488747, 1.0e-4) From 1263577592c1fec82cb3d0b7f7042db4dbfcb60a Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Wed, 25 Mar 2026 20:12:06 +0000 Subject: [PATCH 3/4] Fix remaining Copilot review issues: unused import and duplicate assertion - test_abstract.py: remove unused `import numpy as np`; fix duplicate assertion so second check covers row [1, :] not [0, :] again - test_fit_imaging.py: remove unused fixtures and dead setup block from covariance test (only masked_imaging_covariance_7x7 is needed) Co-Authored-By: Claude Sonnet 4.6 --- test_autolens/imaging/test_fit_imaging.py | 10 +--------- .../point/fit/positions/image/test_abstract.py | 5 ++--- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/test_autolens/imaging/test_fit_imaging.py b/test_autolens/imaging/test_fit_imaging.py index 9544b7183..8a9e8c82d 100644 --- a/test_autolens/imaging/test_fit_imaging.py +++ b/test_autolens/imaging/test_fit_imaging.py @@ -549,16 +549,8 @@ def test__figure_of_merit__sub_2_oversampling__linear_operated_profiles__inversi def test__figure_of_merit__sub_2_oversampling__covariance_noise_matrix__expected_log_likelihood( - masked_imaging_covariance_7x7, image_7x7, psf_3x3, noise_map_7x7, mask_2d_7x7 + masked_imaging_covariance_7x7, ): - dataset = al.Imaging( - data=image_7x7, - psf=psf_3x3, - noise_map=noise_map_7x7, - over_sample_size_lp=2, - ) - masked_imaging_7x7 = dataset.apply_mask(mask=mask_2d_7x7) - g0 = al.Galaxy( redshift=0.5, bulge=al.lp.Sersic(centre=(0.05, 0.05), intensity=1.0), diff --git a/test_autolens/point/fit/positions/image/test_abstract.py b/test_autolens/point/fit/positions/image/test_abstract.py index e57328399..bf129647b 100644 --- a/test_autolens/point/fit/positions/image/test_abstract.py +++ b/test_autolens/point/fit/positions/image/test_abstract.py @@ -1,4 +1,3 @@ -import numpy as np import pytest import autolens as al @@ -41,6 +40,6 @@ def test__abstract_fit_positions_image_pair__multi_plane_tracer__model_positions assert fit_0.model_data[0, :] == pytest.approx( scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 ) - assert fit_0.model_data[0, :] == pytest.approx( - scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 + assert fit_0.model_data[1, :] == pytest.approx( + scaling_factor * fit_1.model_data.array[1, :], 1.0e-1 ) From 9865ea812729fb44a361016f8289963227830919 Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Wed, 25 Mar 2026 20:19:03 +0000 Subject: [PATCH 4/4] Remove duplicate assertion in test_abstract rather than changing row index The second assert was a copy-paste of the first (both checked row [0, :]). Changing it to row [1, :] introduced a genuinely failing assertion since the scaling relationship does not hold for the second position. Simply remove the duplicate instead. Co-Authored-By: Claude Sonnet 4.6 --- test_autolens/point/fit/positions/image/test_abstract.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test_autolens/point/fit/positions/image/test_abstract.py b/test_autolens/point/fit/positions/image/test_abstract.py index bf129647b..ec44381be 100644 --- a/test_autolens/point/fit/positions/image/test_abstract.py +++ b/test_autolens/point/fit/positions/image/test_abstract.py @@ -40,6 +40,3 @@ def test__abstract_fit_positions_image_pair__multi_plane_tracer__model_positions assert fit_0.model_data[0, :] == pytest.approx( scaling_factor * fit_1.model_data.array[0, :], 1.0e-1 ) - assert fit_0.model_data[1, :] == pytest.approx( - scaling_factor * fit_1.model_data.array[1, :], 1.0e-1 - )