def _subgrid_index(self, idex_mask, subgrid_res, nx, ny): """ :param idex_mask: 1d array of mask of data :param subgrid_res: subgrid resolution :return: 1d array of equivalent mask in subgrid resolution """ idex_sub = np.repeat(idex_mask, subgrid_res, axis=0) idex_sub = util.array2image(idex_sub, nx=nx, ny=ny * subgrid_res) idex_sub = np.repeat(idex_sub, subgrid_res, axis=0) idex_sub = util.image2array(idex_sub) return idex_sub
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 = self.f_xx_interp(y, x) f_yy = self.f_yy_interp(y, x) f_xy = self.f_xy_interp(y, x) return f_xx[0][0], f_yy[0][0], f_xy[0][0] else: if self._grid: x_, y_ = util.get_axes(x, y) f_xx = self.f_xx_interp(y_, x_) f_yy = self.f_yy_interp(y_, x_) f_xy = self.f_xy_interp(y_, x_) f_xx = util.image2array(f_xx) f_yy = util.image2array(f_yy) f_xy = util.image2array(f_xy) else: n = len(x) f_xx, f_yy, f_xy = np.zeros(n), np.zeros(n), np.zeros(n) for i in range(n): f_xx[i] = self.f_xx_interp(y[i], x[i]) f_yy[i] = self.f_yy_interp(y[i], x[i]) f_xy[i] = self.f_xy_interp(y[i], x[i]) return f_xx, f_yy, f_xy
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 :param x: x-coordinate (angular position), float or numpy array :param y: y-coordinate (angular position), float or numpy array :param grid_interp_x: numpy array (ascending) to mark the x-direction of the interpolation grid :param grid_interp_y: numpy array (ascending) to mark the y-direction of the interpolation grid :param f_: 2d numpy array of lensing potential, matching the grids in grid_interp_x and grid_interp_y :param f_x: 2d numpy array of deflection in x-direction, matching the grids in grid_interp_x and grid_interp_y :param f_y: 2d numpy array of deflection in y-direction, matching the grids in grid_interp_x and grid_interp_y :param f_xx: 2d numpy array of df/dxx, matching the grids in grid_interp_x and grid_interp_y :param f_yy: 2d numpy array of df/dyy, matching the grids in grid_interp_x and grid_interp_y :param f_xy: 2d numpy array of df/dxy, matching the grids in grid_interp_x and grid_interp_y :return: f_xx, f_yy, f_xy at interpolated positions (x, y) """ 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
def cutout_psf(self, ra_image, dec_image, x, y, image_list, kernelsize, kernel_init, block_center_neighbour=0): """ :param x_: :param y_: :param image_list: list of images (i.e. data - all models subtracted, except a single point source) :param kernelsize: :return: """ mask = self._image_model_class.ImageNumerics.mask ra_grid, dec_grid = self._image_model_class.Data.coordinates ra_grid = util.image2array(ra_grid) dec_grid = util.image2array(dec_grid) radius = block_center_neighbour kernel_list = [] for l in range(len(x)): mask_point_source = self.mask_point_source(ra_image, dec_image, ra_grid, dec_grid, radius, i=l) mask_i = mask * mask_point_source kernel_deshifted = self.cutout_psf_single(x[l], y[l], image_list[l], mask_i, kernelsize, kernel_init) kernel_list.append(kernel_deshifted) return kernel_list
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
def image2array(self, image): """ returns 1d array of values in image in idex_mask :param image: :param idex_mask: :return: """ idex_mask = self._idex_mask array = util.image2array(image) if self._idex_mask_bool is True: return array[idex_mask == 1] else: return array
def __init__(self, multi_band_list, kwargs_model, model, error_map, cov_param, param, kwargs_params, likelihood_mask_list=None, band_index=0, arrow_size=0.02, cmap_string="gist_heat"): self.bandmodel = SingleBandMultiModel(multi_band_list, kwargs_model, likelihood_mask_list=likelihood_mask_list, band_index=band_index) self._kwargs_special_partial = kwargs_params.get('kwargs_special', None) kwarks_lens_partial, kwargs_source_partial, kwargs_lens_light_partial, kwargs_ps_partial, self._kwargs_extinction_partial = self.bandmodel.select_kwargs(**kwargs_params) self._kwargs_lens_partial, self._kwargs_source_partial, self._kwargs_lens_light_partial, self._kwargs_ps_partial = self.bandmodel.update_linear_kwargs(param, kwarks_lens_partial, kwargs_source_partial, kwargs_lens_light_partial, kwargs_ps_partial) self._norm_residuals = self.bandmodel.reduced_residuals(model, error_map=error_map) self._reduced_x2 = self.bandmodel.reduced_chi2(model, error_map=error_map) print("reduced chi^2 of data ", band_index, "= ", self._reduced_x2) self._model = model self._cov_param = cov_param self._param = param self._lensModel = self.bandmodel.LensModel self._lensModelExt = LensModelExtensions(self._lensModel) log_model = np.log10(model) log_model[np.isnan(log_model)] = -5 self._v_min_default = max(np.min(log_model), -5) self._v_max_default = min(np.max(log_model), 10) self._coords = self.bandmodel.Data self._data = self._coords.data self._deltaPix = self._coords.pixel_width self._frame_size = np.max(self._coords.width) x_grid, y_grid = self._coords.pixel_coordinates self._x_grid = util.image2array(x_grid) self._y_grid = util.image2array(y_grid) if isinstance(cmap_string, str): cmap = plt.get_cmap(cmap_string) else: cmap = cmap_string cmap.set_bad(color='k', alpha=1.) cmap.set_under('k') self._cmap = cmap self._arrow_size = arrow_size
def __init__(self, data_class, psf_class=None, lens_model_class=None, source_model_class=None, lens_light_model_class=None, point_source_class=None, extinction_class=None, kwargs_numerics=None, likelihood_mask=None, psf_error_map_bool_list=None, kwargs_pixelbased=None): """ :param data_class: ImageData() instance :param psf_class: PSF() instance :param lens_model_class: LensModel() instance :param source_model_class: LightModel() instance :param lens_light_model_class: LightModel() instance :param point_source_class: PointSource() instance :param kwargs_numerics: keyword arguments passed to the Numerics module :param likelihood_mask: 2d boolean array of pixels to be counted in the likelihood calculation/linear optimization :param psf_error_map_bool_list: list of boolean of length of point source models. Indicates whether PSF error map is used for the point source model stated as the index. :param kwargs_pixelbased: keyword arguments with various settings related to the pixel-based solver (see SLITronomy documentation) being applied to the point sources. """ if likelihood_mask is None: likelihood_mask = np.ones_like(data_class.data) self.likelihood_mask = np.array(likelihood_mask, dtype=bool) self._mask1d = util.image2array(self.likelihood_mask) super(ImageLinearFit, self).__init__(data_class, psf_class=psf_class, lens_model_class=lens_model_class, source_model_class=source_model_class, lens_light_model_class=lens_light_model_class, point_source_class=point_source_class, extinction_class=extinction_class, kwargs_numerics=kwargs_numerics, kwargs_pixelbased=kwargs_pixelbased) if psf_error_map_bool_list is None: psf_error_map_bool_list = [True] * len( self.PointSource.point_source_type_list) self._psf_error_map_bool_list = psf_error_map_bool_list if self._pixelbased_bool is True: # update the pixel-based solver with the likelihood mask self.PixelSolver.set_likelihood_mask(self.likelihood_mask)
def convergence_plot(ax, pixel_grid, lens_model, kwargs_lens, extent=None, vmin=-1, vmax=1, cmap='Greys', **kwargs): """ plot convergence :param ax: matplotlib axis instance :param pixel_grid: lenstronomy PixelGrid() instance (or class with inheritance of PixelGrid() :param lens_model: LensModel() class instance :param kwargs_lens: lens model keyword argument list :param extent: [[min, max] [min, max]] of frame :param vmin: matplotlib vmin :param vmax: matplotlib vmax :param cmap: matplotlib cmap :param kwargs: keyword arguments for matshow :return: matplotlib axis instance with convergence plot """ x_grid, y_grid = pixel_grid.pixel_coordinates x_grid1d = util.image2array(x_grid) y_grid1d = util.image2array(y_grid) kappa_result = lens_model.kappa(x_grid1d, y_grid1d, kwargs_lens) kappa_result = util.array2image(kappa_result) _ = ax.matshow(np.log10(kappa_result), origin='lower', extent=extent, cmap=cmap, vmin=vmin, vmax=vmax, **kwargs) return ax
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 = self.f_x_interp(y, x) f_y = self.f_y_interp(y, x) return f_x[0][0], f_y[0][0] else: if self._grid: x_, y_ = util.get_axes(x, y) f_x = self.f_x_interp(y_, x_) f_y = self.f_y_interp(y_, x_) f_x = util.image2array(f_x) f_y = util.image2array(f_y) else: n = len(x) f_x, f_y = np.zeros(n), np.zeros(n) for i in range(n): f_x[i] = self.f_x_interp(y[i], x[i]) f_y[i] = self.f_y_interp(y[i], x[i]) return f_x, f_y
def function(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): """ :param x: x-coordinate (angular position), float or numpy array :param y: y-coordinate (angular position), float or numpy array :param grid_interp_x: numpy array (ascending) to mark the x-direction of the interpolation grid :param grid_interp_y: numpy array (ascending) to mark the y-direction of the interpolation grid :param f_: 2d numpy array of lensing potential, matching the grids in grid_interp_x and grid_interp_y :param f_x: 2d numpy array of deflection in x-direction, matching the grids in grid_interp_x and grid_interp_y :param f_y: 2d numpy array of deflection in y-direction, matching the grids in grid_interp_x and grid_interp_y :param f_xx: 2d numpy array of df/dxx, matching the grids in grid_interp_x and grid_interp_y :param f_yy: 2d numpy array of df/dyy, matching the grids in grid_interp_x and grid_interp_y :param f_xy: 2d numpy array of df/dxy, matching the grids in grid_interp_x and grid_interp_y :return: potential at interpolated positions (x, y) """ #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_out = self.f_interp(x, y, grid_interp_x, grid_interp_y, f_) return f_out else: if self._grid and n >= self._min_grid_number: x_axes, y_axes = util.get_axes(x, y) f_out = self.f_interp(x_axes, y_axes, grid_interp_x, grid_interp_y, f_, grid=self._grid) f_out = util.image2array(f_out) else: #n = len(x) f_out = np.zeros(n) for i in range(n): f_out[i] = self.f_interp(x[i], y[i], grid_interp_x, grid_interp_y, f_) return f_out
def make_image_fixed_source(self, param, kwargs_options, kwargs_data, kwargs_lens, kwargs_source, kwargs_psf, kwargs_lens_light, kwargs_else, add_noise=False): """ make an image with fixed source parameters :param kwargs_lens: :param kwargs_source: :param kwargs_psf: :param kwargs_lens_light: :param kwargs_else: :return: """ subgrid_res = kwargs_options['subgrid_res'] num_order = kwargs_options.get('shapelet_order', 0) image = [] residuals = [] for i in range(self.num_bands(kwargs_data)): kwargs_data_i = kwargs_data[i] kwargs_psf_i = kwargs_psf["image" + str(i + 1)] param_i = param[i] deltaPix = kwargs_data_i['deltaPix'] x_grid, y_grid = kwargs_data_i['x_coords'], kwargs_data_i[ 'y_coords'] x_grid_sub, y_grid_sub = util.make_subgrid(x_grid, y_grid, subgrid_res) numPix = len(kwargs_data_i['image_data']) makeImage = ImageModel(kwargs_options, kwargs_data_i) image_i, error_map = makeImage.make_image_with_params( x_grid_sub, y_grid_sub, kwargs_lens, kwargs_source, kwargs_psf_i, kwargs_lens_light, kwargs_else, numPix, deltaPix, subgrid_res, param_i, num_order) residuals_i = util.image2array( makeImage.reduced_residuals(image_i, error_map)) residuals.append(residuals_i) if add_noise: image_i = makeImage.add_noise2image(image_i) image.append(image_i) return image, residuals
def make_image_iteration(self, x_grid, y_grid, kwargs_lens, kwargs_source, kwargs_psf, kwargs_lens_light, kwargs_else, numPix, deltaPix, subgrid_res, inv_bool=False, no_lens=False): map_error = self.kwargs_options.get('error_map', False) num_order = self.kwargs_options.get('shapelet_order', 0) data = self.kwargs_data['image_data'] mask = self.kwargs_options['mask'] num_clumps = self.kwargs_options.get('num_clumps', 0) clump_scale = self.kwargs_options.get('clump_scale', 1) if no_lens is True: x_source, y_source = x_grid, y_grid else: x_source, y_source = self.mapping_IS(x_grid, y_grid, kwargs_else, **kwargs_lens) A, error_map, _ = self.get_response_matrix(x_grid, y_grid, x_source, y_source, kwargs_lens, kwargs_source, kwargs_psf, kwargs_lens_light, kwargs_else, numPix, deltaPix, subgrid_res, num_order, mask, map_error=map_error, shapelets_off=self.kwargs_options.get('shapelets_off', False)) d = util.image2array(data*mask) param, cov_param, wls_model = self.DeLens.get_param_WLS(A.T, 1/(self.C_D+error_map), d, inv_bool=inv_bool) if num_clumps > 0: residuals = (wls_model-d)/np.sqrt(self.C_D+error_map) #ra_pos, dec_pos = self.find_max_residuals(residuals, self.ra_coords, self.dec_coords, num_clumps) #x_pos, y_pos, sigma = self.position_size_estimate(ra_pos, dec_pos, kwargs_lens, kwargs_else, deltaPix, clump_scale) x_pos, y_pos, sigma, ra_pos, dec_pos = self.find_clump_param(residuals, self.ra_coords, self.dec_coords, num_clumps, kwargs_lens, kwargs_else, deltaPix, clump_scale) if self.kwargs_options.get('source_clump_type', 'Gaussian') == 'Gaussian': A_clump = self.clump_response(x_source, y_source, x_pos, y_pos, sigma, deltaPix, numPix, subgrid_res, kwargs_psf, mask=mask) elif self.kwargs_options.get('source_clump_type', 'Gaussian') == 'Shapelets': A_clump = self.shapelet_response(x_source, y_source, x_pos, y_pos, sigma, deltaPix, numPix, subgrid_res, kwargs_psf, mask=mask, num_order=self.kwargs_options.get('num_order_clump', 1)) else: raise ValueError("clump_type %s not valid." %(self.kwargs_options['source_clump_type'])) A = np.append(A, A_clump, axis=0) param, cov_param, wls_model = self.DeLens.get_param_WLS(A.T, 1/(self.C_D+error_map), d, inv_bool=inv_bool) else: x_pos, y_pos, sigma, ra_pos, dec_pos = None, None, None, None, None grid_final = util.array2image(wls_model) if not self.kwargs_options['source_type'] == 'NONE': kwargs_source['I0_sersic'] = param[0] i = 1 else: i = 0 kwargs_lens_light['I0_sersic'] = param[i] if self.kwargs_options['lens_light_type'] == 'TRIPLE_SERSIC': kwargs_lens_light['I0_3'] = param[i+1] kwargs_lens_light['I0_2'] = param[i+2] if map_error is True: error_map = util.array2image(error_map) else: error_map = np.zeros_like(grid_final) return grid_final, error_map, cov_param, param, x_pos, y_pos, sigma, ra_pos, dec_pos
def clump_response(self, x_source, y_source, x_pos, y_pos, sigma, deltaPix, numPix, subgrid_res, kwargs_psf, mask=1): """ response matrix of gaussian clumps :param x_source: :param y_source: :param x_pos: :param y_pos: :param sigma: :return: """ num_param = len(sigma) A = np.zeros((num_param, numPix**2)) for i in range(num_param): image = self.gaussian.function(x_source, y_source, amp=1, sigma_x=sigma[i], sigma_y=sigma[i], center_x=x_pos[i], center_y=y_pos[i]) image = util.array2image(image) image = self.re_size_convolve(image, subgrid_res, kwargs_psf) response = util.image2array(image*mask) A[i, :] = response return A
def __init__(self, data_class, psf_class=None, lens_model_class=None, source_model_class=None, lens_light_model_class=None, point_source_class=None, extinction_class=None, kwargs_numerics={}, likelihood_mask=None, psf_error_map_bool_list=None): """ :param data_class: ImageData() instance :param psf_class: PSF() instance :param lens_model_class: LensModel() instance :param source_model_class: LightModel() instance :param lens_light_model_class: LightModel() instance :param point_source_class: PointSource() instance :param kwargs_numerics: keyword arguments passed to the Numerics module :param likelihood_mask: 2d boolean array of pixels to be counted in the likelihood calculation/linear optimization :param psf_error_map_bool_list: list of boolean of length of point source models. Indicates whether PSF error map being applied to the point sources. """ if likelihood_mask is None: likelihood_mask = np.ones_like(data_class.data) self.likelihood_mask = np.array(likelihood_mask, dtype=bool) self._mask1d = util.image2array(self.likelihood_mask) #kwargs_numerics['compute_indexes'] = self.likelihood_mask # here we overwrite the indexes to be computed with the likelihood mask super(ImageLinearFit, self).__init__(data_class, psf_class=psf_class, lens_model_class=lens_model_class, source_model_class=source_model_class, lens_light_model_class=lens_light_model_class, point_source_class=point_source_class, extinction_class=extinction_class, kwargs_numerics=kwargs_numerics) if psf_error_map_bool_list is None: psf_error_map_bool_list = [True] * len( self.PointSource.point_source_type_list) self._psf_error_map_bool_list = psf_error_map_bool_list
def __init__(self, data_class, psf_class=None, lens_model_class=None, source_model_class=None, lens_light_model_class=None, point_source_class=None, kwargs_numerics={}, likelihood_mask=None): """ :param data_class: :param psf_class: :param lens_model_class: :param source_model_class: :param lens_light_model_class: :param point_source_class: :param kwargs_numerics: :param likelihood_mask: 2d boolean array of pixels to be counted in the likelihood calculation/linear optimization """ super(ImageLinearFit, self).__init__(data_class, psf_class=psf_class, lens_model_class=lens_model_class, source_model_class=source_model_class, lens_light_model_class=lens_light_model_class, point_source_class=point_source_class, kwargs_numerics=kwargs_numerics) if likelihood_mask is None: likelihood_mask = np.ones_like(self.Data.data) self.likelihood_mask = np.array(likelihood_mask, dtype=bool) self._mask1d = util.image2array(self.likelihood_mask)
def shapelet_response(self, x_source, y_source, x_pos, y_pos, sigma, deltaPix, numPix, subgrid_res, kwargs_psf, num_order=1, mask=1): """ returns response matrix for general inputs :param x_grid: :param y_grid: :param kwargs_lens: :param kwargs_source: :param kwargs_psf: :param kwargs_lens_light: :param kwargs_else: :param numPix: :param deltaPix: :param subgrid_res: :return: """ num_clump = len(x_pos) numShapelets = (num_order+2)*(num_order+1)/2 num_param = numShapelets*num_clump A = np.zeros((num_param, numPix**2)) k = 0 for j in range(0, num_clump): H_x, H_y = self.shapelets.pre_calc(x_source, y_source, sigma[j], num_order, x_pos[j], y_pos[j]) n1 = 0 n2 = 0 for i in range(0, numShapelets): kwargs_source_shapelet = {'center_x': x_pos[j], 'center_y': y_pos[j], 'n1': n1, 'n2': n2, 'beta': sigma[j], 'amp': 1} image = self.shapelets.function(H_x, H_y, **kwargs_source_shapelet) image = util.array2image(image) image = self.re_size_convolve(image, numPix, deltaPix, subgrid_res, kwargs_psf) response = util.image2array(image*mask) A[k, :] = response if n1 == 0: n1 = n2 + 1 n2 = 0 else: n1 -= 1 n2 += 1 k += 1 return A
def __init__(self, nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampling_indexes, supersampling_factor, flux_evaluate_indexes=None): """ :param nx: number of pixels in x-axis :param ny: number of pixels in y-axis :param transform_pix2angle: 2x2 matrix, mapping of pixel to coordinate :param ra_at_xy_0: ra coordinate at pixel (0,0) :param dec_at_xy_0: dec coordinate at pixel (0,0) :param supersampling_indexes: bool array of shape nx x ny, corresponding to pixels being super_sampled :param supersampling_factor: int, factor (per axis) of super-sampling :param flux_evaluate_indexes: bool array of shape nx x ny, corresponding to pixels being evaluated (for both low and high res). Default is None, replaced by setting all pixels to being evaluated. """ super(AdaptiveGrid, self).__init__(transform_pix2angle, ra_at_xy_0, dec_at_xy_0) self._nx = nx self._ny = ny self._x_grid, self._y_grid = self.coordinate_grid(nx, ny) if flux_evaluate_indexes is None: flux_evaluate_indexes = np.ones_like(self._x_grid, dtype=bool) supersampled_indexes1d = util.image2array(supersampling_indexes) self._high_res_indexes1d = (supersampled_indexes1d) & ( flux_evaluate_indexes) self._low_res_indexes1d = (np.invert(supersampled_indexes1d)) & ( flux_evaluate_indexes) self._supersampling_factor = supersampling_factor self._num_sub = supersampling_factor * supersampling_factor self._x_low_res = self._x_grid[self._low_res_indexes1d] self._y_low_res = self._y_grid[self._low_res_indexes1d] self._num_low_res = len(self._x_low_res)
def __init__(self, nx, ny, transform_pix2angle, ra_at_xy_0, dec_at_xy_0, supersampling_factor=1, flux_evaluate_indexes=None): """ :param nx: number of pixels in x-axis :param ny: number of pixels in y-axis :param transform_pix2angle: 2x2 matrix, mapping of pixel to coordinate :param ra_at_xy_0: ra coordinate at pixel (0,0) :param dec_at_xy_0: dec coordinate at pixel (0,0) :param supersampling_indexes: bool array of shape nx x ny, corresponding to pixels being super_sampled :param supersampling_factor: int, factor (per axis) of super-sampling :param flux_evaluate_indexes: bool array of shape nx x ny, corresponding to pixels being evaluated (for both low and high res). Default is None, replaced by setting all pixels to being evaluated. """ super(RegularGrid, self).__init__(transform_pix2angle, ra_at_xy_0, dec_at_xy_0) self._supersampling_factor = supersampling_factor self._nx = nx self._ny = ny self._x_grid, self._y_grid = self.coordinate_grid(nx, ny) if flux_evaluate_indexes is None: flux_evaluate_indexes = np.ones_like(self._x_grid, dtype=bool) else: flux_evaluate_indexes = util.image2array(flux_evaluate_indexes) self._compute_indexes = self._subgrid_index(flux_evaluate_indexes, self._supersampling_factor, self._nx, self._ny) x_grid_sub, y_grid_sub = util.make_subgrid(self._x_grid, self._y_grid, self._supersampling_factor) self._ra_subgrid = x_grid_sub[self._compute_indexes] self._dec_subgrid = y_grid_sub[self._compute_indexes]
def error_map_estimate(self, kernel, star_cutout_list, amp, x_pos, y_pos, error_map_radius=None, block_center_neighbour=0): """ provides a psf_error_map based on the goodness of fit of the given PSF kernel on the point source cutouts, their estimated amplitudes and positions :param kernel: PSF kernel :param star_cutout_list: list of 2d arrays of cutouts of the point sources with all other model components subtracted :param amp: list of amplitudes of the estimated PSF kernel :param x_pos: pixel position (in original data unit, not in cutout) of the point sources (same order as amp and star cutouts) :param y_pos: pixel position (in original data unit, not in cutout) of the point sources (same order as amp and star cutouts) :param error_map_radius: float, radius (in arc seconds) of the outermost error in the PSF estimate (e.g. to avoid double counting of overlapping PSF erros) :param block_center_neighbour: angle, radius of neighbouring point sources around their centers the estimates is ignored. Default is zero, meaning a not optimal subtraction of the neighbouring point sources might contaminate the estimate. :return: relative uncertainty in the psf model (in quadrature) per pixel based on residuals achieved in the image """ error_map_list = np.zeros( (len(star_cutout_list), len(kernel), len(kernel))) mask_list = np.zeros((len(star_cutout_list), len(kernel), len(kernel))) ra_grid, dec_grid = self._image_model_class.Data.pixel_coordinates ra_grid = util.image2array(ra_grid) dec_grid = util.image2array(dec_grid) mask = self._image_model_class.likelihood_mask for i, star in enumerate(star_cutout_list): x, y, amp_i = x_pos[i], y_pos[i], amp[i] # shift kernel x_int = int(round(x)) y_int = int(round(y)) shift_x = x_int - x shift_y = y_int - y kernel_shifted = interp.shift(kernel, [-shift_y, -shift_x], order=1) # multiply kernel with amplitude model = kernel_shifted * amp_i # compute residuals residual = np.abs(star - model) # subtract background and Poisson noise residuals C_D_cutout = kernel_util.cutout_source( x_int, y_int, self._image_model_class.Data.C_D, len(star), shift=False) # block neighbor points in error estimate mask_point_source = self.mask_point_source( x_pos, y_pos, ra_grid, dec_grid, radius=block_center_neighbour, i=i) mask_i = mask * mask_point_source mask_i = kernel_util.cutout_source(x_int, y_int, mask_i, len(star), shift=False) residual -= np.sqrt(C_D_cutout) residual[residual < 0] = 0 # estimate relative error per star residual /= amp_i error_map_list[i, :, :] = residual**2 * mask_i mask_list[i, :, :] = mask_i # take median absolute error for each pixel # TODO: only for pixels that are not masked error_map = np.median(error_map_list, axis=0) error_map[kernel > 0] /= kernel[kernel > 0]**2 error_map = np.nan_to_num(error_map) error_map[error_map > 1] = 1 # cap on error to be the same # mask the error map outside a certain radius (can avoid double counting of errors when map is overlapping if error_map_radius is not None: pixel_scale = self._image_model_class.Data.pixel_width x_grid, y_grid = util.make_grid(numPix=len(error_map), deltapix=pixel_scale) mask = mask_util.mask_azimuthal(x_grid, y_grid, center_x=0, center_y=0, r=error_map_radius) error_map *= util.array2image(mask) return error_map
def test_symmetry(): array = np.linspace(0, 10, 100) image = util.array2image(array) array_new = util.image2array(image) assert array_new[42] == array[42]
def test_image2array(): image = np.zeros((10, 10)) image[1, 2] = 1 array = util.image2array(image) assert array[12] == 1
def ext_shear_direction(data_class, lens_model_class, kwargs_lens, strength_multiply=10): """ :param kwargs_data: :param kwargs_psf: :param kwargs_options: :param lens_result: :param source_result: :param lens_light_result: :param else_result: :return: """ x_grid, y_grid = data_class.pixel_coordinates x_grid = util.image2array(x_grid) y_grid = util.image2array(y_grid) shear = Shear() f_x_shear, f_y_shear = 0, 0 for i, lens_model in enumerate(lens_model_class.lens_model_list): if lens_model == 'SHEAR': kwargs = kwargs_lens[i] f_x_shear, f_y_shear = shear.derivatives( x_grid, y_grid, e1=kwargs['e1'] * strength_multiply, e2=kwargs['e2'] * strength_multiply) x_shear = x_grid - f_x_shear y_shear = y_grid - f_y_shear f_x_foreground, f_y_foreground = 0, 0 for i, lens_model in enumerate(lens_model_class.lens_model_list): if lens_model == 'FOREGROUND_SHEAR': kwargs = kwargs_lens[i] f_x_foreground, f_y_foreground = shear.derivatives( x_grid, y_grid, e1=kwargs['e1'] * strength_multiply, e2=kwargs['e2'] * strength_multiply) x_foreground = x_grid - f_x_foreground y_foreground = y_grid - f_y_foreground center_x = np.mean(x_grid) center_y = np.mean(y_grid) radius = (np.max(x_grid) - np.min(x_grid)) / 4 circle_shear = util_mask.mask_sphere(x_shear, y_shear, center_x, center_y, radius) circle_foreground = util_mask.mask_sphere(x_foreground, y_foreground, center_x, center_y, radius) f, ax = plt.subplots(1, 1, figsize=(16, 8)) im = ax.matshow(np.log10(data_class.data), origin='lower', alpha=0.5) im = ax.matshow(util.array2image(circle_shear), origin='lower', alpha=0.5, cmap="jet") im = ax.matshow(util.array2image(circle_foreground), origin='lower', alpha=0.5) #f.show() return f, ax
def psf_estimate_individual(self, ra_image, dec_image, point_amp, residuals, cutout_size, kernel_guess, supersampling_factor, block_center_neighbour): """ :param ra_image: list; position in angular units of the image :param dec_image: list; position in angular units of the image :param point_amp: list of model amplitudes of point sources :param residuals: data - model :param cutout_size: pixel size of cutout around single star/quasar to be considered for the psf reconstruction :param kernel_guess: initial guess of super-sampled PSF :param supersampling_factor: int, super-sampling factor :param block_center_neighbour: :return: list of best-guess PSF's for each star based on the residual patterns """ mask = self._image_model_class.likelihood_mask ra_grid, dec_grid = self._image_model_class.Data.pixel_coordinates ra_grid = util.image2array(ra_grid) dec_grid = util.image2array(dec_grid) radius = block_center_neighbour x_, y_ = self._image_model_class.Data.map_coord2pix( ra_image, dec_image) kernel_list = [] for l in range(len(ra_image)): mask_point_source = self.mask_point_source(ra_image, dec_image, ra_grid, dec_grid, radius, i=l) mask_i = mask * mask_point_source # cutout residuals x_int = int(round(x_[l])) y_int = int(round(y_[l])) residual_cutout = kernel_util.cutout_source(x_int, y_int, residuals, cutout_size + 2, shift=False) # cutout the mask mask_cutout = kernel_util.cutout_source(x_int, y_int, mask_i, cutout_size + 2, shift=False) # apply mask residual_cutout_mask = residual_cutout * mask_cutout # re-scale residuals with point source brightness residual_cutout_mask /= point_amp[l] # enlarge residuals by super-sampling factor residual_cutout_mask = residual_cutout_mask.repeat( supersampling_factor, axis=0).repeat(supersampling_factor, axis=1) # inverse shift residuals shift_x = (x_int - x_[l]) * supersampling_factor shift_y = (y_int - y_[l]) * supersampling_factor # for odd number super-sampling if supersampling_factor % 2 == 1: residuals_shifted = ndimage.shift(residual_cutout_mask, shift=[shift_y, shift_x], order=1) else: # for even number super-sampling half a super-sampled pixel offset needs to be performed residuals_shifted = ndimage.shift( residual_cutout_mask, shift=[shift_y - 0.5, shift_x - 0.5], order=1) # and the last column and row need to be removed residuals_shifted = residuals_shifted[:-1, :-1] # re-size shift residuals psf_size = len(kernel_guess) residuals_shifted = image_util.cut_edges(residuals_shifted, psf_size) # normalize residuals correction = residuals_shifted - np.mean(residuals_shifted) # correct old PSF with inverse shifted residuals kernel_new = kernel_guess + correction kernel_list.append(kernel_new) return kernel_list
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, with_convergence=True, coord_center_ra=0, coord_center_dec=0, coord_inverse=False, fast_caustic=False): """ plots a lens model (convergence) and the critical curves and caustics :param ax: :param kwargs_lens: :param numPix: :param deltaPix: :param fast_caustic: boolean, if True, uses faster but less precise caustic calculation (might have troubles for the outer caustic (inner critical curve) :param with_convergence: boolean, if True, plots the convergence of the deflector :return: """ kwargs_data = sim_util.data_configure_simple(numPix, deltaPix, center_ra=coord_center_ra, center_dec=coord_center_dec, inverse=coord_inverse) data = ImageData(**kwargs_data) _coords = data _frame_size = numPix * deltaPix x_grid, y_grid = data.pixel_coordinates lensModelExt = LensModelExtensions(lensModel) x_grid1d = util.image2array(x_grid) y_grid1d = util.image2array(y_grid) if with_convergence: 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: if fast_caustic: 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) plot_util.plot_line_set_list(ax, _coords, ra_caustic_list, dec_caustic_list, color='g') plot_util.plot_line_set_list(ax, _coords, ra_crit_list, dec_crit_list, color='r') else: 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_util.plot_line_set(ax, _coords, ra_caustic_list, dec_caustic_list, color='g') plot_util.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.set_xlim([0, _frame_size]) ax.set_ylim([0, _frame_size]) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) ax.autoscale(False) return ax
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^2/dxdy, d^2/dydx, d^f/dy^2 :param x: x-coordinate (angular position), float or numpy array :param y: y-coordinate (angular position), float or numpy array :param grid_interp_x: numpy array (ascending) to mark the x-direction of the interpolation grid :param grid_interp_y: numpy array (ascending) to mark the y-direction of the interpolation grid :param f_: 2d numpy array of lensing potential, matching the grids in grid_interp_x and grid_interp_y :param f_x: 2d numpy array of deflection in x-direction, matching the grids in grid_interp_x and grid_interp_y :param f_y: 2d numpy array of deflection in y-direction, matching the grids in grid_interp_x and grid_interp_y :param f_xx: 2d numpy array of df/dxx, matching the grids in grid_interp_x and grid_interp_y :param f_yy: 2d numpy array of df/dyy, matching the grids in grid_interp_x and grid_interp_y :param f_xy: 2d numpy array of df/dxy, matching the grids in grid_interp_x and grid_interp_y :return: f_xx, f_xy, f_yx, f_yy at interpolated positions (x, y) """ if not (hasattr(self, '_f_xx_interp')) and (f_xx is None or f_yy is None or f_xy is None): diff = 0.000001 alpha_ra_pp, alpha_dec_pp = self.derivatives( x + diff / 2, y + diff / 2, grid_interp_x=grid_interp_x, grid_interp_y=grid_interp_y, f_=f_, f_x=f_x, f_y=f_y) alpha_ra_pn, alpha_dec_pn = self.derivatives( x + diff / 2, y - diff / 2, grid_interp_x=grid_interp_x, grid_interp_y=grid_interp_y, f_=f_, f_x=f_x, f_y=f_y) alpha_ra_np, alpha_dec_np = self.derivatives( x - diff / 2, y + diff / 2, grid_interp_x=grid_interp_x, grid_interp_y=grid_interp_y, f_=f_, f_x=f_x, f_y=f_y) alpha_ra_nn, alpha_dec_nn = self.derivatives( x - diff / 2, y - diff / 2, grid_interp_x=grid_interp_x, grid_interp_y=grid_interp_y, f_=f_, f_x=f_x, f_y=f_y) f_xx_out = (alpha_ra_pp - alpha_ra_np + alpha_ra_pn - alpha_ra_nn) / diff / 2 f_xy_out = (alpha_ra_pp - alpha_ra_pn + alpha_ra_np - alpha_ra_nn) / diff / 2 f_yx_out = (alpha_dec_pp - alpha_dec_np + alpha_dec_pn - alpha_dec_nn) / diff / 2 f_yy_out = (alpha_dec_pp - alpha_dec_pn + alpha_dec_np - alpha_dec_nn) / diff / 2 return f_xx_out, f_xy_out, f_yx_out, f_yy_out 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, f_xy_out, f_xy_out, f_yy_out 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, grid=self._grid) f_yy_out = self.f_yy_interp(x_, y_, grid_interp_x, grid_interp_y, f_yy, grid=self._grid) f_xy_out = self.f_xy_interp(x_, y_, grid_interp_x, grid_interp_y, f_xy, grid=self._grid) 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_xy_out, f_xy_out, f_yy_out
def distortions(lensModel, kwargs_lens, num_pix=100, delta_pix=0.05, center_ra=0, center_dec=0, differential_scale=0.0001, smoothing_scale=None, **kwargs): """ :param lensModel: LensModel instance :param kwargs_lens: lens model keyword argument list :param num_pix: number of pixels per axis :param delta_pix: pixel scale per axis :param center_ra: center of the grid :param center_dec: center of the grid :param differential_scale: scale of the finite derivative length in units of angles :param smoothing_scale: float or None, Gaussian FWHM of a smoothing kernel applied before plotting :return: matplotlib instance with different panels """ kwargs_grid = sim_util.data_configure_simple(num_pix, delta_pix, center_ra=center_ra, center_dec=center_dec) _coords = ImageData(**kwargs_grid) _frame_size = num_pix * delta_pix ra_grid, dec_grid = _coords.pixel_coordinates extensions = LensModelExtensions(lensModel=lensModel) ra_grid1d = util.image2array(ra_grid) dec_grid1d = util.image2array(dec_grid) lambda_rad, lambda_tan, orientation_angle, dlambda_tan_dtan, dlambda_tan_drad, dlambda_rad_drad, dlambda_rad_dtan, dphi_tan_dtan, dphi_tan_drad, dphi_rad_drad, dphi_rad_dtan = extensions.radial_tangential_differentials( ra_grid1d, dec_grid1d, kwargs_lens=kwargs_lens, center_x=center_ra, center_y=center_dec, smoothing_3rd=differential_scale, smoothing_2nd=None) lambda_rad2d, lambda_tan2d, orientation_angle2d, dlambda_tan_dtan2d, dlambda_tan_drad2d, dlambda_rad_drad2d, dlambda_rad_dtan2d, dphi_tan_dtan2d, dphi_tan_drad2d, dphi_rad_drad2d, dphi_rad_dtan2d = util.array2image(lambda_rad), \ util.array2image(lambda_tan), util.array2image(orientation_angle), util.array2image(dlambda_tan_dtan), util.array2image(dlambda_tan_drad), util.array2image(dlambda_rad_drad), util.array2image(dlambda_rad_dtan), \ util.array2image(dphi_tan_dtan), util.array2image(dphi_tan_drad), util.array2image(dphi_rad_drad), util.array2image(dphi_rad_dtan) if smoothing_scale is not None: lambda_rad2d = ndimage.gaussian_filter(lambda_rad2d, sigma=smoothing_scale / delta_pix) dlambda_rad_drad2d = ndimage.gaussian_filter(dlambda_rad_drad2d, sigma=smoothing_scale / delta_pix) lambda_tan2d = np.abs(lambda_tan2d) # the magnification cut is made to make a stable integral/convolution lambda_tan2d[lambda_tan2d > 100] = 100 lambda_tan2d = ndimage.gaussian_filter(lambda_tan2d, sigma=smoothing_scale / delta_pix) # the magnification cut is made to make a stable integral/convolution dlambda_tan_dtan2d[dlambda_tan_dtan2d > 100] = 100 dlambda_tan_dtan2d[dlambda_tan_dtan2d < -100] = -100 dlambda_tan_dtan2d = ndimage.gaussian_filter(dlambda_tan_dtan2d, sigma=smoothing_scale / delta_pix) orientation_angle2d = ndimage.gaussian_filter(orientation_angle2d, sigma=smoothing_scale / delta_pix) dphi_tan_dtan2d = ndimage.gaussian_filter(dphi_tan_dtan2d, sigma=smoothing_scale / delta_pix) def _plot_frame(ax, map, vmin, vmax, text_string): """ :param ax: matplotlib.axis instance :param map: 2d array :param vmin: minimum plotting scale :param vmax: maximum plotting scale :param text_string: string to describe the label :return: """ font_size = 10 _arrow_size = 0.02 im = ax.matshow(map, extent=[0, _frame_size, 0, _frame_size], vmin=vmin, vmax=vmax) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) ax.autoscale(False) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) cb = plt.colorbar(im, cax=cax, orientation='vertical') #cb.set_label(text_string, fontsize=10) #plot_util.scale_bar(ax, _frame_size, dist=1, text='1"', font_size=font_size) plot_util.text_description(ax, _frame_size, text=text_string, color="k", backgroundcolor='w', font_size=font_size) #if 'no_arrow' not in kwargs or not kwargs['no_arrow']: # plot_util.coordinate_arrows(ax, _frame_size, _coords, # color='w', arrow_size=_arrow_size, # font_size=font_size) f, axes = plt.subplots(3, 4, figsize=(12, 8)) _plot_frame(axes[0, 0], lambda_rad2d, vmin=0.6, vmax=1.4, text_string=r"$\lambda_{rad}$") _plot_frame(axes[0, 1], lambda_tan2d, vmin=-20, vmax=20, text_string=r"$\lambda_{tan}$") _plot_frame(axes[0, 2], orientation_angle2d, vmin=-np.pi / 10, vmax=np.pi / 10, text_string=r"$\phi$") _plot_frame(axes[0, 3], util.array2image(lambda_tan * lambda_rad), vmin=-20, vmax=20, text_string='magnification') _plot_frame(axes[1, 0], dlambda_rad_drad2d / lambda_rad2d, vmin=-.1, vmax=.1, text_string='dlambda_rad_drad') _plot_frame(axes[1, 1], dlambda_tan_dtan2d / lambda_tan2d, vmin=-20, vmax=20, text_string='dlambda_tan_dtan') _plot_frame(axes[1, 2], dlambda_tan_drad2d / lambda_tan2d, vmin=-20, vmax=20, text_string='dlambda_tan_drad') _plot_frame(axes[1, 3], dlambda_rad_dtan2d / lambda_rad2d, vmin=-.1, vmax=.1, text_string='dlambda_rad_dtan') _plot_frame(axes[2, 0], dphi_rad_drad2d, vmin=-.1, vmax=.1, text_string='dphi_rad_drad') _plot_frame(axes[2, 1], dphi_tan_dtan2d, vmin=0, vmax=20, text_string='dphi_tan_dtan: curvature radius') _plot_frame(axes[2, 2], dphi_tan_drad2d, vmin=-.1, vmax=.1, text_string='dphi_tan_drad') _plot_frame(axes[2, 3], dphi_rad_dtan2d, vmin=0, vmax=20, text_string='dphi_rad_dtan') return f, axes
def __init__(self, kwargs_data, kwargs_psf, kwargs_numerics, kwargs_model, kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, arrow_size=0.02, cmap_string="gist_heat"): """ :param kwargs_options: :param kwargs_data: :param arrow_size: :param cmap_string: """ self._kwargs_data = kwargs_data if isinstance(cmap_string, str): cmap = plt.get_cmap(cmap_string) else: cmap = cmap_string cmap.set_bad(color='k', alpha=1.) cmap.set_under('k') self._cmap = cmap self._arrow_size = arrow_size data = ImageData(**kwargs_data) self._coords = data nx, ny = np.shape(kwargs_data['image_data']) Mpix2coord = kwargs_data['transform_pix2angle'] self._Mpix2coord = Mpix2coord self._deltaPix = self._coords.pixel_width self._frame_size = self._deltaPix * nx x_grid, y_grid = data.pixel_coordinates self._x_grid = util.image2array(x_grid) self._y_grid = util.image2array(y_grid) self._imageModel = class_creator.create_image_model( kwargs_data, kwargs_psf, kwargs_numerics, kwargs_model) self._analysis = LensAnalysis(kwargs_model) self._lensModel = LensModel( lens_model_list=kwargs_model.get('lens_model_list', []), z_source=kwargs_model.get('z_source', None), lens_redshift_list=kwargs_model.get('lens_redshift_list', None), multi_plane=kwargs_model.get('multi_plane', False)) self._lensModelExt = LensModelExtensions(self._lensModel) model, error_map, cov_param, param = self._imageModel.image_linear_solve( kwargs_lens, kwargs_source, kwargs_lens_light, kwargs_ps, inv_bool=True) self._kwargs_lens = kwargs_lens self._kwargs_source = kwargs_source self._kwargs_lens_light = kwargs_lens_light self._kwargs_else = kwargs_ps self._model = model self._data = kwargs_data['image_data'] self._cov_param = cov_param self._norm_residuals = self._imageModel.reduced_residuals( model, error_map=error_map) self._reduced_x2 = self._imageModel.reduced_chi2(model, error_map=error_map) log_model = np.log10(model) log_model[np.isnan(log_model)] = -5 self._v_min_default = max(np.min(log_model), -5) self._v_max_default = min(np.max(log_model), 10) print("reduced chi^2 = ", self._reduced_x2)
def arrival_time_surface(ax, lensModel, kwargs_lens, numPix=500, deltaPix=0.01, sourcePos_x=0, sourcePos_y=0, with_caustics=False, point_source=False, n_levels=10, kwargs_contours={}, image_color_list=None, letter_font_size=20): """ :param ax: :param lensModel: :param kwargs_lens: :param numPix: :param deltaPix: :param sourcePos_x: :param sourcePos_y: :param with_caustics: :return: """ kwargs_data = sim_util.data_configure_simple(numPix, deltaPix) data = ImageData(**kwargs_data) _frame_size = numPix * deltaPix _coords = data x_grid, y_grid = data.pixel_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) fermat_surface = lensModel.fermat_potential(x_grid1d, y_grid1d, kwargs_lens, sourcePos_x, sourcePos_y) fermat_surface = util.array2image(fermat_surface) #, 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 / 5, max_order=10) ra_caustic_list, dec_caustic_list = lensModel.ray_shooting( ra_crit_list, dec_crit_list, kwargs_lens) plot_util.plot_line_set(ax, _coords, ra_caustic_list, dec_caustic_list, shift=_frame_size / 2., color='g') plot_util.plot_line_set(ax, _coords, ra_crit_list, dec_crit_list, shift=_frame_size / 2., color='r') if point_source is True: 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) fermat_pot_images = lensModel.fermat_potential(theta_x, theta_y, kwargs_lens) im = ax.contour( x_grid, y_grid, fermat_surface, origin='lower', # extent=[0, _frame_size, 0, _frame_size], levels=np.sort(fermat_pot_images), **kwargs_contours) 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 - _frame_size / 2 y_ = (y_image[i] + 0.5) * deltaPix - _frame_size / 2 if image_color_list is None: color = 'k' else: color = image_color_list[i] ax.plot(x_, y_, 'x', markersize=10, alpha=1, color=color ) # markersize=8*(1 + np.log(np.abs(mag_images[i]))) ax.text(x_ + deltaPix, y_ + deltaPix, abc_list[i], fontsize=letter_font_size, color='k') x_source, y_source = _coords.map_coord2pix(sourcePos_x, sourcePos_y) ax.plot((x_source + 0.5) * deltaPix - _frame_size / 2, (y_source + 0.5) * deltaPix - _frame_size / 2, '*k', markersize=20) else: vmin = np.min(fermat_surface) vmax = np.max(fermat_surface) levels = np.linspace(start=vmin, stop=vmax, num=n_levels) im = ax.contour( x_grid, y_grid, fermat_surface, origin='lower', # extent=[0, _frame_size, 0, _frame_size], levels=levels, **kwargs_contours) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) ax.autoscale(False) return ax
truncate=6) # we now degrate the pixel resoluton by a factor. # This reduces the data volume and increases the spead of the Shapelet decomposition factor = 1 # lower resolution of image with a given factor numPix_large = int(len(ngc_conv) / factor) n_new = int((numPix_large - 1) * factor) ngc_cut = ngc_conv[0:n_new, 0:n_new] x, y = util.make_grid(numPix=numPix_large - 1, deltapix=1) # make a coordinate grid ngc_data_resized = image_util.re_size( ngc_cut, factor) # re-size image to lower resolution # now we come to the Shapelet decomposition # we turn the image in a single 1d array image_1d = util.image2array(ngc_data_resized) # map 2d image in 1d data array # we define the shapelet basis set we want the image to decompose in n_max = 150 # choice of number of shapelet basis functions, 150 is a high resolution number, but takes long beta = 10 # shapelet scale parameter (in units of resized pixels) # import the ShapeletSet class from lenstronomy.LightModel.Profiles.shapelets import ShapeletSet shapeletSet = ShapeletSet() # decompose image and return the shapelet coefficients coeff_ngc = shapeletSet.decomposition(image_1d, x, y, n_max, beta,