import json import pandas as pd import numpy as np from sklearn.neighbors import BallTree """load routes json""" with open("montreal_routes.json", "r") as f: data = json.load(f) """flatten walk geometry""" rows = [] for route in data: route_id = route["route_id"] for leg in route["legs"]: if leg["mode"] != "WALK": continue coords = leg.get("geometry_sampled_50m", []) for i, (lat, lon) in enumerate(coords): rows.append({ "route_id": route_id, "leg_from": leg["from"], "leg_to": leg["to"], "point_index": i, "lat": lat, "lon": lon }) df = pd.DataFrame(rows) """load accessibility data""" access = pd.read_csv("collation_points_grid_centre-ville.csv") access = access.rename(columns={ "latitude": "lat", "longitude": "lon" }) access = access.dropna(subset=["lat", "lon"]) """build spatial index""" access_coords = np.radians(access[["lat", "lon"]].values) tree = BallTree(access_coords, metric="haversine") """match each route point to nearest accessibility point""" route_coords = np.radians(df[["lat", "lon"]].values) dist, idx = tree.query(route_coords, k=1) df["nearest_access_index"] = idx[:, 0] df["distance_to_access_m"] = dist[:, 0] * 6371000 # radians → meters """attach accessibility features""" access_cols = [ "point_id", "arrondissement", "heat_class", "heat_label", "total_feature", "collisions_n", "collisions_vic", "collisions_m", "collisions_bl", "collisions_gr", "permis_n", "permis_loger", "permis_types", "entraves_n", "entraves_act", "entraves_rai", "entraves_fin", "arbres_n", "arbres_especes_top", "arbres_dhp", "emplacements_arbres_n" ] # keep only columns that actually exist (prevents crashes) access_cols = [c for c in access_cols if c in access.columns] for col in access_cols: df[col] = access.iloc[idx[:, 0]][col].values """route summary metrics""" route_summary = df.groupby("route_id").agg({ "distance_to_access_m": "mean", "heat_class": "mean", "collisions_n": "mean", "arbres_n": "mean" }).reset_index() print(route_summary.head()) """save outpus""" # build per-route summaries summary_map = route_summary.set_index("route_id").to_dict(orient="index") # build structured routes routes_out = [] for route_id, g in df.groupby("route_id"): route_obj = { "route_id": int(route_id), "summary": summary_map.get(route_id, {}), "points": g[[ "leg_from", "leg_to", "point_index", "lat", "lon", "distance_to_access_m", ] + access_cols].to_dict(orient="records") } routes_out.append(route_obj) # save JSON with open("routes_with_accessibility.json", "w") as f: json.dump(routes_out, f, indent=2) print("Saved routes_with_accessibility.json")