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"{city}
"
f"🌡️ Temp: {weather['temperature']}°C
"
f"💨 Wind: {weather['wind_speed']} km/h
"
f"🧭 Dir: {weather['wind_direction']}°
"
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("", unsafe_allow_html=True)
# Footer
st.markdown(
"""