Skip to content

Instantly share code, notes, and snippets.

@syrte
Last active January 16, 2022 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syrte/5773809e1f596aa7afdccb0c08c5e9a9 to your computer and use it in GitHub Desktop.
Save syrte/5773809e1f596aa7afdccb0c08c5e9a9 to your computer and use it in GitHub Desktop.
Sky map with proplot
import numpy as np
import proplot as pplt
from matplotlib import pyplot as plt
import cartopy.geodesic


def add_ticks(ax, labelpad=None):
    """
    Only works for major ticks on the left and bottom.
    """
    ax.grid(False)  # prevent redundancy grids
    ax.tick_params('both', which='major', size=pplt.rc['tick.len'])
    if labelpad is None:
        labelpad = pplt.rc['tick.len'] + 2

    for gl in ax._gridliners:
        gl.xpadding = gl.ypadding = labelpad  # for gridliners initialized outside ax.format
    ax.format(labelpad=labelpad)

    ax.figure.canvas.draw_idle()  # necessary for generating xlabel_artists...
    for gl in ax._gridliners:
        tk = np.array([t.get_position()[0] for t in gl.bottom_label_artists if t.get_visible()])
        if tk.any():
            ax.set_xticks(tk)
            ax.set_xticklabels([])

        tk = np.array([t.get_position()[1] for t in gl.left_label_artists if t.get_visible()])
        if tk.any():
            ax.set_yticks(tk)
            ax.set_yticklabels([])


def add_label(ax, xlabel=None, ylabel=None, xlabelpad=13, ylabelpad=13):
    if xlabel:
        ax.xaxis.set_visible(True)  # cartopy sets this to False
        ax.set_xlabel(xlabel, labelpad=xlabelpad)
    if ylabel:
        ax.yaxis.set_visible(True)
        ax.set_ylabel(ylabel, labelpad=ylabelpad)


def add_circle(ax, lon, lat, radius, npts=100, **kwargs):
    """
    lon, lat:
        center
    radius:
        in unit of rad
    """
    pts = cartopy.geodesic.Geodesic(1, 0).circle(lon=lon, lat=lat, radius=radius)
    return ax.fill(*pts.T, transform=pplt.PlateCarree(), **kwargs)


fig = pplt.figure(span=False, suptitle='Example')

ax = fig.subplot(121, proj='gnom', proj_kw={'lon_0': 0, 'lat_0': 45})
ax.format(lonlim=(-20, 20), latlim=(30, 60),
          labels=True, grid=True, gridminor=True,
          lonlocator=np.arange(-50, 50, 5), latlocator=5,
          latformatter="simple", lonformatter="simple",
          )
add_ticks(ax)
add_label(ax, xlabel='ra', ylabel='dec')
add_circle(ax, lon=15, lat=55, radius=0.2, fc='lightblue', alpha=0.5)

x = np.random.uniform(-10, 10, 100)
y = np.random.uniform(40, 60, 100)
ax.scatter(x, y, s=20)


ax2 = fig.subplot(122)
ax2.format(xlim=(-20, 20), ylim=(-20, 20),
           xlabel='xdata', ylabel='ydata')

Result

image

@syrte
Copy link
Author

syrte commented Jan 14, 2022

The gnomonic projection (proj='gnom') is suitable for visualizing small zoomed-in patches.
adopted by e.g., https://lscsoft.docs.ligo.org/ligo.skymap/plot/allsky.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment