import autogalaxy as ag
from autoarray.operators.inversion import inversions

import numpy as np
import pytest

from test_autogalaxy.mock.mock_profiles import MockLightProfile


class TestFitImaging:
    class TestLikelihood:
        def test__1x2_image__no_psf_blurring__plane_fits_data_with_chi_sq_5(self):
            # The image plane image generated by the galaxy is [1.0, 1.0]

            # Thus the chi squared is 4.0**2.0 + 3.0**2.0 = 25.0

            psf = ag.Kernel.manual_2d(
                array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
                pixel_scales=1.0,
            )

            imaging = ag.Imaging(
                image=5.0 * ag.Array.ones(shape_2d=(3, 4)),
                psf=psf,
                noise_map=ag.Array.ones(shape_2d=(3, 4)),
            )
            imaging.image[6] = 4.0

            mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_imaging_7x7 = ag.MaskedImaging(imaging=imaging, mask=mask)

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            assert (
                fit.mask
                == np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                )
            ).all()

            assert (
                fit.image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.noise_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.model_image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 3.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.normalized_residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 3.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.chi_squared_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 16.0, 9.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert fit.chi_squared == 25.0
            assert fit.reduced_chi_squared == 25.0 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 1.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                25.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0)
            )

        def test__1x2_image__include_psf_blurring__plane_fits_data_with_chi_sq_4(self):
            # This PSF changes the blurred image plane image from [1.0, 1.0] to [1.0, 5.0]

            # Thus, the chi squared is 4.0**2.0 + 0.0**2.0 = 16.0

            psf = ag.Kernel.manual_2d(
                array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 3.0], [0.0, 0.0, 0.0]])),
                pixel_scales=1.0,
                renormalize=False,
            )

            imaging = ag.Imaging(
                image=5.0 * ag.Array.ones(shape_2d=(3, 4)),
                psf=psf,
                noise_map=ag.Array.ones(shape_2d=(3, 4)),
            )
            imaging.image[6] = 4.0

            mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_imaging_7x7 = ag.MaskedImaging(
                imaging=imaging, mask=mask, renormalize_psf=False
            )

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            assert (
                fit.mask
                == np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                )
            ).all()

            assert (
                fit.image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.noise_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.model_image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.normalized_residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.chi_squared_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 16.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert fit.chi_squared == 16.0
            assert fit.reduced_chi_squared == 16.0 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 1.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                16.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0)
            )

        def test_hyper_galaxy_changes_noise_above_from_1_to_2__reflected_in_likelihood(
            self
        ):
            # This PSF changes the blurred image plane image from [1.0, 1.0] to [1.0, 5.0]

            # Thus, the chi squared is 4.0**2.0 + 0.0**2.0 = 16.0

            # The hyper_galaxies galaxy increases the noise in both pixels by 1.0, to 2.0.

            # This reduces the chi squared to 2.0 instead of 4.0

            psf = ag.Kernel.manual_2d(
                array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 3.0], [0.0, 0.0, 0.0]])),
                pixel_scales=1.0,
            )

            imaging = ag.Imaging(
                image=5.0 * ag.Array.ones(shape_2d=(3, 4)),
                psf=psf,
                noise_map=ag.Array.ones(shape_2d=(3, 4)),
            )
            imaging.image[6] = 4.0

            mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_imaging_7x7 = ag.MaskedImaging(
                imaging=imaging, mask=mask, renormalize_psf=False
            )

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=MockLightProfile(value=1.0, size=2),
                hyper_galaxy=ag.HyperGalaxy(
                    contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
                ),
                hyper_model_image=ag.Array.ones(shape_2d=(1, 2)),
                hyper_galaxy_image=ag.Array.ones(shape_2d=(1, 2)),
                hyper_minimum_value=0.0,
            )

            plane = ag.Plane(galaxies=[g0])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            assert (
                fit.mask
                == np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                )
            ).all()

            assert (
                fit.image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.noise_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 2.0, 2.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.model_image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.normalized_residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 2.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.chi_squared_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert fit.chi_squared == 4.0
            assert fit.reduced_chi_squared == 4.0 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 2.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                4.0 + 2.0 * np.log(2 * np.pi * 2.0 ** 2.0)
            )

        def test__hyper_image_changes_background_sky__reflected_in_likelihood(self):

            psf = ag.Kernel.manual_2d(
                array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
                pixel_scales=1.0,
            )

            imaging = ag.Imaging(
                image=ag.Array.full(fill_value=4.0, shape_2d=(3, 4)),
                psf=psf,
                noise_map=ag.Array.ones(shape_2d=(3, 4)),
            )
            imaging.image[5] = 5.0

            mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_imaging_7x7 = ag.MaskedImaging(imaging=imaging, mask=mask)

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            hyper_image_sky = ag.hyper_data.HyperImageSky(sky_scale=1.0)

            fit = ag.FitImaging(
                masked_imaging=masked_imaging_7x7,
                plane=plane,
                hyper_image_sky=hyper_image_sky,
            )

            assert (
                fit.mask
                == np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                )
            ).all()

            assert (
                fit.image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 6.0, 5.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.noise_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.model_image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.normalized_residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.chi_squared_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 25.0, 16.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert fit.chi_squared == 41.0
            assert fit.reduced_chi_squared == 41.0 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 1.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                41.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0)
            )

        def test__hyper_background_changes_background_noise_map__reflected_in_likelihood(
            self
        ):

            psf = ag.Kernel.manual_2d(
                array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
                pixel_scales=1.0,
            )

            imaging = ag.Imaging(
                image=5.0 * ag.Array.ones(shape_2d=(3, 4)),
                psf=psf,
                noise_map=ag.Array.ones(shape_2d=(3, 4)),
            )
            imaging.image[6] = 4.0

            mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_imaging_7x7 = ag.MaskedImaging(imaging=imaging, mask=mask)

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            fit = ag.FitImaging(
                masked_imaging=masked_imaging_7x7,
                plane=plane,
                hyper_background_noise=hyper_background_noise,
            )

            assert (
                fit.mask
                == np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                )
            ).all()

            assert (
                fit.image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 5.0, 4.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.noise_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 2.0, 2.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.model_image.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 3.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.normalized_residual_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 2.0, 1.5, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert (
                fit.chi_squared_map.in_2d
                == np.array(
                    [[0.0, 0.0, 0.0, 0.0], [0.0, 4.0, 2.25, 0.0], [0.0, 0.0, 0.0, 0.0]]
                )
            ).all()

            assert fit.chi_squared == 6.25
            assert fit.reduced_chi_squared == 6.25 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 2.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                6.25 + 2.0 * np.log(2 * np.pi * 2.0 ** 2.0)
            )

    class TestCompareToManualProfilesOnly:
        def test___all_fit_quantities__no_hyper_methods(self, masked_imaging_7x7):

            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )

            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            assert masked_imaging_7x7.noise_map.in_2d == pytest.approx(
                fit.noise_map.in_2d
            )

            model_image = plane.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            assert model_image.in_2d == pytest.approx(fit.model_image.in_2d)

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_imaging_7x7.image, model_data=model_image
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(fit.chi_squared_map.in_2d)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)
            assert log_likelihood == fit.figure_of_merit

        def test___fit_galaxy_model_image_dict__corresponds_to_blurred_galaxy_images(
            self, masked_imaging_7x7
        ):
            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )
            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )
            g2 = ag.Galaxy(redshift=1.0)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1, g2])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            g0_blurred_image = g0.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                blurring_grid=masked_imaging_7x7.blurring_grid,
                convolver=masked_imaging_7x7.convolver,
            )

            g1_blurred_image = g1.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                blurring_grid=masked_imaging_7x7.blurring_grid,
                convolver=masked_imaging_7x7.convolver,
            )

            assert fit.galaxy_model_image_dict[g0] == pytest.approx(
                g0_blurred_image, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[g1] == pytest.approx(
                g1_blurred_image, 1.0e-4
            )
            assert (fit.galaxy_model_image_dict[g2].in_1d == np.zeros(9)).all()

            assert fit.model_image.in_2d == pytest.approx(
                fit.galaxy_model_image_dict[g0].in_2d
                + fit.galaxy_model_image_dict[g1].in_2d,
                1.0e-4,
            )

        def test___all_fit_quantities__including_hyper_methods(
            self, masked_imaging_7x7
        ):

            hyper_image_sky = ag.hyper_data.HyperImageSky(sky_scale=1.0)

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            image = hyper_image_sky.hyper_image_from_image(
                image=masked_imaging_7x7.image
            )

            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
                hyper_galaxy=ag.HyperGalaxy(
                    contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
                ),
                hyper_model_image=np.ones(9),
                hyper_galaxy_image=np.ones(9),
                hyper_minimum_value=0.0,
            )
            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitImaging(
                masked_imaging=masked_imaging_7x7,
                plane=plane,
                hyper_image_sky=hyper_image_sky,
                hyper_background_noise=hyper_background_noise,
            )

            hyper_noise_map_background = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            hyper_noise = plane.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            hyper_noise_map = hyper_noise_map_background + hyper_noise

            assert hyper_noise_map.in_2d == pytest.approx(fit.noise_map.in_2d)

            model_image = plane.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            assert model_image.in_2d == pytest.approx(fit.model_image.in_2d)

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=image, model_data=model_image
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(fit.chi_squared_map.in_2d)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=hyper_noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)
            assert log_likelihood == fit.figure_of_merit

        def test___blurred_and_model_images_of_galaxies_and_unmasked_blurred_profile_image_properties(
            self, masked_imaging_7x7
        ):

            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )

            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            blurred_profile_images_of_galaxies = plane.blurred_profile_images_of_galaxies_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            assert blurred_profile_images_of_galaxies[0].in_2d == pytest.approx(
                fit.model_images_of_galaxies[0].in_2d, 1.0e-4
            )

            assert blurred_profile_images_of_galaxies[1].in_2d == pytest.approx(
                fit.model_images_of_galaxies[1].in_2d, 1.0e-4
            )

            unmasked_blurred_profile_image = plane.unmasked_blurred_profile_image_from_grid_and_psf(
                grid=masked_imaging_7x7.grid, psf=masked_imaging_7x7.psf
            )

            assert (
                unmasked_blurred_profile_image == fit.unmasked_blurred_profile_image
            ).all()

            unmasked_blurred_profile_image_of_galaxies = plane.unmasked_blurred_profile_image_of_galaxies_from_grid_and_psf(
                grid=masked_imaging_7x7.grid, psf=masked_imaging_7x7.psf
            )

            assert (
                unmasked_blurred_profile_image_of_galaxies[0]
                == fit.unmasked_blurred_profile_image_of_galaxies[0]
            ).all()
            assert (
                unmasked_blurred_profile_image_of_galaxies[1]
                == fit.unmasked_blurred_profile_image_of_galaxies[1]
            ).all()

    class TestCompareToManualInversionOnly:
        def test___all_quantities__no_hyper_methods(self, masked_imaging_7x7):

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(redshift=0.5, pixelization=pix, regularization=reg)

            plane = ag.Plane(galaxies=[ag.Galaxy(redshift=0.5), g0])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, sparse_grid=None
            )
            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                image=masked_imaging_7x7.image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
            )

            assert inversion.mapped_reconstructed_image.in_2d == pytest.approx(
                fit.model_image.in_2d, 1.0e-4
            )

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_imaging_7x7.image,
                model_data=inversion.mapped_reconstructed_image,
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d, 1.0e-4)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d, 1.0e-4
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(
                fit.chi_squared_map.in_2d, 1.0e-4
            )

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

        def test___fit_galaxy_model_image_dict__has_inversion_mapped_reconstructed_image(
            self, masked_imaging_7x7
        ):
            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(redshift=0.5)
            g1 = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, sparse_grid=None
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                image=masked_imaging_7x7.image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
            )

            assert (fit.galaxy_model_image_dict[g0] == np.zeros(9)).all()

            assert fit.galaxy_model_image_dict[g1].in_2d == pytest.approx(
                inversion.mapped_reconstructed_image.in_2d, 1.0e-4
            )

            assert fit.model_image.in_2d == pytest.approx(
                fit.galaxy_model_image_dict[g1].in_2d, 1.0e-4
            )

        def test___all_fit_quantities__include_hyper_methods(self, masked_imaging_7x7):

            hyper_image_sky = ag.hyper_data.HyperImageSky(sky_scale=1.0)

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            image = hyper_image_sky.hyper_image_from_image(
                image=masked_imaging_7x7.image
            )

            hyper_noise_map_background = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(
                redshift=0.5,
                pixelization=pix,
                regularization=reg,
                hyper_galaxy=ag.HyperGalaxy(
                    contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
                ),
                hyper_model_image=np.ones(9),
                hyper_galaxy_image=np.ones(9),
                hyper_minimum_value=0.0,
            )

            plane = ag.Plane(galaxies=[ag.Galaxy(redshift=0.5), g0])

            fit = ag.FitImaging(
                masked_imaging=masked_imaging_7x7,
                plane=plane,
                hyper_image_sky=hyper_image_sky,
                hyper_background_noise=hyper_background_noise,
            )

            hyper_noise = plane.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )
            hyper_noise_map = hyper_noise_map_background + hyper_noise

            assert hyper_noise_map.in_2d == pytest.approx(fit.noise_map.in_2d)

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )
            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                image=image,
                noise_map=hyper_noise_map,
                convolver=masked_imaging_7x7.convolver,
            )

            assert inversion.mapped_reconstructed_image.in_2d == pytest.approx(
                fit.model_image.in_2d, 1.0e-4
            )

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=image, model_data=inversion.mapped_reconstructed_image
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(fit.chi_squared_map.in_2d)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=hyper_noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

        def test___blurred_and_model_images_of_galaxies_and_unmasked_blurred_profile_image_properties(
            self, masked_imaging_7x7
        ):

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[ag.Galaxy(redshift=0.5), g0])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                image=masked_imaging_7x7.image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
            )

            assert (fit.model_images_of_galaxies[0].in_2d == np.zeros((7, 7))).all()
            assert inversion.mapped_reconstructed_image.in_2d == pytest.approx(
                fit.model_images_of_galaxies[1].in_2d, 1.0e-4
            )

    class TestCompareToManualProfilesAndInversion:
        def test___all_fit_quantities__no_hyper_methods(self, masked_imaging_7x7):
            galaxy_light = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[galaxy_light, galaxy_pix])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            blurred_profile_image = plane.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            assert blurred_profile_image.in_2d == pytest.approx(
                fit.blurred_profile_image.in_2d
            )

            profile_subtracted_image = masked_imaging_7x7.image - blurred_profile_image

            assert profile_subtracted_image.in_2d == pytest.approx(
                fit.profile_subtracted_image.in_2d
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                image=profile_subtracted_image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
                mapper=mapper,
                regularization=reg,
            )

            model_image = blurred_profile_image + inversion.mapped_reconstructed_image

            assert model_image.in_2d == pytest.approx(fit.model_image.in_2d)

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_imaging_7x7.image, model_data=model_image
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_imaging_7x7.noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(fit.chi_squared_map.in_2d)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

        def test___fit_galaxy_model_image_dict__has_blurred_profile_images_and_inversion_mapped_reconstructed_image(
            self, masked_imaging_7x7
        ):

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )
            g1 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=2.0)
            )
            g2 = ag.Galaxy(redshift=0.5)

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1, g2, galaxy_pix])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            g0_blurred_image = g0.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            g1_blurred_image = g1.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            blurred_profile_image = g0_blurred_image + g1_blurred_image

            profile_subtracted_image = masked_imaging_7x7.image - blurred_profile_image
            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                image=profile_subtracted_image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
                mapper=mapper,
                regularization=reg,
            )

            assert (fit.galaxy_model_image_dict[g2] == np.zeros(9)).all()

            assert fit.galaxy_model_image_dict[g0].in_2d == pytest.approx(
                g0_blurred_image.in_2d, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[g1].in_2d == pytest.approx(
                g1_blurred_image.in_2d, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[galaxy_pix].in_2d == pytest.approx(
                inversion.mapped_reconstructed_image.in_2d, 1.0e-4
            )

            assert fit.model_image.in_2d == pytest.approx(
                fit.galaxy_model_image_dict[g0].in_2d
                + fit.galaxy_model_image_dict[g1].in_2d
                + inversion.mapped_reconstructed_image.in_2d,
                1.0e-4,
            )

        def test___all_fit_quantities__include_hyper_methods(self, masked_imaging_7x7):

            hyper_image_sky = ag.hyper_data.HyperImageSky(sky_scale=1.0)

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            image = hyper_image_sky.hyper_image_from_image(
                image=masked_imaging_7x7.image
            )

            hyper_noise_map_background = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )

            galaxy_light = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                hyper_galaxy=ag.HyperGalaxy(
                    contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
                ),
                hyper_model_image=ag.Array.ones(shape_2d=(3, 3)),
                hyper_galaxy_image=ag.Array.ones(shape_2d=(3, 3)),
                hyper_minimum_value=0.0,
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[galaxy_light, galaxy_pix])

            fit = ag.FitImaging(
                masked_imaging=masked_imaging_7x7,
                plane=plane,
                hyper_image_sky=hyper_image_sky,
                hyper_background_noise=hyper_background_noise,
            )

            hyper_noise = plane.hyper_noise_map_from_noise_map(
                noise_map=masked_imaging_7x7.noise_map
            )
            hyper_noise_map = hyper_noise_map_background + hyper_noise

            assert hyper_noise_map.in_2d == pytest.approx(fit.noise_map.in_2d, 1.0e-4)

            blurred_profile_image = plane.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            assert blurred_profile_image.in_2d == pytest.approx(
                fit.blurred_profile_image.in_2d
            )

            profile_subtracted_image = image - blurred_profile_image

            assert profile_subtracted_image.in_2d == pytest.approx(
                fit.profile_subtracted_image.in_2d
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                image=profile_subtracted_image,
                noise_map=hyper_noise_map,
                convolver=masked_imaging_7x7.convolver,
                mapper=mapper,
                regularization=reg,
            )

            model_image = blurred_profile_image + inversion.mapped_reconstructed_image

            assert model_image.in_2d == pytest.approx(fit.model_image.in_2d, 1.0e-4)

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=image, model_data=model_image
            )

            assert residual_map.in_2d == pytest.approx(fit.residual_map.in_2d, 1.0e-4)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert normalized_residual_map.in_2d == pytest.approx(
                fit.normalized_residual_map.in_2d, 1.0e-4
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=hyper_noise_map
            )

            assert chi_squared_map.in_2d == pytest.approx(
                fit.chi_squared_map.in_2d, 1.0e-4
            )

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=hyper_noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

        def test___blurred_and_model_images_of_galaxies_and_unmasked_blurred_profile_image_properties(
            self, masked_imaging_7x7
        ):
            galaxy_light = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[galaxy_light, galaxy_pix])

            fit = ag.FitImaging(masked_imaging=masked_imaging_7x7, plane=plane)

            blurred_profile_image = plane.blurred_profile_image_from_grid_and_convolver(
                grid=masked_imaging_7x7.grid,
                convolver=masked_imaging_7x7.convolver,
                blurring_grid=masked_imaging_7x7.blurring_grid,
            )

            profile_subtracted_image = masked_imaging_7x7.image - blurred_profile_image

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_imaging_7x7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionImaging.from_data_mapper_and_regularization(
                image=profile_subtracted_image,
                noise_map=masked_imaging_7x7.noise_map,
                convolver=masked_imaging_7x7.convolver,
                mapper=mapper,
                regularization=reg,
            )

            assert blurred_profile_image.in_2d == pytest.approx(
                fit.model_images_of_galaxies[0].in_2d, 1.0e-4
            )
            assert inversion.mapped_reconstructed_image.in_2d == pytest.approx(
                fit.model_images_of_galaxies[1].in_2d, 1.0e-4
            )


class TestFitInterferometer:
    class TestLikelihood:
        def test__1x2_image__1x2_visibilities__simple_fourier_transform(self):
            # The image plane image generated by the galaxy is [1.0, 1.0]

            # Thus the chi squared is 4.0**2.0 + 3.0**2.0 = 25.0

            uv_wavelengths = np.array([[0.0, 0.0]])

            interferometer = ag.Interferometer(
                visibilities=ag.Visibilities.full(fill_value=5.0, shape_1d=(1,)),
                noise_map=ag.Visibilities.ones(shape_1d=(1,)),
                uv_wavelengths=uv_wavelengths,
                primary_beam=None,
            )

            interferometer.visibilities[0, 1] = 4.0

            visibilities_mask = np.full(fill_value=False, shape=(1, 2))

            real_space_mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True],
                        [True, False, False, True],
                        [True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_interferometer = ag.MaskedInterferometer(
                interferometer=interferometer,
                visibilities_mask=visibilities_mask,
                real_space_mask=real_space_mask,
                transformer_class=ag.TransformerDFT,
            )

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer, plane=plane
            )

            assert (fit.visibilities_mask == np.array([False, False])).all()

            assert (fit.visibilities.in_1d == np.array([[5.0, 4.0]])).all()
            assert (fit.noise_map.in_1d == np.array([[1.0, 1.0]])).all()
            assert (fit.model_visibilities.in_1d == np.array([2.0, 0.0])).all()
            assert (fit.residual_map.in_1d == np.array([3.0, 4.0])).all()
            assert (fit.normalized_residual_map.in_1d == np.array([3.0, 4.0])).all()
            assert (fit.chi_squared_map.in_1d == np.array([9.0, 16.0])).all()

            assert fit.chi_squared == 25.0
            assert fit.reduced_chi_squared == 25.0 / 2.0
            assert fit.noise_normalization == (2.0 * np.log(2 * np.pi * 1.0 ** 2.0))
            assert fit.log_likelihood == -0.5 * (
                25.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0)
            )

        def test__hyper_background_changes_background_sky__reflected_in_likelihood(
            self
        ):

            uv_wavelengths = np.array([[1.0, 0.0], [1.0, 1.0], [2.0, 2.0]])

            interferometer = ag.Interferometer(
                visibilities=ag.Visibilities.full(fill_value=5.0, shape_1d=(3,)),
                noise_map=ag.Visibilities.full(fill_value=2.0, shape_1d=(3,)),
                uv_wavelengths=uv_wavelengths,
                primary_beam=None,
            )

            visibilities_mask = np.full(fill_value=False, shape=(1, 2))

            real_space_mask = ag.Mask.manual(
                mask_2d=np.array(
                    [
                        [True, True, True, True, True],
                        [True, False, False, False, True],
                        [True, True, True, True, True],
                    ]
                ),
                pixel_scales=1.0,
                sub_size=1,
            )

            masked_interferometer = ag.MaskedInterferometer(
                interferometer=interferometer,
                visibilities_mask=visibilities_mask,
                real_space_mask=real_space_mask,
            )

            # Setup as a ray trace instance, using a light profile for the lens

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2)
            )
            plane = ag.Plane(galaxies=[g0])

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer,
                plane=plane,
                hyper_background_noise=hyper_background_noise,
            )

            assert (
                fit.visibilities.in_1d == np.full(fill_value=5.0, shape=(3, 2))
            ).all()

            assert (fit.noise_map.in_1d == np.full(fill_value=3.0, shape=(3, 2))).all()

    class TestCompareToManualProfilesOnly:
        def test___all_fit_quantities__no_hyper_methods(self, masked_interferometer_7):
            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )

            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            assert masked_interferometer_7.noise_map == pytest.approx(fit.noise_map)

            model_visibilities = plane.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            assert model_visibilities == pytest.approx(fit.model_visibilities, 1e-4)

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_interferometer_7.visibilities, model_data=model_visibilities
            )

            assert residual_map == pytest.approx(fit.residual_map, 1e-4)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert normalized_residual_map == pytest.approx(
                fit.normalized_residual_map, 1e-4
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert chi_squared_map == pytest.approx(fit.chi_squared_map, 1e-4)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=fit.chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)
            assert log_likelihood == fit.figure_of_merit

        def test___fit_galaxy_model_image_dict__corresponds_to_profile_galaxy_images(
            self, masked_interferometer_7
        ):
            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )
            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            g0_profile_image = g0.profile_image_from_grid(
                grid=masked_interferometer_7.grid
            )

            g1_profile_image = g1.profile_image_from_grid(
                grid=masked_interferometer_7.grid
            )

            assert fit.galaxy_model_image_dict[g0].in_1d == pytest.approx(
                g0_profile_image, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[g1].in_1d == pytest.approx(
                g1_profile_image, 1.0e-4
            )

        def test___fit_galaxy_visibilities_dict__corresponds_to_galaxy_visibilities(
            self, masked_interferometer_7
        ):
            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )
            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            g0_profile_visibilities = g0.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            g1_profile_visibilities = g1.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            assert fit.galaxy_model_visibilities_dict[g0].in_1d == pytest.approx(
                g0_profile_visibilities, 1.0e-4
            )
            assert fit.galaxy_model_visibilities_dict[g1].in_1d == pytest.approx(
                g1_profile_visibilities, 1.0e-4
            )

            assert fit.model_visibilities.in_1d == pytest.approx(
                fit.galaxy_model_visibilities_dict[g0].in_1d
                + fit.galaxy_model_visibilities_dict[g1].in_1d,
                1.0e-4,
            )

        def test___all_fit_quantities__hyper_background_noise(
            self, masked_interferometer_7
        ):

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            hyper_noise_map = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            g0 = ag.Galaxy(
                redshift=0.5,
                light_profile=ag.lp.EllipticalSersic(intensity=1.0),
                mass_profile=ag.mp.SphericalIsothermal(einstein_radius=1.0),
            )

            g1 = ag.Galaxy(
                redshift=1.0, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7,
                plane=plane,
                hyper_background_noise=hyper_background_noise,
            )

            assert hyper_noise_map.in_1d == pytest.approx(fit.noise_map.in_1d)

    class TestCompareToManualInversionOnly:
        def test___all_fit_quantities__no_hyper_methods(self, masked_interferometer_7):

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=0.01)

            g0 = ag.Galaxy(redshift=0.5, pixelization=pix, regularization=reg)

            plane = ag.Plane(galaxies=[ag.Galaxy(redshift=0.5), g0])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, sparse_grid=None
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                visibilities=masked_interferometer_7.visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
            )

            assert inversion.mapped_reconstructed_visibilities == pytest.approx(
                fit.model_visibilities, 1.0e-4
            )

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_interferometer_7.visibilities,
                model_data=inversion.mapped_reconstructed_visibilities,
            )

            assert residual_map.in_1d == pytest.approx(fit.residual_map.in_1d, 1.0e-4)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert normalized_residual_map.in_1d == pytest.approx(
                fit.normalized_residual_map.in_1d, 1.0e-4
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert chi_squared_map.in_1d == pytest.approx(
                fit.chi_squared_map.in_1d, 1.0e-4
            )

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

            mapped_reconstructed_image = ag.util.inversion.mapped_reconstructed_data_from_mapping_matrix_and_reconstruction(
                mapping_matrix=fit.inversion.mapper.mapping_matrix,
                reconstruction=fit.inversion.reconstruction,
            )

            assert (
                fit.inversion.mapped_reconstructed_image.in_1d
                == mapped_reconstructed_image
            ).all()

        def test___fit_galaxy_model_image_dict__profile_images_and_inversion_mapped_reconstructed_image(
            self, masked_interferometer_7
        ):
            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(redshift=0.5)
            g1 = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, sparse_grid=None
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                visibilities=masked_interferometer_7.visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
            )

            assert (fit.galaxy_model_image_dict[g0].in_2d == np.zeros((7, 7))).all()

            assert fit.galaxy_model_image_dict[g1].in_1d == pytest.approx(
                inversion.mapped_reconstructed_image.in_1d, 1.0e-4
            )

        def test___fit_galaxy_model_visibilities_dict__has_inversion_mapped_reconstructed_visibilities(
            self, masked_interferometer_7
        ):
            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)

            g0 = ag.Galaxy(redshift=0.5)
            g1 = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, sparse_grid=None
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                mapper=mapper,
                regularization=reg,
                visibilities=masked_interferometer_7.visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
            )

            assert (fit.galaxy_model_visibilities_dict[g0] == np.zeros((7, 2))).all()

            assert fit.galaxy_model_visibilities_dict[g1].in_1d == pytest.approx(
                inversion.mapped_reconstructed_visibilities.in_1d, 1.0e-4
            )

            assert fit.model_visibilities.in_1d == pytest.approx(
                fit.galaxy_model_visibilities_dict[g1].in_1d, 1.0e-4
            )

        def test___all_fit_quantities__hyper_background_noise(
            self, masked_interferometer_7
        ):

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            hyper_noise_map = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=0.01)

            g0 = ag.Galaxy(redshift=0.5, pixelization=pix, regularization=reg)

            plane = ag.Plane(galaxies=[ag.Galaxy(redshift=0.5), g0])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7,
                plane=plane,
                hyper_background_noise=hyper_background_noise,
            )

            assert hyper_noise_map.in_1d == pytest.approx(
                fit.inversion.noise_map, 1.0e-4
            )

            assert hyper_noise_map.in_1d == pytest.approx(fit.noise_map.in_1d)

    class TestCompareToManualProfilesAndInversion:
        def test___all_fit_quantities__no_hyper_methods(self, masked_interferometer_7):
            galaxy_light = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[galaxy_light, galaxy_pix])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            profile_visibilities = plane.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            assert profile_visibilities.in_1d == pytest.approx(
                fit.profile_visibilities.in_1d
            )

            profile_subtracted_visibilities = (
                masked_interferometer_7.visibilities - profile_visibilities
            )

            assert profile_subtracted_visibilities.in_1d == pytest.approx(
                fit.profile_subtracted_visibilities.in_1d
            )

            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                visibilities=profile_subtracted_visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
                mapper=mapper,
                regularization=reg,
            )

            model_visibilities = (
                profile_visibilities + inversion.mapped_reconstructed_visibilities
            )

            assert model_visibilities.in_1d == pytest.approx(
                fit.model_visibilities.in_1d
            )

            residual_map = ag.util.fit.residual_map_from_data_and_model_data(
                data=masked_interferometer_7.visibilities, model_data=model_visibilities
            )

            assert residual_map.in_1d == pytest.approx(fit.residual_map.in_1d)

            normalized_residual_map = ag.util.fit.normalized_residual_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert normalized_residual_map.in_1d == pytest.approx(
                fit.normalized_residual_map.in_1d
            )

            chi_squared_map = ag.util.fit.chi_squared_map_from_residual_map_and_noise_map(
                residual_map=residual_map, noise_map=masked_interferometer_7.noise_map
            )

            assert chi_squared_map.in_1d == pytest.approx(fit.chi_squared_map.in_1d)

            chi_squared = ag.util.fit.chi_squared_from_chi_squared_map(
                chi_squared_map=chi_squared_map
            )

            noise_normalization = ag.util.fit.noise_normalization_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            log_likelihood = ag.util.fit.likelihood_from_chi_squared_and_noise_normalization(
                chi_squared=chi_squared, noise_normalization=noise_normalization
            )

            assert log_likelihood == pytest.approx(fit.log_likelihood, 1e-4)

            log_likelihood_with_regularization = ag.util.fit.likelihood_with_regularization_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                noise_normalization=noise_normalization,
            )

            assert log_likelihood_with_regularization == pytest.approx(
                fit.log_likelihood_with_regularization, 1e-4
            )

            log_evidence = ag.util.fit.evidence_from_inversion_terms(
                chi_squared=chi_squared,
                regularization_term=inversion.regularization_term,
                log_curvature_regularization_term=inversion.log_det_curvature_reg_matrix_term,
                log_regularization_term=inversion.log_det_regularization_matrix_term,
                noise_normalization=noise_normalization,
            )

            assert log_evidence == fit.log_evidence
            assert log_evidence == fit.figure_of_merit

            mapped_reconstructed_image = ag.util.inversion.mapped_reconstructed_data_from_mapping_matrix_and_reconstruction(
                mapping_matrix=fit.inversion.mapper.mapping_matrix,
                reconstruction=fit.inversion.reconstruction,
            )

            assert (
                fit.inversion.mapped_reconstructed_image.in_1d
                == mapped_reconstructed_image
            ).all()

        def test___fit_galaxy_model_visibilities_dict__has_profile_image_and_inversion_mapped_reconstructed_image(
            self, masked_interferometer_7
        ):

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )
            g1 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=2.0)
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1, galaxy_pix])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            g0_visibilities = g0.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            g1_visibilities = g1.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            profile_visibilities = g0_visibilities + g1_visibilities

            profile_subtracted_visibilities = (
                masked_interferometer_7.visibilities - profile_visibilities
            )
            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                visibilities=profile_subtracted_visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
                mapper=mapper,
                regularization=reg,
            )

            g0_image = g0.profile_image_from_grid(grid=masked_interferometer_7.grid)

            g1_image = g1.profile_image_from_grid(grid=masked_interferometer_7.grid)

            assert fit.galaxy_model_image_dict[g0].in_1d == pytest.approx(
                g0_image.in_1d, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[g1].in_1d == pytest.approx(
                g1_image.in_1d, 1.0e-4
            )
            assert fit.galaxy_model_image_dict[galaxy_pix].in_1d == pytest.approx(
                inversion.mapped_reconstructed_image.in_1d, 1.0e-4
            )

        def test___fit_galaxy_model_visibilities_dict__has_profile_visibilitiess_and_inversion_mapped_reconstructed_visibilities(
            self, masked_interferometer_7
        ):

            g0 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )
            g1 = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=2.0)
            )
            g2 = ag.Galaxy(redshift=0.5)

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[g0, g1, g2, galaxy_pix])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7, plane=plane
            )

            g0_visibilities = g0.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            g1_visibilities = g1.profile_visibilities_from_grid_and_transformer(
                grid=masked_interferometer_7.grid,
                transformer=masked_interferometer_7.transformer,
            )

            profile_visibilities = g0_visibilities + g1_visibilities

            profile_subtracted_visibilities = (
                masked_interferometer_7.visibilities - profile_visibilities
            )
            mapper = pix.mapper_from_grid_and_sparse_grid(
                grid=masked_interferometer_7.grid, inversion_uses_border=False
            )

            inversion = inversions.InversionInterferometer.from_data_mapper_and_regularization(
                visibilities=profile_subtracted_visibilities,
                noise_map=masked_interferometer_7.noise_map,
                transformer=masked_interferometer_7.transformer,
                mapper=mapper,
                regularization=reg,
            )

            assert (fit.galaxy_model_visibilities_dict[g2] == np.zeros((7, 2))).all()

            assert fit.galaxy_model_visibilities_dict[g0].in_1d == pytest.approx(
                g0_visibilities.in_1d, 1.0e-4
            )
            assert fit.galaxy_model_visibilities_dict[g1].in_1d == pytest.approx(
                g1_visibilities.in_1d, 1.0e-4
            )
            assert fit.galaxy_model_visibilities_dict[
                galaxy_pix
            ].in_1d == pytest.approx(
                inversion.mapped_reconstructed_visibilities.in_1d, 1.0e-4
            )

            assert fit.model_visibilities.in_1d == pytest.approx(
                fit.galaxy_model_visibilities_dict[g0].in_1d
                + fit.galaxy_model_visibilities_dict[g1].in_1d
                + inversion.mapped_reconstructed_visibilities.in_1d,
                1.0e-4,
            )

        def test___all_fit_quantities__hyper_background_noise(
            self, masked_interferometer_7
        ):

            hyper_background_noise = ag.hyper_data.HyperBackgroundNoise(noise_scale=1.0)

            hyper_noise_map = hyper_background_noise.hyper_noise_map_from_noise_map(
                noise_map=masked_interferometer_7.noise_map
            )

            galaxy_light = ag.Galaxy(
                redshift=0.5, light_profile=ag.lp.EllipticalSersic(intensity=1.0)
            )

            pix = ag.pix.Rectangular(shape=(3, 3))
            reg = ag.reg.Constant(coefficient=1.0)
            galaxy_pix = ag.Galaxy(redshift=1.0, pixelization=pix, regularization=reg)

            plane = ag.Plane(redshift=0.75, galaxies=[galaxy_light, galaxy_pix])

            fit = ag.FitInterferometer(
                masked_interferometer=masked_interferometer_7,
                plane=plane,
                hyper_background_noise=hyper_background_noise,
            )

            assert hyper_noise_map.in_1d == pytest.approx(
                fit.inversion.noise_map, 1.0e-4
            )

            assert hyper_noise_map.in_1d == pytest.approx(fit.noise_map.in_1d)
