-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[ENH] Unit support for ScalarMappables #7383
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 trying to work on this. So I went through units.py and also pyplot.py with imshow function implementations. Is there anything special I should know before trying this? I am currently going through the colormap and normalization documentation as well. |
Look through the normalization, colormap, and colorbar code. |
Should I fork the matplotlib code or the code you've worked on when doing this? |
matplotlib |
@jklymak I dunno if this should be thought through as part of a units MEP or built on top of one, but mostly fyi. |
Cool. OTOH I personally think this should just be its own method versus something that gets tacked into |
it's not about imshow but about all scalermappable. A fairly popular request is to natively get categories working in scatter plots (no loops) and that would kind of come for free with any solution that's generalizable to scalermappables. It can sort of be solved just via a categorical norm, but that doesn't fit with the idea of it being a magically handled type. (Also part of this would be to hook in legends) |
Hah, we can get excited about doing this once units for co-ordinate axes is sorted out in a rational manner. Personally I'm skeptical that this needs to be handled in the core versus adding a few helper functions. |
With respect to colorbars #9903 completely changes how colorbars are handled. Instead of drawing from 0 to 1 it draws from vmin to vmax, which simply lifted some of the logic I think. |
cc @dopplershift the categorical SM task I have in mind is something like this: fig, ax = plt.subplots()
sm = ax.imshow(data)
csm = ax.imshow(label_data)
ax.colorbar(sm)
ax.legend(csm) The secondary task here is that for categorical, I'd wanna tie the mapping into something accessible by legends. |
If your label_data consists of integers, 0...N-1, and you have a ListedColormap with N colors, and you set norm to NoNorm, then you can achieve this discrete coloring with an arbitrary set of colors. Given a matching list of names, the only additional thing you need for the legend is an easy way of telling it to make the nice rectangle patches with the appropriate colors. |
@efiring that's the thing, it's categories, not integers (and yes, in that dataset it's really integers, but for the sake of argument). And I started on the helper function approach to this in #6934, but I'm not crazy about that approach since half the point is to support this sorta automagically the way it's done in other plotting functions. |
@efiring I didn't even know that |
@story645 This is at least one thing I am not understanding: are you saying that you think imshow should accept a 2-D array of strings? |
Yeah...if it can be treated as data in the plot space, then why not also in the imshow space? |
I think an objection would be that stored arrays of strings must be a vanishingly small use case. are there datasets and formats that do this? that seems 🥜 to me! |
And even if there are, I would leave it to the user to do the conversion to numbers for plotting. |
@efiring that's the same argument against plotting supporting categoricals...more to the point though, if the user does the conversion, then there can't be any automatic hooks into legend. @jklymak scatter plots supporting categorical variables in the color array is a fairly common request: #6214, #6802, and any solution for that problem would probably be the same solution for imshow/axeshow. |
Scatter plots make a bit more sense to me - at least the data is "N" instead of "N^2" and you can imagine mixing and matching what is the color versus the x and y axes. Following @efiring's suggestion, can you just write a |
I kind of like the idea of a |
So I tried doing that in #6934 and it quickly became spaghetti...
Yeah, that's what I wonder too...and legends even more so...maybe the code is the same? CategoryNorm creates a list of labels, and I guess falls back to the cmap if there's no list of colors for legend to work on? |
Automatic labels for a colorbar are pretty hard to implement anyway - I think the call would be for a legend like above? It seems writing a legend subclass would be possible as well. |
Well, if the |
And then going off @jklymak 's suggestion, use something like ax.sclegend() (yes have no idea how to name this) that subclassess legend and will generate off norm and cmap info? I'm tentatively not opposed to that approach... |
I really think the colorbar is the wrong tool for this, and a specialized legend (a separate function that calls legend, not more kwargs for the existing legend) is the appropriate tool. Similarly, I am strongly opposed to trying to pile any more functionality of this sort directly into imshow and similar functions. |
I agree that colorbar is the wrong tool, but I tink his wouldn't actually require any new kwargs to be passed to legend since the cmap and norm can be obtained via handle or axes inspection, same as current legend. When thinking through this on the unit side, the implementation would probably be on the norm/cmap side of things any which way since that's probably the way to generalize it to all ScalerMappable. But what I'd want on the units side is a "default norm" of sorts, like the locator and formatter. So if people are using categorical data, they're also using categorical norm unless they explicitly change it. That would give me the "norming for free" and probably wouldn't require any changes to AxesImage or the like. |
I presume the norm would map a list of strings to consecutive integers starting at zero, so that these integers would directly index into a discrete colormap. The user would have to choose a map with a suitable (presumably small) number of well-distinguished colors--something like one of the color sets used for plotting lines. There would be no concept of "over" and "under"; strings not in the list supplied to the norm would be in the "bad" category, for which a color (or full transparency) can be specified in the colormap. |
So thinking through this even more, the most straightforward way to do this at first would probably be to attach a convertor to NoNorm |
Carrying on the discussion in #18139: it seems to me the sticking point is still that I've never seen someone store a 2-D array of strings. If I have seen two-D arrays of "categories" they have been integer arrays with appropriate metadata stating the integer-category mapping. Are 2-D arrays of string objects something anyone has actually wanted to work with? It seems working this up as a standalone package would help show its utility for the core library. I don't see what's preventing a standalone package that is at least of proof of concept. |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
In #6934 (categorical colormapping), I'm trying to add support for imshow visualizing arrays of strings ('cause strings are data...) and then creating the associated colorbar and eventually a legend.
What I've run headlong into (and has created spaghetti code) is that imshow doesn't support unit conversions, which sort of makes sense as norms dictate how things should be colored but it also creates this weird circular dependencies of sorts on how the data gets coded when it's time to also set up the colorbars 'cause of how ticks/locators are done there (still super confused on all that).
I'd really like to add that sort of "unit" knowledge to imshow (or its underlying object).
The plan is to:
Edit: Can't decide the name 'cause this is an issue for anything that takes a colorbar, which is both the AxesImage objects and stuff like scatter.
2) use units in the underlying imshow code in the manner it's currently used in the plot code.
I think this could also maybe be used to later refactor the colorbar code or norms or something. And possibly codifying what's the defaults for floats and ints and the like-basically unit becomes a stylesheet of sorts for data.
The text was updated successfully, but these errors were encountered: