Spaces:
Sleeping
Sleeping
Commit Β·
ca321f9
1
Parent(s): 3bfdad2
fix app
Browse files
app.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
import folium
|
| 4 |
-
import
|
| 5 |
|
| 6 |
-
# ββ Data paths ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
| 10 |
|
| 11 |
AGE_MAP = {1:"<18", 2:"18-24", 3:"25-34", 4:"35-44", 5:"45-54", 6:"55-64", 7:"65+"}
|
| 12 |
SEX_MAP = {1:"Male", 2:"Female"}
|
|
@@ -14,65 +15,38 @@ EDU_MAP = {1:"No HS", 2:"HS Grad", 3:"Some College", 4:"Bachelor's", 5:"Graduate
|
|
| 14 |
INC_MAP = {1:"<$10k", 2:"$10-15k", 3:"$15-25k", 4:"$25-35k", 5:"$35-50k",
|
| 15 |
6:"$50-75k", 7:"$75-100k", 8:"$100-125k", 9:"$125-150k", 10:">$150k"}
|
| 16 |
|
| 17 |
-
# ββ Load
|
| 18 |
print("Loading data...")
|
| 19 |
-
sp
|
| 20 |
-
poi
|
| 21 |
demo = pd.read_csv(DEMO_PATH)
|
| 22 |
|
| 23 |
-
|
| 24 |
-
sp["poi_id"] = sp["poi_id"].astype(int)
|
| 25 |
-
poi["poi_id"] = poi["poi_id"].astype(int)
|
| 26 |
-
|
| 27 |
-
sp = sp.merge(poi, on="poi_id", how="left")
|
| 28 |
-
|
| 29 |
-
# parse act_types string like "[ 2 15]" β list
|
| 30 |
-
def parse_act(x):
|
| 31 |
-
try:
|
| 32 |
-
return list(map(int, str(x).strip("[]").split()))
|
| 33 |
-
except:
|
| 34 |
-
return []
|
| 35 |
-
|
| 36 |
-
poi["act_types"] = poi["act_types"].apply(parse_act)
|
| 37 |
-
|
| 38 |
-
# join stay_points with poi
|
| 39 |
-
sp = sp.merge(poi, on="poi_id", how="left")
|
| 40 |
sp["start_datetime"] = pd.to_datetime(sp["start_datetime"], utc=True)
|
| 41 |
sp["end_datetime"] = pd.to_datetime(sp["end_datetime"], utc=True)
|
| 42 |
sp["duration_min"] = ((sp["end_datetime"] - sp["start_datetime"]).dt.total_seconds() / 60).round(1)
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
print(f"Loaded. Sample agents: {sample_agents[:5]}...")
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
# ββ Core functions βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 50 |
-
def get_agent_data(agent_id):
|
| 51 |
-
agent_sp = sp[sp["agent_id"] == agent_id].sort_values("start_datetime")
|
| 52 |
-
agent_demo = demo[demo["agent_id"] == agent_id].iloc[0]
|
| 53 |
-
return agent_sp, agent_demo
|
| 54 |
-
|
| 55 |
|
|
|
|
| 56 |
def build_map(agent_sp):
|
| 57 |
lat = agent_sp["latitude"].mean()
|
| 58 |
lon = agent_sp["longitude"].mean()
|
| 59 |
m = folium.Map(location=[lat, lon], zoom_start=12, tiles="CartoDB positron")
|
| 60 |
|
| 61 |
-
# trajectory line
|
| 62 |
coords = list(zip(agent_sp["latitude"], agent_sp["longitude"]))
|
| 63 |
if len(coords) > 1:
|
| 64 |
folium.PolyLine(coords, color="#4f86c6", weight=2, opacity=0.6).add_to(m)
|
| 65 |
|
| 66 |
-
|
| 67 |
-
for i, row in agent_sp.iterrows():
|
| 68 |
folium.CircleMarker(
|
| 69 |
location=[row["latitude"], row["longitude"]],
|
| 70 |
-
radius=6,
|
| 71 |
-
color="#e05c5c",
|
| 72 |
-
fill=True,
|
| 73 |
-
fill_opacity=0.8,
|
| 74 |
popup=folium.Popup(
|
| 75 |
-
f"<b>{row['name']}</b><br>
|
|
|
|
|
|
|
| 76 |
max_width=200
|
| 77 |
)
|
| 78 |
).add_to(m)
|
|
@@ -83,61 +57,44 @@ def build_map(agent_sp):
|
|
| 83 |
def build_poi_sequence(agent_sp):
|
| 84 |
lines = []
|
| 85 |
for _, row in agent_sp.iterrows():
|
| 86 |
-
dt = row["start_datetime"]
|
| 87 |
lines.append(
|
| 88 |
-
f"{
|
| 89 |
-
f"
|
|
|
|
| 90 |
)
|
| 91 |
return "\n".join(lines)
|
| 92 |
|
| 93 |
|
| 94 |
-
def build_demo_text(
|
| 95 |
return (
|
| 96 |
-
f"Age: {AGE_MAP.get(
|
| 97 |
-
f"Sex: {SEX_MAP.get(
|
| 98 |
-
f"Education: {EDU_MAP.get(
|
| 99 |
-
f"Income: {INC_MAP.get(
|
| 100 |
)
|
| 101 |
|
| 102 |
|
| 103 |
def on_select(agent_id):
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
return map_html, poi_seq, demo_text
|
| 109 |
|
| 110 |
|
| 111 |
-
# ββ UI βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 112 |
-
with gr.Blocks(title="HiCoTraj Demo", theme=gr.themes.Soft()) as
|
| 113 |
gr.Markdown("## HiCoTraj: Trajectory Visualization")
|
| 114 |
|
| 115 |
with gr.Row():
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
label="Select Agent",
|
| 119 |
-
value=str(sample_agents[0])
|
| 120 |
-
)
|
| 121 |
demo_label = gr.Textbox(label="Ground Truth Demographics", interactive=False)
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
| 125 |
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
agent_dropdown.change(
|
| 130 |
-
fn=on_select,
|
| 131 |
-
inputs=agent_dropdown,
|
| 132 |
-
outputs=[map_out, poi_out, demo_label]
|
| 133 |
-
)
|
| 134 |
-
|
| 135 |
-
# load first agent on startup
|
| 136 |
-
demo_app.load(
|
| 137 |
-
fn=on_select,
|
| 138 |
-
inputs=agent_dropdown,
|
| 139 |
-
outputs=[map_out, poi_out, demo_label]
|
| 140 |
-
)
|
| 141 |
|
| 142 |
if __name__ == "__main__":
|
| 143 |
-
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
import folium
|
| 4 |
+
import os
|
| 5 |
|
| 6 |
+
# ββ Data paths βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 7 |
+
BASE = os.path.dirname(os.path.abspath(__file__))
|
| 8 |
+
STAY_POINTS = os.path.join(BASE, "data", "stay_points_sampled.csv")
|
| 9 |
+
POI_PATH = os.path.join(BASE, "data", "poi_sampled.csv")
|
| 10 |
+
DEMO_PATH = os.path.join(BASE, "data", "demographics_sampled.csv")
|
| 11 |
|
| 12 |
AGE_MAP = {1:"<18", 2:"18-24", 3:"25-34", 4:"35-44", 5:"45-54", 6:"55-64", 7:"65+"}
|
| 13 |
SEX_MAP = {1:"Male", 2:"Female"}
|
|
|
|
| 15 |
INC_MAP = {1:"<$10k", 2:"$10-15k", 3:"$15-25k", 4:"$25-35k", 5:"$35-50k",
|
| 16 |
6:"$50-75k", 7:"$75-100k", 8:"$100-125k", 9:"$125-150k", 10:">$150k"}
|
| 17 |
|
| 18 |
+
# ββ Load βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 19 |
print("Loading data...")
|
| 20 |
+
sp = pd.read_csv(STAY_POINTS)
|
| 21 |
+
poi = pd.read_csv(POI_PATH)
|
| 22 |
demo = pd.read_csv(DEMO_PATH)
|
| 23 |
|
| 24 |
+
sp = sp.merge(poi, on="poi_id", how="left")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
sp["start_datetime"] = pd.to_datetime(sp["start_datetime"], utc=True)
|
| 26 |
sp["end_datetime"] = pd.to_datetime(sp["end_datetime"], utc=True)
|
| 27 |
sp["duration_min"] = ((sp["end_datetime"] - sp["start_datetime"]).dt.total_seconds() / 60).round(1)
|
| 28 |
|
| 29 |
+
sample_agents = sorted(sp["agent_id"].unique().tolist())
|
| 30 |
+
print(f"Ready. {len(sample_agents)} agents loaded.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
+
# ββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 33 |
def build_map(agent_sp):
|
| 34 |
lat = agent_sp["latitude"].mean()
|
| 35 |
lon = agent_sp["longitude"].mean()
|
| 36 |
m = folium.Map(location=[lat, lon], zoom_start=12, tiles="CartoDB positron")
|
| 37 |
|
|
|
|
| 38 |
coords = list(zip(agent_sp["latitude"], agent_sp["longitude"]))
|
| 39 |
if len(coords) > 1:
|
| 40 |
folium.PolyLine(coords, color="#4f86c6", weight=2, opacity=0.6).add_to(m)
|
| 41 |
|
| 42 |
+
for _, row in agent_sp.iterrows():
|
|
|
|
| 43 |
folium.CircleMarker(
|
| 44 |
location=[row["latitude"], row["longitude"]],
|
| 45 |
+
radius=6, color="#e05c5c", fill=True, fill_opacity=0.8,
|
|
|
|
|
|
|
|
|
|
| 46 |
popup=folium.Popup(
|
| 47 |
+
f"<b>{row['name']}</b><br>"
|
| 48 |
+
f"{row['start_datetime'].strftime('%a %m/%d %H:%M')}<br>"
|
| 49 |
+
f"{int(row['duration_min'])} min",
|
| 50 |
max_width=200
|
| 51 |
)
|
| 52 |
).add_to(m)
|
|
|
|
| 57 |
def build_poi_sequence(agent_sp):
|
| 58 |
lines = []
|
| 59 |
for _, row in agent_sp.iterrows():
|
|
|
|
| 60 |
lines.append(
|
| 61 |
+
f"{row['start_datetime'].strftime('%a %m/%d')} "
|
| 62 |
+
f"{row['start_datetime'].strftime('%H:%M')}β{row['end_datetime'].strftime('%H:%M')} "
|
| 63 |
+
f"({int(row['duration_min'])} min) | {row['name']} | {row['act_types']}"
|
| 64 |
)
|
| 65 |
return "\n".join(lines)
|
| 66 |
|
| 67 |
|
| 68 |
+
def build_demo_text(row):
|
| 69 |
return (
|
| 70 |
+
f"Age: {AGE_MAP.get(row['age'], row['age'])} | "
|
| 71 |
+
f"Sex: {SEX_MAP.get(row['sex'], row['sex'])} | "
|
| 72 |
+
f"Education: {EDU_MAP.get(row['education'], row['education'])} | "
|
| 73 |
+
f"Income: {INC_MAP.get(row['hh_income'], row['hh_income'])}"
|
| 74 |
)
|
| 75 |
|
| 76 |
|
| 77 |
def on_select(agent_id):
|
| 78 |
+
agent_id = int(agent_id)
|
| 79 |
+
agent_sp = sp[sp["agent_id"] == agent_id].sort_values("start_datetime")
|
| 80 |
+
agent_demo = demo[demo["agent_id"] == agent_id].iloc[0]
|
| 81 |
+
return build_map(agent_sp), build_poi_sequence(agent_sp), build_demo_text(agent_demo)
|
|
|
|
| 82 |
|
| 83 |
|
| 84 |
+
# ββ UI ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 85 |
+
with gr.Blocks(title="HiCoTraj Demo", theme=gr.themes.Soft()) as app:
|
| 86 |
gr.Markdown("## HiCoTraj: Trajectory Visualization")
|
| 87 |
|
| 88 |
with gr.Row():
|
| 89 |
+
agent_dd = gr.Dropdown(choices=[str(a) for a in sample_agents],
|
| 90 |
+
label="Select Agent", value=str(sample_agents[0]))
|
|
|
|
|
|
|
|
|
|
| 91 |
demo_label = gr.Textbox(label="Ground Truth Demographics", interactive=False)
|
| 92 |
|
| 93 |
+
map_out = gr.HTML(label="Trajectory Map")
|
| 94 |
+
poi_out = gr.Textbox(label="POI Sequence", lines=20, interactive=False)
|
| 95 |
|
| 96 |
+
agent_dd.change(fn=on_select, inputs=agent_dd, outputs=[map_out, poi_out, demo_label])
|
| 97 |
+
app.load(fn=on_select, inputs=agent_dd, outputs=[map_out, poi_out, demo_label])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
if __name__ == "__main__":
|
| 100 |
+
app.launch()
|