Spaces:
Sleeping
Sleeping
souvik0306
commited on
Commit
β’
7b17a2d
1
Parent(s):
b6c80ee
updated code
Browse files- flight_route_ui.py β Old/flight_route_ui.py +1 -1
- Old/main.py +36 -0
- optimizer.py β Old/optimizer.py +0 -0
- flight_distance.py +45 -193
- gradio_ui.py +124 -0
- main.py +27 -18
- optimize.py +142 -0
- ui.py +0 -90
flight_route_ui.py β Old/flight_route_ui.py
RENAMED
@@ -1,6 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
-
from optimizer import *
|
4 |
from weather import *
|
5 |
from flight_distance import * # Assuming this function is defined in your aircraft capabilities module
|
6 |
|
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
+
from Old.optimizer import *
|
4 |
from weather import *
|
5 |
from flight_distance import * # Assuming this function is defined in your aircraft capabilities module
|
6 |
|
Old/main.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
from flight_distance import *
|
3 |
+
from Old.optimizer import *
|
4 |
+
from weather import *
|
5 |
+
|
6 |
+
airport_identifiers = ['CCU', 'CDG', 'SIN'] # Replace with actual identifiers
|
7 |
+
|
8 |
+
#Get Airport Coordinates
|
9 |
+
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
10 |
+
# print("Coordinates: \n",lat_long_dict)
|
11 |
+
|
12 |
+
#Get Distance between each node (airports)
|
13 |
+
trip_distance = calculate_distances(airport_identifiers)
|
14 |
+
# print("Distance b/w Airports: \n",trip_distance)
|
15 |
+
|
16 |
+
#Get onroute weather
|
17 |
+
raw_weather = fetch_weather_for_all_routes(airport_identifiers, lat_long_dict)
|
18 |
+
route_factors = extract_route_factors(raw_weather)
|
19 |
+
# print("On Route weather: \n", raw_weather)
|
20 |
+
|
21 |
+
# # Ensure the graph is bidirectional (undirected)
|
22 |
+
for (a, b), dist in list(trip_distance.items()):
|
23 |
+
trip_distance[(b, a)] = dist
|
24 |
+
|
25 |
+
# Find the optimal route with the new cost metric
|
26 |
+
optimal_route, optimal_distance = find_optimal_route(airport_identifiers, trip_distance, route_factors)
|
27 |
+
|
28 |
+
# Display the optimal route and the total adjusted distance/cost
|
29 |
+
print("Optimal Route:", " -> ".join(optimal_route) + f" -> {optimal_route[0]}")
|
30 |
+
print("Total Round Trip Distance:", optimal_distance)
|
31 |
+
|
32 |
+
aircraft_type = "Airbus A350-900"
|
33 |
+
|
34 |
+
# Check if the aircraft can fly the route without refuel
|
35 |
+
result = can_fly_route(aircraft_type, airport_identifiers)
|
36 |
+
print(result)
|
optimizer.py β Old/optimizer.py
RENAMED
File without changes
|
flight_distance.py
CHANGED
@@ -1,234 +1,86 @@
|
|
1 |
import pandas as pd
|
2 |
-
from math import
|
|
|
|
|
3 |
|
4 |
def get_aircraft_details(aircraft_type):
|
5 |
-
|
6 |
-
|
|
|
|
|
7 |
df = pd.read_csv(csv_file)
|
8 |
-
|
9 |
-
# Check if the aircraft type exists in the DataFrame
|
10 |
if aircraft_type not in df['Aircraft'].values:
|
11 |
return f"Aircraft type '{aircraft_type}' not found in the dataset."
|
12 |
-
|
13 |
-
# Fetch the relevant details for the given aircraft type
|
14 |
aircraft_details = df[df['Aircraft'] == aircraft_type][[
|
15 |
-
'Range_km',
|
16 |
-
'
|
17 |
-
|
18 |
-
|
19 |
-
'MaxFlightTime_hr',
|
20 |
-
'Max_Fuel_Capacity_kg'
|
21 |
-
]]
|
22 |
-
|
23 |
-
# Convert the result to a dictionary for easier reading
|
24 |
-
details_dict = aircraft_details.to_dict(orient='records')[0]
|
25 |
|
26 |
-
return details_dict
|
27 |
|
28 |
def get_airport_lat_long(identifiers):
|
29 |
"""
|
30 |
-
|
31 |
-
|
32 |
-
:param identifiers: List of airport names or IATA codes (minimum of 2)
|
33 |
-
:return: Dictionary with airport identifiers as keys and (latitude, longitude) tuples as values
|
34 |
"""
|
35 |
-
|
36 |
-
return "Please provide at least two airport identifiers."
|
37 |
-
|
38 |
-
# Load the CSV file
|
39 |
-
csv_file = r'airport.csv' # Replace with the actual path if needed
|
40 |
df = pd.read_csv(csv_file)
|
41 |
-
|
42 |
-
# Efficiently filter rows where the 'Name' or 'IATA' matches any of the provided identifiers
|
43 |
df_filtered = df[df['Airport_Name'].isin(identifiers) | df['IATA'].isin(identifiers)]
|
44 |
-
|
45 |
-
# Extract relevant information and store in a dictionary
|
46 |
-
lat_long_dict = {}
|
47 |
-
for _, row in df_filtered.iterrows():
|
48 |
-
identifier = row['IATA'] if row['IATA'] in identifiers else row['Name']
|
49 |
-
lat_long_dict[identifier] = (row['Lat'], row['Long'])
|
50 |
-
|
51 |
-
# Check if all identifiers were found
|
52 |
-
not_found = [id for id in identifiers if id not in lat_long_dict]
|
53 |
-
if not_found:
|
54 |
-
return f"These identifiers were not found: {', '.join(not_found)}"
|
55 |
-
|
56 |
return lat_long_dict
|
57 |
|
|
|
58 |
def haversine_distance(lat1, lon1, lat2, lon2):
|
59 |
"""
|
60 |
-
Calculate the Haversine distance between two points on
|
61 |
"""
|
62 |
-
R = 6371.0 #
|
63 |
-
|
64 |
-
# Convert latitude and longitude from degrees to radians
|
65 |
lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
|
66 |
-
|
67 |
-
# Haversine formula
|
68 |
-
dlat = lat2 - lat1
|
69 |
-
dlon = lon2 - lon1
|
70 |
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
|
71 |
-
|
72 |
-
distance = round(R * c,2)
|
73 |
-
return distance
|
74 |
-
|
75 |
-
def calculate_distances(airport_identifiers):
|
76 |
-
"""
|
77 |
-
Calculate the distance between multiple airports.
|
78 |
-
:param airport_identifiers: List of airport names or IATA codes
|
79 |
-
:return: Dictionary with airport pairs as keys and their distances in kilometers as values
|
80 |
-
"""
|
81 |
-
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
82 |
-
if isinstance(lat_long_dict, str): # Check if there was an error fetching airport data
|
83 |
-
return lat_long_dict
|
84 |
-
|
85 |
-
# Calculate the distance for each combination of airports
|
86 |
-
distances = {}
|
87 |
-
identifiers = list(lat_long_dict.keys())
|
88 |
-
for i in range(len(identifiers)):
|
89 |
-
for j in range(i + 1, len(identifiers)):
|
90 |
-
airport1 = identifiers[i]
|
91 |
-
airport2 = identifiers[j]
|
92 |
-
lat1, lon1 = lat_long_dict[airport1]
|
93 |
-
lat2, lon2 = lat_long_dict[airport2]
|
94 |
-
distance = haversine_distance(lat1, lon1, lat2, lon2)
|
95 |
-
distances[(airport1, airport2)] = distance
|
96 |
|
97 |
-
return distances
|
98 |
|
99 |
def calculate_distances(airport_identifiers):
|
100 |
"""
|
101 |
-
Calculate the distance between
|
102 |
-
|
103 |
-
:param airport_identifiers: List of airport names or IATA codes
|
104 |
-
:return: Dictionary with airport pairs as keys and their distances in kilometers as values
|
105 |
"""
|
106 |
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
107 |
-
if isinstance(lat_long_dict, str): # Check if there was an error fetching airport data
|
108 |
-
return lat_long_dict
|
109 |
-
|
110 |
-
# Calculate the distance for each combination of airports
|
111 |
distances = {}
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
airport1 = identifiers[i]
|
116 |
-
airport2 = identifiers[j]
|
117 |
lat1, lon1 = lat_long_dict[airport1]
|
118 |
lat2, lon2 = lat_long_dict[airport2]
|
119 |
-
|
120 |
-
distances[(airport1, airport2)] = distance
|
121 |
-
|
122 |
return distances
|
123 |
|
124 |
-
def calculate_fuel_and_time(distance, cruising_speed, fuel_burn_rate, reserve_fuel_percentage, max_fuel_capacity, climb_descent_fraction=0.02):
|
125 |
-
"""
|
126 |
-
Calculate the total fuel required for a given distance including reserve fuel and flight time.
|
127 |
|
128 |
-
|
129 |
-
:param cruising_speed: Cruising speed of the aircraft in km/h
|
130 |
-
:param fuel_burn_rate: Fuel consumption rate in kg/hr
|
131 |
-
:param reserve_fuel_percentage: Percentage of fuel to keep as reserve
|
132 |
-
:param max_fuel_capacity: Maximum fuel capacity of the aircraft in kg
|
133 |
-
:return: Total fuel required including reserve, and estimated flight time
|
134 |
"""
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
#
|
|
|
152 |
total_flight_time = climb_time + cruise_time + descent_time
|
153 |
|
154 |
-
#
|
155 |
fuel_required = total_flight_time * fuel_burn_rate
|
156 |
reserve_fuel = reserve_fuel_percentage * max_fuel_capacity
|
157 |
-
# print(fuel_burn_rate, fuel_required, reserve_fuel)
|
158 |
total_fuel_with_reserve = fuel_required + reserve_fuel
|
159 |
|
160 |
return total_fuel_with_reserve, total_flight_time
|
161 |
-
|
162 |
-
|
163 |
-
def check_route_feasibility(aircraft_type, trip_distances, aircraft_specs):
|
164 |
-
"""
|
165 |
-
Check if the aircraft can fly each route without needing refuel and return expected flight times.
|
166 |
-
|
167 |
-
:param aircraft_type: The type of the aircraft (e.g., "Airbus A320")
|
168 |
-
:param trip_distances: Dictionary with airport pairs and distances
|
169 |
-
:param aircraft_specs: Dictionary containing aircraft details
|
170 |
-
:return: Dictionary with feasibility and flight time for each route
|
171 |
-
"""
|
172 |
-
# Extract aircraft specifications
|
173 |
-
fuel_burn_rate = aircraft_specs['Fuel_Consumption_kg/hr'] # kg per hour
|
174 |
-
cruising_speed = aircraft_specs['Speed_kmh'] # km/h
|
175 |
-
max_fuel_capacity = aircraft_specs['Max_Fuel_Capacity_kg'] # kg
|
176 |
-
reserve_fuel_percentage = 0.05 # 5% reserve
|
177 |
-
|
178 |
-
results = {}
|
179 |
-
|
180 |
-
# Check feasibility for each route
|
181 |
-
for (airport1, airport2), distance in trip_distances.items():
|
182 |
-
# Calculate the total fuel required and flight time for the trip including reserve
|
183 |
-
total_fuel_with_reserve, flight_time = calculate_fuel_and_time(
|
184 |
-
distance, cruising_speed, fuel_burn_rate, reserve_fuel_percentage, max_fuel_capacity
|
185 |
-
)
|
186 |
-
|
187 |
-
if total_fuel_with_reserve > max_fuel_capacity:
|
188 |
-
results[(airport1, airport2)] = {
|
189 |
-
"Can Fly": False,
|
190 |
-
"Reason": f"Cannot fly without refuel. Required: {round(total_fuel_with_reserve, 2)} kg, Capacity: {max_fuel_capacity} kg",
|
191 |
-
"Expected Flight Time (hrs)": round(flight_time, 2)
|
192 |
-
}
|
193 |
-
else:
|
194 |
-
results[(airport1, airport2)] = {
|
195 |
-
"Can Fly": True,
|
196 |
-
"Expected Flight Time (hrs)": round(flight_time, 2),
|
197 |
-
"Total Fuel Required (kg)": round(total_fuel_with_reserve, 2)
|
198 |
-
}
|
199 |
-
return results
|
200 |
-
|
201 |
-
def can_fly_route(aircraft_type, airport_identifiers):
|
202 |
-
"""
|
203 |
-
Determine if the aircraft can fly the route without needing refuel, considering fuel capacity and reserve.
|
204 |
-
|
205 |
-
:param aircraft_type: The type of the aircraft (e.g., "Airbus A320")
|
206 |
-
:param airport_identifiers: List of airport names or IATA codes
|
207 |
-
:return: String message indicating if the aircraft can complete the trip or not
|
208 |
-
"""
|
209 |
-
# Fetch aircraft details
|
210 |
-
aircraft_specs = get_aircraft_details(aircraft_type)
|
211 |
-
if isinstance(aircraft_specs, str):
|
212 |
-
return aircraft_specs # Return the error message if aircraft details are not found
|
213 |
-
|
214 |
-
# Calculate distances between airports
|
215 |
-
trip_distances = calculate_distances(airport_identifiers)
|
216 |
-
if isinstance(trip_distances, str):
|
217 |
-
return trip_distances # Return the error message if distances could not be calculated
|
218 |
-
|
219 |
-
# Check if the aircraft can fly each route without refuel
|
220 |
-
return check_route_feasibility(aircraft_type, trip_distances, aircraft_specs)
|
221 |
-
|
222 |
-
# aircraft_type = input("Enter the aircraft type: ")
|
223 |
-
# aircraft_specs = get_aircraft_details(aircraft_type)
|
224 |
-
# print(aircraft_specs)
|
225 |
-
|
226 |
-
# airport_list = ['CCU', 'CDG', 'SIN']
|
227 |
-
# print(get_airport_lat_long(airport_list))
|
228 |
-
|
229 |
-
# trip_distance = calculate_distances(airport_list)
|
230 |
-
# print(trip_distance)
|
231 |
-
|
232 |
-
# # Check if the aircraft can fly the route without refuel
|
233 |
-
# result = can_fly_route(aircraft_type, airport_list)
|
234 |
-
# print(result)
|
|
|
1 |
import pandas as pd
|
2 |
+
from math import radians, sin, cos, sqrt, asin
|
3 |
+
|
4 |
+
### Modular Flight Calculation Functions ###
|
5 |
|
6 |
def get_aircraft_details(aircraft_type):
|
7 |
+
"""
|
8 |
+
Fetch aircraft details based on the given aircraft type.
|
9 |
+
"""
|
10 |
+
csv_file = 'aircraft.csv'
|
11 |
df = pd.read_csv(csv_file)
|
|
|
|
|
12 |
if aircraft_type not in df['Aircraft'].values:
|
13 |
return f"Aircraft type '{aircraft_type}' not found in the dataset."
|
14 |
+
|
|
|
15 |
aircraft_details = df[df['Aircraft'] == aircraft_type][[
|
16 |
+
'Range_km', 'Fuel_Consumption_kg/hr', 'Cruising Speed (kts)',
|
17 |
+
'Speed_kmh', 'MaxFlightTime_hr', 'Max_Fuel_Capacity_kg']]
|
18 |
+
|
19 |
+
return aircraft_details.to_dict(orient='records')[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
|
|
21 |
|
22 |
def get_airport_lat_long(identifiers):
|
23 |
"""
|
24 |
+
Get latitude and longitude for a list of airport identifiers (IATA codes).
|
|
|
|
|
|
|
25 |
"""
|
26 |
+
csv_file = 'airport.csv'
|
|
|
|
|
|
|
|
|
27 |
df = pd.read_csv(csv_file)
|
|
|
|
|
28 |
df_filtered = df[df['Airport_Name'].isin(identifiers) | df['IATA'].isin(identifiers)]
|
29 |
+
lat_long_dict = {row['IATA']: (row['Lat'], row['Long']) for _, row in df_filtered.iterrows()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
return lat_long_dict
|
31 |
|
32 |
+
|
33 |
def haversine_distance(lat1, lon1, lat2, lon2):
|
34 |
"""
|
35 |
+
Calculate the Haversine distance between two points on Earth (in kilometers).
|
36 |
"""
|
37 |
+
R = 6371.0 # Earth radius in kilometers
|
|
|
|
|
38 |
lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
|
39 |
+
dlat, dlon = lat2 - lat1, lon2 - lon1
|
|
|
|
|
|
|
40 |
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
|
41 |
+
return round(R * 2 * asin(sqrt(a)), 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
|
|
43 |
|
44 |
def calculate_distances(airport_identifiers):
|
45 |
"""
|
46 |
+
Calculate the distance between each pair of airports.
|
|
|
|
|
|
|
47 |
"""
|
48 |
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
|
|
|
|
|
|
|
|
49 |
distances = {}
|
50 |
+
for i in range(len(airport_identifiers)):
|
51 |
+
for j in range(i + 1, len(airport_identifiers)):
|
52 |
+
airport1, airport2 = airport_identifiers[i], airport_identifiers[j]
|
|
|
|
|
53 |
lat1, lon1 = lat_long_dict[airport1]
|
54 |
lat2, lon2 = lat_long_dict[airport2]
|
55 |
+
distances[(airport1, airport2)] = haversine_distance(lat1, lon1, lat2, lon2)
|
|
|
|
|
56 |
return distances
|
57 |
|
|
|
|
|
|
|
58 |
|
59 |
+
def calculate_fuel_and_time_for_segment(segment_distance, aircraft_specs):
|
|
|
|
|
|
|
|
|
|
|
60 |
"""
|
61 |
+
Calculate the fuel and time required for a single flight segment.
|
62 |
+
"""
|
63 |
+
cruising_speed = aircraft_specs['Speed_kmh']
|
64 |
+
fuel_burn_rate = aircraft_specs['Fuel_Consumption_kg/hr']
|
65 |
+
max_fuel_capacity = aircraft_specs['Max_Fuel_Capacity_kg']
|
66 |
+
reserve_fuel_percentage = 0.05 # 5% reserve fuel
|
67 |
+
|
68 |
+
climb_speed, descent_speed = 300, 350
|
69 |
+
climb_time, descent_time = 15 / 60, 10 / 60 # in hours
|
70 |
+
climb_distance = climb_speed * climb_time
|
71 |
+
descent_distance = descent_speed * descent_time
|
72 |
+
|
73 |
+
# Calculate cruise distance
|
74 |
+
cruise_distance = segment_distance - (climb_distance + descent_distance)
|
75 |
+
cruise_distance = max(0, cruise_distance) # Ensure cruise distance is not negative
|
76 |
+
|
77 |
+
# Calculate flight time for each phase
|
78 |
+
cruise_time = cruise_distance / cruising_speed
|
79 |
total_flight_time = climb_time + cruise_time + descent_time
|
80 |
|
81 |
+
# Calculate fuel required
|
82 |
fuel_required = total_flight_time * fuel_burn_rate
|
83 |
reserve_fuel = reserve_fuel_percentage * max_fuel_capacity
|
|
|
84 |
total_fuel_with_reserve = fuel_required + reserve_fuel
|
85 |
|
86 |
return total_fuel_with_reserve, total_flight_time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gradio_ui.py
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
from flight_distance import *
|
4 |
+
from optimize import *
|
5 |
+
from weather import *
|
6 |
+
|
7 |
+
# Load airport data and aircraft data from CSV files
|
8 |
+
airport_df = pd.read_csv(r'airport.csv') # Adjust the path to your CSV file
|
9 |
+
aircraft_df = pd.read_csv(r'aircraft.csv') # Adjust the path to your CSV file
|
10 |
+
|
11 |
+
# Create a combined option list with both IATA codes and airport names
|
12 |
+
airport_options = [f"{row['IATA']} - {row['Airport_Name']}" for _, row in airport_df.iterrows()]
|
13 |
+
|
14 |
+
# Ensure the correct column is used for aircraft types
|
15 |
+
aircraft_type_column = 'Aircraft'
|
16 |
+
aircraft_options = aircraft_df[aircraft_type_column].tolist()
|
17 |
+
|
18 |
+
# Gradio function to determine if a route can be flown
|
19 |
+
def check_route(airport_selections, aircraft_type):
|
20 |
+
# Extract IATA codes from the selected options
|
21 |
+
airports = [selection.split(" - ")[0] for selection in airport_selections]
|
22 |
+
|
23 |
+
# Step 1: Get Airport Coordinates
|
24 |
+
lat_long_dict = get_airport_lat_long(airports)
|
25 |
+
|
26 |
+
# Step 2: Calculate Distances between each node (airports)
|
27 |
+
trip_distance = calculate_distances(airports)
|
28 |
+
|
29 |
+
# Step 3: Get on-route weather
|
30 |
+
raw_weather = fetch_weather_for_all_routes(airports, lat_long_dict)
|
31 |
+
route_factors = extract_route_factors(raw_weather)
|
32 |
+
|
33 |
+
# Step 4: Ensure the graph is bidirectional (undirected)
|
34 |
+
for (a, b), dist in list(trip_distance.items()):
|
35 |
+
trip_distance[(b, a)] = dist
|
36 |
+
|
37 |
+
# Step 5: Find the optimal route based on weather, temperature, and distance
|
38 |
+
optimal_route, optimal_distance = find_optimal_route(airports, trip_distance, route_factors)
|
39 |
+
|
40 |
+
# Step 6: Fetch Aircraft Details
|
41 |
+
aircraft_specs = get_aircraft_details(aircraft_type)
|
42 |
+
|
43 |
+
# Check if aircraft details were retrieved successfully
|
44 |
+
if isinstance(aircraft_specs, str):
|
45 |
+
return {"Error": aircraft_specs} # Return error message if aircraft not found
|
46 |
+
|
47 |
+
# Prepare sector-wise details for flight time, fuel required, and refueling need
|
48 |
+
sector_details = []
|
49 |
+
refuel_required = False # Flag to track if refueling is required
|
50 |
+
|
51 |
+
for i in range(len(optimal_route) - 1):
|
52 |
+
segment = (optimal_route[i], optimal_route[i + 1])
|
53 |
+
segment_distance = trip_distance.get(segment) or trip_distance.get((segment[1], segment[0]))
|
54 |
+
|
55 |
+
# Calculate fuel and time for this sector
|
56 |
+
fuel, time = calculate_fuel_and_time_for_segment(segment_distance, aircraft_specs)
|
57 |
+
sector_info = {
|
58 |
+
"Sector": f"{optimal_route[i]} -> {optimal_route[i+1]}",
|
59 |
+
"Fuel Required (kg)": round(fuel, 2),
|
60 |
+
"Flight Time (hrs)": round(time, 2)
|
61 |
+
}
|
62 |
+
|
63 |
+
# Check if refueling is required for this sector
|
64 |
+
if fuel > aircraft_specs['Max_Fuel_Capacity_kg']:
|
65 |
+
sector_info["Refuel Required"] = "Yes"
|
66 |
+
refuel_required = True
|
67 |
+
else:
|
68 |
+
sector_info["Refuel Required"] = "No"
|
69 |
+
|
70 |
+
sector_details.append(sector_info)
|
71 |
+
|
72 |
+
# Check the final leg (return to the starting point)
|
73 |
+
last_segment = (optimal_route[-1], optimal_route[0])
|
74 |
+
last_segment_distance = trip_distance.get(last_segment) or trip_distance.get((last_segment[1], last_segment[0]))
|
75 |
+
fuel, time = calculate_fuel_and_time_for_segment(last_segment_distance, aircraft_specs)
|
76 |
+
|
77 |
+
# Add final leg details
|
78 |
+
final_leg_info = {
|
79 |
+
"Sector": f"{optimal_route[-1]} -> {optimal_route[0]}",
|
80 |
+
"Fuel Required (kg)": round(fuel, 2),
|
81 |
+
"Flight Time (hrs)": round(time, 2)
|
82 |
+
}
|
83 |
+
|
84 |
+
if fuel > aircraft_specs['Max_Fuel_Capacity_kg']:
|
85 |
+
final_leg_info["Refuel Required"] = "Yes"
|
86 |
+
refuel_required = True
|
87 |
+
else:
|
88 |
+
final_leg_info["Refuel Required"] = "No"
|
89 |
+
|
90 |
+
sector_details.append(final_leg_info)
|
91 |
+
|
92 |
+
# Step 7: Prepare and return result
|
93 |
+
if refuel_required:
|
94 |
+
result = {
|
95 |
+
"Optimal Route": " -> ".join(optimal_route) + f" -> {optimal_route[0]}",
|
96 |
+
"Total Round Trip Distance": str(optimal_distance) + " km",
|
97 |
+
"Can Fly Entire Route": "No, refueling required in one or more sectors.",
|
98 |
+
"Sector Details": sector_details
|
99 |
+
}
|
100 |
+
else:
|
101 |
+
result = {
|
102 |
+
"Optimal Route": " -> ".join(optimal_route) + f" -> {optimal_route[0]}",
|
103 |
+
"Total Round Trip Distance": str(optimal_distance) + " km",
|
104 |
+
"Can Fly Entire Route": "Yes, no refueling required.",
|
105 |
+
"Sector Details": sector_details
|
106 |
+
}
|
107 |
+
|
108 |
+
return result
|
109 |
+
|
110 |
+
|
111 |
+
# Gradio Interface
|
112 |
+
with gr.Blocks() as demo:
|
113 |
+
gr.Markdown("## Airport Route Feasibility Checker")
|
114 |
+
airport_selector = gr.Dropdown(airport_options, multiselect=True, label="Select Airports (IATA - Name)")
|
115 |
+
aircraft_selector = gr.Dropdown(aircraft_options, label="Select Aircraft Type")
|
116 |
+
check_button = gr.Button("Check Route Feasibility")
|
117 |
+
|
118 |
+
result_output = gr.JSON(label="Result")
|
119 |
+
|
120 |
+
# Connect the button click to the check_route function
|
121 |
+
check_button.click(fn=check_route, inputs=[airport_selector, aircraft_selector], outputs=result_output)
|
122 |
+
|
123 |
+
# Launch the Gradio app
|
124 |
+
demo.launch()
|
main.py
CHANGED
@@ -1,36 +1,45 @@
|
|
1 |
import pandas as pd
|
2 |
from flight_distance import *
|
3 |
-
from
|
4 |
from weather import *
|
5 |
|
6 |
-
airport_identifiers = ['
|
7 |
|
8 |
-
#Get Airport Coordinates
|
9 |
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
10 |
-
# print("Coordinates: \n",lat_long_dict)
|
11 |
|
12 |
-
#Get Distance between each node (airports)
|
13 |
trip_distance = calculate_distances(airport_identifiers)
|
14 |
-
# print("Distance b/w Airports: \n",trip_distance)
|
15 |
|
16 |
-
#Get
|
|
|
17 |
raw_weather = fetch_weather_for_all_routes(airport_identifiers, lat_long_dict)
|
18 |
route_factors = extract_route_factors(raw_weather)
|
19 |
-
# print("On Route weather: \n", raw_weather)
|
20 |
|
21 |
-
#
|
22 |
for (a, b), dist in list(trip_distance.items()):
|
23 |
trip_distance[(b, a)] = dist
|
24 |
|
25 |
-
# Find the optimal route
|
26 |
optimal_route, optimal_distance = find_optimal_route(airport_identifiers, trip_distance, route_factors)
|
27 |
|
28 |
-
# Display the optimal route and
|
29 |
print("Optimal Route:", " -> ".join(optimal_route) + f" -> {optimal_route[0]}")
|
30 |
-
print("Total Round Trip Distance:", optimal_distance)
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import pandas as pd
|
2 |
from flight_distance import *
|
3 |
+
from optimize import *
|
4 |
from weather import *
|
5 |
|
6 |
+
airport_identifiers = ['CCU', 'SIN', 'LHR'] # Replace with actual identifiers
|
7 |
|
8 |
+
# Step 1: Get Airport Coordinates
|
9 |
lat_long_dict = get_airport_lat_long(airport_identifiers)
|
|
|
10 |
|
11 |
+
# Step 2: Get Distance between each node (airports)
|
12 |
trip_distance = calculate_distances(airport_identifiers)
|
|
|
13 |
|
14 |
+
# Step 3: Get on-route weather
|
15 |
+
# Assuming 'fetch_weather_for_all_routes' is available in weather module
|
16 |
raw_weather = fetch_weather_for_all_routes(airport_identifiers, lat_long_dict)
|
17 |
route_factors = extract_route_factors(raw_weather)
|
|
|
18 |
|
19 |
+
# Step 4: Ensure the graph is bidirectional (undirected)
|
20 |
for (a, b), dist in list(trip_distance.items()):
|
21 |
trip_distance[(b, a)] = dist
|
22 |
|
23 |
+
# Step 5: Find the optimal route based on weather, temperature, and distance
|
24 |
optimal_route, optimal_distance = find_optimal_route(airport_identifiers, trip_distance, route_factors)
|
25 |
|
26 |
+
# Display the optimal route and total adjusted distance
|
27 |
print("Optimal Route:", " -> ".join(optimal_route) + f" -> {optimal_route[0]}")
|
28 |
+
print("Total Round Trip Distance:", optimal_distance, "km")
|
29 |
+
|
30 |
+
# Step 6: Fetch Aircraft Details (e.g., Boeing 787-9)
|
31 |
+
aircraft_type = "Boeing 737-800"
|
32 |
+
aircraft_specs = get_aircraft_details(aircraft_type)
|
33 |
+
|
34 |
+
# Check if aircraft details were retrieved successfully
|
35 |
+
if isinstance(aircraft_specs, str):
|
36 |
+
print(aircraft_specs) # Print error if aircraft not found
|
37 |
+
else:
|
38 |
+
# Step 7: Check if the aircraft can fly the route
|
39 |
+
route_feasibility = check_route_feasibility(optimal_route, trip_distance, aircraft_specs)
|
40 |
+
|
41 |
+
if route_feasibility["Can Fly Entire Route"]:
|
42 |
+
print(f"Total fuel required for the entire route: {route_feasibility['Total Fuel Required (kg)']} kg")
|
43 |
+
print(f"Total flight time for the entire route: {route_feasibility['Total Flight Time (hrs)']} hours")
|
44 |
+
else:
|
45 |
+
print("The aircraft cannot fly the entire route without refueling for at least one sector.")
|
optimize.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import itertools
|
2 |
+
from flight_distance import *
|
3 |
+
|
4 |
+
def extract_route_factors(raw_weather):
|
5 |
+
"""
|
6 |
+
Extract weather and temperature factors for each route segment.
|
7 |
+
"""
|
8 |
+
route_factors = {}
|
9 |
+
for route, segments in raw_weather.items():
|
10 |
+
for segment in segments:
|
11 |
+
segment_key = tuple(segment['segment'].split(' -> '))
|
12 |
+
if segment_key not in route_factors:
|
13 |
+
route_factors[segment_key] = []
|
14 |
+
route_factors[segment_key].append({
|
15 |
+
'weather': segment['weather'],
|
16 |
+
'temperature': segment['temperature']
|
17 |
+
})
|
18 |
+
return route_factors
|
19 |
+
|
20 |
+
|
21 |
+
def weather_risk(weather):
|
22 |
+
"""
|
23 |
+
Return the risk factor associated with weather conditions.
|
24 |
+
"""
|
25 |
+
risk_factors = {
|
26 |
+
"clear sky": 0.1, "few clouds": 0.2, "scattered clouds": 0.3,
|
27 |
+
"broken clouds": 0.4, "overcast clouds": 0.5, "light rain": 0.6,
|
28 |
+
"rain": 0.7, "storm": 0.9
|
29 |
+
}
|
30 |
+
return risk_factors.get(weather, 0.5) # Default risk factor
|
31 |
+
|
32 |
+
|
33 |
+
def temperature_impact(temperature):
|
34 |
+
"""
|
35 |
+
Calculate the impact of temperature on fuel efficiency.
|
36 |
+
"""
|
37 |
+
if temperature < 20 or temperature > 25:
|
38 |
+
return abs(temperature - 22.5) / 30 # Normalize impact to a value between 0 and 1
|
39 |
+
return 0.1 # Low impact in the ideal range
|
40 |
+
|
41 |
+
|
42 |
+
def calculate_adjusted_cost(segment, base_distance, route_factors):
|
43 |
+
"""
|
44 |
+
Calculate the adjusted cost of a segment considering weather and temperature.
|
45 |
+
"""
|
46 |
+
if segment in route_factors:
|
47 |
+
factors = route_factors[segment]
|
48 |
+
elif (segment[1], segment[0]) in route_factors:
|
49 |
+
factors = route_factors[(segment[1], segment[0])]
|
50 |
+
else:
|
51 |
+
raise ValueError(f"Segment {segment} not found in route factors.")
|
52 |
+
|
53 |
+
weather_descriptions = [factor["weather"] for factor in factors]
|
54 |
+
temperatures = [factor["temperature"] for factor in factors]
|
55 |
+
|
56 |
+
most_common_weather = max(set(weather_descriptions), key=weather_descriptions.count)
|
57 |
+
avg_temperature = sum(temperatures) / len(temperatures)
|
58 |
+
|
59 |
+
weather_cost = weather_risk(most_common_weather) * 100 # Weather impact weight
|
60 |
+
temperature_cost = temperature_impact(avg_temperature) * 50 # Temperature impact weight
|
61 |
+
|
62 |
+
total_cost = base_distance + weather_cost + temperature_cost
|
63 |
+
return total_cost
|
64 |
+
|
65 |
+
|
66 |
+
def find_optimal_route(airports, distances, route_factors):
|
67 |
+
"""
|
68 |
+
Find the optimal route between airports considering distance and weather factors.
|
69 |
+
"""
|
70 |
+
best_route, min_distance = None, float('inf')
|
71 |
+
for route in itertools.permutations(airports):
|
72 |
+
total_distance = 0
|
73 |
+
for i in range(len(route) - 1):
|
74 |
+
segment = (route[i], route[i + 1])
|
75 |
+
base_distance = distances.get(segment) or distances.get((segment[1], segment[0]))
|
76 |
+
total_distance += calculate_adjusted_cost(segment, base_distance, route_factors)
|
77 |
+
|
78 |
+
last_segment = (route[-1], route[0])
|
79 |
+
base_distance = distances.get(last_segment) or distances.get((last_segment[1], last_segment[0]))
|
80 |
+
total_distance += calculate_adjusted_cost(last_segment, base_distance, route_factors)
|
81 |
+
|
82 |
+
if total_distance < min_distance:
|
83 |
+
min_distance, best_route = round(total_distance, 2), route
|
84 |
+
|
85 |
+
return best_route, min_distance
|
86 |
+
|
87 |
+
|
88 |
+
### Modular Route Feasibility Checking Functions ###
|
89 |
+
|
90 |
+
def check_segment_feasibility(segment, trip_distance, aircraft_specs):
|
91 |
+
"""
|
92 |
+
Check if the aircraft can fly a single segment without refueling.
|
93 |
+
"""
|
94 |
+
segment_distance = trip_distance.get(segment) or trip_distance.get((segment[1], segment[0]))
|
95 |
+
fuel_required, flight_time = calculate_fuel_and_time_for_segment(segment_distance, aircraft_specs)
|
96 |
+
|
97 |
+
if fuel_required > aircraft_specs['Max_Fuel_Capacity_kg']:
|
98 |
+
return False, fuel_required, flight_time
|
99 |
+
return True, fuel_required, flight_time
|
100 |
+
|
101 |
+
|
102 |
+
def check_route_feasibility(optimal_route, trip_distance, aircraft_specs):
|
103 |
+
"""
|
104 |
+
Check if the aircraft can fly the entire optimal route without refueling.
|
105 |
+
"""
|
106 |
+
total_fuel = 0
|
107 |
+
total_time = 0
|
108 |
+
can_fly_entire_route = True # Flag to check if entire route is feasible
|
109 |
+
|
110 |
+
for i in range(len(optimal_route) - 1):
|
111 |
+
segment = (optimal_route[i], optimal_route[i + 1])
|
112 |
+
can_fly, fuel, time = check_segment_feasibility(segment, trip_distance, aircraft_specs)
|
113 |
+
if not can_fly:
|
114 |
+
print(f"Cannot fly the sector {optimal_route[i]} -> {optimal_route[i+1]} without refueling.")
|
115 |
+
print(f"Fuel required: {round(fuel, 2)} kg, capacity: {aircraft_specs['Max_Fuel_Capacity_kg']} kg")
|
116 |
+
can_fly_entire_route = False
|
117 |
+
else:
|
118 |
+
print(f"Fuel required for {optimal_route[i]} -> {optimal_route[i+1]}: {round(fuel, 2)} kg")
|
119 |
+
print(f"Flight time for this sector: {round(time, 2)} hours")
|
120 |
+
total_fuel += fuel
|
121 |
+
total_time += time
|
122 |
+
|
123 |
+
last_segment = (optimal_route[-1], optimal_route[0])
|
124 |
+
can_fly, fuel, time = check_segment_feasibility(last_segment, trip_distance, aircraft_specs)
|
125 |
+
if not can_fly:
|
126 |
+
print(f"Cannot fly the sector {optimal_route[-1]} -> {optimal_route[0]} without refueling.")
|
127 |
+
print(f"Fuel required: {round(fuel, 2)} kg, capacity: {aircraft_specs['Max_Fuel_Capacity_kg']} kg")
|
128 |
+
can_fly_entire_route = False
|
129 |
+
else:
|
130 |
+
print(f"Fuel required for {optimal_route[-1]} -> {optimal_route[0]}: {round(fuel, 2)} kg")
|
131 |
+
print(f"Flight time for this sector: {round(time, 2)} hours")
|
132 |
+
total_fuel += fuel
|
133 |
+
total_time += time
|
134 |
+
|
135 |
+
if can_fly_entire_route:
|
136 |
+
return {
|
137 |
+
"Total Fuel Required (kg)": round(total_fuel, 2),
|
138 |
+
"Total Flight Time (hrs)": round(total_time, 2),
|
139 |
+
"Can Fly Entire Route": True
|
140 |
+
}
|
141 |
+
else:
|
142 |
+
return {"Can Fly Entire Route": False}
|
ui.py
DELETED
@@ -1,90 +0,0 @@
|
|
1 |
-
import tkinter as tk
|
2 |
-
from tkinter import ttk
|
3 |
-
import pandas as pd
|
4 |
-
|
5 |
-
class AirportSearchApp:
|
6 |
-
def __init__(self, root, csv_file):
|
7 |
-
self.root = root
|
8 |
-
self.root.title("Airport Search")
|
9 |
-
|
10 |
-
self.df = pd.read_csv(csv_file)
|
11 |
-
self.iata_index = {row['IATA']: row['Airport_Name'] for idx, row in self.df.iterrows()}
|
12 |
-
self.name_index = {row['Airport_Name'].lower(): row['IATA'] for idx, row in self.df.iterrows()}
|
13 |
-
self.trie = self.build_trie()
|
14 |
-
|
15 |
-
self.create_widgets()
|
16 |
-
|
17 |
-
def build_trie(self):
|
18 |
-
trie = {}
|
19 |
-
for _, row in self.df.iterrows():
|
20 |
-
node = trie
|
21 |
-
for char in row['Airport_Name'].lower():
|
22 |
-
node = node.setdefault(char, {})
|
23 |
-
node['_end_'] = row['Airport_Name']
|
24 |
-
return trie
|
25 |
-
|
26 |
-
def search_iata(self, iata):
|
27 |
-
return self.iata_index.get(iata.upper(), "Airport not found")
|
28 |
-
|
29 |
-
def search_name(self, prefix):
|
30 |
-
node = self.trie
|
31 |
-
for char in prefix.lower():
|
32 |
-
if char not in node:
|
33 |
-
return []
|
34 |
-
node = node[char]
|
35 |
-
return self.find_airports(node)
|
36 |
-
|
37 |
-
def find_airports(self, node, prefix='', results=None):
|
38 |
-
if results is None:
|
39 |
-
results = []
|
40 |
-
if '_end_' in node:
|
41 |
-
results.append(node['_end_'])
|
42 |
-
for char, next_node in node.items():
|
43 |
-
if char != '_end_':
|
44 |
-
self.find_airports(next_node, prefix + char, results)
|
45 |
-
return results
|
46 |
-
|
47 |
-
def autocomplete(self, prefix, max_results=5):
|
48 |
-
results = self.search_name(prefix)
|
49 |
-
return results[:max_results]
|
50 |
-
|
51 |
-
def create_widgets(self):
|
52 |
-
self.label = tk.Label(self.root, text="Enter Airport Name or IATA Code:")
|
53 |
-
self.label.pack(pady=10)
|
54 |
-
|
55 |
-
self.entry = ttk.Entry(self.root, width=50)
|
56 |
-
self.entry.pack(pady=10)
|
57 |
-
self.entry.bind('<KeyRelease>', self.on_key_release)
|
58 |
-
|
59 |
-
self.listbox = tk.Listbox(self.root, width=50, height=10)
|
60 |
-
self.listbox.pack(pady=10)
|
61 |
-
self.listbox.bind('<<ListboxSelect>>', self.on_select)
|
62 |
-
|
63 |
-
self.result_label = tk.Label(self.root, text="")
|
64 |
-
self.result_label.pack(pady=10)
|
65 |
-
|
66 |
-
def on_key_release(self, event):
|
67 |
-
input_text = self.entry.get()
|
68 |
-
if len(input_text) == 3:
|
69 |
-
# Likely an IATA code
|
70 |
-
airport_name = self.search_iata(input_text)
|
71 |
-
self.result_label.config(text=f"IATA Code: {input_text} -> Airport: {airport_name}")
|
72 |
-
self.listbox.delete(0, tk.END)
|
73 |
-
else:
|
74 |
-
# Autocomplete based on airport name
|
75 |
-
suggestions = self.autocomplete(input_text)
|
76 |
-
self.listbox.delete(0, tk.END)
|
77 |
-
for suggestion in suggestions:
|
78 |
-
self.listbox.insert(tk.END, f"{suggestion} ({self.name_index[suggestion.lower()]})")
|
79 |
-
|
80 |
-
def on_select(self, event):
|
81 |
-
selected_airport = self.listbox.get(self.listbox.curselection())
|
82 |
-
self.result_label.config(text=f"Selected Airport: {selected_airport}")
|
83 |
-
|
84 |
-
def main():
|
85 |
-
root = tk.Tk()
|
86 |
-
app = AirportSearchApp(root, 'airport.csv')
|
87 |
-
root.mainloop()
|
88 |
-
|
89 |
-
if __name__ == "__main__":
|
90 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|