immunobiotech commited on
Commit
516f18a
·
verified ·
1 Parent(s): 2ea7db4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -155
app.py CHANGED
@@ -1,81 +1,124 @@
1
  import gradio as gr
 
 
2
  import requests
3
- import json
4
- from PIL import Image
 
 
 
5
  import io
6
 
7
- # API 기본 URL
8
- BASE_URL = "https://collectionapi.metmuseum.org/public/collection/v1"
9
 
10
- def get_departments():
11
- """Get all departments from the Met API"""
12
- response = requests.get(f"{BASE_URL}/departments")
13
- return response.json()['departments']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- def search_artworks(query, department_id=None, is_highlight=False, has_images=True,
16
- is_on_view=False, medium=None, geo_location=None):
17
- """Search artworks with various filters"""
18
- search_url = f"{BASE_URL}/search"
19
- params = {
20
- 'q': query,
21
- 'hasImages': has_images,
22
- 'isHighlight': is_highlight,
23
- 'isOnView': is_on_view
24
  }
25
 
26
- if department_id:
27
- params['departmentId'] = department_id
28
- if medium:
29
- params['medium'] = medium
30
- if geo_location:
31
- params['geoLocation'] = geo_location
32
-
33
- try:
34
- # Get object IDs from search
35
- response = requests.get(search_url, params=params)
36
- results = response.json()
37
-
38
- if not results.get('objectIDs'):
39
- return [], "No results found."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- # Limit to first 12 objects for performance
42
- object_ids = results['objectIDs'][:12]
43
-
44
- images = []
45
- captions = []
46
-
47
- # Get details for each object
48
- for object_id in object_ids:
49
- object_url = f"{BASE_URL}/objects/{object_id}"
50
- object_response = requests.get(object_url)
51
- artwork = object_response.json()
52
 
53
- if artwork.get('primaryImage'):
54
- try:
55
- img_response = requests.get(artwork['primaryImage'], timeout=10)
56
- img = Image.open(io.BytesIO(img_response.content))
57
-
58
- if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
59
- img = img.convert('RGB')
60
-
61
- artwork_info = f"""
62
- Title: {artwork.get('title', 'Unknown')}
63
- Artist: {artwork.get('artistDisplayName', 'Unknown')}
64
- Date: {artwork.get('objectDate', 'Unknown')}
65
- Medium: {artwork.get('medium', 'Unknown')}
66
- Department: {artwork.get('department', 'Unknown')}
67
- """
68
-
69
- images.append(img)
70
- captions.append(artwork_info)
71
- except Exception as e:
72
- print(f"Error processing image for object {object_id}: {e}")
73
- continue
74
-
75
- return images, "\n\n".join(captions)
76
-
77
- except Exception as e:
78
- return [], f"An error occurred: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  # Custom CSS
81
  custom_css = """
@@ -84,118 +127,59 @@ custom_css = """
84
  color: #ffffff !important;
85
  }
86
  .gr-button {
87
- background: linear-gradient(135deg, #8e2de2, #4a00e0) !important;
88
  border: none !important;
89
  color: white !important;
90
- font-weight: bold !important;
91
- padding: 10px 20px !important;
92
- font-size: 1.1em !important;
93
- box-shadow: 0 4px 15px rgba(0,0,0,0.2) !important;
94
  }
95
  .gr-button:hover {
 
96
  transform: translateY(-2px);
97
- box-shadow: 0 6px 20px rgba(0,0,0,0.3) !important;
98
- transition: all 0.3s ease;
99
- }
100
- .gr-input, .gr-select {
101
- border: 2px solid #4a00e0 !important;
102
- background: rgba(255, 255, 255, 0.1) !important;
103
- color: white !important;
104
- font-size: 1.1em !important;
105
- border-radius: 8px !important;
106
- }
107
- .gr-gallery {
108
- background: rgba(0, 0, 0, 0.3) !important;
109
- border-radius: 15px !important;
110
- padding: 20px !important;
111
- min-height: 800px !important;
112
- box-shadow: 0 8px 32px rgba(0,0,0,0.3) !important;
113
  }
114
  .title-text {
115
  text-align: center !important;
116
  color: #ffffff !important;
117
- font-size: 2.8em !important;
118
- margin-bottom: 0.3em !important;
119
  text-shadow: 2px 2px 4px rgba(0,0,0,0.5) !important;
120
- font-weight: bold !important;
121
- }
122
- .subtitle-text {
123
- text-align: center !important;
124
- color: #cccccc !important;
125
- font-size: 1.3em !important;
126
- margin-bottom: 2em !important;
127
- font-style: italic !important;
128
- text-shadow: 1px 1px 2px rgba(0,0,0,0.3) !important;
129
  }
130
  """
131
 
132
- # Get departments for dropdown
133
- departments = get_departments()
134
- department_choices = {dept['displayName']: dept['departmentId'] for dept in departments}
135
-
136
  # Gradio interface
137
  with gr.Blocks(css=custom_css) as demo:
138
  gr.HTML(
139
  """
140
- <div class="title-text">🎨 The Met Art Explorer</div>
141
- <div class="subtitle-text">Explore over 5,000 years of art from The Metropolitan Museum of Art's collection</div>
142
  """
143
  )
144
 
145
  with gr.Row():
146
- with gr.Column(scale=3):
147
- search_input = gr.Textbox(
148
- label="Search artwork",
149
- placeholder="Enter keywords (e.g., sunflowers, portrait, landscape...)"
150
- )
151
- with gr.Column(scale=2):
152
- department_dropdown = gr.Dropdown(
153
- choices=list(department_choices.keys()),
154
- label="Department",
155
- value=None
156
- )
157
 
158
- with gr.Row():
159
- with gr.Column():
160
- highlight_checkbox = gr.Checkbox(label="Show Highlights Only", value=False)
161
- on_view_checkbox = gr.Checkbox(label="Currently On View", value=False)
162
- with gr.Column():
163
- medium_input = gr.Textbox(
164
- label="Medium",
165
- placeholder="e.g., Paintings, Sculpture, Ceramics"
166
- )
167
- location_input = gr.Textbox(
168
- label="Geographic Location",
169
- placeholder="e.g., France, Japan, Egypt"
170
- )
171
-
172
- search_btn = gr.Button("🔍 Search Collection", variant="primary")
173
-
174
- gallery = gr.Gallery(
175
- label="Search Results",
176
- show_label=True,
177
- elem_id="gallery",
178
- columns=3,
179
- rows=4,
180
- height="800px",
181
- object_fit="contain"
182
- )
183
 
184
- info = gr.Textbox(
185
- label="Artwork Details",
186
- lines=10,
187
- show_label=True
188
- )
189
 
190
- def handle_search(query, dept, highlight, on_view, medium, location):
191
- dept_id = department_choices.get(dept) if dept else None
192
- return search_artworks(query, dept_id, highlight, True, on_view, medium, location)
 
 
193
 
194
- search_btn.click(
195
- fn=handle_search,
196
- inputs=[search_input, department_dropdown, highlight_checkbox,
197
- on_view_checkbox, medium_input, location_input],
198
- outputs=[gallery, info]
199
  )
 
 
 
200
 
201
  demo.launch()
 
1
  import gradio as gr
2
+ import folium
3
+ from folium import plugins
4
  import requests
5
+ import pandas as pd
6
+ from datetime import datetime
7
+ import time
8
+ import branca.colormap as cm
9
+ import numpy as np
10
  import io
11
 
12
+ # OpenSky API URL
13
+ BASE_URL = "https://opensky-network.org/api"
14
 
15
+ def get_states(bounds=None):
16
+ """Get current aircraft states from OpenSky Network"""
17
+ params = {}
18
+ if bounds:
19
+ params.update({
20
+ 'lamin': bounds[0],
21
+ 'lomin': bounds[1],
22
+ 'lamax': bounds[2],
23
+ 'lomax': bounds[3]
24
+ })
25
+
26
+ try:
27
+ response = requests.get(f"{BASE_URL}/states/all", params=params)
28
+ data = response.json()
29
+ return data
30
+ except Exception as e:
31
+ print(f"Error fetching data: {e}")
32
+ return None
33
 
34
+ def create_map(region="world"):
35
+ """Create aircraft tracking map"""
36
+ # Default bounds for different regions
37
+ bounds = {
38
+ "world": None,
39
+ "europe": [35.0, -15.0, 60.0, 40.0],
40
+ "north_america": [25.0, -130.0, 50.0, -60.0],
41
+ "asia": [10.0, 60.0, 50.0, 150.0]
 
42
  }
43
 
44
+ # Get aircraft data
45
+ data = get_states(bounds.get(region))
46
+
47
+ if not data or 'states' not in data:
48
+ return None, "Failed to fetch aircraft data"
49
+
50
+ # Create base map
51
+ m = folium.Map(
52
+ location=[30, 0],
53
+ zoom_start=3,
54
+ tiles='CartoDB dark_matter'
55
+ )
56
+
57
+ # Create aircraft icon
58
+ aircraft_icon = folium.CustomIcon(
59
+ 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-blue.png',
60
+ icon_size=(25, 41)
61
+ )
62
+
63
+ # Create heatmap data
64
+ heat_data = []
65
+
66
+ # Add aircraft markers
67
+ for state in data['states']:
68
+ if state[6] and state[5]: # If latitude and longitude exist
69
+ lat, lon = state[6], state[5]
70
+ callsign = state[1] if state[1] else 'N/A'
71
+ altitude = state[7] if state[7] else 'N/A'
72
+ velocity = state[9] if state[9] else 'N/A'
73
 
74
+ # Add to heatmap data
75
+ heat_data.append([lat, lon, 1])
 
 
 
 
 
 
 
 
 
76
 
77
+ # Create popup content
78
+ popup_content = f"""
79
+ <div style="font-family: Arial; width: 200px;">
80
+ <h4 style="color: #4a90e2;">Flight Information</h4>
81
+ <p><b>Callsign:</b> {callsign}</p>
82
+ <p><b>Altitude:</b> {altitude}m</p>
83
+ <p><b>Velocity:</b> {velocity}m/s</p>
84
+ <p><b>Origin:</b> {state[2]}</p>
85
+ </div>
86
+ """
87
+
88
+ # Add marker
89
+ folium.Marker(
90
+ location=[lat, lon],
91
+ popup=folium.Popup(popup_content, max_width=300),
92
+ icon=folium.DivIcon(
93
+ html=f'''
94
+ <div style="transform: rotate({state[10]}deg)">✈️</div>
95
+ ''',
96
+ icon_size=(20, 20)
97
+ )
98
+ ).add_to(m)
99
+
100
+ # Add heatmap layer
101
+ plugins.HeatMap(heat_data, radius=15).add_to(m)
102
+
103
+ # Add layer control
104
+ folium.LayerControl().add_to(m)
105
+
106
+ # Save map to HTML string
107
+ html_string = m._repr_html_()
108
+
109
+ # Create statistics
110
+ total_aircraft = len(data['states'])
111
+ countries = len(set(state[2] for state in data['states'] if state[2]))
112
+ avg_altitude = np.mean([state[7] for state in data['states'] if state[7]]) if data['states'] else 0
113
+
114
+ stats = f"""
115
+ 📊 Statistics:
116
+ • Total Aircraft: {total_aircraft}
117
+ • Countries: {countries}
118
+ • Average Altitude: {avg_altitude:.0f}m
119
+ """
120
+
121
+ return html_string, stats
122
 
123
  # Custom CSS
124
  custom_css = """
 
127
  color: #ffffff !important;
128
  }
129
  .gr-button {
130
+ background: linear-gradient(135deg, #4a90e2, #357abd) !important;
131
  border: none !important;
132
  color: white !important;
 
 
 
 
133
  }
134
  .gr-button:hover {
135
+ background: linear-gradient(135deg, #357abd, #4a90e2) !important;
136
  transform: translateY(-2px);
137
+ box-shadow: 0 5px 15px rgba(74, 144, 226, 0.4) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  }
139
  .title-text {
140
  text-align: center !important;
141
  color: #ffffff !important;
142
+ font-size: 2.5em !important;
143
+ margin-bottom: 0.5em !important;
144
  text-shadow: 2px 2px 4px rgba(0,0,0,0.5) !important;
 
 
 
 
 
 
 
 
 
145
  }
146
  """
147
 
 
 
 
 
148
  # Gradio interface
149
  with gr.Blocks(css=custom_css) as demo:
150
  gr.HTML(
151
  """
152
+ <div class="title-text">🛩️ Global Aircraft Tracker</div>
 
153
  """
154
  )
155
 
156
  with gr.Row():
157
+ region_select = gr.Dropdown(
158
+ choices=["world", "europe", "north_america", "asia"],
159
+ value="world",
160
+ label="Select Region"
161
+ )
162
+ refresh_btn = gr.Button("🔄 Refresh")
 
 
 
 
 
163
 
164
+ map_html = gr.HTML()
165
+ stats_text = gr.Textbox(label="Statistics", lines=4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
+ def update_map(region):
168
+ return create_map(region)
 
 
 
169
 
170
+ refresh_btn.click(
171
+ fn=update_map,
172
+ inputs=[region_select],
173
+ outputs=[map_html, stats_text]
174
+ )
175
 
176
+ region_select.change(
177
+ fn=update_map,
178
+ inputs=[region_select],
179
+ outputs=[map_html, stats_text]
 
180
  )
181
+
182
+ # Initial map load
183
+ map_html, stats_text = create_map("world")
184
 
185
  demo.launch()