[Matplotlib-devel] Confusion about draw_artist

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[Matplotlib-devel] Confusion about draw_artist

Matthew Brett
Hi,

We're using 'draw_artist' in an image viewer, and I just found that
our viewer is crashing using the macosx backend.  Here's a minimal
example:

import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 1)
im = plt.imshow([[1, 2], [3, 4]])
fig.canvas.draw()
ax.draw_artist(im)

This generates:

Traceback (most recent call last):
  File "draw_artist.py", line 8, in <module>
    ax.draw_artist(im)
  File "/Users/mb312/dev_trees/matplotlib/lib/matplotlib/axes/_base.py",
line 2423, in draw_artist
    raise AttributeError(msg)
AttributeError: draw_artist can only be used after an initial draw
which caches the render

for the macosx backend, and works correctly for the tkagg backend.

I can't see any way to cache the renderer here - could someone give me
a pointer?

Cheers,

Matthew
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about draw_artist

tcaswell
Unless you have flagged the artist as `animated` (via `set_animated` or by kwarg), it will be drawn as part of the next re-draw.  You are better off just changing the `fig.canvas.draw()` to `fig.canvas.draw_idle()` and letting the GUI decide when to re-draw things.

If you want to get any performance gain from animated artists + draw_artist you will need to use blitting (which will work with the OSX backend in 2.0).

Tom

On Wed, Nov 30, 2016 at 2:11 PM Matthew Brett <[hidden email]> wrote:
Hi,

We're using 'draw_artist' in an image viewer, and I just found that
our viewer is crashing using the macosx backend.  Here's a minimal
example:

import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 1)
im = plt.imshow([[1, 2], [3, 4]])
fig.canvas.draw()
ax.draw_artist(im)

This generates:

Traceback (most recent call last):
  File "draw_artist.py", line 8, in <module>
    ax.draw_artist(im)
  File "/Users/mb312/dev_trees/matplotlib/lib/matplotlib/axes/_base.py",
line 2423, in draw_artist
    raise AttributeError(msg)
AttributeError: draw_artist can only be used after an initial draw
which caches the render

for the macosx backend, and works correctly for the tkagg backend.

I can't see any way to cache the renderer here - could someone give me
a pointer?

Cheers,

Matthew
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about draw_artist

Matthew Brett
Hi,

Sorry to keep displaying my confusion on this one but...

On Wed, Jan 4, 2017 at 6:58 PM, Thomas Caswell <[hidden email]> wrote:
> Unless you have flagged the artist as `animated` (via `set_animated` or by
> kwarg), it will be drawn as part of the next re-draw.

Adding `set_animated` doesn't help in the example above;

fig, ax = plt.subplots(1, 1)
ax.set_animated(True)
im = plt.imshow([[1, 2], [3, 4]])
fig.canvas.draw()
ax.draw_artist(im)

> You are better off
> just changing the `fig.canvas.draw()` to `fig.canvas.draw_idle()` and
> letting the GUI decide when to re-draw things.

Changing to `fig.canvas.draw_idle()` above doesn't prevent the error
from `draw_artist`, but I guess I should not have expected it would.
So I guess my question is - how do I use `draw_artist` in this case?
Is there any way to make sure that the renderer is cached first?

> If you want to get any performance gain from animated artists + draw_artist
> you will need to use blitting (which will work with the OSX backend in 2.0).

Yup, the real code does use blitting, but thanks for the reminder,

Cheers,

Matthew
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about draw_artist

Matthew Brett
Hi,

On Thu, Jan 19, 2017 at 11:54 AM, Matthew Brett <[hidden email]> wrote:

> Hi,
>
> Sorry to keep displaying my confusion on this one but...
>
> On Wed, Jan 4, 2017 at 6:58 PM, Thomas Caswell <[hidden email]> wrote:
>> Unless you have flagged the artist as `animated` (via `set_animated` or by
>> kwarg), it will be drawn as part of the next re-draw.
>
> Adding `set_animated` doesn't help in the example above;
>
> fig, ax = plt.subplots(1, 1)
> ax.set_animated(True)
> im = plt.imshow([[1, 2], [3, 4]])
> fig.canvas.draw()
> ax.draw_artist(im)
>
>> You are better off
>> just changing the `fig.canvas.draw()` to `fig.canvas.draw_idle()` and
>> letting the GUI decide when to re-draw things.
>
> Changing to `fig.canvas.draw_idle()` above doesn't prevent the error
> from `draw_artist`, but I guess I should not have expected it would.
> So I guess my question is - how do I use `draw_artist` in this case?
> Is there any way to make sure that the renderer is cached first?
>
>> If you want to get any performance gain from animated artists + draw_artist
>> you will need to use blitting (which will work with the OSX backend in 2.0).
>
> Yup, the real code does use blitting, but thanks for the reminder,

Again - sorry to persist - but I'd be really grateful for any advice,

Cheers,

Matthew
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about draw_artist

Matthew Brett
On Fri, Mar 3, 2017 at 11:19 PM, Matthew Brett <[hidden email]> wrote:

> Hi,
>
> On Thu, Jan 19, 2017 at 11:54 AM, Matthew Brett <[hidden email]> wrote:
>> Hi,
>>
>> Sorry to keep displaying my confusion on this one but...
>>
>> On Wed, Jan 4, 2017 at 6:58 PM, Thomas Caswell <[hidden email]> wrote:
>>> Unless you have flagged the artist as `animated` (via `set_animated` or by
>>> kwarg), it will be drawn as part of the next re-draw.
>>
>> Adding `set_animated` doesn't help in the example above;
>>
>> fig, ax = plt.subplots(1, 1)
>> ax.set_animated(True)
>> im = plt.imshow([[1, 2], [3, 4]])
>> fig.canvas.draw()
>> ax.draw_artist(im)
>>
>>> You are better off
>>> just changing the `fig.canvas.draw()` to `fig.canvas.draw_idle()` and
>>> letting the GUI decide when to re-draw things.
>>
>> Changing to `fig.canvas.draw_idle()` above doesn't prevent the error
>> from `draw_artist`, but I guess I should not have expected it would.
>> So I guess my question is - how do I use `draw_artist` in this case?
>> Is there any way to make sure that the renderer is cached first?
>>
>>> If you want to get any performance gain from animated artists + draw_artist
>>> you will need to use blitting (which will work with the OSX backend in 2.0).
>>
>> Yup, the real code does use blitting, but thanks for the reminder,
>
> Again - sorry to persist - but I'd be really grateful for any advice,

Sorry - again again - but can I nose this one up towards the surface?

Cheers,

Matthew
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about draw_artist

tcaswell
The renderer is cached automatically the first time the figure is fully rendered (typically delayed until it is shown on the screen).  If your artist is not marked as animated, then just try..exect the call to `draw_artist`, as the artist will be drawn as part of the normal draw process when the figure is drawn.  If you have marked it as animated (which you should if you are blitting) then you are going to need to have some call backs in place for draw and resize events (as any 'animated' artists will not be drawn if the figure is re-rendered from scratch by the GUI for what ever reason and to re-grab the background if the window is resized) so put the `draw_artist` in the callback (which comes out after the figure is drawn so you will have a renderer at that point).

Tom

On Fri, Mar 24, 2017 at 10:27 AM Matthew Brett <[hidden email]> wrote:
On Fri, Mar 3, 2017 at 11:19 PM, Matthew Brett <[hidden email]> wrote:
> Hi,
>
> On Thu, Jan 19, 2017 at 11:54 AM, Matthew Brett <[hidden email]> wrote:
>> Hi,
>>
>> Sorry to keep displaying my confusion on this one but...
>>
>> On Wed, Jan 4, 2017 at 6:58 PM, Thomas Caswell <[hidden email]> wrote:
>>> Unless you have flagged the artist as `animated` (via `set_animated` or by
>>> kwarg), it will be drawn as part of the next re-draw.
>>
>> Adding `set_animated` doesn't help in the example above;
>>
>> fig, ax = plt.subplots(1, 1)
>> ax.set_animated(True)
>> im = plt.imshow([[1, 2], [3, 4]])
>> fig.canvas.draw()
>> ax.draw_artist(im)
>>
>>> You are better off
>>> just changing the `fig.canvas.draw()` to `fig.canvas.draw_idle()` and
>>> letting the GUI decide when to re-draw things.
>>
>> Changing to `fig.canvas.draw_idle()` above doesn't prevent the error
>> from `draw_artist`, but I guess I should not have expected it would.
>> So I guess my question is - how do I use `draw_artist` in this case?
>> Is there any way to make sure that the renderer is cached first?
>>
>>> If you want to get any performance gain from animated artists + draw_artist
>>> you will need to use blitting (which will work with the OSX backend in 2.0).
>>
>> Yup, the real code does use blitting, but thanks for the reminder,
>
> Again - sorry to persist - but I'd be really grateful for any advice,

Sorry - again again - but can I nose this one up towards the surface?

Cheers,

Matthew

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel