Custom limits to MappedColormaps - #246
Open
vbrennsteiner wants to merge 2 commits into
Open
Conversation
…stom limits instead of fixed, data-derived limits; add fit/transform pattern to MappedColormaps: leaves current functionality as is but allows for transforming a datarange to colors WITHOUT refitting the color scale to the data range - e.g. we now can fit the colorscale on the 0-1 range and fit arrays ranging from e.g. 0.3-0-95 as well as 0.01 - 0.89 to exactly the same values
mschwoer
reviewed
Jul 7, 2026
| of RGBA tuples. | ||
| vmin : float, optional | ||
| Minimum value for normalization when values is an array. If None, uses the minimum of the array. | ||
| vmax : float, optional |
Contributor
There was a problem hiding this comment.
I read "maximum velocity here" :-D
min/max_value?
|
|
||
| vmin, vmax = np.nanmin(values), np.nanmax(values) | ||
| if vmin is None: | ||
| vmin = np.nanmin(values) |
Contributor
There was a problem hiding this comment.
(nit)
vmin = vmin if vmin is not None else np.nanmin(values)
|
|
||
| if self.vmin is None or self.vmax is None: | ||
| raise ValueError("fit() requires `data`, or both `vmin` and `vmax`, to set the bounds.") | ||
| return self |
Contributor
There was a problem hiding this comment.
do we need to return something?
| return colormap | ||
|
|
||
|
|
||
| class MappedColormaps: |
Contributor
There was a problem hiding this comment.
I think we should move all colormap-related code into a dedicated module
Comment on lines
900
to
912
| if self.percentile is not None: | ||
| self.vmin = np.nanpercentile(data, self.percentile[0]) | ||
| self.vmax = np.nanpercentile(data, self.percentile[1]) | ||
| else: | ||
| self.vmin = np.nanmin(data) | ||
| self.vmax = np.nanmax(data) | ||
|
|
||
| data = np.clip(data, self.vmin, self.vmax) | ||
|
|
||
| rgba = _get_colors_from_cmap(self.cmap, data) | ||
|
|
||
| if as_hex: | ||
| return np.apply_along_axis(mpl_colors.to_hex, -1, rgba, keep_alpha=True) |
Contributor
There was a problem hiding this comment.
shouldn't fit_transform() just call fit() and transform() now?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem addressed by this PR:
A common task of depicting numerical data is mapping values to colors along a consecutive gradient using a colorbar legend. This presents a key challenge: both the scatterplot and the colorbar need to "know" which data value should be mapped to which color. This is commonly solved with a
matplotlib.ScalarMappable, which can map a numerical array to a range of colors.Our
MappedColormapscan produceScalarMappableinstances with the added benefit of adding a percentile cutoff to the upper and lower ends, providing a solution to outliers dominating the scale and compressing the color mapping of other points (see basic plotting tutorial notebook).However, until now, MappedColormaps had a key problem that made it insufficient for producing reusable color mappings: it always mapped the colormap to between the lowest and highest point of the actual data, with no way of setting custom limits. This makes it awkward to produce colorbars, since they start and end at serendipitous values, and it was impossible to fit a colormap to between suitable bounds and easily apply that mapping to data values to be used e.g. in the
color_columnargument of scatter plots, since any call tofit_transformwould automatically reset the mapping.Fix:
This PR fixes those limitations by 1.) adding a
vminandvmaxargument toMappedColormaps.fit_transformto solve the issue with non-ideal ranges, and 2.) adding aMappedColormaps.transform()method that only applies an existing scale to data, without re-fitting to the data's scale.Notes:
Existing functionality of MappedColormaps stays untouched, and unit tests cover the new functionality; additionally, a
.fitmethod has been added to fit data + custom vmin/vmax values, completing the sklearn-like 'fit/transform/fit_transform' interface.