Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Saiba como criar um item do Catálogo de Ativos SpatioTemporal (STAC) para um ativo de dados geoespaciais de raster. Cada ativo de dados geoespaciais carregado em um Microsoft Planetary Computer Pro GeoCatalog deve ter um Item compatível com STAC associado.
Neste guia, você:
- Instale as bibliotecas do Python necessárias usando PIP.
- Exiba e inspecione dados GOES-18 usando o código Python fornecido.
- Extraia metadados do nome do arquivo usando expressões regulares.
- Crie itens STAC a partir de arquivos GeoTIFF otimizados para nuvem usando
rio-stac. - Melhore o item STAC com metadados extraídos do nome do arquivo.
- Adicione o item STAC à coleção STAC principal.
- Valide e salve o catálogo, a coleção e os itens do STAC.
- Adicione os itens STAC ao Microsoft Planetry Computer Pro.
Este tutorial demonstra e explica as capacidades por meio de trechos de código, proporcionando uma experiência interativa no estilo de notebook. Baixe este tutorial como um notebook Jupyter.
Pré-requisitos
Para concluir este guia de início rápido, você precisa:
- Uma conta do Azure com uma assinatura ativa. Use o link para criar uma conta gratuitamente.
- CLI do Azure: Instalar a CLI do Azure
- Um ambiente python com pelo menos a versão 3.8.
- Alguma familiaridade com o padrão STAC e sua implementação na visão geral do STAC do Microsoft Planetary Computer Pro
Principais recursos do STAC
O Catálogo de Ativos SpatioTemporal (STAC) é um padrão aberto para estruturar e compartilhar dados geoespaciais. Ele fornece uma linguagem e um formato comuns para descrever ativos geoespaciais, facilitando a descoberta, o acesso e o uso desses recursos em diferentes plataformas e aplicativos. Veja a seguir os principais recursos do padrão STAC:
- Interoperabilidade: o esquema baseado em JSON padronizado garante fácil integração e compreensão entre ferramentas e sistemas.
- Extensibilidade: campos de núcleo flexíveis com extensões personalizadas para necessidades específicas.
- Capacidade de descoberta: a estrutura consistente aprimora a pesquisa e a descoberta de ativos geoespaciais.
- Acessibilidade: links diretos para ativos de dados facilitam a recuperação e a integração perfeitas.
- Automação: habilita o processamento e a análise automatizados com metadados padronizados.
Benefícios do STAC para padronizar metadados
- Consistência entre tipos de dados: estrutura unificada para diversos tipos de dados geoespaciais.
- Colaboração aprimorada: simplifica o compartilhamento e a colaboração com um formato de metadados comum.
- Integração de dados aprimorada: facilita a integração de conjuntos de dados de várias fontes.
- Gerenciamento simplificado de dados: ferramentas automatizadas reduzem o esforço manual na manutenção de metadados.
- Preparação para o futuro: A natureza extensível se adapta a novos tipos de dados e tecnologias.
O Mc Pro (Microsoft Planetary Computer Pro) usa o STAC como seu padrão de indexação principal para fornecer interoperabilidade entre conjuntos de dados. Este tutorial mostra aos usuários como criar itens STAC do zero usando bibliotecas comuns de software livre.
A Especificação do Item STAC detalha como os Itens STAC são construídos e os metadados mínimos necessários que devem ser preenchidos. O STAC é um padrão flexível, permitindo que os usuários decidam quais dados desejam incluir como parte dos metadados. Metadados que podem ser usados para preencher um Item STAC podem ser incluídos no conjunto de dados, em um arquivo sidecar (.XML, .JSON, .TXT etc.) ou até mesmo em locais como o nome do arquivo. Os usuários devem considerar os tipos de metadados que os usuários podem querer pesquisar e classificar no futuro ao decidir quais metadados incluir.
Esse tutorial usa dados de imagens de amostra do Cloud Optimized GeoTIFF (COG) do conjunto de dados de temperatura da superfície terrestre (LST) dos satélites Geostationary Operational Environmental Satellite R (GOES-R) da Agência Nacional Oceânica e Atmosférica (NOAA). Esses dados são incluídos nos arquivos abertos do Computador Planetário como COG, mas não têm metadados STAC. Os satélites GOES produzem muitos produtos de dados. Mais detalhes podem ser encontrados no Guia de Definição de Produto e Usuários da SérieGOES-R.
O processo usado neste tutorial pode ser generalizado para qualquer tipo de dados em que os campos de metadados de chave são enumerados usando várias bibliotecas de software livre.
Instalar bibliotecas do Python
Para começar, instalamos as bibliotecas do Python necessárias usando PIP:
rasterio: este pacote é usado para ler e gravar dados de raster geoespaciais. Ele fornece ferramentas para trabalhar com formatos de dados de raster, como GeoTIFF.pystac: esse pacote é usado para trabalhar com o padrão STAC. Ele fornece ferramentas para criar, ler e manipular metadados STAC.rio-stac: Este pacote integrarasteriocompystacpara criar Itens STAC a partir de dados raster. Simplifica o processo de geração de metadados STAC para conjuntos de dados de raster.matplotlib: essa biblioteca é usada para criar visualizações e gráficos. No contexto de dados geoespaciais, ele ajuda a renderizar e exibir imagens de raster, permitindo que os usuários inspecionem visualmente os dados antes de criar metadados STAC.azure-storage-blob: Esta biblioteca de cliente de Armazenamento do Azure oferece acesso aos serviços de Blob Storage do Azure. Ele permite interação direta com dados geoespaciais armazenados na nuvem, permitindo que os usuários leiam e trabalhem com arquivos armazenados em contêineres de Blob do Azure sem baixá-los primeiro.
!pip install rasterio pystac rio_stac matplotlib azure-storage-blob
A próxima seção de código exibe alguns dados GOES-18 do Computador Planetário aberto. Selecionamos o conjunto de dados GOES-R Advanced Baseline Imager Level 2 Land Surface Temperature – CONUS e um arquivo arbitrário do dia 208 de 2023.
# Import Necessary Libraries
import requests
from azure.storage.blob import ContainerClient
import matplotlib.pyplot as plt
from rasterio.io import MemoryFile
import os
from urllib.parse import urlparse
# Function to get the SAS token
def get_sas_token(endpoint):
response = requests.get(endpoint)
if response.status_code == 200:
data = response.json()
return data.get("token")
else:
raise Exception(f"Failed to get SAS token: {response.status_code} - {response.text}")
# Define Azure Blob Storage parameters
storage_account_name = "goeseuwest"
container_name = "noaa-goes-cogs"
blob_domain = f"https://{storage_account_name}.blob.core.windows.net"
sas_endpoint = f"https://planetarycomputer.microsoft.com/api/sas/v1/token/{storage_account_name}/{container_name}/"
# Get the SAS token
sas_token = get_sas_token(sas_endpoint)
# Construct the container URL with the SAS token
container_url = f"{blob_domain}/{container_name}?{sas_token}"
# Create a ContainerClient
container_client = ContainerClient.from_container_url(container_url)
# Define data you want, this can be changed for other datasets that are in storage in the open Planetary Computer
satellite = "goes-18" # The specific GOES satellite (GOES-18, also known as GOES-West)
product = "ABI-L2-LSTC" # The data product type (Advanced Baseline Imager Level 2 Land Surface Temperature - CONUS)
year = "2023" # The year the data was collected
day_of_year = "208" # The day of year (DOY) - day 208 corresponds to July 27, 2023
# Construct the directory path
directory_path = f"{satellite}/{product}/{year}/{day_of_year}/"
# Get just the first blob by using next() and limiting the iterator
first_blob = next(container_client.list_blobs(name_starts_with=directory_path))
# Function to read and display a .tif file from a URL
def display_tif_from_url(url, title):
response = requests.get(url, stream=True)
if response.status_code == 200:
with MemoryFile(response.content) as memfile:
with memfile.open() as dataset:
plt.figure(figsize=(10, 10))
plt.imshow(dataset.read(1), cmap='gray')
plt.title(title)
plt.colorbar()
plt.show()
else:
raise Exception(f"Failed to read .tif file: {response.status_code} - {response.text}")
# Create the URL for the blob using the container_url components
file_url = f"{blob_domain}/{container_name}/{first_blob.name}?{sas_token}"
# Extract the filename safely from the URL without the SAS token
parsed_url = urlparse(file_url)
path = parsed_url.path # Gets just the path portion of the URL
filename = os.path.basename(path) # Get just the filename part
# Remove .tif extension if present
file_name = filename.replace('.tif', '')
print(f"Extracted File Name: {file_name}")
display_tif_from_url(file_url, file_name)
Ao examinar os dados e o nome do arquivo, já podemos ver as principais partes de metadados necessárias para criar o Item STAC. O nome do arquivo contém informações sobre qual satélite capturou os dados e quando eles foram capturados.
Para o exemplo, o nome do arquivo é OR_ABI-L2-LSTC-M6_G18_s20232080101177_e20232080103550_c20232080104570_DQF, com base no guia do produto, isso significa:
Componentes detalhados
| Campo | Descrição | Propósito |
|---|---|---|
| OU | Ambiente do sistema operacional | Especifica o ambiente do sistema no qual os dados foram coletados |
| ABI | Instrumento Advanced Baseline Imager | Identifica o instrumento usado para capturar os dados |
| L2 | Produto de nível 2 (produto derivado) | Indica que os dados são um produto derivado, processado a partir de observações brutas |
| LSTC | Produto Temperatura da Superfície Terrestre (Céu Limpo) | Representa o tipo de produto específico, concentrando-se na temperatura da superfície da terra sob condições claras do céu |
| M6 | Modo 6 de varredura (varredura de disco completo) | Descreve o modo de varredura, cobrindo todo o disco da Terra |
| G18 | Satélite GOES-18 (também conhecido como GOES-West) | Identifica o satélite do qual os dados foram coletados |
Detalhes do tempo de observação
Início da Observação (s20232080201177)-
| Campo | Descrição | Propósito |
|---|---|---|
| Ano | 2023 | Especifica o ano da observação |
| Dia do Ano | 208 | Indica o dia do ano em que a observação foi iniciada |
| Hora | 02:01:17 UTC | Fornece a hora exata em que a observação foi iniciada em UTC |
| Décimos de segundo | 7 | Adiciona precisão à hora de início da observação |
Fim da observação (e20232080203550)-
| Campo | Descrição | Propósito |
|---|---|---|
| Ano | 2023 | Especifica o ano da observação |
| Dia do Ano | 208 | Indica o dia do ano em que a observação terminou |
| Hora | 02:03:55 UTC | Fornece a hora exata em que a observação terminou em UTC |
| Décimos de segundo | 0 | Adiciona precisão à hora de término da observação |
Hora de criação do arquivo (c20232080204563)-
| Campo | Descrição | Propósito |
|---|---|---|
| Ano | 2023 | Especifica o ano em que o arquivo foi criado |
| Dia do Ano | 208 | Indica o dia do ano em que o arquivo foi criado |
| Hora | 02:04:56 UTC | Fornece a hora exata em que o arquivo foi criado em UTC |
| Décimos de segundo | 3 | Adiciona precisão ao tempo de criação do arquivo |
Informações adicionais:
| Campo | Descrição | Propósito |
|---|---|---|
| DQF | Sinalizador de Qualidade de Dados, indicando informações de qualidade para os dados correspondentes | Fornece informações sobre a qualidade dos dados |
| .tif | Extensão de arquivo | Indica o formato de arquivo dos dados |
O código a seguir extrai esses metadados do nome do arquivo usando expressões regulares (regex).
import re
from datetime import datetime, timedelta
def extract_goes_metadata(filename):
"""
Extracts key metadata from a NOAA GOES satellite filename using regular expressions.
Args:
filename (str): The filename to parse.
Returns:
dict: A dictionary containing the extracted metadata.
"""
# Regular expression pattern to match the filename format
pattern = re.compile(
r"^(OR)_" # System (OR)
r"(ABI)-(L\d)-(LSTC)-(M\d)_" # Instrument, Level, Product, Mode
r"(G\d{2})_" # Satellite (G18)
r"s(\d{4})(\d{3})(\d{2})(\d{2})(\d{2})(\d)_" # Start time
r"e(\d{4})(\d{3})(\d{2})(\d{2})(\d{2})(\d)_" # End time
r"c(\d{4})(\d{3})(\d{2})(\d{2})(\d{2})(\d)_" # Creation time
r"([A-Z0-9]+)$" # Data quality flag
)
match = pattern.match(filename)
if not match:
return None # Or raise an exception if you prefer
# Extract all fields from the regular expression match groups
(
system, # Operational system environment
instrument, # Advanced Baseline Imager
level, # Product level (L2)
product_type, # Product type (LSTC - Land Surface Temperature)
mode, # Scanning mode (M6)
satellite, # Satellite identifier (G18)
s_year, s_doy, s_hour, s_minute, s_second, s_tenth, # Start time components
e_year, e_doy, e_hour, e_minute, e_second, e_tenth, # End time components
c_year, c_doy, c_hour, c_minute, c_second, c_tenth, # Creation time components
data_quality_flag # Quality flag indicator
) = match.groups()
def parse_goes_time(year, doy, hour, minute, second, tenth):
"""Parses GOES time components into an ISO format string."""
try:
dt = datetime(int(year), 1, 1) + timedelta(
days=int(doy) - 1,
hours=int(hour),
minutes=int(minute),
seconds=int(second),
microseconds=int(tenth) * 100000,
)
return dt
except ValueError:
return None
# Parse the time components into datetime objects
start_time = parse_goes_time(s_year, s_doy, s_hour, s_minute, s_second, s_tenth)
end_time = parse_goes_time(e_year, e_doy, e_hour, e_minute, e_second, e_tenth)
creation_time = parse_goes_time(c_year, c_doy, c_hour, c_minute, c_second, c_tenth)
# Create a dictionary to organize all extracted metadata
metadata = {
"system": system, # Operational system environment (e.g., "OR" for operational)
"instrument": instrument, # Instrument used to capture data (e.g., "ABI" for Advanced Baseline Imager)
"level": level, # Processing level of the data (e.g., "L2" for Level 2)
"product_type": product_type, # Type of product (e.g., "LSTC" for Land Surface Temperature Clear Sky)
"mode": mode, # Scanning mode (e.g., "M6" for Mode 6, full disk scan)
"satellite": satellite, # Satellite identifier (e.g., "G18" for GOES-18)
"start_time": start_time, # Observation start time as datetime object
"end_time": end_time, # Observation end time as datetime object
"creation_time": creation_time, # File creation time as datetime object
"data_quality_flag": data_quality_flag, # Quality flag for the data (e.g., "DQF")
}
return metadata
# Example usage:
print(file_name)
metadata_from_filename = extract_goes_metadata(file_name)
print(metadata_from_filename)
OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF
{'system': 'OR', 'instrument': 'ABI', 'level': 'L2', 'product_type': 'LSTC', 'mode': 'M6', 'satellite': 'G18', 'start_time': datetime.datetime(2023, 7, 27, 0, 1, 17, 700000), 'end_time': datetime.datetime(2023, 7, 27, 0, 3, 55), 'creation_time': datetime.datetime(2023, 7, 27, 0, 4, 56, 800000), 'data_quality_flag': 'DQF'}
Criar Itens STAC a partir de arquivos GeoTIFF Cloud-Optimized
O bloco de código a seguir usa a biblioteca rio-stac para automatizar a criação de itens STAC a partir de GeoTIFFs otimizados para nuvem (COGs).
Quando apontado para um arquivo COG, rio-stac extrai e organiza automaticamente metadados essenciais, como limites espaciais, informações de projeção e propriedades de raster em um formato STAC padronizado. A biblioteca manipula a tarefa complexa de ler os metadados técnicos inseridos do GeoTIFF e converte-os em campos em conformidade com STAC, incluindo:
- Geometria
- Caixa delimitadora (bbox)
- Detalhes da projeção
- Características de raster
- Extensões do STAC
Essa automação reduz significativamente o trabalho manual necessário para criar itens STAC válidos e garante a consistência nos metadados
Observação
O GeoCatalog tem limitações em caracteres que podem ser usados em IDs de item STAC e chaves de ativo. Verifique se suas IDs não contêm os seguintes caracteres: -, , _, +, , (, )e .. Talvez seja necessário modificar a item_id lógica de geração para substituir ou remover esses caracteres de seus nomes de arquivo.
from rio_stac import create_stac_item
from rasterio.io import MemoryFile
import json
from urllib.parse import urlparse, unquote
def create_stac_item_from_cog(url):
"""
Create a basic STAC Item for GOES data using rio-stac with proper spatial handling
Args:
url (str): URL to the COG file
Returns:
pystac.Item: STAC Item with basic metadata and correct spatial information
"""
# Extract the filename safely from the URL
parsed_url = urlparse(url)
path = parsed_url.path # Gets just the path portion of the URL
filename = os.path.basename(path) # Get just the filename part
# Remove .tif extension if present
item_id = filename.replace('.tif', '')
response = requests.get(url, stream=True)
if response.status_code == 200:
with MemoryFile(response.content) as memfile:
with memfile.open() as dataset:
# Create base STAC item from rasterio dataset calling create_stac_item from rio_stac
stac_item = create_stac_item(
source=dataset, # The rasterio dataset object representing the COG file
id=item_id, # Generate a unique ID by extracting the filename without the .tif extension
asset_name='data', # Name of the asset, indicating it contains the primary data
asset_href=url, # URL to the COG file, used as the asset's location
with_proj=True, # Include projection metadata (e.g., CRS, bounding box, etc.)
with_raster=True, # Include raster-specific metadata (e.g., bands, resolution, etc.)
properties={
'datetime': None, # Set datetime to None since explicit start/end times may be added later
# Add rasterio-specific metadata for the raster bands
'raster:bands': [
{
'nodata': dataset.nodata, # Value representing no data in the raster
'data_type': dataset.dtypes[0], # Data type of the raster (e.g., uint16)
'spatial_resolution': dataset.res[0] # Spatial resolution of the raster in meters
}
],
'file:size': len(response.content) # Size of the file in bytes
},
extensions=[
'https://stac-extensions.github.io/file/v2.1.0/schema.json' # Add the file extension schema for additional metadata
]
)
return stac_item
else:
raise Exception(f"Failed to read .tif file: {response.status_code} - {response.text}")
# Example usage
sas_token = get_sas_token(sas_endpoint) # refresh the SAS token prior to creating STAC item
# Create file URL using the first_blob variable that's already defined
file_url = f"{blob_domain}/{container_name}/{first_blob.name}?{sas_token}"
# Create STAC item for the first blob
stac_item = create_stac_item_from_cog(file_url)
# Print the STAC item as JSON
print(json.dumps(stac_item.to_dict(), indent=2))
{
"type": "Feature",
"stac_version": "1.0.0",
"stac_extensions": [
"https://stac-extensions.github.io/file/v2.1.0/schema.json",
"https://stac-extensions.github.io/projection/v1.1.0/schema.json",
"https://stac-extensions.github.io/raster/v1.1.0/schema.json"
],
"id": "OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-161.57885623466754,
14.795666555826678
],
[
-112.42114380921453,
14.79566655500485
],
[
-89.5501123912648,
53.52729778421186
],
[
175.5501122574517,
53.52729779865781
],
[
-161.57885623466754,
14.795666555826678
]
]
]
},
"bbox": [
-161.57885623466754,
14.79566655500485,
175.5501122574517,
53.52729779865781
],
"properties": {
"datetime": "2025-03-26T14:46:05.484602Z",
"raster:bands": [
{
"nodata": 65535.0,
"data_type": "uint16",
"spatial_resolution": 2004.017315487541
}
],
"file:size": 118674,
"proj:epsg": null,
"proj:geometry": {
"type": "Polygon",
"coordinates": [
[
[
-2505021.6463773525,
1583173.791653181
],
[
2505021.6423414997,
1583173.791653181
],
[
2505021.6423414997,
4589199.764884492
],
[
-2505021.6463773525,
4589199.764884492
],
[
-2505021.6463773525,
1583173.791653181
]
]
]
},
"proj:bbox": [
-2505021.6463773525,
1583173.791653181,
2505021.6423414997,
4589199.764884492
],
"proj:shape": [
1500,
2500
],
"proj:transform": [
2004.017315487541,
0.0,
-2505021.6463773525,
0.0,
-2004.017315487541,
4589199.764884492,
0.0,
0.0,
1.0
],
"proj:wkt2": "PROJCS[\"unnamed\",GEOGCS[\"unknown\",DATUM[\"unnamed\",SPHEROID[\"Spheroid\",6378137,298.2572221]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Geostationary_Satellite\"],PARAMETER[\"central_meridian\",-137],PARAMETER[\"satellite_height\",35786023],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],EXTENSION[\"PROJ4\",\"+proj=geos +lon_0=-137 +h=35786023 +x_0=0 +y_0=0 +ellps=GRS80 +units=m +no_defs +sweep=x\"]]"
},
"links": [],
"assets": {
"data": {
"href": "https://goeseuwest.blob.core.windows.net/noaa-goes-cogs/goes-18/ABI-L2-LSTC/2023/208/00/OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF.tif?st=2025-03-25T14%3A46%3A03Z&se=2025-03-26T15%3A31%3A03Z&sp=rl&sv=2024-05-04&sr=c&skoid=9c8ff44a-6a2c-4dfb-b298-1c9212f64d9a&sktid=72f988bf-86f1-41af-91ab-2d7cd011db47&skt=2025-03-26T12%3A41%3A49Z&ske=2025-04-02T12%3A41%3A49Z&sks=b&skv=2024-05-04&sig=BuMxN2NUTdrhzY7Dvpd/X4yfX8gnFpHOzANHQLkKE1k%3D",
"type": "image/tiff; application=geotiff",
"raster:bands": [
{
"data_type": "uint16",
"scale": 1.0,
"offset": 0.0,
"sampling": "area",
"nodata": 65535.0,
"unit": "1",
"statistics": {
"mean": 2.780959413109756,
"minimum": 0,
"maximum": 3,
"stddev": 0.710762086175375,
"valid_percent": 100.0
},
"histogram": {
"count": 11,
"min": 0.0,
"max": 3.0,
"buckets": [
26655,
0,
0,
25243,
0,
0,
7492,
0,
0,
570370
]
}
}
],
"roles": []
}
}
}
Item STAC JSON de rio-stac
A biblioteca rio-stac leu o arquivo GOES COG e extraiu metadados de chave automaticamente.
Além disso, com base no tipo de metadados incluído, o rio-stac adicionou as Extensões STAC relevantes. As Extensões STAC aprimoram a especificação principal adicionando metadados padronizados e específicos do domínio.
- A Extensão de Arquivo fornece metadados de arquivo essenciais, como tamanho e somas de verificação.
- Extensão de projeção captura informações de referência espacial, incluindo sistemas de coordenadas e caixas delimitadoras.
- A Extensão raster padroniza propriedades específicas de dados de raster, como informações de banda e resolução espacial.
As tabelas a seguir fornecem uma explicação de todos os metadados rio-stac encontrados.
Campos principais
| Campo | Descrição | Propósito |
|---|---|---|
| tipo | Sempre "Destaque" | Identifica o tipo como um recurso GeoJSON |
| stac_version | 1.0.0 | Especifica a versão padrão do STAC |
| id | Identificador exclusivo | Contém informações de satélite, produto e hora |
| stac_extensions | Lista de URLs de esquema | Define campos de metadados extras |
Informações espaciais
| Campo | Descrição | Propósito |
|---|---|---|
| geometria | Polígono GeoJSON | Define a pegada de dados em coordenadas WGS84 |
| bbox | Coordenadas da caixa delimitadora | Fornece extensão espacial simples para filtragem rápida |
| proj:geometry | Polígono específico da projeção | Pegada em coordenadas de projeção nativas |
| proj:bbox | Limites de projeção nativos | Extensão espacial no sistema de coordenadas do satélite |
| proj:shape | [1500, 2500] | Dimensões de imagem em pixels |
| proj:transform | Transformação afim | Mapas de pixels para coordenar o espaço |
| proj:wkt2 | Texto Bem Conhecido | Definição completa de projeção |
| proj:epsg | nulo | Nenhum código EPSG padrão existe para esta projeção de mapa |
Informações temporais
| Campo | Descrição | Propósito |
|---|---|---|
| datetime | Carimbo de data e hora da criação | Quando este item STAC foi criado |
Informações de Varredura
| Campo | Descrição | Propósito |
|---|---|---|
| raster:bandas | Conjunto de objetos de banda | Descreve as propriedades de dados de raster |
| tipo_de_dado | "uint16" | Tipo de dados de pixel |
| → resolução espacial | 2004,02 m | Distância de amostra no solo |
| → escala/deslocamento | Fatores de conversão | Transforma valores de pixel em unidades físicas (Kelvin) |
| → nodata | 65535.0 | Valor que não representa nenhum dado |
| estatísticas | Resumo estatístico | Fornece informações de distribuição de dados |
| → histograma | Distribuição de valor | Visualiza a distribuição de dados |
Informações sobre ativos
| Campo | Descrição | Propósito |
|---|---|---|
| assets.data | Ativo de dados principal | Aponta para o arquivo de dados real |
| → href | URL | Localização do Cloud-Optimized GeoTIFF |
| → tipo | Tipo de mídia | Identifica o formato do arquivo |
Metadados de arquivo
| Campo | Descrição | Propósito |
|---|---|---|
| arquivo:tamanho | 943.250 bytes | Tamanho do arquivo de dados |
Adicionando os metadados do Nome do Arquivo
Em seguida, adicionamos os dados que encontramos no nome do arquivo para concluir o preenchimento dos metadados deste Item STAC.
Algo a ser destacado é que todas as datas e horas para itens STAC devem estar em conformidade com o ISO 8601. A biblioteca PySTAC tem uma função datetime_to_str que garante que os dados sejam formatados corretamente.
import pystac
def enhance_stac_item_with_metadata(stac_item, metadata_from_filename):
"""
Enhances a STAC Item with additional metadata from GOES filename.
Args:
stac_item (pystac.Item): Existing STAC Item created by rio-stac
metadata_from_filename (dict): Metadata extracted from filename
Returns:
pystac.Item: Enhanced STAC Item
"""
# Add satellite/sensor properties to the STAC item
stac_item.properties.update({
'platform': f"GOES-{metadata_from_filename['satellite'][1:]}",
'instruments': [metadata_from_filename['instrument']],
'constellation': 'GOES'
})
# Add temporal properties to the STAC item, use pystac to ensure time conforms to ISO 8601
stac_item.datetime = None # Clear the default datetime
stac_item.properties.update({
'start_datetime': pystac.utils.datetime_to_str(metadata_from_filename['start_time']),
'end_datetime': pystac.utils.datetime_to_str(metadata_from_filename['end_time']),
'created': pystac.utils.datetime_to_str(metadata_from_filename['creation_time'])
})
# Add GOES-specific properties to the STAC item
stac_item.properties.update({
'goes:system': metadata_from_filename['system'],
'goes:level': metadata_from_filename['level'],
'goes:product_type': metadata_from_filename['product_type'],
'goes:mode': metadata_from_filename['mode'],
'goes:processing_level': metadata_from_filename['level'],
'goes:data_quality_flag': metadata_from_filename['data_quality_flag']
})
return stac_item
# Example usage in new cell
stac_item = enhance_stac_item_with_metadata(stac_item, metadata_from_filename)
print(json.dumps(stac_item.to_dict(), indent=2))
O item STAC:
{
"type": "Feature",
"stac_version": "1.0.0",
"stac_extensions": [
"https://stac-extensions.github.io/file/v2.1.0/schema.json",
"https://stac-extensions.github.io/projection/v1.1.0/schema.json",
"https://stac-extensions.github.io/raster/v1.1.0/schema.json"
],
"id": "OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-161.57885623466754,
14.795666555826678
],
[
-112.42114380921453,
14.79566655500485
],
[
-89.5501123912648,
53.52729778421186
],
[
175.5501122574517,
53.52729779865781
],
[
-161.57885623466754,
14.795666555826678
]
]
]
},
"bbox": [
-161.57885623466754,
14.79566655500485,
175.5501122574517,
53.52729779865781
],
"properties": {
"datetime": null,
"raster:bands": [
{
"nodata": 65535.0,
"data_type": "uint16",
"spatial_resolution": 2004.017315487541
}
],
"file:size": 118674,
"proj:epsg": null,
"proj:geometry": {
"type": "Polygon",
"coordinates": [
[
[
-2505021.6463773525,
1583173.791653181
],
[
2505021.6423414997,
1583173.791653181
],
[
2505021.6423414997,
4589199.764884492
],
[
-2505021.6463773525,
4589199.764884492
],
[
-2505021.6463773525,
1583173.791653181
]
]
]
},
"proj:bbox": [
-2505021.6463773525,
1583173.791653181,
2505021.6423414997,
4589199.764884492
],
"proj:shape": [
1500,
2500
],
"proj:transform": [
2004.017315487541,
0.0,
-2505021.6463773525,
0.0,
-2004.017315487541,
4589199.764884492,
0.0,
0.0,
1.0
],
"proj:wkt2": "PROJCS[\"unnamed\",GEOGCS[\"unknown\",DATUM[\"unnamed\",SPHEROID[\"Spheroid\",6378137,298.2572221]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Geostationary_Satellite\"],PARAMETER[\"central_meridian\",-137],PARAMETER[\"satellite_height\",35786023],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],EXTENSION[\"PROJ4\",\"+proj=geos +lon_0=-137 +h=35786023 +x_0=0 +y_0=0 +ellps=GRS80 +units=m +no_defs +sweep=x\"]]",
"platform": "GOES-18",
"instruments": [
"ABI"
],
"constellation": "GOES",
"start_datetime": "2023-07-27T00:01:17.700000Z",
"end_datetime": "2023-07-27T00:03:55Z",
"created": "2023-07-27T00:04:56.800000Z",
"goes:system": "OR",
"goes:level": "L2",
"goes:product_type": "LSTC",
"goes:mode": "M6",
"goes:processing_level": "L2",
"goes:data_quality_flag": "DQF"
},
"links": [],
"assets": {
"data": {
"href": "https://goeseuwest.blob.core.windows.net/noaa-goes-cogs/goes-18/ABI-L2-LSTC/2023/208/00/OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF.tif?st=2025-03-25T14%3A46%3A03Z&se=2025-03-26T15%3A31%3A03Z&sp=rl&sv=2024-05-04&sr=c&skoid=9c8ff44a-6a2c-4dfb-b298-1c9212f64d9a&sktid=72f988bf-86f1-41af-91ab-2d7cd011db47&skt=2025-03-26T12%3A41%3A49Z&ske=2025-04-02T12%3A41%3A49Z&sks=b&skv=2024-05-04&sig=BuMxN2NUTdrhzY7Dvpd/X4yfX8gnFpHOzANHQLkKE1k%3D",
"type": "image/tiff; application=geotiff",
"raster:bands": [
{
"data_type": "uint16",
"scale": 1.0,
"offset": 0.0,
"sampling": "area",
"nodata": 65535.0,
"unit": "1",
"statistics": {
"mean": 2.780959413109756,
"minimum": 0,
"maximum": 3,
"stddev": 0.710762086175375,
"valid_percent": 100.0
},
"histogram": {
"count": 11,
"min": 0.0,
"max": 3.0,
"buckets": [
26655,
0,
0,
25243,
0,
0,
7492,
0,
0,
570370
]
}
}
],
"roles": []
}
}
}
Adicionar o item STAC a uma coleção
O MC Pro exige que todos os itens STAC tenham uma referência ao ID da coleção STAC pai na qual foram ingeridos. Para este tutorial, a ID da coleção STAC é o nome do satélite e do produto de dados.
Com o PySTAC, é fácil usar alguns dos metadados coletados dos arquivos de origem para preencher os campos de chave da Coleção STAC e usar as funções de validação internas.
O código a seguir cria uma Coleção STAC principal para armazenar os dados GOES. Em seguida, o código salva essas informações em arquivos usados para criar a coleção STAC do Microsoft Planetary Computer Pro e ingerir itens STAC no Planetry Computer Pro.
# Define collection properties
collection_id = f"{satellite}-{product}"
collection_title = f"{satellite.upper()} {product} Collection"
collection_desc = f"Collection of {satellite} {product} Earth observation data"
# Create spatial extent
bbox = [-180, -60, 10, 60] # placeholder, replace with actual data at a later date
spatial_extent = pystac.SpatialExtent([bbox])
# Create temporal extent, use current date time or replace with existing datetimes in stac_item
start_datetime = datetime.now()
if hasattr(metadata_from_filename, 'get'):
if metadata_from_filename.get('start_time'):
start_datetime = metadata_from_filename.get('start_time')
temporal_extent = pystac.TemporalExtent([[start_datetime, None]])
extent = pystac.Extent(spatial=spatial_extent, temporal=temporal_extent)
# Create the STAC Collection
collection = pystac.Collection(
id=collection_id,
description=collection_desc,
extent=extent,
title=collection_title,
license="public-domain",
)
# Add keywords and provider
collection.keywords = ["GOES", "satellite", "weather", "NOAA", satellite, product]
collection.providers = [
pystac.Provider(
name="NOAA",
roles=["producer", "licensor"],
url="https://www.noaa.gov/"
)
]
# Create output directories
output_dir = "stac_catalog"
collection_dir = os.path.join(output_dir, collection_id)
items_dir = os.path.join(collection_dir, "items")
os.makedirs(items_dir, exist_ok=True)
# Important: Save the collection first to generate proper file paths
collection_path = os.path.join(collection_dir, "collection.json")
collection.set_self_href(collection_path)
# Extract filename for the item
original_filename = first_blob.name.split('/')[-1]
base_filename = original_filename.replace('.tif', '')
item_path = os.path.join(items_dir, f"{base_filename}.json")
# Set the item's proper href
stac_item.set_self_href(item_path)
# Now associate the item with the collection (after setting hrefs)
collection.add_item(stac_item)
# Create a catalog to contain the collection
catalog = pystac.Catalog(
id="goes-data-catalog",
description="GOES Satellite Data Catalog",
title="GOES Data"
)
catalog_path = os.path.join(output_dir, "catalog.json")
catalog.set_self_href(catalog_path)
catalog.add_child(collection)
# Validate the collection and contained items
print("Validating collection and items...")
try:
collection.validate_all()
print("✅ Collection and items validated successfully")
# Save everything to disk
catalog.normalize_and_save(catalog_path, pystac.CatalogType.SELF_CONTAINED)
print(f"✅ STAC catalog saved at: {catalog_path}")
print(f"✅ STAC collection saved at: {collection_path}")
print(f"✅ STAC item saved at: {item_path}")
except Exception as e:
print(f"❌ Validation error: {str(e)}")
Validating collection and items...
✅ Collection and items validated successfully
✅ STAC catalog saved at: stac_catalog/catalog.json
✅ STAC collection saved at: stac_catalog/goes-18-ABI-L2-LSTC/collection.json
✅ STAC item saved at: stac_catalog/goes-18-ABI-L2-LSTC/items/OR_ABI-L2-LSTC-M6_G18_s20232080001177_e20232080003550_c20232080004568_DQF.json
Próximas etapas
Agora que você criou alguns itens STAC, é hora de ingerir os dados no Microsoft Planetry Computer Pro.
Para ingestão de item único:
Para ingestão em massa:
Também oferecemos a ferramenta STAC Forge , que fornece maior automação usando modelos em torno de dados.