proplot-dev / proplot

🎨 A succinct matplotlib wrapper for making beautiful, publication-quality graphics
https://proplot.readthedocs.io
MIT License
1.12k stars 103 forks source link

Axis sharing doesn't work for geo-axis #178

Closed zxdawn closed 4 years ago

zxdawn commented 4 years ago

Description

span and share don't work for geographic axis.

Steps to reproduce

import proplot as plot
f, axs = plot.subplots(nrows=2, ncols=2,
                       spany=3, sharey=3,
                       proj='lcc', proj_kw={'lon_0': 116}
                       )
axs.format(coast=True,
           latlines=1, lonlines=1,
           labels=True,
           lonlim=(113, 119),
           latlim=(37, 41.5),
           )

Expected behavior: matplotlib_shareproj

Lat labels are shared.

Actual behavior: cartopy_share

Equivalent steps in matplotlib

import matplotlib.pyplot as plt
import cartopy.crs as ccrs

proj = ccrs.LambertConformal(central_longitude=116)
fig, axs = plt.subplots(nrows=2, ncols=2,
                        subplot_kw={'projection': proj})

for idx,ax in enumerate(axs.flatten()):
    ax.set_extent([113, 119, 37, 41.5], ccrs.PlateCarree())
    gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                      color='gray', alpha=0.5, linestyle='--',
                      x_inline=False, y_inline=False)
    gl.xlabels_top = False
    gl.ylabels_right = False
    if idx%2 != 0:
        gl.ylabels_left = False
    ax.coastlines()

Proplot version

0.6.1

lukelbd commented 4 years ago

There's actually an open issue for this: #79

lukelbd commented 4 years ago

Might not get to #79 for a while because it's kind of a tricky problem (dealing with different projections, axis labels on different sides of the subplots, etc). But for the time being you can just toggle labels for the edge subplots like so:

import proplot as plot
f, axs = plot.subplots(
    nrows=2, ncols=2,
    spany=3, sharey=3,
    proj='lcc', proj_kw={'lon_0': 116}
)
axs.format(
    coast=True,
    latlines=1, lonlines=1,
    lonlim=(113, 119),
    latlim=(37, 41.5),
)
axs[:, 0].format(labels=True)
axs[-1, :].format(labels=True)
zxdawn commented 4 years ago

Nice trick. But, it would change the xtick label and ytick label at the same time.

I'm trying to get the gridline from the GeoAxes and set some to False:

import proplot as plot
f, axs = plot.subplots(
    nrows=2, ncols=2,
    spany=3, sharey=3,
    proj='lcc', proj_kw={'lon_0': 116}
)
axs.format(
    coast=True,
    latlines=1, lonlines=1,
    lonlim=(113, 119),
    latlim=(37, 41.5),
    labels=True,
)

axs[1].gridlines().left_labels = False

However, it doesn't work and the lines are thicker.

tick_label

lukelbd commented 4 years ago

My bad, you’re right. What you want is:

axs[:, 0].format(latlabels=True) axs[-1, :].format(lonlabels=True)

See the full documentation for GeoAxes.format() https://proplot.readthedocs.io/en/latest/api/proplot.axes.GeoAxes.format.html#proplot.axes.GeoAxes.format.

On May 24, 2020, at 7:56 PM, Xin Zhang notifications@github.com wrote:

Nice trick. But, it would change the xtick label and ytick label at the same time.

I'm trying to get the gridline from the GeoAxes and set some to False:

import proplot as plot f, axs = plot.subplots( nrows=2, ncols=2, spany=3, sharey=3, proj='lcc', proj_kw={'lon_0': 116} ) axs.format( coast=True, latlines=1, lonlines=1, lonlim=(113, 119), latlim=(37, 41.5), labels=True, )

axs[1].gridlines().left_labels = False However, it doesn't work and the lines are thicker.

https://user-images.githubusercontent.com/30388627/82771204-cf9cb900-9e6d-11ea-867c-4aad0a2f3ee9.png — You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/lukelbd/proplot/issues/178#issuecomment-633339501, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEV7HNBXJGYOEBOK54R3GRDRTHF3HANCNFSM4NIXNT2A.

zxdawn commented 4 years ago

Thanks, Luke!

It works well: labels

However the small space between tick and tick labels can't be changed using tick.pad and grid.pad.

lukelbd commented 4 years ago

I believe that issue is related to SciTools/cartopy#1556. The padding is dependent on the DPI of your saved PNG, because someone coded the padding as "dots" (pixels on your screen) instead of "points" (1/72 inches) in the cartopy source code. And proplot makes the default dpi for saved figures rc['savefig.dpi'] = 1200, much larger than the backend dpi rc['figure.dpi'] = 100, because 1200 dots per inch is recommended by most academic journals.

If you set the padding to a very large number, reduce the DPI with e.g. f.save('file.png', dpi=100), or save the file as PDF, this will change the padding.

Honesty if grid labels are important to you I recommend installing basemap and using basemap=True in your call to subplots(). Cartopy still has a lot of kinks to work out. For example:

proj = plot.Proj('lcc', lon_0=118, lonlim=(113, 119), latlim=(37, 42), basemap=True)
fig, axs = plot.subplots(ncols=2, nrows=2, proj=proj)
axs[:, 0].format(latlabels=True)
axs[-1, :].format(lonlabels=True)
...
zxdawn commented 4 years ago

Thanks! Hope that issue will be fixed soon.

The reason why I don't use Basemap is the KeyError: KeyError: 'PROJ_LIB'.

This problem doesn't exist in Linux Terminal, but shows up in the editor like sublime text and pycharm (stackoverflow link):

import os
os.environ["PROJ_LIB"] = '/home/xin/Software/miniconda3/envs/s5p/share/proj'
lukelbd commented 4 years ago

@zxdawn FYI SciTools/cartopy#1556 was just merged into cartopy's master branch