Skip to content

[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

Open
story645 opened this issue Nov 2, 2016 · 30 comments
Open

[ENH] Unit support for ScalarMappables #7383

story645 opened this issue Nov 2, 2016 · 30 comments

Comments

@story645
Copy link
Member

story645 commented Nov 2, 2016

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:

  1. extend the AxisInfo object in units.py with the default norm, colormap, and cbar locators/formatters or to create another object SMInfo or something that stores that info.

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.

@story645 story645 changed the title [ENH] Unit support for ScalerMappables [ENH] Unit support for AxesImage Nov 3, 2016
@story645 story645 changed the title [ENH] Unit support for AxesImage [ENH] Unit support for ScalerMappables Nov 3, 2016
@tacaswell tacaswell added this to the 2.1 (next point release) milestone Nov 4, 2016
@kahnchana
Copy link
Contributor

kahnchana commented Mar 31, 2017

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.

@story645
Copy link
Member Author

Look through the normalization, colormap, and colorbar code.

@kahnchana
Copy link
Contributor

Should I fork the matplotlib code or the code you've worked on when doing this?

@story645
Copy link
Member Author

matplotlib

@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Sep 24, 2017
@story645
Copy link
Member Author

story645 commented Feb 4, 2018

@jklymak I dunno if this should be thought through as part of a units MEP or built on top of one, but mostly fyi.

@jklymak
Copy link
Member

jklymak commented Feb 4, 2018

Cool. OTOH I personally think this should just be its own method versus something that gets tacked into imshow, so I wouldn't write that part of the MEP 😉 But thats just my vote....

@story645
Copy link
Member Author

story645 commented Feb 4, 2018

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)

@jklymak
Copy link
Member

jklymak commented Feb 4, 2018

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.

@jklymak
Copy link
Member

jklymak commented Feb 4, 2018

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.

@story645
Copy link
Member Author

story645 commented Mar 26, 2018

cc @dopplershift the categorical SM task I have in mind is something like this:
stas
using code that would look something like:

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.

@efiring
Copy link
Member

efiring commented Mar 27, 2018

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.
Echoing @jklymak, it seems like the way to do all this is via helper functions. I don't think it should involve any changes to imshow or colorbar or ScalarMappable. But maybe I am missing something.

@story645
Copy link
Member Author

@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.

@dopplershift
Copy link
Contributor

@efiring I didn't even know that NoNorm was a thing--which is probably because it's not demonstrated in any of our documentation.

@jklymak jklymak changed the title [ENH] Unit support for ScalerMappables [ENH] Unit support for ScalarMappables Mar 27, 2018
@efiring
Copy link
Member

efiring commented Mar 27, 2018

@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?

@story645
Copy link
Member Author

story645 commented Mar 27, 2018

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?

@jklymak
Copy link
Member

jklymak commented Mar 27, 2018

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!

@efiring
Copy link
Member

efiring commented Mar 27, 2018

And even if there are, I would leave it to the user to do the conversion to numbers for plotting.

@story645
Copy link
Member Author

@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.

@jklymak
Copy link
Member

jklymak commented Mar 27, 2018

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 CategoryNorm rather than implimenting units? The norm would take values, and check that they are strings and return the mapping into the list. Yeah, it wouldn't be magic, but its sure a lot easier than adding norm selection to the units bag of tricks.

@dopplershift
Copy link
Contributor

I kind of like the idea of a CategoryNorm...but would that get the automated labels for the colorbar?

@story645
Copy link
Member Author

story645 commented Mar 27, 2018

So I tried doing that in #6934 and it quickly became spaghetti...

I kind of like the idea of a CategoryNorm...but would that get the automated labels for the colorbar?

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?

@jklymak
Copy link
Member

jklymak commented Mar 27, 2018

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.

@dopplershift
Copy link
Contributor

Well, if the CategoryNorm had the inverse mapping, you could run the tick values back through it...

@story645
Copy link
Member Author

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...

@efiring
Copy link
Member

efiring commented Mar 28, 2018

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.

@story645
Copy link
Member Author

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.

@efiring
Copy link
Member

efiring commented Mar 28, 2018

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.

@story645
Copy link
Member Author

So thinking through this even more, the most straightforward way to do this at first would probably be to attach a convertor to NoNorm

@jklymak
Copy link
Member

jklymak commented Jul 31, 2020

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.

@github-actions
Copy link

github-actions bot commented Apr 2, 2023

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!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Apr 2, 2023
@story645 story645 added keep Items to be ignored by the “Stale” Github Action and removed status: inactive Marked by the “Stale” Github Action labels Apr 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants