nakas commited on
Commit
a87268f
·
verified ·
1 Parent(s): 0e9bf34

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -47
app.py CHANGED
@@ -3,54 +3,129 @@ import pandas as pd
3
  import numpy as np
4
  from datetime import datetime
5
  import re
 
 
 
 
 
6
 
7
- def parse_weather_data(text):
8
- """Parse the weather data text into a structured format"""
9
- lines = [line.strip() for line in text.split('\n') if line.strip()]
10
- data = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- for line in lines:
13
- if not ('am' in line or 'pm' in line):
14
- continue
15
-
16
- parts = line.split('\t')
17
- if len(parts) < 8:
18
- continue
19
-
20
- try:
21
- # Parse wind speed and gusts (format: "12G30")
22
- wind_match = re.search(r'(\d+)G(\d+)', parts[6]) if len(parts) > 6 else None
23
- wind_speed = int(wind_match.group(1)) if wind_match else np.nan
24
- wind_gust = int(wind_match.group(2)) if wind_match else np.nan
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- row = {
27
- 'datetime': parts[0].strip(),
28
- 'temperature': float(parts[1]),
29
- 'dew_point': float(parts[2]),
30
- 'humidity': float(parts[3]),
31
- 'wind_chill': float(parts[4]) if parts[4].strip() != '' else np.nan,
32
- 'wind_speed': wind_speed,
33
- 'wind_gust': wind_gust,
34
- 'snow_depth': float(parts[7]) if parts[7].strip() != '' else np.nan
35
- }
36
- data.append(row)
37
- except:
38
- continue
 
 
 
 
 
39
 
40
- return pd.DataFrame(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- def analyze_weather_data(data_str):
43
  """Analyze weather data and create visualizations"""
44
  try:
 
 
 
 
 
45
  # Parse data
46
- df = parse_weather_data(data_str)
47
- if len(df) == 0:
48
- return "Error: No valid data found in input."
49
 
50
  # Calculate statistics
51
  stats = {
52
- 'Temperature Range': f"{df['temperature'].min():.1f}°F to {df['temperature'].max():.1f}°F",
53
- 'Average Temperature': f"{df['temperature'].mean():.1f}°F",
54
  'Max Wind Speed': f"{df['wind_speed'].max():.1f} mph",
55
  'Max Wind Gust': f"{df['wind_gust'].max():.1f} mph",
56
  'Average Humidity': f"{df['humidity'].mean():.1f}%",
@@ -59,13 +134,14 @@ def analyze_weather_data(data_str):
59
 
60
  # Create HTML output
61
  html_output = "<div style='font-size: 16px; line-height: 1.5;'>"
 
62
  for key, value in stats.items():
63
  html_output += f"<p><strong>{key}:</strong> {value}</p>"
64
  html_output += "</div>"
65
 
66
  # Create temperature plot
67
  temp_fig = gr.Plot()
68
- df.plot(x='datetime', y=['temperature', 'wind_chill'],
69
  title='Temperature and Wind Chill Over Time',
70
  figsize=(12, 6))
71
  temp_fig.pyplot()
@@ -83,18 +159,30 @@ def analyze_weather_data(data_str):
83
  return f"Error analyzing data: {str(e)}", None, None
84
 
85
  # Create Gradio interface
86
- with gr.Blocks(title="Weather Data Analyzer") as demo:
87
- gr.Markdown("# Weather Data Analyzer")
88
- gr.Markdown("Paste weather data from weather.gov/wrh/timeseries in the text box below.")
 
 
 
 
 
 
89
 
90
  with gr.Row():
91
- input_text = gr.Textbox(
92
- label="Weather Data",
93
- placeholder="Paste weather data here...",
94
- lines=10
 
 
 
 
 
 
95
  )
96
 
97
- analyze_btn = gr.Button("Analyze Weather Data")
98
 
99
  with gr.Row():
100
  stats_output = gr.HTML(label="Statistics")
@@ -105,7 +193,7 @@ with gr.Blocks(title="Weather Data Analyzer") as demo:
105
 
106
  analyze_btn.click(
107
  fn=analyze_weather_data,
108
- inputs=[input_text],
109
  outputs=[stats_output, temp_plot, wind_plot]
110
  )
111
 
 
3
  import numpy as np
4
  from datetime import datetime
5
  import re
6
+ from playwright.sync_api import sync_playwright
7
+ import time
8
+ import os
9
+ import subprocess
10
+ import sys
11
 
12
+ # Install Playwright browsers on startup
13
+ def install_playwright_browsers():
14
+ try:
15
+ if not os.path.exists('/home/user/.cache/ms-playwright'):
16
+ print("Installing Playwright browsers...")
17
+ subprocess.run(
18
+ [sys.executable, "-m", "playwright", "install", "chromium"],
19
+ check=True,
20
+ capture_output=True,
21
+ text=True
22
+ )
23
+ print("Playwright browsers installed successfully")
24
+ except Exception as e:
25
+ print(f"Error installing browsers: {e}")
26
+
27
+ # Install browsers when the module loads
28
+ install_playwright_browsers()
29
+
30
+ def scrape_weather_data(site_id, hours=720):
31
+ """Scrape weather data from weather.gov timeseries"""
32
+ url = f"https://www.weather.gov/wrh/timeseries?site={site_id}&hours={hours}&units=english&chart=on&headers=on&obs=tabular&hourly=false&pview=full&font=12&plot="
33
 
34
+ with sync_playwright() as p:
35
+ # Launch browser with minimal settings
36
+ browser = p.chromium.launch(
37
+ headless=True,
38
+ args=['--no-sandbox', '--disable-dev-shm-usage']
39
+ )
40
+
41
+ # Create context with desktop user agent
42
+ context = browser.new_context(
43
+ user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
44
+ )
45
+
46
+ # Create new page and navigate
47
+ page = context.new_page()
48
+ page.goto(url)
49
+
50
+ # Wait for content to load
51
+ time.sleep(5)
52
+
53
+ # Get all text content
54
+ content = page.evaluate('''() => {
55
+ // Function to get all text content
56
+ const getTextContent = () => {
57
+ const rows = [];
58
+ const tables = document.getElementsByTagName('table');
59
+ for (const table of tables) {
60
+ if (table.textContent.includes('Date/Time')) {
61
+ const headerRow = Array.from(table.querySelectorAll('th'))
62
+ .map(th => th.textContent.trim());
63
+
64
+ const dataRows = Array.from(table.querySelectorAll('tbody tr'))
65
+ .map(row => Array.from(row.querySelectorAll('td'))
66
+ .map(td => td.textContent.trim()));
67
+
68
+ return {headers: headerRow, rows: dataRows};
69
+ }
70
+ }
71
+ return null;
72
+ };
73
 
74
+ return getTextContent();
75
+ }''')
76
+
77
+ browser.close()
78
+ return content
79
+
80
+ def parse_weather_data(data):
81
+ """Parse the weather data into a pandas DataFrame"""
82
+ if not data or 'rows' not in data:
83
+ raise ValueError("No valid weather data found")
84
+
85
+ # Convert to DataFrame
86
+ df = pd.DataFrame(data['rows'])
87
+
88
+ # Assign column names (first 8 columns we care about)
89
+ columns = ['datetime', 'temp', 'dew_point', 'humidity', 'wind_chill', 'wind_dir', 'wind_speed', 'snow_depth']
90
+ df = df.iloc[:, :8]
91
+ df.columns = columns
92
 
93
+ # Convert numeric columns
94
+ df['temp'] = pd.to_numeric(df['temp'], errors='coerce')
95
+ df['dew_point'] = pd.to_numeric(df['dew_point'], errors='coerce')
96
+ df['humidity'] = pd.to_numeric(df['humidity'], errors='coerce')
97
+ df['wind_chill'] = pd.to_numeric(df['wind_chill'], errors='coerce')
98
+ df['snow_depth'] = pd.to_numeric(df['snow_depth'], errors='coerce')
99
+
100
+ # Parse wind speed and gusts
101
+ def parse_wind(x):
102
+ if pd.isna(x): return np.nan, np.nan
103
+ match = re.search(r'(\d+)G(\d+)', str(x))
104
+ if match:
105
+ return float(match.group(1)), float(match.group(2))
106
+ return np.nan, np.nan
107
+
108
+ wind_data = df['wind_speed'].apply(parse_wind)
109
+ df['wind_speed'] = wind_data.apply(lambda x: x[0])
110
+ df['wind_gust'] = wind_data.apply(lambda x: x[1])
111
+
112
+ return df
113
 
114
+ def analyze_weather_data(site_id, hours):
115
  """Analyze weather data and create visualizations"""
116
  try:
117
+ # Scrape data
118
+ raw_data = scrape_weather_data(site_id, hours)
119
+ if not raw_data:
120
+ return "Error: Could not retrieve weather data.", None, None
121
+
122
  # Parse data
123
+ df = parse_weather_data(raw_data)
 
 
124
 
125
  # Calculate statistics
126
  stats = {
127
+ 'Temperature Range': f"{df['temp'].min():.1f}°F to {df['temp'].max():.1f}°F",
128
+ 'Average Temperature': f"{df['temp'].mean():.1f}°F",
129
  'Max Wind Speed': f"{df['wind_speed'].max():.1f} mph",
130
  'Max Wind Gust': f"{df['wind_gust'].max():.1f} mph",
131
  'Average Humidity': f"{df['humidity'].mean():.1f}%",
 
134
 
135
  # Create HTML output
136
  html_output = "<div style='font-size: 16px; line-height: 1.5;'>"
137
+ html_output += f"<p><strong>Weather Station:</strong> {site_id}</p>"
138
  for key, value in stats.items():
139
  html_output += f"<p><strong>{key}:</strong> {value}</p>"
140
  html_output += "</div>"
141
 
142
  # Create temperature plot
143
  temp_fig = gr.Plot()
144
+ df.plot(x='datetime', y=['temp', 'wind_chill'],
145
  title='Temperature and Wind Chill Over Time',
146
  figsize=(12, 6))
147
  temp_fig.pyplot()
 
159
  return f"Error analyzing data: {str(e)}", None, None
160
 
161
  # Create Gradio interface
162
+ with gr.Blocks(title="Weather Station Data Analyzer") as demo:
163
+ gr.Markdown("# Weather Station Data Analyzer")
164
+ gr.Markdown("""
165
+ Enter a weather station ID and number of hours to analyze.
166
+ Example station IDs:
167
+ - YCTIM (Yellowstone Club - Timber)
168
+ - KBZN (Bozeman Airport)
169
+ - KSLC (Salt Lake City)
170
+ """)
171
 
172
  with gr.Row():
173
+ site_id = gr.Textbox(
174
+ label="Weather Station ID",
175
+ value="YCTIM",
176
+ placeholder="Enter station ID (e.g., YCTIM)"
177
+ )
178
+ hours = gr.Number(
179
+ label="Hours of Data",
180
+ value=720,
181
+ minimum=1,
182
+ maximum=1440
183
  )
184
 
185
+ analyze_btn = gr.Button("Fetch and Analyze Weather Data")
186
 
187
  with gr.Row():
188
  stats_output = gr.HTML(label="Statistics")
 
193
 
194
  analyze_btn.click(
195
  fn=analyze_weather_data,
196
+ inputs=[site_id, hours],
197
  outputs=[stats_output, temp_plot, wind_plot]
198
  )
199