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
Add PiecewiseLinearNorm #4666
Closed
Closed
Add PiecewiseLinearNorm #4666
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
7e93605
ENH: Add OffsetNorm and tests
phobson 5e7c187
fix OffsetNorm docstring to numpydoc spec
phobson 9a0b603
OffsetNorm blurb in whats_new
phobson fd9e624
removed OffsetNorm.inverse method
phobson 633505d
attempting to create a baseline image
phobson ab11380
fix bad indexing when returning a scalar
phobson fa57cdd
the real test image
phobson 9a01b9f
refactor tests a bit to handle non-invertable Norms
phobson 1d8eb25
OffsetNorm -> PiecewiseLinearNorm
dopplershift 57ca4fa
Merge branch 'add-asym-norm'
dopplershift 2919b53
Propagate mask from input data
jkseppan bfc96a6
Remove unused clip parameter
jkseppan 58c505c
Use process_value in PiecewiseLinearNorm
jkseppan b069a94
Return a scalar when passed in a scalar
jkseppan fc8ce8c
Return 0.5 for vcenter == vmax
jkseppan 426353c
pep8 fixes
jkseppan ebd3753
Merge pull request #2 from jkseppan/add-asym-norm
dopplershift File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -225,6 +225,7 @@ def rgb2hex(rgb): | |
a = '#%02x%02x%02x' % tuple([int(np.round(val * 255)) for val in rgb[:3]]) | ||
return a | ||
|
||
|
||
hexColorPattern = re.compile("\A#[a-fA-F0-9]{6}\Z") | ||
|
||
|
||
|
@@ -963,6 +964,93 @@ def scaled(self): | |
return (self.vmin is not None and self.vmax is not None) | ||
|
||
|
||
class PiecewiseLinearNorm(Normalize): | ||
""" | ||
A subclass of matplotlib.colors.Normalize. | ||
|
||
Normalizes data into the ``[0.0, 1.0]`` interval. | ||
""" | ||
def __init__(self, vmin=None, vcenter=None, vmax=None, clip=False): | ||
"""Normalize data with an offset midpoint | ||
|
||
Useful when mapping data unequally centered around a conceptual | ||
center, e.g., data that range from -2 to 4, with 0 as the midpoint. | ||
|
||
Parameters | ||
---------- | ||
vmin : float, optional | ||
The data value that defines ``0.0`` in the normalized data. | ||
Defaults to the min value of the dataset. | ||
|
||
vcenter : float, optional | ||
The data value that defines ``0.5`` in the normalized data. | ||
Defaults to halfway between *vmin* and *vmax*. | ||
|
||
vmax : float, optional | ||
The data value that defines ``1.0`` in the normalized data. | ||
Defaults to the the max value of the dataset. | ||
|
||
clip : bool, optional (default is False) | ||
If *clip* is True, values beyond *vmin* and *vmax* will be set | ||
to ``0.0`` or ``1.0``, respectively. Otherwise, values outside | ||
the ``[0.0, 1.0]`` will be returned. | ||
|
||
Examples | ||
-------- | ||
>>> import matplotlib.colors as mcolors | ||
>>> offset = mcolors.PiecewiseLinearNorm(vmin=-2., vcenter=0., vmax=4.) | ||
>>> data = [-2., -1., 0., 1., 2., 3., 4.] | ||
>>> offset(data) | ||
array([0., 0.25, 0.5, 0.625, 0.75, 0.875, 1.0]) | ||
|
||
""" | ||
|
||
self.vmin = vmin | ||
self.vcenter = vcenter | ||
self.vmax = vmax | ||
self.clip = clip | ||
|
||
def __call__(self, value, clip=None): | ||
if clip is None: | ||
clip = self.clip | ||
|
||
result, is_scalar = self.process_value(value) | ||
|
||
self.autoscale_None(result) | ||
vmin, vcenter, vmax = self.vmin, self.vcenter, self.vmax | ||
if vmin == vmax == vcenter: | ||
result.fill(0) | ||
elif not vmin <= vcenter <= vmax: | ||
raise ValueError("minvalue must be less than or equal to " | ||
"centervalue which must be less than or " | ||
"equal to maxvalue") | ||
else: | ||
vmin = float(vmin) | ||
vcenter = float(vcenter) | ||
vmax = float(vmax) | ||
if clip: | ||
mask = ma.getmask(result) | ||
result = ma.array(np.clip(result.filled(vmax), vmin, vmax), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If clip is true, result is assigned here, but it's assigned again below. |
||
mask=mask) | ||
|
||
x, y = [vmin, vcenter, vmax], [0, 0.5, 1] | ||
# returns a scalar if shape == (1,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't seem to hold at least for numpy 1.9.2:
|
||
result = np.ma.masked_array(np.interp(value, x, y)) | ||
|
||
return result | ||
|
||
def autoscale_None(self, A): | ||
' autoscale only None-valued vmin or vmax' | ||
if self.vmin is None and np.size(A) > 0: | ||
self.vmin = ma.min(A) | ||
|
||
if self.vmax is None and np.size(A) > 0: | ||
self.vmax = ma.max(A) | ||
|
||
if self.vcenter is None: | ||
self.vcenter = (self.vmax + self.vmin) * 0.5 | ||
|
||
|
||
class LogNorm(Normalize): | ||
""" | ||
Normalize a given value to the 0-1 range on a log scale | ||
|
Binary file added
BIN
+78.4 KB
lib/matplotlib/tests/baseline_images/test_colors/test_offset_norm.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
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.
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 parameter actually has no effect. Seems to me that (at least in numpy 1.9.2)
np.interp
always does clipping: