diff --git a/autogalaxy/__init__.py b/autogalaxy/__init__.py index c7c42cca7..edefcac01 100644 --- a/autogalaxy/__init__.py +++ b/autogalaxy/__init__.py @@ -3,7 +3,6 @@ from autoarray.dataset.imaging.dataset import Imaging # noqa from autoarray.dataset.interferometer.dataset import Interferometer # noqa from autoarray.dataset.dataset_model import DatasetModel -from autoarray.dataset.over_sampling import OverSamplingDataset from autoarray.inversion.inversion.mapper_valued import MapperValued from autoarray.inversion.pixelization import mesh # noqa from autoarray.inversion import regularization as reg # noqa @@ -35,11 +34,7 @@ from autoarray.structures.grids.uniform_1d import Grid1D # noqa from autoarray.structures.grids.uniform_2d import Grid2D # noqa from autoarray.structures.grids.irregular_2d import Grid2DIrregular # noqa -from autoarray.structures.grids.irregular_2d import Grid2DIrregularUniform # noqa -from autoarray.operators.over_sampling.uniform import OverSamplingUniform # noqa -from autoarray.operators.over_sampling.uniform import OverSamplerUniform # noqa -from autoarray.operators.over_sampling.iterate import OverSamplingIterate -from autoarray.operators.over_sampling.iterate import OverSamplerIterate +from autoarray.operators.over_sampling.over_sampler import OverSampler # noqa from autoarray.structures.mesh.rectangular_2d import Mesh2DRectangular # noqa from autoarray.structures.mesh.voronoi_2d import Mesh2DVoronoi # noqa from autoarray.structures.mesh.delaunay_2d import Mesh2DDelaunay # noqa @@ -113,4 +108,4 @@ conf.instance.register(__file__) -__version__ = "2024.9.21.2" +__version__ = "2025.1.18.7" diff --git a/autogalaxy/aggregator/__init__.py b/autogalaxy/aggregator/__init__.py index 6594c14d4..ae5067da9 100644 --- a/autogalaxy/aggregator/__init__.py +++ b/autogalaxy/aggregator/__init__.py @@ -6,3 +6,5 @@ from autogalaxy.aggregator.ellipse.ellipses import EllipsesAgg from autogalaxy.aggregator.ellipse.multipoles import MultipolesAgg from autogalaxy.aggregator.ellipse.fit_ellipse import FitEllipseAgg +from autogalaxy.aggregator.subplot import SubplotDataset as subplot_dataset +from autogalaxy.aggregator.subplot import SubplotFit as subplot_fit \ No newline at end of file diff --git a/autogalaxy/aggregator/dataset_model.py b/autogalaxy/aggregator/dataset_model.py index a43e41192..bb585705a 100644 --- a/autogalaxy/aggregator/dataset_model.py +++ b/autogalaxy/aggregator/dataset_model.py @@ -47,16 +47,17 @@ def _dataset_model_from( except AttributeError: dataset_model = None - if len(fit.children) > 0: - logger.info( - """ - Using database for a fit with multiple summed Analysis objects. - - DatasetModel objects do not fully support this yet (e.g. variables across Analysis objects may not be correct) - so proceed with caution! - """ - ) - - return [dataset_model] * len(fit.children) + if fit.children is not None: + if len(fit.children) > 0: + logger.info( + """ + Using database for a fit with multiple summed Analysis objects. + + DatasetModel objects do not fully support this yet (e.g. variables across Analysis objects may not be correct) + so proceed with caution! + """ + ) + + return [dataset_model] * len(fit.children) return [dataset_model] diff --git a/autogalaxy/aggregator/galaxies.py b/autogalaxy/aggregator/galaxies.py index ed1c3224e..b52b27634 100644 --- a/autogalaxy/aggregator/galaxies.py +++ b/autogalaxy/aggregator/galaxies.py @@ -42,13 +42,15 @@ def _galaxies_from(fit: af.Fit, instance: af.ModelInstance) -> List[Galaxy]: galaxies = instance.galaxies if hasattr(instance, "extra_galaxies"): - galaxies = galaxies + fit.instance.extra_galaxies + if fit.instance.extra_galaxies is not None: + galaxies = galaxies + fit.instance.extra_galaxies else: galaxies = fit.instance.galaxies if hasattr(fit.instance, "extra_galaxies"): - galaxies = galaxies + fit.instance.extra_galaxies + if fit.instance.extra_galaxies is not None: + galaxies = galaxies + fit.instance.extra_galaxies if fit.children is not None: if len(fit.children) > 0: diff --git a/autogalaxy/aggregator/imaging/imaging.py b/autogalaxy/aggregator/imaging/imaging.py index 9a30e7852..461e57c02 100644 --- a/autogalaxy/aggregator/imaging/imaging.py +++ b/autogalaxy/aggregator/imaging/imaging.py @@ -50,13 +50,10 @@ def _imaging_from( except AttributeError: psf = None - over_sampling = fit.value(name="dataset.over_sampling") - dataset = aa.Imaging( data=data, noise_map=noise_map, psf=psf, - over_sampling=over_sampling, check_noise_map=False, ) @@ -64,6 +61,29 @@ def _imaging_from( dataset = dataset.apply_mask(mask=mask) + try: + over_sample_size_lp = aa.Array2D.from_primary_hdu( + primary_hdu=fit.value(name="dataset.over_sample_size_lp") + ).native + over_sample_size_lp = over_sample_size_lp.apply_mask(mask=mask) + except AttributeError: + over_sample_size_lp = 1 + + try: + over_sample_size_pixelization = aa.Array2D.from_primary_hdu( + primary_hdu=fit.value(name="dataset.over_sample_size_pixelization") + ).native + over_sample_size_pixelization = over_sample_size_pixelization.apply_mask( + mask=mask + ) + except AttributeError: + over_sample_size_pixelization = 1 + + dataset = dataset.apply_over_sampling( + over_sample_size_lp=over_sample_size_lp, + over_sample_size_pixelization=over_sample_size_pixelization, + ) + dataset_list.append(dataset) return dataset_list diff --git a/autogalaxy/aggregator/interferometer/interferometer.py b/autogalaxy/aggregator/interferometer/interferometer.py index 7f7dfa2a7..1408254e4 100644 --- a/autogalaxy/aggregator/interferometer/interferometer.py +++ b/autogalaxy/aggregator/interferometer/interferometer.py @@ -56,7 +56,6 @@ def _interferometer_from( ) ) - over_sampling = fit.value(name="dataset.over_sampling") transformer_class = fit.value(name="dataset.transformer_class") dataset = aa.Interferometer( @@ -64,7 +63,6 @@ def _interferometer_from( noise_map=noise_map, uv_wavelengths=uv_wavelengths, real_space_mask=real_space_mask, - over_sampling=over_sampling, transformer_class=transformer_class, ) diff --git a/autogalaxy/aggregator/subplot.py b/autogalaxy/aggregator/subplot.py new file mode 100644 index 000000000..5cf44a7af --- /dev/null +++ b/autogalaxy/aggregator/subplot.py @@ -0,0 +1,31 @@ +from enum import Enum + +class SubplotDataset(Enum): + """ + The subplots that can be extracted from the subplot_fit image. + + The values correspond to the position of the subplot in the 4x3 grid. + """ + + data = (0, 0) + data_log_10 = (1, 0) + noise_map = (2, 0) + psf = (0, 1) + psf_log_10 = (1, 1) + signal_to_noise_map = (2, 1) + over_sample_size_lp = (0, 2) + over_sample_Size_pixelization = (1, 2) + +class SubplotFit(Enum): + """ + The subplots that can be extracted from the subplot_fit image. + + The values correspond to the position of the subplot in the 4x3 grid. + """ + + data = (0, 0) + signal_to_noise_map = (1, 0) + model_image = (2, 0) + normalized_residual_map = (0, 1) + normalized_residual_map_one_sigma = (1, 1) + chi_squared_map = (2, 1) \ No newline at end of file diff --git a/autogalaxy/analysis/analysis/analysis.py b/autogalaxy/analysis/analysis/analysis.py index 0c25b68ef..ae583b03c 100644 --- a/autogalaxy/analysis/analysis/analysis.py +++ b/autogalaxy/analysis/analysis/analysis.py @@ -60,7 +60,7 @@ def galaxies_via_instance_from( if getattr(instance, "extra_galaxies", None) is not None: return Galaxies( galaxies=instance.galaxies + instance.extra_galaxies, - run_time_dict=run_time_dict + run_time_dict=run_time_dict, ) return Galaxies(galaxies=instance.galaxies, run_time_dict=run_time_dict) @@ -139,7 +139,7 @@ def profile_log_likelihood_function( An `info_dict` is also created which stores information on aspects of the model and dataset that dictate run times, so the profiled times can be interpreted with this context. - The results of this profiling are then output to hard-disk in the `prefiling` folder of the model-fit results, + The results of this profiling are then output to hard-disk in the `profiling` folder of the model-fit results, which they can be inspected to ensure run-times are as expected. Parameters @@ -191,19 +191,19 @@ def profile_log_likelihood_function( fit.figure_of_merit try: - info_dict["image_pixels"] = self.dataset.grids.uniform.shape_slim - info_dict["sub_total_light_profiles"] = ( - self.dataset.grids.uniform.over_sampler.sub_total - ) + info_dict["image_pixels"] = self.dataset.grids.lp.shape_slim + info_dict[ + "sub_total_light_profiles" + ] = self.dataset.grids.lp.over_sampler.sub_total except AttributeError: pass if fit.model_obj.has(cls=aa.Pixelization): info_dict["use_w_tilde"] = fit.inversion.settings.use_w_tilde try: - info_dict["sub_total_pixelization"] = ( - self.dataset.grids.pixelization.over_sampler.sub_total - ) + info_dict[ + "sub_total_pixelization" + ] = self.dataset.grids.pixelization.over_sampler.sub_total except AttributeError: pass info_dict["use_positive_only_solver"] = ( diff --git a/autogalaxy/analysis/analysis/dataset.py b/autogalaxy/analysis/analysis/dataset.py index 4dd25bca4..5e58b4785 100644 --- a/autogalaxy/analysis/analysis/dataset.py +++ b/autogalaxy/analysis/analysis/dataset.py @@ -103,9 +103,14 @@ def save_attributes(self, paths: af.DirectoryPaths): hdu=self.dataset.noise_map.hdu_for_output, prefix="dataset", ) - paths.save_json( - name="over_sampling", - object_dict=to_dict(self.dataset.over_sampling), + paths.save_fits( + name="over_sample_size_lp", + hdu=self.dataset.grids.lp.over_sample_size.native.hdu_for_output, + prefix="dataset", + ) + paths.save_fits( + name="over_sample_size_pixelization", + hdu=self.dataset.grids.pixelization.over_sample_size.native.hdu_for_output, prefix="dataset", ) paths.save_json( diff --git a/autogalaxy/analysis/chaining_util.py b/autogalaxy/analysis/chaining_util.py index 5affa0bc6..930b6a5f6 100644 --- a/autogalaxy/analysis/chaining_util.py +++ b/autogalaxy/analysis/chaining_util.py @@ -204,6 +204,9 @@ def extra_galaxies_from( # extra_galaxies = result.instance.extra_galaxies.as_model((LightProfile, mp.MassProfile,), fixed="centre", prior_pass=True) + if not hasattr(result.instance, "extra_galaxies"): + return None + if result.instance.extra_galaxies is None: return None diff --git a/autogalaxy/analysis/plotter_interface.py b/autogalaxy/analysis/plotter_interface.py index bc5646635..c33e15424 100644 --- a/autogalaxy/analysis/plotter_interface.py +++ b/autogalaxy/analysis/plotter_interface.py @@ -1,6 +1,6 @@ import os from os import path -from typing import Dict, List, Union +from typing import List, Union from autoconf import conf import autoarray as aa @@ -67,19 +67,15 @@ def __init__(self, image_path: str, title_prefix: str = None): os.makedirs(image_path, exist_ok=True) - def mat_plot_1d_from(self, subfolders: str, format: str = "png") -> MatPlot1D: + @property + def fmt(self) -> List[str]: + return conf.instance["visualize"]["plots"]["subplot_format"] + + def mat_plot_1d_from(self) -> MatPlot1D: """ Returns a 1D matplotlib plotting object whose `Output` class uses the `image_path`, such that it outputs images to the `image` folder of the non-linear search. - Parameters - ---------- - subfolders - Subfolders between the `image` folder of the non-linear search and where the images are output. For example, - images associsted with a fit are output to the subfolder `fit`. - format - The format images are output as, e.g. `.png` files. - Returns ------- MatPlot1D @@ -87,24 +83,14 @@ def mat_plot_1d_from(self, subfolders: str, format: str = "png") -> MatPlot1D: """ return MatPlot1D( title=aplt.Title(prefix=self.title_prefix), - output=aplt.Output( - path=path.join(self.image_path, subfolders), format=format - ), + output=aplt.Output(path=path.join(self.image_path), format=self.fmt), ) - def mat_plot_2d_from(self, subfolders, format="png") -> MatPlot2D: + def mat_plot_2d_from(self) -> MatPlot2D: """ Returns a 2D matplotlib plotting object whose `Output` class uses the `image_path`, such that it outputs images to the `image` folder of the non-linear search. - Parameters - ---------- - subfolders - Subfolders between the `image` folder of the non-linear search and where the images are output. For example, - images associsted with a fit are output to the subfolder `fit`. - format - The format images are output as, e.g. `.png` files. - Returns ------- MatPlot2D @@ -112,26 +98,26 @@ def mat_plot_2d_from(self, subfolders, format="png") -> MatPlot2D: """ return MatPlot2D( title=aplt.Title(prefix=self.title_prefix), - output=aplt.Output( - path=path.join(self.image_path, subfolders), format=format - ), + output=aplt.Output(path=path.join(self.image_path), format=self.fmt), ) def galaxies( - self, galaxies: List[Galaxy], grid: aa.type.Grid2DLike, during_analysis: bool + self, + galaxies: List[Galaxy], + grid: aa.type.Grid2DLike, ): """ Visualizes a list of galaxies. - Images are output to the `image` folder of the `image_path` in a subfolder called `galaxies`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood galaxies inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the + `image_path` points to the search's results folder and this function visualizes the maximum log likelihood + galaxies inferred by the search so far. - Visualization includes individual images of attributes of the galaxies (e.g. its image, convergence, deflection - angles) and a subplot of all these attributes on the same figure. + Visualization includes subplots of the individual images of attributes of the galaxies (e.g. its image, + convergence, deflection angles) and .fits files containing these attributes. - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [galaxies] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `galaxies` header. Parameters ---------- @@ -140,8 +126,6 @@ def galaxies( grid A 2D grid of (y,x) arc-second coordinates used to perform ray-tracing, which is the masked grid tied to the dataset. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. """ galaxies = Galaxies(galaxies=galaxies) @@ -149,9 +133,7 @@ def galaxies( def should_plot(name): return plot_setting(section="galaxies", name=name) - subfolders = "galaxies" - - mat_plot_2d = self.mat_plot_2d_from(subfolders=subfolders) + mat_plot_2d = self.mat_plot_2d_from() plotter = GalaxiesPlotter( galaxies=galaxies, @@ -163,37 +145,7 @@ def should_plot(name): if should_plot("subplot_galaxy_images"): plotter.subplot_galaxy_images() - plotter.figures_2d( - image=should_plot("image"), - convergence=should_plot("convergence"), - potential=should_plot("potential"), - deflections_y=should_plot("deflections"), - deflections_x=should_plot("deflections"), - magnification=should_plot("magnification"), - ) - - if not during_analysis and should_plot("all_at_end_png"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders=path.join(subfolders, "end"), - ) - - plotter = GalaxiesPlotter( - galaxies=galaxies, - grid=grid, - mat_plot_2d=mat_plot_2d, - include_2d=self.include_2d, - ) - - plotter.figures_2d( - image=True, - convergence=True, - potential=True, - deflections_y=True, - deflections_x=True, - magnification=True, - ) - - mat_plot_2d = self.mat_plot_2d_from(subfolders="") + mat_plot_2d = self.mat_plot_2d_from() plotter = GalaxiesPlotter( galaxies=galaxies, @@ -205,124 +157,70 @@ def should_plot(name): if should_plot("subplot_galaxies"): plotter.subplot() - if not during_analysis and should_plot("all_at_end_fits"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders=path.join(subfolders, "fits"), format="fits" - ) - - plotter = GalaxiesPlotter( - galaxies=galaxies, - grid=grid, - mat_plot_2d=mat_plot_2d, - include_2d=self.include_2d, - ) - - plotter.figures_2d( - image=True, - convergence=True, - potential=True, - deflections_y=True, - deflections_x=True, - magnification=True, - ) - - def galaxies_1d( - self, galaxies: [List[Galaxy]], grid: aa.type.Grid2DLike, during_analysis: bool - ): - """ - Visualizes a list of `Galaxy` objects. - - Images are output to the `image` folder of the `image_path` in a subfolder called `galaxies`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `Galaxy`'s inferred by the search so far. + mat_plot_1d = self.mat_plot_1d_from() - Visualization includes individual images of attributes of each galaxy (e.g. 1D plots of their image, - convergence) and a subplot of all these attributes on the same figure. - - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [galaxies] header. - - Parameters - ---------- - galaxies - A list of the maximum log likelihood `Galaxy`'s of the non-linear search. - grid - A 2D grid of (y,x) arc-second coordinates used to perform ray-tracing, which is the masked grid tied to - the dataset. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. - """ - - def should_plot(name): - return plot_setting(section="galaxies_1d", name=name) + galaxies_plotter = GalaxiesPlotter( + galaxies=galaxies, + grid=grid, + mat_plot_1d=mat_plot_1d, + ) - mat_plot_1d = self.mat_plot_1d_from(subfolders="galaxies_1d") + try: + if should_plot("subplot_galaxies_1d"): + galaxies_plotter.subplot_galaxies_1d() + except OverflowError: + pass - for galaxy in galaxies: - galaxy_plotter = GalaxyPlotter( - galaxy=galaxy, - grid=grid, - mat_plot_1d=mat_plot_1d, - include_2d=self.include_2d, + try: + if should_plot("subplot_galaxies_1d_decomposed"): + galaxies_plotter.subplot_galaxies_1d_decomposed() + except OverflowError: + pass + + if should_plot("fits_galaxy_images"): + multi_plotter = aplt.MultiFigurePlotter( + plotter_list=[ + GalaxyPlotter(galaxy=galaxy, grid=grid, mat_plot_2d=mat_plot_2d) + for galaxy in galaxies + ], ) - try: - galaxy_plotter.figures_1d_decomposed( - image=should_plot("image"), - convergence=should_plot("convergence"), - potential=should_plot("potential"), - ) - except OverflowError: - pass + multi_plotter.output_to_fits( + func_name_list=["figures_2d"] * len(galaxies), + figure_name_list=[ + "image", + ] + * len(galaxies), + # tag_list=[name for name, galaxy in galaxies.items()], + tag_list=[f"galaxy_{i}" for i in range(len(galaxies))], + filename="galaxy_images", + remove_fits_first=True, + ) - def inversion(self, inversion: aa.Inversion, during_analysis: bool): + def inversion(self, inversion: aa.Inversion): """ Visualizes an `Inversion` object. - Images are output to the `image` folder of the `image_path` in a subfolder called `inversion`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `Inversion` inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + points to the search's results folder and this function visualizes the maximum log likelihood `Inversion` + inferred by the search so far. - Visualization includes individual images of attributes of the dataset (e.g. the reconstructed image, the - reconstruction) and a subplot of all these attributes on the same figure. + Visualization includes subplots of individual images of attributes of the dataset (e.g. the reconstructed image, + the reconstruction) and .fits file of attributes. - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [inversion] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `inversion` header. Parameters ---------- inversion The inversion used to fit the dataset whose attributes are visualized. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. """ def should_plot(name): return plot_setting(section="inversion", name=name) - subfolders = "inversion" - - mat_plot_2d = self.mat_plot_2d_from(subfolders=subfolders) - - inversion_plotter = aplt.InversionPlotter( - inversion=inversion, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - inversion_plotter.figures_2d( - reconstructed_image=should_plot("reconstructed_image") - ) - - inversion_plotter.figures_2d_of_pixelization( - pixelization_index=0, - data_subtracted=should_plot("data_subtracted"), - reconstructed_image=should_plot("reconstructed_image"), - reconstruction=should_plot("reconstruction"), - mesh_pixels_per_image_pixels=should_plot("mesh_pixels_per_image_pixels"), - errors=should_plot("errors"), - regularization_weights=should_plot("regularization_weights"), - ) - - mat_plot_2d = self.mat_plot_2d_from(subfolders="") + mat_plot_2d = self.mat_plot_2d_from() inversion_plotter = aplt.InversionPlotter( inversion=inversion, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d @@ -334,43 +232,6 @@ def should_plot(name): for mapper_index in range(len(mapper_list)): inversion_plotter.subplot_of_mapper(mapper_index=mapper_index) - if not during_analysis and should_plot("all_at_end_png"): - mat_plot_2d = self.mat_plot_2d_from(subfolders=path.join(subfolders, "end")) - - inversion_plotter = aplt.InversionPlotter( - inversion=inversion, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - inversion_plotter.figures_2d(reconstructed_image=True) - - inversion_plotter.figures_2d_of_pixelization( - pixelization_index=0, - reconstructed_image=True, - reconstruction=True, - errors=True, - regularization_weights=True, - ) - - if not during_analysis and should_plot("all_at_end_fits"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders=path.join(subfolders, "fits"), format="fits" - ) - - inversion_plotter = aplt.InversionPlotter( - inversion=inversion, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - inversion_plotter.figures_2d(reconstructed_image=True) - - inversion_plotter.figures_2d_of_pixelization( - pixelization_index=0, - reconstructed_image=True, - reconstruction=True, - errors=True, - regularization_weights=True, - interpolate_to_uniform=True, - ) - def adapt_images( self, adapt_images: AdaptImages, @@ -378,14 +239,13 @@ def adapt_images( """ Visualizes the adapt images used by a model-fit for adaptive pixelization mesh's and regularization. - Images are output to the `image` folder of the `image_path` in a subfolder called `adapt`. When - used with a non-linear search the `image_path` is the output folder of the non-linear search. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. - Visualization includes an image of the overall adapt model image and a subplot of all galaxy images on the same - figure. + Visualization includes a subplot image of all galaxy images on the same figure. - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [adapt] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `adapt` header. Parameters ---------- @@ -396,16 +256,13 @@ def adapt_images( def should_plot(name): return plot_setting(section="adapt", name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="adapt") + mat_plot_2d = self.mat_plot_2d_from() adapt_plotter = AdaptPlotter( mat_plot_2d=mat_plot_2d, include_2d=self.include_2d ) - if should_plot("model_image"): - adapt_plotter.figure_model_image(model_image=adapt_images.model_image) - - if should_plot("images_of_galaxies"): - adapt_plotter.subplot_images_of_galaxies( + if should_plot("subplot_adapt_images"): + adapt_plotter.subplot_adapt_images( adapt_galaxy_name_image_dict=adapt_images.galaxy_image_dict ) diff --git a/autogalaxy/config/general.yaml b/autogalaxy/config/general.yaml index 361abe732..57de26dbf 100644 --- a/autogalaxy/config/general.yaml +++ b/autogalaxy/config/general.yaml @@ -1,6 +1,7 @@ fits: flip_for_ds9: true grid: + remove_projected_centre: false # Whether 1D plots of a light profile should remove the central point to avoid the large numerical central value skewing the y axis. max_evaluation_grid_size: 1000 # An evaluation grid whose shape is adaptive chosen is used to compute quantities like critical curves, this integer is the max size of the grid ensuring faster run times. adapt: adapt_minimum_percent: 0.01 diff --git a/autogalaxy/config/grids.yaml b/autogalaxy/config/grids.yaml index 6891a7f60..e77427ee3 100644 --- a/autogalaxy/config/grids.yaml +++ b/autogalaxy/config/grids.yaml @@ -30,6 +30,7 @@ radial_minimum: gNFW: 1.0e-06 gNFWMCRLudlow: 1.0e-06 gNFWVirialMassConcSph: 1.0e-06 + gNFWVirialMassgNFWConcSph: 1.0e-06 gNFWSph: 1.0e-06 Isothermal: 1.0e-08 IsothermalCore: 1.0e-08 @@ -73,161 +74,3 @@ radial_minimum: SMBH: 1.0e-8 SMBHBinary: 1.0e-8 EllProfile: 1.0e-08 - -# Over sampling is an important numerical technique, whereby light profiles images are evaluated on a higher resolution -# grid than the image data to ensure the calculation is accurate. - -# By default, a user does not specify the over sampling factor, and a default over sampling scheme is used for each -# profile. This scheme first goes to the centre of the profile, and computes circles with certain radial values -# (e.g. radii). It then assigns an over sampling `sub_size` to each circle, where the central circles have the highest -# over sampling factor and the outer circles have the lowest. - -# The size of the circles that are appropriate for determining the over sampling factor are dependent on the resolution -# of the grid. For a high resolution grid (e.g. low pixel scale), a smaller circle central circle is necessary to -# over sample the profile accurately. The config file below therefore specifies the "radial factors" used for -# automatically determining the over sampling factors for each profile, which is the factor the pixel scale is multiplied -# by to determine the circle size. - -# The config entry below defines the default over sampling factor for each profile, where: - -# radial_factor_list: The factors that are multiplied by the pixel scale to determine the circle size that is used. -# sub_size_list: The over sampling factor that is used for each circle size. - -# For the default entries below, oversampling of degree 32 x 32 is used within a circle of radius 3.01 x pixel scale, -# 4 x 4 within a circle of radius 10.01 x pixel scale and 2 x 2 for all pixels outside of this radius. - -over_sampling: - radial_factor_list: - Chameleon: [3.01, 10.01] - ChameleonSph: [3.01, 10.01] - DevVaucouleurs: [3.01, 10.01] - DevVaucouleursSph: [3.01, 10.01] - dPIE: [3.01, 10.01] - dPIESph: [3.01, 10.01] - ExponentialRadialGradient: [3.01, 10.01] - ExponentialRadialGradientSph: [3.01, 10.01] - ElsonFreeFall: [3.01, 10.01] - ElsonFreeFallSph: [3.01, 10.01] - Exponential: [3.01, 10.01] - ExponentialCore: [3.01, 10.01] - ExponentialCoreSph: [3.01, 10.01] - ExponentialSph: [3.01, 10.01] - ExternalShear: [3.01, 10.01] - Gaussian: [3.01, 10.01] - GaussianSph: [3.01, 10.01] - GaussianGradient: [3.01, 10.01] - GaussianGradientSph: [3.01, 10.01] - gNFW: [3.01, 10.01] - gNFWMCRLudlow: [3.01, 10.01] - gNFWVirialMassConcSph: [3.01, 10.01] - gNFWSph: [3.01, 10.01] - Isothermal: [3.01, 10.01] - IsothermalCore: [3.01, 10.01] - IsothermalCoreSph: [3.01, 10.01] - IsothermalSph: [3.01, 10.01] - MassSheet: [3.01, 10.01] - Moffat: [3.01, 10.01] - MoffatSph: [3.01, 10.01] - PowerLawMultipole: [3.01, 10.01] - NFW: [3.01, 10.01] - NFWMCRDuffySph: [3.01, 10.01] - NFWMCRLudlow: [3.01, 10.01] - NFWMCRLudlowSph: [3.01, 10.01] - NFWMCRScatterLudlow: [3.01, 10.01] - NFWMCRScatterLudlowSph: [3.01, 10.01] - NFWVirialMassConcSph: [3.01, 10.01] - NFWSph: [3.01, 10.01] - NFWTruncatedMCRDuffySph: [3.01, 10.01] - NFWTruncatedMCRLudlowSph: [3.01, 10.01] - NFWTruncatedMCRScatterLudlowSph: [3.01, 10.01] - NFWTruncatedSph: [3.01, 10.01] - PointMass: [3.01, 10.01] - PowerLaw: [3.01, 10.01] - PowerLawBroken: [3.01, 10.01] - PowerLawBrokenSph: [3.01, 10.01] - PowerLawCore: [3.01, 10.01] - PowerLawCoreSph: [3.01, 10.01] - PowerLawSph: [3.01, 10.01] - Sersic: [3.01, 10.01] - SersicCore: [3.01, 10.01] - SersicCoreSph: [3.01, 10.01] - SersicRadialGradient: [3.01, 10.01] - SersicSph: [3.01, 10.01] - SersicRadialGradientSph: [3.01, 10.01] - ShapeletCartesianSph: [3.01, 10.01] - ShapeletCartesian: [3.01, 10.01] - ShapeletPolarSph: [3.01, 10.01] - ShapeletPolar: [3.01, 10.01] - ShapeletExponentialSph: [3.01, 10.01] - ShapeletExponential: [3.01, 10.01] - SMBH: [3.01, 10.01] - SMBHBinary: [3.01, 10.01] - EllProfile: [3.01, 10.01] - PlotExample: [3.01, 10.01] - sub_size_list: - Chameleon: [32, 4, 2] - ChameleonSph: [32, 4, 2] - DevVaucouleurs: [32, 4, 2] - DevVaucouleursSph: [32, 4, 2] - dPIE: [32, 4, 2] - dPIESph: [32, 4, 2] - ExponentialRadialGradient: [32, 4, 2] - ExponentialRadialGradientSph: [32, 4, 2] - ElsonFreeFall: [32, 4, 2] - ElsonFreeFallSph: [32, 4, 2] - Exponential: [32, 4, 2] - ExponentialCore: [32, 4, 2] - ExponentialCoreSph: [32, 4, 2] - ExponentialSph: [32, 4, 2] - ExternalShear: [32, 4, 2] - Gaussian: [32, 4, 2] - GaussianSph: [32, 4, 2] - GaussianGradient: [32, 4, 2] - GaussianGradientSph: [32, 4, 2] - gNFW: [32, 4, 2] - gNFWMCRLudlow: [32, 4, 2] - gNFWVirialMassConcSph: [32, 4, 2] - gNFWSph: [32, 4, 2] - Isothermal: [32, 4, 2] - IsothermalCore: [32, 4, 2] - IsothermalCoreSph: [32, 4, 2] - IsothermalSph: [32, 4, 2] - MassSheet: [32, 4, 2] - Moffat: [32, 4, 2] - MoffatSph: [32, 4, 2] - PowerLawMultipole: [32, 4, 2] - NFW: [32, 4, 2] - NFWMCRDuffySph: [32, 4, 2] - NFWMCRLudlow: [32, 4, 2] - NFWMCRLudlowSph: [32, 4, 2] - NFWMCRScatterLudlow: [32, 4, 2] - NFWMCRScatterLudlowSph: [32, 4, 2] - NFWVirialMassConcSph : [32, 4, 2] - NFWSph: [32, 4, 2] - NFWTruncatedMCRDuffySph: [32, 4, 2] - NFWTruncatedMCRLudlowSph: [32, 4, 2] - NFWTruncatedMCRScatterLudlowSph: [32, 4, 2] - NFWTruncatedSph: [32, 4, 2] - PointMass: [32, 4, 2] - PowerLaw: [32, 4, 2] - PowerLawBroken: [32, 4, 2] - PowerLawBrokenSph: [32, 4, 2] - PowerLawCore: [32, 4, 2] - PowerLawCoreSph: [32, 4, 2] - PowerLawSph: [32, 4, 2] - Sersic: [32, 4, 2] - SersicCore: [32, 4, 2] - SersicCoreSph: [32, 4, 2] - SersicRadialGradient: [32, 4, 2] - SersicSph: [32, 4, 2] - SersicRadialGradientSph: [32, 4, 2] - ShapeletCartesianSph: [32, 4, 2] - ShapeletCartesian: [32, 4, 2] - ShapeletPolarSph: [32, 4, 2] - ShapeletPolar: [32, 4, 2] - ShapeletExponentialSph: [32, 4, 2] - ShapeletExponential: [32, 4, 2] - SMBH: [32, 4, 2] - SMBHBinary: [32, 4, 2] - EllProfile: [32, 4, 2] - PlotExample: [32, 4, 2] \ No newline at end of file diff --git a/autogalaxy/config/notation.yaml b/autogalaxy/config/notation.yaml index ba30f9bfd..264a3c8de 100644 --- a/autogalaxy/config/notation.yaml +++ b/autogalaxy/config/notation.yaml @@ -9,6 +9,7 @@ label: centre_1: x coefficient: \lambda c_2: c_{\rm 2} + c_gNFW: c_{\rm gNFW} concentration: conc core_radius: C_{\rm r} core_radius_0: C_{rm r0} diff --git a/autogalaxy/config/visualize/plots.yaml b/autogalaxy/config/visualize/plots.yaml index c46c62db0..8f35e3e9f 100644 --- a/autogalaxy/config/visualize/plots.yaml +++ b/autogalaxy/config/visualize/plots.yaml @@ -3,96 +3,43 @@ # For example, if `plots: fit: subplot_fit=True``, the ``fit_dataset.png`` subplot file will # be plotted every time visualization is performed. +subplot_format: [png] # Output format of all subplots, can be png, pdf or both (e.g. [png, pdf]) + dataset: # Settings for plots of all datasets (e.g. ImagingPlotter, InterferometerPlotter). subplot_dataset: true # Plot subplot containing all dataset quantities (e.g. the data, noise-map, etc.)? - data: false # Plot the individual data of every dataset? - noise_map: false # Plot the individual noise-map of every dataset? - signal_to_noise_map: false # Plot the individual signal-to-noise-map of every dataset? - over_sampling: false # Plot the over-sampling sub-size, used to evaluate light profiles, of every dataset? - over_sampling_non_uniform: false # Plot the over-sampling sub-size, used to evaluate non uniform grids, of every dataset? - over_sampling_pixelization: false # Plot the over-sampling sub-size, used to evaluate pixelizations, of every dataset? -imaging: # Settings for plots of imaging datasets (e.g. ImagingPlotter). - psf: false + fit: # Settings for plots of all fits (e.g. FitImagingPlotter, FitInterferometerPlotter). subplot_fit: true # Plot subplot of all fit quantities for any dataset (e.g. the model data, residual-map, etc.)? subplot_fit_log10: true # Plot subplot of all fit quantities for any dataset using log10 color maps (e.g. the model data, residual-map, etc.)? - all_at_end_png: true # Plot all individual plots listed below as .png (even if False)? - all_at_end_fits: true # Plot all individual plots listed below as .fits (even if False)? - all_at_end_pdf: false # Plot all individual plots listed below as publication-quality .pdf (even if False)? subplot_of_galaxies: false # Plot subplot of the model-image, subtracted image and other quantities of each galaxy? subplot_galaxy_images: false # Plot subplot of the image of each galaxy in the model? - subtracted_images_of_galaxies: false - data: false # Plot individual plots of the data? - noise_map: false # Plot individual plots of the noise-map? - signal_to_noise_map: false # Plot individual plots of the signal-to-noise-map? - model_data: false # Plot individual plots of the model-data? - residual_map: false # Plot individual plots of the residual-map? - normalized_residual_map: false # Plot individual plots of the normalized-residual-map? - chi_squared_map: false # Plot individual plots of the chi-squared-map? - residual_flux_fraction: false # Plot individual plots of the residual_flux_fraction? - model_images_of_galaxies: false # Plot individual plots of each galaxy's model image? + fits_fit: false # Output a .fits file containing the fit model data, residual map, normalized residual map and chi-squared? + fits_model_galaxy_images : false # Output a .fits file containing the model images of every galaxy? + fit_imaging: {} # Settings for plots of fits to imaging datasets (e.g. FitImagingPlotter). + galaxies: # Settings for plots of galaxies (e.g. GalaxiesPlotter). subplot_galaxies: true # Plot subplot of all quantities in each galaxies group (e.g. images, convergence)? - all_at_end_png: true # Plot all individual plots listed below as .png (even if False)? - all_at_end_fits: true # Plot all individual plots listed below as .fits (even if False)? - all_at_end_pdf: false # Plot all individual plots listed below as publication-quality .pdf (even if False)? subplot_galaxy_images: false # Plot subplot of the image of each galaxy in the model? - image: false - source_plane_image: false - convergence: false - deflections: false - potential: false - magnification: false -galaxies_1d: # Settings for 1D plots of galaxies (e.g. GalaxiesPlotter). - image: false - convergence: false - potential: false + subplot_galaxies_1d: false # Plot subplot of all quantities in 1D of each galaxies group (e.g. images, convergence)? + subplot_galaxies_1d_decomposed: false # Plot subplot of all quantities in 1D decomposed of each galaxies group (e.g. images, convergence)? + fits_galaxy_images: false # Output a .fits file containing images of every galaxy? + inversion: # Settings for plots of inversions (e.g. InversionPlotter). subplot_inversion: true # Plot subplot of all quantities in each inversion (e.g. reconstrucuted image, reconstruction)? subplot_mappings: true # Plot subplot of the image-to-source pixels mappings of each pixelization? - all_at_end_png: true # Plot all individual plots listed below as .png (even if False)? - all_at_end_fits: true # Plot all individual plots listed below as .fits (even if False)? - all_at_end_pdf: false # Plot all individual plots listed below as publication-quality .pdf (even if False)? - data_subtracted: false # Plot individual plots of the data with the other inversion linear objects subtracted? - errors: false # Plot image of the errors of every mesh-pixel reconstructed value? - sub_pixels_per_image_pixels: false # Plot the number of sub pixels per masked data pixels? - mesh_pixels_per_image_pixels: false # Plot the number of image-plane mesh pixels per masked data pixels? - reconstructed_image: false # Plot image of the reconstructed data (e.g. in the image-plane)? - reconstruction: false # Plot the reconstructed inversion (e.g. the pixelization's mesh in the source-plane)? - regularization_weights: false # Plot the effective regularization weight of every inversion mesh pixel? + fits_reconstruction: false # output reconstruction.fits containing the reconstructed pixelization and noise map on the adaptive mesh? + adapt: # Settings for plots of adapt images used by adaptive pixelizations. - images_of_galaxies: true - model_image: true -interferometer: # Settings for plots of interferometer datasets (e.g. InterferometerPlotter). - amplitudes_vs_uv_distances: false - phases_vs_uv_distances: false - uv_wavelengths: false - dirty_image: false - dirty_noise_map: false - dirty_signal_to_noise_map: false + subplot_adapt_images: true # Plot subplot showing each adapt image used for adaptive pixelization? + fit_interferometer: # Settings for plots of fits to interferometer datasets (e.g. FitInterferometerPlotter). subplot_fit_dirty_images: false # Plot subplot of the dirty-images of all interferometer datasets? subplot_fit_real_space: false # Plot subplot of the real-space images of all interferometer datasets? - amplitudes_vs_uv_distances: false - phases_vs_uv_distances: false - uv_wavelengths: false - dirty_image: false - dirty_noise_map: false - dirty_signal_to_noise_map: false - dirty_residual_map: false - dirty_normalized_residual_map: false - dirty_chi_squared_map: false + fits_dirty_images: false # output dirty_images.fits showing the dirty image, noise-map, model-data, resiual-map, normalized residual map and chi-squared map? + fit_ellipse: # Settings for plots of ellipse fitting fits (e.g. FitEllipse) data : true # Plot the data of the ellipse fit? data_no_ellipse: true # Plot the data without the black data ellipses, which obscure noisy data? -fit_quantity: # Settings for plots of fit quantities (e.g. FitQuantityPlotter). - all_at_end_png: true # Plot all individual plots listed below as .png (even if False)? - all_at_end_fits: true # Plot all individual plots listed below as .fits (even if False)? - all_at_end_pdf: false # Plot all individual plots listed below as publication-quality .pdf (even if False)? - chi_squared_map: false - image: true - model_image: false - noise_map: false - residual_map: false - normalized_residual_map: false + +fit_quantity: {} # Settings for plots of fit quantities (e.g. FitQuantityPlotter). \ No newline at end of file diff --git a/autogalaxy/ellipse/model/analysis.py b/autogalaxy/ellipse/model/analysis.py index 7e228ece3..47cc4e6f1 100644 --- a/autogalaxy/ellipse/model/analysis.py +++ b/autogalaxy/ellipse/model/analysis.py @@ -199,11 +199,6 @@ def save_attributes(self, paths: af.DirectoryPaths): hdu=self.dataset.mask.hdu_for_output, prefix="dataset", ) - paths.save_json( - name="over_sampling", - object_dict=to_dict(self.dataset.over_sampling), - prefix="dataset", - ) def profile_log_likelihood_function( self, instance: af.ModelInstance, paths: Optional[af.DirectoryPaths] = None diff --git a/autogalaxy/ellipse/model/plotter_interface.py b/autogalaxy/ellipse/model/plotter_interface.py index bce0ecdf6..e1432730c 100644 --- a/autogalaxy/ellipse/model/plotter_interface.py +++ b/autogalaxy/ellipse/model/plotter_interface.py @@ -16,9 +16,9 @@ def imaging(self, dataset: aa.Imaging): """ Visualizes an `Imaging` dataset object. - Images are output to the `image` folder of the `image_path` in a subfolder called `imaging`. When used with - a non-linear search the `image_path` is the output folder of the non-linear search. - `. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. + Visualization includes individual images of attributes of the dataset (e.g. the image, noise map, PSF) and a subplot of all these attributes on the same figure. @@ -34,19 +34,7 @@ def imaging(self, dataset: aa.Imaging): def should_plot(name): return plot_setting(section=["dataset", "imaging"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="dataset") - - dataset_plotter = aplt.ImagingPlotter( - dataset=dataset, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - dataset_plotter.figures_2d( - data=should_plot("data"), - noise_map=should_plot("noise_map"), - signal_to_noise_map=should_plot("signal_to_noise_map"), - ) - - mat_plot_2d = self.mat_plot_2d_from(subfolders="") + mat_plot_2d = self.mat_plot_2d_from() dataset_plotter = aplt.ImagingPlotter( dataset=dataset, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d @@ -58,37 +46,30 @@ def should_plot(name): def fit_ellipse( self, fit_list: List[FitEllipse], - during_analysis: bool, - subfolders: str = "fit_dataset", ): """ Visualizes a `FitEllipse` object, which fits an imaging dataset. - Images are output to the `image` folder of the `image_path` in a subfolder called `fit`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `FitEllipse` inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + points to the search's results folder and this function visualizes the maximum log likelihood `FitEllipse` + inferred by the search so far. - Visualization includes individual images of attributes of the `FitEllipse` (e.g. the model data, residual map) - and a subplot of all `FitEllipse`'s images on the same figure. + Visualization includes a subplot of individual images of attributes of the `FitEllipse` (e.g. the model data, + residual map). - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [fit] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `fit` and `fit_ellipse` headers. Parameters ---------- fit The maximum log likelihood `FitEllipse` of the non-linear search which is used to plot the fit. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. - visuals_2d - An object containing attributes which may be plotted over the figure (e.g. the centres of mass and light - profiles). """ def should_plot(name): return plot_setting(section=["fit", "fit_ellipse"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders=subfolders) + mat_plot_2d = self.mat_plot_2d_from() fit_plotter = FitEllipsePlotter( fit_list=fit_list, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d @@ -111,16 +92,3 @@ def should_plot(name): data=True, disable_data_contours=True, ) - - if not during_analysis and should_plot("all_at_end_png"): - mat_plot_2d = self.mat_plot_2d_from(subfolders=path.join(subfolders, "end")) - - fit_plotter = FitEllipsePlotter( - fit_list=fit_list, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - fit_plotter.figures_2d(data=True) - fit_plotter.figures_2d( - data=True, - disable_data_contours=True, - ) diff --git a/autogalaxy/ellipse/model/visualizer.py b/autogalaxy/ellipse/model/visualizer.py index 42862f101..4c8f80dcd 100644 --- a/autogalaxy/ellipse/model/visualizer.py +++ b/autogalaxy/ellipse/model/visualizer.py @@ -60,9 +60,6 @@ def visualize( instance An instance of the model that is being fitted to the data by this analysis (whose parameters have been set via a non-linear search). - during_analysis - If True the visualization is being performed midway through the non-linear search before it is finished, - which may change which images are output. """ fit_list = analysis.fit_list_from(instance=instance) @@ -71,4 +68,4 @@ def visualize( ) plotter.imaging(dataset=analysis.dataset) - plotter.fit_ellipse(fit_list=fit_list, during_analysis=during_analysis) + plotter.fit_ellipse(fit_list=fit_list) diff --git a/autogalaxy/galaxy/galaxy.py b/autogalaxy/galaxy/galaxy.py index 8c135387f..08b89a787 100644 --- a/autogalaxy/galaxy/galaxy.py +++ b/autogalaxy/galaxy/galaxy.py @@ -323,6 +323,15 @@ def traced_grid_2d_from(self, grid: aa.type.Grid2DLike) -> aa.type.Grid2DLike: """ Trace an input grid using the galaxy's its deflection angles. """ + if isinstance(grid, aa.Grid2D): + return aa.Grid2D( + values=grid - self.deflections_yx_2d_from(grid=grid), + mask=grid.mask, + over_sample_size=grid.over_sample_size, + over_sampled=grid.over_sampled + - self.deflections_yx_2d_from(grid=grid.over_sampled), + ) + return grid - self.deflections_yx_2d_from(grid=grid) @aa.grid_dec.to_projected diff --git a/autogalaxy/galaxy/plot/adapt_plotters.py b/autogalaxy/galaxy/plot/adapt_plotters.py index 2c1000fb3..933242c65 100644 --- a/autogalaxy/galaxy/plot/adapt_plotters.py +++ b/autogalaxy/galaxy/plot/adapt_plotters.py @@ -59,7 +59,7 @@ def figure_galaxy_image(self, galaxy_image: aa.Array2D): ), ) - def subplot_images_of_galaxies( + def subplot_adapt_images( self, adapt_galaxy_name_image_dict: Dict[Galaxy, aa.Array2D] ): """ @@ -81,8 +81,6 @@ def subplot_images_of_galaxies( for path, galaxy_image in adapt_galaxy_name_image_dict.items(): self.figure_galaxy_image(galaxy_image=galaxy_image) - self.mat_plot_2d.output.subplot_to_figure( - auto_filename="subplot_adapt_images_of_galaxies" - ) + self.mat_plot_2d.output.subplot_to_figure(auto_filename="subplot_adapt_images") self.close_subplot_figure() diff --git a/autogalaxy/galaxy/plot/galaxies_plotters.py b/autogalaxy/galaxy/plot/galaxies_plotters.py index 604157531..14573cd4b 100644 --- a/autogalaxy/galaxy/plot/galaxies_plotters.py +++ b/autogalaxy/galaxy/plot/galaxies_plotters.py @@ -343,3 +343,54 @@ def subplot_galaxy_images(self): auto_filename=f"subplot_galaxy_images" ) self.close_subplot_figure() + + def subplot_galaxies_1d(self): + """ + Output a subplot of attributes of every individual 1D attribute of the `Galaxy` object. + + For example, a 1D plot showing how the image, convergence of each component varies radially outwards. + + If the plotter has a 1D grid object this is used to evaluate each quantity. If it has a 2D grid, a 1D grid is + computed from the light profile. This is performed by aligning a 1D grid with the major-axis of the light + profile in projection, uniformly computing 1D values based on the 2D grid's size and pixel-scale. + """ + number_subplots = len(self.galaxies) * 3 + + self.open_subplot_figure(number_subplots=number_subplots) + + for galaxy_index in range(0, len(self.galaxies)): + galaxy_plotter = self.galaxy_plotter_from(galaxy_index=galaxy_index) + + galaxy_plotter.figures_1d(image=True) + galaxy_plotter.figures_1d(convergence=True) + galaxy_plotter.figures_1d(potential=True) + + self.mat_plot_1d.output.subplot_to_figure(auto_filename="subplot_galaxies_1d") + self.close_subplot_figure() + + def subplot_galaxies_1d_decomposed(self): + """ + Output a subplot of attributes of every individual 1D attribute of the `Galaxy` object decompoed into + their different light and mass profiles. + + For example, a 1D plot showing how the image, convergence of each component varies radially outwards. + + If the plotter has a 1D grid object this is used to evaluate each quantity. If it has a 2D grid, a 1D grid is + computed from the light profile. This is performed by aligning a 1D grid with the major-axis of the light + profile in projection, uniformly computing 1D values based on the 2D grid's size and pixel-scale. + """ + number_subplots = len(self.galaxies) * 3 + + self.open_subplot_figure(number_subplots=number_subplots) + + for galaxy_index in range(0, len(self.galaxies)): + galaxy_plotter = self.galaxy_plotter_from(galaxy_index=galaxy_index) + + galaxy_plotter.figures_1d_decomposed(image=True) + galaxy_plotter.figures_1d_decomposed(convergence=True) + galaxy_plotter.figures_1d_decomposed(potential=True) + + self.mat_plot_1d.output.subplot_to_figure( + auto_filename="subplot_galaxies_1d_decomposed" + ) + self.close_subplot_figure() diff --git a/autogalaxy/galaxy/to_inversion.py b/autogalaxy/galaxy/to_inversion.py index 76d233ed7..67869b23c 100644 --- a/autogalaxy/galaxy/to_inversion.py +++ b/autogalaxy/galaxy/to_inversion.py @@ -308,7 +308,7 @@ def cls_light_profile_func_list_galaxy_dict_from( if len(light_profile_list) > 0: lp_linear_func = LightProfileLinearObjFuncList( - grid=self.dataset.grids.uniform, + grid=self.dataset.grids.lp, blurring_grid=self.dataset.grids.blurring, convolver=self.dataset.convolver, light_profile_list=light_profile_list, @@ -496,9 +496,6 @@ def mapper_from( return mapper_from( mapper_grids=mapper_grids, - over_sampler=self.dataset.grids.pixelization.over_sampling.over_sampler_from( - mask=self.dataset.mask - ), regularization=regularization, run_time_dict=self.run_time_dict, ) @@ -550,7 +547,7 @@ def mapper_galaxy_dict(self) -> Dict[aa.AbstractMapper, Galaxy]: mapper = self.mapper_from( mesh=pixelization_list[mapper_index].mesh, regularization=pixelization_list[mapper_index].regularization, - source_plane_data_grid=self.dataset.grids.pixelization.over_sampler.over_sampled_grid, + source_plane_data_grid=self.dataset.grids.pixelization, source_plane_mesh_grid=mesh_grid_list[mapper_index], adapt_galaxy_image=adapt_galaxy_image, image_plane_mesh_grid=mesh_grid_list[mapper_index], diff --git a/autogalaxy/gui/clicker.py b/autogalaxy/gui/clicker.py index dca919deb..a24c249fc 100644 --- a/autogalaxy/gui/clicker.py +++ b/autogalaxy/gui/clicker.py @@ -6,7 +6,7 @@ class Clicker: - def __init__(self, image, pixel_scales, search_box_size): + def __init__(self, image, pixel_scales, search_box_size, in_pixels: bool = False): self.image = image pixel_scales = aa.util.geometry.convert_pixel_scales_2d( @@ -17,6 +17,7 @@ def __init__(self, image, pixel_scales, search_box_size): self.search_box_size = search_box_size self.click_list = [] + self.in_pixels = in_pixels def onclick(self, event): if event.dblclick: @@ -46,17 +47,21 @@ def onclick(self, event): y_pixels_max = y x_pixels_max = x - grid_arcsec = self.image.geometry.grid_scaled_2d_from( - grid_pixels_2d=aa.Grid2D.no_mask( - values=[[[y_pixels_max + 0.5, x_pixels_max + 0.5]]], - pixel_scales=self.pixel_scales, + print("clicked on the pixel:", y_pixels, x_pixels) + print("Max flux pixel:", y_pixels_max, x_pixels_max) + + if self.in_pixels: + self.click_list.append((y_pixels_max, x_pixels_max)) + else: + grid_arcsec = self.image.geometry.grid_scaled_2d_from( + grid_pixels_2d=aa.Grid2D.no_mask( + values=[[[y_pixels_max + 0.5, x_pixels_max + 0.5]]], + pixel_scales=self.pixel_scales, + ) ) - ) - y_arcsec = grid_arcsec[0, 0] - x_arcsec = grid_arcsec[0, 1] + y_arcsec = grid_arcsec[0, 0] + x_arcsec = grid_arcsec[0, 1] - print("clicked on the pixel:", y_pixels, x_pixels) - print("Max flux pixel:", y_pixels_max, x_pixels_max) - print("Arc-sec Coordinate", y_arcsec, x_arcsec) + print("Arc-sec Coordinate", y_arcsec, x_arcsec) - self.click_list.append((y_arcsec, x_arcsec)) + self.click_list.append((y_arcsec, x_arcsec)) diff --git a/autogalaxy/gui/scribbler.py b/autogalaxy/gui/scribbler.py index d8183f504..1a6304365 100644 --- a/autogalaxy/gui/scribbler.py +++ b/autogalaxy/gui/scribbler.py @@ -2,9 +2,6 @@ import numpy as np import matplotlib import matplotlib.pyplot as plt -import matplotlib.colors as colors - -from skimage.transform import rescale class Scribbler: @@ -16,6 +13,7 @@ def __init__( cmap=None, brush_width=0.05, backend="TkAgg", + mask_overlay=None, ): """ @@ -33,11 +31,18 @@ def __init__( # create initial plot self.figure = plt.figure() self.ax = self.figure.add_subplot(111) + if cmap is None: plt.imshow(image, interpolation="none") else: norm = cmap.norm_from(array=image) plt.imshow(image, cmap=cmap.config_dict["cmap"], norm=norm) + + if mask_overlay is not None: + grid = mask_overlay.derive_grid.edge + grid = mask_overlay.geometry.grid_pixel_centres_2d_from(grid_scaled_2d=grid) + plt.scatter(y=grid[:, 0], x=grid[:, 1], c="k", marker="x", s=10) + plt.axis([0, image.shape[1], image.shape[0], 0]) plt.axis("off") # if title: diff --git a/autogalaxy/imaging/fit_imaging.py b/autogalaxy/imaging/fit_imaging.py index 06f331691..da96317bb 100644 --- a/autogalaxy/imaging/fit_imaging.py +++ b/autogalaxy/imaging/fit_imaging.py @@ -48,7 +48,7 @@ def __init__( noise-map (if an inversion is performed the `log_evidence`, including additional terms describing the linear algebra solution, is computed). - When performing a `model-fit`via an `AnalysisImaging` object the `figure_of_merit` of this `FitImaging` object + When performing a `model-fit`via an `AnalysisImaging` object the `figure_of_merit` of this object is called and returned in the `log_likelihood_function`. Parameters @@ -98,11 +98,11 @@ def blurred_image(self) -> aa.Array2D: self.galaxies.cls_list_from(cls=LightProfileOperated) ): return self.galaxies.image_2d_from( - grid=self.grids.uniform, + grid=self.grids.lp, ) return self.galaxies.blurred_image_2d_from( - grid=self.grids.uniform, + grid=self.grids.lp, convolver=self.dataset.convolver, blurring_grid=self.grids.blurring, ) @@ -178,7 +178,7 @@ def galaxy_model_image_dict(self) -> Dict[Galaxy, np.ndarray]: """ galaxy_blurred_image_2d_dict = self.galaxies.galaxy_blurred_image_2d_dict_from( - grid=self.grids.uniform, + grid=self.grids.lp, convolver=self.dataset.convolver, blurring_grid=self.grids.blurring, ) @@ -250,7 +250,7 @@ def unmasked_blurred_image(self) -> aa.Array2D: exc.raise_linear_light_profile_in_unmasked() return self.galaxies.unmasked_blurred_image_2d_from( - grid=self.grids.uniform, psf=self.dataset.psf + grid=self.grids.lp, psf=self.dataset.psf ) @property @@ -265,7 +265,7 @@ def unmasked_blurred_image_of_galaxies_list(self) -> List[aa.Array2D]: exc.raise_linear_light_profile_in_unmasked() return self.galaxies.unmasked_blurred_image_2d_list_from( - grid=self.grids.uniform, psf=self.dataset.psf + grid=self.grids.lp, psf=self.dataset.psf ) @property diff --git a/autogalaxy/imaging/model/plotter_interface.py b/autogalaxy/imaging/model/plotter_interface.py index 2352e4e1a..fdcdd0e8c 100644 --- a/autogalaxy/imaging/model/plotter_interface.py +++ b/autogalaxy/imaging/model/plotter_interface.py @@ -1,5 +1,5 @@ from os import path -from typing import List +from typing import ClassVar, List import autoarray as aa import autoarray.plot as aplt @@ -11,19 +11,88 @@ from autogalaxy.analysis.plotter_interface import plot_setting +def fits_to_fits( + should_plot: bool, + fit: FitImaging, + mat_plot_2d: aplt.MatPlot2D, + fit_plotter_cls: ClassVar, +): + """ + Output attributes of a `FitImaging` to .fits format. + + This function is separated on its own so that it can be called by `PyAutoLens` and therefore avoid repeating + large amounts of code for visualization. + + Parameters + ---------- + should_plot + The function which inspects the configuration files to determine if a .fits file should be output. + fit + The fit to output to a .fits file. + mat_plot_2d + The 2D matplotlib plot used to create the .fits files. + fit_plotter_cls + The plotter class used to create the .fits files. + """ + + if should_plot("fits_fit"): + multi_plotter = aplt.MultiFigurePlotter( + plotter_list=[fit_plotter_cls(fit=fit, mat_plot_2d=mat_plot_2d)] * 4, + ) + + multi_plotter.output_to_fits( + func_name_list=["figures_2d"] * len(multi_plotter.plotter_list), + figure_name_list=[ + "model_image", + "residual_map", + "normalized_residual_map", + "chi_squared_map", + ], + # tag_list=[name for name, galaxy in galaxies.items()], + tag_list=[ + "model_image", + "residual_map", + "normalized_residual_map", + "chi_squared_map", + ], + filename="fit", + remove_fits_first=True, + ) + + if should_plot("fits_model_galaxy_images"): + + multi_plotter = aplt.MultiFigurePlotter( + plotter_list=[ + aplt.Array2DPlotter(array=image, mat_plot_2d=mat_plot_2d) + for (galaxy, image) in fit.galaxy_model_image_dict.items() + ], + ) + + number_plots = len(multi_plotter.plotter_list) + + multi_plotter.output_to_fits( + func_name_list=["figure_2d"] * number_plots, + figure_name_list=[None] * number_plots, + # tag_list=[name for name, galaxy in galaxies.items()], + tag_list=[f"galaxy_{i}" for i in range(number_plots)], + filename="model_galaxy_images", + remove_fits_first=True, + ) + + class PlotterInterfaceImaging(PlotterInterface): def imaging(self, dataset: aa.Imaging): """ Output visualization of an `Imaging` dataset, typically before a model-fit is performed. - Images are output to the `image` folder of the `image_path` in a subfolder called `dataset`. When used with - a non-linear search the `image_path` is the output folder of the non-linear search. - `. - Visualization includes individual images of attributes of the dataset (e.g. the image, noise map, PSF) and a - subplot of all these attributes on the same figure. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. + + Visualization includes a subplot of the individual images of attributes of the dataset (e.g. the image, + noise map, PSF). The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under - the `dataset` header. + the `dataset` and `imaging` headers. Parameters ---------- @@ -34,23 +103,7 @@ def imaging(self, dataset: aa.Imaging): def should_plot(name): return plot_setting(section=["dataset", "imaging"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="dataset") - - dataset_plotter = aplt.ImagingPlotter( - dataset=dataset, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - dataset_plotter.figures_2d( - data=should_plot("data"), - noise_map=should_plot("noise_map"), - psf=should_plot("psf"), - signal_to_noise_map=should_plot("signal_to_noise_map"), - over_sampling=should_plot("over_sampling"), - over_sampling_non_uniform=should_plot("over_sampling_non_uniform"), - over_sampling_pixelization=should_plot("over_sampling_pixelization"), - ) - - mat_plot_2d = self.mat_plot_2d_from(subfolders="") + mat_plot_2d = self.mat_plot_2d_from() dataset_plotter = aplt.ImagingPlotter( dataset=dataset, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d @@ -60,115 +113,60 @@ def should_plot(name): dataset_plotter.subplot_dataset() def fit_imaging( - self, fit: FitImaging, during_analysis: bool, subfolders: str = "fit_dataset" + self, + fit: FitImaging, ): """ Visualizes a `FitImaging` object, which fits an imaging dataset. - Images are output to the `image` folder of the `image_path` in a subfolder called `fit`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `FitImaging` inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + points to the search's results folder and this function visualizes the maximum log likelihood `FitImaging` + inferred by the search so far. - Visualization includes individual images of attributes of the `FitImaging` (e.g. the model data, residual map) - and a subplot of all `FitImaging`'s images on the same figure. + Visualization includes a subplot of individual images of attributes of the `FitImaging` (e.g. the model data, + residual map) and .fits files containing its attributes grouped together. - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [fit] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `fit` and `fit_imaging` headers. Parameters ---------- fit The maximum log likelihood `FitImaging` of the non-linear search which is used to plot the fit. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. - visuals_2d - An object containing attributes which may be plotted over the figure (e.g. the centres of mass and light - profiles). """ def should_plot(name): return plot_setting(section=["fit", "fit_imaging"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders=subfolders) + mat_plot_2d = self.mat_plot_2d_from() fit_plotter = FitImagingPlotter( fit=fit, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d ) - fit_plotter.figures_2d( - data=should_plot("data"), - noise_map=should_plot("noise_map"), - signal_to_noise_map=should_plot("signal_to_noise_map"), - model_image=should_plot("model_data"), - residual_map=should_plot("residual_map"), - normalized_residual_map=should_plot("normalized_residual_map"), - chi_squared_map=should_plot("chi_squared_map"), - ) - - fit_plotter.figures_2d_of_galaxies( - subtracted_image=should_plot("subtracted_images_of_galaxies"), - model_image=should_plot("model_images_of_galaxies"), - ) - if should_plot("subplot_fit"): fit_plotter.subplot_fit() if should_plot("subplot_of_galaxies"): fit_plotter.subplot_of_galaxies() - if not during_analysis and should_plot("all_at_end_png"): - mat_plot_2d = self.mat_plot_2d_from(subfolders=path.join(subfolders, "end")) - - fit_plotter = FitImagingPlotter( - fit=fit, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - fit_plotter.figures_2d( - data=True, - noise_map=True, - signal_to_noise_map=True, - model_image=True, - residual_map=True, - normalized_residual_map=True, - chi_squared_map=True, - ) - - fit_plotter.figures_2d_of_galaxies(subtracted_image=True, model_image=True) - - if not during_analysis and should_plot("all_at_end_fits"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders=path.join(subfolders, "fits"), format="fits" - ) - - fit_plotter = FitImagingPlotter( - fit=fit, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - fit_plotter.figures_2d( - data=True, - noise_map=True, - signal_to_noise_map=True, - model_image=True, - residual_map=True, - normalized_residual_map=True, - chi_squared_map=True, - ) - - fit_plotter.figures_2d_of_galaxies( - subtracted_image=True, - model_image=True, - ) + fits_to_fits( + should_plot=should_plot, + fit=fit, + mat_plot_2d=mat_plot_2d, + fit_plotter_cls=FitImagingPlotter, + ) def imaging_combined(self, dataset_list: List[aa.Imaging]): """ Output visualization of all `Imaging` datasets in a summed combined analysis, typically before a model-fit is performed. - Images are output to the `image` folder of the `image_path` in a subfolder called `dataset_combined`. When - used with a non-linear search the `image_path` is the output folder of the non-linear search. - `. - Visualization includes individual images of attributes of each dataset (e.g. the image, noise map, PSF) on - a single subplot, such that the full suite of multiple datasets can be viewed on the same figure. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. + + Visualization includes a single subplot of individual images of attributes of each dataset (e.g. the image, + noise map, PSF), such that the full suite of multiple datasets can be viewed on the same figure. The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the `dataset` header. @@ -182,7 +180,7 @@ def imaging_combined(self, dataset_list: List[aa.Imaging]): def should_plot(name): return plot_setting(section=["dataset", "imaging"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="combined") + mat_plot_2d = self.mat_plot_2d_from() dataset_plotter_list = [ aplt.ImagingPlotter( @@ -201,7 +199,7 @@ def should_plot(name): multi_plotter.subplot_of_figures_multi( func_name_list=["figures_2d"] * 4, figure_name_list=["data", "noise_map", "signal_to_noise_map", "psf"], - filename_suffix="dataset", + filename_suffix="dataset_combined", ) for plotter in multi_plotter.plotter_list: @@ -210,7 +208,7 @@ def should_plot(name): multi_plotter.subplot_of_figures_multi( func_name_list=["figures_2d"] * 4, figure_name_list=["data", "noise_map", "signal_to_noise_map", "psf"], - filename_suffix="dataset_log10", + filename_suffix="dataset_combined_log10", ) def fit_imaging_combined(self, fit_list: List[FitImaging]): @@ -218,11 +216,11 @@ def fit_imaging_combined(self, fit_list: List[FitImaging]): Output visualization of all `FitImaging` objects in a summed combined analysis, typically during or after a model-fit is performed. - Images are output to the `image` folder of the `image_path` in a subfolder called `combined`. When used - with a non-linear search the `image_path` is the output folder of the non-linear search. - `. - Visualization includes individual images of attributes of each fit (e.g. data, normalized residual-map) on - a single subplot, such that the full suite of multiple datasets can be viewed on the same figure. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. + + Visualization includes a single subplot of individual images of attributes of each fit (e.g. data, + normalized residual-map), such that the full suite of multiple datasets can be viewed on the same figure. The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the `fit` header. @@ -236,7 +234,7 @@ def fit_imaging_combined(self, fit_list: List[FitImaging]): def should_plot(name): return plot_setting(section=["fit", "fit_imaging"], name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="combined") + mat_plot_2d = self.mat_plot_2d_from() fit_plotter_list = [ FitImagingPlotter( @@ -286,9 +284,9 @@ def make_subplot_fit(filename_suffix): plotter.mat_plot_2d.cmap.kwargs["vmin"] = None plotter.mat_plot_2d.cmap.kwargs["vmax"] = None - make_subplot_fit(filename_suffix="fit") + make_subplot_fit(filename_suffix="fit_combined") for plotter in multi_plotter.plotter_list: plotter.mat_plot_2d.use_log10 = True - make_subplot_fit(filename_suffix="fit_log10") + make_subplot_fit(filename_suffix="fit_combined_log10") diff --git a/autogalaxy/imaging/model/visualizer.py b/autogalaxy/imaging/model/visualizer.py index 201c72d48..feb2b79b1 100644 --- a/autogalaxy/imaging/model/visualizer.py +++ b/autogalaxy/imaging/model/visualizer.py @@ -68,9 +68,6 @@ def visualize( instance An instance of the model that is being fitted to the data by this analysis (whose parameters have been set via a non-linear search). - during_analysis - If True the visualization is being performed midway through the non-linear search before it is finished, - which may change which images are output. """ fit = analysis.fit_from(instance=instance) @@ -80,20 +77,16 @@ def visualize( plotter.imaging(dataset=analysis.dataset) try: - plotter.fit_imaging(fit=fit, during_analysis=during_analysis) + plotter.fit_imaging(fit=fit) except exc.InversionException: pass galaxies = fit.galaxies_linear_light_profiles_to_light_profiles - plotter.galaxies( - galaxies=galaxies, grid=fit.grids.uniform, during_analysis=during_analysis - ) - plotter.galaxies_1d( - galaxies=galaxies, grid=fit.grids.uniform, during_analysis=during_analysis - ) + plotter.galaxies(galaxies=galaxies, grid=fit.grids.lp) + if fit.inversion is not None: - plotter.inversion(inversion=fit.inversion, during_analysis=during_analysis) + plotter.inversion(inversion=fit.inversion) @staticmethod def visualize_before_fit_combined( diff --git a/autogalaxy/imaging/simulator.py b/autogalaxy/imaging/simulator.py index 95d1fe395..73981655b 100644 --- a/autogalaxy/imaging/simulator.py +++ b/autogalaxy/imaging/simulator.py @@ -12,19 +12,29 @@ def via_galaxies_from( self, galaxies: List[Galaxy], grid: aa.type.Grid2DLike ) -> aa.Imaging: """ - Simulate an `Imaging` dataset from an input plane and grid. + Simulate an `Imaging` dataset from an input list of `Galaxy` objects and a 2D grid of (y,x) coordinates. - The planbe is used to generate the image of the galaxies which is simulated. + The light profiles of each galaxy are used to generate the image of the galaxies which is simulated. The steps of the `SimulatorImaging` simulation process (e.g. PSF convolution, noise addition) are - described in the `SimulatorImaging` `__init__` method docstring. + described in the `SimulatorImaging` `__init__` method docstring, found in the PyAutoArray project. + + If one of more galaxy light profiles are a `LightProfileSNR` object, the `intensity` of the light profile is + automatically set such that the signal-to-noise ratio of the light profile is equal to its input + `signal_to_noise_ratio` value. + + For example, if a `LightProfileSNR` object has a `signal_to_noise_ratio` of 5.0, the intensity of the light + profile is set such that the peak surface brightness of the profile is 5.0 times the background noise level of + the image. Parameters ---------- galaxies - The galaxies whose light is simulated. + The galaxies whose light profiles are evaluated using the input 2D grid of (y,x) coordinates in order to + generate the image of the galaxies which is then simulated. grid - The image-plane grid which the image of the strong lens is generated on. + The 2D grid of (y,x) coordinates which the light profiles of the galaxies are evaluated using in order + to generate the image of the galaxies. """ galaxies = Galaxies(galaxies=galaxies) @@ -41,7 +51,11 @@ def via_galaxies_from( grid=grid, psf_shape_2d=self.psf.shape_native ) - dataset = self.via_image_from(image=image) + over_sample_size = grid.over_sample_size.resized_from( + new_shape=image.shape_native, mask_pad_value=1 + ) + + dataset = self.via_image_from(image=image, over_sample_size=over_sample_size) return dataset.trimmed_after_convolution_from( kernel_shape=self.psf.shape_native diff --git a/autogalaxy/interferometer/fit_interferometer.py b/autogalaxy/interferometer/fit_interferometer.py index 7095ced45..3aa12c882 100644 --- a/autogalaxy/interferometer/fit_interferometer.py +++ b/autogalaxy/interferometer/fit_interferometer.py @@ -45,7 +45,7 @@ def __init__( algebra solution, is computed). When performing a model-fit` via ` AnalysisInterferometer` object the `figure_of_merit` of - this `FitInterferometer` object is called and returned in the `log_likelihood_function`. + this object is called and returned in the `log_likelihood_function`. Parameters ---------- @@ -94,7 +94,7 @@ def profile_visibilities(self) -> aa.Visibilities: a Fourier transform to the sum of light profile images. """ return self.galaxies.visibilities_from( - grid=self.grids.uniform, transformer=self.dataset.transformer + grid=self.grids.lp, transformer=self.dataset.transformer ) @property @@ -165,7 +165,7 @@ def galaxy_model_image_dict(self) -> Dict[Galaxy, np.ndarray]: data being fitted. """ galaxy_model_image_dict = self.galaxies.galaxy_image_2d_dict_from( - grid=self.grids.uniform + grid=self.grids.lp ) galaxy_linear_obj_image_dict = self.galaxy_linear_obj_data_dict_from( @@ -189,7 +189,7 @@ def galaxy_model_visibilities_dict(self) -> Dict[Galaxy, np.ndarray]: data being fitted. """ galaxy_model_visibilities_dict = self.galaxies.galaxy_visibilities_dict_from( - grid=self.grids.uniform, transformer=self.dataset.transformer + grid=self.grids.lp, transformer=self.dataset.transformer ) galaxy_linear_obj_data_dict = self.galaxy_linear_obj_data_dict_from( diff --git a/autogalaxy/interferometer/model/plotter_interface.py b/autogalaxy/interferometer/model/plotter_interface.py index 335dbe25a..fa421cae5 100644 --- a/autogalaxy/interferometer/model/plotter_interface.py +++ b/autogalaxy/interferometer/model/plotter_interface.py @@ -1,4 +1,5 @@ from os import path +from typing import ClassVar import autoarray as aa import autoarray.plot as aplt @@ -12,19 +13,117 @@ from autogalaxy.analysis.plotter_interface import plot_setting +def fits_to_fits( + should_plot: bool, + fit: FitInterferometer, + mat_plot_2d: aplt.MatPlot2D, + fit_plotter_cls: ClassVar, +): + """ + Output attributes of a `FitInterferometer` to .fits format. + + This function is separated on its own so that it can be called by `PyAutoLens` and therefore avoid repeating + large amounts of code for visualization. + + Parameters + ---------- + should_plot + The function which inspects the configuration files to determine if a .fits file should be output. + fit + The fit to output to a .fits file. + mat_plot_2d + The 2D matplotlib plot used to create the .fits files. + fit_plotter_cls + The plotter class used to create the .fits files. + """ + # if should_plot("fits_fit"): + # + # multi_plotter = aplt.MultiFigurePlotter( + # plotter_list=[FitInterferometerPlotter(fit=fit, mat_plot_2d=mat_plot_2d)] * 4, + # ) + # + # multi_plotter.output_to_fits( + # func_name_list=["figures_2d"] * len(multi_plotter.plotter_list), + # figure_name_list=[ + # "model_data", + # "residual_map_real", + # "residual_map_real", + # "normalized_residual_map_real", + # "chi_squared_map_real", + # ], + # # tag_list=[name for name, galaxy in galaxies.items()], + # tag_list=[ + # "model_data", + # "residual_map", + # "normalized_residual_map", + # "chi_squared_map", + # ], + # filename="fit", + # remove_fits_first=True, + # ) + + if should_plot("fits_model_galaxy_images"): + multi_plotter = aplt.MultiFigurePlotter( + plotter_list=[ + aplt.Array2DPlotter(array=image, mat_plot_2d=mat_plot_2d) + for (galaxy, image) in fit.galaxy_model_image_dict.items() + ], + ) + + multi_plotter.output_to_fits( + func_name_list=["figure_2d"] * len(multi_plotter.plotter_list), + figure_name_list=[None] * len(multi_plotter.plotter_list), + # tag_list=[name for name, galaxy in galaxies.items()], + tag_list=[f"galaxy_{i}" for i in range(len(multi_plotter.plotter_list))], + filename="model_galaxy_images", + remove_fits_first=True, + ) + + if should_plot("fits_dirty_images"): + number_plots = 6 + + multi_plotter = aplt.MultiFigurePlotter( + plotter_list=[FitInterferometerPlotter(fit=fit, mat_plot_2d=mat_plot_2d)] + * number_plots, + ) + + multi_plotter.output_to_fits( + func_name_list=["figures_2d"] * len(multi_plotter.plotter_list), + figure_name_list=[ + "dirty_image", + "dirty_noise_map", + "dirty_model_image", + "dirty_residual_map", + "dirty_normalized_residual_map", + "dirty_chi_squared_map", + ], + # tag_list=[name for name, galaxy in galaxies.items()], + tag_list=[ + "dirty_image", + "dirty_noise_map", + "dirty_model_image", + "dirty_residual_map", + "dirty_normalized_residual_map", + "dirty_chi_squared_map", + ], + filename="dirty_images", + remove_fits_first=True, + ) + + class PlotterInterfaceInterferometer(PlotterInterface): def interferometer(self, dataset: aa.Interferometer): """ Visualizes an `Interferometer` dataset object. - Images are output to the `image` folder of the `image_path` in a subfolder called `interferometer`. When - used with a non-linear search the `image_path` is the output folder of the non-linear search. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + is the output folder of the non-linear search. - Visualization includes individual images of attributes of the dataset (e.g. the visibilities, noise map, - uv-wavelengths) and a subplot of all these attributes on the same figure. + Visualization includes a subplot of individual images of attributes of the dataset (e.g. the visibilities, + noise map, uv-wavelengths). - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [dataset] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `dataset` and `interferometer` headers. Parameters ---------- @@ -35,28 +134,8 @@ def interferometer(self, dataset: aa.Interferometer): def should_plot(name): return plot_setting(section=["dataset", "interferometer"], name=name) - mat_plot_1d = self.mat_plot_1d_from(subfolders="dataset") - mat_plot_2d = self.mat_plot_2d_from(subfolders="dataset") - - dataset_plotter = aplt.InterferometerPlotter( - dataset=dataset, - include_2d=self.include_2d, - mat_plot_1d=mat_plot_1d, - mat_plot_2d=mat_plot_2d, - ) - - dataset_plotter.figures_2d( - data=should_plot("data"), - u_wavelengths=should_plot("uv_wavelengths"), - v_wavelengths=should_plot("uv_wavelengths"), - amplitudes_vs_uv_distances=should_plot("amplitudes_vs_uv_distances"), - phases_vs_uv_distances=should_plot("phases_vs_uv_distances"), - dirty_image=should_plot("dirty_image"), - dirty_noise_map=should_plot("dirty_noise_map"), - dirty_signal_to_noise_map=should_plot("dirty_signal_to_noise_map"), - ) - - mat_plot_2d = self.mat_plot_2d_from(subfolders="") + mat_plot_1d = self.mat_plot_1d_from() + mat_plot_2d = self.mat_plot_2d_from() dataset_plotter = aplt.InterferometerPlotter( dataset=dataset, @@ -71,38 +150,31 @@ def should_plot(name): def fit_interferometer( self, fit: FitInterferometer, - during_analysis: bool, - subfolders: str = "fit_dataset", ): """ Visualizes a `FitInterferometer` object, which fits an interferometer dataset. - Images are output to the `image` folder of the `image_path` in a subfolder called `fit`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `FitInterferometer` inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + points to the search's results folder and this function visualizes the maximum log likelihood `FitInterferometer` + inferred by the search so far. - Visualization includes individual images of attributes of the `FitInterferometer` (e.g. the model data, - residual map) and a subplot of all `FitInterferometer`'s images on the same figure. + Visualization includes a subplot of individual images of attributes of the `FitInterferometer` (e.g. the model + data, residual map) and .fits files containing its attributes grouped together. - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [fit] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `fit` and `fit_interferometer` headers. Parameters ---------- fit The maximum log likelihood `FitInterferometer` of the non-linear search which is used to plot the fit. - during_analysis - Whether visualization is performed during a non-linear search or once it is completed. - visuals_2d - An object containing attributes which may be plotted over the figure (e.g. the centres of mass and light - profiles). """ def should_plot(name): return plot_setting(section=["fit", "fit_interferometer"], name=name) - mat_plot_1d = self.mat_plot_1d_from(subfolders=subfolders) - mat_plot_2d = self.mat_plot_2d_from(subfolders=subfolders) + mat_plot_1d = self.mat_plot_1d_from() + mat_plot_2d = self.mat_plot_2d_from() fit_plotter = FitInterferometerPlotter( fit=fit, @@ -114,72 +186,15 @@ def should_plot(name): if should_plot("subplot_fit"): fit_plotter.subplot_fit() + if should_plot("subplot_fit_dirty_images"): + fit_plotter.subplot_fit_dirty_images() + if should_plot("subplot_fit_real_space"): fit_plotter.subplot_fit_real_space() - fit_plotter.figures_2d( - data=should_plot("data"), - noise_map=should_plot("noise_map"), - signal_to_noise_map=should_plot("signal_to_noise_map"), - model_data=should_plot("model_data"), - residual_map_real=should_plot("residual_map"), - residual_map_imag=should_plot("residual_map"), - chi_squared_map_real=should_plot("chi_squared_map"), - chi_squared_map_imag=should_plot("chi_squared_map"), - normalized_residual_map_real=should_plot("normalized_residual_map"), - normalized_residual_map_imag=should_plot("normalized_residual_map"), - dirty_image=should_plot("dirty_image"), - dirty_noise_map=should_plot("dirty_noise_map"), - dirty_signal_to_noise_map=should_plot("dirty_signal_to_noise_map"), - dirty_residual_map=should_plot("residual_map"), - dirty_normalized_residual_map=should_plot("normalized_residual_map"), - dirty_chi_squared_map=should_plot("chi_squared_map"), + fits_to_fits( + should_plot=should_plot, + fit=fit, + mat_plot_2d=mat_plot_2d, + fit_plotter_cls=FitInterferometerPlotter, ) - - if not during_analysis and should_plot("all_at_end_png"): - mat_plot_1d = self.mat_plot_1d_from(subfolders=path.join(subfolders, "end")) - mat_plot_2d = self.mat_plot_2d_from(subfolders=path.join(subfolders, "end")) - - fit_plotter = FitInterferometerPlotter( - fit=fit, - include_2d=self.include_2d, - mat_plot_1d=mat_plot_1d, - mat_plot_2d=mat_plot_2d, - ) - - fit_plotter.figures_2d( - data=True, - noise_map=True, - signal_to_noise_map=True, - model_data=True, - residual_map_real=True, - residual_map_imag=True, - chi_squared_map_real=True, - chi_squared_map_imag=True, - normalized_residual_map_real=True, - normalized_residual_map_imag=True, - dirty_image=True, - dirty_noise_map=True, - dirty_signal_to_noise_map=True, - dirty_residual_map=True, - dirty_normalized_residual_map=True, - dirty_chi_squared_map=True, - ) - - if not during_analysis and should_plot("all_at_end_fits"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders=path.join("fit_dataset", "fits"), format="fits" - ) - - fit_plotter = FitInterferometerPlotter( - fit=fit, include_2d=self.include_2d, mat_plot_2d=mat_plot_2d - ) - - fit_plotter.figures_2d( - dirty_image=True, - dirty_noise_map=True, - dirty_signal_to_noise_map=True, - dirty_residual_map=True, - dirty_normalized_residual_map=True, - dirty_chi_squared_map=True, - ) diff --git a/autogalaxy/interferometer/model/visualizer.py b/autogalaxy/interferometer/model/visualizer.py index 03e5d4655..87a9103f7 100644 --- a/autogalaxy/interferometer/model/visualizer.py +++ b/autogalaxy/interferometer/model/visualizer.py @@ -72,9 +72,6 @@ def visualize( instance An instance of the model that is being fitted to the data by this analysis (whose parameters have been set via a non-linear search). - during_analysis - If True the visualization is being performed midway through the non-linear search before it is finished, - which may change which images are output. """ fit = analysis.fit_from(instance=instance) @@ -86,15 +83,13 @@ def visualize( galaxies = fit.galaxies_linear_light_profiles_to_light_profiles PlotterInterface.galaxies( - galaxies=galaxies, grid=fit.grids.uniform, during_analysis=during_analysis - ) - PlotterInterface.galaxies_1d( - galaxies=galaxies, grid=fit.grids.uniform, during_analysis=during_analysis + galaxies=galaxies, + grid=fit.grids.lp, ) try: PlotterInterface.fit_interferometer( - fit=fit, during_analysis=during_analysis + fit=fit, ) except exc.InversionException: pass @@ -102,7 +97,7 @@ def visualize( if fit.inversion is not None: try: PlotterInterface.inversion( - inversion=fit.inversion, during_analysis=during_analysis + inversion=fit.inversion, ) except IndexError: pass diff --git a/autogalaxy/interferometer/plot/fit_interferometer_plotters.py b/autogalaxy/interferometer/plot/fit_interferometer_plotters.py index 710aec7b4..8fd3995ab 100644 --- a/autogalaxy/interferometer/plot/fit_interferometer_plotters.py +++ b/autogalaxy/interferometer/plot/fit_interferometer_plotters.py @@ -111,7 +111,7 @@ def galaxies_plotter_from(self, galaxies: List[Galaxy]) -> GalaxiesPlotter: """ return GalaxiesPlotter( galaxies=galaxies, - grid=self.fit.grids.uniform, + grid=self.fit.grids.lp, mat_plot_2d=self.mat_plot_2d, visuals_2d=self.get_visuals_2d_real_space(), include_2d=self.include_2d, diff --git a/autogalaxy/interferometer/simulator.py b/autogalaxy/interferometer/simulator.py index a76db13d7..66118e145 100644 --- a/autogalaxy/interferometer/simulator.py +++ b/autogalaxy/interferometer/simulator.py @@ -22,7 +22,7 @@ def via_galaxies_from(self, galaxies: List[Galaxy], grid: aa.type.Grid2DLike): An arrays representing the effective exposure time of each pixel. psf: PSF An arrays describing the PSF the simulated image is blurred with. - add_poisson_noise: Bool + add_poisson_noise_to_data: Bool If `True` poisson noise_maps is simulated and added to the image, based on the total counts in each image pixel noise_seed: int diff --git a/autogalaxy/plot/__init__.py b/autogalaxy/plot/__init__.py index 66f83252d..81623d62f 100644 --- a/autogalaxy/plot/__init__.py +++ b/autogalaxy/plot/__init__.py @@ -29,6 +29,7 @@ VectorYXQuiver, PatchOverlay, InterpolatedReconstruction, + DelaunayDrawer, VoronoiDrawer, OriginScatter, MaskScatter, diff --git a/autogalaxy/plot/get_visuals/two_d.py b/autogalaxy/plot/get_visuals/two_d.py index b9aac1b54..73f0efc04 100644 --- a/autogalaxy/plot/get_visuals/two_d.py +++ b/autogalaxy/plot/get_visuals/two_d.py @@ -280,7 +280,7 @@ def via_fit_imaging_from(self, fit: FitImaging) -> Visuals2D: visuals_2d_via_fit = super().via_fit_imaging_from(fit=fit) visuals_2d_via_light_mass_obj = self.via_light_mass_obj_from( - light_mass_obj=fit.galaxies, grid=fit.grids.uniform + light_mass_obj=fit.galaxies, grid=fit.grids.lp ) return visuals_2d_via_fit + visuals_2d_via_light_mass_obj diff --git a/autogalaxy/plot/mat_plot/two_d.py b/autogalaxy/plot/mat_plot/two_d.py index d2f37ca2d..eebc44048 100644 --- a/autogalaxy/plot/mat_plot/two_d.py +++ b/autogalaxy/plot/mat_plot/two_d.py @@ -30,6 +30,7 @@ def __init__( vector_yx_quiver: Optional[aplt.VectorYXQuiver] = None, patch_overlay: Optional[aplt.PatchOverlay] = None, interpolated_reconstruction: Optional[aplt.InterpolatedReconstruction] = None, + delaunay_drawer: Optional[aplt.DelaunayDrawer] = None, voronoi_drawer: Optional[aplt.VoronoiDrawer] = None, origin_scatter: Optional[aplt.OriginScatter] = None, mask_scatter: Optional[aplt.MaskScatter] = None, @@ -120,6 +121,8 @@ def __init__( voronoi_drawer Interpolations the reconstruction of a `Mapper` object from its irregular grid (e.g. Delaunay, Voronoi) to a uniform 2D array and plots it via `plt.imshow()`. + delaunay_drawer + Draws a colored Delaunay mesh of pixels using `plt.tripcolor`. voronoi_drawer Draws a colored Voronoi mesh of pixels using `plt.fill`. origin_scatter @@ -203,6 +206,7 @@ def __init__( contour=contour, grid_plot=grid_plot, interpolated_reconstruction=interpolated_reconstruction, + delaunay_drawer=delaunay_drawer, voronoi_drawer=voronoi_drawer, use_log10=use_log10, ) diff --git a/autogalaxy/profiles/light/linear/abstract.py b/autogalaxy/profiles/light/linear/abstract.py index 710d729d6..a44194e3b 100644 --- a/autogalaxy/profiles/light/linear/abstract.py +++ b/autogalaxy/profiles/light/linear/abstract.py @@ -244,8 +244,6 @@ def pixels_in_mask(self) -> int: ------- The number of pixels in the mask of the grid. """ - if isinstance(self.grid, aa.Grid2DOverSampled): - return self.grid.pixels_in_mask return self.grid.mask.pixels_in_mask @property diff --git a/autogalaxy/profiles/mass/__init__.py b/autogalaxy/profiles/mass/__init__.py index bc54ad1ec..ab248dffd 100644 --- a/autogalaxy/profiles/mass/__init__.py +++ b/autogalaxy/profiles/mass/__init__.py @@ -17,6 +17,7 @@ gNFW, gNFWSph, gNFWVirialMassConcSph, + gNFWVirialMassgNFWConcSph, NFWTruncatedSph, NFWTruncatedMCRDuffySph, NFWTruncatedMCRLudlowSph, diff --git a/autogalaxy/profiles/mass/dark/__init__.py b/autogalaxy/profiles/mass/dark/__init__.py index f9509ab7f..37c26c344 100644 --- a/autogalaxy/profiles/mass/dark/__init__.py +++ b/autogalaxy/profiles/mass/dark/__init__.py @@ -1,6 +1,7 @@ from .gnfw import gNFW, gNFWSph from .gnfw_mcr import gNFWMCRLudlow from .gnfw_virial_mass_conc import gNFWVirialMassConcSph +from .gnfw_virial_mass_gnfw_conc import gNFWVirialMassgNFWConcSph from .nfw import NFW, NFWSph from .nfw_mcr import NFWMCRLudlowSph, NFWMCRDuffySph, NFWMCRLudlow from .nfw_mcr_scatter import NFWMCRScatterLudlow, NFWMCRScatterLudlowSph diff --git a/autogalaxy/profiles/mass/dark/gnfw_virial_mass_gnfw_conc.py b/autogalaxy/profiles/mass/dark/gnfw_virial_mass_gnfw_conc.py new file mode 100644 index 000000000..df706fa14 --- /dev/null +++ b/autogalaxy/profiles/mass/dark/gnfw_virial_mass_gnfw_conc.py @@ -0,0 +1,132 @@ +from typing import Tuple + +from autogalaxy.profiles.mass.dark.gnfw import gNFWSph + +from astropy import units + +import numpy as np +from autogalaxy import cosmology as cosmo + +from scipy.integrate import quad + + +def kappa_s_and_scale_radius( + cosmology, virial_mass, concentration, overdens, redshift_object, redshift_source, inner_slope +): + # gNFW concentration imported + + critical_density = ( + cosmology.critical_density(redshift_object).to(units.solMass / units.kpc**3) + ).value + + critical_surface_density = ( + cosmology.critical_surface_density_between_redshifts_solar_mass_per_kpc2_from( + redshift_0=redshift_object, redshift_1=redshift_source + ) + ) + + kpc_per_arcsec = cosmology.kpc_per_arcsec_from(redshift=redshift_object) + + if overdens == 0: + x = cosmology.Om(redshift_object) - 1 + overdens = 18 * np.pi**2 + 82 * x - 39 * x**2 # Bryan & Norman (1998) + + virial_radius = ( + virial_mass / (overdens * critical_density * (4.0 * np.pi / 3.0)) + ) ** ( + 1.0 / 3.0 + ) # r_vir + + scale_radius_kpc = ( + virial_radius / concentration + ) # scale radius of gNFW profile in kpc + + ############################## + def integrand(r): + return (r**2 / r**inner_slope) * (1 + r / scale_radius_kpc) ** ( + inner_slope - 3 + ) + + de_c = ( + (overdens / 3.0) + * (virial_radius**3 / scale_radius_kpc**inner_slope) + / quad(integrand, 0, virial_radius)[0] + ) # rho_c + ############################## + + rho_s = critical_density * de_c # rho_s + kappa_s = rho_s * scale_radius_kpc / critical_surface_density # kappa_s + scale_radius = scale_radius_kpc / kpc_per_arcsec # scale radius in arcsec + + return kappa_s, scale_radius, virial_radius, overdens + + +class gNFWVirialMassgNFWConcSph(gNFWSph): + def __init__( + self, + centre: Tuple[float, float] = (0.0, 0.0), + log10m_vir: float = 12.0, + c_gNFW: float = 10.0, + overdens: float = 0.0, + redshift_object: float = 0.5, + redshift_source: float = 1.0, + inner_slope: float = 1.0, + ): + """ + Spherical gNFW profile initialized with the virial mass and c_gNFW concentration of the halo. + + The virial radius of the halo is defined as the radius at which the density of the halo + equals overdens * the critical density of the Universe. r_vir = (3*m_vir/4*pi*overdens*critical_density)^1/3. + + If the overdens parameter is set to 0, the virial overdensity of Bryan & Norman (1998) will be used. + + Parameters + ---------- + centre + The (y,x) arc-second coordinates of the profile centre. + log10m_vir + The log10(virial mass) of the dark matter halo. + c_gNFW + The c_gNFW concentration of the dark matter halo + overdens + The spherical overdensity used to define the virial radius of the dark matter + halo: r_vir = (3*m_vir/4*pi*overdens*critical_density)^1/3. If this parameter is set to 0, the virial + overdensity of Bryan & Norman (1998) will be used. + redshift_object + Lens redshift. + redshift_source + Source redshift. + inner_slope + The inner slope of the dark matter halo's gNFW density profile. + """ + + self.log10m_vir = log10m_vir + self.c_gNFW = c_gNFW + self.redshift_object = redshift_object + self.redshift_source = redshift_source + self.inner_slope = inner_slope + + ( + kappa_s, + scale_radius, + virial_radius, + overdens, + ) = kappa_s_and_scale_radius( + cosmology=cosmo.Planck15(), + virial_mass=10**log10m_vir, + concentration=c_gNFW, + overdens=overdens, + redshift_object=redshift_object, + redshift_source=redshift_source, + inner_slope=inner_slope, + ) + + self.virial_radius = virial_radius + self.overdens = overdens + + super().__init__( + centre=centre, + kappa_s=kappa_s, + inner_slope=inner_slope, + scale_radius=scale_radius, + ) \ No newline at end of file diff --git a/autogalaxy/profiles/mass/total/power_law_multipole.py b/autogalaxy/profiles/mass/total/power_law_multipole.py index 354bdabb0..da5c5cc8a 100644 --- a/autogalaxy/profiles/mass/total/power_law_multipole.py +++ b/autogalaxy/profiles/mass/total/power_law_multipole.py @@ -171,18 +171,18 @@ def deflections_yx_2d_from( * self.einstein_radius ** (self.slope - 1.0) * radial_grid ** (2.0 - self.slope) ) - / (self.m**2.0 - (3.0 - self.slope)) + / (self.m**2.0 - (3.0 - self.slope) ** 2.0) * self.k_m * np.cos(self.m * (polar_angle_grid - self.angle_m)) ) a_angle = ( ( - self.m**2.0 + self.m * self.einstein_radius ** (self.slope - 1.0) * radial_grid ** (2.0 - self.slope) ) - / (self.m**2.0 - (3.0 - self.slope)) + / (self.m**2.0 - (3.0 - self.slope) ** 2.0) * self.k_m * np.sin(self.m * (polar_angle_grid - self.angle_m)) ) diff --git a/autogalaxy/quantity/dataset_quantity.py b/autogalaxy/quantity/dataset_quantity.py index b90c3628f..683f3d464 100644 --- a/autogalaxy/quantity/dataset_quantity.py +++ b/autogalaxy/quantity/dataset_quantity.py @@ -14,7 +14,8 @@ def __init__( self, data: Union[aa.Array2D, aa.VectorYX2D], noise_map: Union[aa.Array2D, aa.VectorYX2D], - over_sampling: Optional[aa.OverSamplingDataset] = aa.OverSamplingDataset(), + over_sample_size_lp: Union[int, aa.Array2D] = 4, + over_sample_size_pixelization: Union[int, aa.Array2D] = 4, ): """ A quantity dataset, which represents a derived quantity of a light profile, mass profile, galaxy or galaxies @@ -57,10 +58,13 @@ def __init__( An array describing the RMS standard deviation error in each pixel used for computing quantities like the chi-squared in a fit, which is often chosen in an arbitrary way for a quantity dataset given the quantities are not observed using real astronomical instruments. - over_sampling - The over sampling schemes which divide the grids into sub grids of smaller pixels within their host image - pixels when using the grid to evaluate a function (e.g. images) to better approximate the 2D line integral - This class controls over sampling for all the different grids (e.g. `grid`, `grids.pixelization). + over_sample_size_lp + The over sampling scheme size, which divides the grid into a sub grid of smaller pixels when computing + values (e.g. images) from the grid to approximate the 2D line integral of the amount of light that falls + into each pixel. + over_sample_size_pixelization + How over sampling is performed for the grid which is associated with a pixelization, which is therefore + passed into the calculations performed in the `inversion` module. """ if data.shape != noise_map.shape: if data.shape[0:-1] == noise_map.shape[0:]: @@ -76,7 +80,8 @@ def __init__( super().__init__( data=data, noise_map=noise_map, - over_sampling=over_sampling, + over_sample_size_lp=over_sample_size_lp, + over_sample_size_pixelization=over_sample_size_pixelization, ) @classmethod @@ -84,7 +89,8 @@ def via_signal_to_noise_map( cls, data: Union[aa.Array2D, aa.VectorYX2D], signal_to_noise_map: Union[aa.Array2D], - over_sampling: Optional[aa.OverSamplingIterate] = None, + over_sample_size_lp: Union[int, aa.Array2D] = 4, + over_sample_size_pixelization: Union[int, aa.Array2D] = 4, ): """ Represents a derived quantity of a light profile, mass profile, galaxy or galaxies as a dataset that can be @@ -100,6 +106,13 @@ def via_signal_to_noise_map( The data of the quantity (e.g. 2D convergence, 2D potential, 2D deflections) that is fitted. signal_to_noise_map The 2D signal to noise map of the quantity's data. + over_sample_size_lp + The over sampling scheme size, which divides the grid into a sub grid of smaller pixels when computing + values (e.g. images) from the grid to approximate the 2D line integral of the amount of light that falls + into each pixel. + over_sample_size_pixelization + How over sampling is performed for the grid which is associated with a pixelization, which is therefore + passed into the calculations performed in the `inversion` module. """ try: noise_map = data / signal_to_noise_map @@ -117,7 +130,8 @@ def via_signal_to_noise_map( return DatasetQuantity( data=data, noise_map=noise_map, - over_sampling=over_sampling, + over_sample_size_lp=over_sample_size_lp, + over_sample_size_pixelization=over_sample_size_pixelization, ) @property @@ -133,7 +147,8 @@ def y(self) -> "DatasetQuantity": return DatasetQuantity( data=self.data.y, noise_map=self.noise_map.y, - over_sampling=self.over_sampling, + over_sample_size_lp=self.over_sample_size_lp, + over_sample_size_pixelization=self.over_sample_size_pixelization, ) @property @@ -149,7 +164,8 @@ def x(self) -> "DatasetQuantity": return DatasetQuantity( data=self.data.x, noise_map=self.noise_map.x, - over_sampling=self.over_sampling, + over_sample_size_lp=self.over_sample_size_lp, + over_sample_size_pixelization=self.over_sample_size_pixelization, ) def apply_mask(self, mask: aa.Mask2D) -> "DatasetQuantity": @@ -172,11 +188,16 @@ def apply_mask(self, mask: aa.Mask2D) -> "DatasetQuantity": data = self.data.apply_mask(mask=mask) noise_map = self.noise_map.apply_mask(mask=mask) + over_sample_size_lp = self.over_sample_size_lp.apply_mask(mask=mask) + over_sample_size_pixelization = self.over_sample_size_pixelization.apply_mask( + mask=mask + ) dataset = DatasetQuantity( data=data, noise_map=noise_map, - over_sampling=self.over_sampling, + over_sample_size_lp=over_sample_size_lp, + over_sample_size_pixelization=over_sample_size_pixelization, ) dataset.unmasked = unmasked_dataset diff --git a/autogalaxy/quantity/fit_quantity.py b/autogalaxy/quantity/fit_quantity.py index 675e37dbe..6e976b88d 100644 --- a/autogalaxy/quantity/fit_quantity.py +++ b/autogalaxy/quantity/fit_quantity.py @@ -56,7 +56,7 @@ def __init__( def model_data(self): if self.model_data_manual is None: func = getattr(self.light_mass_obj, self.func_str) - return func(grid=self.grids.uniform) + return func(grid=self.grids.lp) return self.model_data_manual diff --git a/autogalaxy/quantity/model/plotter_interface.py b/autogalaxy/quantity/model/plotter_interface.py index ea5c62a6b..98070b253 100644 --- a/autogalaxy/quantity/model/plotter_interface.py +++ b/autogalaxy/quantity/model/plotter_interface.py @@ -16,15 +16,15 @@ def fit_quantity( Visualizes a `FitQuantity` object, which fits a quantity of a light or mass profile (e.g. an image, potential) to the same quantity of another light or mass profile. - Images are output to the `image` folder of the `image_path` in a subfolder called `fit_quantity`. When - used with a non-linear search the `image_path` points to the search's results folder and this function - visualizes the maximum log likelihood `FitQuantity` inferred by the search so far. + Images are output to the `image` folder of the `image_path`. When used with a non-linear search the `image_path` + points to the search's results folder and this function visualizes the maximum log likelihood `FitQuantity` + inferred by the search so far. - Visualization includes individual images of attributes of the `FitQuantity` (e.g. the model data, residual map) - and a subplot of all `FitQuantity`'s images on the same figure. + Visualization includes a subplot of individual images of attributes of the `FitQuantity` (e.g. the model data, + residual map). - The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under the - [fit_quantity] header. + The images output by the `PlotterInterface` are customized using the file `config/visualize/plots.yaml` under + the `fit_quantity` header. Parameters ---------- @@ -38,7 +38,7 @@ def fit_quantity( def should_plot(name): return plot_setting(section="fit_quantity", name=name) - mat_plot_2d = self.mat_plot_2d_from(subfolders="fit_quantity") + mat_plot_2d = self.mat_plot_2d_from() fit_quantity_plotter = fit_quanaity_plotter_cls( fit=fit, @@ -49,40 +49,3 @@ def should_plot(name): if should_plot("subplot_fit"): fit_quantity_plotter.subplot_fit() - - mat_plot_2d = self.mat_plot_2d_from(subfolders="fit_quantity") - - fit_quantity_plotter = FitQuantityPlotter( - fit=fit, - mat_plot_2d=mat_plot_2d, - visuals_2d=visuals_2d, - include_2d=self.include_2d, - ) - - fit_quantity_plotter.figures_2d( - image=should_plot("image"), - noise_map=should_plot("noise_map"), - model_image=should_plot("model_image"), - residual_map=should_plot("residual_map"), - normalized_residual_map=should_plot("normalized_residual_map"), - chi_squared_map=should_plot("chi_squared_map"), - ) - - if should_plot("all_at_end_fits"): - mat_plot_2d = self.mat_plot_2d_from( - subfolders="fit_quantity/fits", format="fits" - ) - - fit_plotter = FitQuantityPlotter( - fit=fit, mat_plot_2d=mat_plot_2d, include_2d=self.include_2d - ) - - fit_plotter.figures_2d( - image=True, - noise_map=True, - signal_to_noise_map=True, - model_image=True, - residual_map=True, - normalized_residual_map=True, - chi_squared_map=True, - ) diff --git a/autogalaxy/quantity/model/visualizer.py b/autogalaxy/quantity/model/visualizer.py index 2b2af686a..398139d77 100644 --- a/autogalaxy/quantity/model/visualizer.py +++ b/autogalaxy/quantity/model/visualizer.py @@ -35,9 +35,6 @@ def visualize( instance An instance of the model that is being fitted to the data by this analysis (whose parameters have been set via a non-linear search). - during_analysis - If True the visualization is being performed midway through the non-linear search before it is finished, - which may change which images are output. """ if os.environ.get("PYAUTOFIT_TEST_MODE") == "1": diff --git a/autogalaxy/util/__init__.py b/autogalaxy/util/__init__.py index 751609cef..07b85cd91 100644 --- a/autogalaxy/util/__init__.py +++ b/autogalaxy/util/__init__.py @@ -1,6 +1,7 @@ from autoarray.geometry import geometry_util as geometry from autoarray.mask import mask_1d_util as mask_1d from autoarray.mask import mask_2d_util as mask_2d +from autoarray.operators.over_sampling import over_sample_util as over_sample from autoarray.structures.arrays import array_1d_util as array_1d from autoarray.structures.arrays import array_2d_util as array_2d from autoarray.structures.grids import grid_1d_util as grid_1d diff --git a/docs/api/data.rst b/docs/api/data.rst index e283421ca..a0d3b6180 100644 --- a/docs/api/data.rst +++ b/docs/api/data.rst @@ -67,8 +67,7 @@ applied to datasets to apply over sampling to their fit. :template: custom-class-template.rst :recursive: - OverSamplingUniform - OverSamplingIterate + OverSampling 1D Data Structures diff --git a/docs/howtogalaxy/chapter_2_modeling.rst b/docs/howtogalaxy/chapter_2_modeling.rst index 66c2432b2..67ee3985b 100644 --- a/docs/howtogalaxy/chapter_2_modeling.rst +++ b/docs/howtogalaxy/chapter_2_modeling.rst @@ -5,27 +5,27 @@ In chapter 2, we'll take you through how to model galaxies using a non-linear se The chapter contains the following tutorials: -`Tutorial 1: Non-linear Search `_ -- How a non-linear search is used to fit a lens model. +`Tutorial 1: Non-linear Search `_ +- How a non-linear search is used to fit a model and the concepts of a parameter space and priors. -`Tutorial 2: Parameter Space And Priors `_ -- The Concepts of a parameter space and priors. +`Tutorial 2: Practicalities `_ +- Practicalities of performing model-fitting, like how to inspect the results on your hard-disk. -`Tutorial 3: Realism and Complexity `_ -- Finding a balance between realism and complexity when composing and fitting a lens model. +`Tutorial 3: Realism and Complexity `_ +- Finding a balance between realism and complexity when composing and fitting a model. -`Tutorial 4: Dealing with Failure `_ -- What to do when PyAutoLens finds an inaccurate lens model. +`Tutorial 4: Dealing with Failure `_ +- What to do when PyAutoGalaxy finds an inaccurate model. -`Tutorial 5: Linear Profiles `_ +`Tutorial 5: Linear Profiles `_ - Light profiles which capture complex morphologies in a reduced number of non-linear parameters. -`Tutorial 6: Masking and Positions `_ -- How to mask and mark positions on your data to improve the lens model. +`Tutorial 6: Masking `_ +- How to mask your data to improve the model. -`Tutorial 7: Results `_ -- Overview of the results available after successfully fitting a lens model. +`Tutorial 7: Results `_ +- Overview of the results available after successfully fitting a model. -`Tutorial 8: Need for Speed `_ +`Tutorial 8: Need for Speed `_ - How to fit complex models whilst balancing efficiency and run-time. diff --git a/docs/installation/conda.rst b/docs/installation/conda.rst index 6957e6629..2df01a4ed 100644 --- a/docs/installation/conda.rst +++ b/docs/installation/conda.rst @@ -46,7 +46,7 @@ You may get warnings which state something like: .. code-block:: bash - ERROR: autoarray 2024.9.21.2 has requirement numpy<=1.22.1, but you'll have numpy 1.22.2 which is incompatible. + ERROR: autoarray 2025.1.18.7 has requirement numpy<=1.22.1, but you'll have numpy 1.22.2 which is incompatible. ERROR: numba 0.53.1 has requirement llvmlite<0.37,>=0.36.0rc1, but you'll have llvmlite 0.38.0 which is incompatible. If you see these messages, they do not mean that the installation has failed and the instructions below will @@ -106,7 +106,7 @@ For interferometer analysis there are two optional dependencies that must be ins .. code-block:: bash pip install pynufft - pip install pylops==1.11.1 + pip install pylops==2.3.1 **PyAutoGalaxy** will run without these libraries and it is recommended that you only install them if you intend to do interferometer analysis. diff --git a/docs/installation/pip.rst b/docs/installation/pip.rst index 760f86674..e5c90874d 100644 --- a/docs/installation/pip.rst +++ b/docs/installation/pip.rst @@ -27,7 +27,7 @@ You may get warnings which state something like: .. code-block:: bash - ERROR: autoarray 2024.9.21.2 has requirement numpy<=1.22.1, but you'll have numpy 1.22.2 which is incompatible. + ERROR: autoarray 2025.1.18.7 has requirement numpy<=1.22.1, but you'll have numpy 1.22.2 which is incompatible. ERROR: numba 0.53.1 has requirement llvmlite<0.37,>=0.36.0rc1, but you'll have llvmlite 0.38.0 which is incompatible. If you see these messages, they do not mean that the installation has failed and the instructions below will @@ -86,7 +86,7 @@ For interferometer analysis there are two optional dependencies that must be ins .. code-block:: bash pip install pynufft - pip install pylops==1.11.1 + pip install pylops==2.3.1 **PyAutoGalaxy** will run without these libraries and it is recommended that you only install them if you intend to do interferometer analysis. diff --git a/docs/installation/source.rst b/docs/installation/source.rst index e4cd49647..ec1d3ca02 100644 --- a/docs/installation/source.rst +++ b/docs/installation/source.rst @@ -56,7 +56,7 @@ For unit tests to pass you will also need the following optional requirements: .. code-block:: bash pip install pynufft - pip install pylops==1.11.1 + pip install pylops==2.3.1 If you are using a ``conda`` environment, add the source repository as follows: diff --git a/docs/overview/overview_1_start_here.rst b/docs/overview/overview_1_start_here.rst index ce3046d85..368a67598 100644 --- a/docs/overview/overview_1_start_here.rst +++ b/docs/overview/overview_1_start_here.rst @@ -268,7 +268,7 @@ object. exposure_time=300.0, background_sky_level=1.0, psf=ag.Kernel2D.from_gaussian(shape_native=(11, 11), sigma=0.1, pixel_scales=0.05), - add_poisson_noise=True, + add_poisson_noise_to_data=True, ) diff --git a/test_autogalaxy/aggregator/imaging/test_aggregator_imaging.py b/test_autogalaxy/aggregator/imaging/test_aggregator_imaging.py index b7009a859..61eef4635 100644 --- a/test_autogalaxy/aggregator/imaging/test_aggregator_imaging.py +++ b/test_autogalaxy/aggregator/imaging/test_aggregator_imaging.py @@ -12,10 +12,8 @@ def test__dataset_generator_from_aggregator__analysis_has_single_dataset( data=image_7x7, psf=psf_3x3, noise_map=noise_map_7x7, - over_sampling=ag.OverSamplingDataset( - uniform=ag.OverSamplingIterate(fractional_accuracy=0.5, sub_steps=[2]), - pixelization=ag.OverSamplingUniform(sub_size=3), - ), + over_sample_size_lp=5, + over_sample_size_pixelization=3, ) masked_imaging_7x7 = imaging.apply_mask(mask=mask_2d_7x7) @@ -34,14 +32,8 @@ def test__dataset_generator_from_aggregator__analysis_has_single_dataset( for dataset_list in dataset_gen: assert (dataset_list[0].data == masked_imaging_7x7.data).all() - assert isinstance( - dataset_list[0].grids.uniform.over_sampling, ag.OverSamplingIterate - ) - assert isinstance( - dataset_list[0].grids.pixelization.over_sampling, ag.OverSamplingUniform - ) - assert dataset_list[0].grids.uniform.over_sampling.sub_steps == [2] - assert dataset_list[0].grids.uniform.over_sampling.fractional_accuracy == 0.5 + assert dataset_list[0].grids.over_sample_size_lp.slim[0] == 5 + assert dataset_list[0].grids.over_sample_size_pixelization.slim[0] == 3 clean(database_file=database_file) diff --git a/test_autogalaxy/aggregator/interferometer/test_aggregator_interferometer.py b/test_autogalaxy/aggregator/interferometer/test_aggregator_interferometer.py index f0581d098..d6257103d 100644 --- a/test_autogalaxy/aggregator/interferometer/test_aggregator_interferometer.py +++ b/test_autogalaxy/aggregator/interferometer/test_aggregator_interferometer.py @@ -18,10 +18,6 @@ def test__interferometer_generator_from_aggregator__analysis_has_single_dataset( noise_map=visibilities_noise_map_7, uv_wavelengths=uv_wavelengths_7x2, real_space_mask=mask_2d_7x7, - over_sampling=ag.OverSamplingDataset( - uniform=ag.OverSamplingIterate(fractional_accuracy=0.5, sub_steps=[2]), - pixelization=ag.OverSamplingUniform(sub_size=3), - ), transformer_class=ag.TransformerDFT, ) @@ -40,14 +36,6 @@ def test__interferometer_generator_from_aggregator__analysis_has_single_dataset( for dataset_list in dataset_gen: assert (dataset_list[0].data == interferometer_7.data).all() assert (dataset_list[0].real_space_mask == mask_2d_7x7).all() - assert isinstance( - dataset_list[0].grids.uniform.over_sampling, ag.OverSamplingIterate - ) - assert isinstance( - dataset_list[0].grids.pixelization.over_sampling, ag.OverSamplingUniform - ) - assert dataset_list[0].grids.uniform.over_sampling.sub_steps == [2] - assert dataset_list[0].grids.uniform.over_sampling.fractional_accuracy == 0.5 assert isinstance(dataset_list[0].transformer, ag.TransformerDFT) clean(database_file=database_file) diff --git a/test_autogalaxy/analysis/test_plotter_interface.py b/test_autogalaxy/analysis/test_plotter_interface.py index fb461850b..3893e508c 100644 --- a/test_autogalaxy/analysis/test_plotter_interface.py +++ b/test_autogalaxy/analysis/test_plotter_interface.py @@ -24,48 +24,21 @@ def test__galaxies( plotter_interface.galaxies( galaxies=galaxies_7x7, - grid=masked_imaging_7x7.grids.uniform, - during_analysis=False, + grid=masked_imaging_7x7.grids.lp, ) assert path.join(plot_path, "subplot_galaxies.png") in plot_patch.paths - - plot_path = path.join(plot_path, "galaxies") - assert path.join(plot_path, "subplot_galaxy_images.png") in plot_patch.paths - assert path.join(plot_path, "image_2d.png") in plot_patch.paths - assert path.join(plot_path, "convergence_2d.png") in plot_patch.paths - assert path.join(plot_path, "potential_2d.png") not in plot_patch.paths - assert path.join(plot_path, "deflections_y_2d.png") not in plot_patch.paths - assert path.join(plot_path, "deflections_x_2d.png") not in plot_patch.paths - assert path.join(plot_path, "magnification_2d.png") in plot_patch.paths - - convergence = ag.util.array_2d.numpy_array_2d_via_fits_from( - file_path=path.join(plot_path, "fits", "convergence_2d.fits"), hdu=0 + assert path.join(plot_path, "subplot_galaxies_1d.png") in plot_patch.paths + assert ( + path.join(plot_path, "subplot_galaxies_1d_decomposed.png") in plot_patch.paths ) - assert convergence.shape == (7, 7) - - -def test__galaxies_1d( - masked_imaging_7x7, galaxies_7x7, include_2d_all, plot_path, plot_patch -): - if path.exists(plot_path): - shutil.rmtree(plot_path) - - plotter_interface = PlotterInterface(image_path=plot_path) - - plotter_interface.galaxies_1d( - galaxies=galaxies_7x7, - grid=masked_imaging_7x7.grids.uniform, - during_analysis=False, + image = ag.util.array_2d.numpy_array_2d_via_fits_from( + file_path=path.join(plot_path, "galaxy_images.fits"), hdu=0 ) - plot_path = path.join(plot_path, "galaxies_1d") - - assert path.join(plot_path, "image_1d_decomposed.png") in plot_patch.paths - assert path.join(plot_path, "convergence_1d_decomposed.png") not in plot_patch.paths - assert path.join(plot_path, "potential_1d_decomposed.png") in plot_patch.paths + assert image.shape == (5, 5) def test__inversion( @@ -81,18 +54,11 @@ def test__inversion( plotter_interface = PlotterInterface(image_path=plot_path) plotter_interface.inversion( - inversion=rectangular_inversion_7x7_3x3, during_analysis=True + inversion=rectangular_inversion_7x7_3x3, ) assert path.join(plot_path, "subplot_inversion_0.png") in plot_patch.paths - plot_path = path.join(plot_path, "inversion") - - assert path.join(plot_path, "reconstructed_image.png") in plot_patch.paths - assert path.join(plot_path, "reconstruction.png") in plot_patch.paths - assert path.join(plot_path, "inversion", "errors.png") not in plot_patch.paths - assert path.join(plot_path, "regularization_weights.png") not in plot_patch.paths - def test__adapt_images( masked_imaging_7x7, @@ -112,9 +78,6 @@ def test__adapt_images( adapt_images=adapt_images, ) - plot_path = path.join(plot_path, "adapt") + plot_path = path.join(plot_path) - assert path.join(plot_path, "adapt_model_image.png") in plot_patch.paths - assert ( - path.join(plot_path, "subplot_adapt_images_of_galaxies.png") in plot_patch.paths - ) + assert path.join(plot_path, "subplot_adapt_images.png") in plot_patch.paths diff --git a/test_autogalaxy/config/grids.yaml b/test_autogalaxy/config/grids.yaml index fc0c3dbac..a779246ac 100644 --- a/test_autogalaxy/config/grids.yaml +++ b/test_autogalaxy/config/grids.yaml @@ -76,158 +76,3 @@ radial_minimum: SersicGradientSph: 0.0001 EllProfile: 0.0001 SersicAdaptTest: 0.0001 - - -# Over sampling is an important numerical technique, whereby light profiles images are evaluated on a higher resolution -# grid than the image data to ensure the calculation is accurate. - -# By default, a user does not specify the over sampling factor, and a default over sampling scheme is used for each -# profile. This scheme first goes to the centre of the profile, and computes circles with certain radial values -# (e.g. radii). It then assigns an over sampling `sub_size` to each circle, where the central circles have the highest -# over sampling factor and the outer circles have the lowest. - -# The size of the circles that are appropriate for determining the over sampling factor are dependent on the resolution -# of the grid. For a high resolution grid (e.g. low pixel scale), a smaller circle central circle is necessary to -# over sample the profile accurately. The config file below therefore specifies the "radial factors" used for -# automatically determining the over sampling factors for each profile, which is the factor the pixel scale is multiplied -# by to determine the circle size. - -# The config entry below defines the default over sampling factor for each profile, where: - -# radial_factor_list: The factors that are multiplied by the pixel scale to determine the circle size that is used. -# sub_size_list: The over sampling factor that is used for each circle size. - -# For the default entries below, oversampling of degree 32 x 32 is used within a circle of radius 3.01 x pixel scale, -# 4 x 4 within a circle of radius 10.01 x pixel scale and 2 x 2 for all pixels outside of this radius. - -over_sampling: - radial_factor_list: - Chameleon: [1.0] - ChameleonSph: [1.0] - DevVaucouleurs: [1.0] - DevVaucouleursSph: [1.0] - dPIE: [1.0] - dPIESph: [1.0] - ExponentialRadialGradient: [1.0] - ExponentialRadialGradientSph: [1.0] - ElsonFreeFall: [1.0] - ElsonFreeFallSph: [1.0] - Exponential: [1.0] - ExponentialCore: [1.0] - ExponentialCoreSph: [1.0] - ExponentialSph: [1.0] - ExternalShear: [1.0] - Gaussian: [1.0] - GaussianSph: [1.0] - gNFW: [1.0] - gNFWMCRLudlow: [1.0] - gNFWVirialMassConcSph: [1.0] - gNFWSph: [1.0] - Isothermal: [1.0] - IsothermalCore: [1.0] - IsothermalCoreSph: [1.0] - IsothermalSph: [1.0] - MassSheet: [1.0] - Moffat: [1.0] - MoffatSph: [1.0] - PowerLawMultipole: [1.0] - NFW: [1.0] - NFWMCRDuffySph: [1.0] - NFWMCRLudlow: [1.0] - NFWMCRLudlowSph: [1.0] - NFWMCRScatterLudlow: [1.0] - NFWMCRScatterLudlowSph: [1.0] - NFWVirialMassConcSph: [1.0] - NFWSph: [1.0] - NFWTruncatedMCRDuffySph: [1.0] - NFWTruncatedMCRLudlowSph: [1.0] - NFWTruncatedMCRScatterLudlowSph: [1.0] - NFWTruncatedSph: [1.0] - PointMass: [1.0] - PowerLaw: [1.0] - PowerLawBroken: [1.0] - PowerLawBrokenSph: [1.0] - PowerLawCore: [1.0] - PowerLawCoreSph: [1.0] - PowerLawSph: [1.0] - Sersic: [1.0] - SersicCore: [1.0] - SersicCoreSph: [1.0] - SersicRadialGradient: [1.0] - SersicSph: [1.0] - SersicRadialGradientSph: [1.0] - ShapeletCartesianSph: [1.0] - ShapeletCartesian: [1.0] - ShapeletPolarSph: [1.0] - ShapeletPolar: [1.0] - ShapeletExponentialSph: [1.0] - ShapeletExponential: [1.0] - SMBH: [1.0] - SMBHBinary: [1.0] - EllProfile: [1.0] - SersicAdaptTest: [0.1] - sub_size_list: - Chameleon: [1, 1] - ChameleonSph: [1, 1] - DevVaucouleurs: [1, 1] - DevVaucouleursSph: [1, 1] - dPIE: [1, 1] - dPIESph: [1, 1] - ExponentialRadialGradient: [1, 1] - ExponentialRadialGradientSph: [1, 1] - ElsonFreeFall: [1, 1] - ElsonFreeFallSph: [1, 1] - Exponential: [1, 1] - ExponentialCore: [1, 1] - ExponentialCoreSph: [1, 1] - ExponentialSph: [1, 1] - ExternalShear: [1, 1] - Gaussian: [1, 1] - GaussianSph: [1, 1] - gNFW: [1, 1] - gNFWMCRLudlow: [1, 1] - gNFWVirialMassConcSph: [1, 1] - gNFWSph: [1, 1] - Isothermal: [1, 1] - IsothermalCore: [1, 1] - IsothermalCoreSph: [1, 1] - IsothermalSph: [1, 1] - MassSheet: [1, 1] - Moffat: [1, 1] - MoffatSph: [1, 1] - PowerLawMultipole: [1, 1] - NFW: [1, 1] - NFWMCRDuffySph: [1, 1] - NFWMCRLudlow: [1, 1] - NFWMCRLudlowSph: [1, 1] - NFWMCRScatterLudlow: [1, 1] - NFWMCRScatterLudlowSph: [1, 1] - NFWVirialMassConcSph : [1, 1] - NFWSph: [1, 1] - NFWTruncatedMCRDuffySph: [1, 1] - NFWTruncatedMCRLudlowSph: [1, 1] - NFWTruncatedMCRScatterLudlowSph: [1, 1] - NFWTruncatedSph: [1, 1] - PointMass: [1, 1] - PowerLaw: [1, 1] - PowerLawBroken: [1, 1] - PowerLawBrokenSph: [1, 1] - PowerLawCore: [1, 1] - PowerLawCoreSph: [1, 1] - PowerLawSph: [1, 1] - Sersic: [1, 1] - SersicCore: [1, 1] - SersicCoreSph: [1, 1] - SersicRadialGradient: [1, 1] - SersicSph: [1, 1] - SersicRadialGradientSph: [1, 1] - ShapeletCartesianSph: [1, 1] - ShapeletCartesian: [1, 1] - ShapeletPolarSph: [1, 1] - ShapeletPolar: [1, 1] - ShapeletExponentialSph: [1, 1] - ShapeletExponential: [1, 1] - SMBH: [1, 1] - SMBHBinary: [1, 1] - EllProfile: [1, 1] - SersicAdaptTest: [8, 1] \ No newline at end of file diff --git a/test_autogalaxy/config/non_linear.yaml b/test_autogalaxy/config/non_linear.yaml index f4788e591..a805c821e 100644 --- a/test_autogalaxy/config/non_linear.yaml +++ b/test_autogalaxy/config/non_linear.yaml @@ -1,3 +1,21 @@ +mock: + MockMLE: + initialize: + method: prior + printing: + silence: false + updates: + iterations_per_update: 2500 + remove_state_files_at_end: true + MockSearch: + initialize: + method: prior + printing: + silence: false + search: {} + updates: + iterations_per_update: 2500 + remove_state_files_at_end: true GridSearch: general: number_of_cores: 2 @@ -24,24 +42,6 @@ mcmc: updates: iterations_per_update: 2500 remove_state_files_at_end: true -mock: - MockMLEr: - initialize: - method: prior - printing: - silence: false - updates: - iterations_per_update: 2500 - remove_state_files_at_end: true - MockSearch: - initialize: - method: prior - printing: - silence: false - search: {} - updates: - iterations_per_update: 2500 - remove_state_files_at_end: true nest: DynestyDynamic: initialize: diff --git a/test_autogalaxy/config/visualize.yaml b/test_autogalaxy/config/visualize.yaml index 2b170d7c2..93f4ab426 100644 --- a/test_autogalaxy/config/visualize.yaml +++ b/test_autogalaxy/config/visualize.yaml @@ -363,85 +363,26 @@ mat_wrap_2d: s: 17 plots: dataset: - data: true - noise_map: false - signal_to_noise_map: false subplot_dataset: true fit: - all_at_end_fits: true - all_at_end_png: false - chi_squared_map: true - data: true - model_data: true - model_images_of_galaxies: false - noise_map: false - normalized_residual_map: true - residual_map: false - signal_to_noise_map: false subplot_fit: true subplot_of_galaxies: false - subtracted_images_of_galaxies: true + fits_fit: true # Output a .fits file containing the fit model data, residual map, normalized residual map and chi-squared? + fits_model_galaxy_images : true # Output a .fits file containing the model images of every galaxy? fit_imaging: {} fit_interferometer: - amplitudes_vs_uv_distances: false - dirty_chi_squared_map: false - dirty_image: false - dirty_noise_map: false - dirty_normalized_residual_map: false - dirty_residual_map: false - dirty_signal_to_noise_map: false - phases_vs_uv_distances: false - uv_wavelengths: false + fits_dirty_images: true # output dirty_images.fits showing the dirty image, noise-map, model-data, resiual-map, normalized residual map and chi-squared map? fit_quantity: - all_at_end_fits: false - all_at_end_png: false - chi_squared_map: false - image: true - model_image: true - noise_map: false - normalized_residual_map: false - residual_map: false subplot_fit: false - galaxies_1d: - convergence: false - image: true - potential: true adapt: - images_of_galaxies: true - model_image: true - imaging: - psf: true - interferometer: - amplitudes_vs_uv_distances: false - dirty_image: false - dirty_noise_map: false - dirty_signal_to_noise_map: false - phases_vs_uv_distances: false - uv_wavelengths: false + subplot_adapt_images: true inversion: - all_at_end_png: false - chi_squared_map: true - errors: false - interpolated_errors: true - interpolated_reconstruction: true - normalized_residual_map: false - reconstructed_image: true - reconstruction: true - regularization_weights: false - residual_map: false subplot_inversion: true - other: - stochastic_histogram: false galaxies: - all_at_end_fits: true - all_at_end_png: false - convergence: true - deflections: false - image: true - magnification: true - potential: false - source_plane_image: true subplot_galaxies: true subplot_galaxy_images: true + subplot_galaxies_1d: true + subplot_galaxies_1d_decomposed: true + fits_galaxy_images: true # Output a .fits file containing images of every galaxy? positions: image_with_positions: true diff --git a/test_autogalaxy/ellipse/test_fit_ellipse.py b/test_autogalaxy/ellipse/test_fit_ellipse.py index 7a5918802..6fc1976ff 100644 --- a/test_autogalaxy/ellipse/test_fit_ellipse.py +++ b/test_autogalaxy/ellipse/test_fit_ellipse.py @@ -67,16 +67,16 @@ def test___points_from_major_axis__multipole(imaging_lh): assert fit._points_from_major_axis[1, 1] == pytest.approx(-0.038278334, 1.0e-4) -def test__mask_interp(imaging_lh, imaging_lh_masked): - ellipse_0 = ag.Ellipse(centre=(0.0, 0.0), ell_comps=(0.0, 0.0), major_axis=1.0) - - fit = ag.FitEllipse(dataset=imaging_lh, ellipse=ellipse_0) - - assert fit.mask_interp == pytest.approx([False, False, False, False, False], 1.0e-4) - - fit = ag.FitEllipse(dataset=imaging_lh_masked, ellipse=ellipse_0) - - assert fit.mask_interp == pytest.approx([False, True, True, True, True], 1.0e-4) +# def test__mask_interp(imaging_lh, imaging_lh_masked): +# ellipse_0 = ag.Ellipse(centre=(0.0, 0.0), ell_comps=(0.0, 0.0), major_axis=1.0) +# +# fit = ag.FitEllipse(dataset=imaging_lh, ellipse=ellipse_0) +# +# assert fit.mask_interp == pytest.approx([False, False, False, False, False], 1.0e-4) +# +# fit = ag.FitEllipse(dataset=imaging_lh_masked, ellipse=ellipse_0) +# +# assert fit.mask_interp == pytest.approx([False, True, True, True, True], 1.0e-4) def test__total_points_interp(imaging_lh, imaging_lh_masked): diff --git a/test_autogalaxy/galaxy/plot/test_hyper_galaxy_plotters.py b/test_autogalaxy/galaxy/plot/test_adapt_plotters.py similarity index 72% rename from test_autogalaxy/galaxy/plot/test_hyper_galaxy_plotters.py rename to test_autogalaxy/galaxy/plot/test_adapt_plotters.py index a622ba8ce..8e1eec666 100644 --- a/test_autogalaxy/galaxy/plot/test_hyper_galaxy_plotters.py +++ b/test_autogalaxy/galaxy/plot/test_adapt_plotters.py @@ -14,7 +14,7 @@ def make_adapt_plotter_setup(): ) -def test__plot_adapt_images_of_galaxies( +def test__plot_adapt_adapt_images( adapt_galaxy_name_image_dict_7x7, mask_2d_7x7, include_2d_all, plot_path, plot_patch ): adapt_plotter = aplt.AdaptPlotter( @@ -22,9 +22,7 @@ def test__plot_adapt_images_of_galaxies( mat_plot_2d=aplt.MatPlot2D(output=aplt.Output(plot_path, format="png")), ) - adapt_plotter.subplot_images_of_galaxies( + adapt_plotter.subplot_adapt_images( adapt_galaxy_name_image_dict=adapt_galaxy_name_image_dict_7x7 ) - assert ( - path.join(plot_path, "subplot_adapt_images_of_galaxies.png") in plot_patch.paths - ) + assert path.join(plot_path, "subplot_adapt_images.png") in plot_patch.paths diff --git a/test_autogalaxy/galaxy/plot/test_galaxies_plotter.py b/test_autogalaxy/galaxy/plot/test_galaxies_plotter.py index a95ff559f..71a88e3ed 100644 --- a/test_autogalaxy/galaxy/plot/test_galaxies_plotter.py +++ b/test_autogalaxy/galaxy/plot/test_galaxies_plotter.py @@ -65,13 +65,15 @@ def test__figures_of_galaxies( def test__galaxies_sub_plot_output( - galaxies_x2_7x7, grid_2d_7x7, include_2d_all, plot_path, plot_patch + galaxies_x2_7x7, grid_2d_7x7, include_2d_all, include_1d_all, plot_path, plot_patch ): plotter = aplt.GalaxiesPlotter( galaxies=galaxies_x2_7x7, grid=grid_2d_7x7, include_2d=include_2d_all, mat_plot_2d=aplt.MatPlot2D(output=aplt.Output(plot_path, format="png")), + include_1d=include_1d_all, + mat_plot_1d=aplt.MatPlot2D(output=aplt.Output(plot_path, format="png")), ) plotter.subplot_galaxies() @@ -79,3 +81,11 @@ def test__galaxies_sub_plot_output( plotter.subplot_galaxy_images() assert path.join(plot_path, "subplot_galaxy_images.png") in plot_patch.paths + + plotter.subplot_galaxies_1d() + assert path.join(plot_path, "subplot_galaxies_1d.png") in plot_patch.paths + + plotter.subplot_galaxies_1d_decomposed() + assert ( + path.join(plot_path, "subplot_galaxies_1d_decomposed.png") in plot_patch.paths + ) diff --git a/test_autogalaxy/galaxy/test_galaxies.py b/test_autogalaxy/galaxy/test_galaxies.py index 726513b44..5167723b0 100644 --- a/test_autogalaxy/galaxy/test_galaxies.py +++ b/test_autogalaxy/galaxy/test_galaxies.py @@ -284,4 +284,4 @@ def test__plane_image_from(grid_2d_7x7): plane_image = plane_image_from(grid=grid_2d_7x7, galaxies=[galaxy], buffer=0.1) - assert plane_image[0] == pytest.approx(12.5227, 1.0e-4) + assert plane_image[0] == pytest.approx(12.5595, 1.0e-3) diff --git a/test_autogalaxy/galaxy/test_galaxy.py b/test_autogalaxy/galaxy/test_galaxy.py index 4bc5c8da0..ca087dfad 100644 --- a/test_autogalaxy/galaxy/test_galaxy.py +++ b/test_autogalaxy/galaxy/test_galaxy.py @@ -587,54 +587,6 @@ def test__centre_of_profile_in_right_place(): assert deflections.native[1, 4, 1] > 0 assert deflections.native[1, 3, 1] < 0 - grid = ag.Grid2D.uniform( - shape_native=(7, 7), - pixel_scales=1.0, - over_sampling=ag.OverSamplingIterate( - fractional_accuracy=0.99, sub_steps=[2, 4] - ), - ) - - galaxy = ag.Galaxy( - redshift=0.5, - mass=ag.mp.Isothermal(centre=(2.0, 1.0), einstein_radius=1.0), - mass_0=ag.mp.Isothermal(centre=(2.0, 1.0), einstein_radius=1.0), - ) - convergence = galaxy.convergence_2d_from(grid=grid) - max_indexes = np.unravel_index( - convergence.native.argmax(), convergence.shape_native - ) - assert max_indexes == (1, 4) - - potential = galaxy.potential_2d_from(grid=grid) - max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) - assert max_indexes == (1, 4) - - deflections = galaxy.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 - - galaxy = ag.Galaxy( - redshift=0.5, mass=ag.mp.IsothermalSph(centre=(2.0, 1.0), einstein_radius=1.0) - ) - convergence = galaxy.convergence_2d_from(grid=grid) - max_indexes = np.unravel_index( - convergence.native.argmax(), convergence.shape_native - ) - assert max_indexes == (1, 4) - - potential = galaxy.potential_2d_from(grid=grid) - max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) - assert max_indexes == (1, 4) - - deflections = galaxy.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__cannot_pass_light_or_mass_list(): light_list = [ag.lp.Sersic(), ag.lp.Sersic()] @@ -687,17 +639,13 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): galaxy = ag.Galaxy(redshift=0.5, light=ag.lp.Sersic(intensity=1.0)) - over_sampling = ag.OverSamplingUniform(sub_size=1) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=1) image = galaxy.image_2d_from(grid=grid) assert image[0] == pytest.approx(0.15987224303572964, 1.0e-6) - over_sampling = ag.OverSamplingUniform(sub_size=2) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=2) image = galaxy.image_2d_from(grid=grid) @@ -708,17 +656,13 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): redshift=0.5, light=ag.lp.Sersic(centre=(3.0, 3.0), intensity=1.0) ) - over_sampling = ag.OverSamplingUniform(sub_size=1) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=1) image = galaxy.image_2d_from(grid=grid) assert image[0] == pytest.approx(0.006719704400094508, 1.0e-6) - over_sampling = ag.OverSamplingUniform(sub_size=2) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=2) image = galaxy.image_2d_from(grid=grid) @@ -726,69 +670,6 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): assert image[1] == pytest.approx(0.013323319136547789, 1.0e-6) -def test__decorator__grid_iterate_in__iterates_array_result_correctly(gal_x1_lp): - mask = ag.Mask2D( - mask=[ - [True, True, True, True, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, True, True, True, True], - ], - pixel_scales=(1.0, 1.0), - ) - - over_sampling = ag.OverSamplingIterate(fractional_accuracy=1.0, sub_steps=[2]) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) - - galaxy = ag.Galaxy(redshift=0.5, light=ag.lp.Sersic(intensity=1.0)) - - image = galaxy.image_2d_from(grid=grid) - - grid_sub_2 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=2) - ) - image_sub_2 = galaxy.image_2d_from(grid=grid_sub_2) - - assert image[0] == pytest.approx(0.17481917162057087, 1.0e-6) - assert (image == image_sub_2).all() - - over_sampling = ag.OverSamplingIterate( - fractional_accuracy=0.95, sub_steps=[2, 4, 8] - ) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) - - galaxy = ag.Galaxy( - redshift=0.5, light=ag.lp.Sersic(centre=(0.08, 0.08), intensity=1.0) - ) - - image = galaxy.image_2d_from(grid=grid) - - grid_sub_4 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=4) - ) - image_sub_4 = galaxy.image_2d_from(grid=grid_sub_4) - - assert image[0] == pytest.approx(0.17754459861988386, 1.0e-6) - assert image[0] == image_sub_4[0] - - grid_sub_8 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=8) - ) - image_sub_8 = galaxy.image_2d_from(grid=grid_sub_8) - - over_sampling = ag.OverSamplingUniform(sub_size=8) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) - - image = galaxy.image_2d_from(grid=grid) - - assert image[4] == pytest.approx(4.173185729427679, 1.0e-6) - assert image[4] == image_sub_8[4] - - def test__output_to_and_load_from_json(): json_file = path.join( "{}".format(path.dirname(path.realpath(__file__))), "files", "galaxy.json" diff --git a/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py b/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py index 0c43849e2..de73868d2 100644 --- a/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py +++ b/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py @@ -23,13 +23,6 @@ def test__imaging(imaging_7x7, include_2d_all, plot_path, plot_patch): assert path.join(plot_path, "subplot_dataset.png") in plot_patch.paths - plot_path = path.join(plot_path, "dataset") - - assert path.join(plot_path, "data.png") in plot_patch.paths - assert path.join(plot_path, "noise_map.png") not in plot_patch.paths - assert path.join(plot_path, "psf.png") in plot_patch.paths - assert path.join(plot_path, "signal_to_noise_map.png") not in plot_patch.paths - def test__imaging_combined(imaging_7x7, plot_path, plot_patch): if path.exists(plot_path): @@ -39,9 +32,7 @@ def test__imaging_combined(imaging_7x7, plot_path, plot_patch): visualizer.imaging_combined(dataset_list=[imaging_7x7, imaging_7x7]) - plot_path = path.join(plot_path, "combined") - - assert path.join(plot_path, "subplot_dataset.png") in plot_patch.paths + assert path.join(plot_path, "subplot_dataset_combined.png") in plot_patch.paths def test__fit_imaging( @@ -57,23 +48,22 @@ def test__fit_imaging( plotter_interface = PlotterInterfaceImaging(image_path=plot_path) plotter_interface.fit_imaging( - fit=fit_imaging_x2_galaxy_inversion_7x7, during_analysis=False + fit=fit_imaging_x2_galaxy_inversion_7x7, ) - plot_path = path.join(plot_path, "fit_dataset") - assert path.join(plot_path, "subplot_fit.png") in plot_patch.paths - assert path.join(plot_path, "data.png") in plot_patch.paths - assert path.join(plot_path, "noise_map.png") not in plot_patch.paths - assert path.join(plot_path, "subtracted_image_of_galaxy_1.png") in plot_patch.paths - assert path.join(plot_path, "model_image_of_galaxy_1.png") not in plot_patch.paths + image = ag.util.array_2d.numpy_array_2d_via_fits_from( + file_path=path.join(plot_path, "fit.fits"), hdu=0 + ) + + assert image.shape == (5, 5) image = ag.util.array_2d.numpy_array_2d_via_fits_from( - file_path=path.join(plot_path, "fits", "data.fits"), hdu=0 + file_path=path.join(plot_path, "model_galaxy_images.fits"), hdu=0 ) - assert image.shape == (7, 7) + assert image.shape == (5, 5) def test__fit_imaging_combined( @@ -86,6 +76,4 @@ def test__fit_imaging_combined( visualizer.fit_imaging_combined(fit_list=2 * [fit_imaging_x2_galaxy_inversion_7x7]) - plot_path = path.join(plot_path, "combined") - - assert path.join(plot_path, "subplot_fit.png") in plot_patch.paths + assert path.join(plot_path, "subplot_fit_combined.png") in plot_patch.paths diff --git a/test_autogalaxy/imaging/test_fit_imaging.py b/test_autogalaxy/imaging/test_fit_imaging.py index 457507b10..3b3103fc2 100644 --- a/test_autogalaxy/imaging/test_fit_imaging.py +++ b/test_autogalaxy/imaging/test_fit_imaging.py @@ -237,13 +237,13 @@ def test__galaxy_model_image_dict(masked_imaging_7x7): fit = ag.FitImaging(dataset=masked_imaging_7x7, galaxies=[g0, g1, g2, g3]) g0_blurred_image_2d = g0.blurred_image_2d_from( - grid=masked_imaging_7x7.grids.uniform, + grid=masked_imaging_7x7.grids.lp, blurring_grid=masked_imaging_7x7.grids.blurring, convolver=masked_imaging_7x7.convolver, ) g1_blurred_image_2d = g1.blurred_image_2d_from( - grid=masked_imaging_7x7.grids.uniform, + grid=masked_imaging_7x7.grids.lp, blurring_grid=masked_imaging_7x7.grids.blurring, convolver=masked_imaging_7x7.convolver, ) @@ -426,14 +426,14 @@ def test___unmasked_blurred_images(masked_imaging_7x7): fit = ag.FitImaging(dataset=masked_imaging_7x7, galaxies=[g0, g1]) unmasked_blurred_image = galaxies.unmasked_blurred_image_2d_from( - grid=masked_imaging_7x7.grids.uniform, psf=masked_imaging_7x7.psf + grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf ) assert (fit.unmasked_blurred_image == unmasked_blurred_image).all() unmasked_blurred_image_of_galaxies_list = ( galaxies.unmasked_blurred_image_2d_list_from( - grid=masked_imaging_7x7.grids.uniform, psf=masked_imaging_7x7.psf + grid=masked_imaging_7x7.grids.lp, psf=masked_imaging_7x7.psf ) ) diff --git a/test_autogalaxy/imaging/test_simulate_and_fit_imaging.py b/test_autogalaxy/imaging/test_simulate_and_fit_imaging.py index 2324e2791..e60c00cce 100644 --- a/test_autogalaxy/imaging/test_simulate_and_fit_imaging.py +++ b/test_autogalaxy/imaging/test_simulate_and_fit_imaging.py @@ -9,7 +9,11 @@ def test__perfect_fit__chi_squared_0(): - grid = ag.Grid2D.uniform(shape_native=(11, 11), pixel_scales=0.2) + grid = ag.Grid2D.uniform( + shape_native=(11, 11), + pixel_scales=0.2, + over_sample_size=1, + ) psf = ag.Kernel2D.from_gaussian( shape_native=(3, 3), pixel_scales=0.2, sigma=0.75, normalize=True @@ -23,7 +27,7 @@ def test__perfect_fit__chi_squared_0(): ) simulator = ag.SimulatorImaging( - exposure_time=300.0, psf=psf, add_poisson_noise=False + exposure_time=300.0, psf=psf, add_poisson_noise_to_data=False ) dataset = simulator.via_galaxies_from(galaxies=[galaxy_0, galaxy_1], grid=grid) @@ -56,6 +60,7 @@ def test__perfect_fit__chi_squared_0(): noise_map_path=path.join(file_path, "noise_map.fits"), psf_path=path.join(file_path, "psf.fits"), pixel_scales=0.2, + over_sample_size_lp=1, ) mask = ag.Mask2D.circular( @@ -110,7 +115,7 @@ def test__simulate_imaging_data_and_fit__known_likelihood(): fit = ag.FitImaging(dataset=masked_dataset, galaxies=[galaxy_0, galaxy_1]) - assert fit.figure_of_merit == pytest.approx(532.19918562, 1.0e-2) + assert fit.figure_of_merit == pytest.approx(538.9777105858, 1.0e-2) # Check that using a Basis gives the same result. @@ -129,11 +134,15 @@ def test__simulate_imaging_data_and_fit__known_likelihood(): fit = ag.FitImaging(dataset=masked_dataset, galaxies=[galaxy_0, galaxy_1]) - assert fit.figure_of_merit == pytest.approx(532.19918562, 1.0e-2) + assert fit.figure_of_merit == pytest.approx(538.9777105858, 1.0e-2) def test__simulate_imaging_data_and_fit__linear_light_profiles_agree_with_standard_light_profiles(): - grid = ag.Grid2D.uniform(shape_native=(11, 11), pixel_scales=0.2) + grid = ag.Grid2D.uniform( + shape_native=(11, 11), + pixel_scales=0.2, + over_sample_size=1, + ) psf = ag.Kernel2D.from_gaussian( shape_native=(3, 3), pixel_scales=0.2, sigma=0.75, normalize=True @@ -146,7 +155,7 @@ def test__simulate_imaging_data_and_fit__linear_light_profiles_agree_with_standa ) simulator = ag.SimulatorImaging( - exposure_time=300.0, psf=psf, add_poisson_noise=False + exposure_time=300.0, psf=psf, add_poisson_noise_to_data=False ) dataset = simulator.via_galaxies_from(galaxies=[galaxy], grid=grid) @@ -161,6 +170,7 @@ def test__simulate_imaging_data_and_fit__linear_light_profiles_agree_with_standa ) masked_dataset = dataset.apply_mask(mask=mask) + masked_dataset = masked_dataset.apply_over_sampling(over_sample_size_lp=1) fit = ag.FitImaging(dataset=masked_dataset, galaxies=[galaxy]) @@ -177,21 +187,21 @@ def test__simulate_imaging_data_and_fit__linear_light_profiles_agree_with_standa ) assert fit_linear.inversion.reconstruction == pytest.approx( - np.array([0.1, 0.2]), 1.0e-4 + np.array([0.1, 0.2]), 1.0e-2 ) assert fit_linear.linear_light_profile_intensity_dict[ galaxy_linear.bulge - ] == pytest.approx(0.1, 1.0e-4) + ] == pytest.approx(0.1, 1.0e-2) assert fit_linear.linear_light_profile_intensity_dict[ galaxy_linear.disk - ] == pytest.approx(0.2, 1.0e-4) + ] == pytest.approx(0.2, 1.0e-2) assert fit.log_likelihood == fit_linear.figure_of_merit assert fit_linear.figure_of_merit == pytest.approx(-45.02798, 1.0e-4) galaxy_image = galaxy.blurred_image_2d_from( - grid=masked_dataset.grids.uniform, + grid=masked_dataset.grids.lp, convolver=masked_dataset.convolver, blurring_grid=masked_dataset.grids.blurring, ) diff --git a/test_autogalaxy/imaging/test_simulator.py b/test_autogalaxy/imaging/test_simulator.py index 86ed9e92d..257783e5e 100644 --- a/test_autogalaxy/imaging/test_simulator.py +++ b/test_autogalaxy/imaging/test_simulator.py @@ -85,7 +85,8 @@ def test__simulator__via_galaxies_from(): psf=psf, exposure_time=10000.0, background_sky_level=100.0, - add_poisson_noise=False, + add_poisson_noise_to_data=False, + include_poisson_noise_in_noise_map=False, ) dataset = simulator.via_galaxies_from(galaxies=[galaxy_0, galaxy_1], grid=grid) @@ -99,7 +100,7 @@ def test__simulator__via_galaxies_from(): assert dataset.shape_native == (20, 20) assert dataset.data.native[0, 0] != imaging_via_image.data.native[0, 0] assert dataset.data.native[10, 10] == imaging_via_image.data.native[10, 10] - assert (dataset.psf == imaging_via_image.psf).all() + assert dataset.psf == pytest.approx(imaging_via_image.psf, 1.0e-4) assert (dataset.noise_map == imaging_via_image.noise_map).all() @@ -130,7 +131,7 @@ def test__simulator__simulate_imaging_from_galaxy__source_galaxy__compare_to_ima psf=psf, exposure_time=10000.0, background_sky_level=100.0, - add_poisson_noise=True, + add_poisson_noise_to_data=True, noise_seed=1, ) diff --git a/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py b/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py index 3c63ab463..a313a768e 100644 --- a/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py +++ b/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py @@ -1,6 +1,8 @@ from os import path import pytest +import autogalaxy as ag + from autogalaxy.interferometer.model.plotter_interface import ( PlotterInterfaceInterferometer, ) @@ -20,12 +22,6 @@ def test__interferometer(interferometer_7, include_2d_all, plot_path, plot_patch assert path.join(plot_path, "subplot_dataset.png") in plot_patch.paths - plot_path = path.join(plot_path, "dataset") - - assert path.join(plot_path, "data.png") in plot_patch.paths - assert path.join(plot_path, "u_wavelengths.png") not in plot_patch.paths - assert path.join(plot_path, "v_wavelengths.png") not in plot_patch.paths - def test__fit_interferometer( interferometer_7, @@ -37,11 +33,31 @@ def test__fit_interferometer( PlotterInterface = PlotterInterfaceInterferometer(image_path=plot_path) PlotterInterface.fit_interferometer( - fit=fit_interferometer_x2_galaxy_inversion_7x7, during_analysis=True + fit=fit_interferometer_x2_galaxy_inversion_7x7, ) - plot_path = path.join(plot_path, "fit_dataset") - assert path.join(plot_path, "subplot_fit.png") in plot_patch.paths - assert path.join(plot_path, "data.png") in plot_patch.paths - assert path.join(plot_path, "noise_map.png") not in plot_patch.paths + + # visibilities = ag.util.array_2d.numpy_array_2d_via_fits_from( + # file_path=path.join(plot_path, "fit.fits"), hdu=0 + # ) + # + # assert visibilities.shape == (5, 5) + + # visibilities = ag.util.array_2d.numpy_array_2d_via_fits_from( + # file_path=path.join(plot_path, "model_galaxy_visibilities.fits"), hdu=0 + # ) + # + # assert visibilities.shape == (5, 5) + + image = ag.util.array_2d.numpy_array_2d_via_fits_from( + file_path=path.join(plot_path, "model_galaxy_images.fits"), hdu=0 + ) + + assert image.shape == (5, 5) + + image = ag.util.array_2d.numpy_array_2d_via_fits_from( + file_path=path.join(plot_path, "dirty_images.fits"), hdu=0 + ) + + assert image.shape == (5, 5) diff --git a/test_autogalaxy/interferometer/test_fit_interferometer.py b/test_autogalaxy/interferometer/test_fit_interferometer.py index 3f844af88..e55deff70 100644 --- a/test_autogalaxy/interferometer/test_fit_interferometer.py +++ b/test_autogalaxy/interferometer/test_fit_interferometer.py @@ -148,8 +148,8 @@ def test___galaxy_model_image_dict(interferometer_7): settings_inversion=ag.SettingsInversion(use_w_tilde=False), ) - g0_image = g0.image_2d_from(grid=interferometer_7.grids.uniform) - g1_image = g1.image_2d_from(grid=interferometer_7.grids.uniform) + g0_image = g0.image_2d_from(grid=interferometer_7.grids.lp) + g1_image = g1.image_2d_from(grid=interferometer_7.grids.lp) assert fit.galaxy_model_image_dict[g0] == pytest.approx(g0_image, 1.0e-4) assert fit.galaxy_model_image_dict[g1] == pytest.approx(g1_image, 1.0e-4) @@ -187,14 +187,13 @@ def test___galaxy_model_image_dict(interferometer_7): mapper_grids = pixelization.mesh.mapper_grids_from( mask=interferometer_7.real_space_mask, - source_plane_data_grid=interferometer_7.grids.uniform, + source_plane_data_grid=interferometer_7.grids.lp, border_relocator=interferometer_7.grids.border_relocator, source_plane_mesh_grid=None, ) mapper = ag.Mapper( mapper_grids=mapper_grids, - over_sampler=interferometer_7.grids.pixelization.over_sampler, border_relocator=interferometer_7.grids.border_relocator, regularization=pixelization.regularization, ) @@ -266,10 +265,10 @@ def test___galaxy_model_visibilities_dict(interferometer_7): ) g0_visibilities = g0.visibilities_from( - grid=interferometer_7.grids.uniform, transformer=interferometer_7.transformer + grid=interferometer_7.grids.lp, transformer=interferometer_7.transformer ) g1_visibilities = g1.visibilities_from( - grid=interferometer_7.grids.uniform, transformer=interferometer_7.transformer + grid=interferometer_7.grids.lp, transformer=interferometer_7.transformer ) assert fit.galaxy_model_visibilities_dict[g0] == pytest.approx( @@ -314,14 +313,13 @@ def test___galaxy_model_visibilities_dict(interferometer_7): mapper_grids = pixelization.mesh.mapper_grids_from( mask=interferometer_7.real_space_mask, - source_plane_data_grid=interferometer_7.grids.uniform, + source_plane_data_grid=interferometer_7.grids.lp, border_relocator=interferometer_7.grids.border_relocator, source_plane_mesh_grid=None, ) mapper = ag.Mapper( mapper_grids=mapper_grids, - over_sampler=interferometer_7.grids.pixelization.over_sampler, border_relocator=interferometer_7.grids.border_relocator, regularization=pixelization.regularization, ) diff --git a/test_autogalaxy/interferometer/test_simulate_and_fit_interferometer.py b/test_autogalaxy/interferometer/test_simulate_and_fit_interferometer.py index 41434cefd..c89db5e56 100644 --- a/test_autogalaxy/interferometer/test_simulate_and_fit_interferometer.py +++ b/test_autogalaxy/interferometer/test_simulate_and_fit_interferometer.py @@ -9,7 +9,11 @@ def test__perfect_fit__chi_squared_0(): - grid = ag.Grid2D.uniform(shape_native=(51, 51), pixel_scales=0.1) + grid = ag.Grid2D.uniform( + shape_native=(51, 51), + pixel_scales=0.1, + over_sample_size=1, + ) galaxy_0 = ag.Galaxy( redshift=0.5, light=ag.lp.Sersic(centre=(0.1, 0.1), intensity=0.1) @@ -136,7 +140,11 @@ def test__simulate_interferometer_data_and_fit__known_likelihood(): def test__linear_light_profiles_agree_with_standard_light_profiles(): - grid = ag.Grid2D.uniform(shape_native=(51, 51), pixel_scales=0.1) + grid = ag.Grid2D.uniform( + shape_native=(51, 51), + pixel_scales=0.1, + over_sample_size=1, + ) galaxy = ag.Galaxy( redshift=0.5, @@ -198,14 +206,14 @@ def test__linear_light_profiles_agree_with_standard_light_profiles(): ] == pytest.approx(0.2, 1.0e-2) assert fit.log_likelihood == pytest.approx(fit_linear.log_likelihood, 1.0e-4) - galaxy_image = galaxy.image_2d_from(grid=dataset.grids.uniform) + galaxy_image = galaxy.image_2d_from(grid=dataset.grids.lp) assert fit_linear.galaxy_model_image_dict[galaxy_linear] == pytest.approx( galaxy_image, 1.0e-4 ) galaxy_visibilities = galaxy.visibilities_from( - grid=dataset.grids.uniform, transformer=dataset.transformer + grid=dataset.grids.lp, transformer=dataset.transformer ) assert fit_linear.galaxy_model_visibilities_dict[galaxy_linear] == pytest.approx( diff --git a/test_autogalaxy/operate/test_image.py b/test_autogalaxy/operate/test_image.py index 1ae19e9c7..d2fea8ca9 100644 --- a/test_autogalaxy/operate/test_image.py +++ b/test_autogalaxy/operate/test_image.py @@ -103,7 +103,7 @@ def test__unmasked_blurred_image_2d_from(): pixel_scales=1.0, ) - grid = ag.Grid2D.from_mask(mask=mask) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=1) lp = ag.lp.Sersic(intensity=0.1) diff --git a/test_autogalaxy/plot/mat_wrap/config/visualize/plots.ini b/test_autogalaxy/plot/mat_wrap/config/visualize/plots.ini index 488f75893..ddf91ea9a 100644 --- a/test_autogalaxy/plot/mat_wrap/config/visualize/plots.ini +++ b/test_autogalaxy/plot/mat_wrap/config/visualize/plots.ini @@ -29,7 +29,7 @@ all_at_end_png=False subplot_inversion=True reconstructed_image=False reconstruction=False -errors=False +reconstruction_noise_map=False residual_map=False normalized_residual_map=False chi_squared_map=False diff --git a/test_autogalaxy/profiles/light/standard/test_abstract.py b/test_autogalaxy/profiles/light/standard/test_abstract.py index 09d257f4d..f499ebd50 100644 --- a/test_autogalaxy/profiles/light/standard/test_abstract.py +++ b/test_autogalaxy/profiles/light/standard/test_abstract.py @@ -44,7 +44,11 @@ def test__luminosity_within_centre__compare_to_gridded_calculations(): def test__image_1d_from__grid_2d_in__returns_1d_image_via_projected_quantities(): - grid_2d = ag.Grid2D.uniform(shape_native=(5, 5), pixel_scales=1.0) + grid_2d = ag.Grid2D.uniform( + shape_native=(5, 5), + pixel_scales=1.0, + over_sample_size=1, + ) lp = ag.lp.Gaussian( centre=(0.0, 0.0), ell_comps=(0.0, 0.0), intensity=1.0, sigma=1.0 @@ -87,17 +91,13 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): lp = ag.lp.Sersic(intensity=1.0) - over_sampling = ag.OverSamplingUniform(sub_size=1) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=1) image = lp.image_2d_from(grid=grid) assert image[0] == pytest.approx(0.15987224303572964, 1.0e-6) - over_sampling = ag.OverSamplingUniform(sub_size=2) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=2) image = lp.image_2d_from(grid=grid) @@ -106,17 +106,13 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): lp = ag.lp.Sersic(centre=(3.0, 3.0), intensity=1.0) - over_sampling = ag.OverSamplingUniform(sub_size=1) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=1) image = lp.image_2d_from(grid=grid) assert image[0] == pytest.approx(0.006719704400094508, 1.0e-6) - over_sampling = ag.OverSamplingUniform(sub_size=2) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=over_sampling) + grid = ag.Grid2D.from_mask(mask=mask, over_sample_size=2) image = lp.image_2d_from(grid=grid) @@ -124,63 +120,6 @@ def test__decorator__oversample_uniform__numerical_values(gal_x1_lp): assert image[1] == pytest.approx(0.01332332, 1.0e-6) -def test__decorators__grid_iterate_in__iterates_grid_correctly(): - mask = ag.Mask2D( - mask=[ - [True, True, True, True, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, True, True, True, True], - ], - pixel_scales=(1.0, 1.0), - ) - - grid = ag.Grid2D.from_mask( - mask=mask, - over_sampling=ag.OverSamplingIterate(fractional_accuracy=1.0, sub_steps=[2]), - ) - - lp = ag.lp.Sersic(intensity=1.0) - - image = lp.image_2d_from(grid=grid) - - grid_sub_2 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=2) - ) - image_sub_2 = lp.image_2d_from(grid=grid_sub_2) - - assert image[0] == pytest.approx(0.17481917, 1.0e-4) - assert (image == image_sub_2).all() - - grid = ag.Grid2D.from_mask( - mask=mask, - over_sampling=ag.OverSamplingIterate( - fractional_accuracy=0.95, sub_steps=[2, 4, 8] - ), - ) - - lp = ag.lp.Sersic(centre=(0.08, 0.08), intensity=1.0) - - image = lp.image_2d_from(grid=grid) - - grid_sub_4 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=4) - ) - image_sub_4 = lp.image_2d_from(grid=grid_sub_4) - - assert image[0] == pytest.approx(0.17754459861988386, 1.0e-4) - assert image[0] == image_sub_4[0] - - grid_sub_8 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=8) - ) - image_sub_8 = lp.image_2d_from(grid=grid_sub_8) - - assert image[4] == pytest.approx(4.173185729427679, 1.0e-4) - assert image[4] == image_sub_8[4] - - def test__regression__centre_of_profile_in_right_place(): grid = ag.Grid2D.uniform(shape_native=(7, 7), pixel_scales=1.0) @@ -193,19 +132,3 @@ def test__regression__centre_of_profile_in_right_place(): image = lp.image_2d_from(grid=grid) max_indexes = np.unravel_index(image.native.argmax(), image.shape_native) assert max_indexes == (1, 4) - - # grid = ag.Grid2D.uniform( - # shape_native=(7, 7), - # pixel_scales=1.0, - # over_sampling=ag.OverSamplingIterate(fractional_accuracy=0.99, sub_steps=[2, 4]), - # ) - # - # lp = ag.lp.Sersic(centre=(2.0, 1.0), intensity=1.0) - # image = lp.image_2d_from(grid=grid) - # max_indexes = np.unravel_index(image.native.argmax(), image.shape_native) - # assert max_indexes == (1, 4) - # - # lp = ag.lp.SersicSph(centre=(2.0, 1.0), intensity=1.0) - # image = lp.image_2d_from(grid=grid) - # max_indexes = np.unravel_index(image.native.argmax(), image.shape_native) - # assert max_indexes == (1, 4) diff --git a/test_autogalaxy/profiles/light/test_snr.py b/test_autogalaxy/profiles/light/test_snr.py index ecd41ea67..515dc45df 100644 --- a/test_autogalaxy/profiles/light/test_snr.py +++ b/test_autogalaxy/profiles/light/test_snr.py @@ -19,7 +19,7 @@ def test__signal_to_noise_via_simulator_correct(): grid=grid, galaxies=[ag.Galaxy(redshift=0.5, light=sersic)] ) - assert 9.0 < dataset.signal_to_noise_max < 11.5 + assert 8.0 < dataset.signal_to_noise_max < 11.5 psf = ag.Kernel2D.from_gaussian( shape_native=(3, 3), sigma=2.0, pixel_scales=0.2, normalize=True @@ -36,4 +36,4 @@ def test__signal_to_noise_via_simulator_correct(): grid=grid, galaxies=[ag.Galaxy(redshift=0.5, light=sersic)] ) - assert 9.0 < dataset.signal_to_noise_max < 11.5 + assert 8.5 < dataset.signal_to_noise_max < 11.5 diff --git a/test_autogalaxy/profiles/mass/abstract/test_abstract.py b/test_autogalaxy/profiles/mass/abstract/test_abstract.py index fe66afbf0..56ef5f258 100644 --- a/test_autogalaxy/profiles/mass/abstract/test_abstract.py +++ b/test_autogalaxy/profiles/mass/abstract/test_abstract.py @@ -200,51 +200,14 @@ def test__regression__centre_of_profile_in_right_place(): assert deflections.native[2, 4, 0] < 0 assert deflections.native[1, 4, 1] > 0 assert deflections.native[1, 3, 1] < 0 - # - # grid = ag.Grid2D.uniform( - # shape_native=(7, 7), - # pixel_scales=1.0, - # over_sampling=ag.OverSamplingIterate(fractional_accuracy=0.99, sub_steps=[2, 4]), - # ) - # - # mass_profile = ag.mp.Isothermal(centre=(2.0, 1.0), einstein_radius=1.0) - # convergence = mass_profile.convergence_2d_from(grid=grid) - # max_indexes = np.unravel_index( - # convergence.native.argmax(), convergence.shape_native - # ) - # assert max_indexes == (1, 4) - # - # potential = mass_profile.potential_2d_from(grid=grid) - # max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) - # assert max_indexes == (1, 4) - # - # deflections = mass_profile.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 - # - # mass_profile = ag.mp.IsothermalSph(centre=(2.0, 1.0), einstein_radius=1.0) - # - # convergence = mass_profile.convergence_2d_from(grid=grid) - # max_indexes = np.unravel_index( - # convergence.native.argmax(), convergence.shape_native - # ) - # assert max_indexes == (1, 4) - # - # potential = mass_profile.potential_2d_from(grid=grid) - # max_indexes = np.unravel_index(potential.native.argmin(), potential.shape_native) - # assert max_indexes == (1, 4) - # - # deflections = mass_profile.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__decorators__convergence_1d_from__grid_2d_in__returns_1d_image_via_projected_quantities(): - grid_2d = ag.Grid2D.uniform(shape_native=(5, 5), pixel_scales=1.0) + grid_2d = ag.Grid2D.uniform( + shape_native=(5, 5), + pixel_scales=1.0, + over_sample_size=1, + ) sie = ag.mp.Isothermal(centre=(0.0, 0.0), ell_comps=(0.0, 0.0), einstein_radius=1.0) @@ -340,60 +303,3 @@ def test__decorators__potential_1d_from__grid_2d_in__returns_1d_image_via_projec assert potential_1d == pytest.approx(potential_projected, 1.0e-4) assert (potential_1d.grid_radial == np.array([0.0, 1.0, 2.0])).all() - - -def test__decorators__grid_iterate_in__iterates_grid_result_correctly(gal_x1_mp): - mask = ag.Mask2D( - mask=[ - [True, True, True, True, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, False, False, False, True], - [True, True, True, True, True], - ], - pixel_scales=(1.0, 1.0), - ) - - grid = ag.Grid2D.from_mask( - mask=mask, - over_sampling=ag.OverSamplingIterate(fractional_accuracy=1.0, sub_steps=[2]), - ) - - mass_profile = ag.mp.Isothermal(centre=(0.08, 0.08), einstein_radius=1.0) - - convergence = mass_profile.convergence_2d_from(grid=grid) - - grid_sub_2 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=2) - ) - convergence_sub_2 = mass_profile.convergence_2d_from(grid=grid_sub_2) - - assert convergence[0] == pytest.approx(0.35882721247144705, 1.0e-4) - assert convergence == pytest.approx(convergence_sub_2, 1.0e-6) - - grid = ag.Grid2D.from_mask( - mask=mask, - over_sampling=ag.OverSamplingIterate( - fractional_accuracy=0.99, sub_steps=[2, 4, 8] - ), - ) - - mass_profile = ag.mp.Isothermal(centre=(0.08, 0.08), einstein_radius=1.0) - - convergence = mass_profile.convergence_2d_from(grid=grid) - - grid_sub_4 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=4) - ) - convergence_sub_4 = mass_profile.convergence_2d_from(grid=grid_sub_4) - - assert convergence[0] == pytest.approx(0.360512586364902, 1.0e-4) - assert convergence[0] == convergence_sub_4[0] - - grid_sub_8 = ag.Grid2D( - values=grid, mask=mask, over_sampling=ag.OverSamplingUniform(sub_size=8) - ) - convergence_sub_8 = mass_profile.convergence_2d_from(grid=grid_sub_8) - - assert convergence[4] == pytest.approx(1.8257180092529044, 1.0e-4) - assert convergence[4] == convergence_sub_8[4] diff --git a/test_autogalaxy/profiles/mass/total/test_power_law_multipole.py b/test_autogalaxy/profiles/mass/total/test_power_law_multipole.py index 5ab8a7f89..29271d67a 100644 --- a/test_autogalaxy/profiles/mass/total/test_power_law_multipole.py +++ b/test_autogalaxy/profiles/mass/total/test_power_law_multipole.py @@ -16,8 +16,8 @@ def test__deflections_yx_2d_from(): deflections = mp.deflections_yx_2d_from(grid=ag.Grid2DIrregular([[1.0, 0.0]])) - assert deflections[0, 0] == pytest.approx(-0.072229375535, 1e-3) - assert deflections[0, 1] == pytest.approx(-0.2089041286, 1e-3) + assert deflections[0, 0] == pytest.approx(-0.036120991, 1e-3) + assert deflections[0, 1] == pytest.approx(-0.0476260676, 1e-3) mp = ag.mp.PowerLawMultipole( m=4, @@ -29,8 +29,8 @@ def test__deflections_yx_2d_from(): deflections = mp.deflections_yx_2d_from(grid=ag.Grid2DIrregular([[1.0, 0.0]])) - assert deflections[0, 0] == pytest.approx(-0.2532106, 1e-3) - assert deflections[0, 1] == pytest.approx(-0.5514646, 1e-3) + assert deflections[0, 0] == pytest.approx(-0.096376665, 1e-3) + assert deflections[0, 1] == pytest.approx(-0.1298677210, 1e-3) def test__convergence_2d_from(): diff --git a/test_autogalaxy/profiles/test_adapt_over_sample.py b/test_autogalaxy/profiles/test_adapt_over_sample.py deleted file mode 100644 index 68786e473..000000000 --- a/test_autogalaxy/profiles/test_adapt_over_sample.py +++ /dev/null @@ -1,25 +0,0 @@ -import numpy as np -import pytest - -import autogalaxy as ag - - -def test__adapt_over_sample__used_if_no_over_sampling_input(gal_x1_lp): - # In grid.yaml this class has settings which use the autoarray over sampling adaptive decorator. - - class SersicAdaptTest(ag.lp.Sersic): - pass - - mask = ag.Mask2D.circular( - radius=1.0, - shape_native=(21, 21), - pixel_scales=0.1, - ) - - light = SersicAdaptTest(intensity=1.0) - - grid = ag.Grid2D.from_mask(mask=mask, over_sampling=None) - - image = light.image_2d_from(grid=grid) - - assert np.max(image) == pytest.approx(53.83706341021047, 1.0e-6) diff --git a/test_autogalaxy/profiles/test_radial_minima.py b/test_autogalaxy/profiles/test_radial_minima.py index 122d16e19..6aef7f2a1 100644 --- a/test_autogalaxy/profiles/test_radial_minima.py +++ b/test_autogalaxy/profiles/test_radial_minima.py @@ -19,8 +19,12 @@ def test__grid_2d__moves_radial_coordinates__does_not_double_transform(): assert convergence_0 == pytest.approx(convergence_1, 1.0e-8) - grid_2d = ag.Grid2D.no_mask(values=[[[0.5, 0.5]]], pixel_scales=1.0) - grid_2d_offset = ag.Grid2D.no_mask(values=[[[0.5001, 0.5001]]], pixel_scales=1.0) + grid_2d = ag.Grid2D.no_mask( + values=[[[0.5, 0.5]]], pixel_scales=1.0, origin=(0.5, 0.5) + ) + grid_2d_offset = ag.Grid2D.no_mask( + values=[[[0.5001, 0.5001]]], pixel_scales=1.0, origin=(0.5001, 0.5001) + ) isothermal = ag.mp.Isothermal(centre=(0.0, 0.0), einstein_radius=1.0) @@ -34,7 +38,7 @@ def test__grid_2d__moves_radial_coordinates__does_not_double_transform(): convergence_1 = isothermal.convergence_2d_from(grid=grid_2d) convergence_0 = isothermal.convergence_2d_from(grid=grid_2d_offset) - assert convergence_0 == pytest.approx(convergence_1, 1.0e-8) + assert convergence_0 == pytest.approx(convergence_1, 1.0e-5) def test__grid_2d_irrergular__moves_radial_coordinates__does_not_double_transform(): diff --git a/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py b/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py index 351c919b5..699581d7b 100644 --- a/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py +++ b/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py @@ -29,5 +29,3 @@ def test__fit_quantity( plot_path = path.join(plot_path, "fit_quantity") assert path.join(plot_path, "subplot_fit.png") not in plot_patch.paths - assert path.join(plot_path, "data.png") in plot_patch.paths - assert path.join(plot_path, "noise_map.png") not in plot_patch.paths diff --git a/test_autogalaxy/quantity/test_dataset_quantity.py b/test_autogalaxy/quantity/test_dataset_quantity.py index 323bfa269..94b1cf15b 100644 --- a/test_autogalaxy/quantity/test_dataset_quantity.py +++ b/test_autogalaxy/quantity/test_dataset_quantity.py @@ -75,21 +75,20 @@ def test__grid( ): dataset = dataset_quantity_7x7_array_2d.apply_mask(mask=mask_2d_7x7) - assert isinstance(dataset.grids.uniform, ag.Grid2D) - assert (dataset.grids.uniform == grid_2d_7x7).all() + assert isinstance(dataset.grids.lp, ag.Grid2D) + assert (dataset.grids.lp == grid_2d_7x7).all() dataset_quantity = ag.DatasetQuantity( data=ag.Array2D.ones(shape_native=(7, 7), pixel_scales=1.0), noise_map=ag.Array2D.full( fill_value=2.0, shape_native=(7, 7), pixel_scales=1.0 ), - over_sampling=ag.OverSamplingDataset(uniform=ag.OverSamplingIterate()), + over_sample_size_lp=4, ) dataset = dataset_quantity.apply_mask(mask=mask_2d_7x7) - assert isinstance(dataset.grids.uniform.over_sampling, ag.OverSamplingIterate) - assert (dataset.grids.uniform == grid_2d_7x7).all() + assert (dataset.grids.lp == grid_2d_7x7).all() def test__vector_data__y_x():