Spaces:
Sleeping
Sleeping
import dash | |
from dash import dcc, html, Input, Output | |
import plotly.graph_objs as go | |
import requests | |
import os | |
from datetime import datetime | |
# Inline weather_model.py with fixes | |
def get_weather_data(city, days, api_key): | |
try: | |
# Fallback to coordinates if city name fails | |
city_coords = { | |
"Hyderabad": {"lat": 17.3850, "lon": 78.4867}, | |
"Gadwal": {"lat": 16.2350, "lon": 77.8050}, | |
"Bengaluru": {"lat": 12.9716, "lon": 77.5946} | |
} | |
coords = city_coords.get(city) | |
if not coords: | |
geo_url = f"http://api.openweathermap.org/geo/1.0/direct?q={city}&limit=1&appid={api_key}" | |
geo_response = requests.get(geo_url).json() | |
if not geo_response: | |
return None | |
coords = {"lat": geo_response[0]['lat'], "lon": geo_response[0]['lon']} | |
url = f"http://api.openweathermap.org/data/2.5/onecall?lat={coords['lat']}&lon={coords['lon']}&exclude=minutely,hourly&units=metric&appid={api_key}" | |
response = requests.get(url, timeout=10).json() | |
current = { | |
'temp': response['current']['temp'], | |
'weather': response['current']['weather'][0]['description'], | |
'humidity': response['current']['humidity'], | |
'wind_speed': response['current']['wind_speed'] | |
} | |
forecast = [] | |
for i in range(min(days, len(response['daily']))): | |
day = response['daily'][i] | |
forecast.append({ | |
'date': datetime.fromtimestamp(day['dt']).strftime('%Y-%m-%d'), | |
'temp': day['temp']['day'], | |
'precipitation': day.get('rain', 0) + day.get('snow', 0), | |
'wind_speed': day['wind_speed'], | |
'weather': day['weather'][0]['main'] | |
}) | |
return {'current': current, 'forecast': forecast} | |
except requests.exceptions.RequestException as e: | |
print(f"Network error for {city}: {e}") | |
return None | |
except KeyError as e: | |
print(f"API response error for {city}: {e}") | |
return None | |
except Exception as e: | |
print(f"Unexpected error for {city}: {e}") | |
return None | |
# Initialize Dash app | |
app = dash.Dash(__name__) | |
app.title = "Weather Forecast Dashboard" | |
# Use environment variable for API key | |
API_KEY = os.getenv("OPENWEATHERMAP_API_KEY", "53d50455f91b6bc3c920959e2954576d") | |
# Fixed locations | |
LOCATIONS = ["Hyderabad", "Gadwal", "Bengaluru"] | |
DAYS = 5 # Fixed 5-day forecast | |
# Layout | |
app.layout = html.Div([ | |
html.Div([ | |
html.H1("Weather Forecast Dashboard", style={'textAlign': 'center', 'color': '#FFFFFF'}), | |
html.P("Current weather for Hyderabad, Gadwal, and Bengaluru (Karnataka).", | |
style={'textAlign': 'center', 'color': '#D3D9D4'}) | |
], style={'backgroundColor': '#212A31', 'padding': '20px'}), | |
html.Div([ | |
html.H2("Weather Overview", style={'color': '#FFFFFF', 'padding': '10px'}), | |
html.Div(id='weather-display', style={'display': 'flex', 'flexWrap': 'wrap', 'justifyContent': 'space-around'}) | |
], style={'backgroundColor': '#2E3944', 'padding': '20px', 'borderRadius': '10px'}), | |
], style={'backgroundColor': '#1A2329', 'fontFamily': 'Arial', 'minHeight': '100vh'}) | |
# Callback to update dashboard | |
def update_dashboard(_): | |
weather_components = [] | |
for city in LOCATIONS: | |
weather_data = get_weather_data(city, DAYS, API_KEY) | |
if not weather_data: | |
weather_components.append( | |
html.Div(f"Error: Could not fetch data for {city}", style={'color': '#FF5555', 'padding': '10px'}) | |
) | |
continue | |
current = weather_data['current'] | |
forecast = weather_data['forecast'] | |
# Text Summary | |
summary = html.Div([ | |
html.H3(f"{city}", style={'color': '#FFFFFF'}), | |
html.P(f"Current Temp: {current['temp']}°C", style={'color': '#D3D9D4'}), | |
html.P(f"Condition: {current['weather']}", style={'color': '#D3D9D4'}), | |
html.P(f"Humidity: {current['humidity']}%", style={'color': '#D3D9D4'}), | |
html.P(f"Wind Speed: {current['wind_speed']} km/h", style={'color': '#D3D9D4'}), | |
], style={'width': '30%', 'padding': '10px'}) | |
# Donut Charts | |
temp_values = [f['temp'] for f in forecast] | |
temp_fig = go.Figure(data=[go.Pie(labels=[f['date'] for f in forecast], values=temp_values, hole=.3)]) | |
temp_fig.update_layout(title=f"{city} - Temperature (°C)", template='plotly_dark') | |
precip_values = [f['precipitation'] for f in forecast] | |
precip_fig = go.Figure(data=[go.Pie(labels=[f['date'] for f in forecast], values=precip_values, hole=.3)]) | |
precip_fig.update_layout(title=f"{city} - Precipitation (mm)", template='plotly_dark') | |
wind_values = [f['wind_speed'] for f in forecast] | |
wind_fig = go.Figure(data=[go.Pie(labels=[f['date'] for f in forecast], values=wind_values, hole=.3)]) | |
wind_fig.update_layout(title=f"{city} - Wind Speed (km/h)", template='plotly_dark') | |
# Combine into a city section | |
city_section = html.Div([ | |
summary, | |
dcc.Graph(figure=temp_fig, style={'width': '20%', 'display': 'inline-block'}), | |
dcc.Graph(figure=precip_fig, style={'width': '20%', 'display': 'inline-block'}), | |
dcc.Graph(figure=wind_fig, style={'width': '20%', 'display': 'inline-block'}), | |
], style={'margin': '20px', 'backgroundColor': '#2E3944', 'borderRadius': '10px', 'padding': '10px'}) | |
weather_components.append(city_section) | |
return weather_components | |
# Run server on port 7860 for Hugging Face Spaces | |
if __name__ == '__main__': | |
app.run_server(debug=True, host='0.0.0.0', port=7860) |