Errorbars not drawn correctly in logarithmic scales

Hi,

I've a problem with some errorbars not drawn correctly in (double)
logarithmic plots. See this PDF for an example:

http://dl.wolfgang-draxinger.net/C6_77MeV_raddamage.pdf

The vertical errorbar for the datapoint at x=1e3 are not drawn. Similar
also happens for some horizontal errorbars. Using the very same drawing
commands, except switching to a logarithmic scaling the errorbars draw
just fine.

So what's going on there?

Wolfgang Draxinger

Which version of matplotlib are you using? Also, are you setting the log scale before (preferred) or after (won’t work) the call to hist()?

Ben Root

···

On Thursday, March 8, 2012, Wolfgang Draxinger <wdraxinger.maillist@…4015…> wrote:

Hi,

I’ve a problem with some errorbars not drawn correctly in (double)

logarithmic plots. See this PDF for an example:

http://dl.wolfgang-draxinger.net/C6_77MeV_raddamage.pdf

The vertical errorbar for the datapoint at x=1e3 are not drawn. Similar

also happens for some horizontal errorbars. Using the very same drawing
commands, except switching to a logarithmic scaling the errorbars draw
just fine.

So what’s going on there?

Wolfgang Draxinger

Grrr, not hist(), but errorbar().

Ben Root

···

On Thursday, March 8, 2012, Benjamin Root <ben.root@…1304…> wrote:

On Thursday, March 8, 2012, Wolfgang Draxinger <wdraxinger.maillist@…4015…> wrote:

Hi,

I’ve a problem with some errorbars not drawn correctly in (double)
logarithmic plots. See this PDF for an example:

http://dl.wolfgang-draxinger.net/C6_77MeV_raddamage.pdf

The vertical errorbar for the datapoint at x=1e3 are not drawn. Similar
also happens for some horizontal errorbars. Using the very same drawing
commands, except switching to a logarithmic scaling the errorbars draw

just fine.

So what’s going on there?

Wolfgang Draxinger

Which version of matplotlib are you using? Also, are you setting the log scale before (preferred) or after (won’t work) the call to hist()?

Ben Root

Version is matplotlib-1.1.0, installed through standard Gentoo ebuild.
And the scale parameters are set before all the drawing calls.

Wolfgang

···

On Thu, 8 Mar 2012 19:47:05 -0600 Benjamin Root <ben.root@...1304...> wrote:

Which version of matplotlib are you using? Also, are you setting the
log scale before (preferred) or after (won't work) the call to hist()?

Wolfgang,

Can I have the data you used to produce these errorbars so I can test this bug?

Ben Root

···

On Fri, Mar 9, 2012 at 3:29 AM, Wolfgang Draxinger <wdraxinger.maillist@…4015…> wrote:

On Thu, 8 Mar 2012 19:47:05 -0600 > > Benjamin Root <ben.root@…3286…> wrote:

Which version of matplotlib are you using? Also, are you setting the

log scale before (preferred) or after (won’t work) the call to hist()?

Version is matplotlib-1.1.0, installed through standard Gentoo ebuild.

And the scale parameters are set before all the drawing calls.

Wolfgang

Here's the data

# Fluence.... -sigma Signal... -sigma area
      1127 48.32 9.114 10.31 0.1318
1.127e+04 482.9 35.96 16.15 0.4994
1.127e+05 4829 231.2 101.1 2.568
1.127e+06 4.829e+04 4631 1689 12.22

And here's the ploting tool source code (also used for generating the
linked PDF).

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# vim: filetype python

import sys, os, argparse

import math, numpy, scipy, scipy.optimize

import matplotlib, matplotlib.cm
import matplotlib.pyplot as pyplot
import pylab

def expmodel(p, x):
  return p[0] + numpy.exp(p[1]*x)*p[2]

def experror(p, x, y):
  return y - expmodel(p, x)

def linmodel(p, x):
  return p[0] + p[1]*x

def linerror(p, x, y):
  return y - linmodel(p, x)

if __name__ == '__main__':
  optparse = argparse.ArgumentParser(description='plot raddark dat files with errorbars and linear or exponential model regression plots', prog=sys.argv[0])
  optparse.add_argument('--xlabel', type=str, default='Particle Count')
  optparse.add_argument('--ylabel', type=str, default='Signal')
  optparse.add_argument('--title', type=str, default='')
  optparse.add_argument('--outlier', '-O', action='append', type=str)
  optfitgrp = optparse.add_mutually_exclusive_group()
  optfitgrp.add_argument('--exp', '-e', action='store_true')
  optfitgrp.add_argument('--lin', '-l', action='store_true')
  optparse.add_argument('--log', action='store_true')
  optparse.add_argument('files', type=str, nargs='+')

  options = optparse.parse_args(sys.argv[1:])

  data = [ numpy.loadtxt(filename) for filename in options.files ]

  if options.outlier:
    outlier = [ numpy.loadtxt(filename) for filename in options.outlier ]

  ax = pyplot.subplot(1,1,1)
  if options.log:
    ax.loglog()

  ax.set_title(options.title)
  ax.set_xlabel(options.xlabel)
  ax.set_ylabel(options.ylabel)
  ax.grid(True, 'both')

  for f,d in zip(options.files, data):
    ax.errorbar(d[..., 0], d[..., 2], d[..., 3], d[..., 1], fmt='o', label=f)

  if options.outlier:
    for f,d in zip(options.outlier, outlier):
      ax.errorbar(d[..., 0], d[..., 2], d[..., 3], d[..., 1], fmt='+', label=f)

  if options.exp or options.lin:
    data_xs = numpy.concatenate( [ d[..., 0] for d in data ] )
    data_ys = numpy.concatenate( [ d[..., 2] for d in data ] )
    if options.outlier:
      x_max = numpy.nanmax( numpy.concatenate((data_xs, numpy.concatenate([ o[..., 0] for o in outlier ]))) )
      x_min = numpy.nanmin( numpy.concatenate((data_xs, numpy.concatenate([ o[..., 0] for o in outlier ]))) )
    else:
      x_max = numpy.nanmax(data_xs)
      x_min = numpy.nanmin(data_xs)
    x_ptp = x_max - x_min
    xs = numpy.arange(x_min - 0.05*x_ptp, x_max + 0.05*x_ptp, x_ptp/10000.)

    if options.exp:
      p = scipy.optimize.leastsq(experror, [numpy.nanmin(data_ys), 1e-6/x_ptp, 1./numpy.ptp(data_ys)], args=(data_xs, data_ys))
      ys = expmodel(p[0], xs)
    if options.lin:
      p = scipy.optimize.leastsq(linerror, [numpy.nanmin(data_ys), 1./x_ptp, 1./numpy.ptp(data_ys)], args=(data_xs, data_ys))
      ys = linmodel(p[0], xs)

    ax.plot(xs, ys, label="fit")
  
  ax.legend(loc='upper left')

  pyplot.show()

···

On Fri, 9 Mar 2012 11:19:15 -0600 Benjamin Root <ben.root@...1304...> wrote:

Can I have the data you used to produce these errorbars so I can test
this bug?

Ah, finally figured it out. The issue is that your y-value for that error bar is 9.114, but you want to plot error bars that are +/-10.31. That line gets thrown out by matplotlib because you can’t plot at negative values for log scale. There is a trick that might work. The set_yscale method has a kwarg “nonposy” which could be set to “clip”. You could also try setting to the “symlog” scale which might let you get away with a negative value.

I hope that helps!
Ben Root

···

On Fri, Mar 9, 2012 at 1:14 PM, Wolfgang Draxinger <wdraxinger.maillist@…4015…> wrote:

On Fri, 9 Mar 2012 11:19:15 -0600 > > Benjamin Root <ben.root@…3286…> wrote:

Can I have the data you used to produce these errorbars so I can test

this bug?

Here’s the data

Fluence… -sigma Signal… -sigma area

  1127      48.32      9.114      10.31     0.1318

1.127e+04 482.9 35.96 16.15 0.4994

1.127e+05 4829 231.2 101.1 2.568

1.127e+06 4.829e+04 4631 1689 12.22

Ah, finally figured it out. The issue is that your y-value for that
error bar is 9.114, but you want to plot error bars that are
+/-10.31. That line gets thrown out by matplotlib because you can't
plot at negative values for log scale.

Yes, I came to the same conclusion. I think matplotlib should print
some warning or raise some exception if confronted with data like that,
it can't handle.

There is a trick that might
work. The set_yscale method has a kwarg "nonposy" which could be set
to "clip". You could also try setting to the "symlog" scale which
might let you get away with a negative value.

I'll try that.

Thanks

Wolfgang

···

On Mon, 12 Mar 2012 15:51:15 -0500 Benjamin Root <ben.root@...1304...> wrote:

I never got the trick with set_yscale="clip" to work for my plots (MPL
1.1.0).
So I'm passing my error values to this little function in order to correct
the yerr_neg:

def filt_neg_err(y, yerr, set_ymin=1e-6):
    ymin = y - yerr
    filt = ymin < 0
    yerr_pos = yerr.copy()
    yerr_neg = yerr.copy()
    yerr_neg[filt] = y[filt] - set_ymin
    return np.array([yerr_neg, yerr_pos])

Cheers,
Arne

Benjamin Root-2 wrote:

···

On Fri, Mar 9, 2012 at 1:14 PM, Wolfgang Draxinger < > wdraxinger.maillist@...4015...> wrote:

On Fri, 9 Mar 2012 11:19:15 -0600 >> Benjamin Root <ben.root@...1304...> wrote:

> Can I have the data you used to produce these errorbars so I can test
> this bug?

Here's the data

# Fluence.... -sigma Signal... -sigma area
     1127 48.32 9.114 10.31 0.1318
1.127e+04 482.9 35.96 16.15 0.4994
1.127e+05 4829 231.2 101.1 2.568
1.127e+06 4.829e+04 4631 1689 12.22

Ah, finally figured it out. The issue is that your y-value for that error
bar is 9.114, but you want to plot error bars that are +/-10.31. That
line
gets thrown out by matplotlib because you can't plot at negative values
for
log scale. There is a trick that might work. The set_yscale method has a
kwarg "nonposy" which could be set to "clip". You could also try setting
to the "symlog" scale which might let you get away with a negative value.

I hope that helps!
Ben Root

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

--
View this message in context: http://old.nabble.com/Errorbars-not-drawn-correctly-in-logarithmic-scales-tp33469114p33544881.html
Sent from the matplotlib - users mailing list archive at Nabble.com.