Closed riley-brady closed 3 months ago
I get this error when I call pplt.figure()
:(
AttributeError: 'Figure' object has no attribute '_cachedRenderer'
Matplotlib v3.8.3 Python 3.11.8
Hi Kyle @chudlerk! Thanks for pointing this out. I was just trying to get the package to import but clearly didn't do any testing. It's hard to capture the depth of dependency issues here until https://github.com/proplot-dev/proplot/pull/413 is merged.
Might need to defer to @lukelbd on this, since he has a better idea of what this _cachedRenderer
does. It looks like it was dropped starting with 3.6.0
. See https://matplotlib.org/stable/api/prev_api_changes/api_changes_3.6.0.html#renderer-optional-for-get-tightbbox-and-get-window-extent.
They do have a Figure._get_renderer()
that seems to have replaced the cached renderer.
There's two spots in proplot
this needs to be addressed.
Under figure.py
, Figure._get_renderer()
. That just copies the call from matplotlib
's tight_layout
, which seemingly was deprecated at 3.6. This method might be able to check matplotlib
version and say <3.6
use that block, otherwise just run Figure._get_renderer()
from matplotlib.Figure
.
Under figure.py
, Figure._context_adjusting()
:
def _context_adjusting(self, cache=True):
"""
Prevent re-running auto layout steps due to draws triggered by figure
resizes. Otherwise can get infinite loops.
"""
kw = {'_is_adjusting': True}
if not cache:
kw['_cachedRenderer'] = None # temporarily ignore it
return context._state_context(self, **kw)
I'm less sure of what's going on here and how this needs to be modified for more recent versions.
@lukelbd , I gave it a little bit of a try today and can't really figure out what the renderer stuff is doing. I have it turned on so you can push commits directly to this if you'd like to try this weekend.
@chudlerk I've found success on my work stack just pinning matplotlib==3.5.3
and that will jive with all the most recent xarray/xclim/dask/metpy, etc. etc. If you do these small import fixes from this PR with that I think it's a good temporary solution.
Thanks Riley @riley-brady! I've got a working environment also by pinning matplotlib that way. At one point I think I had some issues with newer versions of python not working with the old matplotlib version. But everything is working fine with 3.9.
I was getting some weird errors with:
python==3.10.13
matplotlib==3.4.3
proplot==0.9.7
cartopy=0.22
Where cartopy
was throwing an error related to packaging.version
. It only seemed to resolve by bumping matplotlib
to 3.5.3. Was able to keep python at 3.10.13 this way. Not sure how that matplotlib
version impacted it, because the packaging
version and python version was fixed.
Hello, I had the same issue with cmap_d
and locally modified the code in a similar way as shown above. It imports fine, but the I also got the _cachedRenderer
error. So I modified the line in proplot
'sfigure.py
:
if self._cachedRenderer:
renderer = self._cachedRenderer
to
if hasattr(self,'_cachedRenderer') and self._cachedRenderer:
renderer = self._cachedRenderer
I was testing some example code:
fig,axs = pplt.subplots(nrows=1,ncols=1)
axs.scatter([0,2,3,4],[1,2,4,2])
but now I get a new error:
ValueError: 'Fire' is not a valid value for cmap; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
Unfortunately I can't use matplotlib==3.5.3
since I have another package that requires matplotlib>=3.6.0
.
Has anyone found a workaround for this?
@reemagit , in the meantime you can just use a different colormap from that list. It looks like Fire
is the default and not being registered. Just pass in cmap='viridis'
to scatter.
In the meantime:
cmaps
folder with Fire.json
in it. (My pathing is e.g. ~/miniforge3/envs/<conda_env_name>/lib/python3.10/site-packages/proplot
). If there is a cmaps folder with Fire.json
in it, that means that with the modern matplotlib
version it's just not registering the custom ones correctly.proplot/colors.py
. See the changes in this PR. If you haven't implemented those -- try them out. You just need to make sure that database = mcm._gen_cmap_registry()
creates the proper colormap registry with Fire.json
included.Thanks for the suggestions. With the PR changes and using the standard colormaps it seems to work.
I tried understanding why it wouldn't load the colormaps. Posting what I understood below in case it can be useful:
I checked and the 'Fire.json' file exists, and proplot is able to load it. However it doesn't get loaded in the global ColormapRegistry so it throws an error. I think this is because the line in matplotlib mpl._api.check_in_list(sorted(mpl.cm._colormaps)
checks if Fire
exists in mpl.cm._colormaps
, but in the corrected code we add the colormap database to setattr(mcm, attr, database)
, with attr
being either "_cmap_registry" or "cmap_d". So at the end of the proplot
's _init_cmap_database
function I changed it to
#setattr(mcm, attr, database) # Line that I removed
setattr(mcm, '_colormaps', database)
setattr(mpl, 'colormaps', mcm._colormaps)
In this way the Database is loaded in the global mpl.colormaps
and 'mcm._colormaps' objects.
Even after doing this, it still wouldn't find the 'Fire' colormap. Then I saw that the matplotlib.colormaps
contained the 'fire' colormap (lowercase). As I found out, the ColormapDatabase
is not case-sensitive when requesting a colormap, so it works regardless. However, the function checking if 'Fire' exists uses
_api.check_in_list(sorted(_colormaps), name=name)
The sorted
functions converts the keys of _colormaps to a list, and so it becomes case-sensitive. So the final solution was to just call the "fire" (lowercase) colormap, and it would work. So the final solution if one wants to use the proplot
's colormaps is to change the lines above and always specify the lowercase name.
Not sure if my workaround introduced other issues, but it seems to be working so far. Hope this helps.
Works for me on Python 3.11.5 (main, Sep 11 2023, 08:31:25) [Clang 14.0.6 ] on darwin
and
matplotlib 3.8.3
matplotlib-inline 0.1.6
!
Works for me on
Python 3.11.5 (main, Sep 11 2023, 08:31:25) [Clang 14.0.6 ] on darwin
andmatplotlib 3.8.3
matplotlib-inline 0.1.6
!
Is this with @reemagit's fixes? Have you tried plotting some stuff? PR head will only fix imports, but not plotting.
I installed from the commit c0bf6b6b8ec047e302eea78631942467575e75cb and plotting works without an issue on my end.
matplotlib 3.8.4
proplot 1.0.4
I tried
import matplotlib.pyplot as plt
import numpy as np
import proplot as pplt
x = y = np.linspace(-1.0, 1.0, 50)
values = np.random.rand(x.size, y.size)
fig, ax = pplt.subplots()
ax.pcolormesh(x, y, values.T, cmap="fire")
plt.show()
and got the following error:
Traceback (most recent call last):
File "/Users/46h/repo/proplot-test/test/test_plot_2d.py", line 9, in <module>
fig, ax = pplt.subplots(ncols=2, nrows=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/ui.py", line 232, in subplots
axs = fig.add_subplots(*args, rc_kw=rc_kw, **kwsubs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/figure.py", line 1407, in add_subplots
return self._add_subplots(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/figure.py", line 1170, in _add_subplots
axs[idx] = self.add_subplot(ss, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/figure.py", line 1393, in add_subplot
return self._add_subplot(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/figure.py", line 1063, in _add_subplot
ax = super().add_subplot(ss, _subplot_spec=ss, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/figure.py", line 782, in add_subplot
ax = projection_class(self, *args, **pkw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/46h/repo/proplot-test/proplot/axes/cartesian.py", line 343, in __init__
super().__init__(*args, **kwargs)
File "/Users/46h/repo/proplot-test/proplot/axes/plot.py", line 1279, in __init__
super().__init__(*args, **kwargs)
File "/Users/46h/repo/proplot-test/proplot/axes/base.py", line 828, in __init__
self._apply_auto_share()
File "/Users/46h/repo/proplot-test/proplot/axes/base.py", line 1397, in _apply_auto_share
child._sharey_setup(parent)
File "/Users/46h/repo/proplot-test/proplot/axes/cartesian.py", line 640, in _sharey_setup
self._sharey_limits(sharey)
File "/Users/46h/repo/proplot-test/proplot/axes/cartesian.py", line 583, in _sharey_limits
self.get_shared_y_axes().join(self, sharey) # share limit/scale changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'GrouperView' object has no attribute 'join'. Did you mean: 'joined'?
I updated this line to self.sharey(sharey)
and it worked. I don't have any issue with colormaps.
Running
fig, ax = pplt.subplots()
in JupyterLab throws the cached renderer error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File [~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/pyplot.py:197](http://localhost:8888/~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/pyplot.py#line=196), in _draw_all_if_interactive()
195 def _draw_all_if_interactive() -> None:
196 if matplotlib.is_interactive():
--> 197 draw_all()
File [~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/_pylab_helpers.py:132](http://localhost:8888/~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/_pylab_helpers.py#line=131), in Gcf.draw_all(cls, force)
130 for manager in cls.get_all_fig_managers():
131 if force or manager.canvas.figure.stale:
--> 132 manager.canvas.draw_idle()
File [~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/backend_bases.py:1893](http://localhost:8888/~/miniconda3/envs/proplot-test/lib/python3.11/site-packages/matplotlib/backend_bases.py#line=1892), in FigureCanvasBase.draw_idle(self, *args, **kwargs)
1891 if not self._is_idle_drawing:
1892 with self._idle_draw_cntx():
-> 1893 self.draw(*args, **kwargs)
File [~/repo/proplot-test/proplot/figure.py:463](http://localhost:8888/~/repo/proplot-test/proplot/figure.py#line=462), in _add_canvas_preprocessor.<locals>._canvas_preprocess(self, *args, **kwargs)
461 ctx3 = rc.context(fig._render_context) # draw with figure-specific setting
462 with ctx1, ctx2, ctx3:
--> 463 fig.auto_layout()
464 return func(self, *args, **kwargs)
File [~/repo/proplot-test/proplot/figure.py:1443](http://localhost:8888/~/repo/proplot-test/proplot/figure.py#line=1442), in Figure.auto_layout(self, renderer, aspect, tight, resize)
1440 # *Impossible* to get notebook backend to work with auto resizing so we
1441 # just do the tight layout adjustments and skip resizing.
1442 gs = self.gridspec
-> 1443 renderer = self._get_renderer()
1444 if aspect is None:
1445 aspect = True
File [~/repo/proplot-test/proplot/figure.py:891](http://localhost:8888/~/repo/proplot-test/proplot/figure.py#line=890), in Figure._get_renderer(self)
887 def _get_renderer(self):
888 """
889 Get a renderer at all costs. See matplotlib's tight_layout.py.
890 """
--> 891 if self._cachedRenderer:
892 renderer = self._cachedRenderer
893 else:
AttributeError: 'Figure' object has no attribute '_cachedRenderer'
But running
fig, ax = pplt.subplots()
plt.show()
works just fine.
It seems to work if I delete the if statement above.
There still seems to be a cmap registry issue but only for scatter plots.
x = np.random.uniform(size=(500, 2))
fig, ax = pplt.subplots()
ax.scatter(x[:, 0], x[:, 1])
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[15], line 4
1 x = np.random.uniform(size=(500, 2))
3 fig, ax = pplt.subplots()
----> 4 ax.scatter(x[:, 0], x[:, 1])
File [~/repo/proplot-test/proplot/internals/inputs.py:296](http://localhost:8888/~/repo/proplot-test/proplot/internals/inputs.py#line=295), in _preprocess_or_redirect.<locals>._decorator.<locals>._preprocess_or_redirect(self, *args, **kwargs)
293 ureg.setup_matplotlib(True)
295 # Call main function
--> 296 return func(self, *args, **kwargs)
File [~/repo/proplot-test/proplot/axes/plot.py:3271](http://localhost:8888/~/repo/proplot-test/proplot/axes/plot.py#line=3270), in PlotAxes.scatter(self, *args, **kwargs)
3267 """
3268 %(plot.scatter)s
3269 """
3270 kwargs = _parse_vert(default_vert=True, **kwargs)
-> 3271 return self._apply_scatter(*args, **kwargs)
File [~/repo/proplot-test/proplot/axes/plot.py:3239](http://localhost:8888/~/repo/proplot-test/proplot/axes/plot.py#line=3238), in PlotAxes._apply_scatter(self, xs, ys, ss, cc, vert, **kwargs)
3237 for _, n, x, y, s, c, kw in self._iter_arg_cols(xs, ys, ss, cc, **kw):
3238 kw['s'], kw['c'] = s, c # make _parse_cycle() detect these
-> 3239 kw = self._parse_cycle(n, cycle_manually=cycle_manually, **kw)
3240 *eb, kw = self._add_error_bars(x, y, vert=vert, default_barstds=True, **kw)
3241 *es, kw = self._add_error_shading(x, y, vert=vert, color_key='c', **kw)
File [~/repo/proplot-test/proplot/axes/plot.py:2346](http://localhost:8888/~/repo/proplot-test/proplot/axes/plot.py#line=2345), in PlotAxes._parse_cycle(self, ncycle, cycle, cycle_kw, cycle_manually, return_cycle, **kwargs)
2344 props[prop] = key
2345 if props:
-> 2346 dict_ = next(parser.prop_cycler)
2347 for prop, key in props.items():
2348 value = dict_[prop]
AttributeError: '_process_plot_var_args' object has no attribute 'prop_cycler'
fig, ax = pplt.subplots()
ax.scatter(x[:, 0], x[:, 1], c="black")
ValueError: 'fire' is not a valid value for cmap
fig, ax = pplt.subplots()
ax.scatter(x[:, 0], x[:, 1], c=np.linspace(0.0, 1.0, x.shape[0]), cmap="viridis")
ValueError: 'fire' is not a valid value for cmap
It works if you change the rc param:
pplt.rc["cmap.sequential"] = "viridis"
fig, ax = pplt.subplots()
ax.scatter(x[:, 0], x[:, 1], c=np.linspace(0.0, 1.0, x.shape[0]), cmap="fire")
@lukelbd are you able to resolve this into a minor patch release? I think we have most of what we need here to get it working. You know the ins and outs of proplot
and matplotlib
well enough to pull this together pretty quickly hopefully.
Using both of your latest commits 0af21cffe23556b354940fe5c0e713a605c7ff3a and c0bf6b6b8ec047e302eea78631942467575e75cb
python==3.11.5
matplotlib==3.8.4
I get this error when running in a jupyter notebook.
import matplotlib
import proplot as pplt
import numpy as np
matplotlib.use("Agg")
state = np.random.RandomState(51423)
fig = pplt.figure(share=False, refwidth=2.3)
# Colorbars
ax = fig.subplot(121, title="Axes colorbars")
data = state.rand(10, 10)
m = ax.heatmap(data, cmap="dusk")
ax.colorbar(m, loc="r", cmap="viridis")
ax.colorbar(m, loc="t" , cmap="viridis") # title is automatically adjusted
ax.colorbar(m, loc="ll", label="colorbar label", cmap="viridis") # inset colorbar demonstration
# Legends
ax = fig.subplot(122, title="Axes legends", titlepad="0em")
data = (state.rand(10, 5) - 0.5).cumsum(axis=0)
hs = ax.plot(data, lw=3, labels=list("abcde"))
ax.legend(loc="ll", label="legend label") # automatically infer handles and labels
ax.legend(hs, loc="t", ncols=5, frame=False) # automatically infer labels from handles
ax.legend(hs, list("jklmn"), loc="r", ncols=1, frame=False) # manually override labels
fig.format(
abc=True,
xlabel="xlabel",
ylabel="ylabel",
suptitle="Colorbar and legend location demo",
)
fig.savefig("testproplot.png")
The error
ValueError Traceback (most recent call last)
Cell In[1], [line 14](vscode-notebook-cell:?execution_count=1&line=14)
[12](vscode-notebook-cell:?execution_count=1&line=12) data = state.rand(10, 10)
[13](vscode-notebook-cell:?execution_count=1&line=13) m = ax.heatmap(data, cmap="dusk")
---> [14](vscode-notebook-cell:?execution_count=1&line=14) ax.colorbar(m, loc="r", cmap="viridis")
[15](vscode-notebook-cell:?execution_count=1&line=15) ax.colorbar(m, loc="t" , cmap="viridis") # title is automatically adjusted
[16](vscode-notebook-cell:?execution_count=1&line=16) ax.colorbar(m, loc="ll", label="colorbar label", cmap="viridis") # inset colorbar demonstration
....
ValueError: 'Fire' is not a valid value for cmap; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Grays', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_grey', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gist_yerg', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'grey', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
Note that without
import matplotlib
matplotlib.use("Agg")
I get
ImportError: Cannot load backend 'TkAgg' which requires the 'tk' interactive framework, as 'headless' is currently running
Any tips would be much appreciated.
@Migelo adding pplt.rc["cmap.sequential"] = "viridis"
at the beginning of the script removes the colormap error for me. But then it throws the error:
File [~/miniconda3/envs/ment-flow/lib/python3.11/site-packages/proplot/axes/base.py:2614], in Axes.get_tightbbox(self, renderer, *args, **kwargs)
2612 self._apply_title_above()
2613 if self._colorbar_fill:
-> 2614 self._colorbar_fill.update_ticks(manual_only=True) # only if needed
2615 if self._inset_parent is not None and self._inset_zoom:
2616 self.indicate_inset_zoom()
TypeError: Colorbar.update_ticks() got an unexpected keyword argument 'manual_only'
I don't have any issues with colorbars when using ax.pcolormesh
, so that could be a solution for now?
Unfortunately I just don't know this package too well end-to-end nor matplotlib
. So I did a very hacky fix and haven't been able to try to dig into this since.
@austin-hoover thx for the fix. Same here.
My example works with matplotlib==3.5.3
but breaks with matplotlib==3.6.0
.
File "/freya/ptmp/mpa/mihac/athenaruns/halo_profiles/testproplot.py", line 18, in <module>
ax.colorbar(m, loc="r", cmap="viridis")
File "/freya/ptmp/mpa/mihac/proplot/proplot/axes/base.py", line 2781, in colorbar
return self._add_colorbar(mappable, values, loc=loc, align=align, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/freya/ptmp/mpa/mihac/proplot/proplot/internals/warnings.py", line 110, in _deprecate_kwargs_wrapper
return func_orig(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/freya/ptmp/mpa/mihac/proplot/proplot/axes/base.py", line 1150, in _add_colorbar
obj.minorlocator = minorlocator # backwards compatibility
^^^^^^^^^^^^^^^^
File "/u/mihac/.pyenv/versions/proplot/lib/python3.11/site-packages/matplotlib/colorbar.py", line 438, in minorlocator
self._long_axis().set_minor_locator(loc)
File "/u/mihac/.pyenv/versions/proplot/lib/python3.11/site-packages/matplotlib/axis.py", line 1816, in set_minor_locator
_api.check_isinstance(mticker.Locator, locator=locator)
File "/u/mihac/.pyenv/versions/proplot/lib/python3.11/site-packages/matplotlib/_api/__init__.py", line 93, in check_isinstance
raise TypeError(
TypeError: 'locator' must be an instance of matplotlib.ticker.Locator, not a None
To clarify, I am running my edits here successfully with:
matplotlib==3.5.3
xarray==2024.2.0
pandas==2.2.1
numpy==1.23.5
To name a few core packages. I spent a few mind-numbing days working on a standard analytics environment. I can't remember at this point who was driving up matplotlib
versioning. Some packages are really eager with their lower-bound matplotlib
version.
I fixed my problem in https://github.com/riley-brady/proplot/pull/1
@Migelo and @austin-hoover , just merged your commit into here. I was just having problems again with proplot
, even on this updated PR. I seemingly have to lock matplotlib
at 3.5.3
for this to work at all. Which is problematic since 3.5.3
doesn't work with python 3.11.
Great thx! What exactly is giving you issues, I'm happy to look.
@Migelo , I'm getting the dreaded colormap registry issue.
import proplot
import xarray as xr
data = xr.DataArray([[1,2,3],[1,2,3]])
data.plot()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[4], line 1
----> 1 data.plot()
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/xarray/plot/accessor.py:48, in DataArrayPlotAccessor.__call__(self, **kwargs)
46 @functools.wraps(dataarray_plot.plot, assigned=("__doc__", "__annotations__"))
47 def __call__(self, **kwargs) -> Any:
---> 48 return dataarray_plot.plot(self._da, **kwargs)
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/xarray/plot/dataarray_plot.py:309, in plot(darray, row, col, col_wrap, ax, hue, subplot_kws, **kwargs)
305 plotfunc = hist
307 kwargs["ax"] = ax
--> 309 return plotfunc(darray, **kwargs)
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/xarray/plot/dataarray_plot.py:1627, in _plot2d.<locals>.newplotfunc(***failed resolving arguments***)
1625 if add_labels and "label" not in cbar_kwargs:
1626 cbar_kwargs["label"] = label_from_attrs(darray)
-> 1627 cbar = _add_colorbar(primitive, ax, cbar_ax, cbar_kwargs, cmap_params)
1628 elif cbar_ax is not None or cbar_kwargs:
1629 # inform the user about keywords which aren't used
1630 raise ValueError(
1631 "cbar_ax and cbar_kwargs can't be used with add_colorbar=False."
1632 )
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/xarray/plot/utils.py:724, in _add_colorbar(primitive, ax, cbar_ax, cbar_kwargs, cmap_params)
721 cbar_kwargs.pop("extend")
723 fig = ax.get_figure()
--> 724 cbar = fig.colorbar(primitive, **cbar_kwargs)
726 return cbar
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/figure.py:1280, in FigureBase.colorbar(self, mappable, cax, ax, use_gridspec, **kwargs)
1276 NON_COLORBAR_KEYS = ['fraction', 'pad', 'shrink', 'aspect', 'anchor',
1277 'panchor']
1278 cb_kw = {k: v for k, v in kwargs.items() if k not in NON_COLORBAR_KEYS}
-> 1280 cb = cbar.Colorbar(cax, mappable, **cb_kw)
1282 if not userax:
1283 self.sca(current_ax)
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/_api/deprecation.py:384, in delete_parameter.<locals>.wrapper(*inner_args, **inner_kwargs)
379 @functools.wraps(func)
380 def wrapper(*inner_args, **inner_kwargs):
381 if len(inner_args) <= name_idx and name not in inner_kwargs:
382 # Early return in the simple, non-deprecated case (much faster than
383 # calling bind()).
--> 384 return func(*inner_args, **inner_kwargs)
385 arguments = signature.bind(*inner_args, **inner_kwargs).arguments
386 if is_varargs and arguments.get(name):
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/colorbar.py:384, in Colorbar.__init__(self, ax, mappable, cmap, norm, alpha, values, boundaries, orientation, ticklocation, extend, spacing, ticks, format, drawedges, filled, extendfrac, extendrect, label, location)
381 spine.set_visible(False)
382 self.outline = self.ax.spines['outline'] = _ColorbarSpine(self.ax)
--> 384 self.dividers = collections.LineCollection(
385 [],
386 colors=[mpl.rcParams['axes.edgecolor']],
387 linewidths=[0.5 * mpl.rcParams['axes.linewidth']],
388 clip_on=False)
389 self.ax.add_collection(self.dividers)
391 self._locator = None
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/collections.py:1409, in LineCollection.__init__(self, segments, zorder, **kwargs)
1407 # Unfortunately, mplot3d needs this explicit setting of 'facecolors'.
1408 kwargs.setdefault('facecolors', 'none')
-> 1409 super().__init__(
1410 zorder=zorder,
1411 **kwargs)
1412 self.set_segments(segments)
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/_api/deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
448 if len(args) > name_idx:
449 warn_deprecated(
450 since, message="Passing the %(name)s %(obj_type)s "
451 "positionally is deprecated since Matplotlib %(since)s; the "
452 "parameter will become keyword-only %(removal)s.",
453 name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/collections.py:157, in Collection.__init__(self, edgecolors, facecolors, linewidths, linestyles, capstyle, joinstyle, antialiaseds, offsets, offset_transform, norm, cmap, pickradius, hatch, urls, zorder, **kwargs)
97 """
98 Parameters
99 ----------
(...)
154 :doc:`/gallery/misc/zorder_demo` for all defaults and examples.
155 """
156 artist.Artist.__init__(self)
--> 157 cm.ScalarMappable.__init__(self, norm, cmap)
158 # list of un-scaled dash patterns
159 # this is needed scaling the dash pattern by linewidth
160 self._us_linestyles = [(0, None)]
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/cm.py:400, in ScalarMappable.__init__(self, norm, cmap)
398 self.set_norm(norm) # The Normalize instance of this ScalarMappable.
399 self.cmap = None # So that the setter knows we're initializing.
--> 400 self.set_cmap(cmap) # The Colormap instance of this ScalarMappable.
401 #: The last colorbar associated with this ScalarMappable. May be None.
402 self.colorbar = None
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/cm.py:585, in ScalarMappable.set_cmap(self, cmap)
576 """
577 Set the colormap for luminance data.
578
(...)
581 cmap : `.Colormap` or str or None
582 """
583 in_init = self.cmap is None
--> 585 self.cmap = _ensure_cmap(cmap)
586 if not in_init:
587 self.changed()
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/cm.py:723, in _ensure_cmap(cmap)
720 cmap_name = cmap if cmap is not None else mpl.rcParams["image.cmap"]
721 # use check_in_list to ensure type stability of the exception raised by
722 # the internal usage of this (ValueError vs KeyError)
--> 723 _api.check_in_list(sorted(_colormaps), cmap=cmap_name)
724 return mpl.colormaps[cmap_name]
File ~/miniforge3/envs/analysis_py311/lib/python3.11/site-packages/matplotlib/_api/__init__.py:131, in check_in_list(_values, _print_supported_values, **kwargs)
129 if _print_supported_values:
130 msg += f"; supported values are {', '.join(map(repr, values))}"
--> 131 raise ValueError(msg)
ValueError: 'Fire' is not a valid value for cmap; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
Hi everyone,
Thanks a lot for tackling the update on proplot to make it functional again. I really love proplot, it's an awesome package that really helped me through my PhD (1000s of kudos to @lukelbd) and it's of course when you can't use it anymore that you realize how much you miss it. And whenever I talk about it to friends, they look at the documentation and systematically say some thing along the lines of "I've been looking for something like that for ages, that would change my life if I could use it". So I wanted to help a bit with the maintenance.
I'm pretty much stuck at the same place as you all are, all the corrections that @riley-brady, @austin-hoover and @Migelo have implemented in this pull request make proplot work for me (see packages versions below), except that I get that colormap error if I don't specify pplt.rc["cmap.sequential"] = "viridis"
. Funny enough, it still plots the figure I want with the "Fire" colormap... I tried to dig further and decorticate the colors.py file with no success. I just can't figure out where proplot specify the list of new cmap to add to the ColormapDatabase. But anyway, I don't think that's the issue.
In a jupyter notebook, using the following code, I get no error:
import xarray as xr
import proplot as pplt
ds = xr.tutorial.load_dataset('air_temperature')
f, axs = pplt.subplots()
axs.pcolormesh(ds.air.isel(time=100),cmap='Fire')
But if I instead replace the last line by:
ds.air.isel(time=100).plot(ax =axs,cmap='Fire')
I do get that "Fire" colormap error (while still having the correct figure). Note that if I specify another colormap such as viridis
in the plot call, I still get the fire error!
From there, I am tempted to suggest the following scenario:
matplotlib
does not know of the updated list of colormaps and doesn't care, yet uses the rcParam for the colormap. It does some test to check the cmap name (hence the error), then proplot takes over and changes the colormap eventually. What baffles me is why would a pplt.rc parameter be used by matplotlib even if we do not want that default parameter to be used. And why it wasn't throwing an error earlier, if that's the case. Does proplot overwrite the matplotlib rc parameters? If so, when and where? Can we then also specify a change in the matplotlib colormap database, to include the proplot and seaborn colormaps from the beginning? I'll try to dig in that direction.
If you have any clue on whether this is a good path to follow or not, I'm happy to hear! Once again, thanks for the hard work!
On my fork, the issue comes when adding a colorbar and not specifying pplt.rc["cmap.sequential"] = "viridis"
. Without colorbar, everything works. Both of your examples work when I add the colorbar rcparam. I'm assuming xarray is calling ax.colorbar
.
import numpy as np
import proplot as pplt
pplt.rc["grid"] = False
data = np.arange(100).reshape(10, 10)
fig, ax = pplt.subplots()
m = ax.pcolormesh(data, discrete=False);
import numpy as np
import proplot as pplt
pplt.rc["grid"] = False
data = np.arange(100).reshape(10, 10)
fig, ax = pplt.subplots()
m = ax.pcolormesh(data, discrete=False)
ax.colorbar(m);
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[1], line 9
7 fig, ax = pplt.subplots()
8 m = ax.pcolormesh(data, discrete=False)
----> 9 ax.colorbar(m);
File [~/repo/proplot-fork/proplot/axes/base.py:2786](http://localhost:8888/lab/workspaces/~/repo/proplot-fork/proplot/axes/base.py#line=2785), in Axes.colorbar(self, mappable, values, loc, location, **kwargs)
2784 self._register_guide('colorbar', (mappable, values), (loc, align), **kwargs)
2785 else:
-> 2786 return self._add_colorbar(mappable, values, loc=loc, align=align, **kwargs)
File [~/repo/proplot-fork/proplot/internals/warnings.py:110](http://localhost:8888/lab/workspaces/~/repo/proplot-fork/proplot/internals/warnings.py#line=109), in _rename_kwargs.<locals>._decorator.<locals>._deprecate_kwargs_wrapper(*args, **kwargs)
105 key_new = key_new.format(value)
106 _warn_proplot(
107 f'Keyword {key_old!r} was deprecated in version {version} and may '
108 f'be removed in {_next_release()}. Please use {key_new!r} instead.'
109 )
--> 110 return func_orig(*args, **kwargs)
File [~/repo/proplot-fork/proplot/axes/base.py:1151](http://localhost:8888/lab/workspaces/~/repo/proplot-fork/proplot/axes/base.py#line=1150), in Axes._add_colorbar(self, mappable, values, loc, align, space, pad, width, length, shrink, label, title, reverse, rotation, grid, edges, drawedges, extend, extendsize, extendfrac, ticks, locator, locator_kw, format, formatter, ticklabels, formatter_kw, minorticks, minorlocator, minorlocator_kw, tickminor, ticklen, ticklenratio, tickdir, tickdirection, tickwidth, tickwidthratio, ticklabelsize, ticklabelweight, ticklabelcolor, labelloc, labellocation, labelsize, labelweight, labelcolor, c, color, lw, linewidth, edgefix, rasterized, **kwargs)
1146 minorlocator = AutoLocator()
1148 # Create colorbar and update ticks and axis direction
1149 # NOTE: This also adds the guides._update_ticks() monkey patch that triggers
1150 # updates to DiscreteLocator when parent axes is drawn.
-> 1151 obj = cax._colorbar_fill = cax.figure.colorbar(
1152 mappable, cax=cax, ticks=locator, format=formatter,
1153 drawedges=grid, extendfrac=extendfrac, **kwargs
1154 )
1155 obj.minorlocator = minorlocator # backwards compatibility
1156 obj.update_ticks = guides._update_ticks.__get__(obj) # backwards compatible
File [~/repo/proplot-fork/proplot/figure.py:1658](http://localhost:8888/lab/workspaces/~/repo/proplot-fork/proplot/figure.py#line=1657), in Figure.colorbar(self, mappable, values, loc, location, row, col, rows, cols, span, space, pad, width, **kwargs)
1656 if cax is not None:
1657 with context._state_context(cax, _internal_call=True): # do not wrap pcolor
-> 1658 cb = super().colorbar(mappable, cax=cax, **kwargs)
1659 # Axes panel colorbar
1660 elif ax is not None:
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/figure.py:1310](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/figure.py#line=1309), in FigureBase.colorbar(self, mappable, cax, ax, use_gridspec, **kwargs)
1306 cax.grid(visible=False, which='both', axis='both')
1308 NON_COLORBAR_KEYS = [ # remove kws that cannot be passed to Colorbar
1309 'fraction', 'pad', 'shrink', 'aspect', 'anchor', 'panchor']
-> 1310 cb = cbar.Colorbar(cax, mappable, **{
1311 k: v for k, v in kwargs.items() if k not in NON_COLORBAR_KEYS})
1312 cax.figure.stale = True
1313 return cb
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/colorbar.py:377](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/colorbar.py#line=376), in Colorbar.__init__(self, ax, mappable, cmap, norm, alpha, values, boundaries, orientation, ticklocation, extend, spacing, ticks, format, drawedges, extendfrac, extendrect, label, location)
374 spine.set_visible(False)
375 self.outline = self.ax.spines['outline'] = _ColorbarSpine(self.ax)
--> 377 self.dividers = collections.LineCollection(
378 [],
379 colors=[mpl.rcParams['axes.edgecolor']],
380 linewidths=[0.5 * mpl.rcParams['axes.linewidth']],
381 clip_on=False)
382 self.ax.add_collection(self.dividers)
384 self._locator = None
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/collections.py:1438](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/collections.py#line=1437), in LineCollection.__init__(self, segments, zorder, **kwargs)
1436 # Unfortunately, mplot3d needs this explicit setting of 'facecolors'.
1437 kwargs.setdefault('facecolors', 'none')
-> 1438 super().__init__(
1439 zorder=zorder,
1440 **kwargs)
1441 self.set_segments(segments)
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/collections.py:156](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/collections.py#line=155), in Collection.__init__(self, edgecolors, facecolors, linewidths, linestyles, capstyle, joinstyle, antialiaseds, offsets, offset_transform, norm, cmap, pickradius, hatch, urls, zorder, **kwargs)
96 """
97 Parameters
98 ----------
(...)
153 :doc:`[/gallery/misc/zorder_demo](http://localhost:8888/gallery/misc/zorder_demo)` for all defaults and examples.
154 """
155 artist.Artist.__init__(self)
--> 156 cm.ScalarMappable.__init__(self, norm, cmap)
157 # list of un-scaled dash patterns
158 # this is needed scaling the dash pattern by linewidth
159 self._us_linestyles = [(0, None)]
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py:416](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py#line=415), in ScalarMappable.__init__(self, norm, cmap)
414 self.set_norm(norm) # The Normalize instance of this ScalarMappable.
415 self.cmap = None # So that the setter knows we're initializing.
--> 416 self.set_cmap(cmap) # The Colormap instance of this ScalarMappable.
417 #: The last colorbar associated with this ScalarMappable. May be None.
418 self.colorbar = None
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py:605](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py#line=604), in ScalarMappable.set_cmap(self, cmap)
596 """
597 Set the colormap for luminance data.
598
(...)
601 cmap : `.Colormap` or str or None
602 """
603 in_init = self.cmap is None
--> 605 self.cmap = _ensure_cmap(cmap)
606 if not in_init:
607 self.changed()
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py:744](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/cm.py#line=743), in _ensure_cmap(cmap)
741 # use check_in_list to ensure type stability of the exception raised by
742 # the internal usage of this (ValueError vs KeyError)
743 if cmap_name not in _colormaps:
--> 744 _api.check_in_list(sorted(_colormaps), cmap=cmap_name)
745 return mpl.colormaps[cmap_name]
File [~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/_api/__init__.py:129](http://localhost:8888/lab/workspaces/~/miniconda3/envs/proplot-fork/lib/python3.11/site-packages/matplotlib/_api/__init__.py#line=128), in check_in_list(values, _print_supported_values, **kwargs)
127 if _print_supported_values:
128 msg += f"; supported values are {', '.join(map(repr, values))}"
--> 129 raise ValueError(msg)
ValueError: 'Fire' is not a valid value for cmap; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Grays', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_grey', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gist_yerg', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'grey', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
import numpy as np
import proplot as pplt
pplt.rc["grid"] = False
pplt.rc["cmap.sequential"] = "viridis"
data = np.arange(100).reshape(10, 10)
fig, ax = pplt.subplots()
m = ax.pcolormesh(data, discrete=False, cmap="fire")
ax.colorbar(m);
Idk I'm confused. The colormaps are available from matplotlib.cm upon import, without changing rc.
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import proplot as pplt
cm.get_cmap("fire")
However plt.get_cmap("fire")
throws an error. I guess the colorbar function passes the default cmap to matplotlib.cm._ensure_cmap
, which throws an error if outside default cmaps. Then later proplot is providing the custom cmap to the colorbar function.
@lukelbd can we just change the default cmap to "viridis" and merge these changes? That seems to fix remaining errors for now.
There also seems to have been an important change in matplotlib colormap API in 3.6 or 3.7, with a lot of deprecations, including for get_cmap
which will be removed in mpl 3.9: https://github.com/matplotlib/matplotlib/issues/20853
This wouldn't help for sure... I have tried to modify a bit the colors.py accordingly but without success yet. We might need to rethink the proplot colormap API to match those changes, as the matplotlib.cm
functions will eventually be removed. But that would require some in-depth changes, and a proper understanding of what is going on in there. Which I do not have. Making sure we have backward compatibility will also be a nightmare.
EDIT: in colors.py, in _init_cmap_database(), adding the following lines helps:
if _version_mpl >= '3.6':
if mpl.colormaps.register is not _register_cmap:
mpl.colormaps.register = _register_cmap
if mpl.colormaps.get_cmap is not _get_cmap:
mpl.colormaps.get_cmap = _get_cmap
else:
if mcm.get_cmap is not _get_cmap:
[...]
Then I can execute the following cell and get the proper colormap.
import xarray as xr
import matplotlib as mpl
import proplot as pplt
mpl.colormaps.get_cmap()
Same as you, except using the newest mpl colormaps API. Still get the colorbar issue, though.
Just for info, I tried to follow the chain of errors thrown by the 'fire' cmap issue. I think one of the issues comes from the matplotlib.cm.py
file, l. 238 (in latest version):
# public access to the colormaps should be via `matplotlib.colormaps`. For now,
# we still create the registry here, but that should stay an implementation
# detail.
_colormaps = ColormapRegistry(_gen_cmap_registry())
globals().update(_colormaps)
This last line declare the default list of cmap stored in _cm_listed.py
as the recognized list of cmap. From what I can understand, it basically calls this everytime the _ensure_cmap
method is called, which is the case when creating a cbar without a mappable. So it resets the list of _colormaps even when we changed it in proplot. I don't understand why the matplotlib developers opted for this method...
Unless they change this, I don't think we can circumvent this. So changing the default cmap to "viridis" as suggested by @austin-hoover seems the best (and only) way forward at the moment.
Indeed there is import error for matplotlib==3.9.0 related to this issue.
I'm not sure what more to do here, honestly. I haven't had the free time to dig deeply into this. We're currently locking a lot of packages at low versions at work to make this work, but at some point that won't be feasible.
Please anyone tag me with any branches off this PR with edits/any additional notes and edits I need to make to get over the hump with this PR. I'll see if I can try to get this merged from there.
I think this PR should be merged. I have proplot working with python 3.11.9 and
matplotlib==3.8.4 matplotlib-inline==0.1.7 numpy==2.0.0 xarray==2024.6.0
@lukelbd Hi Luke, we are really anticipating the new version of ProPlot, could you please spare some time to merge this PR?
I just updated the default cmap to Viridis I believe, and messaged Luke privately to see if I could get his eyes on this.
I just updated the default cmap to Viridis I believe, and messaged Luke privately to see if I could get his eyes on this.
Hi, thank you very much for the pull request. Unfortunately, I don't think that in the short term, the main developer will want to continue to refine proplot.
Perhaps we should combine our efforts https://github.com/cvanelteren/proplot/tree/mpl3.8.3
There are issues when using cartopy==0.23 and matplotlib==3.9 for geographic plotting. I attempted to fix them, and it was useful for me. However, there are still issues when plotting coastlines that I am currently unable to fix. my way is add _gridliners to class _CartopyAxes self._gridliners = [a for a in self.artists if isinstance(a, Gridliner)] and add self.axis_name='x'/‘y’ for _LonAxis and _LatAxis
Perhaps we should combine our efforts https://github.com/cvanelteren/proplot/tree/mpl3.8.3
@cvanelteren Have you made any headway on this? Anything separate from what I've incorporated here? Feel free to target this branch and tag me and I can merge into it.
Work has been insane for me lately. Lots of downsizing on my team so haven't been able to think about this at all. We've either version-locked everything to out-of-date environments to use proplot
or just dropped it from our newer environments.
I have connected with @lukelbd. He's similarly slammed with his postdoc. He mentioned he's aware of this and hoping to get a v0.10 release out this summer with the MPL compatibility changes. I let him know how much work/thought people are putting into it here, so hoping he can draw from this thread or advise on it.
Again, I'm happy to merge anything into this branch that people find works so folks can do an install targeted at this branch to get higher MPL versions to work before Luke can do a release.
I have made some headway and implemented some unittests of which this repo is in high need of. Unfortunately with the release of 3.9 there are breaking changes that overhauls the colormaps heavily. Haven't looked into these changes yet.
The unittests are key to ensure everything is working. There are plenty of examples in the proplot docs that we can leverage for this end. I think this step is crucial to prevent monkey patching it to work with future versions of mpl and ensure that the role of proplot is still warranted other than a mere mpl style that we could apply. Ofc this requires partly a vision from the original author rather than a mutiny ;-).
Yes definitely a big need for testing. @lukelbd said this is one of his main priorities. He had been working on that here: https://github.com/proplot-dev/proplot/pull/413.
It's tough in a package like this. Unit testing can only go so far. But you sort of need snapshot testing since you're ensuring that images align as expected. A healthy mix of both would be good.
Hopefully he has some breathing room from academia soon to do a focused effort here. Ideally a few of us can help contribute to get testing up to par. I think we need to set up a CI/CD with nightly testing against upstream package versions + have a suit of tests going along with that that just test against failures due to MPL/cartopy changes in particular.
Consolidating my ramble:
Outside of that it would be nice to release this package to a community org with a more broad set of merge permissions to help when Luke is too busy to focus on this for periods of time.
What's the best route here @cvanelteren? Do you want to just cherry pick anything I have here that you don't have and open a PR here on main targeting your branch? You can link to this thread here and we can continue discussion there. We bought a house and are getting married soon on top of the job craziness, so it's hard for me to drive the ship :) But once we get buy-in from Luke, I should hopefully be able to help a bit with testing stuff.
I think the best way forward would be to finish small meaningful tasks. In the long run it would be good to get a stable unitsuite going. I am aware of the branch you listed, but am more concerned with the lack of communication on @lukelbd's side. As it currently stands this package is loosing track of the latest changes and makes it harder for people to just install and run it. I think my branch (and perhaps this one too) monkey patches too much in. I would say let's focus on these unittests first so that we can after it, at least have a quicker turn around on what broke with the latest mpl patches. This does require however, @lukelbd to become atleast communicative on these PRs -- after all we cannot proceed to merge and make this package up-to-date without his blessing (and merge powers).
Have a look, if time permits, at the unittests I provided. MPL provides a nice way to do it out of the box.
Agreed on all of that.
I agree that we should avoid this conditional monkey patching. We could have a coordinated effort to just get a unit test suite set up with merge permissions. Then can use that to diagnose what's going on and see if we can get focused attention from Luke.
If you open up a targeted branch I should be able to do some light reviewing soon. I am gone all next week for my wedding. Once I'm back I should have more time to review/help with unit testing getting set up.
I can see if I can make a dent in the unittests -- now tracking this actively on https://github.com/proplot-dev/proplot/compare/master...cvanelteren:proplot:unittest
@riley-brady would be lovely if you can arrange this. Again no mutiny is intended -- I really like the place that this package has and would hate to see it go down ;-).
I have merged the unittests with mine and added some. I think this is a pretty good spot to move forward; will some thoughts about how to proceed in the coming week, perhaps getting some inspiration from mpl. Browsing through their source they don't do particularly sophisticated checks. Could use some input on how to test the internals further (if needed at all).
Awesome, thanks for pushing this forward!
Could you open a PR at https://github.com/cvanelteren/proplot/pulls or https://github.com/proplot-dev/proplot/pulls with your branch? I can't comment on https://github.com/proplot-dev/proplot/compare/master...cvanelteren:proplot:unittest without it being a targeted PR.
I have merged the unittests with mine and added some
Is this from @lukelbd's other branch or elsewhere? Just clarifying what you are merging in.
@riley-brady just added it #458. I will have a look at latest mpl to see what changed, then we can skip the intermediate versions for working towards a mpl 3.9.1 release.
EDIT: see #459
matplotlib==3.6.0
by leveraging_gen_cmap_registry()
to set up colormap database.matplotlib==3.8.3
by referencing hidden_fontconfig_pattern
module for setting up fontconfig parser.