fcp2021 / GUI.py
GUI.py
Raw
#import list
import tkinter as tk
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, 
NavigationToolbar2Tk)
import os
from tkinter import *
from Project_Classes import Simulation, Animation, evolution_simulation
########## SET UP THE MAIN WINDOW ##########
def page1(root): 
    window = tk.Frame(root)
    window.grid()
    root.title('Covid-19 Simulation')
    window.configure(bg='white')
    window = tk.Frame(root)
    window.grid()
    window.configure(bg='white')
    explanation = Label(window, bg='white', text="TV = True Value\n").pack()

    
    #Create labels at top
    S1 = tk.Label(window, bg='white', fg='black', width=30, text='Size of Experiment: 1000 People')
    S1.pack()
    S2 = tk.Label(window, bg='white', fg='black', width=30, text='1 Asymptomatic case introduced')
    S2.pack()
    S3 = tk.Label(window, bg='white', fg='black', width=30, text='1 Symptomatic case introduced')
    S3.pack()
    S4 = tk.Label(window, bg='white', fg='black', width=40, text='Average daily interactions (asymptomatic): 1')
    S4.pack()
    S5 = tk.Label(window, bg='white', fg='black', width=40, text='Average daily interactions (asymptomatic): 1')
    S5.pack()
    S6 = tk.Label(window, bg='white', fg='black', width=30, text='Max travel distance (symptomatic): 10')
    S6.pack()
    S7 = tk.Label(window, bg='white', fg='black', width=30, text='Max travel distance (symptomatic): 10')
    S7.pack()
    S8 = tk.Label(window, bg='white', fg='black', width=30, text='Days Of Experiment')
    S8.pack()
   #Save and convert variables to constants
    def Save():
       global SOEV # SOEV = Size of Experiment variable
       global ICAV # ICAV = introduced cases asymp variable
       global ICSV # ICSV = introduced cases symp variable
       #global SIPV # SIPV = starting ill people variable
       global SIOA # SIOA = Social Interaction Of Asym
       global SIOS # SIOS = Social Interaction Of Sym
       global TDOA # Travel Distance of Asym
       global TDOS # Travel Distance of Sym
       global Days

       SOEV = int(str(k1.get()))         
       
       #SIPV = int(str(k3.get())) 
       #SIPV = SIPV*0.01
       #SIPV = round(SOEV*SIPV, 0)      
       
       ICAV = int(str(k3.get())) 
       #ICAV = round(ICAV*0.01*SIPV, 0)       
       
       ICSV = int(str(k2.get())) 
       #ICSV = (ICSV*0.01)
       #ICSV = (ICSV-1)*SIPV
       #ICSV = round(-ICSV, 0) 
       
       SIOA = float(str(k4.get()))  
       #SIOA = round(SIOA*0.01, 2)
       
       SIOS = float(str(k5.get()))         
       #SIOS = round(SIOS*0.01, 2)
       
       TDOA = int(str(k6.get()))         
       #TDOA = round(TDOA*0.01, 2)
       
       TDOS = int(str(k7.get()))         
       #TDOS = round(TDOS*0.01, 2)
       
       Days = int(str(k8.get()))
       


       simulation = Simulation(SOEV, ICAV, ICSV, SIOA, TDOA, SIOS, TDOS, Days, lockdown = False)
       simulation.init_array()
       animation = Animation(simulation.days, simulation.size**2, simulation)
       animation.show()
    """ DEBUG CHECKER 
       print(SOEV, " people in EX")
       print(ICSV, " people will have SYM")
       print(ICAV, " Will not have simp")
       #print(SIPV, " total ppl are ill")
       print(SIOS, " Symp Interaction (multiply true value)")
       print(SIOA, " Asymp interaction (multiply True Value)")
       print(TDOA, " Asym Travel (multiply True Value)")
       print(TDOS, " asym Travel (muiltiply true value")
       print(Days, "Of experiment")
             # DEBUG CHECKER """
         
    #Create Sliders
    def Size_of_Experiment_Slider(d1):
        S1.config(text='Size of Experiment: ' + str(int(d1)**2) + ' People')
    k1 = tk.Scale(window, label='Size of Experiment', from_=100, to=2500, orient=tk.HORIZONTAL, length=430, showvalue=0, tickinterval=200, resolution=10, command=Size_of_Experiment_Slider, bg='white')
    k1.set(1500)
    k1.pack()
    def Chances_of_symptoms (d2):
        S2.config(text= d2 + ' Symptomatic cases introduced')
    k2 = tk.Scale(window, label='Starting symptomatic', from_=0, to=50, orient=tk.HORIZONTAL, length=430, showvalue=0,tickinterval=10, resolution=1, command=Chances_of_symptoms, bg='white')
    k2.set(1)
    k2.pack()
    
    def Starting_Ill_People (d3):
        S3.config(text=d3 + ' Asymptomatic cases introduced')
    k3 = tk.Scale(window, label='Starting Asymptomatic', from_=0, to=50, orient=tk.HORIZONTAL, length=430, showvalue=0,tickinterval=10, resolution=1, command=Starting_Ill_People, bg='white')
    k3.set(1)
    k3.pack()
 
    def Social_interaction_ASYM (d4):
        S4.config(text='Average daily interactions (asymptomatic): ' + d4)
    k4 = tk.Scale(window, label='Social interaction of Asym %', from_=0, to=2, orient=tk.HORIZONTAL, length=430, showvalue=0,tickinterval=0.2, resolution=0.05, command=Social_interaction_ASYM, bg='white')
    k4.set(1)
    k4.pack()
    def Social_interaction_SYM (d5):
        S5.config(text='Average daily interactions (symptomatic): ' + d5 )
    k5 = tk.Scale(window, label='Social interaction of sym %', from_=0, to=2, orient=tk.HORIZONTAL, length=430, showvalue=0,tickinterval=0.2, resolution=0.05, command=Social_interaction_SYM, bg='white')
    k5.set(1)
    k5.pack()
    
    def Travel_ASYM(d6):
        S6.config(text='Max travel distance (asymptomatic): ' + d6)
    k6 = tk.Scale(window, label='Max travel distance (asymptomatic): ', from_=1, to=51, orient=tk.HORIZONTAL, length=430, showvalue=0, tickinterval=10, resolution=1, command=Travel_ASYM, bg='white')
    k6.set(5)
    k6.pack()
    def Travel_SYM(d7):
        S7.config(text='Max travel distance (symptomatic): ' + d7 )
    k7 = tk.Scale(window, label='Max travel distance (symptomatic): ', from_=1, to=51, orient=tk.HORIZONTAL, length=430, showvalue=0, tickinterval=10, resolution=1, command=Travel_SYM, bg='white')
    k7.set(5)
    k7.pack()
    
    def Days(d8):
        S8.config(text='Days Of Experiment ' + d8)
    k8 = tk.Scale(window, label='Days Of Experiment', from_=0, to=1000, orient=tk.HORIZONTAL, length=430, showvalue=0, tickinterval=100, resolution=10, command=Days, bg='white')
    k8.set(500)
    k8.pack()
    #Create Text box input
    DaysL = Label(window, text="Custom Days Of Experiment:", bg = 'white')
    DaysL.pack()
    DaysE = Entry(window, bd =5, textvariable=Days)
    DaysE.pack()
 
    #Create buttons
   
    button1 = Button(master = window, command = Save, height = 1, width = 35, bg="white", text = "Simulate").pack()
    #button2 = Button(window, text = str(pause_play()), width=20, command=changepage, bg='white').pack()   
    button3 = Button(window, text = 'See: UKs COVID-19 data', width=20, command=changepage, bg='white').pack()   

########## SET UP THE GRAPH ##########

# Data was taken from 01/01/2021 to 06/05/2021
def realData(data):
    realdata = pd.read_csv('UK_full_covid_data_may.csv') 
    
    totalcase = realdata.iloc[335:,4].values
    posiCase = realdata.iloc[335:,5].values 
    newTest = realdata.iloc[335:,25].values 
    posiRate = realdata.iloc[335:,31].values 

    death = realdata.iloc[335:,8].values 
    totaldeaths = realdata.iloc[335:,7].values
    hospAdmission = realdata.iloc[335:,19].values  
    icu = realdata.iloc[335:,17].values
    
    totalVax = realdata.iloc[335:,34].values
    vax = realdata.iloc[335:,35].values
    fullyVax = realdata.iloc[335:,36].values
    newVax = realdata.iloc[335:,37].values
    
    if data == "case": return posiCase
    elif data == "totalcase": return totalcase
    elif data == "newTest": return newTest
    elif data == "posiRate": return posiRate
    
    elif data == "death": return death
    elif data == "totaldeaths": return totaldeaths
    elif data == "hosp": return hospAdmission
    elif data == "icu": return icu
    
    elif data == "totalVax": return totalVax
    elif data == "vax": return vax
    elif data == "fullyVax": return fullyVax
    elif data == "newVax": return newVax

# Set data for x-axis
def xData(xAxis):
    if xAxis == "case": return np.arange(0, len(realData("case")))
    elif xAxis == "totalcase": return np.arange(0, len(realData("totalcase")))
    elif xAxis == "newTest": return np.arange(0, len(realData("newTest")))
    elif xAxis == "posiRate": return np.arange(0, len(realData("posiRate")))
    elif xAxis == "death": return np.arange(0, len(realData("death")))
    elif xAxis == "totaldeaths": return np.arange(0, len(realData("totaldeaths")))
    elif xAxis == "hosp": return np.arange(0, len(realData("hosp")))
    elif xAxis == "icu": return np.arange(0, len(realData("icu")))
    elif xAxis == "totalVax": return np.arange(0, len(realData("totalVax")))
    elif xAxis == "vax": return np.arange(0, len(realData("vax")))
    elif xAxis == "fullyVax": return np.arange(0, len(realData("fullyVax")))
    elif xAxis == "newVax": return np.arange(0, len(realData("newVax")))

# Set data for y-axis
def yData(yAxis):
    if yAxis == "case": return realData("case")
    elif yAxis == "totalcase": return realData("totalcase")
    elif yAxis == "newTest": return realData("newTest")
    elif yAxis == "posiRate": return realData("posiRate")
    elif yAxis == "death": return realData("death")
    elif yAxis == "totaldeaths": return realData("totaldeaths")
    elif yAxis == "hosp": return realData("hosp")
    elif yAxis == "icu": return realData("icu")
    elif yAxis == "totalVax": return realData("totalVax")
    elif yAxis == "vax": return realData("vax")
    elif yAxis == "fullyVax": return realData("fullyVax")
    elif yAxis == "newVax": return realData("newVax")

# Create the graph 

def page2(root):
    # Create the graph 
    def graph(ver, mode):
        '''
            Creates line plots
            
            Parameters
            -------
            ver : str
                group of data to be plotted and shown in the GUI
            mode : str
                type of expected presentation
            Returns
            -------
            None.
                '''
        fig = plt.figure(figsize=(8, 7))
        ax_upper_left = fig.add_subplot(2.5, 2, 1)
        ax_upper_right = fig.add_subplot(2.5, 2, 2)
        ax_lower_left = fig.add_subplot(2.5, 2, 3)
        ax_lower_right = fig.add_subplot(2.5, 2, 4)
        
        if ver == "ver1":    
            line1, = ax_upper_left.plot(xData("case"), yData("case"), color='maroon')
            line2, = ax_upper_right.plot(xData("totalcase"), yData("totalcase"), color='firebrick')
            line3, = ax_lower_left.plot(xData("newTest"), yData("newTest"), color='indianred')
            line4, = ax_lower_right.plot(xData("posiRate"), yData("posiRate"), color='salmon')
            
            ax_upper_left.set_ylabel('Number of Positive Cases', fontsize=11)
            ax_upper_right.set_ylabel('Total Cases', fontsize=11)
            ax_lower_left.set_ylabel('New Testing', fontsize=11)
            ax_lower_right.set_ylabel('Positive Rate (%)', fontsize=11)
            
            fig.tight_layout()
            fig.suptitle("Positive Cases & New Testing")
            fig.subplots_adjust(top=0.92)
            
            if mode == "img": 
                newWindow = Toplevel(window)        # Display the image on a new window
                newWindow.title("Covid-19 Related Graph")
                newWindow.geometry("800x590")
                newWindow.configure(bg="white")
                canvas1 = FigureCanvasTkAgg(fig, master = newWindow)  
                canvas1.draw()
                toolbar = NavigationToolbar2Tk(canvas1, newWindow)
                toolbar.update()
                canvas1.get_tk_widget().pack()
                button = Button(newWindow, text = "\nClick and Quit\n", bg="white", height = 1, width = 15, command = newWindow.destroy).pack()
            
            elif mode == "mp4": 
                def update(num):        
                    line1.set_data(xData("case")[:num], yData("case")[:num])
                    line2.set_data(xData("totalcase")[:num], yData("totalcase")[:num])
                    line3.set_data(xData("newTest")[:num], yData("newTest")[:num])
                    line4.set_data(xData("posiRate")[:num], yData("posiRate")[:num])
                    return line1, line2, line3, line4
                
                ani = animation.FuncAnimation(fig, update, len(xData("case")), interval=50, blit=True )       
                return ani
    
        elif ver == "ver2":
            line1, = ax_upper_left.plot(xData("death"), yData("death"), color='darkblue')
            line2, = ax_upper_right.plot(xData("totaldeaths"), yData("totaldeaths"), color='blue')
            line3, = ax_lower_left.plot(xData("hosp"), yData("hosp"), color='royalblue')
            line4, = ax_lower_right.plot(xData("icu"), yData("icu"), color='cornflowerblue')
            
            ax_upper_left.set_ylabel('Number of Death', fontsize=11)
            ax_upper_right.set_ylabel('Total Deaths', fontsize=11)
            ax_lower_left.set_ylabel('Hospital Admission', fontsize=11)
            ax_lower_right.set_ylabel('ICU patients', fontsize=11)
            
            fig.tight_layout()
            fig.suptitle("Death Cases & Hospital Related")
            fig.subplots_adjust(top=0.94)
            
            if mode == "img": 
                newWindow = Toplevel(window)        # Display the image on a new window
                newWindow.title("Covid-19 Related Graph")
                newWindow.geometry("800x590")
                newWindow.configure(bg="white")
                canvas2 = FigureCanvasTkAgg(fig, master = newWindow)  
                canvas2.draw()
                toolbar = NavigationToolbar2Tk(canvas2, newWindow)
                toolbar.update()
                canvas2.get_tk_widget().pack()
                button = Button(newWindow, text = "\nClick and Quit\n", bg="white", height = 1, width = 15, command = newWindow.destroy).pack()
           
            elif mode == "mp4":      
                def update(num):
                    line1.set_data(xData("death")[:num], yData("death")[:num])
                    line2.set_data(xData("totaldeaths")[:num], yData("totaldeaths")[:num])
                    line3.set_data(xData("hosp")[:num], yData("hosp")[:num])
                    line4.set_data(xData("icu")[:num], yData("icu")[:num])
                    return line1, line2, line3, line4
                
                ani = animation.FuncAnimation(fig, update, len(xData("death")), interval=50, blit=True )
                return ani
            
        elif ver == "ver3":
            line1, = ax_upper_left.plot(xData("vax"), yData("vax"), color='limegreen')
            line2, = ax_upper_right.plot(xData("totalVax"), yData("totalVax"), color='yellowgreen')
            line3, = ax_lower_left.plot(xData("fullyVax"), yData("fullyVax"), color='seagreen')
            line4, = ax_lower_right.plot(xData("newVax"), yData("newVax"), color='darkgreen')
            
            ax_upper_left.set_ylabel('Number of People Vaccinated', fontsize=11)
            ax_upper_right.set_ylabel('Total Number of People Vaccinated', fontsize=11)
            ax_lower_left.set_ylabel('Number of People Fully Vaccinated', fontsize=11)
            ax_lower_right.set_ylabel('Number of New Vaccinated', fontsize=11)
            
            fig.tight_layout()
            fig.suptitle("Vaccination")
            fig.subplots_adjust(top=0.93)        
    
            if mode == "img": 
                newWindow = Toplevel(window)        # Display the image on a new window
                newWindow.title("Covid-19 Related Graph")
                newWindow.grid()
                newWindow.configure(bg="white")
                canvas3 = FigureCanvasTkAgg(fig, master = newWindow)  
                canvas3.draw()
                toolbar = NavigationToolbar2Tk(canvas3, newWindow)
                toolbar.update()
                canvas3.get_tk_widget().pack()
                button = Button(newWindow, text = "\nClick and Quit\n", bg="white", height = 1, width = 15, command = newWindow.destroy).pack()
            
            elif mode == "mp4":
                def update(num):
                    line1.set_data(xData("vax")[:num], yData("vax")[:num])
                    line2.set_data(xData("totalVax")[:num], yData("totalVax")[:num])
                    line3.set_data(xData("fullyVax")[:num], yData("fullyVax")[:num])
                    line4.set_data(xData("newVax")[:num], yData("newVax")[:num])
                    return line1, line2, line3, line4
                
                ani = animation.FuncAnimation(fig, update, len(xData("vax")), interval=50, blit=True )
                return ani
    
    def saveMP4(ver):
        plot = graph(ver, "mp4")
        plt.rcParams['animation.ffmpeg_path'] ='C:\\ffmpeg\\bin\\ffmpeg.exe'
        FFwriter=animation.FFMpegWriter(fps=10, extra_args=['-vcodec', 'libx264'])
        plot.save('realData.mp4', writer=FFwriter)
    
    # Set up window for GUI real data
    window = tk.Frame(root)
    window.grid()
    window.configure(bg='white')
    explanation = Label(window, bg='white', text="Source: UK_Full_Covid_Data (Date issued: 01/01/2021-06/05/2021)\n").pack()
    reminder = Label(window, bg='white', text="Remember 3W's to reduce the risk of COVID-19 :D\n").pack()
    
    font_tuple = ("Helvatica", 16, "bold")
    # create separation for video section
    section1 = Label(window, bg='white', text="======= Video section =======")
    section1.configure(font = font_tuple)
    section1.pack()
    
    instruction1 = Label(window, bg='white', text="Click the button to see the animation of the graph\n").pack()
    
    def chooseVideo(num):       # choose the video to be played upon button click
        if num == 1:
            saveMP4("ver1")
            os.system("realData.mp4")
            
        elif num == 2:
            saveMP4("ver2")
            os.system("realData.mp4")
            
        elif num == 3:
            saveMP4("ver3")
            os.system("realData.mp4")
            
    var = IntVar()
    
    # open the chosen video on the media player
    def openVideo1(): chooseVideo(1)    
    def openVideo2():chooseVideo(2)        
    def openVideo3(): chooseVideo(3)  
    
    # open a new window that displays the plot
    def openPlot1(): graph("ver1", "img")  
    def openPlot2(): graph("ver2", "img")       
    def openPlot3(): graph("ver3", "img")
    
    # LIST OF BUTTONS FOR THE VIDEOS
    rb1 = Radiobutton(window, text= "Play: Positive Cases & New Testing", variable = var, value=1, command=openVideo1, height=2, bg='white')
    rb1.place(x=250, y=130)
    rb1.pack()
    
    rb2 = Radiobutton(window, text= "Play: Death Cases & Hospital Related", variable = var, value=1, command=openVideo2, height=2, bg='white')
    rb2.place(x=250, y=180)
    rb2.pack()
    
    rb3 = Radiobutton(window, text= "Play: Vaccination", variable = var, value=1, command=openVideo3, height=2, bg='white')
    rb3.place(x=250, y=230)
    rb3.pack()
    
    # create separation for image section
    section2 = Label(window, bg='white', text="\n======= Image section =======")
    section2.configure(font = font_tuple)
    section2.place(x=250, y=470)
    section2.pack()
    
    instruction2 = Label(window, bg='white', text="Click the button to see the image of the graph\n\n")
    instruction2.place(x=250, y=497)
    instruction2.pack()
    
    # LIST OF BUTTON FOR THE PLOT IMAGE
    plot_button1 = Button(master = window, command = openPlot1, height = 2, width = 35, bg="white", text = "Positive Cases & New Testing").pack()
    plot_button2 = Button(master = window, command = openPlot2, height = 2, width = 35, bg="white", text = "Death cases & Hospital Related").pack()
    plot_button3 = Button(master = window, command = openPlot3, height = 2, width = 35, bg="white", text = "Vaccination").pack()
    
    backbutton = tk.Button(window, text = 'Back', command = changepage, bg="white", height = 1, width = 15)
    backbutton.pack()

#Change Page from window 1 - 2 
def changepage():
    global pagenum, root
    for widget in root.winfo_children():
        widget.destroy()
    if pagenum == 1:
        page2(root)
        pagenum = 2
    else:
        page1(root)
        pagenum = 1

pagenum = 1
root = tk.Tk()
page1(root)
root.mainloop()