Mapu142 commited on
Commit
a5d060b
·
verified ·
1 Parent(s): aacc386

Update app.py

Browse files

regreso a la versión anterior porque la nueva no funciono :'/

Files changed (1) hide show
  1. app.py +76 -160
app.py CHANGED
@@ -5,12 +5,11 @@ import geopandas as gpd
5
  from shapely.geometry import LineString, Point
6
  import folium
7
  from streamlit_folium import st_folium
8
- import networkx as nx
9
- from collections import defaultdict # Add this line if missing
10
  import os, sys
11
  import traceback
12
 
13
- print(">>> Ejecutando archivo:", os.path.abspath(__file__))
14
  print("Python ejecutado:", sys.executable)
15
 
16
  # Cargar shapes.txt manteniendo la precisión
@@ -32,191 +31,108 @@ shapes_gdf.columns = ["shape_id", "geometry"]
32
  crs_obj = CRS.from_epsg(4326) # Crea el objeto CRS correctamente
33
  shapes_gdf = gpd.GeoDataFrame(shapes_gdf, geometry="geometry", crs=crs_obj)
34
 
35
- # Precompute graph for routing
36
- route_short = routes.set_index('route_id')['route_short_name'].to_dict()
37
- stops_routes = defaultdict(set)
38
- G = nx.DiGraph()
39
-
40
- # Group by route_id and shape_id to capture variants/directions
41
- group_cols = ['route_id', 'shape_id']
42
- trips_grouped = trips.groupby(group_cols)
43
-
44
- transfer_penalty = 20
45
-
46
- for name, group in trips_grouped:
47
- if group.empty:
48
- continue
49
- route_id, shape_id = name
50
- trip_id_sample = group['trip_id'].iloc[0]
51
- stops_trip = stop_times[stop_times['trip_id'] == trip_id_sample].sort_values('stop_sequence')
52
- stop_ids = stops_trip['stop_id'].tolist()
53
-
54
- # Add routes to stops
55
- for stop_id in stop_ids:
56
- stops_routes[stop_id].add(route_id)
57
-
58
- # Add ride edges
59
- for i in range(len(stop_ids) - 1):
60
- stop1 = stop_ids[i]
61
- stop2 = stop_ids[i + 1]
62
- G.add_edge((stop1, route_id), (stop2, route_id), weight=1)
63
-
64
- # Add transfer edges
65
- for stop_id, routes_set in stops_routes.items():
66
- routes_list = list(routes_set)
67
- for i in range(len(routes_list)):
68
- for j in range(len(routes_list)):
69
- if i != j:
70
- G.add_edge((stop_id, routes_list[i]), (stop_id, routes_list[j]), weight=transfer_penalty)
71
-
72
- # UI
73
  st.title("🚍 Planificador inteligente — TransMilenio")
74
- st.write("Esta app detecta si la ruta **en la que ya vas** te sirve para llegar al destino, y sugiere transbordos si es necesario.")
75
 
76
- # Inputs
 
 
 
 
 
 
77
  st.header("1️⃣ ¿En qué ruta vas?")
78
- ruta_seleccionada = st.selectbox("Selecciona tu ruta", routes.route_short_name.unique())
 
 
 
79
 
80
  st.header("2️⃣ ¿Dónde estás?")
81
  col1, col2 = st.columns(2)
82
  with col1:
83
  modo_origen = st.radio("Selecciona cómo indicar dónde estás:", ["Parada", "Coordenadas"])
84
 
85
- route_id = routes.loc[routes.route_short_name == ruta_seleccionada, "route_id"].iloc[0]
86
- trips_ruta = trips[trips.route_id == route_id]
87
-
88
- if trips_ruta.empty:
89
- st.error("No se encontraron viajes para esta ruta.")
90
- st.stop()
91
-
92
- # Get all unique stops for the route across all trips
93
- trip_ids = trips_ruta['trip_id'].unique()
94
- all_stops_route = stop_times[stop_times['trip_id'].isin(trip_ids)].merge(stops, on="stop_id")['stop_name'].unique()
95
-
96
  if modo_origen == "Parada":
97
- parada_origen = st.selectbox("Selecciona tu parada actual", all_stops_route)
98
  stop_actual = stops[stops.stop_name == parada_origen].iloc[0]
99
- current_stop_id = stop_actual['stop_id']
100
  else:
101
  lat = st.number_input("Latitud", value=4.65)
102
  lon = st.number_input("Longitud", value=-74.1)
103
- # Find nearest stop among all stops on the route
104
- all_stops_route_df = stop_times[stop_times['trip_id'].isin(trip_ids)].merge(stops, on="stop_id").drop_duplicates('stop_id')
105
- stops_route_gdf = gpd.GeoDataFrame(all_stops_route_df, geometry=gpd.points_from_xy(all_stops_route_df.stop_lon, all_stops_route_df.stop_lat), crs=4326)
106
- user_point = Point(lon, lat)
107
- distances = stops_route_gdf.geometry.distance(user_point)
108
- nearest_idx = distances.argmin()
109
- stop_actual = stops_route_gdf.iloc[nearest_idx]
110
- current_stop_id = stop_actual['stop_id']
111
- st.write(f"Parada más cercana detectada: {stop_actual.stop_name}")
112
 
113
  st.header("3️⃣ ¿A dónde vas?")
114
  destino = st.text_input("Escribe la parada o dirección de destino")
115
 
116
  calcular = st.button("Calcular ruta")
117
 
 
 
 
 
118
  if calcular:
119
- # Find a trip that includes the current stop (to determine variant)
120
- relevant_trips = stop_times[(stop_times['stop_id'] == current_stop_id) & (stop_times['trip_id'].isin(trip_ids))]['trip_id'].unique()
121
- if len(relevant_trips) == 0:
122
- st.error("La parada actual no está en esta ruta.")
 
 
 
123
  st.stop()
124
- trip_id = relevant_trips[0] # Pick first matching trip
125
- st.write(f"Usando trip: `{trip_id}`")
126
 
127
- stops_trip = stop_times[stop_times.trip_id == trip_id].merge(stops, on="stop_id").sort_values('stop_sequence')
 
 
128
 
129
- # Current sequence
130
- current_sequence = stops_trip[stops_trip.stop_id == current_stop_id]['stop_sequence'].iloc[0]
131
 
132
- # Find destination
133
- destino_results = stops[stops.stop_name.str.contains(destino, case=False, na=False)]
134
- if destino_results.empty:
135
- st.error("No se encontró la parada de destino. Intenta con otro nombre.")
136
- st.stop()
137
- destino_stop = destino_results.iloc[0]
138
- destination_id = destino_stop['stop_id']
139
- st.write(f"Destino interpretado como: {destino_stop.stop_name}")
140
-
141
- # Direct check
142
- destino_in_trip = stops_trip[(stops_trip.stop_id == destination_id) & (stops_trip.stop_sequence > current_sequence)]
143
- if not destino_in_trip.empty:
144
- dest_seq = destino_in_trip['stop_sequence'].iloc[0]
145
- num_paradas = dest_seq - current_sequence
146
- st.success(f"Esta ruta **SÍ** te sirve directamente. Debes bajarte en {num_paradas} paradas: **{destino_stop.stop_name}**")
147
- parada_destino = destino_stop
148
  else:
149
- # Graph routing
150
- source = (current_stop_id, route_id)
151
- targets = [(destination_id, r) for r in stops_routes[destination_id]]
152
-
153
- paths = {}
154
- for t in targets:
155
- try:
156
- path = nx.shortest_path(G, source, t, weight='weight')
157
- cost = nx.shortest_path_length(G, source, t, weight='weight')
158
- paths[cost] = path
159
- except nx.NetworkXNoPath:
160
- pass
161
-
162
- if paths:
163
- min_cost = min(paths.keys())
164
- best_path = paths[min_cost]
165
-
166
- # Reconstruct legs
167
- legs = []
168
- current_leg_route = best_path[0][1]
169
- start_stop_id = best_path[0][0]
170
- leg_stops = 0
171
- for i in range(1, len(best_path)):
172
- next_stop_id, next_route = best_path[i]
173
- if next_route != current_leg_route:
174
- from_name = stops[stops.stop_id == start_stop_id]['stop_name'].iloc[0]
175
- to_name = stops[stops.stop_id == best_path[i-1][0]]['stop_name'].iloc[0]
176
- legs.append({
177
- 'route': route_short[current_leg_route],
178
- 'from': from_name,
179
- 'to': to_name,
180
- 'num_paradas': leg_stops
181
- })
182
- start_stop_id = best_path[i-1][0]
183
- current_leg_route = next_route
184
- leg_stops = 0
185
- leg_stops += 1
186
- # Last leg
187
- from_name = stops[stops.stop_id == start_stop_id]['stop_name'].iloc[0]
188
- to_name = stops[stops.stop_id == best_path[-1][0]]['stop_name'].iloc[0]
189
- legs.append({
190
- 'route': route_short[current_leg_route],
191
- 'from': from_name,
192
- 'to': to_name,
193
- 'num_paradas': leg_stops
194
- })
195
-
196
- # Recommendation
197
- rec = "Ruta recomendada:\n"
198
- for idx, leg in enumerate(legs):
199
- if idx == 0:
200
- rec += f"- Vas en {leg['route']} desde {leg['from']}, bájate en {leg['num_paradas']} paradas en {leg['to']}.\n"
201
- else:
202
- rec += f"- Luego, en {leg['from']}, toma {leg['route']} y bájate en {leg['num_paradas']} paradas en {leg['to']}.\n"
203
- st.success(rec)
204
- parada_destino = destino_stop
205
- else:
206
- st.warning("No se encontró ruta con transbordos.")
207
- parada_destino = None
208
-
209
- # Map
210
  st.header("🗺️ Mapa de tu ruta y posición")
 
 
211
  m = folium.Map(location=[stop_actual["stop_lat"], stop_actual["stop_lon"]], zoom_start=13)
212
- folium.Marker([stop_actual["stop_lat"], stop_actual["stop_lon"]], tooltip="Estás aquí", icon=folium.Icon(color="blue")).add_to(m)
213
-
214
- # Draw shape
215
- shape_id = trips[trips.trip_id == trip_id]['shape_id'].iloc[0]
 
 
 
 
 
 
 
216
  shape_geom = shapes_gdf[shapes_gdf.shape_id == shape_id].geometry.iloc[0]
217
- folium.PolyLine(locations=[(lat, lon) for lon, lat in zip(shape_geom.coords.xy[0], shape_geom.coords.xy[1])], weight=5, color="red", tooltip=f"Ruta {ruta_seleccionada}").add_to(m)
218
-
 
 
 
 
 
 
 
219
  if parada_destino is not None:
220
- folium.Marker([parada_destino.stop_lat, parada_destino.stop_lon], tooltip=f"Destino: {parada_destino.stop_name}", icon=folium.Icon(color="green")).add_to(m)
221
-
 
 
 
 
222
  st_folium(m, width=700, height=500)
 
5
  from shapely.geometry import LineString, Point
6
  import folium
7
  from streamlit_folium import st_folium
8
+
 
9
  import os, sys
10
  import traceback
11
 
12
+ print(">>> Ejecutando archivo:", os.path.abspath(_file_))
13
  print("Python ejecutado:", sys.executable)
14
 
15
  # Cargar shapes.txt manteniendo la precisión
 
31
  crs_obj = CRS.from_epsg(4326) # Crea el objeto CRS correctamente
32
  shapes_gdf = gpd.GeoDataFrame(shapes_gdf, geometry="geometry", crs=crs_obj)
33
 
34
+ # =========================
35
+ # UI
36
+ # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  st.title("🚍 Planificador inteligente — TransMilenio")
 
38
 
39
+ st.write("Esta app detecta si la ruta *en la que ya vas* te sirve para llegar al destino.")
40
+
41
+
42
+ # =========================
43
+ # INPUTS DEL USUARIO
44
+ # =========================
45
+
46
  st.header("1️⃣ ¿En qué ruta vas?")
47
+ ruta_seleccionada = st.selectbox(
48
+ "Selecciona tu ruta",
49
+ routes.route_short_name.unique(),
50
+ )
51
 
52
  st.header("2️⃣ ¿Dónde estás?")
53
  col1, col2 = st.columns(2)
54
  with col1:
55
  modo_origen = st.radio("Selecciona cómo indicar dónde estás:", ["Parada", "Coordenadas"])
56
 
 
 
 
 
 
 
 
 
 
 
 
57
  if modo_origen == "Parada":
58
+ parada_origen = st.selectbox("Selecciona tu parada actual", stops.stop_name.unique())
59
  stop_actual = stops[stops.stop_name == parada_origen].iloc[0]
60
+
61
  else:
62
  lat = st.number_input("Latitud", value=4.65)
63
  lon = st.number_input("Longitud", value=-74.1)
64
+ stop_actual = {"stop_lat": lat, "stop_lon": lon}
65
+
 
 
 
 
 
 
 
66
 
67
  st.header("3️⃣ ¿A dónde vas?")
68
  destino = st.text_input("Escribe la parada o dirección de destino")
69
 
70
  calcular = st.button("Calcular ruta")
71
 
72
+ # =========================
73
+ # PROCESAMIENTO
74
+ # =========================
75
+
76
  if calcular:
77
+
78
+ # ---- 1. Filtrar rutas por route_short_name ----
79
+ route_id = routes.loc[routes.route_short_name == ruta_seleccionada, "route_id"].iloc[0]
80
+ trips_ruta = trips[trips.route_id == route_id]
81
+
82
+ if trips_ruta.empty:
83
+ st.error("No se encontraron viajes para esta ruta.")
84
  st.stop()
 
 
85
 
86
+ # ---- 2. Seleccionar un trip (en GTFS cada ruta tiene varios) ----
87
+ trip_id = trips_ruta.iloc[0].trip_id
88
+ st.write(f"Usando trip: {trip_id}")
89
 
90
+ stops_trip = stop_times[stop_times.trip_id == trip_id].merge(stops, on="stop_id")
 
91
 
92
+ # ---- 3. Buscar destino por nombre aproximado ----
93
+ destino_results = stops_trip[stops_trip.stop_name.str.contains(destino, case=False, na=False)]
94
+
95
+ if not destino_results.empty:
96
+ parada_destino = destino_results.iloc[0]
97
+ st.success(f"Esta ruta *SÍ* te sirve. Debes bajarte en: *{parada_destino.stop_name}*")
 
 
 
 
 
 
 
 
 
 
98
  else:
99
+ st.warning("Esta ruta NO te lleva directamente al destino. (Transbordos: próximo paso)")
100
+ parada_destino = None
101
+
102
+ # =========================
103
+ # MAPA
104
+ # =========================
105
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  st.header("🗺️ Mapa de tu ruta y posición")
107
+
108
+ # Crear mapa centrado en la posición actual
109
  m = folium.Map(location=[stop_actual["stop_lat"], stop_actual["stop_lon"]], zoom_start=13)
110
+
111
+ # ---- Marcar posición actual ----
112
+ folium.Marker(
113
+ [stop_actual["stop_lat"], stop_actual["stop_lon"]],
114
+ tooltip="Estás aquí",
115
+ icon=folium.Icon(color="blue")
116
+ ).add_to(m)
117
+
118
+ # ---- Dibujar route shape ----
119
+ # Buscar shape_id asociado
120
+ shape_id = trips_ruta.iloc[0].shape_id
121
  shape_geom = shapes_gdf[shapes_gdf.shape_id == shape_id].geometry.iloc[0]
122
+
123
+ folium.PolyLine(
124
+ locations=[(lat, lon) for lon, lat in zip(shape_geom.coords.xy[0], shape_geom.coords.xy[1])],
125
+ weight=5,
126
+ color="red",
127
+ tooltip=f"Ruta {ruta_seleccionada}"
128
+ ).add_to(m)
129
+
130
+ # ---- Marcar destino si existe----
131
  if parada_destino is not None:
132
+ folium.Marker(
133
+ [parada_destino.stop_lat, parada_destino.stop_lon],
134
+ tooltip=f"Destino: {parada_destino.stop_name}",
135
+ icon=folium.Icon(color="green")
136
+ ).add_to(m)
137
+
138
  st_folium(m, width=700, height=500)