Skip to content

Import of Test Examples changes matplotlib backend #2191

Closed

Description

@uliano

Expected behavior

Importing example datafiles should not affect matplotlib backend as with 'agg' bad things happen (cfr. [7])

Actual behavior

uliano@dewey:~$ ipython
Python 3.7.1 | packaged by conda-forge | (default, Nov 13 2018, 10:30:07) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.2.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import matplotlib                                                       
In [2]: matplotlib.get_backend()                                                
Out[2]: 'Qt5Agg'
In [3]: from MDAnalysis.tests.datafiles import PSF,DCD                          
In [4]: matplotlib.get_backend()                                                
Out[4]: 'agg'
In [5]: import matplotlib.pyplot as plt                                         
In [6]: plt.plot([1,2])                                                         
Out[6]: [<matplotlib.lines.Line2D at 0xb18bdd860>]
In [7]: plt.show()                                                              
/opt/anaconda3/lib/python3.7/site-packages/matplotlib/figure.py:445: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
  % get_backend())

Currently version of MDAnalysis

uliano@dewey:~$ python -c "import MDAnalysis as mda; print(mda.__version__)"
0.19.2
uliano@dewey:~$ python -V
Python 3.7.1
uliano@dewey:~$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.2
BuildVersion:	18C54

Activity

  1. orbeckst commented on Jan 30, 2019

    @orbeckst
    Member

    Fair enough, but honestly I have been struggling to understand how to do this differently because matplotlib does not allow us to change the backend later. How can we ensure that our tests run with the agg backend and not with any of the GUI ones?

  2. richardjgowers commented on Jan 30, 2019

    @richardjgowers
    Member

    We could do a pytest fixture that switches the backend to/from, something like:

    @pytest.fixture
    def mpl():
        curr = matplotlib.get_backend()
        try:
            matplotlib.use('agg')
            yield
        finally:
            matplotlib.use(curr)
    
    def test_plot(mpl):
        # test with backend temporarily changed

    But matplotlib complains about the backend being set after pyplot import, so there's another step I'm missing. Maybe a forced reload of the package?

  3. jbarnoud commented on Jan 30, 2019

    @jbarnoud
    Contributor

    We could set the backend when we import matplotlib in each test module that needs it, instead of doing the import at the package level in the init. It is not much of a problem if pytest changes the backend, the real issue is that the init changes it which mean we cannot safely import from datafiles.

  4. uliano commented on Jan 31, 2019

    @uliano
    Author

    Now I see where it comes from, as @jbarnoud says; the documentation is full of like examples. For example I stumbled upon this:
    https://www.mdanalysis.org/docs/documentation_pages/analysis/contacts.html#examples-for-contact-analysis

  5. tylerjereddy commented on Jan 31, 2019

    @tylerjereddy
    Member

    The discussion above seems to suggest the backend adjustment is actually happening for the unit test infrastructure, rather than for the examples in docstrings.

    If the main reason for having some kind of top-level data module backend switch to agg is because of docstrings, we might consider using i.e., refguide_check.py instead of vanilla doctests, since the backend switch to Agg happens gracefully / automatically for doctesting that way.

    But if it is really unit tests that are the problem refguide doesn't solve the issue. Do we actually CI test our docstrings with vanilla doctest? I'd guess not--standard library doctest is a real pain for scientific code, which is why refguide was created. There's some interest in creating a third-party refguide library so that different packages don't keep vendoring the module.

  6. tylerjereddy commented on Jan 31, 2019

    @tylerjereddy
    Member

    There's also switch_backend() if that's needed

  7. orbeckst commented on Mar 5, 2020

    @orbeckst
    Member

    We should get rid of

    # Any tests that plot with matplotlib need to run with the simple agg backend
    # because on Travis there is no DISPLAY set. This doesn't warn if we import
    # files from the tests after loading matplotlib. This will remove unnecessary
    # user warnings.
    try:
    import matplotlib
    matplotlib.use('agg', warn=False)
    except ImportError:
    pass
    which was included to let the CI run cleanly but presumably we could achieve this in a different manner by, say, setting matplotlibrc on Travis.

  8. orbeckst commented on Jun 16, 2020

    @orbeckst
    Member

    https://matplotlib.org/3.2.1/tutorials/introductory/usage.html#backends says that we can set

    export MPLBACKEND=agg

    in our CI environment and then that will overrule anything else. In particular, it allows us to get rid off matplotlib.use().

  9. self-assigned this
    on Jun 16, 2020
  10. added this to the 1.0.x milestone on Jun 16, 2020
  11. added 2 commits that reference this issue on Jun 16, 2020
    77630a1
    d8fa7bf
  12. added a commit that references this issue on Jun 16, 2020
    34288cc
  13. added a commit that references this issue on Jun 26, 2020
    04e5d20
  14. added a commit that references this issue on Jul 12, 2020
    dbaf957
  15. orbeckst commented on Jul 28, 2020

    @orbeckst
    Member

    The fix for this issue also removes the error (with matplotlib ≥ 3.3)

    ..../MDAnalysisTests/__init__.py:126: in <module>
    
    matplotlib.use('agg', warn=False)
    E   TypeError: use() got an unexpected keyword argument 'warn'
    

    because the whole line is removed in in PR #2763

  16. added a commit that references this issue on Mar 30, 2021
    f51ecc8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions