def reg_to_ds9reg(row, image): angconv = util.angconv("deg", row["angunit"]) nxref = image.header["nxref"] nyref = image.header["nyref"] dx = image.header["dx"] * angconv dy = image.header["dy"] * angconv if not round(-dx, 9) == round(dy, 9): print("Warning: image |dx| is not equal to |dy|.") print("|dx| = %f, |dy| = %f" % (round(-dx, 9), round(dy, 9))) else: pass x = row["xc"] / dx + nxref y = row["yc"] / dy + nyref if row["shape"] == "box": width = -row["width"] / dx height = row["height"] / dy angle = row["angle"] return "image; box(%f,%f,%f,%f,%f)" % (x, y, width, height, angle) if row["shape"] == "circle": r = -row["radius"] / dx return "image; circle(%f,%f,%f)" % (x, y, r) if row["shape"] == "ellipse": a = -row["mina"] / 2.0 / dx b = row["maja"] / 2.0 / dy angle = row["angle"] return "image; ellipse(%f,%f,%f,%f,%f)" % (x, y, a, b, angle)
def winmod(self, image, save_totalflux=False): ''' Trim the image with image regions. Args: image (IMFITS) save_totalflux (boolean, default = False): If save_totalflux=True, the trimmed have the same total flux as before editting image. Returns: IMFITS object. ''' xgrid = np.arange(image.header["nx"]) ygrid = np.arange(image.header["ny"]) X, Y = np.meshgrid(xgrid, ygrid) area = np.zeros(X.shape, dtype="Bool") for index, row in self.iterrows(): angconv = util.angconv(row["angunit"], "deg") x0 = row["xc"] * angconv / image.header["dx"] + image.header[ "nxref"] - 1 y0 = row["yc"] * angconv / image.header["dy"] + image.header[ "nyref"] - 1 if row["shape"] == "box": width = row["width"] * angconv / image.header["dx"] height = row["height"] * angconv / image.header["dy"] angle = row["angle"] tmparea = region_box(X, Y, x0, y0, width, height, angle) elif row["shape"] == "circle": radius = row["radius"] * angconv / image.header["dx"] tmparea = region_circle(X, Y, x0, y0, radius) elif row["shape"] == "ellipse": radius1 = row["mina"] / 2.0 * angconv / image.header["dx"] radius2 = row["maja"] / 2.0 * angconv / image.header["dy"] angle = row["angle"] tmparea = region_ellipse(X, Y, x0, y0, radius1, radius2, angle) else: print("[WARNING] The shape %s is not available." % (row["shape"])) area += tmparea editimage = copy.deepcopy(image) for idxs in np.arange(image.header["ns"]): for idxf in np.arange(image.header["nf"]): matrix = editimage.data[idxs, idxf] editimage.data[idxs, idxf][~area] = 0.0 if save_totalflux: totalflux = editimage.totalflux(istokes=idxs, ifreq=idxf) editimage.data[idxs, idxf] *= totalflux / matrix.sum() # Update and Return editimage.update_fits() return editimage
def plot_circle(row, angunit="mas", **pltargs): angconv = util.angconv(row.angunit, angunit) xc = row.xc * angconv yc = row.yc * angconv radius = row.radius * angconv theta = np.linspace(0., 360., 200) cost = np.cos(np.deg2rad(theta)) sint = np.sin(np.deg2rad(theta)) X = radius * cost + xc Y = radius * sint + yc plt.plot(X, Y, **pltargs)
def maskimage(self, image): ''' Make a mask image. Each pixel of the output image is stored as a single bit—i.e., a 0 or 1. Args: image (IMFITS) Returns: IMFITS object. ''' xgrid = np.arange(image.header["nx"]) ygrid = np.arange(image.header["ny"]) X, Y = np.meshgrid(xgrid, ygrid) area = np.zeros(X.shape, dtype="Bool") for index, row in self.iterrows(): angconv = util.angconv(row["angunit"], "deg") x0 = row["xc"] * angconv / image.header["dx"] + image.header[ "nxref"] - 1 y0 = row["yc"] * angconv / image.header["dy"] + image.header[ "nyref"] - 1 if row["shape"] == "box": width = row["width"] * angconv / image.header["dx"] height = row["height"] * angconv / image.header["dy"] angle = row["angle"] tmparea = region_box(X, Y, x0, y0, width, height, angle) elif row["shape"] == "circle": radius = row["radius"] * angconv / image.header["dx"] tmparea = region_circle(X, Y, x0, y0, radius) elif row["shape"] == "ellipse": radius1 = row["mina"] / 2.0 * angconv / image.header["dx"] radius2 = row["maja"] / 2.0 * angconv / image.header["dy"] angle = row["angle"] tmparea = region_ellipse(X, Y, x0, y0, radius1, radius2, angle) else: print("[WARNING] The shape %s is not available." % (row["shape"])) area += tmparea maskimage = copy.deepcopy(image) for idxs in np.arange(image.header["ns"]): for idxf in np.arange(image.header["nf"]): maskimage.data[idxs, idxf][area] = 1.0 maskimage.data[idxs, idxf][~area] = 0.0 # Update and Return maskimage.update_fits() return maskimage
def shift(self, dx=0, dy=0, angunit="mas"): ''' Shift region. Args: dx (float, default=0): Shift in x-axis. dy (float, default=0): Shift in y-axis. angunit (str, default=mas): Anguler unit of dx and dy. ''' for index, row in self.iterrows(): angconv = util.angconv(angunit, row["angunit"]) self.loc[index, "xc"] += dx * angconv self.loc[index, "yc"] += dy * angconv
def plot_ellipse(row, angunit="mas", **pltargs): angconv = util.angconv(row.angunit, angunit) xc = row.xc * angconv yc = row.yc * angconv maja = row.maja * angconv mina = row.mina * angconv a = mina / 2. b = maja / 2. theta = np.linspace(0., 360., 200) cost = np.cos(np.deg2rad(theta)) sint = np.sin(np.deg2rad(theta)) X = a * cost + xc Y = b * sint + yc cosa = np.cos(np.deg2rad(row.angle)) sina = np.sin(np.deg2rad(row.angle)) XX = (X - xc) * cosa - (Y - yc) * sina + xc YY = (X - xc) * sina + (Y - yc) * cosa + yc plt.plot(XX, YY, **pltargs)
def plot_box(row, angunit, **pltargs): angconv = util.angconv(row.angunit, angunit) xc = row.xc * angconv yc = row.yc * angconv width = row.width * angconv height = row.height * angconv x0 = xc + width / 2.0 x1 = xc - width / 2.0 y0 = yc - height / 2.0 y1 = yc + height / 2.0 X0 = x0 X1 = x1 X2 = x1 X3 = x0 Y0 = y0 Y1 = y0 Y2 = y1 Y3 = y1 cosa = np.cos(np.deg2rad(row.angle)) sina = np.sin(np.deg2rad(row.angle)) X0 = (x0 - xc) * cosa + (y0 - yc) * sina + xc Y0 = -(x0 - xc) * sina + (y0 - yc) * cosa + yc X1 = (x1 - xc) * cosa + (y0 - yc) * sina + xc Y1 = -(x1 - xc) * sina + (y0 - yc) * cosa + yc X2 = (x1 - xc) * cosa + (y1 - yc) * sina + xc Y2 = -(x1 - xc) * sina + (y1 - yc) * cosa + yc X3 = (x0 - xc) * cosa + (y1 - yc) * sina + xc Y3 = -(x0 - xc) * sina + (y1 - yc) * cosa + yc plt.plot([X0, X1], [Y0, Y1], **pltargs) plt.plot([X1, X2], [Y1, Y2], **pltargs) plt.plot([X2, X3], [Y2, Y3], **pltargs) plt.plot([X3, X0], [Y3, Y0], **pltargs)
def ds9reg_to_reg(ds9reg, image, angunit="mas"): angconv = util.angconv("deg", angunit) nxref = image.header["nxref"] nyref = image.header["nyref"] dx = image.header["dx"] * angconv dy = image.header["dy"] * angconv if not round(-dx, 9) == round(dy, 9): print("Warning: image |dx| is not equal to |dy|.") print("|dx| = %f, |dy| = %f" % (round(-dx, 9), round(dy, 9))) else: pass ds9reg = ds9reg.split("\n") region = IMRegion() region.initialize() for reg in ds9reg: if reg[0:3] == "box": list = map(np.float64, reg[4:-1].split(",")) x = list[0] y = list[1] width = list[2] height = list[3] angle = list[4] width *= (-dx) height *= dy xc = (x - nxref) * dx yc = (y - nyref) * dy region = region.add_box(xc=xc, yc=yc, width=width, height=height, angle=angle, angunit=angunit) if reg[0:6] == "circle": list = map(np.float64, reg[7:-1].split(",")) x = list[0] y = list[1] r = list[2] radius = r * (-dx) xc = (x - nxref) * dx yc = (y - nyref) * dy region = region.add_circle(xc=xc, yc=yc, radius=radius, angunit=angunit) if reg[0:7] == "ellipse": list = map(np.float64, reg[8:-1].split(",")) x = list[0] y = list[1] a = list[2] b = list[3] angle = list[4] - 90.0 maja = a * 2.0 * dy mina = b * 2.0 * (-dx) xc = (x - nxref) * dx yc = (y - nyref) * dy region = region.add_ellipse(xc=xc, yc=yc, maja=maja, mina=mina, angle=angle, angunit=angunit) if reg[0:7] == "polygon": print("Error: polygon cannot be used.") return region
def remove_duplicates(self): ''' Remove duplicated regions. Returns: IMRegion. ''' region = self.copy() outregion = self.copy() for index, row in region.iterrows(): # Align angular unit angconv = util.angconv(row.angunit, "mas") region.loc[index, "xc"] *= angconv region.loc[index, "yc"] *= angconv region.loc[index, "width"] *= angconv region.loc[index, "height"] *= angconv region.loc[index, "radius"] *= angconv region.loc[index, "maja"] *= angconv region.loc[index, "mina"] *= angconv region.loc[index, "angunit"] = "mas" # Make "length" column for characteristic length if row["shape"] == "box": width = region.loc[index, "width"] height = region.loc[index, "height"] region.loc[index, "length"] = np.sqrt(width * width + height * height) elif row["shape"] == "circle": radius = region.loc[index, "radius"] region.loc[index, "length"] = radius * 2.0 elif row["shape"] == "ellipse": maja = region.loc[index, "maja"] mina = region.loc[index, "mina"] region.loc[index, "length"] = max(maja, mina) mesh = np.nanmin([ region["width"].min(), region["height"].min(), region["radius"].min() * 2.0, region["maja"].min(), region["mina"].min() ]) mesh /= 10.0 length = region["length"].max() xmin = region["xc"].min() - length xmax = region["xc"].max() + length ymin = region["yc"].min() - length ymax = region["yc"].max() + length nx = int(round((xmax - xmin) / mesh)) + 1 ny = int(round((ymax - ymin) / mesh)) + 1 xgrid = np.linspace(xmax, xmin, nx) ygrid = np.linspace(ymin, ymax, ny) X, Y = np.meshgrid(xgrid, ygrid) # Make area panel items = len(region) area = np.zeros((items, ny, nx)) for index, row in region.iterrows(): if row["shape"] == "box": area[index] = region_box(X, Y, row.xc, row.yc, row.width, row.height, row.angle) elif row["shape"] == "circle": area[index] = region_circle(X, Y, row.xc, row.yc, row.radius) elif row["shape"] == "ellipse": area[index] = region_ellipse(X, Y, row.xc, row.yc, row.mina / 2.0, row.maja / 2.0, row.angle) # Search duplicated area droplist = [] for index, row in region.iterrows(): area1 = area[index] area1 = area1 > 0 area2 = area[0:index].sum(axis=0) + area[index + 1:].sum(axis=0) area2 = area2 > 0 merge = area1 + area2 merge = merge > 0 if np.allclose(merge, area2): # area_index is duplicated. area[index] = np.zeros((ny, nx)) droplist.append(index) else: pass print("Duplicated region is:") print(droplist) # Remove duplicated area outregion = outregion.drop(droplist) outregion = outregion.reset_index(drop=True) # return region return outregion