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.
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
There was a problem hiding this comment.
I am a bit confused about how I expect this to behave...
|
I am a bit concerned about the inverse tests: In [14]: nn = mc.DivergingNorm(0, 1, 10)
In [15]: nn.inverse(nn(np.arange(10))) == np.arange(10)
Out[15]:
masked_array(data = [ True False False False False False False False False False],
mask = False,
fill_value = True) |
|
If I add the inverse function back in the color bar does not work correctly even with import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
x = np.linspace(-2, 7)
y = np.linspace(-1*np.pi, np.pi)
X, Y = np.meshgrid(x, y)
Z = x * np.sin(Y)**2
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(9, 3))
cmap = plt.cm.coolwarm
norm = mcolors.DivergingNorm(vmin=-2, vcenter=0, vmax=7)
img1 = ax1.imshow(Z, cmap=cmap, norm=None)
cbar1 = fig.colorbar(img1, ax=ax1)
img2 = ax2.imshow(Z, cmap=cmap, norm=norm)
cbar2 = fig.colorbar(img2, ax=ax2)
img3 = ax3.imshow(Z, cmap=cmap, norm=norm)
cbar3 = fig.colorbar(img3, ax=ax3, spacing='proportional')attn @efiring def inverse(self, value):
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)
# in degenerate cases, prefer the center value to the extremes
degen = (result == vcenter) if vcenter == vmax else None
x, y = [vmin, vcenter, vmax], [0, 0.5, 1]
result = ma.masked_array(np.interp(result, y, x),
mask=ma.getmask(result))
if degen is not None:
result[degen] = 0.5
if is_scalar:
result = np.atleast_1d(result)[0]
return result
|
|
@efiring I have sunk another few hours into trying to understand the color bar code and am still failing 😞 (but I am getting closer!). It looks like |
|
I think the problem is that for |
|
@tacaswell, the use of inverse is deliberate; I found I needed it when I added LogNorm. It allows one to find the boundaries in data space corresponding to a linear increase in plot space. This is critical. I'm puzzled as to why the inverse inherited from Normalize seems to be giving a reasonable result. Please give me a little time to figure this out. I agree that the colorbar code is very hard to follow, even for me, who wrote most of it many years ago. |
|
Looking at #5061, I think I understand: the picture you are showing is with the inverse, and #5061 is showing the picture without the inverse. Well, the picture with the inverse is correct in the sense that it is consistent with colorbar's logic--it just isn't what you expect or want. Consider the case of a more extreme norm, the LogNorm: if you were to put in linearly-selected tick values, they would be all bunched together at one end. |
|
Hmm, yes, colorbar code, I took a look at it last night when working on the @efiring @tacaswell you should feel happy to note that I have a plan on refactoring the colorbar. While the code still lay clear in my mind of the parts of colorbar that I looked at (the last |
|
I am starting to think that getting this in for 1.5 is a bigger can of worms than anticipated. |
|
Due to the issues with the inverse and the colorbar, punting this to the next release. |
|
On 2015/09/14 5:50 AM, Thomas A Caswell wrote:
Good move. I don't see it as urgent. |
|
Okay, I now understand the inverse thing in So the solution lies into seperating this conflation of scales into the two distinct scales, something I had planned for MEP29, but didn't realise until now just how significantly this refactor plays into this issue. |
|
This seems to have died an untimely death. Does anyone want to champion? |
|
How about making such thing a wishlist item or something similar, to make it something that can get picked up, but doesn't count as a blocker for release. |
|
Moved to #12419.... |

Renamed and rebased version of #4666