Instruction:
Can you tell what is the following Python 3 function doing
def g_(self, X):
        if self._interpol:
            if not hasattr(self, '_g_interp'):

                if self._lookup:
                    x = self._x_lookup
                    g_x = self._g_lookup
                else:
                    x = np.linspace(0, self._max_interp_X, self._num_interp_X)
                    g_x = self._g(x)
                self._g_interp = interp.interp1d(x, g_x, kind='linear', axis=-1, copy=False, bounds_error=False,
                                                 fill_value=0, assume_sorted=True)
            return self._g_interp(X)
        else:
            return self._g(X)

Response: computes the h function for the current state of the object


Instruction:
How would you code a function in Python 3 to
convert angle at Rs into rho0

Response:
def _alpha2rho0(self, theta_Rs, Rs):

        """
        convert angle at Rs into rho0
        """

        rho0 = theta_Rs / (4. * Rs ** 2 * (1. + np.log(1. / 2.)))
        return rho0


Instruction:
Explain what the following Python 3 code does
def _rho02alpha(self, rho0, Rs):

        """
        convert rho0 to angle at Rs

        :param rho0:
        :param Rs:
        :return:
        """

        theta_Rs = rho0 * (4 * Rs ** 2 * (1 + np.log(1. / 2.)))
        return theta_Rs

Response: convert rho0 to angle at Rs


Instruction:
Can you generate a brief explanation for the following Python 3 code
def param_name_list(self):
        name_list = []
        for func in self.func_list:
            name_list.append(func.param_names)
        return name_list

Response: returns the list of all parameter names


Instruction:
Implement a Python 3 function for
returning the surface brightness of the image

Response:
def surface_brightness(self, x, y, kwargs_list, k=None):
        """
        :param x: coordinate in units of arcsec relative to the center of the image
        :type x: set or single 1d numpy array
        """
        x = np.array(x, dtype=float)
        y = np.array(y, dtype=float)
        flux = np.zeros_like(x)
        for i, func in enumerate(self.func_list):
            if k is None or k == i:
                out = np.array(func.function(x, y, **kwargs_list[i]), dtype=float)
                flux += out
        return flux


Instruction:
Given the following Python 3 function, write the documentation
def light_3d(self, r, kwargs_list, k=None):
        r = np.array(r, dtype=float)
        flux = np.zeros_like(r)
        for i, func in enumerate(self.func_list):
            if k is None or k == i:
                kwargs = {k: v for k, v in kwargs_list[i].items() if not k in ['center_x', 'center_y']}
                if self.profile_type_list[i] in ['HERNQUIST', 'HERNQUIST_ELLIPSE', 'PJAFFE', 'PJAFFE_ELLIPSE',
                                                     'GAUSSIAN', 'GAUSSIAN_ELLIPSE', 'MULTI_GAUSSIAN',
                                                     'MULTI_GAUSSIAN_ELLIPSE', 'POWER_LAW']:
                    flux += func.light_3d(r, **kwargs)
                else:
                    raise ValueError('Light model %s does not support a 3d light distribution!'
                                         % self.profile_type_list[i])
        return flux

Response: compute 3d density at radius r


Instruction:
Make a summary of the following Python 3 code
def total_flux(self, kwargs_list, norm=False, k=None):
        norm_flux_list = []
        for i, model in enumerate(self.profile_type_list):
            if k is None or k == i:
                if model in ['SERSIC', 'SERSIC_ELLIPSE', 'INTERPOL', 'GAUSSIAN', 'GAUSSIAN_ELLIPSE',
                             'MULTI_GAUSSIAN', 'MULTI_GAUSSIAN_ELLIPSE']:
                    kwargs_new = kwargs_list[i].copy()
                    if norm is True:
                        if model in ['MULTI_GAUSSIAN', 'MULTI_GAUSSIAN_ELLIPSE']:
                            new = {'amp': np.array(kwargs_new['amp'])/kwargs_new['amp'][0]}
                        else:
                            new = {'amp': 1}
                        kwargs_new.update(new)
                    norm_flux = self.func_list[i].total_flux(**kwargs_new)
                    norm_flux_list.append(norm_flux)
                else:
                    raise ValueError("profile %s does not support flux normlization." % model)
                #  TODO implement total flux for e.g. 'HERNQUIST', 'HERNQUIST_ELLIPSE', 'PJAFFE', 'PJAFFE_ELLIPSE',
                    # 'GAUSSIAN', 'GAUSSIAN_ELLIPSE', 'POWER_LAW', 'NIE', 'CHAMELEON', 'DOUBLE_CHAMELEON', 'UNIFORM'
        return norm_flux_list

Response: Compute the total flux of each individual light profile.


Instruction:
Make a summary of the following Python 3 code
def k_bn(self, n, Re):
        bn = self.b_n(n)
        k = bn*Re**(-1./n)
        return k, bn

Response: returns the k and bn of the sersic profile such that Re is the half light radius given n_sersic slope


Instruction:
Can you implement a function in Python 3 that
computes the reduced x - axis

Response:
def _x_reduced(self, x, y, n_sersic, r_eff, center_x, center_y):
        """
        coordinate transform to normalized radius
        :param x:
        :param y:
        :param center_x:
        :param center_y:
        :return:
        """
        x_ = x - center_x
        y_ = y - center_y
        r = np.sqrt(x_**2 + y_**2)
        if isinstance(r, int) or isinstance(r, float):
            r = max(self._s, r)
        else:
            r[r < self._s] = self._s
        x_reduced = (r/r_eff)**(1./n_sersic)
        return x_reduced


Instruction:
Write a Python 3 function for
calculating the alpha effect of a set of sersic entries at a given deflection angle at r_eff.

Response:
def _alpha_eff(self, r_eff, n_sersic, k_eff):
        """
        deflection angle at r_eff
        :param r_eff:
        :param n_sersic:
        :param k_eff:
        :return:
        """
        b = self.b_n(n_sersic)
        alpha_eff = n_sersic * r_eff * k_eff * b**(-2*n_sersic) * np.exp(b) * special.gamma(2*n_sersic)
        return -alpha_eff


Instruction:
Explain what the following Python 3 code does
def density(self, x, y, n_sersic, r_eff, k_eff, center_x=0, center_y=0):
        raise ValueError("not implemented! Use a Multi-Gaussian-component decomposition.")

Response: This method computes the density of the Sersic profile at the given coordinates.


Instruction:
Make a summary of the following Python 3 code
def _total_flux(self, r_eff, I_eff, n_sersic):
        bn = self.b_n(n_sersic)
        return I_eff * r_eff**2 * 2 * np.pi * n_sersic * np.exp(bn) / bn**(2*n_sersic) * scipy.special.gamma(2*n_sersic)

Response: Compute the total flux of a Sersic profile.


Instruction:
How would you explain what the following Python 3 function does
def function(self, x, y, theta_E, gamma, center_x=0, center_y=0):
        gamma = self._gamma_limit(gamma)

        x_ = x - center_x
        y_ = y - center_y
        E = theta_E / ((3. - gamma) / 2.) ** (1. / (1. - gamma))
        # E = phi_E_spp
        eta= -gamma + 3

        p2 = x_**2+y_**2
        s2 = 0. # softening
        return 2 * E**2/eta**2 * ((p2 + s2)/E**2)**(eta/2)

Response: Function that calculates the function of the lense logarithmic logarithm.


Instruction:
Implement a Python 3 function for
converting 3d density into 2d projected density parameter

Response:
def rho2theta(self, rho0, gamma):
        """
        converts 3d density into 2d projected density parameter
        :param rho0:
        :param gamma:
        :return:
        """
        fac = np.sqrt(np.pi) * special.gamma(1. / 2 * (-1 + gamma)) / special.gamma(gamma / 2.) * 2 / (3 - gamma) * rho0

        #fac = theta_E**(gamma - 1)
        theta_E = fac**(1. / (gamma - 1))
        return theta_E


Instruction:
Given the following Python 3 function, write the documentation
def theta2rho(self, theta_E, gamma):
        fac1 = np.sqrt(np.pi) * special.gamma(1. / 2 * (-1 + gamma)) / special.gamma(gamma / 2.) * 2 / (3 - gamma)
        fac2 = theta_E**(gamma - 1)
        rho0 = fac2 / fac1
        return rho0

Response: converts projected density parameter into 3d density parameter


Instruction:
Here you have a function in Python 3, explain what it does
def mass_3d(self, r, rho0, gamma):
        mass_3d = 4 * np.pi * rho0 /(-gamma + 3) * r ** (-gamma + 3)
        return mass_3d

Response: calculate the mass of a 3d sphere or radius r


Instruction:
How would you code a function in Python 3 to
calculate the mass of a 2d sphere of radius r

Response:
def mass_2d(self, r, rho0, gamma):
        """
        mass enclosed projected 2d sphere of radius r
        :param r:
        :param rho0:
        :param a:
        :param s:
        :return:
        """
        alpha = np.sqrt(np.pi) * special.gamma(1. / 2 * (-1 + gamma)) / special.gamma(gamma / 2.) * r ** (2 - gamma)/(3 - gamma) *np.pi * 2 * rho0
        mass_2d = alpha*r
        return mass_2d


Instruction:
How would you implement a function in Python 3 that
computes the density of the n - tuple

Response:
def density(self, r, rho0, gamma):
        """
        computes the density
        :param x:
        :param y:
        :param rho0:
        :param a:
        :param s:
        :return:
        """
        rho = rho0 / r**gamma
        return rho


Instruction:
How would you explain what the following Python 3 function does
def density_2d(self, x, y, rho0, gamma, center_x=0, center_y=0):
        x_ = x - center_x
        y_ = y - center_y
        r = np.sqrt(x_**2 + y_**2)
        sigma = np.sqrt(np.pi) * special.gamma(1./2*(-1+gamma))/special.gamma(gamma/2.) * r**(1-gamma) * rho0
        return sigma

Response: projected density of a 2D logarithm


Instruction:
How would you code a function in Python 3 to
compute the averaged LOS velocity dispersion in the slit

Response:
def vel_disp(self, kwargs_mass, kwargs_light, kwargs_anisotropy, kwargs_apertur):
        """
        computes the averaged LOS velocity dispersion in the slit (convolved)

        :param kwargs_mass: mass model parameters (following lenstronomy lens model conventions)
        :param kwargs_light: deflector light parameters (following lenstronomy light model conventions)
        :param kwargs_anisotropy: anisotropy parameters, may vary according to anisotropy type chosen.
            We refer to the Anisotropy() class for details on the parameters.
        :param kwargs_apertur: Aperture parameters, may vary depending on aperture type chosen.
            We refer to the Aperture() class for details on the parameters.
        :return: integrated LOS velocity dispersion in units [km/s]
        """
        sigma2_R_sum = 0
        for i in range(0, self._num_sampling):
            sigma2_R = self.draw_one_sigma2(kwargs_mass, kwargs_light, kwargs_anisotropy, kwargs_apertur)
            sigma2_R_sum += sigma2_R
        sigma_s2_average = sigma2_R_sum / self._num_sampling
        # apply unit conversion from arc seconds and deflections to physical velocity disperison in (km/s)
        sigma_s2_average *= 2 * const.G  # correcting for integral prefactor
        return np.sqrt(sigma_s2_average/(const.arcsec**2 * self.cosmo.D_d**2 * const.Mpc))/1000.


Instruction:
Given the following Python 3 function, write the documentation
def sigma2_R(self, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        I_R_sigma2 = self.I_R_simga2(R, kwargs_mass, kwargs_light, kwargs_anisotropy)
        I_R = self.lightProfile.light_2d(R, kwargs_light)
        return I_R_sigma2 / I_R

Response: returns unweighted los velocity dispersion for a specified projected radius


Instruction:
Can you write a function in Python 3 where it
returns df x y of the function

Response:
def derivatives(self, x, y, n_sersic, R_sersic, k_eff, center_x=0, center_y=0):
        """
        returns df/dx and df/dy of the function
        """
        x_ = x - center_x
        y_ = y - center_y
        r = np.sqrt(x_**2 + y_**2)
        if isinstance(r, int) or isinstance(r, float):
            r = max(self._s, r)
        else:
            r[r < self._s] = self._s
        alpha = -self.alpha_abs(x, y, n_sersic, R_sersic, k_eff, center_x, center_y)
        f_x = alpha * x_ / r
        f_y = alpha * y_ / r
        return f_x, f_y


Instruction:
Explain what the following Python 3 code does
def derivatives(self, x, y, theta_E, s, q):
        if q >= 1:
            q = 0.999999
        psi = self._psi(x, y, q, s)
        f_x = theta_E / np.sqrt(1. - q ** 2) * np.arctan(np.sqrt(1. - q ** 2) * x / (psi+s))
        f_y = theta_E / np.sqrt(1. - q ** 2) * np.arctanh(np.sqrt(1. - q ** 2) * y / (psi + q**2*s))
        return f_x, f_y

Response: returns df x y of the function


Instruction:
Write a Python 3 function for
returning Hessian matrix of function d^2f x y theta_E s q

Response:
def hessian(self, x, y, theta_E, s, q):
        """
        returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy
        """
        alpha_ra, alpha_dec = self.derivatives(x, y, theta_E, s, q)
        diff = self._diff
        alpha_ra_dx, alpha_dec_dx = self.derivatives(x + diff, y, theta_E, s, q)
        alpha_ra_dy, alpha_dec_dy = self.derivatives(x, y + diff, theta_E, s, q)

        f_xx = (alpha_ra_dx - alpha_ra) / diff
        f_xy = (alpha_ra_dy - alpha_ra) / diff
        # f_yx = (alpha_dec_dx - alpha_dec)/diff
        f_yy = (alpha_dec_dy - alpha_dec) / diff
        return f_xx, f_yy, f_xy


Instruction:
How would you explain what the following Python 3 function does
def _psi(self, x, y, q, s):
        return np.sqrt(q**2 * (s**2 + x**2) + y**2)

Response:
expression after equation (8) in Keeton&Kochanek 1998

        :param x:
        :param y:
        :param q:
        :param s:
        :return:


Instruction:
Can you tell what is the following Python 3 function doing
def function(self, x, y, kappa_ext, ra_0=0, dec_0=0):
        theta, phi = param_util.cart2polar(x - ra_0, y - dec_0)
        f_ = 1./2 * kappa_ext * theta**2
        return f_

Response: calculate the function of the convergence set


Instruction:
Implement a Python 3 function for
getting the derivatives of the convergence species

Response:
def derivatives(self, x, y, kappa_ext, ra_0=0, dec_0=0):
        """
        deflection angle

        :param x: x-coordinate
        :param y: y-coordinate
        :param kappa_ext: external convergence
        :return: deflection angles (first order derivatives)
        """
        x_ = x - ra_0
        y_ = y - dec_0
        f_x = kappa_ext * x_
        f_y = kappa_ext * y_
        return f_x, f_y


Instruction:
Explain what the following Python 3 code does
def hessian(self, x, y, kappa_ext, ra_0=0, dec_0=0):
        gamma1 = 0
        gamma2 = 0
        kappa = kappa_ext
        f_xx = kappa + gamma1
        f_yy = kappa - gamma1
        f_xy = gamma2
        return f_xx, f_yy, f_xy

Response: Hessian matrix for the current convergence set.


Instruction:
Here you have a function in Python 3, explain what it does
def map_coord2pix(ra, dec, x_0, y_0, M):
    x, y = M.dot(np.array([ra, dec]))
    return x + x_0, y + y_0

Response: This routine maps a coordinate system to a pixel coordinates.


Instruction:
Write a Python 3 script for
converting a 1d array into an n * n 2d array

Response:
def array2image(array, nx=0, ny=0):
    """
    returns the information contained in a 1d array into an n*n 2d array (only works when lenght of array is n**2)

    :param array: image values
    :type array: array of size n**2
    :returns:  2d array
    :raises: AttributeError, KeyError
    """
    if nx == 0 or ny == 0:
        n = int(np.sqrt(len(array)))
        if n**2 != len(array):
            raise ValueError("lenght of input array given as %s is not square of integer number!" %(len(array)))
        nx, ny = n, n
    image = array.reshape(int(nx), int(ny))
    return image


Instruction:
Can you generate a brief explanation for the following Python 3 code
def image2array(image):
    nx, ny = image.shape  # find the size of the array
    imgh = np.reshape(image, nx*ny)  # change the shape to be 1d
    return imgh

Response: returns the information contained in a 2d array into an n 1d array


Instruction:
How would you code a function in Python 3 to
make a grid with linear transformation

Response:
def make_grid_transformed(numPix, Mpix2Angle):
    """
    returns grid with linear transformation (deltaPix and rotation)
    :param numPix: number of Pixels
    :param Mpix2Angle: 2-by-2 matrix to mat a pixel to a coordinate
    :return: coordinate grid
    """
    x_grid, y_grid = make_grid(numPix, deltapix=1)
    ra_grid, dec_grid = map_coord2pix(x_grid, y_grid, 0, 0, Mpix2Angle)
    return ra_grid, dec_grid


Instruction:
Explain what the following Python 3 code does
def grid_from_coordinate_transform(numPix, Mpix2coord, ra_at_xy_0, dec_at_xy_0):
    a = np.arange(numPix)
    matrix = np.dstack(np.meshgrid(a, a)).reshape(-1, 2)
    x_grid = matrix[:, 0]
    y_grid = matrix[:, 1]
    ra_grid = x_grid * Mpix2coord[0, 0] + y_grid * Mpix2coord[0, 1] + ra_at_xy_0
    dec_grid = x_grid * Mpix2coord[1, 0] + y_grid * Mpix2coord[1, 1] + dec_at_xy_0
    return ra_grid, dec_grid

Response: return a grid in x and y coordinates that satisfy the coordinate system


Instruction:
Can you write a function in Python 3 where it
computes the axes x and y of a given 2d grid

Response:
def get_axes(x, y):
    """
    computes the axis x and y of a given 2d grid
    :param x:
    :param y:
    :return:
    """
    n=int(np.sqrt(len(x)))
    if n**2 != len(x):
        raise ValueError("lenght of input array given as %s is not square of integer number!" % (len(x)))
    x_image = x.reshape(n,n)
    y_image = y.reshape(n,n)
    x_axes = x_image[0,:]
    y_axes = y_image[:,0]
    return x_axes, y_axes


Instruction:
Can you tell what is the following Python 3 function doing
def averaging(grid, numGrid, numPix):

    Nbig = numGrid
    Nsmall = numPix
    small = grid.reshape([int(Nsmall), int(Nbig/Nsmall), int(Nsmall), int(Nbig/Nsmall)]).mean(3).mean(1)
    return small

Response: resizes 2d pixel grid with numGrid to numPix and averages over the pixels


Instruction:
Explain what the following Python 3 code does
def displaceAbs(x, y, sourcePos_x, sourcePos_y):
    x_mapped = x - sourcePos_x
    y_mapped = y - sourcePos_y
    absmapped = np.sqrt(x_mapped**2+y_mapped**2)
    return absmapped

Response:
Displace the observer in angel
    by the absolute distance of the observer in sourcePos_x and sourcePos_y.


Instruction:
Make a summary of the following Python 3 code
def min_square_dist(x_1, y_1, x_2, y_2):
    dist = np.zeros_like(x_1)
    for i in range(len(x_1)):
        dist[i] = np.min((x_1[i] - x_2)**2 + (y_1[i] - y_2)**2)
    return dist

Response: returns minimum of quadratic distance of pairs x1 y1 to pairs x2 y2


Instruction:
Can you generate the documentation for the following Python 3 function
def points_on_circle(radius, points):
    angle = np.linspace(0, 2*np.pi, points)
    x_coord = np.cos(angle)*radius
    y_coord = np.sin(angle)*radius
    return x_coord, y_coord

Response: Returns a set of uniform points around a circle


Instruction:
Implement a function in Python 3 to
find local minima in a 2d grid and returns the indices of local minima that are in the source positions x y

Response:
def neighborSelect(a, x, y):
    """
    finds (local) minima in a 2d grid

    :param a: 1d array of displacements from the source positions
    :type a: numpy array with length numPix**2 in float
    :returns:  array of indices of local minima, values of those minima
    :raises: AttributeError, KeyError
    """
    dim = int(np.sqrt(len(a)))
    values = []
    x_mins = []
    y_mins = []
    for i in range(dim+1,len(a)-dim-1):
        if (a[i] < a[i-1]
            and a[i] < a[i+1]
            and a[i] < a[i-dim]
            and a[i] < a[i+dim]
            and a[i] < a[i-(dim-1)]
            and a[i] < a[i-(dim+1)]
            and a[i] < a[i+(dim-1)]
            and a[i] < a[i+(dim+1)]):
                if(a[i] < a[(i-2*dim-1)%dim**2]
                    and a[i] < a[(i-2*dim+1)%dim**2]
                    and a[i] < a[(i-dim-2)%dim**2]
                    and a[i] < a[(i-dim+2)%dim**2]
                    and a[i] < a[(i+dim-2)%dim**2]
                    and a[i] < a[(i+dim+2)%dim**2]
                    and a[i] < a[(i+2*dim-1)%dim**2]
                    and a[i] < a[(i+2*dim+1)%dim**2]):
                    if(a[i] < a[(i-3*dim-1)%dim**2]
                        and a[i] < a[(i-3*dim+1)%dim**2]
                        and a[i] < a[(i-dim-3)%dim**2]
                        and a[i] < a[(i-dim+3)%dim**2]
                        and a[i] < a[(i+dim-3)%dim**2]
                        and a[i] < a[(i+dim+3)%dim**2]
                        and a[i] < a[(i+3*dim-1)%dim**2]
                        and a[i] < a[(i+3*dim+1)%dim**2]):
                        x_mins.append(x[i])
                        y_mins.append(y[i])
                        values.append(a[i])
    return np.array(x_mins), np.array(y_mins), np.array(values)


Instruction:
Can you tell what is the following Python 3 function doing
def make_subgrid(ra_coord, dec_coord, subgrid_res=2):
    ra_array = array2image(ra_coord)
    dec_array = array2image(dec_coord)
    n = len(ra_array)
    d_ra_x = ra_array[0][1] - ra_array[0][0]
    d_ra_y = ra_array[1][0] - ra_array[0][0]
    d_dec_x = dec_array[0][1] - dec_array[0][0]
    d_dec_y = dec_array[1][0] - dec_array[0][0]

    ra_array_new = np.zeros((n*subgrid_res, n*subgrid_res))
    dec_array_new = np.zeros((n*subgrid_res, n*subgrid_res))
    for i in range(0, subgrid_res):
        for j in range(0, subgrid_res):
            ra_array_new[i::subgrid_res, j::subgrid_res] = ra_array + d_ra_x * (-1/2. + 1/(2.*subgrid_res) + j/float(subgrid_res)) + d_ra_y * (-1/2. + 1/(2.*subgrid_res) + i/float(subgrid_res))
            dec_array_new[i::subgrid_res, j::subgrid_res] = dec_array + d_dec_x * (-1/2. + 1/(2.*subgrid_res) + j/float(subgrid_res)) + d_dec_y * (-1/2. + 1/(2.*subgrid_res) + i/float(subgrid_res))

    ra_coords_sub = image2array(ra_array_new)
    dec_coords_sub = image2array(dec_array_new)
    return ra_coords_sub, dec_coords_sub

Response: make a subgrid of a single site


Instruction:
Write a Python 3 function that can
function that calculates the function of the lense logarithmic mass

Response:
def function(self, x, y, theta_E, gamma, e1, e2, center_x=0, center_y=0):
        """
        :param x: set of x-coordinates
        :type x: array of size (n)
        :param theta_E: Einstein radius of lense
        :type theta_E: float.
        :param gamma: power law slope of mass profifle
        :type gamma: <2 float
        :param q: Axis ratio
        :type q: 0<q<1
        :param phi_G: position angel of SES
        :type q: 0<phi_G<pi/2
        :returns:  function
        :raises: AttributeError, KeyError
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        gamma, q = self._param_bounds(gamma, q)
        theta_E *= q
        x_shift = x - center_x
        y_shift = y - center_y
        E = theta_E / (((3 - gamma) / 2.) ** (1. / (1 - gamma)) * np.sqrt(q))
        #E = phi_E
        eta = -gamma+3
        xt1 = np.cos(phi_G)*x_shift+np.sin(phi_G)*y_shift
        xt2 = -np.sin(phi_G)*x_shift+np.cos(phi_G)*y_shift
        p2 = xt1**2+xt2**2/q**2
        s2 = 0. # softening
        return 2 * E**2/eta**2 * ((p2 + s2)/E**2)**(eta/2)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def mass_3d_lens(self, r, theta_E, gamma, e1, e2):
        return self.spp.mass_3d_lens(r, theta_E, gamma)

Response: computes the spherical power - law mass enclosed with SPP routiune


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _param_bounds(self, gamma, q):
        if gamma < 1.4:
            gamma = 1.4
        if gamma > 2.9:
            gamma = 2.9
        if q < 0.01:
            q = 0.01
        return float(gamma), q

Response: get the parameter bounds


Instruction:
Create a Python 3 function to
test whether the image positions map back to the same source position

Response:
def solver_penalty(self, kwargs_lens, kwargs_ps, kwargs_cosmo, tolerance):
        """
        test whether the image positions map back to the same source position
        :param kwargs_lens:
        :param kwargs_ps:
        :return: add penalty when solver does not find a solution
        """
        dist = self._param.check_solver(kwargs_lens, kwargs_ps, kwargs_cosmo)
        if dist > tolerance:
            return dist * 10**10
        return 0


Instruction:
Explain what the following Python 3 code does
def check_additional_images(self, kwargs_ps, kwargs_lens):
        ra_image_list, dec_image_list = self._pointSource.image_position(kwargs_ps=kwargs_ps, kwargs_lens=kwargs_lens)
        if len(ra_image_list) > 0:
            if len(ra_image_list[0]) > self._param.num_point_source_images:
                return True
        return False

Response: checks whether additional images have been found and placed in kwargs_ps


Instruction:
Write a Python 3 script to
function that computes the Sersic profile for a specific set of sources.

Response:
def function(self, x, y, amp, R_sersic, n_sersic, center_x=0, center_y=0):
        """
        returns Sersic profile
        """
        #if n_sersic < 0.2:
        #    n_sersic = 0.2
        #if R_sersic < 10.**(-6):
        #    R_sersic = 10.**(-6)
        R_sersic = np.maximum(0, R_sersic)
        x_shift = x - center_x
        y_shift = y - center_y
        R = np.sqrt(x_shift*x_shift + y_shift*y_shift)
        if isinstance(R, int) or isinstance(R, float):
            R = max(self._smoothing, R)
        else:
            R[R < self._smoothing] = self._smoothing
        _, bn = self.k_bn(n_sersic, R_sersic)
        R_frac = R/R_sersic
        #R_frac = R_frac.astype(np.float32)
        if isinstance(R, int) or isinstance(R, float):
            if R_frac > 100:
                result = 0
            else:
                exponent = -bn*(R_frac**(1./n_sersic)-1.)
                result = amp * np.exp(exponent)
        else:
            R_frac_real = R_frac[R_frac <= 100]
            exponent = -bn*(R_frac_real**(1./n_sersic)-1.)
            result = np.zeros_like(R)
            result[R_frac <= 100] = amp * np.exp(exponent)
        return np.nan_to_num(result)


Instruction:
Implement a function in Python 3 to
function that computes the Sersic profile for a specific ephemeris system.

Response:
def function(self, x, y, amp, R_sersic, n_sersic, e1, e2, center_x=0, center_y=0):
        """
        returns Sersic profile
        """
        #if n_sersic < 0.2:
        #    n_sersic = 0.2
        #if R_sersic < 10.**(-6):
        #    R_sersic = 10.**(-6)
        R_sersic = np.maximum(0, R_sersic)
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_shift = x - center_x
        y_shift = y - center_y

        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)

        xt1 = cos_phi*x_shift+sin_phi*y_shift
        xt2 = -sin_phi*x_shift+cos_phi*y_shift
        xt2difq2 = xt2/(q*q)
        R_ = np.sqrt(xt1*xt1+xt2*xt2difq2)
        if isinstance(R_, int) or isinstance(R_, float):
            R_ = max(self._smoothing, R_)
        else:
            R_[R_ < self._smoothing] = self._smoothing
        k, bn = self.k_bn(n_sersic, R_sersic)
        R_frac = R_/R_sersic
        R_frac = R_frac.astype(np.float32)
        if isinstance(R_, int) or isinstance(R_, float):
            if R_frac > 100:
                result = 0
            else:
                exponent = -bn*(R_frac**(1./n_sersic)-1.)
                result = amp * np.exp(exponent)
        else:
            R_frac_real = R_frac[R_frac <= 100]
            exponent = -bn*(R_frac_real**(1./n_sersic)-1.)
            result = np.zeros_like(R_)
            result[R_frac <= 100] = amp * np.exp(exponent)
        return np.nan_to_num(result)


Instruction:
Write a Python 3 script for
returning the function of the Core - Sersic system

Response:
def function(self, x, y, amp, R_sersic, Re, n_sersic, gamma, e1, e2, center_x=0, center_y=0, alpha=3.):
        """
        returns Core-Sersic function
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        Rb = R_sersic
        x_shift = x - center_x
        y_shift = y - center_y

        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)

        xt1 = cos_phi*x_shift+sin_phi*y_shift
        xt2 = -sin_phi*x_shift+cos_phi*y_shift
        xt2difq2 = xt2/(q*q)
        R_ = np.sqrt(xt1*xt1+xt2*xt2difq2)
        #R_ = R_.astype(np.float32)
        if isinstance(R_, int) or isinstance(R_, float):
            R_ = max(self._smoothing, R_)
        else:
            R_[R_ < self._smoothing] = self._smoothing
        if isinstance(R_, int) or isinstance(R_, float):
            R = max(self._smoothing, R_)
        else:
            R=np.empty_like(R_)
            _R = R_[R_ > self._smoothing]  #in the SIS regime
            R[R_ <= self._smoothing] = self._smoothing
            R[R_ > self._smoothing] = _R

        k, bn = self.k_bn(n_sersic, Re)
        result = amp * (1 + (Rb / R) ** alpha) ** (gamma / alpha) * np.exp(-bn * (((R ** alpha + Rb ** alpha) / Re ** alpha) ** (1. / (alpha * n_sersic)) - 1.))
        return np.nan_to_num(result)


Instruction:
Create a Python 3 function to
return df x y of the function that is derivatives of the function that is at center_x and center_y

Response:
def derivatives(self, x, y, theta_E, r_trunc, center_x=0, center_y=0):
        """
        returns df/dx and df/dy of the function
        """
        x_shift = x - center_x
        y_shift = y - center_y

        dphi_dr = self._dphi_dr(x_shift, y_shift, theta_E, r_trunc)
        dr_dx, dr_dy = self._dr_dx(x_shift, y_shift)
        f_x = dphi_dr * dr_dx
        f_y = dphi_dr * dr_dy
        return f_x, f_y


Instruction:
Write a Python 3 script for
returning Hessian matrix of function d^2f x y theta_E r_trunc center_x center_y

Response:
def hessian(self, x, y, theta_E, r_trunc, center_x=0, center_y=0):
        """
        returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy
        """
        x_shift = x - center_x
        y_shift = y - center_y
        dphi_dr = self._dphi_dr(x_shift, y_shift, theta_E, r_trunc)
        d2phi_dr2 = self._d2phi_dr2(x_shift, y_shift, theta_E, r_trunc)
        dr_dx, dr_dy = self._dr_dx(x, y)
        d2r_dx2, d2r_dy2, d2r_dxy = self._d2r_dx2(x_shift, y_shift)
        f_xx = d2r_dx2*dphi_dr + dr_dx**2*d2phi_dr2
        f_yy = d2r_dy2*dphi_dr + dr_dy**2*d2phi_dr2
        f_xy = d2r_dxy*dphi_dr + dr_dx*dr_dy*d2phi_dr2
        return f_xx, f_yy, f_xy


Instruction:
Create a Python 3 function to
return the function of the NFW profile

Response:
def function(self, x, y, sigma0, Rs, e1, e2, center_x=0, center_y=0):
        """
        returns double integral of NFW profile
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_shift = x - center_x
        y_shift = y - center_y
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        e = abs(1 - q)
        x_ = (cos_phi*x_shift+sin_phi*y_shift)*np.sqrt(1 - e)
        y_ = (-sin_phi*x_shift+cos_phi*y_shift)*np.sqrt(1 + e)
        f_ = self.spherical.function(x_, y_, sigma0, Rs)
        return f_


Instruction:
How would you explain what the following Python 3 function does
def derivatives(self, x, y, sigma0, Rs, e1, e2, center_x=0, center_y=0):
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_shift = x - center_x
        y_shift = y - center_y
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        e = abs(1 - q)
        x_ = (cos_phi*x_shift+sin_phi*y_shift)*np.sqrt(1 - e)
        y_ = (-sin_phi*x_shift+cos_phi*y_shift)*np.sqrt(1 + e)

        f_x_prim, f_y_prim = self.spherical.derivatives(x_, y_, sigma0, Rs)
        f_x_prim *= np.sqrt(1 - e)
        f_y_prim *= np.sqrt(1 + e)
        f_x = cos_phi*f_x_prim-sin_phi*f_y_prim
        f_y = sin_phi*f_x_prim+cos_phi*f_y_prim
        return f_x, f_y

Response: returns df x y of the function


Instruction:
Can you tell what is the following Python 3 function doing
def _nfw_func(self, x):

        c = 0.000001

        if isinstance(x, np.ndarray):
            x[np.where(x<c)] = c
            nfwvals = np.ones_like(x)
            inds1 = np.where(x < 1)
            inds2 = np.where(x > 1)

            nfwvals[inds1] = (1 - x[inds1] ** 2) ** -.5 * np.arctanh((1 - x[inds1] ** 2) ** .5)
            nfwvals[inds2] = (x[inds2] ** 2 - 1) ** -.5 * np.arctan((x[inds2] ** 2 - 1) ** .5)

            return nfwvals

        elif isinstance(x, float) or isinstance(x, int):
            x = max(x, c)
            if x == 1:
                return 1
            if x < 1:
                return (1 - x ** 2) ** -.5 * np.arctanh((1 - x ** 2) ** .5)
            else:
                return (x ** 2 - 1) ** -.5 * np.arctan((x ** 2 - 1) ** .5)

Response: This function returns the Classic NFW function in terms of arctanh and arctanh.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def density(self, R, Rs, rho0, r_core):

        M0 = 4*np.pi*rho0 * Rs ** 3
        return (M0/4/np.pi) * ((r_core + R)*(R + Rs)**2) ** -1

Response: calculate the density of the NFW profile


Instruction:
How would you implement a function in Python 3 that
projects two dimenstional NFW profile at radius R

Response:
def density_2d(self, x, y, Rs, rho0, r_core, center_x=0, center_y=0):
        """
        projected two dimenstional NFW profile (kappa*Sigma_crit)

        :param R: radius of interest
        :type R: float/numpy array
        :param Rs: scale radius
        :type Rs: float
        :param rho0: density normalization (characteristic density)
        :type rho0: float
        :param r200: radius of (sub)halo
        :type r200: float>0
        :return: Epsilon(R) projected density at radius R
        """
        x_ = x - center_x
        y_ = y - center_y
        R = np.sqrt(x_ ** 2 + y_ ** 2)
        b = r_core * Rs ** -1
        x = R * Rs ** -1
        Fx = self._F(x, b)

        return 2 * rho0 * Rs * Fx


Instruction:
Can you implement a function in Python 3 that
calculates the mass of a 3d sphere or radius r

Response:
def mass_3d(self, R, Rs, rho0, r_core):
        """
        mass enclosed a 3d sphere or radius r

        :param r:
        :param Ra:
        :param Rs:
        :return:
        """
        b = r_core * Rs ** -1
        x = R * Rs ** -1

        M_0 = 4 * np.pi * Rs**3 * rho0

        return M_0 * (x * (1+x) ** -1 * (-1+b) ** -1 + (-1+b) ** -2 *
                      ((2*b-1)*np.log(1/(1+x)) + b **2 * np.log(x / b + 1)))


Instruction:
Can you write a function in Python 3 where it
returns the alpha of the NFW profile at radius R

Response:
def cnfwAlpha(self, R, Rs, rho0, r_core, ax_x, ax_y):
        """
        deflection angel of NFW profile along the projection to coordinate axis

        :param R: radius of interest
        :type R: float/numpy array
        :param Rs: scale radius
        :type Rs: float
        :param rho0: density normalization (characteristic density)
        :type rho0: float
        :param r200: radius of (sub)halo
        :type r200: float>0
        :param axis: projection to either x- or y-axis
        :type axis: same as R
        :return: Epsilon(R) projected density at radius R
        """
        if isinstance(R, int) or isinstance(R, float):
            R = max(R, 0.00001)
        else:
            R[R <= 0.00001] = 0.00001

        x = R / Rs
        b = r_core * Rs ** -1
        b = max(b, 0.000001)
        gx = self._G(x, b)

        a = 4*rho0*Rs*gx/x**2
        return a * ax_x, a * ax_y


Instruction:
Make a summary of the following Python 3 code
def function(self, x, y, Rs, theta_Rs, e1, e2, center_x=0, center_y=0):
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_shift = x - center_x
        y_shift = y - center_y
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        e = min(abs(1. - q), 0.99)
        xt1 = (cos_phi*x_shift+sin_phi*y_shift)*np.sqrt(1 - e)
        xt2 = (-sin_phi*x_shift+cos_phi*y_shift)*np.sqrt(1 + e)
        R_ = np.sqrt(xt1**2 + xt2**2)
        rho0_input = self.nfw._alpha2rho0(theta_Rs=theta_Rs, Rs=Rs)
        if Rs < 0.0000001:
            Rs = 0.0000001
        f_ = self.nfw.nfwPot(R_, Rs, rho0_input)
        return f_

Response: function returns the function of the NFW profile


Instruction:
Can you create a Python 3 function that
returns df x y and df y of the function

Response:
def derivatives(self, x, y, Rs, theta_Rs, e1, e2, center_x=0, center_y=0):
        """
        returns df/dx and df/dy of the function (integral of NFW)
        """
        phi_G, q = param_util.ellipticity2phi_q(e1, e2)
        x_shift = x - center_x
        y_shift = y - center_y
        cos_phi = np.cos(phi_G)
        sin_phi = np.sin(phi_G)
        e = min(abs(1. - q), 0.99)
        xt1 = (cos_phi*x_shift+sin_phi*y_shift)*np.sqrt(1 - e)
        xt2 = (-sin_phi*x_shift+cos_phi*y_shift)*np.sqrt(1 + e)
        R_ = np.sqrt(xt1**2 + xt2**2)
        rho0_input = self.nfw._alpha2rho0(theta_Rs=theta_Rs, Rs=Rs)
        if Rs < 0.0000001:
            Rs = 0.0000001
        f_x_prim, f_y_prim = self.nfw.nfwAlpha(R_, Rs, rho0_input, xt1, xt2)
        f_x_prim *= np.sqrt(1 - e)
        f_y_prim *= np.sqrt(1 + e)
        f_x = cos_phi*f_x_prim-sin_phi*f_y_prim
        f_y = sin_phi*f_x_prim+cos_phi*f_y_prim
        return f_x, f_y


Instruction:
Can you generate the documentation for the following Python 3 function
def pso(self, n_particles=10, n_iterations=10, lowerLimit=-0.2, upperLimit=0.2, threadCount=1, mpi=False, print_key='default'):
        init_pos = self.chain.get_args(self.chain.kwargs_data_init)
        num_param = self.chain.num_param
        lowerLimit = [lowerLimit] * num_param
        upperLimit = [upperLimit] * num_param
        if mpi is True:
            pso = MpiParticleSwarmOptimizer(self.chain, lowerLimit, upperLimit, n_particles, threads=1)
        else:
            pso = ParticleSwarmOptimizer(self.chain, lowerLimit, upperLimit, n_particles, threads=threadCount)
        if not init_pos is None:
            pso.gbest.position = init_pos
            pso.gbest.velocity = [0]*len(init_pos)
            pso.gbest.fitness, _ = self.chain.likelihood(init_pos)
        X2_list = []
        vel_list = []
        pos_list = []
        time_start = time.time()
        if pso.isMaster():
            print('Computing the %s ...' % print_key)
        num_iter = 0
        for swarm in pso.sample(n_iterations):
            X2_list.append(pso.gbest.fitness*2)
            vel_list.append(pso.gbest.velocity)
            pos_list.append(pso.gbest.position)
            num_iter += 1
            if pso.isMaster():
                if num_iter % 10 == 0:
                    print(num_iter)
        if not mpi:
            result = pso.gbest.position
        else:
            result = MpiUtil.mpiBCast(pso.gbest.position)
        kwargs_data = self.chain.update_data(result)
        if mpi is True and not pso.isMaster():
            pass
        else:
            time_end = time.time()
            print("Shifts found: ", result)
            print(time_end - time_start, 'time used for PSO', print_key)
        return kwargs_data, [X2_list, pos_list, vel_list, []]

Response: Returns the best fit for the lense model on catalogue basis with particle swarm optimizer.


Instruction:
How would you implement a function in Python 3 that
computes likelihood for a MCMC chainF

Response:
def _likelihood(self, args):
        """
        routine to compute X2 given variable parameters for a MCMC/PSO chainF
        """
        #generate image and computes likelihood
        kwargs_data = self.update_data(args)
        imageModel = class_creator.create_image_model(kwargs_data, self._kwargs_psf, self._kwargs_numerics, self._kwargs_model)
        logL = imageModel.likelihood_data_given_model(self._kwargs_lens, self._kwargs_source, self._kwargs_lens_light, self._kwargs_else, source_marg=self._source_marg)
        return logL, None


Instruction:
Can you generate a brief explanation for the following Python 3 code
def optimize(self, n_particles=50, n_iterations=250, restart=1):

        """
        the best result of all optimizations will be returned.
        total number of lens models sovled: n_particles*n_iterations

        :param n_particles: number of particle swarm particles
        :param n_iterations: number of particle swarm iternations
        :param restart: number of times to execute the optimization;

        :return: lens model keywords, [optimized source position], best fit image positions
        """

        if restart < 0:
            raise ValueError("parameter 'restart' must be integer of value > 0")

        # particle swarm optimization
        penalties, parameters, src_pen_best = [],[], []

        for run in range(0, restart):

            penalty, params = self._single_optimization(n_particles, n_iterations)
            penalties.append(penalty)
            parameters.append(params)
            src_pen_best.append(self._optimizer.src_pen_best)

        # select the best optimization
        best_index = np.argmin(penalties)

        # combine the optimized parameters with the parameters kept fixed during the optimization to obtain full kwargs_lens
        kwargs_varied = self._params.argstovary_todictionary(parameters[best_index])
        kwargs_lens_final = kwargs_varied + self._params.argsfixed_todictionary()

        # solve for the optimized image positions
        srcx, srcy = self._optimizer.lensing._ray_shooting_fast(kwargs_varied)
        source_x, source_y = np.mean(srcx), np.mean(srcy)

        # if we have a good enough solution, no point in recomputing the image positions since this can be quite slow
        # and will give the same answer
        if src_pen_best[best_index] < self._tol_src_penalty:
            x_image, y_image = self.x_pos, self.y_pos
        else:
            # Here, the solver has the instance of "lensing_class" or "LensModel" for multiplane/singleplane respectively.
            print('Warning: possibly a bad fit.')
            x_image, y_image = self.solver.findBrightImage(source_x, source_y, kwargs_lens_final, arrival_time_sort=False)
            #x_image, y_image = self.solver.image_position_from_source(source_x, source_y, kwargs_lens_final, arrival_time_sort = False)
        if self._verbose:
            print('optimization done.')
            print('Recovered source position: ', (srcx, srcy))

        return kwargs_lens_final, [source_x, source_y], [x_image, y_image]

Response: This function performs a single optimization of the lens model and returns the best fit image positions and the best fit image keywords.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def de_projection_3d(amplitudes, sigmas):
    amplitudes_3d = amplitudes / sigmas / np.sqrt(2*np.pi)
    return amplitudes_3d, sigmas

Response: de - projects a 2d Gaussians from a 2d projected to a 3d profile


Instruction:
Make a summary of the following Python 3 code
def set_pixel_size(self, deltaPix):
        self._pixel_size = deltaPix
        if self.psf_type == 'GAUSSIAN':
            try:
                del self._kernel_point_source
            except:
                pass

Response: update the pixel size of the current node


Instruction:
Can you create a Python 3 function that
calculates center of mass

Response:
def com(self, center1_x, center1_y, center2_x, center2_y, Fm):
        """
        :return: center of mass
        """
        com_x = (Fm * center1_x + center2_x)/(Fm + 1.)
        com_y = (Fm * center1_y + center2_y)/(Fm + 1.)
        return com_x, com_y


Instruction:
Explain what the following Python 3 code does
def angle(self, center1_x, center1_y, center2_x, center2_y):
        phi_G = np.arctan2(center2_y - center1_y, center2_x - center1_x)
        return phi_G

Response: compute the rotation angle of the dipole


Instruction:
Make a summary of the following Python 3 code
def logL(self, kwargs_lens, kwargs_ps, kwargs_cosmo):
        x_pos, y_pos = self._pointSource.image_position(kwargs_ps=kwargs_ps, kwargs_lens=kwargs_lens)
        x_pos, y_pos = self._param.real_image_positions(x_pos[0], y_pos[0], kwargs_cosmo)
        x_source, y_source = self._lensModel.ray_shooting(x_pos, y_pos, kwargs_lens)
        delay_arcsec = self._lensModel.fermat_potential(x_pos, y_pos, x_source, y_source, kwargs_lens)
        D_dt_model = kwargs_cosmo['D_dt']
        delay_days = const.delay_arcsec2days(delay_arcsec, D_dt_model)
        logL = self._logL_delays(delay_days, self._delays_measured, self._delays_errors)
        return logL

Response: compute the log likelihood of the model given the time delay


Instruction:
Write a Python 3 function that can
compute the log likelihood of modeled delays vs measured time delays under considerations of errors

Response:
def _logL_delays(self, delays_model, delays_measured, delays_errors):
        """
        log likelihood of modeled delays vs measured time delays under considerations of errors

        :param delays_model: n delays of the model (not relative delays)
        :param delays_measured: relative delays (1-2,1-3,1-4) relative to the first in the list
        :param delays_errors: gaussian errors on the measured delays
        :return: log likelihood of data given model
        """
        delta_t_model = np.array(delays_model[1:]) - delays_model[0]
        logL = np.sum(-(delta_t_model - delays_measured) ** 2 / (2 * delays_errors ** 2))
        return logL


Instruction:
Can you tell what is the following Python 3 function doing
def shift_coordinate_grid(self, x_shift, y_shift, pixel_unit=False):
        if pixel_unit is True:
            ra_shift, dec_shift = self.map_pix2coord(x_shift, y_shift)
        else:
            ra_shift, dec_shift = x_shift, y_shift
        self._ra_at_xy_0 += ra_shift
        self._dec_at_xy_0 += dec_shift
        self._x_at_radec_0, self._y_at_radec_0 = util.map_coord2pix(-self._ra_at_xy_0, -self._dec_at_xy_0, 0, 0,
                                                                    self._Ma2pix)

Response: shifts the coordinate grid of the data class with the given shift in x and y


Instruction:
Can you create a Python 3 function that
extracts the array of parameters from kwargs_list

Response:
def _extract_array(self, kwargs_list):
        """
        inverse of _update_kwargs
        :param kwargs_list:
        :return:
        """
        if self._solver_type == 'PROFILE_SHEAR':
            e1 = kwargs_list[1]['e1']
            e2 = kwargs_list[1]['e2']
            phi_ext, gamma_ext = param_util.ellipticity2phi_gamma(e1, e2)
        else:
            phi_ext = 0
        lens_model = self._lens_mode_list[0]
        if lens_model in ['SPEP', 'SPEMD', 'SIE', 'NIE']:
            e1 = kwargs_list[0]['e1']
            e2 = kwargs_list[0]['e2']
            center_x = kwargs_list[0]['center_x']
            center_y = kwargs_list[0]['center_y']
            theta_E = kwargs_list[0]['theta_E']
            x = [theta_E, e1, e2, center_x, center_y, phi_ext]
        elif lens_model in ['NFW_ELLIPSE']:
            e1 = kwargs_list[0]['e1']
            e2 = kwargs_list[0]['e2']
            center_x = kwargs_list[0]['center_x']
            center_y = kwargs_list[0]['center_y']
            theta_Rs = kwargs_list[0]['theta_Rs']
            x = [theta_Rs, e1, e2, center_x, center_y, phi_ext]
        elif lens_model in ['SHAPELETS_CART']:
            coeffs = list(kwargs_list[0]['coeffs'])
            [c10, c01, c20, c11, c02] = coeffs[1: 6]
            x = [c10, c01, c20, c11, c02, phi_ext]
        else:
            raise ValueError("Lens model %s not supported for 4-point solver!" % lens_model)
        return x


Instruction:
Implement a Python 3 function for
returning df dx and dy of the function

Response:
def derivatives(self, x, y, grid_interp_x=None, grid_interp_y=None, f_=None, f_x=None, f_y=None, f_xx=None, f_yy=None, f_xy=None):
        """
        returns df/dx and df/dy of the function
        """
        #self._check_interp(grid_interp_x, grid_interp_y, f_, f_x, f_y, f_xx, f_yy, f_xy)
        n = len(np.atleast_1d(x))
        if n <= 1 and np.shape(x) == ():
        #if type(x) == float or type(x) == int or type(x) == type(np.float64(1)) or len(x) <= 1:
            f_x_out = self.f_x_interp(x, y, grid_interp_x, grid_interp_y, f_x)
            f_y_out = self.f_y_interp(x, y, grid_interp_x, grid_interp_y, f_y)
            return f_x_out[0][0], f_y_out[0][0]
        else:
            if self._grid and n >= self._min_grid_number:
                x_, y_ = util.get_axes(x, y)
                f_x_out = self.f_x_interp(x_, y_, grid_interp_x, grid_interp_y, f_x)
                f_y_out = self.f_y_interp(x_, y_, grid_interp_x, grid_interp_y, f_y)
                f_x_out = util.image2array(f_x_out)
                f_y_out = util.image2array(f_y_out)
            else:
                #n = len(x)
                f_x_out, f_y_out = np.zeros(n), np.zeros(n)
                for i in range(n):
                    f_x_out[i] = self.f_x_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_x)
                    f_y_out[i] = self.f_y_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_y)
        return f_x_out, f_y_out


Instruction:
How would you code a function in Python 3 to
return the Hessian matrix of function f

Response:
def hessian(self, x, y, grid_interp_x=None, grid_interp_y=None, f_=None, f_x=None, f_y=None, f_xx=None, f_yy=None, f_xy=None):
        """
        returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy
        """
        #self._check_interp(grid_interp_x, grid_interp_y, f_, f_x, f_y, f_xx, f_yy, f_xy)
        n = len(np.atleast_1d(x))
        if n <= 1 and np.shape(x) == ():
        #if type(x) == float or type(x) == int or type(x) == type(np.float64(1)) or len(x) <= 1:
            f_xx_out = self.f_xx_interp(x, y, grid_interp_x, grid_interp_y, f_xx)
            f_yy_out = self.f_yy_interp(x, y, grid_interp_x, grid_interp_y, f_yy)
            f_xy_out = self.f_xy_interp(x, y, grid_interp_x, grid_interp_y, f_xy)
            return f_xx_out[0][0], f_yy_out[0][0], f_xy_out[0][0]
        else:
            if self._grid and n >= self._min_grid_number:
                x_, y_ = util.get_axes(x, y)
                f_xx_out = self.f_xx_interp(x_, y_, grid_interp_x, grid_interp_y, f_xx)
                f_yy_out = self.f_yy_interp(x_, y_, grid_interp_x, grid_interp_y, f_yy)
                f_xy_out = self.f_xy_interp(x_, y_, grid_interp_x, grid_interp_y, f_xy)
                f_xx_out = util.image2array(f_xx_out)
                f_yy_out = util.image2array(f_yy_out)
                f_xy_out = util.image2array(f_xy_out)
            else:
                #n = len(x)
                f_xx_out, f_yy_out, f_xy_out = np.zeros(n), np.zeros(n), np.zeros(n)
                for i in range(n):
                    f_xx_out[i] = self.f_xx_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_xx)
                    f_yy_out[i] = self.f_yy_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_yy)
                    f_xy_out[i] = self.f_xy_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_xy)
        return f_xx_out, f_yy_out, f_xy_out


Instruction:
Can you create a Python 3 function that
plots a single lens model and the critical curves and caustics.

Response:
def lens_model_plot(ax, lensModel, kwargs_lens, numPix=500, deltaPix=0.01, sourcePos_x=0, sourcePos_y=0,
                    point_source=False, with_caustics=False):
    """
    plots a lens model (convergence) and the critical curves and caustics

    :param ax:
    :param kwargs_lens:
    :param numPix:
    :param deltaPix:
    :return:
    """
    kwargs_data = sim_util.data_configure_simple(numPix, deltaPix)
    data = Data(kwargs_data)
    _frame_size = numPix * deltaPix
    _coords = data._coords
    x_grid, y_grid = data.coordinates
    lensModelExt = LensModelExtensions(lensModel)
    #ra_crit_list, dec_crit_list, ra_caustic_list, dec_caustic_list = lensModelExt.critical_curve_caustics(
    #    kwargs_lens, compute_window=_frame_size, grid_scale=deltaPix/2.)
    x_grid1d = util.image2array(x_grid)
    y_grid1d = util.image2array(y_grid)
    kappa_result = lensModel.kappa(x_grid1d, y_grid1d, kwargs_lens)
    kappa_result = util.array2image(kappa_result)
    im = ax.matshow(np.log10(kappa_result), origin='lower', extent=[0, _frame_size, 0, _frame_size], cmap='Greys',
                    vmin=-1, vmax=1) #, cmap=self._cmap, vmin=v_min, vmax=v_max)
    if with_caustics is True:
        ra_crit_list, dec_crit_list = lensModelExt.critical_curve_tiling(kwargs_lens, compute_window=_frame_size,
                                                                         start_scale=deltaPix, max_order=10)
        ra_caustic_list, dec_caustic_list = lensModel.ray_shooting(ra_crit_list, dec_crit_list, kwargs_lens)
        plot_line_set(ax, _coords, ra_caustic_list, dec_caustic_list, color='g')
        plot_line_set(ax, _coords, ra_crit_list, dec_crit_list, color='r')
    if point_source:
        from lenstronomy.LensModel.Solver.lens_equation_solver import LensEquationSolver
        solver = LensEquationSolver(lensModel)
        theta_x, theta_y = solver.image_position_from_source(sourcePos_x, sourcePos_y, kwargs_lens,
                                                             min_distance=deltaPix, search_window=deltaPix*numPix)
        mag_images = lensModel.magnification(theta_x, theta_y, kwargs_lens)
        x_image, y_image = _coords.map_coord2pix(theta_x, theta_y)
        abc_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
        for i in range(len(x_image)):
            x_ = (x_image[i] + 0.5) * deltaPix
            y_ = (y_image[i] + 0.5) * deltaPix
            ax.plot(x_, y_, 'dk', markersize=4*(1 + np.log(np.abs(mag_images[i]))), alpha=0.5)
            ax.text(x_, y_, abc_list[i], fontsize=20, color='k')
        x_source, y_source = _coords.map_coord2pix(sourcePos_x, sourcePos_y)
        ax.plot((x_source + 0.5) * deltaPix, (y_source + 0.5) * deltaPix, '*k', markersize=10)
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    ax.autoscale(False)
    #image_position_plot(ax, _coords, self._kwargs_else)
    #source_position_plot(ax, self._coords, self._kwargs_source)
    return ax


Instruction:
Can you tell what is the following Python 3 function doing
def plot_mcmc_behaviour(ax, samples_mcmc, param_mcmc, dist_mcmc, num_average=100):
    num_samples = len(samples_mcmc[:, 0])
    num_average = int(num_average)
    n_points = int((num_samples - num_samples % num_average) / num_average)
    for i, param_name in enumerate(param_mcmc):
        samples = samples_mcmc[:, i]
        samples_averaged = np.average(samples[:int(n_points * num_average)].reshape(n_points, num_average), axis=1)
        end_point = np.mean(samples_averaged)
        samples_renormed = (samples_averaged - end_point) / np.std(samples_averaged)
        ax.plot(samples_renormed, label=param_name)

    dist_averaged = -np.max(dist_mcmc[:int(n_points * num_average)].reshape(n_points, num_average), axis=1)
    dist_normed = (dist_averaged - np.max(dist_averaged)) / (np.max(dist_averaged) - np.min(dist_averaged))
    ax.plot(dist_normed, label="logL", color='k', linewidth=2)
    ax.legend()
    return ax

Response: Plots the MCMC behaviour and looks for convergence of the chain


Instruction:
Write a Python 3 script to
print the main plots together in a joint frame

Response:
def plot_main(self, with_caustics=False, image_names=False):
        """
        print the main plots together in a joint frame

        :return:
        """

        f, axes = plt.subplots(2, 3, figsize=(16, 8))
        self.data_plot(ax=axes[0, 0])
        self.model_plot(ax=axes[0, 1], image_names=True)
        self.normalized_residual_plot(ax=axes[0, 2], v_min=-6, v_max=6)
        self.source_plot(ax=axes[1, 0], deltaPix_source=0.01, numPix=100, with_caustics=with_caustics)
        self.convergence_plot(ax=axes[1, 1], v_max=1)
        self.magnification_plot(ax=axes[1, 2])
        f.tight_layout()
        f.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0., hspace=0.05)
        return f, axes


Instruction:
Explain what the following Python 3 code does
def plot_separate(self):
        f, axes = plt.subplots(2, 3, figsize=(16, 8))

        self.decomposition_plot(ax=axes[0, 0], text='Lens light', lens_light_add=True, unconvolved=True)
        self.decomposition_plot(ax=axes[1, 0], text='Lens light convolved', lens_light_add=True)
        self.decomposition_plot(ax=axes[0, 1], text='Source light', source_add=True, unconvolved=True)
        self.decomposition_plot(ax=axes[1, 1], text='Source light convolved', source_add=True)
        self.decomposition_plot(ax=axes[0, 2], text='All components', source_add=True, lens_light_add=True,
                                    unconvolved=True)
        self.decomposition_plot(ax=axes[1, 2], text='All components convolved', source_add=True,
                                    lens_light_add=True, point_source_add=True)
        f.tight_layout()
        f.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0., hspace=0.05)
        return f, axes

Response: plot the different model components separately


Instruction:
Create a Python 3 function to
subtract model components from data

Response:
def plot_subtract_from_data_all(self):
        """
        subtract model components from data

        :return:
        """
        f, axes = plt.subplots(2, 3, figsize=(16, 8))

        self.subtract_from_data_plot(ax=axes[0, 0], text='Data')
        self.subtract_from_data_plot(ax=axes[0, 1], text='Data - Point Source', point_source_add=True)
        self.subtract_from_data_plot(ax=axes[0, 2], text='Data - Lens Light', lens_light_add=True)
        self.subtract_from_data_plot(ax=axes[1, 0], text='Data - Source Light', source_add=True)
        self.subtract_from_data_plot(ax=axes[1, 1], text='Data - Source Light - Point Source', source_add=True,
                                         point_source_add=True)
        self.subtract_from_data_plot(ax=axes[1, 2], text='Data - Lens Light - Point Source', lens_light_add=True,
                                         point_source_add=True)
        f.tight_layout()
        f.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0., hspace=0.05)
        return f, axes


Instruction:
Explain what the following Python 3 code does
def derivatives(self, x, y, coeffs, beta, center_x=0, center_y=0):
        shapelets = self._createShapelet(coeffs)
        r, phi = param_util.cart2polar(x, y, center=np.array([center_x, center_y]))
        alpha1_shapelets, alpha2_shapelets = self._alphaShapelets(shapelets, beta)
        f_x = self._shapeletOutput(r, phi, beta, alpha1_shapelets)
        f_y = self._shapeletOutput(r, phi, beta, alpha2_shapelets)
        return f_x, f_y

Response: returns df dx dy of the function


Instruction:
How would you implement a function in Python 3 that
returns Hessian matrix of function d^2f / dx^2 y d^2f / dy^2

Response:
def hessian(self, x, y, coeffs, beta, center_x=0, center_y=0):
        """
        returns Hessian matrix of function d^2f/dx^2, d^f/dy^2, d^2/dxdy
        """
        shapelets = self._createShapelet(coeffs)
        r, phi = param_util.cart2polar(x, y, center=np.array([center_x, center_y]))
        kappa_shapelets=self._kappaShapelets(shapelets, beta)
        gamma1_shapelets, gamma2_shapelets=self._gammaShapelets(shapelets, beta)
        kappa_value=self._shapeletOutput(r, phi, beta, kappa_shapelets)
        gamma1_value=self._shapeletOutput(r, phi, beta, gamma1_shapelets)
        gamma2_value=self._shapeletOutput(r, phi, beta, gamma2_shapelets)
        f_xx = kappa_value + gamma1_value
        f_xy = gamma2_value
        f_yy = kappa_value - gamma1_value
        return f_xx, f_yy, f_xy


Instruction:
Write a Python 3 script for
creating a shapelet array out of the coefficients a and b.

Response:
def _createShapelet(self,coeff):
        """
        returns a shapelet array out of the coefficients *a, up to order l

        :param num_l: order of shapelets
        :type num_l: int.
        :param coeff: shapelet coefficients
        :type coeff: floats
        :returns:  complex array
        :raises: AttributeError, KeyError
        """
        n_coeffs = len(coeff)
        num_l = self._get_num_l(n_coeffs)
        shapelets=np.zeros((num_l+1,num_l+1),'complex')
        nl=0
        k=0
        i=0
        while i < len(coeff):
            if i%2==0:
                shapelets[nl][k]+=coeff[i]/2.
                shapelets[k][nl]+=coeff[i]/2.
                if k==nl:
                    nl+=1
                    k=0
                    i+=1
                    continue
                else:
                    k+=1
                    i+=1
                    continue
            else:
                shapelets[nl][k] += 1j*coeff[i]/2.
                shapelets[k][nl] -= 1j*coeff[i]/2.
                i+=1
        return shapelets


Instruction:
Can you write a function in Python 3 where it
returns the the numerical values of a set of shapelets at polar coordinates :param shapelets: set of shapelets [l=,r=,a_lr=] :type shapelets: array of size (n,3) :param coordPolar: set of coordinates in polar units :type coordPolar: array of size (n,2) :returns: array of same size with coords [r,phi] :raises: AttributeError, KeyError

Response:
def _shapeletOutput(self, r, phi, beta, shapelets):
        """
        returns the the numerical values of a set of shapelets at polar coordinates
        :param shapelets: set of shapelets [l=,r=,a_lr=]
        :type shapelets: array of size (n,3)
        :param coordPolar: set of coordinates in polar units
        :type coordPolar: array of size (n,2)
        :returns:  array of same size with coords [r,phi]
        :raises: AttributeError, KeyError
        """
        if type(r) == float or type(r) == int or type(r) == type(np.float64(1)) or len(r) <= 1:
            values = 0.
        else:
            values = np.zeros(len(r), 'complex')
        for nl in range(0,len(shapelets)): #sum over different shapelets
            for nr in range(0,len(shapelets)):
                value = shapelets[nl][nr]*self._chi_lr(r, phi, nl, nr, beta)
                values += value
        return values.real


Instruction:
Can you generate the documentation for the following Python 3 function
def _chi_lr(self,r, phi, nl,nr,beta):
        m=int((nr-nl).real)
        n=int((nr+nl).real)
        p=int((n-abs(m))/2)
        p2=int((n+abs(m))/2)
        q=int(abs(m))
        if p % 2==0: #if p is even
            prefac=1
        else:
            prefac=-1
        prefactor=prefac/beta**(abs(m)+1)*np.sqrt(math.factorial(p)/(np.pi*math.factorial(p2)))
        poly=self.poly[p][q]
        return prefactor*r**q*poly((r/beta)**2)*np.exp(-(r/beta)**2/2)*np.exp(-1j*m*phi)

Response: Compute the generalized polar basis function in the convention of Massey & Refregier eqn 8


Instruction:
Write a Python 3 script to
calculate convergence kappa given lensing potential shapelet coefficients laplacian and beta

Response:
def _kappaShapelets(self, shapelets, beta):
        """
        calculates the convergence kappa given lensing potential shapelet coefficients (laplacian/2)
        :param shapelets: set of shapelets [l=,r=,a_lr=]
        :type shapelets: array of size (n,3)
        :returns:  set of kappa shapelets.
        :raises: AttributeError, KeyError
        """
        output=np.zeros((len(shapelets)+1,len(shapelets)+1),'complex')
        for nl in range(0,len(shapelets)):
            for nr in range(0,len(shapelets)):
                a_lr=shapelets[nl][nr]
                if nl>0:
                    output[nl-1][nr+1]+=a_lr*np.sqrt(nl*(nr+1))/2
                    if nr>0:
                        output[nl-1][nr-1]+=a_lr*np.sqrt(nl*nr)/2
                output[nl+1][nr+1]+=a_lr*np.sqrt((nl+1)*(nr+1))/2
                if nr>0:
                    output[nl+1][nr-1]+=a_lr*np.sqrt((nl+1)*nr)/2
        return output/beta**2


Instruction:
Can you generate the documentation for the following Python 3 function
def _alphaShapelets(self,shapelets, beta):
        output_x = np.zeros((len(shapelets)+1, len(shapelets)+1), 'complex')
        output_y = np.zeros((len(shapelets)+1, len(shapelets)+1), 'complex')
        for nl in range(0,len(shapelets)):
            for nr in range(0,len(shapelets)):
                a_lr=shapelets[nl][nr]
                output_x[nl][nr+1]-=a_lr*np.sqrt(nr+1)/2
                output_y[nl][nr+1]-=a_lr*np.sqrt(nr+1)/2*1j
                output_x[nl+1][nr]-=a_lr*np.sqrt(nl+1)/2
                output_y[nl+1][nr]+=a_lr*np.sqrt(nl+1)/2*1j
                if nl>0:
                    output_x[nl-1][nr]+=a_lr*np.sqrt(nl)/2
                    output_y[nl-1][nr]-=a_lr*np.sqrt(nl)/2*1j
                if nr>0:
                    output_x[nl][nr-1]+=a_lr*np.sqrt(nr)/2
                    output_y[nl][nr-1]+=a_lr*np.sqrt(nr)/2*1j
        return output_x/beta,output_y/beta

Response: Calculates the deflection angles given lensing potential shapelet coefficients


Instruction:
Write a Python 3 function that can
return the critical projected mass density in units of M_sun Mpc^2

Response:
def epsilon_crit(self):
        """
        returns the critical projected mass density in units of M_sun/Mpc^2 (physical units)
        """
        const_SI = const.c**2 / (4*np.pi * const.G)  #c^2/(4*pi*G) in units of [kg/m]
        conversion = const.Mpc / const.M_sun  # converts [kg/m] to [M_sun/Mpc]
        pre_const = const_SI*conversion   #c^2/(4*pi*G) in units of [M_sun/Mpc]
        Epsilon_Crit = self.D_s/(self.D_d*self.D_ds) * pre_const #[M_sun/Mpc^2]
        return Epsilon_Crit


Instruction:
Can you generate the documentation for the following Python 3 function
def F(self, x):
        if isinstance(x, np.ndarray):
            nfwvals = np.ones_like(x)
            inds1 = np.where(x < 1)
            inds2 = np.where(x > 1)
            nfwvals[inds1] = (1 - x[inds1] ** 2) ** -.5 * np.arctanh((1 - x[inds1] ** 2) ** .5)
            nfwvals[inds2] = (x[inds2] ** 2 - 1) ** -.5 * np.arctan((x[inds2] ** 2 - 1) ** .5)
            return nfwvals

        elif isinstance(x, float) or isinstance(x, int):
            if x == 1:
                return 1
            if x < 1:
                return (1 - x ** 2) ** -.5 * np.arctanh((1 - x ** 2) ** .5)
            else:
                return (x ** 2 - 1) ** -.5 * np.arctan((x ** 2 - 1) ** .5)

Response: r - > r


Instruction:
Implement a function in Python 3 to
project two dimenstional NFW profile at radius R

Response:
def density_2d(self, x, y, Rs, rho0, r_trunc, center_x=0, center_y=0):
        """
        projected two dimenstional NFW profile (kappa*Sigma_crit)

        :param R: radius of interest
        :type R: float/numpy array
        :param Rs: scale radius
        :type Rs: float
        :param rho0: density normalization (characteristic density)
        :type rho0: float
        :param r200: radius of (sub)halo
        :type r200: float>0
        :return: Epsilon(R) projected density at radius R
        """
        x_ = x - center_x
        y_ = y - center_y
        R = np.sqrt(x_ ** 2 + y_ ** 2)
        x = R * Rs ** -1
        tau = float(r_trunc) * Rs ** -1
        Fx = self._F(x, tau)
        return 2 * rho0 * Rs * Fx


Instruction:
Can you implement a function in Python 3 that
calculates the mass of a 3d sphere or radius r

Response:
def mass_3d(self, R, Rs, rho0, r_trunc):
        """
        mass enclosed a 3d sphere or radius r

        :param r:
        :param Ra:
        :param Rs:
        :return:
        """

        x = R * Rs ** -1

        func = (r_trunc ** 2 * (-2 * x * (1 + r_trunc ** 2) + 4 * (1 + x) * r_trunc * np.arctan(x / r_trunc) -
                                2 * (1 + x) * (-1 + r_trunc ** 2) * np.log(Rs) + 2 * (1 + x) * (-1 + r_trunc ** 2) * np.log(Rs * (1 + x)) +
                                2 * (1 + x) * (-1 + r_trunc ** 2) * np.log(Rs * r_trunc) -
                                (1 + x) * (-1 + r_trunc ** 2) * np.log(Rs ** 2 * (x ** 2 + r_trunc ** 2)))) / (2. * (1 + x) * (1 + r_trunc ** 2) ** 2)

        m_3d = 4*np.pi*Rs ** 3 * rho0 * func
        return m_3d


Instruction:
Can you tell what is the following Python 3 function doing
def nfwPot(self, R, Rs, rho0, r_trunc):
        x = R / Rs
        tau = float(r_trunc) / Rs
        hx = self._h(x, tau)
        return 2 * rho0 * Rs ** 3 * hx

Response: calculate lensing potential of NFW profile


Instruction:
How would you implement a function in Python 3 that
returns the alpha of the NFW profile at radius R

Response:
def nfwAlpha(self, R, Rs, rho0, r_trunc, ax_x, ax_y):
        """
        deflection angel of NFW profile along the projection to coordinate axis

        :param R: radius of interest
        :type R: float/numpy array
        :param Rs: scale radius
        :type Rs: float
        :param rho0: density normalization (characteristic density)
        :type rho0: float
        :param r200: radius of (sub)halo
        :type r200: float>0
        :param axis: projection to either x- or y-axis
        :type axis: same as R
        :return: Epsilon(R) projected density at radius R
        """
        if isinstance(R, int) or isinstance(R, float):
            R = max(R, 0.00001)
        else:
            R[R <= 0.00001] = 0.00001

        x = R / Rs
        tau = float(r_trunc) / Rs
        gx = self._g(x, tau)
        a = 4 * rho0 * Rs * gx / x ** 2
        return a * ax_x, a * ax_y


Instruction:
How would you code a function in Python 3 to
calculate mass of a 2D system from a set of R and Rs

Response:
def mass_2d(self,R,Rs,rho0,r_trunc):

        """
        analytic solution of the projection integral
        (convergence)

        :param x: R/Rs
        :type x: float >0
        """

        x = R / Rs
        tau = r_trunc / Rs
        gx = self._g(x,tau)
        m_2d = 4 * rho0 * Rs * R ** 2 * gx / x ** 2 * np.pi
        return m_2d


Instruction:
Write a Python 3 function for
computing analytic solution of integral for NFW profile

Response:
def _g(self, x, tau):
        """
        analytic solution of integral for NFW profile to compute deflection angel and gamma

        :param x: R/Rs
        :type x: float >0
        """
        return tau ** 2 * (tau ** 2 + 1) ** -2 * (
                (tau ** 2 + 1 + 2 * (x ** 2 - 1)) * self.F(x) + tau * np.pi + (tau ** 2 - 1) * np.log(tau) +
                np.sqrt(tau ** 2 + x ** 2) * (-np.pi + self.L(x, tau) * (tau ** 2 - 1) * tau ** -1))


Instruction:
Given the following Python 3 function, write the documentation
def _h(self, X, tau):

        """
        a horrible expression for the integral to compute potential

        :param x: R/Rs
        :param tau: t/Rs
        :type x: float >0
        """

        def cos_func(y):
            if isinstance(y, float) or isinstance(y, int):
                if y > 1:
                    return np.arccosh(y)
                else:
                    return np.arccos(y)
            else:
                values = np.ones_like(y)
                inds1 = np.where(y < 1)
                inds2 = np.where(y > 1)
                values[inds1] = np.arccos(y[inds1])
                # values[inds2] = np.arccosh(y[inds2])
                values[inds2] = np.arccos((1 - y[inds2]) ** .5)
                return values

        def nfw_func(x):
            if isinstance(x,float) or isinstance(x,int):
                if x<1:
                    return np.log(x / 2.) ** 2 - np.arccosh(1. / x) ** 2
                else:
                    return np.log(x / 2.)**2 - np.arccos(1. /x)**2
            else:
                inds1 = np.where(x < 1)
                inds2 = np.where(x >= 1)
                y = np.zeros_like(x)
                y[inds1] = np.log(x[inds1] / 2.) ** 2 - np.arccosh(1. / x[inds1]) ** 2
                y[inds2] = np.log(x[inds2] / 2.) ** 2 - np.arccosh(1. / x[inds2]) ** 2

                return y

        def tnfw_func(x,tau):

            u = x**2
            t2 = tau**2
            Lx = self.L(u**.5, tau)

            return (t2 + 1) ** -2 * (
                2 * t2 * np.pi * (tau - (t2 + u) ** .5 + tau * np.log(tau + (t2 + u) ** .5))
                +
                2 * (t2 - 1) * tau * (t2 + u) ** .5 * Lx
                +
                t2 * (t2 - 1) * Lx ** 2
                +
                4 * t2 * (u - 1) * self.F(u**.5)
                +
                t2 * (t2 - 1) * (cos_func(u ** -0.5)) ** 2
                +
                t2 * ((t2 - 1) * np.log(tau) - t2 - 1) * np.log(u)
                -
                t2 * (
                (t2 - 1) * np.log(tau) * np.log(4 * tau) + 2 * np.log(0.5 * tau) - 2 * tau * (tau - np.pi) * np.log(
                    tau * 2)))

        c = 1e-9
        rescale = 1

        if np.any(X-c<1):

            warnings.warn('Truncated NFW potential not yet implemented for x<1. Using the expression for the NFW '
                          'potential in this regime isntead.')
            rescale = tnfw_func(1.00001,tau)*nfw_func(1)**-1

        if isinstance(X,float) or isinstance(X,int):
            if X<1:
                X = min(X,0.001)
                return nfw_func(X)*rescale
            else:
                return tnfw_func(X,tau)
        else:

            X[np.where(X<0.001)] = 0.001

            values = np.zeros_like(X)
            inds1,inds2 = np.where(X<1),np.where(X>=1)
            values[inds1] = nfw_func(X[inds1])*rescale
            values[inds2] = tnfw_func(X[inds2],tau)

            return values

Response: a horrible expression for the integral to compute potential


Instruction:
Implement a function in Python 3 to
transform cartesian coords [x,y] into polar coords [r,phi] in the frame of the lense center :param coord: set of coordinates :type coord: array of size (n,2) :param center: rotation point :type center: array of size (2) :returns: array of same size with coords [r,phi] :raises: AttributeError, KeyError

Response:
def cart2polar(x, y, center=np.array([0, 0])):
    """
    transforms cartesian coords [x,y] into polar coords [r,phi] in the frame of the lense center

    :param coord: set of coordinates
    :type coord: array of size (n,2)
    :param center: rotation point
    :type center: array of size (2)
    :returns:  array of same size with coords [r,phi]
    :raises: AttributeError, KeyError
    """
    coordShift_x = x - center[0]
    coordShift_y = y - center[1]
    r = np.sqrt(coordShift_x**2+coordShift_y**2)
    phi = np.arctan2(coordShift_y, coordShift_x)
    return r, phi


Instruction:
How would you code a function in Python 3 to
transform polar coords [r,phi] into cartesian coords [x,y] in the frame of the lense center :param coord: set of coordinates :type coord: array of size (n,2) :param center: rotation point :type center: array of size (2) :returns: array of same size with coords [x,y] :raises: AttributeError, KeyError

Response:
def polar2cart(r, phi, center):
    """
    transforms polar coords [r,phi] into cartesian coords [x,y] in the frame of the lense center

    :param coord: set of coordinates
    :type coord: array of size (n,2)
    :param center: rotation point
    :type center: array of size (2)
    :returns:  array of same size with coords [x,y]
    :raises: AttributeError, KeyError
    """
    x = r*np.cos(phi)
    y = r*np.sin(phi)
    return x - center[0], y - center[1]


Instruction:
Explain what the following Python 3 code does
def ellipticity2phi_gamma(e1, e2):
    phi = np.arctan2(e2, e1)/2
    gamma = np.sqrt(e1**2+e2**2)
    return phi, gamma

Response: returns the angle and abs value of the ellipticity component


Instruction:
How would you explain what the following Python 3 function does
def transform_e1e2(x, y, e1, e2, center_x=0, center_y=0):
    x_shift = x - center_x
    y_shift = y - center_y
    x_ = (1-e1) * x_shift - e2 * y_shift
    y_ = -e2 * x_shift + (1 + e1) * y_shift
    det = np.sqrt((1-e1)*(1+e1) + e2**2)
    return x_ / det, y_ / det

Response: This function transforms the coordinates x y with eccentricities e1 e2 into an elliptical coordiante system.


Instruction:
Write a Python 3 script for
computing the phi and q of the ellipticity

Response:
def ellipticity2phi_q(e1, e2):
    """
    :param e1:
    :param e2:
    :return:
    """
    phi = np.arctan2(e2, e1)/2
    c = np.sqrt(e1**2+e2**2)
    if c > 0.999:
        c = 0.999
    q = (1-c)/(1+c)
    return phi, q


Instruction:
Here you have a function in Python 3, explain what it does
def time_delays(self, kwargs_lens, kwargs_ps, kappa_ext=0):
        fermat_pot = self.lens_analysis.fermat_potential(kwargs_lens, kwargs_ps)
        time_delay = self.lensCosmo.time_delay_units(fermat_pot, kappa_ext)
        return time_delay

Response: predicts the time delays at the image positions


Instruction:
Write a Python 3 function that can
compute the velocity dispersion of the LOS lens model

Response:
def velocity_dispersion(self, kwargs_lens, kwargs_lens_light, lens_light_model_bool_list=None, aniso_param=1,
                            r_eff=None, R_slit=0.81, dR_slit=0.1, psf_fwhm=0.7, num_evaluate=1000):
        """
        computes the LOS velocity dispersion of the lens within a slit of size R_slit x dR_slit and seeing psf_fwhm.
        The assumptions are a Hernquist light profile and the spherical power-law lens model at the first position.

        Further information can be found in the AnalyticKinematics() class.

        :param kwargs_lens: lens model parameters
        :param kwargs_lens_light: deflector light parameters
        :param aniso_param: scaled r_ani with respect to the half light radius
        :param r_eff: half light radius, if not provided, will be computed from the lens light model
        :param R_slit: width of the slit
        :param dR_slit: length of the slit
        :param psf_fwhm: full width at half maximum of the seeing condition
        :param num_evaluate: number of spectral rendering of the light distribution that end up on the slit
        :return: velocity dispersion in units [km/s]
        """
        gamma = kwargs_lens[0]['gamma']
        if 'center_x' in kwargs_lens_light[0]:
            center_x, center_y = kwargs_lens_light[0]['center_x'], kwargs_lens_light[0]['center_y']
        else:
            center_x, center_y = 0, 0
        if r_eff is None:
            r_eff = self.lens_analysis.half_light_radius_lens(kwargs_lens_light, center_x=center_x, center_y=center_y, model_bool_list=lens_light_model_bool_list)
        theta_E = kwargs_lens[0]['theta_E']
        r_ani = aniso_param * r_eff
        sigma2 = self.analytic_kinematics.vel_disp(gamma, theta_E, r_eff, r_ani, R_slit, dR_slit, FWHM=psf_fwhm, rendering_number=num_evaluate)
        return sigma2


Instruction:
Here you have a function in Python 3, explain what it does
def velocity_dispersion_numerical(self, kwargs_lens, kwargs_lens_light, kwargs_anisotropy, kwargs_aperture, psf_fwhm,
                                      aperture_type, anisotropy_model, r_eff=None, kwargs_numerics={}, MGE_light=False,
                                      MGE_mass=False, lens_model_kinematics_bool=None, light_model_kinematics_bool=None,
                                      Hernquist_approx=False):
        """
        Computes the LOS velocity dispersion of the deflector galaxy with arbitrary combinations of light and mass models.
        For a detailed description, visit the description of the Galkin() class.
        Additionaly to executing the Galkin routine, it has an optional Multi-Gaussian-Expansion decomposition of lens
        and light models that do not have a three-dimensional distribution built in, such as Sersic profiles etc.

        The center of all the lens and lens light models that are part of the kinematic estimate must be centered on the
        same point.

        :param kwargs_lens: lens model parameters
        :param kwargs_lens_light: lens light parameters
        :param kwargs_anisotropy: anisotropy parameters (see Galkin module)
        :param kwargs_aperture: aperture parameters (see Galkin module)
        :param psf_fwhm: full width at half maximum of the seeing (Gaussian form)
        :param aperture_type: type of aperture (see Galkin module
        :param anisotropy_model: stellar anisotropy model (see Galkin module)
        :param r_eff: a rough estimate of the half light radius of the lens light in case of computing the MGE of the
         light profile
        :param kwargs_numerics: keyword arguments that contain numerical options (see Galkin module)
        :param MGE_light: bool, if true performs the MGE for the light distribution
        :param MGE_mass: bool, if true performs the MGE for the mass distribution
        :param lens_model_kinematics_bool: bool list of length of the lens model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore substructure, shear etc that do not describe the
            main deflector potential
        :param light_model_kinematics_bool: bool list of length of the light model. Only takes a subset of all the models
            as part of the kinematics computation (can be used to ignore light components that do not describe the main
            deflector
        :return: LOS velocity dispersion [km/s]
        """

        kwargs_cosmo = {'D_d': self.lensCosmo.D_d, 'D_s': self.lensCosmo.D_s, 'D_ds': self.lensCosmo.D_ds}
        mass_profile_list = []
        kwargs_profile = []
        if lens_model_kinematics_bool is None:
            lens_model_kinematics_bool = [True] * len(kwargs_lens)
        for i, lens_model in enumerate(self.kwargs_options['lens_model_list']):
            if lens_model_kinematics_bool[i] is True:
                mass_profile_list.append(lens_model)
                if lens_model in ['INTERPOL', 'INTERPOL_SCLAED']:
                    center_x, center_y = self._lensModelExt.lens_center(kwargs_lens, k=i)
                    kwargs_lens_i = copy.deepcopy(kwargs_lens[i])
                    kwargs_lens_i['grid_interp_x'] -= center_x
                    kwargs_lens_i['grid_interp_y'] -= center_y
                else:
                    kwargs_lens_i = {k: v for k, v in kwargs_lens[i].items() if not k in ['center_x', 'center_y']}
                kwargs_profile.append(kwargs_lens_i)

        if MGE_mass is True:
            lensModel = LensModel(lens_model_list=mass_profile_list)
            massModel = LensModelExtensions(lensModel)
            theta_E = massModel.effective_einstein_radius(kwargs_profile)
            r_array = np.logspace(-4, 2, 200) * theta_E
            mass_r = lensModel.kappa(r_array, np.zeros_like(r_array), kwargs_profile)
            amps, sigmas, norm = mge.mge_1d(r_array, mass_r, N=20)
            mass_profile_list = ['MULTI_GAUSSIAN_KAPPA']
            kwargs_profile = [{'amp': amps, 'sigma': sigmas}]

        light_profile_list = []
        kwargs_light = []
        if light_model_kinematics_bool is None:
            light_model_kinematics_bool = [True] * len(kwargs_lens_light)
        for i, light_model in enumerate(self.kwargs_options['lens_light_model_list']):
            if light_model_kinematics_bool[i]:
                light_profile_list.append(light_model)
                kwargs_lens_light_i = {k: v for k, v in kwargs_lens_light[i].items() if not k in ['center_x', 'center_y']}
                if 'q' in kwargs_lens_light_i:
                    kwargs_lens_light_i['q'] = 1
                kwargs_light.append(kwargs_lens_light_i)
        if r_eff is None:
            lensAnalysis = LensAnalysis({'lens_light_model_list': light_profile_list})
            r_eff = lensAnalysis.half_light_radius_lens(kwargs_light, model_bool_list=light_model_kinematics_bool)
        if Hernquist_approx is True:
            light_profile_list = ['HERNQUIST']
            kwargs_light = [{'Rs':  r_eff, 'amp': 1.}]
        else:
            if MGE_light is True:
                lightModel = LightModel(light_profile_list)
                r_array = np.logspace(-3, 2, 200) * r_eff * 2
                flux_r = lightModel.surface_brightness(r_array, 0, kwargs_light)
                amps, sigmas, norm = mge.mge_1d(r_array, flux_r, N=20)
                light_profile_list = ['MULTI_GAUSSIAN']
                kwargs_light = [{'amp': amps, 'sigma': sigmas}]

        galkin = Galkin(mass_profile_list, light_profile_list, aperture_type=aperture_type,
                        anisotropy_model=anisotropy_model, fwhm=psf_fwhm, kwargs_cosmo=kwargs_cosmo, **kwargs_numerics)
        sigma2 = galkin.vel_disp(kwargs_profile, kwargs_light, kwargs_anisotropy, kwargs_aperture)
        return sigma2

Response: This method computes the LOS velocity dispersion of the deflector galaxy with arbitrary combinations of lens and light models.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def function(self, x, y, amp, sigma, center_x=0, center_y=0):
        x_ = x - center_x
        y_ = y - center_y
        r = np.sqrt(x_**2 + y_**2)
        sigma_x, sigma_y = sigma, sigma
        c = 1. / (2 * sigma_x * sigma_y)
        num_int = self._num_integral(r, c)
        amp_density = self._amp2d_to_3d(amp, sigma_x, sigma_y)
        amp2d = amp_density / (np.sqrt(np.pi) * np.sqrt(sigma_x * sigma_y * 2))
        amp2d *= 2 * 1. / (2 * c)
        return num_int * amp2d

Response: returns the function of the Gaussian


Instruction:
Make a summary of the following Python 3 code
def _num_integral(self, r, c):
        out = integrate.quad(lambda x: (1-np.exp(-c*x**2))/x, 0, r)
        return out[0]

Response: get the num_integral of the logarithm of the logarithm


Instruction:
How would you code a function in Python 3 to
return df dx dy of the function

Response:
def derivatives(self, x, y, amp, sigma, center_x=0, center_y=0):
        """
        returns df/dx and df/dy of the function
        """
        x_ = x - center_x
        y_ = y - center_y
        R = np.sqrt(x_**2 + y_**2)
        sigma_x, sigma_y = sigma, sigma
        if isinstance(R, int) or isinstance(R, float):
            R = max(R, self.ds)
        else:
            R[R <= self.ds] = self.ds
        alpha = self.alpha_abs(R, amp, sigma)
        return alpha / R * x_, alpha / R * y_


Instruction:
Can you tell what is the following Python 3 function doing
def hessian(self, x, y, amp, sigma, center_x=0, center_y=0):
        x_ = x - center_x
        y_ = y - center_y
        r = np.sqrt(x_**2 + y_**2)
        sigma_x, sigma_y = sigma, sigma
        if isinstance(r, int) or isinstance(r, float):
            r = max(r, self.ds)
        else:
            r[r <= self.ds] = self.ds
        d_alpha_dr = -self.d_alpha_dr(r, amp, sigma_x, sigma_y)
        alpha = self.alpha_abs(r, amp, sigma)

        f_xx = -(d_alpha_dr/r + alpha/r**2) * x_**2/r + alpha/r
        f_yy = -(d_alpha_dr/r + alpha/r**2) * y_**2/r + alpha/r
        f_xy = -(d_alpha_dr/r + alpha/r**2) * x_*y_/r
        return f_xx, f_yy, f_xy

Response: returns Hessian matrix of function d^2f x y and sigma


Instruction:
Given the following Python 3 function, write the documentation
def alpha_abs(self, R, amp, sigma):
        sigma_x, sigma_y = sigma, sigma
        amp_density = self._amp2d_to_3d(amp, sigma_x, sigma_y)
        alpha = self.mass_2d(R, amp_density, sigma) / np.pi / R
        return alpha

Response: Calculates the absolute value of the deflections log - mass


Instruction:
Can you generate the documentation for the following Python 3 function
def _amp3d_to_2d(self, amp, sigma_x, sigma_y):
        return amp * np.sqrt(np.pi) * np.sqrt(sigma_x * sigma_y * 2)

Response: Convert 3d density into 2d density parameter


Instruction:
Can you tell what is the following Python 3 function doing
def _amp2d_to_3d(self, amp, sigma_x, sigma_y):
        return amp / (np.sqrt(np.pi) * np.sqrt(sigma_x * sigma_y * 2))

Response: Convert 2d density into 3d density


Instruction:
Can you generate a brief explanation for the following Python 3 code
def function(self, x, y, amp, alpha, beta, center_x, center_y):
        x_shift = x - center_x
        y_shift = y - center_y
        return amp * (1. + (x_shift**2+y_shift**2)/alpha**2)**(-beta)

Response: Function that computes the Moffat profile.


Instruction:
Here you have a function in Python 3, explain what it does
def _parameter_constraints(self, theta_E, gamma, q, phi_G, s_scale):
        if theta_E < 0:
            theta_E = 0
        if s_scale < 0.00000001:
            s_scale = 0.00000001
        if gamma < 1.2:
            gamma = 1.2
            theta_E = 0
        if gamma > 2.9:
            gamma = 2.9
            theta_E = 0
        if q < 0.01:
            q = 0.01
            theta_E = 0
        if q > 1:
            q = 1.
            theta_E = 0
        return theta_E, gamma, q, phi_G, s_scale

Response: Sets the bounds to parameters due to numerical stability.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def compute_lower_upper_errors(sample, num_sigma=1):
    if num_sigma > 3:
        raise ValueError("Number of sigma-constraints restircted to three. %s not valid" % num_sigma)
    num = len(sample)
    num_threshold1 = int(round((num-1)*0.833))
    num_threshold2 = int(round((num-1)*0.977249868))
    num_threshold3 = int(round((num-1)*0.998650102))

    median = np.median(sample)
    sorted_sample = np.sort(sample)
    if num_sigma > 0:
        upper_sigma1 = sorted_sample[num_threshold1-1]
        lower_sigma1 = sorted_sample[num-num_threshold1-1]
    else:
        return median, [[]]
    if num_sigma > 1:
        upper_sigma2 = sorted_sample[num_threshold2-1]
        lower_sigma2 = sorted_sample[num-num_threshold2-1]
    else:
        return median, [[median-lower_sigma1, upper_sigma1-median]]
    if num_sigma > 2:
        upper_sigma3 = sorted_sample[num_threshold3-1]
        lower_sigma3 = sorted_sample[num-num_threshold3-1]
        return median, [[median-lower_sigma1, upper_sigma1-median], [median-lower_sigma2, upper_sigma2-median],
                      [median-lower_sigma3, upper_sigma3-median]]
    else:
        return median, [[median-lower_sigma1, upper_sigma1-median], [median-lower_sigma2, upper_sigma2-median]]

Response: This function computes the upper and lower sigma from the median value.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def pdf_new(self, x, mu, sigma, skw):
        if skw > 1 or skw < -1:
            print("skewness %s out of range" % skw)
            skw = 1.
        e, w, a = self.map_mu_sigma_skw(mu, sigma, skw)
        pdf = self.pdf(x, e, w, a)
        return pdf

Response: function with different parameterisation


Instruction:
Create a Python 3 function for
calculating the weight of the logarithm of the variance and the delta

Response:
def _w_sigma_delta(self, sigma, delta):
        """
        invert variance
        :param sigma:
        :param delta:
        :return: w parameter
        """
        sigma2=sigma**2
        w2 = sigma2/(1-2*delta**2/np.pi)
        w = np.sqrt(w2)
        return w


Instruction:
Can you generate the documentation for the following Python 3 function
def map_mu_sigma_skw(self, mu, sigma, skw):
        delta = self._delta_skw(skw)
        a = self._alpha_delta(delta)
        w = self._w_sigma_delta(sigma, delta)
        e = self._e_mu_w_delta(mu, w, delta)
        return e, w, a

Response: Map mu sigma skw to e w a


Instruction:
Write a Python 3 script for
returning the lense model of the catalogue basis with particle swarm optimizer.

Response:
def pso(self, n_particles, n_iterations, lower_start=None, upper_start=None, threadCount=1, init_pos=None,
            mpi=False, print_key='PSO'):
        """
        returns the best fit for the lense model on catalogue basis with particle swarm optimizer
        """
        if lower_start is None or upper_start is None:
            lower_start, upper_start = np.array(self.lower_limit), np.array(self.upper_limit)
            print("PSO initialises its particles with default values")
        else:
            lower_start = np.maximum(lower_start, self.lower_limit)
            upper_start = np.minimum(upper_start, self.upper_limit)
        if mpi is True:
            pso = MpiParticleSwarmOptimizer(self.chain, lower_start, upper_start, n_particles, threads=1)
            if pso.isMaster():
                print('MPI option chosen')
        else:
            pso = ParticleSwarmOptimizer(self.chain, lower_start, upper_start, n_particles, threads=threadCount)
        if init_pos is None:
            init_pos = (upper_start - lower_start) / 2 + lower_start
        if not init_pos is None:
            pso.gbest.position = init_pos
            pso.gbest.velocity = [0]*len(init_pos)
            pso.gbest.fitness, _ = self.chain.likelihood(init_pos)
        X2_list = []
        vel_list = []
        pos_list = []
        time_start = time.time()
        if pso.isMaster():
            print('Computing the %s ...' % print_key)
        num_iter = 0
        for swarm in pso.sample(n_iterations):
            X2_list.append(pso.gbest.fitness*2)
            vel_list.append(pso.gbest.velocity)
            pos_list.append(pso.gbest.position)
            num_iter += 1
            if pso.isMaster():
                if num_iter % 10 == 0:
                    print(num_iter)
        if not mpi:
            result = pso.gbest.position
        else:
            result = MpiUtil.mpiBCast(pso.gbest.position)

        #if (pso.isMaster() and mpi is True) or self.chain.sampling_option == 'X2_catalogue':
        if mpi is True and not pso.isMaster():
            pass
        else:
            lens_dict, source_dict, lens_light_dict, ps_dict, kwargs_cosmo = self.chain.param.args2kwargs(result)
            print(pso.gbest.fitness * 2 / (self.chain.effectiv_num_data_points(lens_dict, source_dict, lens_light_dict, ps_dict)), 'reduced X^2 of best position')
            print(pso.gbest.fitness, 'logL')
            print(self.chain.effectiv_num_data_points(lens_dict, source_dict, lens_light_dict, ps_dict), 'effective number of data points')
            print(lens_dict, 'lens result')
            print(source_dict, 'source result')
            print(lens_light_dict, 'lens light result')
            print(ps_dict, 'point source result')
            print(kwargs_cosmo, 'cosmo result')
            time_end = time.time()
            print(time_end - time_start, 'time used for PSO', print_key)
            print('===================')
        return result, [X2_list, pos_list, vel_list, []]


Instruction:
Can you write a function in Python 3 where it
runs mcmc on the parameter space given parameter bounds with CosmoHammerSampler returns the chain

Response:
def mcmc_CH(self, walkerRatio, n_run, n_burn, mean_start, sigma_start, threadCount=1, init_pos=None, mpi=False):
        """
        runs mcmc on the parameter space given parameter bounds with CosmoHammerSampler
        returns the chain
        """
        lowerLimit, upperLimit = self.lower_limit, self.upper_limit

        mean_start = np.maximum(lowerLimit, mean_start)
        mean_start = np.minimum(upperLimit, mean_start)

        low_start = mean_start - sigma_start
        high_start = mean_start + sigma_start
        low_start = np.maximum(lowerLimit, low_start)
        high_start = np.minimum(upperLimit, high_start)
        sigma_start = (high_start - low_start) / 2
        mean_start = (high_start + low_start) / 2
        params = np.array([mean_start, lowerLimit, upperLimit, sigma_start]).T

        chain = LikelihoodComputationChain(
            min=lowerLimit,
            max=upperLimit)

        temp_dir = tempfile.mkdtemp("Hammer")
        file_prefix = os.path.join(temp_dir, "logs")
        #file_prefix = "./lenstronomy_debug"
        # chain.addCoreModule(CambCoreModule())
        chain.addLikelihoodModule(self.chain)
        chain.setup()

        store = InMemoryStorageUtil()
        #store = None
        if mpi is True:
            sampler = MpiCosmoHammerSampler(
            params=params,
            likelihoodComputationChain=chain,
            filePrefix=file_prefix,
            walkersRatio=walkerRatio,
            burninIterations=n_burn,
            sampleIterations=n_run,
            threadCount=1,
            initPositionGenerator=init_pos,
            storageUtil=store)
        else:
            sampler = CosmoHammerSampler(
                params=params,
                likelihoodComputationChain=chain,
                filePrefix=file_prefix,
                walkersRatio=walkerRatio,
                burninIterations=n_burn,
                sampleIterations=n_run,
                threadCount=threadCount,
                initPositionGenerator=init_pos,
                storageUtil=store)
        time_start = time.time()
        if sampler.isMaster():
            print('Computing the MCMC...')
            print('Number of walkers = ', len(mean_start)*walkerRatio)
            print('Burn-in iterations: ', n_burn)
            print('Sampling iterations:', n_run)
        sampler.startSampling()
        if sampler.isMaster():
            time_end = time.time()
            print(time_end - time_start, 'time taken for MCMC sampling')
        # if sampler._sampler.pool is not None:
        #     sampler._sampler.pool.close()
        try:
            shutil.rmtree(temp_dir)
        except Exception as ex:
            print(ex, 'shutil.rmtree did not work')
            pass
        #samples = np.loadtxt(file_prefix+".out")
        #prob = np.loadtxt(file_prefix+"prob.out")
        return store.samples, store.prob


Instruction:
Explain what the following Python 3 code does
def bkg_noise(readout_noise, exposure_time, sky_brightness, pixel_scael, num_exposures=1):
    exposure_time_tot = num_exposures * exposure_time
    readout_noise_tot = num_exposures * readout_noise ** 2
    sky_per_pixel = sky_brightness * pixel_scael ** 2
    sigma_bkg = np.sqrt(readout_noise_tot + exposure_time_tot * sky_per_pixel ** 2) / exposure_time_tot
    return sigma_bkg

Response: Compute the expected background noise of a pixel in units of counts per second per pixel


Instruction:
Given the following Python 3 function, write the documentation
def reset_point_source_cache(self, bool=True):
        if self.PointSource is not None:
            self.PointSource.delete_lens_model_cach()
            self.PointSource.set_save_cache(bool)

Response: Resets all the cache in the point source class and saves it from then on.


Instruction:
Can you tell what is the following Python 3 function doing
def linear_response_matrix(self, kwargs_lens=None, kwargs_source=None, kwargs_lens_light=None, kwargs_ps=None):
        A = self._response_matrix(self.ImageNumerics.ra_grid_ray_shooting, self.ImageNumerics.dec_grid_ray_shooting,
                                      kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, self.ImageNumerics.mask)
        return A

Response: This method computes the linear response matrix for the given set of parameters.