2

I am plotting iteratively using matplotlib in python. I am setting the axis of the plot, so as to display e.g. only 50 lines at a time. A pseudo code is given below as an example:

x = 0
y = 1
line_plot = 50
axis.set_ylim(0 , line_plot)
    while True:
         plot(x,y)
         y = y+1
         if y > line_plot :
               axis.set_ylim(y , y+line_plot)

This code will run indefinitely, and eventually the memory required for the plot will get quite large, even if only 50 lines are present on the graph (since all data points are kept in memory). I would like to know if there is a command in python to delete all data that is out of axis limits, freeing some memory space.

Thank you, Gaelle

2 Answers 2

1

This will depend a little bit on how exactly your script looks like. You need some method to determine the y-coordinates of every line, and based on some criteria remove them or not. But if you do something like:

x = np.arange(1)
y = np.ones(1)

pl.figure()
l1 = pl.plot(x,y)[0]
y[:] += 1
l2 = pl.plot(x,y)[0]

and call get_ydata() on both lines, they will have the same y-values, so get_ydata() seems to return the original array, not necessarily the values drawn in the plot (which apparently is a bug, see: this matplotlib issue). If, instead of y[:] += 1 you make an actual copy of the array (y = y.copy()+1), you can use get_ydata(). If this is the case in your real-world problem, such a solution might work:

import matplotlib
import matplotlib.pylab as pl
import numpy as np

pl.close('all')

x = np.arange(100000)
y = np.ones(x.size)

pl.figure()
ax = pl.gca()
line_plot = 50
ax.set_ylim(0, line_plot)

for i in range(200):
    pl.plot(x, y)
    y = y.copy() + 1
    if y[0] > line_plot:
        ax.set_ylim(y[0]-line_plot, y[0])

    for l in ax.get_lines():
        yval = l.get_ydata()[0]
        if(yval < ax.get_ylim()[0]):
            l.remove()

If I remove the for l in ax.get_lines part, the memory usage scales with i, with this part included the memory usage stays constant, even for very large values of i

Sign up to request clarification or add additional context in comments.

2 Comments

I also found it annoying, but if the actual data is kept (instead of a reference to the original array) that would create quite a memory overhead?
It is to avoid a) any changes we make internally from leaking out and b) to prevent surprises due to hidden shared objects. Definitely has a memory cost, but the downsides of not copying could be much worse.
0

You want look at the animation examples

# make a figure and axes object
fig, ax = plt.subplots()
# make a Line2D artist
ln, = ax.plot([], [], linestyle='', marker='o')
# local version of the data
xdata, ydata = [], []
for j in range(200):
    # update your copy of the data
    xdata.append(j)
    ydata.append(j*j)
    xdata = xdata[-50:]
    ydata = ydata[-50:]
    # update the Line2D objects copy of the data
    ln.set_data(xdata, ydata)
    # autoscale limits to new data
    ax.relim()
    ax.autoscale()
    # needed in non-interactive mode and/or mpl < 1.5
    # fig.canvas.draw_idle()
    # sleep, but run the GUI event loop
    plt.pause(.1)

4 Comments

But this only animates one single line? It seems that Gaelle wants to plot multiple lines, only showing the last 50 ones (or the ones which are within the visible y-range
The OP is plotting single points, you can get the same effect with my last edit.
I read it as plotting lines instead of points, otherwise "the memory required for the plot will get quite large, even if only 50 lines are present on the graph" wouldn't make sense to me. But anyhow, lets see...
Thank you all for your inputs. I am currently away from a PC, but will return in two days time. In the mean time, I can already clarify one thing : x, y are in real case vectors, with x containing n values and y being a vector of ones(1,n)*increment, this increment determining the "line" where the vector x is plotted on the figure. I simplified the example as in essence the question still holds if I plot a point instead of an entire vector. I hope this is clear!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.