You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#19968 introduced a no-output draw fig.draw_no_output() which does what fig.canvas.draw() does, but with presumably less side effects. This change should be better reflected in the code base, tests, and docs.
Good first issue, because there isn't really anything tricky here. If someone takes it on, it may be preferable to take it on in stages so it is not a megalithic change.
We'll get to the name when we can name those two things. I'm not quite sure what exactly 1 actually does, but that's the name we need. This needs somebody who knows exactly what is done internally. Might be it's layout_artists. Then we could say draw = layout_artists + render.
If nobody steps up, we can try to find the name jointly in the next dev call.
I call the all put together but not rendered thing the graphic, since in the visualization literature is a graphic whether it's theoretical or rendered to an image. Probably stole the terminology from Grammar of Graphics
which is probably a short hand for graphical design (from "A Presentation Tool" by Jock Mackinlay)
The way this is implemented is that we do fig.draw(render_with_no_op_methods). Thus, everything on the Artist side of the draw (resolving anything lazy (limits, some RBGA mapping that we cache, some truncation in Line2D, resolve any "relative to other artist" transfroms), computing how big the text will be, sort where ticks are, etc) will happen. In the normal course of events, the Artist.draw methods are responsible for boiling down everything it knows from the user and using that information to set up GraphicConexts and call the renderer.draw_XYZ methods (see https://matplotlib.org/stable/api/backend_bases_api.html#matplotlib.backend_bases.RendererBase it is out of these primitives (which map closely to the SVG primitives) that we make everything). Exactly what gets done in draw_xyz is up to the backend (e.g. in svg this produces text, in the case of AGG it composites another layer onto its internal buffer) and in the draw_no_output case it does nothing.
It should also be noted, that when we talk about doing stuff on a GPU we usually get stuck on "we do too much in Python", it is this aspect of doing lots and lots of work in the Artist.draw method. On the other hand, this design is also what lets us support the variety of backends that we do!
In the first diagram what GoG calls "Graphic" is what we call "Artist" and in the second the construction of the Artists is what is labeled "Graphical Design". In both cases we are worried about details inside of the "Render" or "render" parts so I do not think either is going to provide us useful naming guidance in this case.
Thus, everything on the Artist side of the draw (resolving anything lazy (limits, some RBGA mapping that we cache, some truncation in Line2D, resolve any "relative to other artist" transfroms), computing how big the text will be, sort where ticks are, etc) will happen.
This is exactly the thing which Eric and I are hoping we find a "name" for.
In the normal course of events, the Artist.draw methods are responsible for
boiling down everything it knows from the user and
using that information to set up GraphicConexts and call the renderer.draw_XYZ methods
(numbering added by me). I think from an API design perspective, the fact that we implement draw_no_output by (basically) setting a flag that lets us skip step (2), doesn't matter, because most users don't and shouldn't have to know that.
I approved the existing name because I don't have a better suggestion. But if we do have a good name for (1), we should use that instead of "draw".
layout_artists. Then we could say draw = layout_artists + render.
I can definitely get behind this.
The routine walks the artist tree and calls the draw method on every artist. It just stops short of outputting the results to the renderer.
but I don't think the implementation should affect the naming. I think we can still say fig.draw = fig.layout + fig.render even if that's not "true" at an implementation level, it's definitely true semantically.
"layout" might not be "all encompassing" enough, but is basically what I was hoping for.
I'm not sure it is terribly practical to change the nomenclature all the way back to Artist. That seems a lot of churn for little practical gain.
Again, I'll remind folks were are trying to come up with a replacement name for fig.canvas.draw which has served the purpose for 15 years despite not containing any indication that it did not actually produce an output. That the replacement should also contain the verb draw makes perfect sense to me a) because that is the historical verb and b) because that is what it is doing, except it stops at the point of making an output. I think of it as drawing something in your favourite graphics program, but never sending it to the printer.
I suppose the verb "compose" is really what is happening here, and maybe fig.compose_no_output would be OK, but given we call this "draw" everywhere else, I'm still not particularly convinced the slight difference in verb is that helpful.
I like compose(). _no_output postfix is unneeded there as composing does not have a notion of output in the first place.
I agree with @brunobeltran that the naming here does not need to reflect implementation (or low-level naming).
At the semantic top level we'd have "drawing is composing + renderding". The low-level implementation can only draw. The realization of an isolated compose() is done by drawing with a null-renderer.
Activity
timhoffm commentedon Apr 17, 2021
I agree with #19968 (review) that we should try to think of a better name before rolling this out everywhere.
tacaswell commentedon Apr 17, 2021
Sorry if I jumped the gun on merging with this name
xref #19765 (comment)
jklymak commentedon Apr 17, 2021
I await a better name with bated breath!
timhoffm commentedon Apr 18, 2021
Coming from #19968 (review)
We'll get to the name when we can name those two things. I'm not quite sure what exactly 1 actually does, but that's the name we need. This needs somebody who knows exactly what is done internally. Might be it's
layout_artists. Then we could saydraw=layout_artists+render.If nobody steps up, we can try to find the name jointly in the next dev call.
jklymak commentedon Apr 18, 2021
The routine walks the artist tree and calls the
drawmethod on every artist. It just stops short of outputting the results to the renderer.story645 commentedon Apr 18, 2021
I call the all put together but not rendered thing the graphic, since in the visualization literature is a graphic whether it's theoretical or rendered to an image. Probably stole the terminology from Grammar of Graphics


which is probably a short hand for graphical design (from "A Presentation Tool" by Jock Mackinlay)
jklymak commentedon Apr 18, 2021
I think we are after a verb, not a noun, and I think we call those things "Artists".
tacaswell commentedon Apr 19, 2021
The way this is implemented is that we do
fig.draw(render_with_no_op_methods). Thus, everything on theArtistside of the draw (resolving anything lazy (limits, some RBGA mapping that we cache, some truncation in Line2D, resolve any "relative to other artist" transfroms), computing how big the text will be, sort where ticks are, etc) will happen. In the normal course of events, theArtist.drawmethods are responsible for boiling down everything it knows from the user and using that information to set upGraphicConexts and call therenderer.draw_XYZmethods (see https://matplotlib.org/stable/api/backend_bases_api.html#matplotlib.backend_bases.RendererBase it is out of these primitives (which map closely to the SVG primitives) that we make everything). Exactly what gets done indraw_xyzis up to the backend (e.g. in svg this produces text, in the case of AGG it composites another layer onto its internal buffer) and in thedraw_no_outputcase it does nothing.Concretely, if we look at
Axis.drawmatplotlib/lib/matplotlib/axis.py
Lines 1116 to 1145 in bf9ae97
self._update_ticks()is where we sort out who is visible etc and all of the logic to re-use ticks lives)drawsTextobject that is the label to please draw itselfAt no point in here did we actually use the renderer, we have to go a couple of more level down through
matplotlib/lib/matplotlib/axis.py
Lines 302 to 312 in bf9ae97
matplotlib/lib/matplotlib/text.py
Lines 737 to 744 in bf9ae97
matplotlib/lib/matplotlib/lines.py
Lines 753 to 777 in bf9ae97
It should also be noted, that when we talk about doing stuff on a GPU we usually get stuck on "we do too much in Python", it is this aspect of doing lots and lots of work in the
Artist.drawmethod. On the other hand, this design is also what lets us support the variety of backends that we do!This suggest
draw_no_renderis a better name?I suspect the historical path we took to get to the collection of
drawmethods is that the very first version of Matplotlib was a gtk application gtk usesdrawin this context (e.g. https://developer.gnome.org/gtkmm-tutorial/stable/sec-cairo-drawing-lines.html.en). This is pretty thematically consistent with GUI toolkits for "the code that runs to sort out what color the pixels on the screen should be" as QT uses "paint" in this context.In the first diagram what GoG calls "Graphic" is what we call "Artist" and in the second the construction of the Artists is what is labeled "Graphical Design". In both cases we are worried about details inside of the "Render" or "render" parts so I do not think either is going to provide us useful naming guidance in this case.
brunobeltran commentedon Apr 22, 2021
This is exactly the thing which Eric and I are hoping we find a "name" for.
(numbering added by me). I think from an API design perspective, the fact that we implement
draw_no_outputby (basically) setting a flag that lets us skip step (2), doesn't matter, because most users don't and shouldn't have to know that.I approved the existing name because I don't have a better suggestion. But if we do have a good name for (1), we should use that instead of "draw".
brunobeltran commentedon Apr 22, 2021
I can definitely get behind this.
but I don't think the implementation should affect the naming. I think we can still say fig.draw = fig.layout + fig.render even if that's not "true" at an implementation level, it's definitely true semantically.
"layout" might not be "all encompassing" enough, but is basically what I was hoping for.
brunobeltran commentedon Apr 22, 2021
EDIT: sorry for the close/open. My mouse hates me.
1 remaining item
jklymak commentedon Apr 22, 2021
I'm not sure it is terribly practical to change the nomenclature all the way back to
Artist. That seems a lot of churn for little practical gain.Again, I'll remind folks were are trying to come up with a replacement name for
fig.canvas.drawwhich has served the purpose for 15 years despite not containing any indication that it did not actually produce an output. That the replacement should also contain the verbdrawmakes perfect sense to me a) because that is the historical verb and b) because that is what it is doing, except it stops at the point of making an output. I think of it as drawing something in your favourite graphics program, but never sending it to the printer.I suppose the verb "compose" is really what is happening here, and maybe
fig.compose_no_outputwould be OK, but given we call this "draw" everywhere else, I'm still not particularly convinced the slight difference in verb is that helpful.[-]fig.draw_no_output should replace many (most) instances of fig.canvas.draw[/-][+]rename fig.draw_no_output[/+]tacaswell commentedon Apr 23, 2021
I renamed and re-labeled this issue to reflect the discussion we are actually having here ;)
timhoffm commentedon Apr 23, 2021
I like
compose()._no_outputpostfix is unneeded there as composing does not have a notion of output in the first place.I agree with @brunobeltran that the naming here does not need to reflect implementation (or low-level naming).
At the semantic top level we'd have "drawing is composing + renderding". The low-level implementation can only draw. The realization of an isolated
compose()is done by drawing with a null-renderer.QuLogic commentedon Aug 17, 2021
This is going out in 3.5 soon; does anyone have any new/final opinions on renaming?
timhoffm commentedon Aug 26, 2021
Naming decision on the dev call:
draw_without_rendering().jklymak commentedon Aug 27, 2021
I still vote for
draw_no_output, so if someone who prefersdraw_without_renderingcould put the PR through, they should do that.API: rename draw_no_output to draw_without_rendering
API: rename draw_no_output to draw_without_rendering