Process finished with exit code -1073741819 (0xC0000005) Python Tkinter GUI Canvas Update

0

I need to update a TKagg Canvas plot on every iteration of a threading timer. The plot is displayed on the first iteration of the timer and then the program pauses and outputs - 'Process finished with exit code -1073741819 (0xC0000005)'

I have been struggling to get this code to work for a few days now. Any help would be appreciated. The code runs as is and should output the same exit code. I cannot figure out how to attach my test matrix, but it is just a 401x401 numpy array containing values between 0.0-0.05

import threading
from tkinter import *
from tkinter import ttk
import tkinter as tk
import numpy as np
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
matplotlib.use('Agg')
from matplotlib import cm, colors
import os
import os.path


class APP(tk.Tk):
    update_interval = 0.2
    dwell_time = np.array([20., 20., 20.])
    current_count = 0
    colormap = 'jet'

    window_height = 480
    window_width = 720

    num_columns = 20
    num_rows = 20

    canvas_width = window_width / num_columns * 13
    canvas_height = window_height / num_rows * 16

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # create a container
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=False)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # initialize an empty array of frames
        self.frames = {}

        # iterate through the tuple of page frames - basically creates/configures an empty frame for each page
        for F in (Page1, Page2):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="NSEW")

            frame.grid_rowconfigure(0, weight=1)  # fills the whole window
            frame.grid_columnconfigure(0, weight=1)  # fills the whole window

        self.show_frame(Page1)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def resource_path(relative_path):
        return os.path.join(os.path.dirname(os.path.abspath(__file__)), relative_path)

    filename = "22222222_20210203083122.csv"
    filepath = resource_path('PDT_Patient_Treatment_Maps/' + filename)
    dose_map = np.load(resource_path('test.npy'))
    print(dose_map)

class Page1(tk.Frame):
    f = Figure()
    update_interval = 0.2
    dwell_time = np.array([20., 20., 20.])
    current_count = 0
    colormap = 'jet'

    window_height = 480
    window_width = 720

    num_columns = 20
    num_rows = 20

    canvas_width = window_width / num_columns * 13
    canvas_height = window_height / num_rows * 16

    plt = f.add_subplot(111)

    def start_treatment(self):

        counts_per_each_diffuser = (APP.dwell_time / APP.update_interval).astype(int)
        self.cumulative_count = counts_per_each_diffuser.cumsum()
        self.total_count = self.cumulative_count[-1]
        self.max_count = counts_per_each_diffuser.max()
        self.current_map = np.zeros(APP.dose_map.shape)  # initialize detection map
        self.timer_update()

    def timer_update(self):
        """update detector map and progress bar"""
        timer = threading.Timer(APP.update_interval, self.timer_update)
        timer.start()
        if APP.current_count >= self.total_count:
            timer.cancel()
            APP.current_count = 0

        else:
            self.update_det_map()
            self.current_count += 1
            current_percentage = self.current_count / self.total_count
            current_percentage = current_percentage if current_percentage <= 1 else 1
            self.progress['value'] = round(current_percentage, 3) * 100
            self.style.configure('text.Horizontal.TProgressbar', text='{:.1%}'.format(current_percentage))

    def update_det_map(self):
        self.show_det_map(self.current_map, self.det_canvas, self.plt)

    def show_det_map(self, map_data, canvas, ax):
        """convert 2d map data into PhotoImage RGB data and draw it on detector canvas"""

        self.gray2rgb = cm.get_cmap(self.colormap)
        img = (np.delete(self.gray2rgb(map_data), 3, 2) * 255).astype(np.uint8)
        ax.clear()
        ax.imshow(img, cmap=self.gray2rgb)
        canvas.draw()

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        # initializes grid to have evenly weighted rows and columns for the page
        # self.dose_map = dose_map
        cols = 0
        while cols < 20:
            self.grid_columnconfigure(cols, weight=1)
            self.grid_rowconfigure(cols, weight=1)
            cols += 1

        self.det_canvas = FigureCanvasTkAgg(self.f, self)
        self.det_canvas.draw()
        self.det_canvas.get_tk_widget().grid(row=0, column=6, rowspan=16, columnspan=13, padx=5, pady=10, sticky='NSEW')
        self.det_canvas._tkcanvas.grid(sticky='nsew', pady=10, padx=10)
        self.det_canvas._tkcanvas.config(highlightbackground='grey64', highlightthickness=1)

        # progress bar
        self.style = ttk.Style(self)
        self.style.layout('text.Horizontal.TProgressbar',
                          [('Horizontal.Progressbar.trough',
                            {'children': [('Horizontal.Progressbar.pbar',
                                           {'side': 'left', 'sticky': 'ns'})],
                             'sticky': 'nsew'}),
                           ('Horizontal.Progressbar.label', {'sticky': 'ns'})])
        self.style.configure('text.Horizontal.TProgressbar', text='0.0 %', font=('Times', 12))
        self.progress = ttk.Progressbar(self, orient=HORIZONTAL, mode='determinate')
        self.progress.configure(style='text.Horizontal.TProgressbar')
        self.progress.grid(row=18, column=0, rowspan=1, columnspan=20, padx=10, pady=5, sticky='NSEW')

        # inserts space between lumeda logo and username label
        self.grid_rowconfigure(17, weight=1)  # weight controls number of spaces
        self.grid_rowconfigure(19, weight=1)  # weight controls number of spaces

        style = ttk.Style()
        style.configure('green.TButton', background='green4', font='bold', foreground='green4', highlightcolor='green4')
        self.start_btn = ttk.Button(self, text="START", style='green.TButton',
                                    command=lambda: self.start_treatment())
        self.start_btn.grid(row=20, column=5, rowspan=1, columnspan=1, pady=10, padx=5, sticky='nsew')


class Page2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)


if __name__ == '__main__':
    root = APP()
    root.geometry("720x460")
    root.resizable(0, 0)
    root.mainloop()

python
matplotlib
tkinter
python-multithreading
tkinter-canvas

1 Answer

0

Ended up using the after() function and everything worked. Thank You!

answered on Stack Overflow Feb 4, 2021 by Maxwell Gerhardson

User contributions licensed under CC BY-SA 3.0