From 283d59ce0087762290c2fa1dff560164190648f5 Mon Sep 17 00:00:00 2001 From: James Nightingale Date: Mon, 11 Nov 2024 19:31:39 +0000 Subject: [PATCH 1/4] method switches to ShapeSolver if one image --- autolens/analysis/result.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/autolens/analysis/result.py b/autolens/analysis/result.py index 3ec792ec8..a3cb26139 100644 --- a/autolens/analysis/result.py +++ b/autolens/analysis/result.py @@ -14,7 +14,7 @@ ) from autolens.lens.tracer import Tracer from autolens.point.solver import PointSolver - +from autolens.point.solver.shape_solver import ShapeSolver class Result(AgResultDataset): @property @@ -101,8 +101,33 @@ def image_plane_multiple_image_positions(self) -> aa.Grid2DIrregular: source_plane_coordinate=self.source_plane_centre.in_list[0], ) + if multiple_images.shape[0] == 1: + return self.image_plane_multiple_image_positions_for_single_image_from(multiple_image=multiple_images) + return aa.Grid2DIrregular(values=multiple_images) + def image_plane_multiple_image_positions_for_single_image_from(self, multiple_image) -> aa.Grid2DIrregular: + + grid = self.analysis.dataset.mask.derive_grid.all_false + + solver = ShapeSolver.for_grid( + grid=grid, + pixel_scale_precision=0.001, + ) + + centre = self.source_plane_centre.in_list[0] + + multiple_images = solver.solve_triangles( + tracer=self.max_log_likelihood_tracer, + shape=aa.Circle(y=centre[0], x=centre[1], radius=0.1) + ) + + print(multiple_images.vertices) + fdsdfsfsd + + + pass + def positions_threshold_from( self, factor=1.0, From 8055110f095ac926d9309af37d50822f6cb39530 Mon Sep 17 00:00:00 2001 From: James Nightingale Date: Mon, 11 Nov 2024 19:52:57 +0000 Subject: [PATCH 2/4] hit wall on shapesolver API but most of way there --- autolens/analysis/result.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/autolens/analysis/result.py b/autolens/analysis/result.py index a3cb26139..953ea3a11 100644 --- a/autolens/analysis/result.py +++ b/autolens/analysis/result.py @@ -102,11 +102,23 @@ def image_plane_multiple_image_positions(self) -> aa.Grid2DIrregular: ) if multiple_images.shape[0] == 1: - return self.image_plane_multiple_image_positions_for_single_image_from(multiple_image=multiple_images) + return self.image_plane_multiple_image_positions_for_single_image_from(image_0=multiple_images) return aa.Grid2DIrregular(values=multiple_images) - def image_plane_multiple_image_positions_for_single_image_from(self, multiple_image) -> aa.Grid2DIrregular: + def image_plane_multiple_image_positions_for_single_image_from(self, image_0) -> aa.Grid2DIrregular: + """ + If the standard point solver only locates one multiple image, finds a second image which is not technically + a multiple image in the point source regime but is close to it. + + This is performed by placing a circle at the source-plane centre and growing it until the `ShapeSolver` + finds a second multiple image which is a sufficiently far enough distance away from the first multiple image. + + Parameters + ---------- + image_0 + The first multiple image of the source-plane centre computed via the standard point solver. + """ grid = self.analysis.dataset.mask.derive_grid.all_false @@ -117,16 +129,25 @@ def image_plane_multiple_image_positions_for_single_image_from(self, multiple_im centre = self.source_plane_centre.in_list[0] - multiple_images = solver.solve_triangles( + triangles = solver.solve_triangles( tracer=self.max_log_likelihood_tracer, - shape=aa.Circle(y=centre[0], x=centre[1], radius=0.1) + shape=aa.Circle(y=centre[0], x=centre[1], radius=0.01) ) - print(multiple_images.vertices) - fdsdfsfsd + multiple_images = triangles.centres + + distances = np.sum((multiple_images - image_0) ** 2, axis=1) + + print(np.min(distances)) + + hgjjhjh + + furthest_index = np.argmax(distances) + image_1 = multiple_images[furthest_index] + print(image_0[0], image_1) - pass + return aa.Grid2DIrregular(values=[image_0[0], image_1]) def positions_threshold_from( self, From 8cd2b37385cc8f8e2428fa3e99a3e42126fabdbb Mon Sep 17 00:00:00 2001 From: James Nightingale Date: Mon, 11 Nov 2024 20:37:02 +0000 Subject: [PATCH 3/4] multiple image calculation for single images --- autolens/analysis/result.py | 56 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/autolens/analysis/result.py b/autolens/analysis/result.py index 953ea3a11..b5bcb9fb5 100644 --- a/autolens/analysis/result.py +++ b/autolens/analysis/result.py @@ -102,52 +102,54 @@ def image_plane_multiple_image_positions(self) -> aa.Grid2DIrregular: ) if multiple_images.shape[0] == 1: - return self.image_plane_multiple_image_positions_for_single_image_from(image_0=multiple_images) + return self.image_plane_multiple_image_positions_for_single_image_from() return aa.Grid2DIrregular(values=multiple_images) - def image_plane_multiple_image_positions_for_single_image_from(self, image_0) -> aa.Grid2DIrregular: + def image_plane_multiple_image_positions_for_single_image_from(self, increments : int = 20) -> aa.Grid2DIrregular: """ - If the standard point solver only locates one multiple image, finds a second image which is not technically - a multiple image in the point source regime but is close to it. + If the standard point solver only locates one multiple image, finds one or more additional images, which are + not technically multiple image in the point source regime, but are close enough to it they can be used + in a position threshold likelihood. - This is performed by placing a circle at the source-plane centre and growing it until the `ShapeSolver` - finds a second multiple image which is a sufficiently far enough distance away from the first multiple image. + This is performed by incrementally moving the source-plane centre's coordinates towards the centre of the + source-plane at (0.0", 0.0"). This ensures that the centre will eventually go inside the caustic, where + multiple images are formed. + + To move the source-plane centre, the original source-plane centre is multiplied by a factor that decreases + from 1.0 to 0.0 in increments of 1/increments. For example, if the source-plane centre is (1.0", -0.5") and + the `factor` is 0.5, the input source-plane centre is (0.5", -0.25"). + + The multiple images are always computed for the same mass model, thus they will always be valid multiple images + for the model being fitted, but as the factor decrease the multiple images may move furhter from their observed + positions. Parameters ---------- - image_0 - The first multiple image of the source-plane centre computed via the standard point solver. + increments + The number of increments the source-plane centre is moved to compute multiple images. """ grid = self.analysis.dataset.mask.derive_grid.all_false - solver = ShapeSolver.for_grid( - grid=grid, - pixel_scale_precision=0.001, - ) - centre = self.source_plane_centre.in_list[0] - triangles = solver.solve_triangles( - tracer=self.max_log_likelihood_tracer, - shape=aa.Circle(y=centre[0], x=centre[1], radius=0.01) + solver = PointSolver.for_grid( + grid=grid, + pixel_scale_precision=0.001, ) - multiple_images = triangles.centres - - distances = np.sum((multiple_images - image_0) ** 2, axis=1) - - print(np.min(distances)) - - hgjjhjh + for i in range(1, increments): - furthest_index = np.argmax(distances) - image_1 = multiple_images[furthest_index] + factor = 1.0 - (1.0 * (i/increments)) - print(image_0[0], image_1) + multiple_images = solver.solve( + tracer=self.max_log_likelihood_tracer, + source_plane_coordinate=(centre[0] * factor, centre[1] * factor), + ) - return aa.Grid2DIrregular(values=[image_0[0], image_1]) + if multiple_images.shape[0] > 1: + return aa.Grid2DIrregular(values=multiple_images) def positions_threshold_from( self, From 3555dd6aec951d70c56910b7742e6dceef0c766b Mon Sep 17 00:00:00 2001 From: James Nightingale Date: Mon, 11 Nov 2024 20:55:14 +0000 Subject: [PATCH 4/4] fix test where output was flipped or changed --- autolens/analysis/result.py | 12 +++++++++++- test_autolens/analysis/test_result.py | 6 +++--- .../point/fit/positions/image/test_abstract.py | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/autolens/analysis/result.py b/autolens/analysis/result.py index b5bcb9fb5..b297f03bc 100644 --- a/autolens/analysis/result.py +++ b/autolens/analysis/result.py @@ -1,3 +1,4 @@ +import logging import os import numpy as np from typing import Optional, Union @@ -14,7 +15,9 @@ ) from autolens.lens.tracer import Tracer from autolens.point.solver import PointSolver -from autolens.point.solver.shape_solver import ShapeSolver + +logger = logging.getLogger(__name__) + class Result(AgResultDataset): @property @@ -130,6 +133,13 @@ def image_plane_multiple_image_positions_for_single_image_from(self, increments The number of increments the source-plane centre is moved to compute multiple images. """ + logger.info(""" + Could not find multiple images for maximum likelihood lens model. + + Incrementally moving source centre inwards towards centre of source-plane until caustic crossing occurs + and multiple images are formed. + """) + grid = self.analysis.dataset.mask.derive_grid.all_false centre = self.source_plane_centre.in_list[0] diff --git a/test_autolens/analysis/test_result.py b/test_autolens/analysis/test_result.py index 50809b671..82c1a1729 100644 --- a/test_autolens/analysis/test_result.py +++ b/test_autolens/analysis/test_result.py @@ -227,7 +227,7 @@ def test__image_plane_multiple_image_positions(analysis_imaging_7x7): multiple_images = result.image_plane_multiple_image_positions - assert pytest.approx((0.968719, 0.366210), 1.0e-4) in multiple_images.in_list + assert pytest.approx((0.968719, 0.366210), 1.0e-2) in multiple_images.in_list def test__positions_threshold_from(analysis_imaging_7x7): @@ -247,9 +247,9 @@ def test__positions_threshold_from(analysis_imaging_7x7): result = res.Result(samples_summary=samples_summary, analysis=analysis_imaging_7x7) - assert result.positions_threshold_from() == pytest.approx(1.1001488121, 1.0e-4) + assert result.positions_threshold_from() == pytest.approx(0.930414842576, 1.0e-4) assert result.positions_threshold_from(factor=5.0) == pytest.approx( - 5.5007440609, 1.0e-4 + 4.652074212, 1.0e-4 ) assert result.positions_threshold_from(minimum_threshold=10.0) == pytest.approx( 10.0, 1.0e-4 diff --git a/test_autolens/point/fit/positions/image/test_abstract.py b/test_autolens/point/fit/positions/image/test_abstract.py index f82779813..89cd0c3df 100644 --- a/test_autolens/point/fit/positions/image/test_abstract.py +++ b/test_autolens/point/fit/positions/image/test_abstract.py @@ -77,8 +77,8 @@ def test__multi_plane_position_solving(): ) assert fit_0.model_data[0, 0] == pytest.approx( - scaling_factor * fit_1.model_data[0, 0], 1.0e-1 + scaling_factor * fit_1.model_data[1, 0], 1.0e-1 ) - assert fit_0.model_data[0, 1] == pytest.approx( + assert fit_0.model_data[1, 1] == pytest.approx( scaling_factor * fit_1.model_data[0, 1], 1.0e-1 )