nakas commited on
Commit
fbbf258
·
verified ·
1 Parent(s): dc9373d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -92
app.py CHANGED
@@ -1,167 +1,133 @@
1
  import gradio as gr
2
  import requests
3
  import os
 
4
 
5
  # Your Google Pollen API key should be set as a secret in your Hugging Face Space
6
  API_KEY = os.environ.get("GOOGLE_API_KEY")
7
 
8
- # --- Event Handlers ---
9
-
10
- def handle_map_select(evt: gr.SelectData):
11
- """
12
- This function is triggered when a user clicks on the map.
13
- It returns the selected latitude and longitude.
14
- """
15
- return evt.value["latitude"], evt.value["longitude"]
 
 
 
 
 
 
 
16
 
 
17
  def get_pollen_data(latitude, longitude):
18
  """
19
  Fetches and formats all available pollen data from the Google Pollen API.
 
20
  """
21
  if not API_KEY:
22
- error_message = "Error: GOOGLE_API_KEY not found. Please set it as a secret in your Hugging Face Space."
23
- # Return an error message for all three output tabs
24
- return error_message, error_message, error_message
25
 
26
  if not latitude or not longitude:
27
- # Return a blank message for all three tabs if there's no input
28
- return "", "", ""
29
 
30
  try:
31
  lat = float(latitude)
32
  lon = float(longitude)
33
  except (ValueError, TypeError):
34
  error_message = "Error: Invalid latitude or longitude."
35
- return error_message, error_message, error_message
36
 
37
  endpoint = "https://pollen.googleapis.com/v1/forecast:lookup"
38
- params = {
39
- "key": API_KEY,
40
- "location.latitude": lat,
41
- "location.longitude": lon,
42
- "days": 5,
43
- "languageCode": "en"
44
- }
45
 
46
  try:
47
  response = requests.get(endpoint, params=params)
48
  response.raise_for_status()
49
  data = response.json()
 
50
 
51
  if not data.get('dailyInfo'):
52
- no_data_message = "No pollen data found for this location in the API response."
53
- return no_data_message, no_data_message, no_data_message
54
 
55
- # Initialize strings for each pollen category tab
56
  outputs = {'TREE': "", 'GRASS': "", 'WEED': ""}
57
-
58
  for day_info in data.get('dailyInfo', []):
59
  date = day_info.get('date', {})
60
  date_str = f"{date.get('year', 'N/A')}-{date.get('month', 'N/A'):02d}-{date.get('day', 'N/A'):02d}"
61
 
62
- # Add date header to each category for the current day
63
  for cat in outputs.keys():
64
  outputs[cat] += f"## Date: {date_str}\n"
65
 
66
  pollen_found_for_day = {'TREE': False, 'GRASS': False, 'WEED': False}
67
 
68
- # Process every pollen type returned by the API for the day
69
  for pollen in day_info.get('pollenTypeInfo', []):
70
  plant_type = pollen.get('plantType', 'UNKNOWN')
71
- if plant_type not in outputs:
72
- continue
73
 
74
  pollen_found_for_day[plant_type] = True
75
 
76
  display_name = pollen.get('displayName', 'N/A')
77
- in_season_str = "Yes" if pollen.get('inSeason', False) else "No"
78
-
79
- # Start formatting the detailed output for this pollen type
80
- formatted_pollen_info = f"### {display_name}\n"
81
- formatted_pollen_info += f"- **In Season:** {in_season_str}\n"
82
-
83
- # Extract and display all details from indexInfo
84
  index_info = pollen.get('indexInfo', {})
85
- if index_info:
86
- index_value = index_info.get('value', 'N/A')
87
- category = index_info.get('category', 'N/A')
88
- description = index_info.get('description', '')
89
- color = index_info.get('color', '#FFFFFF')
90
- color_swatch = f'<span style="display: inline-block; width: 15px; height: 15px; background-color: {color}; border: 1px solid #ccc; border-radius: 3px; vertical-align: middle;"></span>'
91
-
92
- formatted_pollen_info += f"- **Index Value:** {index_value}\n"
93
- formatted_pollen_info += f"- **Category:** {color_swatch} {category}\n"
94
- if description:
95
- formatted_pollen_info += f"- **Description:** *{description}*\n"
96
 
97
- # Extract and display all health recommendations
98
- health_recs = pollen.get('healthRecommendations', [])
99
- if health_recs:
100
- formatted_pollen_info += "- **Health Recommendations:**\n"
101
- for rec in health_recs:
102
- formatted_pollen_info += f" - {rec}\n"
103
-
104
- outputs[plant_type] += formatted_pollen_info + "\n---\n" # Add a separator
105
 
106
- # If after checking all pollen types, a category had none, add a message
107
  for p_type, found in pollen_found_for_day.items():
108
  if not found:
109
- outputs[p_type] += "- No specific pollen data was returned for this category on this day.\n\n---\n"
110
 
111
- # Return the final formatted strings for each tab
112
- return outputs['TREE'].strip(), outputs['GRASS'].strip(), outputs['WEED'].strip()
113
 
114
- except requests.exceptions.RequestException as e:
115
- error_message = f"Error connecting to the API: {e}"
116
- return error_message, error_message, error_message
117
  except Exception as e:
118
- error_message = f"An unexpected error occurred: {e}"
119
- return error_message, error_message, error_message
120
 
121
  # --- Gradio Interface ---
122
- with gr.Blocks(theme=gr.themes.Soft(), css="footer {display: none !important}") as demo:
123
- gr.Markdown("# 🤧 Interactive Pollen Forecast Map")
124
- gr.Markdown("Click on the map to select a location, or enter coordinates manually. The pollen forecast for the next 5 days will be displayed below.")
125
 
126
  with gr.Row():
127
- with gr.Column(scale=2):
128
- # Use the native Gradio Map component
129
- map_component = gr.Map(label="Location Map", value={"latitude": 45.6770, "longitude": -111.0429}, interactive=True)
130
-
131
  with gr.Column(scale=1):
132
- lat_input = gr.Textbox(label="Latitude", placeholder="Select on map or enter here")
133
- lon_input = gr.Textbox(label="Longitude", placeholder="Select on map or enter here")
 
134
  gr.Examples(
135
- examples=[
136
- ["40.7128", "-74.0060"], # New York, NY
137
- ["34.0522", "-118.2437"], # Los Angeles,CA
138
- ["51.5074", "-0.1278"], # London, UK
139
- ],
140
  inputs=[lat_input, lon_input],
141
  label="Example Locations"
142
  )
 
 
 
143
 
144
- with gr.Tabs() as data_tabs:
145
  with gr.TabItem("🌳 Tree"):
146
  tree_output = gr.Markdown()
147
  with gr.TabItem("🌱 Grass"):
148
  grass_output = gr.Markdown()
149
  with gr.TabItem("🌿 Weed"):
150
  weed_output = gr.Markdown()
151
-
152
- # --- Event Listeners ---
153
-
154
- # 1. When a user clicks the map, update the latitude and longitude textboxes.
155
- map_component.select(handle_map_select, None, [lat_input, lon_input])
156
-
157
- # 2. When the latitude or longitude textboxes change (either from map click or manual entry),
158
- # automatically call the pollen API.
159
- lat_input.change(get_pollen_data, [lat_input, lon_input], [tree_output, grass_output, weed_output])
160
- lon_input.change(get_pollen_data, [lat_input, lon_input], [tree_output, grass_output, weed_output])
161
-
162
- # 3. When the app loads, get data for the default location.
163
- demo.load(get_pollen_data, [lat_input, lon_input], [tree_output, grass_output, weed_output])
164
 
 
 
 
 
 
 
 
 
 
 
165
 
166
  if __name__ == "__main__":
167
  demo.launch()
 
1
  import gradio as gr
2
  import requests
3
  import os
4
+ import folium
5
 
6
  # Your Google Pollen API key should be set as a secret in your Hugging Face Space
7
  API_KEY = os.environ.get("GOOGLE_API_KEY")
8
 
9
+ # --- Map Function ---
10
+ def create_map_html(latitude, longitude):
11
+ """Creates a Folium map and returns its HTML representation."""
12
+ try:
13
+ lat = float(latitude)
14
+ lon = float(longitude)
15
+ # Create a map centered on the coordinates
16
+ m = folium.Map(location=[lat, lon], zoom_start=12, tiles="OpenStreetMap")
17
+ # Add a marker to the map
18
+ folium.Marker([lat, lon], popup="Selected Location").add_to(m)
19
+ return m._repr_html_()
20
+ except (ValueError, TypeError):
21
+ # Return a default map if inputs are invalid or empty
22
+ m = folium.Map(location=[40.7128, -74.0060], zoom_start=5, tiles="OpenStreetMap")
23
+ return m._repr_html_()
24
 
25
+ # --- API Call Function ---
26
  def get_pollen_data(latitude, longitude):
27
  """
28
  Fetches and formats all available pollen data from the Google Pollen API.
29
+ Also returns an updated map.
30
  """
31
  if not API_KEY:
32
+ error_message = "Error: GOOGLE_API_KEY not found. Please set it as a secret."
33
+ map_html = create_map_html(latitude, longitude)
34
+ return error_message, error_message, error_message, map_html
35
 
36
  if not latitude or not longitude:
37
+ return "", "", "", create_map_html(latitude, longitude)
 
38
 
39
  try:
40
  lat = float(latitude)
41
  lon = float(longitude)
42
  except (ValueError, TypeError):
43
  error_message = "Error: Invalid latitude or longitude."
44
+ return error_message, error_message, error_message, create_map_html(latitude, longitude)
45
 
46
  endpoint = "https://pollen.googleapis.com/v1/forecast:lookup"
47
+ params = {"key": API_KEY, "location.latitude": lat, "location.longitude": lon, "days": 5, "languageCode": "en"}
 
 
 
 
 
 
48
 
49
  try:
50
  response = requests.get(endpoint, params=params)
51
  response.raise_for_status()
52
  data = response.json()
53
+ map_html = create_map_html(latitude, longitude)
54
 
55
  if not data.get('dailyInfo'):
56
+ no_data_message = "No pollen data found for this location."
57
+ return no_data_message, no_data_message, no_data_message, map_html
58
 
 
59
  outputs = {'TREE': "", 'GRASS': "", 'WEED': ""}
 
60
  for day_info in data.get('dailyInfo', []):
61
  date = day_info.get('date', {})
62
  date_str = f"{date.get('year', 'N/A')}-{date.get('month', 'N/A'):02d}-{date.get('day', 'N/A'):02d}"
63
 
 
64
  for cat in outputs.keys():
65
  outputs[cat] += f"## Date: {date_str}\n"
66
 
67
  pollen_found_for_day = {'TREE': False, 'GRASS': False, 'WEED': False}
68
 
 
69
  for pollen in day_info.get('pollenTypeInfo', []):
70
  plant_type = pollen.get('plantType', 'UNKNOWN')
71
+ if plant_type not in outputs: continue
 
72
 
73
  pollen_found_for_day[plant_type] = True
74
 
75
  display_name = pollen.get('displayName', 'N/A')
 
 
 
 
 
 
 
76
  index_info = pollen.get('indexInfo', {})
77
+ category = index_info.get('category', 'N/A')
78
+ color = index_info.get('color', '#FFFFFF')
79
+ color_swatch = f'<span style="display: inline-block; width: 15px; height: 15px; background-color: {color}; border: 1px solid #ccc; vertical-align: middle;"></span>'
 
 
 
 
 
 
 
 
80
 
81
+ formatted_pollen_info = f"### {display_name}\n- **Category:** {color_swatch} {category}\n"
82
+ outputs[plant_type] += formatted_pollen_info + "\n---\n"
 
 
 
 
 
 
83
 
 
84
  for p_type, found in pollen_found_for_day.items():
85
  if not found:
86
+ outputs[p_type] += "- No specific pollen data returned for this category on this day.\n\n---\n"
87
 
88
+ return outputs['TREE'].strip(), outputs['GRASS'].strip(), outputs['WEED'].strip(), map_html
 
89
 
 
 
 
90
  except Exception as e:
91
+ error_message = f"An error occurred: {e}"
92
+ return error_message, error_message, error_message, create_map_html(latitude, longitude)
93
 
94
  # --- Gradio Interface ---
95
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
96
+ gr.Markdown("# 🤧 Pollen Forecast Map")
97
+ gr.Markdown("Enter coordinates and click 'Get Forecast' to see the 5-day pollen forecast and the location on the map.")
98
 
99
  with gr.Row():
 
 
 
 
100
  with gr.Column(scale=1):
101
+ lat_input = gr.Textbox(label="Latitude", value="40.7128")
102
+ lon_input = gr.Textbox(label="Longitude", value="-74.0060")
103
+ submit_button = gr.Button("Get Forecast", variant="primary")
104
  gr.Examples(
105
+ examples=[["34.0522", "-118.2437"], ["51.5074", "-0.1278"]],
 
 
 
 
106
  inputs=[lat_input, lon_input],
107
  label="Example Locations"
108
  )
109
+
110
+ with gr.Column(scale=2):
111
+ map_output = gr.HTML(label="Location Map")
112
 
113
+ with gr.Tabs():
114
  with gr.TabItem("🌳 Tree"):
115
  tree_output = gr.Markdown()
116
  with gr.TabItem("🌱 Grass"):
117
  grass_output = gr.Markdown()
118
  with gr.TabItem("🌿 Weed"):
119
  weed_output = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
+ submit_button.click(
122
+ fn=get_pollen_data,
123
+ inputs=[lat_input, lon_input],
124
+ outputs=[tree_output, grass_output, weed_output, map_output]
125
+ )
126
+ demo.load(
127
+ fn=get_pollen_data,
128
+ inputs=[lat_input, lon_input],
129
+ outputs=[tree_output, grass_output, weed_output, map_output]
130
+ )
131
 
132
  if __name__ == "__main__":
133
  demo.launch()