Search code examples
csvmatplotlibuser-interfacetkinterdata-cleaning

Issues in creating pysimplegui or Tkinter graph GUI by reading csv file , cleaning it and plotting graph (histogram+PDF)


I want to create GUI which should automatically clean data in csv file once selected and plot superimposed PDF & histogram graph. I have uploaded basic python program which generates the required graph but I am unbale to convert it into interface. I guess, only "open file" & "plot" buttons would suffice the requirement. image- want to retrieve data from 'N'th column (13) only with skipping top 4 rows

I am basically from metallurgy background and trying my hands in this field. Any help would be greatly appreciated

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

raw_data = pd.read_csv("D:/Project/Python/NDC/Outlier_ND/800016_DAT.csv",skiprows=4,header=None)
clean = pd.DataFrame(raw_data)
data1 = clean.iloc[:, [13]]

Q1 = data1.quantile(0.25)
Q3 = data1.quantile(0.75)
IQR = Q3 - Q1

data_IQR = data1[~((data1 < (Q1 - 1.5 * IQR)) |(data1 > (Q3 + 1.5 * IQR))).any(axis=1)]
data_IQR.shape
print(data1.shape)
print(data_IQR.shape)

headerList = ['Actual_MR']
data_IQR.to_csv(r'D:\Project\Python\NDC\Outlier_ND\800016_DAT_IQR.csv', header=headerList, index=False)
data = pd.read_csv("D:/Project/Python/NDC/Outlier_ND/800016_DAT_IQR.csv")

mean, sd = norm.fit(data)
plt.hist(data, bins=25, density=True, alpha=0.6, facecolor = '#2ab0ff', edgecolor='#169acf', linewidth=0.5)
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x, mean, sd)
plt.plot(x, p, 'red', linewidth=2)
title = " Graph \n mean: {:.2f} and SD: {:.2f}".format(mean, sd)
plt.title(title)
plt.xlabel('MR')
plt.ylabel('Pr')
plt.show()


Solution

  • Following code demo how PySimpleGUI to work with matplotlib, detail please find all remark in script.

    import math, random
    from pathlib import Path
    
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    from matplotlib.figure import Figure
    import PySimpleGUI as sg
    
    # 1. Define the class as the interface between matplotlib and PySimpleGUI
    class Canvas(FigureCanvasTkAgg):
        """
        Create a canvas for matplotlib pyplot under tkinter/PySimpleGUI canvas
        """
        def __init__(self, figure=None, master=None):
            super().__init__(figure=figure, master=master)
            self.canvas = self.get_tk_widget()
            self.canvas.pack(side='top', fill='both', expand=1)
    
    # 2. create PySimpleGUI window, a fixed-size Frame with Canvas which expand in both x and y.
    font = ("Courier New", 11)
    sg.theme("DarkBlue3")
    sg.set_options(font=font)
    layout = [
        [sg.Input(expand_x=True, key='Path'),
         sg.FileBrowse(file_types=(("ALL CSV Files", "*.csv"), ("ALL Files", "*.*"))),
         sg.Button('Plot')],
        [sg.Frame("", [[sg.Canvas(background_color='green', expand_x=True, expand_y=True, key='Canvas')]], size=(640, 480))],
        [sg.Push(), sg.Button('Exit')]
    ]
    window = sg.Window('Matplotlib', layout, finalize=True)
    
    # 3. Create a matplotlib canvas under sg.Canvas or sg.Graph
    fig = Figure(figsize=(5, 4), dpi=100)
    ax = fig.add_subplot()
    canvas = Canvas(fig, window['Canvas'].Widget)
    
    # 4. initial for figure
    ax.set_title(f"Sensor Data")
    ax.set_xlabel("X axis")
    ax.set_ylabel("Y axis")
    ax.set_xlim(0, 1079)
    ax.set_ylim(-1.1, 1.1)
    ax.grid()
    canvas.draw()                       # do Update to GUI canvas
    
    # 5. PySimpleGUI event loop
    while True:
        event, values = window.read()
        if event in (sg.WINDOW_CLOSED, 'Exit'):
            break
        elif event == 'Plot':
            """
            path = values['Path']
            if not Path(path).is_file():
                continue
            """
            # 6. Get data from path and plot from here
            ax.cla()                    # Clear axes first if required
            ax.set_title(f"Sensor Data")
            ax.set_xlabel("X axis")
            ax.set_ylabel("Y axis")
            ax.grid()
            theta = random.randint(0, 359)
            x = [degree for degree in range(1080)]
            y = [math.sin((degree+theta)/180*math.pi) for degree in range(1080)]
            ax.plot(x, y)
            canvas.draw()               # do Update to GUI canvas
    
    # 7. Close window to exit
    window.close()
    

    enter image description here