diff --git a/autogalaxy/__init__.py b/autogalaxy/__init__.py index 1a07536c4..ce10ff8cb 100644 --- a/autogalaxy/__init__.py +++ b/autogalaxy/__init__.py @@ -56,7 +56,7 @@ from .analysis import model_util from .analysis.adapt_images.adapt_images import AdaptImages -from .analysis.adapt_images.adapt_image_maker import AdaptImageMaker +from .analysis.adapt_images.adapt_images import galaxy_name_image_dict_via_result_from from . import aggregator as agg from . import exc from . import plot diff --git a/autogalaxy/aggregator/agg_util.py b/autogalaxy/aggregator/agg_util.py index c0f2bf7a0..20998f62e 100644 --- a/autogalaxy/aggregator/agg_util.py +++ b/autogalaxy/aggregator/agg_util.py @@ -1,6 +1,8 @@ from __future__ import annotations +import numpy as np from typing import List, Optional +from autoconf.fitsable import flip_for_ds9_from from autoconf.fitsable import ndarray_via_hdu_from import autofit as af @@ -140,9 +142,24 @@ def adapt_images_from( galaxy_name_image_dict[value.header["EXTNAME"].lower()] = adapt_image + galaxy_name_image_plane_mesh_grid_dict = {} + + for i, value in enumerate(fit.value(name="adapt_image_plane_mesh_grids")[1:]): + + adapt_image_plane_mesh_grid = aa.Grid2DIrregular( + values=flip_for_ds9_from(value.data.astype("float")), + ) + + galaxy_name_image_plane_mesh_grid_dict[value.header["EXTNAME"].lower()] = ( + adapt_image_plane_mesh_grid + ) + instance = fit.model.instance_from_prior_medians(ignore_assertions=True) - adapt_images = AdaptImages(galaxy_name_image_dict=galaxy_name_image_dict) + adapt_images = AdaptImages( + galaxy_name_image_dict=galaxy_name_image_dict, + galaxy_name_image_plane_mesh_grid_dict=galaxy_name_image_plane_mesh_grid_dict, + ) adapt_images = adapt_images.updated_via_instance_from( instance=instance, diff --git a/autogalaxy/analysis/adapt_images/adapt_image_maker.py b/autogalaxy/analysis/adapt_images/adapt_image_maker.py deleted file mode 100644 index 5317f8804..000000000 --- a/autogalaxy/analysis/adapt_images/adapt_image_maker.py +++ /dev/null @@ -1,47 +0,0 @@ -from autoconf import cached_property - -from autogalaxy.analysis.adapt_images.adapt_images import AdaptImages - - -class AdaptImageMaker: - def __init__(self, result, use_model_images: bool = False): - """ - Class used for making adapt images on-the-fly for efficient computations. - - Adapt images can be slow to compute, especially for large datasets. When an analysis pipeline is resumed - from already computed results, the adapt images in early fits may not be used. By default, a pipeline would - still recalculate the adapt images for every fit, slowing down the time it takes to resume a pipeline. - - By using the `AdaptImageMaker`, the adapt images are computed on-the-fly during the fit, when and only when - the `adapt_images` attribute of the `Analysis` class is called. This means that if the adapt images are not - used when resuming a pipeline, they are not recalculated, speeding up the time it takes to resume a pipeline. - - Parameters - ---------- - result - The result from a previous stage of the pipeline which contains the information necessary to make the - adapt images. - use_model_images - Whether to use the model images from the result to make the adapt images. If `False`, the galaxies - subtracted images of each dataset are used. - """ - - self.result = result - self.use_model_images = use_model_images - - @cached_property - def adapt_images(self): - """ - Returns the adapt images from the result. - - The adapt images are therefore only computed when this attribute is called, which for pipelines resuming - from already computed results means this function is often omitted, saving computational time. - - This function is cached, therefore once the adapt images are computed they are stored in memory and not - recomputed when this attribute is called again, saving computational time. - - Returns - ------- - The adapt images from the result. - """ - return self.result.adapt_images_from(use_model_images=self.use_model_images) diff --git a/autogalaxy/analysis/adapt_images/adapt_images.py b/autogalaxy/analysis/adapt_images/adapt_images.py index 235aa729a..e10760b1d 100644 --- a/autogalaxy/analysis/adapt_images/adapt_images.py +++ b/autogalaxy/analysis/adapt_images/adapt_images.py @@ -11,11 +11,68 @@ from autogalaxy.galaxy.galaxy import Galaxy +def galaxy_name_image_dict_via_result_from( + result, use_model_images: bool = False +) -> "AdaptImages": + """ + Returns the adapt-images from a non-linear search result. + + For model-fitting, the adapt-images are typically setup using the maximum log likelihood model of the + previous model-fit. This means the model-fitting is used to cleanly deblend the light of the different + galaxies in the image (e.g. separate the lens light from the source light). + + This method uses attributes of a result (e.g. dictionary mapping galaxy instances to their model-images) + to create the adapt-images. + + This can use either: + + - The model image of each galaxy in the best-fit model. + - The subtracted image of each galaxy in the best-fit model, where the subtracted image is the dataset + minus the model images of all other galaxies. + + Certain models produce galaxy-images with negative flux values (e.g. a pixelization), which can cause + numerical issues with the adaptive schemes. To prevent this, we set a minimum flux value for each + galaxy-image, which is a fraction of the maximum flux value of that image defined via a config file. + + Parameters + ---------- + result + The result of a previous model-fit, which contains the model-image of each galaxy. + use_model_images + If True, the model images of the galaxies are used to create the adapt images. If False, the subtracted + images of the galaxies are used. + + Returns + ------- + The adapt-images, which are the model-image of each galaxy inferred via the previous model-fit. + """ + adapt_minimum_percent = conf.instance["general"]["adapt"]["adapt_minimum_percent"] + + galaxy_name_image_dict = {} + + for path, galaxy in result.path_galaxy_tuples: + if use_model_images: + galaxy_image = result.model_image_galaxy_dict[path] + else: + galaxy_image = result.subtracted_signal_to_noise_map_galaxy_dict[path] + + minimum_galaxy_value = adapt_minimum_percent * np.max(galaxy_image.array) + galaxy_image[galaxy_image < minimum_galaxy_value] = minimum_galaxy_value + + galaxy_name_image_dict[path] = galaxy_image + + return galaxy_name_image_dict + + class AdaptImages: def __init__( self, galaxy_image_dict: Optional[Dict[Galaxy, aa.Array2D]] = None, galaxy_name_image_dict: Optional[Dict[Tuple[str, ...], aa.Array2D]] = None, + galaxy_image_plane_mesh_grid_dict: Optional[Dict[Galaxy, aa.Array2D]] = None, + galaxy_name_image_plane_mesh_grid_dict: Optional[ + Dict[Tuple[str, ...], aa.Grid2DIrregular] + ] = None, ): """ Contains the adapt-images which are used to make a pixelization's mesh and regularization adapt to the @@ -54,6 +111,11 @@ def __init__( self.galaxy_image_dict = galaxy_image_dict self.galaxy_name_image_dict = galaxy_name_image_dict + self.galaxy_image_plane_mesh_grid_dict = galaxy_image_plane_mesh_grid_dict + self.galaxy_name_image_plane_mesh_grid_dict = ( + galaxy_name_image_plane_mesh_grid_dict + ) + @property def mask(self) -> aa.Mask2D: """ @@ -85,59 +147,6 @@ def model_image(self) -> aa.Array2D: return adapt_model_image - @classmethod - def from_result(cls, result, use_model_images: bool = False) -> "AdaptImages": - """ - Returns the adapt-images from a non-linear search result. - - For model-fitting, the adapt-images are typically setup using the maximum log likelihood model of the - previous model-fit. This means the model-fitting is used to cleanly deblend the light of the different - galaxies in the image (e.g. separate the lens light from the source light). - - This method uses attributes of a result (e.g. dictionary mapping galaxy instances to their model-images) - to create the adapt-images. - - This can use either: - - - The model image of each galaxy in the best-fit model. - - The subtracted image of each galaxy in the best-fit model, where the subtracted image is the dataset - minus the model images of all other galaxies. - - Certain models produce galaxy-images with negative flux values (e.g. a pixelization), which can cause - numerical issues with the adaptive schemes. To prevent this, we set a minimum flux value for each - galaxy-image, which is a fraction of the maximum flux value of that image defined via a config file. - - Parameters - ---------- - result - The result of a previous model-fit, which contains the model-image of each galaxy. - use_model_images - If True, the model images of the galaxies are used to create the adapt images. If False, the subtracted - images of the galaxies are used. - - Returns - ------- - The adapt-images, which are the model-image of each galaxy inferred via the previous model-fit. - """ - adapt_minimum_percent = conf.instance["general"]["adapt"][ - "adapt_minimum_percent" - ] - - galaxy_name_image_dict = {} - - for path, galaxy in result.path_galaxy_tuples: - if use_model_images: - galaxy_image = result.model_image_galaxy_dict[path] - else: - galaxy_image = result.subtracted_signal_to_noise_map_galaxy_dict[path] - - minimum_galaxy_value = adapt_minimum_percent * np.max(galaxy_image.array) - galaxy_image[galaxy_image < minimum_galaxy_value] = minimum_galaxy_value - - galaxy_name_image_dict[path] = galaxy_image - - return AdaptImages(galaxy_name_image_dict=galaxy_name_image_dict) - def updated_via_instance_from(self, instance, mask=None) -> "AdaptImages": """ Returns adapt-images which have been updated to map galaxy instances instead of galaxy names. @@ -168,16 +177,37 @@ def updated_via_instance_from(self, instance, mask=None) -> "AdaptImages": """ from autogalaxy.galaxy.galaxy import Galaxy - galaxy_image_dict = {} + galaxy_image_dict = None + + if self.galaxy_name_image_dict is not None: + + galaxy_image_dict = {} + + for galaxy_name, galaxy in instance.path_instance_tuples_for_class(Galaxy): + galaxy_name = str(galaxy_name) - for galaxy_name, galaxy in instance.path_instance_tuples_for_class(Galaxy): - galaxy_name = str(galaxy_name) + if galaxy_name in self.galaxy_name_image_dict: + galaxy_image_dict[galaxy] = self.galaxy_name_image_dict[galaxy_name] - if galaxy_name in self.galaxy_name_image_dict: - galaxy_image_dict[galaxy] = self.galaxy_name_image_dict[galaxy_name] + if mask is not None: + for key, image in galaxy_image_dict.items(): + galaxy_image_dict[key] = aa.Array2D(values=image, mask=mask) - if mask is not None: - for key, image in galaxy_image_dict.items(): - galaxy_image_dict[key] = aa.Array2D(values=image, mask=mask) + galaxy_image_plane_mesh_grid_dict = None - return AdaptImages(galaxy_image_dict=galaxy_image_dict) + if self.galaxy_name_image_plane_mesh_grid_dict is not None: + + galaxy_image_plane_mesh_grid_dict = {} + + for galaxy_name, galaxy in instance.path_instance_tuples_for_class(Galaxy): + galaxy_name = str(galaxy_name) + + if galaxy_name in self.galaxy_name_image_plane_mesh_grid_dict: + galaxy_image_plane_mesh_grid_dict[galaxy] = ( + self.galaxy_name_image_plane_mesh_grid_dict[galaxy_name] + ) + + return AdaptImages( + galaxy_image_dict=galaxy_image_dict, + galaxy_image_plane_mesh_grid_dict=galaxy_image_plane_mesh_grid_dict, + ) diff --git a/autogalaxy/analysis/analysis/dataset.py b/autogalaxy/analysis/analysis/dataset.py index 467c51e46..54e7b48bd 100644 --- a/autogalaxy/analysis/analysis/dataset.py +++ b/autogalaxy/analysis/analysis/dataset.py @@ -7,7 +7,6 @@ import autofit as af import autoarray as aa -from autogalaxy.analysis.adapt_images.adapt_image_maker import AdaptImageMaker from autogalaxy.analysis.adapt_images.adapt_images import AdaptImages from autogalaxy.cosmology.lensing import LensingCosmology from autogalaxy.analysis.analysis.analysis import Analysis @@ -22,7 +21,7 @@ class AnalysisDataset(Analysis): def __init__( self, dataset: Union[aa.Imaging, aa.Interferometer], - adapt_image_maker: Optional[AdaptImageMaker] = None, + adapt_images: Optional[AdaptImages] = None, cosmology: LensingCosmology = None, settings_inversion: aa.SettingsInversion = None, preloads: aa.Preloads = None, @@ -41,8 +40,8 @@ def __init__( ---------- dataset The dataset that is the model is fitted too. - adapt_image_maker - Makes the adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are + adapt_images + The adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are used by certain classes for adapting the analysis to the properties of the dataset. cosmology The Cosmology assumed for this analysis. @@ -61,26 +60,12 @@ def __init__( ) self.dataset = dataset - self.adapt_image_maker = adapt_image_maker - self._adapt_images = None + self.adapt_images = adapt_images self.settings_inversion = settings_inversion or aa.SettingsInversion() self.title_prefix = title_prefix - @property - def adapt_images(self): - - if self._adapt_images is not None: - return self._adapt_images - - if self.adapt_image_maker is None: - return None - - self._adapt_images = self.adapt_image_maker.adapt_images - - return self._adapt_images - def modify_before_fit(self, paths: af.DirectoryPaths, model: af.Collection): """ This function is called immediately before the non-linear search begins and performs final tasks and checks @@ -119,10 +104,6 @@ def modify_before_fit(self, paths: af.DirectoryPaths, model: af.Collection): self.dataset.grids.border_relocator - if self.adapt_image_maker is not None: - if not paths.is_complete: - self._adapt_images = self.adapt_image_maker.adapt_images - super().modify_before_fit(paths=paths, model=model) return self diff --git a/autogalaxy/analysis/chaining_util.py b/autogalaxy/analysis/chaining_util.py index 95306e45f..ee4d35323 100644 --- a/autogalaxy/analysis/chaining_util.py +++ b/autogalaxy/analysis/chaining_util.py @@ -109,7 +109,6 @@ def source_custom_model_from(result: Result, source_is_model: bool = False) -> a if source_is_model: pixelization = af.Model( aa.Pixelization, - image_mesh=result.instance.galaxies.source.pixelization.image_mesh, mesh=result.instance.galaxies.source.pixelization.mesh, regularization=result.model.galaxies.source.pixelization.regularization, ) @@ -122,7 +121,6 @@ def source_custom_model_from(result: Result, source_is_model: bool = False) -> a pixelization = af.Model( aa.Pixelization, - image_mesh=result.instance.galaxies.source.pixelization.image_mesh, mesh=result.instance.galaxies.source.pixelization.mesh, regularization=result.instance.galaxies.source.pixelization.regularization, ) diff --git a/autogalaxy/analysis/plotter_interface.py b/autogalaxy/analysis/plotter_interface.py index 1ee0acde9..8719301df 100644 --- a/autogalaxy/analysis/plotter_interface.py +++ b/autogalaxy/analysis/plotter_interface.py @@ -1,5 +1,6 @@ from __future__ import annotations import csv +import numpy as np import os from typing import List, Union, TYPE_CHECKING @@ -279,25 +280,50 @@ def should_plot(name): mat_plot_2d=mat_plot_2d, ) - if should_plot("subplot_adapt_images"): - adapt_plotter.subplot_adapt_images( - adapt_galaxy_name_image_dict=adapt_images.galaxy_name_image_dict - ) + if adapt_images.galaxy_name_image_dict is not None: + + if should_plot("subplot_adapt_images"): + adapt_plotter.subplot_adapt_images( + adapt_galaxy_name_image_dict=adapt_images.galaxy_name_image_dict + ) if should_plot("fits_adapt_images"): - image_list = [ - adapt_images.galaxy_name_image_dict[name].native_for_fits - for name in adapt_images.galaxy_name_image_dict.keys() - ] - hdu_list = hdu_list_for_output_from( - values_list=[ - image_list[0].mask.astype("float"), + if adapt_images.galaxy_name_image_dict is not None: + + image_list = [ + adapt_images.galaxy_name_image_dict[name].native_for_fits + for name in adapt_images.galaxy_name_image_dict.keys() + ] + + hdu_list = hdu_list_for_output_from( + values_list=[ + image_list[0].mask.astype("float"), + ] + + image_list, + ext_name_list=["mask"] + + list(adapt_images.galaxy_name_image_dict.keys()), + header_dict=adapt_images.mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "adapt_images.fits", overwrite=True) + + if adapt_images.galaxy_name_image_plane_mesh_grid_dict is not None: + + image_plane_mesh_grid_list = [ + adapt_images.galaxy_name_image_plane_mesh_grid_dict[name].native + for name in adapt_images.galaxy_name_image_plane_mesh_grid_dict.keys() ] - + image_list, - ext_name_list=["mask"] - + list(adapt_images.galaxy_name_image_dict.keys()), - header_dict=adapt_images.mask.header_dict, - ) - hdu_list.writeto(self.image_path / "adapt_images.fits", overwrite=True) + print(list(adapt_images.galaxy_name_image_plane_mesh_grid_dict.keys())) + + hdu_list = hdu_list_for_output_from( + values_list=[np.array([1])] + image_plane_mesh_grid_list, + ext_name_list=[""] + + list(adapt_images.galaxy_name_image_plane_mesh_grid_dict.keys()), + ) + + hdu_list.writeto( + self.image_path / "adapt_image_plane_mesh_grids.fits", + overwrite=True, + ) diff --git a/autogalaxy/analysis/result.py b/autogalaxy/analysis/result.py index 8557d5409..58d76a46c 100644 --- a/autogalaxy/analysis/result.py +++ b/autogalaxy/analysis/result.py @@ -120,33 +120,3 @@ def subtracted_signal_to_noise_map_galaxy_dict(self) -> Dict[str, Galaxy]: galaxy_path: galaxy_subtracted_signal_to_noise_map_dict[galaxy] for galaxy_path, galaxy in self.path_galaxy_tuples } - - def adapt_images_from(self, use_model_images: bool = False) -> AdaptImages: - """ - Returns the adapt-images which are used to make a pixelization's mesh and regularization adapt to the - reconstructed galaxy's morphology. - - This can use either: - - - The model image of each galaxy in the best-fit model. - - The subtracted image of each galaxy in the best-fit model, where the subtracted image is the dataset - minus the model images of all other galaxies. - - In **PyAutoLens** these adapt images have had lensing calculations performed on them and therefore for source - galaxies are their lensed model images in the image-plane. - - Parameters - ---------- - use_model_images - If True, the model images of the galaxies are used to create the adapt images. If False, the subtracted - images of the galaxies are used. - """ - - return AdaptImages.from_result( - result=self, - use_model_images=use_model_images, - ) - - @property - def adapt_image_maker(self): - return self.analysis.adapt_image_maker diff --git a/autogalaxy/config/priors/image_mesh/README.rst b/autogalaxy/config/priors/image_mesh/README.rst deleted file mode 100644 index 3f7a402af..000000000 --- a/autogalaxy/config/priors/image_mesh/README.rst +++ /dev/null @@ -1,6 +0,0 @@ -The ``image_mesh`` folder contains configuration files for the default priors assumed for ``image_mesh`` objects. - -These model components construct the (y,x) grid of coordinates used for a mesh in the image-plane. - -For example, the `KMeans` image-mesh computes the centres of the image mesh by running a KMeans clustering algorithm -on the data, and clusters points in its brighter regions. \ No newline at end of file diff --git a/autogalaxy/config/priors/image_mesh/hilbert.yaml b/autogalaxy/config/priors/image_mesh/hilbert.yaml deleted file mode 100644 index 038fc4d85..000000000 --- a/autogalaxy/config/priors/image_mesh/hilbert.yaml +++ /dev/null @@ -1,31 +0,0 @@ -Hilbert: - pixels: - type: Uniform - lower_limit: 50.0 - upper_limit: 2500.0 - width_modifier: - type: Absolute - value: 100.0 - limits: - lower: 50.0 - upper: inf - weight_floor: - type: LogUniform - lower_limit: 0.00001 - upper_limit: 1.0 - width_modifier: - type: Absolute - value: 0.1 - limits: - lower: 0.0 - upper: inf - weight_power: - type: Uniform - lower_limit: 0.0 - upper_limit: 5.0 - width_modifier: - type: Absolute - value: 5.0 - limits: - lower: 0.0 - upper: inf \ No newline at end of file diff --git a/autogalaxy/config/priors/image_mesh/kmeans.yaml b/autogalaxy/config/priors/image_mesh/kmeans.yaml deleted file mode 100644 index ece8c704e..000000000 --- a/autogalaxy/config/priors/image_mesh/kmeans.yaml +++ /dev/null @@ -1,31 +0,0 @@ -KMeans: - pixels: - type: Uniform - lower_limit: 50.0 - upper_limit: 2500.0 - width_modifier: - type: Absolute - value: 100.0 - limits: - lower: 50.0 - upper: inf - weight_floor: - type: LogUniform - lower_limit: 0.00001 - upper_limit: 1.0 - width_modifier: - type: Absolute - value: 0.1 - limits: - lower: 0.0 - upper: inf - weight_power: - type: Uniform - lower_limit: 0.0 - upper_limit: 5.0 - width_modifier: - type: Absolute - value: 5.0 - limits: - lower: 0.0 - upper: inf \ No newline at end of file diff --git a/autogalaxy/config/priors/image_mesh/overlay.yaml b/autogalaxy/config/priors/image_mesh/overlay.yaml deleted file mode 100644 index 17c283ab0..000000000 --- a/autogalaxy/config/priors/image_mesh/overlay.yaml +++ /dev/null @@ -1,21 +0,0 @@ -Overlay: - shape_0: - type: Uniform - lower_limit: 20.0 - upper_limit: 45.0 - width_modifier: - type: Absolute - value: 8.0 - limits: - lower: 3.0 - upper: inf - shape_1: - type: Uniform - lower_limit: 20.0 - upper_limit: 45.0 - width_modifier: - type: Absolute - value: 8.0 - limits: - lower: 3.0 - upper: inf \ No newline at end of file diff --git a/autogalaxy/fixtures.py b/autogalaxy/fixtures.py index a245b9b96..569c8a805 100644 --- a/autogalaxy/fixtures.py +++ b/autogalaxy/fixtures.py @@ -215,9 +215,27 @@ def make_adapt_galaxy_name_image_dict_7x7(): return adapt_galaxy_name_image_dict +def make_adapt_galaxy_name_image_plane_mesh_grid_dict_7x7(): + image_plane_mesh_grid_0 = ag.Grid2DIrregular( + values=[(0.0, 0.0), (1.0, 1.0), (2.0, 2.0)] + ) + + image_plane_mesh_grid_1 = ag.Grid2DIrregular( + values=[(3.0, 3.0), (4.0, 4.0), (5.0, 5.0)] + ) + + adapt_galaxy_name_image_plane_mesh_grid_dict = { + str(("galaxies", "g0")): image_plane_mesh_grid_0, + str(("galaxies", "g1")): image_plane_mesh_grid_1, + } + + return adapt_galaxy_name_image_plane_mesh_grid_dict + + def make_adapt_images_7x7(): return ag.AdaptImages( galaxy_name_image_dict=make_adapt_galaxy_name_image_dict_7x7(), + galaxy_name_image_plane_mesh_grid_dict=make_adapt_galaxy_name_image_plane_mesh_grid_dict_7x7(), ) @@ -261,15 +279,18 @@ def make_samples_summary_with_result(): def make_analysis_imaging_7x7(): analysis = ag.AnalysisImaging( dataset=make_masked_imaging_7x7(), + adapt_images=make_adapt_images_7x7(), use_jax=False, ) - analysis._adapt_images = make_adapt_images_7x7() return analysis def make_analysis_interferometer_7(): - analysis = ag.AnalysisInterferometer(dataset=make_interferometer_7(), use_jax=False) - analysis._adapt_images = make_adapt_images_7x7() + analysis = ag.AnalysisInterferometer( + dataset=make_interferometer_7(), + adapt_images=make_adapt_images_7x7(), + use_jax=False, + ) return analysis diff --git a/autogalaxy/galaxy/to_inversion.py b/autogalaxy/galaxy/to_inversion.py index cf86a2c83..ee3db53fa 100644 --- a/autogalaxy/galaxy/to_inversion.py +++ b/autogalaxy/galaxy/to_inversion.py @@ -396,34 +396,11 @@ def image_plane_mesh_grid_list( image_plane_mesh_grid_list = [] for galaxy in self.galaxies.galaxies_with_cls_list_from(cls=aa.Pixelization): - pixelization = galaxy.cls_list_from(cls=aa.Pixelization)[0] - - if pixelization.image_mesh is not None: - try: - adapt_data = self.adapt_images.galaxy_image_dict[galaxy] - except (AttributeError, KeyError): - adapt_data = None - - if pixelization.image_mesh.uses_adapt_images: - raise aa.exc.PixelizationException( - """ - Attempted to perform fit using a pixelization which requires an - image-mesh (E.g. KMeans, Hilbert). - - However, the adapt-images passed to the fit (E.g. FitImaging, FitInterferometer) - is None. Without an adapt image, an image-mesh cannot be used. - """ - ) - + try: image_plane_mesh_grid = ( - pixelization.image_mesh.image_plane_mesh_grid_from( - mask=self.dataset.mask, - adapt_data=adapt_data, - settings=self.settings_inversion, - ) + self.adapt_images.galaxy_image_plane_mesh_grid_dict[galaxy] ) - - else: + except (AttributeError, KeyError, TypeError): image_plane_mesh_grid = None image_plane_mesh_grid_list.append(image_plane_mesh_grid) diff --git a/autogalaxy/imaging/model/analysis.py b/autogalaxy/imaging/model/analysis.py index c7ad8e36f..30314bacd 100644 --- a/autogalaxy/imaging/model/analysis.py +++ b/autogalaxy/imaging/model/analysis.py @@ -4,7 +4,7 @@ import autofit as af import autoarray as aa -from autogalaxy.analysis.adapt_images.adapt_image_maker import AdaptImageMaker +from autogalaxy.analysis.adapt_images.adapt_images import AdaptImages from autogalaxy.analysis.analysis.dataset import AnalysisDataset from autogalaxy.cosmology.lensing import LensingCosmology from autogalaxy.imaging.model.result import ResultImaging @@ -19,7 +19,7 @@ class AnalysisImaging(AnalysisDataset): def __init__( self, dataset: aa.Imaging, - adapt_image_maker: Optional[AdaptImageMaker] = None, + adapt_images: Optional[AdaptImages] = None, cosmology: LensingCosmology = None, settings_inversion: aa.SettingsInversion = None, preloads: aa.Preloads = None, @@ -45,8 +45,8 @@ def __init__( ---------- dataset The `Imaging` dataset that the model is fitted to. - adapt_image_maker - Makes the adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are + adapt_images + The adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are used by certain classes for adapting the analysis to the properties of the dataset. cosmology The Cosmology assumed for this analysis. @@ -58,7 +58,7 @@ def __init__( """ super().__init__( dataset=dataset, - adapt_image_maker=adapt_image_maker, + adapt_images=adapt_images, cosmology=cosmology, settings_inversion=settings_inversion, preloads=preloads, diff --git a/autogalaxy/interferometer/model/analysis.py b/autogalaxy/interferometer/model/analysis.py index aa7559da4..dea6dad9b 100644 --- a/autogalaxy/interferometer/model/analysis.py +++ b/autogalaxy/interferometer/model/analysis.py @@ -7,7 +7,7 @@ import autofit as af import autoarray as aa -from autogalaxy.analysis.adapt_images.adapt_image_maker import AdaptImageMaker +from autogalaxy.analysis.adapt_images.adapt_images import AdaptImages from autogalaxy.analysis.analysis.dataset import AnalysisDataset from autogalaxy.cosmology.lensing import LensingCosmology from autogalaxy.interferometer.model.result import ResultInterferometer @@ -26,7 +26,7 @@ class AnalysisInterferometer(AnalysisDataset): def __init__( self, dataset: aa.Interferometer, - adapt_image_maker: Optional[AdaptImageMaker] = None, + adapt_images: Optional[AdaptImages] = None, cosmology: LensingCosmology = None, settings_inversion: aa.SettingsInversion = None, preloads: aa.Preloads = None, @@ -52,8 +52,8 @@ def __init__( ---------- dataset The interferometer dataset that the model is fitted too. - adapt_image_maker - Makes the adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are + adapt_images + The adapt-model image and galaxies images of a previous result in a model-fitting pipeline, which are used by certain classes for adapting the analysis to the properties of the dataset. cosmology The Cosmology assumed for this analysis. @@ -65,7 +65,7 @@ def __init__( """ super().__init__( dataset=dataset, - adapt_image_maker=adapt_image_maker, + adapt_images=adapt_images, cosmology=cosmology, settings_inversion=settings_inversion, preloads=preloads, diff --git a/autogalaxy/plot/visuals/two_d.py b/autogalaxy/plot/visuals/two_d.py index 1a44e245e..20f529155 100644 --- a/autogalaxy/plot/visuals/two_d.py +++ b/autogalaxy/plot/visuals/two_d.py @@ -81,9 +81,12 @@ def plot_via_plotter(self, plotter, grid_indexes=None): ) if self.multiple_images is not None: - plotter.multiple_images_scatter.scatter_grid( - grid=self.multiple_images.array - ) + try: + plotter.multiple_images_scatter.scatter_grid( + grid=self.multiple_images.array + ) + except (AttributeError, ValueError): + plotter.multiple_images_scatter.scatter_grid(grid=self.multiple_images) if self.tangential_critical_curves is not None: try: diff --git a/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py b/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py index 9c7db3ead..bc7f6710d 100644 --- a/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py +++ b/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py @@ -193,6 +193,26 @@ def test__fit_imaging__adapt_images(agg_7x7, adapt_images_7x7): == list(adapt_images_7x7.galaxy_name_image_dict.values())[0] ).all() + print( + list( + fit_list[0].adapt_images.galaxy_image_plane_mesh_grid_dict.values() + )[0] + ) + print( + list(adapt_images_7x7.galaxy_name_image_plane_mesh_grid_dict.values())[ + 0 + ] + ) + + assert ( + list( + fit_list[0].adapt_images.galaxy_image_plane_mesh_grid_dict.values() + )[0] + == list( + adapt_images_7x7.galaxy_name_image_plane_mesh_grid_dict.values() + )[0] + ).all() + assert i == 2 # clean(database_file=database_file) diff --git a/test_autogalaxy/aggregator/interferometer/test_aggregator_fit_interferometer.py b/test_autogalaxy/aggregator/interferometer/test_aggregator_fit_interferometer.py index f62b59fee..603224c1b 100644 --- a/test_autogalaxy/aggregator/interferometer/test_aggregator_fit_interferometer.py +++ b/test_autogalaxy/aggregator/interferometer/test_aggregator_fit_interferometer.py @@ -113,7 +113,9 @@ def test__fit_interferometer__adapt_images( model, adapt_images_7x7, ): - analysis = ag.AnalysisInterferometer(dataset=interferometer_7, use_jax=False) + analysis = ag.AnalysisInterferometer( + dataset=interferometer_7, adapt_images=adapt_images_7x7, use_jax=False + ) analysis._adapt_images = adapt_images_7x7 agg = aggregator_from( @@ -137,6 +139,15 @@ def test__fit_interferometer__adapt_images( == list(adapt_images_7x7.galaxy_name_image_dict.values())[0] ).all() + assert ( + list( + fit_list[0].adapt_images.galaxy_image_plane_mesh_grid_dict.values() + )[0] + == list( + adapt_images_7x7.galaxy_name_image_plane_mesh_grid_dict.values() + )[0] + ).all() + assert i == 2 clean(database_file=database_file) diff --git a/test_autogalaxy/analysis/analysis/test_analysis_dataset.py b/test_autogalaxy/analysis/analysis/test_analysis_dataset.py index 5bad3cbf9..c0cb01888 100644 --- a/test_autogalaxy/analysis/analysis/test_analysis_dataset.py +++ b/test_autogalaxy/analysis/analysis/test_analysis_dataset.py @@ -8,7 +8,9 @@ directory = path.dirname(path.realpath(__file__)) -def test__instance_with_associated_adapt_images_from(masked_imaging_7x7): +def test__instance_with_associated_adapt_images_from__galaxy_name_image_dict( + masked_imaging_7x7, +): galaxies = af.ModelInstance() galaxies.galaxy = ag.Galaxy(redshift=0.5) galaxies.source = ag.Galaxy(redshift=1.0) @@ -16,7 +18,7 @@ def test__instance_with_associated_adapt_images_from(masked_imaging_7x7): instance = af.ModelInstance() instance.galaxies = galaxies - adapt_galaxy_name_image_dict = { + galaxy_name_image_dict = { str(("galaxies", "galaxy")): ag.Array2D.ones( shape_native=(3, 3), pixel_scales=1.0 ), @@ -26,11 +28,12 @@ def test__instance_with_associated_adapt_images_from(masked_imaging_7x7): } adapt_images = ag.AdaptImages( - galaxy_name_image_dict=adapt_galaxy_name_image_dict, + galaxy_name_image_dict=galaxy_name_image_dict, ) - analysis = ag.AnalysisImaging(dataset=masked_imaging_7x7, use_jax=False) - analysis._adapt_images = adapt_images + analysis = ag.AnalysisImaging( + dataset=masked_imaging_7x7, adapt_images=adapt_images, use_jax=False + ) adapt_images = analysis.adapt_images_via_instance_from(instance=instance) @@ -40,3 +43,40 @@ def test__instance_with_associated_adapt_images_from(masked_imaging_7x7): assert adapt_images.galaxy_image_dict[galaxies.source].native == pytest.approx( 2.0 * np.ones((3, 3)), 1.0e-4 ) + + +def test__instance_with_associated_adapt_images_from__galaxy_name_image_plane_mesh_grid_dict( + masked_imaging_7x7, +): + galaxies = af.ModelInstance() + galaxies.galaxy = ag.Galaxy(redshift=0.5) + galaxies.source = ag.Galaxy(redshift=1.0) + + instance = af.ModelInstance() + instance.galaxies = galaxies + + galaxy_name_image_plane_mesh_grid_dict = { + str(("galaxies", "galaxy")): ag.Grid2DIrregular( + values=[(3.0, 3.0), (3.0, 3.0)] + ), + str(("galaxies", "source")): ag.Grid2DIrregular( + values=[(4.0, 4.0), (4.0, 4.0)] + ), + } + + adapt_images = ag.AdaptImages( + galaxy_name_image_plane_mesh_grid_dict=galaxy_name_image_plane_mesh_grid_dict, + ) + + analysis = ag.AnalysisImaging( + dataset=masked_imaging_7x7, adapt_images=adapt_images, use_jax=False + ) + + adapt_images = analysis.adapt_images_via_instance_from(instance=instance) + + assert adapt_images.galaxy_image_plane_mesh_grid_dict[ + galaxies.galaxy + ].native == pytest.approx(3.0 * np.ones((2, 2)), 1.0e-4) + assert adapt_images.galaxy_image_plane_mesh_grid_dict[ + galaxies.source + ].native == pytest.approx(4.0 * np.ones((2, 2)), 1.0e-4) diff --git a/test_autogalaxy/galaxy/test_galaxy.py b/test_autogalaxy/galaxy/test_galaxy.py index 6922a1a41..b1cb27679 100644 --- a/test_autogalaxy/galaxy/test_galaxy.py +++ b/test_autogalaxy/galaxy/test_galaxy.py @@ -638,7 +638,6 @@ def test__output_to_and_load_from_json(): light=ag.lp.Sersic(intensity=1.0), mass=ag.mp.Isothermal(einstein_radius=1.0), pixelization=ag.Pixelization( - image_mesh=ag.image_mesh.Overlay(shape=(3, 3)), mesh=ag.mesh.Voronoi(), regularization=ag.reg.Constant(), ), @@ -651,4 +650,3 @@ def test__output_to_and_load_from_json(): assert galaxy_from_json.redshift == 1.0 assert galaxy_from_json.light.intensity == 1.0 assert galaxy_from_json.mass.einstein_radius == 1.0 - assert galaxy_from_json.pixelization.image_mesh.shape == (3, 3) diff --git a/test_autogalaxy/galaxy/test_to_inversion.py b/test_autogalaxy/galaxy/test_to_inversion.py index a767cb7ac..dcf87d2bf 100644 --- a/test_autogalaxy/galaxy/test_to_inversion.py +++ b/test_autogalaxy/galaxy/test_to_inversion.py @@ -56,35 +56,37 @@ def test__lp_linear_func_list_galaxy_dict(lp_0, masked_imaging_7x7): def test__image_plane_mesh_grid_list(masked_imaging_7x7): - pixelization = ag.m.MockPixelization( - image_mesh=ag.m.MockImageMesh(image_plane_mesh_grid=np.array([1.0, 1.0])) + + pixelization = ag.m.MockPixelization() + + galaxy_pix = ag.Galaxy( + redshift=0.5, + pixelization=pixelization, ) - galaxy_pix = ag.Galaxy(redshift=0.5, pixelization=pixelization) + adapt_images = ag.AdaptImages( + galaxy_image_dict={galaxy_pix: 2}, + galaxy_image_plane_mesh_grid_dict={galaxy_pix: 3}, + ) to_inversion = ag.GalaxiesToInversion( - galaxies=[galaxy_pix], - dataset=masked_imaging_7x7, + galaxies=[galaxy_pix], dataset=masked_imaging_7x7, adapt_images=adapt_images ) image_plane_mesh_grid_list = to_inversion.image_plane_mesh_grid_list - assert (image_plane_mesh_grid_list == np.array([[1.0, 1.0]])).all() + assert image_plane_mesh_grid_list[0] == 3 - galaxy_pix = ag.Galaxy( - redshift=0.5, - pixelization=pixelization, - ) - - adapt_images = ag.AdaptImages(galaxy_image_dict={galaxy_pix: 2}) + # No Adapt Images to_inversion = ag.GalaxiesToInversion( - galaxies=[galaxy_pix], dataset=masked_imaging_7x7, adapt_images=adapt_images + galaxies=[galaxy_pix], + dataset=masked_imaging_7x7, ) image_plane_mesh_grid_list = to_inversion.image_plane_mesh_grid_list - assert (image_plane_mesh_grid_list == np.array([[2.0, 2.0]])).all() + assert image_plane_mesh_grid_list[0] is None # No Galalxies