bitsofchris Claude Opus 4.7 (1M context) commited on
Commit
6fd1ae5
Β·
1 Parent(s): 8949df4

Move weekly forecast above the comparison table; timestamps into hero

Browse files

- Lead with the forecast itself: hero β†’ weekly chart β†’ 24h same-hour
table β†’ radar β†’ scoreboard β†’ accordions. The reader sees the live
forecast first, then the side-by-side detail.
- Hero table grows a 'When' column: each row carries its own timestamp
('2:02 PM EDT, Mon May 11' for Ecowitt, '2 PM EDT, Mon May 11' for
the NWS hour). Drops the standalone 'Last Ecowitt reading…' caption
since the same info is now in the table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +2 -3
  2. src/weather_ui.py +9 -15
app.py CHANGED
@@ -429,6 +429,8 @@ with gr.Blocks(title="Toto Weather Forecast", theme=gr.themes.Soft()) as demo:
429
  gr.Markdown(SUBTITLE)
430
 
431
  hero_md = gr.Markdown()
 
 
432
  comparison_md = gr.Markdown()
433
  gr.HTML(
434
  # KOKX is the NWS radar site at Upton, NY β€” covers Long Island incl.
@@ -450,9 +452,6 @@ with gr.Blocks(title="Toto Weather Forecast", theme=gr.themes.Soft()) as demo:
450
  "<span style='opacity:0.55'>πŸ”„ Live data + forecast auto-refresh every 15 minutes.</span>"
451
  )
452
 
453
- gr.Markdown(f"### πŸ“… {VIEW_WEEK['label']}")
454
- week_plot = gr.Plot(label="Weekly")
455
-
456
  gr.Markdown("### πŸ† How has each model done so far?")
457
  scoreboard_md = gr.Markdown()
458
  residual_plot = gr.Plot(label="Forecast residual")
 
429
  gr.Markdown(SUBTITLE)
430
 
431
  hero_md = gr.Markdown()
432
+ gr.Markdown(f"### πŸ“… {VIEW_WEEK['label']}")
433
+ week_plot = gr.Plot(label="Weekly")
434
  comparison_md = gr.Markdown()
435
  gr.HTML(
436
  # KOKX is the NWS radar site at Upton, NY β€” covers Long Island incl.
 
452
  "<span style='opacity:0.55'>πŸ”„ Live data + forecast auto-refresh every 15 minutes.</span>"
453
  )
454
 
 
 
 
455
  gr.Markdown("### πŸ† How has each model done so far?")
456
  scoreboard_md = gr.Markdown()
457
  residual_plot = gr.Plot(label="Forecast residual")
src/weather_ui.py CHANGED
@@ -85,17 +85,16 @@ def hero_markdown(
85
  if cur_temp is None or when_ts is None:
86
  return "_(no current readings yet)_"
87
 
88
- when = when_ts.tz_convert(tz).strftime("%-I:%M %p %Z on %a %b %-d")
89
 
90
  nws_temp_str = "β€”"
91
- nws_short = ""
92
  glyph = "🌑"
93
  gap_str = ""
94
- nws_hour_label = "this hour"
95
  if nws_first is not None and not nws_first.empty:
96
  idx0 = nws_first.index[0] if isinstance(nws_first, pd.DataFrame) else nws_first.name
97
  if isinstance(idx0, pd.Timestamp):
98
- nws_hour_label = idx0.tz_convert(tz).strftime("%-I %p %Z")
99
  row = nws_first.iloc[0] if isinstance(nws_first, pd.DataFrame) else nws_first
100
  if isinstance(row, pd.Series):
101
  if "temp_f" in row and pd.notna(row["temp_f"]):
@@ -104,20 +103,15 @@ def hero_markdown(
104
  sign = "+" if gap >= 0 else ""
105
  gap_str = f" <span style='opacity:0.55'>(NWS off by {sign}{gap:.1f}Β°F)</span>"
106
  if "short_forecast" in row:
107
- nws_short = str(row["short_forecast"])
108
- glyph = emoji_for(nws_short)
109
 
110
  table = (
111
- "| Source | Temperature |\n"
112
- "|---|---|\n"
113
- f"| πŸ“‘ Ecowitt (measured) | **{cur_temp:.1f}Β°F** |\n"
114
- f"| 🌎 NWS forecast for {nws_hour_label} | {nws_temp_str}{gap_str} |"
115
- )
116
- return (
117
- f"### {glyph} {place}\n\n"
118
- f"{table}\n\n"
119
- f"<span style='opacity:0.55'>Last Ecowitt reading at {when}</span>"
120
  )
 
121
 
122
 
123
  def aligned_comparison_markdown(
 
85
  if cur_temp is None or when_ts is None:
86
  return "_(no current readings yet)_"
87
 
88
+ eco_when = when_ts.tz_convert(tz).strftime("%-I:%M %p %Z, %a %b %-d")
89
 
90
  nws_temp_str = "β€”"
91
+ nws_when = "β€”"
92
  glyph = "🌑"
93
  gap_str = ""
 
94
  if nws_first is not None and not nws_first.empty:
95
  idx0 = nws_first.index[0] if isinstance(nws_first, pd.DataFrame) else nws_first.name
96
  if isinstance(idx0, pd.Timestamp):
97
+ nws_when = idx0.tz_convert(tz).strftime("%-I %p %Z, %a %b %-d")
98
  row = nws_first.iloc[0] if isinstance(nws_first, pd.DataFrame) else nws_first
99
  if isinstance(row, pd.Series):
100
  if "temp_f" in row and pd.notna(row["temp_f"]):
 
103
  sign = "+" if gap >= 0 else ""
104
  gap_str = f" <span style='opacity:0.55'>(NWS off by {sign}{gap:.1f}Β°F)</span>"
105
  if "short_forecast" in row:
106
+ glyph = emoji_for(str(row["short_forecast"]))
 
107
 
108
  table = (
109
+ "| Source | Temperature | When |\n"
110
+ "|---|---|---|\n"
111
+ f"| πŸ“‘ Ecowitt (measured) | **{cur_temp:.1f}Β°F** | {eco_when} |\n"
112
+ f"| 🌎 NWS forecast | {nws_temp_str}{gap_str} | {nws_when} |"
 
 
 
 
 
113
  )
114
+ return f"### {glyph} {place}\n\n{table}"
115
 
116
 
117
  def aligned_comparison_markdown(