proplot-dev / proplot

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

TwoSlopeNorm incompatible with proplot axes + xarray commands #404

Open zxdawn opened 1 year ago

zxdawn commented 1 year ago

Description

The TwoSlopeNorm doesn't work with proplot.

Steps to reproduce

import numpy as np
import proplot as pplt
from matplotlib.colors import TwoSlopeNorm
import xarray as xr

x, y = np.meshgrid(np.linspace(0,50,51), np.linspace(0,50,51))
z = np.linspace(-2,4,50*50).reshape(50,50)

newnorm = TwoSlopeNorm(vmin=-1, vcenter=0, vmax=3)

fig, axs = pplt.subplots()
xr.DataArray(z).plot(ax=axs, vmin=-1, vmax=3, norm=newnorm, cmap="RdBu_r", discrete=False)

Expected behavior:

image

Actual behavior:

image

Equivalent steps in matplotlib

# your code here, if applicable
import matplotlib.pyplot as plt

pc = plt.pcolormesh(x,y,z, norm=newnorm, cmap="RdBu_r")
plt.colorbar(pc)

Proplot version

Paste the results of import matplotlib; print(matplotlib.__version__); import proplot; print(proplot.version) here.

3.5.2
0.9.5.post332
lukelbd commented 1 year ago

This seems to be a conflict between xarray and proplot plotting utilities where vmin and vmax are not respected for TwoSlopeNorm... strange that the error does not seem to occur for other normalizers. (Edit: I found the error also occurs for proplot DivergingNorm -- so seems to be related to the handling of normalizers with a vcenter).

It appears that a workaround for now is to use ax.pcolor(z, ...) instead of z.plot(ax=ax, ...).

Xarray command (version 2022.3.0):

import numpy as np
import proplot as pplt
import matplotlib.colors as mcolors
import xarray as xr

x, y = np.meshgrid(np.linspace(0,50,51), np.linspace(0,50,51))
z = np.linspace(-2,4,50*50).reshape(50,50)
fig, ax = pplt.subplots()
norm = mcolors.TwoSlopeNorm(vcenter=0)
z = xr.DataArray(z)
z.plot(ax=ax, vmin=-1, vmax=3, norm=norm, cmap='burd')

iTerm2 AI80iU tmpt73_1uap

Proplot command (version 0.9.5.post339):

import numpy as np
import proplot as pplt
import matplotlib.colors as mcolors
import xarray as xr

x, y = np.meshgrid(np.linspace(0,50,51), np.linspace(0,50,51))
z = np.linspace(-2,4,50*50).reshape(50,50)
fig, ax = pplt.subplots()
norm = mcolors.TwoSlopeNorm(vcenter=0)
z = xr.DataArray(z)
ax.pcolor(z, vmin=-1, vmax=3, norm=norm, cmap='burd', discrete=False, colorbar='r', extend='both')

iTerm2 mV4wJk tmpx92pvdz3