Skip to content

Using theme_matplotlib() Raises AttributeError #1121

Description

@GrapesGoober

Problem

Hi all, I'm using Plotnine for a first time. Currently migrating my visualizations from matplotlib and I've played around with plotnine's heatmap.

I found a possible bug when running theme_matplotlib(). The plot works fine without theme_matplotlib(), but has a problem when I add theme_matplotlib() to the ggplot

Replicate

  • Using dependencies
    matplotlib==3.11.0
    plotnine==0.15.8
    
  • Run python via script mode (a *.py file, not *.ipynb)
    from plotnine import (
        aes,
        geom_tile,
        ggplot,
        theme_matplotlib,
    )
    from plotnine.data import faithfuld
    
    plot = (
        ggplot(faithfuld, aes("waiting", "eruptions", fill="density"))
        + geom_tile()
        + theme_matplotlib()
    )
    plot.show()
  • Expected outcome: a heatmap
  • Instead I got error
    (.venv) PS C:\Users\Grapes\Desktop\Workbench\plotnine-scripts> & c:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Scripts\python.exe c:/Users/Grapes/Desktop/Workbench/plotnine-scripts/run_theme_matplotlib.py
    Traceback (most recent call last):
      File "c:\Users\Grapes\Desktop\Workbench\plotnine-scripts\run_theme_matplotlib.py", line 16, in <module>
        plot.show()
        ~~~~~~~~~^^
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\plotnine\ggplot.py", line 193, in show
        self.draw(show=True)
        ~~~~~~~~~^^^^^^^^^^^
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\plotnine\ggplot.py", line 304, in draw
        with plot_context(self, show=show):
             ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\plotnine\_utils\context.py", line 74, in __enter__
        self.rc_context.__enter__()
        ~~~~~~~~~~~~~~~~~~~~~~~~~^^
      File "C:\Program Files\Python313\Lib\contextlib.py", line 141, in __enter__
        return next(self.gen)
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\matplotlib\__init__.py", line 1210, in rc_context
        rcParams.update(rc)
        ~~~~~~~~~~~~~~~^^^^
      File "<frozen _collections_abc>", line 987, in update
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\matplotlib\__init__.py", line 779, in __setitem__
        cval = valid_key(val)
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\matplotlib\rcsetup.py", line 310, in validate_backend
        if s is _auto_backend_sentinel or backend_registry.is_valid_backend(s):
                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
      File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\matplotlib\backends\registry.py", line 224, in is_valid_backend
        if not backend.startswith("module://"):
               ^^^^^^^^^^^^^^^^^^
    AttributeError: 'object' object has no attribute 'startswith'  
    

What I found

  • I dug around the plotnine source code locally a bit and found BackendRegistry.is_valid_backend method with the if-check
    if not backend.startswith("module://"):
        backend = backend.lower()
  • Here, the argument backend is expected to be string, but instead it is received an object, not str. This raised the exception. I added a bandaid fix on my local installation to trigger its intended error message instead.
    if not isinstance(backend, str):
        return False
    
    if not backend.startswith("module://"):
        backend = backend.lower()
  • Running the heatmap python script, I get this message instead.
    File "C:\Users\Grapes\Desktop\Workbench\plotnine-scripts\.venv\Lib\site-packages\matplotlib\__init__.py", line 781, in __setitem__
        raise ValueError(f"Key {key}: {ve}") from None
    ValueError: Key backend: '<object object at 0x000001E0483EF970>' is not a valid value for backend; supported values are ['gtk3agg', 'gtk3cairo', 'gtk4agg', 'gtk4cairo', 'macosx', 'nbagg', 'notebook', 'qtagg', 'qtcairo', 'qt5agg', 'qt5cairo', 'tkagg', 'tkcairo', 'webagg', 'wx', 'wxagg', 'wxcairo', 'agg', 'cairo', 'pdf', 'pgf', 'ps', 'svg', 'template']
    
  • I think this is the intended error message. After this message, I try changing my matplotlib backend to use something else, say tkagg:
    import matplotlib
    from plotnine import (
        aes,
        geom_tile,
        ggplot,
        theme_matplotlib,
    )
    from plotnine.data import faithfuld
    
    matplotlib.use("tkagg")
    
    plot = (
        ggplot(faithfuld, aes("waiting", "eruptions", fill="density"))
        + geom_tile()
        + theme_matplotlib()
    )
    plot.show()
  • This can now plot the heatmap as expected.
  • I hypothesize the root cause being the method BackendRegistry.is_valid_backend receives an object instead of a string.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Addressed in Next VersionThe issue has been fixed, but it has not in the current official release.Next Minor ReleasePlanned for the next minor releasebug

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions