<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Recuperando dados do OpenStreetMap
O que é o OpenStreetMap?
O OpenStreetMap (OSM) é um conjunto de dados que visa criar um mapa editável gratuito do mundo, contendo muitas informações sobre o nosso ambiente, ele é um projeto colaborativo global (crowd sourced).
No OSM podemos obter dados, por exemplo, sobre ruas, edifícios e serviços.
O OSM tem uma grande base de usuários com mais de 4 milhões e mais de um milhão de contribuintes que atualizam ativamente o banco de dados do OSM com 3 milhões de mudanças por dia. No total, o OSM contém mais de 4 bilhões de nós que formam a base do mundo mapeado digitalmente, e que o OSM oferece (estatísticas de novembro de 2017).
O OpenStreetMap não é usado apenas para integrar os mapas do OSM como mapas em segundo plano para visualizações ou mapas on-line, mas também para muitas outras finalidades, como roteamento, geocodificação , educação e pesquisa. O OSM é também amplamente utilizado para realizar planejamentos de respostas humanitárias, por exemplo, em áreas de crise (após desastres naturais) e para fomentar o desenvolvimento econômico (veja mais no site Humanitarian OpenStreetMap Team (HOTOSM)).
OSMnx
Uma outroa biblioteca com muitas funcionalidades para GIS em Python é o OSMnx
que pode ser usado para recuperar, construir, analisar e visualizar redes de ruas do OpenStreetMap, e também recuperar dados sobre pontos de interesse, como restaurantes e escolas. Também é fácil conduzir o roteamento de rede com base em caminhada, ciclismo ou direção, combinando as funcionalidades do OSMnx com um pacote de grafos do python chamado NetworkX.
Fazer o download e visualizar os dados do OpenStreetMap com o OSMnx
Um dos recursos mais úteis que o OSMnx fornece é uma maneira fácil para recuperar dados do OpenStreetMap (usando API OverPass).
Neste tutorial, aprenderemos a baixar e visualizar dados do OSM cobrindo uma área específica de interesse.
O OSMnx torna isso muito fácil, pois permite especificar um endereço para recuperar os dados do OpenStreetMap em torno dessa área. Na verdade, o OSMnx usa a mesma API de geocodificação da Nominatim para fazer isso, o que testamos durante o a aula de geocoding.
Vamos recuperar os dados do OpenStreetMap (OSM) especificando "Brasil, Ceará, Fortaleza" como o endereço onde os dados devem ser baixados.
Podemos baixar o pacote OSMnx no nosso ambiente com o seguitne comando
Step1:  Como podemos ver os dados que recuperamos é um objeto de dados especial chamado networkx.classes.multidigraph.MultiDiGraph. 
Um DiGraph é um tipo de dados que armazena vértices e arestas com dados ou atributos opcionais. O que podemos ver aqui é que esse tipo de dado pertence a um módulo Python chamado networkx que pode ser usado para criar, manipular e estudar a estrutura, a dinâmica e possui funções especificas para análise em rede de grafo. O módulo Networkx contém algoritmos que podem ser usados para calcular caminhos mais curtos ao longo das redes rodoviárias usando, por exemplo, o algoritmo de Dijkstra ou A* algorithm.
Vamos ver como é a nossa rede de ruas. É fácil visualizar o gráfico com osmnx com a função plot_graph(). A função utiliza o Matplotlib para visualizar os dados, portanto, como resultado, ele retorna uma figura de matplotlib
Step2:  Agora podemos ver que nosso gráfico contém os vértices ou nós (círculos azuis) e as arestas (linhas cinzas) que conectam esses nós entre si.
Também é possível recuperar outros tipos de recursos de dados do OSM com osmnx, como edifícios ou pontos de interesse (POIs).
Análise de rede em Python
Encontrar um caminho mais curto usando uma rede de ruas específica, é um problema comum em GIS.
Isto ferramente de extrema importância no mundo moderno e está presente em diversas aplicações, por exemplo, os aplicativos de GPS, que são aplicações usadas diariamente para encontrar o roteamento usando algoritmos específicos para encontrar a rota ideal entre dois (ou múltiplos) pontos.
O módulo Networkx fornece muitas ferramentas que podem ser usadas para analisar redes de várias maneiras diferentes. Também contém algoritmos
como o algoritmo deDijkstra ou
A* que são comumente usados para encontrar caminhos mais curtos ao longo da rede de transporte.
Em seguida, testaremos as funcionalidades de roteamento do osmnx encontrando um caminho mais curto entre dois pontos baseados em estradas possuem acesso para carros.
Vamos primeiro fazer o download dos dados do OSM de Fortaleza, mas desta vez incluir apenas os segmentos da rua que são tranquilos. No omsnx é possível recuperar apenas as ruas que são dirigíveis especificando ''drive'' no parâmetro network_type que pode ser usado para especificar que tipos de ruas são recuperadas do OpenStreetMap (outras possibilidades são walk e bike).
Step3:  Agora que foi recuperado apenas as ruas onde é possível dirigir com um carro. Vamos confirmar
isso dando uma olhada nos atributos da rede de ruas. A maneira mais fácil de fazer isso é converter o
gráfico (nós e arestas) em GeoDataFrames (geopandas).
A conversão de um gráfico em um GeoDataFrame pode ser feita utilizando a função graph_to_gdfs(), que retorna os nodes (vértices) e as edges (arestas).
Step4:  Então podemos observar que temos muitas colunas em nosso GeoDataFrame. A maioria das colunas são auto-explicativas, mas a tabela a seguir descreve todas elas.
| Column                                                     | Description                 | Data type         |
|------------------------------------------------------------|-----------------------------|-------------------|
| bridge    | Bridge feature              | boolean           |
| geometry                                                   | Geometry of the feature     | Shapely.geometry  |
| highway  | Tag for roads (road type)   | str / list        |
| lanes      | Number of lanes             | int (or nan)      |
| lenght    | Length of feature (meters)  | float             |
| maxspeed| maximum legal speed limit   | int /list         |
| name        | Name of the (street) element| str (or nan)      |
| oneway    | One way road                | boolean           |
| osmid           | Unique ids for the element  | list              |
| u                              | The first node of edge      | int               |
| v                              | The last node of edge       | int               |
Como os nosso dados de nós e arestas são GeoDataFrames, podemos visualizar eles separadamente, utilizando apenas a função plot().
Step5:  Análise de menor caminho
Vamos agora calcular o caminho mais curto entre dois pontos. Primeiro, precisamos especificar os locais de origem e destino de nossa rota.
O nosso objetivo será obter a rota e a distância percorrida em metros, do departamento de computação para o Shopping Benfica, utilizando a rede rodoviária.
Primeiro precisamos definir a localização da nossa origiem e destino. Para isso podemos usar o OpenStreeMapo ou Google Maps para obter as coordenadas.
Step6:  Em seguida precisamos de uma rede de ruas que apresente pelo menos os pontos de origem e destino. A alternativa mais simples seria carregar toda a rede de ruas da cidade de Fortaleza, porém isso acrescentaria um custo de computação amais. Utilizando os nosso conhecimento, vamos diminuir a rede de busca.
Visualizando as divisões administrativas das AIS, visto na aula passada, podemos ver que o campus do pici está na AIS 6 e o shopping na AIS 5, e que as duas são adjacentes. O módulo OSMnx possui diversas opções para carregar dados do OSM, é uma delas é passando um polígono da área desejada em que se deseja obter o grafo.
Vamos utilizar as divisões administrativas das AIS para obter um grafo reduzido para a nossa análise.
Step7:  Agora vamos utilizar o OSMnx para obter o grafo dentro do nosso polygon. Para isso podemos utilizar a função graph_from_polygon(). Lembrando que queremos somente a rede de carros, então usaremos o parâmetro network_type.
Step8:  Para calcular a menor rota no grafo precisamos que os nodes de origem e destino estejam presentes no grafo. Para isso vamos calcular o nó mais próximo do nosso ponto de origem e do nosso ponto de destino.
Step9:  Agora que já temos os nós de origem e destino, vamos calcular o menor caminho na rede de ruas utilizando o algoritmo de Dijkstra. Para isso podemos usar a função shortest_path do networkx.
Step10:  Como resultado, obtemos uma lista de todos os nós que estão no caminho mais curto.
Poderíamos extrair os locais desses nós do nodes_proj GeoDataFrame e criar uma LineString dos pontos, mas, felizmente, o OSMnx pode fazer isso para nós e podemos traçar o caminho mais curto usando a funçãoplot_graph_route()
Step11:  Para calcular o tamanho da nossa rota em metros, vamos primeiro criar um LineString da nossa rota, depois mudar a e projeção e finalmente usaremos o método length
Para criar o nosso LineString precisamos das informações de latitude e longitude, porém só temos o id dos nós. Então primeiro vamos filtrar dos nossos dados o nós da nossa rota pelo id.
Step12:  Como pode ser visto as coordenadas estão na projeção Mercator, que é a mesma utilizada pelo Google (de onde definimos as nossas coordenadas). Para podermos calcular a distância em metros, vamos primeiro transformar a projeção dos dados para a projeção SIRGAS 2000 / UTM zone 24S (EPSG 31984)
Step13:  Finalmente podemos criar o nosso LineString usando a projeção apropriada para a nossa tarefa.
<ASSISTANT_TASK:>
Python Code:
import osmnx as ox
import matplotlib.pyplot as plt
%matplotlib inline
# Specify the name that is used to seach for the data
place_name = "Brasil, Ceará, Fortaleza"
# Fetch OSM street network from the location
graph = ox.graph_from_place(place_name)
type(graph)
Explanation: Recuperando dados do OpenStreetMap
O que é o OpenStreetMap?
O OpenStreetMap (OSM) é um conjunto de dados que visa criar um mapa editável gratuito do mundo, contendo muitas informações sobre o nosso ambiente, ele é um projeto colaborativo global (crowd sourced).
No OSM podemos obter dados, por exemplo, sobre ruas, edifícios e serviços.
O OSM tem uma grande base de usuários com mais de 4 milhões e mais de um milhão de contribuintes que atualizam ativamente o banco de dados do OSM com 3 milhões de mudanças por dia. No total, o OSM contém mais de 4 bilhões de nós que formam a base do mundo mapeado digitalmente, e que o OSM oferece (estatísticas de novembro de 2017).
O OpenStreetMap não é usado apenas para integrar os mapas do OSM como mapas em segundo plano para visualizações ou mapas on-line, mas também para muitas outras finalidades, como roteamento, geocodificação , educação e pesquisa. O OSM é também amplamente utilizado para realizar planejamentos de respostas humanitárias, por exemplo, em áreas de crise (após desastres naturais) e para fomentar o desenvolvimento econômico (veja mais no site Humanitarian OpenStreetMap Team (HOTOSM)).
OSMnx
Uma outroa biblioteca com muitas funcionalidades para GIS em Python é o OSMnx
que pode ser usado para recuperar, construir, analisar e visualizar redes de ruas do OpenStreetMap, e também recuperar dados sobre pontos de interesse, como restaurantes e escolas. Também é fácil conduzir o roteamento de rede com base em caminhada, ciclismo ou direção, combinando as funcionalidades do OSMnx com um pacote de grafos do python chamado NetworkX.
Fazer o download e visualizar os dados do OpenStreetMap com o OSMnx
Um dos recursos mais úteis que o OSMnx fornece é uma maneira fácil para recuperar dados do OpenStreetMap (usando API OverPass).
Neste tutorial, aprenderemos a baixar e visualizar dados do OSM cobrindo uma área específica de interesse.
O OSMnx torna isso muito fácil, pois permite especificar um endereço para recuperar os dados do OpenStreetMap em torno dessa área. Na verdade, o OSMnx usa a mesma API de geocodificação da Nominatim para fazer isso, o que testamos durante o a aula de geocoding.
Vamos recuperar os dados do OpenStreetMap (OSM) especificando "Brasil, Ceará, Fortaleza" como o endereço onde os dados devem ser baixados.
Podemos baixar o pacote OSMnx no nosso ambiente com o seguitne comando: conda install -c conda-forge osmnx
End of explanation
# Plot the streets
fig, ax = ox.plot_graph(graph)
Explanation: Como podemos ver os dados que recuperamos é um objeto de dados especial chamado networkx.classes.multidigraph.MultiDiGraph. 
Um DiGraph é um tipo de dados que armazena vértices e arestas com dados ou atributos opcionais. O que podemos ver aqui é que esse tipo de dado pertence a um módulo Python chamado networkx que pode ser usado para criar, manipular e estudar a estrutura, a dinâmica e possui funções especificas para análise em rede de grafo. O módulo Networkx contém algoritmos que podem ser usados para calcular caminhos mais curtos ao longo das redes rodoviárias usando, por exemplo, o algoritmo de Dijkstra ou A* algorithm.
Vamos ver como é a nossa rede de ruas. É fácil visualizar o gráfico com osmnx com a função plot_graph(). A função utiliza o Matplotlib para visualizar os dados, portanto, como resultado, ele retorna uma figura de matplotlib:
End of explanation
# Specify the name that is used to seach for the data
place_name = "Brasil, Ceará, Fortaleza"
# Fetch OSM street network from the location
graph_drive = ox.graph_from_place(place_name, network_type='drive')
fig, ax = ox.plot_graph(graph_drive)
Explanation: Agora podemos ver que nosso gráfico contém os vértices ou nós (círculos azuis) e as arestas (linhas cinzas) que conectam esses nós entre si.
Também é possível recuperar outros tipos de recursos de dados do OSM com osmnx, como edifícios ou pontos de interesse (POIs).
Análise de rede em Python
Encontrar um caminho mais curto usando uma rede de ruas específica, é um problema comum em GIS.
Isto ferramente de extrema importância no mundo moderno e está presente em diversas aplicações, por exemplo, os aplicativos de GPS, que são aplicações usadas diariamente para encontrar o roteamento usando algoritmos específicos para encontrar a rota ideal entre dois (ou múltiplos) pontos.
O módulo Networkx fornece muitas ferramentas que podem ser usadas para analisar redes de várias maneiras diferentes. Também contém algoritmos
como o algoritmo deDijkstra ou
A* que são comumente usados para encontrar caminhos mais curtos ao longo da rede de transporte.
Em seguida, testaremos as funcionalidades de roteamento do osmnx encontrando um caminho mais curto entre dois pontos baseados em estradas possuem acesso para carros.
Vamos primeiro fazer o download dos dados do OSM de Fortaleza, mas desta vez incluir apenas os segmentos da rua que são tranquilos. No omsnx é possível recuperar apenas as ruas que são dirigíveis especificando ''drive'' no parâmetro network_type que pode ser usado para especificar que tipos de ruas são recuperadas do OpenStreetMap (outras possibilidades são walk e bike).
End of explanation
# Retrieve only edges from the graph
nodes, edges = ox.graph_to_gdfs(graph_drive)
# Check the data type
print('Data type of edges: ', type(edges))
# Check columns
print(edges.columns)
edges.head(5)
Explanation: Agora que foi recuperado apenas as ruas onde é possível dirigir com um carro. Vamos confirmar
isso dando uma olhada nos atributos da rede de ruas. A maneira mais fácil de fazer isso é converter o
gráfico (nós e arestas) em GeoDataFrames (geopandas).
A conversão de um gráfico em um GeoDataFrame pode ser feita utilizando a função graph_to_gdfs(), que retorna os nodes (vértices) e as edges (arestas).
End of explanation
# plot only the road's network
edges.plot()
Explanation: Então podemos observar que temos muitas colunas em nosso GeoDataFrame. A maioria das colunas são auto-explicativas, mas a tabela a seguir descreve todas elas.
| Column                                                     | Description                 | Data type         |
|------------------------------------------------------------|-----------------------------|-------------------|
| bridge    | Bridge feature              | boolean           |
| geometry                                                   | Geometry of the feature     | Shapely.geometry  |
| highway  | Tag for roads (road type)   | str / list        |
| lanes      | Number of lanes             | int (or nan)      |
| lenght    | Length of feature (meters)  | float             |
| maxspeed| maximum legal speed limit   | int /list         |
| name        | Name of the (street) element| str (or nan)      |
| oneway    | One way road                | boolean           |
| osmid           | Unique ids for the element  | list              |
| u                              | The first node of edge      | int               |
| v                              | The last node of edge       | int               |
Como os nosso dados de nós e arestas são GeoDataFrames, podemos visualizar eles separadamente, utilizando apenas a função plot().
End of explanation
from shapely.geometry import Point
# approximate coord of computer department: -3.746088, -38.574236
# approximate coord of benfica shopping: -3.739631, -38.540785
origin = Point(-3.746088, -38.574236)
destiny = Point(-3.739631, -38.540785)
Explanation: Análise de menor caminho
Vamos agora calcular o caminho mais curto entre dois pontos. Primeiro, precisamos especificar os locais de origem e destino de nossa rota.
O nosso objetivo será obter a rota e a distância percorrida em metros, do departamento de computação para o Shopping Benfica, utilizando a rede rodoviária.
Primeiro precisamos definir a localização da nossa origiem e destino. Para isso podemos usar o OpenStreeMapo ou Google Maps para obter as coordenadas.
End of explanation
import geopandas as gpd
# filename of the ais data
ais_fp = 'data/ais.shp'
# load the ais data
ais_gdf = gpd.read_file(ais_fp)
# separate only the desired data
poly_ais_5 = ais_gdf.loc[ais_gdf['AIS'] == 5, 'geometry'].values[0]
poly_ais_6 = ais_gdf.loc[ais_gdf['AIS'] == 6, 'geometry'].values[0]
poly = poly_ais_5.union(poly_ais_6)
poly
Explanation: Em seguida precisamos de uma rede de ruas que apresente pelo menos os pontos de origem e destino. A alternativa mais simples seria carregar toda a rede de ruas da cidade de Fortaleza, porém isso acrescentaria um custo de computação amais. Utilizando os nosso conhecimento, vamos diminuir a rede de busca.
Visualizando as divisões administrativas das AIS, visto na aula passada, podemos ver que o campus do pici está na AIS 6 e o shopping na AIS 5, e que as duas são adjacentes. O módulo OSMnx possui diversas opções para carregar dados do OSM, é uma delas é passando um polígono da área desejada em que se deseja obter o grafo.
Vamos utilizar as divisões administrativas das AIS para obter um grafo reduzido para a nossa análise.
End of explanation
graph = ox.graph_from_polygon(poly, network_type='drive')
fig, ax = ox.plot_graph(graph)
Explanation: Agora vamos utilizar o OSMnx para obter o grafo dentro do nosso polygon. Para isso podemos utilizar a função graph_from_polygon(). Lembrando que queremos somente a rede de carros, então usaremos o parâmetro network_type.
End of explanation
# Get the x and y coordinates
origin_xy = (origin.x, origin.y)
dest_xy = (destiny.x, destiny.y)
# Find the closest origin and target nodes from the graph (the ids of them)
orig_node = ox.get_nearest_node(graph, origin_xy, method='euclidean')
target_node = ox.get_nearest_node(graph, dest_xy, method='euclidean')
# Show the results
print(orig_node)
print(target_node)
Explanation: Para calcular a menor rota no grafo precisamos que os nodes de origem e destino estejam presentes no grafo. Para isso vamos calcular o nó mais próximo do nosso ponto de origem e do nosso ponto de destino.
End of explanation
import networkx as nx
# Calculate the shortest path
route = nx.shortest_path(G=graph, source=orig_node, target=target_node, weight='length')
# Show what we have
print(route)
Explanation: Agora que já temos os nós de origem e destino, vamos calcular o menor caminho na rede de ruas utilizando o algoritmo de Dijkstra. Para isso podemos usar a função shortest_path do networkx.
End of explanation
# Plot the shortest path
fig, ax = ox.plot_graph_route(graph, route, orig_dest_size=20)
Explanation: Como resultado, obtemos uma lista de todos os nós que estão no caminho mais curto.
Poderíamos extrair os locais desses nós do nodes_proj GeoDataFrame e criar uma LineString dos pontos, mas, felizmente, o OSMnx pode fazer isso para nós e podemos traçar o caminho mais curto usando a funçãoplot_graph_route():
End of explanation
# Retrieve only edges from the graph
nodes, edges = ox.graph_to_gdfs(graph)
# Get the nodes along the shortest path
route_nodes = nodes.loc[route]
route_nodes.head()
Explanation: Para calcular o tamanho da nossa rota em metros, vamos primeiro criar um LineString da nossa rota, depois mudar a e projeção e finalmente usaremos o método length
Para criar o nosso LineString precisamos das informações de latitude e longitude, porém só temos o id dos nós. Então primeiro vamos filtrar dos nossos dados o nós da nossa rota pelo id.
End of explanation
# Change projection of the data
new_epsg = 31984 # more accurate for northeast region
route_nodes_proj = route_nodes.to_crs(epsg=new_epsg)
route_nodes_proj.head()
Explanation: Como pode ser visto as coordenadas estão na projeção Mercator, que é a mesma utilizada pelo Google (de onde definimos as nossas coordenadas). Para podermos calcular a distância em metros, vamos primeiro transformar a projeção dos dados para a projeção SIRGAS 2000 / UTM zone 24S (EPSG 31984)
End of explanation
from shapely.geometry import LineString, Point
# Create a geometry for the shortest path
route_line = LineString(list(route_nodes_proj.geometry.values))
print("tamanho da rota em metros: {:.3f} m".format(route_line.length))
route_line
Explanation: Finalmente podemos criar o nosso LineString usando a projeção apropriada para a nossa tarefa.
End of explanation
<END_TASK>