colorbar issue

John and others developers,

I think the current colorbar implementation has some (minor) issue
related with how ticks are treated.

Here is a quick example,

  imshow(np.arange(100).reshape((10,10)))
  cb = colorbar()

This gives you a nice colorbar, However, an issue arises when you want
to change the ticks.

  cax = cb.ax
  cax.set_yticks([0, 40, 80])

And the colorbar got messed up.

Changing ticks and ticklabels after the colobar is created is quite tricky.
And, the easiest solution is to set those when creating the colorbar.

As far as I can see, the real confusion comes fromthe fact that, in
the current colorbar implementation, the data coordinate of the
colorbar axes has nothing to do with the actual color scale.
In the above example, while the color scale ranges from 0 to 99, the
data coordinate (ylim) is still from 0 to 1.

A few months back, I worked on a revised implementation of the
colorbar, and that version of colorbar is currently included in the
axes_grid toolkit. It is backward-compatible, but it uses
"axes_locator" feature that I'm a bit reluctant to push into the
mainline matplotlib.

So, here is a few possible resolutions I consider.

1) leave it as is. but issue a warning when a users calls "set_yticks"
(or its relatives) on the colobar axes.

2) use the reimplemented version of the colorbar, but drop the
axes_locator part. The colorbar will be fully functional except the
"extend" feature (triangles at the ends of the colorbar. see
http://matplotlib.sourceforge.net/examples/api/colorbar_only.html).

3) use the reimplemented version of the colorbar.

4) someone else comes up with a better implementation.

I don't think there is an immediate need for any changes as I see it
as a minor issue.
I'm just posting this as there has been a few recent questions
regarding the colorbar behavior in the user list.

Any suggestion and/or comments?
Regards,

-JJ

Jae-Joon Lee wrote:

John and others developers,

I think the current colorbar implementation has some (minor) issue
related with how ticks are treated.

Here is a quick example,

  imshow(np.arange(100).reshape((10,10)))
  cb = colorbar()

This gives you a nice colorbar, However, an issue arises when you want
to change the ticks.

  cax = cb.ax
  cax.set_yticks([0, 40, 80])

And the colorbar got messed up.

Changing ticks and ticklabels after the colobar is created is quite tricky.
And, the easiest solution is to set those when creating the colorbar.

As far as I can see, the real confusion comes fromthe fact that, in
the current colorbar implementation, the data coordinate of the
colorbar axes has nothing to do with the actual color scale.
In the above example, while the color scale ranges from 0 to 99, the
data coordinate (ylim) is still from 0 to 1.

How do you get around this while supporting both the proportional and the non-proportional modes?

A few months back, I worked on a revised implementation of the
colorbar, and that version of colorbar is currently included in the
axes_grid toolkit. It is backward-compatible, but it uses
"axes_locator" feature that I'm a bit reluctant to push into the
mainline matplotlib.

So, here is a few possible resolutions I consider.

1) leave it as is. but issue a warning when a users calls "set_yticks"
(or its relatives) on the colobar axes.

Based on a quick look, I think that with some refactoring, we could add a set_ticks method. In a way, the question here is whether the colorbar should be thought of as a conventional axes object, or whether it is OK for it to have its own API. I think the latter is more natural, because it is a specialized object; once its orientation is established, there is only one set of ticks and one axis label. Ideally, cbar.ax would be an Axes object stripped down to its essentials; but that would involve major mpl refactoring.

Intercepting calls to set_yticks and set_xticks and replacing them with warnings to use a new set_ticks would be good.

2) use the reimplemented version of the colorbar, but drop the
axes_locator part. The colorbar will be fully functional except the
"extend" feature (triangles at the ends of the colorbar. see
http://matplotlib.sourceforge.net/examples/api/colorbar_only.html).

This is not acceptable. The "extend" feature is essential.

3) use the reimplemented version of the colorbar.

4) someone else comes up with a better implementation.

Regarding 3 or 4, if you or anyone else can come up with a better implementation, preserving at least the present functionality, that's great. The present implementation was a pain to develop and is hard to understand and maintain.

Eric

···

I don't think there is an immediate need for any changes as I see it
as a minor issue.
I'm just posting this as there has been a few recent questions
regarding the colorbar behavior in the user list.

Any suggestion and/or comments?
Regards,

-JJ

How do you get around this while supporting both the proportional and the
non-proportional modes?

I must confess that I never considered that option. And, no, my
current implementation does not support non-proportional mode. So, I
guess syncing the data coordinate with ticks has its own problem.

1) leave it as is. but issue a warning when a users calls "set_yticks"
(or its relatives) on the colobar axes.

Based on a quick look, I think that with some refactoring, we could add a
set_ticks method. In a way, the question here is whether the colorbar
should be thought of as a conventional axes object, or whether it is OK for
it to have its own API. I think the latter is more natural, because it is a
specialized object; once its orientation is established, there is only one
set of ticks and one axis label. Ideally, cbar.ax would be an Axes object
stripped down to its essentials; but that would involve major mpl
refactoring.

Intercepting calls to set_yticks and set_xticks and replacing them with
warnings to use a new set_ticks would be good.

Adding a "set_ticks" method seems reasonable.

2) use the reimplemented version of the colorbar, but drop the
axes_locator part. The colorbar will be fully functional except the
"extend" feature (triangles at the ends of the colorbar. see
http://matplotlib.sourceforge.net/examples/api/colorbar_only.html).

This is not acceptable. The "extend" feature is essential.

I see.

3) use the reimplemented version of the colorbar.

4) someone else comes up with a better implementation.

Regarding 3 or 4, if you or anyone else can come up with a better
implementation, preserving at least the present functionality, that's great.
The present implementation was a pain to develop and is hard to understand
and maintain.

As a person who never uses "extend" and "non-proportional" mode, I'm
afraid that I do not have much motivation for now. But, it would be
great if someone can come up with a better implementation!

Regards,

-JJ

A patch is attached.
It does some refactoring and introduces three new methods, set_ticks,
set_ticklabels and update_ticks, on the colorbar class.
So, now one can do

imshow(np.arange(100).reshape((10,10)))
cb = colorbar()
cb.set_ticks([0, 40, 80])

Issuing a warning when user try to call Axis.set_ticks (or others)
directly seems not straight forward as the axes can be created
externally (i.e., when *cax* is provided).

I'll wait for response for a few more days and will commit the change.
Regards,

-JJ

colorbar.diff (2.85 KB)

···

On Mon, Jan 25, 2010 at 7:19 PM, Jae-Joon Lee <lee.j.joon@...149...> wrote:

Adding a "set_ticks" method seems reasonable.

Jae-Joon Lee wrote:

Adding a "set_ticks" method seems reasonable.

A patch is attached.

It looks like exactly what I had in mind with respect to set_ticks. I wasn't thinking about set_ticklabels; my sense is that manually setting ticklabels tends to be tricky and error-prone, and should be discouraged. Maybe it should be permitted only when a FixedLocator is already in use.

It does some refactoring and introduces three new methods, set_ticks,
set_ticklabels and update_ticks, on the colorbar class.
So, now one can do

imshow(np.arange(100).reshape((10,10)))
cb = colorbar()
cb.set_ticks([0, 40, 80])

Issuing a warning when user try to call Axis.set_ticks (or others)
directly seems not straight forward as the axes can be created
externally (i.e., when *cax* is provided).

Attached patch against svn (without your patch) shows how this can be done for the Axes methods. I would be more difficult (but not impossible) for the Axis methods, because we need to use them. I think that handling the Axes methods *may* be worthwhile (marginal), but handling the Axis methods is more trouble than it is worth.

Eric

cbar_axfix.diff (1.87 KB)

···

On Mon, Jan 25, 2010 at 7:19 PM, Jae-Joon Lee <lee.j.joon@...149...> wrote:

I'll wait for response for a few more days and will commit the change.
Regards,

-JJ

I just committed the changes.
Regards,

-JJ

···

On Wed, Jan 27, 2010 at 2:31 PM, Eric Firing <efiring@...229...> wrote:

Jae-Joon Lee wrote:

On Mon, Jan 25, 2010 at 7:19 PM, Jae-Joon Lee <lee.j.joon@...149...> >> wrote:

Adding a "set_ticks" method seems reasonable.

A patch is attached.

It looks like exactly what I had in mind with respect to set_ticks. I
wasn't thinking about set_ticklabels; my sense is that manually setting
ticklabels tends to be tricky and error-prone, and should be discouraged.
Maybe it should be permitted only when a FixedLocator is already in use.

It does some refactoring and introduces three new methods, set_ticks,
set_ticklabels and update_ticks, on the colorbar class.
So, now one can do

imshow(np.arange(100).reshape((10,10)))
cb = colorbar()
cb.set_ticks([0, 40, 80])

Issuing a warning when user try to call Axis.set_ticks (or others)
directly seems not straight forward as the axes can be created
externally (i.e., when *cax* is provided).

Attached patch against svn (without your patch) shows how this can be done
for the Axes methods. I would be more difficult (but not impossible) for
the Axis methods, because we need to use them. I think that handling the
Axes methods *may* be worthwhile (marginal), but handling the Axis methods
is more trouble than it is worth.

Eric

I'll wait for response for a few more days and will commit the change.
Regards,

-JJ