Passing errorbar width arguments to bar/barh ?

Hi all,

I just spent some time digging through the matplotlib code, and I see
that the errorbar line width argument isn't passed through to the
underlying call. In axis.bar, we have this code:

        if xerr is not None or yerr is not None:
            if orientation == 'vertical':
                # using list comps rather than arrays to preserve unit info
                x = [l+0.5*w for l, w in zip(left, width)]
                y = [b+h for b,h in zip(bottom, height)]

            elif orientation == 'horizontal':
                # using list comps rather than arrays to preserve unit info
                x = [l+w for l,w in zip(left, width)]
                y = [b+0.5*h for b,h in zip(bottom, height)]

            self.errorbar(
                x, y,
                yerr=yerr, xerr=xerr,
                fmt=None, ecolor=ecolor, capsize=capsize)

while errorbar has this signature:

    def errorbar(self, x, y, yerr=None, xerr=None,
                 fmt='-', ecolor=None, elinewidth=None, capsize=3,
                 barsabove=False, lolims=False, uplims=False,
                 xlolims=False, xuplims=False, **kwargs):

For a poster, we wanted thicker errorbars drawn and had to resort to:

plt.rcParams['lines.markeredgewidth'] = 2
plt.rcParams['lines.linewidth'] = 2

and reverting back to normal width after making the errorbar calls.
Should I file a ticket about this, or are such fine-tuning tasks
considered as fair game for rcParams manipulations?

I'm happy to file the ticket, I just don't want to create unnecessary
noise if the rcparams is meant to be 'the way' to do it.

Cheers,

f

Hi all,

I just spent some time digging through the matplotlib code, and I see
that the errorbar line width argument isn't passed through to the
underlying call. In axis.bar, we have this code:

         if xerr is not None or yerr is not None:
             if orientation == 'vertical':
                 # using list comps rather than arrays to preserve unit info
                 x = [l+0.5*w for l, w in zip(left, width)]
                 y = [b+h for b,h in zip(bottom, height)]

             elif orientation == 'horizontal':
                 # using list comps rather than arrays to preserve unit info
                 x = [l+w for l,w in zip(left, width)]
                 y = [b+0.5*h for b,h in zip(bottom, height)]

             self.errorbar(
                 x, y,
                 yerr=yerr, xerr=xerr,
                 fmt=None, ecolor=ecolor, capsize=capsize)

while errorbar has this signature:

     def errorbar(self, x, y, yerr=None, xerr=None,
                  fmt='-', ecolor=None, elinewidth=None, capsize=3,
                  barsabove=False, lolims=False, uplims=False,
                  xlolims=False, xuplims=False, **kwargs):

For a poster, we wanted thicker errorbars drawn and had to resort to:

plt.rcParams['lines.markeredgewidth'] = 2
plt.rcParams['lines.linewidth'] = 2

and reverting back to normal width after making the errorbar calls.
Should I file a ticket about this, or are such fine-tuning tasks
considered as fair game for rcParams manipulations?

No, that seems like a terrible kluge--not at all what rcParams is for. bar, errorbar, hist could use some major refactoring. In the meantime, since bar simply calls errorbar, it seems to me that the solution is for bar to take a kwarg, say "errorkw", which is a dict that will be passed to errorbar via **errorkw, and that can have any valid errorbar kwargs in it. There is some precedent for this sort of thing, and I find it a useful way of keeping kwargs from getting out of control when one is making complicated compound plots.

If there is no objection, I will do it.

Eric

···

On 06/01/2010 01:17 PM, Fernando Perez wrote:

I'm happy to file the ticket, I just don't want to create unnecessary
noise if the rcparams is meant to be 'the way' to do it.

Cheers,

f

------------------------------------------------------------------------------

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

I just took a look at bar() and errorbar(). bar() has linewidth and uses it properly (I believe), except in the case where one specifies yerr/xerr (it doesn’t pass on kwargs nor does it apply the linewidth parameter).

Then looking at errorbar(), there is a kwarg called ‘elinewidth’ which superceeds ‘linewidth’ if it is set. Yet, I see no other use of ‘elinewidth’, only ‘linewidth’ in a dict called lines_kw. I am not sure if I see the point in having a parameter called ‘elinewidth’ (unless one wanted to make a distinction between the width of the bar’s lines and the width of the line for the caps?), but that might be a side-issue.

I am not convinced that adding a dictionary argument to bar() would make much sense. Why not simply pass the kwargs to errorbar()? That way, if one wanted to use yerr/xerr, they could also include elinewidth and others if they wish (or, even better, let linewidth and other parameters go back through since those represent the user’s intention in the first place).

Just my two cents,
Ben Root

···

On Tue, Jun 1, 2010 at 6:35 PM, Eric Firing <efiring@…229…> wrote:

On 06/01/2010 01:17 PM, Fernando Perez wrote:

Hi all,

I just spent some time digging through the matplotlib code, and I see

that the errorbar line width argument isn’t passed through to the

underlying call. In axis.bar, we have this code:

     if xerr is not None or yerr is not None:
         if orientation == 'vertical':
             # using list comps rather than arrays to preserve unit info
             x = [l+0.5*w for l, w in zip(left, width)]
             y = [b+h for b,h in zip(bottom, height)]
         elif orientation == 'horizontal':
             # using list comps rather than arrays to preserve unit info
             x = [l+w for l,w in zip(left, width)]
             y = [b+0.5*h for b,h in zip(bottom, height)]
         self.errorbar(
             x, y,
             yerr=yerr, xerr=xerr,
             fmt=None, ecolor=ecolor, capsize=capsize)

while errorbar has this signature:

 def errorbar(self, x, y, yerr=None, xerr=None,
              fmt='-', ecolor=None, elinewidth=None, capsize=3,
              barsabove=False, lolims=False, uplims=False,
              xlolims=False, xuplims=False, **kwargs):

For a poster, we wanted thicker errorbars drawn and had to resort to:

plt.rcParams[‘lines.markeredgewidth’] = 2

plt.rcParams[‘lines.linewidth’] = 2

and reverting back to normal width after making the errorbar calls.

Should I file a ticket about this, or are such fine-tuning tasks

considered as fair game for rcParams manipulations?

No, that seems like a terrible kluge–not at all what rcParams is for.

bar, errorbar, hist could use some major refactoring. In the meantime,

since bar simply calls errorbar, it seems to me that the solution is for

bar to take a kwarg, say “errorkw”, which is a dict that will be passed

to errorbar via **errorkw, and that can have any valid errorbar kwargs

in it. There is some precedent for this sort of thing, and I find it a

useful way of keeping kwargs from getting out of control when one is

making complicated compound plots.

If there is no objection, I will do it.

Eric

I’m happy to file the ticket, I just don’t want to create unnecessary

noise if the rcparams is meant to be ‘the way’ to do it.

Cheers,

f



Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel



Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

it seems to me that the solution is for
bar to take a kwarg, say "errorkw", which is a dict that will be passed
to errorbar via **errorkw, and that can have any valid errorbar kwargs
in it. There is some precedent for this sort of thing, and I find it a
useful way of keeping kwargs from getting out of control when one is
making complicated compound plots.

That would be my suggessted approach as well, I've used it elsewhere.

If there is no objection, I will do it.

Fabulous, many thanks!

Cheers,

f

···

On Tue, Jun 1, 2010 at 4:35 PM, Eric Firing <efiring@...229...> wrote:

While this is certainly a bug that needs to be fixed (and Eric is
right that these functions are heavily overworked and hairy), there is
a better workaround than the one you tried. From the errorbar
docstring:

        Return value is a length 3 tuple. The first element is the
        :class:`~matplotlib.lines.Line2D` instance for the *y* symbol
        lines. The second element is a list of error bar cap lines,
        the third element is a list of
        :class:`~matplotlib.collections.LineCollection` instances for
        the horizontal and vertical error ranges.

So you can call the appropriate methods on the return objects. Eg

  ylines, caplines, vlines = ax.errorbar(...)

if you want to set the vertical line thickness, it is a LineCollection
instance so you can call

  vlines.set_linewidth(2.0)

Since it is a Collection instance, you can also vary the vertical
linewidths by passing in a sequuence of linewidths.

Hope this helps,
JDH

···

On Tue, Jun 1, 2010 at 6:17 PM, Fernando Perez <fperez.net@...149...> wrote:

Hi all,

I just spent some time digging through the matplotlib code, and I see
that the errorbar line width argument isn't passed through to the
underlying call. In axis.bar, we have this code:

   if xerr is not None or yerr is not None:
       if orientation == &#39;vertical&#39;:
           \# using list comps rather than arrays to preserve unit info
           x = \[l\+0\.5\*w for l, w in zip\(left, width\)\]
           y = \[b\+h for b,h in zip\(bottom, height\)\]

       elif orientation == &#39;horizontal&#39;:
           \# using list comps rather than arrays to preserve unit info
           x = \[l\+w for l,w in zip\(left, width\)\]
           y = \[b\+0\.5\*h for b,h in zip\(bottom, height\)\]

       self\.errorbar\(
           x, y,
           yerr=yerr, xerr=xerr,
           fmt=None, ecolor=ecolor, capsize=capsize\)

while errorbar has this signature:

def errorbar(self, x, y, yerr=None, xerr=None,
fmt='-', ecolor=None, elinewidth=None, capsize=3,
barsabove=False, lolims=False, uplims=False,
xlolims=False, xuplims=False, **kwargs):

For a poster, we wanted thicker errorbars drawn and had to resort to:

plt.rcParams['lines.markeredgewidth'] = 2
plt.rcParams['lines.linewidth'] = 2

and reverting back to normal width after making the errorbar calls.
Should I file a ticket about this, or are such fine-tuning tasks
considered as fair game for rcParams manipulations?

I'm happy to file the ticket, I just don't want to create unnecessary
noise if the rcparams is meant to be 'the way' to do it.

Ignore me :slight_smile: I had a temporary mental failure and see that this
won't help you since you are calling "bar" and when bar is called with
the xerr/yerr args the errorbar return values aren't passed back up.
And my solution wasn't correct anyhow, since the third argument
returned from errorbar is a *list* of LineCollection instances, not a
LineCollection instance. Shutting up....

JDH

···

On Wed, Jun 2, 2010 at 8:01 AM, John Hunter <jdh2358@...149...> wrote:

While this is certainly a bug that needs to be fixed (and Eric is
right that these functions are heavily overworked and hairy), there is
a better workaround than the one you tried. From the errorbar
docstring:

I am curious as to why bar() should even be acting like errorbar(). As a user, I would expect bar() to do bar graphs and errorbar() to do error bar graphs. Is there some sort of use-case that I am missing where it makes sense to generate errorbars from a bar() function?

Ben Root

···

On Wed, Jun 2, 2010 at 8:06 AM, John Hunter <jdh2358@…149…> wrote:

On Wed, Jun 2, 2010 at 8:01 AM, John Hunter <jdh2358@…149…> wrote:

While this is certainly a bug that needs to be fixed (and Eric is

right that these functions are heavily overworked and hairy), there is

a better workaround than the one you tried. From the errorbar

docstring:

Ignore me :slight_smile: I had a temporary mental failure and see that this

won’t help you since you are calling “bar” and when bar is called with

the xerr/yerr args the errorbar return values aren’t passed back up.

And my solution wasn’t correct anyhow, since the third argument

returned from errorbar is a list of LineCollection instances, not a

LineCollection instance. Shutting up…

JDH



Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Some of this stuff is just really old (circa 2003). When you have
just a few users and someone sends you a patch, you tend to accept it
:slight_smile:

First we had bar, then we had errorbar, and someone wanted the
convenience of easily adding errorbars to bar plots. Over time, these
conveniences have grown into a fairly complex interface (xerr, yerr,
asymmetric errors). So it has grown more organically than by design
and some rationalization and normalization of functionality would be a
good thing. We have to balance that with the downsides of code
breakage, however.

JDH

···

On Wed, Jun 2, 2010 at 9:48 AM, Benjamin Root <ben.root@...553...> wrote:

I am curious as to why bar() should even be acting like errorbar(). As a
user, I would expect bar() to do bar graphs and errorbar() to do error bar
graphs. Is there some sort of use-case that I am missing where it makes
sense to generate errorbars from a bar() function?

it seems to me that the solution is for
bar to take a kwarg, say "errorkw", which is a dict that will be passed
to errorbar via **errorkw, and that can have any valid errorbar kwargs
in it. There is some precedent for this sort of thing, and I find it a
useful way of keeping kwargs from getting out of control when one is
making complicated compound plots.

That would be my suggessted approach as well, I've used it elsewhere.

If there is no objection, I will do it.

Fabulous, many thanks!

Done in svn 8369. Its usage is illustrated in barchart_demo.py. Partially following your lead with subplots, I spelled it error_kw.

Eric

···

On 06/01/2010 03:33 PM, Fernando Perez wrote:

On Tue, Jun 1, 2010 at 4:35 PM, Eric Firing<efiring@...229...> wrote:

Cheers,

f

------------------------------------------------------------------------------

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

I kinda figured something like that was the case. I am just cautious about additional “organic” development of these functions. I have encountered some functions where it was a bug that the function did not pass on the kwargs, and others where it wasn’t a bug. Does the approach of using a separate dict called error_kw fit in with some sort of overall design/best practices or might there be a better way to approach this.

I merely ask because I am quite new here and I am curious about what style we want for our code. Maybe we should consider some sort of special universal (for matplotlib) module that does special handling of kwargs? I am just throwing out some thoughts.

Ben Root

···

On Wed, Jun 2, 2010 at 10:26 AM, John Hunter <jdh2358@…552…149…> wrote:

On Wed, Jun 2, 2010 at 9:48 AM, Benjamin Root <ben.root@…553…> wrote:

I am curious as to why bar() should even be acting like errorbar(). As a

user, I would expect bar() to do bar graphs and errorbar() to do error bar

graphs. Is there some sort of use-case that I am missing where it makes

sense to generate errorbars from a bar() function?

Some of this stuff is just really old (circa 2003). When you have

just a few users and someone sends you a patch, you tend to accept it

:slight_smile:

First we had bar, then we had errorbar, and someone wanted the

convenience of easily adding errorbars to bar plots. Over time, these

conveniences have grown into a fairly complex interface (xerr, yerr,

asymmetric errors). So it has grown more organically than by design

and some rationalization and normalization of functionality would be a

good thing. We have to balance that with the downsides of code

breakage, however.

     > I am curious as to why bar() should even be acting like
    errorbar(). As a
     > user, I would expect bar() to do bar graphs and errorbar() to do
    error bar
     > graphs. Is there some sort of use-case that I am missing where
    it makes
     > sense to generate errorbars from a bar() function?

See barchart_demo.py. I don't use barcharts myself, but I can imagine that if I did, I might want errorbars on them.

    Some of this stuff is just really old (circa 2003). When you have
    just a few users and someone sends you a patch, you tend to accept it
    :-)

    First we had bar, then we had errorbar, and someone wanted the
    convenience of easily adding errorbars to bar plots. Over time, these
    conveniences have grown into a fairly complex interface (xerr, yerr,
    asymmetric errors). So it has grown more organically than by design
    and some rationalization and normalization of functionality would be a
    good thing. We have to balance that with the downsides of code
    breakage, however.

I kinda figured something like that was the case. I am just cautious
about additional "organic" development of these functions. I have
encountered some functions where it was a bug that the function did not
pass on the kwargs, and others where it wasn't a bug. Does the approach
of using a separate dict called error_kw fit in with some sort of
overall design/best practices or might there be a better way to approach
this.

It is precedented--see the relatively new subplots command, and Axes.text, which has had a fontdict kwarg for a long time.

I don't know of a better way of handling this sort of thing. Perhaps it could be used more frequently and consistently within mpl.

Organic growth, with its faults and its advantages, is inherent in projects like mpl--and even in commercial products like Matlab.

mpl has only a little bit of written coding guidance. See http://matplotlib.sourceforge.net/devel/coding_guide.html, most of which is not actually about coding.

I merely ask because I am quite new here and I am curious about what
style we want for our code. Maybe we should consider some sort of
special universal (for matplotlib) module that does special handling of
kwargs? I am just throwing out some thoughts.

You are welcome to propose something, but to have a chance of adoption it will need to be something that, for the most part, doesn't break users' code.

Eric

···

On 06/02/2010 01:20 PM, Benjamin Root wrote:

On Wed, Jun 2, 2010 at 10:26 AM, John Hunter <jdh2358@…149… > <mailto:jdh2358@…149…>> wrote:
    On Wed, Jun 2, 2010 at 9:48 AM, Benjamin Root <ben.root@…553… > <mailto:ben.root@…553…>> wrote:

Ben Root

Fabulous, much appreciated!

Regards,

f

···

On Wed, Jun 2, 2010 at 1:44 PM, Eric Firing <efiring@...229...> wrote:

Done in svn 8369. Its usage is illustrated in barchart_demo.py.
Partially following your lead with subplots, I spelled it error_kw.