Thanks to visit codestin.com
Credit goes to github.com

Skip to content

RF: always close old figure windows #3916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

matthew-brett
Copy link
Contributor

The plot directive first runs the specified code, then collects figures with::

fig_managers = _pylab_helpers.Gcf.get_all_fig_managers()

If you are using the "context" option, prior figures maybe generated from a
previous plot directive command, are still open, and therefore collected with
the new figure(s). The old figures will usually be earlier in the list, and
so, for something like this ReST block, you will always get the first
generated figure (range(10)) repeated in the second plot directive panel::

#######

A title
#######

.. plot::
   :context:

    import matplotlib.pyplot as plt
   plt.plot(range(10))

    Then some text.

    .. plot::
   :context:

    plt.figure()
   plt.plot(range(5), 'r')

This PR always closes previous figure windows before running the plot
directive code.

See email discussion thread starting here:

https://www.mail-archive.com/[email protected]/msg10816.html

@mdboom
Copy link
Member

mdboom commented Dec 12, 2014

Doesn't this break one of the reasons for context mode -- that it allows you to create a figure in one block and then add to it in subsequent ones? This is what the existing :nofigs: and :context: reset features are for.

@matthew-brett
Copy link
Contributor Author

Aha - I thought that I had missed something.

I can understand the need to build up figures over the course of a few plot directives, and this will break that.

On the other hand, accidentally picking up an old figure seems like a bad idea too, and easy to do.

I think the current answer would be, always do a :context: reset at the top of a new page to avoid this?

That would still not deal with my test case though, where the user called plt.figure() at some point within a page.

Is there another way of avoiding picking up an old figure by accident?

@mdboom
Copy link
Member

mdboom commented Dec 12, 2014

:context: reset will avoid picking up the old figure, but it will also clear everything else. I guess the problem here is that :context: reset resets the state and clears the figures. And maybe you want to do the latter without the former. You can also just explicitly call fig.close()...

@matthew-brett
Copy link
Contributor Author

Yes, I was doing that with an explicit extra hidden plot_directive at the top of the page, but that's pretty ugly and easy to forget. You'd have to do one of those each time you used plt.figure().

What about closing all but the last figure on the basis it is most unlikely you'd want the first of two figures in the plot directive display?

@matthew-brett
Copy link
Contributor Author

Or just to add a 'close-existing' option that is false by default?

At least this would be a good explicit solution, although I am sure there will be some surprised users with the default behavior.

@mdboom
Copy link
Member

mdboom commented Dec 15, 2014

close-existing or close-figs seems like a reasonable solution.

@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch from cb4bba2 to 432f5a6 Compare December 17, 2014 19:50
@matthew-brett
Copy link
Contributor Author

OK - I added close-figs and some tests and I think I found and fixed a bug in the context clearing.

@tacaswell
Copy link
Member

All I see here is tests...

I also think you need to white-list the tests so that travis will find them.

@matthew-brett
Copy link
Contributor Author

I added back the code - bad rebase.

I think I whitelisted the tests?

@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch from 432f5a6 to b40e827 Compare December 18, 2014 18:45
@mdboom
Copy link
Member

mdboom commented Dec 19, 2014

This looks great, and it's nice to finally have some tests for the plot directive.

Looking at the Travis logs, though, it does seem that the new tests are not actually being run (even though you've added it to the testing list). I may not have a chance to drill down as to why -- I think this is the only tests we have outside of matplotlib.tests, so maybe there's some broken assumption there?

@matthew-brett
Copy link
Contributor Author

I think the tests aren't being run because sphinx is not installed (the
tests get skipped).

I will try adding sphinx to the dependencies in the travis file.

@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch 3 times, most recently from a69de87 to cbee4f4 Compare December 23, 2014 10:43
@matthew-brett
Copy link
Contributor Author

OK - I believe the tests are running and passing now. The tests revealed a Python 2.6 problem, with an easy fix - ah testing.

@@ -23,7 +23,7 @@ matrix:
env: BUILD_DOCS=true

install:
- pip install -q --use-mirrors nose python-dateutil $NUMPY pep8 pyparsing pillow
- pip install -q --use-mirrors nose python-dateutil $NUMPY pep8 pyparsing pillow sphinx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also remove the sphinx installation on line 30?

@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch from cbee4f4 to aa7a399 Compare December 23, 2014 21:23
@matthew-brett
Copy link
Contributor Author

Anything more I can do here?

@tacaswell
Copy link
Member

Can you also add a note in https://github.com/matplotlib/matplotlib/tree/master/doc/users/whats_new ?

One of our biggest problems is 'stealth' features that exist but no one knows about.

It seems like it would simpler/cleaner to pass the value of context through to render_figures and do the logic in that function, rather that passing a collection of mutually exclusive kwargs. However, I don't think it is worth making much of a fuss about that at this point in time.

@tacaswell
Copy link
Member

@matthew-brett This needs a re-base

@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch from 886d103 to e980de6 Compare January 1, 2015 01:49
Add `close-figs` choice to `context` option of plot_directive.  This
keeps the current context, but closes any previous figures.

This is necessary because the plot directive first runs the specified
code, then collects figures with:

    fig_managers = _pylab_helpers.Gcf.get_all_fig_managers()

If you are using the "context" option, prior figures maybe generated
from a previous plot directive command, are still open, and therefore
collected with the new figure(s).  The old figures will usually be
earlier in the list, and so, for something like this ReST block, you
will always get the first generated figure (``range(10)``) repeated in
the second plot directive panel:

    #######
    A title
    #######

    .. plot::
        :context:

        import matplotlib.pyplot as plt
        plt.plot(range(10))

        Then some text.

    .. plot::
        :context:

        plt.figure()
        plt.plot(range(5), 'r')

This PR add a context option of form `:context: close-figs` that closes
any previous figure windows before running the directive code.

It also adds a small test sphinx project to test the directive commands.

See email discussion thread starting here:

https://www.mail-archive.com/[email protected]/msg10816.html
re.flags argument to re.sub appears to a 2.7 innovation.
Add small section on `close-figs` argument for plot directive.
@matthew-brett matthew-brett force-pushed the plot-directive-old-figures branch from e980de6 to 5e4a602 Compare January 1, 2015 01:54
@matthew-brett
Copy link
Contributor Author

Rebased on master. I hope. Had a few glasses of wine for the new year.

tacaswell added a commit that referenced this pull request Jan 2, 2015
ENH : add option to close figures in plot directive
@tacaswell tacaswell merged commit ab549ac into matplotlib:master Jan 2, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants