def load_noise_map(noise_map_path, noise_map_hdu, pixel_scale, image, background_noise_map, exposure_time_map,
                   convert_noise_map_from_weight_map, convert_noise_map_from_inverse_noise_map,
                   noise_map_from_image_and_background_noise_map, convert_from_electrons, gain, convert_from_adus):
    """Factory for loading the noise-map from a .fits file.

    This factory also includes a number of routines for converting the noise-map from from other units (e.g. \
    a weight map) or computing the noise-map from other unblurred_image_1d (e.g. the ccd image and background noise-map).

    Parameters
    ----------
    noise_map_path : str
        The path to the noise_map .fits file containing the noise_map (e.g. '/path/to/noise_map.fits')
    noise_map_hdu : int
        The hdu the noise_map is contained in the .fits file specified by *noise_map_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    image : ndarray
        The image-image, which the noise-map can be calculated using.
    background_noise_map : ndarray
        The background noise-map, which the noise-map can be calculated using.
    exposure_time_map : ndarray
        The exposure-time map, which the noise-map can be calculated using.
    convert_noise_map_from_weight_map : bool
        If True, the noise-map loaded from the .fits file is converted from a weight-map to a noise-map (see \
        *NoiseMap.from_weight_map).
    convert_noise_map_from_inverse_noise_map : bool
        If True, the noise-map loaded from the .fits file is converted from an inverse noise-map to a noise-map (see \
        *NoiseMap.from_inverse_noise_map).
    background_noise_map_path : str
        The path and filename of the .fits image containing the background noise-map.
    background_noise_map_hdu : int
        The hdu the background noise-map is contained in the .fits file that *background_noise_map_path* points too.
    convert_background_noise_map_from_weight_map : bool
        If True, the bacground noise-map loaded from the .fits file is converted from a weight-map to a noise-map (see \
        *NoiseMap.from_weight_map).
    convert_background_noise_map_from_inverse_noise_map : bool
        If True, the background noise-map loaded from the .fits file is converted from an inverse noise-map to a \
        noise-map (see *NoiseMap.from_inverse_noise_map).
    noise_map_from_image_and_background_noise_map : bool
        If True, the noise-map is computed from the observed image and background noise-map \
        (see NoiseMap.from_image_and_background_noise_map).
    convert_from_electrons : bool
        If True, the input unblurred_image_1d are in units of electrons and all converted to electrons / second using the exposure \
        time map.
    gain : float
        The image gain, used for convert from ADUs.
    convert_from_adus : bool
        If True, the input unblurred_image_1d are in units of adus and all converted to electrons / second using the exposure \
        time map and gain.
    """
    noise_map_options = sum([convert_noise_map_from_weight_map,
                             convert_noise_map_from_inverse_noise_map,
                             noise_map_from_image_and_background_noise_map])

    if noise_map_options > 1:
        raise exc.DataException('You have specified more than one method to load the noise_map map, e.g.:'
                                   'convert_noise_map_from_weight_map | '
                                   'convert_noise_map_from_inverse_noise_map |'
                                   'noise_map_from_image_and_background_noise_map')

    if noise_map_options == 0 and noise_map_path is not None:
        return NoiseMap.from_fits_with_pixel_scale(file_path=noise_map_path, hdu=noise_map_hdu, pixel_scale=pixel_scale)
    elif convert_noise_map_from_weight_map and noise_map_path is not None:
        weight_map = Array.from_fits(file_path=noise_map_path, hdu=noise_map_hdu)
        return NoiseMap.from_weight_map(weight_map=weight_map, pixel_scale=pixel_scale)
    elif convert_noise_map_from_inverse_noise_map and noise_map_path is not None:
        inverse_noise_map = Array.from_fits(file_path=noise_map_path, hdu=noise_map_hdu)
        return NoiseMap.from_inverse_noise_map(inverse_noise_map=inverse_noise_map, pixel_scale=pixel_scale)
    elif noise_map_from_image_and_background_noise_map:

        if background_noise_map is None:
            raise exc.DataException('Cannot compute the noise-map from the image and background noise_map map if a '
                                       'background noise_map map is not supplied.')

        if not (convert_from_electrons or convert_from_adus) and exposure_time_map is None:
            raise exc.DataException('Cannot compute the noise-map from the image and background noise_map map if an '
                                       'exposure-time (or exposure time map) is not supplied to convert to adus')

        if convert_from_adus and gain is None:
            raise exc.DataException('Cannot compute the noise-map from the image and background noise_map map if a'
                                       'gain is not supplied to convert from adus')

        return NoiseMap.from_image_and_background_noise_map(pixel_scale=pixel_scale, image=image,
                                                            background_noise_map=background_noise_map,
                                                            exposure_time_map=exposure_time_map,
                                                            convert_from_electrons=convert_from_electrons,
                                                            gain=gain, convert_from_adus=convert_from_adus)
    else:
        raise exc.DataException(
            'A noise_map map was not loaded, specify a noise_map_path or option to compute a noise_map map.')

Factory for loading the noise - map from a . fits file .


def load_background_noise_map(background_noise_map_path, background_noise_map_hdu, pixel_scale,
                              convert_background_noise_map_from_weight_map,
                              convert_background_noise_map_from_inverse_noise_map):
    """Factory for loading the background noise-map from a .fits file.

    This factory also includes a number of routines for converting the background noise-map from from other units (e.g. \
    a weight map).

    Parameters
    ----------
    background_noise_map_path : str
        The path to the background_noise_map .fits file containing the background noise-map \
        (e.g. '/path/to/background_noise_map.fits')
    background_noise_map_hdu : int
        The hdu the background_noise_map is contained in the .fits file specified by *background_noise_map_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    convert_background_noise_map_from_weight_map : bool
        If True, the bacground noise-map loaded from the .fits file is converted from a weight-map to a noise-map (see \
        *NoiseMap.from_weight_map).
    convert_background_noise_map_from_inverse_noise_map : bool
        If True, the background noise-map loaded from the .fits file is converted from an inverse noise-map to a \
        noise-map (see *NoiseMap.from_inverse_noise_map).
    """
    background_noise_map_options = sum([convert_background_noise_map_from_weight_map,
                                        convert_background_noise_map_from_inverse_noise_map])

    if background_noise_map_options == 0 and background_noise_map_path is not None:
        return NoiseMap.from_fits_with_pixel_scale(file_path=background_noise_map_path, hdu=background_noise_map_hdu,
                                                   pixel_scale=pixel_scale)
    elif convert_background_noise_map_from_weight_map and background_noise_map_path is not None:
        weight_map = Array.from_fits(file_path=background_noise_map_path, hdu=background_noise_map_hdu)
        return NoiseMap.from_weight_map(weight_map=weight_map, pixel_scale=pixel_scale)
    elif convert_background_noise_map_from_inverse_noise_map and background_noise_map_path is not None:
        inverse_noise_map = Array.from_fits(file_path=background_noise_map_path, hdu=background_noise_map_hdu)
        return NoiseMap.from_inverse_noise_map(inverse_noise_map=inverse_noise_map, pixel_scale=pixel_scale)
    else:
        return None

Factory for loading the background noise - map from a . fits file .


def load_poisson_noise_map(poisson_noise_map_path, poisson_noise_map_hdu, pixel_scale,
                           convert_poisson_noise_map_from_weight_map,
                           convert_poisson_noise_map_from_inverse_noise_map,
                           poisson_noise_map_from_image,
                           image, exposure_time_map, convert_from_electrons, gain, convert_from_adus):
    """Factory for loading the Poisson noise-map from a .fits file.

    This factory also includes a number of routines for converting the Poisson noise-map from from other units (e.g. \
    a weight map) or computing the Poisson noise_map from other unblurred_image_1d (e.g. the ccd image).

    Parameters
    ----------
    poisson_noise_map_path : str
        The path to the poisson_noise_map .fits file containing the Poisson noise-map \
         (e.g. '/path/to/poisson_noise_map.fits')
    poisson_noise_map_hdu : int
        The hdu the poisson_noise_map is contained in the .fits file specified by *poisson_noise_map_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    convert_poisson_noise_map_from_weight_map : bool
        If True, the Poisson noise-map loaded from the .fits file is converted from a weight-map to a noise-map (see \
        *NoiseMap.from_weight_map).
    convert_poisson_noise_map_from_inverse_noise_map : bool
        If True, the Poisson noise-map loaded from the .fits file is converted from an inverse noise-map to a \
        noise-map (see *NoiseMap.from_inverse_noise_map).
    poisson_noise_map_from_image : bool
        If True, the Poisson noise-map is estimated using the image.
    image : ndarray
        The image, which the Poisson noise-map can be calculated using.
    background_noise_map : ndarray
        The background noise-map, which the Poisson noise-map can be calculated using.
    exposure_time_map : ndarray
        The exposure-time map, which the Poisson noise-map can be calculated using.
    convert_from_electrons : bool
        If True, the input unblurred_image_1d are in units of electrons and all converted to electrons / second using the exposure \
        time map.
    gain : float
        The image gain, used for convert from ADUs.
    convert_from_adus : bool
        If True, the input unblurred_image_1d are in units of adus and all converted to electrons / second using the exposure \
        time map and gain.
    """
    poisson_noise_map_options = sum([convert_poisson_noise_map_from_weight_map,
                                     convert_poisson_noise_map_from_inverse_noise_map,
                                     poisson_noise_map_from_image])

    if poisson_noise_map_options == 0 and poisson_noise_map_path is not None:
        return PoissonNoiseMap.from_fits_with_pixel_scale(file_path=poisson_noise_map_path, hdu=poisson_noise_map_hdu,
                                                          pixel_scale=pixel_scale)
    elif poisson_noise_map_from_image:

        if not (convert_from_electrons or convert_from_adus) and exposure_time_map is None:
            raise exc.DataException('Cannot compute the Poisson noise-map from the image if an '
                                       'exposure-time (or exposure time map) is not supplied to convert to adus')

        if convert_from_adus and gain is None:
            raise exc.DataException('Cannot compute the Poisson noise-map from the image if a'
                                       'gain is not supplied to convert from adus')

        return PoissonNoiseMap.from_image_and_exposure_time_map(pixel_scale=pixel_scale, image=image,
                                                                exposure_time_map=exposure_time_map,
                                                                convert_from_electrons=convert_from_electrons,
                                                                gain=gain,
                                                                convert_from_adus=convert_from_adus)

    elif convert_poisson_noise_map_from_weight_map and poisson_noise_map_path is not None:
        weight_map = Array.from_fits(file_path=poisson_noise_map_path, hdu=poisson_noise_map_hdu)
        return PoissonNoiseMap.from_weight_map(weight_map=weight_map, pixel_scale=pixel_scale)
    elif convert_poisson_noise_map_from_inverse_noise_map and poisson_noise_map_path is not None:
        inverse_noise_map = Array.from_fits(file_path=poisson_noise_map_path, hdu=poisson_noise_map_hdu)
        return PoissonNoiseMap.from_inverse_noise_map(inverse_noise_map=inverse_noise_map, pixel_scale=pixel_scale)
    else:
        return None

Factory for loading the Poisson noise - map from a . fits file .


def load_psf(psf_path, psf_hdu, pixel_scale, renormalize=False):
    """Factory for loading the psf from a .fits file.

    Parameters
    ----------
    psf_path : str
        The path to the psf .fits file containing the psf (e.g. '/path/to/psf.fits')
    psf_hdu : int
        The hdu the psf is contained in the .fits file specified by *psf_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    renormalize : bool
        If True, the PSF is renoralized such that all elements sum to 1.0.
    """
    if renormalize:
        return PSF.from_fits_renormalized(file_path=psf_path, hdu=psf_hdu, pixel_scale=pixel_scale)
    if not renormalize:
        return PSF.from_fits_with_scale(file_path=psf_path, hdu=psf_hdu, pixel_scale=pixel_scale)

def load_psf ( psf_path , psf_hdu , pixel_scale , renormalize = False ) : if renormalize : return PSF . from_fits_renormalized ( file_path = psf_path , hdu = psf_hdu , pixel_scale = pixel_scale ) if not renormalize : return PSF . from_fits_with_scale ( file_path = psf_path , hdu = psf_hdu , pixel_scale = pixel_scale )

Factory for loading the psf from a . fits file .


def load_exposure_time_map(exposure_time_map_path, exposure_time_map_hdu, pixel_scale, shape, exposure_time,
                           exposure_time_map_from_inverse_noise_map, inverse_noise_map):
    """Factory for loading the exposure time map from a .fits file.

    This factory also includes a number of routines for computing the exposure-time map from other unblurred_image_1d \
    (e.g. the background noise-map).

    Parameters
    ----------
    exposure_time_map_path : str
        The path to the exposure_time_map .fits file containing the exposure time map \
        (e.g. '/path/to/exposure_time_map.fits')
    exposure_time_map_hdu : int
        The hdu the exposure_time_map is contained in the .fits file specified by *exposure_time_map_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    shape : (int, int)
        The shape of the image, required if a single value is used to calculate the exposure time map.
    exposure_time : float
        The exposure-time used to compute the expsure-time map if only a single value is used.
    exposure_time_map_from_inverse_noise_map : bool
        If True, the exposure-time map is computed from the background noise_map map \
        (see *ExposureTimeMap.from_background_noise_map*)
    inverse_noise_map : ndarray
        The background noise-map, which the Poisson noise-map can be calculated using.
    """
    exposure_time_map_options = sum([exposure_time_map_from_inverse_noise_map])

    if exposure_time is not None and exposure_time_map_path is not None:
        raise exc.DataException(
            'You have supplied both a exposure_time_map_path to an exposure time map and an exposure time. Only'
            'one quantity should be supplied.')

    if exposure_time_map_options == 0:

        if exposure_time is not None and exposure_time_map_path is None:
            return ExposureTimeMap.single_value(value=exposure_time, pixel_scale=pixel_scale, shape=shape)
        elif exposure_time is None and exposure_time_map_path is not None:
            return ExposureTimeMap.from_fits_with_pixel_scale(file_path=exposure_time_map_path,
                                                              hdu=exposure_time_map_hdu, pixel_scale=pixel_scale)

    else:

        if exposure_time_map_from_inverse_noise_map:
            return ExposureTimeMap.from_exposure_time_and_inverse_noise_map(pixel_scale=pixel_scale,
                                                                            exposure_time=exposure_time,
                                                                            inverse_noise_map=inverse_noise_map)

Factory for loading the exposure time map from a . fits file .


def load_background_sky_map(background_sky_map_path, background_sky_map_hdu, pixel_scale):
    """Factory for loading the background sky from a .fits file.

    Parameters
    ----------
    background_sky_map_path : str
        The path to the background_sky_map .fits file containing the background sky map \
        (e.g. '/path/to/background_sky_map.fits').
    background_sky_map_hdu : int
        The hdu the background_sky_map is contained in the .fits file specified by *background_sky_map_path*.
    pixel_scale : float
        The size of each pixel in arc seconds.
    """
    if background_sky_map_path is not None:
        return ScaledSquarePixelArray.from_fits_with_pixel_scale(file_path=background_sky_map_path,
                                                                 hdu=background_sky_map_hdu, pixel_scale=pixel_scale)
    else:
        return None

def load_background_sky_map ( background_sky_map_path , background_sky_map_hdu , pixel_scale ) : if background_sky_map_path is not None : return ScaledSquarePixelArray . from_fits_with_pixel_scale ( file_path = background_sky_map_path , hdu = background_sky_map_hdu , pixel_scale = pixel_scale ) else : return None

Factory for loading the background sky from a . fits file .


def load_positions(positions_path):
    """Load the positions of an image.

    Positions correspond to a set of pixels in the lensed source galaxy that are anticipated to come from the same \
    multiply-imaged region of the source-plane. Mass models which do not trace the pixels within a threshold value of \
    one another are resampled during the non-linear search.

    Positions are stored in a .dat file, where each line of the file gives a list of list of (y,x) positions which \
    correspond to the same region of the source-plane. Thus, multiple source-plane regions can be input over multiple \
    lines of the same positions file.

    Parameters
    ----------
    positions_path : str
        The path to the positions .dat file containing the positions (e.g. '/path/to/positions.dat')
    """
    with open(positions_path) as f:
        position_string = f.readlines()

    positions = []

    for line in position_string:
        position_list = ast.literal_eval(line)
        positions.append(position_list)

    return positions

def load_positions ( positions_path ) : with open ( positions_path ) as f : position_string = f . readlines ( ) positions = [ ] for line in position_string : position_list = ast . literal_eval ( line ) positions . append ( position_list ) return positions


def output_positions(positions, positions_path):
    """Output the positions of an image to a positions.dat file.

    Positions correspond to a set of pixels in the lensed source galaxy that are anticipated to come from the same \
    multiply-imaged region of the source-plane. Mass models which do not trace the pixels within a threshold value of \
    one another are resampled during the non-linear search.

    Positions are stored in a .dat file, where each line of the file gives a list of list of (y,x) positions which \
    correspond to the same region of the source-plane. Thus, multiple source-plane regions can be input over multiple \
    lines of the same positions file.

    Parameters
    ----------
    positions : [[[]]]
        The lists of positions (e.g. [[[1.0, 1.0], [2.0, 2.0]], [[3.0, 3.0], [4.0, 4.0]]])
    positions_path : str
        The path to the positions .dat file containing the positions (e.g. '/path/to/positions.dat')
    """
    with open(positions_path, 'w') as f:
        for position in positions:
            f.write("%s\n" % position)

def output_positions ( positions , positions_path ) : with open ( positions_path , 'w' ) as f : for position in positions : f . write ( "%s\n" % position )

Output the positions of an image to a positions . dat file .


def signal_to_noise_map(self):
        """The estimated signal-to-noise_maps mappers of the image."""
        signal_to_noise_map = np.divide(self.image, self.noise_map)
        signal_to_noise_map[signal_to_noise_map < 0] = 0
        return signal_to_noise_map

def signal_to_noise_map ( self ) : signal_to_noise_map = np . divide ( self . image , self . noise_map ) signal_to_noise_map [ signal_to_noise_map < 0 ] = 0 return signal_to_noise_map

The estimated signal - to - noise_maps mappers of the image .


def absolute_signal_to_noise_map(self):
        """The estimated absolute_signal-to-noise_maps mappers of the image."""
        return np.divide(np.abs(self.image), self.noise_map)

def absolute_signal_to_noise_map ( self ) : return np . divide ( np . abs ( self . image ) , self . noise_map )

The estimated absolute_signal - to - noise_maps mappers of the image .


def from_weight_map(cls, pixel_scale, weight_map):
        """Setup the noise-map from a weight map, which is a form of noise-map that comes via HST image-reduction and \
        the software package MultiDrizzle.

        The variance in each pixel is computed as:

        Variance = 1.0 / sqrt(weight_map).

        The weight map may contain zeros, in which cause the variances are converted to large values to omit them from \
        the analysis.

        Parameters
        -----------
        pixel_scale : float
            The size of each pixel in arc seconds.
        weight_map : ndarray
            The weight-value of each pixel which is converted to a variance.
        """
        np.seterr(divide='ignore')
        noise_map = 1.0 / np.sqrt(weight_map)
        noise_map[noise_map == np.inf] = 1.0e8
        return NoiseMap(array=noise_map, pixel_scale=pixel_scale)

def from_weight_map ( cls , pixel_scale , weight_map ) : np . seterr ( divide = 'ignore' ) noise_map = 1.0 / np . sqrt ( weight_map ) noise_map [ noise_map == np . inf ] = 1.0e8 return NoiseMap ( array = noise_map , pixel_scale = pixel_scale )

Setup the noise - map from a weight map which is a form of noise - map that comes via HST image - reduction and \ the software package MultiDrizzle .


def from_inverse_noise_map(cls, pixel_scale, inverse_noise_map):
        """Setup the noise-map from an root-mean square standard deviation map, which is a form of noise-map that \
        comes via HST image-reduction and the software package MultiDrizzle.

        The variance in each pixel is computed as:

        Variance = 1.0 / inverse_std_map.

        The weight map may contain zeros, in which cause the variances are converted to large values to omit them from \
        the analysis.

        Parameters
        -----------
        pixel_scale : float
            The size of each pixel in arc seconds.
        inverse_noise_map : ndarray
            The inverse noise_map value of each pixel which is converted to a variance.
        """
        noise_map = 1.0 / inverse_noise_map
        return NoiseMap(array=noise_map, pixel_scale=pixel_scale)

Setup the noise - map from an root - mean square standard deviation map which is a form of noise - map that \ comes via HST image - reduction and the software package MultiDrizzle .


def simulate_as_gaussian(cls, shape, pixel_scale, sigma, centre=(0.0, 0.0), axis_ratio=1.0, phi=0.0):
        """Simulate the PSF as an elliptical Gaussian profile."""
        from autolens.model.profiles.light_profiles import EllipticalGaussian
        gaussian = EllipticalGaussian(centre=centre, axis_ratio=axis_ratio, phi=phi, intensity=1.0, sigma=sigma)
        grid_1d = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(mask=np.full(shape, False),
                                                                                pixel_scales=(
                                                                                pixel_scale, pixel_scale))
        gaussian_1d = gaussian.intensities_from_grid(grid=grid_1d)
        gaussian_2d = mapping_util.map_unmasked_1d_array_to_2d_array_from_array_1d_and_shape(array_1d=gaussian_1d,
                                                                                shape=shape)
        return PSF(array=gaussian_2d, pixel_scale=pixel_scale, renormalize=True)

Simulate the PSF as an elliptical Gaussian profile .


def from_fits_renormalized(cls, file_path, hdu, pixel_scale):
        """Loads a PSF from fits and renormalizes it

        Parameters
        ----------
        pixel_scale
        file_path: String
            The path to the file containing the PSF
        hdu : int
            The HDU the PSF is stored in the .fits file.

        Returns
        -------
        psf: PSF
            A renormalized PSF instance
        """
        psf = PSF.from_fits_with_scale(file_path, hdu, pixel_scale)
        psf[:, :] = np.divide(psf, np.sum(psf))
        return psf

def from_fits_renormalized ( cls , file_path , hdu , pixel_scale ) : psf = PSF . from_fits_with_scale ( file_path , hdu , pixel_scale ) psf [ : , : ] = np . divide ( psf , np . sum ( psf ) ) return psf


def from_fits_with_scale(cls, file_path, hdu, pixel_scale):
        """
        Loads the PSF from a .fits file.

        Parameters
        ----------
        pixel_scale
        file_path: String
            The path to the file containing the PSF
        hdu : int
            The HDU the PSF is stored in the .fits file.
        """
        return cls(array=array_util.numpy_array_2d_from_fits(file_path, hdu), pixel_scale=pixel_scale)

def from_fits_with_scale ( cls , file_path , hdu , pixel_scale ) : return cls ( array = array_util . numpy_array_2d_from_fits ( file_path , hdu ) , pixel_scale = pixel_scale )


def new_psf_with_renormalized_array(self):
        """Renormalize the PSF such that its data_vector values sum to unity."""
        return PSF(array=self, pixel_scale=self.pixel_scale, renormalize=True)

def new_psf_with_renormalized_array ( self ) : return PSF ( array = self , pixel_scale = self . pixel_scale , renormalize = True )

Renormalize the PSF such that its data_vector values sum to unity .


def convolve(self, array):
        """
        Convolve an array with this PSF

        Parameters
        ----------
        image : ndarray
            An array representing the image the PSF is convolved with.

        Returns
        -------
        convolved_image : ndarray
            An array representing the image after convolution.

        Raises
        ------
        KernelException if either PSF psf dimension is odd
        """
        if self.shape[0] % 2 == 0 or self.shape[1] % 2 == 0:
            raise exc.KernelException("PSF Kernel must be odd")

        return scipy.signal.convolve2d(array, self, mode='same')

def
convolve
(
self
,
array
)
:
if
self
.
shape
[
0
]
%
2
==
0
or
self
.
shape
[
1
]
%
2
==
0
:
raise
exc
.
KernelException
(
"PSF Kernel must be odd"
)
return
scipy
.
signal
.
convolve2d
(
array
,
self
,
mode
=
'same'
)


def geometry_from_grid(self, grid, buffer=1e-8):
        """Determine the geometry of the rectangular grid, by overlaying it over a grid of coordinates such that its \
         outer-most pixels align with the grid's outer most coordinates plus a small buffer.

        Parameters
        -----------
        grid : ndarray
            The (y,x) grid of coordinates over which the rectangular pixelization is placed to determine its geometry.
        buffer : float
            The size the pixelization is buffered relative to the grid.
        """
        y_min = np.min(grid[:, 0]) - buffer
        y_max = np.max(grid[:, 0]) + buffer
        x_min = np.min(grid[:, 1]) - buffer
        x_max = np.max(grid[:, 1]) + buffer
        pixel_scales = (float((y_max - y_min) / self.shape[0]), float((x_max - x_min) / self.shape[1]))
        origin = ((y_max + y_min) / 2.0, (x_max + x_min) / 2.0)
        pixel_neighbors, pixel_neighbors_size = self.neighbors_from_pixelization()
        return self.Geometry(shape=self.shape, pixel_scales=pixel_scales, origin=origin,
                             pixel_neighbors=pixel_neighbors, pixel_neighbors_size=pixel_neighbors_size)

def geometry_from_grid ( self , grid , buffer = 1e-8 ) : y_min = np . min ( grid [ : , 0 ] ) - buffer y_max = np . max ( grid [ : , 0 ] ) + buffer x_min = np . min ( grid [ : , 1 ] ) - buffer x_max = np . max ( grid [ : , 1 ] ) + buffer pixel_scales = ( float ( ( y_max - y_min ) / self . shape [ 0 ] ) , float ( ( x_max - x_min ) / self . shape [ 1 ] ) ) origin = ( ( y_max + y_min ) / 2.0 , ( x_max + x_min ) / 2.0 ) pixel_neighbors , pixel_neighbors_size = self . neighbors_from_pixelization ( ) return self . Geometry ( shape = self . shape , pixel_scales = pixel_scales , origin = origin , pixel_neighbors = pixel_neighbors , pixel_neighbors_size = pixel_neighbors_size )

Determine the geometry of the rectangular grid by overlaying it over a grid of coordinates such that its \ outer - most pixels align with the grid s outer most coordinates plus a small buffer .


def geometry_from_grid(self, grid, pixel_centres, pixel_neighbors, pixel_neighbors_size, buffer=1e-8):
        """Determine the geometry of the Voronoi pixelization, by alligning it with the outer-most coordinates on a \
        grid plus a small buffer.

        Parameters
        -----------
        grid : ndarray
            The (y,x) grid of coordinates which determine the Voronoi pixelization's geometry.
        pixel_centres : ndarray
            The (y,x) centre of every Voronoi pixel in arc-seconds.
        origin : (float, float)
            The arc-second origin of the Voronoi pixelization's coordinate system.
        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 : ndarrayy
            An array of length (voronoi_pixels) which gives the number of neighbors of every pixel in the \
            Voronoi grid.
        """
        y_min = np.min(grid[:, 0]) - buffer
        y_max = np.max(grid[:, 0]) + buffer
        x_min = np.min(grid[:, 1]) - buffer
        x_max = np.max(grid[:, 1]) + buffer
        shape_arcsec = (y_max - y_min, x_max - x_min)
        origin = ((y_max + y_min) / 2.0, (x_max + x_min) / 2.0)
        return self.Geometry(shape_arcsec=shape_arcsec, pixel_centres=pixel_centres, origin=origin,
                             pixel_neighbors=pixel_neighbors, pixel_neighbors_size=pixel_neighbors_size)

def geometry_from_grid ( self , grid , pixel_centres , pixel_neighbors , pixel_neighbors_size , buffer = 1e-8 ) : y_min = np . min ( grid [ : , 0 ] ) - buffer y_max = np . max ( grid [ : , 0 ] ) + buffer x_min = np . min ( grid [ : , 1 ] ) - buffer x_max = np . max ( grid [ : , 1 ] ) + buffer shape_arcsec = ( y_max - y_min , x_max - x_min ) origin = ( ( y_max + y_min ) / 2.0 , ( x_max + x_min ) / 2.0 ) return self . Geometry ( shape_arcsec = shape_arcsec , pixel_centres = pixel_centres , origin = origin , pixel_neighbors = pixel_neighbors , pixel_neighbors_size = pixel_neighbors_size )

Determine the geometry of the Voronoi pixelization by alligning it with the outer - most coordinates on a \ grid plus a small buffer .


def voronoi_from_pixel_centers(pixel_centers):
        """Compute the Voronoi grid of the pixelization, using the pixel centers.

        Parameters
        ----------
        pixel_centers : ndarray
            The (y,x) centre of every Voronoi pixel.
        """
        return scipy.spatial.Voronoi(np.asarray([pixel_centers[:, 1], pixel_centers[:, 0]]).T,
                                     qhull_options='Qbb Qc Qx Qm')

def
voronoi_from_pixel_centers
(
pixel_centers
)
:
return
scipy
.
spatial
.
Voronoi
(
np
.
asarray
(
[
pixel_centers
[
:
,
1
]
,
pixel_centers
[
:
,
0
]
]
)
.
T
,
qhull_options
=
'Qbb Qc Qx Qm'
)

Compute the Voronoi grid of the pixelization using the pixel centers .


def neighbors_from_pixelization(self, pixels, ridge_points):
        """Compute the neighbors of every Voronoi pixel as an ndarray of the pixel index's each pixel shares a \
        vertex with.

        The ridge points of the Voronoi grid are used to derive this.

        Parameters
        ----------
        ridge_points : scipy.spatial.Voronoi.ridge_points
            Each Voronoi-ridge (two indexes representing a pixel mapping_matrix).
        """
        return pixelization_util.voronoi_neighbors_from_pixels_and_ridge_points(pixels=pixels,
                                                                                ridge_points=np.asarray(ridge_points))

Compute the neighbors of every Voronoi pixel as an ndarray of the pixel index s each pixel shares a \ vertex with .


def set_xy_labels(units, kpc_per_arcsec, xlabelsize, ylabelsize, xyticksize):
    """Set the x and y labels of the figure, and set the fontsize of those labels.

    The x and y labels are always the distance scales, thus the labels are either arc-seconds or kpc and depend on the \
    units the figure is plotted in.

    Parameters
    -----------
    units : str
        The units of the y / x axis of the plots, in arc-seconds ('arcsec') or kiloparsecs ('kpc').
    kpc_per_arcsec : float
        The conversion factor between arc-seconds and kiloparsecs, required to plot the units in kpc.
    xlabelsize : int
        The fontsize of the x axes label.
    ylabelsize : int
        The fontsize of the y axes label.
    xyticksize : int
        The font size of the x and y ticks on the figure axes.
    """
    if units in 'arcsec' or kpc_per_arcsec is None:

        plt.xlabel('x (arcsec)', fontsize=xlabelsize)
        plt.ylabel('y (arcsec)', fontsize=ylabelsize)

    elif units in 'kpc':

        plt.xlabel('x (kpc)', fontsize=xlabelsize)
        plt.ylabel('y (kpc)', fontsize=ylabelsize)

    else:
        raise exc.PlottingException('The units supplied to the plotted are not a valid string (must be pixels | '
                                     'arcsec | kpc)')

    plt.tick_params(labelsize=xyticksize)

Set the x and y labels of the figure and set the fontsize of those labels .


def grid_interpolate(func):
    """
    Decorate a profile method that accepts a coordinate grid and returns a data grid.

    If an interpolator attribute is associated with the input grid then that interpolator is used to down sample the
    coordinate grid prior to calling the function and up sample the result of the function.

    If no interpolator attribute is associated with the input grid then the function is called as normal.

    Parameters
    ----------
    func
        Some method that accepts a grid

    Returns
    -------
    decorated_function
        The function with optional interpolation
    """

    @wraps(func)
    def wrapper(profile, grid, grid_radial_minimum=None, *args, **kwargs):
        if hasattr(grid, "interpolator"):
            interpolator = grid.interpolator
            if grid.interpolator is not None:
                values = func(profile, interpolator.interp_grid, grid_radial_minimum, *args, **kwargs)
                if values.ndim == 1:
                    return interpolator.interpolated_values_from_values(values=values)
                elif values.ndim == 2:
                    y_values = interpolator.interpolated_values_from_values(values=values[:, 0])
                    x_values = interpolator.interpolated_values_from_values(values=values[:, 1])
                    return np.asarray([y_values, x_values]).T
        return func(profile, grid, grid_radial_minimum, *args, **kwargs)

    return wrapper

def grid_interpolate ( func ) : @ wraps ( func ) def wrapper ( profile , grid , grid_radial_minimum = None , * args , * * kwargs ) : if hasattr ( grid , "interpolator" ) : interpolator = grid . interpolator if grid . interpolator is not None : values = func ( profile , interpolator . interp_grid , grid_radial_minimum , * args , * * kwargs ) if values . ndim == 1 : return interpolator . interpolated_values_from_values ( values = values ) elif values . ndim == 2 : y_values = interpolator . interpolated_values_from_values ( values = values [ : , 0 ] ) x_values = interpolator . interpolated_values_from_values ( values = values [ : , 1 ] ) return np . asarray ( [ y_values , x_values ] ) . T return func ( profile , grid , grid_radial_minimum , * args , * * kwargs ) return wrapper

Decorate a profile method that accepts a coordinate grid and returns a data grid .


def unmasked_blurred_image_from_psf_and_unmasked_image(self, psf, unmasked_image_1d):
        """For a padded grid-stack and psf, compute an unmasked blurred image from an unmasked unblurred image.

        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.

        Parameters
        ----------
        psf : ccd.PSF
            The PSF of the image used for convolution.
        unmasked_image_1d : ndarray
            The 1D unmasked image which is blurred.
        """
        blurred_image_1d = self.regular.convolve_array_1d_with_psf(padded_array_1d=unmasked_image_1d,
                                                                   psf=psf)

        return self.regular.scaled_array_2d_from_array_1d(array_1d=blurred_image_1d)

For a padded grid - stack and psf compute an unmasked blurred image from an unmasked unblurred image .


def grid_stack_from_mask_sub_grid_size_and_psf_shape(cls, mask, sub_grid_size, psf_shape):
        """Setup a grid-stack of grid_stack from a mask, sub-grid size and psf-shape.

        Parameters
        -----------
        mask : Mask
            The mask whose unmasked pixels (*False*) are used to generate the grid-stack's grid_stack.
        sub_grid_size : int
            The size of a sub-pixel's sub-grid (sub_grid_size x sub_grid_size).
        psf_shape : (int, int)
            the shape of the PSF used in the analysis, which defines the mask's blurring-region.
        """
        regular_grid = RegularGrid.from_mask(mask)
        sub_grid = SubGrid.from_mask_and_sub_grid_size(mask, sub_grid_size)
        blurring_grid = RegularGrid.blurring_grid_from_mask_and_psf_shape(mask, psf_shape)
        return GridStack(regular_grid, sub_grid, blurring_grid)

Setup a grid - stack of grid_stack from a mask sub - grid size and psf - shape .


def from_shape_pixel_scale_and_sub_grid_size(cls, shape, pixel_scale, sub_grid_size=2):
        """Setup a grid-stack of grid_stack from a 2D array shape, a pixel scale and a sub-grid size.

        This grid corresponds to a fully unmasked 2D array.

        Parameters
        -----------
        shape : (int, int)
            The 2D shape of the array, where all pixels are used to generate the grid-stack's grid_stack.
        pixel_scale : float
            The size of each pixel in arc seconds.
        sub_grid_size : int
            The size of a sub-pixel's sub-grid (sub_grid_size x sub_grid_size).
        """
        regular_grid = RegularGrid.from_shape_and_pixel_scale(shape=shape, pixel_scale=pixel_scale)
        sub_grid = SubGrid.from_shape_pixel_scale_and_sub_grid_size(shape=shape, pixel_scale=pixel_scale,
                                                                    sub_grid_size=sub_grid_size)
        blurring_grid = np.array([[0.0, 0.0]])
        return GridStack(regular_grid, sub_grid, blurring_grid)

Setup a grid - stack of grid_stack from a 2D array shape a pixel scale and a sub - grid size . This grid corresponds to a fully unmasked 2D array .


def padded_grid_stack_from_mask_sub_grid_size_and_psf_shape(cls, mask, sub_grid_size, psf_shape):
        """Setup a grid-stack of masked grid_stack from a mask,  sub-grid size and psf-shape.

        Parameters
        -----------
        mask : Mask
            The mask whose masked pixels the grid-stack are setup using.
        sub_grid_size : int
            The size of a sub-pixels sub-grid (sub_grid_size x sub_grid_size).
        psf_shape : (int, int)
            The shape of the PSF used in the analysis, which defines the mask's blurring-region.
        """
        regular_padded_grid = PaddedRegularGrid.padded_grid_from_shape_psf_shape_and_pixel_scale(
            shape=mask.shape,
            psf_shape=psf_shape,
            pixel_scale=mask.pixel_scale)
        sub_padded_grid = PaddedSubGrid.padded_grid_from_mask_sub_grid_size_and_psf_shape(mask=mask,
                                                                                sub_grid_size=sub_grid_size,
                                                                                psf_shape=psf_shape)
        # TODO : The blurring grid is not used when the grid mapper is called, the 0.0 0.0 stops errors inr ayT_racing
        # TODO : implement a more explicit solution
        return GridStack(regular=regular_padded_grid, sub=sub_padded_grid, blurring=np.array([[0.0, 0.0]]))

Setup a grid - stack of masked grid_stack from a mask sub - grid size and psf - shape .


def map_function(self, func, *arg_lists):
        """Map a function to all grid_stack in a grid-stack"""
        return GridStack(*[func(*args) for args in zip(self, *arg_lists)])

def map_function ( self , func , * arg_lists ) : return GridStack ( * [ func ( * args ) for args in zip ( self , * arg_lists ) ] )

Map a function to all grid_stack in a grid - stack


def array_2d_from_array_1d(self, array_1d):
        """ Map a 1D array the same dimension as the grid to its original masked 2D array.

        Parameters
        -----------
        array_1d : ndarray
            The 1D array which is mapped to its masked 2D array.
        """
        return mapping_util.map_masked_1d_array_to_2d_array_from_array_1d_shape_and_one_to_two(
            array_1d=array_1d, shape=self.mask.shape, one_to_two=self.mask.masked_grid_index_to_pixel)

Map a 1D array the same dimension as the grid to its original masked 2D array .


def scaled_array_2d_from_array_1d(self, array_1d):
        """ Map a 1D array the same dimension as the grid to its original masked 2D array and return it as a scaled \
        array.

        Parameters
        -----------
        array_1d : ndarray
            The 1D array of which is mapped to a 2D scaled array.
        """
        return scaled_array.ScaledSquarePixelArray(array=self.array_2d_from_array_1d(array_1d),
                                                   pixel_scale=self.mask.pixel_scale,
                                                   origin=self.mask.origin)

def scaled_array_2d_from_array_1d ( self , array_1d ) : return scaled_array . ScaledSquarePixelArray ( array = self . array_2d_from_array_1d ( array_1d ) , pixel_scale = self . mask . pixel_scale , origin = self . mask . origin )

Map a 1D array the same dimension as the grid to its original masked 2D array and return it as a scaled \ array .


def yticks(self):
        """Compute the yticks labels of this grid, used for plotting the y-axis ticks when visualizing a regular"""
        return np.linspace(np.min(self[:, 0]), np.max(self[:, 0]), 4)

def yticks ( self ) : return np . linspace ( np . min ( self [ : , 0 ] ) , np . max ( self [ : , 0 ] ) , 4 )

Compute the yticks labels of this grid used for plotting the y - axis ticks when visualizing a regular


def xticks(self):
        """Compute the xticks labels of this grid, used for plotting the x-axis ticks when visualizing a regular"""
        return np.linspace(np.min(self[:, 1]), np.max(self[:, 1]), 4)

def xticks ( self ) : return np . linspace ( np . min ( self [ : , 1 ] ) , np . max ( self [ : , 1 ] ) , 4 )

Compute the xticks labels of this grid used for plotting the x - axis ticks when visualizing a regular


def regular_data_1d_from_sub_data_1d(self, sub_array_1d):
        """For an input sub-gridded array, map its hyper-values from the sub-gridded values to a 1D regular grid of \
        values by summing each set of each set of sub-pixels values and dividing by the total number of sub-pixels.

        Parameters
        -----------
        sub_array_1d : ndarray
            A 1D sub-gridded array of values (e.g. the intensities, surface-densities, potential) which is mapped to
            a 1d regular array.
        """
        return np.multiply(self.sub_grid_fraction, sub_array_1d.reshape(-1, self.sub_grid_length).sum(axis=1))

def regular_data_1d_from_sub_data_1d ( self , sub_array_1d ) : return np . multiply ( self . sub_grid_fraction , sub_array_1d . reshape ( - 1 , self . sub_grid_length ) . sum ( axis = 1 ) )

For an input sub - gridded array map its hyper - values from the sub - gridded values to a 1D regular grid of \ values by summing each set of each set of sub - pixels values and dividing by the total number of sub - pixels .


def unmasked_sparse_to_sparse(self):
        """The 1D index mappings between the unmasked sparse-grid and masked sparse grid."""

        return mapping_util.unmasked_sparse_to_sparse_from_mask_and_pixel_centres(
            mask=self.regular_grid.mask,
            unmasked_sparse_grid_pixel_centres=self.unmasked_sparse_grid_pixel_centres,
            total_sparse_pixels=self.total_sparse_pixels).astype(
            'int')

The 1D index mappings between the unmasked sparse - grid and masked sparse grid .


def sparse_to_unmasked_sparse(self):
        """The 1D index mappings between the masked sparse-grid and unmasked sparse grid."""
        return mapping_util.sparse_to_unmasked_sparse_from_mask_and_pixel_centres(
            total_sparse_pixels=self.total_sparse_pixels, mask=self.regular_grid.mask,
            unmasked_sparse_grid_pixel_centres=self.unmasked_sparse_grid_pixel_centres).astype('int')

The 1D index mappings between the masked sparse - grid and unmasked sparse grid .


def regular_to_sparse(self):
        """The 1D index mappings between the regular-grid and masked sparse-grid."""

        return mapping_util.regular_to_sparse_from_sparse_mappings(
            regular_to_unmasked_sparse=self.regular_to_unmasked_sparse,
            unmasked_sparse_to_sparse=self.unmasked_sparse_to_sparse).astype('int')

def regular_to_sparse ( self ) : return mapping_util . regular_to_sparse_from_sparse_mappings ( regular_to_unmasked_sparse = self . regular_to_unmasked_sparse , unmasked_sparse_to_sparse = self . unmasked_sparse_to_sparse ) . astype ( 'int' )

The 1D index mappings between the regular - grid and masked sparse - grid .


def padded_grid_from_shape_psf_shape_and_pixel_scale(cls, shape, psf_shape, pixel_scale):
        """Setup a regular padded grid from a 2D array shape, psf-shape and pixel-scale.

        The center of every pixel is used to setup the grid's (y,x) arc-second coordinates, including padded pixels \
        which are beyond the input shape but will blurred light into the 2D array's shape due to the psf.

        Parameters
        ----------
        shape : (int, int)
            The (y,x) shape of the masked-grid's 2D image in units of pixels.
        psf_shape : (int, int)
           The shape of the psf which defines the blurring region and therefore size of padding.
        pixel_scale : float
            The scale of each pixel in arc seconds
        """
        padded_shape = (shape[0] + psf_shape[0] - 1, shape[1] + psf_shape[1] - 1)
        padded_regular_grid = grid_util.regular_grid_1d_masked_from_mask_pixel_scales_and_origin(
            mask=np.full(padded_shape, False), pixel_scales=(pixel_scale, pixel_scale))
        padded_mask = msk.Mask.unmasked_for_shape_and_pixel_scale(shape=padded_shape, pixel_scale=pixel_scale)
        return PaddedRegularGrid(arr=padded_regular_grid, mask=padded_mask, image_shape=shape)

Setup a regular padded grid from a 2D array shape psf - shape and pixel - scale .


def padded_blurred_image_2d_from_padded_image_1d_and_psf(self, padded_image_1d, psf):
        """Compute a 2D padded blurred image from a 1D padded image.

        Parameters
        ----------
        padded_image_1d : ndarray
            A 1D unmasked image which is blurred with the PSF.
        psf : ndarray
            An array describing the PSF kernel of the image.
        """
        padded_model_image_1d = self.convolve_array_1d_with_psf(padded_array_1d=padded_image_1d, psf=psf)
        return self.scaled_array_2d_from_array_1d(array_1d=padded_model_image_1d)

Compute a 2D padded blurred image from a 1D padded image .


def array_2d_from_array_1d(self, padded_array_1d):
        """ Map a padded 1D array of values to its original 2D array, trimming all edge values.

        Parameters
        -----------
        padded_array_1d : ndarray
            A 1D array of values which were computed using the *PaddedRegularGrid*.
        """
        padded_array_2d = self.map_to_2d_keep_padded(padded_array_1d)
        pad_size_0 = self.mask.shape[0] - self.image_shape[0]
        pad_size_1 = self.mask.shape[1] - self.image_shape[1]
        return (padded_array_2d[pad_size_0 // 2:self.mask.shape[0] - pad_size_0 // 2,
                pad_size_1 // 2:self.mask.shape[1] - pad_size_1 // 2])

def array_2d_from_array_1d ( self , padded_array_1d ) : padded_array_2d = self . map_to_2d_keep_padded ( padded_array_1d ) pad_size_0 = self . mask . shape [ 0 ] - self . image_shape [ 0 ] pad_size_1 = self . mask . shape [ 1 ] - self . image_shape [ 1 ] return ( padded_array_2d [ pad_size_0 // 2 : self . mask . shape [ 0 ] - pad_size_0 // 2 , pad_size_1 // 2 : self . mask . shape [ 1 ] - pad_size_1 // 2 ] )

Map a padded 1D array of values to its original 2D array trimming all edge values .


def map_to_2d_keep_padded(self, padded_array_1d):
        """ Map a padded 1D array of values to its padded 2D array.

        Parameters
        -----------
        padded_array_1d : ndarray
            A 1D array of values which were computed using the *PaddedRegularGrid*.
        """
        return mapping_util.map_unmasked_1d_array_to_2d_array_from_array_1d_and_shape(array_1d=padded_array_1d,
                                                                                shape=self.mask.shape)

Map a padded 1D array of values to its padded 2D array .


def relocated_grid_stack_from_grid_stack(self, grid_stack):
        """Determine a set of relocated grid_stack from an input set of grid_stack, by relocating their pixels based on the \
        borders.

        The blurring-grid does not have its coordinates relocated, as it is only used for computing analytic \
        light-profiles and not inversion-grid_stack.

        Parameters
        -----------
        grid_stack : GridStack
            The grid-stack, whose grid_stack coordinates are relocated.
        """
        border_grid = grid_stack.regular[self]
        return GridStack(regular=self.relocated_grid_from_grid_jit(grid=grid_stack.regular, border_grid=border_grid),
                         sub=self.relocated_grid_from_grid_jit(grid=grid_stack.sub, border_grid=border_grid),
                         blurring=None,
                         pix=self.relocated_grid_from_grid_jit(grid=grid_stack.pix, border_grid=border_grid))

def relocated_grid_stack_from_grid_stack ( self , grid_stack ) : border_grid = grid_stack . regular [ self ] return GridStack ( regular = self . relocated_grid_from_grid_jit ( grid = grid_stack . regular , border_grid = border_grid ) , sub = self . relocated_grid_from_grid_jit ( grid = grid_stack . sub , border_grid = border_grid ) , blurring = None , pix = self . relocated_grid_from_grid_jit ( grid = grid_stack . pix , border_grid = border_grid ) )

Determine a set of relocated grid_stack from an input set of grid_stack by relocating their pixels based on the \ borders .


def set_defaults(key):
    """
    Load a default value for redshift from config and set it as the redshift for source or lens galaxies that have
    falsey redshifts

    Parameters
    ----------
    key: str

    Returns
    -------
    decorator
        A decorator that wraps the setter function to set defaults
    """

    def decorator(func):
        @functools.wraps(func)
        def wrapper(phase, new_value):
            new_value = new_value or []
            for item in new_value:
                # noinspection PyTypeChecker
                galaxy = new_value[item] if isinstance(item, str) else item
                galaxy.redshift = galaxy.redshift or conf.instance.general.get("redshift", key, float)
            return func(phase, new_value)

        return wrapper

    return decorator

def
set_defaults
(
key
)
:
def
decorator
(
func
)
:
@
functools
.
wraps
(
func
)
def
wrapper
(
phase
,
new_value
)
:
new_value
=
new_value
or
[
]
for
item
in
new_value
:
# noinspection PyTypeChecker
galaxy
=
new_value
[
item
]
if
isinstance
(
item
,
str
)
else
item
galaxy
.
redshift
=
galaxy
.
redshift
or
conf
.
instance
.
general
.
get
(
"redshift"
,
key
,
float
)
return
func
(
phase
,
new_value
)
return
wrapper
return
decorator


def run(self, data, results=None, mask=None, positions=None):
        """
        Run a fit for each galaxy from the previous phase.

        Parameters
        ----------
        data: LensData
        results: ResultsCollection
            Results from all previous phases
        mask: Mask
            The mask
        positions

        Returns
        -------
        results: HyperGalaxyResults
            A collection of results, with one item per a galaxy
        """
        model_image = results.last.unmasked_model_image
        galaxy_tuples = results.last.constant.name_instance_tuples_for_class(g.Galaxy)

        results_copy = copy.copy(results.last)

        for name, galaxy in galaxy_tuples:
            optimizer = self.optimizer.copy_with_name_extension(name)
            optimizer.variable.hyper_galaxy = g.HyperGalaxy
            galaxy_image = results.last.unmasked_image_for_galaxy(galaxy)
            optimizer.fit(self.__class__.Analysis(data, model_image, galaxy_image))

            getattr(results_copy.variable, name).hyper_galaxy = optimizer.variable.hyper_galaxy
            getattr(results_copy.constant, name).hyper_galaxy = optimizer.constant.hyper_galaxy

        return results_copy

def run ( self , data , results = None , mask = None , positions = None ) : model_image = results . last . unmasked_model_image galaxy_tuples = results . last . constant . name_instance_tuples_for_class ( g . Galaxy ) results_copy = copy . copy ( results . last ) for name , galaxy in galaxy_tuples : optimizer = self . optimizer . copy_with_name_extension ( name ) optimizer . variable . hyper_galaxy = g . HyperGalaxy galaxy_image = results . last . unmasked_image_for_galaxy ( galaxy ) optimizer . fit ( self . __class__ . Analysis ( data , model_image , galaxy_image ) ) getattr ( results_copy . variable , name ) . hyper_galaxy = optimizer . variable . hyper_galaxy getattr ( results_copy . constant , name ) . hyper_galaxy = optimizer . constant . hyper_galaxy return results_copy

Run a fit for each galaxy from the previous phase .


def map_2d_array_to_masked_1d_array_from_array_2d_and_mask(mask, array_2d):
    """For a 2D array and mask, map the values of all unmasked pixels to a 1D array.

    The pixel coordinate origin is at the top left corner of the 2D array and goes right-wards and downwards, such
    that for an array of shape (3,3) where all pixels are unmasked:

    - pixel [0,0] of the 2D array will correspond to index 0 of the 1D array.
    - pixel [0,1] of the 2D array will correspond to index 1 of the 1D array.
    - pixel [1,0] of the 2D array will correspond to index 4 of the 1D array.

    Parameters
     ----------
    mask : ndarray
        A 2D array of bools, where *False* values mean unmasked and are included in the mapping.
    array_2d : ndarray
        The 2D array of values which are mapped to a 1D array.

    Returns
    --------
    ndarray
        A 1D array of values mapped from the 2D array with dimensions (total_unmasked_pixels).

    Examples
    --------
    mask = np.array([[True, False, True],
                     [False, False, False]
                     [True, False, True]])

    array_2d = np.array([[1.0, 2.0, 3.0],
                          [4.0, 5.0, 6.0],
                          [7.0, 8.0, 9.0]])

    array_1d = map_2d_array_to_masked_1d_array_from_array_2d_and_mask(mask=mask, array_2d=array_2d)
    """

    total_image_pixels = mask_util.total_regular_pixels_from_mask(mask)

    array_1d = np.zeros(shape=total_image_pixels)
    index = 0

    for y in range(mask.shape[0]):
        for x in range(mask.shape[1]):
            if not mask[y, x]:
                array_1d[index] = array_2d[y, x]
                index += 1

    return array_1d

For a 2D array and mask map the values of all unmasked pixels to a 1D array .


def sparse_to_unmasked_sparse_from_mask_and_pixel_centres(total_sparse_pixels, mask,
                                                          unmasked_sparse_grid_pixel_centres):
    """Determine the mapping between every masked pixelization-grid pixel and pixelization-grid pixel. This is
    performed by checking whether each pixelization-grid pixel is within the regular-masks, and mapping the indexes.

    Parameters
    -----------
    total_sparse_pixels : int
        The total number of pixels in the pixelization grid which fall within the regular-masks.
    mask : ccd.masks.Mask
        The regular-masks within which pixelization pixels must be inside
    unmasked_sparse_grid_pixel_centres : ndarray
        The centres of the unmasked pixelization grid pixels.
    """

    pix_to_full_pix = np.zeros(total_sparse_pixels)

    pixel_index = 0

    for full_pixel_index in range(unmasked_sparse_grid_pixel_centres.shape[0]):

        y = unmasked_sparse_grid_pixel_centres[full_pixel_index, 0]
        x = unmasked_sparse_grid_pixel_centres[full_pixel_index, 1]

        if not mask[y, x]:
            pix_to_full_pix[pixel_index] = full_pixel_index
            pixel_index += 1

    return pix_to_full_pix

Determine the mapping between every masked pixelization - grid pixel and pixelization - grid pixel . This is performed by checking whether each pixelization - grid pixel is within the regular - masks and mapping the indexes .


def unmasked_sparse_to_sparse_from_mask_and_pixel_centres(mask, unmasked_sparse_grid_pixel_centres,
                                                          total_sparse_pixels):
    """Determine the mapping between every pixelization-grid pixel and masked pixelization-grid pixel. This is
    performed by checking whether each pixelization-grid pixel is within the regular-masks, and mapping the indexes.

    Pixelization pixels are paired with the next masked pixel index. This may mean that a pixel is not paired with a
    pixel near it, if the next pixel is on the next row of the grid. This is not a problem, as it is only
    unmasked pixels that are referened when computing image_to_pix, which is what this array is used for.

    Parameters
    -----------
    total_sparse_pixels : int
        The total number of pixels in the pixelization grid which fall within the regular-masks.
    mask : ccd.masks.Mask
        The regular-masks within which pixelization pixels must be inside
    unmasked_sparse_grid_pixel_centres : ndarray
        The centres of the unmasked pixelization grid pixels.
    """

    total_unmasked_sparse_pixels = unmasked_sparse_grid_pixel_centres.shape[0]

    unmasked_sparse_to_sparse = np.zeros(total_unmasked_sparse_pixels)
    pixel_index = 0

    for unmasked_sparse_pixel_index in range(total_unmasked_sparse_pixels):

        y = unmasked_sparse_grid_pixel_centres[unmasked_sparse_pixel_index, 0]
        x = unmasked_sparse_grid_pixel_centres[unmasked_sparse_pixel_index, 1]

        unmasked_sparse_to_sparse[unmasked_sparse_pixel_index] = pixel_index

        if not mask[y, x]:
            if pixel_index < total_sparse_pixels - 1:
                pixel_index += 1

    return unmasked_sparse_to_sparse

Determine the mapping between every pixelization - grid pixel and masked pixelization - grid pixel . This is performed by checking whether each pixelization - grid pixel is within the regular - masks and mapping the indexes .


def regular_to_sparse_from_sparse_mappings(regular_to_unmasked_sparse, unmasked_sparse_to_sparse):
    """Using the mapping between the regular-grid and unmasked pixelization grid, compute the mapping between each regular
    pixel and the masked pixelization grid.

    Parameters
    -----------
    regular_to_unmasked_sparse : ndarray
        The index mapping between every regular-pixel and masked pixelization pixel.
    unmasked_sparse_to_sparse : ndarray
        The index mapping between every masked pixelization pixel and unmasked pixelization pixel.
    """
    total_regular_pixels = regular_to_unmasked_sparse.shape[0]

    regular_to_sparse = np.zeros(total_regular_pixels)

    for regular_index in range(total_regular_pixels):
    #    print(regular_index, regular_to_unmasked_sparse[regular_index], unmasked_sparse_to_sparse.shape[0])
        regular_to_sparse[regular_index] = unmasked_sparse_to_sparse[regular_to_unmasked_sparse[regular_index]]

    return regular_to_sparse

Using the mapping between the regular - grid and unmasked pixelization grid compute the mapping between each regular pixel and the masked pixelization grid .


def sparse_grid_from_unmasked_sparse_grid(unmasked_sparse_grid, sparse_to_unmasked_sparse):
    """Use the central arc-second coordinate of every unmasked pixelization grid's pixels and mapping between each
    pixelization pixel and unmasked pixelization pixel to compute the central arc-second coordinate of every masked
    pixelization grid pixel.

    Parameters
    -----------
    unmasked_sparse_grid : ndarray
        The (y,x) arc-second centre of every unmasked pixelization grid pixel.
    sparse_to_unmasked_sparse : ndarray
        The index mapping between every pixelization pixel and masked pixelization pixel.
    """
    total_pix_pixels = sparse_to_unmasked_sparse.shape[0]

    pix_grid = np.zeros((total_pix_pixels, 2))

    for pixel_index in range(total_pix_pixels):
        pix_grid[pixel_index, 0] = unmasked_sparse_grid[sparse_to_unmasked_sparse[pixel_index], 0]
        pix_grid[pixel_index, 1] = unmasked_sparse_grid[sparse_to_unmasked_sparse[pixel_index], 1]

    return pix_grid

Use the central arc - second coordinate of every unmasked pixelization grid s pixels and mapping between each pixelization pixel and unmasked pixelization pixel to compute the central arc - second coordinate of every masked pixelization grid pixel .


def extracted_array_2d_from_array_2d_and_coordinates(array_2d, y0, y1, x0, x1):
    """Resize an array to a new size by extracting a sub-set of the array.

    The extracted input coordinates use NumPy convention, such that the upper values should be specified as +1 the \
    dimensions of the extracted array.

    In the example below, an array of size (5,5) is extracted using the coordinates y0=1, y1=4, x0=1, x1=4. This
    extracts an array of dimensions (2,2) and is equivalent to array_2d[1:4, 1:4]

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is an array is extracted from.
    y0 : int
        The lower row number (e.g. the higher y-coodinate) of the array that is extracted for the resize.
    y1 : int
        The upper row number (e.g. the lower y-coodinate) of the array that is extracted for the resize.
    x0 : int
        The lower column number (e.g. the lower x-coodinate) of the array that is extracted for the resize.
    x1 : int
        The upper column number (e.g. the higher x-coodinate) of the array that is extracted for the resize.

    Returns
    -------
    ndarray
        The extracted 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    extracted_array = extract_array_2d(array_2d=array_2d, y0=1, y1=4, x0=1, x1=4)
    """

    new_shape = (y1-y0, x1-x0)

    resized_array = np.zeros(shape=new_shape)

    for y_resized, y in enumerate(range(y0, y1)):
        for x_resized, x in enumerate(range(x0, x1)):
                resized_array[y_resized, x_resized] = array_2d[y, x]

    return resized_array

Resize an array to a new size by extracting a sub - set of the array .


def resized_array_2d_from_array_2d_and_resized_shape(array_2d, resized_shape, origin=(-1, -1), pad_value=0.0):
    """Resize an array to a new size around a central pixel.

    If the origin (e.g. the central pixel) of the resized array is not specified, the central pixel of the array is \
    calculated automatically. For example, a (5,5) array's central pixel is (2,2). For even dimensions the central \
    pixel is assumed to be the lower indexed value, e.g. a (6,4) array's central pixel is calculated as (2,1).

    The default origin is (-1, -1) because numba requires that the function input is the same type throughout the \
    function, thus a default 'None' value cannot be used.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    resized_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))
    """

    y_is_even = int(array_2d.shape[0]) % 2 == 0
    x_is_even = int(array_2d.shape[1]) % 2 == 0

    if origin is (-1, -1):

        if y_is_even:
            y_centre = int(array_2d.shape[0] / 2)
        elif not y_is_even:
            y_centre = int(array_2d.shape[0] / 2)

        if x_is_even:
            x_centre = int(array_2d.shape[1] / 2)
        elif not x_is_even:
            x_centre = int(array_2d.shape[1] / 2)

        origin = (y_centre, x_centre)

    resized_array = np.zeros(shape=resized_shape)

    if y_is_even:
        y_min = origin[0] - int(resized_shape[0] / 2)
        y_max = origin[0] + int((resized_shape[0] / 2)) + 1
    elif not y_is_even:
        y_min = origin[0] - int(resized_shape[0] / 2)
        y_max = origin[0] + int((resized_shape[0] / 2)) + 1

    if x_is_even:
        x_min = origin[1] - int(resized_shape[1] / 2)
        x_max = origin[1] + int((resized_shape[1] / 2)) + 1
    elif not x_is_even:
        x_min = origin[1] - int(resized_shape[1] / 2)
        x_max = origin[1] + int((resized_shape[1] / 2)) + 1

    for y_resized, y in enumerate(range(y_min, y_max)):
        for x_resized, x in enumerate(range(x_min, x_max)):
            if y >= 0 and y < array_2d.shape[0] and x >= 0 and x < array_2d.shape[1]:
                if y_resized >= 0 and y_resized < resized_shape[0] and x_resized >= 0 and x_resized < resized_shape[1]:
                    resized_array[y_resized, x_resized] = array_2d[y, x]
            else:
                if y_resized >= 0 and y_resized < resized_shape[0] and x_resized >= 0 and x_resized < resized_shape[1]:
                    resized_array[y_resized, x_resized] = pad_value

    return resized_array

Resize an array to a new size around a central pixel .


def bin_up_array_2d_using_mean(array_2d, bin_up_factor):
    """Bin up an array to coarser resolution, by binning up groups of pixels and using their mean value to determine \
     the value of the new pixel.

    If an array of shape (8,8) is input and the bin up size is 2, this would return a new array of size (4,4) where \
    every pixel was the mean of each collection of 2x2 pixels on the (8,8) array.

    If binning up the array leads to an edge being cut (e.g. a (9,9) array binned up by 2), an array is first \
    extracted around the centre of that array.

    Parameters
    ----------
    array_2d : ndarray
        The 2D array that is resized.
    new_shape : (int, int)
        The (y,x) new pixel dimension of the trimmed array.
    origin : (int, int)
        The oigin of the resized array, e.g. the central pixel around which the array is extracted.

    Returns
    -------
    ndarray
        The resized 2D array from the input 2D array.

    Examples
    --------
    array_2d = np.ones((5,5))
    resize_array = resize_array_2d(array_2d=array_2d, new_shape=(2,2), origin=(2, 2))
    """

    padded_array_2d = pad_2d_array_for_binning_up_with_bin_up_factor(array_2d=array_2d, bin_up_factor=bin_up_factor)

    binned_array_2d = np.zeros(shape=(padded_array_2d.shape[0] // bin_up_factor,
                                      padded_array_2d.shape[1] // bin_up_factor))

    for y in range(binned_array_2d.shape[0]):
        for x in range(binned_array_2d.shape[1]):
            value = 0.0
            for y1 in range(bin_up_factor):
                for x1 in range(bin_up_factor):
                    padded_y = y*bin_up_factor + y1
                    padded_x = x*bin_up_factor + x1
                    value += padded_array_2d[padded_y, padded_x]

            binned_array_2d[y,x] = value / (bin_up_factor ** 2.0)

    return binned_array_2d

Bin up an array to coarser resolution by binning up groups of pixels and using their mean value to determine \ the value of the new pixel .


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 .