diff --git a/autogalaxy/__init__.py b/autogalaxy/__init__.py index 2c2aea6e9..6266a883b 100644 --- a/autogalaxy/__init__.py +++ b/autogalaxy/__init__.py @@ -107,6 +107,11 @@ from .gui.scribbler import Scribbler from autoconf import conf +from autoconf.fitsable import ndarray_via_hdu_from +from autoconf.fitsable import ndarray_via_fits_from +from autoconf.fitsable import header_obj_from +from autoconf.fitsable import output_to_fits +from autoconf.fitsable import hdu_list_for_output_from conf.instance.register(__file__) diff --git a/autogalaxy/aggregator/agg_util.py b/autogalaxy/aggregator/agg_util.py index 91bf0f57f..da3fa69e3 100644 --- a/autogalaxy/aggregator/agg_util.py +++ b/autogalaxy/aggregator/agg_util.py @@ -1,17 +1,59 @@ from __future__ import annotations from typing import List, Optional +from autoconf.fitsable import ndarray_via_hdu_from + import autofit as af import autoarray as aa +from autoarray.mask.mask_2d import Mask2DKeys + from autogalaxy.analysis.adapt_images.adapt_images import AdaptImages +def mask_header_from(fit): + """ + Returns the mask, header and pixel scales of the `PyAutoFit` `Fit` object. + + These quantities are commonly loaded during the aggregator interface therefore this method is used to + avoid code duplication. + + Parameters + ---------- + fit + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database. + + + Returns + ------- + The mask, header and pixel scales of the `PyAutoFit` `Fit` object. + """ + + header = aa.Header(header_sci_obj=fit.value(name="dataset")[0].header) + pixel_scales = ( + header.header_sci_obj[Mask2DKeys.PIXSCAY.value], + header.header_sci_obj[Mask2DKeys.PIXSCAY.value], + ) + origin = ( + header.header_sci_obj[Mask2DKeys.ORIGINY.value], + header.header_sci_obj[Mask2DKeys.ORIGINX.value], + ) + mask = aa.Mask2D( + mask=ndarray_via_hdu_from(fit.value(name="dataset")[0]), + pixel_scales=pixel_scales, + origin=origin, + ) + + return mask, header + + def adapt_images_from( fit: af.Fit, ) -> List[AdaptImages]: """ - Updates adaptive images when loading the galaxies from a `PyAutoFit` sqlite database `Fit` object. + Updates adaptive images when loading the galaxies from a `PyAutoFit` loaded directory `Fit` or sqlite + database `Fit` object. This function ensures that if adaptive features (e.g. an `Hilbert` image-mesh) are used in a model-fit, they work when using the database to load and inspect the results of the model-fit. @@ -19,7 +61,8 @@ def adapt_images_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database. galaxies A list of galaxies corresponding to a sample of a non-linear search and model-fit. @@ -30,31 +73,26 @@ def adapt_images_from( fit_list = [fit] if not fit.children else fit.children - if fit.value(name="adapt_images.adapt_images") is None: + if fit.value(name="adapt_images") is None: return [None] * len(fit_list) adapt_images_list = [] for fit in fit_list: - try: - mask = aa.Mask2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.mask")[0] - ) - except TypeError: - mask = aa.Mask2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.real_space_mask")[0] - ) + mask, header = mask_header_from(fit=fit) galaxy_name_image_dict = {} - adapt_image_name_list = fit.value(name="adapt_images.adapt_images") - - for name in adapt_image_name_list: - adapt_image = aa.Array2D.from_primary_hdu( - primary_hdu=fit.value(name=f"adapt_images.{name}")[0] + for i, value in enumerate(fit.value(name="adapt_images")[1:]): + adapt_image = aa.Array2D.no_mask( + values=ndarray_via_hdu_from(value), + pixel_scales=mask.pixel_scales, + header=header, + origin=mask.origin, ) adapt_image = adapt_image.apply_mask(mask=mask) - galaxy_name_image_dict[name] = adapt_image + + galaxy_name_image_dict[value.header["EXTNAME"].lower()] = adapt_image instance = fit.model.instance_from_prior_medians(ignore_prior_limits=True) @@ -91,7 +129,8 @@ def mesh_grids_of_planes_list_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. total_fits The total number of `Analysis` objects summed to create the fit. use_preloaded_grid diff --git a/autogalaxy/aggregator/dataset_model.py b/autogalaxy/aggregator/dataset_model.py index bb585705a..130b00abd 100644 --- a/autogalaxy/aggregator/dataset_model.py +++ b/autogalaxy/aggregator/dataset_model.py @@ -12,9 +12,10 @@ def _dataset_model_from( fit: af.Fit, instance: af.ModelInstance ) -> List[aa.DatasetModel]: """ - Returns a `DatasetModel` object from a `PyAutoFit` sqlite database `Fit` object. + Returns a `DatasetModel` object from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). @@ -30,7 +31,8 @@ def _dataset_model_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/ellipse/ellipses.py b/autogalaxy/aggregator/ellipse/ellipses.py index 7c92f4839..cc4f3ee15 100644 --- a/autogalaxy/aggregator/ellipse/ellipses.py +++ b/autogalaxy/aggregator/ellipse/ellipses.py @@ -13,9 +13,10 @@ def _ellipses_from(fit: af.Fit, instance: af.ModelInstance) -> List[List[Ellipse]]: """ - Returns a list of `Ellipse` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `Ellipse` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). @@ -31,7 +32,8 @@ def _ellipses_from(fit: af.Fit, instance: af.ModelInstance) -> List[List[Ellipse Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -63,7 +65,8 @@ class EllipsesAgg(af.AggBase): Interfaces with an `PyAutoFit` aggregator object to create instances of `Ellipse` objects from the results of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). @@ -100,7 +103,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/ellipse/fit_ellipse.py b/autogalaxy/aggregator/ellipse/fit_ellipse.py index 0fe101295..3773bb914 100644 --- a/autogalaxy/aggregator/ellipse/fit_ellipse.py +++ b/autogalaxy/aggregator/ellipse/fit_ellipse.py @@ -16,12 +16,13 @@ def _fit_ellipse_from( instance: Optional[af.ModelInstance] = None, ) -> List[List[FitEllipse]]: """ - Returns a list of `FitEllipse` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `FitEllipse` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). Each individual attribute can be loaded from the database via the `fit.value()` method. @@ -38,7 +39,8 @@ def _fit_ellipse_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -78,34 +80,35 @@ def __init__( aggregator: af.Aggregator, ): """ - Interfaces with an `PyAutoFit` aggregator object to create instances of `FitEllipse` objects from the results - of a model-fit. + Interfaces with an `PyAutoFit` aggregator object to create instances of `FitEllipse` objects from the results + of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). + - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). - The `aggregator` contains the path to each of these files, and they can be loaded individually. This class - can load them all at once and create an `FitEllipse` object via the `_fit_ellipse_from` method. + The `aggregator` contains the path to each of these files, and they can be loaded individually. This class + can load them all at once and create an `FitEllipse` object via the `_fit_ellipse_from` method. - This class's methods returns generators which create the instances of the `FitEllipse` objects. This ensures - that large sets of results can be efficiently loaded from the hard-disk and do not require storing all - `FitEllipse` instances in the memory at once. + This class's methods returns generators which create the instances of the `FitEllipse` objects. This ensures + that large sets of results can be efficiently loaded from the hard-disk and do not require storing all + `FitEllipse` instances in the memory at once. - For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which - creates instances of the corresponding 3 `FitEllipse` objects. + For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which + creates instances of the corresponding 3 `FitEllipse` objects. - If multiple `Ellipse` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method - is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of - `FitEllipse` objects. + If multiple `Ellipse` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method + is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of + `FitEllipse` objects. - This can be done manually, but this object provides a more concise API. + This can be done manually, but this object provides a more concise API. - Parameters - ---------- - aggregator - A `PyAutoFit` aggregator object which can load the results of model-fits. + Parameters + ---------- + aggregator + A `PyAutoFit` aggregator object which can load the results of model-fits. """ super().__init__(aggregator=aggregator) @@ -120,7 +123,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/ellipse/multipoles.py b/autogalaxy/aggregator/ellipse/multipoles.py index ece37b7db..518259b75 100644 --- a/autogalaxy/aggregator/ellipse/multipoles.py +++ b/autogalaxy/aggregator/ellipse/multipoles.py @@ -15,9 +15,10 @@ def _multipoles_from( fit: af.Fit, instance: af.ModelInstance ) -> List[List[List[EllipseMultipole]]]: """ - Returns a list of `EllipseMultipole` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `EllipseMultipole` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). @@ -33,7 +34,8 @@ def _multipoles_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -65,7 +67,8 @@ class MultipolesAgg(af.AggBase): Interfaces with an `PyAutoFit` aggregator object to create instances of `EllipseMultipole` objects from the results of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). @@ -102,7 +105,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/galaxies.py b/autogalaxy/aggregator/galaxies.py index b52b27634..60dbd3779 100644 --- a/autogalaxy/aggregator/galaxies.py +++ b/autogalaxy/aggregator/galaxies.py @@ -13,9 +13,10 @@ def _galaxies_from(fit: af.Fit, instance: af.ModelInstance) -> List[Galaxy]: """ - Returns a list of `Galaxy` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `Galaxy` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). - The adapt images associated with adaptive galaxy features (`adapt` folder). @@ -32,7 +33,8 @@ def _galaxies_from(fit: af.Fit, instance: af.ModelInstance) -> List[Galaxy]: Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -73,7 +75,8 @@ class GalaxiesAgg(af.AggBase): Interfaces with an `PyAutoFit` aggregator object to create instances of `Galaxy` objects from the results of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The model and its best fit parameters (e.g. `model.json`). - The adapt images associated with adaptive galaxy features (`adapt` folder). @@ -111,7 +114,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/imaging/fit_imaging.py b/autogalaxy/aggregator/imaging/fit_imaging.py index e805df1ee..d10494fc1 100644 --- a/autogalaxy/aggregator/imaging/fit_imaging.py +++ b/autogalaxy/aggregator/imaging/fit_imaging.py @@ -22,12 +22,13 @@ def _fit_imaging_from( use_preloaded_grid: bool = True, ) -> List[FitImaging]: """ - Returns a list of `FitImaging` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `FitImaging` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). - The settings of inversions used by the fit (`dataset/settings_inversion.json`). Each individual attribute can be loaded from the database via the `fit.value()` method. @@ -45,7 +46,8 @@ def _fit_imaging_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -111,41 +113,42 @@ def __init__( use_preloaded_grid: bool = True, ): """ - Interfaces with an `PyAutoFit` aggregator object to create instances of `FitImaging` objects from the results - of a model-fit. - - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: - - - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). - - The settings of inversions used by the fit (`dataset/settings_inversion.json`). - - The `aggregator` contains the path to each of these files, and they can be loaded individually. This class - can load them all at once and create an `FitImaging` object via the `_fit_imaging_from` method. - - This class's methods returns generators which create the instances of the `FitImaging` objects. This ensures - that large sets of results can be efficiently loaded from the hard-disk and do not require storing all - `FitImaging` instances in the memory at once. - - For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which - creates instances of the corresponding 3 `FitImaging` objects. - - If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method - is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of - `FitImaging` objects. - - This can be done manually, but this object provides a more concise API. - - Parameters - ---------- - aggregator - A `PyAutoFit` aggregator object which can load the results of model-fits. - settings_inversion - Optionally overwrite the `SettingsInversion` of the `Inversion` object that is created from the fit. - use_preloaded_grid - Certain pixelization's construct their mesh in the source-plane from a stochastic KMeans algorithm. This - grid may be output to hard-disk after the model-fit and loaded via the database to ensure the same grid is - used as the fit. + Interfaces with an `PyAutoFit` aggregator object to create instances of `FitImaging` objects from the results + of a model-fit. + + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: + + - The imaging data, noise-map, PSF and settings as .fits files (e.g. `dataset/data.fits`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). + - The settings of inversions used by the fit (`dataset/settings_inversion.json`). + + The `aggregator` contains the path to each of these files, and they can be loaded individually. This class + can load them all at once and create an `FitImaging` object via the `_fit_imaging_from` method. + + This class's methods returns generators which create the instances of the `FitImaging` objects. This ensures + that large sets of results can be efficiently loaded from the hard-disk and do not require storing all + `FitImaging` instances in the memory at once. + + For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which + creates instances of the corresponding 3 `FitImaging` objects. + + If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method + is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of + `FitImaging` objects. + + This can be done manually, but this object provides a more concise API. + + Parameters + ---------- + aggregator + A `PyAutoFit` aggregator object which can load the results of model-fits. + settings_inversion + Optionally overwrite the `SettingsInversion` of the `Inversion` object that is created from the fit. + use_preloaded_grid + Certain pixelization's construct their mesh in the source-plane from a stochastic KMeans algorithm. This + grid may be output to hard-disk after the model-fit and loaded via the database to ensure the same grid is + used as the fit. """ super().__init__(aggregator=aggregator) @@ -163,7 +166,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/imaging/imaging.py b/autogalaxy/aggregator/imaging/imaging.py index c3a472820..dae4ed718 100644 --- a/autogalaxy/aggregator/imaging/imaging.py +++ b/autogalaxy/aggregator/imaging/imaging.py @@ -1,23 +1,28 @@ from functools import partial from typing import List +from autoconf.fitsable import ndarray_via_hdu_from + import autofit as af import autoarray as aa +from autogalaxy.aggregator import agg_util + def _imaging_from( fit: af.Fit, ) -> List[aa.Imaging]: """ - Returns a list of `Imaging` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `Imaging` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - - The imaging data as a .fits file (`dataset/data.fits`). - - The noise-map as a .fits file (`dataset/noise_map.fits`). - - The point spread function as a .fits file (`dataset/psf.fits`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). + - The imaging data as a .fits file (`dataset.fits[hdu=1]`). + - The noise-map as a .fits file (`dataset.fits[hdu=2]`). + - The point spread function as a .fits file (`dataset.fits[hdu=3]`). - The settings of the `Imaging` data structure used in the fit (`dataset/settings.json`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). Each individual attribute can be loaded from the database via the `fit.value()` method. @@ -31,7 +36,8 @@ def _imaging_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. """ fit_list = [fit] if not fit.children else fit.children @@ -39,17 +45,22 @@ def _imaging_from( dataset_list = [] for fit in fit_list: - data = aa.Array2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.data")[0] - ) - noise_map = aa.Array2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.noise_map")[0] - ) - try: - psf = aa.Kernel2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.psf")[0] + mask, header = agg_util.mask_header_from(fit=fit) + + def values_from(hdu: int, cls): + return cls.no_mask( + values=ndarray_via_hdu_from(fit.value(name="dataset")[hdu]), + pixel_scales=mask.pixel_scales, + header=header, + origin=mask.origin, ) - except TypeError: + + data = values_from(hdu=1, cls=aa.Array2D) + noise_map = values_from(hdu=2, cls=aa.Array2D) + + try: + psf = values_from(hdu=3, cls=aa.Kernel2D) + except (TypeError, IndexError): psf = None dataset = aa.Imaging( @@ -59,26 +70,20 @@ def _imaging_from( check_noise_map=False, ) - mask = aa.Mask2D.from_primary_hdu(primary_hdu=fit.value(name="dataset.mask")[0]) - 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")[0] - ).native + over_sample_size_lp = values_from(hdu=4, cls=aa.Array2D).native over_sample_size_lp = over_sample_size_lp.apply_mask(mask=mask) - except TypeError: + except (TypeError, IndexError): 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")[0] - ).native + over_sample_size_pixelization = values_from(hdu=5, cls=aa.Array2D).native over_sample_size_pixelization = over_sample_size_pixelization.apply_mask( mask=mask ) - except TypeError: + except (TypeError, IndexError): over_sample_size_pixelization = 1 dataset = dataset.apply_over_sampling( @@ -94,37 +99,38 @@ def _imaging_from( class ImagingAgg: def __init__(self, aggregator: af.Aggregator): """ - Interfaces with an `PyAutoFit` aggregator object to create instances of `Imaging` objects from the results - of a model-fit. + Interfaces with an `PyAutoFit` aggregator object to create instances of `Imaging` objects from the results + of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - - The imaging data as a .fits file (`dataset/data.fits`). - - The noise-map as a .fits file (`dataset/noise_map.fits`). - - The point spread function as a .fits file (`dataset/psf.fits`). - - The settings of the `Imaging` data structure used in the fit (`dataset/settings.json`). - - The mask used to mask the `Imaging` data structure in the fit (`dataset/mask.fits`). + - The imaging data as a .fits file (`dataset.fits[hdu=1]`). + - The noise-map as a .fits file (`dataset.fits[hdu=2]`). + - The point spread function as a .fits file (`dataset.fits[hdu=3]`). + - The settings of the `Imaging` data structure used in the fit (`dataset/settings.json`). + - The mask used to mask the `Imaging` data structure in the fit (`dataset.fits[hdu=0]`). - The `aggregator` contains the path to each of these files, and they can be loaded individually. This class - can load them all at once and create an `Imaging` object via the `_imaging_from` method. + The `aggregator` contains the path to each of these files, and they can be loaded individually. This class + can load them all at once and create an `Imaging` object via the `_imaging_from` method. - This class's methods returns generators which create the instances of the `Imaging` objects. This ensures - that large sets of results can be efficiently loaded from the hard-disk and do not require storing all - `Imaging` instances in the memory at once. + This class's methods returns generators which create the instances of the `Imaging` objects. This ensures + that large sets of results can be efficiently loaded from the hard-disk and do not require storing all + `Imaging` instances in the memory at once. - For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which - creates instances of the corresponding 3 `Imaging` objects. + For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which + creates instances of the corresponding 3 `Imaging` objects. - If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method - is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of - `Imaging` objects. + If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method + is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of + `Imaging` objects. - This can be done manually, but this object provides a more concise API. + This can be done manually, but this object provides a more concise API. - Parameters - ---------- - aggregator - A `PyAutoFit` aggregator object which can load the results of model-fits. + Parameters + ---------- + aggregator + A `PyAutoFit` aggregator object which can load the results of model-fits. """ self.aggregator = aggregator diff --git a/autogalaxy/aggregator/interferometer/fit_interferometer.py b/autogalaxy/aggregator/interferometer/fit_interferometer.py index 316e3aac4..f2f802396 100644 --- a/autogalaxy/aggregator/interferometer/fit_interferometer.py +++ b/autogalaxy/aggregator/interferometer/fit_interferometer.py @@ -18,14 +18,14 @@ def _fit_interferometer_from( fit: af.Fit, instance: Optional[af.ModelInstance] = None, - real_space_mask: Optional[aa.Mask2D] = None, settings_inversion: aa.SettingsInversion = None, use_preloaded_grid: bool = True, ) -> List[FitInterferometer]: """ - Returns a list of `FitInterferometer` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `FitInterferometer` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - The interferometer data, noise-map, uv-wavelengths and settings as .fits files (e.g. `dataset/data.fits`). - The real space mask defining the grid of the interferometer for the FFT (`dataset/real_space_mask.fits`). @@ -47,7 +47,8 @@ def _fit_interferometer_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). @@ -62,7 +63,6 @@ def _fit_interferometer_from( dataset_list = _interferometer_from( fit=fit, - real_space_mask=real_space_mask, ) galaxies_list = _galaxies_from(fit=fit, instance=instance) @@ -113,50 +113,49 @@ def __init__( aggregator: af.Aggregator, settings_inversion: Optional[aa.SettingsInversion] = None, use_preloaded_grid: bool = True, - real_space_mask: Optional[aa.Mask2D] = None, ): """ - Interfaces with an `PyAutoFit` aggregator object to create instances of `FitInterferometer` objects from the - results of a model-fit. - - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: - - - The interferometer data, noise-map, uv-wavelengths and settings as .fits files (e.g. `dataset/data.fits`). - - The real space mask defining the grid of the interferometer for the FFT (`dataset/real_space_mask.fits`). - - The settings of inversions used by the fit (`dataset/settings_inversion.json`). - - The `aggregator` contains the path to each of these files, and they can be loaded individually. This class - can load them all at once and create an `FitInterferometer` object via the `_fit_interferometer_from` method. - - This class's methods returns generators which create the instances of the `FitInterferometer` objects. This ensures - that large sets of results can be efficiently loaded from the hard-disk and do not require storing all - `FitInterferometer` instances in the memory at once. - - For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which - creates instances of the corresponding 3 `FitInterferometer` objects. - - If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method - is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of - `FitImaging` objects. - - This can be done manually, but this object provides a more concise API. - - Parameters - ---------- - aggregator - A `PyAutoFit` aggregator object which can load the results of model-fits. - settings_inversion - Optionally overwrite the `SettingsInversion` of the `Inversion` object that is created from the fit. - use_preloaded_grid - Certain pixelization's construct their mesh in the source-plane from a stochastic KMeans algorithm. This - grid may be output to hard-disk after the model-fit and loaded via the database to ensure the same grid is - used as the fit. + Interfaces with an `PyAutoFit` aggregator object to create instances of `FitInterferometer` objects from the + results of a model-fit. + + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: + + - The interferometer data, noise-map, uv-wavelengths and settings as .fits files (e.g. `dataset/data.fits`). + - The real space mask defining the grid of the interferometer for the FFT (`dataset/real_space_mask.fits`). + - The settings of inversions used by the fit (`dataset/settings_inversion.json`). + + The `aggregator` contains the path to each of these files, and they can be loaded individually. This class + can load them all at once and create an `FitInterferometer` object via the `_fit_interferometer_from` method. + + This class's methods returns generators which create the instances of the `FitInterferometer` objects. This ensures + that large sets of results can be efficiently loaded from the hard-disk and do not require storing all + `FitInterferometer` instances in the memory at once. + + For example, if the `aggregator` contains 3 model-fits, this class can be used to create a generator which + creates instances of the corresponding 3 `FitInterferometer` objects. + + If multiple `Imaging` objects were fitted simultaneously via analysis summing, the `fit.child_values()` method + is instead used to load lists of the data, noise-map, PSF and mask and combine them into a list of + `FitImaging` objects. + + This can be done manually, but this object provides a more concise API. + + Parameters + ---------- + aggregator + A `PyAutoFit` aggregator object which can load the results of model-fits. + settings_inversion + Optionally overwrite the `SettingsInversion` of the `Inversion` object that is created from the fit. + use_preloaded_grid + Certain pixelization's construct their mesh in the source-plane from a stochastic KMeans algorithm. This + grid may be output to hard-disk after the model-fit and loaded via the database to ensure the same grid is + used as the fit. """ super().__init__(aggregator=aggregator) self.settings_inversion = settings_inversion self.use_preloaded_grid = use_preloaded_grid - self.real_space_mask = real_space_mask def object_via_gen_from( self, fit, instance: Optional[af.ModelInstance] = None @@ -169,7 +168,8 @@ def object_via_gen_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. instance A manual instance that overwrites the max log likelihood instance in fit (e.g. for drawing the instance randomly from the PDF). diff --git a/autogalaxy/aggregator/interferometer/interferometer.py b/autogalaxy/aggregator/interferometer/interferometer.py index 7bdf2ac2d..1886ad250 100644 --- a/autogalaxy/aggregator/interferometer/interferometer.py +++ b/autogalaxy/aggregator/interferometer/interferometer.py @@ -1,21 +1,23 @@ from functools import partial -from typing import List, Optional +from typing import List import autofit as af import autoarray as aa +from autogalaxy.aggregator import agg_util + def _interferometer_from( fit: af.Fit, - real_space_mask: Optional[aa.Mask2D] = None, ) -> List[aa.Interferometer]: """ - Returns a list of `Interferometer` objects from a `PyAutoFit` sqlite database `Fit` object. + Returns a list of `Interferometer` objects from a `PyAutoFit` loaded directory `Fit` or sqlite database `Fit` object. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - - The interferometer visibilities data as a .fits file (`dataset/data.fits`). - - The visibilities noise-map as a .fits file (`dataset/noise_map.fits`). + - The interferometer visibilities data as a .fits file (`dataset.fits[hdu=1]`). + - The visibilities noise-map as a .fits file (`dataset.fits[hdu=2]`). - The uv wavelengths as a .fits file (`dataset/uv_wavelengths.fits`). - The real space mask defining the grid of the interferometer for the FFT (`dataset/real_space_mask.fits`). - The settings of the `Interferometer` data structure used in the fit (`dataset/settings.json`). @@ -32,7 +34,8 @@ def _interferometer_from( Parameters ---------- fit - A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry in a sqlite database. + A `PyAutoFit` `Fit` object which contains the results of a model-fit as an entry which has been loaded from + an output directory or from an sqlite database.. """ fit_list = [fit] if not fit.children else fit.children @@ -40,21 +43,15 @@ def _interferometer_from( dataset_list = [] for fit in fit_list: + real_space_mask, header = agg_util.mask_header_from(fit=fit) + data = aa.Visibilities( - visibilities=fit.value(name="dataset.data")[0].data.astype("float") + visibilities=fit.value(name="dataset")[1].data.astype("float") ) noise_map = aa.VisibilitiesNoiseMap( - fit.value(name="dataset.noise_map")[0].data.astype("float") - ) - uv_wavelengths = fit.value(name="dataset.uv_wavelengths")[0].data - - real_space_mask = ( - real_space_mask - if real_space_mask is not None - else aa.Mask2D.from_primary_hdu( - primary_hdu=fit.value(name="dataset.real_space_mask")[0] - ) + fit.value(name="dataset")[2].data.astype("float") ) + uv_wavelengths = fit.value(name="dataset")[3].data transformer_class = fit.value(name="dataset.transformer_class") @@ -77,10 +74,11 @@ def __init__(self, aggregator: af.Aggregator): Interfaces with an `PyAutoFit` aggregator object to create instances of `Interferometer` objects from the results of a model-fit. - The results of a model-fit can be stored in a sqlite database, including the following attributes of the fit: + The results of a model-fit can be loaded from hard-disk or stored in a sqlite database, including the following + attributes of the fit: - - The interferometer visibilities data as a .fits file (`dataset/data.fits`). - - The visibilities noise-map as a .fits file (`dataset/noise_map.fits`). + - The interferometer visibilities data as a .fits file (`dataset.fits[hdu=1]`). + - The visibilities noise-map as a .fits file (`dataset.fits[hdu=2]`). - The uv wavelengths as a .fits file (`dataset/uv_wavelengths.fits`). - The real space mask defining the grid of the interferometer for the FFT (`dataset/real_space_mask.fits`). - The settings of the `Interferometer` data structure used in the fit (`dataset/settings.json`). @@ -110,21 +108,14 @@ def __init__(self, aggregator: af.Aggregator): def dataset_gen_from( self, - real_space_mask: Optional[aa.Mask2D] = None, ) -> List[aa.Interferometer]: """ Returns a generator of `Interferometer` objects from an input aggregator. See `__init__` for a description of how the `Interferometer` objects are created by this method. - - Parameters - ---------- - real_space_mask - The real space mask. """ func = partial( _interferometer_from, - real_space_mask=real_space_mask, ) return self.aggregator.map(func=func) diff --git a/autogalaxy/analysis/analysis/dataset.py b/autogalaxy/analysis/analysis/dataset.py index ff7a6088b..3da87d19c 100644 --- a/autogalaxy/analysis/analysis/dataset.py +++ b/autogalaxy/analysis/analysis/dataset.py @@ -5,6 +5,8 @@ from autoconf import conf from autoconf.dictable import to_dict, output_to_json +from autoconf.fitsable import hdu_list_for_output_from + import autofit as af import autoarray as aa @@ -151,10 +153,14 @@ def save_attributes(self, paths: af.DirectoryPaths): For this analysis the following are output: - - The dataset (data / noise-map / over sampler / etc.). - The settings associated with the inversion. - The settings associated with the pixelization. - The Cosmology. + + The following .fits files are also output via the plotter interface: + + - The mask applied to the dataset, in the `PrimaryHDU` of `dataset.fits`. + - The dataset (data / noise-map / over sampler / etc.). - The adapt image's model image and galaxy images, if used. It is common for these attributes to be loaded by many of the template aggregator functions given in the @@ -168,26 +174,6 @@ def save_attributes(self, paths: af.DirectoryPaths): The paths object which manages all paths, e.g. where the non-linear search outputs are stored, visualization, and the pickled objects used by the aggregator output by this function. """ - paths.save_fits( - name="data", - fits=self.dataset.data.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="noise_map", - fits=self.dataset.noise_map.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="over_sample_size_lp", - fits=self.dataset.grids.lp.over_sample_size.native.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="over_sample_size_pixelization", - fits=self.dataset.grids.pixelization.over_sample_size.native.hdu_for_output, - prefix="dataset", - ) paths.save_json( name="settings_inversion", object_dict=to_dict(self.settings_inversion), @@ -197,22 +183,6 @@ def save_attributes(self, paths: af.DirectoryPaths): object_dict=to_dict(self.cosmology), ) - if self.adapt_images is not None: - paths.save_json( - name="adapt_images", - object_dict=to_dict( - list(self.adapt_images.galaxy_name_image_dict.keys()) - ), - prefix="adapt_images", - ) - - for name in self.adapt_images.galaxy_name_image_dict.keys(): - paths.save_fits( - name=name, - fits=self.adapt_images.galaxy_name_image_dict[name].hdu_for_output, - prefix="adapt_images", - ) - def save_results(self, paths: af.DirectoryPaths, result: ResultDataset): """ At the end of a model-fit, this routine saves attributes of the `Analysis` object to the `files` diff --git a/autogalaxy/analysis/plotter_interface.py b/autogalaxy/analysis/plotter_interface.py index c33e15424..a1de60d1b 100644 --- a/autogalaxy/analysis/plotter_interface.py +++ b/autogalaxy/analysis/plotter_interface.py @@ -1,8 +1,10 @@ import os -from os import path +from pathlib import Path from typing import List, Union from autoconf import conf +from autoconf.fitsable import hdu_list_for_output_from + import autoarray as aa import autoarray.plot as aplt @@ -36,7 +38,7 @@ def plot_setting(section: Union[List[str], str], name: str) -> bool: class PlotterInterface: - def __init__(self, image_path: str, title_prefix: str = None): + def __init__(self, image_path: Union[Path, str], title_prefix: str = None): """ Provides an interface between an output path and all plotter objects. @@ -60,7 +62,7 @@ def __init__(self, image_path: str, title_prefix: str = None): A string that is added before the title of all figures output by visualization, for example to put the name of the dataset and galaxy in the title. """ - self.image_path = image_path + self.image_path = Path(image_path) self.title_prefix = title_prefix self.include_2d = Include2D() @@ -83,7 +85,7 @@ def mat_plot_1d_from(self) -> MatPlot1D: """ return MatPlot1D( title=aplt.Title(prefix=self.title_prefix), - output=aplt.Output(path=path.join(self.image_path), format=self.fmt), + output=aplt.Output(path=self.image_path, format=self.fmt), ) def mat_plot_2d_from(self) -> MatPlot2D: @@ -98,7 +100,7 @@ def mat_plot_2d_from(self) -> MatPlot2D: """ return MatPlot2D( title=aplt.Title(prefix=self.title_prefix), - output=aplt.Output(path=path.join(self.image_path), format=self.fmt), + output=aplt.Output(path=self.image_path, format=self.fmt), ) def galaxies( @@ -178,24 +180,14 @@ def should_plot(name): 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 - ], + hdu_list = hdu_list_for_output_from( + values_list=[grid.mask.astype("float")] + + [galaxy.image_2d_from(grid=grid) for galaxy in galaxies], + ext_name_list=["mask"] + [f"galaxy_{i}" for i in range(len(galaxies))], + header_dict=grid.mask.header_dict, ) - 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, - ) + hdu_list.writeto(self.image_path / "galaxy_images.fits", overwrite=True) def inversion(self, inversion: aa.Inversion): """ @@ -264,5 +256,21 @@ def should_plot(name): if should_plot("subplot_adapt_images"): adapt_plotter.subplot_adapt_images( - adapt_galaxy_name_image_dict=adapt_images.galaxy_image_dict + adapt_galaxy_name_image_dict=adapt_images.galaxy_name_image_dict ) + + values_list = [ + adapt_images.galaxy_name_image_dict[name].native + for name in adapt_images.galaxy_name_image_dict.keys() + ] + + hdu_list = hdu_list_for_output_from( + values_list=[ + adapt_images.mask.astype("float"), + ] + + values_list, + ext_name_list=["mask"] + list(adapt_images.galaxy_name_image_dict.keys()), + header_dict=adapt_images.mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "adapt_images.fits", overwrite=True) diff --git a/autogalaxy/ellipse/model/analysis.py b/autogalaxy/ellipse/model/analysis.py index 857c570d3..068b730c4 100644 --- a/autogalaxy/ellipse/model/analysis.py +++ b/autogalaxy/ellipse/model/analysis.py @@ -2,7 +2,7 @@ import time from typing import Dict, List, Optional, Tuple -from autoconf.dictable import to_dict +from autoconf.fitsable import hdu_list_for_output_from import autofit as af import autoarray as aa @@ -184,21 +184,7 @@ def save_attributes(self, paths: af.DirectoryPaths): The paths object which manages all paths, e.g. where the non-linear search outputs are stored, visualization, and the pickled objects used by the aggregator output by this function. """ - paths.save_fits( - name="data", - fits=self.dataset.data.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="noise_map", - fits=self.dataset.noise_map.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="mask", - fits=self.dataset.mask.hdu_for_output, - prefix="dataset", - ) + pass 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 e1432730c..1c6767eac 100644 --- a/autogalaxy/ellipse/model/plotter_interface.py +++ b/autogalaxy/ellipse/model/plotter_interface.py @@ -1,5 +1,6 @@ from typing import List -from os import path + +from autoconf.fitsable import hdu_list_for_output_from import autoarray as aa import autoarray.plot as aplt @@ -43,6 +44,22 @@ def should_plot(name): if should_plot("subplot_dataset"): dataset_plotter.subplot_dataset() + hdu_list = hdu_list_for_output_from( + values_list=[ + dataset.mask.astype("float"), + dataset.data.native, + dataset.noise_map.native, + ], + ext_name_list=[ + "mask", + "data", + "noise_map", + ], + header_dict=dataset.mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "dataset.fits", overwrite=True) + def fit_ellipse( self, fit_list: List[FitEllipse], diff --git a/autogalaxy/imaging/model/analysis.py b/autogalaxy/imaging/model/analysis.py index 8e1d69869..6f6b2f21e 100644 --- a/autogalaxy/imaging/model/analysis.py +++ b/autogalaxy/imaging/model/analysis.py @@ -1,7 +1,8 @@ import numpy as np - from typing import Dict, Optional, Tuple +from autoconf.fitsable import hdu_list_for_output_from + import autofit as af import autoarray as aa @@ -200,47 +201,34 @@ def fit_from( def save_attributes(self, paths: af.DirectoryPaths): """ - Before the non-linear search begins, this routine saves attributes of the `Analysis` object to the `files` - folder such that they can be loaded after the analysis using PyAutoFit's database and aggregator tools. + Before the non-linear search begins, this routine saves attributes of the `Analysis` object to the `files` + folder such that they can be loaded after the analysis using PyAutoFit's database and aggregator tools. - For this analysis, it uses the `AnalysisDataset` object's method to output the following: + For this analysis, it uses the `AnalysisDataset` object's method to output the following: - - The imaging dataset (data / noise-map / psf / over sampler / etc.). - - The mask applied to the dataset. - - The settings associated with the inversion. - - The settings associated with the pixelization. - - The Cosmology. - - The adapt image's model image and galaxy images, if used. + - The settings associated with the inversion. + - The settings associated with the pixelization. + - The Cosmology. + - The adapt image's model image and galaxy images, as `adapt_images.fits`, if used. - This function also outputs attributes specific to an imaging dataset: + The following .fits files are also output via the plotter interface: - - Its PSF. - - Its mask. + - The mask applied to the dataset, in the `PrimaryHDU` of `dataset.fits`. + - The imaging dataset as `dataset.fits` (data / noise-map / psf / over sampler / etc.). - It is common for these attributes to be loaded by many of the template aggregator functions given in the - `aggregator` modules. For example, when using the database tools to perform a fit, the default behaviour is for - the dataset, settings and other attributes necessary to perform the fit to be loaded via the pickle files - output by this function. + It is common for these attributes to be loaded by many of the template aggregator functions given in the + `aggregator` modules. For example, when using the database tools to perform a fit, the default behaviour is for + the dataset, settings and other attributes necessary to perform the fit to be loaded via the pickle files + output by this function. - Parameters - ---------- - paths - The paths object which manages all paths, e.g. where the non-linear search outputs are stored, - visualization, and the pickled objects used by the aggregator output by this function. + Parameters + ---------- + paths + The paths object which manages all paths, e.g. where the non-linear search outputs are stored, + visualization, and the pickled objects used by the aggregator output by this function. """ super().save_attributes(paths=paths) - paths.save_fits( - name="psf", - fits=self.dataset.psf.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="mask", - fits=self.dataset.mask.hdu_for_output, - prefix="dataset", - ) - def profile_log_likelihood_function( self, instance: af.ModelInstance, paths: Optional[af.DirectoryPaths] = None ) -> Tuple[Dict, Dict]: diff --git a/autogalaxy/imaging/model/plotter_interface.py b/autogalaxy/imaging/model/plotter_interface.py index 7074f2b2e..894e5154c 100644 --- a/autogalaxy/imaging/model/plotter_interface.py +++ b/autogalaxy/imaging/model/plotter_interface.py @@ -1,5 +1,7 @@ -from os import path -from typing import ClassVar, List +from pathlib import Path +from typing import List + +from autoconf.fitsable import hdu_list_for_output_from import autoarray as aa import autoarray.plot as aplt @@ -13,9 +15,8 @@ def fits_to_fits( should_plot: bool, + image_path: Path, fit: FitImaging, - mat_plot_2d: aplt.MatPlot2D, - fit_plotter_cls: ClassVar, ): """ Output attributes of a `FitImaging` to .fits format. @@ -27,56 +28,47 @@ def fits_to_fits( ---------- should_plot The function which inspects the configuration files to determine if a .fits file should be output. + image_path + The path the .fits files are output and the name of the .fits files. 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", + hdu_list = hdu_list_for_output_from( + values_list=[ + fit.mask.astype("float"), + fit.model_data, + fit.residual_map, + fit.normalized_residual_map, + fit.chi_squared_map, ], - # tag_list=[name for name, galaxy in galaxies.items()], - tag_list=[ - "model_image", + ext_name_list=[ + "mask", + "model_data", "residual_map", "normalized_residual_map", "chi_squared_map", ], - filename="fit", - remove_fits_first=True, + header_dict=fit.mask.header_dict, ) + hdu_list.writeto(image_path / "fit.fits", overwrite=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(fit.galaxy_model_image_dict.keys()) + 1 + + hdu_list = hdu_list_for_output_from( + values_list=[fit.mask.astype("float")] + + [image.native for image in fit.galaxy_model_image_dict.values()], + ext_name_list=[ + "mask", + ] + + [f"galaxy_{i}" for i in range(number_plots)], + header_dict=fit.mask.header_dict, ) - 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, - ) + hdu_list.writeto(image_path / "model_galaxy_images.fits", overwrite=True) class PlotterInterfaceImaging(PlotterInterface): @@ -111,6 +103,28 @@ def should_plot(name): if should_plot("subplot_dataset"): dataset_plotter.subplot_dataset() + hdu_list = hdu_list_for_output_from( + values_list=[ + dataset.mask.astype("float"), + dataset.data.native, + dataset.noise_map.native, + dataset.psf.native, + dataset.grids.lp.over_sample_size.native, + dataset.grids.pixelization.over_sample_size.native, + ], + ext_name_list=[ + "mask", + "data", + "noise_map", + "psf", + "over_sample_size_lp", + "over_sample_size_pixelization", + ], + header_dict=dataset.mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "dataset.fits", overwrite=True) + def fit_imaging( self, fit: FitImaging, @@ -151,9 +165,8 @@ def should_plot(name): fits_to_fits( should_plot=should_plot, + image_path=self.image_path, fit=fit, - mat_plot_2d=mat_plot_2d, - fit_plotter_cls=FitImagingPlotter, ) def imaging_combined(self, dataset_list: List[aa.Imaging]): diff --git a/autogalaxy/imaging/model/visualizer.py b/autogalaxy/imaging/model/visualizer.py index feb2b79b1..fc2cc0d93 100644 --- a/autogalaxy/imaging/model/visualizer.py +++ b/autogalaxy/imaging/model/visualizer.py @@ -1,3 +1,5 @@ +from autoconf.fitsable import hdu_list_for_output_from + import autofit as af from autoarray import exc @@ -27,11 +29,13 @@ def visualize_before_fit( the imaging data. """ + dataset = analysis.dataset + plotter = PlotterInterfaceImaging( image_path=paths.image_path, title_prefix=analysis.title_prefix ) - plotter.imaging(dataset=analysis.dataset) + plotter.imaging(dataset=dataset) if analysis.adapt_images is not None: plotter.adapt_images(adapt_images=analysis.adapt_images) diff --git a/autogalaxy/interferometer/model/analysis.py b/autogalaxy/interferometer/model/analysis.py index d4924f2bf..1dce6801f 100644 --- a/autogalaxy/interferometer/model/analysis.py +++ b/autogalaxy/interferometer/model/analysis.py @@ -3,6 +3,7 @@ from typing import Dict, Optional, Tuple from autoconf.dictable import to_dict +from autoconf.fitsable import hdu_list_for_output_from import autofit as af import autoarray as aa @@ -204,45 +205,38 @@ def fit_from( def save_attributes(self, paths: af.DirectoryPaths): """ - Before the model-fit begins, this routine saves attributes of the `Analysis` object to the `files` folder - such that they can be loaded after the analysis using PyAutoFit's database and aggregator tools. + Before the model-fit begins, this routine saves attributes of the `Analysis` object to the `files` folder + such that they can be loaded after the analysis using PyAutoFit's database and aggregator tools. - For this analysis, it uses the `AnalysisDataset` object's method to output the following: + It outputs the following attributes of the dataset: - - The interferometer dataset (data / noise-map / uv-wavelengths / settings / etc.). - - The real space mask defining how the images appear in real-space and used for the FFT. - - The settings associated with the inversion. - - The settings associated with the pixelization. - - The Cosmology. - - The adapt image's model image and galaxy images, if used. - This function also outputs attributes specific to an interferometer dataset: - - Its uv-wavelengths - - Its real space mask. + For this analysis, it uses the `AnalysisDataset` object's method to output the following: - It is common for these attributes to be loaded by many of the template aggregator functions given in the - `aggregator` modules. For example, when using the database tools to perform a fit, the default behaviour is for - the dataset, settings and other attributes necessary to perform the fit to be loaded via the pickle files - output by this function. + - The settings associated with the inversion. + - The settings associated with the pixelization. + - The Cosmology. + - The adapt image's model image and galaxy images, as `adapt_images.fits`, if used. - Parameters - ---------- - paths - The paths object which manages all paths, e.g. where the non-linear search outputs are stored, visualization, - and the pickled objects used by the aggregator output by this function. + The following .fits files are also output via the plotter interface: + + - The real space mask applied to the dataset, in the `PrimaryHDU` of `dataset.fits`. + - The interferometer dataset as `dataset.fits` (data / noise-map / uv_wavelengths). + + It is common for these attributes to be loaded by many of the template aggregator functions given in the + `aggregator` modules. For example, when using the database tools to perform a fit, the default behaviour is for + the dataset, settings and other attributes necessary to perform the fit to be loaded via the pickle files + output by this function. + + Parameters + ---------- + paths + The paths object which manages all paths, e.g. where the non-linear search outputs are stored, visualization, + and the pickled objects used by the aggregator output by this function. """ super().save_attributes(paths=paths) - hdu = aa.util.array_2d.hdu_for_output_from( - array_2d=self.dataset.uv_wavelengths, - ) - paths.save_fits(name="uv_wavelengths", fits=hdu, prefix="dataset") - paths.save_fits( - name="real_space_mask", - fits=self.dataset.real_space_mask.hdu_for_output, - prefix="dataset", - ) paths.save_json( "transformer_class", to_dict(self.dataset.transformer.__class__), "dataset" ) diff --git a/autogalaxy/interferometer/model/plotter_interface.py b/autogalaxy/interferometer/model/plotter_interface.py index fa421cae5..18130f1e6 100644 --- a/autogalaxy/interferometer/model/plotter_interface.py +++ b/autogalaxy/interferometer/model/plotter_interface.py @@ -1,5 +1,6 @@ -from os import path -from typing import ClassVar +from pathlib import Path + +from autoconf.fitsable import hdu_list_for_output_from import autoarray as aa import autoarray.plot as aplt @@ -15,9 +16,8 @@ def fits_to_fits( should_plot: bool, + image_path: Path, fit: FitInterferometer, - mat_plot_2d: aplt.MatPlot2D, - fit_plotter_cls: ClassVar, ): """ Output attributes of a `FitInterferometer` to .fits format. @@ -29,76 +29,36 @@ def fits_to_fits( ---------- should_plot The function which inspects the configuration files to determine if a .fits file should be output. + image_path + The path the .fits files are output and the name of the .fits files. 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() - ], + hdu_list = hdu_list_for_output_from( + values_list=[fit.dataset.real_space_mask.astype("float")] + + [image.native for image in fit.galaxy_model_image_dict.values()], + ext_name_list=["mask"] + + [f"galaxy_{i}" for i in range(len(fit.galaxy_model_image_dict.values()))], + header_dict=fit.dataset.real_space_mask.header_dict, ) - 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, - ) + hdu_list.writeto(image_path / "model_galaxy_images.fits", overwrite=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", + hdu_list = hdu_list_for_output_from( + values_list=[ + fit.dataset.real_space_mask.astype("float"), + fit.dirty_image.native, + fit.dirty_noise_map.native, + fit.dirty_model_image.native, + fit.dirty_residual_map.native, + fit.dirty_normalized_residual_map.native, + fit.dirty_chi_squared_map.native, ], - # tag_list=[name for name, galaxy in galaxies.items()], - tag_list=[ + ext_name_list=["mask"] + + [ "dirty_image", "dirty_noise_map", "dirty_model_image", @@ -106,10 +66,11 @@ def fits_to_fits( "dirty_normalized_residual_map", "dirty_chi_squared_map", ], - filename="dirty_images", - remove_fits_first=True, + header_dict=fit.dataset.real_space_mask.header_dict, ) + hdu_list.writeto(image_path / "fit_dirty_images.fits", overwrite=True) + class PlotterInterfaceInterferometer(PlotterInterface): def interferometer(self, dataset: aa.Interferometer): @@ -147,6 +108,19 @@ def should_plot(name): if should_plot("subplot_dataset"): dataset_plotter.subplot_dataset() + hdu_list = hdu_list_for_output_from( + values_list=[ + dataset.real_space_mask.astype("float"), + dataset.data.in_array, + dataset.noise_map.in_array, + dataset.uv_wavelengths, + ], + ext_name_list=["mask", "data", "noise_map", "uv_wavelengths"], + header_dict=dataset.real_space_mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "dataset.fits", overwrite=True) + def fit_interferometer( self, fit: FitInterferometer, @@ -194,7 +168,6 @@ def should_plot(name): fits_to_fits( should_plot=should_plot, + image_path=self.image_path, fit=fit, - mat_plot_2d=mat_plot_2d, - fit_plotter_cls=FitInterferometerPlotter, ) diff --git a/autogalaxy/quantity/model/analysis.py b/autogalaxy/quantity/model/analysis.py index 9b455200f..4c764957d 100644 --- a/autogalaxy/quantity/model/analysis.py +++ b/autogalaxy/quantity/model/analysis.py @@ -1,4 +1,5 @@ from autoconf.dictable import to_dict +from autoconf.fitsable import hdu_list_for_output_from import autofit as af @@ -133,11 +134,13 @@ def save_attributes(self, paths: af.DirectoryPaths): For this analysis, it uses the `AnalysisDataset` object's method to output the following: - - The dataset's data. - - The dataset's noise-map. - The settings associated with the dataset. - The Cosmology. - - Its mask. + + The following .fits files are also output via the plotter interface: + + - The mask applied to the dataset, in the `PrimaryHDU` of `dataset.fits`. + - The imaging dataset as `dataset.fits` (data / noise-map / psf / over sampler / etc.). It is common for these attributes to be loaded by many of the template aggregator functions given in the `aggregator` modules. For example, when using the database tools to perform a fit, the default behaviour is for @@ -150,21 +153,7 @@ def save_attributes(self, paths: af.DirectoryPaths): The paths object which manages all paths, e.g. where the non-linear search outputs are stored, visualization, and the pickled objects used by the aggregator output by this function. """ - paths.save_fits( - name="data", - fits=self.dataset.data.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="noise_map", - fits=self.dataset.noise_map.hdu_for_output, - prefix="dataset", - ) - paths.save_fits( - name="mask", - fits=self.dataset.mask.hdu_for_output, - prefix="dataset", - ) + paths.save_json( name="cosmology", object_dict=to_dict(self.cosmology), diff --git a/autogalaxy/quantity/model/plotter_interface.py b/autogalaxy/quantity/model/plotter_interface.py index 98070b253..1d925b40c 100644 --- a/autogalaxy/quantity/model/plotter_interface.py +++ b/autogalaxy/quantity/model/plotter_interface.py @@ -1,3 +1,6 @@ +from autoconf.fitsable import hdu_list_for_output_from + +from autogalaxy.quantity.dataset_quantity import DatasetQuantity from autogalaxy.quantity.fit_quantity import FitQuantity from autogalaxy.quantity.plot.fit_quantity_plotters import FitQuantityPlotter from autogalaxy.analysis.plotter_interface import PlotterInterface @@ -6,6 +9,40 @@ class PlotterInterfaceQuantity(PlotterInterface): + def dataset_quantity(self, dataset: DatasetQuantity): + """ + Output visualization of an `Imaging` dataset, typically before a model-fit is performed. + + 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` and `imaging` headers. + + Parameters + ---------- + dataset + The imaging dataset which is visualized. + """ + hdu_list = hdu_list_for_output_from( + values_list=[ + dataset.mask.astype("float"), + dataset.data.native, + dataset.noise_map.native, + ], + ext_name_list=[ + "mask", + "data", + "noise_map", + ], + header_dict=dataset.mask.header_dict, + ) + + hdu_list.writeto(self.image_path / "dataset.fits", overwrite=True) + def fit_quantity( self, fit: FitQuantity, diff --git a/autogalaxy/quantity/model/visualizer.py b/autogalaxy/quantity/model/visualizer.py index 398139d77..30a5feeca 100644 --- a/autogalaxy/quantity/model/visualizer.py +++ b/autogalaxy/quantity/model/visualizer.py @@ -6,6 +6,34 @@ class VisualizerQuantity(af.Visualizer): + @staticmethod + def visualize_before_fit( + analysis, + paths: af.AbstractPaths, + model: af.AbstractPriorModel, + ): + """ + PyAutoFit calls this function immediately before the non-linear search begins. + + It visualizes objects which do not change throughout the model fit like the dataset. + + Parameters + ---------- + paths + The paths object which manages all paths, e.g. where the non-linear search outputs are stored, + visualization and the pickled objects used by the aggregator output by this function. + model + The model object, which includes model components representing the galaxies that are fitted to + the imaging data. + """ + dataset = analysis.dataset + + plotter = PlotterInterfaceQuantity( + image_path=paths.image_path, title_prefix=analysis.title_prefix + ) + + plotter.dataset_quantity(dataset=dataset) + @staticmethod def visualize( analysis, diff --git a/test_autogalaxy/aggregator/conftest.py b/test_autogalaxy/aggregator/conftest.py index 235737d62..6a125ca14 100644 --- a/test_autogalaxy/aggregator/conftest.py +++ b/test_autogalaxy/aggregator/conftest.py @@ -47,6 +47,8 @@ def aggregator_from(database_file, analysis, model, samples): search.paths = af.DirectoryPaths(path_prefix=database_file) search.fit(model=model, analysis=analysis) + analysis.visualize_before_fit(paths=search.paths, model=model) + database_file = path.join(conf.instance.output_path, f"{database_file}.sqlite") agg = af.Aggregator.from_database(filename=database_file) diff --git a/test_autogalaxy/aggregator/ellipse/conftest.py b/test_autogalaxy/aggregator/ellipse/conftest.py index 7e1a40e88..4df8107f6 100644 --- a/test_autogalaxy/aggregator/ellipse/conftest.py +++ b/test_autogalaxy/aggregator/ellipse/conftest.py @@ -47,6 +47,8 @@ def aggregator_from(database_file, analysis, model, samples): search.paths = af.DirectoryPaths(path_prefix=database_file) search.fit(model=model, analysis=analysis) + analysis.visualize_before_fit(paths=search.paths, model=model) + database_file = path.join(conf.instance.output_path, f"{database_file}.sqlite") agg = af.Aggregator.from_database(filename=database_file) diff --git a/test_autogalaxy/aggregator/ellipse/test_aggregator_fit_ellipse.py b/test_autogalaxy/aggregator/ellipse/test_aggregator_fit_ellipse.py index 0b09c76c5..d799bb446 100644 --- a/test_autogalaxy/aggregator/ellipse/test_aggregator_fit_ellipse.py +++ b/test_autogalaxy/aggregator/ellipse/test_aggregator_fit_ellipse.py @@ -30,6 +30,8 @@ def make_agg_7x7(samples, model, analysis_ellipse_7x7): search.paths = af.DirectoryPaths(path_prefix=file_prefix) search.fit(model=model, analysis=analysis_ellipse_7x7) + analysis_ellipse_7x7.visualize_before_fit(paths=search.paths, model=model) + database_file = output_path / f"{file_prefix}.sqlite" agg = af.Aggregator.from_database(filename=database_file) diff --git a/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py b/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py index a01eb8b3b..216f9d105 100644 --- a/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py +++ b/test_autogalaxy/aggregator/imaging/test_aggregator_fit_imaging.py @@ -30,6 +30,8 @@ def make_agg_7x7(samples, model, analysis_imaging_7x7): search.paths = af.DirectoryPaths(path_prefix=file_prefix) search.fit(model=model, analysis=analysis_imaging_7x7) + analysis_imaging_7x7.visualize_before_fit(paths=search.paths, model=model) + database_file = output_path / f"{file_prefix}.sqlite" agg = af.Aggregator.from_database(filename=database_file) diff --git a/test_autogalaxy/analysis/test_plotter_interface.py b/test_autogalaxy/analysis/test_plotter_interface.py index 3893e508c..ef7e96878 100644 --- a/test_autogalaxy/analysis/test_plotter_interface.py +++ b/test_autogalaxy/analysis/test_plotter_interface.py @@ -34,11 +34,11 @@ def test__galaxies( path.join(plot_path, "subplot_galaxies_1d_decomposed.png") in plot_patch.paths ) - image = ag.util.array_2d.numpy_array_2d_via_fits_from( + image = ag.ndarray_via_fits_from( file_path=path.join(plot_path, "galaxy_images.fits"), hdu=0 ) - assert image.shape == (5, 5) + assert image.shape == (7, 7) def test__inversion( @@ -71,7 +71,7 @@ def test__adapt_images( plotter_interface = PlotterInterface(image_path=plot_path) adapt_images = ag.AdaptImages( - galaxy_image_dict=adapt_galaxy_name_image_dict_7x7, + galaxy_name_image_dict=adapt_galaxy_name_image_dict_7x7, ) plotter_interface.adapt_images( @@ -81,3 +81,9 @@ def test__adapt_images( plot_path = path.join(plot_path) assert path.join(plot_path, "subplot_adapt_images.png") in plot_patch.paths + + image = ag.ndarray_via_fits_from( + file_path=path.join(plot_path, "adapt_images.fits"), hdu=0 + ) + + assert image.shape == (7, 7) diff --git a/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py b/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py index de73868d2..0f86cd413 100644 --- a/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py +++ b/test_autogalaxy/imaging/model/test_plotter_interface_imaging.py @@ -23,6 +23,12 @@ def test__imaging(imaging_7x7, include_2d_all, plot_path, plot_patch): assert path.join(plot_path, "subplot_dataset.png") in plot_patch.paths + image = ag.ndarray_via_fits_from( + file_path=path.join(plot_path, "dataset.fits"), hdu=0 + ) + + assert image.shape == (7, 7) + def test__imaging_combined(imaging_7x7, plot_path, plot_patch): if path.exists(plot_path): @@ -53,17 +59,15 @@ def test__fit_imaging( assert path.join(plot_path, "subplot_fit.png") 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 - ) + image = ag.ndarray_via_fits_from(file_path=path.join(plot_path, "fit.fits"), hdu=0) - assert image.shape == (5, 5) + assert image.shape == (7, 7) - image = ag.util.array_2d.numpy_array_2d_via_fits_from( + image = ag.ndarray_via_fits_from( file_path=path.join(plot_path, "model_galaxy_images.fits"), hdu=0 ) - assert image.shape == (5, 5) + assert image.shape == (7, 7) def test__fit_imaging_combined( diff --git a/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py b/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py index a313a768e..6bf737532 100644 --- a/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py +++ b/test_autogalaxy/interferometer/model/test_plotter_interface_interferometer.py @@ -22,6 +22,12 @@ def test__interferometer(interferometer_7, include_2d_all, plot_path, plot_patch assert path.join(plot_path, "subplot_dataset.png") in plot_patch.paths + image = ag.ndarray_via_fits_from( + file_path=path.join(plot_path, "dataset.fits"), hdu=0 + ) + + assert image.shape == (7, 7) + def test__fit_interferometer( interferometer_7, @@ -38,26 +44,14 @@ def test__fit_interferometer( assert path.join(plot_path, "subplot_fit.png") 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( + image = ag.ndarray_via_fits_from( file_path=path.join(plot_path, "model_galaxy_images.fits"), hdu=0 ) - assert image.shape == (5, 5) + assert image.shape == (7, 7) - image = ag.util.array_2d.numpy_array_2d_via_fits_from( - file_path=path.join(plot_path, "dirty_images.fits"), hdu=0 + image = ag.ndarray_via_fits_from( + file_path=path.join(plot_path, "fit_dirty_images.fits"), hdu=0 ) - assert image.shape == (5, 5) + assert image.shape == (7, 7) diff --git a/test_autogalaxy/quantity/files/array/output_test/data.fits b/test_autogalaxy/quantity/files/array/output_test/data.fits index 90140e2a0..4746fc2e7 100644 Binary files a/test_autogalaxy/quantity/files/array/output_test/data.fits and b/test_autogalaxy/quantity/files/array/output_test/data.fits differ diff --git a/test_autogalaxy/quantity/files/array/output_test/noise_map.fits b/test_autogalaxy/quantity/files/array/output_test/noise_map.fits index 0f91870ec..9a8e8e0cb 100644 Binary files a/test_autogalaxy/quantity/files/array/output_test/noise_map.fits and b/test_autogalaxy/quantity/files/array/output_test/noise_map.fits differ diff --git a/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py b/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py index 699581d7b..96e3c5484 100644 --- a/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py +++ b/test_autogalaxy/quantity/model/test_plotter_interface_quantity.py @@ -2,6 +2,8 @@ from os import path import pytest +import autogalaxy as ag + from autogalaxy.quantity.model.plotter_interface import PlotterInterfaceQuantity directory = path.dirname(path.abspath(__file__)) @@ -12,6 +14,26 @@ def make_plotter_interface_plotter_setup(): return path.join("{}".format(directory), "files") +def test__dataset( + dataset_quantity_7x7_array_2d, + include_2d_all, + plot_path, + plot_patch, +): + if path.exists(plot_path): + shutil.rmtree(plot_path) + + PlotterInterface = PlotterInterfaceQuantity(image_path=plot_path) + + PlotterInterface.dataset_quantity(dataset=dataset_quantity_7x7_array_2d) + + image = ag.ndarray_via_fits_from( + file_path=path.join(plot_path, "dataset.fits"), hdu=0 + ) + + assert image.shape == (7, 7) + + def test__fit_quantity( fit_quantity_7x7_array_2d, fit_quantity_7x7_vector_yx_2d, @@ -26,6 +48,4 @@ def test__fit_quantity( PlotterInterface.fit_quantity(fit=fit_quantity_7x7_array_2d) - plot_path = path.join(plot_path, "fit_quantity") - assert path.join(plot_path, "subplot_fit.png") not in plot_patch.paths