File size: 5,902 Bytes
77b0eff
 
 
 
187fcd9
1e25fc9
187fcd9
b0b1de3
 
 
 
 
 
 
 
 
 
 
 
187fcd9
 
 
 
b0b1de3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77b0eff
 
 
 
 
187fcd9
 
 
 
b0b1de3
187fcd9
77b0eff
1e25fc9
77b0eff
 
 
b0b1de3
77b0eff
 
 
 
187fcd9
 
77b0eff
 
 
 
 
187fcd9
 
77b0eff
187fcd9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77b0eff
26e237b
77b0eff
26e237b
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
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
@app.callback(
    Output('weather-display', 'children'),
    Input('weather-display', 'id')  # Dummy input to trigger on load
)
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)