Delete/clear/overwrite already drawn canvas with matplotlib.backends.backend_tkagg

Viewed 18

I have a GUI where i monitor sensor data and plot it in a graph. Therefore i create a canvas with the matplotlib.backends.backend_tkagg module. When i hit a button, the sensor data gets stored in numpy arrays and is drawn every 400 ms. When i hit the button again, the monitoring stops and no new drawing is happening. Now when i hit the button again, the same process is starting again. The old drawn graph does disappaer as i wish, but the problem with this is, that there is a new line created which is very annoying. The first picture shows the old graph. The second picture shows the graph after i restarted the process. In the third picture even a third new line appears. Picture 1: old graph after stopping process

Picture 2: new graph after restarting the process

Picture 3: new graph with third line

Now i show you the code i used:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as tk
import numpy as np

dataPlot1 = np.array([])
dataPlot2 = np.array([])
timePlot = np.array([])

def plot_graph():
    if condition == True:
        root.after(400, plot_graph)

    if len(ExChange) > 0:
        if len(dataPlot1) < number_of_data_points:
            timePlot = np.append(timePlot, ExChange[0])
            dataPlot1 = np.append(dataPlot1, ExChange[1])
            dataPlot2 = np.append(dataPlot2, ExChange[3])    

        elif len(dataPlot1) == number_of_data_points:
            timePlot[0:number_of_data_points - 1] = timePlot[1:number_of_data_points]
            timePlot[number_of_data_points - 1] = ExChange[0]

            dataPlot1[0:(number_of_data_points - 1)] = dataPlot1[1:number_of_data_points]
            dataPlot1[number_of_data_points - 1] = ExChange[1]

            dataPlot2[0:(number_of_data_points-1)] = dataPlot2[1:number_of_data_points]
            dataPlot2[number_of_data_points-1] = ExChange[3]

        if len(timePlot) > 0:
            min_value_1 = 0
            max_value_1 = 0
            min_value_2 = 0
            max_value_2 = 0
        
            if PlotCondition[0] == 1:
                lines1.set_xdata(timePlot)
                lines1.set_ydata(dataPlot1)
                if np.amin(dataPlot1) > min_value_1 and min_value_1 == 0:
                    min_value_1 = np.amin(dataPlot1)
                if np.amin(dataPlot1) < min_value_1:
                    if np.amin(dataPlot1) == 0.0 or np.amin(dataPlot1) == 0:
                        pass
                    else:
                        min_value_1 = np.amin(dataPlot1)
                if np.amax(dataPlot1) > max_value_1:
                    max_value_1 = np.amax(dataPlot1)
            else:
                lines1.set_ydata([])
                lines1.set_xdata([])
            
            if PlotCondition[1] == 1:
                lines2.set_xdata(timePlot)
                lines2.set_ydata(dataPlot2)
                if np.amin(dataPlot2) > min_value_1 and min_value_1 == 0:
                    min_value_1 = np.amin(dataPlot2)
                if np.amin(dataPlot2) < min_value_1:
                    if np.amin(dataPlot2) == 0.0 or np.amin(dataPlot2) == 0:
                        pass
                    else: 
                        min_value_1 = np.amin(dataPlot2)
                if np.amax(dataPlot2) > max_value_1:
                    max_value_1 = np.amax(dataPlot2)
            else:
                lines2.set_ydata([])
                lines2.set_xdata([])   
        
        lines1.set_xdata(timePlot)
        lines1.set_ydata(dataPlot1)
        
        lines2.set_xdata(timePlot)
        lines2.set_ydata(dataPlot2)
    
        canvas.draw()

if __name__ == '__main__':
    root = tk.Tk()

    # ------------------ Create frame for Control ------------------#
    frm_frameC = tk.LabelFrame(root, padx=10, pady=10, bg='light grey', bd=3, width=1650, height=800)
    frm_frameC.place(x=0, y=0)

    # ------------------ Create figure for plotting ------------------#
    fig = Figure()
    ax = fig.add_subplot(111)
    ax.set_title('Data monitoring')
    ax.set_xlabel('time in [s]')
    ax.set_ylabel('[l/min]')
    ax.set_xlim(0, 30)
    ax.set_ylim(0, 101)
    ax2 = ax.twinx()
    ax2.set_ylabel('[l]')
    ax2.set_ylim(0, 1001)
    lines1 = ax.plot([], [], color='saddlebrown')[0]
    lines2 = ax.plot([], [], color='peru')[0]
    canvas = FigureCanvasTkAgg(fig, master=frm_frameC)
    canvas.get_tk_widget().place(x=5, y=5, width=1000, height=400)
    canvas.draw()

I tried to cut out the relevant parts of my code. There is happening more stuff but the key objective is in the code below. The GUI gest created when the script is run. After hitting a button the "def plot_graph()" gets called. There is another process (running with multiprocessing) which is filling the ExChange array with data. The plot_graph function stores the data in the lines objects if the plotcondition euqals 1. The plotcondition gets set by another two buttons, it is for selection which graph shall be drawn. When hitting the button to start the plot_graph, this function stops because the condition isnt True anymore. When hitting again it sets the condition to true and calls the function again.

I already tried setting all lines objects with no data like lines1.set_ydata([]) and lines1.set_xdata([]). But when i then do the canvas.draw() with the empty data lines before starting the plot_graph function again, the described behaviour appears.

Anyone has an advice how i can get rid of the old graph and starting with a blank white figure?

0 Answers
Related