lyimo commited on
Commit
ce1be2b
1 Parent(s): 237d44d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -182
app.py CHANGED
@@ -3,216 +3,220 @@ import requests
3
  import pandas as pd
4
  from sklearn.linear_model import LogisticRegression
5
  from fastai.vision.all import *
6
- from fastai.vision.all import PILImage
7
  import os
8
- from datetime import datetime
9
 
10
  # Load the trained model for image-based fog classification
11
  learn = load_learner('fog_classifier.pkl')
12
  labels = learn.dls.vocab
13
 
14
- # Use environment variables for API keys
15
  API_KEY = os.environ.get("OPENWEATHER_API_KEY")
16
  BASE_URL = 'https://api.openweathermap.org/data/2.5/'
17
 
18
- # Define the prediction function for image-based fog classification
19
  def predict_image(img):
 
20
  img = PILImage.create(img)
21
  img = img.resize((512, 512))
22
  pred, pred_idx, probs = learn.predict(img)
23
  return {labels[i]: float(probs[i]) for i in range(len(labels))}
24
 
25
- # Function to get weather data
26
- def get_weather_data(location):
27
- current_weather_url = f'{BASE_URL}weather?q={location}&appid={API_KEY}&units=metric'
28
- current_response = requests.get(current_weather_url)
29
- current_data = current_response.json()
30
-
31
- current_weather = {
32
- 'temperature': current_data['main'].get('temp', 0),
33
- 'feels_like': current_data['main'].get('feels_like', 0),
34
- 'description': current_data['weather'][0].get('description', ''),
35
- 'wind_speed': current_data['wind'].get('speed', 0),
36
- 'pressure': current_data['main'].get('pressure', 0),
37
- 'humidity': current_data['main'].get('humidity', 0),
38
- 'visibility': current_data.get('visibility', 10000) / 1000,
39
- 'dew_point': current_data['main'].get('temp', 0) - ((100 - current_data['main'].get('humidity', 0)) / 5.0)
40
  }
41
- return current_weather
42
-
43
- # Function to train the fog prediction model
44
- def train_fog_model():
45
- df = pd.read_csv('fog_weather_data.csv')
46
- df = pd.get_dummies(df, columns=['Description'], drop_first=True)
47
- X = df.drop('Fog', axis=1)
48
- y = df['Fog']
49
- model = LogisticRegression()
50
- model.fit(X, y)
51
- return model, X.columns
52
-
53
- # Function to predict fog based on weather data
54
- def predict_fog(model, feature_columns, weather_data):
55
- new_data = pd.DataFrame({
56
- 'Temperature': [weather_data.get('temperature', 0)],
57
- 'Feels like': [weather_data.get('feels_like', 0)],
58
- 'Wind speed': [weather_data.get('wind_speed', 0)],
59
- 'Pressure': [weather_data.get('pressure', 0)],
60
- 'Humidity': [weather_data.get('humidity', 0)],
61
- 'Dew point': [weather_data.get('dew_point', 0)],
62
- 'Visibility': [weather_data.get('visibility', 10)]
63
- })
64
-
65
- for col in feature_columns:
66
- if col.startswith('Description_'):
67
- new_data[col] = 0
68
 
69
- description_column = f"Description_{weather_data.get('description', '').replace(' ', '_')}"
70
- if description_column in feature_columns:
71
- new_data[description_column] = 1
72
-
73
- prediction = model.predict(new_data)
74
- return "Foggy weather" if prediction[0] == 1 else "Clear weather"
75
-
76
- # Function to get 5-day weather forecast
77
- def get_5day_forecast(location):
78
- forecast_url = f'{BASE_URL}forecast?q={location}&appid={API_KEY}&units=metric'
79
- forecast_response = requests.get(forecast_url)
80
- forecast_data = forecast_response.json()
81
-
82
- forecast_list = []
83
- for entry in forecast_data['list']:
84
- forecast_list.append({
85
- 'date': entry['dt_txt'],
86
- 'temperature': entry['main'].get('temp', 0),
87
- 'humidity': entry['main'].get('humidity', 0),
88
- 'description': entry['weather'][0].get('description', '')
89
- })
90
- return forecast_list
91
 
92
- # Load the fog prediction model
93
- fog_model, feature_columns = train_fog_model()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- # Function to predict current weather and fog
96
- def predict_current_weather(location):
97
  try:
 
 
 
 
98
  current_weather = get_weather_data(location)
99
- fog_prediction = predict_fog(fog_model, feature_columns, current_weather)
100
-
101
- result = f"Current weather in {location}:\n"
102
- result += f"Temperature: {current_weather.get('temperature', 0)}°C\n"
103
- result += f"Feels like: {current_weather.get('feels_like', 0)}°C\n"
104
- result += f"Description: {current_weather.get('description', '')}\n"
105
- result += f"Wind speed: {current_weather.get('wind_speed', 0)} m/s\n"
106
- result += f"Pressure: {current_weather.get('pressure', 0)} hPa\n"
107
- result += f"Humidity: {current_weather.get('humidity', 0)}%\n"
108
- result += f"Dew point: {current_weather.get('dew_point', 0)}°C\n"
109
- result += f"Visibility: {current_weather.get('visibility', 10)} km\n"
110
- result += f"\nFog Prediction: {fog_prediction}"
111
-
112
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  except Exception as e:
114
  return f"Error: {str(e)}"
115
 
116
- # Function to determine transmission power based on combined results
117
- def determine_transmission_power(image_prediction, weather_prediction, humidity):
118
- image_class = max(image_prediction, key=image_prediction.get)
119
- weather_class = "Foggy weather" if weather_prediction == "Foggy weather" else "Clear weather"
120
-
121
- if humidity > 80: # High humidity increases the likelihood of fog
122
- if image_class == "Dense_Fog" or weather_class == "Foggy weather":
123
- return "High"
124
- elif image_class == "Moderate_Fog":
125
- return "Medium"
126
- else:
127
- return "Normal"
128
- else:
129
- if image_class == "Dense_Fog":
130
- return "Medium"
131
- elif image_class == "Moderate_Fog":
132
- return "Normal"
133
- else:
134
- return "Normal"
135
-
136
- # Function to format 5-day weather forecast
137
- def format_5day_forecast(forecast_list):
138
- forecast_dict = {}
139
- for entry in forecast_list:
140
- date = entry['date'].split()[0]
141
- if date not in forecast_dict:
142
- forecast_dict[date] = {
143
- 'temperature': entry['temperature'],
144
- 'humidity': entry['humidity'],
145
- 'description': entry['description']
146
- }
147
- else:
148
- forecast_dict[date]['temperature'] += entry['temperature']
149
- forecast_dict[date]['humidity'] += entry['humidity']
150
- forecast_dict[date]['description'] = entry['description']
151
-
152
- formatted_forecast = []
153
- for date, data in forecast_dict.items():
154
- avg_temperature = data['temperature'] / 8 # 8 entries per day
155
- avg_humidity = data['humidity'] / 8
156
- formatted_forecast.append(f"Date: {date}\nTemperature: {avg_temperature:.2f}°C\nHumidity: {avg_humidity:.2f}%\nDescription: {data['description']}\n")
157
-
158
- return "\n".join(formatted_forecast)
159
-
160
- # Main function to integrate all functionalities
161
- def integrated_prediction(image, location):
162
- # Predict fog from image
163
- image_prediction = predict_image(image)
164
-
165
- # Get current weather data and predict fog
166
- current_weather = get_weather_data(location)
167
- weather_prediction = predict_fog(fog_model, feature_columns, current_weather)
168
-
169
- # Get 5-day weather forecast
170
- forecast_list = get_5day_forecast(location)
171
- formatted_forecast = format_5day_forecast(forecast_list)
172
-
173
- # Determine transmission power based on current and future fog predictions
174
- transmission_power = determine_transmission_power(image_prediction, weather_prediction, current_weather.get('humidity', 0))
175
-
176
- # Check fog predictions for the next 5 days
177
- fog_days = []
178
- for entry in forecast_list:
179
- date = entry['date'].split()[0]
180
- weather_data = {
181
- 'temperature': entry.get('temperature', 0),
182
- 'humidity': entry.get('humidity', 0),
183
- 'description': entry.get('description', ''),
184
- 'visibility': 10, # Assuming visibility is 10 km for simplicity
185
- 'dew_point': entry.get('temperature', 0) - ((100 - entry.get('humidity', 0)) / 5.0)
186
- }
187
- fog_prediction = predict_fog(fog_model, feature_columns, weather_data)
188
- if fog_prediction == "Foggy weather":
189
- fog_days.append(date)
190
-
191
- # Prepare the result
192
- result = f"Current Weather and Fog Prediction:\n{predict_current_weather(location)}\n\n"
193
- result += f"5-Day Weather Forecast:\n{formatted_forecast}\n\n"
194
- result += f"Transmission Power: {transmission_power}\n"
195
-
196
- if fog_days:
197
- result += f"Foggy conditions predicted on: {', '.join(fog_days)}\n"
198
- if len(fog_days) == 5:
199
- result += "Transmission power will be kept high for the next 5 days.\n"
200
- else:
201
- result += f"Transmission power will be high on: {fog_days[-1]}\n"
202
-
203
- return result
204
-
205
  # Gradio interface
206
  with gr.Blocks() as demo:
207
- gr.Markdown("# Integrated Fog Prediction and Transmission Power Decision")
208
-
209
  with gr.Row():
210
- image_input = gr.Image(label="Upload Image")
211
  location_input = gr.Textbox(label="Enter Location")
212
-
213
- predict_button = gr.Button("Predict and Determine Transmission Power")
214
- output = gr.Textbox(label="Prediction and Transmission Power Result")
215
-
216
  predict_button.click(integrated_prediction, inputs=[image_input, location_input], outputs=output)
217
 
218
  demo.launch()
 
3
  import pandas as pd
4
  from sklearn.linear_model import LogisticRegression
5
  from fastai.vision.all import *
 
6
  import os
7
+ from datetime import datetime, timedelta
8
 
9
  # Load the trained model for image-based fog classification
10
  learn = load_learner('fog_classifier.pkl')
11
  labels = learn.dls.vocab
12
 
 
13
  API_KEY = os.environ.get("OPENWEATHER_API_KEY")
14
  BASE_URL = 'https://api.openweathermap.org/data/2.5/'
15
 
 
16
  def predict_image(img):
17
+ """Predict fog conditions from image and return confidence scores"""
18
  img = PILImage.create(img)
19
  img = img.resize((512, 512))
20
  pred, pred_idx, probs = learn.predict(img)
21
  return {labels[i]: float(probs[i]) for i in range(len(labels))}
22
 
23
+ def calculate_fog_risk_score(weather_data):
24
+ """Calculate a fog risk score (0-1) based on weather conditions"""
25
+ # Normalized weights for each factor
26
+ weights = {
27
+ 'humidity': 0.3,
28
+ 'dew_point_temp_diff': 0.3,
29
+ 'visibility': 0.2,
30
+ 'wind_speed': 0.1,
31
+ 'pressure_change': 0.1
 
 
 
 
 
 
32
  }
33
+
34
+ # Calculate dew point
35
+ dew_point = weather_data['temperature'] - ((100 - weather_data['humidity']) / 5.0)
36
+ dew_point_temp_diff = abs(weather_data['temperature'] - dew_point)
37
+
38
+ # Normalize each factor to 0-1 scale
39
+ humidity_score = min(weather_data['humidity'] / 100, 1)
40
+ dew_point_score = 1 - min(dew_point_temp_diff / 5, 1) # Closer to dew point = higher score
41
+ visibility_score = 1 - min(weather_data['visibility'] / 10, 1) # Lower visibility = higher score
42
+ wind_score = 1 - min(weather_data['wind_speed'] / 10, 1) # Lower wind = higher score
43
+ pressure_score = min(abs(weather_data['pressure'] - 1013.25) / 50, 1) # Deviation from normal pressure
44
+
45
+ # Calculate weighted score
46
+ fog_risk = (
47
+ weights['humidity'] * humidity_score +
48
+ weights['dew_point_temp_diff'] * dew_point_score +
49
+ weights['visibility'] * visibility_score +
50
+ weights['wind_speed'] * wind_score +
51
+ weights['pressure_change'] * pressure_score
52
+ )
53
+
54
+ return fog_risk
 
 
 
 
 
55
 
56
+ def get_weather_data(location):
57
+ """Get current weather data with enhanced error handling"""
58
+ try:
59
+ current_weather_url = f'{BASE_URL}weather?q={location}&appid={API_KEY}&units=metric'
60
+ response = requests.get(current_weather_url)
61
+ response.raise_for_status()
62
+ data = response.json()
63
+
64
+ return {
65
+ 'temperature': data['main'].get('temp', 0),
66
+ 'feels_like': data['main'].get('feels_like', 0),
67
+ 'description': data['weather'][0].get('description', ''),
68
+ 'wind_speed': data['wind'].get('speed', 0),
69
+ 'pressure': data['main'].get('pressure', 0),
70
+ 'humidity': data['main'].get('humidity', 0),
71
+ 'visibility': data.get('visibility', 10000) / 1000,
72
+ 'timestamp': datetime.fromtimestamp(data['dt'])
73
+ }
74
+ except requests.exceptions.RequestException as e:
75
+ raise Exception(f"Failed to fetch weather data: {str(e)}")
 
 
76
 
77
+ def get_forecast_data(location):
78
+ """Get 5-day forecast with enhanced error handling"""
79
+ try:
80
+ forecast_url = f'{BASE_URL}forecast?q={location}&appid={API_KEY}&units=metric'
81
+ response = requests.get(forecast_url)
82
+ response.raise_for_status()
83
+ data = response.json()
84
+
85
+ forecasts = []
86
+ for item in data['list']:
87
+ forecasts.append({
88
+ 'temperature': item['main'].get('temp', 0),
89
+ 'humidity': item['main'].get('humidity', 0),
90
+ 'description': item['weather'][0].get('description', ''),
91
+ 'wind_speed': item['wind'].get('speed', 0),
92
+ 'pressure': item['main'].get('pressure', 0),
93
+ 'visibility': item.get('visibility', 10000) / 1000,
94
+ 'timestamp': datetime.fromtimestamp(item['dt'])
95
+ })
96
+ return forecasts
97
+ except requests.exceptions.RequestException as e:
98
+ raise Exception(f"Failed to fetch forecast data: {str(e)}")
99
+
100
+ def determine_transmission_power(image_prediction, weather_data, forecast_data=None):
101
+ """
102
+ Determine transmission power based on current conditions and forecast
103
+ Returns: (power_level, duration, explanation)
104
+ """
105
+ # Get fog confidence from image
106
+ image_fog_confidence = max(
107
+ image_prediction.get('Dense_Fog', 0),
108
+ image_prediction.get('Moderate_Fog', 0) * 0.6
109
+ )
110
+
111
+ # Calculate weather-based fog risk
112
+ current_fog_risk = calculate_fog_risk_score(weather_data)
113
+
114
+ # Combine image and weather predictions with weighted average
115
+ # Give slightly more weight to image prediction as it's more reliable
116
+ combined_fog_risk = (image_fog_confidence * 0.6) + (current_fog_risk * 0.4)
117
+
118
+ # Initialize explanation
119
+ explanation = []
120
+
121
+ # Determine base power level from current conditions
122
+ if combined_fog_risk > 0.7:
123
+ power_level = "High"
124
+ explanation.append(f"High fog risk detected (Risk score: {combined_fog_risk:.2f})")
125
+ elif combined_fog_risk > 0.4:
126
+ power_level = "Medium"
127
+ explanation.append(f"Moderate fog risk detected (Risk score: {combined_fog_risk:.2f})")
128
+ else:
129
+ power_level = "Normal"
130
+ explanation.append(f"Low fog risk detected (Risk score: {combined_fog_risk:.2f})")
131
+
132
+ # Analyze forecast data if available
133
+ duration = timedelta(hours=1) # Default duration
134
+ if forecast_data:
135
+ future_risks = []
136
+ for forecast in forecast_data[:40]: # 5 days of 3-hour forecasts
137
+ risk = calculate_fog_risk_score(forecast)
138
+ future_risks.append(risk)
139
+
140
+ # Find periods of high risk
141
+ high_risk_periods = [risk > 0.6 for risk in future_risks]
142
+ if any(high_risk_periods):
143
+ # Find the last high-risk timestamp
144
+ last_high_risk_idx = len(high_risk_periods) - 1 - high_risk_periods[::-1].index(True)
145
+ duration = forecast_data[last_high_risk_idx]['timestamp'] - weather_data['timestamp']
146
+
147
+ explanation.append(f"High fog risk predicted to continue for {duration.days} days and {duration.hours} hours")
148
+
149
+ # Adjust power level based on forecast
150
+ if sum(high_risk_periods) / len(high_risk_periods) > 0.5:
151
+ power_level = "High"
152
+ explanation.append("Power level set to High due to sustained fog risk in forecast")
153
+
154
+ return power_level, duration, explanation
155
 
156
+ def integrated_prediction(image, location):
157
+ """Main function to process image and weather data"""
158
  try:
159
+ # Get image prediction
160
+ image_prediction = predict_image(image)
161
+
162
+ # Get current weather
163
  current_weather = get_weather_data(location)
164
+
165
+ # Get forecast
166
+ forecast_data = get_forecast_data(location)
167
+
168
+ # Determine transmission power
169
+ power_level, duration, explanation = determine_transmission_power(
170
+ image_prediction,
171
+ current_weather,
172
+ forecast_data
173
+ )
174
+
175
+ # Format result
176
+ result = [
177
+ f"Current Conditions ({current_weather['timestamp'].strftime('%Y-%m-%d %H:%M')})",
178
+ f"Temperature: {current_weather['temperature']:.1f}°C",
179
+ f"Humidity: {current_weather['humidity']}%",
180
+ f"Visibility: {current_weather['visibility']:.1f} km",
181
+ f"Wind Speed: {current_weather['wind_speed']} m/s",
182
+ "",
183
+ "Analysis Results:",
184
+ *explanation,
185
+ "",
186
+ f"Recommended Power Level: {power_level}",
187
+ f"Duration: {duration.days} days and {duration.hours} hours",
188
+ "",
189
+ "5-Day Forecast Summary:"
190
+ ]
191
+
192
+ # Add daily forecast summary
193
+ current_date = current_weather['timestamp'].date()
194
+ for day in range(5):
195
+ forecast_date = current_date + timedelta(days=day)
196
+ day_forecasts = [f for f in forecast_data if f['timestamp'].date() == forecast_date]
197
+
198
+ if day_forecasts:
199
+ avg_risk = sum(calculate_fog_risk_score(f) for f in day_forecasts) / len(day_forecasts)
200
+ result.append(f"{forecast_date.strftime('%Y-%m-%d')}: "
201
+ f"Fog Risk: {'High' if avg_risk > 0.6 else 'Moderate' if avg_risk > 0.3 else 'Low'} "
202
+ f"({avg_risk:.2f})")
203
+
204
+ return "\n".join(result)
205
+
206
  except Exception as e:
207
  return f"Error: {str(e)}"
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  # Gradio interface
210
  with gr.Blocks() as demo:
211
+ gr.Markdown("# Enhanced Fog Prediction and Transmission Power System")
212
+
213
  with gr.Row():
214
+ image_input = gr.Image(label="Upload Current Conditions Image")
215
  location_input = gr.Textbox(label="Enter Location")
216
+
217
+ predict_button = gr.Button("Analyze and Determine Transmission Power")
218
+ output = gr.Textbox(label="Analysis Results", lines=15)
219
+
220
  predict_button.click(integrated_prediction, inputs=[image_input, location_input], outputs=output)
221
 
222
  demo.launch()