Repository navigation
Description
[Matplotlib version 1.5.2 on Python 3.5.2, installed from MacPorts on Mac OS X 10.9.6]
I have a function for producing a standalone colour-bar and the matching normalizer, to facilitate saving array images to files:
def fieldCB(field, label = None, scale = 'lin', sym = False, **kwargs):
"""Return a colorbar figure for the given field."""
min = field.min()
max = field.max()
if sym:
if -min > max: max = -min
else: min = -max
fcb = plt.figure(figsize = (3,4), frameon = False)
if scale == 'log':
af = np.abs(field)
amin = af[af!=0].min()
amax = af[af<=inf].max()
cbnorm = clr.SymLogNorm(linthresh = amin, linscale = amin/amax,
vmin = min, vmax = max)
else:
cbnorm = clr.Normalize(vmin = min, vmax = max)
c = cb.ColorbarBase(fcb.add_subplot(132), norm = cbnorm, format = '% g')
if label: c.set_label(label)
return fcb, cbnorm
However, when called with the 'log' scale option, i get an error:
File "/Users/arobinson/Dropbox/escsim_wip/simesc/draw.py", line 532, in fieldCB
c = cb.ColorbarBase(fcb.add_subplot(132), norm = cbnorm, format = '% g')
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/colorbar.py", line 323, in __init__
self.draw_all()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/colorbar.py", line 344, in draw_all
self._process_values()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/colorbar.py", line 675, in _process_values
b = self.norm.inverse(self._uniform_y(self.cmap.N + 1))
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/matplotlib/colors.py", line 1154, in inverse
val = val * (self._upper - self._lower) + self._lower
AttributeError: 'SymLogNorm' object has no attribute '_upper'
The reason appears to be that these attributes (self._upper and self._lower) are only created during calls to SymLogNorm._transform_vmin_vmax, which is not called during SymLogNorm.__init__. Calling it manually (by adding cbnorm._transform_vmin_vmax() after the instantiation) seems to resolve the problem.
On a mostly unrelated note, the resulting colour-bars seem to enjoy having all their ticks unpleasantly crowded together on either end. Scaling the tick locations logarithmically as well would be preferable. (No pressure; I can probably do it manually; my weird fidgeting with the threshold is probably making it worse, anyways.)
Edit: From looking into the code some more, it looks as if there is some intention is that the object calibrates itself when called on an array, whereas I had been under the impression that this would only produce a normalized array, leaving the normalizer unaffected. SymLogNorm._transform_vmin_vmax is called during this process. Use of this property should simplify things for me either way.
Activity
tacaswell commentedon Jul 17, 2016
All of the
Normobjects try to be friendly and pick their own limits based on the first array it is called with if not specified. typically the norms have been called at least once with an array as part of the draw process.I suspect the fix is something like adding a check in
SymLog's__init__that if both vmin and vmax are specified to call_transform_vmin_vmax().Want to take a shot at it? Your example is an almost perfect test.
aWinglessMonkey commentedon Jul 17, 2016
I could try, but it would be directly through GitHub, copy-pasted from edits to the package installed here.
Call _transform_vmin_vmax during SymLogNorm.__init__
aWinglessMonkey commentedon Jul 17, 2016
Well, that was easier than I remembered.
dstansby commentedon Jul 21, 2019
It looks like this was fixed, so I'm going to close. Feel free to comment or re-open if I've missed something.