Home>

Display the read csv file on tkinter, select the range I want to least square by right-clicking the mouse on the graph, and draw the least-squares line by left-double-clicking. Do this twice, draw two least squares lines, and then press the "intersection" button displayed on tkinter to make a point at the intersection of the two least squares. I would like to create it.
I was able to display the graph on tkinter, operate the mouse, and set the button, but even if I press the button, the intersection is not marked and the following error message appears. I'm worried because I don't know how to resolve this error message.

can't invoke "update" command: application has been destroyed
Corresponding source code
from tkinter import *
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
from scipy import optimize
import pylab
import turtle
import tkinter as tk
x_data = []
y_data = []
katamuki = []
seppen = []
state = 0
f = open ('xrr_data.csv','r')
datalist = f.readlines ()
for data in datalist:
    if state == 1:
        x_data.append (float (data.split (',') [0]))
        y_data.append (float (data.split (',') [1]))
    if "Angle, Intensity" in data:
        state = 1
f.close ()
xdata = np.array (x_data)
ydata = np.array (y_data)

def drawlsm (lind, rind):
    global xdata2
    global ydata2
    xdata2 = xdata [lind: rind]
    ydata2 = ydata [lind: rind]
    parameter0 = [0.,0.]
    result = optimize.leastsq (fit_func, parameter0, args = (xdata2, ydata2))
    print (result)
    a_fit = result [0] [0]
    b_fit = result [0] [1]
    print (a_fit, b_fit)
    plt.plot (xdata, a_fit * xdata + b_fit,'k-', label ='fitted line', linewidth = 3, alpha = 0.3)

#Least squares method with scipy.optimize
def fit_func (parameter, x, y):
    a = parameter [0]
    b = parameter [1]
    residual = y-(a * x + b)
    return residual
def oncmask (event):
    global stat
    global leftind, rightind
    ind = np.searchsorted (xdata, event.xdata)
    plt.title ("You clicked index =" + str (ind))
    if event.button == 3 and stat == 1:
        leftind = ind
        ax.plot ([xdata [ind]],

[ydata [ind]],

".", color = "red")
        stat = 2
    elif event.button == 3 and stat == 2:
        rightind = ind
        ax.plot (xdata [leftind: rightind],

ydata [leftind: rightind],

color = "red")
        stat = 3
        print (leftind, rightind)
    elif event.button == 1 and event.dblclick == 1 and stat == 3:
        plt.title ("Approved")
        mask [leftind: rightind] = False
        drawlsm (leftind, rightind)
        stat = 1
    elif event.button == 2 and stat == 3:
        plt.title ("Canceled")
        ax.plot (xdata [leftind: rightind],

ydata [leftind: rightind],

color = "blue")
        ax.plot ([xdata [leftind]],

[ydata [leftind]],

".", color = "green")
        stat = 1
    fig.canvas.draw ()
katamuki2 = np.array (katamuki)
seppen2 = np.array (seppen)

def getintersection (): # Get the intersection of the last line and the line drawn immediately before it
    global xa # intersection x coordinate
    indent = len (katamuki2) # number of elements in the slope list
    indent2 = len (seppen2) # number of elements in the intercept list
    print ("Number of elements in tilt list = {},

 Number of elements in intercept list = {} ". format (indent, indent2))
    #xa ask
    xa = (seppen2 [indent2-1]-seppen2 [indent2-2])/(katamuki2 [indent-2]-katamuki2 [indent-1]) # (b1-b0)/(a0-a1)
    print ("intersection coordinates = {}" .format (xa))
    ya = katamuki2 [indent-1] * xa + seppen2 [indent2-1] # Find the y coordinate from the x coordinate
    plt.plot (xa, ya, ".", color = "m") # intersection plot
    plt.show ()
    fig.canvas.draw ()
# x = np.arange (0, 10, 0.1)
# y = np.random.rand (100)
mask = np.ones (len (xdata), dtype = bool)stat = 1
fig = plt.figure ()
ax = fig.add_subplot (111)
ax.plot (xdata, ydata)
#Window settings
root = Tk ()
root.title ("Plot window")
root.geometry ()
#Frame setting
frame_1 = Frame (root, bd = 4, relief = GROOVE)
frame_2 = Frame (root, bd = 4, relief = GROOVE)
#widget settings
btn2 = Button (frame_1, text ='intersection', font = ("", 18), command = getintersection)
canvas = FigureCanvasTkAgg (fig, frame_2) # Put fig on canvas
#Widget placement
frame_1.grid (row = 0, column = 0, sticky = W + E)
frame_2.grid (row = 1, column = 0)
btn2.pack (fill = X)
canvas.get_tk_widget (). grid (row = 0, column = 0)
cid = fig.canvas.mpl_connect ('button_press_event', oncmask)
canvas.start_event_loop ()
What I tried

When I created a program that quits tkinter when the button was pressed and tried it, I was able to quit tkinter but got the same error message.

Supplementary information (FW/tool version, etc.)

I'm new to Python, and I'm sure there are some points that I can't explain, but I'd appreciate any advice.
Thank you.

"Addition"
The excel data looks like this.

Column 1 Column 2
Angle Intensity
0.027 879036
0.029 838848
0.031 766020
0.033 745008
0.035 714204
0.037 695844
0.039 677280
0.041 656268
0.043 628116
0.045 661164
0.047 649332
0.049 651984
0.051 640560
0.053 631788
0.055 647496
0.057 643620
0.059 656064
0.061 641988
0.063 668916
0.065 663000
0.067 671160
0.069 661164
0.071 680136
0.073 666876
0.075 691560
0.077 681564
0.079 712368
0.081 706656
0.083 744600
0.085 720732
0.087 740520
0.089 750108
0.091 745008
0.093 754800
0.095 776832
0.097 777240
0.099 778260
0.101 778260
0.103 795396
0.105 810492
0.107 812124
0.109 813960
0.111 812532
0.113 807636
0.115 838440
  • Answer # 1

    Problems at the end of the program

    (* Addition: It is not an answer to the problem of intersection)

    Cause: For a destroyed widget
    A running event loop is trying to access.

    Workaround: When using tkinter/matplotlib together,
    Stop the event loop in advance and then destroy it.

    def _quit (): # Called when all windows are closed
        canvas.stop_event_loop ()
        root.destroy ()
    root.protocol ("WM_DELETE_WINDOW", _quit)

    By the way, if you use root.mainloop instead of canvas.start_event_loop,
    Root.quit instead of canvas.stop_event_loop,
    Use the stop method corresponding to the event loop.


    In a normal tkinter program,
    When you close the window, the program ends, so
    Both of these methods are often treated as the end of the program,
    If the event loop is involved, it may be necessary to use it properly.

    Discard root.destroy resource

    Stop the root.quit event loop