Matplotlib's line2D
objects, such as those returned by a call to plot
, have a convenient method, set_data
, that let's me quickly update the values plotted by a single line without affecting the rest of the plot or the formatting of the line.
#sample plot
from matplotlib.pyplot import plot
p = plot(arange(10),arange(10))[0]
#now update the data
p.set_data(arange(10),arange(10)+2)
draw()
Is there any relatively simple (few lines of code) way to do the same with an errorbar
plot? I'd like to be able to set up a complicated plot with assorted text, arrows, lines, etc., then quickly cycle just the errorbar portion of the plot through several different sets of data.
The object returned by errorbar
seems to be pretty complex and so far my attempts at deleting and redrawing have failed.
Thanks to the help from @tacaswell . Below is the python function that can both update xerr
and yerr
, as well as the x_data
and y_data
for the baseline plotting:
def adjustErrbarxy(self, errobj, x, y, x_error, y_error):
ln, (errx_top, errx_bot, erry_top, erry_bot), (barsx, barsy) = errobj
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)
The first input parameter ( self
is for python class) is the already created errorbar
plot handler, that is also the object whose properties need to be updated; x
and y
are the updated numpy
arrays which should be shown the average values along x
and y
axis; the last two parameters x_error
and y_error
are the errorbar
ranges calculated for x
and y
arrays. If only the errorbars are need to be updated, the x_base
and y_base
should be writen as ln.get_xdata()
and ln.get_ydata()
, respectively.
Up to now, the solution for the errorbar
updating in matplotlib
is truly non-trivial, hope it be much easier in the future versions.
I followed the link provided by Tong and learned that there is a problem in his code - input of self variable is not needed. There is also a more generalized solution provided by mitpre - I used it and it works great. Below is the code for quicker reference:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.