bug in ContourSet and additional kwargs

Hello list, Hi Eric,

I stumbled upon the old thread "ploting matrix data" and the changes in my
mpl-svn working copy allowing to provide under_color and over_color as a
keyword argument of contourf.

Matthias Michler wrote:

[snip]

> Second question: Could it be useful to add two kwargs 'over_color'
> and 'under_color' to contourf in order to allow specification of a
> extended ListedColormap by kwarg 'colors' and these two colors?
> I tried to include this in the attached patch
> (added_under_and_over_color_to_ContourSet.patch) and use it in the
> example contourf_with_extended_colorbar_new.py. But it dosn't work
> completely correct. Although the over color is correctly set to cyan in
> the cmap In [14]: my_contourf.cmap._rgba_over
> Out[14]: (0.0, 1.0, 1.0, 1.0)
> red is used for values above the colormap-bounds.
>
> Thanks in advance for any comments and hints.

I need to look at your patch--but a priori, I am a bit worried about the
tendency of APIs to get more and more complicated, with more and more
kwargs, as time goes on.

Eric

First of all I think my previously described error in the over-color is due to
a bug in the set up of the colors.ListedColormap during the initialisation of
ContourSet if 'self.colors' is not None.
For the number of entries in the map 'N' the number of layers is
passed "N=len(self.layers)", which is not useful if self.extend is 'both'.
Let's say I want 3 regions and provide 3 colors. If extend is 'both' the
number of layers is the #{colored regions between min and max} + 2 = 5. For
N=5 in the initialisation of the ListedColormap the list of colors is
extended to have length 'N=5' (by repetition). Therefore an additional layer
(more precisely 2) occurs in the colormap and although the over_color is set
to something different the (repeted) first element of 'colors' is used to
color values above the highest level.

I propose the following case differentiation:
if self.extend == "both":
    N = len(self.layers) - 2
elif self.extend in ('max', 'min'):
    N = len(self.layers) - 1
else:
    N = len(self.layers)

Maybe N = len(self.levels) - 1 is always a good solution.

Is this a bug and does my proposal resolve it without destroying something
else?

Now back to my previous proposal to include the additional keyword
arguments 'under_color' and 'over_color'.
I attached two scripts, which show the difference between the old and the new
usage of a listed colormap specifing under/over_color. In the old behavior
you have to set the under and over color after setting up the contour.
  my_contourf.cmap.set_over('cyan')
  my_contourf.cmap.set_under('yellow')
and in the new behavior you can pass
over_color='cyan', under_color='yellow',
to the contourf-function.

Could these keyword arguments be useful?

Thanks in advance for any comments.

Kind regards,
Matthias

contourf_with_extended_colorbar_NEW.py (1.02 KB)

contourf_with_extended_colorbar_OLD.py (1.09 KB)

···

On Tuesday 14 April 2009 20:39:06 Eric Firing wrote:

Matthias Michler wrote:

Hello list, Hi Eric,

I stumbled upon the old thread "ploting matrix data" and the changes in my mpl-svn working copy allowing to provide under_color and over_color as a keyword argument of contourf.

Matthias Michler wrote:

[snip]

Second question: Could it be useful to add two kwargs 'over_color'
and 'under_color' to contourf in order to allow specification of a
extended ListedColormap by kwarg 'colors' and these two colors?
I tried to include this in the attached patch
(added_under_and_over_color_to_ContourSet.patch) and use it in the
example contourf_with_extended_colorbar_new.py. But it dosn't work
completely correct. Although the over color is correctly set to cyan in
the cmap In [14]: my_contourf.cmap._rgba_over
Out[14]: (0.0, 1.0, 1.0, 1.0)
red is used for values above the colormap-bounds.

Thanks in advance for any comments and hints.

I need to look at your patch--but a priori, I am a bit worried about the
tendency of APIs to get more and more complicated, with more and more
kwargs, as time goes on.

Eric

First of all I think my previously described error in the over-color is due to a bug in the set up of the colors.ListedColormap during the initialisation of ContourSet if 'self.colors' is not None.
For the number of entries in the map 'N' the number of layers is passed "N=len(self.layers)", which is not useful if self.extend is 'both'. Let's say I want 3 regions and provide 3 colors. If extend is 'both' the number of layers is the #{colored regions between min and max} + 2 = 5. For N=5 in the initialisation of the ListedColormap the list of colors is extended to have length 'N=5' (by repetition). Therefore an additional layer (more precisely 2) occurs in the colormap and although the over_color is set to something different the (repeted) first element of 'colors' is used to color values above the highest level.

I propose the following case differentiation: if self.extend == "both":
    N = len(self.layers) - 2
elif self.extend in ('max', 'min'):
    N = len(self.layers) - 1
else:
    N = len(self.layers)

Maybe N = len(self.levels) - 1 is always a good solution.

Is this a bug and does my proposal resolve it without destroying something else?

Yes, it is a bug, but I think this is only part of it. It may take me a week to get it all sorted out. Accommodating contour, contourf, and clabel all at the same time makes things complicated.

Now back to my previous proposal to include the additional keyword arguments 'under_color' and 'over_color'.
I attached two scripts, which show the difference between the old and the new usage of a listed colormap specifing under/over_color. In the old behavior you have to set the under and over color after setting up the contour. my_contourf.cmap.set_over('cyan') my_contourf.cmap.set_under('yellow')
and in the new behavior you can pass over_color='cyan', under_color='yellow',
to the contourf-function.

Could these keyword arguments be useful?

Yes, but not useful enough in general to justify adding them as keywords to contourf. Where kwargs "under", "over", and "bad" belong is in the Colormap initialization. I will add them there some time during the coming week. I will also provide a simpler version of your example, so that there will be an illustration of using over and under when the colors are listed.

Eric

···

On Tuesday 14 April 2009 20:39:06 Eric Firing wrote:

Thanks in advance for any comments.

Kind regards,
Matthias

Matthias Michler wrote:
[...]

First of all I think my previously described error in the over-color is due to a bug in the set up of the colors.ListedColormap during the initialisation of ContourSet if 'self.colors' is not None.
For the number of entries in the map 'N' the number of layers is passed "N=len(self.layers)", which is not useful if self.extend is 'both'. Let's say I want 3 regions and provide 3 colors. If extend is 'both' the number of layers is the #{colored regions between min and max} + 2 = 5. For N=5 in the initialisation of the ListedColormap the list of colors is extended to have length 'N=5' (by repetition). Therefore an additional layer (more precisely 2) occurs in the colormap and although the over_color is set to something different the (repeted) first element of 'colors' is used to color values above the highest level.

I propose the following case differentiation: if self.extend == "both":
    N = len(self.layers) - 2
elif self.extend in ('max', 'min'):
    N = len(self.layers) - 1
else:
    N = len(self.layers)

Maybe N = len(self.levels) - 1 is always a good solution.

Is this a bug and does my proposal resolve it without destroying something else?

Matthias,

I think I have fixed the problem. I also changed the second plot in contourf_demo to include the extended colorbar. Attached is a modification of one of your illustrative scripts with some unnecessary kwargs stripped out. In particular, when contourf makes a ListedColormap, you don't need or want to specify the norm--it uses the appropriate one, which is NoNorm. Also, you probably don't need to specify the view limits when making the subplot (contourf will autoscale with tight boundaries), and you don't need to pass the extend kwarg to colormap--it gets it from the ContourSet object.

Eric

cf_ext_cbar.py (932 Bytes)

Hi Eric,

thanks a lot for fixing this bug and including an extended colorbar in the
examples.

Kind regards,
Matthias

···

On Wednesday 28 April 2010 09:21:54 Eric Firing wrote:

Matthias Michler wrote:
[...]

> First of all I think my previously described error in the over-color is
> due to a bug in the set up of the colors.ListedColormap during the
> initialisation of ContourSet if 'self.colors' is not None.
> For the number of entries in the map 'N' the number of layers is
> passed "N=len(self.layers)", which is not useful if self.extend is
> 'both'. Let's say I want 3 regions and provide 3 colors. If extend is
> 'both' the number of layers is the #{colored regions between min and max}
> + 2 = 5. For N=5 in the initialisation of the ListedColormap the list of
> colors is extended to have length 'N=5' (by repetition). Therefore an
> additional layer (more precisely 2) occurs in the colormap and although
> the over_color is set to something different the (repeted) first element
> of 'colors' is used to color values above the highest level.
>
> I propose the following case differentiation:
> if self.extend == "both":
> N = len(self.layers) - 2
> elif self.extend in ('max', 'min'):
> N = len(self.layers) - 1
> else:
> N = len(self.layers)
>
> Maybe N = len(self.levels) - 1 is always a good solution.
>
> Is this a bug and does my proposal resolve it without destroying
> something else?

Matthias,

I think I have fixed the problem. I also changed the second plot in
contourf_demo to include the extended colorbar. Attached is a
modification of one of your illustrative scripts with some unnecessary
kwargs stripped out. In particular, when contourf makes a
ListedColormap, you don't need or want to specify the norm--it uses the
appropriate one, which is NoNorm. Also, you probably don't need to
specify the view limits when making the subplot (contourf will autoscale
with tight boundaries), and you don't need to pass the extend kwarg to
colormap--it gets it from the ContourSet object.

Eric