[Matplotlib-users] Replacing deprecated use of pyplot.subplot
Paul Hobson
pmhobson at gmail.com
Sat Jan 20 16:03:38 EST 2018
Errr, make that last line:
h_mpl = bode_plot(h, ax_mag=g_mpl['axes'][0], ax_phase=g_mpl['axes']*[1]*)
On Sat, Jan 20, 2018 at 1:02 PM, Paul Hobson <pmhobson at gmail.com> wrote:
> 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/af8d4e
>> e39dfa574c2b3b335f4cdb4be858ae469a/control/freqplot.py#L175
>> [3] https://github.com/murrayrm/python-control/blob/dc1820a4e64d
>> 73937c7de8df078c41ec1773e048/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/2d0c53d9/attachment-0001.html>
More information about the Matplotlib-users
mailing list