deepguess commited on
Commit
1254cf1
·
1 Parent(s): 22f9a57
Files changed (1) hide show
  1. app.py +80 -41
app.py CHANGED
@@ -4,6 +4,9 @@ import torch
4
  from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
5
  import os
6
  from datetime import datetime
 
 
 
7
 
8
  # Model setup
9
  processor = AutoProcessor.from_pretrained("deepguess/weather-vlm-qwen2.5-7b", trust_remote_code=True)
@@ -79,10 +82,39 @@ MODE_INFO = {
79
  "research": "In-depth research perspective"
80
  }
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  @spaces.GPU(duration=90)
83
- def analyze_weather_image(image, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p):
84
- if image is None:
85
- return "Please upload an image to analyze."
 
 
 
 
 
 
86
 
87
  # Move model to GPU
88
  model.cuda()
@@ -124,7 +156,8 @@ def analyze_weather_image(image, analysis_type, custom_prompt, analysis_mode, te
124
 
125
  # Add metadata
126
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
127
- metadata = f"\n\n---\n*Analysis completed: {timestamp} | Mode: {analysis_mode} | Type: {analysis_type}*"
 
128
 
129
  return response + metadata
130
 
@@ -135,18 +168,35 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
135
  #analysis-output { font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; }
136
  .gr-button-primary { background-color: #2563eb; }
137
  .gr-button-primary:hover { background-color: #1e40af; }
 
138
  """) as demo:
139
  gr.Markdown(f"# {TITLE}")
140
  gr.Markdown(DESCRIPTION)
141
 
142
  with gr.Row():
143
  with gr.Column(scale=1):
144
- # Image input
145
- image_input = gr.Image(
146
- label="Upload Weather Image",
147
- type="pil",
148
- elem_id="image-upload"
149
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  # Analysis type selector
152
  analysis_type = gr.Dropdown(
@@ -250,25 +300,6 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
250
  outputs=custom_prompt
251
  )
252
 
253
- # Examples section
254
- example_data = [
255
- ["examples/500mb_heights.jpg", "Model Output", "technical", 0.7, 512],
256
- ["examples/sounding.jpg", "Sounding Analysis", "educational", 0.7, 512],
257
- ["examples/radar_composite.jpg", "Radar/Satellite", "operational", 0.7, 384],
258
- ["examples/spc_outlook.jpg", "Severe Weather", "operational", 0.7, 512],
259
- ["examples/ensemble_spaghetti.jpg", "Ensemble Analysis", "research", 0.8, 640],
260
- ] if os.path.exists("examples") else []
261
-
262
- if example_data:
263
- gr.Examples(
264
- examples=example_data,
265
- inputs=[image_input, analysis_type, analysis_mode, temperature, max_tokens],
266
- outputs=output,
267
- fn=lambda img, typ, mode, temp, tok: analyze_weather_image(img, typ, "", mode, temp, tok, 0.95),
268
- cache_examples=False,
269
- label="Example Analyses"
270
- )
271
-
272
  # Tips section
273
  with gr.Accordion("💡 Pro Tips for Best Results", open=False):
274
  gr.Markdown("""
@@ -277,6 +308,19 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
277
  - **Clarity**: Ensure text/contours are legible
278
  - **Completeness**: Include colorbars, titles, valid times
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  ### Analysis Tips by Data Type:
281
 
282
  **Model Output (GFS, HRRR, ECMWF, NAM):**
@@ -293,17 +337,6 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
293
  - Include timestamp and location
294
  - Specify interest in particular features
295
  - Ask about storm motion or development
296
-
297
- **Surface/Upper Air Charts:**
298
- - Ensure contours and labels are clear
299
- - Ask about specific features or patterns
300
- - Request frontal analysis or jet stream discussion
301
-
302
- ### Parameter Settings:
303
- - **Temperature 0.3-0.5**: Factual, consistent analysis
304
- - **Temperature 0.6-0.8**: Balanced analysis with some interpretation
305
- - **Temperature 0.9-1.0**: More speculative, exploring possibilities
306
- - **Max Tokens**: Use 256-384 for quick analysis, 512-768 for detailed
307
  """)
308
 
309
  # Update mode description when mode changes
@@ -316,9 +349,15 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
316
  # Set up event handler
317
  analyze_btn.click(
318
  fn=analyze_weather_image,
319
- inputs=[image_input, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p],
320
  outputs=output
321
  )
 
 
 
 
 
 
322
 
323
  # Launch the app
324
  if __name__ == "__main__":
 
4
  from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
5
  import os
6
  from datetime import datetime
7
+ from PIL import Image
8
+ import requests
9
+ from io import BytesIO
10
 
11
  # Model setup
12
  processor = AutoProcessor.from_pretrained("deepguess/weather-vlm-qwen2.5-7b", trust_remote_code=True)
 
82
  "research": "In-depth research perspective"
83
  }
84
 
85
+ # Example URLs for different weather data types
86
+ EXAMPLE_URLS = {
87
+ "SPC Convective Outlook": "https://www.spc.noaa.gov/products/outlook/day1otlk.gif",
88
+ "SPC Mesoanalysis (Surface)": "https://inside.nssl.noaa.gov/ewp/wp-content/uploads/sites/22/2019/05/19ZSPCCape.png",
89
+ "College of DuPage Nexrad": "https://upload.wikimedia.org/wikipedia/commons/9/9b/NEXRAD_radar_of_an_EF2_tornado_in_Kansas_on_March_13%2C_2024.png",
90
+ "Tropical Tidbits GFS 500mb": "https://sites.gatech.edu/eas-mesoscale-blog/files/2023/04/Hebert_Fig4-768x531.png",
91
+ "GOES-16 Visible": "https://cdn.star.nesdis.noaa.gov/GOES16/ABI/CONUS/GEOCOLOR/1250x750.jpg",
92
+ "KOUN Sounding": "https://sharppy.github.io/SHARPpy/_images/gui.sharppy.png",
93
+ }
94
+
95
+ def load_image_from_url(url):
96
+ """Load an image from URL."""
97
+ try:
98
+ response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'})
99
+ response.raise_for_status()
100
+ img = Image.open(BytesIO(response.content))
101
+ # Convert to RGB if necessary
102
+ if img.mode != 'RGB':
103
+ img = img.convert('RGB')
104
+ return img
105
+ except Exception as e:
106
+ return None, f"Error loading image from URL: {str(e)}"
107
+
108
  @spaces.GPU(duration=90)
109
+ def analyze_weather_image(image, image_url, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p):
110
+ # Handle image input - either direct upload or URL
111
+ if image_url and image_url.strip():
112
+ result = load_image_from_url(image_url.strip())
113
+ if isinstance(result, tuple): # Error case
114
+ return result[1]
115
+ image = result
116
+ elif image is None:
117
+ return "Please upload an image or provide an image URL to analyze."
118
 
119
  # Move model to GPU
120
  model.cuda()
 
156
 
157
  # Add metadata
158
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
159
+ source = "URL" if image_url and image_url.strip() else "Upload"
160
+ metadata = f"\n\n---\n*Analysis completed: {timestamp} | Mode: {analysis_mode} | Type: {analysis_type} | Source: {source}*"
161
 
162
  return response + metadata
163
 
 
168
  #analysis-output { font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; }
169
  .gr-button-primary { background-color: #2563eb; }
170
  .gr-button-primary:hover { background-color: #1e40af; }
171
+ .url-button { min-width: 120px; }
172
  """) as demo:
173
  gr.Markdown(f"# {TITLE}")
174
  gr.Markdown(DESCRIPTION)
175
 
176
  with gr.Row():
177
  with gr.Column(scale=1):
178
+ # Image input options
179
+ with gr.Tabs():
180
+ with gr.Tab("Upload Image"):
181
+ image_input = gr.Image(
182
+ label="Upload Weather Image",
183
+ type="pil",
184
+ elem_id="image-upload"
185
+ )
186
+
187
+ with gr.Tab("Image URL"):
188
+ image_url_input = gr.Textbox(
189
+ label="Image URL",
190
+ placeholder="https://example.com/weather-image.jpg",
191
+ lines=1
192
+ )
193
+
194
+ # Quick URL examples
195
+ gr.Markdown("**Quick Examples:**")
196
+ url_buttons = []
197
+ for name, url in EXAMPLE_URLS.items():
198
+ btn = gr.Button(name, size="sm", elem_classes="url-button")
199
+ btn.click(lambda u=url: u, outputs=image_url_input)
200
 
201
  # Analysis type selector
202
  analysis_type = gr.Dropdown(
 
300
  outputs=custom_prompt
301
  )
302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  # Tips section
304
  with gr.Accordion("💡 Pro Tips for Best Results", open=False):
305
  gr.Markdown("""
 
308
  - **Clarity**: Ensure text/contours are legible
309
  - **Completeness**: Include colorbars, titles, valid times
310
 
311
+ ### Using URLs:
312
+ - Supports direct links to JPG, PNG, GIF images
313
+ - Some weather sites may block direct access
314
+ - For best results, use official weather service URLs
315
+ - Alternative: Save image locally and upload
316
+
317
+ ### Common Weather Data Sources:
318
+ - **SPC**: Convective outlooks, mesoanalysis
319
+ - **College of DuPage**: NEXRAD, model data
320
+ - **Tropical Tidbits**: Model analysis maps
321
+ - **GOES Imagery**: Satellite data
322
+ - **WPC**: Surface analysis, QPF
323
+
324
  ### Analysis Tips by Data Type:
325
 
326
  **Model Output (GFS, HRRR, ECMWF, NAM):**
 
337
  - Include timestamp and location
338
  - Specify interest in particular features
339
  - Ask about storm motion or development
 
 
 
 
 
 
 
 
 
 
 
340
  """)
341
 
342
  # Update mode description when mode changes
 
349
  # Set up event handler
350
  analyze_btn.click(
351
  fn=analyze_weather_image,
352
+ inputs=[image_input, image_url_input, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p],
353
  outputs=output
354
  )
355
+
356
+ # Clear image upload when URL is entered
357
+ image_url_input.change(
358
+ lambda: None,
359
+ outputs=image_input
360
+ )
361
 
362
  # Launch the app
363
  if __name__ == "__main__":