Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Port part of errorfill from Tony Yu's mpltools. #1010

Merged
merged 8 commits into from

5 participants

Damon McDougall Phil Elson John Hunter Michael Droettboom Benjamin Root
Damon McDougall
Collaborator

Specifically, the function extrema_from_error_input from

https://github.com/tonysyu/mpltools/blob/master/mpltools/special/errorfill.py#L54

is ported to matplotlib.mlab.

lib/matplotlib/mlab.py
((6 lines not shown))
+ """
+ Offsets an array *x* by +/- an error and returns a tuple (x - err, x + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *x*. The quantities x +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, xerr[0] is the error below *x* and
+ xerr[1] is error above *x*.
+ """
+ if np.isscalar(xerr) or len(xerr) == len(x):
+ xmin = x - xerr
+ xmax = x + xerr
+ elif len(xerr) == 2:
+ xmin, xmax = x - xerr[0], x + xerr[1]
Phil Elson Collaborator
pelson added a note

What about the undefined case (not a scalar, nor len in [2, n])?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/mlab.py
@@ -3182,3 +3182,22 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(x, xerr):
+ """
John Hunter Owner
jdh2358 added a note

Although it is just a variable name in this context, the use case from Tony's errorfill is offsetting in the y-axis direction. Thus naming everything x and xerr might be a little confusing. Perhaps y and yerr would be better?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/mlab.py
@@ -3182,3 +3182,22 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(x, xerr):
+ """
+ Offsets an array *x* by +/- an error and returns a tuple (x - err, x + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *x*. The quantities x +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, xerr[0] is the error below *x* and
+ xerr[1] is error above *x*.
+ """
John Hunter Owner
jdh2358 added a note

I suggest adding in the docstring some example code or a embedded plot directive link to an example that shows how to use this with fill_between

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/mlab.py
@@ -3182,3 +3182,22 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(x, xerr):
+ """
+ Offsets an array *x* by +/- an error and returns a tuple (x - err, x + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *x*. The quantities x +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, xerr[0] is the error below *x* and
+ xerr[1] is error above *x*.
+ """
+ if np.isscalar(xerr) or len(xerr) == len(x):
John Hunter Owner
jdh2358 added a note

Rather than np.isscalar you should use mpl's duck-typing functions, like:

if cbook.is_numlike(xerr) or (cbook.iterable(xerr) and len(xerr)==len(x)):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Phil Elson
Collaborator

Coming at this fresh, why is this called offset_line? It doesn't seem to offset anything, nor use lines. Naming functions is always the hardest part, and the best that I could come up with was error_range (which I don't actually find any better ;-) ).

I could see this function being useful for handling numpy arrays, which makes me wonder whether it would be better to put this straight into numpy rather than mlab?

Damon McDougall
Collaborator

@pelson I have no idea! It seemed natural given the example in the docstring. How about offset_data?

John Hunter
Owner

@pelson re numpy vs mlab: if we have something that is useful to people I like to ship it so that our code works across multiple versions of numpy. If numpy wants something from mlab, or someone wants to push to get it into numpy, that's great, but I'd like to have it in several release cycles of numpy before we stop shipping it. We've done this with a ton of mlab functions over the years and it doesn't seem to have caused many problems. This function in particular is mainly a convenience method for fill_between -- I don't see it being generically useful enough to make it into numpy.

lib/matplotlib/mlab.py
@@ -3182,3 +3182,34 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(y, yerr):
+ """
+ Offsets an array *y* by +/- an error and returns a tuple (y - err, y + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *y*. The quantities y +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, yerr[0] is the error below *y* and
+ yerr[1] is error above *y*.
+
+ For example:
Phil Elson Collaborator
pelson added a note

My memory is a little haze, but if you put a double colon, and then indent the code, you will get a pretty code block if/when rendered with Sphinx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/mlab.py
@@ -3182,3 +3182,34 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(y, yerr):
+ """
+ Offsets an array *y* by +/- an error and returns a tuple (y - err, y + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *y*. The quantities y +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, yerr[0] is the error below *y* and
+ yerr[1] is error above *y*.
+
+ .. For example::
Benjamin Root Collaborator

remove "For"

Phil Elson Collaborator
pelson added a note

And the leading .. ?

Benjamin Root Collaborator

I keep getting sphinx syntax mixed up in my head. A directive is made up of a leading double dots, a space and a single word followed by double colons. Any arguments for that directive follow the double colons. "keyword" arguments (if any) are provided on the subsequent indented lines with the name of the keyword surrounded by colons and the value after it (see doc/api/index.rst for an example). Finally, any remaining indented text is treated as-is as a large string block.

It doesn't look like there is an ".. example::" directive, so I would re-write this part of the docstring as:

yerr[1] is error above *y*. For example::
Damon McDougall Collaborator

@WeatherGod Where do I put the double dots in your example?

I followed the example below (from pyplot.py):

def figlegend(handles, labels, loc, **kwargs):
    """
    Place a legend in the figure.

    *labels*
      a sequence of strings

    *handles*
      a sequence of :class:`~matplotlib.lines.Line2D` or
      :class:`~matplotlib.patches.Patch` instances

    *loc*
      can be a string or an integer specifying the legend
      location

    A :class:`matplotlib.legend.Legend` instance is returned.

    Example::

      figlegend( (line1, line2, line3),
                 ('label1', 'label2', 'label3'),
                 'upper right' )

    .. seealso::

       :func:`~matplotlib.pyplot.legend`

    """
    l = gcf().legend(handles, labels, loc, **kwargs)
    draw_if_interactive()
    return l

I don't have sphinx, and I have no experience with it, so I'm deferring to you guys for epic sphinxage :)

Benjamin Root Collaborator

You don't. Whenever you want to display a code block, you use just double-colons and indent the code block. You might also have to have a blank line as well. The word "example" before the double-colons is not special and can be any word. Sometimes, we even just use double colons on a line all by itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/matplotlib/mlab.py
((11 lines not shown))
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *y*. The quantities y +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, yerr[0] is the error below *y* and
+ yerr[1] is error above *y*.
+
+ .. For example::
+
+ from pylab import *
+ x = linspace(0, 2*pi, num=100, endpoint=True)
+ y = sin(x)
+ y_minus, y_plus = mlab.offset_line(y, 0.1)
+ plot(x, y)
+ fill_between(x, ym, y2=yp)
+ show()
+ """
Phil Elson Collaborator
pelson added a note

I think there is supposed to be an empty line after the end of the code-block. Stylistically it doesn't hurt either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Phil Elson
Collaborator

Ok, there is no reason for this not to make it into 1.2.x so I have updated the milestone.

Michael Droettboom
Owner

@dmcdougall : Do you consider this ready to merge?

Damon McDougall
Collaborator

@mdboom Sounds good to me. Thanks for the feedback.

Michael Droettboom mdboom merged commit 486a0cd into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 14, 2012
  1. Damon McDougall

    Port part of errorfill from Tony Yu's mpltools.

    dmcdougall authored
    Specifically, the function `extrema_from_error_input` from
    
    https://github.com/tonysyu/mpltools/blob/master/mpltools/special/errorfill.py#L54
    
    is ported to matplotlib.mlab.
  2. Damon McDougall

    Make variable name more intuitive.

    dmcdougall authored
    Renamed *x* to *y*.
  3. Damon McDougall
  4. Damon McDougall

    Make `offset_line` use mpl's duck-typing.

    dmcdougall authored
    Utilises cbook.is_numlike, etc.
  5. Damon McDougall
Commits on Jul 15, 2012
  1. Damon McDougall
Commits on Jul 21, 2012
  1. Damon McDougall

    Fix minor code style issues

    dmcdougall authored
Commits on Jul 22, 2012
  1. Damon McDougall
This page is out of date. Refresh to see the latest.
Showing with 30 additions and 0 deletions.
  1. +30 −0 lib/matplotlib/mlab.py
30 lib/matplotlib/mlab.py
View
@@ -3182,3 +3182,33 @@ def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
c2x, c2y = c1x + 1./3. * (q2x - q0x), c1y + 1./3. * (q2y - q0y)
# c3x, c3y = q2x, q2y
return q0x, q0y, c1x, c1y, c2x, c2y, q2x, q2y
+
+def offset_line(y, yerr):
+ """
+ Offsets an array *y* by +/- an error and returns a tuple (y - err, y + err).
+
+ The error term can be:
+
+ o A scalar. In this case, the returned tuple is obvious.
+ o A vector of the same length as *y*. The quantities y +/- err are computed
+ component-wise.
+ o A tuple of length 2. In this case, yerr[0] is the error below *y* and
+ yerr[1] is error above *y*. For example::
+
+ from pylab import *
+ x = linspace(0, 2*pi, num=100, endpoint=True)
+ y = sin(x)
+ y_minus, y_plus = mlab.offset_line(y, 0.1)
+ plot(x, y)
+ fill_between(x, ym, y2=yp)
+ show()
+
+ """
+ if cbook.is_numlike(yerr) or (cbook.iterable(yerr) and len(yerr) == len(y)):
+ ymin = y - yerr
+ ymax = y + yerr
+ elif len(yerr) == 2:
+ ymin, ymax = y - yerr[0], y + yerr[1]
+ else:
+ raise ValueError("yerr must be scalar, 1xN or 2xN")
+ return ymin, ymax
Something went wrong with that request. Please try again.