Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show grid ticks on geographic plots #227

Open
zxdawn opened this issue Sep 26, 2020 · 4 comments · May be fixed by #253
Open

Show grid ticks on geographic plots #227

zxdawn opened this issue Sep 26, 2020 · 4 comments · May be fixed by #253
Labels
Milestone

Comments

@zxdawn
Copy link

zxdawn commented Sep 26, 2020

Description

Currently, only grid_lines is supported for geographic plots.
It would be useful to add the grid_ticks for cleaner plot.

Steps to reproduce

import proplot as plot

fig, axs = plot.subplots(proj='cyl')
axs.format(land=True,
           labels=True,
           lonlines=20,
           latlines=20,
           gridminor=True,
           lonlim=(-140, 60),
           latlim=(-10, 50))

Expected behavior: [What you expected to happen]

Ticks without gridlines.

I found one example showing ticks with Gridlines:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter

dlon, dlat = 60, 30
xticks = np.arange(0, 360.1, dlon)
yticks = np.arange(-90, 90.1, dlat)

fig = plt.figure(figsize=(6,5))
ax = fig.add_subplot(1,1,1, projection=ccrs.PlateCarree(central_longitude=180))
ax.coastlines() #海岸线

gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False,linewidth=1, linestyle=':', color='k', alpha=0.8)
gl.xlocator = mticker.FixedLocator(xticks)
gl.ylocator = mticker.FixedLocator(yticks)

ax.set_xticks(xticks, crs=ccrs.PlateCarree())
ax.set_yticks(yticks, crs=ccrs.PlateCarree())

ax.xaxis.set_major_formatter(LongitudeFormatter(zero_direction_label=True))
ax.yaxis.set_major_formatter(LatitudeFormatter())

image

Actual behavior: [What actually happened]
Can't let ticks show.
test_tick

Proplot version

0.6.4

@zxdawn
Copy link
Author

zxdawn commented Sep 26, 2020

This method of retrieving gridline ticks may be useful for adding the function:

# create grid
gridliner = ax.gridlines(draw_labels=True)

# we need to draw the figure, such that the gridlines are populated
fig.canvas.draw()   

ysegs = gridliner.yline_artists[0].get_segments()
yticks = [yseg[0,1] for yseg in ysegs]

xsegs = gridliner.xline_artists[0].get_segments()
xticks = [xseg[0,0] for xseg in xsegs]

print(xticks)
print(yticks)
[-180.0, -120.0, -60.0, 0.0, 60.0, 120.0]
[-80.0, -60.0, -40.0, -20.0, 0.0, 20.0, 40.0, 60.0, 80.0, 100.0]

@lukelbd lukelbd linked a pull request Jun 30, 2021 that will close this issue
@lukelbd
Copy link
Collaborator

lukelbd commented Jul 12, 2021

You can monitor #253 for updates

Please also note the padding you see in that example is a cartopy bug confusing "pixels" with "points". It was fixed in SciTools/cartopy#1556. You can upgrade to cartopy v0.19 to get nicely-padded labels or play with ax.format(labelpad=N).

@lukelbd lukelbd added this to the Version 0.10 milestone Jul 21, 2021
@kM-Stone
Copy link

Hi, maybe try ax.format(labels = False)first, then use ax.set_xticks([0, 60, 120, 180, 240, 300, 360], crs=ccrs.PlateCarree()) to specify tick lines explicitly. It worked for me with Version 0.6.4.

import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import matplotlib.pyplot as plt
import proplot as pplt

# plt.figure(figsize=(8, 10))
fig, ax1 = pplt.subplots(proj=ccrs.PlateCarree(central_longitude=180),width=5)

ax1.coastlines()

lon_formatter = LongitudeFormatter(zero_direction_label=True)
lat_formatter = LatitudeFormatter()
ax1.xaxis.set_major_formatter(lon_formatter)
ax1.yaxis.set_major_formatter(lat_formatter)

ax1.set_xticks([30, 60, 120, 180, 240, 300, 350], crs=ccrs.PlateCarree())
ax1.set_yticks([0, 20, 40], crs=ccrs.PlateCarree())

ax1.tick_params(which='minor',direction='out',length=3,width=1,)
ax1.tick_params(which='major',direction='out', length=5, width=1, colors='k',)

ax1.format(land=True,
        #    labels=True,
           gridminor=True,
           lonlim=(-140, 60),
           latlim=(-10, 50))

output

@syrte
Copy link

syrte commented Jan 14, 2022

kM-Stone's solution does not work properly for some other projections such as 'gnom'.

---> 16 ax1.set_xticks([30, 60, 120, 180, 240, 300, 350], crs=ccrs.PlateCarree())
     17 ax1.set_yticks([0, 20, 40], crs=ccrs.PlateCarree())
     18 

~/local/conda/envs/myenv/lib/python3.8/site-packages/cartopy/mpl/geoaxes.py in set_xticks(self, ticks, minor, crs)
    986                                    (ccrs._RectangularProjection,
    987                                     ccrs.Mercator)):
--> 988                 raise RuntimeError('Cannot handle non-rectangular coordinate '
    989                                    'systems.')
    990             proj_xyz = self.projection.transform_points(crs,

RuntimeError: Cannot handle non-rectangular coordinate systems.

I found a temporary workaround for general projections. I put it here in case it is helpful for anyone.

import numpy as np
import proplot as pplt


def add_ticks(ax, labelpad=None):
    """Only works for major ticks on the left and bottom."""
    ax.grid(False)
    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
    ax.format(labelpad=labelpad)
    ax.figure.canvas.draw_idle()  # necessary for generating xlabel_artists...

    for gl in ax._gridliners:
        xy = np.array([t.get_position() for t in gl.bottom_label_artists if t.get_visible()])
        if xy.any():
            ax.set_xticks(xy[:, 0])
            ax.set_xticklabels([])

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


fig = pplt.figure(span=False, suptitle='Example')
ax = fig.subplot(111, 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,
          )
add_ticks(ax)

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants