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

incompatibilities with matplotlib 3.4 #248

Closed scottstanie closed 3 years ago

scottstanie commented 3 years ago

Description

(Updating this issue from original problem). It seems that matplotlib 3.4 has changed some of their internals that proplot was relying on, and now several things are broken.

  1. proplot throws an error on import. I believe it's from using a private method of matplotlib.cbook: _suppress_matplotlib_deprecation_warning is not longer present.

Here's the 3.3.x code: https://github.com/matplotlib/matplotlib/blob/v3.3.x/lib/matplotlib/cbook/__init__.py#L31-L36

Now in 3.4.x that method is gone: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/cbook/__init__.py

Also, it looks like cbook is being entirely deprecated: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/cbook/deprecation.py

I'm not sure if we need the line https://github.com/lukelbd/proplot/blob/master/proplot/config.py#L1097 that uses cbook, as it appears to be the only place it's used and is just suppressing a warning. If it's not needed, I could submit a PR removing that line.

  1. I attempted to remove that line in a fork, but get a new error when doing pplt.subplots(): AttributeError: 'CartesianAxesSubplot' object has no attribute '_subplotspec'

I'm not sure how actively maintained the repo is, so it might be good to place a warning/upper limit on MPL version until the changes are made.

Steps to reproduce

A "Minimal, Complete and Verifiable Example" will make it much easier for maintainers to help you.

import proplot

Expected behavior: [What you expected to happen]

Actual behavior: [What actually happened]

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-560ed637e72e> in <module>
----> 1 import proplot

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/__init__.py in <module>
      6 # In the future we will not import the class names
      7 import pkg_resources as _pkg
----> 8 from .config import *  # noqa: F401 F403
      9 from .internals import timers
     10 with timers._benchmark('imports'):

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/config.py in <module>
   1569 
   1570 with timers._benchmark('rc'):
-> 1571     _ = RcConfigurator()
   1572 
   1573 #: Instance of `RcConfigurator`. This is used to change global settings.

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/config.py in __init__(self, local, user, default)
    238         """
    239         self._context = []
--> 240         self.reset(local=local, user=user, default=default)
    241 
    242     def __enter__(self):

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/config.py in reset(self, local, user, default)
    803         # NOTE: see _remove_blacklisted_style_params bugfix
    804         if default:
--> 805             rc_matplotlib.update(_get_style_dicts('original', filter=False))
    806             rc_matplotlib.update(rcsetup._rc_matplotlib_default)
    807             rc_proplot.update(rcsetup._rc_proplot_default)

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/config.py in _get_style_dicts(style, infer, filter)
   1151 
   1152     # Always apply the default style *first* so styles are rigid
-> 1153     kw_matplotlib = _get_default_dict()
   1154     if style == 'default' or style is mpl.rcParamsDefault:
   1155         return kw_matplotlib

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/config.py in _get_default_dict()
   1093     # filter them out. Beware if hidden attribute changes.
   1094     rcdict = _get_filtered_dict(mpl.rcParamsDefault, warn=False)
-> 1095     with cbook._suppress_matplotlib_deprecation_warning():
   1096         rcdict = dict(RcParams(rcdict))
   1097     for attr in ('_deprecated_remain_as_none', '_deprecated_set'):

AttributeError: module 'matplotlib.cbook' has no attribute '_suppress_matplotlib_deprecation_warning'
  1. After fix:
    
    import proplot as pplt
    pplt.subplots()
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-9-80deb9bcdb53> in <module>
    ----> 1 pplt.subplots()

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/ui.py in subplots(array, ncols, nrows, ref, order, aspect, figsize, width, height, journal, axwidth, axheight, hspace, wspace, space, hratios, wratios, width_ratios, height_ratios, left, bottom, right, top, basemap, proj, projection, proj_kw, projection_kw, kwargs) 562 subplotspec = gridspec[y0:y1 + 1, x0:x1 + 1] 563 with fig._context_authorize_add_subplot(): --> 564 axs[idx] = fig.add_subplot( 565 subplotspec, number=num, main=True, 566 axes_kw[num]

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/figure.py in add_subplot(self, *args, *kwargs) 1047 'unexpected behavior. Please use "proplot.subplots()" instead.' 1048 ) -> 1049 return super().add_subplot(args, **kwargs) 1050 1051 def auto_layout(self, renderer=None, resize=None, aspect=None, tight=None):

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/matplotlib/figure.py in add_subplot(self, *args, kwargs) 779 projection_class, pkw = self._process_projection_requirements( 780 *args, *kwargs) --> 781 ax = subplot_class_factory(projection_class)(self, args, pkw) 782 key = (projection_class, pkw) 783 return self._add_axes_internal(ax, key)

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/matplotlib/axes/_subplots.py in init(self, fig, *args, kwargs) 34 """ 35 # _axes_class is set in the subplot_class_factory ---> 36 self._axes_class.init(self, fig, [0, 0, 1, 1], kwargs) 37 # This will also update the axes position. 38 self.set_subplotspec(SubplotSpec._from_subplot_args(fig, args))

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/axes/cartesian.py in init(self, *args, *kwargs) 213 """ 214 # Impose default formatter --> 215 super().init(args, **kwargs) 216 formatter = pticker.AutoFormatter() 217 self.xaxis.set_major_formatter(formatter)

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/axes/base.py in init(self, number, main, *args, **kwargs) 306 # Automatic axis sharing and formatting 307 # TODO: Instead of format() call specific setters --> 308 self._auto_share_setup() 309 self.format(rc_mode=1) # mode == 1 applies the custom proplot params 310

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/axes/base.py in _auto_share_setup(self) 355 # NOTE: This can get very repetitive, but probably minimal impact? 356 # Share x axes --> 357 parent, *children = self._get_extent_axes('x') 358 for child in children: 359 child._sharex_setup(parent)

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/axes/base.py in _get_extent_axes(self, x, panels) 387 idx = 0 if x == 'x' else 1 388 argfunc = np.argmax if x == 'x' else np.argmin --> 389 irange = self._range_gridspec(x) 390 if panels: 391 axs = self.figure._iter_axes(hidden=False, children=False)

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/proplot/axes/base.py in _range_gridspec(self, x) 534 if not hasattr(self, 'get_subplotspec'): 535 raise RuntimeError('Axes is not a subplot.') --> 536 ss = self.get_subplotspec() 537 if hasattr(ss, 'get_active_rows_columns'): 538 func = ss.get_active_rows_columns

~/opt/anaconda3/envs/mapping/lib/python3.8/site-packages/matplotlib/axes/_subplots.py in get_subplotspec(self) 65 def get_subplotspec(self): 66 """Return the .SubplotSpec instance associated with the subplot.""" ---> 67 return self._subplotspec 68 69 def set_subplotspec(self, subplotspec):

AttributeError: 'CartesianAxesSubplot' object has no attribute '_subplotspec'



### Proplot version

Python 3.8,
proplot version 0.6.4
zxdawn commented 3 years ago

I got another error when using matplotlib 3.4.1:

>>> import proplot as plot
/yin_raid/xin/miniconda3/envs/test_proplot/lib/python3.8/site-packages/proplot/config.py:1454: ProPlotWarning: Rebuilding font cache.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/yin_raid/xin/miniconda3/envs/test_proplot/lib/python3.8/site-packages/proplot/__init__.py", line 8, in <module>
    from .config import *  # noqa: F401 F403
  File "/yin_raid/xin/miniconda3/envs/test_proplot/lib/python3.8/site-packages/proplot/config.py", line 1568, in <module>
    register_fonts()
  File "/yin_raid/xin/miniconda3/envs/test_proplot/lib/python3.8/site-packages/proplot/config.py", line 1459, in register_fonts
    mfonts.json_dump(mfonts.fontManager, mfonts._fmcache)
AttributeError: module 'matplotlib.font_manager' has no attribute '_fmcache'
tacaswell commented 3 years ago

The following (in addition to matplotlib/matplotlib#20403) pplt.subplots() to work again (but it seems to not handle the initial draw with hi-dpi correctly).

diff --git a/proplot/axes/base.py b/proplot/axes/base.py
index a728c085..96763309 100644
--- a/proplot/axes/base.py
+++ b/proplot/axes/base.py
@@ -188,7 +188,7 @@ Returns
 """

-class Axes(maxes.Axes):
+class Axes(maxes.Subplot):
     """
     Lowest-level axes subclass. Handles titles and axis
     sharing. Adds several new methods and overrides existing ones.
diff --git a/proplot/config.py b/proplot/config.py
index 7223ab59..b55d7e7c 100644
--- a/proplot/config.py
+++ b/proplot/config.py
@@ -1094,7 +1094,7 @@ def _get_default_dict():
     # WARNING: Some deprecated rc params remain in dictionary as None so we
     # filter them out. Beware if hidden attribute changes.
     rcdict = _get_filtered_dict(mpl.rcParamsDefault, warn=False)
-    with cbook._suppress_matplotlib_deprecation_warning():
+    with cbook._api.suppress_matplotlib_deprecation_warning():
         rcdict = dict(RcParams(rcdict))
     for attr in ('_deprecated_remain_as_none', '_deprecated_set'):
         if hasattr(mpl, attr):  # _deprecated_set is in matplotlib before v3
@@ -1426,6 +1426,7 @@ def register_fonts():

     To visualize the registered fonts, use `~proplot.demos.show_fonts`.
     """
+    return
     # Find proplot fonts
     # WARNING: If you include a font file with an unrecognized style,
     # matplotlib may use that font instead of the 'normal' one! Valid styles:
diff --git a/proplot/constructor.py b/proplot/constructor.py
index 0df27018..62a7ad63 100644
--- a/proplot/constructor.py
+++ b/proplot/constructor.py
@@ -132,7 +132,7 @@ FORMATTERS = {  # note default LogFormatter uses ugly e+00 notation
     'logit': mticker.LogitFormatter,
     'eng': mticker.EngFormatter,
     'percent': mticker.PercentFormatter,
-    'index': mticker.IndexFormatter,
+    # 'index': mticker.IndexFormatter,
     'e': partial(pticker.FracFormatter, symbol=r'$e$', number=np.e),
     'pi': partial(pticker.FracFormatter, symbol=r'$\pi$', number=np.pi),
     'tau': partial(pticker.FracFormatter, symbol=r'$\tau$', number=2 * np.pi),
diff --git a/proplot/figure.py b/proplot/figure.py
index 85e84924..bd86c05d 100644
--- a/proplot/figure.py
+++ b/proplot/figure.py
@@ -88,10 +88,10 @@ def _canvas_preprocessor(canvas, method):
         # and displaying within inline notebook backend (previously worked around
         # this by forcing additional draw() call in this function before proceeding
         # with print_figure). Solution is to use _state_context with _cachedRenderer.
-        fallback = _not_none(fig._fallback_to_cm, rc['mathtext.fallback_to_cm'])
-        rc_context = rc.context({'mathtext.fallback_to_cm': fallback})
+        # fallback = _not_none(fig._fallback_to_cm, rc['mathtext.fallback_to_cm'])
+        # rc_context = rc.context({'mathtext.fallback_to_cm': fallback})
         fig_context = fig._context_preprocessing(cache=(method != 'print_figure'))
-        with rc_context, fig_context:
+        with fig_context:
             fig.auto_layout()
             result = func(self, *args, **kwargs)
         return result
rvalenzuelar commented 3 years ago

I got this error with the following versions:

# Name                    Version                   Build  Channel
matplotlib                3.4.2                    pypi_0    pypi
proplot                   0.6.4                    pypi_0    pypi

However, these versions are working fine:

# Name                    Version                   Build  Channel
matplotlib                3.1.1                    py37h54f8f79_0
matplotlib-base           3.1.3                   py37h9aa3819_0   
proplot                   0.6.4                    <pip>
lukelbd commented 3 years ago

Hi @scottstanie @tacaswell, thanks for your examples. #251 should fix all of the 3.3 and 3.4-related deprecation warnings and errors.

Sorry for the wait -- I took some time off of proplot to focus on my PhD (the first year of proplot development took up an enormous amount of my time). Now that I'm caught up I plan to develop proplot at a more measured pace going forward.

tacaswell commented 3 years ago

I decided to take some time off of proplot to focus on my lagging PhD

Good plan! While it has been observed that the scientific Python stack is built on the ashes of failed academic careers, please do take care of your self professionally.

scottstanie commented 3 years ago

No need to apologize! thanks for putting all the effort into the library, and glad to hear you found a better balance 👍