Nikhil Singh commited on
Commit
e08472a
·
1 Parent(s): 8f1daaf
Files changed (3) hide show
  1. .gitignore +1 -0
  2. app.py +133 -4
  3. pyproject.toml +3 -1
.gitignore CHANGED
@@ -1,3 +1,4 @@
1
  __pycache__/
2
  *.pyc
3
  .venv/
 
 
1
  __pycache__/
2
  *.pyc
3
  .venv/
4
+ .gradio/
app.py CHANGED
@@ -1,7 +1,136 @@
1
  import gradio as gr
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import asyncio
3
+ import plotly.graph_objects as go
4
+ import h3
5
+ from src.trackemdown.core import fetch_geotags
6
 
7
+ def create_map(results):
8
+ """Create an interactive map showing the geotag locations and hexagon boundaries"""
9
+ if not results:
10
+ return go.Figure()
11
 
12
+ lats = [result.latitude for result in results]
13
+ lons = [result.longitude for result in results]
14
+ addresses = [result.address for result in results]
15
+ geotags = [result.geotag for result in results]
16
+
17
+ fig = go.Figure()
18
+
19
+ # Add hexagon boundaries for each geotag
20
+ colors = ['blue', 'green', 'purple', 'orange', 'brown', 'pink', 'gray', 'olive', 'cyan', 'magenta']
21
+
22
+ for i, geotag in enumerate(geotags):
23
+ try:
24
+ # Get hexagon boundary coordinates
25
+ boundary = h3.cell_to_boundary(geotag)
26
+
27
+ # Convert to lat/lon lists (boundary returns (lat, lon) tuples)
28
+ hex_lats = [coord[0] for coord in boundary] + [boundary[0][0]] # Close the polygon
29
+ hex_lons = [coord[1] for coord in boundary] + [boundary[0][1]]
30
+
31
+ # Add hexagon outline
32
+ fig.add_trace(go.Scattermap(
33
+ lat=hex_lats,
34
+ lon=hex_lons,
35
+ mode='lines',
36
+ line=dict(width=2, color=colors[i % len(colors)]),
37
+ name=f"H3 Hexagon {i+1}",
38
+ hovertemplate=f'<b>H3 Geotag: {geotag}</b><extra></extra>',
39
+ showlegend=True
40
+ ))
41
+
42
+ except Exception as e:
43
+ print(f"Could not draw hexagon for {geotag}: {e}")
44
+
45
+ # Add location markers
46
+ fig.add_trace(go.Scattermap(
47
+ lat=lats,
48
+ lon=lons,
49
+ mode='markers',
50
+ marker=dict(size=8, color='red'),
51
+ text=[f"{addr}<br>Geotag: {geotag}" for addr, geotag in zip(addresses, geotags)],
52
+ hovertemplate='<b>%{text}</b><extra></extra>',
53
+ name="Locations",
54
+ showlegend=True
55
+ ))
56
+
57
+ fig.update_layout(
58
+ map=dict(
59
+ style="open-street-map",
60
+ zoom=2,
61
+ center=dict(lat=lats[0], lon=lons[0]) if lats else dict(lat=0, lon=0)
62
+ ),
63
+ height=500,
64
+ margin=dict(l=0, r=0, t=0, b=0),
65
+ legend=dict(x=0.02, y=0.98)
66
+ )
67
+
68
+ return fig
69
+
70
+ async def get_geotags_async(query: str, resolution: int):
71
+ try:
72
+ results = await fetch_geotags(query, resolution)
73
+
74
+ # Format results for table display
75
+ formatted_results = []
76
+ for result in results:
77
+ formatted_results.append([
78
+ result.address,
79
+ f"{result.latitude:.6f}",
80
+ f"{result.longitude:.6f}",
81
+ result.geotag
82
+ ])
83
+
84
+ # Create map
85
+ map_fig = create_map(results)
86
+
87
+ return formatted_results, map_fig, gr.update(visible=False)
88
+
89
+ except Exception as e:
90
+ empty_fig = go.Figure()
91
+ empty_fig.update_layout(height=400, margin=dict(l=0, r=0, t=0, b=0))
92
+ return [], empty_fig, gr.update(value=f"Error: {str(e)}", visible=True)
93
+
94
+ def get_geotags(query: str, resolution: int):
95
+ loop = asyncio.new_event_loop()
96
+ asyncio.set_event_loop(loop)
97
+ try:
98
+ return loop.run_until_complete(get_geotags_async(query, resolution))
99
+ finally:
100
+ loop.close()
101
+
102
+ # H3 Resolution levels:
103
+ # 0: ~4,250 km hexagons (continent scale)
104
+ # 5: ~252 km hexagons (large city scale)
105
+ # 9: ~0.1 km hexagons (neighborhood scale)
106
+ # 12: ~0.01 km hexagons (building scale)
107
+ # 15: ~0.0005 km hexagons (room scale) - highest resolution
108
+
109
+ with gr.Blocks() as demo:
110
+ gr.Markdown("# TrackEmDown")
111
+
112
+ with gr.Row():
113
+ query_input = gr.Textbox(label="Address or Coordinates")
114
+ resolution_input = gr.Number(label="H3 Resolution", value=15, minimum=0, maximum=15)
115
+
116
+ search_btn = gr.Button("Generate Geotags")
117
+
118
+ results_table = gr.Dataframe(
119
+ headers=["Address", "Latitude", "Longitude", "H3 Geotag"],
120
+ datatype=["str", "str", "str", "str"],
121
+ interactive=False,
122
+ wrap=True
123
+ )
124
+
125
+ map_plot = gr.Plot(label="Map View")
126
+
127
+ error_output = gr.Textbox(label="Error", lines=3, interactive=False, visible=False)
128
+
129
+ search_btn.click(
130
+ fn=get_geotags,
131
+ inputs=[query_input, resolution_input],
132
+ outputs=[results_table, map_plot, error_output]
133
+ )
134
+
135
+ if __name__ == "__main__":
136
+ demo.launch(share=True)
pyproject.toml CHANGED
@@ -9,7 +9,9 @@ dependencies = [
9
  "uvicorn[standard]>=0.24.0",
10
  "h3>=3.7.6",
11
  "httpx>=0.25.2",
12
- "pydantic>=2.5.0"
 
 
13
  ]
14
 
15
  [build-system]
 
9
  "uvicorn[standard]>=0.24.0",
10
  "h3>=3.7.6",
11
  "httpx>=0.25.2",
12
+ "pydantic>=2.5.0",
13
+ "gradio>=4.0.0",
14
+ "plotly>=5.0.0"
15
  ]
16
 
17
  [build-system]