Создайте элемент SpatioTemporal Asset Catalog (STAC)

Узнайте, как создать элемент каталога ресурсов SpatioTemporal (STAC) для растрового геопространственного ресурса. Каждый геопространственный набор данных, загружаемый в Microsoft Planetary Computer Pro GeoCatalog, должен иметь связанный элемент, соответствующий стандарту STAC.

В этом руководстве вы:

  • Установите необходимые библиотеки Python с помощью PIP.
  • Отображение и проверка данных GOES-18 с помощью предоставленного кода Python.
  • Извлеките метаданные из имени файла с помощью регулярных выражений.
  • Создайте элементы STAC из файлов GeoTIFF Cloud-Optimized с помощью rio-stac.
  • Улучшите элемент STAC, используя метаданные, извлеченные из имени файла.
  • Добавьте элемент STAC в родительскую коллекцию STAC.
  • Проверьте и сохраните каталог STAC, коллекцию и объекты.
  • Добавьте элементы STAC в Microsoft Planetary Computer Pro.

В этом руководстве показаны и объясняются возможности с помощью фрагментов кода для интерактивного интерфейса стиля записной книжки, скачайте это руководство в виде записной книжки Jupyter.

Предпосылки

Чтобы завершить это краткое начальное руководство, вам требуется:

Ключевые функции STAC

Каталог активов SpatioTemporal (STAC) — это открытый стандарт для структурирования и совместного использования геопространственных данных. Он предоставляет общий язык и формат для описания геопространственных ресурсов, что упрощает обнаружение, доступ и использование этих ресурсов на разных платформах и приложениях. Ниже приведены ключевые функции стандарта STAC:

  • Взаимодействие. Стандартизованная схема на основе JSON обеспечивает простую интеграцию и понимание между инструментами и системами.
  • Расширяемость: гибкие поля ядра с пользовательскими расширениями для конкретных потребностей.
  • Возможность обнаружения: согласованная структура улучшает поиск и обнаружение геопространственных ресурсов.
  • Доступность: Прямые ссылки на ресурсы данных упрощают извлечение и интеграцию.
  • Автоматизация. Включает автоматическую обработку и анализ с стандартизированными метаданными.

Преимущества STAC для стандартизации метаданных

  • Согласованность между типами данных: единая платформа для различных геопространственных типов данных.
  • Улучшенная совместная работа: упрощение общего доступа и совместной работы с общим форматом метаданных.
  • Улучшенная интеграция данных: упрощает интеграцию наборов данных из нескольких источников.
  • Упрощенное управление данными: автоматизированные средства сокращают усилия вручную при обслуживании метаданных.
  • Подготовка к будущему: гибкость и расширяемость позволяют адаптироваться к новым типам данных и технологиям.

Microsoft Planetary Computer Pro (MC Pro) использует STAC в качестве основного стандарта индексирования для обеспечения взаимодействия между наборами данных. В этом руководстве показано, как создавать элементы STAC с нуля с помощью общих библиотек с открытым исходным кодом.

Спецификация элементов STAC описывает, как создаются элементы STAC и необходимые минимальные метаданные, которые должны быть заполнены. STAC — это гибкий стандарт, позволяющий пользователям решать, какие данные они хотят включить в рамках метаданных. Метаданные, которые можно использовать для заполнения элемента STAC, могут быть включены в ресурс данных, в сопутствующем файле (.XML, .JSON, .TXT и т. д.) или даже в таких местах, как имя файла. Пользователи должны учитывать типы метаданных, по которым они могут захотеть выполнить поиск и сортировку в будущем, решая, какие метаданные следует включить.

В этом руководстве используются образцы данных изображений GeoTIFF (COG), оптимизированных для облачного хранения, из данных Национального океанического и атмосферного агентства (NOAA) Геостационарных операционных спутников R (GOES-R) набора данных по температуре поверхности земли (LST). Эти данные включены в открытый планетарный компьютер в виде ФАЙЛОВ COG, но не хватает метаданных STAC. Спутники GOES производят множество продуктов данных. Дополнительные сведения см. в руководстве по определению продуктов и пользователям серииGOES-R.

Процесс, используемый в этом руководстве, можно обобщить для любого типа данных, в которых перечисляются поля ключевых метаданных с помощью нескольких библиотек с открытым исходным кодом.

Установка библиотек Python

Для начала мы устанавливаем необходимые библиотеки Python с помощью PIP:

  • rasterio: Этот пакет используется для чтения и записи геопространственных растровых данных. Он предоставляет средства для работы с форматами данных растровых данных, такими как GeoTIFF.

  • pystac: этот пакет используется для работы со стандартом STAC. Он предоставляет средства для создания, чтения и управления метаданными STAC.

  • rio-stac: этот пакет интегрирует rasterio с pystac для создания элементов STAC из растровых данных. Это упрощает процесс создания метаданных STAC для растровых наборов данных.

  • matplotlib: эта библиотека используется для создания визуализаций и графиков. В контексте геопространственных данных она помогает визуализировать и отображать растровые изображения, позволяя пользователям визуально оценивать данные перед созданием метаданных STAC.

  • azure-storage-blob: Эта клиентская библиотека служба хранилища Azure предоставляет доступ к сервисам Хранилище BLOB-объектов Azure. Он позволяет напрямую взаимодействовать с облачными геопространственных данными, позволяя пользователям читать и работать с файлами, хранящимися в контейнерах BLOB-объектов Azure, не скачивая их сначала.

!pip install rasterio pystac rio_stac matplotlib azure-storage-blob 

В следующем разделе кода отображаются некоторые данные GOES-18 с открытого планетарного компьютера. Мы выбираем набор данных GOES-R Advanced Baseline Imager level 2 Land Surface Temperature ( CONUS ) и произвольный файл из дня 208 из 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)

Черно-белая визуализация геопространственных растровых данных со спутника GOES-18, показывающая распределение температуры поверхности земли в регионе.

Просматривая данные и имя файла, мы уже видим ключевые фрагменты метаданных, необходимые для сборки элемента STAC. Имя файла содержит сведения о том, какой спутник захватил данные и когда он был записан.

Для примера имя файла — OR_ABI-L2-LSTC-M6_G18_s20232080101177_e20232080103550_c20232080104570_DQF на основе руководства по продукту, это означает:

Подробные компоненты

Поле Описание Цель
ИЛИ Операционная система Указывает системную среду, в которой были собраны данные
ABI Инструмент Advanced Baseline Imager Определяет инструмент, используемый для записи данных
L2 Продукт уровня 2 (производный продукт) Указывает, что данные являются производным продуктом, обработанным из необработанных наблюдений
LSTC Продукт "Температура поверхности земли" (Clear Sky) Представляет конкретный тип продукта, фокусируясь на температуре поверхности земли в условиях ясного неба
M6 Режим 6 (проверка полного диска) Описывает режим сканирования, охватывающий полный диск Земли
G18 Спутник GOES-18 (также известный как GOES-West) Определяет спутник, из которого были собраны данные

Сведения о времени наблюдения

Начало наблюдения (s20232080201177)-

Поле Описание Цель
Год 2023 Указывает год наблюдения
День года 208 Указывает день года, когда началось наблюдение
Время 02:01:17 UTC Предоставляет точное время начала наблюдения в формате UTC
Десятые секунды 7 Добавляет точность в время начала наблюдения

Завершение наблюдения (e2023208020203550)-

Поле Описание Цель
Год 2023 Указывает год наблюдения
День года 208 Указывает день года, когда наблюдение закончилось
Время 02:03:55 UTC Предоставляет точное время окончания наблюдения в формате UTC
Десятые секунды 0 Добавляет точность к времени окончания наблюдения

Время создания файла (c2023208020204563)-

Поле Описание Цель
Год 2023 Указывает год создания файла
День года 208 Указывает день года создания файла
Время 02:04:56 UTC Предоставляет точное время создания файла в формате UTC
Десятые секунды 3 Добавляет точность во время создания файла

Дополнительные сведения

Поле Описание Цель
DQF Флаг качества данных, указывающий сведения о качестве соответствующих данных Предоставляет сведения о качестве данных
.tif Расширение файла Указывает формат файла данных

Следующий код извлекает эти метаданные из имени файла с помощью регулярных выражений (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'}

Создание STAC элементов из файлов GeoTIFF Cloud-Optimized

Следующий блок кода использует rio-stac библиотеку для автоматизации создания элементов STAC из Cloud-Optimized GeoTIFFs (COG).

При указании на COG-файл rio-stac автоматически извлекает и упорядочивает важные метаданные, такие как пространственные границы, сведения о проекции и растровые свойства в стандартизированном формате STAC. Библиотека обрабатывает сложную задачу чтения внедренных технических метаданных из GeoTIFF и преобразует ее в поля, совместимые с STAC, включая:

  • Геометрия
  • Ограничивающий прямоугольник (bbox)
  • Сведения о проекции
  • Растровые характеристики
  • Расширения STAC

Эта автоматизация значительно снижает нагрузку вручную, необходимую для создания допустимых элементов STAC, и обеспечивает согласованность в метаданных.

Замечание

GeoCatalog имеет ограничения на символы, которые можно использовать в идентификаторах элементов STAC и ключах активов. Убедитесь, что идентификаторы не содержат следующие символы: -, _, +, (, ), и .. Может потребоваться изменить логику item_id создания, чтобы заменить или удалить эти символы из имен файлов.

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 элемента STAC из rio-stac

Библиотека rio-stac считывает COG-файл GOES и автоматически извлекает метаданные ключа.

Кроме того, rio-stac добавил соответствующие расширения STAC на основе типа включаемых метаданных. Расширения STAC повышают базовую спецификацию, добавляя стандартизированные метаданные, относящиеся к домену.

  • Расширение файла предоставляет основные метаданные файла, такие как размер и контрольные суммы.
  • Расширение проекции фиксирует сведения о пространственной ссылке, включая системы координат и рамки.
  • Расширение raster стандартизирует свойства, относящиеся к растровых данных, например сведения о полосе и пространственное разрешение.

В следующих таблицах приведено объяснение всех найденных метаданных rio-stac.

Основные поля

Поле Описание Цель
тип Всегда "Функция" Определяет тип как компонент GeoJSON
версия stac 1.0.0 Указывает стандартную версию STAC
идентификатор Уникальный идентификатор Содержит сведения о спутнике, продукте и времени
stac_extensions Список URL-адресов схемы Определяет дополнительные поля метаданных

Пространственные сведения

Поле Описание Цель
геометрия Многоугольник GeoJSON Определяет объем данных в координатах WGS84
bbox Координаты ограничивающего прямоугольника Предоставляет простую пространственные экстенты для быстрого фильтрации
proj:geometry Многоугольник, специфичный для проекции Отпечаток в собственных координатах проекции
proj:bbox Границы собственной проекции Пространственная протяженность в системе координат спутника
proj:shape [1500, 2500] Размеры изображения в пикселях
proj:transform аффинное преобразование Сопоставляет пиксель с координатным пространством
proj:wkt2 текст Well-Known Полное определение проекции
proj:epsg ноль Для этой проекции карты нет стандартного кода EPSG

Темпоральная информация

Поле Описание Цель
дата/время Метка времени создания После того как был создан этот элемент STAC

Сведения о растре

Поле Описание Цель
растр:полосы Массив объектов группы Описание свойств растровых данных
Тип данных uint16 Тип данных пикселей
пространственное разрешение 2004,02 м Дистанция измерения земного объекта
→ масштабирование или смещение Факторы преобразования Преобразует значения пикселей в физические единицы (Kelvin)
нет данных 65535.0 Значение, представляющее отсутствие данных
статистика → Статистическая сводка Предоставляет сведения о распределении данных
гистограмма → Распределение значений Визуализация распределения данных

Сведения о ресурсах

Поле Описание Цель
данные активов Основной ресурс данных Указывает на фактический файл данных
→ href URL-адрес Расположение файла Cloud-Optimized GeoTIFF
тип → Тип мультимедиа Определяет формат файла

Метаданные файла

Поле Описание Цель
файл:размер 943 250 байт Размер файла данных

Добавление метаданных из имени файла

Затем мы добавим данные, найденные в имени файла, чтобы завершить заполнение метаданных для этого элемента STAC.

Важно отметить, что все значения даты и времени для элементов STAC должны соответствовать стандарту ISO 8601. Библиотека PySTAC имеет функцию datetime_to_str, которая гарантирует правильность форматирования данных.

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))

Элемент 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": []
        }
      }
    }

Добавление элемента STAC в коллекцию

MC Pro требует, чтобы все элементы STAC имели ссылку на идентификатор родительской коллекции STAC, в которую они были добавлены. В этом руководстве идентификатор коллекции STAC — это имя спутника и продукта данных.

С помощью PySTAC можно легко использовать некоторые метаданные, собранные из исходных файлов, для заполнения ключевых полей коллекции STAC и использования встроенных функций проверки.

Следующий код создает родительскую коллекцию STAC для размещения данных GOES. Затем код сохраняет эту информацию в файлы, используемые для создания коллекции STAC Microsoft Planetary Computer Pro и интеграции элементов STAC в Microsoft 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

Дальнейшие шаги

Теперь, когда вы создали несколько элементов STAC, пришло время загрузить данные в сервис Microsoft Planetary Computer Pro.

Для приема отдельных элементов:

Для массового приема:

Используйте инструмент STAC Forge для повышения автоматизации, используя шаблоны, связанные с данными.