[PYTHON] Make the SIR model calculation program GUI

Introduction

In my last article, I described the SIR model that explains the spread of infectious diseases. At that time, I also posted a Python program for numerical integration that solves the SIR model. In this article, I will try to make the Python program into a GUI.

Previous article: Mathematical prediction model for infectious diseases (SIR model): Case study (1) https://qiita.com/kotai2003/items/d74583b588841e6427a2

GUI description

The reason for converting the program I made into a GUI is "I want others to use it." In the future, I would like to distribute it in the form of setup.exe, not just the GUI Py code.

First, the screen configuration of the GUI created this time. Enter the infection rate (Beta) and removal rate (Gamma) of the SIR model in the blanks on the right and press the Draw button below it to plot the calculation result of the SIR model on the center screen.


\begin{align}

\frac{dS}{dt} &= -\beta SI \\
\frac{dI}{dt} &=  \beta SI -\gamma I \\
\frac{dR}{dt} &=  \gamma I \\

\end{align} 
\begin{align}
S &:Infectable person\quad \text{(Susceptible)} \\
I &:Infected person\quad \text{(Infectious)} \\
R &:Those who died after infection or who acquired immunity\quad \text{(Removed)} \\
\beta &:Infection rate\quad \text{(The infectious rate)} \quad [1/day] \\
\gamma &:Exclusion rate\quad \text{(The Recovery rate)} \quad [1/day] \\
\end{align}

On the initial screen, "Typical Condition ~" is written, but this is for reference when entering the infection rate (Beta) and removal rate (Gamma).

スクリーンショット 2020-02-22 20.38.20.png

The next screen shows the calculation result. The numerical integration result of the SIR model is displayed in Line Plot. The newly entered infection rate (Beta) and removal rate (Gamma) values will be updated in the title.

スクリーンショット 2020-02-22 20.38.41.png

You can exit the GUI by pressing the Quit button at the bottom right.

スクリーンショット 2020-02-22 20.40.14.png

Program description

The GUI library used Tkinter. I will briefly explain the operation of the program.

(1) Prepare Canvas Widget with Tkinter. In Tkinter's Entry Widget, prepare a text box for entering the infection rate (Beta) and removal rate (Gamma). (2) Calculate the SIR model with scipy and plot the result with matplotlib. (3) Draw the matplotlib figure with the Canvas Widget.

Import the required libraries.

import tkinter
import tkinter.messagebox as tkmsg
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk

import numpy as np
from functools import partial
from scipy.integrate import odeint

Prepare the functions required for numerical integration of the SIR model.


# SIR Differential Equation
def SIR_EQ(v, t, beta, gamma):
    '''
    dS/dt = -beta * S * I
    dI/dt = beta * S * I - gamma * I
    dR/dt = gamma * I

    [v[0], v[1], v[2]]=[S, I, R]

    dv[0]/dt = -beta * v[0] * v[1]
    dv[1]/dt = beta * v[0] * v[1] - gamma * v[1]
    dv[2]/dt = gamma * v[1]

    '''
    return [-beta*v[0]*v[1], beta * v[0] * v[1] - gamma * v[1], gamma * v[1]]

# Solving SIR Equation
def Calc_SIR(var_b, var_r):
    # parameters
    t_max = 14
    dt = 0.01
    #beta_const = 0.0026
    #gamma_const = 0.5

    beta_const = var_b
    gamma_const = var_r

    # initial_state
    S_0 = 762
    I_0 = 1
    R_0 = 0
    ini_state = [S_0, I_0, R_0]  # [S[0], I[0], R[0]]

    # numerical integration
    times = np.arange(1, t_max, dt)
    args = (beta_const, gamma_const)
    # Solver SIR model
    result = odeint(SIR_EQ, ini_state, times, args)
    return times,result

Prepare a function to be executed at the time of Tkinter button Event. It is a mechanism to prepare an axes instance (= ax) of matplotlib in the DrawCanvas function and plot that instance. The final canvas.draw () will show the axes instance of matplotlib in the canvas widget.

def Quit():
    tkmsg.showinfo("Tomomi Research Inc.","Thank you for running this program!")
    root.quit()
    root.destroy()

#Draw Button
def DrawCanvas(canvas, ax):
    value_beta = EditBox_beta.get()
    value_gamma = EditBox_gamma.get()
    if value_beta != '':
        EditBox_beta.delete(0, tkinter.END)
        EditBox_gamma.delete(0, tkinter.END)
        ax.cla()
        beta = float(value_beta)
        gamma = float(value_gamma)
        t_r, res_r = Calc_SIR(beta,gamma)

        ax.plot(t_r, res_r)
        ax.legend(['Susceptible', 'Infectious', 'Removed'])
        ax.set_title('Beta='+str(beta)+', Gamma='+str(gamma) )
        ax.set_xlabel('time(days)')
        ax.set_ylabel('population')
    canvas.draw()

This part is the main program. The settings for each Tkinter widget are described here.

if __name__ == '__main__':
    try:
        # GUI generate
        root = tkinter.Tk()
        root.title("SIR model")

        # Graph setting
        fig, ax1 = plt.subplots()
        #fig.gca().set_aspect('equal', adjustable='box')  #Adjusting the graph area#get current axes

        ax1.set_title('Typical Condition:  beta=0.0026, gamma=0.5, $S_0$=762, $I_0$=1')


        # Generate Canvas
        Canvas = FigureCanvasTkAgg(fig, master=root)
        Canvas.get_tk_widget().grid(row=0, column=0, rowspan=10)

        #Beta
        EditBox_beta = tkinter.Entry(width=5)  #Generate text box
        EditBox_beta.grid(row=1, column=2)

        GridLabel_beta = tkinter.Label(text="Beta")
        GridLabel_beta.grid(row=1, column=1)

        # Gamma
        EditBox_gamma = tkinter.Entry(width=5)  #Generate text box
        EditBox_gamma.grid(row=4, column=2)

        GridLabel_gamma = tkinter.Label(text="Gamma")
        GridLabel_gamma.grid(row=4, column=1)

        #Various settings related to buttons
        ReDrawButton = tkinter.Button(text="Draw", width=15, command=partial(DrawCanvas, Canvas, ax1))  #Button generation
        ReDrawButton.grid(row=5, column=1, columnspan=2)  #Drawing position(Texto)

        QuitButton = tkinter.Button(text="Quit", width=15, command=Quit)  #Button generation
        QuitButton.grid(row=7, column=1, columnspan=2)  #Drawing position(Texto)

        DrawCanvas(Canvas, ax1)
        root.mainloop()
    except:
        import traceback

        traceback.print_exc()
    finally:
        input(">>")  #Waiting for display when an error is spit out

Summary

It seems that Tkinter and PyQT are famous as Python GUI libraries, but I heard that Tkiknter is easy to program even for beginners, so I chose Tkinter. I'm still interested in PyQT, so if you've used both, please leave a comment.

I think the advantage of Python GUI is that it is Cross Platform. If you create one program, you can use it for Windows, Mac OS, Linux without any changes. Currently, I am thinking of developing a Deep Learning program on Windows and implementing it on Jetson (Linux) made by Nvidia. At that time, I think the Python GUI will be very useful.

Reference material

  1. Story of combining GUI (Tkinter) with Matplotlib https://www.shtsno24.tokyo/2018/12/matplotlibguitkinter.html
  2. Matplotlib & Seaborn Implementation Handbook https://amzn.to/2ujQ2CL
  3. Introduction of mathematical prediction model for infectious diseases (SIR model) https://qiita.com/kotai2003/items/3078f4095c3e94e5325c
  4. Mathematical prediction model for infectious diseases (SIR model): Case study (1) https://qiita.com/kotai2003/items/d74583b588841e6427a2
  5. Embedding in Tk https://matplotlib.org/gallery/user_interfaces/embedding_in_tk_canvas_sgskip.html

Recommended Posts

Make the SIR model calculation program GUI
Make any key the primary key in Django's model
GUI simulation of the new coronavirus (SEIR model)
Make the model a string on a Django HTML template
Implement the mathematical model "SIR model" of infectious diseases with OpenModelica