DBH - Ghana Instruments

🧩 Syntax:
import tkinter as tk
from tkinter import messagebox
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import matplotlib.pyplot as plt
from PIL import ImageTk, Image
from statistics import stdev, mean, median, mode

previous_width = 0

def open_regular_calculator():
    
    def evaluate_expression(expression):
        try:
            result = eval(expression)
            if abs(result) == 1.2246467991473532e-16:
                result = 0
            result_label.config(text=f"Result: {result}")

        except Exception as e:
            result_label.config(text="Invalid expression")

    def on_button_click(expression):
        entry_text = entry.get()
        entry_text += expression
        entry.delete(0, tk.END)
        entry.insert(tk.END, entry_text)

    def clear_entry():
        entry.delete(0, tk.END)
    def update_font_size(event):
        global previous_width
        window_width = root.winfo_width()
        if abs(window_width - previous_width) > 100: 
            font_size = max(int(window_width / 30), 8)
            try:
                entry.config(font=("Arial", font_size))
                for child in button_frame.winfo_children():
                    child.config(font=("Arial", font_size))
            except tk.TclError:
                pass
            
            previous_width = window_width
    

    clear_window(root)
    root.maxsize(1720,1080)
    root.title("Calculator")
    
    entry = tk.Entry(root, width=40, font=("Arial", 14))
    entry.pack()

    button_frame = tk.Frame(root)
    button_frame.pack(fill=tk.BOTH, expand=True)

    buttons = [
        '7', '8', '9', '/',
        '4', '5', '6', '*',
        '1', '2', '3', '-',
        '0', '.', '**', '+',
        '(', ')', 'np.sin(', 'np.cos(',
        'np.tan(', 'np.pi'
    ]

    row, col = 0, 0
    for button in buttons:
        button2 = button
        if button == "**":
            button2 = "xΚΈ"
        elif button == "np.sin(":
            button2 = "sin"
        elif button == "np.cos(":
            button2 = "cos"
        elif button == "np.tan(":
            button2 = "tan"
        elif button == "np.pi":
            button2 = "Ο€"
        tk.Button(button_frame, text=button2, width=10, command=lambda b=button: on_button_click(b), font=("Arial", 12)).grid(row=row, column=col, sticky="nsew")
        col += 1
        if col > 3:
            col = 0
            row += 1

    button_frame.columnconfigure((0, 1, 2, 3), weight=1)
    button_frame.rowconfigure((0, 1, 2, 3, 4), weight=1)

    evaluate_button = tk.Button(root, text="Evaluate", command=lambda: evaluate_expression(entry.get()), font=("Arial", 12)) 
    evaluate_button.pack(side=tk.LEFT, padx=10, pady=10)

    clear_button = tk.Button(root, text="Clear", command=clear_entry, font=("Arial", 12))
    clear_button.pack(side=tk.LEFT, padx=10, pady=10)

    home_button = tk.Button(root, text="Home", command=open_homepage, font=("Arial", 12))
    home_button.pack(side=tk.LEFT, padx=10, pady=10)

    result_label = tk.Label(root, text="", font=("Arial", 18))
    result_label.pack()

    root.bind('<Configure>', update_font_size)

def open_graphing_calculator():
    def evaluate_expression(expression, x):
        try:
            y = eval(expression)
            return y
        except (NameError, SyntaxError):
            print("Invalid expression: ", expression)
            return None

    fig, ax = plt.subplots()

    def plot_graph():
        ax.clear()

        expressions = entry.get().split(',')
        x = np.linspace(-1000, 1000, 100000)

        for expression in expressions:
            y = evaluate_expression(expression, x)
            if y is not None:
                ax.plot(x, y, label=expression)

        ax.set(xlabel='x', ylabel='y', title='Graph of the Functions', xlim=(0, 10), ylim=(0, 10))
        ax.grid(True)
        ax.legend()

        canvas.draw()

    def find_zeros():
        expressions = entry.get().split(',')
        for expression in expressions:
            x = np.linspace(-1000, 1000, 100001)
            y = evaluate_expression(expression, x)
            if y is not None:
                zeros = x[np.where(np.diff(np.sign(y)))[0]]
                if len(zeros) == 0:
                    messagebox.showinfo("Zeros", "No zeros found.")
                else:
                    rounded_zeros = [round(z, 3) for z in zeros]
                    if (abs(rounded_zeros[0]) == (abs(rounded_zeros[1])+0.02)) or (abs(rounded_zeros[0]) == (abs(rounded_zeros[1])-0.02)):
                        rounded_zeros.pop(0)
                    if len(rounded_zeros) > 6:
                        start_index = len(rounded_zeros) // 2 - 3
                        end_index = len(rounded_zeros) // 2 + 3
                        rounded_zeros = rounded_zeros[start_index:end_index]
                        messagebox.showinfo(f"Zeros for {expression}", f"Zeros found at: {rounded_zeros}\nResults may be inaccurate due to rounding point error")
                    else:
                        messagebox.showinfo(f"Zeros for {expression}", f"Zeros found at: {rounded_zeros}\nResults may be inaccurate due to rounding point error")



    def on_scroll(event):
        x_min, x_max = ax.get_xlim()
        y_min, y_max = ax.get_ylim()

        x_range = (x_max - x_min) / 2
        y_range = (y_max - y_min) / 2

        if event.button == 'up':
            ax.set_xlim(x_min + x_range / 4, x_max - x_range / 4)
            ax.set_ylim(y_min + y_range / 4, y_max - y_range / 4)
        elif event.button == 'down':
            ax.set_xlim(x_min - x_range, x_max + x_range)
            ax.set_ylim(y_min - y_range, y_max + y_range)

        canvas.draw()

    def on_click(event):
        if event.button == 1:
            ax.start_xlim = ax.get_xlim()
            ax.start_ylim = ax.get_ylim()
            ax.start_x = event.x
            ax.start_y = event.y

    def on_motion(event):
        if event.button == 1 and hasattr(ax, 'start_x') and hasattr(ax, 'start_y'):
            x_range = (ax.start_xlim[1] - ax.start_xlim[0])
            y_range = (ax.start_ylim[1] - ax.start_ylim[0])

            sensitivity = 1

            width = canvas.get_tk_widget().winfo_width()
            height = canvas.get_tk_widget().winfo_height()

            ax.set_xlim(
                ax.start_xlim[0] - (event.x - ax.start_x) * x_range * sensitivity / width,
                ax.start_xlim[1] - (event.x - ax.start_x) * x_range * sensitivity / width
            )
            ax.set_ylim(
                ax.start_ylim[0] + (ax.start_y - event.y) * y_range * sensitivity / height,
                ax.start_ylim[1] + (ax.start_y - event.y) * y_range * sensitivity / height
            )

            canvas.draw()

    clear_window(root)
    root.title("Graphing Calculator")

    label = tk.Label(root, text="Enter mathematical expressions (separated by commas):")
    label.pack()

    entry = tk.Entry(root, width=40, font=("Arial", 14))
    entry.pack()

    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

    plot_button = tk.Button(root, text="Plot Graph", command=plot_graph, font=("Arial", 12))
    plot_button.pack()

    zeros_button = tk.Button(root, text="Find Zeros", command=find_zeros, font=("Arial", 12))
    zeros_button.pack()

    home_button = tk.Button(root, text="Home", command=open_homepage, font=("Arial", 12))
    home_button.pack()

    canvas.mpl_connect('scroll_event', on_scroll)
    canvas.mpl_connect('button_press_event', on_click)
    canvas.mpl_connect('motion_notify_event', on_motion)
    root.mainloop()

def open_statistics_calculator():

    def calculate_statistics(data):
        std_dev = stdev(data)
        median_val = median(data)
        mean_val = mean(data)
        mode_val = mode(data)

        return std_dev, median_val, mean_val, mode_val

    
    def calculate_and_display_statistics():
        data_str = entry.get()
        try:
            data = [float(num) for num in data_str.split(",")]

            std_dev, median_val, mean_val, mode_val = calculate_statistics(data)

            result_label.config(text=
                                     f"Standard Deviation: {std_dev}\n"
                                     f"Median: {median_val}\n"
                                     f"Mean: {mean_val}\n"
                                     f"Mode: {mode_val}")
        except ValueError:
            result_label.config(text="Invalid data format. Please enter comma-separated numbers.")

    clear_window(root)
    root.title("Statistics Calculator")

    label = tk.Label(root, text="Enter comma-separated numbers:")
    label.pack()

    entry = tk.Entry(root, width=40, font=("Arial", 14))
    entry.pack()

    calculate_button = tk.Button(root, text="Calculate", command=calculate_and_display_statistics, font=("Arial", 12))
    calculate_button.pack()

    result_label = tk.Label(root, text="", font=("Arial", 12))
    result_label.pack()

    home_button = tk.Button(root, text="Home", command=open_homepage, font=("Arial", 12))
    home_button.pack()

def open_regression_calculator():
    def calculate_regression(data, regression_type):
        x_values, y_values = zip(*data)
        x_values = np.array(x_values)
        y_values = np.array(y_values)

        if regression_type == "linear":
            coefficients = np.polyfit(x_values, y_values, 1)
            equation = f"y = {coefficients[0]:.2f}x + {coefficients[1]:.2f}"
            regression_values = coefficients[0] * x_values + coefficients[1]
        elif regression_type == "polynomial":
            coefficients = np.polyfit(x_values, y_values, 2)
            equation = f"y = {coefficients[0]:.2f}x^2 + {coefficients[1]:.2f}x + {coefficients[2]:.2f}"
            regression_values = coefficients[0] * x_values ** 2 + coefficients[1] * x_values + coefficients[2]
        elif regression_type == "logarithmic":
            coefficients = np.polyfit(np.log(x_values), y_values, 1)
            equation = f"y = {coefficients[0]:.2f} * ln(x) + {coefficients[1]:.2f}"
            regression_values = coefficients[0] * np.log(x_values) + coefficients[1]
        elif regression_type == "exponential":
            coefficients = np.polyfit(x_values, np.log(y_values), 1)
            equation = f"y = {np.exp(coefficients[1]):.2f} * e^{coefficients[0]:.2f}x"
            regression_values = np.exp(coefficients[1]) * np.exp(coefficients[0] * x_values)
        else:
            return None, None

        return equation, regression_values



    def calculate_and_display_regression_line():
        data_str = entry.get()
        regression_type = regression_var.get()

        try:
            data = [tuple(map(float, pair.split(","))) for pair in data_str.split(";")]
            equation, regression_values = calculate_regression(data, regression_type)

            if equation is None:
                result_label.config(text="Invalid regression type.")
            else:
                result_label.config(text=f"Regression Equation: {equation}")

                ax.clear()
                ax.scatter(*zip(*data), color='red', label='Data Points')
                ax.set_xlabel('x')
                ax.set_ylabel('y')
                ax.legend()

                x_values = [pair[0] for pair in data]
                y_values = [pair[1] for pair in data]
                ax.plot(x_values, y_values, 'ro', label='Data Points')
                ax.plot(x_values, regression_values, label='Regression Line')

                canvas.draw()
        except ValueError:
            result_label.config(text="Invalid data format. Please enter semicolon-separated x,y pairs.")





    clear_window(root)

    regression_var = tk.StringVar()
    regression_var.set("linear")


    regression_title_label = tk.Label(root, text="Regression Calculator", font=("Arial", 24), background='white')
    regression_title_label.pack(pady=20)

    data_label = tk.Label(root, text="Enter data (semicolon-separated x,y pairs):", font=("Arial", 16), background='white')
    data_label.pack()

    entry = tk.Entry(root, font=("Arial", 16))
    entry.pack()

    regression_type_label = tk.Label(root, text="Select regression type:", font=("Arial", 16), background='white')
    regression_type_label.pack()

    regression_type_menu = tk.OptionMenu(root, regression_var, "linear", "polynomial", "logarithmic", "exponential")
    regression_type_menu.config(font=("Arial", 16))
    regression_type_menu.pack(pady=10)

    calculate_button = tk.Button(root, text="Calculate", command=calculate_and_display_regression_line, font=("Arial", 16))
    calculate_button.pack(pady=20)

    home_button = tk.Button(root, text="Home", command=open_homepage, font=("Arial", 16))
    home_button.pack(pady=20)

    result_label = tk.Label(root, text="", font=("Arial", 16), background='white')
    result_label.pack()

    fig = Figure(figsize=(6, 5), dpi=100)
    ax = fig.add_subplot(1, 1, 1)

    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
    canvas.draw()

    

root = tk.Tk()
root.geometry("800x600")
root.title("Calculator")
root.configure(background='white')

homepage_frame = tk.Frame(root)
homepage_frame.configure(background='white')
homepage_frame.pack(fill='both', expand=True)


def clear_window(window):
    for widget in window.winfo_children():
        widget.destroy()

def open_homepage():
    global logo_image
    global logo_tk
    global logo_label
    clear_window(root)
    logo_image = Image.open("Ghana Instruments.png")
    logo_image = logo_image.resize((200, 200))

    logo_tk = ImageTk.PhotoImage(logo_image)

    logo_label = tk.Label(root, image=logo_tk)
    logo_label.pack()

    homepage_frame = tk.Frame(root)
    homepage_frame.pack(pady=50)

    regular_calc_button = tk.Button(homepage_frame, text="Regular Calculator", command=open_regular_calculator, font=("Arial", 16))
    regular_calc_button.pack(pady=10)

    graphing_calc_button = tk.Button(homepage_frame, text="Graphing Calculator", command=open_graphing_calculator, font=("Arial", 16))
    graphing_calc_button.pack(pady=10)

    statistics_calc_button = tk.Button(homepage_frame, text="Statistics Calculator", command=open_statistics_calculator, font=("Arial", 16))
    statistics_calc_button.pack(pady=10)

    regression_calc_button = tk.Button(homepage_frame, text="Regression Calculator", command=open_regression_calculator, font=("Arial", 16))
    regression_calc_button.pack(pady=10)



open_homepage()

root.mainloop()