import gradio as gr import requests import pandas as pd import folium from folium import plugins import json from datetime import datetime, timedelta import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots class AirQualityMonitor: def __init__(self): self.base_url = "https://www.airnowapi.org/aq" # You'll need to get an API key from https://docs.airnowapi.org/ self.api_key = "YOUR_API_KEY_HERE" # Replace with actual API key def get_current_observations(self, state_code=None, bbox=None): """Get current air quality observations""" if not self.api_key or self.api_key == "YOUR_API_KEY_HERE": # Return sample data for demo purposes return self._get_sample_data() url = f"{self.base_url}/observation/zipCode/current/" params = { 'format': 'application/json', 'API_KEY': self.api_key, 'distance': 100 } if state_code: # Get observations for a specific state params['zipCode'] = self._get_state_zip(state_code) try: response = requests.get(url, params=params) response.raise_for_status() return response.json() except Exception as e: print(f"API Error: {e}") return self._get_sample_data() def _get_state_zip(self, state_code): """Get a representative zip code for a state""" state_zips = { 'CA': '90210', 'NY': '10001', 'TX': '73301', 'FL': '33101', 'IL': '60601', 'PA': '19101', 'OH': '43215', 'GA': '30301', 'NC': '27601', 'MI': '48201', 'NJ': '07001', 'VA': '23219', 'WA': '98101', 'AZ': '85001', 'MA': '02101', 'TN': '37201', 'IN': '46201', 'MO': '63101', 'MD': '21201', 'WI': '53201' } return state_zips.get(state_code, '90210') def _get_sample_data(self): """Return sample data for demonstration""" return [ { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "PST", "ReportingArea": "Los Angeles-South Coast Air Basin", "StateCode": "CA", "Latitude": 34.0522, "Longitude": -118.2437, "ParameterName": "PM2.5", "AQI": 65, "Category": {"Number": 2, "Name": "Moderate"} }, { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "EST", "ReportingArea": "New York", "StateCode": "NY", "Latitude": 40.7128, "Longitude": -74.0060, "ParameterName": "Ozone", "AQI": 45, "Category": {"Number": 1, "Name": "Good"} }, { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "CST", "ReportingArea": "Chicago", "StateCode": "IL", "Latitude": 41.8781, "Longitude": -87.6298, "ParameterName": "PM2.5", "AQI": 85, "Category": {"Number": 3, "Name": "Unhealthy for Sensitive Groups"} }, { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "MST", "ReportingArea": "Phoenix", "StateCode": "AZ", "Latitude": 33.4484, "Longitude": -112.0740, "ParameterName": "Ozone", "AQI": 95, "Category": {"Number": 3, "Name": "Unhealthy for Sensitive Groups"} }, { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "PST", "ReportingArea": "Seattle", "StateCode": "WA", "Latitude": 47.6062, "Longitude": -122.3321, "ParameterName": "PM2.5", "AQI": 25, "Category": {"Number": 1, "Name": "Good"} }, { "DateObserved": "2025-06-29", "HourObserved": 14, "LocalTimeZone": "EST", "ReportingArea": "Miami", "StateCode": "FL", "Latitude": 25.7617, "Longitude": -80.1918, "ParameterName": "Ozone", "AQI": 55, "Category": {"Number": 2, "Name": "Moderate"} } ] def get_aqi_color(aqi): """Return color based on AQI value""" if aqi <= 50: return "#00E400" # Green elif aqi <= 100: return "#FFFF00" # Yellow elif aqi <= 150: return "#FF7E00" # Orange elif aqi <= 200: return "#FF0000" # Red elif aqi <= 300: return "#8F3F97" # Purple else: return "#7E0023" # Maroon def create_air_quality_map(data): """Create an interactive map with air quality data""" if not data: # Create empty map centered on US m = folium.Map(location=[39.8283, -98.5795], zoom_start=4) folium.Marker( [39.8283, -98.5795], popup="No data available. Please add your AirNow API key.", icon=folium.Icon(color='red') ).add_to(m) return m._repr_html_() # Calculate map center lats = [float(station['Latitude']) for station in data] lons = [float(station['Longitude']) for station in data] center_lat = sum(lats) / len(lats) center_lon = sum(lons) / len(lons) # Create map m = folium.Map(location=[center_lat, center_lon], zoom_start=4) # Add markers for each monitoring station for station in data: lat = float(station['Latitude']) lon = float(station['Longitude']) aqi = station.get('AQI', 0) parameter = station.get('ParameterName', 'Unknown') area = station.get('ReportingArea', 'Unknown Area') category = station.get('Category', {}).get('Name', 'Unknown') color = get_aqi_color(aqi) popup_html = f"""
AQI: {aqi}
Parameter: {parameter}
Category: {category}
Date: {station.get('DateObserved', 'N/A')}
Time: {station.get('HourObserved', 'N/A')}:00 {station.get('LocalTimeZone', '')}
Good (0-50)
Moderate (51-100)
Unhealthy for Sensitive (101-150)
Unhealthy (151-200)
Very Unhealthy (201-300)