def plot(self, title='MOC', frame=None): """ Plot the MOC object using a mollweide projection. **Deprecated**: New `fill` and `border` methods produce more reliable results and allow you to specify additional matplotlib style parameters. Parameters ---------- title : str The title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ frame = ICRS() if frame is None else frame from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if self.max_order > plot_order: plotted_moc = self.degrade_to_order(plot_order) else: plotted_moc = self num_pixels_map = 1024 delta = 2. * np.pi / num_pixels_map x = np.arange(-np.pi, np.pi, delta) y = np.arange(-np.pi/2, np.pi/2, delta) lon_rad, lat_rad = np.meshgrid(x, y) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError("Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(nside2npix(1 << plotted_moc.max_order)) pix_id = plotted_moc._best_res_pixels() # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 z = np.flip(m[pix_map], axis=1) plt.figure(figsize=(10, 10)) ax = plt.subplot(111, projection="mollweide") ax.set_xticklabels(['150°', '120°', '90°', '60°', '30°', '0°', '330°', '300°', '270°', '240°', '210°', '180°']) color_map = LinearSegmentedColormap.from_list('w2r', ['#eeeeee', '#aa0000']) color_map.set_under('w') color_map.set_bad('gray') ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) ax.tick_params(labelsize=14, labelcolor='#000000') plt.title(title) plt.grid(True, linestyle='--', linewidth=1, color='#555555') plt.show()
def plot(self, title='MOC', frame=None): """ Plot the MOC object using a mollweide projection. **Deprecated**: New `fill` and `border` methods produce more reliable results and allow you to specify additional matplotlib style parameters. Parameters ---------- title : str The title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ import warnings warnings.warn('This method is deprecated and is no longer tested.' 'Please refer to this documentation page for plotting MOCs using' 'matplotlib: https://mocpy.readthedocs.io/en/latest/examples/examples.html#loading-and-plotting-the-moc-of-sdss', DeprecationWarning) frame = ICRS() if frame is None else frame from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if self.max_order > plot_order: plotted_moc = self.degrade_to_order(plot_order) else: plotted_moc = self num_pixels_map = 1024 delta = 2. * np.pi / num_pixels_map x = np.arange(-np.pi, np.pi, delta) y = np.arange(-np.pi/2, np.pi/2, delta) lon_rad, lat_rad = np.meshgrid(x, y) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError("Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(12*4**(plotted_moc.max_order)) pix_id = core.flatten_pixels(plotted_moc._interval_set._intervals, plotted_moc.max_order) # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 z = np.flip(m[pix_map], axis=1) plt.figure(figsize=(10, 10)) ax = plt.subplot(111, projection="mollweide") ax.set_xticklabels(['150°', '120°', '90°', '60°', '30°', '0°', '330°', '300°', '270°', '240°', '210°', '180°']) color_map = LinearSegmentedColormap.from_list('w2r', ['#eeeeee', '#aa0000']) color_map.set_under('w') color_map.set_bad('gray') ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) ax.tick_params(labelsize=14, labelcolor='#000000') plt.title(title) plt.grid(True, linestyle='--', linewidth=1, color='#555555') plt.show()
def _compute_graph_HEALPix_boundaries(depth, ipixels): def insert_edge(G, l1, l2, p1_lon, p1_lat, p2_lon, p2_lat): # Nodes are indexed by str(skycoord). When getting ordered nodes, one can retrieve back the skycoord instance # by accessing the python dict `pts_d`. try: # Avoid the special case where holes are touching to each other # 'x' belongs to the MOC # ' ' is part of the holes in the MOC # |xxx # |xxx # ---A--- # xxx| # xxx| # # If this case occurs we split the node A into 2. One is attached to the bottom left graph and the other to the # top right one. When computing the MST (minimal spanning tree) from a graph, we need our graphs to have # only nodes of degrees 1 or 2 (i.e. to be lines). if G.degree[l1] >= 2: l1 += '_' except: pass try: if G.degree[l2] >= 2: l2 += '_' except: pass # Set the skycoord instance as an attribute of the nodes G.add_node(l1, ra=p1_lon, dec=p1_lat) G.add_node(l2, ra=p2_lon, dec=p2_lat) G.add_edge(l1, l2) # Phase 1: Retrieve the ipixels located at the border of # this connexe MOC component ipixels = ipixels.astype(np.int) hp = HEALPix(nside=(1 << depth), order='nested', frame=ICRS()) neighbours = hp.neighbours(ipixels)[[0, 2, 4, 6], :] ipixels = ipixels.astype(np.uint64) neighbours = neighbours.astype(np.uint64) isin = np.isin(neighbours, ipixels) border = isin.sum(axis=0) < 4 ipixels_border = ipixels[border] isin_border = isin[:, border] # Phase 2: Build the graph from the positions of the ipixels boundaries #import cdshealpix as healpix #ipix_lon, ipix_lat = healpix.vertices(ipixels_border, depth) #ipix_lon[:, [1, 3]] = ipix_lon[:, [3, 1]] #ipix_lat[:, [1, 3]] = ipix_lat[:, [3, 1]] ipix_lon, ipix_lat = hp.boundaries_lonlat(ipixels_border, step=1) ipix_lon_deg = ipix_lon.to_value(u.deg) ipix_lat_deg = ipix_lat.to_value(u.deg) ipix_lon_repr = \ np.around(np.asarray(ipix_lon.reshape((1, -1))[0]), decimals=3).tolist() ipix_lat_repr = \ np.around(np.asarray(ipix_lat.reshape((1, -1))[0]), decimals=3).tolist() west_border = ~isin_border[0, :] south_border = ~isin_border[1, :] east_border = ~isin_border[2, :] north_border = ~isin_border[3, :] E = nx.Graph() for i in range(ipixels_border.shape[0]): lon_deg = ipix_lon_deg[i] lat_deg = ipix_lat_deg[i] p0_lon = lon_deg[0] p1_lon = lon_deg[1] p2_lon = lon_deg[2] p3_lon = lon_deg[3] p0_lat = lat_deg[0] p1_lat = lat_deg[1] p2_lat = lat_deg[2] p3_lat = lat_deg[3] off = 4*i off2 = 4*(i + 1) repr_lon = ipix_lon_repr[off:off2] repr_lat = ipix_lat_repr[off:off2] s0 = str(repr_lon[0]) + ' ' + str(repr_lat[0]) s1 = str(repr_lon[1]) + ' ' + str(repr_lat[1]) s2 = str(repr_lon[2]) + ' ' + str(repr_lat[2]) s3 = str(repr_lon[3]) + ' ' + str(repr_lat[3]) # WEST border if west_border[i]: insert_edge(E, s1, s2, p1_lon, p1_lat, p2_lon, p2_lat) # NORTH border if north_border[i]: insert_edge(E, s2, s3, p2_lon, p2_lat, p3_lon, p3_lat) # EAST border if east_border[i]: insert_edge(E, s3, s0, p3_lon, p3_lat, p0_lon, p0_lat) # SOUTH border if south_border[i]: insert_edge(E, s0, s1, p0_lon, p0_lat, p1_lon, p1_lat) return E
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)
def plot(self, title='MOC', frame=None): """ Plot the MOC object in a mollweide view This method uses matplotlib. Parameters ---------- title : str the title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ frame = ICRS() if frame is None else frame from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if self.max_order > plot_order: plotted_moc = self.degrade_to_order(plot_order) else: plotted_moc = self num_pixels_map = 1024 delta = 2 * np.pi / num_pixels_map x = np.arange(-np.pi, np.pi, delta) y = np.arange(-np.pi / 2, np.pi / 2, delta) lon_rad, lat_rad = np.meshgrid(x, y) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError( "Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(nside2npix(1 << plotted_moc.max_order)) pix_id_arr = plotted_moc._best_res_pixels() # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id_arr, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id_arr = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id_arr] = 1 z = np.flip(m[pix_map], axis=1) plt.figure(figsize=(10, 10)) ax = plt.subplot(111, projection="mollweide") ax.set_xticklabels([ '150°', '120°', '90°', '60°', '30°', '0°', '330°', '300°', '270°', '240°', '210°', '180°' ]) color_map = LinearSegmentedColormap.from_list('w2r', ['#eeeeee', '#aa0000']) color_map.set_under('w') color_map.set_bad('gray') ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) ax.tick_params(labelsize=14, labelcolor='#000000') plt.title(title) plt.grid(True, linestyle='--', linewidth=1, color='#555555') plt.show()
def _compute_graph_HEALPix_boundaries(depth, ipixels): def insert_edge(G, l1, l2, p1_lon, p1_lat, p2_lon, p2_lat): # Nodes are indexed by str(skycoord). When getting ordered nodes, one can retrieve back the skycoord instance # by accessing the python dict `pts_d`. try: # Avoid the special case where holes are touching to each other # 'x' belongs to the MOC # ' ' is part of the holes in the MOC # |xxx # |xxx # ---A--- # xxx| # xxx| # # If this case occurs we split the node A into 2. One is attached to the bottom left graph and the other to the # top right one. When computing the MST (minimal spanning tree) from a graph, we need our graphs to have # only nodes of degrees 1 or 2 (i.e. to be lines). if G.degree[l1] >= 2: l1 += '_' except: pass try: if G.degree[l2] >= 2: l2 += '_' except: pass # Set the skycoord instance as an attribute of the nodes G.add_node(l1, ra=p1_lon, dec=p1_lat) G.add_node(l2, ra=p2_lon, dec=p2_lat) G.add_edge(l1, l2) # Phase 1: Retrieve the ipixels located at the border of # this connexe MOC component ipixels = ipixels.astype(np.int) hp = HEALPix(nside=(1 << depth), order='nested', frame=ICRS()) neighbours = hp.neighbours(ipixels)[[0, 2, 4, 6], :] ipixels = ipixels.astype(np.uint64) neighbours = neighbours.astype(np.uint64) isin = np.isin(neighbours, ipixels) border = isin.sum(axis=0) < 4 ipixels_border = ipixels[border] isin_border = isin[:, border] # Phase 2: Build the graph from the positions of the ipixels boundaries #import cdshealpix as healpix #ipix_lon, ipix_lat = healpix.vertices(ipixels_border, depth) #ipix_lon[:, [1, 3]] = ipix_lon[:, [3, 1]] #ipix_lat[:, [1, 3]] = ipix_lat[:, [3, 1]] ipix_lon, ipix_lat = hp.boundaries_lonlat(ipixels_border, step=1) ipix_lon_deg = ipix_lon.to_value(u.deg) ipix_lat_deg = ipix_lat.to_value(u.deg) ipix_lon_repr = \ np.around(np.asarray(ipix_lon.reshape((1, -1))[0]), decimals=3).tolist() ipix_lat_repr = \ np.around(np.asarray(ipix_lat.reshape((1, -1))[0]), decimals=3).tolist() west_border = ~isin_border[0, :] south_border = ~isin_border[1, :] east_border = ~isin_border[2, :] north_border = ~isin_border[3, :] E = nx.Graph() for i in range(ipixels_border.shape[0]): lon_deg = ipix_lon_deg[i] lat_deg = ipix_lat_deg[i] p0_lon = lon_deg[0] p1_lon = lon_deg[1] p2_lon = lon_deg[2] p3_lon = lon_deg[3] p0_lat = lat_deg[0] p1_lat = lat_deg[1] p2_lat = lat_deg[2] p3_lat = lat_deg[3] off = 4*i off2 = 4*(i + 1) repr_lon = ipix_lon_repr[off:off2] repr_lat = ipix_lat_repr[off:off2] s0 = str(repr_lon[0]) + ' ' + str(repr_lat[0]) s1 = str(repr_lon[1]) + ' ' + str(repr_lat[1]) s2 = str(repr_lon[2]) + ' ' + str(repr_lat[2]) s3 = str(repr_lon[3]) + ' ' + str(repr_lat[3]) # WEST border if west_border[i]: insert_edge(E, s1, s2, p1_lon, p1_lat, p2_lon, p2_lat) # NORTH border if north_border[i]: insert_edge(E, s2, s3, p2_lon, p2_lat, p3_lon, p3_lat) # EAST border if east_border[i]: insert_edge(E, s3, s0, p3_lon, p3_lat, p0_lon, p0_lat) # SOUTH border if south_border[i]: insert_edge(E, s0, s1, p0_lon, p0_lat, p1_lon, p1_lat) return E
def my_plot(moc, frame=None, labels=False, title='', grid=False, save='', color='black', degrade=True): frame = Galactic() if frame is None else frame from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if moc.max_order > plot_order and degrade: plotted_moc = moc.degrade_to_order(plot_order) else: plotted_moc = moc num_pixels_map = 1024 delta = 2. * np.pi / num_pixels_map x = np.arange(-np.pi, np.pi, delta) y = np.arange(-np.pi / 2, np.pi / 2, delta) lon_rad, lat_rad = np.meshgrid(x, y) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError( "Only Galactic/ICRS coordinate systems are supported.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(12 * 4**(plotted_moc.max_order)) pix_id = core.flatten_pixels(plotted_moc._interval_set._intervals, plotted_moc.max_order) # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 z = np.flip(m[pix_map], axis=1) figsize = (12, 10) fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111, projection="aitoff") color_map = LinearSegmentedColormap.from_list('w2r', ['white', color]) color_map.set_under('w') color_map.set_bad('w') # Note I flip x ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) if labels: ax.tick_params(labelsize=14, labelcolor='#000000') if title: plt.title(title) if grid: plt.grid(True, linestyle='--', linewidth=1, color='#555555') ax.set_xticklabels([ '210', '240', '270', '300', '330', '0', '30', '60', '90', '120', '150' ]) ax.grid(grid) plt.tight_layout() if not labels: # disable tick labels ax.set_xticklabels([]) ax.set_yticklabels([]) if save: plt.savefig(save) else: plt.show()