Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -182,74 +182,90 @@ MONTANA_PEAKS = {
|
|
182 |
}
|
183 |
|
184 |
def get_radar_and_snow_forecasts():
|
185 |
-
"""Get current radar and
|
186 |
try:
|
187 |
-
#
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
"https://forecast.weather.gov/wwamap/png/US.png"
|
195 |
-
]
|
196 |
|
|
|
197 |
frames = []
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
|
|
|
|
|
|
202 |
|
203 |
-
#
|
204 |
-
|
205 |
-
|
|
|
206 |
|
207 |
-
#
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
-
|
215 |
-
|
216 |
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
217 |
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
else:
|
223 |
-
|
224 |
-
|
225 |
-
|
|
|
|
|
|
|
|
|
226 |
|
227 |
-
# Draw text with
|
228 |
x, y = 10, 10
|
229 |
for dx, dy in [(-1,-1), (-1,1), (1,-1), (1,1)]:
|
230 |
-
draw.text((x+dx, y+dy),
|
231 |
-
|
232 |
-
draw.text((x, y), text, fill='white', font=font)
|
233 |
-
draw.text((x, y+25), timestamp_text, fill='white', font=font)
|
234 |
|
235 |
-
frames.append(
|
236 |
|
|
|
|
|
|
|
|
|
237 |
if not frames:
|
238 |
-
raise Exception("No
|
239 |
|
240 |
-
#
|
241 |
with tempfile.NamedTemporaryFile(suffix='.gif', delete=False) as tmp_file:
|
242 |
frames[0].save(
|
243 |
tmp_file.name,
|
244 |
save_all=True,
|
245 |
append_images=frames[1:],
|
246 |
-
duration=
|
247 |
loop=0
|
248 |
)
|
249 |
return tmp_file.name
|
250 |
|
251 |
except Exception as e:
|
252 |
-
print(f"Error creating
|
253 |
# Create error message image
|
254 |
img = Image.new('RGB', (800, 600), color='black')
|
255 |
draw = ImageDraw.Draw(img)
|
|
|
182 |
}
|
183 |
|
184 |
def get_radar_and_snow_forecasts():
|
185 |
+
"""Get current radar and forecast loop."""
|
186 |
try:
|
187 |
+
# For the Montana region, get:
|
188 |
+
# 1. Current base reflectivity
|
189 |
+
# 2. Short-term forecast (0-6 hours)
|
190 |
+
# 3. Medium-term forecast (6-12 hours)
|
191 |
+
base_url = "https://radar.weather.gov/ridge/Overlays/Foregrounds"
|
192 |
+
overlay_url = "https://radar.weather.gov/ridge/Overlays"
|
193 |
+
background_url = "https://radar.weather.gov/ridge/Overlays/Backgrounds"
|
|
|
|
|
194 |
|
195 |
+
# Build image frames
|
196 |
frames = []
|
197 |
+
|
198 |
+
# Current conditions plus 6 forecast periods (7 total frames)
|
199 |
+
for hour in range(7):
|
200 |
+
try:
|
201 |
+
# Start with the static background
|
202 |
+
background = Image.open(requests.get(f"{background_url}/Topo/Short/KMSX_Topo_Short.jpg", timeout=10).content)
|
203 |
+
background = background.convert('RGB')
|
204 |
|
205 |
+
# Add county overlays
|
206 |
+
counties = Image.open(requests.get(f"{overlay_url}/Counties/Short/KMSX_Counties_Short.gif", timeout=10).content)
|
207 |
+
counties = counties.convert('RGBA')
|
208 |
+
background.paste(counties, (0, 0), counties)
|
209 |
|
210 |
+
# Add highways
|
211 |
+
highways = Image.open(requests.get(f"{overlay_url}/Highways/Short/KMSX_Highways_Short.gif", timeout=10).content)
|
212 |
+
highways = highways.convert('RGBA')
|
213 |
+
background.paste(highways, (0, 0), highways)
|
214 |
+
|
215 |
+
# Add current radar or forecast overlay
|
216 |
+
if hour == 0:
|
217 |
+
# Current radar
|
218 |
+
radar = Image.open(requests.get(f"{base_url}/Base/KMSX_Base_0.gif", timeout=10).content)
|
219 |
+
else:
|
220 |
+
# Forecast radar (using NDFD data)
|
221 |
+
forecast_time = datetime.now() + timedelta(hours=hour)
|
222 |
+
forecast_str = forecast_time.strftime("%Y%m%d_%H")
|
223 |
+
radar = Image.open(requests.get(f"https://forecast.weather.gov/wrf_images/KMSX/Reflectivity/Reflectivity_{forecast_str}.gif", timeout=10).content)
|
224 |
|
225 |
+
radar = radar.convert('RGBA')
|
226 |
+
background.paste(radar, (0, 0), radar)
|
|
|
227 |
|
228 |
+
# Add timestamp
|
229 |
+
draw = ImageDraw.Draw(background)
|
230 |
+
if hour == 0:
|
231 |
+
time_text = "Current Conditions"
|
232 |
else:
|
233 |
+
forecast_time = datetime.now() + timedelta(hours=hour)
|
234 |
+
time_text = f"Forecast +{hour}h ({forecast_time.strftime('%I%p')})"
|
235 |
+
|
236 |
+
try:
|
237 |
+
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20)
|
238 |
+
except:
|
239 |
+
font = ImageFont.load_default()
|
240 |
|
241 |
+
# Draw text with outline
|
242 |
x, y = 10, 10
|
243 |
for dx, dy in [(-1,-1), (-1,1), (1,-1), (1,1)]:
|
244 |
+
draw.text((x+dx, y+dy), time_text, fill='black', font=font)
|
245 |
+
draw.text((x, y), time_text, fill='white', font=font)
|
|
|
|
|
246 |
|
247 |
+
frames.append(background)
|
248 |
|
249 |
+
except Exception as e:
|
250 |
+
print(f"Error processing frame {hour}: {str(e)}")
|
251 |
+
continue
|
252 |
+
|
253 |
if not frames:
|
254 |
+
raise Exception("No frames could be generated")
|
255 |
|
256 |
+
# Save as animated GIF
|
257 |
with tempfile.NamedTemporaryFile(suffix='.gif', delete=False) as tmp_file:
|
258 |
frames[0].save(
|
259 |
tmp_file.name,
|
260 |
save_all=True,
|
261 |
append_images=frames[1:],
|
262 |
+
duration=1500, # 1.5 seconds per frame
|
263 |
loop=0
|
264 |
)
|
265 |
return tmp_file.name
|
266 |
|
267 |
except Exception as e:
|
268 |
+
print(f"Error creating forecast display: {str(e)}")
|
269 |
# Create error message image
|
270 |
img = Image.new('RGB', (800, 600), color='black')
|
271 |
draw = ImageDraw.Draw(img)
|