matplotlib adds second y-axis and stops updating in tkinter applet

I have a tkinter application with four different plots. The code pulls data from several different sources and updates them sequentially.

The problem is that three of the plots stop updating and introduce a second y-axis, while one continues undisturbed, and the three that stop updating do so at different times. Whatever causes this issue does not raise an error or exception:

tkinter screenshot of plots with failed updates

A second system that is being controlled through the same applet has continued plotting and updating without issue.

The GUI has frames for the full pane shown in the image above, then subframes for each plot’s row (since there are some other widgets in the same row), called “pidtypes” in the code. The top plot lives in the primary frame, and the next three live in their own subframes.

The blank plots are generated with the below code:

        # making the top plot

        _window         = _dict["grid"]
        _plot           = _dict["plot"]
        _plot["fig"]    = Figure((w, h))
        _plot["ax"]     = _plot["fig"].add_subplot(111)

        _plot["fig"].set_tight_layout(tight = True)

        _plot["graph"]  = FigureCanvasTkAgg(_plot["fig"], master = _window)enter image description here
        _plot["canvas"] = _plot["graph"].get_tk_widget()

        _plot["canvas"].grid(row = 2, sticky = tk.E)
        _plot["canvas"].grid_propagate(0)

        # making the next three plots

        for j, pidtype in enumerate(self.pidtype):

            window      = _dict[pidtype]["grid"]
            plot        = _dict[pidtype]["plot"]
            plot["fig"] = Figure((w, h))
            plot["ax"]  = plot["fig"].add_subplot(111)

            plot["ax"].yaxis.offsetText.set_fontsize(8)
            plot["fig"].set_tight_layout(tight = True)
            plot["fig"].autofmt_xdate(rotation = 30)

            plot["graph"]   = FigureCanvasTkAgg(plot["fig"], master = window)
            plot["canvas"]  = plot["graph"].get_tk_widget()

            plot["canvas"].grid(row = 0, sticky = tk.E)

The lines are made here:

        data    = _dict["data"]
        _plot   = _dict["plot"]
        t_list  = data["time"]

        _plot["line"], = _plot["ax"].plot_date(t_list, data["pid"], '-')

        for pidtype in self.pidtype:

            plot            = _dict[pidtype]["plot"]
            plot["line"],   = plot["ax"].plot_date(t_list, data[pidtype], '-', label = pidtype)
            plot["target"], = plot["ax"].plot_date(t_list, self.target_line(comb, pidtype), '--', label="target")

And here is the code that updates the plots, which is called periodically in an “after” loop:

def update_figure(self, line, x, y, fig, ax):

   line.set_data(x, y)
   ax.relim(visible_only=True)
   ax.autoscale(tight=True)
   fig.canvas.draw_idle()

Thus far, I cross-checked the parameters of the plot that works correctly (the top one) against the other three. Interestingly, all claim to have the same x limits and the lines they contain have the same data on the x-axis, not truncating where the plot no longer updates. I can pull the data from the failed plots and re-plot them in a new figure without any issues.

I can also create a new figure and copy one of the failed Axes objects into it, and generate the same problem:

image of plot with truncated axis

so I expect there’s something within the Axes object that should point to what’s going on, i.e., outside of tkinter.

Has anyone encountered this before, and if so, any ideas as to what I might be passing to matplotlib to cause this, and how to fix it? I’m having trouble identifying a possible source since the symptom is so unusual.

  • Aren’t you playing a dangerous game with the namespace with variables such as plot and _plot?

    – 

  • The question requires a complete minimal reproducible example, which includes data. If we can’t copy, paste, and run the code, then it’s incomplete.

    – 




  • That’s fair! Both are just references to dictionaries containing the figure, axis, canvas, and graph objects. I suppose it could all be “_plot” since the existing “_plot” is overwritten in the “for” loop anyhow.

    – 

  • 1

    @TrentonMcKinney I’ll do my best! I’ll update the post later this afternoon or tomorrow. In its current form, the code interfaces with hardware and updates every 5 seconds, and didn’t run into this issue until the 2-hour mark. I’ll replace the hardware interface with np.random, set it to update more frequently, and see if regenerate the problem within 20-30 minutes.

    – 

Leave a Comment