def offset_astrometry(hdu: fits.hdu, offset_ra: float, offset_dec: float, output: str): """ Offsets the astrometric solution of a fits HDU by the specified amounts. :param hdu: Astropy HDU object to be offset. :param offset_ra: Amount to offset Right Ascension by, in degrees. :param offset_dec: Amount to offset Declination by, in degrees. :param output: String specifying the output directory. :return: """ hdu, path = ff.path_or_hdu(hdu) print(offset_ra, offset_dec) print('Writing tweaked file to:') print('\t', output) print(hdu[0].header['CRVAL1'], hdu[0].header['CRVAL2']) hdu[0].header['CRVAL1'] = hdu[0].header['CRVAL1'] - offset_ra hdu[0].header['CRVAL2'] = hdu[0].header['CRVAL2'] - offset_dec print(hdu[0].header['CRVAL1'], hdu[0].header['CRVAL2']) hdu.writeto(output, overwrite=True) if path: hdu.close() return hdu
def load_psfex_oversampled(model: Union[str, 'astropy.io.fits.HDUList'], x: float, y: float): """ Since PSFEx generates a model using basis vectors, with the linear combination dependent on image position, this is used to collapse that into a useable kernel for convolution and insertion purposes. See https://psfex.readthedocs.io/en/latest/Appendices.html This function will return the PSFEx output with the pixel scale of the PSFEx output. To retrieve an image with the same pixel scale as the original science image, use load_psfex() :param model: Path to PSFEx-generated model, as a FITS file (usually ends in .psf); OR HDUList representing the file. :param x: pixel x-coordinate to use for model input :param y: pixel y-coordinate to use for model input :return: numpy.ndarray representing the PSF model as an image. """ model, path = ff.path_or_hdu(model) header = model[1].header a = model[1].data[0][0] xs = check_iterable(x) ys = check_iterable(y) psfs = [] for i, x in enumerate(xs): y = ys[i] x = (x - header['POLZERO1']) / header['POLSCAL1'] y = (y - header['POLZERO2']) / header['POLSCAL2'] if len(a) == 3: psf = a[0] + a[1] * x + a[2] * y elif len(a) == 6: psf = a[0] + a[1] * x + a[2] * x**2 + a[3] * y + a[4] * y**2 + a[ 5] * x * y elif len(a) == 10: psf = a[0] + a[1] * x + a[2] * x ** 2 + a[3] * x ** 3 + a[4] * y + a[5] * x * y + a[6] * x ** 2 * y + \ a[7] * y ** 2 + a[8] * x * y ** 2 + a[9] * y ** 3 else: raise ValueError( "I haven't accounted for polynomials of order > 3. My bad.") psfs.append(psf) if path: model.close() return psfs
def random_position(image: fits.HDUList, hg_ra: float, hg_dec: float, limit: int = 10, show: bool = False): image, path = ff.path_or_hdu(image) header = image[0].header data = image[0].data # Find host galaxy pixel wcs_info = wcs.WCS(header) hg_x, hg_y = wcs_info.all_world2pix(hg_ra, hg_dec, 0) hg_x = int(np.round(hg_x)) hg_y = int(np.round(hg_y)) image_copy = data.copy()[hg_y - limit:hg_y + limit, hg_x - limit:hg_x + limit] noise = np.median(image_copy) image_copy = image_copy - noise image_flatten = image_copy.flatten(1) i = st.value_from_pdf(np.arange(image_flatten.shape[0]), image_flatten / max(image_flatten)) i = int(i) x, y = np.unravel_index(i, image_copy.shape) if show: plt.imshow(image_copy) plt.scatter(x, y) plt.show() plt.close() plt.plot(image_flatten / max(image_flatten)) plt.show() x += hg_x - limit + np.random.uniform(-0.5, 0.5) y += hg_y - limit + np.random.uniform(-0.5, 0.5) ra, dec = wcs_info.all_pix2world(x, y, 0) if path: image.close() return x, y, ra, dec
def plot_all_params(image: Union[str, fits.hdu.HDUList], cat: Union[str, Table, np.ndarray], show: bool = True, cutout: bool = False, ra_key: str = "ALPHA_SKY", dec_key: str = "DELTA_SKY", a_key: str = "A_WORLD", b_key: str = "B_WORLD", theta_key: str = "THETA_WORLD", kron: bool = False, kron_key: str = "KRON_RADIUS"): """ Plots :param image: :param cat: :param cutout: Plots a cutout of the image centre. Forces 'show' to True. :return: """ if cutout: show = True image, path = ff.path_or_hdu(image) data = image[0].data wcs_image = wcs.WCS(header=image[0].header) plt.subplot(projection=wcs_image) norm = ImageNormalize(data, interval=ZScaleInterval(), stretch=SqrtStretch()) plt.imshow(data, origin='lower', norm=norm, ) plot_gal_params(hdu=image, ras=cat[ra_key], decs=cat[dec_key], a=cat[a_key], b=cat[b_key], theta=cat[theta_key], colour='red') if kron: plot_gal_params(hdu=image, ras=cat[ra_key], decs=cat[dec_key], a=cat[kron_key] * cat[a_key], b=cat[kron_key] * cat[b_key], theta=cat[theta_key], colour='violet') if show: plt.show() if cutout: n_x = data.shape[1] n_y = data.shape[0] mid_x = int(n_x / 2) mid_y = int(n_y / 2) left = mid_x - 45 right = mid_x + 45 bottom = mid_y - 45 top = mid_y + 45 gal = ff.trim(hdu=image, left=left, right=right, bottom=bottom, top=top) plt.imshow(gal[0].data) plot_gal_params(hdu=gal, ras=cat[ra_key], decs=cat[dec_key], a=cat[a_key], b=cat[b_key], theta=cat[theta_key], colour='red') if kron: plot_gal_params(hdu=image, ras=cat[ra_key], decs=cat[dec_key], a=cat[kron_key] * cat[a_key], b=cat[kron_key] * cat[b_key], theta=cat[theta_key], colour='violet') if show: plt.show() if path: image.close()
def plot_subimage(fig: plt.figure, hdu: Union[str, fits.HDUList], ra: float, dec: float, frame: Union[int, float], world_frame: bool = False, title: str = None, n: int = 1, n_x: int = 1, n_y: int = 1, cmap: str = 'viridis', show_cbar: bool = False, stretch: str = 'sqrt', vmin: float = None, vmax: float = None, show_grid: bool = False, ticks: int = None, interval: str = 'minmax', show_coords: bool = True, ylabel: str = None, font_size: int = 12, reverse_y=False): """ :param fig: :param hdu: :param ra: :param dec: :param frame: in pixels, or in arcsecs (?) if world_frame is True. :param world_frame: :param title: :param n: :param n_x: :param n_y: :param cmap: :param show_cbar: :param stretch: :param vmin: :param vmax: :param show_grid: :param ticks: :param interval: :param show_coords: :param ylabel: :param font_size: :param reverse_y: :return: """ print(hdu) hdu, path = ff.path_or_hdu(hdu=hdu) print(hdu[0].data.shape) hdu_cut = ff.trim_frame_point(hdu=hdu, ra=ra, dec=dec, frame=frame, world_frame=world_frame) wcs_cut = wcs.WCS(header=hdu_cut[0].header) print(n_y, n_x, n) if show_coords: plot = fig.add_subplot(n_y, n_x, n, projection=wcs_cut) if ticks is not None: lat = plot.coords[0] lat.set_ticks(number=ticks) else: plot = fig.add_subplot(n_y, n_x, n) frame1 = plt.gca() frame1.axes.get_xaxis().set_visible(False) frame1.axes.set_yticks([]) # frame1.axes.get_yaxis().set_visible(False) if show_grid: plt.grid(color='black', ls='dashed') if type(vmin) is str: if vmin == 'median_full': vmin = np.nanmedian(hdu[0].data) elif vmin == 'median_cut': vmin = np.nanmedian(hdu_cut[0].data) else: raise ValueError('Unrecognised vmin string argument.') if interval == 'minmax': interval = MinMaxInterval() elif interval == 'zscale': interval = ZScaleInterval() else: raise ValueError('Interval not recognised.') print(hdu_cut[0].data.shape) if stretch == 'log': norm = ImageNormalize(hdu_cut[0].data, interval=interval, stretch=LogStretch(), vmin=vmin, vmax=vmax) elif stretch == 'sqrt': norm = ImageNormalize(hdu_cut[0].data, interval=interval, stretch=SqrtStretch(), vmin=vmin, vmax=vmax) else: raise ValueError('Stretch not recognised.') plot.title.set_text(title) plot.title.set_size(font_size) print(ylabel) if ylabel is not None: plot.set_ylabel(ylabel, size=12) im = plt.imshow(hdu_cut[0].data, norm=norm, cmap=cmap) if reverse_y: plot.invert_yaxis() c_ticks = np.linspace(norm.vmin, norm.vmax, 5, endpoint=True) if show_cbar: cbar = plt.colorbar(im) # ticks=c_ticks) return plot, hdu_cut