nakas commited on
Commit
10e1f78
Β·
verified Β·
1 Parent(s): 4343d23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -41
app.py CHANGED
@@ -96,7 +96,7 @@ def get_pollen_data(lat, lon, days=5):
96
  return f"Unexpected error: {str(e)}"
97
 
98
  def format_pollen_data(data):
99
- """Format pollen data for display"""
100
  if isinstance(data, str): # Error message
101
  return data, None
102
 
@@ -110,7 +110,16 @@ def format_pollen_data(data):
110
  # Location info if available
111
  if "regionInfo" in data:
112
  region = data["regionInfo"]
113
- output.append(f"**Location:** {region.get('displayName', 'Unknown')}\n")
 
 
 
 
 
 
 
 
 
114
 
115
  # Daily pollen data
116
  daily_data = []
@@ -139,43 +148,80 @@ def format_pollen_data(data):
139
  date_obj = datetime.now()
140
 
141
  formatted_date = date_obj.strftime("%B %d, %Y")
 
142
 
143
- output.append(f"## πŸ“… {formatted_date}\n")
144
 
145
  if "pollenTypeInfo" in day_info:
146
  pollen_types = day_info["pollenTypeInfo"]
147
 
148
  # Create a row for the dataframe
149
- row_data = {"Date": formatted_date}
 
 
 
 
150
 
151
  for pollen in pollen_types:
152
  pollen_type = pollen["code"].replace("_", " ").title()
153
  index_info = pollen.get("indexInfo", {})
154
- index_value = index_info.get("value", "N/A")
155
  category = index_info.get("category", "Unknown")
156
 
157
- # Add color coding based on category
158
- color_map = {
159
- "VERY_LOW": "🟒",
160
- "LOW": "🟑",
161
- "MEDIUM": "🟠",
162
- "HIGH": "πŸ”΄",
163
- "VERY_HIGH": "🟣"
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  }
165
- color = color_map.get(category, "βšͺ")
166
 
167
- output.append(f"**{pollen_type}:** {color} {category} (Index: {index_value})")
168
- row_data[pollen_type] = f"{category} ({index_value})"
 
 
 
 
 
169
 
170
  # Add plant descriptions if available
171
  if "plantDescription" in pollen:
172
  plants = pollen["plantDescription"]
173
  if "plants" in plants:
174
  plant_list = [plant["displayName"] for plant in plants["plants"][:3]] # Show top 3
175
- output.append(f" - *Main sources: {', '.join(plant_list)}*")
176
 
177
  output.append("")
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  daily_data.append(row_data)
180
 
181
  output.append("---\n")
@@ -185,16 +231,28 @@ def format_pollen_data(data):
185
  if daily_data:
186
  df = pd.DataFrame(daily_data)
187
 
188
- # Add legend
189
- output.append("\n## πŸ“Š Pollen Index Legend")
190
- output.append("🟒 Very Low | 🟑 Low | 🟠 Medium | πŸ”΄ High | 🟣 Very High\n")
 
 
 
 
 
 
 
 
 
191
 
192
- # Add tips
193
- output.append("## πŸ’‘ Tips")
194
- output.append("- Check pollen levels before outdoor activities")
195
- output.append("- Take allergy medications during high pollen days")
196
- output.append("- Keep windows closed during peak pollen times")
197
- output.append("- Shower and change clothes after being outdoors")
 
 
 
198
 
199
  return "\n".join(output), df
200
 
@@ -217,7 +275,8 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
217
  gr.HTML("""
218
  <div style="text-align: center; padding: 20px;">
219
  <h1>🌸 Pollen Forecast Map</h1>
220
- <p>Click on the map to select a location and get detailed pollen forecasts powered by Google Pollen API</p>
 
221
  </div>
222
  """)
223
 
@@ -225,35 +284,56 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
225
  with gr.Column(scale=1):
226
  gr.HTML("<h3>πŸ“ Location Selection</h3>")
227
 
 
 
 
 
 
 
 
 
 
 
228
  # Coordinate inputs
229
  lat_input = gr.Number(
230
  label="Latitude",
231
  value=40.7128,
232
  precision=6,
233
- info="Enter latitude or click on map"
234
  )
235
  lon_input = gr.Number(
236
  label="Longitude",
237
  value=-74.0060,
238
  precision=6,
239
- info="Enter longitude or click on map"
240
  )
241
 
242
- update_btn = gr.Button("πŸ”„ Update Location", variant="primary")
243
 
244
  # Preset locations
245
- gr.HTML("<h4>πŸ“ Quick Locations</h4>")
 
 
 
246
  with gr.Row():
247
- nyc_btn = gr.Button("πŸ™οΈ NYC", size="sm")
248
- la_btn = gr.Button("🌴 LA", size="sm")
249
  chicago_btn = gr.Button("🌬️ Chicago", size="sm")
250
  miami_btn = gr.Button("πŸ–οΈ Miami", size="sm")
 
 
 
251
 
252
  with gr.Column(scale=2):
253
  # Map display
254
  map_html = gr.HTML(
255
  value=create_map(),
256
- label="Interactive Map"
 
 
 
 
 
 
 
257
  )
258
 
259
  with gr.Row():
@@ -271,19 +351,46 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
271
  )
272
 
273
  # Event handlers
 
 
 
 
 
 
 
 
 
 
 
274
  def set_nyc():
275
- return 40.7128, -74.0060
276
 
277
  def set_la():
278
- return 34.0522, -118.2437
279
 
280
  def set_chicago():
281
- return 41.8781, -87.6298
282
 
283
  def set_miami():
284
- return 25.7617, -80.1918
 
 
 
 
 
 
285
 
286
  # Button events
 
 
 
 
 
 
 
 
 
 
287
  update_btn.click(
288
  fn=update_location,
289
  inputs=[lat_input, lon_input],
@@ -292,7 +399,7 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
292
 
293
  nyc_btn.click(
294
  fn=set_nyc,
295
- outputs=[lat_input, lon_input]
296
  ).then(
297
  fn=update_location,
298
  inputs=[lat_input, lon_input],
@@ -301,7 +408,7 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
301
 
302
  la_btn.click(
303
  fn=set_la,
304
- outputs=[lat_input, lon_input]
305
  ).then(
306
  fn=update_location,
307
  inputs=[lat_input, lon_input],
@@ -310,7 +417,7 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
310
 
311
  chicago_btn.click(
312
  fn=set_chicago,
313
- outputs=[lat_input, lon_input]
314
  ).then(
315
  fn=update_location,
316
  inputs=[lat_input, lon_input],
@@ -319,7 +426,25 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
319
 
320
  miami_btn.click(
321
  fn=set_miami,
322
- outputs=[lat_input, lon_input]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  ).then(
324
  fn=update_location,
325
  inputs=[lat_input, lon_input],
@@ -341,6 +466,9 @@ with gr.Blocks(title="🌸 Pollen Forecast Map", theme=gr.themes.Soft()) as app:
341
 
342
  # Load initial data
343
  app.load(
 
 
 
344
  fn=update_location,
345
  inputs=[lat_input, lon_input],
346
  outputs=[map_html, pollen_output, pollen_table]
 
96
  return f"Unexpected error: {str(e)}"
97
 
98
  def format_pollen_data(data):
99
+ """Format pollen data for display in user-friendly terms"""
100
  if isinstance(data, str): # Error message
101
  return data, None
102
 
 
110
  # Location info if available
111
  if "regionInfo" in data:
112
  region = data["regionInfo"]
113
+ output.append(f"**πŸ“ Location:** {region.get('displayName', 'Unknown')}\n")
114
+
115
+ # Add explanation of what pollen index means
116
+ output.append("## πŸ“Š Understanding Your Pollen Forecast\n")
117
+ output.append("**The Pollen Index** measures pollen concentration in the air:")
118
+ output.append("- **0-2:** Very Low - Most people won't have symptoms")
119
+ output.append("- **3-5:** Low - Few people with severe allergies may have mild symptoms")
120
+ output.append("- **6-7:** Medium - People with allergies will likely have symptoms")
121
+ output.append("- **8-9:** High - Most people with allergies will have symptoms")
122
+ output.append("- **10+:** Very High - Everyone with allergies will have severe symptoms\n")
123
 
124
  # Daily pollen data
125
  daily_data = []
 
148
  date_obj = datetime.now()
149
 
150
  formatted_date = date_obj.strftime("%B %d, %Y")
151
+ day_of_week = date_obj.strftime("%A")
152
 
153
+ output.append(f"## πŸ“… {day_of_week}, {formatted_date}\n")
154
 
155
  if "pollenTypeInfo" in day_info:
156
  pollen_types = day_info["pollenTypeInfo"]
157
 
158
  # Create a row for the dataframe
159
+ row_data = {"Date": f"{day_of_week}, {formatted_date}"}
160
+
161
+ # Calculate overall day severity
162
+ max_index = 0
163
+ total_types = 0
164
 
165
  for pollen in pollen_types:
166
  pollen_type = pollen["code"].replace("_", " ").title()
167
  index_info = pollen.get("indexInfo", {})
168
+ index_value = index_info.get("value", 0)
169
  category = index_info.get("category", "Unknown")
170
 
171
+ if isinstance(index_value, (int, float)) and index_value > max_index:
172
+ max_index = index_value
173
+ total_types += 1
174
+
175
+ # Convert technical terms to user-friendly descriptions
176
+ severity_map = {
177
+ "VERY_LOW": {"emoji": "🟒", "description": "Excellent", "advice": "Great day to be outdoors!"},
178
+ "LOW": {"emoji": "🟑", "description": "Good", "advice": "Most people will be fine outdoors"},
179
+ "MEDIUM": {"emoji": "🟠", "description": "Moderate", "advice": "Consider taking allergy medication"},
180
+ "HIGH": {"emoji": "πŸ”΄", "description": "Poor", "advice": "Limit outdoor activities if allergic"},
181
+ "VERY_HIGH": {"emoji": "🟣", "description": "Very Poor", "advice": "Stay indoors if possible"}
182
+ }
183
+
184
+ severity = severity_map.get(category, {"emoji": "βšͺ", "description": "Unknown", "advice": "Monitor symptoms"})
185
+
186
+ # More specific pollen type descriptions
187
+ pollen_descriptions = {
188
+ "Tree": "🌳 Tree pollen (oak, birch, cedar, etc.)",
189
+ "Grass": "🌱 Grass pollen (timothy, bermuda, etc.)",
190
+ "Weed": "🌿 Weed pollen (ragweed, sagebrush, etc.)"
191
  }
 
192
 
193
+ pollen_desc = pollen_descriptions.get(pollen_type, f"🌸 {pollen_type}")
194
+
195
+ output.append(f"### {pollen_desc}")
196
+ output.append(f"**Level:** {severity['emoji']} {severity['description']} (Index: {index_value}/10)")
197
+ output.append(f"**What this means:** {severity['advice']}")
198
+
199
+ row_data[pollen_type] = f"{severity['description']} ({index_value})"
200
 
201
  # Add plant descriptions if available
202
  if "plantDescription" in pollen:
203
  plants = pollen["plantDescription"]
204
  if "plants" in plants:
205
  plant_list = [plant["displayName"] for plant in plants["plants"][:3]] # Show top 3
206
+ output.append(f"**Main sources:** {', '.join(plant_list)}")
207
 
208
  output.append("")
209
 
210
+ # Add overall day assessment
211
+ if max_index > 0:
212
+ if max_index <= 2:
213
+ day_rating = "🟒 **Excellent day** for outdoor activities!"
214
+ elif max_index <= 5:
215
+ day_rating = "🟑 **Good day** - most people will be comfortable outside"
216
+ elif max_index <= 7:
217
+ day_rating = "🟠 **Moderate day** - allergy sufferers should prepare"
218
+ elif max_index <= 9:
219
+ day_rating = "πŸ”΄ **Challenging day** - limit outdoor exposure if allergic"
220
+ else:
221
+ day_rating = "🟣 **Very difficult day** - stay indoors if you have allergies"
222
+
223
+ output.append(f"**Overall Assessment:** {day_rating}\n")
224
+
225
  daily_data.append(row_data)
226
 
227
  output.append("---\n")
 
231
  if daily_data:
232
  df = pd.DataFrame(daily_data)
233
 
234
+ # Add comprehensive advice section
235
+ output.append("\n## πŸ’‘ Practical Tips for Pollen Season")
236
+ output.append("### 🏠 **Indoor Protection:**")
237
+ output.append("- Keep windows and doors closed during high pollen days")
238
+ output.append("- Use air conditioning with clean HEPA filters")
239
+ output.append("- Consider an air purifier for your bedroom")
240
+
241
+ output.append("\n### 🚢 **When Going Outside:**")
242
+ output.append("- Check this forecast before planning outdoor activities")
243
+ output.append("- Wear wraparound sunglasses to protect your eyes")
244
+ output.append("- Consider wearing a mask during very high pollen days")
245
+ output.append("- Plan outdoor activities for late evening when pollen counts are lower")
246
 
247
+ output.append("\n### 🚿 **After Being Outdoors:**")
248
+ output.append("- Shower and change clothes to remove pollen")
249
+ output.append("- Wash your hair before bed to avoid pollen on your pillow")
250
+ output.append("- Keep pets indoors or wipe them down after walks")
251
+
252
+ output.append("\n### πŸ’Š **Medication Timing:**")
253
+ output.append("- Start allergy medications BEFORE symptoms begin")
254
+ output.append("- Take antihistamines in the evening for next-day protection")
255
+ output.append("- Consult your doctor about prescription options for severe allergies")
256
 
257
  return "\n".join(output), df
258
 
 
275
  gr.HTML("""
276
  <div style="text-align: center; padding: 20px;">
277
  <h1>🌸 Pollen Forecast Map</h1>
278
+ <p>Get detailed, easy-to-understand pollen forecasts for any location worldwide!</p>
279
+ <p><strong>πŸ’‘ How to use:</strong> Search by address, use preset cities, or enter coordinates manually</p>
280
  </div>
281
  """)
282
 
 
284
  with gr.Column(scale=1):
285
  gr.HTML("<h3>πŸ“ Location Selection</h3>")
286
 
287
+ # Address search
288
+ gr.HTML("<h4>πŸ” Search by Address</h4>")
289
+ address_input = gr.Textbox(
290
+ label="Enter Address or City",
291
+ placeholder="e.g., Central Park, New York or Paris, France",
292
+ info="Enter any address, city, or landmark"
293
+ )
294
+ search_btn = gr.Button("πŸ” Search Address", variant="primary")
295
+
296
+ gr.HTML("<h4>πŸ“ Or Use Coordinates</h4>")
297
  # Coordinate inputs
298
  lat_input = gr.Number(
299
  label="Latitude",
300
  value=40.7128,
301
  precision=6,
302
+ info="Enter latitude (-90 to 90)"
303
  )
304
  lon_input = gr.Number(
305
  label="Longitude",
306
  value=-74.0060,
307
  precision=6,
308
+ info="Enter longitude (-180 to 180)"
309
  )
310
 
311
+ update_btn = gr.Button("πŸ”„ Update Location", variant="secondary")
312
 
313
  # Preset locations
314
+ gr.HTML("<h4>πŸ™οΈ Popular Cities</h4>")
315
+ with gr.Row():
316
+ nyc_btn = gr.Button("πŸ—½ New York", size="sm")
317
+ la_btn = gr.Button("🌴 Los Angeles", size="sm")
318
  with gr.Row():
 
 
319
  chicago_btn = gr.Button("🌬️ Chicago", size="sm")
320
  miami_btn = gr.Button("πŸ–οΈ Miami", size="sm")
321
+ with gr.Row():
322
+ london_btn = gr.Button("πŸ‡¬πŸ‡§ London", size="sm")
323
+ tokyo_btn = gr.Button("πŸ‡―πŸ‡΅ Tokyo", size="sm")
324
 
325
  with gr.Column(scale=2):
326
  # Map display
327
  map_html = gr.HTML(
328
  value=create_map(),
329
+ label="πŸ“ Current Location"
330
+ )
331
+
332
+ # Location info display
333
+ location_info = gr.Textbox(
334
+ label="πŸ“ Selected Location",
335
+ value="New York City, NY, USA",
336
+ interactive=False
337
  )
338
 
339
  with gr.Row():
 
351
  )
352
 
353
  # Event handlers
354
+ def search_address(address):
355
+ """Search for address and return coordinates"""
356
+ if not address.strip():
357
+ return 40.7128, -74.0060, "Please enter an address to search"
358
+
359
+ lat, lon, display_name = geocode_address(address)
360
+ if lat is not None and lon is not None:
361
+ return lat, lon, display_name
362
+ else:
363
+ return 40.7128, -74.0060, display_name # display_name contains error message
364
+
365
  def set_nyc():
366
+ return 40.7128, -74.0060, "New York City, NY, USA"
367
 
368
  def set_la():
369
+ return 34.0522, -118.2437, "Los Angeles, CA, USA"
370
 
371
  def set_chicago():
372
+ return 41.8781, -87.6298, "Chicago, IL, USA"
373
 
374
  def set_miami():
375
+ return 25.7617, -80.1918, "Miami, FL, USA"
376
+
377
+ def set_london():
378
+ return 51.5074, -0.1278, "London, England, UK"
379
+
380
+ def set_tokyo():
381
+ return 35.6762, 139.6503, "Tokyo, Japan"
382
 
383
  # Button events
384
+ search_btn.click(
385
+ fn=search_address,
386
+ inputs=[address_input],
387
+ outputs=[lat_input, lon_input, location_info]
388
+ ).then(
389
+ fn=update_location,
390
+ inputs=[lat_input, lon_input],
391
+ outputs=[map_html, pollen_output, pollen_table]
392
+ )
393
+
394
  update_btn.click(
395
  fn=update_location,
396
  inputs=[lat_input, lon_input],
 
399
 
400
  nyc_btn.click(
401
  fn=set_nyc,
402
+ outputs=[lat_input, lon_input, location_info]
403
  ).then(
404
  fn=update_location,
405
  inputs=[lat_input, lon_input],
 
408
 
409
  la_btn.click(
410
  fn=set_la,
411
+ outputs=[lat_input, lon_input, location_info]
412
  ).then(
413
  fn=update_location,
414
  inputs=[lat_input, lon_input],
 
417
 
418
  chicago_btn.click(
419
  fn=set_chicago,
420
+ outputs=[lat_input, lon_input, location_info]
421
  ).then(
422
  fn=update_location,
423
  inputs=[lat_input, lon_input],
 
426
 
427
  miami_btn.click(
428
  fn=set_miami,
429
+ outputs=[lat_input, lon_input, location_info]
430
+ ).then(
431
+ fn=update_location,
432
+ inputs=[lat_input, lon_input],
433
+ outputs=[map_html, pollen_output, pollen_table]
434
+ )
435
+
436
+ london_btn.click(
437
+ fn=set_london,
438
+ outputs=[lat_input, lon_input, location_info]
439
+ ).then(
440
+ fn=update_location,
441
+ inputs=[lat_input, lon_input],
442
+ outputs=[map_html, pollen_output, pollen_table]
443
+ )
444
+
445
+ tokyo_btn.click(
446
+ fn=set_tokyo,
447
+ outputs=[lat_input, lon_input, location_info]
448
  ).then(
449
  fn=update_location,
450
  inputs=[lat_input, lon_input],
 
466
 
467
  # Load initial data
468
  app.load(
469
+ fn=lambda: (40.7128, -74.0060, "New York City, NY, USA"),
470
+ outputs=[lat_input, lon_input, location_info]
471
+ ).then(
472
  fn=update_location,
473
  inputs=[lat_input, lon_input],
474
  outputs=[map_html, pollen_output, pollen_table]