Spaces:
Sleeping
Sleeping
import streamlit as st | |
import requests | |
from geopy.distance import great_circle | |
import folium | |
from streamlit_folium import st_folium | |
from datetime import datetime | |
def format_datetime(iso_string): | |
# Convert ISO 8601 string to datetime object | |
dt_object = datetime.fromisoformat(iso_string) | |
# Format as DD-MM-YYYY and 24-hour time | |
return dt_object.strftime("%d-%m-%Y %H:%M") | |
# Expanded list of Indian cities with their latitude and longitude | |
cities = { | |
"Visakhapatnam": (17.6868, 83.2185), | |
"Delhi": (28.6139, 77.2090), | |
"Mumbai": (19.0760, 72.8777), | |
"Bangalore": (12.9716, 77.5946), | |
"Chennai": (13.0827, 80.2707), | |
"Kolkata": (22.5726, 88.3639), | |
"Hyderabad": (17.3850, 78.4867), | |
"Pune": (18.5204, 73.8567), | |
"Jaipur": (26.9124, 75.7873), | |
"Ahmedabad": (23.0225, 72.5714), | |
"Surat": (21.1702, 72.8311), | |
"Lucknow": (26.8467, 80.9462), | |
"Kanpur": (26.4499, 80.3319), | |
"Nagpur": (21.1458, 79.0882), | |
"Indore": (22.7196, 75.8577), | |
"Bhopal": (23.2599, 77.4126), | |
"Patna": (25.5941, 85.1376), | |
"Vadodara": (22.3072, 73.1812), | |
"Ludhiana": (30.9010, 75.8573), | |
"Agra": (27.1767, 78.0081), | |
"Nashik": (19.9975, 73.7898), | |
"Faridabad": (28.4089, 77.3178), | |
"Meerut": (28.9845, 77.7064), | |
"Rajkot": (22.3039, 70.8022), | |
"Varanasi": (25.3176, 82.9739), | |
"Srinagar": (34.0837, 74.7973), | |
"Amritsar": (31.6340, 74.8723), | |
"Navi Mumbai": (19.0330, 73.0297), | |
"Allahabad": (25.4358, 81.8463), | |
"Ranchi": (23.3441, 85.3096), | |
"Coimbatore": (11.0168, 76.9558), | |
"Jabalpur": (23.1815, 79.9864), | |
"Gwalior": (26.2183, 78.1828), | |
"Vijayawada": (16.5062, 80.6480), | |
"Jodhpur": (26.2389, 73.0243), | |
"Madurai": (9.9252, 78.1198), | |
"Raipur": (21.2514, 81.6296), | |
"Kota": (25.2138, 75.8648), | |
"Guwahati": (26.1445, 91.7362), | |
"Chandigarh": (30.7333, 76.7794), | |
"Solapur": (17.6599, 75.9064) | |
} | |
def get_weather(lat, lon): | |
# Using Open-Meteo API | |
url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true" | |
response = requests.get(url) | |
if response.status_code == 200: | |
data = response.json() | |
current_weather = data['current_weather'] | |
weather = { | |
'temperature': current_weather['temperature'], | |
'wind_speed': current_weather['windspeed'], | |
'wind_direction': current_weather['winddirection'], | |
'time': current_weather['time'] | |
} | |
return weather | |
else: | |
return None | |
def find_nearest_city(lat, lon): | |
min_distance = float('inf') | |
nearest_city = None | |
for city, (city_lat, city_lon) in cities.items(): | |
distance = great_circle((lat, lon), (city_lat, city_lon)).kilometers | |
if distance < min_distance: | |
min_distance = distance | |
nearest_city = city | |
return nearest_city | |
# Streamlit Layout | |
st.set_page_config(page_title="Indian Cities Weather", layout="wide") | |
st.title("🌤️ Indian Cities Weather App") | |
# Dropdown Menu | |
st.sidebar.subheader("Select a City") | |
selected_city = st.sidebar.selectbox("Choose a city:", list(cities.keys())) | |
# Show weather for selected city | |
if selected_city: | |
lat, lon = cities[selected_city] | |
weather = get_weather(lat, lon) | |
if weather: | |
st.markdown(f"### Weather in {selected_city}") | |
st.markdown(f"- 🌡️ Temperature: **{weather['temperature']}°C**") | |
st.markdown(f"- 💨 Wind Speed: **{weather['wind_speed']} km/h**") | |
st.markdown(f"- 🧭 Wind Direction: **{weather['wind_direction']}°**") | |
formatted_time = format_datetime(weather['time']) | |
st.markdown(f"- 🕒 Reported at: **{formatted_time}**") | |
# Interactive Map with Clickable Markers | |
st.subheader("📍 Click on the Map or Select a City to Get Weather Information") | |
# Create a map with OpenStreetMap tiles for better compatibility | |
m = folium.Map(location=[22.9734, 78.6569], zoom_start=5, tiles='OpenStreetMap', | |
attr='Map data © OpenStreetMap contributors') | |
# Add markers with popups for each city | |
for city, (lat, lon) in cities.items(): | |
weather = get_weather(lat, lon) | |
if weather: | |
popup_text = (f"<b>{city}</b><br>" | |
f"🌡️ Temp: {weather['temperature']}°C<br>" | |
f"💨 Wind: {weather['wind_speed']} km/h<br>" | |
f"🧭 Dir: {weather['wind_direction']}°<br>" | |
f"🕒 Time: {weather['time']}") | |
folium.Marker( | |
[lat, lon], | |
popup=folium.Popup(popup_text, max_width=250), | |
tooltip=city, | |
icon=folium.Icon(color='blue', icon='info-sign') | |
).add_to(m) | |
# Display map in Streamlit | |
clicked_location = st_folium(m, width=800, height=600) | |
# Get weather of nearest city when clicking on map | |
if clicked_location and clicked_location['last_clicked']: | |
lat = clicked_location['last_clicked']['lat'] | |
lon = clicked_location['last_clicked']['lng'] | |
nearest_city = find_nearest_city(lat, lon) | |
if nearest_city: | |
st.markdown(f"### Nearest City: **{nearest_city}**") | |
nearest_lat, nearest_lon = cities[nearest_city] | |
weather = get_weather(nearest_lat, nearest_lon) | |
if weather: | |
st.markdown(f"- 🌡️ Temperature: **{weather['temperature']}°C**") | |
st.markdown(f"- 💨 Wind Speed: **{weather['wind_speed']} km/h**") | |
st.markdown(f"- 🧭 Wind Direction: **{weather['wind_direction']}°**") | |
st.markdown(f"- 🕒 Reported at: **{weather['time']}**") | |
st.markdown("<style>body {background-color: #F0F8FF;}</style>", unsafe_allow_html=True) | |
# Footer | |
st.markdown( | |
""" | |
<div class="footer"> | |
Developed by <b>SKB</b> | © 2025. All Rights Reserved | |
</div> | |
""", | |
unsafe_allow_html=True, | |
) | |