[Matplotlib-users] Replacing deprecated use of pyplot.subplot

Paul Hobson pmhobson at gmail.com
Sat Jan 20 16:02:02 EST 2018


Hey Rory,

In general, especially for library code, you should avoid relying on the
pyplot state machine.

That means explicitly passing Axes and Figure object around to and from
your functions.

For me, making that switch meant added an `ax=None` kwarg to the end of my
function signatures.

Then I carry around an axes_validator function that looks something like
this:
https://github.com/matplotlib/mpl-probscale/blob/master/probscale/validate.py#L6

But that's not really necessary. So in your case, I think you should do
something like this:


import numpy as np
import matplotlib.pyplot as plt


def bode_plot(g, ax_mag=None, ax_phase=None, mag_opts=None,
phase_opts=None):
    # create axes if they're not both supplied
    if not ax_mag or not ax_phase:
        fig, (ax_mag, ax_phase) = plt.subplots(nrows=2)

    # make the plotting options empty dicts if
    # not supplied
    if not mag_opts:
        mag_opts = {}

    if not phase_opts:
        phase_opts = {}

    # compute signal stuff
    freq, mag, phase = freq_resp(g)

    # 99% sure semilogx returns a tuple of artists, so I unpack it
    # you should check this though
    mag_artist, = ax_mag.semilogx(freq, 20 * np.log10(mag), **mag_opts)
    phase_artist, = ax_phase.semilogx(freq, phase, **phase_opts)

    # package the output for later (if you want to modify artists)
    output = {
        'fig': fig,
        'axes': (ax_mag, ax_phase),
        'arists': (mag_artist, phase_artist)
    }
    return output

And then you'd use the code like this:

fig, (ax_mag, ax_phase) = plt.subplots(nrows=2, figsize=(12, 6))
g_mpl = bode_plot(g, ax_mag=ax_mag, ax_phase=ax_phase, color='r',
linewidth=2, label='G')
h_mpl = bode_plot(h, ax_mag=ax_mag, ax_phase=ax_phase, color='b'm
linewidth=1, label='H')
ax_mag.legend()


Or do something like this:
g_mpl = bode_plot(g, color='r', linewidth=2, label='G')
h_mpl = bode_plot(h, ax_mag=g_mpl['axes'][0], ax_phase=g_mpl['axes'][0])


Does that help?
-Paul


On Sat, Jan 20, 2018 at 11:44 AM, Rory Yorke <rory.yorke at gmail.com> wrote:

> Hi,
>
> I'm a contributor to the Python Control Systems Library [1], which uses
> Matplotlib for plotting.
>
> We recently noticed deprecation warnings due to how we use
> pyplot.subplot.  We use it in the Matlab manner of either getting a
> handle to an existing axis, or creating one if no suitable axis exists.
>
> The warning is
>
>   MatplotlibDeprecationWarning: Adding an axes using the same arguments
>   as a previous axes currently reuses the earlier instance.  In a future
>   version, a new instance will always be created and returned.
>   Meanwhile, this warning can be suppressed, and the future behavior
>   ensured, by passing a unique label to each axes instance.
>
> For example, to plot the frequency response a linear dynamical system
> (AKA Bode plot of the system), the relevant function could be simplified
> to:
>
>     def bode_plot(g):
>        freq, mag, phase = freq_resp(g)
>        subplot(211)
>        semilogx(freq, 20*log10(mag))
>        subplot(212)
>        semilogx(freq, phase)
>
> We've replaced that with code like this:
>
>     def bode_plot(g):
>        freq, mag, phase = freq_resp(g)
>
>        ax_mag = None
>        ax_phase = None
>        for ax in gcf.axes():
>            if ax.get_label() == 'control-bode-magnitude':
>              ax_mag = ax
>            elif ax.get_label() == 'control-bode-phase':
>              ax_phase = ax
>
>        if ax_mag is None or ax_phase is None:
>          clf()
>          ax_mag = subplot(211, label = 'control-bode-magnitude')
>          ax_phase = subplot(212, label = 'control-bode-phase)
>
>        ax_mag.semilogx(freq, 20*log10(mag))
>        ax_phase.semilogx(freq, phase)
>
> This means that calls like
>
>     bode_plot(g)
>     bode_plot(h)
>
> will show the response of g and h on the same figure.
>
> Is this method of using labels to check for existing axes reasonable?
> Is there a better way?
>
> Actual code exhibiting warnings at [2]; new code at [3].  The latter
> link is to an as-yet unmerged branch, and may disappear.
>
> Thanks,
>
> Rory
>
> [1] https://github.com/python-control/python-control
> [2] https://github.com/python-control/python-control/blob/
> af8d4ee39dfa574c2b3b335f4cdb4be858ae469a/control/freqplot.py#L175
> [3] https://github.com/murrayrm/python-control/blob/
> dc1820a4e64d73937c7de8df078c41ec1773e048/control/freqplot.py#L138
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users at python.org
> https://mail.python.org/mailman/listinfo/matplotlib-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20180120/495750c2/attachment.html>


More information about the Matplotlib-users mailing list