""" Main interface for the FlightSure application. Preforms Gradio interface setup and calls the backend function. Author: William Parker """ import os import pickle from datetime import datetime from typing import Optional import gradio as gr import joblib import pandas as pd from dotenv import load_dotenv from gradio_calendar import Calendar from numpy import ndarray from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import LinearRegression import open_weather # Get variables load_dotenv() unvalidated_open_weather_api_key: str | None = os.getenv("OPEN_WEATHER_API_KEY") env_open_weather_api_key: str if unvalidated_open_weather_api_key is not None: env_open_weather_api_key = unvalidated_open_weather_api_key with open( os.path.join(os.path.dirname(__file__), "helpers", "airport_codes.pickle"), "rb" ) as f: airport_codes = pickle.load(f) # Main processing function def backend( open_weather_api_key_input: str, airport: str, flight_time: str, date: datetime, ): """ Main processing function for the FlightSure application. Uses the OpenWeather API to get the weather forecast for the given airport and time. Then predicts the flight delay based on the weather forecast. """ # Format date time format_str = "%H:%M" if len(flight_time.split(":")) == 2 else "%H:%M:%S" time_obj = datetime.strptime(flight_time, format_str).time() scheduled_time = datetime.combine(date.date(), time_obj) if unvalidated_open_weather_api_key is not None: open_weather_api_key = env_open_weather_api_key elif open_weather_api_key_input != "": open_weather_api_key = open_weather_api_key_input else: raise ValueError( "OpenWeather API Key is missing. Please enter it in the text box or in the .env file." ) # Get weather raw_forecast = open_weather.get_weather( airport, scheduled_time, open_weather_api_key ) input_dict = open_weather.parse_weather(raw_forecast) # Create a text summary of the weather weather_forecast = f"""Temperature: {round(input_dict["Temperature"][0])} F Pressure: {input_dict["Altimeter_Pressure"][0]} hPa Visibility: {input_dict["Visibility"][0]} m Wind Speed: {input_dict["Wind_Speed"][0]} mph Rain: {round(input_dict["Precipitation"][0], 2)} mm""" input_values = pd.DataFrame(input_dict) # Run the models model_path = os.path.join(os.path.dirname(__file__), "..", "models", airport) weather_cancellation_classification_path = os.path.join( model_path, "weather_cancellation_classification.pkl" ) weather_cancellation_classification: RandomForestClassifier = joblib.load( weather_cancellation_classification_path ) cancellation_prediction: bool = weather_cancellation_classification.predict( input_values )[0] cancellation_chance: ndarray = weather_cancellation_classification.predict_proba( input_values )[0] cancellation_text = f"We predict that your flight will {'' if cancellation_prediction else 'not'} be canceled. Chance of cancellation: {round(cancellation_chance[1] * 100, 2)}%." weather_delay_classification_path = os.path.join( model_path, "weather_delay_classification.pkl" ) weather_delay_classification: RandomForestClassifier = joblib.load( weather_delay_classification_path ) delay_bool_prediction: bool = weather_delay_classification.predict(input_values)[0] delay_bool_chance: ndarray = weather_delay_classification.predict_proba( input_values )[0] delay_text = f"We predict that your flight will {'' if delay_bool_prediction else 'not'} be delayed. Chance of delay: {round(delay_bool_chance[1] * 100, 2)}%. " weather_delay_regression_path = os.path.join( model_path, "weather_delay_regression.pkl" ) weather_delay_regression: LinearRegression = joblib.load( weather_delay_regression_path ) delay_length: float = weather_delay_regression.predict(input_values)[0] if delay_bool_prediction: delay_length_text = ( f"The predicted delay length is {round(delay_length)} minutes." ) else: delay_length_text = "N/A" return weather_forecast, cancellation_text, delay_text, delay_length_text # Interface Components open_weather_api_textbox = gr.Textbox( label="OpenWeather API Key:", info="Leave blank if you set this in the .env file." ) dropdown = gr.components.Dropdown( choices=airport_codes, label="Select your airport code:" ) time_textbox = gr.components.Textbox(label="Enter departure time:") calendar = Calendar( type="datetime", label="Select date of departure:", info="Click the calendar icon to bring up the calendar.", ) inputs = [open_weather_api_textbox, dropdown, time_textbox, calendar] weather_stats_textbox = gr.Textbox(label="Weather Forecast:") cancellation_chance_textbox = gr.Textbox(label="Chance of Cancellation:") delay_chance_textbox = gr.Textbox(label="Chance of Delay:") delay_length_textbox = gr.Textbox(label="Length of Delay:") outputs = [ weather_stats_textbox, cancellation_chance_textbox, delay_chance_textbox, delay_length_textbox, ] # Interface interface = gr.Interface( fn=backend, inputs=inputs, outputs=outputs, title="FlightSure", allow_flagging=False, ) # Launch if __name__ == "__main__": interface.launch()