0

I listen with serial port to some data. I display these values in a tkinter output and a dashboard done in pygame. everything works great.

now I tried to integrate a plotter window with pyplot.the user can choose 2 value of 6 values. after 1-2 minutes the plotter slows down, I think the plotter hold the old values of the graph somewhere. how can I handle this in a better was.

import matplotlib.pyplot as plt

the init

def initPlotter():
    global showPlotterFlag
    global lastPlotterChoice
    global fevent
    global fig
    global ax1, ax2
    global start

    start = time.time()

    plt.style.use('bmh')
    fig, (ax1, ax2) = plt.subplots(2)
    fig.suptitle('mobile instruments plot')
    plottertext = ["aaaaaaaaa", "bbbbbbbbbbbbbb",
                           "cccccccccc", "ddddddddd", "eeeeeee", "ffffffffff"]
    plotterAxis = [[0, 5], [50, 150], [0, 6000], [0.7, 1.3], [50, 250], [8, 16]]

    maxVal = 0

    for i in range(6):
        if lastPlotterChoice[i] == 1:
            maxVal += 1
            if (maxVal == 1):
                #ax1.set_title(plottertext [i])
                ax1.set_ylabel(plottertext [i])
                ax1.set_ylim([plotterAxis[i][0], plotterAxis[i][1]])
            if (maxVal == 2):
                #ax2.set_title(plottertext [i])
                ax2.set_ylabel(plottertext [i])
                ax2.set_ylim(plotterAxis[i][0], plotterAxis[i][1])
    if maxVal == 1:
        ax2.set_ylabel('nicht benutzt')
    fevent = plt.connect('close_event', handle_close)

    plt.show(block=False)
    showPlotterFlag=True

on the main loop:

def showPlotterDisplay():
    global yps
    global valueInArray
    global valuesCurr
    global ax1, ax2
    global start

    yps += 1
    maxVal = 0

    now = time.time() - start

    for i in range(6):
        if lastPlotterChoice[i] == 1:
            maxVal += 1
            if (maxVal == 1):
                ax1.set_xlim([now-12, now+3])
                ax1.plot(now, valueInArray[i], 'g.')  # valueInArray[1] r+

            if (maxVal == 2):
                ax2.set_xlim([now-12, now+3])
                ax2.plot(now, valueInArray[i], 'r.')  # valueInArray[1] r+
bluelemonade
  • 1,115
  • 1
  • 14
  • 26

1 Answers1

0

In matplotlib, every time you plot (or draw on the axis in any way, e.g. with imshow) you're not clearing the previous state, you're just adding on top of what was there.

In long loops, this causes the axis to become overloaded with actors, thus slowing down your code.

One possible solution, assuming you don't need all lines plotted at the same time on one axis, is to ax.clear() the axis before plotting the data at the next iteration. If, on the other hand, you need a lot of data on one axis, your best bet is to work in non-interactive mode (plt.ioff()), plot everything you need and finally show()/save your figure (this way you skip all the intermediate rendering and redrawing). The final plot will still be slow, but the intermediate steps won't be as bad.

GPhilo
  • 18,519
  • 9
  • 63
  • 89
  • ok, with ax.clear I can only see one value on the grid. that's not what I want. It would be Ok to see the last 30-40 values to get a feeling what's going on. this means I have to put the number of values into an array an then show it. how is the speed when I always show the values when I got a new value? – bluelemonade Oct 15 '19 at 09:06
  • Yes, `clear` wipes everything off the plot. Another possible way you have is to save the results of the `plot` calls and [remove the old lines you don't need anymore](https://stackoverflow.com/questions/4981815/how-to-remove-lines-in-a-matplotlib-plot) – GPhilo Oct 15 '19 at 09:13
  • hmmm, I read the thread but lines = ax1.plot(now, valueInArray[i], 'g.') print(len(lines)) gives me only one object in the lines array. how can I see all my points and delete them when they are outside the view? – bluelemonade Oct 15 '19 at 10:28
  • Keep track of the lines in a list – Jody Klymak Oct 15 '19 at 14:39