from IPython.display import display
from bokeh.plotting import output_notebook
from bokeh.plotting import show
import geopandas as gpd
from shapely.geometry import Point
from shapely.ops import linemerge
from gdf2bokeh import Gdf2Bokeh
from osmgt import OsmGt
from graph_tool.topology import shortest_path
output_notebook()
location = "Roanne"
%%time
pois_gdf = OsmGt.pois_from_location(location).get_gdf()
display(pois_gdf.head(2))
2022-06-25 21:37:41 - OsmGtPoi - INFO : From location: Roanne 2022-06-25 21:37:41 - OsmGtPoi - INFO : Loading data... 2022-06-25 21:37:41 - OsmGtPoi - INFO : NominatimApi: Query 200:OK in 0.44 sec. 2022-06-25 21:37:42 - OsmGtPoi - INFO : OverpassApi: Query 200:OK in 1.06 sec. 2022-06-25 21:37:42 - OsmGtPoi - INFO : Formating data 2022-06-25 21:37:42 - OsmGtPoi - INFO : Prepare GeoDataframe 2022-06-25 21:37:42 - OsmGtPoi - INFO : GeoDataframe Ready
addr:postcode | amenity | atm | change_machine | name | opening_hours | operator | operator:wikidata | operator:wikipedia | phone | ... | office | second_hand | recycling:cartons | recycling:plastic_packaging | indoor | post_box:type | beauty | tobacco | not:brand:wikidata | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 42300 | post_office | yes | yes | Roanne Principal | Mo,We-Fr 08:30-18:00; Tu 08:30-12:00,13:45-18:... | La Poste | Q373724 | fr:La Poste (entreprise française) | 3631 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POINT (4.07240 46.04048) |
1 | NaN | place_of_worship | NaN | NaN | Chapelle Jean Puy | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | POINT (4.07073 46.03766) |
2 rows × 139 columns
CPU times: user 159 ms, sys: 4.31 ms, total: 163 ms Wall time: 1.67 s
%%time
roads_initialized = OsmGt.roads_from_location(
location,
mode="vehicle",
additional_nodes=pois_gdf
)
roads_gdf = roads_initialized.get_gdf()
display(roads_gdf.head(2))
2022-06-25 21:37:42 - OsmGtRoads - INFO : From location: Roanne 2022-06-25 21:37:42 - OsmGtRoads - INFO : Loading data... 2022-06-25 21:37:43 - OsmGtRoads - INFO : NominatimApi: Query 200:OK in 0.35 sec. 2022-06-25 21:37:45 - OsmGtRoads - INFO : OverpassApi: Query 200:OK in 1.55 sec. 2022-06-25 21:37:45 - OsmGtRoads - INFO : Rebuild network data 2022-06-25 21:37:45 - OsmGtRoads - INFO : Network cleaning... 2022-06-25 21:37:45 - OsmGtRoads - INFO : Starting: Adding new nodes on the network 2022-06-25 21:37:45 - OsmGtRoads - INFO : Find nearest line for each node 2022-06-25 21:37:45 - OsmGtRoads - INFO : Split line 2022-06-25 21:37:45 - OsmGtRoads - INFO : Topology lines checker: to add: 449, to split: 442 2022-06-25 21:37:45 - OsmGtRoads - INFO : Starting: Find intersections 2022-06-25 21:37:45 - OsmGtRoads - INFO : Done: Find intersections 2022-06-25 21:37:45 - OsmGtRoads - INFO : Build lines 2022-06-25 21:37:45 - OsmGtRoads - INFO : Prepare GeoDataframe 2022-06-25 21:37:46 - OsmGtRoads - INFO : GeoDataframe Ready
highway | lanes | maxspeed | name | oneway | ref | id | osm_url | topo_uuid | topology | ... | SubClasses | turn:lanes | placement | cycleway:both:lane | maxspeed:backward | maxspeed:forward | busway:right | cycleway:left:oneway | maxheight | geometry | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | primary | 2 | 50 | Rue de Charlieu | yes | D 482 | 24035569 | https://www.openstreetmap.org/way/24035569 | 1_forward | unchanged | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | LINESTRING (4.08544 46.05234, 4.08546 46.05248... |
1 | primary | NaN | 50 | Rue de Charlieu | yes | D 482 | 24035570 | https://www.openstreetmap.org/way/24035570 | 2_forward | unchanged | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | LINESTRING (4.09088 46.06633, 4.09084 46.06622... |
2 rows × 78 columns
CPU times: user 1.18 s, sys: 108 ms, total: 1.29 s Wall time: 3.39 s
%%time
layers_to_add = [
{
"input_gdf": roads_gdf,
"legend": "roads",
"color": "black",
},
{
"input_gdf": pois_gdf,
"legend": "POIs",
"color": "blue",
"size": 9
},
]
my_map = Gdf2Bokeh(
"My roads and POIs - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
# print(dir(my_map))
# print(my_map._Gdf2Bokeh__BOKEH_LAYER_CONTAINERS)
show(my_map.figure)
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:17, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>
%%time
roads_topology_gdfs = roads_initialized.topology_checker()
lines_unchanged = roads_topology_gdfs["lines_unchanged"]
lines_added = roads_topology_gdfs["lines_added"]
lines_split = roads_topology_gdfs["lines_split"]
nodes_added = roads_topology_gdfs["nodes_added"]
intersections_added = roads_topology_gdfs["intersections_added"]
layers_to_add = [
{
"input_gdf": lines_unchanged,
"legend": "roads unchanged",
"color": "black",
},
{
"input_gdf": lines_added,
"legend": "roads added",
"color": "green",
},
{
"input_gdf": lines_split,
"legend": "roads split",
"color": "orange",
},
{
"input_gdf": intersections_added,
"legend": "Intersections added",
"color": "brown",
},
{
"input_gdf": nodes_added,
"legend": "Nodes added", # POIs here
"style": "square",
"color": "blue",
"size": 9
},
]
my_map = Gdf2Bokeh(
"Topology about my roads and POIs - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
show(my_map.figure)
2022-06-25 21:37:46 - OsmGtRoads - INFO : Prepare topology data 2022-06-25 21:37:47 - OsmGtRoads - INFO : GeoDataframe Ready
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:39, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>
%%time
graph = roads_initialized.get_graph()
# a plot method has been added on OsmGT.
graph.plot()
2022-06-25 21:37:47 - OsmGtRoads - INFO : Prepare graph 2022-06-25 21:37:48 - OsmGtRoads - INFO : Graph to image
CPU times: user 20.7 s, sys: 32.9 ms, total: 20.7 s Wall time: 11.9 s
%%time
# now, we have to define a start point and a end point and get their wkt
start_node_topo_uuid = 47
end_node_topo_uuid = 63
# 'topo_uuid' is generated by osmgt (during the topology processing).
# Some roads has been split that's whyso this id has been created.
start_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
end_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == end_node_topo_uuid]
start_node_wkt = start_node_gdf.iloc[0]["geometry"].wkt
end_node_wkt = end_node_gdf.iloc[0]["geometry"].wkt
# the graph have some methods (graph-tools method always exists!) to find egdes, vertices... Let's use the .find_vertex_from_name(). the wkt is the vertex name...
source_vertex = graph.find_vertex_from_name(start_node_wkt)
target_vertex = graph.find_vertex_from_name(end_node_wkt)
# shortest path computing...
path_vertices, path_edges = shortest_path(
graph,
source=source_vertex,
target=target_vertex,
weights=graph.edge_weights # weigth is based on line length
)
# get path by using edge names
roads_ids = [
graph.edge_names[edge]
for edge in path_edges
]
roads_gdf_copy = roads_gdf.copy(deep=True)
shortest_path_found = roads_gdf_copy[roads_gdf['topo_uuid'].isin(roads_ids)].to_crs(3857)['geometry'].to_list()
shortest_path_found_gdf = gpd.GeoDataFrame(index=[0], crs="EPSG:3857", geometry=[linemerge(shortest_path_found)])
layers_to_add = [
{
"input_gdf": shortest_path_found_gdf,
"legend": "shortest_path",
"color": "red",
"line_width": 5
},
{
"input_gdf": start_node_gdf,
"legend": "source node",
"color": "blue",
"style": "circle",
"size": 9
},
{
"input_gdf": end_node_gdf,
"legend": "target node",
"color": "green",
"style": "circle",
"size": 9
},
]
my_shortest_path_map = Gdf2Bokeh(
"My shortest path - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:58, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>
%%time
start_node_topo_uuid = 47
end_node_topo_uuid = 63
start_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
end_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == end_node_topo_uuid]
start_node = start_node_gdf.iloc[0]["geometry"]
end_node = end_node_gdf.iloc[0]["geometry"]
shortest_paths = OsmGt.shortest_path_from_location(
"Roanne",
[
(start_node, end_node),
(start_node, end_node), # duplicate pairs are cleaned
],
mode="pedestrian"
)
layers_to_add = [
{
"input_gdf": shortest_paths[["geometry"]],
"legend": "shortest_path",
"color": "red",
"line_width": 5
},
{
"input_gdf": start_node_gdf,
"legend": "source node",
"color": "blue",
"style": "circle",
"size": 9
},
{
"input_gdf": end_node_gdf,
"legend": "target node",
"color": "green",
"style": "circle",
"size": 9
},
]
my_shortest_path_map = Gdf2Bokeh(
"My shortest path - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
display(shortest_paths)
2022-06-25 21:37:59 - OsmGtShortestPath - INFO : Shortest path processing... 2022-06-25 21:37:59 - OsmGtShortestPath - INFO : From location: Roanne 2022-06-25 21:37:59 - OsmGtShortestPath - INFO : Loading data... 2022-06-25 21:38:00 - OsmGtShortestPath - INFO : NominatimApi: Query 200:OK in 0.34 sec. 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : OverpassApi: Query 200:OK in 2.83 sec. 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Rebuild network data 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Network cleaning... 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Starting: Adding new nodes on the network 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Find nearest line for each node 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Split line 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Topology lines checker: to add: 2, to split: 2 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Starting: Find intersections 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Done: Find intersections 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Build lines 2022-06-25 21:38:03 - OsmGtShortestPath - INFO : Prepare graph 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : Prepare GeoDataframe 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : GeoDataframe Ready 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : Compute shortest path from 3249 to 3250 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : Prepare GeoDataframe 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : GeoDataframe Ready 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : Prepare GeoDataframe 2022-06-25 21:38:04 - OsmGtShortestPath - INFO : GeoDataframe Ready
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:41, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>
%%time
topo_uuids_poi = [99, 167, 188]
source_nodes = pois_gdf[pois_gdf['topo_uuid'].isin(topo_uuids_poi)]
# 2 = 2 min ; 5 = 5 min ; 10 = 10 min
isochrones_polygon_values = {
1: "#d9ef8b",
5: "#fee08b",
10: "#f46d43"
}
isochrones_lines_values = {
1: "#668100",
5: "#e2a803",
10: "#962603"
}
trip_speed = 0.5 # km/h
location_points = list(source_nodes["geometry"])
# location_points.extend(location_points)
isochrones_polygons, isochrones_lines = OsmGt.isochrone_times_from_nodes(
location_points,
list(isochrones_polygon_values.keys()),
trip_speed,
mode="pedestrian"
)
isochrones_polygons["color"] = isochrones_polygons["iso_name"].map(lambda x: isochrones_polygon_values[x])
isochrones_lines["color"] = isochrones_lines["iso_name"].map(lambda x: isochrones_lines_values[x])
layers_to_add = [
{
"input_gdf": source_nodes,
"legend": "Source nodes",
"style": "circle",
"color": "red",
"size": 5
},
{
"input_gdf": isochrones_polygons,
"legend": "iso_name",
"fill_color": "color",
"line_color": "color",
"fill_alpha": 0.5
},
{
"input_gdf": isochrones_lines,
"legend": "iso_name",
"color": "color",
"line_width": 2
},
]
my_shortest_path_map = Gdf2Bokeh(
"Isochrones from times - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
print("\nIsochrones polygons output")
display(isochrones_polygons)
print("\nIsochrones lines output")
display(isochrones_lines.head(2))
2022-06-25 21:38:04 - OsmGtIsochrone - INFO : Isochrone processing... 2022-06-25 21:38:04 - OsmGtIsochrone - INFO : From bbox: (4.061888539709741, 46.027182206766824, 4.076692360290259, 46.03868145992405) 2022-06-25 21:38:04 - OsmGtIsochrone - INFO : Loading data... 2022-06-25 21:38:05 - OsmGtIsochrone - INFO : OverpassApi: Query 200:OK in 1.04 sec. 2022-06-25 21:38:05 - OsmGtIsochrone - INFO : Rebuild network data 2022-06-25 21:38:05 - OsmGtIsochrone - INFO : Network cleaning... 2022-06-25 21:38:05 - OsmGtIsochrone - INFO : Starting: Adding new nodes on the network 2022-06-25 21:38:05 - OsmGtIsochrone - INFO : Find nearest line for each node 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Split line 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Topology lines checker: to add: 3, to split: 3 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Starting: Find intersections 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Done: Find intersections 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Build lines 2022-06-25 21:38:06 - OsmGtIsochrone - INFO : Get water data from OSM 2022-06-25 21:38:07 - OsmGtIsochrone - INFO : OverpassApi: Query 200:OK in 1.64 sec. 2022-06-25 21:38:07 - OsmGtIsochrone - INFO : Prepare GeoDataframe 2022-06-25 21:38:08 - OsmGtIsochrone - INFO : GeoDataframe Ready 2022-06-25 21:38:08 - OsmGtIsochrone - INFO : Prepare graph 2022-06-25 21:38:10 - OsmGtIsochrone - INFO : Compute isochrone: 10 minutes => 84 meters 2022-06-25 21:38:10 - OsmGtIsochrone - INFO : Compute isochrone: 5 minutes => 42 meters 2022-06-25 21:38:10 - OsmGtIsochrone - INFO : Compute isochrone: 1 minutes => 9 meters 2022-06-25 21:38:11 - OsmGtIsochrone - INFO : GeoDataframe Ready
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:57, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>
%%time
topo_uuids_poi = [99, 167, 188]
source_nodes = pois_gdf[pois_gdf['topo_uuid'].isin(topo_uuids_poi)]
# 2 = 2 min ; 5 = 5 min ; 10 = 10 min
isochrones_polygon_values = {
20: "#d9ef8b",
50: "#fee08b",
100: "#f46d43"
}
isochrones_lines_values = {
20: "#668100",
50: "#e2a803",
100: "#962603"
}
trip_speed = 3 # km/h
location_points = list(source_nodes["geometry"])
# location_points.extend(location_points)
isochrones_polygons, isochrones_lines = OsmGt.isochrone_distances_from_nodes(
location_points,
list(isochrones_polygon_values.keys()),
trip_speed,
mode="pedestrian"
)
isochrones_polygons["color"] = isochrones_polygons["iso_distance"].map(lambda x: isochrones_polygon_values[x])
isochrones_lines["color"] = isochrones_lines["iso_distance"].map(lambda x: isochrones_lines_values[x])
layers_to_add = [
{
"input_gdf": source_nodes,
"legend": "Source nodes",
"style": "circle",
"color": "red",
"size": 5
},
{
"input_gdf": isochrones_polygons,
"legend": "iso_name",
"fill_color": "color",
"line_color": "color",
"fill_alpha": 0.5
},
{
"input_gdf": isochrones_lines,
"legend": "iso_name",
"color": "color",
"line_width": 2
},
]
my_shortest_path_map = Gdf2Bokeh(
"Isochrones from times - from OsmGT (https://github.com/amauryval)",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
print("\nIsochrones polygons output")
display(isochrones_polygons)
print("\nIsochrones lines output")
display(isochrones_lines.head(2))
2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Isochrone processing... 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : From bbox: (4.061701690130644, 46.02705247377093, 4.076879209869356, 46.03881116562478) 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Loading data... 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : OverpassApi: Query 200:OK in 0.62 sec. 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Rebuild network data 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Network cleaning... 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Starting: Adding new nodes on the network 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Find nearest line for each node 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Split line 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Topology lines checker: to add: 3, to split: 3 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Starting: Find intersections 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Done: Find intersections 2022-06-25 21:38:12 - OsmGtIsochrone - INFO : Build lines 2022-06-25 21:38:13 - OsmGtIsochrone - INFO : Get water data from OSM 2022-06-25 21:38:15 - OsmGtIsochrone - INFO : OverpassApi: Query 200:OK in 2.26 sec. 2022-06-25 21:38:15 - OsmGtIsochrone - INFO : Prepare GeoDataframe 2022-06-25 21:38:15 - OsmGtIsochrone - INFO : GeoDataframe Ready 2022-06-25 21:38:15 - OsmGtIsochrone - INFO : Prepare graph 2022-06-25 21:38:18 - OsmGtIsochrone - INFO : Compute isochrone: 2.0 minutes => 100 meters 2022-06-25 21:38:18 - OsmGtIsochrone - INFO : Compute isochrone: 1.0 minutes => 50 meters 2022-06-25 21:38:18 - OsmGtIsochrone - INFO : Compute isochrone: 0.4 minutes => 20 meters 2022-06-25 21:38:19 - OsmGtIsochrone - INFO : GeoDataframe Ready
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) File <timed exec>:57, in <module> File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:90, in Gdf2Bokeh.__init__(self, title, width, height, x_range, y_range, background_map_name, layers) 88 self._layers_configuration = layers 89 if layers is not None: ---> 90 self.__add_layers() File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:303, in Gdf2Bokeh.__add_layers(self) 300 assert isinstance(self._layers_configuration, list), "layers arg is not a list" 302 for layer_settings in self._layers_configuration: --> 303 _ = self.add_layer(layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:337, in Gdf2Bokeh.add_layer(self, layer_settings) 335 bokeh_container = self.add_points(**layer_settings) 336 elif layer_geom_types.issubset(linestrings_type_compatibility): --> 337 bokeh_container = self.add_lines(**layer_settings) 338 elif layer_geom_types.issubset(polygons_type_compatibility): 339 bokeh_container = self.add_polygons(**layer_settings) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:154, in Gdf2Bokeh.add_lines(self, input_gdf, legend, **kwargs) 151 # go to check the multilinestring continuity, because the bokeh format cannot display a multilinestring 152 # containing a discontinuity. We'll convert the objet into linestring if needed. 153 input_data = self.__post_proc_multilinestring_gdf(input_data) --> 154 bokeh_layer_container = self._format_gdf_features_to_bokeh(input_data) 155 kwargs = self.__check_is_legend_field_exists_in_input_gdf( 156 input_data, legend, kwargs 157 ) 159 rendered = self.figure.multi_line( 160 xs="x", ys="y", source=bokeh_layer_container, **kwargs 161 ) File ~/miniconda3/envs/osmgt/lib/python3.9/site-packages/gdf2bokeh/main.py:431, in Gdf2Bokeh._format_gdf_features_to_bokeh(self, input_gdf) 422 def _format_gdf_features_to_bokeh(self, input_gdf: gpd.GeoDataFrame) -> ColumnDataSource: 423 """ 424 To build the bokeh data input from a GeoDataframe. 425 (...) 429 :rtype: ColumnDataSource 430 """ --> 431 assert isinstance( 432 input_gdf, gpd.GeoDataFrame 433 ), f"use a GeoDataframe please => found {type(input_gdf)}" 434 assert "geometry" in input_gdf.columns 436 bokeh_data = self.__convert_gdf_to_bokeh_data(input_gdf) AssertionError: use a GeoDataframe please => found <class 'pandas.core.frame.DataFrame'>