Skip to content

update errorbar artists #4556

Closed
Closed

Description

@zhangt58

Hi,
I'm try to make the matplotlib errorbar plotting update as some input data varies, such plotting is embed into wxpython panel. I can update the matplotlib.line2D container field properties, e.g. update x_data through set_xdata, etc, but I cannot find any clue about how to control the Errorbar container's properties, can somebody help me out?
Thanks!
Tong Zhang

Activity

  1. tacaswell commented on Jun 26, 2015

    @tacaswell
    Member

    See http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.errorbar

    errorbar returns a funny object which sort of looks like an Artist, but is actually a subclass of a tuple, that plays nice with the legend.

    For now, you just have to go in and poke at each of the pieces individually, but these really should be methods on the object returned by errorbar, ex the following will change the errorbars symmetrically

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    x = np.linspace(0, 2*np.pi, 15)
    y = np.sin(x)
    y_err = np.cos(x) * 0.1
    err = ax.errorbar(x, y, y_err)
    
    
    def adjust_yerr(err, y_error):
        ln, (err_top, err_bot), (bars, ) = err
        y_base = ln.get_ydata()
        x_base = ln.get_xdata()
    
        yerr_top = y_base + y_error
        yerr_bot = y_base - y_error
    
        err_top.set_ydata(yerr_top)
        err_bot.set_ydata(yerr_bot)
    
        new_segments = [np.array([[x, yt], [x, yb]]) for
                        x, yt, yb in zip(x_base, yerr_top, yerr_bot)]
    
        bars.set_segments(new_segments)
        plt.draw() # don't need this on master

    I started a bit of work to clean this up (#3944) but have not had time to come back to that in a while.

  2. added this to the milestone on Jun 26, 2015
  3. changed the title [-]update matplotlib errorbar plotting in wxPython frame[/-] [+]update errorbar artists[/+] on Jun 26, 2015
  4. added
    Difficulty: Mediumhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues
    on Jun 26, 2015
  5. tacaswell commented on Jun 26, 2015

    @tacaswell
    Member

    I changed the title as this has nothing to do with Wx

  6. zhangt58 commented on Jun 27, 2015

    @zhangt58
    Author

    @tacaswell thanks very much for your script, now I got my job done. Below is the script that both update xerr and yerr, as well as the x_data and y_data for the baseline plotting:

    def adjustErrbarxy(errobj, x, y, x_error, y_error):
        ln, (errx_top, errx_bot, erry_top, erry_bot), (barsx, barsy) = errobj
    
        ln.set_data(x,y)
        x_base = x
        y_base = y
    
        xerr_top = x_base + x_error
        xerr_bot = x_base - x_error
        yerr_top = y_base + y_error
        yerr_bot = y_base - y_error
    
        errx_top.set_xdata(xerr_top)
        errx_bot.set_xdata(xerr_bot)
        errx_top.set_ydata(y_base)
        errx_bot.set_ydata(y_base)
    
        erry_top.set_xdata(x_base)
        erry_bot.set_xdata(x_base)
        erry_top.set_ydata(yerr_top)
        erry_bot.set_ydata(yerr_bot)
    
        new_segments_x = [np.array([[xt, y], [xb,y]]) for xt, xb, y in zip(xerr_top, xerr_bot, y_base)]
        new_segments_y = [np.array([[x, yt], [x,yb]]) for x, yt, yb in zip(x_base, yerr_top, yerr_bot)]
        barsx.set_segments(new_segments_x)
        barsy.set_segments(new_segments_y)

    In which x, y, x_error, y_error are the input parameters (dynamic numpy arrays) for updating errorbar artists; however, another issue was discovered, that is the updated plotting just show scattered point, but not line up the x-y plot, I fixed it by drawing one more x-y line2D artist and then update its x_data and y_data; I'm wandering if there is an easy way to show the x-y line2D plot when I update the errorbar artists?

  7. tacaswell commented on Jul 2, 2015

    @tacaswell
    Member

    Great, closing as not really a bug and #3944 is heading towards cleaning up bundled artists.

    You just need to add ln.set_data(x, y) to update the line in your function (or I don't understand your question).

    @archman If you wouldn't mind cleaning that function up a bit so that it does not take self and deals with not having all of the artists it expects that would make a good addition to the examples.

  8. zhangt58 commented on Jul 2, 2015

    @zhangt58
    Author

    @tacaswell update the post as suggested, thanks.

  9. mitpre commented on Jan 10, 2020

    @mitpre

    Just leaving here a bit more general solution. It still has a flaw that you can swap the directions of errorbars when updating ...

    def update_errorbar(errobj, x, y, xerr=None, yerr=None):
        ln, caps, bars = errobj
    
    
        if len(bars) == 2:
            assert xerr is not None and yerr is not None, "Your errorbar object has 2 dimension of error bars defined. You must provide xerr and yerr."
            barsx, barsy = bars  # bars always exist (?)
            try:  # caps are optional
                errx_top, errx_bot, erry_top, erry_bot = caps
            except ValueError:  # in case there is no caps
                pass
    
        elif len(bars) == 1:
            assert (xerr is     None and yerr is not None) or\
                   (xerr is not None and yerr is     None),  \
                   "Your errorbar object has 1 dimension of error bars defined. You must provide xerr or yerr."
    
            if xerr is not None:
                barsx, = bars  # bars always exist (?)
                try:
                    errx_top, errx_bot = caps
                except ValueError:  # in case there is no caps
                    pass
            else:
                barsy, = bars  # bars always exist (?)
                try:
                    erry_top, erry_bot = caps
                except ValueError:  # in case there is no caps
                    pass
    
        ln.set_data(x,y)
    
        try:
            errx_top.set_xdata(x + xerr)
            errx_bot.set_xdata(x - xerr)
            errx_top.set_ydata(y)
            errx_bot.set_ydata(y)
        except NameError:
            pass
        try:
            barsx.set_segments([np.array([[xt, y], [xb, y]]) for xt, xb, y in zip(x + xerr, x - xerr, y)])
        except NameError:
            pass
    
        try:
            erry_top.set_xdata(x)
            erry_bot.set_xdata(x)
            erry_top.set_ydata(y + yerr)
            erry_bot.set_ydata(y - yerr)
        except NameError:
            pass
        try:
            barsy.set_segments([np.array([[x, yt], [x, yb]]) for x, yt, yb in zip(x, y + yerr, y - yerr)])
        except NameError:
            pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Difficulty: Mediumhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions