proplot: Slower speed of saving plotted Geographic data with cartopy

Description

I’m plotting large datasets using proplot (0.9.5.post78) and cartopy (0.20.0). The speed is much slower than the pyplot one.

Steps to reproduce

import time
import numpy as np
import proplot as pplt
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

import warnings
warnings.filterwarnings('ignore')

offset = -40
lon = np.linspace(offset, 360 + offset - 1, 3000)
lat = np.linspace(-60, 60 + 1, 500)
state = np.random.RandomState(51423)
data = state.rand(len(lat), len(lon))

def proplot_test():
    start = time.time()
    fig, axs = pplt.subplots(proj='stere', figsize=(4,4))
    axs.coastlines()
    axs.pcolormesh(lon, lat, data, cmap='viridis')
    end = time.time()
    print('proplot plot cost: ', end - start)
    fig.savefig('test_proplot.jpg', dpi=300)
    save_end = time.time()
    print('proplot save cost: ', save_end - end)

def pyplot_test():
    start = time.time()
    fig, ax = plt.subplots(figsize=(4,4), subplot_kw=dict(projection=ccrs.Stereographic()))
    ax.coastlines()
    ax.pcolormesh(lon, lat, data, cmap='viridis', transform=ccrs.PlateCarree())
    end = time.time()
    print('pyplot plot cost: ', end - start)
    fig.savefig('test_pyplot.jpg', dpi=300)
    save_end = time.time()
    print('pyplot save cost: ', save_end - end)

proplot_test()
pyplot_test()

Expected behavior: [What you expected to happen]

The speed is similar with pyplot.

Actual behavior: [What actually happened]

proplot plot cost:  2.1709158420562744
proplot save cost:  5.2430949211120605

pyplot plot cost:  1.9175093173980713
pyplot save cost:  1.4209530353546143

In jupyterlab, the cost of plotting data by proplot is 7s while the pyplot one is 3.7s. I suppose this is the same problem of saving figures, because jupyter notebook needs to show the figure inline.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17

Commits related to this issue

Most upvoted comments

Ok cool. Yep in your first example cartopy wasn’t having to transform anything at all (because the default is native map coordinates rather than longitude-latitude), so it was faster. Keep in mind proplot’s only dependency is matplotlib (no specific version) so your proj version differences aren’t due to proplot – something else is going on.

I also figured out that the speedup shown above is only relevant for cartopy plots. This fix seems obvious because it is obvious – matplotlib’s Axes.get_tightbbox() already skips artists that are bounded by the subplot edge, however its method for skipping them (for some reason) fails with cartopy artists, while my method (for some reason) succeeds. May submit a cartopy PR at some point. Relevant lines:

https://github.com/matplotlib/matplotlib/blob/9765379ce6e7343070e815afc0988874041b98e2/lib/matplotlib/axes/_base.py#L4646-L4657

Great! Not so much a “bug” just a limitation of how “tight layout” is calculated – in order to get the positions of every object in the subplot (and, thus, ensure the subplots are sufficiently separated to prevent overlapping content), we have to draw every object in the subplot. Then, in order to save or display the figure, we have to draw the objects again using the relevant backend. However, it could probably be massively improved by skipping objects that are “clipped” by the subplot edges (i.e., skipping objects with obj.get_clip_on() set to True). I’ll experiment with this for the next version.