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.