Mais

Dado um shapefile, como posso retornar o polígono contendo uma localização lat / lon?

Dado um shapefile, como posso retornar o polígono contendo uma localização lat / lon?


Eu tenho um arquivo de forma gerado pelo pacote de produtos ESRI. Não tenho nenhum produto ESRI e meu orçamento não dá suporte à compra deles. Além de questões fiscais, pode haver limitações técnicas com a implantação de produtos ESRI, mas isso é um ponto discutível, uma vez que não temos dinheiro.

Usando .NET e, se necessário, bibliotecas de código aberto, como posso ler os dados do meu arquivo de forma e retornar o polígono que contém uma coordenada de latitude e longitude? Eu vejo isso sendo construído como um código de serviço e dada uma coordenada, ele retorna o polígono. Conceitualmente não é muito difícil, mas não tenho certeza de quais bibliotecas vão ajudar nisso.

Pensamentos?

editar # 1 - Eu me contentaria em retornar a ID ou descrição do polígono ou alguma outra propriedade de string. Se eu quiser mais informações, vou buscar usando o ID ou nome do polígono ou ???

editar # 2 - A solução deve ser algo que eu possa chamar de um serviço. Por exemplo, uma biblioteca que posso chamar de meu código .NET funcionaria perfeitamente. Um aplicativo que deve ser instalado e os dados inseridos por meio de sua IU não funcionarão, pois meu aplicativo será implantado.


SpatiaLite é uma das muitas soluções potenciais. Provavelmente depende um pouco se o shapefile em que você está trabalhando é dinâmico ou é sempre o mesmo arquivo (ou um de alguns arquivos de conteúdo estático), mas carregar o shapefile usando a extensão de tabela virtual VirtualShape ou a função SQL ImportSHP () irá disponibilizá-lo no SpatiaLite.

Em seguida, você pode usar qualquer uma das funções espaciais SpatiaLite, como ST_Contains ou ST_Intersects (depende do que você entende por "contém" - por exemplo, o que acontece se o ponto está na fronteira?) Para selecionar o ponto incluindo alguns ou todos os atributos.

Dependendo do número de linhas, você pode querer usar um índice espacial para auxiliar na pesquisa, embora uma varredura completa da tabela não seja um problema para até alguns milhares de polígonos. Nota: SpatiaLite requer que o índice seja definido e explicitamente incluído em cada operação de pesquisa. Não é suficiente apenas criar o índice.

O uso de C # não é problema - basta usar System.Data.SQLite e carregar a DLL / biblioteca compartilhada como uma extensão.


Há uma tonelada de software livre por aí que permite exportar o polígono e ver as suas coordenadas latitude e longitude.

Sua pergunta foi respondida anteriormente. Como exportar polígonos para CSV com coordenadas?


Geocodificar um endereço e realizar testes de polígono de ponto com GDAL / OGR em Python

Suponha que você tenha uma lista de endereços e queira conectá-los a algum tipo de informação baseada em localização. Por exemplo, seus endereços podem estar espalhados por vários bairros e você deseja descobrir a qual bairro cada endereço pertence, porque você tem mais informações (como renda média, porcentagem de migrantes, etc.) sobre cada bairro e deseja combiná-lo com o seu dados. Em muitos países, as autoridades administrativas reúnem essas informações geográficas e fornecem os dados em seus sites.

No cenário dado, três etapas são necessárias para combinar os endereços com as informações geográficas:

  1. Geocodificar o endereço, ou seja, descobrir as coordenadas geográficas (latitude, longitude) para este endereço
  2. Dado um arquivo com informações geográficas (dados GIS) que formam várias áreas distintas como polígonos, descobrir qual desses polígonos contém o endereço geocodificado
  3. Obtenha as informações necessárias, como um identificador de vizinhança do polígono

Este breve post mostra como fazer isso com os pacotes Python googlemaps e GDAL.

1. Geocodificação

A geocodificação precisa pode ser feita usando o pacote googlemaps, que faz interface com a API do Google Maps. Você precisará obter uma chave de API para usar o serviço. Veja a documentação sobre como fazer isso.

Depois de obter uma chave API e instalar o pacote, é bastante simples geocodificar um endereço. Vamos experimentar com o endereço do WZB:

A estrutura de dados retornada é bastante grande, aqui está um recorte dela:

O mais importante é que o geocodificador sempre retorna um Lista de resultados e quando o endereço de pesquisa é ambíguo, podemos obter vários resultados. Como os resultados são ordenados da certeza mais alta para a mais baixa, geralmente é seguro buscar apenas o primeiro resultado. Em nosso caso, também estamos interessados ​​apenas nas coordenadas geográficas, que estão dentro da geometria e estrutura de localização rarr:

Já é isso em termos de geocodificação! Parece muito simples, mas você deve considerar as seguintes armadilhas em potencial:

  • Você pode obter resultados imprecisos / errados, especialmente quando há erros de digitação nos endereços, códigos postais ausentes, endereços ambíguos, etc. Você deve sempre verificar os resultados 1) automaticamente quanto à plausibilidade (por exemplo, ao trabalhar com dados de um país específico, verifique se as geocoordenadas estão todas dentro de uma faixa plausível para aquele país) e 2) manualmente, verificando uma amostra de seus dados
  • Algo pode dar errado durante a solicitação da API. A conexão com a Internet pode ser interrompida, o servidor pode não responder, etc. Nesses casos, uma exceção será levantada. Você deve envolver sua solicitação em um bloco try-except e registrar o evento para investigação posterior
  • É claro que, com um conjunto de dados real, precisaríamos geocodificar muitos endereços. Esteja ciente de que o serviço API do Google emprega limitação de taxa e negará outras solicitações por 24 horas assim que você ultrapassar o limite de 2.500 solicitações por dia. Veja esta tabela para mais informações.

2. Testes ponto-no-polígono com GDAL / OGR

Suponha que agora você queira combinar seus endereços com outras informações regionais, por exemplo, com dados sobre seu respectivo bairro, comunidade ou outro. Às vezes, é suficiente usar informações na estrutura address_components da resposta da API do Google porque essa estrutura já contém informações a que área um endereço pertence em diferentes níveis administrativos:

Podemos verificar aqui que este endereço se encontra no estado de Berlim, e ali no distrito de Mitte. No entanto, essas informações podem não ser precisas o suficiente para seus objetivos. Por exemplo, os dados sobre vizinhanças geralmente são muito mais refinados. As informações geográficas dessa escala são frequentemente fornecidas por autoridades administrativas e podem estar disponíveis para download em diferentes formatos GIS, como KML, KMZ, GML, GeoJSON ou Shapefile (.shp). Esses arquivos podem ser processados ​​em Python com o pacote GDAL. GDAL significa Geospatial Data Abstraction Library - uma biblioteca de software abrangente para lidar com uma ampla variedade de formatos de dados geoespaciais. Podemos usá-lo para processar os formatos GIS mencionados acima.

Se você deseja instalar o pacote Python GDAL em todo o sistema em um sistema operacional Linux, você pode simplesmente instalar python-gdal ou python3-gdal via apto ou outros gerenciadores de pacotes. Instalando em um Python Ambiente Virtual (venv) é recomendado, mas um pouco mais complicado: primeiro, instale as bibliotecas libgdal e libgdal-dev. Descubra qual versão do pacote está disponível em todo o sistema, por exemplo, executando apt show python3-gdal. No Ubuntu 16.04, isso fornece GDAL versão 2.1.3. Em seguida, defina os caminhos de arquivo de cabeçalho corretos no shell do terminal:

Finalmente, instale a versão correta do pacote em seu venv via pip: pip install GDAL == 2.1.3.

Vamos continuar usando um arquivo GIS que é fornecido pelo Berlin Departamento de Desenvolvimento Urbano e Habitação do Senado. Vamos trabalhar com algo chamado Lebensweltlich orientierte Räume (LOR), que são espaços hierárquicos que vão de 60 áreas maiores a 447 bairros de granulação fina em Berlim. Cada uma dessas áreas (LORs) pode ser associada a um rico conjunto de dados, por exemplo, do site Berlin Open Data. Mas, para fazer isso, primeiro precisamos identificar o número LOR de nossos endereços. Podemos fazer isso processando um arquivo GIS que contém as áreas LOR com seu número LOR associado e verificando qual área LOR contém nosso endereço fornecido, ou seja, nossas geo-coordenadas já obtidas. O departamento do senado fornece um arquivo GIS no formato KMZ em seu site. É importante observar que este arquivo usa o sistema de coordenadas WGS 84, que é o mesmo sistema de coordenadas que a API do Google usa para geocodificação. Se nosso arquivo GIS usasse outro sistema de coordenadas diferente de WGS 84, precisaríamos converter as coordenadas antes de usá-las, caso contrário, qualquer processamento posterior não funcionaria!

Antes de processar o arquivo com Python, devemos dar uma olhada nele usando um aplicativo GIS como o QGIS, que é uma ferramenta de código aberto disponível para a maioria dos sistemas operacionais. Usando o & # 8220painel de navegação & # 8221 à esquerda, você pode simplesmente clicar duas vezes em um arquivo KMZ para exibi-lo. Aqui podemos ver as áreas projetadas dos 447 bairros LOR de Berlim no arquivo & # 8220Planungsraum_FL.kmz & # 8221:

Outra ferramenta útil do QGIS é o botão & # 8220Identify Features & # 8221 na parte superior. Os recursos são as geometrias em seu arquivo GIS e com esta ferramenta você pode selecionar geometrias individuais e ver seus atributos. No nosso caso, isso significa que podemos selecionar os polígonos das áreas de vizinhança. No lado direito, será aberto um painel que mostra os atributos desta área. O único atributo importante para nós é & # 8220Name & # 8221, que inclui o código LOR:

Agora que identificamos o atributo que precisaremos extrair, podemos começar a trabalhar com o arquivo KMZ em Python. Primeiramente, importamos o módulo GDAL necessário, carregamos um driver para lidar com arquivos KML / KMZ e, em seguida, abrimos nosso arquivo KMZ:

Cada arquivo GIS organiza suas geometrias em camadas. Vamos ver quantas camadas estão dentro deste arquivo e selecionar uma camada para trabalhar:

Abrimos o arquivo com as 447 áreas do bairro. Vamos verificar se realmente temos 447 & # 8220 recursos & # 8221 (

Então, isso parece certo! Vamos dar uma olhada dentro de um recurso específico:

Podemos ver que, para um determinado recurso, podemos extraí-lo & # 8217s LOR usando o atributo & # 8220Name & # 8221. Agora, a parte crucial é: como decidimos se um endereço, ou seja, seu ponto geocodificado, está dentro de uma área, ou seja, uma geometria de recurso & # 8217s? Felizmente, GDAL fornece uma função para isso, ou seja, o método Contains () de um Geometria objeto. Ele testa se uma geometria (em nosso caso: uma área vizinha) contém outra geometria (uma coordenada de um endereço). Para usá-lo, precisamos primeiro converter nossa coordenada obtida na API do Google em um objeto Geometria:

Isso retorna False porque o endereço WZB não está contido na primeira área LOR que selecionamos dos 447 recursos. Claro que precisamos verificar todas as áreas para o ponto. Basicamente, temos todas as informações agora para atingir nosso objetivo. O que sobrou é um loop que faz as verificações de um determinado ponto e retorna o LOR se o ponto estiver contido em uma geometria do elemento & # 8217s:

O código LOR & # 821601011105 & # 8217 para o endereço WZB parece correto, pois os nomes das áreas hierárquicas associadas a este código são 01-Mitte, 01-Zentrum, 11-Tiergarten Süd, 05-Nördl. Landwehrkanal.

Observe que este método implementado rapidamente é uma abordagem de & # 8220 força bruta & # 8221. Quando você tem muitos endereços e / ou muitas geometrias em um arquivo GIS, o processo de verificação de todos os endereços com todas as geometrias disponíveis pode ficar muito lento. Você pode melhorar o desempenho:

  • aproveitar hierarquias geográficas, se disponível
  • calculando primeiro o centróide de todas as geometrias de recursos, em seguida, para cada ponto calculando as distâncias até os centróides, classifique por distância ascendente e, em seguida, faça as verificações de ponto no polígono
  • use computação em todas as CPUs disponíveis por meio de multiprocessamento.

Mais coisas que podem ser feitas com GDAL são explicadas no livro de receitas GDAL / OGR.


Determine o fuso horário com GeoTools de shapefiles

Os fusos horários definem a diferença do respectivo horário local para o Horário de Greenwich (GMT) e as regras para a mudança do horário de verão. Com as possibilidades existentes de troca global online de dados e informações, o conhecimento exato do fuso horário do parceiro de comunicação desempenha um papel importante para evitar mal-entendidos e erros.

Fusos horários

Devido ao uso generalizado de dispositivos GPS ou geolocalização com base em endereços IP, muitas vezes não é um grande problema obter as coordenadas geográficas de um lugar. A determinação do fuso horário a partir dessas coordenadas não é, portanto, uma questão trivial, porque os limites dos fusos horários não seguem regras uniformes, mas são baseados em - temporariamente mutáveis ​​- circunstâncias políticas e geográficas. Assim, os limites do fuso horário são iguais aos limites dos estados na Europa Central. A sua denominação segue o esquema "Europa / capital". Por exemplo, a Alemanha pertence ao fuso horário Europa / Berlim, a França à Europa / Paris e a Croácia à Europa / Zagreb.

Para países com grandes áreas, como Canadá ou Estados Unidos, essa regra não se aplica mais, porque uma subdivisão do território em vários fusos horários é necessária. Cada país pode lidar com a divisão concreta como quiser. Nos EUA existem além dos grandes fusos horários como América / Los_Angeles, América / Chicago ou América / New_York alguns pequenos fusos horários para condados, por exemplo, América / Kentucky / Louisville ou América / Indiana / Indianápolis.

Em alto mar, em águas internacionais, por outro lado, o fuso horário se mantém estritamente dentro da longitude. Os fusos horários são aqui de 15 ° de largura e têm nomes como Etc / GMT para a zona em torno do meridiano zero, Etc / GMT + 1 para a zona em torno de 15 ° Oeste ou Etc / GMT-1 em 15 ° Leste. O cálculo do fuso horário de um navio em águas internacionais é, portanto, possível por meio de uma equação simples. Escrito em Java, pode ser assim:

Shapefiles: Um mapa no software

Em terra, esse método simples não funciona mais. Aqui é necessário um mapa preciso, que contém os limites dos fusos horários e seus nomes. Logicamente, este mapa não deve consistir em papel, mas deve ser avaliado por software. Um formato frequentemente usado para esses mapas "eletrônicos" é o arquivo de forma ESRI. Este é um mapa vetorial que permite o mapeamento de formas geométricas exatas por pontos, linhas e polígonos. Além disso, os atributos podem ser definidos para anexar nomes geográficos e propriedades à geometria.

Felizmente, Eric Muller apresenta em efele.net/maps/tz/ shapefiles para diferentes regiões para download. O arquivo tz_world.zip contém os fusos horários de todo o mundo como polígonos. Ele representa um bom ponto de partida para novos experimentos.

Esses shapefiles não são mais suportados. Uma alternativa é o construtor de limite de fuso horário de Evan Siroky. Na página Releases estão os shapefiles timezones.shapefile.zip gerados a partir de dados reais do OpenStreetMap.

Primeiro você deve descompactar o arquivo zip em um diretório vazio. Os arquivos sempre pertencem um ao outro! Embora no software geográfico comum, o arquivo tz_world.shp resp. combinado_shapefile.shp é chamado de "arquivo de forma", os outros arquivos (.dbf, .prj,.) devem estar presentes no mesmo diretório também!

Java e GeoTools

Uma boa ferramenta para lidar com shapefiles e dados geográficos é o Open Source Java Toolkit GeoTools. O download e a configuração do ambiente de desenvolvimento são descritos no guia de início rápido. Usei Ivy e Ant para isso: a linha

no dependências seção de ivy.xml faz o download de todos os arquivos JAR necessários do GeoTools versão 14.1 para funcionar com shapefiles. No entanto, GeoTools nem sempre pode ser encontrado nos repositórios Maven / Ivy padrão, então tive que adicionar o repositório Osgeo explicitamente a ivysettings.xml:

Após essas etapas preparatórias, ele pode ir diretamente para a programação. O código-fonte completo está disponível no Github como repositório Git tzdataservice.

Lendo os shapefiles

Uma vez que a leitura dos shapefiles pode ser uma operação relativamente longa, faz sentido terceirizar esta etapa em seu próprio método. Responsáveis ​​pelo carregamento de shapefiles são as classes ShapefileDataStoreFactory e ShapefileDataStore das bibliotecas GeoTools. A configuração das propriedades apropriadas antes do carregamento causa a geração de um índice espacial, o que acelera a busca baseada em localização posteriormente. O resultado do carregamento é um SimpleFeatureSource que é o ponto de partida para todas as operações seguintes:

Análise do esquema

Após o carregamento bem-sucedido, você pode imprimir as propriedades do arquivo de forma:

Esta função aplicada a tz_world.shp dá o resultado:

Isso significa que tz_world contém dois recursos: Uma vez que a geometria do polígono the_geom e, por outro lado, os nomes (IDs) dos fusos horários como uma string em TZID. O arquivo de forma de evansiroky / timezone-boundary-builder tem uma estrutura semelhante, mas o nome do atributo de fuso horário é tzid aqui. A geometria possui o sistema de referência SRID 4326, ou seja, os pontos são codificados no sistema de referência WGS84 por meio de coordenadas geográficas de 180 ° Oeste a 180 ° Leste e 90 ° Sul a 90 ° Norte. É exatamente o mesmo sistema que aplicativos de mapas populares como o Google Maps e OpenStreetMap ou o sistema GPS estão usando.

Filtrar por coordenadas

A determinação do fuso horário a partir de coordenadas geográficas fornecidas é realizada em duas etapas: Primeiro, a função de filtro contém é aplicado ao featureSource. A função de filtro obtém o nome da geometria the_geom e as coordenadas geográficas (x, y) como parâmetros. O resultado da filtragem é um SimpleFeatureCollection contendo o polígono no qual o ponto pesquisado está localizado. (Se esse polígono não existir, a coleção está vazia.) A segunda etapa determina o valor do atributo tzid (resp. TZID para efele.net) a partir do resultado que contém o nome do fuso horário:

Pesquise nas águas costeiras territoriais

Com os dois métodos descritos anteriormente, agora é possível determinar o fuso horário em continentes, ilhas e em águas internacionais. O que falta são as águas costeiras pertencentes ao território estadual. Suas bordas não estão incluídas em tz_world.shp.

Os arquivos de forma mais recentes do construtor de limite de fuso horário já incluem as águas costeiras! Portanto, o seguinte algoritmo não precisa ser aplicado.

Com os shapefiles do efele.net você pode estimar as fronteiras com a regra de que as águas costeiras devem ter uma dimensão máxima de 12 milhas náuticas (cerca de 22 km). Com essas informações, você pode usar o filtro dentro de que também encontra pontos próximos a um polígono. Infelizmente, a possibilidade de passar uma unidade de comprimento, como "km", para o filtro não está implementada. GeoTools interpreta o valor numérico sempre relativo ao sistema de referência do mapa. O valor 0,1 usado no código de amostra, portanto, significa 0,1 °. São aproximadamente 11 km na direção norte-sul.

Atuação

Particularmente interessante é a velocidade do algoritmo e sua precisão. Para tanto, usei como entrada o arquivo de texto cities15000.txt de geonames.org. Ele contém as coordenadas e fusos horários de 23461 lugares em todo o mundo. Um computador com processador Core2 Quad Q8400 fabricado em 2010 precisou de quatro minutos e meio para determinar os fusos horários de todos os 23461 registros, que são apenas 11 ms por local. Os resultados foram diferentes para 407 registros, ou seja, um erro de 1,7%. Uma análise dos erros não trouxe clareza se os erros estão no shapefile, no algoritmo ou na base de dados de geonames.

No entanto, o desempenho muito bom ocorre apenas quando o arquivo de forma é carregado apenas uma vez para todos os 23461 registros. Uma inicialização repetida que chama openInputShapefile pois cada coordenada degradaria o desempenho drasticamente.

Serviço de internet

Por fim, um serviço da web REST agora deve fornecer o método para determinar o fuso horário a partir das coordenadas. O serviço pode ser implementado de forma que o carregamento e a indexação do arquivo de forma ocorram apenas uma vez. A determinação de um único fuso horário pode ser realizada muito rapidamente, pois todos os dados necessários já estão na memória. A utilização de HTTP e REST como protocolos de comunicação permite que até clientes, não programados em Java, determinem o fuso horário. Para minha ferramenta GEOPosition eu uso, por exemplo, PHP com curl como cliente.

Java 7 define com JAX-RS um padrão para declarar serviços da web RESTful. Para ativar e executar esse serviço com Java SE 7, você também precisará de uma implementação JAX-RS. O óbvio é usar a implementação de referência Jersey. Você pode instruir Ivy a baixar todos os JARs de Jersey necessários adicionando as linhas

ao dependências seção de ivy.xml. Depois disso, ele pode ir diretamente para a implementação do método de serviço da web. As anotações JAX-RS @GET, @Path e @Produces definem o método HTTP para chamar o serviço (GET), o caminho URL relativo (bylonlat //) e o tipo de resultado (texto simples). A implementação tenta primeiro determinar o fuso horário do arquivo de forma. Se o resultado estiver vazio, ele calcula o fuso horário a partir da longitude (TzDataEtc):

Para completar o programa um a Principal função é necessária. Ele executa o carregamento único do arquivo de forma e inicia o servidor Java 7 HTTP integrado na porta 28100. Você pode usar outras portas, é claro. O servidor está vinculado apenas à interface de loopback com o endereço IP 127.0.0.1 por motivos de segurança. A definição da classe possui a anotação JAX-RS @Path. Quando o servidor HTTP é iniciado, Jersey pesquisa todas as classes para esta anotação e as registra como um serviço da web no caminho especificado.

O programa do servidor requer o caminho para o arquivo de forma como argumento da linha de comando:

Agora você pode inserir um URL como http: // localhost: 28100 / tz / bylonlat / 9/50 no navegador. Deve então responder o fuso horário para as coordenadas longitude 9 ° Leste e latitude 50 ° Norte. Ou você pode usar ondulação, o "canivete suíço" para o desenvolvedor da web:

Conclusão

Um novo teste com cities15000.txt demonstra a função do serviço da web. Como esperado, o desempenho é pior do que a chamada direta, mas ainda é muito bom com cerca de 60 ms por consulta. Além disso, o servidor é capaz de processar solicitações simultâneas em vários threads em paralelo.

O serviço da web está em execução estável em meu site há vários anos. Ele fornece informações de fuso horário para a ferramenta GEOPosition. Ele mostra - além do fuso horário - as coordenadas, a altitude acima do nível do mar e os horários do nascer e do pôr do sol em qualquer local da Terra. Para poder exibir o último na hora local, o conhecimento do fuso horário exato também é necessário.


Crie exibições de mapa com dados geográficos

Existem muitos conjuntos de dados geoespaciais que contêm dados com coordenadas em latitude e longitude em unidades de graus. Este exemplo ilustra como importar dados geográficos com coordenadas em latitude e longitude, exibir dados geográficos em uma exibição de mapa e personalizar a exibição.

Em particular, este exemplo ilustra como

Importar vetores geográficos específicos e conjuntos de dados raster

Crie exibições de mapa e visualize os dados

Exibir vários conjuntos de dados em uma única exibição de mapa

Personalize a exibição de um mapa com uma régua de escala e seta para o norte

Personalize a exibição de um mapa com um mapa inserido

Exemplo 1: Importar dados vetoriais geográficos de polígono

Os dados vetoriais geográficos podem ser armazenados em uma variedade de formatos diferentes, por exemplo formatos shapefile e GPS Exchange (GPX). Este exemplo importa dados vetoriais geográficos de polígono de um arquivo de forma. Os vértices em um arquivo de forma podem estar em coordenadas geográficas (latitude e longitude) ou em um sistema de referência de coordenadas projetadas.

Leia os limites dos estados dos EUA no arquivo usastatehi.shp incluído no software Mapping Toolbox & # 8482. Os limites do estado estão em latitude e longitude.

Exemplo 2: Exibir dados vetoriais geográficos de polígono

Exibe os dados vetoriais geográficos do polígono nos eixos de um mapa. Como a extensão geográfica está nos Estados Unidos, você pode usar o usamap para configurar os eixos do mapa. Use o geoshow para projetar e exibir os dados geográficos nos eixos do mapa. Exiba uma cor do oceano no fundo, definindo a cor do rosto do quadro.

Exemplo 3: Importar dados vetoriais geográficos de ponto e linha

Importe dados vetoriais geográficos de ponto do arquivo boston_placenames.gpx incluído com o software Mapping Toolbox & # 8482. O arquivo contém coordenadas de latitude e longitude de feições de pontos geográficos em parte de Boston, Massachusetts, EUA. Use gpxread para ler o arquivo GPX e retornar um vetor geoponto.

Importe dados vetoriais de linha do arquivo sample_route.gpx incluído com o software Mapping Toolbox & # 8482. O arquivo contém coordenadas de latitude e longitude para uma rota GPS do Aeroporto Internacional Boston Logan para The MathWorks, Inc em Natick Massachusetts, EUA. Use gpxread para ler o arquivo GPX e retornar um vetor geoponto.

Exemplo 4: Exibir dados vetoriais geográficos de ponto e linha

Exiba os dados vetoriais geográficos em eixos de mapa centralizados no estado de Massachusetts, usando os dados dos limites do estado e os arquivos GPX. As coordenadas de todos esses conjuntos de dados estão em latitude e longitude.

Encontre o limite do estado para Massachusetts.

Use usamap para configurar os eixos do mapa para a região ao redor de Massachusetts. Pinte o oceano definindo a cor do rosto da moldura. Exiba os limites do estado e destaque Massachusetts usando geoshow para exibir os dados geográficos nos eixos do mapa. Como a rota GPX é um conjunto de pontos armazenados em um vetor de geoponto, forneça as coordenadas de latitude e longitude para geo-mostrar a rota como uma linha.

Exemplo 5: definir limites de latitude e longitude com base na extensão dos dados

Amplie o mapa calculando novos limites de latitude e longitude para o mapa usando a extensão dos nomes de locais e dados de rota. Aumente os limites em 0,05 graus.

Construa um mapa de eixos com os novos limites e exiba os dados geográficos.

Exemplo 6: Importar dados raster geográficos

Os dados raster geográficos podem ser armazenados em uma variedade de formatos diferentes, por exemplo, formatos GeoTIFF, Esri Grid, DTED e ENVI. Para ler dados nesses formatos, use a função readgeoraster.

Para ler uma imagem associada a um arquivo mundial, use as funções imread e worldfileread. Use imread para ler a imagem e worldfileread para ler o worldfile e construir um objeto de referência espacial. Para este exemplo, importe dados para a região ao redor de Boston, Massachusetts. As coordenadas da imagem estão em latitude e longitude.

Exemplo 7: Exibir dados raster geográficos

Exibe a imagem RGB nos eixos do mapa. Os limites do mapa são definidos para os limites definidos pelo objeto de referência espacial, R. As coordenadas dos dados estão em latitude e longitude.

Exemplo 8: Exibir vetor geográfico e dados raster

Você pode exibir dados raster e vetoriais em uma única exibição de mapa. Como as coordenadas de todos esses conjuntos de dados estão em latitude e longitude, use o geoshow para exibi-los em um único mapa. Configure novos limites com base nos limites da rota, nomes de locais e a imagem geral.


Trabalho com dados geoespaciais em Python

Os dados geoespaciais estão se tornando um conjunto de dados cada vez mais poderoso para uma variedade de aplicativos. Este tipo de dado, que incorpora um elemento geográfico, é uma ótima representação da “Revolução do Big Data” como um todo devido à sua granularidade, tamanho, disponibilidade e flexibilidade. Linguagens de programação modernas oferecem a capacidade de trabalhar com esse tipo de dados, algo que antes só era possível por meio de softwares especializados.

Python, a linguagem que usaremos em nossos exemplos, oferece muitos pacotes para trabalhar com dados geoespaciais e seus tipos de arquivo relevantes. Especificamente, usamos xarray, netCDF4, geopandas e shapely. A instalação desses pacotes nem sempre é simples devido às muitas bibliotecas que precisam ser instaladas como dependências.

Em nossa experiência, descobrimos que configurar um ambiente virtual é a maneira mais simples e limpa de instalar com êxito todos os pacotes relevantes. Um ambiente virtual Python é uma caixa de areia isolada para projetos Python. Isso permite que os projetos tenham suas próprias dependências, independentemente das dependências de outros projetos. Ambientes virtuais também evitam problemas relacionados à versão ao trabalhar com pacotes mais antigos, pacotes esotéricos e compartilhamento de código entre desenvolvedores.

Este código foi executado em Python 3.6.6 e Conda 4.5.10. no Mac OS El Capitan 10.11.4

Recomendamos enfaticamente o uso do Anaconda para gerenciar as versões dos pacotes.

Para configurar o ambiente virtual, abra o terminal e execute os seguintes comandos (isso assume que você está no diretório correto ou tem python em suas variáveis ​​de caminho):

env_name é o nome do ambiente que você está criando, sem aspas são necessárias. O comando de ativação de fonte inicializa o ambiente e coloca você nele.

Agora seu ambiente precisará de novos pacotes. Por ser um ambiente virtual baseado em conda, muitos pacotes básicos virão pré-instalados. Instalamos o Jupyter para começar a usar o seguinte comando:

conda install -n env_name package_name

Ambientes virtuais permitem que você defina a versão do pacote também. Simplesmente modifique o comando acima com package_name = X.X onde X.X é o número da versão relevante para o pacote. Para fins de trabalho de dados geoespaciais, instalamos os seguintes pacotes:

4. bem formada versão 1.6.4.post1

Finalmente, se estiver usando Jupyter - que também recomendamos, execute o seguinte comando:

“Nome para mostrar no Jupyter” é o nome que você gostaria que fosse exibido ao listar os kernels em um Notebook Jupyter. Depois que esse comando for executado, podemos iniciar um bloco de notas Jupyter como normalmente faríamos e selecionar o novo ambiente que acabamos de criar como um kernel no Jupyter.

Recuperando Dados NOAA

Agora que configuramos nosso ambiente virtual, podemos obter alguns dados da Administração Oceânica e Atmosférica Nacional (NOAA). A NOAA, por meio dos Centros Nacionais de Informações Ambientais (NCEI), fornece acesso a dados para rastreamento de dados atmosféricos, oceanográficos, costeiros e geofísicos. Aparentemente, você pode até obter dados que descrevem recursos na superfície do sol:

“Das profundezas do oceano à superfície do sol e de registros de gelo de milhões de anos a imagens de satélite quase em tempo real, a NCEI é a autoridade líder do país em informações ambientais.”

Os dados que estamos usando em nosso exemplo serão da Análise de Precipitação Diária baseada em Medidor Unificado Global da CPC. Este conjunto de dados tem dados diários que remontam a 1979, cobrindo o globo em etapas de 0,5 grau de longitude e latitude. Os próprios dados consistem em medições de medidor em estações para uma geografia definida. As observações do medidor são críticas na construção de análises de precipitação, mas discutiremos esse conjunto de dados em profundidade em outra peça.

Os dados podem ser acessados ​​por meio de um site FTP administrado pela NOAA e podem ser baixados aqui: ftp://ftp.cdc.noaa.gov/Datasets/cpc_global_precip/

Nosso GitHub possui código para baixar esses dados usando python, mas também é possível baixar manualmente. Os arquivos estão no formato netCDF (Network Common Data Form). Os arquivos netCDF4 são comumente usados ​​para manter grandes quantidades de dados espaciais. Em particular, é uma maneira conveniente de armazenar dados da grade como uma série temporal.

Anteriormente, instalamos alguns pacotes em nosso ambiente virtual que ajudam o Python a lidar com arquivos netCDF. In particular, we xarray’s open_dataset function to open our .nc files. xarray provides the ability to compute on netCDF frames much in the way pandas provides the ability to compute on panel data. xarray also contains functions that allow data to easily to be converted to DataFrames and vice versa. For familiarity, we convert netCDF data to DataFrames in this example. The following function can open netCDF files and return a monthly time series of rainfall for our chosen location and year range:

So now we are up and running with some NOAA data can dig into the analysis.

Part 2: Tag Missing Data Using Shapefiles

Find Missing Data

In order to start tagging missing data, we want to take a more granular look than the one provided by the function in our earlier post. Luckily some of the core code of our previous function can easily be reworked in order to concatenate the raw data into a DataFrame:

To start, stats only contains raw data from the .nc files in the form of a DataFrame. The DataFrame has four columns: [lat, lon, time, precipitation]. Time is date with daily granularity.

We can send stats to the following function and process the data to find the number of locations missing x days of data for year y:

We trim out data for Antarctica and the Arctic because our focus is precipitation analysis to better understand vegetation trends, but this is not necessary for other types of analysis. Those regions actually have a lot of data as its crucial to studies on climate change.

Now that we have an understanding of the gaps in our data, we can dig further to look at the missing days by location:

This function returns a DataFrame where each row is lat and lon, a year, and the number of missing days of data for that lat and lon. While this is useful, it would be much easier to understand if we could get a country and state level tagging of each lat and lon. In order to tag the data we will need to use shapefiles.

Working with Shapefiles

Shapefiles store geometric locations and attributes such points, lines, and polygons. Using a shapefile we can create polygons and define their borders in terms of (lat, lon) pairings. Specifically, we will be utilizing the Database of Global Administrative Areas (GADM) files that have pre-defined polygons that describe every country on Earth. The files have six levels of increasing granularity. For our purposes, we use level 2 which is able to give a country and state breakdown.

The GADM files can be downloaded by country or by world. World is easy enough to work with but if you do want to download by country to save space we have a module that can stitch shapefiles together in a DataFrame. In order to do this, we need to use the geopandas package which has the ability to read shapefiles as well as functions for spatial operations with polygons all in a convenient pandas like DataFrame:

In order to stitch the files together, we must first create a list of geopandas frames and then use panda’s concat function. Looking at the data from our shapefile, we see that there is a column called “geometry” which lays out polygons for the associated country and state in NAME_0 and NAME_1, respectively. Now we can check to see where our lat, lon pairs with missing data are located.

Using Geopandas to Tag Missing Data

In order to get our geographic tagging, we will have to convert our lat and lon pairs into POINT objects and then utilize geopandas sjoin which allows for joining on a “within” function. This checks to see if a POINT is within a POLYGON

Consider a data frame called unique_locations with a column of lats and a column of lons that represent all unique lat, lon pairings in our NOAA data with missing data:

from shapely.geometry import Point, Polygon

CRS is a coordinate reference system. This needs to be specified in order to complete the join. More info on CRS can be found in the geopandas docs http://geopandas.org/projections.html

Visit Arbol’s GitHub for more information on our project.

Arbol makes automated payments based on weather outcomes using smart contracts and third-party weather data.


1.9 Creating a Square Polygon Grid Over a Study Area

Recently researchers have been creating grids for analyses of various shapes. We already explored how to create a hexagonal grid but now we will learn how to create a square grid within the extent of a pre-defined study area. This method requires a few more steps but square polygon grids and the resulting adjacency matrix are common in disease epidemiology and will be used in future exercises.

  1. Exercise 1.9 - Download and extract zip folder into your preferred location
  2. Set working directory to the extracted folder in R under File - Change dir.
  3. First we need to load the packages needed for the exercise

muleys <-read.csv("muleysexample.csv", header=T)
summary(muleys$id)
str(muleys)
#Remove outlier locations
newmuleys <-subset(muleys, muleys$Long > -110.50 & muleys$Lat > 37.8
& muleys$Long < -107)
muleys <- newmuleys

#Make a spatial data frame of locations after removing outliers
coords<-data.frame(x = muleys$Long, y = muleys$Lat)
crs<-"+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
head(coords)

deer.spdf <- SpatialPointsDataFrame(coords= coords, data = muleys, proj4string =
CRS(crs))
head(deer.spdf)
proj4string(deer.spdf)

xy <- expand.grid(x = x, y = y)
class(xy)
str(xy)

#Identifiy projection before creating Spatial Points Data Frame
crs2<-"+proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0
+y_0=0+ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
grid.pts<-SpatialPointsDataFrame(coords= xy, data=xy, proj4string = CRS(crs2))
plot(grid.pts)
gridded(grid.pts)
class(grid.pts)

x <- seq(from = -1155027, to = -1106865, by = 1500)
y <- seq(from = 1695607, to = 1739463, by = 1500)

##BE SURE TO RUN CODE FROM XY CREATION THROUGH NEW2 AGAIN THEN BEFORE CODE BELOW!!


NetCDF

NetCDF (network Common Data Form) is a:

  • Self-Describing
  • Portable
  • Scalable
  • Appendable
  • Sharable
  • Archivable

data format standard for exchanging scientific data.

Self-describing? Portable? Scalable? Appendable? Sharable? Archivable?
Information describing the data contents of the file are embedded within the data file itself. This means that there is a header which describes the layout of the rest of the file, in particular the data arrays, as well as arbitrary file metadata in the form of name/value attributes. A NetCDF file is machine-independent i.e. it can be accessed by computers with different ways of storing integers, characters, and floating-point numbers.For instance, issues such as endianness being addressed in the software libraries. A small subset of a large dataset may be accessed efficiently. Data may be appended to a properly structured NetCDF file without copying the dataset or redefining its structure. One writer and multiple readers may simultaneously access the same NetCDF file. Access to all earlier forms of NetCDF data will be supported by current and future versions of the software.

The netCDF project homepage is hosted by the Unidata program at the University Corporation for Atmospheric Research (UCAR).

As all self-describing data formats, netCDF includes a standard API (Application program interface) and portable data access libraries in a variety of languages, including python. There are netCDF tools that can open and work with arbitrary netCDF files, using the embedded descriptions to interpret the data.

What does it really mean when we say that a netCDF file is self-describing? Let’s find out with an example “MITgcm_state.nc”. If you do not have downloaded the metos_python data for this lesson, please see the setup instructions).

In this example, we will be looking at the metadataof a netCDF file. For this we open the netCDF file with the netCDF4 python package you were asked to install.

Check a netCDF file?

Most of the time, netCDF filename extensions are either .nc or .nc4. However, it is not a mandatory requirement so it is useful to learn to check if a file is a netCDF file:

file is a bash shell command and is not a netCDF utility. You can use it for any kind of files and it attempts torecognize its data format.

NetCDF and python?

The most common low-level python packages to handle netcdf is called netcdf4 python package. The functionalities covered by this python package are close to those covered by Unidata netCDF library.

Start a new jupyter notebook and enter:

Creating netCDF files

All of the following code examples assume that the netcdf4-python library has been imported:

Create an empty netCDF4 dataset and store it on disk

Then you should find a new file called “foo.nc” in your working directory:

The Dataset constructor defaults to creating NETCDF4 format objects. Other formats may be specified with the format keyword argument (see the netCDF4-python docs).

The first argument that Dataset takes is the path and name of the netCDF4 file that will be created, updated, or read. The second argument is the mode with which to access the file. Use:

  • w (write mode) to create a new file, use clobber=True to over-write and existing one
  • r (read mode) to open an existing file read-only
  • r+ (append mode) to open an existing file and change its contents

Dimensions

Create dimensions on a dataset with the createDimension() method. We first create a new netCDF file but this time we don’t close it immediately and create 3 dimensions:

The first dimension is called time with unlimited size (i.e. variable values may be appended along the this dimension). Unlimited size dimensions must be declared before (“to the left of”) other dimensions. We usually use only a single unlimited size dimension that is used for time.

The other 3 dimensions are spatial dimensions with sizes of 3, 4, and 5, respectively.

The recommended maximum number of dimensions is 4. The recommended order of dimensions is time, z, y, x. Not all datasets are required to have all 4 dimensions.

Variables

Create variables on a dataset with the createVariable() method, for example:

The first argument to createVariable() is the variable name.

The second argument is the variable type. There are many way of specifying type, but Python built-in types work well in the absence of specific requirements.

The third argument is a tuple of previously defined dimension names. As noted above,

The recommended maximum number of dimensions is 4 The recommended order of dimensions is t, z, y, x Not all variables are required to have all 4 dimensions All variables should be created with the zlib=True argument to enable data compression within the netCDF4 file.

When appropriate, the least_significant_digit argument should be used to improve compression and storage efficiency by quantizing the variable data to the specified precision. In the example above the orography data will be quantized such that a precision of 0.1 is retained.

When appropriate, the fill_value argument can be used to specify the value that the variable gets filled with before any data is written to it. Doing so overrides the default netCDF _FillValue (which depends on the type of the variable). If fill_value is set to False, then the variable is not pre-filled.

In the example above the orography data will be initialized to zero, the appropriate value for grid points that are over ocean.

Writing and Retrieving Data

Writing Data

Variable data in netCDF4 datasets are stored in NumPy array or masked array objects.

An appropriately sized and shaped NumPy array can be loaded into a dataset variable by assigning it to a slice that span the variable:

We defined a one-dimensional array data_out and reshape it to a 2 dimensional array and then store it in the orography netCDF variable.

Let’s have look to the netCDF file we generated and in particular its metadata:


  • Point - Creates a file containing selected STK facility, place and target points.
  • Polygon - Creates a file containing selected STK area target polygons.
  • Arc - Creates a file containing selected STK vehicles' (satellite, aircraft, ship, ground vehicle) tracks.
  • Polyline - Creates a file suitable for Communications contours and other shapes that are not necessarily closed. Also supports area targets, facilities, and selected vehicles.

The objects list contains all objects (depending on the shape that you choose) whose data can be exported to the GIS shapefile.

If you have selected a polygon shape, Figure of Merit objects with contours are included in the list.

When a transmitter is exported to a GIS shapefile, the file will contain contour values.

Tracking Analyst is an extension to Esri ArcMap™ that supports temporal information with geographic feature data. This includes adding time and date information to features in GIS shapefiles.

Click Export. to create the file. By default, the file will be:

You can assign the file a different name and browse to a different folder.

If you export an AzEl mask shapefile for a facility, STK will exclude any step that is at the same altitude as the facility. This prevents STK from attempting to compute a mask that results in a single point (or less).

Systems Tool Kit (STK) ,  v 12.2  Latest Help Update: June, 2021


The Spatials Table in Access

The Spatials table can be accessed as a secondary tab under the Locations tab. The default view for this form is “datasheet” view. However, monitoring team members may choose to create more personalized¯orms if desired.

Figure 6.3. The Spatials table is nestled under the Location tab. This table does not store spatial information. Rather, it points to¯iles that contain spatial data via a filepath.

It is very easy to create many spatial objects (shapefiles or rasters) that can be used in the analysis of monitoring data. O spatials table provides a way document each layer, and futher can be used to quickly load the objects to R if the file path is accurate.


How to process GRIB2 weather data for wind turbine applications (Shapefile)

Written by
Elliott Wobler
Technical Solutions Engineer

This tutorial covers how to work with Spire Weather’s global forecast data in GRIB2 format using Python.

This tutorial uses Shapefile input.

Overview

This tutorial covers how to work with Spire Weather’s global forecast data in GRIB2 format using Python.

If you have never worked with GRIB2 data before, it’s recommended to start with the getting started tutorial, since this current one will address slightly more advanced topics.

Specifically, this tutorial demonstrates how to retrieve wind speed and direction at different vertical levels (i.e. heights relevant to wind turbines) within the bounds of a complex polygon (e.g. a nation’s border).

By the end of this tutorial, you will know how to:

  1. Load files containing GRIB2 messages into a Python program
  2. Inspect the GRIB2 data to understand which weather variables are included
  3. Filter the GRIB2 data to weather variables of interest at different vertical levels
  4. Compute wind speed and direction from eastward and northward wind components
  5. Crop the GRIB2 data to the area defined by an Esri Shapefile input
  6. Convert the transformed GRIB2 data into a CSV output file for further analysis and visualization

Downloading the Data

The first step is downloading data from Spire Weather’s File API.

This tutorial expects the GRIB2 messages to contain NWP data from Spire’s Renewable Energy data bundle.

For information on using Spire Weather’s File API endpoints, please see the API documentation and FAQ.

The FAQ also contains detailed examples covering how to download multiple forecast files at once using cURL.

For the purposes of this tutorial, it is assumed that the GRIB2 data has already been successfully downloaded, if not get a sample here.

Understanding filenames

Files downloaded from Spire Weather’s API products all share the same file naming convention.

Just from looking at the filename, we can determine:

  • the date and time that the forecast was issued
  • the date and time that the forecasted data is valid for
  • the horizontal resolution of the global forecast data
  • the weather data variables that are included in the file (see the full list of Spire Weather’s commercial data bundles)

For more detailed information on the above, please refer to our FAQ.

Python Requirements

The following Python packages are required for this tutorial.

Although using conda is not strictly required, it is the officially recommended method for installing PyNIO (see link below).

Once a conda environment has been created and activated, the following commands can be run directly:

Inspecting the Data

After downloading the data and setting up a Python environment with the required packages, the next step is inspecting the data contents in order to determine which weather variables are available to access. Data inspection can be done purely with PyNIO, but in this tutorial we will instead use PyNIO as the engine for xarray and load the data into an xarray dataset for transformation. Note that an explicit import of PyNIO is not required, so long as it’s installed properly in the active Python environment.

First, import the xarray package:

Next, open the GRIB2 data with xarray using PyNIO as its engine (note that the GRIB2 data should be from Spire’s Renewable Energy data bundle):

ds = xr.open_dataset("path_to_renewable_energy_file.grib2", engine="pynio")

Finally, for each of the variables, print the lookup key, human-readable name, and units of measurement:

The output of the above should look something like this, giving a clear overview of the available data fields:

Since this tutorial covers working with GRIB2 data at different vertical levels, we should also inspect the level_type field:

The output of the above should look like this:

Notice that three of the included variables have the same level_type value of Specific altitude above mean sea level (m) .

This means that the same exact methodology can be used to process these variables at different vertical levels, though for the purpose of this tutorial we will stick to looking at just the wind component variables: UGRD_P0_L103_GLL0 and VGRD_P0_L103_GLL0 .

Understanding Height Values

To better understand available depth values, we can start by printing metadata for one of the wind component variables:
print(ds["UGRD_P0_L103_GLL0"])
The output of the above should look something like this:

At the end of the first line, the list contains not only the lat_0 and lon_0 index names we would expect after the basic tutorial, but also a new one called lv_HTGL0 .
We know from our previous print statement that lv_HTGL0 refers to Specified height level above ground (m) , and the fourth line of the latest print output provides a preview of lv_HTGL0 values. From this information, we can intuit that there is a third index for this data called lv_HTGL0 which corresponds to the height of the data in meters.
We can print metadata on an index with the same method used to inspect variables:
print(ds["lv_HTGL0"])
The output of the above should look like this:

The first line of the output tells us that there are three possible values, expressed as (lv_HTGL0: 3) , and the second line tells us what those values are: [ 80., 100., 120.]
This means that for every unique pair of lat_0 and lon_0 coordinates, there are three distinct vertical level (i.e. height) values which can be retrieved by specifying a lv_HTGL0 value of 80 , 100 , or 120 .

Processing the Data

Now that we know which weather variables and vertical levels are included in the GRIB2 data, we can start processing our xarray dataset.

Filtering the xarray data to a specific variable

With xarray , filtering the dataset’s contents to our variables of interest is accomplished by specifying an array of strings:

It’s recommended to perform this step before converting the xarray dataset into a pandas DataFrame (rather than filtering the DataFrame later), since it minimizes the size of the data being converted and therefore reduces the overall runtime.

Converting the xarray data into a pandas.DataFrame

To convert the filtered xarray dataset into a pandas DataFrame, simply run the following:

Filtering the pandas.DataFrame to a specific height

Using the information gathered from the Understanding Height Values section, we can now filter the DataFrame to a specific height.

The first thing we do is copy the height index values (in meters) into a new DataFrame column:

Next, we create the expression we will use to filter the DataFrame.

We can filter the wind components data to a height level of 100 meters with the following expression:

height_filter = (df["height"] == 100)

Finally, we apply the filter to the DataFrame:

Our DataFrame has now been filtered to only include wind components data at a height of 100 meters.

Loading an Esri Shapefile with the GDAL Python package

Although the package we installed with conda was named gdal , we import it into Python as osgeo . This is an abbreviation of the Open Source Geospatial Foundation, which GDAL/OGR (a Free and Open Source Software) is licensed through.

The Shapefile format, originally developed by Esri, is a common standard in the world of geographic information systems. It defines the geometry and attributes of geographically referenced features in three or more files with specific file extensions. The three mandatory file extensions are .shp , .shx , and .dbf — and all of these related component files are expected to be stored in the same file directory. Many pre-existing Shapefiles can be downloaded for free online (e.g. national borders, exclusive economic zones, etc.) and custom shapes can also be created in a variety of free software tools. In this example we use the country of Italy as our complex polygon, but this could just as easily be the area surrounding an airport or some other small region.

When opening a Shapefile with GDAL, we only need to point to the file with the .shp extension. However, it is required that the other component files exist in the same directory. If we are opening a file called italy.shp , there should at least be files named italy.shx and italy.dbf in the same directory as well.

Once we have defined the driver and the path to our Shapefile polygon, we can load it into our script like this:

Getting the bounding box that contains a Shapefile area

Eventually we will crop the data to the precise area defined by the Shapefile, but this is a computationally expensive process so it’s best to limit the data size first. In theory we could skip the step of cropping to a simple box altogether, but in practice it’s worth doing so to reduce the overall runtime.

GDAL makes it easy to calculate the coarse bounding box that contains a complex Shapefile area:

Coordinate values can then be accessed individually from the resulting array:

The order of geospatial coordinates is a common source of confusion, so take care to note that GDAL’s GetExtent function returns an array where the longitude values come before the latitude values.

Cropping the pandas.DataFrame to a geospatial bounding box

Now that the filtered data is converted into a pandas DataFrame and we have the bounds containing our area of interest, we can crop the data to a simple box.

The first step in this process is unpacking the latitude and longitude values from the DataFrame’s index , which can be accessed through the index names of lat_0 and lon_0 :

Although latitude values are already in the standard range of -90 degress to +90 degrees, longitude values are in the range of 0 para +360.

To make the data easier to work with, we convert longitude values into the standard range of -180 degrees to +180 degrees:

With latitude and longitude data now in the desired value ranges, we can store them as new columns in our existing DataFrame:

Then, we use the bounding box values from the previous section (the components of the bbox array) to construct the DataFrame filter expressions:

Finally, we apply the filters to our existing DataFrame:

The resulting DataFrame has been cropped to the bounds of the box that contains the complex Shapefile area.

Cropping the pandas.DataFrame to the precise bounds of a Shapefile area

In order to crop the DataFrame to the precise bounds of the complex Shapefile area, we will need to check every coordinate pair in our data. Similar to the previous section where we remapped every longitude value, we will perform this action with a map expression.

To pass each coordinate pair into the map function, we create a new DataFrame column called point where each value is a tuple containing both latitude and longitude:

We can then pass each coordinate pair tuple value into the map function, along with the previously loaded Shapefile area, and process them in a function called check_point_in_area which we will define below. The check_point_in_area function will return either True or False to indicate whether the provided coordinate pair is inside of the area or not. As a result, we will end up with a new DataFrame column of boolean values called inArea :

Once the inArea column is populated, we perform a simple filter to remove rows where the inArea value is False . This effectively removes data for all point locations that are not within the Shapefile’s area:

Of course, the success of the above is dependent upon the logic inside of the check_point_in_area function, which we have not yet implemented. Since the Shapefile area was loaded with GDAL, we can leverage a GDAL geometry method called Contains to quickly check if the area contains a specific point. In order to do this, the coordinate pair must first be converted into a wkbPoint geometry in GDAL:

All Shapefiles are composed of one or more feature, so to ensure our code is robust we will need to check each component feature individually. Features can be retrieved by their numerical index with area.GetFeature(i) , and the total number of features can be retrieved with area.GetFeatureCount() . Using these two functions with the Contains method mentioned above, we can iterate through each feature and check if it contains the point geometry:

Putting the pieces together, here is what we get for our final check_point_in_area function:

As you can see, the only variable returned by the check_point_in_area function is a boolean value indicating whether the specified point is in the area or not. These boolean values then populate the new inArea DataFrame column. This allows us to apply the filter from above and end up with the precisely cropped data we want:

Computing the wind speed and direction from the wind components

Now that the data has been cropped to our area of interest – reducing the total size of our data points – we can compute the wind speed and direction from the eastward (U) and northward (V) wind component values.

First, we need to import some utility functions from Python’s math module:

Then, the wind speed can be computed with the following:

The wind direction can be computed like so:

Note that the values returned by the wind_direction_from_u_v function refer to the meteorological representation of wind direction in degrees:

In order to apply these functions across all data points in our DataFrame, we need to utilize lambda functions:

Once the lambda functions are defined, we can apply them to the DataFrame and map their output to new data columns:

We now have new data columns called wind-speed and wind-direction which contain the computed values for each location.

Parsing the forecast time from the filename

Each individual file contains global weather forecast data for the same point in time.

Using our knowledge from the Understanding Filenames section of this tutorial, and assuming that the filename argument is in the expected format, we can write a function to parse the valid forecast time from the filename:

Then, we can create a new DataFrame column for time which stores this value as a string in every row:

Although it may seem unnecessary to store the same exact timestamp value in every row, this is an important step if we want to eventually concatenate our DataFrame with forecast data for other times (demonstrated below in Processing Multiple Data Files).

Saving the data to a CSV output file

Perform a final filter on our DataFrame to select only the columns that we want in our output:

Save the processed DataFrame to an output CSV file:

Setting the index=False parameter ensures that the DataFrame index columns are not included in the output. This way, we exclude the lat_0 , lon_0 , and lv_HTGL0 values since we already have columns for latitude and remapped longitude (and all remaining data is at the same height after our filtering).

Please note that converting from GRIB2 to CSV can result in very large file sizes, especially if the data is not significantly cropped or filtered.

Processing Multiple Data Files

It is often desirable to process multiple data files at once, in order to combine the results into a single unified CSV output file.

For example, let’s say that we have just used the Spire Weather API to download a full forecast’s worth of GRIB2 data into a local directory called forecast_data/ . We can then read those filenames into a list and sort them alphabetically for good measure:

From here, we can iterate through the filenames and pass each one into a function that performs the steps outlined in the Processing the Data section of this tutorial.

Once all of our final DataFrames are ready, we can use pandas to concatenate them together like so (where final_dataframes is a list of DataFrames):

We end up with a combined DataFrame called output_df which we can save to an output CSV file like we did before:

Complete Code

Below is an operational Python script which uses the techniques described in this tutorial and also includes explanatory in-line comments.

The script takes three arguments (the wind component variable names are hard-coded in the script):

The local directory where the Renewable Energy Weather GRIB2 data is stored

The local directory where the Shapefile components are stored

The height index value for filtering the data to a single vertical level ( 80 , 100 , or 120 )

For example, the script can be run like this:

python script.py --source-data grib_directory/ --shapefile shpfile_directory/italy.shp --height 100

Here is the complete code:

Final Notes

Using the CSV data output from our final script, we can now easily visualize the processed data in a free tool such as kepler.gl. We can also set thresholds for alerts, generate statistics, or fuse with other datasets.

Spire Weather also offers pre-created visualizations through the Web Map Service (WMS) API which you can read more about here.

For additional code samples, check out Spire Weather’s public GitHub repository.

Would you like to book a consultation?

Learn more about our Weather APIs and how Spire Weather can help you enable the data advantage.


All feature types in shapefiles convert to geometry types in the geodatabase. Unlike coverages, shapefile feature types are similar to the geometry types stored in a geodatabase, so conversion is more straightforward. For more information, see How data converts when importing.

Each of the component files of a shapefile is limited to 2 GB each. Therefore, .dbf files cannot exceed 2 GB and .shp files cannot exceed 2 GB (these are the only files that are likely to be huge). The total size for all the component files can exceed 2 GB.


Assista o vídeo: Zmiana widoku plików i folderów.