def numpy_array_2d_to_fits(array_2d, file_path, overwrite=False):
    """Write a 2D NumPy array to a .fits file.

    Before outputting a NumPy array, the array is flipped upside-down using np.flipud. This is so that the arrays \
    appear the same orientation as .fits files loaded in DS9.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is written to fits.
    file_path : str
        The full path of the file that is output, including the file name and '.fits' extension.
    overwrite : bool
        If True and a file already exists with the input file_path the .fits file is overwritten. If False, an error \
        will be raised.

    Returns
    -------
    None

    Examples
    --------
    array_2d = np.ones((5,5))
    numpy_array_to_fits(array=array_2d, file_path='/path/to/file/filename.fits', overwrite=True)
    """
    if overwrite and os.path.exists(file_path):
        os.remove(file_path)

    new_hdr = fits.Header()
    hdu = fits.PrimaryHDU(np.flipud(array_2d), new_hdr)
    hdu.writeto(file_path)

def numpy_array_2d_to_fits ( array_2d , file_path , overwrite = False ) : if overwrite and os . path . exists ( file_path ) : os . remove ( file_path ) new_hdr = fits . Header ( ) hdu = fits . PrimaryHDU ( np . flipud ( array_2d ) , new_hdr ) hdu . writeto ( file_path )

Write a 2D NumPy array to a . fits file .


def numpy_array_2d_from_fits(file_path, hdu):
    """Read a 2D NumPy array to a .fits file.

    After loading the NumPy array, the array is flipped upside-down using np.flipud. This is so that the arrays \
    appear the same orientation as .fits files loaded in DS9.

    Parameters
    ----------
    file_path : str
        The full path of the file that is loaded, including the file name and '.fits' extension.
    hdu : int
        The HDU extension of the array that is loaded from the .fits file.

    Returns
    -------
    ndarray
        The NumPy array that is loaded from the .fits file.

    Examples
    --------
    array_2d = numpy_array_from_fits(file_path='/path/to/file/filename.fits', hdu=0)
    """
    hdu_list = fits.open(file_path)
    return np.flipud(np.array(hdu_list[hdu].data))

def numpy_array_2d_from_fits ( file_path , hdu ) : hdu_list = fits . open ( file_path ) return np . flipud ( np . array ( hdu_list [ hdu ] . data ) )

Read a 2D NumPy array to a . fits file .


def convolve_mapping_matrix(self, mapping_matrix):
        """For a given inversion mapping matrix, convolve every pixel's mapped regular with the PSF kernel.

        A mapping matrix provides non-zero entries in all elements which map two pixels to one another
        (see *inversions.mappers*).

        For example, lets take an regular which is masked using a 'cross' of 5 pixels:

        [[ True, False,  True]],
        [[False, False, False]],
        [[ True, False,  True]]

        As example mapping matrix of this cross is as follows (5 regular pixels x 3 source pixels):

        [1, 0, 0] [0->0]
        [1, 0, 0] [1->0]
        [0, 1, 0] [2->1]
        [0, 1, 0] [3->1]
        [0, 0, 1] [4->2]

        For each source-pixel, we can create an regular of its unit-surface brightnesses by mapping the non-zero
        entries back to masks. For example, doing this for source pixel 1 gives:

        [[0.0, 1.0, 0.0]],
        [[1.0, 0.0, 0.0]]
        [[0.0, 0.0, 0.0]]

        And source pixel 2:

        [[0.0, 0.0, 0.0]],
        [[0.0, 1.0, 1.0]]
        [[0.0, 0.0, 0.0]]

        We then convolve each of these regular with our PSF kernel, in 2 dimensions, like we would a normal regular. For
        example, using the kernel below:

        kernel:

        [[0.0, 0.1, 0.0]]
        [[0.1, 0.6, 0.1]]
        [[0.0, 0.1, 0.0]]

        Blurred Source Pixel 1 (we don't need to perform the convolution into masked pixels):

        [[0.0, 0.6, 0.0]],
        [[0.6, 0.0, 0.0]],
        [[0.0, 0.0, 0.0]]

        Blurred Source pixel 2:

        [[0.0, 0.0, 0.0]],
        [[0.0, 0.7, 0.7]],
        [[0.0, 0.0, 0.0]]

        Finally, we map each of these blurred regular back to a blurred mapping matrix, which is analogous to the
        mapping matrix.

        [0.6, 0.0, 0.0] [0->0]
        [0.6, 0.0, 0.0] [1->0]
        [0.0, 0.7, 0.0] [2->1]
        [0.0, 0.7, 0.0] [3->1]
        [0.0, 0.0, 0.6] [4->2]

        If the mapping matrix is sub-gridded, we perform the convolution on the fractional surface brightnesses in an
        identical fashion to above.

        Parameters
        -----------
        mapping_matrix : ndarray
            The 2D mapping matix describing how every inversion pixel maps to an datas_ pixel.
        """
        return self.convolve_matrix_jit(mapping_matrix, self.image_frame_indexes,
                                        self.image_frame_psfs, self.image_frame_lengths)

def convolve_mapping_matrix ( self , mapping_matrix ) : return self . convolve_matrix_jit ( mapping_matrix , self . image_frame_indexes , self . image_frame_psfs , self . image_frame_lengths )

For a given inversion mapping matrix convolve every pixel s mapped regular with the PSF kernel .


def mass_within_circle_in_units(self, radius: dim.Length, unit_mass='angular', kpc_per_arcsec=None,
                                    critical_surface_density=None):
        """ Integrate the mass profiles's convergence profile to compute the total mass within a circle of \
        specified radius. This is centred on the mass profile.

        The following units for mass can be specified and output:

        - Dimensionless angular units (default) - 'angular'.
        - Solar masses - 'angular' (multiplies the angular mass by the critical surface mass density).

        Parameters
        ----------
        radius : dim.Length
            The radius of the circle to compute the dimensionless mass within.
        unit_mass : str
            The units the mass is returned in (angular | angular).
        critical_surface_density : float or None
            The critical surface mass density of the strong lens configuration, which converts mass from angulalr \
            units to phsical units (e.g. solar masses).
        """

        self.check_units_of_radius_and_critical_surface_density(
            radius=radius, critical_surface_density=critical_surface_density)

        profile = self.new_profile_with_units_converted(
            unit_length=radius.unit_length, unit_mass='angular',
            kpc_per_arcsec=kpc_per_arcsec, critical_surface_density=critical_surface_density)

        mass_angular = dim.Mass(value=quad(profile.mass_integral, a=0.0, b=radius, args=(1.0,))[0], unit_mass='angular')
        return mass_angular.convert(unit_mass=unit_mass, critical_surface_density=critical_surface_density)

Integrate the mass profiles s convergence profile to compute the total mass within a circle of \ specified radius . This is centred on the mass profile .


def mass_within_ellipse_in_units(self, major_axis, unit_mass='angular', kpc_per_arcsec=None,
                                     critical_surface_density=None):
        """ Integrate the mass profiles's convergence profile to compute the total angular mass within an ellipse of \
        specified major axis. This is centred on the mass profile.

        The following units for mass can be specified and output:

        - Dimensionless angular units (default) - 'angular'.
        - Solar masses - 'angular' (multiplies the angular mass by the critical surface mass density)

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        unit_mass : str
            The units the mass is returned in (angular | angular).
        critical_surface_density : float or None
            The critical surface mass density of the strong lens configuration, which converts mass from angular \
            units to phsical units (e.g. solar masses).
        """

        self.check_units_of_radius_and_critical_surface_density(
            radius=major_axis, critical_surface_density=critical_surface_density)

        profile = self.new_profile_with_units_converted(
            unit_length=major_axis.unit_length, unit_mass='angular',
            kpc_per_arcsec=kpc_per_arcsec, critical_surface_density=critical_surface_density)

        mass_angular = dim.Mass(value=quad(profile.mass_integral, a=0.0, b=major_axis, args=(self.axis_ratio,))[0],
                                unit_mass='angular')
        return mass_angular.convert(unit_mass=unit_mass, critical_surface_density=critical_surface_density)

Integrate the mass profiles s convergence profile to compute the total angular mass within an ellipse of \ specified major axis . This is centred on the mass profile .


def mass_integral(self, x, axis_ratio):
        """Routine to integrate an elliptical light profiles - set axis ratio to 1 to compute the luminosity within a \
        circle"""
        r = x * axis_ratio
        return 2 * np.pi * r * self.convergence_func(x)

def mass_integral ( self , x , axis_ratio ) : r = x * axis_ratio return 2 * np . pi * r * self . convergence_func ( x )


def density_between_circular_annuli_in_angular_units(self, inner_annuli_radius, outer_annuli_radius):
        """Calculate the mass between two circular annuli and compute the density by dividing by the annuli surface
        area.

        The value returned by the mass integral is dimensionless, therefore the density between annuli is returned in \
        units of inverse radius squared. A conversion factor can be specified to convert this to a physical value \
        (e.g. the critical surface mass density).

        Parameters
        -----------
        inner_annuli_radius : float
            The radius of the inner annulus outside of which the density are estimated.
        outer_annuli_radius : float
            The radius of the outer annulus inside of which the density is estimated.
        """
        annuli_area = (np.pi * outer_annuli_radius ** 2.0) - (np.pi * inner_annuli_radius ** 2.0)
        return (self.mass_within_circle_in_units(radius=outer_annuli_radius) -
                self.mass_within_circle_in_units(radius=inner_annuli_radius)) \
               / annuli_area

Calculate the mass between two circular annuli and compute the density by dividing by the annuli surface area .


def einstein_radius_rescaled(self):
        """Rescale the einstein radius by slope and axis_ratio, to reduce its degeneracy with other mass-profiles
        parameters"""
        return ((3 - self.slope) / (1 + self.axis_ratio)) * self.einstein_radius ** (self.slope - 1)

def einstein_radius_rescaled ( self ) : return ( ( 3 - self . slope ) / ( 1 + self . axis_ratio ) ) * self . einstein_radius ** ( self . slope - 1 )

Rescale the einstein radius by slope and axis_ratio to reduce its degeneracy with other mass - profiles parameters


def convergence_from_grid(self, grid):
        """ Calculate the projected convergence at a given set of arc-second gridded coordinates.

        Parameters
        ----------
        grid : grids.RegularGrid
            The grid of (y,x) arc-second coordinates the surface density is computed on.
        """

        surface_density_grid = np.zeros(grid.shape[0])

        grid_eta = self.grid_to_elliptical_radii(grid)

        for i in range(grid.shape[0]):
            surface_density_grid[i] = self.convergence_func(grid_eta[i])

        return surface_density_grid

def convergence_from_grid ( self , grid ) : surface_density_grid = np . zeros ( grid . shape [ 0 ] ) grid_eta = self . grid_to_elliptical_radii ( grid ) for i in range ( grid . shape [ 0 ] ) : surface_density_grid [ i ] = self . convergence_func ( grid_eta [ i ] ) return surface_density_grid

Calculate the projected convergence at a given set of arc - second gridded coordinates .


def tabulate_integral(self, grid, tabulate_bins):
        """Tabulate an integral over the surface density of deflection potential of a mass profile. This is used in \
        the GeneralizedNFW profile classes to speed up the integration procedure.

        Parameters
        -----------
        grid : grids.RegularGrid
            The grid of (y,x) arc-second coordinates the potential / deflection_stacks are computed on.
        tabulate_bins : int
            The number of bins to tabulate the inner integral of this profile.
        """
        eta_min = 1.0e-4
        eta_max = 1.05 * np.max(self.grid_to_elliptical_radii(grid))

        minimum_log_eta = np.log10(eta_min)
        maximum_log_eta = np.log10(eta_max)
        bin_size = (maximum_log_eta - minimum_log_eta) / (tabulate_bins - 1)

        return eta_min, eta_max, minimum_log_eta, maximum_log_eta, bin_size

Tabulate an integral over the surface density of deflection potential of a mass profile . This is used in \ the GeneralizedNFW profile classes to speed up the integration procedure .


def intensity_at_radius(self, radius):
        """ Compute the intensity of the profile at a given radius.

        Parameters
        ----------
        radius : float
            The distance from the centre of the profile.
        """
        return self.intensity * np.exp(
            -self.sersic_constant * (((radius / self.effective_radius) ** (1. / self.sersic_index)) - 1))

def intensity_at_radius ( self , radius ) : return self . intensity * np . exp ( - self . sersic_constant * ( ( ( radius / self . effective_radius ) ** ( 1. / self . sersic_index ) ) - 1 ) )

Compute the intensity of the profile at a given radius .


def sersic_constant(self):
        """ A parameter derived from Sersic index which ensures that effective radius contains 50% of the profile's
        total integrated light.
        """
        return (2 * self.sersic_index) - (1. / 3.) + (4. / (405. * self.sersic_index)) + (
                46. / (25515. * self.sersic_index ** 2)) + (131. / (1148175. * self.sersic_index ** 3)) - (
                       2194697. / (30690717750. * self.sersic_index ** 4))

A parameter derived from Sersic index which ensures that effective radius contains 50% of the profile s total integrated light .


def luminosity_within_circle_in_units(self, radius : dim.Length, unit_luminosity='eps', kpc_per_arcsec=None, exposure_time=None):
        """Compute the total luminosity of the galaxy's light profiles within a circle of specified radius.

        See *light_profiles.luminosity_within_circle* for details of how this is performed.

        Parameters
        ----------
        radius : float
            The radius of the circle to compute the dimensionless mass within.
        unit_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        if self.has_light_profile:
            return sum(map(lambda p: p.luminosity_within_circle_in_units(radius=radius, unit_luminosity=unit_luminosity,
                                                                         kpc_per_arcsec=kpc_per_arcsec, exposure_time=exposure_time),
                           self.light_profiles))
        else:
            return None

def luminosity_within_circle_in_units ( self , radius : dim . Length , unit_luminosity = 'eps' , kpc_per_arcsec = None , exposure_time = None ) : if self . has_light_profile : return sum ( map ( lambda p : p . luminosity_within_circle_in_units ( radius = radius , unit_luminosity = unit_luminosity , kpc_per_arcsec = kpc_per_arcsec , exposure_time = exposure_time ) , self . light_profiles ) ) else : return None

Compute the total luminosity of the galaxy s light profiles within a circle of specified radius .


def luminosity_within_ellipse_in_units(self, major_axis : dim.Length, unit_luminosity='eps', kpc_per_arcsec=None, exposure_time=None):
        """Compute the total luminosity of the galaxy's light profiles, within an ellipse of specified major axis. This
        is performed via integration of each light profile and is centred, oriented and aligned with each light
        model's individual geometry.

        See *light_profiles.luminosity_within_ellipse* for details of how this is performed.

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        unit_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        if self.has_light_profile:
            return sum(map(lambda p: p.luminosity_within_ellipse_in_units(major_axis=major_axis, unit_luminosity=unit_luminosity,
                                                                          kpc_per_arcsec=kpc_per_arcsec, exposure_time=exposure_time),
                           self.light_profiles))
        else:
            return None

def luminosity_within_ellipse_in_units ( self , major_axis : dim . Length , unit_luminosity = 'eps' , kpc_per_arcsec = None , exposure_time = None ) : if self . has_light_profile : return sum ( map ( lambda p : p . luminosity_within_ellipse_in_units ( major_axis = major_axis , unit_luminosity = unit_luminosity , kpc_per_arcsec = kpc_per_arcsec , exposure_time = exposure_time ) , self . light_profiles ) ) else : return None

Compute the total luminosity of the galaxy s light profiles within an ellipse of specified major axis . This is performed via integration of each light profile and is centred oriented and aligned with each light model s individual geometry .


def mass_within_circle_in_units(self, radius, unit_mass='angular', kpc_per_arcsec=None, critical_surface_density=None):
        """Compute the total angular mass of the galaxy's mass profiles within a circle of specified radius.

        See *profiles.mass_profiles.mass_within_circle* for details of how this is performed.

        Parameters
        ----------
        radius : float
            The radius of the circle to compute the dimensionless mass within.
        unit_mass : str
            The units the mass is returned in (angular | solMass).
        critical_surface_density : float
            The critical surface mass density of the strong lens configuration, which converts mass from angulalr \
            units to physical units (e.g. solar masses).
        """
        if self.has_mass_profile:
            return sum(map(lambda p: p.mass_within_circle_in_units(radius=radius, unit_mass=unit_mass,
                                                                   kpc_per_arcsec=kpc_per_arcsec,
                                                                   critical_surface_density=critical_surface_density),
                           self.mass_profiles))
        else:
            return None

def mass_within_circle_in_units ( self , radius , unit_mass = 'angular' , kpc_per_arcsec = None , critical_surface_density = None ) : if self . has_mass_profile : return sum ( map ( lambda p : p . mass_within_circle_in_units ( radius = radius , unit_mass = unit_mass , kpc_per_arcsec = kpc_per_arcsec , critical_surface_density = critical_surface_density ) , self . mass_profiles ) ) else : return None

Compute the total angular mass of the galaxy s mass profiles within a circle of specified radius .


def mass_within_ellipse_in_units(self, major_axis, unit_mass='angular', kpc_per_arcsec=None, critical_surface_density=None):
        """Compute the total angular mass of the galaxy's mass profiles within an ellipse of specified major_axis.

        See *profiles.mass_profiles.angualr_mass_within_ellipse* for details of how this is performed.

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        units_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        if self.has_mass_profile:
            return sum(map(lambda p: p.mass_within_ellipse_in_units(major_axis=major_axis, unit_mass=unit_mass,
                                                                    kpc_per_arcsec=kpc_per_arcsec,
                                                                    critical_surface_density=critical_surface_density),
                           self.mass_profiles))
        else:
            return None

def mass_within_ellipse_in_units ( self , major_axis , unit_mass = 'angular' , kpc_per_arcsec = None , critical_surface_density = None ) : if self . has_mass_profile : return sum ( map ( lambda p : p . mass_within_ellipse_in_units ( major_axis = major_axis , unit_mass = unit_mass , kpc_per_arcsec = kpc_per_arcsec , critical_surface_density = critical_surface_density ) , self . mass_profiles ) ) else : return None

Compute the total angular mass of the galaxy s mass profiles within an ellipse of specified major_axis .


def einstein_radius_in_units(self, unit_length='arcsec', kpc_per_arcsec=None):
        """The Einstein Radius of this galaxy, which is the sum of Einstein Radii of its mass profiles.

        If the galaxy is composed of multiple ellipitcal profiles with different axis-ratios, this Einstein Radius \
        may be inaccurate. This is because the differently oriented ellipses of each mass profile """

        if self.has_mass_profile:
            return sum(map(lambda p: p.einstein_radius_in_units(unit_length=unit_length, kpc_per_arcsec=kpc_per_arcsec),
                           self.mass_profiles))
        else:
            return None

def einstein_radius_in_units ( self , unit_length = 'arcsec' , kpc_per_arcsec = None ) : if self . has_mass_profile : return sum ( map ( lambda p : p . einstein_radius_in_units ( unit_length = unit_length , kpc_per_arcsec = kpc_per_arcsec ) , self . mass_profiles ) ) else : return None

The Einstein Radius of this galaxy which is the sum of Einstein Radii of its mass profiles .


def einstein_mass_in_units(self, unit_mass='angular', critical_surface_density=None):
        """The Einstein Mass of this galaxy, which is the sum of Einstein Radii of its mass profiles.

        If the galaxy is composed of multiple ellipitcal profiles with different axis-ratios, this Einstein Mass \
        may be inaccurate. This is because the differently oriented ellipses of each mass profile """

        if self.has_mass_profile:
            return sum(
                map(lambda p: p.einstein_mass_in_units(unit_mass=unit_mass,
                                                       critical_surface_density=critical_surface_density),
                    self.mass_profiles))
        else:
            return None

def einstein_mass_in_units ( self , unit_mass = 'angular' , critical_surface_density = None ) : if self . has_mass_profile : return sum ( map ( lambda p : p . einstein_mass_in_units ( unit_mass = unit_mass , critical_surface_density = critical_surface_density ) , self . mass_profiles ) ) else : return None

The Einstein Mass of this galaxy which is the sum of Einstein Radii of its mass profiles .


def hyper_noise_from_contributions(self, noise_map, contributions):
        """Compute a scaled galaxy hyper noise-map from a baseline noise-map.

        This uses the galaxy contribution map and the *noise_factor* and *noise_power* hyper-parameters.

        Parameters
        -----------
        noise_map : ndarray
            The observed noise-map (before scaling).
        contributions : ndarray
            The galaxy contribution map.
        """
        return self.noise_factor * (noise_map * contributions) ** self.noise_power

def hyper_noise_from_contributions ( self , noise_map , contributions ) : return self . noise_factor * ( noise_map * contributions ) ** self . noise_power

Compute a scaled galaxy hyper noise - map from a baseline noise - map .


def convolve_image(self, image_array, blurring_array):
        """For a given 1D regular array and blurring array, convolve the two using this convolver.

        Parameters
        -----------
        image_array : ndarray
            1D array of the regular values which are to be blurred with the convolver's PSF.
        blurring_array : ndarray
            1D array of the blurring regular values which blur into the regular-array after PSF convolution.
        """
        return self.convolve_jit(image_array, self.image_frame_indexes, self.image_frame_psfs, self.image_frame_lengths,
                                 blurring_array, self.blurring_frame_indexes, self.blurring_frame_psfs,
                                 self.blurring_frame_lengths)

def convolve_image ( self , image_array , blurring_array ) : return self . convolve_jit ( image_array , self . image_frame_indexes , self . image_frame_psfs , self . image_frame_lengths , blurring_array , self . blurring_frame_indexes , self . blurring_frame_psfs , self . blurring_frame_lengths )

For a given 1D regular array and blurring array convolve the two using this convolver .


def intensities_of_galaxies_from_grid(grid, galaxies):
    """Compute the intensities of a list of galaxies from an input grid, by summing the individual intensities \
    of each galaxy's light profile.

    If the input grid is a *grids.SubGrid*, the intensites is calculated on the sub-grid and binned-up to the \
    original regular grid by taking the mean value of every set of sub-pixels.

    If no galaxies are entered into the function, an array of all zeros is returned.

    Parameters
    -----------
    grid : RegularGrid
        The grid (regular or sub) of (y,x) arc-second coordinates at the centre of every unmasked pixel which the \
        intensities are calculated on.
    galaxies : [galaxy.Galaxy]
        The galaxies whose light profiles are used to compute the surface densities.
    """
    if galaxies:
        return sum(map(lambda g: g.intensities_from_grid(grid), galaxies))
    else:
        return np.full((grid.shape[0]), 0.0)

def intensities_of_galaxies_from_grid ( grid , galaxies ) : if galaxies : return sum ( map ( lambda g : g . intensities_from_grid ( grid ) , galaxies ) ) else : return np . full ( ( grid . shape [ 0 ] ) , 0.0 )

Compute the intensities of a list of galaxies from an input grid by summing the individual intensities \ of each galaxy s light profile .


def convergence_of_galaxies_from_grid(grid, galaxies):
    """Compute the convergence of a list of galaxies from an input grid, by summing the individual convergence \
    of each galaxy's mass profile.

    If the input grid is a *grids.SubGrid*, the convergence is calculated on the sub-grid and binned-up to the \
    original regular grid by taking the mean value of every set of sub-pixels.

    If no galaxies are entered into the function, an array of all zeros is returned.

    Parameters
    -----------
    grid : RegularGrid
        The grid (regular or sub) of (y,x) arc-second coordinates at the centre of every unmasked pixel which the \
        convergence is calculated on.
    galaxies : [galaxy.Galaxy]
        The galaxies whose mass profiles are used to compute the convergence.
    """
    if galaxies:
        return sum(map(lambda g: g.convergence_from_grid(grid), galaxies))
    else:
        return np.full((grid.shape[0]), 0.0)

def convergence_of_galaxies_from_grid ( grid , galaxies ) : if galaxies : return sum ( map ( lambda g : g . convergence_from_grid ( grid ) , galaxies ) ) else : return np . full ( ( grid . shape [ 0 ] ) , 0.0 )

Compute the convergence of a list of galaxies from an input grid by summing the individual convergence \ of each galaxy s mass profile .


def potential_of_galaxies_from_grid(grid, galaxies):
    """Compute the potential of a list of galaxies from an input grid, by summing the individual potential \
    of each galaxy's mass profile.

    If the input grid is a *grids.SubGrid*, the surface-density is calculated on the sub-grid and binned-up to the \
    original regular grid by taking the mean value of every set of sub-pixels.

    If no galaxies are entered into the function, an array of all zeros is returned.

    Parameters
    -----------
    grid : RegularGrid
        The grid (regular or sub) of (y,x) arc-second coordinates at the centre of every unmasked pixel which the \
        potential is calculated on.
    galaxies : [galaxy.Galaxy]
        The galaxies whose mass profiles are used to compute the surface densities.
    """
    if galaxies:
        return sum(map(lambda g: g.potential_from_grid(grid), galaxies))
    else:
        return np.full((grid.shape[0]), 0.0)

def potential_of_galaxies_from_grid ( grid , galaxies ) : if galaxies : return sum ( map ( lambda g : g . potential_from_grid ( grid ) , galaxies ) ) else : return np . full ( ( grid . shape [ 0 ] ) , 0.0 )

Compute the potential of a list of galaxies from an input grid by summing the individual potential \ of each galaxy s mass profile .


def deflections_of_galaxies_from_grid(grid, galaxies):
    """Compute the deflections of a list of galaxies from an input grid, by summing the individual deflections \
    of each galaxy's mass profile.

    If the input grid is a *grids.SubGrid*, the potential is calculated on the sub-grid and binned-up to the \
    original regular grid by taking the mean value of every set of sub-pixels.

    If no galaxies are entered into the function, an array of all zeros is returned.

    Parameters
    -----------
    grid : RegularGrid
        The grid (regular or sub) of (y,x) arc-second coordinates at the centre of every unmasked pixel which the \
        deflections is calculated on.
    galaxies : [galaxy.Galaxy]
        The galaxies whose mass profiles are used to compute the surface densities.
    """
    if len(galaxies) > 0:
        deflections = sum(map(lambda galaxy: galaxy.deflections_from_grid(grid), galaxies))
    else:
        deflections = np.full((grid.shape[0], 2), 0.0)

    if isinstance(grid, grids.SubGrid):
        return np.asarray([grid.regular_data_1d_from_sub_data_1d(deflections[:, 0]),
                           grid.regular_data_1d_from_sub_data_1d(deflections[:, 1])]).T

    return deflections

def deflections_of_galaxies_from_grid ( grid , galaxies ) : if len ( galaxies ) > 0 : deflections = sum ( map ( lambda galaxy : galaxy . deflections_from_grid ( grid ) , galaxies ) ) else : deflections = np . full ( ( grid . shape [ 0 ] , 2 ) , 0.0 ) if isinstance ( grid , grids . SubGrid ) : return np . asarray ( [ grid . regular_data_1d_from_sub_data_1d ( deflections [ : , 0 ] ) , grid . regular_data_1d_from_sub_data_1d ( deflections [ : , 1 ] ) ] ) . T return deflections

Compute the deflections of a list of galaxies from an input grid by summing the individual deflections \ of each galaxy s mass profile .


def deflections_of_galaxies_from_sub_grid(sub_grid, galaxies):
    """Compute the deflections of a list of galaxies from an input sub-grid, by summing the individual deflections \
    of each galaxy's mass profile.

    The deflections are calculated on the sub-grid and binned-up to the original regular grid by taking the mean value \
    of every set of sub-pixels.

    If no galaxies are entered into the function, an array of all zeros is returned.

    Parameters
    -----------
    sub_grid : RegularGrid
        The grid (regular or sub) of (y,x) arc-second coordinates at the centre of every unmasked pixel which the \
        deflections is calculated on.
    galaxies : [galaxy.Galaxy]
        The galaxies whose mass profiles are used to compute the surface densities.
    """
    if galaxies:
        return sum(map(lambda galaxy: galaxy.deflections_from_grid(sub_grid), galaxies))
    else:
        return np.full((sub_grid.shape[0], 2), 0.0)

def deflections_of_galaxies_from_sub_grid ( sub_grid , galaxies ) : if galaxies : return sum ( map ( lambda galaxy : galaxy . deflections_from_grid ( sub_grid ) , galaxies ) ) else : return np . full ( ( sub_grid . shape [ 0 ] , 2 ) , 0.0 )

Compute the deflections of a list of galaxies from an input sub - grid by summing the individual deflections \ of each galaxy s mass profile .


def blurred_image_of_planes_from_1d_images_and_convolver(total_planes, image_plane_image_1d_of_planes,
                                                         image_plane_blurring_image_1d_of_planes, convolver,
                                                         map_to_scaled_array):
    """For a tracer, extract the image-plane image of every plane and blur it with the PSF.

    If none of the galaxies in a plane have a light profie or pixelization (and thus don't have an image) a *None* \
    is used.

    Parameters
    ----------
    total_planes : int
        The total number of planes that blurred images are computed for.
    image_plane_image_1d_of_planes : [ndarray]
        For every plane, the 1D image-plane image.
    image_plane_blurring_image_1d_of_planes : [ndarray]
        For every plane, the 1D image-plane blurring image.
    convolver : hyper.ccd.convolution.ConvolverImage
        Class which performs the PSF convolution of a masked image in 1D.
    map_to_scaled_array : func
        A function which maps a masked image from 1D to 2D.
    """

    blurred_image_of_planes = []

    for plane_index in range(total_planes):

        # If all entries are zero, there was no light profile / pixeization
        if np.count_nonzero(image_plane_image_1d_of_planes[plane_index]) > 0:

            blurred_image_1d_of_plane = blurred_image_1d_from_1d_unblurred_and_blurring_images(
                unblurred_image_1d=image_plane_image_1d_of_planes[plane_index],
                blurring_image_1d=image_plane_blurring_image_1d_of_planes[plane_index],
                convolver=convolver)

            blurred_image_of_plane = map_to_scaled_array(array_1d=blurred_image_1d_of_plane)

            blurred_image_of_planes.append(blurred_image_of_plane)

        else:

            blurred_image_of_planes.append(None)

    return blurred_image_of_planes

For a tracer extract the image - plane image of every plane and blur it with the PSF .


def unmasked_blurred_image_of_planes_from_padded_grid_stack_and_psf(planes, padded_grid_stack, psf):
    """For lens data, compute the unmasked blurred image of every unmasked unblurred image of each plane. To do this, \
    this function iterates over all planes to extract their unmasked unblurred images.

    If a galaxy in a plane has a pixelization, the unmasked image is returned as None, as as the inversion's model \
    image cannot be mapped to an unmasked version.

    This relies on using the lens data's padded-grid, which is a grid of (y,x) coordinates which extends over the \
    entire image as opposed to just the masked region.

    This returns a list, where each list index corresponds to [plane_index].

    Parameters
    ----------
    planes : [plane.Plane]
        The list of planes the unmasked blurred images are computed using.
    padded_grid_stack : grids.GridStack
        A padded-grid_stack, whose padded grid is used for PSF convolution.
    psf : ccd.PSF
        The PSF of the image used for convolution.
    """
    unmasked_blurred_image_of_planes = []

    for plane in planes:

        if plane.has_pixelization:
            unmasked_blurred_image_of_plane = None
        else:
            unmasked_blurred_image_of_plane = \
                padded_grid_stack.unmasked_blurred_image_from_psf_and_unmasked_image(

                    psf=psf, unmasked_image_1d=plane.image_plane_image_1d)

        unmasked_blurred_image_of_planes.append(unmasked_blurred_image_of_plane)

    return unmasked_blurred_image_of_planes

For lens data compute the unmasked blurred image of every unmasked unblurred image of each plane . To do this \ this function iterates over all planes to extract their unmasked unblurred images .


def unmasked_blurred_image_of_planes_and_galaxies_from_padded_grid_stack_and_psf(planes, padded_grid_stack, psf):
    """For lens data, compute the unmasked blurred image of every unmasked unblurred image of every galaxy in each \
    plane. To do this, this function iterates over all planes and then galaxies to extract their unmasked unblurred \
    images.

    If a galaxy in a plane has a pixelization, the unmasked image of that galaxy in the plane is returned as None \
    as as the inversion's model image cannot be mapped to an unmasked version.

    This relies on using the lens data's padded-grid, which is a grid of (y,x) coordinates which extends over the \
    entire image as opposed to just the masked region.

    This returns a list of lists, where each list index corresponds to [plane_index][galaxy_index].

    Parameters
    ----------
    planes : [plane.Plane]
        The list of planes the unmasked blurred images are computed using.
    padded_grid_stack : grids.GridStack
        A padded-grid_stack, whose padded grid is used for PSF convolution.
    psf : ccd.PSF
        The PSF of the image used for convolution.
    """
    return [plane.unmasked_blurred_image_of_galaxies_from_psf(padded_grid_stack, psf) for plane in planes]

For lens data compute the unmasked blurred image of every unmasked unblurred image of every galaxy in each \ plane . To do this this function iterates over all planes and then galaxies to extract their unmasked unblurred \ images .


def contribution_maps_1d_from_hyper_images_and_galaxies(hyper_model_image_1d, hyper_galaxy_images_1d, hyper_galaxies,
                                                        hyper_minimum_values):
    """For a fitting hyper_galaxy_image, hyper_galaxy model image, list of hyper galaxies images and model hyper galaxies, compute
    their contribution maps, which are used to compute a scaled-noise_map map. All quantities are masked 1D arrays.

    The reason this is separate from the *contributions_from_fitting_hyper_images_and_hyper_galaxies* function is that
    each hyper_galaxy image has a list of hyper galaxies images and associated hyper galaxies (one for each galaxy). Thus,
    this function breaks down the calculation of each 1D masked contribution map and returns them in the same datas
    structure (2 lists with indexes [image_index][contribution_map_index].

    Parameters
    ----------
    hyper_model_image_1d : ndarray
        The best-fit model image to the datas (e.g. from a previous analysis phase).
    hyper_galaxy_images_1d : [ndarray]
        The best-fit model image of each hyper galaxy to the datas (e.g. from a previous analysis phase).
    hyper_galaxies : [galaxy.Galaxy]
        The hyper galaxies which represent the model components used to scale the noise_map, which correspond to
        individual galaxies in the image.
    hyper_minimum_values : [float]
        The minimum value of each hyper_galaxy-image contribution map, which ensure zero's don't impact the scaled noise-map.
    """
    # noinspection PyArgumentList
    return list(map(lambda hyper_galaxy, hyper_galaxy_image_1d, hyper_minimum_value:
                    hyper_galaxy.contributions_from_model_image_and_galaxy_image(model_image=hyper_model_image_1d,
                                                                                galaxy_image=hyper_galaxy_image_1d,
                                                                                minimum_value=hyper_minimum_value),
                    hyper_galaxies, hyper_galaxy_images_1d, hyper_minimum_values))

For a fitting hyper_galaxy_image hyper_galaxy model image list of hyper galaxies images and model hyper galaxies compute their contribution maps which are used to compute a scaled - noise_map map . All quantities are masked 1D arrays .


def scaled_noise_map_from_hyper_galaxies_and_contribution_maps(contribution_maps, hyper_galaxies, noise_map):
    """For a contribution map and noise-map, use the model hyper galaxies to compute a scaled noise-map.

    Parameters
    -----------
    contribution_maps : ndarray
        The image's list of 1D masked contribution maps (e.g. one for each hyper galaxy)
    hyper_galaxies : [galaxy.Galaxy]
        The hyper galaxies which represent the model components used to scale the noise_map, which correspond to
        individual galaxies in the image.
    noise_map : ccd.NoiseMap or ndarray
        An array describing the RMS standard deviation error in each pixel, preferably in units of electrons per
        second.
    """
    scaled_noise_maps = list(map(lambda hyper_galaxy, contribution_map:
                                 hyper_galaxy.hyper_noise_from_contributions(noise_map=noise_map,
                                                                             contributions=contribution_map),
                                 hyper_galaxies, contribution_maps))
    return noise_map + sum(scaled_noise_maps)

For a contribution map and noise - map use the model hyper galaxies to compute a scaled noise - map .


def for_data_and_tracer(cls, lens_data, tracer, padded_tracer=None):
        """Fit lens data with a model tracer, automatically determining the type of fit based on the \
        properties of the galaxies in the tracer.

        Parameters
        -----------
        lens_data : lens_data.LensData or lens_data.LensDataHyper
            The lens-images that is fitted.
        tracer : ray_tracing.TracerNonStack
            The tracer, which describes the ray-tracing and strong lens configuration.
        padded_tracer : ray_tracing.Tracer or None
            A tracer with an identical strong lens configuration to the tracer above, but using the lens data's \
            padded grid_stack such that unmasked model-images can be computed.
        """

        if tracer.has_light_profile and not tracer.has_pixelization:
            return LensProfileFit(lens_data=lens_data, tracer=tracer, padded_tracer=padded_tracer)
        elif not tracer.has_light_profile and tracer.has_pixelization:
            return LensInversionFit(lens_data=lens_data, tracer=tracer, padded_tracer=None)
        elif tracer.has_light_profile and tracer.has_pixelization:
            return LensProfileInversionFit(lens_data=lens_data, tracer=tracer, padded_tracer=None)
        else:
            raise exc.FittingException('The fit routine did not call a Fit class - check the '
                                       'properties of the tracer')

Fit lens data with a model tracer automatically determining the type of fit based on the \ properties of the galaxies in the tracer .


def transform_grid(func):
    """Wrap the function in a function that checks whether the coordinates have been transformed. If they have not \
    been transformed then they are transformed.

    Parameters
    ----------
    func : (profiles, *args, **kwargs) -> Object
        A function that requires transformed coordinates

    Returns
    -------
        A function that can except cartesian or transformed coordinates
    """

    @wraps(func)
    def wrapper(profile, grid, *args, **kwargs):
        """

        Parameters
        ----------
        profile : GeometryProfile
            The profiles that owns the function
        grid : ndarray
            PlaneCoordinates in either cartesian or profiles coordinate system
        args
        kwargs

        Returns
        -------
            A value or coordinate in the same coordinate system as those passed in.
        """
        if not isinstance(grid, TransformedGrid):
            return func(profile, profile.transform_grid_to_reference_frame(grid), *args, **kwargs)
        else:
            return func(profile, grid, *args, **kwargs)

    return wrapper

def transform_grid ( func ) : @ wraps ( func ) def wrapper ( profile , grid , * args , ** kwargs ) : if not isinstance ( grid , TransformedGrid ) : return func ( profile , profile . transform_grid_to_reference_frame ( grid ) , * args , ** kwargs ) else : return func ( profile , grid , * args , ** kwargs ) return wrapper

Wrap the function in a function that checks whether the coordinates have been transformed . If they have not \ been transformed then they are transformed .


def cache(func):
    """
    Caches results of a call to a grid function. If a grid that evaluates to the same byte value is passed into the same
    function of the same instance as previously then the cached result is returned.

    Parameters
    ----------
    func
        Some instance method that takes a grid as its argument

    Returns
    -------
    result
        Some result, either newly calculated or recovered from the cache
    """

    def wrapper(instance: GeometryProfile, grid: np.ndarray, *args, **kwargs):
        if not hasattr(instance, "cache"):
            instance.cache = {}
        key = (func.__name__, grid.tobytes())
        if key not in instance.cache:
            instance.cache[key] = func(instance, grid)
        return instance.cache[key]

    return wrapper

def cache ( func ) : def wrapper ( instance : GeometryProfile , grid : np . ndarray , * args , ** kwargs ) : if not hasattr ( instance , "cache" ) : instance . cache = { } key = ( func . __name__ , grid . tobytes ( ) ) if key not in instance . cache : instance . cache [ key ] = func ( instance , grid ) return instance . cache [ key ] return wrapper

Caches results of a call to a grid function . If a grid that evaluates to the same byte value is passed into the same function of the same instance as previously then the cached result is returned .


def cos_and_sin_from_x_axis(self):
        """ Determine the sin and cosine of the angle between the profile's ellipse and the positive x-axis, \
        counter-clockwise. """
        phi_radians = np.radians(self.phi)
        return np.cos(phi_radians), np.sin(phi_radians)

def cos_and_sin_from_x_axis ( self ) : phi_radians = np . radians ( self . phi ) return np . cos ( phi_radians ) , np . sin ( phi_radians )

Determine the sin and cosine of the angle between the profile s ellipse and the positive x - axis \ counter - clockwise .


def grid_angle_to_profile(self, grid_thetas):
        """The angle between each angle theta on the grid and the profile, in radians.

        Parameters
        -----------
        grid_thetas : ndarray
            The angle theta counter-clockwise from the positive x-axis to each coordinate in radians.
        """
        theta_coordinate_to_profile = np.add(grid_thetas, - self.phi_radians)
        return np.cos(theta_coordinate_to_profile), np.sin(theta_coordinate_to_profile)

def grid_angle_to_profile ( self , grid_thetas ) : theta_coordinate_to_profile = np . add ( grid_thetas , - self . phi_radians ) return np . cos ( theta_coordinate_to_profile ) , np . sin ( theta_coordinate_to_profile )

The angle between each angle theta on the grid and the profile in radians .


def mapping_matrix_from_sub_to_pix(sub_to_pix, pixels, regular_pixels, sub_to_regular, sub_grid_fraction):
    """Computes the mapping matrix, by iterating over the known mappings between the sub-grid and pixelization.

    Parameters
    -----------
    sub_to_pix : ndarray
        The mappings between the observed regular's sub-pixels and pixelization's pixels.
    pixels : int
        The number of pixels in the pixelization.
    regular_pixels : int
        The number of datas pixels in the observed datas and thus on the regular grid.
    sub_to_regular : ndarray
        The mappings between the observed regular's sub-pixels and observed regular's pixels.
    sub_grid_fraction : float
        The fractional area each sub-pixel takes up in an regular-pixel.
    """

    mapping_matrix = np.zeros((regular_pixels, pixels))

    for sub_index in range(sub_to_regular.shape[0]):
        mapping_matrix[sub_to_regular[sub_index], sub_to_pix[sub_index]] += sub_grid_fraction

    return mapping_matrix

def mapping_matrix_from_sub_to_pix ( sub_to_pix , pixels , regular_pixels , sub_to_regular , sub_grid_fraction ) : mapping_matrix = np . zeros ( ( regular_pixels , pixels ) ) for sub_index in range ( sub_to_regular . shape [ 0 ] ) : mapping_matrix [ sub_to_regular [ sub_index ] , sub_to_pix [ sub_index ] ] += sub_grid_fraction return mapping_matrix

Computes the mapping matrix by iterating over the known mappings between the sub - grid and pixelization .


def voronoi_regular_to_pix_from_grids_and_geometry(regular_grid, regular_to_nearest_pix, pixel_centres,
                                                   pixel_neighbors, pixel_neighbors_size):
    """ Compute the mappings between a set of regular-grid pixels and pixelization pixels, using information on \
    how regular pixels map to their closest pixelization pixel on the image-plane pix-grid and the pixelization's \
    pixel centres.

    To determine the complete set of regular-pixel to pixelization pixel mappings, we must pair every regular-pixel to \
    its nearest pixel. Using a full nearest neighbor search to do this is slow, thus the pixel neighbors (derived via \
    the Voronoi grid) are used to localize each nearest neighbor search via a graph search.

    Parameters
    ----------
    regular_grid : RegularGrid
        The grid of (y,x) arc-second coordinates at the centre of every unmasked pixel, which has been traced to \
        to an irregular grid via lens.
    regular_to_nearest_pix : ndarray
        A 1D array that maps every regular-grid pixel to its nearest pix-grid pixel (as determined on the unlensed \
        2D array).
    pixel_centres : ndarray
        The (y,x) centre of every Voronoi pixel in arc-seconds.
    pixel_neighbors : ndarray
        An array of length (voronoi_pixels) which provides the index of all neighbors of every pixel in \
        the Voronoi grid (entries of -1 correspond to no neighbor).
    pixel_neighbors_size : ndarray
        An array of length (voronoi_pixels) which gives the number of neighbors of every pixel in the \
        Voronoi grid.
     """

    regular_to_pix = np.zeros((regular_grid.shape[0]))

    for regular_index in range(regular_grid.shape[0]):

        nearest_pix_pixel_index = regular_to_nearest_pix[regular_index]

        while True:

            nearest_pix_pixel_center = pixel_centres[nearest_pix_pixel_index]

            sub_to_nearest_pix_distance = (regular_grid[regular_index, 0] - nearest_pix_pixel_center[0]) ** 2 + \
                                          (regular_grid[regular_index, 1] - nearest_pix_pixel_center[1]) ** 2

            closest_separation_from_pix_neighbor = 1.0e8

            for neighbor_index in range(pixel_neighbors_size[nearest_pix_pixel_index]):

                neighbor = pixel_neighbors[nearest_pix_pixel_index, neighbor_index]

                separation_from_neighbor = (regular_grid[regular_index, 0] - pixel_centres[neighbor, 0]) ** 2 + \
                                           (regular_grid[regular_index, 1] - pixel_centres[neighbor, 1]) ** 2

                if separation_from_neighbor < closest_separation_from_pix_neighbor:

                    closest_separation_from_pix_neighbor = separation_from_neighbor
                    closest_neighbor_index = neighbor_index

            neighboring_pix_pixel_index = pixel_neighbors[nearest_pix_pixel_index, closest_neighbor_index]
            sub_to_neighboring_pix_distance = closest_separation_from_pix_neighbor

            if sub_to_nearest_pix_distance <= sub_to_neighboring_pix_distance:
                regular_to_pix[regular_index] = nearest_pix_pixel_index
                break
            else:
                nearest_pix_pixel_index = neighboring_pix_pixel_index

    return regular_to_pix

Compute the mappings between a set of regular - grid pixels and pixelization pixels using information on \ how regular pixels map to their closest pixelization pixel on the image - plane pix - grid and the pixelization s \ pixel centres .


def voronoi_sub_to_pix_from_grids_and_geometry(sub_grid, regular_to_nearest_pix, sub_to_regular, pixel_centres,
                                               pixel_neighbors, pixel_neighbors_size):
    """ Compute the mappings between a set of sub-grid pixels and pixelization pixels, using information on \
    how the regular pixels hosting each sub-pixel map to their closest pixelization pixel on the image-plane pix-grid \
    and the pixelization's pixel centres.

    To determine the complete set of sub-pixel to pixelization pixel mappings, we must pair every sub-pixel to \
    its nearest pixel. Using a full nearest neighbor search to do this is slow, thus the pixel neighbors (derived via \
    the Voronoi grid) are used to localize each nearest neighbor search by using a graph search.

    Parameters
    ----------
    regular_grid : RegularGrid
        The grid of (y,x) arc-second coordinates at the centre of every unmasked pixel, which has been traced to \
        to an irregular grid via lens.
    regular_to_nearest_pix : ndarray
        A 1D array that maps every regular-grid pixel to its nearest pix-grid pixel (as determined on the unlensed \
        2D array).
    pixel_centres : (float, float)
        The (y,x) centre of every Voronoi pixel in arc-seconds.
    pixel_neighbors : ndarray
        An array of length (voronoi_pixels) which provides the index of all neighbors of every pixel in \
        the Voronoi grid (entries of -1 correspond to no neighbor).
    pixel_neighbors_size : ndarray
        An array of length (voronoi_pixels) which gives the number of neighbors of every pixel in the \
        Voronoi grid.
     """

    sub_to_pix = np.zeros((sub_grid.shape[0]))

    for sub_index in range(sub_grid.shape[0]):

        nearest_pix_pixel_index = regular_to_nearest_pix[sub_to_regular[sub_index]]

        while True:

            nearest_pix_pixel_center = pixel_centres[nearest_pix_pixel_index]

            sub_to_nearest_pix_distance = (sub_grid[sub_index, 0] - nearest_pix_pixel_center[0]) ** 2 + \
                                          (sub_grid[sub_index, 1] - nearest_pix_pixel_center[1]) ** 2

            closest_separation_from_pix_to_neighbor = 1.0e8

            for neighbor_index in range(pixel_neighbors_size[nearest_pix_pixel_index]):

                neighbor = pixel_neighbors[nearest_pix_pixel_index, neighbor_index]

                separation_from_neighbor = (sub_grid[sub_index, 0] - pixel_centres[neighbor, 0]) ** 2 + \
                                           (sub_grid[sub_index, 1] - pixel_centres[neighbor, 1]) ** 2

                if separation_from_neighbor < closest_separation_from_pix_to_neighbor:
                    closest_separation_from_pix_to_neighbor = separation_from_neighbor
                    closest_neighbor_index = neighbor_index

            neighboring_pix_pixel_index = pixel_neighbors[nearest_pix_pixel_index, closest_neighbor_index]
            sub_to_neighboring_pix_distance = closest_separation_from_pix_to_neighbor

            if sub_to_nearest_pix_distance <= sub_to_neighboring_pix_distance:
                sub_to_pix[sub_index] = nearest_pix_pixel_index
                break
            else:
                nearest_pix_pixel_index = neighboring_pix_pixel_index

    return sub_to_pix

Compute the mappings between a set of sub - grid pixels and pixelization pixels using information on \ how the regular pixels hosting each sub - pixel map to their closest pixelization pixel on the image - plane pix - grid \ and the pixelization s pixel centres .


def luminosity_within_circle_in_units(self, radius: dim.Length, unit_luminosity='eps', kpc_per_arcsec=None,
                                          exposure_time=None):
        """Integrate the light profile to compute the total luminosity within a circle of specified radius. This is \
        centred on the light profile's centre.

        The following units for mass can be specified and output:

        - Electrons per second (default) - 'eps'.
        - Counts - 'counts' (multiplies the luminosity in electrons per second by the exposure time).

        Parameters
        ----------
        radius : float
            The radius of the circle to compute the dimensionless mass within.
        unit_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float or None
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """

        if not isinstance(radius, dim.Length):
            radius = dim.Length(value=radius, unit_length='arcsec')

        profile = self.new_profile_with_units_converted(unit_length=radius.unit_length, unit_luminosity=unit_luminosity,
                                                        kpc_per_arcsec=kpc_per_arcsec, exposure_time=exposure_time)

        luminosity = quad(profile.luminosity_integral, a=0.0, b=radius, args=(1.0,))[0]
        return dim.Luminosity(luminosity, unit_luminosity)

def luminosity_within_circle_in_units ( self , radius : dim . Length , unit_luminosity = 'eps' , kpc_per_arcsec = None , exposure_time = None ) : if not isinstance ( radius , dim . Length ) : radius = dim . Length ( value = radius , unit_length = 'arcsec' ) profile = self . new_profile_with_units_converted ( unit_length = radius . unit_length , unit_luminosity = unit_luminosity , kpc_per_arcsec = kpc_per_arcsec , exposure_time = exposure_time ) luminosity = quad ( profile . luminosity_integral , a = 0.0 , b = radius , args = ( 1.0 , ) ) [ 0 ] return dim . Luminosity ( luminosity , unit_luminosity )

Integrate the light profile to compute the total luminosity within a circle of specified radius . This is \ centred on the light profile s centre .


def luminosity_within_ellipse_in_units(self, major_axis, unit_luminosity='eps', kpc_per_arcsec=None,
                                           exposure_time=None):
        """Integrate the light profiles to compute the total luminosity within an ellipse of specified major axis. \
        This is centred on the light profile's centre.

        The following units for mass can be specified and output:

        - Electrons per second (default) - 'eps'.
        - Counts - 'counts' (multiplies the luminosity in electrons per second by the exposure time).

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        unit_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float or None
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """

        if not isinstance(major_axis, dim.Length):
            major_axis = dim.Length(major_axis, 'arcsec')

        profile = self.new_profile_with_units_converted(unit_length=major_axis.unit_length,
                                                        unit_luminosity=unit_luminosity,
                                                        kpc_per_arcsec=kpc_per_arcsec, exposure_time=exposure_time)
        luminosity = quad(profile.luminosity_integral, a=0.0, b=major_axis, args=(self.axis_ratio,))[0]
        return dim.Luminosity(luminosity, unit_luminosity)

def luminosity_within_ellipse_in_units ( self , major_axis , unit_luminosity = 'eps' , kpc_per_arcsec = None , exposure_time = None ) : if not isinstance ( major_axis , dim . Length ) : major_axis = dim . Length ( major_axis , 'arcsec' ) profile = self . new_profile_with_units_converted ( unit_length = major_axis . unit_length , unit_luminosity = unit_luminosity , kpc_per_arcsec = kpc_per_arcsec , exposure_time = exposure_time ) luminosity = quad ( profile . luminosity_integral , a = 0.0 , b = major_axis , args = ( self . axis_ratio , ) ) [ 0 ] return dim . Luminosity ( luminosity , unit_luminosity )

Integrate the light profiles to compute the total luminosity within an ellipse of specified major axis . \ This is centred on the light profile s centre .


def luminosity_integral(self, x, axis_ratio):
        """Routine to integrate the luminosity of an elliptical light profile.

        The axis ratio is set to 1.0 for computing the luminosity within a circle"""
        r = x * axis_ratio
        return 2 * np.pi * r * self.intensities_from_grid_radii(x)

def luminosity_integral ( self , x , axis_ratio ) : r = x * axis_ratio return 2 * np . pi * r * self . intensities_from_grid_radii ( x )

Routine to integrate the luminosity of an elliptical light profile .


def intensities_from_grid_radii(self, grid_radii):
        """Calculate the intensity of the Gaussian light profile on a grid of radial coordinates.

        Parameters
        ----------
        grid_radii : float
            The radial distance from the centre of the profile. for each coordinate on the grid.
        """
        return np.multiply(np.divide(self.intensity, self.sigma * np.sqrt(2.0 * np.pi)),
                           np.exp(-0.5 * np.square(np.divide(grid_radii, self.sigma))))

def intensities_from_grid_radii ( self , grid_radii ) : return np . multiply ( np . divide ( self . intensity , self . sigma * np . sqrt ( 2.0 * np . pi ) ) , np . exp ( - 0.5 * np . square ( np . divide ( grid_radii , self . sigma ) ) ) )

Calculate the intensity of the Gaussian light profile on a grid of radial coordinates .


def intensities_from_grid_radii(self, grid_radii):
        """
        Calculate the intensity of the Sersic light profile on a grid of radial coordinates.

        Parameters
        ----------
        grid_radii : float
            The radial distance from the centre of the profile. for each coordinate on the grid.
        """
        np.seterr(all='ignore')
        return np.multiply(self.intensity, np.exp(
            np.multiply(-self.sersic_constant,
                        np.add(np.power(np.divide(grid_radii, self.effective_radius), 1. / self.sersic_index), -1))))

def intensities_from_grid_radii ( self , grid_radii ) : np . seterr ( all = 'ignore' ) return np . multiply ( self . intensity , np . exp ( np . multiply ( - self . sersic_constant , np . add ( np . power ( np . divide ( grid_radii , self . effective_radius ) , 1. / self . sersic_index ) , - 1 ) ) ) )

Calculate the intensity of the Sersic light profile on a grid of radial coordinates .


def intensities_from_grid_radii(self, grid_radii):
        """Calculate the intensity of the cored-Sersic light profile on a grid of radial coordinates.

        Parameters
        ----------
        grid_radii : float
            The radial distance from the centre of the profile. for each coordinate on the grid.
        """
        return np.multiply(np.multiply(self.intensity_prime, np.power(
            np.add(1, np.power(np.divide(self.radius_break, grid_radii), self.alpha)), (self.gamma / self.alpha))),
                           np.exp(np.multiply(-self.sersic_constant,
                                              (np.power(np.divide(np.add(np.power(grid_radii, self.alpha), (
                                                      self.radius_break ** self.alpha)),
                                                                  (self.effective_radius ** self.alpha)), (
                                                                1.0 / (self.alpha * self.sersic_index)))))))

def intensities_from_grid_radii ( self , grid_radii ) : return np . multiply ( np . multiply ( self . intensity_prime , np . power ( np . add ( 1 , np . power ( np . divide ( self . radius_break , grid_radii ) , self . alpha ) ) , ( self . gamma / self . alpha ) ) ) , np . exp ( np . multiply ( - self . sersic_constant , ( np . power ( np . divide ( np . add ( np . power ( grid_radii , self . alpha ) , ( self . radius_break ** self . alpha ) ) , ( self . effective_radius ** self . alpha ) ) , ( 1.0 / ( self . alpha * self . sersic_index ) ) ) ) ) ) )

Calculate the intensity of the cored - Sersic light profile on a grid of radial coordinates .


def luminosities_of_galaxies_within_circles_in_units(self, radius : dim.Length, unit_luminosity='eps', exposure_time=None):
        """Compute the total luminosity of all galaxies in this plane within a circle of specified radius.

        See *galaxy.light_within_circle* and *light_profiles.light_within_circle* for details \
        of how this is performed.

        Parameters
        ----------
        radius : float
            The radius of the circle to compute the dimensionless mass within.
        units_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        return list(map(lambda galaxy: galaxy.luminosity_within_circle_in_units(
            radius=radius, unit_luminosity=unit_luminosity, kpc_per_arcsec=self.kpc_per_arcsec,
            exposure_time=exposure_time),
                        self.galaxies))

Compute the total luminosity of all galaxies in this plane within a circle of specified radius .


def luminosities_of_galaxies_within_ellipses_in_units(self, major_axis : dim.Length, unit_luminosity='eps',
                                                          exposure_time=None):
        """
        Compute the total luminosity of all galaxies in this plane within a ellipse of specified major-axis.

        The value returned by this integral is dimensionless, and a conversion factor can be specified to convert it \
        to a physical value (e.g. the photometric zeropoint).

        See *galaxy.light_within_ellipse* and *light_profiles.light_within_ellipse* for details
        of how this is performed.

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        units_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        return list(map(lambda galaxy: galaxy.luminosity_within_ellipse_in_units(
            major_axis=major_axis, unit_luminosity=unit_luminosity, kpc_per_arcsec=self.kpc_per_arcsec,
            exposure_time=exposure_time),
                        self.galaxies))

Compute the total luminosity of all galaxies in this plane within a ellipse of specified major - axis .


def masses_of_galaxies_within_circles_in_units(self, radius : dim.Length, unit_mass='angular',
                                                   critical_surface_density=None):
        """Compute the total mass of all galaxies in this plane within a circle of specified radius.

        See *galaxy.angular_mass_within_circle* and *mass_profiles.angular_mass_within_circle* for details
        of how this is performed.

        Parameters
        ----------
        radius : float
            The radius of the circle to compute the dimensionless mass within.
        units_mass : str
            The units the mass is returned in (angular | solMass).
        critical_surface_density : float
            The critical surface mass density of the strong lens configuration, which converts mass from angulalr \
            units to physical units (e.g. solar masses).
        """
        return list(map(lambda galaxy: galaxy.mass_within_circle_in_units(
                        radius=radius, unit_mass=unit_mass, kpc_per_arcsec=self.kpc_per_arcsec,
                        critical_surface_density=critical_surface_density),
                        self.galaxies))

Compute the total mass of all galaxies in this plane within a circle of specified radius .


def masses_of_galaxies_within_ellipses_in_units(self, major_axis : dim.Length, unit_mass='angular',
                                                    critical_surface_density=None):
        """Compute the total mass of all galaxies in this plane within a ellipse of specified major-axis.

        See *galaxy.angular_mass_within_ellipse* and *mass_profiles.angular_mass_within_ellipse* for details \
        of how this is performed.

        Parameters
        ----------
        major_axis : float
            The major-axis radius of the ellipse.
        units_luminosity : str
            The units the luminosity is returned in (eps | counts).
        exposure_time : float
            The exposure time of the observation, which converts luminosity from electrons per second units to counts.
        """
        return list(map(lambda galaxy: galaxy.mass_within_ellipse_in_units(
                        major_axis=major_axis, unit_mass=unit_mass, kpc_per_arcsec=self.kpc_per_arcsec,
                        critical_surface_density=critical_surface_density),
                        self.galaxies))

Compute the total mass of all galaxies in this plane within a ellipse of specified major - axis .


def trace_grid_stack_to_next_plane(self):
        """Trace this plane's grid_stacks to the next plane, using its deflection angles."""

        def minus(grid, deflections):
            return grid - deflections

        return self.grid_stack.map_function(minus, self.deflection_stack)

def trace_grid_stack_to_next_plane ( self ) : def minus ( grid , deflections ) : return grid - deflections return self . grid_stack . map_function ( minus , self . deflection_stack )

Trace this plane s grid_stacks to the next plane using its deflection angles .


def yticks(self):
        """Compute the yticks labels of this grid_stack, used for plotting the y-axis ticks when visualizing an image \
        """
        return np.linspace(np.amin(self.grid_stack.regular[:, 0]), np.amax(self.grid_stack.regular[:, 0]), 4)

def yticks ( self ) : return np . linspace ( np . amin ( self . grid_stack . regular [ : , 0 ] ) , np . amax ( self . grid_stack . regular [ : , 0 ] ) , 4 )

Compute the yticks labels of this grid_stack used for plotting the y - axis ticks when visualizing an image \


def xticks(self):
        """Compute the xticks labels of this grid_stack, used for plotting the x-axis ticks when visualizing an \
        image"""
        return np.linspace(np.amin(self.grid_stack.regular[:, 1]), np.amax(self.grid_stack.regular[:, 1]), 4)

def xticks ( self ) : return np . linspace ( np . amin ( self . grid_stack . regular [ : , 1 ] ) , np . amax ( self . grid_stack . regular [ : , 1 ] ) , 4 )

Compute the xticks labels of this grid_stack used for plotting the x - axis ticks when visualizing an \ image


def unmasked_blurred_image_of_galaxies_from_psf(self, padded_grid_stack, psf):
        """This is a utility function for the function above, which performs the iteration over each plane's galaxies \
        and computes each galaxy's unmasked blurred image.

        Parameters
        ----------
        padded_grid_stack
        psf : ccd.PSF
            The PSF of the image used for convolution.
        """
        return [padded_grid_stack.unmasked_blurred_image_from_psf_and_unmasked_image(
            psf, image) if not galaxy.has_pixelization else None for galaxy, image in
                zip(self.galaxies, self.image_plane_image_1d_of_galaxies)]

This is a utility function for the function above which performs the iteration over each plane s galaxies \ and computes each galaxy s unmasked blurred image .


def trace_to_next_plane(self):
        """Trace the positions to the next plane."""
        return list(map(lambda positions, deflections: np.subtract(positions, deflections),
                        self.positions, self.deflections))

def trace_to_next_plane ( self ) : return list ( map ( lambda positions , deflections : np . subtract ( positions , deflections ) , self . positions , self . deflections ) )


def single_value(cls, value, shape, pixel_scale, origin=(0.0, 0.0)):
        """
        Creates an instance of Array and fills it with a single value

        Parameters
        ----------
        value: float
            The value with which the array should be filled
        shape: (int, int)
            The shape of the array
        pixel_scale: float
            The scale of a pixel in arc seconds

        Returns
        -------
        array: ScaledSquarePixelArray
            An array filled with a single value
        """
        array = np.ones(shape) * value
        return cls(array, pixel_scale, origin)

def single_value ( cls , value , shape , pixel_scale , origin = ( 0.0 , 0.0 ) ) : array = np . ones ( shape ) * value return cls ( array , pixel_scale , origin )


def zoomed_scaled_array_around_mask(self, mask, buffer=1):
        """Extract the 2D region of an array corresponding to the rectangle encompassing all unmasked values.

        This is used to extract and visualize only the region of an image that is used in an analysis.

        Parameters
        ----------
        mask : mask.Mask
            The mask around which the scaled array is extracted.
        buffer : int
            The buffer of pixels around the extraction.
        """
        return self.new_with_array(array=array_util.extracted_array_2d_from_array_2d_and_coordinates(
            array_2d=self,  y0=mask.zoom_region[0]-buffer, y1=mask.zoom_region[1]+buffer,
            x0=mask.zoom_region[2]-buffer, x1=mask.zoom_region[3]+buffer))

Extract the 2D region of an array corresponding to the rectangle encompassing all unmasked values .


def resized_scaled_array_from_array(self, new_shape, new_centre_pixels=None, new_centre_arcsec=None):
        """resized the array to a new shape and at a new origin.

        Parameters
        -----------
        new_shape : (int, int)
            The new two-dimensional shape of the array.
        """
        if new_centre_pixels is None and new_centre_arcsec is None:
            new_centre = (-1, -1)  # In Numba, the input origin must be the same image type as the origin, thus we cannot
            # pass 'None' and instead use the tuple (-1, -1).
        elif new_centre_pixels is not None and new_centre_arcsec is None:
            new_centre = new_centre_pixels
        elif new_centre_pixels is None and new_centre_arcsec is not None:
            new_centre = self.arc_second_coordinates_to_pixel_coordinates(arc_second_coordinates=new_centre_arcsec)
        else:
            raise exc.DataException('You have supplied two centres (pixels and arc-seconds) to the resize scaled'
                                       'array function')

        return self.new_with_array(array=array_util.resized_array_2d_from_array_2d_and_resized_shape(
            array_2d=self, resized_shape=new_shape, origin=new_centre))

resized the array to a new shape and at a new origin .


def fit_lens_data_with_sensitivity_tracers(lens_data, tracer_normal, tracer_sensitive):
    """Fit lens data with a normal tracer and sensitivity tracer, to determine our sensitivity to a selection of \
    galaxy components. This factory automatically determines the type of fit based on the properties of the galaxies \
    in the tracers.

    Parameters
    -----------
    lens_data : lens_data.LensData or lens_data.LensDataHyper
        The lens-images that is fitted.
    tracer_normal : ray_tracing.AbstractTracer
        A tracer whose galaxies have the same model components (e.g. light profiles, mass profiles) as the \
        lens data that we are fitting.
    tracer_sensitive : ray_tracing.AbstractTracerNonStack
        A tracer whose galaxies have the same model components (e.g. light profiles, mass profiles) as the \
        lens data that we are fitting, but also addition components (e.g. mass clumps) which we measure \
        how sensitive we are too.
    """

    if (tracer_normal.has_light_profile and tracer_sensitive.has_light_profile) and \
            (not tracer_normal.has_pixelization and not tracer_sensitive.has_pixelization):
        return SensitivityProfileFit(lens_data=lens_data, tracer_normal=tracer_normal,
                                     tracer_sensitive=tracer_sensitive)

    elif (not tracer_normal.has_light_profile and not tracer_sensitive.has_light_profile) and \
            (tracer_normal.has_pixelization and tracer_sensitive.has_pixelization):
        return SensitivityInversionFit(lens_data=lens_data, tracer_normal=tracer_normal,
                                     tracer_sensitive=tracer_sensitive)
    else:

        raise exc.FittingException('The sensitivity_fit routine did not call a SensitivityFit class - check the '
                                   'properties of the tracers')

Fit lens data with a normal tracer and sensitivity tracer to determine our sensitivity to a selection of \ galaxy components . This factory automatically determines the type of fit based on the properties of the galaxies \ in the tracers .


def unmasked_for_shape_and_pixel_scale(cls, shape, pixel_scale, invert=False):
        """Setup a mask where all pixels are unmasked.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        """
        mask = np.full(tuple(map(lambda d: int(d), shape)), False)
        if invert: mask = np.invert(mask)
        return cls(array=mask, pixel_scale=pixel_scale)

def unmasked_for_shape_and_pixel_scale ( cls , shape , pixel_scale , invert = False ) : mask = np . full ( tuple ( map ( lambda d : int ( d ) , shape ) ) , False ) if invert : mask = np . invert ( mask ) return cls ( array = mask , pixel_scale = pixel_scale )

Setup a mask where all pixels are unmasked .


def circular(cls, shape, pixel_scale, radius_arcsec, centre=(0., 0.), invert=False):
        """Setup a mask where unmasked pixels are within a circle of an input arc second radius and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        radius_arcsec : float
            The radius (in arc seconds) of the circle within which pixels unmasked.
        centre: (float, float)
            The centre of the circle used to mask pixels.
        """
        mask = mask_util.mask_circular_from_shape_pixel_scale_and_radius(shape, pixel_scale, radius_arcsec,
                                                                         centre)
        if invert: mask = np.invert(mask)
        return cls(array=mask.astype('bool'), pixel_scale=pixel_scale)

Setup a mask where unmasked pixels are within a circle of an input arc second radius and centre .


def circular_annular(cls, shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec, centre=(0., 0.),
                         invert=False):
        """Setup a mask where unmasked pixels are within an annulus of input inner and outer arc second radii and \
         centre.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_radius_arcsec : float
            The radius (in arc seconds) of the inner circle outside of which pixels are unmasked.
        outer_radius_arcsec : float
            The radius (in arc seconds) of the outer circle within which pixels are unmasked.
        centre: (float, float)
            The centre of the annulus used to mask pixels.
        """
        mask = mask_util.mask_circular_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec,
                                                                                outer_radius_arcsec, centre)
        if invert: mask = np.invert(mask)
        return cls(array=mask.astype('bool'), pixel_scale=pixel_scale)

Setup a mask where unmasked pixels are within an annulus of input inner and outer arc second radii and \ centre .


def circular_anti_annular(cls, shape, pixel_scale, inner_radius_arcsec, outer_radius_arcsec, outer_radius_2_arcsec,
                              centre=(0., 0.), invert=False):
        """Setup a mask where unmasked pixels are outside an annulus of input inner and outer arc second radii, but \
        within a second outer radius, and at a given centre.

        This mask there has two distinct unmasked regions (an inner circle and outer annulus), with an inner annulus \
        of masked pixels.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_radius_arcsec : float
            The radius (in arc seconds) of the inner circle inside of which pixels are unmasked.
        outer_radius_arcsec : float
            The radius (in arc seconds) of the outer circle within which pixels are masked and outside of which they \
            are unmasked.
        outer_radius_2_arcsec : float
            The radius (in arc seconds) of the second outer circle within which pixels are unmasked and outside of \
            which they masked.
        centre: (float, float)
            The centre of the anti-annulus used to mask pixels.
        """
        mask = mask_util.mask_circular_anti_annular_from_shape_pixel_scale_and_radii(shape, pixel_scale, inner_radius_arcsec,
                                                                                outer_radius_arcsec,
                                                                                outer_radius_2_arcsec, centre)
        if invert: mask = np.invert(mask)
        return cls(array=mask.astype('bool'), pixel_scale=pixel_scale)

Setup a mask where unmasked pixels are outside an annulus of input inner and outer arc second radii but \ within a second outer radius and at a given centre .


def elliptical(cls, shape, pixel_scale, major_axis_radius_arcsec, axis_ratio, phi, centre=(0., 0.),
                   invert=False):
        """ Setup a mask where unmasked pixels are within an ellipse of an input arc second major-axis and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the ellipse within which pixels are unmasked.
        axis_ratio : float
            The axis-ratio of the ellipse within which pixels are unmasked.
        phi : float
            The rotation angle of the ellipse within which pixels are unmasked, (counter-clockwise from the positive \
             x-axis).
        centre: (float, float)
            The centre of the ellipse used to mask pixels.
        """
        mask = mask_util.mask_elliptical_from_shape_pixel_scale_and_radius(shape, pixel_scale, major_axis_radius_arcsec,
                                                                          axis_ratio, phi, centre)
        if invert: mask = np.invert(mask)
        return cls(array=mask.astype('bool'), pixel_scale=pixel_scale)

Setup a mask where unmasked pixels are within an ellipse of an input arc second major - axis and centre .


def elliptical_annular(cls, shape, pixel_scale,inner_major_axis_radius_arcsec, inner_axis_ratio, inner_phi,
                           outer_major_axis_radius_arcsec, outer_axis_ratio, outer_phi, centre=(0.0, 0.0),
                           invert=False):
        """Setup a mask where unmasked pixels are within an elliptical annulus of input inner and outer arc second \
        major-axis and centre.

        Parameters
        ----------
        shape: (int, int)
            The (y,x) shape of the mask in units of pixels.
        pixel_scale: float
            The arc-second to pixel conversion factor of each pixel.
        inner_major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the inner ellipse within which pixels are masked.
        inner_axis_ratio : float
            The axis-ratio of the inner ellipse within which pixels are masked.
        inner_phi : float
            The rotation angle of the inner ellipse within which pixels are masked, (counter-clockwise from the \
            positive x-axis).
        outer_major_axis_radius_arcsec : float
            The major-axis (in arc seconds) of the outer ellipse within which pixels are unmasked.
        outer_axis_ratio : float
            The axis-ratio of the outer ellipse within which pixels are unmasked.
        outer_phi : float
            The rotation angle of the outer ellipse within which pixels are unmasked, (counter-clockwise from the \
            positive x-axis).
        centre: (float, float)
            The centre of the elliptical annuli used to mask pixels.
        """
        mask = mask_util.mask_elliptical_annular_from_shape_pixel_scale_and_radius(shape, pixel_scale,
                           inner_major_axis_radius_arcsec, inner_axis_ratio, inner_phi,
                           outer_major_axis_radius_arcsec, outer_axis_ratio, outer_phi, centre)
        if invert: mask = np.invert(mask)
        return cls(array=mask.astype('bool'), pixel_scale=pixel_scale)

Setup a mask where unmasked pixels are within an elliptical annulus of input inner and outer arc second \ major - axis and centre .


def zoom_region(self):
        """The zoomed rectangular region corresponding to the square encompassing all unmasked values.

        This is used to zoom in on the region of an image that is used in an analysis for visualization."""

        # Have to convert mask to bool for invert function to work.
        where = np.array(np.where(np.invert(self.astype('bool'))))
        y0, x0 = np.amin(where, axis=1)
        y1, x1 = np.amax(where, axis=1)
        return [y0, y1+1, x0, x1+1]

def zoom_region ( self ) : where = np . array ( np . where ( np . invert ( self . astype ( 'bool' ) ) ) ) y0 , x0 = np . amin ( where , axis = 1 ) y1 , x1 = np . amax ( where , axis = 1 ) return [ y0 , y1 + 1 , x0 , x1 + 1 ]

The zoomed rectangular region corresponding to the square encompassing all unmasked values .


def instance_for_arguments(self, arguments):
        """
        Create an instance of the associated class for a set of arguments

        Parameters
        ----------
        arguments: {Prior: value}
            Dictionary mapping_matrix priors to attribute analysis_path and value pairs

        Returns
        -------
            An instance of the class
        """
        profiles = {**{key: value.instance_for_arguments(arguments)
                       for key, value
                       in self.profile_prior_model_dict.items()}, **self.constant_profile_dict}

        try:
            redshift = self.redshift.instance_for_arguments(arguments)
        except AttributeError:
            redshift = self.redshift
        pixelization = self.pixelization.instance_for_arguments(arguments) \
            if isinstance(self.pixelization, pm.PriorModel) \
            else self.pixelization
        regularization = self.regularization.instance_for_arguments(arguments) \
            if isinstance(self.regularization, pm.PriorModel) \
            else self.regularization
        hyper_galaxy = self.hyper_galaxy.instance_for_arguments(arguments) \
            if isinstance(self.hyper_galaxy, pm.PriorModel) \
            else self.hyper_galaxy

        return galaxy.Galaxy(redshift=redshift, pixelization=pixelization, regularization=regularization,
                             hyper_galaxy=hyper_galaxy, **profiles)

def instance_for_arguments ( self , arguments ) : profiles = { ** { key : value . instance_for_arguments ( arguments ) for key , value in self . profile_prior_model_dict . items ( ) } , ** self . constant_profile_dict } try : redshift = self . redshift . instance_for_arguments ( arguments ) except AttributeError : redshift = self . redshift pixelization = self . pixelization . instance_for_arguments ( arguments ) if isinstance ( self . pixelization , pm . PriorModel ) else self . pixelization regularization = self . regularization . instance_for_arguments ( arguments ) if isinstance ( self . regularization , pm . PriorModel ) else self . regularization hyper_galaxy = self . hyper_galaxy . instance_for_arguments ( arguments ) if isinstance ( self . hyper_galaxy , pm . PriorModel ) else self . hyper_galaxy return galaxy . Galaxy ( redshift = redshift , pixelization = pixelization , regularization = regularization , hyper_galaxy = hyper_galaxy , ** profiles )


def gaussian_prior_model_for_arguments(self, arguments):
        """
        Create a new galaxy prior from a set of arguments, replacing the priors of some of this galaxy prior's prior
        models with new arguments.

        Parameters
        ----------
        arguments: dict
            A dictionary mapping_matrix between old priors and their replacements.

        Returns
        -------
        new_model: GalaxyModel
            A model with some or all priors replaced.
        """
        new_model = copy.deepcopy(self)

        for key, value in filter(lambda t: isinstance(t[1], pm.PriorModel), self.__dict__.items()):
            setattr(new_model, key, value.gaussian_prior_model_for_arguments(arguments))

        return new_model

def gaussian_prior_model_for_arguments ( self , arguments ) : new_model = copy . deepcopy ( self ) for key , value in filter ( lambda t : isinstance ( t [ 1 ] , pm . PriorModel ) , self . __dict__ . items ( ) ) : setattr ( new_model , key , value . gaussian_prior_model_for_arguments ( arguments ) ) return new_model

Create a new galaxy prior from a set of arguments replacing the priors of some of this galaxy prior s prior models with new arguments .


def plot_image(
        image, plot_origin=True, mask=None, extract_array_from_mask=False, zoom_around_mask=False,
        should_plot_border=False, positions=None, as_subplot=False,
        units='arcsec', kpc_per_arcsec=None, figsize=(7, 7), aspect='square',
        cmap='jet', norm='linear', norm_min=None, norm_max=None, linthresh=0.05, linscale=0.01,
        cb_ticksize=10, cb_fraction=0.047, cb_pad=0.01, cb_tick_values=None, cb_tick_labels=None,
        title='Image', titlesize=16, xlabelsize=16, ylabelsize=16, xyticksize=16,
        mask_pointsize=10, position_pointsize=30, grid_pointsize=1,
        output_path=None, output_format='show', output_filename='image'):
    """Plot the observed image of the ccd data.

    Set *autolens.data.array.plotters.array_plotters* for a description of all input parameters not described below.

    Parameters
    -----------
    image : ScaledSquarePixelArray
        The image of the data.
    plot_origin : True
        If true, the origin of the data's coordinate system is plotted as a 'x'.
    image_plane_pix_grid : ndarray or data.array.grid_stacks.PixGrid
        If an adaptive pixelization whose pixels are formed by tracing pixels from the data, this plots those pixels \
        over the immage.
    """
    origin = get_origin(array=image, plot_origin=plot_origin)

    array_plotters.plot_array(
        array=image, origin=origin, mask=mask, extract_array_from_mask=extract_array_from_mask,
        zoom_around_mask=zoom_around_mask,
        should_plot_border=should_plot_border, positions=positions, as_subplot=as_subplot,
        units=units, kpc_per_arcsec=kpc_per_arcsec, figsize=figsize, aspect=aspect,
        cmap=cmap, norm=norm, norm_min=norm_min, norm_max=norm_max, linthresh=linthresh, linscale=linscale,
        cb_ticksize=cb_ticksize, cb_fraction=cb_fraction, cb_pad=cb_pad,
        cb_tick_values=cb_tick_values, cb_tick_labels=cb_tick_labels,
        title=title, titlesize=titlesize, xlabelsize=xlabelsize, ylabelsize=ylabelsize, xyticksize=xyticksize,
        mask_pointsize=mask_pointsize, position_pointsize=position_pointsize, grid_pointsize=grid_pointsize,
        output_path=output_path, output_format=output_format, output_filename=output_filename)

def plot_image ( image , plot_origin = True , mask = None , extract_array_from_mask = False , zoom_around_mask = False , should_plot_border = False , positions = None , as_subplot = False , units = 'arcsec' , kpc_per_arcsec = None , figsize = ( 7 , 7 ) , aspect = 'square' , cmap = 'jet' , norm = 'linear' , norm_min = None , norm_max = None , linthresh = 0.05 , linscale = 0.01 , cb_ticksize = 10 , cb_fraction = 0.047 , cb_pad = 0.01 , cb_tick_values = None , cb_tick_labels = None , title = 'Image' , titlesize = 16 , xlabelsize = 16 , ylabelsize = 16 , xyticksize = 16 , mask_pointsize = 10 , position_pointsize = 30 , grid_pointsize = 1 , output_path = None , output_format = 'show' , output_filename = 'image' ) : origin = get_origin ( array = image , plot_origin = plot_origin ) array_plotters . plot_array ( array = image , origin = origin , mask = mask , extract_array_from_mask = extract_array_from_mask , zoom_around_mask = zoom_around_mask , should_plot_border = should_plot_border , positions = positions , as_subplot = as_subplot , units = units , kpc_per_arcsec = kpc_per_arcsec , figsize = figsize , aspect = aspect , cmap = cmap , norm = norm , norm_min = norm_min , norm_max = norm_max , linthresh = linthresh , linscale = linscale , cb_ticksize = cb_ticksize , cb_fraction = cb_fraction , cb_pad = cb_pad , cb_tick_values = cb_tick_values , cb_tick_labels = cb_tick_labels , title = title , titlesize = titlesize , xlabelsize = xlabelsize , ylabelsize = ylabelsize , xyticksize = xyticksize , mask_pointsize = mask_pointsize , position_pointsize = position_pointsize , grid_pointsize = grid_pointsize , output_path = output_path , output_format = output_format , output_filename = output_filename )

Plot the observed image of the ccd data .


def norm_and_check(source_tree, requested):
    """Normalise and check a backend path.

    Ensure that the requested backend path is specified as a relative path,
    and resolves to a location under the given source tree.

    Return an absolute version of the requested path.
    """
    if os.path.isabs(requested):
        raise ValueError("paths must be relative")

    abs_source = os.path.abspath(source_tree)
    abs_requested = os.path.normpath(os.path.join(abs_source, requested))
    # We have to use commonprefix for Python 2.7 compatibility. So we
    # normalise case to avoid problems because commonprefix is a character
    # based comparison :-(
    norm_source = os.path.normcase(abs_source)
    norm_requested = os.path.normcase(abs_requested)
    if os.path.commonprefix([norm_source, norm_requested]) != norm_source:
        raise ValueError("paths must be inside source tree")

    return abs_requested

def
norm_and_check
(
source_tree
,
requested
)
:
if
os
.
path
.
isabs
(
requested
)
:
raise
ValueError
(
"paths must be relative"
)
abs_source
=
os
.
path
.
abspath
(
source_tree
)
abs_requested
=
os
.
path
.
normpath
(
os
.
path
.
join
(
abs_source
,
requested
)
)
norm_source
=
os
.
path
.
normcase
(
abs_source
)
norm_requested
=
os
.
path
.
normcase
(
abs_requested
)
if
os
.
path
.
commonprefix
(
[
norm_source
,
norm_requested
]
)
!=
norm_source
:
raise
ValueError
(
"paths must be inside source tree"
)
return
abs_requested


def contained_in(filename, directory):
    """Test if a file is located within the given directory."""
    filename = os.path.normcase(os.path.abspath(filename))
    directory = os.path.normcase(os.path.abspath(directory))
    return os.path.commonprefix([filename, directory]) == directory

def contained_in ( filename , directory ) : filename = os . path . normcase ( os . path . abspath ( filename ) ) directory = os . path . normcase ( os . path . abspath ( directory ) ) return os . path . commonprefix ( [ filename , directory ] ) == directory

Test if a file is located within the given directory .


def _build_backend():
    """Find and load the build backend"""
    # Add in-tree backend directories to the front of sys.path.
    backend_path = os.environ.get('PEP517_BACKEND_PATH')
    if backend_path:
        extra_pathitems = backend_path.split(os.pathsep)
        sys.path[:0] = extra_pathitems

    ep = os.environ['PEP517_BUILD_BACKEND']
    mod_path, _, obj_path = ep.partition(':')
    try:
        obj = import_module(mod_path)
    except ImportError:
        raise BackendUnavailable(traceback.format_exc())

    if backend_path:
        if not any(
            contained_in(obj.__file__, path)
            for path in extra_pathitems
        ):
            raise BackendInvalid("Backend was not loaded from backend-path")

    if obj_path:
        for path_part in obj_path.split('.'):
            obj = getattr(obj, path_part)
    return obj


def build_sdist(sdist_directory, config_settings):
    """Invoke the mandatory build_sdist hook."""
    backend = _build_backend()
    try:
        return backend.build_sdist(sdist_directory, config_settings)
    except getattr(backend, 'UnsupportedOperation', _DummyException):
        raise GotUnsupportedOperation(traceback.format_exc())

def build_sdist ( sdist_directory , config_settings ) : backend = _build_backend ( ) try : return backend . build_sdist ( sdist_directory , config_settings ) except getattr ( backend , 'UnsupportedOperation' , _DummyException ) : raise GotUnsupportedOperation ( traceback . format_exc ( ) )


def get(self, *args, **kwargs):

        """
        An interface for get requests that handles errors more gracefully to
        prevent data loss
        """

        try:
            req_func = self.session.get if self.session else requests.get
            req = req_func(*args, **kwargs)
            req.raise_for_status()
            self.failed_last = False
            return req

        except requests.exceptions.RequestException as e:
            self.log_error(e)
            for i in range(1, self.num_retries):
                sleep_time = self.retry_rate * i
                self.log_function("Retrying in %s seconds" % sleep_time)
                self._sleep(sleep_time)
                try:
                    req = requests.get(*args, **kwargs)
                    req.raise_for_status()
                    self.log_function("New request successful")
                    return req
                except requests.exceptions.RequestException:
                    self.log_function("New request failed")

            # Allows for the api to ignore one potentially bad request
            if not self.failed_last:
                self.failed_last = True
                raise ApiError(e)
            else:
                raise FatalApiError(e)

def
get
(
self
,
*
args
,
**
kwargs
)
:
try
:
req_func
=
self
.
session
.
get
if
self
.
session
else
requests
.
get
req
=
req_func
(
*
args
,
**
kwargs
)
req
.
raise_for_status
(
)
self
.
failed_last
=
False
return
req
except
requests
.
exceptions
.
RequestException
as
e
:
self
.
log_error
(
e
)
for
i
in
range
(
1
,
self
.
num_retries
)
:
sleep_time
=
self
.
retry_rate
*
i
self
.
log_function
(
"Retrying in %s seconds"
%
sleep_time
)
self
.
_sleep
(
sleep_time
)
try
:
req
=
requests
.
get
(
*
args
,
**
kwargs
)
req
.
raise_for_status
(
)
self
.
log_function
(
"New request successful"
)
return
req
except
requests
.
exceptions
.
RequestException
:
self
.
log_function
(
"New request failed"
)
if
not
self
.
failed_last
:
self
.
failed_last
=
True
raise
ApiError
(
e
)
else
:
raise
FatalApiError
(
e
)