Problem using set_data

Hi

the following code snippet is from a simple wxpython/matplotlib app

# Data object class

class PlotData(object):

     # Constructor (dummy arrays)

     def __init__(self):
         self.np = 100

         self.xa = numpy.arange(100.0)
         self.ya = 2.0 * self.xa
         self.ys = 4.0 * self.xa

# Plot window class

class PlotWin(object):
     def __init__(self, data):
         self.data = data # Store reference to data object
         self.figure = Figure() # Initialise figure

         # Create an Axes object to plot on

         self.ax1 = self.figure.gca()
         self.ax1.yaxis.tick_left()
         self.ax1.xaxis.tick_bottom()

         # Plot the data

         self.lines=[]

         self.lines.append(self.ax1.plot(self.data.xa, self.data.ya, 'g'))
         self.lines.append(self.ax1.plot(self.data.xa, self.data.ys, '-r'))

     # Update plot with new data

     def RefreshPlot(self, data):
         self.lines[0].set_data((self.data.xa,self.data.ya))
         self.lines[1].set_data((self.data.xa,self.data.ys))

         self.canvas.draw()

# Main program

if __name__ == "__main__":
     data = PlotData()
     pwin = PlotWin(data)
     pwin.RefreshPlot(data)

The plot data changes during the application and I just want to replace the existing data with the new data (which may have a different number of points compared to the old data). I get the Python error "'list' object has no attribute 'set_data'" when the code executes RefreshPlot(). AFAIK lines[0] and lines[1] are 'Line2D' objects (at least that's what Python says they are when I ask to have them printed) , which do have a 'set_data' method. I'm sure there's something really easy that I need to do but just can't see it - all suggestions gratefully received!

Thanks in advance

Alun Griffiths

Hi Alun,

Hi

the following code snippet is from a simple wxpython/matplotlib app

# Data object class

class PlotData(object):

     # Constructor (dummy arrays)

     def __init__(self):
         self.np = 100

         self.xa = numpy.arange(100.0)
         self.ya = 2.0 * self.xa
         self.ys = 4.0 * self.xa

# Plot window class

class PlotWin(object):
     def __init__(self, data):
         self.data = data # Store reference to data object
         self.figure = Figure() # Initialise figure

         # Create an Axes object to plot on

         self.ax1 = self.figure.gca()
         self.ax1.yaxis.tick_left()
         self.ax1.xaxis.tick_bottom()

         # Plot the data

         self.lines=[]

         self.lines.append(self.ax1.plot(self.data.xa, self.data.ya, 'g'))
         self.lines.append(self.ax1.plot(self.data.xa, self.data.ys, '-r'))

     # Update plot with new data

     def RefreshPlot(self, data):
         self.lines[0].set_data((self.data.xa,self.data.ya))
         self.lines[1].set_data((self.data.xa,self.data.ys))

         self.canvas.draw()

# Main program

if __name__ == "__main__":
     data = PlotData()
     pwin = PlotWin(data)
     pwin.RefreshPlot(data)

The plot data changes during the application and I just want to
replace the existing data with the new data (which may have a
different number of points compared to the old data). I get the
Python error "'list' object has no attribute 'set_data'" when the
code executes RefreshPlot(). AFAIK lines[0] and lines[1] are
'Line2D' objects (at least that's what Python says they are when I
ask to have them printed) , which do have a 'set_data' method. I'm
sure there's something really easy that I need to do but just can't
see it - all suggestions gratefully received!

I think the problem is:

self.lines.append(self.ax1.plot(self.data.xa, self.data.ya, 'g'))

plot() returns a list of lines. You are appending that list to self.lines, so
when you index self.lines[0] later, you are getting the list returned by
plot. You should either use extend() instead of append, or you need to index
deeper: self.lines[0][0] and self.lines[0][1].

Darren

···

On Wednesday 25 June 2008 07:09:52 am eShopping wrote:

Hi Darren

thanks for the quick reply. I tried

self.lines[0][0].set_data((self.data.xa,self.data.ya))
self.lines[0][1].set_data((self.data.xa,self.data.ys))

but got the error 'list index out of range' after the second statement. I also tried

self.lines[0][0].set_data((self.data.xa,self.data.ya))
self.lines[1][0].set_data((self.data.xa,self.data.ys))

There were no errors in this case but the data does not plot correctly. Finally, I tried

self.lines[0][0].set_xdata(self.data.xa)
self.lines[0][0].set_ydata(self.data.ya)
self.lines[1][0].set_xdata(self.data.xa)
self.lines[1][0].set_ydata(self.data.ys)

but matplotlib complained that 'xdata and ydata must be the same length' after executing the first of these statements (presumably because the new xa array has a different number of elements than the old ya array)

···

At 13:05 25/06/2008, you wrote:

Hi Alun,

On Wednesday 25 June 2008 07:09:52 am eShopping wrote:
> Hi
>
> the following code snippet is from a simple wxpython/matplotlib app
>
> # Data object class
>
> class PlotData(object):
>
> # Constructor (dummy arrays)
>
> def __init__(self):
> self.np = 100
>
> self.xa = numpy.arange(100.0)
> self.ya = 2.0 * self.xa
> self.ys = 4.0 * self.xa
>
> # Plot window class
>
> class PlotWin(object):
> def __init__(self, data):
> self.data = data # Store reference to data object
> self.figure = Figure() # Initialise figure
>
> # Create an Axes object to plot on
>
> self.ax1 = self.figure.gca()
> self.ax1.yaxis.tick_left()
> self.ax1.xaxis.tick_bottom()
>
> # Plot the data
>
> self.lines=[]
>
> self.lines.append(self.ax1.plot(self.data.xa, self.data.ya, 'g'))
> self.lines.append(self.ax1.plot(self.data.xa, self.data.ys, '-r'))
>
> # Update plot with new data
>
> def RefreshPlot(self, data):
> self.lines[0].set_data((self.data.xa,self.data.ya))
> self.lines[1].set_data((self.data.xa,self.data.ys))
>
> self.canvas.draw()
>
> # Main program
>
> if __name__ == "__main__":
> data = PlotData()
> pwin = PlotWin(data)
> pwin.RefreshPlot(data)
>
> The plot data changes during the application and I just want to
> replace the existing data with the new data (which may have a
> different number of points compared to the old data). I get the
> Python error "'list' object has no attribute 'set_data'" when the
> code executes RefreshPlot(). AFAIK lines[0] and lines[1] are
> 'Line2D' objects (at least that's what Python says they are when I
> ask to have them printed) , which do have a 'set_data' method. I'm
> sure there's something really easy that I need to do but just can't
> see it - all suggestions gratefully received!

I think the problem is:

self.lines.append(self.ax1.plot(self.data.xa, self.data.ya, 'g'))

plot() returns a list of lines. You are appending that list to self.lines, so
when you index self.lines[0] later, you are getting the list returned by
plot. You should either use extend() instead of append, or you need to index
deeper: self.lines[0][0] and self.lines[0][1].

Darren

The self.lines[0][1] idiom is really ugly. Avoid it with Darren't
first suggestions::

  self.lines.extend(ax.plot(something))

If the xdata or ydata change in size, you will need to set them both
simultaneously:

  line.set_data(xdata, ydata)

JDH

···

On Wed, Jun 25, 2008 at 7:31 AM, eShopping <etrade.griffiths@...312...> wrote:

Hi Darren

thanks for the quick reply. I tried

self.lines[0][0].set_data((self.data.xa,self.data.ya))
self.lines[0][1].set_data((self.data.xa,self.data.ys))

but got the error 'list index out of range' after the second
statement. I also tried

self.lines[0][0].set_data((self.data.xa,self.data.ya))
self.lines[1][0].set_data((self.data.xa,self.data.ys))

There were no errors in this case but the data does not plot
correctly. Finally, I tried

self.lines[0][0].set_xdata(self.data.xa)
self.lines[0][0].set_ydata(self.data.ya)
self.lines[1][0].set_xdata(self.data.xa)
self.lines[1][0].set_ydata(self.data.ys)

but matplotlib complained that 'xdata and ydata must be the same
length' after executing the first of these statements (presumably
because the new xa array has a different number of elements than the
old ya array)