def test_all_three_mm_tables_are_inside_header_wcs(self, input_table_mm): tbl1 = deepcopy(input_table_mm) tbl2 = deepcopy(input_table_mm) tbl3 = deepcopy(input_table_mm) tbl2["x_mm"] += 50 tbl3["y_mm"] += 25 hdr = imp_utils._make_bounding_header_for_tables([tbl1, tbl2, tbl3], 100 * u.um) for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x_mm"], tbl["y_mm"], "D") for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: x, y = imp_utils.calc_footprint(hdr, "D") x, y = imp_utils.val2pix(hdr, x, y, "D") x0, y0 = imp_utils.val2pix(hdr, 0, 0, "D") plt.plot(x, y, "b") plt.plot(x0, y0, "ro") for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x_mm"], tbl["y_mm"], "D") plt.plot(x, y, "k.") plt.show()
def test_image_is_added_to_small_canvas(self, image_hdu_rect, image_hdu_square): im_hdu = image_hdu_rect im_hdu.header["CRVAL1"] -= 150 * u.arcsec.to(u.deg) im_hdu.header["CRVAL2"] += 40 * u.arcsec.to(u.deg) hdr = imp_utils.get_canvas_header([im_hdu, image_hdu_square]) im = np.zeros((hdr["NAXIS2"], hdr["NAXIS1"])) canvas_hdu = fits.ImageHDU(header=hdr, data=im) canvas_hdu = imp_utils.add_imagehdu_to_imagehdu(im_hdu, canvas_hdu) canvas_hdu = imp_utils.add_imagehdu_to_imagehdu( image_hdu_square, canvas_hdu) flux = np.sum(im_hdu.data) + np.sum(image_hdu_square.data) assert np.sum(canvas_hdu.data) == approx(flux, rel=1e-2) if PLOTS: for im in [im_hdu, image_hdu_square]: x, y = imp_utils.calc_footprint(im.header) x, y = imp_utils.val2pix(canvas_hdu.header, x, y) plt.plot(x, y, "r-") x0, y0 = imp_utils.val2pix(canvas_hdu.header, 0, 0) plt.plot(x0, y0, "ro") plt.gca().set_aspect(1) plt.imshow(canvas_hdu.data, origin="lower") plt.show()
def test_all_three_tables_are_inside_header_wcs(self, input_table): tbl1 = deepcopy(input_table) tbl2 = deepcopy(input_table) tbl3 = deepcopy(input_table) tbl2["x"] -= 25 tbl3["y"] -= 60 hdr = imp_utils._make_bounding_header_for_tables([tbl1, tbl2, tbl3]) as2deg = u.arcsec.to(u.deg) for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x"] * as2deg, tbl["y"] * as2deg) for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: x, y = imp_utils.calc_footprint(hdr) x, y = imp_utils.val2pix(hdr, x, y) x0, y0 = imp_utils.val2pix(hdr, 0, 0) plt.plot(x, y, "b") plt.plot(x0, y0, "ro") for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x"] / 3600., tbl["y"] / 3600.) plt.plot(x, y, "k.") plt.show()
def test_mm_image_is_added_to_small_canvas(self, image_hdu_rect_mm, image_hdu_square_mm): im_hdu = image_hdu_rect_mm im_hdu.header["CRVAL1D"] -= 150 im_hdu.header["CRVAL2D"] += 40 hdr = imp_utils.get_canvas_header([im_hdu, image_hdu_square_mm], pixel_scale=1 * u.mm) im = np.zeros((hdr["NAXIS2"], hdr["NAXIS1"])) canvas_hdu = fits.ImageHDU(header=hdr, data=im) canvas_hdu = imp_utils.add_imagehdu_to_imagehdu(im_hdu, canvas_hdu, wcs_suffix="D") assert np.sum(canvas_hdu.data) == approx(np.sum(im_hdu.data)) if PLOTS: for im in [im_hdu, image_hdu_square_mm]: x, y = imp_utils.calc_footprint(im.header, "D") x, y = imp_utils.val2pix(canvas_hdu.header, x, y, "D") plt.plot(x, y, "r-") x0, y0 = imp_utils.val2pix(canvas_hdu.header, 0, 0, "D") plt.plot(x0, y0, "ro") plt.gca().set_aspect(1) plt.imshow(canvas_hdu.data, origin="lower") plt.show()
def test_all_two_mm_imagehdus_are_inside_header_wcs( self, image_hdu_square_mm, image_hdu_rect_mm): image_hdu_rect_mm.header["CRVAL1D"] -= 40 image_hdu_square_mm.header["CRVAL2D"] += 80 hdr = imp_utils._make_bounding_header_from_imagehdus( [image_hdu_square_mm, image_hdu_rect_mm], pixel_scale=1 * u.mm) for imhdr in [image_hdu_square_mm.header, image_hdu_rect_mm.header]: x, y = imp_utils.calc_footprint(imhdr, "D") x, y = imp_utils.val2pix(hdr, x, y, "D") for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: for imhdr in [ image_hdu_square_mm.header, image_hdu_rect_mm.header, hdr ]: x, y = imp_utils.calc_footprint(imhdr, "D") xp, yp = imp_utils.val2pix(imhdr, x, y, "D") plt.plot(x, y, "r-") plt.plot(0, 0, "ro") plt.gca().set_aspect(1) plt.show()
def test_mm_image_and_tables_on_large_canvas(self, input_table_mm, image_hdu_rect_mm, image_hdu_square_mm): image_hdu_rect = image_hdu_rect_mm image_hdu_square = image_hdu_square_mm tbl1 = deepcopy(input_table_mm) tbl2 = deepcopy(input_table_mm) tbl1["y_mm"] -= 100 tbl2["x_mm"] += 100 tbl2["y_mm"] += 100 im_hdu = image_hdu_rect im_hdu.header["CRVAL1D"] -= 150 im_hdu.header["CRVAL2D"] += 20 hdr = imp_utils.get_canvas_header( [im_hdu, image_hdu_square, tbl1, tbl2], pixel_scale=3 * u.mm) im = np.zeros((hdr["NAXIS2"], hdr["NAXIS1"])) canvas_hdu = fits.ImageHDU(header=hdr, data=im) canvas_hdu = imp_utils.add_table_to_imagehdu(tbl1, canvas_hdu, wcs_suffix="D") canvas_hdu = imp_utils.add_table_to_imagehdu(tbl2, canvas_hdu, wcs_suffix="D") canvas_hdu = imp_utils.add_imagehdu_to_imagehdu(im_hdu, canvas_hdu, wcs_suffix="D") canvas_hdu = imp_utils.add_imagehdu_to_imagehdu(image_hdu_square, canvas_hdu, wcs_suffix="D") total_flux = np.sum(tbl1["flux"]) + np.sum(tbl2["flux"]) + \ np.sum(im_hdu.data) + np.sum(image_hdu_square.data) assert np.sum(canvas_hdu.data) == approx(total_flux) if PLOTS: for im in [im_hdu, image_hdu_square]: x, y = imp_utils.calc_footprint(im, "D") x, y = imp_utils.val2pix(canvas_hdu, x, y, "D") plt.plot(x, y, "r-") x0, y0 = imp_utils.val2pix(canvas_hdu, 0, 0, "D") plt.plot(x0, y0, "ro") plt.gca().set_aspect(1) plt.imshow(canvas_hdu.data, origin="lower") plt.show()
def test_mm_points_are_added_to_massive_canvas(self, input_table_mm): tbl1 = deepcopy(input_table_mm) tbl2 = deepcopy(input_table_mm) tbl3 = deepcopy(input_table_mm) tbl1["y_mm"] += 50 tbl2["x_mm"] += 20 tbl3["x_mm"] -= 25 tbl3["y_mm"] -= 25 hdr = imp_utils.get_canvas_header([tbl1, tbl2, tbl3], pixel_scale=1 * u.mm) im = np.zeros((hdr["NAXIS2"], hdr["NAXIS1"])) canvas_hdu = fits.ImageHDU(header=hdr, data=im) for tbl in [tbl1, tbl2, tbl3]: canvas_hdu = imp_utils.add_table_to_imagehdu(tbl, canvas_hdu, True, wcs_suffix="D") total_flux = np.sum([tbl1["flux"], tbl1["flux"], tbl1["flux"]]) assert np.sum(canvas_hdu.data) == total_flux if PLOTS: x, y = imp_utils.val2pix(hdr, 0, 0, "D") plt.plot(x, y, "ro") "top left is green, top right is yellow" plt.imshow(canvas_hdu.data, origin="lower") plt.show()
def test_add_many_mm_tables_and_imagehdus(self, input_table_mm, image_hdu_rect_mm, image_hdu_square_mm): image_hdu_rect = image_hdu_rect_mm image_hdu_square = image_hdu_square_mm tbl1 = deepcopy(input_table_mm) tbl2 = deepcopy(input_table_mm) tbl1["y_mm"] -= 50 tbl2["x_mm"] += 50 tbl2["y_mm"] += 50 im_hdu = image_hdu_rect im_hdu.header["CRVAL1D"] -= 150 # mm im_hdu.header["CRVAL2D"] += 20 fields = [im_hdu, tbl1, tbl2, image_hdu_square] hdr = imp_utils.get_canvas_header(fields, pixel_scale=1 * u.mm) implane = opt_imp.ImagePlane(hdr) implane.add(fields, wcs_suffix="D") total_flux = np.sum(tbl1["flux"]) + np.sum(tbl2["flux"]) + \ np.sum(im_hdu.data) + np.sum(image_hdu_square.data) assert np.sum(implane.data) == approx(total_flux) if PLOTS: for im in [im_hdu, image_hdu_square]: x, y = imp_utils.calc_footprint(im.header, "D") x, y = imp_utils.val2pix(implane.header, x, y, "D") plt.plot(x, y, "r-") for tbl in [tbl1, tbl2]: hdr = imp_utils._make_bounding_header_for_tables( [tbl], pixel_scale=1 * u.mm) x, y = imp_utils.calc_footprint(hdr, "D") x, y = imp_utils.val2pix(implane.header, x, y, "D") plt.plot(x, y, "r-") x0, y0 = imp_utils.val2pix(implane.header, 0, 0, "D") plt.plot(x0, y0, "ro") plt.gca().set_aspect(1) plt.imshow(implane.data, origin="lower", norm=LogNorm()) plt.show()
def test_add_many_tables_and_imagehdus(self, input_table, image_hdu_rect, image_hdu_square): tbl1 = deepcopy(input_table) tbl2 = deepcopy(input_table) tbl1["y"] -= 50 tbl2["x"] += 50 tbl2["y"] += 50 im_hdu = image_hdu_rect im_hdu.header["CRVAL1"] -= 150 * u.arcsec.to(u.deg) im_hdu.header["CRVAL2"] += 20 * u.arcsec.to(u.deg) fields = [im_hdu, tbl1, tbl2, image_hdu_square] hdr = imp_utils.get_canvas_header(fields, pixel_scale=1 * u.arcsec) implane = opt_imp.ImagePlane(hdr) implane.add(fields) total_flux = np.sum(tbl1["flux"]) + np.sum(tbl2["flux"]) + \ np.sum(im_hdu.data) + np.sum(image_hdu_square.data) assert np.sum(implane.data) == approx(total_flux) if PLOTS: for im in [im_hdu, image_hdu_square]: x, y = imp_utils.calc_footprint(im.header) x, y = imp_utils.val2pix(implane.header, x, y) plt.plot(x, y, "r-") for tbl in [tbl1, tbl2]: hdr = imp_utils._make_bounding_header_for_tables([tbl]) x, y = imp_utils.calc_footprint(hdr) x, y = imp_utils.val2pix(implane.header, x, y) plt.plot(x, y, "r-") x0, y0 = imp_utils.val2pix(implane.header, 0, 0) plt.plot(x0, y0, "ro") plt.gca().set_aspect(1) plt.imshow(implane.data, origin="lower", norm=LogNorm()) plt.show()
def test_all_two_imagehdus_are_inside_header_wcs(self, image_hdu_square, image_hdu_rect): image_hdu_rect.header["CRVAL1"] -= 70 * u.arcsec.to(u.deg) image_hdu_square.header["CRVAL2"] += 70 * u.arcsec.to(u.deg) hdr = imp_utils._make_bounding_header_from_imagehdus( [image_hdu_square, image_hdu_rect]) for imhdr in [image_hdu_square.header, image_hdu_rect.header]: x, y = imp_utils.calc_footprint(imhdr) x, y = imp_utils.val2pix(hdr, x, y) for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: for imhdr in [image_hdu_square.header, image_hdu_rect.header, hdr]: x, y = imp_utils.calc_footprint(imhdr) xp, yp = imp_utils.val2pix(imhdr, x, y) plt.plot(x, y, "r-") plt.plot(0, 0, "ro") plt.gca().set_aspect(1) plt.show()
def test_all_5_objects_are_inside_header_wcs(self, image_hdu_square, image_hdu_rect, input_table): tbl1 = deepcopy(input_table) tbl2 = deepcopy(input_table) tbl3 = deepcopy(input_table) tbl2["x"] -= 150 tbl3["y"] -= 100 image_hdu_rect.header["CRVAL1"] += 100 * u.arcsec.to(u.deg) image_hdu_square.header["CRVAL1"] += 0 * u.arcsec.to(u.deg) image_hdu_square.header["CRVAL2"] += 100 * u.arcsec.to(u.deg) hdr = imp_utils.get_canvas_header( [image_hdu_square, tbl1, tbl2, tbl3, image_hdu_rect], pixel_scale=1 * u.arcsec) for im in [image_hdu_square.header, image_hdu_rect.header]: x, y = imp_utils.calc_footprint(im) x, y = imp_utils.val2pix(hdr, x, y) for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] as2deg = u.arcsec.to(u.deg) for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x"] * as2deg, tbl["y"] * as2deg) for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: x, y = imp_utils.calc_footprint(hdr) x, y = imp_utils.val2pix(hdr, x, y) plt.plot(x, y, "b") x0, y0 = imp_utils.val2pix(hdr, 0, 0) plt.plot(x0, y0, "ro") for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x"] * as2deg, tbl["y"] * as2deg) plt.plot(x, y, "k.") for im in [image_hdu_square.header, image_hdu_rect.header]: x, y = imp_utils.calc_footprint(im) x, y = imp_utils.val2pix(hdr, x, y) plt.plot(x, y, "r-") plt.gca().set_aspect(1) plt.show()
def test_all_5_objects_are_inside_mm_header_wcs(self, image_hdu_square_mm, image_hdu_rect_mm, input_table_mm): tbl1 = deepcopy(input_table_mm) tbl2 = deepcopy(input_table_mm) tbl3 = deepcopy(input_table_mm) tbl2["x_mm"] -= 150 tbl3["y_mm"] -= 100 image_hdu_rect_mm.header["CRVAL1D"] += 100 image_hdu_square_mm.header["CRVAL1D"] += 0 image_hdu_square_mm.header["CRVAL2D"] += 100 hdr = imp_utils.get_canvas_header( [image_hdu_square_mm, tbl1, tbl2, tbl3, image_hdu_rect_mm], pixel_scale=1 * u.mm) for im in [image_hdu_square_mm.header, image_hdu_rect_mm.header]: x, y = imp_utils.calc_footprint(im, "D") x, y = imp_utils.val2pix(hdr, x, y, "D") for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x_mm"], tbl["y_mm"], "D") for xi, yi in zip(x, y): assert 0 <= xi < hdr["NAXIS1"] assert 0 <= yi < hdr["NAXIS2"] if PLOTS: x, y = imp_utils.calc_footprint(hdr, "D") x, y = imp_utils.val2pix(hdr, x, y, "D") plt.plot(x, y, "b") x0, y0 = imp_utils.val2pix(hdr, 0, 0, "D") plt.plot(x0, y0, "ro") for tbl in [tbl1, tbl2, tbl3]: x, y = imp_utils.val2pix(hdr, tbl["x_mm"], tbl["y_mm"], "D") plt.plot(x, y, "k.") for im in [image_hdu_square_mm.header, image_hdu_rect_mm.header]: x, y = imp_utils.calc_footprint(im, "D") x, y = imp_utils.val2pix(hdr, x, y, "D") plt.plot(x, y, "r-") plt.gca().set_aspect(1) plt.show()
def sky2fp(header, xsky, ysky): """ Convert sky coordinates to image plane coordinated Parameters ---------- header : Header Header of a FieldOfView object which contains two sets of WCS keywords xsky, ysky : float, array [deg] The on-sky coordinated Returns ------- xdet, ydet : float, array [mm] The coordinated on the image plane """ xpix, ypix = imp_utils.val2pix(header, xsky, ysky) xdet, ydet = imp_utils.pix2val(header, xpix, ypix, "D") return xdet, ydet
def extract_area_from_imagehdu(imagehdu, fov_volume): """ Extracts the part of a ImageHDU that fits inside the fov_volume Parameters ---------- imagehdu : fits.ImageHDU The field ImageHDU, either an image of a wavelength [um] cube fov_volume : dict Contains {"xs": [xmin, xmax], "ys": [ymin, ymax], "waves": [wave_min, wave_max], "xy_unit": "deg" or "mm", "wave_unit": "um"} Returns ------- new_imagehdu : fits.ImageHDU """ hdr = imagehdu.header new_hdr = {} x_hdu, y_hdu = imp_utils.calc_footprint(imagehdu) # field edges in "deg" x_fov, y_fov = fov_volume["xs"], fov_volume["ys"] x0s, x1s = max(min(x_hdu), min(x_fov)), min(max(x_hdu), max(x_fov)) y0s, y1s = max(min(y_hdu), min(y_fov)), min(max(y_hdu), max(y_fov)) xp, yp = imp_utils.val2pix(hdr, np.array([x0s, x1s]), np.array([y0s, y1s])) (x0p, x1p), (y0p, y1p) = np.round(xp).astype(int), np.round(yp).astype(int) if x0p == x1p: x1p += 1 if y0p == y1p: y1p += 1 new_hdr = imp_utils.header_from_list_of_xy([x0s, x1s], [y0s, y1s], pixel_scale=hdr["CDELT1"]) if hdr["NAXIS"] == 3: # Look 0.5*wdel past the fov edges in each direction to catch any # slices where the middle wavelength value doesn't fall inside the # fov waverange, but up to 50% of the slice is actually inside the # fov waverange: # E.g. FOV: [1.92, 2.095], HDU bin centres: [1.9, 2.0, 2.1] # CDELT3 = 0.1, and HDU bin edges: [1.85, 1.95, 2.05, 2.15] # So 1.9 slice needs to be multiplied by 0.3, and 2.1 slice should be # multipled by 0.45 to reach the scaled contribution of the edge slices # This scaling factor is: # f = ((hdu_bin_centre - fov_edge [+/-] 0.5 * cdelt3) % cdelt3) / cdelt3 hdu_waves = get_cube_waveset(hdr) wdel = hdr["CDELT3"] wunit = u.Unit(hdr.get("CUNIT3", "AA")) fov_waves = utils.quantify(fov_volume["waves"], u.um).to(wunit).value mask = ((hdu_waves > fov_waves[0] - 0.5 * wdel) * (hdu_waves <= fov_waves[1] + 0.5 * wdel)) # need to go [+/-] half a bin # OC [2021-12-14] if fov range is not covered by the source return nothing if not np.any(mask): print("FOV {} um - {} um: not covered by Source".format(fov_waves[0], fov_waves[1])) return None i0p, i1p = np.where(mask)[0][0], np.where(mask)[0][-1] f0 = (abs(hdu_waves[i0p] - fov_waves[0] + 0.5 * wdel) % wdel) / wdel # blue edge f1 = (abs(hdu_waves[i1p] - fov_waves[1] - 0.5 * wdel) % wdel) / wdel # red edge data = imagehdu.data[i0p:i1p+1, y0p:y1p, x0p:x1p] data[0, :, :] *= f0 if i1p > i0p: data[-1, :, :] *= f1 # w0, w1 : the closest cube wavelengths outside the fov edge wavelengths # fov_waves : the fov edge wavelengths # f0, f1 : the scaling factors for the blue and red edge cube slices # # w0, w1 = hdu_waves[i0p], hdu_waves[i1p] # print(f"\nw0: {w0}, f0: {f0}, {fov_waves}, f1: {f1}, w1: {w1}") new_hdr.update({"NAXIS": 3, "NAXIS3": data.shape[0], "CRVAL3": hdu_waves[i0p], "CRPIX3": 0, "CDELT3": hdr["CDELT3"], "CUNIT3": hdr["CUNIT3"], "CTYPE3": hdr["CTYPE3"], "BUNIT": hdr["BUNIT"]}) else: data = imagehdu.data[y0p:y1p, x0p:x1p] new_hdr["SPEC_REF"] = hdr.get("SPEC_REF") new_imagehdu = fits.ImageHDU(data=data) new_imagehdu.header.update(new_hdr) return new_imagehdu