def build_polygon(self): if self.edges_ra is None: self.get_edges_sky() self.polygon = SphericalPolygon.from_radec(self.edges_ra, self.edges_dec, self.meta_wcs.wcs.crval)
def build_polygon(self): inner_pix = self.wcs.pixel_to_world_values(2, 2) # define polygon on the sky self.polygon = SphericalPolygon.from_radec(self.corners[:, 0], self.corners[:, 1], inner_pix)
def build_polygon(self, member='total'): if self.edges_ra is None: self.get_edges_sky(member=member) self.polygon = SphericalPolygon.from_radec(self.edges_ra, self.edges_dec, self.meta_wcs.wcs.crval)
def getWcsRegion(imageRow): region = None stcs = imageRow["regionSTCS"] if (stcs is not None): a = stcs.split(' ') if len(a) == 10: ras = [ float(a[2]), float(a[4]), float(a[6]), float(a[8]), float(a[2]) ] decs = [ float(a[3]), float(a[5]), float(a[7]), float(a[9]), float(a[3]) ] print ras print decs region = SphericalPolygon.from_radec(ras, decs) return region
def getWcsRegion(imageRow): region = None stcs = imageRow["regionSTCS"] if stcs is not None: a = stcs.split(" ") if len(a) == 10: ras = [float(a[2]), float(a[4]), float(a[6]), float(a[8]), float(a[2])] decs = [float(a[3]), float(a[5]), float(a[7]), float(a[9]), float(a[3])] print ras print decs region = SphericalPolygon.from_radec(ras, decs) return region
def quad_to_poly(ra, dec, **kwargs): p = SphericalPolygon.from_radec(ra, dec, degrees=True) points = p.polygons[0]._points _ra, _dec = [], [] for A, B in zip(points[0:-1], points[1:]): length = great_circle_arc.length(A, B, degrees=True) if not np.isfinite(length): length = 2 interpolated = great_circle_arc.interpolate(A, B, length * 4) lon, lat = vector.vector_to_lonlat(interpolated[:, 0], interpolated[:, 1], interpolated[:, 2], degrees=True) for lon0, lat0, lon1, lat1 in zip(lon[0:-1], lat[0:-1], lon[1:], lat[1:]): _ra.append(lon0) _dec.append(lat0) _ra.append(lon1) _dec.append(lat1) return PolyCollection([np.c_[_ra, _dec]], **kwargs)
def _calc_sky_orig(self, overlap=None, delta=True): """ Compute sky background value. Parameters ---------- overlap : SkyImage, SkyGroup, SphericalPolygon, list of tuples, \ None, optional Another `SkyImage`, `SkyGroup`, :py:class:`spherical_geometry.polygons.SphericalPolygon`, or a list of tuples of (RA, DEC) of vertices of a spherical polygon. This parameter is used to indicate that sky statistics should computed only in the region of intersection of *this* image with the polygon indicated by `overlap`. When `overlap` is `None`, sky statistics will be computed over the entire image. delta : bool, optional Should this function return absolute sky value or the difference between the computed value and the value of the sky stored in the `sky` property. Returns ------- skyval : float, None Computed sky value (absolute or relative to the `sky` attribute). If there are no valid data to perform this computations (e.g., because this image does not overlap with the image indicated by `overlap`), `skyval` will be set to `None`. npix : int Number of pixels used to compute sky statistics. polyarea : float Area (in srad) of the polygon that bounds data used to compute sky statistics. """ if overlap is None: if self.mask is None: data = self.image else: data = self.image[self.mask] polyarea = self.poly_area else: fill_mask = np.zeros(self.image.shape, dtype=bool) if isinstance(overlap, (SkyImage, SkyGroup, SphericalPolygon)): intersection = self.intersection(overlap) polyarea = np.fabs(intersection.area()) radec = intersection.to_radec() else: # assume a list of (ra, dec) tuples: radec = [] polyarea = 0.0 for r, d in overlap: poly = SphericalPolygon.from_radec(r, d) polyarea1 = np.fabs(poly.area()) if polyarea1 == 0.0 or len(r) < 4: continue polyarea += polyarea1 radec.append(self.intersection(poly).to_radec()) if polyarea == 0.0: return (None, 0, 0.0) for ra, dec in radec: if len(ra) < 4: continue # set pixels in 'fill_mask' that are inside a polygon to True: x, y = self.wcs_inv(ra, dec) poly_vert = list(zip(*[x, y])) polygon = region.Polygon(True, poly_vert) fill_mask = polygon.scan(fill_mask) if self.mask is not None: fill_mask &= self.mask data = self.image[fill_mask] if data.size < 1: return (None, 0, 0.0) # Calculate sky try: skyval, npix = self._skystat(data) except ValueError: return (None, 0, 0.0) if delta: skyval -= self._sky return skyval, npix, polyarea
def calc_bounding_polygon(self, stepsize=None): """ Compute image's bounding polygon. Parameters ---------- stepsize : int, None, optional Indicates the maximum separation between two adjacent vertices of the bounding polygon along each side of the image. Corners of the image are included automatically. If `stepsize` is `None`, bounding polygon will contain only vertices of the image. """ ny, nx = self.image.shape if stepsize is None: nintx = 2 ninty = 2 else: nintx = max(2, int(np.ceil((nx + 1.0) / stepsize))) ninty = max(2, int(np.ceil((ny + 1.0) / stepsize))) xs = np.linspace(-0.5, nx - 0.5, nintx, dtype=np.float) ys = np.linspace(-0.5, ny - 0.5, ninty, dtype=np.float)[1:-1] nptx = xs.size npty = ys.size npts = 2 * (nptx + npty) borderx = np.empty((npts + 1, ), dtype=np.float) bordery = np.empty((npts + 1, ), dtype=np.float) # "bottom" points: borderx[:nptx] = xs bordery[:nptx] = -0.5 # "right" sl = np.s_[nptx:nptx + npty] borderx[sl] = nx - 0.5 bordery[sl] = ys # "top" sl = np.s_[nptx + npty:2 * nptx + npty] borderx[sl] = xs[::-1] bordery[sl] = ny - 0.5 # "left" sl = np.s_[2 * nptx + npty:-1] borderx[sl] = -0.5 bordery[sl] = ys[::-1] # close polygon: borderx[-1] = borderx[0] bordery[-1] = bordery[0] ra, dec = self.wcs_fwd(borderx, bordery, with_bounding_box=False) # TODO: for strange reasons, occasionally ra[0] != ra[-1] and/or # dec[0] != dec[-1] (even though we close the polygon in the # previous two lines). Then SphericalPolygon fails because # points are not closed. Threfore we force it to be closed: ra[-1] = ra[0] dec[-1] = dec[0] self._radec = [(ra, dec)] self._polygon = SphericalPolygon.from_radec(ra, dec) self._poly_area = np.fabs(self._polygon.area())
def _skycoord_to_spherical_polygon(skycoord): return SphericalPolygon.from_radec(skycoord.spherical.lon.degree, skycoord.spherical.lat.degree, degrees=True)
def _calc_sky_orig(self, overlap=None, delta=True): """ Compute sky background value. Parameters ---------- overlap : SkyImage, SkyGroup, SphericalPolygon, list of tuples, \ None, optional Another `SkyImage`, `SkyGroup`, :py:class:`spherical_geometry.polygons.SphericalPolygon`, or a list of tuples of (RA, DEC) of vertices of a spherical polygon. This parameter is used to indicate that sky statistics should computed only in the region of intersection of *this* image with the polygon indicated by `overlap`. When `overlap` is `None`, sky statistics will be computed over the entire image. delta : bool, optional Should this function return absolute sky value or the difference between the computed value and the value of the sky stored in the `sky` property. Returns ------- skyval : float, None Computed sky value (absolute or relative to the `sky` attribute). If there are no valid data to perform this computations (e.g., because this image does not overlap with the image indicated by `overlap`), `skyval` will be set to `None`. npix : int Number of pixels used to compute sky statistics. polyarea : float Area (in srad) of the polygon that bounds data used to compute sky statistics. """ if overlap is None: if self.mask is None: data = self.image else: data = self.image[self.mask] polyarea = self.poly_area else: fill_mask = np.zeros(self.image.shape, dtype=bool) if isinstance(overlap, (SkyImage, SkyGroup, SphericalPolygon)): intersection = self.intersection(overlap) polyarea = np.fabs(intersection.area()) radec = intersection.to_radec() else: # assume a list of (ra, dec) tuples: radec = [] polyarea = 0.0 for r, d in overlap: poly = SphericalPolygon.from_radec(r, d) polyarea1 = np.fabs(poly.area()) if polyarea1 == 0.0 or len(r) < 4: continue polyarea += polyarea1 radec.append(self.intersection(poly).to_radec()) if polyarea == 0.0: return (None, 0, 0.0) for ra, dec in radec: if len(ra) < 4: continue # set pixels in 'fill_mask' that are inside a polygon to True: x, y = self.wcs_inv(ra, dec) poly_vert = list(zip(*[x, y])) polygon = region.Polygon(True, poly_vert) fill_mask = polygon.scan(fill_mask) if self.mask is not None: fill_mask &= self.mask data = self.image[fill_mask] if data.size < 1: return (None, 0, 0.0) # Calculate sky try: skyval, npix = self._skystat(data) except ValueError: return (None, 0, 0.0) if delta: skyval -= self._sky return skyval, npix, polyarea
def calc_bounding_polygon(self, stepsize=None): """ Compute image's bounding polygon. Parameters ---------- stepsize : int, None, optional Indicates the maximum separation between two adjacent vertices of the bounding polygon along each side of the image. Corners of the image are included automatically. If `stepsize` is `None`, bounding polygon will contain only vertices of the image. """ ny, nx = self.image.shape if stepsize is None: nintx = 2 ninty = 2 else: nintx = max(2, int(np.ceil((nx + 1.0) / stepsize))) ninty = max(2, int(np.ceil((ny + 1.0) / stepsize))) xs = np.linspace(-0.5, nx - 0.5, nintx, dtype=np.float) ys = np.linspace(-0.5, ny - 0.5, ninty, dtype=np.float)[1:-1] nptx = xs.size npty = ys.size npts = 2 * (nptx + npty) borderx = np.empty((npts + 1,), dtype=np.float) bordery = np.empty((npts + 1,), dtype=np.float) # "bottom" points: borderx[:nptx] = xs bordery[:nptx] = -0.5 # "right" sl = np.s_[nptx:nptx + npty] borderx[sl] = nx - 0.5 bordery[sl] = ys # "top" sl = np.s_[nptx + npty:2 * nptx + npty] borderx[sl] = xs[::-1] bordery[sl] = ny - 0.5 # "left" sl = np.s_[2 * nptx + npty:-1] borderx[sl] = -0.5 bordery[sl] = ys[::-1] # close polygon: borderx[-1] = borderx[0] bordery[-1] = bordery[0] ra, dec = self.wcs_fwd(borderx, bordery, with_bounding_box=False) # TODO: for strange reasons, occasionally ra[0] != ra[-1] and/or # dec[0] != dec[-1] (even though we close the polygon in the # previous two lines). Then SphericalPolygon fails because # points are not closed. Threfore we force it to be closed: ra[-1] = ra[0] dec[-1] = dec[0] self._radec = [(ra, dec)] self._polygon = SphericalPolygon.from_radec(ra, dec) self._poly_area = np.fabs(self._polygon.area())
def __init__(self, ra, dec, inside=None, max_depth=10): ra = ra.to(u.rad).value dec = dec.to(u.rad).value # Check if the vertices form a closed polygon if ra[0] != ra[-1] or dec[0] != dec[-1]: # If not, append the first vertex to ``vertices`` ra = np.append(ra, ra[0]) dec = np.append(dec, dec[0]) vertices = SkyCoord(ra=ra, dec=dec, unit="rad", frame="icrs") if inside: # Convert it to (x, y, z) cartesian coordinates on the sphere inside = (inside.icrs.ra.rad, inside.icrs.dec.rad) self.polygon = SphericalPolygon.from_lonlat(lon=ra, lat=dec, center=inside, degrees=False) start_depth, ipixels = self._get_starting_depth() end_depth = max_depth # When the start depth returned is > to the depth requested # For that specific case, we only do one iteration at start_depth # Thus the MOC will contain the partially intersecting cells with the # contained ones at start_depth # And we degrade the MOC to the max_depth self.degrade_to_max_depth = False if start_depth > end_depth: end_depth = start_depth self.degrade_to_max_depth = True self.ipix_d = {str(order): [] for order in range(start_depth, end_depth + 1)} ## Iterative version of the algorithm: seems a bit faster than the recursive one for depth in range(start_depth, end_depth + 1): # Define a HEALPix at the current depth hp = HEALPix(nside=(1 << depth), order='nested', frame=ICRS()) # Get the lon and lat of the corners of the pixels # intersecting the polygon lon, lat = hp.boundaries_lonlat(ipixels, step=1) lon = lon.to(u.rad).value lat = lat.to(u.rad).value # closes the lon and lat array so that their first and last value matches lon = self._closes_numpy_2d_array(lon) lat = self._closes_numpy_2d_array(lat) num_ipix_inter_poly = ipixels.shape[0] # Define a 3d numpy array containing the corners coordinates of the intersecting pixels # The first dim is the num of ipixels # The second is the number of coordinates (5 as it defines the closed polygon of a HEALPix cell) # The last is of size 2 (lon and lat) shapes = np.vstack((lon.ravel(), lat.ravel())).T.reshape(num_ipix_inter_poly, 5, -1) ipix_in_polygon_l = [] ipix_inter_polygon_l = [] for i in range(num_ipix_inter_poly): shape = shapes[i] # Definition of a SphericalPolygon from the border coordinates of a HEALPix cell ipix_shape = SphericalPolygon.from_radec(lon=shape[:, 0], lat=shape[:, 1], degrees=False) ipix = ipixels[i] if self.polygon.intersects_poly(ipix_shape): # If we are at the max depth then we direcly add to the MOC the intersecting ipixels if depth == end_depth: ipix_in_polygon_l.append(ipix) else: # Check whether polygon contains ipix or not if self.polygon_contains_ipix(ipix_shape): ipix_in_polygon_l.append(ipix) else: # The ipix is just intersecting without being contained in the polygon # We split it in its 4 children child_ipix = ipix << 2 ipix_inter_polygon_l.extend([child_ipix, child_ipix + 1, child_ipix + 2, child_ipix + 3]) self.ipix_d.update({str(depth): ipix_in_polygon_l}) ipixels = np.asarray(ipix_inter_polygon_l)