-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[MNT]: Turn ContourSet into a (nearly) plain Collection #25128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm assuming this would be an alternative to #24388 (given the overlap between contour and streamplot sets), which stalled out on collections not having remove methods and my not having the time/energy to sort that out, and this seems the better approach to me? |
It's not the same as the idea here is to use Collection and not Container (which are very different things -- one is in the draw tree and the other one is not); and ContourSets can already be removed just fine (currently by removing the individual component collections). |
Well so that would be my question on that one too-to move the return type to a collection instead of to a container b/c they seem structured very similarly to me. |
They are not the same at all. A Container just holds a few artists together, which may be completely different from one another (in the case of StreamplotSet, a LineCollection (lines) and a PatchCollection (arrows) which exist as attributes) [sure, StreamplotSet is not a Container but it could be], whereas a Collection is for homogeneous "artist-like" objects (e.g. LineCollection is like a list of Line2Ds), which don't even have an independent existence (there isn't actually a bunch of Line2Ds as everything is directly in numpy arrays for efficiency). |
Sorry wasn't trying to say that a collection was a container, I legit just forgot that streamplot was LineCollection + PatchCollection and thought it was a list of one artist type Sorry for derailing the discussion here and thanks for clarifying |
I am 👍🏻 in principle (but did not read the diff carefully). This is good both from a consistency point of view and for making a move to the data-prototype style artists easier. |
Sounds very sensible to me. Flattening each contour level into a single There are a couple of ramifications of this:
Looking ahead, there is future work relevant here. If we are not using the outer-to-hole relationship for rendering then we don't need to ask contourpy to calculate it. The new |
Let's move the discussion to #25247. |
Fixed by #25247. |
Summary
Currently, ContourSets are not Artists, which causes issues such as #6139 (essentially, the API is not uniform, and they do not appear directly in the draw tree).
At a low level, a ContourSet is represented as a list of PathCollections (the
.collections
attribute), with one such PathCollection per contour level value; the individual paths in the PathCollection are the connected components of that contour level. But we could instead "lift" things up one level and make ContourSet directly inherit from Collection (actually inheriting from PathCollection doesn't really help; despite the name, PathCollection is more designed for "resizable" paths such as scatter plots with variable sizes), and use a single Path object for each contour level (using MOVETOs as needed if the Path needs to be broken in multiple connected components. While slightly tedious, temporary backcompat with the old API could be provided via on-access creation of the "old" attributes, similarly to what was done in #24455.There's actually (AFAICT) only one main difficulty with this approach, which is that draw_path_collection (called by Collection.draw) doesn't support hatching individual paths. However, this could be implemented by still implementing a ContourSet.draw which directly calls draw_path_collection if no hatching is needed, and in the other case re-decomposes the collection as needed to emit the right set of draw_path with the right hatching set.
attn @ianthomas23
Proposed fix
A first patch (which goes on top of #25121) is provided below.
Quite a few things (hatching, labeling, legends, etc.) are not implemented yet, but this at least allows one to call e.g.
contour(np.random.rand(5, 5))
and get a contour plot.The text was updated successfully, but these errors were encountered: