Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
DOC: draft of a full explanation of norm + colormap interactions#18487
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Conversation
80b7c57
to9d22732
CompareUh oh!
There was an error while loading.Please reload this page.
doc/api/image_api.rst Outdated
scaled = (resampled - .1) * (data_max - data_min) + data_min | ||
For "most" user data is OK, but can fail in interesting ways. First, | ||
if range of the input data is large, but the range the user actually |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
"if the range"
So far, it looks like this includes pretty useful info at good places in the docs. However, I suggest being more colloquial. I guess you could describe a colormap as a 1-D path through R^3 space, but maybe "a list of N colors specified as RGB" will be more accessible? It took me a while to understand what you were trying to say, and my undergrad degree was Mathematics and Physics, albeit a few years ago ;-) |
Uh oh!
There was an error while loading.Please reload this page.
doc/api/colors_api.rst Outdated
the data <sphx_glr_tutorials_colors_colormaps.py>` but in general | ||
"good" colormaps smoothly and continuously change their RGB values as | ||
a function of the input data. By looking at the RGB values as we go | ||
through the full range of the user data (e.g. a colorbar) we can trace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Not sure what a colorbar has to do with this sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Also the "good" in parenthesis is probably a stand in for some precise term and otherwise not true for categorical data and questionable on discrete data.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
max of the data are drastically different than the vmin / vmax of the | ||
norm we use a data range expanded from vmin/vmax in the rescaling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This sentence kind of runs on.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
doc/api/colors_api.rst Outdated
class in `~.cm` and the `~.Normalize` and `~.Colormap` classes in | ||
`~.colors` (this module). | ||
At the core, colormapping is going from a scalar value to a RGB tuple |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I still feel this is more complicated than it needs to be, and not even particularly true if you want to be mathematically rigorous; colormaps are finite discrete ordered points in R^3, not a smooth curve or path, so I find taking about it like this distracting. The first step is normalizing the data between vmin and vmax to the range 0-1, perhaps using a non-linear function, and secondly, using a linear lookup table to find the RGBA color closest to that value between 0 and 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I always like code examples to make the abstract concrete:
A color mapping from floating point data values to colors takes place in two steps. First the data is normalized between 0 and 1. This requires a `vmin` and `vmax` the define which values are mapped to 0 and 1, respectively, and it requires a function that defines the mapping between these two values. The simplest case is a linear map :: import matplotlib.colors as mcolorsnorm = mcolors.Normalize(vmin=100, vmax=300) norm([100, 200, 300]) # returns 0.0, 0.5, 1.0but a logarithmic norm is also possible :: norm = mcolors.LogNorm(vmin=10, vmax=1000)norm([10, 100, 1000]) # returns 0.0, 0.5, 1.0Once the data has been normalized between 0 and 1, it can be passed to a colormap to return RGB(A) values ::cmap = cm.viridiscmap([0.0, 0.5, 1.0]) # returns RGBA array with the first three colors of viridis colormap. # array([[0.267004, 0.004874, 0.329415, 1. ], # [0.127568, 0.566949, 0.550556, 1. ], # [0.993248, 0.906157, 0.143936, 1. ]])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
We use discrete colormaps as an implementation detail (both for performance and because we are targeting 8bit RGB which is inherently discrete), but if we had infinite precision floats and an analytic function for the colormap the whole system would still hold together.
I think the correct solution is to include both versions :)
55c6446
tocbe0c6e
Comparecbe0c6e
to0478be2
CompareThis make it clearer that we only need this in one of the code pathsand avoids creating the un-used ScalarMappable in the png savefig codepath.
Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
0478be2
to317a6af
Comparethe colors_api.rst file is probably ready for a re-review, but I have not come back to the image_api.rst text yet. |
Normalization and Colormapping of Continuous Data | ||
------------------------------------------------- | ||
Some `~.artist.Artist` classes can map an array of input data to RGBA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
There is a TOC aspect to this file, and then you've added an explanation. a) not 100% sure the explanation belongs here, versus an intermediate/advanced tutorial. Most long-form explanations are tutorials currently (i.e. transform stack). I'm not adamantly advocating for that, but it would be more consistent with current practice. It would also make your examples easier to write.
Regardless, this large narrative in the middle of the TOC makes the TOC very hard to parse. At the very least, this should go at the end?
At the core, colormapping is going from a scalar value to a RGB tuple (formally | ||
:math:`f(x) : ℝ^1 \rightarrow ℝ^3`). To effectively communicate through the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
At the core, colormapping is going from a scalar value to a RGB tuple (formally | |
:math:`f(x) : ℝ^1\rightarrow ℝ^3`). To effectively communicate through the | |
At the core, colormapping is going from a scalar value to a RGB tuple (formally | |
:math:`f(x) : ℝ^1\rightarrowℝ_[0,1]^1\rightarrowℝ^3`). To effectively communicate through the |
At the core, colormapping is going from a scalar value to a RGB tuple (formally | ||
:math:`f(x) : ℝ^1 \rightarrow ℝ^3`). To effectively communicate through the | ||
color we want pick a :ref:`colormap suited to the data | ||
<sphx_glr_tutorials_colors_colormaps.py>`. For continuous data types [#f1]_ a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The outline here is a little non-linear, and seems to take a while before it settles into an order.
- mapping
- choosing colormap
- mapping
- norm
- norm
- colormapping
I think this could all be three paragraphs, or maybe 5 if you want to be expansive:
- overview
- norm step
- colormap step
If you plan to talk about the "Curve through space" I wonder if a diagram would make this much clearer. Expressing this with math formalisms without diagrams is going to lose your audience.
Since this Pull Request has not been updated in 60 days, it has been marked "inactive." This does not mean that it will be closed, though it may be moved to a "Draft" state. This helps maintainers prioritize their reviewing efforts. You can pick the PR back up anytime - please ping us if you need a review or guidance to move the PR forward! If you do not plan on continuing the work, please let us know so that we can either find someone to take the PR over, or close it. |
PR Summary
This is the start of the documentation I said I would write on the call about float issues in resampling / normalizing / colormapping images, but I got distracted making sure that we had this well documented.
The text athttps://matplotlib.org/3.3.1/tutorials/colors/colormapnorms.html is correct, but terse. The code athttps://matplotlib.org/3.3.1/gallery/userdemo/colormap_normalizations.html is almost the same but even less text.https://matplotlib.org/3.3.1/tutorials/colors/colormaps.html is mostly about how to pick the right color map, andhttps://matplotlib.org/3.3.1/tutorials/colors/colormap-manipulation.html is about working with colormap objects once you have them.
I think the second one should probably go away and the first should link back to this new text.