hexbin log bins and colorbar

OK, at least now we are running the sample example :slight_smile:

The problem is that the LogFormatter has a default which is
"decadeOnly=True" and in the first case which "worked" three of the
tick locations coincidentally came down on decades (0, 1, 2 -> 1, 10,
100). In the case you were working with, only one of the ticks mapped
to the decade.

So for this case we want a locator that returns integers 0,1,2... that
will then get mapped via Eric's custom formatter to the 10^i formats.
Unfortunately, there is no easy way to set the locator for the
colorbar. An easy workaround *for this case* is to simply set the
tick locations

  cb = plt.colorbar(format=LogFormatterHB(), ticks=[0,1,2])

but in general you may not know the decade span that you need. It
does all feel a bit kludgy. The problem as you noted in one of your
earlier posts is that the data is log scaled before being passed into
the PolyCollection and the fact that it is log scaled is then lost to
the colorbar. It seems everything would fit together more naturally
if we passed in raw scalar data to the PolyCollection and set the norm
to be colors.LogNorm, and then also set norm=colors.LogNorm on the
colorbar

I tried:

  polycol = plt.hexbin(data['jetMomentum'][cut] / 1000,
data['deltaR'][cut],gridsize=50, norm=colors.LogNorm())
  cb = plt.colorbar(norm=colors.LogNorm())

but this appears to be broken:

msierig@...2993...:Downloads> python test.py
Traceback (most recent call last):
  File "test.py", line 29, in <module>
    cb = plt.colorbar()
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/pyplot.py",
line 1356, in colorbar
    ret = gcf().colorbar(mappable, cax = cax, ax=ax, **kw)
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/figure.py",
line 1103, in colorbar
    cb = cbar.Colorbar(cax, mappable, **kw)
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 690, in __init__
    ColorbarBase.__init__(self, ax, **kw)
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 242, in __init__
    self.draw_all()
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 260, in draw_all
    self._config_axes(X, Y)
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 332, in _config_axes
    self.update_ticks()
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 271, in update_ticks
    ticks, ticklabels, offset_string = self._ticker()
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/colorbar.py",
line 458, in _ticker
    b = np.array(locator())
  File "/home/msierig/dev/lib/python2.6/site-packages/matplotlib/ticker.py",
line 1173, in __call__
    vmin = self.axis.get_minpos()

···

On Mon, Feb 22, 2010 at 3:42 PM, Jan Strube <curiousjan@...287...> wrote:

Hi John,
the attachment may not make it to the list. However, please run the modified
test.py that I have attached.
It requires the attached input file.
Then change it to read the original input file.
In my case:
The broken case:

I committed some changes to support this -- the following now works:

  polycol = plt.hexbin(data['jetMomentum'][cut] / 1000,
data['deltaR'][cut],gridsize=50, norm=colors.LogNorm())

  cb = plt.colorbar(norm=polycol.norm)

Eric - I was surprised the colorbar does not use the mappable norm by
default (if passed norm=None). Instead it uses ::

  norm = colors.Normalize()

is this a feature?

JDH

···

On Mon, Feb 22, 2010 at 4:33 PM, John Hunter <jdh2358@...287...> wrote:

polycol = plt.hexbin(data['jetMomentum'][cut] / 1000,
data['deltaR'][cut],gridsize=50, norm=colors.LogNorm())
cb = plt.colorbar(norm=colors.LogNorm())

but this appears to be broken:

John Hunter wrote:

polycol = plt.hexbin(data['jetMomentum'][cut] / 1000,
data['deltaR'][cut],gridsize=50, norm=colors.LogNorm())
cb = plt.colorbar(norm=colors.LogNorm())

but this appears to be broken:

I committed some changes to support this -- the following now works:

  polycol = plt.hexbin(data['jetMomentum'][cut] / 1000,
data['deltaR'][cut],gridsize=50, norm=colors.LogNorm())

  cb = plt.colorbar(norm=polycol.norm)

Eric - I was surprised the colorbar does not use the mappable norm by
default (if passed norm=None). Instead it uses ::

  norm = colors.Normalize()

is this a feature?

Yes. You are looking at ColorbarBase, which does not have an associated mappable. The derived Colorbar class does grab the cmap and norm from the mappable used in the initialization. Is this somehow not working? Did you really need to specify the norm explicitly?

Eric

···

On Mon, Feb 22, 2010 at 4:33 PM, John Hunter <jdh2358@...287...> wrote:

JDH

Hi John,

thanks for keeping at it. I have updated from svn

But this script

import matplotlib

matplotlib.use(‘Agg’)

import matplotlib.pyplot as plt

import numpy as np

from matplotlib.ticker import LogFormatter

from matplotlib import colors

class LogFormatterHB(LogFormatter):

def call(self, v, pos=None):

vv = self._base ** v

print vv

return LogFormatter.call(self, vv, pos)

data = np.load(‘deltaR_parton_jet_109370.npz’)

ptcut = np.logical_and(data[‘jetMomentum’] < 300000, data[‘jetMomentum’]>0)

deltaRCut = data[‘deltaR’]>0

cut = np.logical_and(ptcut, deltaRCut)

fig = plt.figure()

polycol = plt.hexbin(data[‘jetMomentum’][cut] / 1000, data[‘deltaR’][cut],

gridsize=50, norm=colors.LogNorm())

plt.title(‘deltaR between parton(eta<2.5) and jet(eta<2.5)’)

plt.xlabel(‘jet pt (GeV)’)

plt.ylabel(‘deltaR’)

cb = plt.colorbar(norm=polycol.norm)

cb.set_label(‘# entries’)

fig.savefig(‘hexbin_demo.png’, dpi=100)

#plt.show()

gives me an error:

python test.py

Traceback (most recent call last):

File “test.py”, line 24, in

cb = plt.colorbar(norm=polycol.norm)

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/pyplot.py”, line 1356, in colorbar

ret = gcf().colorbar(mappable, cax = cax, ax=ax, **kw)

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/figure.py”, line 1104, in colorbar

cb = cbar.Colorbar(cax, mappable, **kw)

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py”, line 649, in init

ColorbarBase.init(self, ax, **kw)

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py”, line 240, in init

self.draw_all()

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py”, line 251, in draw_all

self._config_axes(X, Y)

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py”, line 278, in _config_axes

ticks, ticklabels, offset_string = self._ticker()

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py”, line 417, in _ticker

b = np.array(locator())

File “/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/ticker.py”, line 1085, in call

vmin = self.axis.get_minpos()

AttributeError: DummyAxis instance has no attribute ‘get_minpos’

Cheers,

Jan

···

On Tue, Feb 23, 2010 at 12:26 AM, John Hunter <jdh2358@…287…> wrote:

On Mon, Feb 22, 2010 at 4:33 PM, John Hunter <jdh2358@…287…> wrote:

polycol = plt.hexbin(data[‘jetMomentum’][cut] / 1000,

data[‘deltaR’][cut],gridsize=50, norm=colors.LogNorm())

cb = plt.colorbar(norm=colors.LogNorm())

but this appears to be broken:

I committed some changes to support this – the following now works:

polycol = plt.hexbin(data[‘jetMomentum’][cut] / 1000,

data[‘deltaR’][cut],gridsize=50, norm=colors.LogNorm())

cb = plt.colorbar(norm=polycol.norm)

Eric - I was surprised the colorbar does not use the mappable norm by

default (if passed norm=None). Instead it uses ::

norm = colors.Normalize()

is this a feature?

JDH

Hi John,
thanks for keeping at it. I have updated from svn
But this script
File
"/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py",
line 278, in _config_axes
ticks, ticklabels, offset_string = self._ticker()
File
"/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/colorbar.py",
line 417, in _ticker
b = np.array(locator())
File
"/Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib-1.0.svn_r8037-py2.6-macosx-10.6-universal.egg/matplotlib/ticker.py",
line 1085, in __call__
vmin = self.axis.get_minpos()
AttributeError: DummyAxis instance has no attribute 'get_minpos'

Take a look at the file name in the traceback: matplotlib-1.0.svn_r8037

The r8037 is the svn revision number. According the svn log, I made
my commit on r8149, so you are not running HEAD. You may have
multiple matplotlib's installed and are not picking up the right egg.
I recommend

  > rm -rf /Users/Jan/PYTHON/lib/python2.6/site-packages/matplotlib*

and then doing a clean install from mpl svn r8149 or later.

JDH

···

On Tue, Feb 23, 2010 at 4:12 AM, Jan Strube <curiousjan@...287...> wrote:

No, I didn't test this, I just read the code (apparently the wrong
code) and concluded I needed it. I did just test w/o it and all is
well. Sorry for the noise.

JDH

···

On Mon, Feb 22, 2010 at 6:28 PM, Eric Firing <efiring@...202...> wrote:

Yes. You are looking at ColorbarBase, which does not have an associated
mappable. The derived Colorbar class does grab the cmap and norm from the
mappable used in the initialization. Is this somehow not working? Did you
really need to specify the norm explicitly?

Gentlemen!

Thanks a lot for your help.

This works now for me (with and without the norm in the colorbar() call)

Best,

Jan

···

On Tue, Feb 23, 2010 at 3:47 PM, John Hunter <jdh2358@…287…> wrote:

On Mon, Feb 22, 2010 at 6:28 PM, Eric Firing <efiring@…202…> wrote:

Yes. You are looking at ColorbarBase, which does not have an associated

mappable. The derived Colorbar class does grab the cmap and norm from the

mappable used in the initialization. Is this somehow not working? Did you

really need to specify the norm explicitly?

No, I didn’t test this, I just read the code (apparently the wrong

code) and concluded I needed it. I did just test w/o it and all is

well. Sorry for the noise.

JDH