-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathdesktop_app.py
More file actions
144 lines (111 loc) · 5.68 KB
/
desktop_app.py
File metadata and controls
144 lines (111 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import customtkinter as ctk
from weather_engine import WeatherEngine
from weather_visualizer import WeatherVisualizer
import threading
import tkinter.messagebox as messagebox
from PIL import Image
import os
class WeatherApp(ctk.CTk):
def __init__(self):
super().__init__()
self.title("Weather Prediction System")
self.geometry("1100x700") # Wider for better visualization
# Initialize Engine
self.engine = WeatherEngine()
self.viz = WeatherVisualizer(output_dir="app_plots")
self.training_data = None #(df, X_reg, y_reg)
# UI Layout
self.setup_ui()
def setup_ui(self):
# Sidebar
self.sidebar = ctk.CTkFrame(self, width=220, corner_radius=0)
self.sidebar.pack(side="left", fill="y")
self.logo_label = ctk.CTkLabel(self.sidebar, text="WeatherAI", font=ctk.CTkFont(size=24, weight="bold"))
self.logo_label.pack(pady=30)
self.train_btn = ctk.CTkButton(self.sidebar, text="Train Models", command=self.start_training)
self.train_btn.pack(pady=10, padx=20)
self.predict_btn = ctk.CTkButton(self.sidebar, text="Run Predictions", command=self.run_predictions, state="disabled")
self.predict_btn.pack(pady=10, padx=20)
self.open_plots_btn = ctk.CTkButton(self.sidebar, text="Open Plots Folder", command=self.open_plot_folder, state="disabled")
self.open_plots_btn.pack(pady=10, padx=20)
# Main Content
self.main_frame = ctk.CTkFrame(self)
self.main_frame.pack(side="right", fill="both", expand=True, padx=20, pady=20)
self.status_label = ctk.CTkLabel(self.main_frame, text="System Ready", font=ctk.CTkFont(size=16))
self.status_label.pack(pady=10)
self.progress = ctk.CTkProgressBar(self.main_frame)
self.progress.pack(pady=5, padx=20, fill="x")
self.progress.set(0)
# Dashboard / Image Area
self.image_container = ctk.CTkFrame(self.main_frame)
self.image_container.pack(pady=10, padx=20, fill="both", expand=True)
self.image_label = ctk.CTkLabel(self.image_container, text="Graphs will appear here after prediction")
self.image_label.pack(expand=True)
self.log_box = ctk.CTkTextbox(self.main_frame, height=150)
self.log_box.pack(pady=10, padx=20, fill="x")
def log(self, message):
self.log_box.insert("end", f"> {message}\n")
self.log_box.see("end")
def open_plot_folder(self):
os.startfile(os.path.abspath(self.viz.output_dir))
def start_training(self):
self.train_btn.configure(state="disabled")
self.status_label.configure(text="Training Neural Networks...")
self.progress.set(0.1)
thread = threading.Thread(target=self.train_thread)
thread.start()
def train_thread(self):
try:
self.log("Step 1: Loading 20 years of weather data...")
self.training_data = self.engine.run_full_pipeline()
# training_data is (df, X_reg, y_reg)
self.progress.set(1.0)
self.log("Step 2: Training both Predictor and Classifier complete.")
self.after(0, self.training_done)
except Exception as error:
err_msg = str(error)
self.after(0, lambda m=err_msg: messagebox.showerror("Training Error", m))
self.after(0, lambda: self.train_btn.configure(state="normal"))
def training_done(self):
self.status_label.configure(text="Model Ready")
self.predict_btn.configure(state="normal")
self.train_btn.configure(state="normal")
self.log("Ready to generate predictions.")
def run_predictions(self):
self.status_label.configure(text="Generating Visualizations...")
self.log("Calculating predictions and generating comparison charts...")
# We'll run visualization on a thread too
thread = threading.Thread(target=self.predict_thread)
thread.start()
def predict_thread(self):
try:
df, X_reg, y_reg = self.training_data
# Predict
pred_features = self.engine.predictor.predict(X_reg)
pred_classes = self.engine.classifier.predict(self.engine.scaler.transform(pred_features))
actual_classes = df['ClassCode'].values[365:] # Match the offset
# Generate Plots
# 1. Classes plot
self.viz.plot_classes(actual_classes, pred_classes)
# 2. Key feature comparison (Max Temp)
self.viz.plot_comparison(y_reg, pred_features, 0) # Max Temp
self.after(0, self.display_results)
except Exception as error:
# Capturing the error in a local variable for the lambda
err_msg = str(error)
self.after(0, lambda m=err_msg: messagebox.showerror("Prediction Error", m))
def display_results(self):
# Load the newly created image
img_path = os.path.join(self.viz.output_dir, "Classes_Comparison.png")
if os.path.exists(img_path):
img = Image.open(img_path)
# Resize image to fit the container
# Container is roughly 800x400
img_ctk = ctk.CTkImage(light_image=img, dark_image=img, size=(750, 350))
self.image_label.configure(image=img_ctk, text="")
self.status_label.configure(text="Predictions Complete")
self.open_plots_btn.configure(state="normal")
self.log("Results visualised. You can also click 'Open Plots Folder' to see detailed charts for all features.")
if __name__ == "__main__":
app = WeatherApp()
app.mainloop()