import autolens as al
import numpy as np
import pytest

import autofit as af
from autolens.lens.lens_fit.lens_imaging_fit import (
    likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization,
)
from autolens.lens.lens_fit.lens_imaging_fit import evidence_from_inversion_terms
from test.unit.mock.model.mock_profiles import MockLightProfile


class TestInversionEvidence:
    def test__simple_values(self):

        likelihood_with_regularization_terms = likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization(
            chi_squared=3.0, regularization_term=6.0, noise_normalization=2.0
        )

        assert likelihood_with_regularization_terms == -0.5 * (3.0 + 6.0 + 2.0)

        evidences = evidence_from_inversion_terms(
            chi_squared=3.0,
            regularization_term=6.0,
            log_curvature_regularization_term=9.0,
            log_regularization_term=10.0,
            noise_normalization=30.0,
        )

        assert evidences == -0.5 * (3.0 + 6.0 + 9.0 - 10.0 + 30.0)


class TestFitProperties:
    def test__total_inversions(self, lens_imaging_data_7x7):

        g0 = al.Galaxy(redshift=0.5)

        g1 = al.Galaxy(redshift=1.0)

        g2 = al.Galaxy(redshift=2.0)

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1, g2])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        assert fit.total_inversions == 0

        g2 = al.Galaxy(
            redshift=2.0,
            pixelization=al.pixelizations.Rectangular(),
            regularization=al.regularization.Constant(),
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1, g2])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        assert fit.total_inversions == 1

        g0 = al.Galaxy(
            redshift=0.5,
            pixelization=al.pixelizations.Rectangular(),
            regularization=al.regularization.Constant(),
        )

        g1 = al.Galaxy(
            redshift=1.0,
            pixelization=al.pixelizations.Rectangular(),
            regularization=al.regularization.Constant(),
        )

        g2 = al.Galaxy(
            redshift=2.0,
            pixelization=al.pixelizations.Rectangular(),
            regularization=al.regularization.Constant(),
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1, g2])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        assert fit.total_inversions == 3


class TestLikelihood:
    def test__1x2_image__no_psf_blurring__tracing_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 = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(imaging_data=imaging_data, mask=mask)

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

        g0 = al.Galaxy(redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2))
        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

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

        assert (fit._data == np.array([5.0, 4.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([1.0, 1.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 1.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([4.0, 3.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([4.0, 3.0])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([16.0, 9.0])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.likelihood == -0.5 * (25.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0))

    def test__1x2_image__include_psf_blurring__tracing_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 = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 3.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(imaging_data=imaging_data, mask=mask)

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

        g0 = al.Galaxy(redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2))
        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

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

        assert (fit._data == np.array([5.0, 4.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([1.0, 1.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 4.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([4.0, 0.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([4.0, 0.0])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([16.0, 0.0])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.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 = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 3.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(imaging_data=imaging_data, mask=mask)

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

        g0 = al.Galaxy(
            redshift=0.5,
            light_profile=MockLightProfile(value=1.0, size=2),
            hyper_galaxy=al.HyperGalaxy(
                contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
            ),
            hyper_model_image_1d=np.ones(2),
            hyper_galaxy_image_1d=np.ones(2),
            hyper_minimum_value=0.0,
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

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

        assert (fit._data == np.array([5.0, 4.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([2.0, 2.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 4.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([4.0, 0.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([2.0, 0.0])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([4.0, 0.0])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.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 = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(imaging_data=imaging_data, mask=mask)

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

        g0 = al.Galaxy(redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2))
        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        hyper_image_sky = al.HyperImageSky(sky_scale=1.0)

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_image_sky=hyper_image_sky,
        )

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

        assert (fit._data == np.array([6.0, 5.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([1.0, 1.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 1.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([5.0, 4.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([5.0, 4.0])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([25.0, 16.0])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.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 = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(imaging_data=imaging_data, mask=mask)

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

        g0 = al.Galaxy(redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2))
        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        hyper_background_noise = al.HyperBackgroundNoise(noise_scale=1.0)

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_background_noise=hyper_background_noise,
        )

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

        assert (fit._data == np.array([5.0, 4.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([2.0, 2.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 1.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([4.0, 3.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([2.0, 1.5])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([4.0, 2.25])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.likelihood == -0.5 * (6.25 + 2.0 * np.log(2 * np.pi * 2.0 ** 2.0))

    def test__hyper_noise_map_max_changes_noise_map__reflected_in_likelihood(self):

        psf = al.PSF(
            array=(np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]])),
            pixel_scale=1.0,
        )

        imaging_data = al.ImagingData(
            5.0 * np.ones((3, 4)), pixel_scale=1.0, psf=psf, noise_map=np.ones((3, 4))
        )
        imaging_data.image[1, 2] = 4.0

        mask = al.Mask(
            array=np.array(
                [
                    [True, True, True, True],
                    [True, False, False, True],
                    [True, True, True, True],
                ]
            ),
            pixel_scale=1.0,
            sub_size=1,
        )

        lens_imaging_data_7x7 = al.LensImagingData(
            imaging_data=imaging_data, mask=mask, hyper_noise_map_max=1.0
        )

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

        g0 = al.Galaxy(redshift=0.5, light_profile=MockLightProfile(value=1.0, size=2))
        tracer = al.Tracer.from_galaxies(galaxies=[g0])

        hyper_background_noise = al.HyperBackgroundNoise(noise_scale=1.0)

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_background_noise=hyper_background_noise,
        )

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

        assert (fit._data == np.array([5.0, 4.0])).all()
        assert (
            fit.image(return_in_2d=True, return_masked=True)
            == 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 == np.array([1.0, 1.0])).all()
        assert (
            fit.noise_map(return_in_2d=True, return_masked=True)
            == 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_data == np.array([1.0, 1.0])).all()
        assert (
            fit.model_image(return_in_2d=True)
            == 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 == np.array([4.0, 3.0])).all()
        assert (
            fit.residual_map(return_in_2d=True)
            == 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 == np.array([4.0, 3.0])).all()
        assert (
            fit.normalized_residual_map(return_in_2d=True)
            == 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 == np.array([16.0, 9.0])).all()
        assert (
            fit.chi_squared_map(return_in_2d=True)
            == 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.likelihood == -0.5 * (25.0 + 2.0 * np.log(2 * np.pi * 1.0 ** 2.0))


class TestCompareToManualProfilesOnly:
    def test___all_lens_fit_quantities__no_hyper_methods(self, lens_imaging_data_7x7):

        g0 = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
            mass_profile=al.mass_profiles.SphericalIsothermal(einstein_radius=1.0),
        )

        g1 = al.Galaxy(
            redshift=1.0,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        assert lens_imaging_data_7x7.noise_map(return_in_2d=True) == pytest.approx(
            fit.noise_map(return_in_2d=True, return_masked=True)
        )

        model_image_1d = tracer.blurred_profile_image_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=False,
        )
        model_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=model_image_1d
        )

        assert model_image_1d == pytest.approx(fit._model_data, 1e-4)
        assert model_image_2d == pytest.approx(fit.model_image(return_in_2d=True))

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=lens_imaging_data_7x7._image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=model_image_1d,
        )
        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )

        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            noise_map=lens_imaging_data_7x7.noise_map(return_in_2d=True),
            mask=lens_imaging_data_7x7.mask,
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

    def test___lens_fit_galaxy_model_image_dict__corresponds_to_blurred_galaxy_images(
        self, lens_imaging_data_7x7
    ):
        g0 = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
            mass_profile=al.mass_profiles.SphericalIsothermal(einstein_radius=1.0),
        )
        g1 = al.Galaxy(
            redshift=1.0,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )
        g2 = al.Galaxy(redshift=1.0)

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1, g2])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        traced_grids_of_planes = tracer.traced_grids_of_planes_from_grid(
            grid=lens_imaging_data_7x7.grid, return_in_2d=False
        )
        traced_blurring_grids_of_planes = tracer.traced_grids_of_planes_from_grid(
            grid=lens_imaging_data_7x7.blurring_grid, return_in_2d=False
        )

        g0_image_1d = g0.profile_image_from_grid(
            grid=traced_grids_of_planes[0], return_in_2d=False, return_binned=True
        )
        g0_blurring_image_1d = g0.profile_image_from_grid(
            grid=traced_blurring_grids_of_planes[0],
            return_in_2d=False,
            return_binned=True,
        )

        g0_blurred_image_1d = lens_imaging_data_7x7.convolver.convolve_image(
            image_array=g0_image_1d, blurring_array=g0_blurring_image_1d
        )

        g1_image_1d = g1.profile_image_from_grid(
            grid=traced_grids_of_planes[1], return_in_2d=False, return_binned=True
        )
        g1_blurring_image_1d = g1.profile_image_from_grid(
            grid=traced_blurring_grids_of_planes[1],
            return_in_2d=False,
            return_binned=True,
        )

        g1_blurred_image_1d = lens_imaging_data_7x7.convolver.convolve_image(
            image_array=g1_image_1d, blurring_array=g1_blurring_image_1d
        )

        assert fit.galaxy_model_image_1d_dict[g0] == pytest.approx(
            g0_blurred_image_1d, 1.0e-4
        )
        assert fit.galaxy_model_image_1d_dict[g1] == pytest.approx(
            g1_blurred_image_1d, 1.0e-4
        )
        assert (fit.galaxy_model_image_1d_dict[g2] == np.zeros(9)).all()

        assert fit._model_data == pytest.approx(
            fit.galaxy_model_image_1d_dict[g0] + fit.galaxy_model_image_1d_dict[g1],
            1.0e-4,
        )

        g0_blurred_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=g0_blurred_image_1d
        )
        g1_blurred_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=g1_blurred_image_1d
        )

        assert fit.galaxy_model_image_2d_dict[g0] == pytest.approx(
            g0_blurred_image_2d, 1.0e-4
        )
        assert fit.galaxy_model_image_2d_dict[g1] == pytest.approx(
            g1_blurred_image_2d, 1.0e-4
        )

        assert fit.model_image(return_in_2d=True) == pytest.approx(
            fit.galaxy_model_image_2d_dict[g0] + fit.galaxy_model_image_2d_dict[g1],
            1.0e-4,
        )

    def test___all_lens_fit_quantities__including_hyper_methods(
        self, lens_imaging_data_7x7
    ):

        hyper_noise_map_max = 0.2
        lens_imaging_data_7x7.hyper_noise_map_max = hyper_noise_map_max

        hyper_image_sky = al.HyperImageSky(sky_scale=1.0)

        hyper_background_noise = al.HyperBackgroundNoise(noise_scale=1.0)

        image_1d = hyper_image_sky.image_scaled_sky_from_image(
            image=lens_imaging_data_7x7._image_1d
        )

        hyper_noise_map_background_1d = hyper_background_noise.noise_map_scaled_noise_from_noise_map(
            noise_map=lens_imaging_data_7x7._noise_map_1d
        )

        g0 = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
            mass_profile=al.mass_profiles.SphericalIsothermal(einstein_radius=1.0),
            hyper_galaxy=al.HyperGalaxy(
                contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
            ),
            hyper_model_image_1d=np.ones(9),
            hyper_galaxy_image_1d=np.ones(9),
            hyper_minimum_value=0.0,
        )
        g1 = al.Galaxy(
            redshift=1.0,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_image_sky=hyper_image_sky,
            hyper_background_noise=hyper_background_noise,
        )

        hyper_noise_1d = tracer.hyper_noise_map_1d_from_noise_map_1d(
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d
        )

        hyper_noise_map_1d = hyper_noise_map_background_1d + hyper_noise_1d

        hyper_noise_map_1d[
            hyper_noise_map_1d > hyper_noise_map_max
        ] = hyper_noise_map_max

        hyper_noise_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=hyper_noise_map_1d
        )

        assert hyper_noise_map_1d == pytest.approx(fit._noise_map, 1e-4)
        assert hyper_noise_map_2d == pytest.approx(
            fit.noise_map(return_in_2d=True, return_masked=True)
        )

        model_image_1d = tracer.blurred_profile_image_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=False,
        )

        model_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=model_image_1d
        )

        assert model_image_1d == pytest.approx(fit._model_data, 1e-4)
        assert model_image_2d == pytest.approx(fit.model_image(return_in_2d=True))

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=model_image_1d,
        )
        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )

        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            noise_map=hyper_noise_map_2d, mask=lens_imaging_data_7x7.mask
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

    def test___blurred_and_model_images_of_planes_and_unmasked_blurred_profile_image_properties(
        self, lens_imaging_data_7x7
    ):

        g0 = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
            mass_profile=al.mass_profiles.SphericalIsothermal(einstein_radius=1.0),
        )

        g1 = al.Galaxy(
            redshift=1.0,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        blurred_profile_image_2d_of_planes = tracer.blurred_profile_images_of_planes_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=True,
        )

        model_images_of_planes = fit.model_images_of_planes(return_in_2d=True)

        assert blurred_profile_image_2d_of_planes[0] == pytest.approx(
            model_images_of_planes[0], 1.0e-4
        )
        assert blurred_profile_image_2d_of_planes[1] == pytest.approx(
            model_images_of_planes[1], 1.0e-4
        )

        unmasked_blurred_profile_image = tracer.unmasked_blurred_profile_image_from_grid_and_psf(
            grid=lens_imaging_data_7x7.grid, psf=lens_imaging_data_7x7.psf
        )

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

        unmasked_blurred_profile_image_of_planes = tracer.unmasked_blurred_profile_image_of_planes_from_grid_and_psf(
            grid=lens_imaging_data_7x7.grid, psf=lens_imaging_data_7x7.psf
        )

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

        unmasked_blurred_profile_image_of_galaxies = tracer.unmasked_blurred_profile_image_of_planes_and_galaxies_from_grid_and_psf(
            grid=lens_imaging_data_7x7.grid, psf=lens_imaging_data_7x7.psf
        )

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


class TestCompareToManualInversionOnly:
    def test___all_lens_fit_quantities__no_hyper_methods(self, lens_imaging_data_7x7):

        pix = al.pixelizations.Rectangular(shape=(3, 3))
        reg = al.regularization.Constant(coefficient=1.0)

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

        tracer = al.Tracer.from_galaxies(galaxies=[al.Galaxy(redshift=0.5), g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, pixelization_grid=None
        )
        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            mapper=mapper,
            regularization=reg,
            image_1d=lens_imaging_data_7x7._image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
        )

        assert inversion.reconstructed_data_1d == pytest.approx(fit._model_data, 1e-4)
        assert inversion.reconstructed_data_2d == fit.model_image(return_in_2d=True)

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=lens_imaging_data_7x7._image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=inversion.reconstructed_data_1d,
        )
        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )
        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            mask=lens_imaging_data_7x7.mask,
            noise_map=lens_imaging_data_7x7.noise_map(return_in_2d=True),
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

        likelihood_with_regularization = likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization(
            chi_squared=chi_squared,
            regularization_term=inversion.regularization_term,
            noise_normalization=noise_normalization,
        )

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

        evidence = 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 evidence == fit.evidence
        assert evidence == fit.figure_of_merit

    def test___lens_fit_galaxy_model_image_dict__has_inversion_reconstructed_data(
        self, lens_imaging_data_7x7
    ):
        pix = al.pixelizations.Rectangular(shape=(3, 3))
        reg = al.regularization.Constant(coefficient=1.0)

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

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, pixelization_grid=None
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            mapper=mapper,
            regularization=reg,
            image_1d=lens_imaging_data_7x7._image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
        )

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

        assert fit.galaxy_model_image_1d_dict[g1] == pytest.approx(
            inversion.reconstructed_data_1d, 1.0e-4
        )

        assert fit._model_data == pytest.approx(
            fit.galaxy_model_image_1d_dict[g1], 1.0e-4
        )

        assert fit.galaxy_model_image_2d_dict[g1] == pytest.approx(
            inversion.reconstructed_data_2d, 1.0e-4
        )

        assert fit.model_image(return_in_2d=True) == pytest.approx(
            fit.galaxy_model_image_2d_dict[g1], 1.0e-4
        )

    def test___all_lens_fit_quantities__include_hyper_methods(
        self, lens_imaging_data_7x7
    ):

        hyper_noise_map_max = 0.2
        lens_imaging_data_7x7.hyper_noise_map_max = hyper_noise_map_max

        hyper_image_sky = al.HyperImageSky(sky_scale=1.0)

        hyper_background_noise = al.HyperBackgroundNoise(noise_scale=1.0)

        image_1d = hyper_image_sky.image_scaled_sky_from_image(
            image=lens_imaging_data_7x7._image_1d
        )

        hyper_noise_map_background_1d = hyper_background_noise.noise_map_scaled_noise_from_noise_map(
            noise_map=lens_imaging_data_7x7._noise_map_1d
        )

        pix = al.pixelizations.Rectangular(shape=(3, 3))
        reg = al.regularization.Constant(coefficient=1.0)

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

        tracer = al.Tracer.from_galaxies(galaxies=[al.Galaxy(redshift=0.5), g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_image_sky=hyper_image_sky,
            hyper_background_noise=hyper_background_noise,
        )

        hyper_noise_1d = tracer.hyper_noise_map_1d_from_noise_map_1d(
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d
        )
        hyper_noise_map_1d = hyper_noise_map_background_1d + hyper_noise_1d
        hyper_noise_map_1d[
            hyper_noise_map_1d > hyper_noise_map_max
        ] = hyper_noise_map_max

        hyper_noise_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=hyper_noise_map_1d
        )
        assert hyper_noise_map_1d == pytest.approx(fit._noise_map, 1e-4)
        assert hyper_noise_map_2d == pytest.approx(
            fit.noise_map(return_in_2d=True, return_masked=True)
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )
        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            mapper=mapper,
            regularization=reg,
            image_1d=image_1d,
            noise_map_1d=hyper_noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
        )

        assert inversion.reconstructed_data_1d == pytest.approx(fit._model_data, 1e-4)
        assert inversion.reconstructed_data_2d == fit.model_image(return_in_2d=True)

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=inversion.reconstructed_data_1d,
        )
        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )
        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            mask=lens_imaging_data_7x7.mask, noise_map=hyper_noise_map_2d
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

        likelihood_with_regularization = likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization(
            chi_squared=chi_squared,
            regularization_term=inversion.regularization_term,
            noise_normalization=noise_normalization,
        )

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

        evidence = 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 evidence == fit.evidence
        assert evidence == fit.figure_of_merit

    def test___blurred_and_model_images_of_planes_and_unmasked_blurred_profile_image_properties(
        self, lens_imaging_data_7x7
    ):

        pix = al.pixelizations.Rectangular(shape=(3, 3))
        reg = al.regularization.Constant(coefficient=1.0)

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

        tracer = al.Tracer.from_galaxies(galaxies=[al.Galaxy(redshift=0.5), g0])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            mapper=mapper,
            regularization=reg,
            image_1d=lens_imaging_data_7x7._image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
        )

        model_images_of_planes = fit.model_images_of_planes(return_in_2d=True)

        assert (model_images_of_planes[0] == np.zeros((7, 7))).all()
        assert inversion.reconstructed_data_2d == pytest.approx(
            model_images_of_planes[1], 1.0e-4
        )


class TestCompareToManualProfilesAndInversion:
    def test___all_lens_fit_quantities__no_hyper_methods(self, lens_imaging_data_7x7):
        galaxy_light = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )

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

        tracer = al.Tracer.from_galaxies(galaxies=[galaxy_light, galaxy_pix])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        blurred_profile_image_1d = tracer.blurred_profile_image_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=False,
        )

        blurred_profile_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=blurred_profile_image_1d
        )

        assert blurred_profile_image_1d == pytest.approx(
            fit.blurred_profile_image(return_in_2d=False), 1e-4
        )
        assert blurred_profile_image_2d == pytest.approx(
            fit.blurred_profile_image(return_in_2d=True)
        )

        profile_subtracted_image_1d = (
            lens_imaging_data_7x7._image_1d - blurred_profile_image_1d
        )
        profile_subtracted_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=profile_subtracted_image_1d
        )

        assert profile_subtracted_image_1d == pytest.approx(
            fit.profile_subtracted_image(return_in_2d=False)
        )
        assert profile_subtracted_image_2d == pytest.approx(
            fit.profile_subtracted_image(return_in_2d=True)
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            image_1d=profile_subtracted_image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
            mapper=mapper,
            regularization=reg,
        )

        model_image_1d = blurred_profile_image_1d + inversion.reconstructed_data_1d
        model_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=model_image_1d
        )

        assert model_image_1d == pytest.approx(fit._model_data, 1e-4)
        assert model_image_2d == pytest.approx(fit.model_image(return_in_2d=True))

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=lens_imaging_data_7x7._image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=model_image_1d,
        )
        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=lens_imaging_data_7x7._noise_map_1d,
        )
        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            mask=lens_imaging_data_7x7.mask,
            noise_map=lens_imaging_data_7x7.noise_map(return_in_2d=True),
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

        likelihood_with_regularization = likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization(
            chi_squared=chi_squared,
            regularization_term=inversion.regularization_term,
            noise_normalization=noise_normalization,
        )

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

        evidence = 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 evidence == fit.evidence
        assert evidence == fit.figure_of_merit

    def test___lens_fit_galaxy_model_image_dict__has_blurred_profile_images_and_inversion_reconstructed_data(
        self, lens_imaging_data_7x7
    ):

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

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

        tracer = al.Tracer.from_galaxies(galaxies=[g0, g1, g2, galaxy_pix])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        traced_grids = tracer.traced_grids_of_planes_from_grid(
            grid=lens_imaging_data_7x7.grid
        )
        traced_blurring_grids = tracer.traced_grids_of_planes_from_grid(
            grid=lens_imaging_data_7x7.blurring_grid
        )

        g0_image_1d = g0.profile_image_from_grid(
            grid=traced_grids[0], return_in_2d=False, return_binned=True
        )
        g0_blurring_image_1d = g0.profile_image_from_grid(
            grid=traced_blurring_grids[0], return_in_2d=False, return_binned=False
        )

        g0_blurred_image_1d = lens_imaging_data_7x7.convolver.convolve_image(
            image_array=g0_image_1d, blurring_array=g0_blurring_image_1d
        )

        g1_image_1d = g1.profile_image_from_grid(
            grid=traced_grids[1], return_in_2d=False, return_binned=True
        )
        g1_blurring_image_1d = g1.profile_image_from_grid(
            grid=traced_blurring_grids[1], return_in_2d=False, return_binned=False
        )

        g1_blurred_image_1d = lens_imaging_data_7x7.convolver.convolve_image(
            image_array=g1_image_1d, blurring_array=g1_blurring_image_1d
        )

        blurred_profile_image_1d = g0_blurred_image_1d + g1_blurred_image_1d

        profile_subtracted_image_1d = (
            lens_imaging_data_7x7._image_1d - blurred_profile_image_1d
        )
        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            image_1d=profile_subtracted_image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
            mapper=mapper,
            regularization=reg,
        )

        assert fit.galaxy_model_image_1d_dict[g0] == pytest.approx(
            g0_blurred_image_1d, 1.0e-4
        )
        assert fit.galaxy_model_image_1d_dict[g1] == pytest.approx(
            g1_blurred_image_1d, 1.0e-4
        )
        assert (fit.galaxy_model_image_1d_dict[g2] == np.zeros(9)).all()
        assert fit.galaxy_model_image_1d_dict[galaxy_pix] == pytest.approx(
            inversion.reconstructed_data_1d, 1.0e-4
        )

        assert fit._model_data == pytest.approx(
            fit.galaxy_model_image_1d_dict[g0]
            + fit.galaxy_model_image_1d_dict[g1]
            + fit.galaxy_model_image_1d_dict[galaxy_pix],
            1.0e-4,
        )

        g0_blurred_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=g0_blurred_image_1d
        )
        g1_blurred_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=g1_blurred_image_1d
        )

        assert fit.galaxy_model_image_2d_dict[g0] == pytest.approx(
            g0_blurred_image_2d, 1.0e-4
        )
        assert fit.galaxy_model_image_2d_dict[g1] == pytest.approx(
            g1_blurred_image_2d, 1.0e-4
        )
        assert fit.galaxy_model_image_2d_dict[galaxy_pix] == pytest.approx(
            inversion.reconstructed_data_2d, 1.0e-4
        )

        assert fit.model_image(return_in_2d=True) == pytest.approx(
            fit.galaxy_model_image_2d_dict[g0]
            + fit.galaxy_model_image_2d_dict[g1]
            + inversion.reconstructed_data_2d,
            1.0e-4,
        )

    def test___all_lens_fit_quantities__include_hyper_methods(
        self, lens_imaging_data_7x7
    ):

        hyper_noise_map_max = 0.2
        lens_imaging_data_7x7.hyper_noise_map_max = hyper_noise_map_max

        hyper_image_sky = al.HyperImageSky(sky_scale=1.0)

        hyper_background_noise = al.HyperBackgroundNoise(noise_scale=1.0)

        image_1d = hyper_image_sky.image_scaled_sky_from_image(
            image=lens_imaging_data_7x7._image_1d
        )

        hyper_noise_map_background_1d = hyper_background_noise.noise_map_scaled_noise_from_noise_map(
            noise_map=lens_imaging_data_7x7._noise_map_1d
        )

        galaxy_light = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
            hyper_galaxy=al.HyperGalaxy(
                contribution_factor=1.0, noise_factor=1.0, noise_power=1.0
            ),
            hyper_model_image_1d=np.ones(9),
            hyper_galaxy_image_1d=np.ones(9),
            hyper_minimum_value=0.0,
        )

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

        tracer = al.Tracer.from_galaxies(galaxies=[galaxy_light, galaxy_pix])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7,
            tracer=tracer,
            hyper_image_sky=hyper_image_sky,
            hyper_background_noise=hyper_background_noise,
        )

        hyper_noise_1d = tracer.hyper_noise_map_1d_from_noise_map_1d(
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d
        )
        hyper_noise_map_1d = hyper_noise_map_background_1d + hyper_noise_1d
        hyper_noise_map_1d[
            hyper_noise_map_1d > hyper_noise_map_max
        ] = hyper_noise_map_max

        hyper_noise_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=hyper_noise_map_1d
        )

        assert hyper_noise_map_1d == pytest.approx(fit._noise_map, 1e-4)
        assert hyper_noise_map_2d == pytest.approx(
            fit.noise_map(return_in_2d=True, return_masked=True)
        )

        blurred_profile_image_1d = tracer.blurred_profile_image_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=False,
        )

        blurred_profile_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=blurred_profile_image_1d
        )

        assert blurred_profile_image_1d == pytest.approx(
            fit.blurred_profile_image(return_in_2d=False), 1e-4
        )
        assert blurred_profile_image_2d == pytest.approx(
            fit.blurred_profile_image(return_in_2d=True)
        )

        profile_subtracted_image_1d = image_1d - blurred_profile_image_1d
        profile_subtracted_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=profile_subtracted_image_1d
        )

        assert profile_subtracted_image_1d == pytest.approx(
            fit.profile_subtracted_image(return_in_2d=False)
        )
        assert profile_subtracted_image_2d == pytest.approx(
            fit.profile_subtracted_image(return_in_2d=True)
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            image_1d=profile_subtracted_image_1d,
            noise_map_1d=hyper_noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
            mapper=mapper,
            regularization=reg,
        )

        model_image_1d = blurred_profile_image_1d + inversion.reconstructed_data_1d
        model_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=model_image_1d
        )

        assert model_image_1d == pytest.approx(fit._model_data, 1e-4)
        assert model_image_2d == pytest.approx(fit.model_image(return_in_2d=True))

        residual_map_1d = af.fit_util.residual_map_from_data_mask_and_model_data(
            data=image_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            model_data=model_image_1d,
        )

        residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=residual_map_1d
        )

        assert residual_map_1d == pytest.approx(fit._residual_map, 1e-4)
        assert residual_map_2d == pytest.approx(fit.residual_map(return_in_2d=True))

        normalized_residual_map_1d = af.fit_util.normalized_residual_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )

        normalized_residual_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=normalized_residual_map_1d
        )

        assert normalized_residual_map_1d == pytest.approx(
            fit._normalized_residual_map, 1e-4
        )
        assert normalized_residual_map_2d == pytest.approx(
            fit.normalized_residual_map(return_in_2d=True)
        )

        chi_squared_map_1d = af.fit_util.chi_squared_map_from_residual_map_noise_map_and_mask(
            residual_map=residual_map_1d,
            mask=lens_imaging_data_7x7._mask_1d,
            noise_map=hyper_noise_map_1d,
        )

        chi_squared_map_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=chi_squared_map_1d
        )

        assert chi_squared_map_1d == pytest.approx(fit._chi_squared_map, 1e-4)
        assert chi_squared_map_2d == pytest.approx(
            fit.chi_squared_map(return_in_2d=True)
        )

        chi_squared = af.fit_util.chi_squared_from_chi_squared_map_and_mask(
            chi_squared_map=chi_squared_map_2d, mask=lens_imaging_data_7x7.mask
        )

        noise_normalization = af.fit_util.noise_normalization_from_noise_map_and_mask(
            mask=lens_imaging_data_7x7.mask, noise_map=hyper_noise_map_2d
        )

        likelihood = af.fit_util.likelihood_from_chi_squared_and_noise_normalization(
            chi_squared=chi_squared, noise_normalization=noise_normalization
        )

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

        likelihood_with_regularization = likelihood_with_regularization_from_chi_squared_regularization_term_and_noise_normalization(
            chi_squared=chi_squared,
            regularization_term=inversion.regularization_term,
            noise_normalization=noise_normalization,
        )

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

        evidence = 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 evidence == fit.evidence
        assert evidence == fit.figure_of_merit

    def test___blurred_and_model_images_of_planes_and_unmasked_blurred_profile_image_properties(
        self, lens_imaging_data_7x7
    ):
        galaxy_light = al.Galaxy(
            redshift=0.5,
            light_profile=al.light_profiles.EllipticalSersic(intensity=1.0),
        )

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

        tracer = al.Tracer.from_galaxies(galaxies=[galaxy_light, galaxy_pix])

        fit = al.LensImagingFit.from_lens_data_and_tracer(
            lens_data=lens_imaging_data_7x7, tracer=tracer
        )

        blurred_profile_image_1d = tracer.blurred_profile_image_from_grid_and_convolver(
            grid=lens_imaging_data_7x7.grid,
            convolver=lens_imaging_data_7x7.convolver,
            blurring_grid=lens_imaging_data_7x7.blurring_grid,
            return_in_2d=False,
        )

        blurred_profile_image_2d = lens_imaging_data_7x7.mapping.scaled_array_2d_from_array_1d(
            array_1d=blurred_profile_image_1d
        )

        profile_subtracted_image_1d = (
            lens_imaging_data_7x7._image_1d - blurred_profile_image_1d
        )

        mapper = pix.mapper_from_grid_and_pixelization_grid(
            grid=lens_imaging_data_7x7.grid, inversion_uses_border=False
        )

        inversion = al.Inversion.from_data_1d_mapper_and_regularization(
            image_1d=profile_subtracted_image_1d,
            noise_map_1d=lens_imaging_data_7x7._noise_map_1d,
            convolver=lens_imaging_data_7x7.convolver,
            mapper=mapper,
            regularization=reg,
        )

        model_images_of_planes = fit.model_images_of_planes(return_in_2d=True)

        assert blurred_profile_image_2d == pytest.approx(
            model_images_of_planes[0], 1.0e-4
        )
        assert inversion.reconstructed_data_2d == pytest.approx(
            model_images_of_planes[1], 1.0e-4
        )
