Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Obtenga información sobre cómo crear un elemento del Catálogo de activos spatioTemporales (STAC) para un recurso de datos geoespaciales de ráster. Todos los recursos de datos geoespaciales que se cargan en un equipo de Ordenador Planetario de Microsoft Pro GeoCatalog deben tener un elemento compatible con STAC asociado.
En esta guía, podrá:
- Instale las bibliotecas de Python necesarias mediante PIP.
- Muestre e inspeccione los datos GOES-18 mediante el código de Python proporcionado.
- Extraiga metadatos del nombre de archivo mediante expresiones regulares.
- Cree elementos de STAC a partir de archivos GeoTIFF optimizados para la nube mediante
rio-stac
. - Mejore el elemento de STAC con metadatos extraídos del nombre de archivo.
- Agregue el elemento STAC a una colección de STAC primaria.
- Valide y guarde el catálogo, la colección y los elementos de STAC.
- Agregue los elementos de STAC a Microsoft Planetary Computer Pro.
En este tutorial se muestran y explican las funcionalidades a través de fragmentos de código, para obtener una experiencia interactiva de estilo de cuaderno, descargue este tutorial como un cuaderno de Jupyter Notebook.
Prerrequisitos
Para completar este inicio rápido necesita instalar:
- Una cuenta de Azure con una suscripción activa. Use el vínculo para crear una cuenta de forma gratuita.
- CLI de Azure: Instalación de la CLI de Azure
- Un entorno de Python con al menos la versión 3.8.
- Familiaridad con el estándar STAC y su implementación en Microsoft Planetary Computer Pro STAC Overview
Características clave de STAC
El Catálogo de activos spatioTemporales (STAC) es un estándar abierto para estructurar y compartir datos geoespaciales. Proporciona un lenguaje común y un formato para describir recursos geoespaciales, lo que facilita la detección, el acceso y el uso de estos recursos en distintas plataformas y aplicaciones. A continuación se muestran las características clave del estándar STAC:
- Interoperabilidad: el esquema estandarizado basado en JSON garantiza una fácil integración y comprensión entre herramientas y sistemas.
- Extensibilidad: campos principales flexibles con extensiones personalizadas para necesidades específicas.
- Detectabilidad: la estructura coherente mejora la búsqueda y detección de recursos geoespaciales.
- Accesibilidad: los vínculos directos a los recursos de datos facilitan la recuperación y la integración sin problemas.
- Automatización: habilita el procesamiento y el análisis automatizados con metadatos estandarizados.
Ventajas de STAC para estandarizar metadatos
- Coherencia entre tipos de datos: marco unificado para diversos tipos de datos geoespaciales.
- Colaboración mejorada: simplifica el uso compartido y la colaboración con un formato de metadatos común.
- Integración de datos mejorada: facilita la integración de conjuntos de datos de varios orígenes.
- Administración de datos simplificada: las herramientas automatizadas reducen el esfuerzo manual para mantener los metadatos.
- Corrección futura: La naturaleza extensible se adapta a los nuevos tipos de datos y tecnologías.
Microsoft Planetary Computer Pro (MC Pro) usa STAC como estándar de indexación principal para proporcionar interoperabilidad entre conjuntos de datos. En este tutorial se muestra a los usuarios cómo crear elementos de STAC desde cero mediante bibliotecas comunes de código abierto.
La especificación de elementos de STAC detalla cómo se construyen los elementos de STAC y los metadatos mínimos necesarios que se deben rellenar. STAC es un estándar flexible, lo que permite a los usuarios decidir qué datos quieren incluir como parte de los metadatos. Metadatos que se pueden usar para rellenar un elemento de STAC tal vez incluido en el recurso de datos, en un archivo sidecar (.XML, . JSON, .TXT etc.), o incluso en ubicaciones como el nombre de archivo. Los usuarios deben tener en cuenta los tipos de metadatos que podrían querer buscar y ordenar en el futuro al decidir qué metadatos incluir.
Este tutorial usa datos de muestra de imágenes GeoTIFF optimizadas para nubes (COG) del conjunto de datos de temperatura de superficie terrestre (LST) geoestacionaria de la Agencia Nacional de Medio Ambiente (NOAA) Geoestacionaria operativa satélite R (GOES-R) de temperatura de superficie terrestre (LST). Estos datos se incluyen en el ordenador planetario abierto como archivos COG, pero carece de metadatos de STAC. Los satélites GOES producen muchos productos de datos. Puede encontrar más detalles en la Guía de definición de productos y usuarios de la serie GOES-R.
El proceso usado en este tutorial se puede generalizar para cualquier tipo de datos donde los campos de metadatos clave se enumeran mediante varias bibliotecas de código abierto.
Instalación de bibliotecas de Python
Para empezar, se instalan las bibliotecas de Python necesarias mediante PIP:
rasterio
: Este paquete se usa para leer y escribir datos de trama geoespacial. Proporciona herramientas para trabajar con formatos de datos ráster como GeoTIFF.pystac
: este paquete se usa para trabajar con el estándar STAC. Proporciona herramientas para crear, leer y manipular metadatos de STAC.rio-stac
: Este paquete integrarasterio
conpystac
para crear elementos STAC a partir de datos ráster. Simplifica el proceso de generación de metadatos de STAC para conjuntos de datos ráster.matplotlib
: esta biblioteca se usa para crear visualizaciones y trazados. En el contexto de los datos geoespaciales, ayuda a representar y mostrar imágenes ráster, lo que permite a los usuarios inspeccionar visualmente los datos antes de crear metadatos de STAC.azure-storage-blob
: esta biblioteca cliente de Azure Storage proporciona acceso a los servicios de Azure Blob Storage. Permite la interacción directa con datos geoespaciales almacenados en la nube, lo que permite a los usuarios leer y trabajar con archivos almacenados en contenedores de blobs de Azure sin descargarlos primero.
!pip install rasterio pystac rio_stac matplotlib azure-storage-blob
En la siguiente sección de código se muestran algunos datos GOES-18 del ordenador planetario abierto. Seleccionamos el conjunto de datos GOES-R Advanced Baseline Imager Level 2 Land Surface Temperature - CONUS y un archivo arbitrario del día 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)
Al examinar los datos y el nombre de archivo, ya podemos ver los fragmentos clave de metadatos necesarios para compilar el elemento de STAC. El nombre de archivo contiene información sobre qué satélite capturó los datos y cuándo se capturó.
Para el ejemplo, el nombre de archivo es OR_ABI-L2-LSTC-M6_G18_s20232080101177_e20232080103550_c20232080104570_DQF, en función de la guía del producto, esto significa:
Componentes detallados
Campo | Descripción | Propósito |
---|---|---|
O | Entorno del sistema operativo | Especifica el entorno del sistema en el que se recopilaron los datos. |
ABI | Instrumento Advanced Baseline Imager | Identifica el instrumento usado para capturar los datos. |
L2 | Producto de nivel 2 (producto derivado) | Indica que los datos son un producto derivado, procesado a partir de observaciones sin procesar. |
LSTC | Producto Land Surface Temperature (Clear Sky) | Representa el tipo de producto específico, centrándose en la temperatura de la superficie terrestre bajo condiciones de cielo claro. |
M6 | Escaneo del Modo 6 (escaneo de disco completo) | Describe el modo de exploración, que cubre el disco completo de la Tierra |
G18 | SATÉLITE GOES-18 (también conocido como GOES-West) | Identifica el satélite desde el que se recopilaron los datos. |
Detalles del tiempo de observación
Inicio de la observación (s20232080201177)-
Campo | Descripción | Propósito |
---|---|---|
Año | 2023 | Especifica el año de la observación. |
Día del año | 208 | Indica el día del año en que se inició la observación. |
Tiempo | 02:01:17 UTC | Proporciona la hora exacta en que se inició la observación en UTC. |
Décimos de Segundo | 7 | Agrega precisión a la hora de inicio de la observación. |
Fin de la observación (e20232080203550)-
Campo | Descripción | Propósito |
---|---|---|
Año | 2023 | Especifica el año de la observación. |
Día del año | 208 | Indica el día del año cuando finalizó la observación. |
Tiempo | 02:03:55 UTC | Proporciona la hora exacta en que la observación finalizó en UTC. |
Décimos de Segundo | 0 | Agrega precisión a la hora de finalización de la observación |
Tiempo de creación de archivos (c20232080204563)-
Campo | Descripción | Propósito |
---|---|---|
Año | 2023 | Especifica el año en que se creó el archivo. |
Día del año | 208 | Indica el día del año en que se creó el archivo. |
Tiempo | 02:04:56 UTC | Proporciona la hora exacta en que se creó el archivo en UTC. |
Décimos de Segundo | 3 | Agrega precisión al tiempo de creación del archivo. |
Información adicional:
Campo | Descripción | Propósito |
---|---|---|
DQF | Marca de calidad de datos, que indica información de calidad para los datos correspondientes | Proporciona información sobre la calidad de los datos |
.tif | Extensión de archivo | Indica el formato de archivo de los datos. |
El código siguiente extrae estos metadatos del nombre de archivo mediante expresiones 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'}
Crear elementos STAC a partir de archivos GeoTIFF Cloud-Optimized
El siguiente bloque de código utiliza la biblioteca rio-stac
para automatizar la creación de ítems STAC a partir de GeoTIFFs (COGs) Cloud-Optimized.
Cuando se apunta a un archivo COG, rio-stac
extrae y organiza automáticamente metadatos esenciales, como límites espaciales, información de proyección y propiedades ráster en un formato STAC estandarizado. La biblioteca controla la tarea compleja de leer los metadatos técnicos incrustados de GeoTIFF y los convierte en campos compatibles con STAC, entre los que se incluyen:
- Geometría
- Cuadro de límite (bbox)
- Detalles de proyección
- Características Raster
- Extensiones de STAC
Esta automatización reduce significativamente el trabajo manual necesario para crear elementos STAC válidos y garantiza la coherencia en los metadatos.
Nota:
GeoCatalog tiene limitaciones en los caracteres que se pueden usar en identificadores de elemento de STAC y claves de recurso. Asegúrese de que los identificadores no contienen los siguientes caracteres: -
, _
, +
, (
, )
y .
. Es posible que tenga que modificar la item_id
lógica de generación para reemplazar o quitar estos caracteres de los nombres de archivo.
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": []
}
}
}
JSON del elemento STAC de rio-stac
La biblioteca rio-stac lee automáticamente el archivo COG GOES y extrae los metadatos de clave.
Además, en función del tipo de metadatos incluido, rio-stac agregó las extensiones de STAC pertinentes. Las extensiones de STAC mejoran la especificación principal agregando metadatos estandarizados y específicos del dominio.
- Extensión de archivo proporciona metadatos de archivo esenciales, como el tamaño y las sumas de verificación.
- La extensión de proyección captura información de referencia espacial, incluidos los sistemas de coordenadas y los cuadros de límite.
- La extensión de ráster estandariza las propiedades específicas de los datos ráster, como la información de banda y la resolución espacial.
En las tablas siguientes se proporciona una explicación de todos los metadatos que se encuentran en rio-stac.
Campos principales
Campo | Descripción | Propósito |
---|---|---|
tipo | Siempre "Característica" | Identifica el tipo como una característica de GeoJSON. |
stac_version | "1.0.0" | Especifica la versión estándar de STAC. |
id | Identificador único | Contiene información de satélite, producto y hora |
stac_extensions | Lista de direcciones URL de esquema | Define campos de metadatos adicionales |
Información espacial
Campo | Descripción | Propósito |
---|---|---|
geometría | Polígono GeoJSON | Define la superficie de datos en coordenadas WGS84 |
bbox | Coordenadas de rectángulo de selección | Proporciona una extensión espacial sencilla para el filtrado rápido |
proj:geometry | Polígono específico de proyección | Superficie en coordenadas de proyección nativas |
proj:bbox | Límites de proyección nativa | Extensión espacial en el sistema de coordenadas del satélite |
proj:forma | [1500, 2500] | Dimensiones de imagen en píxeles |
proj:transform | Afinar transformación | Asigna el píxel al espacio de coordenadas |
proj:wkt2 | Texto conocido | Definición de proyección completa |
proj:epsg | nulo | No existe ningún código EPSG estándar para esta proyección de mapa |
Información temporal
Campo | Descripción | Propósito |
---|---|---|
fecha y hora | Marca de tiempo de creación | Cuando se creó este elemento de STAC |
Información de trama
Campo | Descripción | Propósito |
---|---|---|
raster:bands | Matriz de objetos de banda | Describe las propiedades de datos ráster |
→ tipo_de_dato | "uint16" | Tipo de datos de píxeles |
→ spatial_resolution | 2004.02m | Distancia de muestreo en tierra |
→ escala/desplazamiento | Factores de conversión | Transforma los valores de píxel en unidades físicas (Kelvin) |
→ nodata | 65535.0 | Valor que no representa datos |
estadísticas | Resumen estadístico | Proporciona información de distribución de datos |
→ histograma | Distribución de valores | Visualiza la distribución de datos |
Información del activo
Campo | Descripción | Propósito |
---|---|---|
assets.data | Recurso de datos principal | Apunta al archivo de datos original |
→ href | URL | Ubicación del Cloud-Optimized GeoTIFF |
→ tipo | Tipo de medio | Identifica el formato de archivo |
Metadatos de archivo
Campo | Descripción | Propósito |
---|---|---|
archivo:tamaño | 943 250 bytes | Tamaño del archivo de datos |
Adición de los metadatos del nombre de archivo
A continuación, agregamos los datos que encontramos en el nombre de archivo para completar el relleno de los metadatos de este elemento de STAC.
Una cosa que hay que tener en cuenta es que todos los elementos de fecha y hora para los elementos de STAC deben cumplir con ISO 8601. La biblioteca PySTAC tiene una función datetime_to_str que garantiza que los datos tengan el formato correcto.
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))
El elemento 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": []
}
}
}
Agregar el elemento STAC a una colección
MC Pro requiere que todos los elementos de STAC tengan una referencia al identificador principal de la colección de STAC en la que se incorporan. En este tutorial, el identificador de la colección de STAC es el nombre del satélite y el producto de datos.
Con PySTAC, es fácil usar algunos de los metadatos recopilados de los archivos de origen para rellenar los campos clave de la colección STAC y usar las funciones de validación integradas.
El código siguiente crea una colección STAC primaria para hospedar los datos GOES. A continuación, el código guarda esta información en los archivos usados para crear la colección Microsoft Planetary Computer Pro STAC e ingerir elementos de STAC en Planetary 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
Pasos siguientes
Ahora que ha creado algunos elementos de STAC, es el momento de ingerir los datos en Microsoft Planetary Computer Pro.
Para la ingesta de un solo elemento:
Para la ingesta masiva:
También ofrecemos la herramienta STAC Forge , que proporciona una mayor automatización mediante plantillas en torno a los datos.