[Matplotlib-users] possible regression in plt.draw (mpl 1.4.3 -> 1.5.0) when using fig.text using transformations

Thomas Caswell tcaswell at gmail.com
Fri Mar 4 08:59:53 EST 2016


Sorry this caused grief for you.  There is definitely a tension when
working on a library as big, old, and widely used as mpl, we want to make
things better, but we are almost always going to break something for
someone (even bug fixes break people who have work-arounds to the
bug-fixes!).

Tom

On Fri, Mar 4, 2016 at 8:39 AM Oliver Willekens <oliver.willekens at gmail.com>
wrote:

> >[...] in general [DPI/figure issues] will come up because the Transforms
> close over many values that can (and do!) change from user input or as part
> of the draw process.
>
> Thought I had the transformations all figured out, but it looks like I
> should definitely play some more with it.
>
> Thank you, Tom, for referring me to the git pull request and explaining
> the cause of this.
>
> Oliver
>
>
>
> 2016-03-03 14:54 GMT+01:00 Thomas Caswell <tcaswell at gmail.com>:
>
>> If you want to _really_ force a redraw, you will need to to
>> `fig.canvas.draw()`.
>>
>> In https://github.com/matplotlib/matplotlib/pull/5150 we change
>> `plt.draw()` to use the `canvas.draw_idle` method.  The draw_idle
>> effectively asks the GUI framework to please re-draw the next time it is
>> convenient.  The main benefit of this is if you request multiple draw_idle
>> before giving the GUI a chance to re-paint there will only be one actual
>> call to `canvas.draw`.
>>
>> Using `ax.text` is much simpler you should just use that ;)
>>
>> In general going through screen coordinates in user code is not advised.
>> In this particular case you are going right back to 'normalized' unit so
>> you will not have DPI / figure size issues, but in general those will come
>> up because the Transforms close over many values that can (and do!) change
>> from user input or as part of the draw process.  In almost all cases, it is
>> better to pass a transfrom into the artists and let mpl internals sort of
>> exactly when to evaluate them.
>>
>> Tom
>>
>> On Thu, Mar 3, 2016 at 6:31 AM Oliver Willekens <
>> oliver.willekens at gmail.com> wrote:
>>
>>> Dear matplotlib users and developers,
>>>
>>> I’m using plt.draw() to force the rendering of all artists and then,
>>> based on their newly calculated positions, place a text label on the figure
>>> window in figure coordinates.
>>>
>>> The goal is to add a text label near the conventional y-axis, at the
>>> top, right-aligned. Example code that demonstrates the problem:
>>>
>>> #!/usr/bin/env python
>>> # -*- coding: utf-8 -*-
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import matplotlib as mpl
>>> print(mpl.__version__)
>>>
>>> x = np.linspace(0, 50)
>>> y = 4*np.sin(x) + 5
>>>
>>> fig = plt.figure(figsize=(18,9.8))
>>> ax = fig.add_axes((0.1, 0.1, 0.8, 0.8),
>>>     frameon=True,
>>>     aspect='equal',
>>>     adjustable='box',
>>>     xlim=(x.min(), x.max()),
>>>     ylim=(0, 10),
>>>     xticks=[x.min(), x.max()],
>>>     yticks=[0, 10],
>>>     xlabel='dimension (unit)')
>>> ax.plot(x, y)
>>> plt.draw()  # force redraw
>>>
>>> ylabel_pos = fig.transFigure.inverted().transform_point(ax.transAxes.transform_point((0,1)))
>>> label1 = fig.text(ylabel_pos[0], ylabel_pos[1], "label1", ha="right", va="bottom")
>>> plt.savefig('/tmp/test_pre_mpl_v_{}.png'.format(mpl.__version__))
>>> ylabel_pos = fig.transFigure.inverted().transform_point(ax.transAxes.transform_point((0,1)))
>>> label2 = fig.text(ylabel_pos[0], ylabel_pos[1], "label2", ha="right", va="bottom")
>>> plt.savefig('/tmp/test_post_mpl_v_{}.png'.format(mpl.__version__))
>>>
>>> The code shows that in mpl 1.4.3 both label1 and label2 end up at the
>>> same (desired) position. However, mpl 1.5.0 and 1.5.1 (just installed to
>>> check) show that label1 is at a height of 0.9 in the figure coordinates.
>>> After the first call to savefig, the figure is rendered with the axes
>>> getting a new height and width (due to the call to aspect='equal',
>>> adjustable='box') and so the subsequent call to savefig renders label2
>>> in the correct position.
>>>
>>> Using ax.text(x=0, y=1, s='label', transform=ax.transAxes, ha="right",
>>> va="bottom") gets the job done alright (both in 1.4.3, as well as
>>> 1.5.0), but the call to fig.text using the subsequent transforms should
>>> have worked, I believe, and so this seems to indicate something has changed
>>> in the rendering of a rescaled axes using plt.draw.
>>>
>>> Kind regards,
>>> Oliver
>>>
>>> P.S. I posted this to the older sourceforge mailing list as well, by
>>> accident. Hadn’t changed the send-to address yet, even though Thomas
>>> Caswell had pointed it out to me already in August 2015. My apologies.
>>>>>> _______________________________________________
>>> 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/20160304/8f53d6c0/attachment.html>


More information about the Matplotlib-users mailing list