-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Add PiecewiseLinearNorm #4666
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
Conversation
Borrows heavily from @Tillsen's solution found on StackOverflow here: http://goo.gl/RPXMYB Used with his permission dicussesd on Github here: https://github.com/matplotlib/matplotlib/pull/3858`
This will allow the ticks of colors to be spaced as desired. Also simplified the math per the brilliant @joferkington http://stackoverflow.com/a/20146989/1552748
couldn't actually run the test suite b/c python iesn't installed as a framework.
I have tested the numpy issue and it looks like it has been like this since at least 1.6.0 |
|
I am a bit nervous that the inverse was removed. |
Any update on this? |
I will take a look at this tomorrow and see what I can add. Should I make a PR to merge into this branch, or work on top of this in a separate PR? |
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) |
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:
In [34]: np.interp(np.arange(10), [4, 5, 6], [0, 0.5, 1])
Out[34]: array([ 0. , 0. , 0. , 0. , 0. , 0.5, 1. , 1. , 1. , 1. ])
Need to allow it in __call__ since colorbar can pass a value for clip.
To make it more similar to the other norms Also remove misleading comment about returning scalars
Since possibly some earlier versions of numpy returned a scalar, wrap the value in atleast_1d before indexing.
np.interp handles the case vmin == vcenter, we have to add a special case to make the last test case pass
I added some suggestions on my branch, also submitted as a pull request to @dopplershift's branch. |
just looked at it dopplershift#2 but we still lack the generality... I think the API should read: def __init__(self, stops, clip=False): We need stops as a kind of dictionary, not too sure on that yet. Whether class CenteredLinearNorm(PiecewiseLinearNorm):
def __init__(self, vmin, vcenter, vmax, clip=False):
stops = [(0., vmin), (0.5, vcenter), (1., vmax)]
PiecewiseLinearNorm.__init__(self, stops, clip)
|
I also started working on this a while ago, but got distracted. I was envisioning an API something like |
@tacaswell Any reason why you have them as two separate lists? We have a 1:1 mapping, this would require an extra check that the two lists have equal lengths, and if we have two lists, we can easily put them into ordered dict format with |
Because they have different units and because there are less ways to input If we take a list of tuples then we also need to take a 2D arrays, which Also, this matches the underlying On Thu, Sep 3, 2015 at 11:32 AM OceanWolf notifications@github.com wrote:
|
Well I don't see different units as a problem... it underpins the whole definition of a dict {'time': 5}, string, int. With "more ways to input it wrong" I think I see why you say that, because you think in terms of a list of tuples, but as I say we should think of it instead as passing in an def __init__(self, stops, clip=False):
stops = OrderedDict(stops) # will raise a ValueError on bad data
stops = OrderedDict(sorted(stops.items(), key=lambda t: t[0])) # sort keys
map_points, data_points = stops.keys(), stops.values() # get data ready for np.interp
if not np.all(np.diff(data_points) > 0):
raise ValueError("stops must increase monotonically") We need far simpler error checking here because we utilize ordered dicts, this also makes the class a lot more useful as we simply duck-type the data input based on its dict-like structure. Anything that can get cast to a dict, we accept. While we don't support OrderedDict yet because of our support for python-2.6 we can for now cast to an ordinary dict and then extract and work internally with a list of tuples, this casting to a dict will mean we can also accept OrederedDicts right now, but internally handle them a bit more clumsily until we drop support for 2.6. |
Are you sure there is a use case for a general piecewise linear mapping? Centering a diverging colormap's neutral color on a specific data value makes a lot of sense to me, but I'm not so sure about the more general case. |
@jkseppan I thought earlier about this earlier today, and I wondered about our accent colour map (a qualitative one), that might work well with data sources where we want to see the local variation, but the data contains big jumps in the data which would drown out that local variation otherwise... |
@dopplershift was very excited about this for meteorology where they have color maps with multiple natural break points. The other canonical use case would be to correctly map |
@dopplershift @jkseppan This needs a rebase. If this turns back into just a centered norm for now, that is cool it just needs to be renamed. |
It seems that the problem with #3858 was finding a fitting name for the norm, and people liked PiecewiseLinearNorm, but that suggests more generality than implemented here. How about DivergingNorm, since it's likely to get used with a diverging colormap? Then we can later implement the more general case as PiecewiseLinearNorm if needed. |
I have just started on the generic version of this, we shall see how far I get... |
Sold on diverging norm On Sun, Sep 13, 2015, 10:08 OceanWolf notifications@github.com wrote:
|
closing in lieu of #5054 |
Renamed version of #3858.
Tests are failing on my machine due to my numpy 1.9.2
interp
dropping masked arrays:I see:
no mask