Skip to content

Commit

Permalink
Merge pull request #12 from amauryval/dev_cleaning
Browse files Browse the repository at this point in the history
Dev cleaning
  • Loading branch information
amauryval authored Sep 2, 2020
2 parents ce38452 + 420928c commit 6e79a2f
Show file tree
Hide file tree
Showing 16 changed files with 496 additions and 546 deletions.
89 changes: 0 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,95 +36,6 @@ conda install -c amauryval osmgt

Check example.html example (doc is coming)


```Python
from osmgt import OsmGt

# GET POIs
poi_from_location = OsmGt.poi_from_location(
"Lyon"
)

poi_from_bbox = OsmGt.poi_from_bbox(
(-74.018433, 40.718087, -73.982749, 40.733356)
)

# 2 methods available:
poi_study_area_data_wkt = poi_from_bbox.study_area_geom() # to get the shapely Polygon of the study data
poi_gdf = poi_from_bbox.get_gdf() # to get the geodataframe containing all the POIs


# GET ROADS
roads_from_location = OsmGt.roads_from_location(
"Lyon",
mode="pedestrian", # 'pedestrian' or 'vehicle' supported
additionnal_nodes=None, # optional, to connect nodes on the roads network (geodataframe or None)
)

roads_from_bbox = OsmGt.roads_from_bbox(
(4.0237426757812, 46.019674567761, 4.1220188140869, 46.072575637028),
mode="pedestrian", # 'pedestrian' or 'vehicle' supported
additionnal_nodes=None, # optional, to connect nodes on the roads network (geodataframe or None)
)

# 3 methods available:
roads_study_area_data_wkt = roads_from_location.study_area_geom() # to get the shapely Polygon of the study data
roads_gdf = roads_from_location.get_gdf() # to get the geodataframe containing all the roads
roads_graph = roads_from_location.get_graph() # to get the graph (graph-tool graph) of the osm network

# 1 sub-method [more info will coming soon] can be found with the graph object:
roads_graph.plot() # in order to generate a graph png output

```

# How to use the graph ?

Example: compute a shortest path

```Python
from osmgt import OsmGt
from graph_tool.topology import shortest_path

# get data
location_name = "Lyon"
mode = "pedestrian"
poi_from_location_gdf = OsmGt.poi_from_location(location_name).get_gdf()
roads_from_location = OsmGt.roads_from_location(location_name, mode=mode, additionnal_nodes=poi_from_location_gdf)

# get roads geodataframe and generate the graph
roads_from_location_gdf = roads_from_location.get_gdf()
graph = roads_from_location.get_graph() # the graph-tool graph

# 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_wkt = poi_from_location_gdf[poi_from_location_gdf['topo_uuid'] == start_node_topo_uuid].iloc[0]["geometry"].wkt
end_node_wkt = poi_from_location_gdf[poi_from_location_gdf['topo_uuid'] == end_node_topo_uuid].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
]
shortest_path_found = roads_from_location_gdf[roads_from_location_gdf['topo_uuid'].isin(roads_ids)]
```


# How to run the dockerfile
```
docker build -t osmgt . && docker run -p 8888:8888 osmgt:latest
Expand Down
7 changes: 4 additions & 3 deletions example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@
],
"source": [
"%%time\n",
"roads_from_location = OsmGt.roads_from_location(location, mode=\"vehicle\", additionnal_nodes=poi_from_location_gdf)\n",
"roads_from_location = OsmGt.roads_from_location(location, mode=\"vehicle\", additional_nodes=poi_from_location_gdf)\n",
"roads_from_location_gdf = roads_from_location.get_gdf()"
]
},
Expand Down Expand Up @@ -518,6 +518,7 @@
}
],
"source": [
"%%time\n",
"# apply colors based on topology field\n",
"roads_from_location_gdf = roads_from_location_gdf[[\"topo_uuid\", \"id\", \"topology\", \"geometry\"]]\n",
"\n",
Expand Down Expand Up @@ -1091,7 +1092,7 @@
" \"legend\": \"iso_name\",\n",
" \"fill_color\": \"color\",\n",
" \"line_color\": \"color\",\n",
" \"fill_alpha\": 0.7\n",
" \"fill_alpha\": 0.5\n",
" },\n",
" {\n",
" \"input_gdf\": source_node,\n",
Expand Down Expand Up @@ -1151,7 +1152,7 @@
" \"legend\": \"isochrone from distance\",\n",
" \"fill_color\": \"red\",\n",
" \"line_color\": \"red\",\n",
" \"fill_alpha\": 0.7\n",
" \"fill_alpha\": 0.5\n",
" },\n",
" {\n",
" \"input_gdf\": isochrones_lines_from_location,\n",
Expand Down
2 changes: 1 addition & 1 deletion example.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_from_web():

# get NETWORK
network_from_web_found = OsmGt.roads_from_location(
location, additionnal_nodes=poi_gdf, mode="vehicle"
location, additional_nodes=poi_gdf, mode="vehicle"
)
# network_from_web_found = OsmGt.roads_from_bbox(bbox, additionnal_nodes=poi_gdf, mode="vehicle")

Expand Down
284 changes: 145 additions & 139 deletions index.html

Large diffs are not rendered by default.

33 changes: 19 additions & 14 deletions osmgt/compoments/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class OsmGtCore(Logger):

_FEATURE_OSM_TYPE: Optional[str] = None

_OUTPUT_EXPECTED_GEOM_TYPE: Optional[str] = None

def __init__(self) -> None:
super().__init__()

Expand Down Expand Up @@ -101,11 +103,6 @@ def from_bbox(self, bbox_value: Tuple[float, float, float, float]) -> None:
# reordered because of nominatim
self._bbox_value = (bbox_value[1], bbox_value[0], bbox_value[3], bbox_value[2])

def _get_study_area_from_bbox(
self, bbox: Tuple[float, float, float, float]
) -> None:
return

def _query_on_overpass_api(self, request: str) -> List[Dict]:
return OverpassApi(self.logger).query(request)[self._QUERY_ELEMENTS_FIELD]

Expand All @@ -121,8 +118,8 @@ def _from_bbox_query_builder(
) -> str:
assert isinstance(bbox_value, tuple)
assert len(bbox_value) == 4
bbox_value_formated = ", ".join(map(str, bbox_value))
query = query.format(geo_filter=bbox_value_formated)
bbox_value_str = ", ".join(map(str, bbox_value))
query = query.format(geo_filter=bbox_value_str)
return f"({query});{out_geom_query};"

def _check_topology_field(self, input_gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
Expand All @@ -134,15 +131,14 @@ def _check_topology_field(self, input_gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame

def get_gdf(self, verbose: bool = True) -> gpd.GeoDataFrame:
if verbose:
self.logger.info("Prepare Geodataframe")
self.logger.info("Prepare GeoDataframe")

if len(self._output_data) == 0:
raise EmptyData(
"Geodataframe creation is impossible, because no data has been found"
"GeoDataframe creation is impossible, because no data has been found"
)

if not isinstance(self._output_data, gpd.GeoDataFrame):
self._check_build_input_data()
# more performance comparing .from_features() method
df: pd.DataFrame = pd.DataFrame(self._output_data)
geometry = df[self._GEOMETRY_FIELD] # TODO check type
Expand All @@ -155,14 +151,23 @@ def get_gdf(self, verbose: bool = True) -> gpd.GeoDataFrame:
else:
output_gdf: gpd.GeoDataFrame = self._output_data

self._check_build_input_data(output_gdf)

output_gdf: gpd.GeoDataFrame = self._clean_attributes(output_gdf)
self.logger.info("Geodataframe Ready")

self.logger.info("GeoDataframe Ready")

return output_gdf

def _check_build_input_data(self) -> None:
if self._output_data is None:
raise ErrorOsmGtCore("Data is empty!")
def _check_build_input_data(self, output_gdf) -> None:
if output_gdf.shape[0] == 0:
raise EmptyData("Data is empty!")

geom_types_found = set(output_gdf[self._GEOMETRY_FIELD].geom_type.to_list())
if geom_types_found != {self._OUTPUT_EXPECTED_GEOM_TYPE}:
raise ErrorOsmGtCore(
f"Output geom type not supported! Only {self._OUTPUT_EXPECTED_GEOM_TYPE} supported ; {geom_types_found} found"
)

def _clean_attributes(self, input_gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
for col_name in input_gdf.columns:
Expand Down
12 changes: 3 additions & 9 deletions osmgt/compoments/poi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import geopandas as gpd
from typing import Tuple
from typing import List
from typing import Optional
from typing import Dict

from osmgt.compoments.core import OsmGtCore
Expand All @@ -11,26 +9,22 @@
from osmgt.core.global_values import poi_query


class ErrorPoiData(Exception):
pass


class OsmGtPoi(OsmGtCore):

_FEATURE_OSM_TYPE: str = "node"

_OUTPUT_EXPECTED_GEOM_TYPE = "Point"

def __init__(self) -> None:
super().__init__()

def from_location(self, location_name: str):
def from_location(self, location_name: str) -> None:
super().from_location(location_name)

request = self._from_location_name_query_builder(self._location_id, poi_query)
raw_data = self._query_on_overpass_api(request)
self._output_data = self.__build_points(raw_data)

return self

def from_bbox(self, bbox_value: Tuple[float, float, float, float]) -> None:
super().from_bbox(bbox_value)

Expand Down
Loading

0 comments on commit 6e79a2f

Please sign in to comment.