Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Коллекции STAC (каталог ресурсов SpatioTemporal) используются в GeoCatalog для индексирования и хранения связанных пространственно-временных ресурсов. В этом комплексном руководстве вы создадите новую коллекцию STAC, загрузите изображения Sentinel-2 в коллекцию и выполните запросы этих изображений с помощью API GeoCatalog.
Изучив это руководство, вы:
- Создадим собственную коллекцию STAC в планетарном компьютере Pro GeoCatalog
- Добавление спутниковых снимков в эту коллекцию из Европейского космического агентства
- Настройте коллекцию, чтобы изображения в коллекции могли визуализироваться в веб-интерфейсе Planetary Computer Pro
- Запрос данных из коллекции STAC с помощью STAC API Planetary Computer Pro
В этом руководстве показаны и объясняются возможности с помощью фрагментов кода для интерактивного интерфейса стиля записной книжки, скачайте это руководство в виде записной книжки Jupyter.
Предпосылки
Перед выполнением этого руководства вам потребуется планетарный компьютер Pro GeoCatalog, развернутый в подписке Azure. Вам также нужна среда для выполнения этой записной книжки и установки необходимых пакетов. Мы предлагаем выполнять это руководство на виртуальной машине Azure Machine Learning или использовать интеграцию записной книжки Visual Studio Code в виртуальной среде Python. Однако этот блокнот должен выполняться везде, где поддерживаются блокноты Jupyter, если выполнены следующие требования.
- Python 3.10 или более поздней версии
- Azure CLI установлен, и вы запустите az login для входа в учетную запись Azure.
- Необходимые требования, перечисленные в разделе «Опции руководства», установлены.
Откройте Jupyter notebook в Azure Machine Learning или VS Code
Вход в Azure с помощью Azure CLI
Следующая команда регистрирует вас в Azure с помощью Azure CLI. Выполните команду и следуйте инструкциям для входа.
!az login
Выбор параметров руководства
Перед выполнением этого руководства вам потребуются права доступа участника к существующему экземпляру GeoCatalog. Введите URL-адрес экземпляра GeoCatalog в переменной geocatalog_url. В этом руководстве вы создадите коллекцию для изображений Sentinel-2, предоставляемых Европейским космическим агентством (ESA), которые в настоящее время хранятся в каталоге данных планетарного компьютера Майкрософт.
# URL for your given GeoCatalog
geocatalog_url = (
"<GEOCATALOG_URL>"
)
geocatalog_url = geocatalog_url.rstrip("/") # Remove trailing slash if present
api_version = "2025-04-30-preview"
# User selections for demo
# Collection within the Planetary Computer
pc_collection = "sentinel-2-l2a"
# Bounding box for AOI
bbox_aoi = [-22.455626, 63.834083, -22.395201, 63.880750]
# Date range to search for imagery
param_date_range = "2024-02-04/2024-02-11"
# Maximum number of items to ingest
param_max_items = 6
Импорт необходимых пакетов
Прежде чем создать коллекцию STAC, необходимо импортировать несколько пакетов Python и определить вспомогательные функции для получения необходимого маркера доступа.
pip install pystac-client azure-identity requests pillow
# Import the required packages
import json
import random
import string
import time
from datetime import datetime, timedelta, timezone
from io import BytesIO
from typing import Any, Optional, Dict
import requests
from azure.identity import AzureCliCredential
from IPython.display import Markdown as md
from IPython.display import clear_output
from PIL import Image
from pystac_client import Client
# Function to get a bearer token for the Planetary Computer Pro API
MPC_APP_ID = "https://geocatalog.spatio.azure.com"
_access_token = None
def getBearerToken():
global _access_token
if not _access_token or datetime.fromtimestamp(_access_token.expires_on) < datetime.now() + timedelta(minutes=5):
credential = AzureCliCredential()
_access_token = credential.get_token(f"{MPC_APP_ID}/.default")
return {"Authorization": f"Bearer {_access_token.token}"}
# Method to print error messages when checking response status
def raise_for_status(r: requests.Response) -> None:
try:
r.raise_for_status()
except requests.exceptions.HTTPError as e:
try:
print(json.dumps(r.json(), indent=2))
except:
print(r.content)
finally:
raise
Создание коллекции STAC
Определение JSON коллекции STAC
Затем вы определяете коллекцию STAC как элемент JSON. В этом руководстве используйте существующий JSON коллекции STAC для коллекции Sentinel-2-l2a в рамках Планетарного компьютера Microsoft. Коллекция назначается случайным идентификатором и заголовком, чтобы избежать конфликта с другими существующими коллекциями.
# Load example STAC collection JSON
response = requests.get(
f"https://planetarycomputer.microsoft.com/api/stac/v1/collections/{pc_collection}"
)
raise_for_status(response)
stac_collection = response.json()
collection_id = pc_collection + "-tutorial-" + str(random.randint(0, 1000))
# Genereate a unique name for the test collection
stac_collection["id"] = collection_id
stac_collection["title"] = collection_id
# Determine the storage account and container for the assets
pc_storage_account = stac_collection.pop("msft:storage_account")
pc_storage_container = stac_collection.pop("msft:container")
pc_collection_asset_container = (
f"https://{pc_storage_account}.blob.core.windows.net/{pc_storage_container}"
)
# View your STAC collection JSON
stac_collection
При создании коллекции в GeoCatalog в JSON коллекции не может быть ресурсов уровня коллекции (например, эскиза коллекции), связанных с коллекцией, поэтому сначала удалите существующие ресурсы (не беспокойтесь, что вы добавите эскиз позже).
# Save the thumbnail url
thumbnail_url = stac_collection['assets']['thumbnail']['href']
# Remove the assets field from the JSON (you'll see how to add this back later)
print("Removed the following items from the STAC Collection JSON:")
stac_collection.pop('assets')
# Create a STAC collection by posting to the STAC collections API
collections_endpoint = f"{geocatalog_url}/stac/collections"
response = requests.post(
collections_endpoint,
json=stac_collection,
headers=getBearerToken(),
params={"api-version": api_version}
)
if response.status_code==201:
print("STAC Collection created named:",stac_collection['title'])
else:
raise_for_status(response)
Откройте веб-интерфейс GeoCatalog, и вы увидите новую коллекцию, указанную на вкладке "Коллекции".
Эскиз коллекции Access
Затем вы хотите добавить эскиз в нашу коллекцию, чтобы отобразиться вместе с нашей коллекцией. В целях этой демонстрации используйте эскиз из существующей коллекции Sentinel-2 в планетарном компьютере Майкрософт.
# Read thumbnail for your collection
thumbnail_response = requests.get(thumbnail_url)
raise_for_status(thumbnail_response)
img = Image.open(BytesIO(thumbnail_response.content))
img
Добавьте эскиз в ваш планетарный компьютер Pro GeoCatalog
После чтения эскиза вы можете добавить его в нашу коллекцию, разместив его в конечной точке API ресурсов коллекции GeoCatalogs, а также требуемый json активов.
# Define the GeoCatalog collections API endpoint
collection_assets_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/assets"
# Read the example thumbnail from this collection from the Planetary Computer
thumbnail = {"file": ("lulc.png", thumbnail_response.content)}
# Define the STAC collection asset type - thumbnail in this case
asset = {
"data": '{"key": "thumbnail", "href":"", "type": "image/png", '
'"roles": ["test_asset"], "title": "test_asset"}'
}
# Post the thumbnail to the GeoCatalog collections asset endpoint
response = requests.post(
collection_assets_endpoint,
data=asset,
files=thumbnail,
headers=getBearerToken(),
params={"api-version": api_version}
)
if response.status_code==201:
print("STAC Collection thumbnail updated for:",stac_collection['title'])
else:
raise_for_status(response)
Прочитайте новую коллекцию в вашем Planetary Computer Pro GeoCatalog
Обновите браузер и увидите эскиз. Вы также можете получить JSON коллекции программным способом, выполнив следующий вызов к конечной точке коллекций:
# Request the collection JSON from your GeoCatalog
collection_endpoint = f"{geocatalog_url}/stac/collections/{stac_collection['id']}"
response = requests.get(
collection_endpoint,
json={'collection_id':stac_collection['id']},
headers=getBearerToken(),
params={"api-version": api_version}
)
if response.status_code==200:
print("STAC Collection successfully read:",stac_collection['title'])
else:
raise_for_status(response)
response.json()
print(f"""
You successfully created a new STAC Collection in GeoCatalog named {collection_id}.
You can view your collection by visiting the GeoCatalog Explorer: {geocatalog_url}/collections
""")
Прием элементов STAC и ресурсов
После создания этой коллекции вы готовы принять новые элементы STAC в коллекцию STAC с помощью API элементов GeoCatalog! Выполните этот процесс следующим образом:
- Получение маркера SAS от планетарного компьютера Майкрософт
- Зарегистрируйте этот токен в качестве источника загрузки в GeoCatalog
- Опубликуйте элементы STAC из этой коллекции в API элементов GeoCatalog.
- Проверка успешного приема элементов
ingestion_sources_endpoint = f"{geocatalog_url}/inma/ingestion-sources"
ingestion_source_endpoint = lambda id: f"{geocatalog_url}/inma/ingestion-sources/{id}"
def find_ingestion_source(container_url: str) -> Optional[Dict[str, Any]]:
response = requests.get(
ingestion_sources_endpoint,
headers=getBearerToken(),
params={"api-version": api_version},
)
for source in response.json()["value"]:
ingestion_source_id = source["id"]
response = requests.get(
ingestion_source_endpoint(ingestion_source_id),
headers=getBearerToken(),
params={"api-version": api_version},
)
raise_for_status(response)
response = response.json()
if response["connectionInfo"]["containerUrl"] == container_url:
return response
def create_ingestion_source(container_url: str, sas_token: str):
response = requests.post(
ingestion_sources_endpoint,
json={
"kind": "SasToken",
"connectionInfo": {
"containerUrl": container_url,
"sasToken": sas_token,
},
},
headers=getBearerToken(),
params={"api-version": api_version},
)
raise_for_status(response)
def remove_ingestion_source(ingestion_source_id: str):
response = requests.delete(
ingestion_source_endpoint(ingestion_source_id),
headers=getBearerToken(),
params={"api-version": api_version},
)
raise_for_status(response)
Выполнить запрос к планетарному компьютеру
Сначала необходимо запросить планетарный компьютер для поиска изображений Sentinel-2, которые соответствуют нашим конкретным требованиям. В этом случае вы ищете изображения Sentinel-2 на планетарном компьютере, который соответствует следующим критериям:
- Коллекция — изображения из коллекции Sentinel-2-l2a
- Диапазон времени — собираемый от 4 февраля до 11 февраля 2024 г.
- Область интереса — изображение, собранное над южной Исландией (определено как ограничивающий прямоугольник)
Выполнив этот поиск, вы увидите, что соответствующие элементы STAC находятся в планетарном компьютере.
# Search criteria
print("Using the below parameters to search the Planetary Computer:\n")
print("Collection:", pc_collection)
print("Bounding box for area of interest:",bbox_aoi)
print("Date range:",param_date_range)
print("Max number of items:",param_max_items)
# Query the Planetary Computer
# Connect to the Planetary Computer
catalog = Client.open("https://planetarycomputer.microsoft.com/api/stac/v1")
search = catalog.search(collections=[pc_collection], bbox=bbox_aoi, datetime=param_date_range)
total_items = search.item_collection()
items = total_items[:param_max_items]
print("Total number of matching items:",len(total_items))
print("Total number of items for ingest base on user selected parameter:",len(items))
if total_items==0:
print("No items matched your user specified parameters used at the top of this demo. Update these parameters")
# Print an example STAC item returned by the Planetary Computer
items[0]
Регистрация источника приема
Перед приемом этих элементов STAC и связанных с ними ресурсов (изображений) в коллекцию GeoCatalog необходимо определить, нужно ли зарегистрировать новый источник приема. GeoCatalog использует источники приема для отслеживания мест хранения (контейнеров в Azure Blob Storage), к которым у него есть доступ.
Регистрация источника загрузки данных осуществляется путем предоставления GeoCatalog расположения контейнера хранилища и маркера SAS с правами на чтение для доступа к контейнеру. Если элементы STAC или связанные с ними ресурсы находятся в контейнере хранилища, то при отсутствии доступа вашего GeoCatalog к ingest операция будет завершена сбоем.
Чтобы запустить этот процесс, сначала запросите маркер SAS с планетарного компьютера, который предоставляет нам доступ на чтение к контейнеру, где находятся образы Sentinel-2.
# Request API token from the Planetary Computer
pc_token = requests.get("https://planetarycomputer.microsoft.com/api/sas/v1/token/{}".format(pc_collection)).json()
print(f"Planetary Computer API Token will expire {pc_token['msft:expiry']}")
Затем попытайтесь зарегистрировать этот контейнер хранилища BLOB-объектов Azure и связанный маркер SAS в качестве источника приема с помощью GeoCatalog. Существует потенциал того, что источник приема уже существует для этого контейнера хранилища. Если да, найдите идентификатор существующего источника приема.
Предупреждение
Если будет найден дублирующий источник приема с маркером, срок действия которого истекает в течение следующих 15 минут, он будет удален и заменен. Удаление источника загрузки, который используется в настоящее время при выполнении загрузки, может нарушить эти загрузки.
existing_ingestion_source: Optional[Dict[str, Any]] = find_ingestion_source(pc_collection_asset_container)
if existing_ingestion_source:
connection_info = existing_ingestion_source["connectionInfo"]
expiration = datetime.fromisoformat(connection_info["expiration"].split('.')[0]) # works in all Python 3.X versions
expiration = expiration.replace(tzinfo=timezone.utc) # set timezone to UTC
if expiration < datetime.now(tz=timezone.utc) + timedelta(minutes=15):
print(f"Recreating existing ingestion source for {pc_collection_asset_container}")
remove_ingestion_source(existing_ingestion_source["id"])
create_ingestion_source(pc_collection_asset_container, pc_token["token"])
else:
print(f"Using existing ingestion source for {pc_collection_asset_container} with expiration {expiration}")
else:
print(f"Creating ingestion source for {pc_collection_asset_container}")
create_ingestion_source(pc_collection_asset_container, pc_token["token"])
Импортировать элементы STAC, используя API элементов GeoCatalog
Теперь, когда вы зарегистрировали источник данных или убедились, что он существует, вы будете импортировать найденные элементы STAC в Планетарный компьютер с помощью API элементов GeoCatalog. Это можно сделать, разместив каждый элемент в API элементов, который создает новую операцию приема в GeoCatalog.
# Ingest items
items_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/items"
operation_ids = []
for item in items:
item_json = item.to_dict()
item_json['collection'] = collection_id
# Remove non-static assets
del(item_json['assets']['rendered_preview'])
del(item_json['assets']['preview'])
del(item_json['assets']['tilejson'])
response = requests.post(
items_endpoint,
json=item_json,
headers=getBearerToken(),
params={"api-version": api_version}
)
operation_ids.append(response.json()['id'])
print(f"Ingesting item {item_json['id']} with operation id {response.json()['id']}")
Учитывая, что процесс приема данных Sentinel-2 может занять некоторое время, вы можете запустить этот код, чтобы проверить статус ваших операций загрузки с помощью API операций GeoCatalog.
# Check the status of the operations
operations_endpoint = f"{geocatalog_url}/inma/operations"
# Loop through all the operations ids until the status of each operation ids is "Finished"
pending=True
start = time.time()
while pending:
# Count the number of operation ids that are finished vs unfinished
num_running = 0
num_finished = 0
num_failed = 0
clear_output(wait=True)
for operation_id in operation_ids:
response = requests.get(
f"{operations_endpoint}/{operation_id}",
headers=getBearerToken(),
params={"api-version": api_version},
)
raise_for_status(response)
status = response.json()["status"]
print(f"Operation id {operation_id} status: {status}")
if status == "Running":
num_running+=1
elif status == "Failed":
num_failed+=1
elif status == "Succeeded":
num_finished+=1
num_running
stop=time.time()
# Print the sumary of num finished, num running and num failed
print("Ingesting Imagery:")
print(f"\tFinished: {num_finished}\n\tRunning: {num_running}\n\tFailed: {num_failed}")
print("Time Elapsed (seconds):",str(stop-start))
if num_running == 0:
pending=False
print(f"Ingestion Complete!\n\t{num_finished} items ingested.\n\t{num_failed} items failed.")
else:
print(f"Waiting for {num_running} operations to finish")
time.sleep(5)
Вы должны иметь возможность обновить веб-браузер и щелкнуть вкладку "Элементы", чтобы увидеть эти только что отправленные элементы.
Управление коллекциями
После импорта этих элементов STAC и связанных с ними ресурсов (изображений) в коллекцию STAC вам необходимо предоставить GeoCatalog другие файлы конфигурации, прежде чем визуализировать эти элементы в веб-интерфейсе GeoCatalog.
Параметры визуализации коллекции
Сначала загрузите файл конфигурации визуализации для этой коллекции с Планетарного Компьютера. Этот файл конфигурации можно считывать в GeoCatalog для отрисовки изображений различными способами в обозревателе. Это связано с тем, что элементы STAC могут содержать множество различных ресурсов (изображений), которые можно объединить для создания совершенно новых изображений определенной области, которая выделяет видимые или невидимые функции. Например, элементы STAC Sentinel-2 имеют более 12 различных изображений из разных частей электромагнитного спектра. Эта конфигурация отрисовки указывает GeoCatalog, как объединить эти изображения, чтобы он мог отображать изображения в естественных цветах или псевдоцветах (инфракрасных цветах).
# Read render JSON from Planetary Computer
render_json = requests.get("https://planetarycomputer.microsoft.com/api/data/v1/mosaic/info?collection={}".format(pc_collection)).json()
render_json['renderOptions']
После чтения этой конфигурации параметров отрисовки с планетарного компьютера можно включить эти параметры отрисовки для коллекции, разместив эту конфигурацию в конечной точке параметров отрисовки.
# Post render options config to GeoCatalog render-options API
render_config_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/configurations/render-options"
for render_option in render_json['renderOptions']:
# Rename render configs such that they can be stored by GeoCatalog
render_option['id'] = render_option['name'].translate(str.maketrans('', '', string.punctuation)).lower().replace(" ","-")[:30]
# Post render definition
response = requests.post(
render_config_endpoint,
json=render_option,
headers=getBearerToken(),
params={"api-version": api_version}
)
Определения мозаики
Как и в описанной выше конфигурации отрисовки, обозреватель GeoCatalog позволяет указать одно или несколько определений мозаики для коллекции. Эти определения мозаики позволяют нам задавать инструкции Проводнику GeoCatalog о том, как фильтровать элементы, отображаемые в Проводнике. Например, одна базовая конфигурация отрисовки (показанная в следующей ячейке) указывает GeoCatalog отображать последнее изображение для любой заданной области. Более сложные конфигурации отрисовки позволяют отображать различные представления, такие как наименее облачное изображение для заданного расположения, снятое в октябре 2023 года.
# Post mosaic definition
mosiacs_config_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/configurations/mosaics"
response = requests.post(
mosiacs_config_endpoint,
json={"id": "mos1",
"name": "Most recent available",
"description": "Most recent available imagery in this collection",
"cql": []
},
headers=getBearerToken(),
params={"api-version": api_version}
)
Открытие веб-интерфейса GeoCatalog
Поздравляю! Вы создали коллекцию, добавили элементы и ресурсы STAC и обновили коллекцию, чтобы включить необходимые файлы конфигурации, чтобы его можно было просмотреть через обозреватель в веб-интерфейсе GeoCatalog.
Вернитесь в эксплорер GeoCatalog в веб-интерфейсе, чтобы просмотреть вашу коллекцию!
Сбор запросов с помощью API STAC
Теперь, когда вы просмотрели коллекцию в GeoCatalog Explorer, вы сможете узнать, как использовать API STAC GeoCatalog для поиска и извлечения элементов и ресурсов STAC для дальнейшего анализа.
Этот процесс начинается с отправки поиска в API STAC GeoCatalog. В частности, вы будете искать изображения в вашей коллекции, которые находятся внутри исходной ограничивающей рамки, которую вы использовали для извлечения изображений из Планетарного Компьютера.
Неудивительно, что этот запрос возвращает все элементы STAC, ранее помещенные в коллекцию.
stac_search_endpoint = f"{geocatalog_url}/stac/search"
response = requests.post(
stac_search_endpoint,
json={"collections":[collection_id],
"bbox":bbox_aoi
},
headers=getBearerToken(),
params={"api-version": api_version, "sign": "true"}
)
matching_items = response.json()['features']
print(len(matching_items))
В предыдущем запросе вы также указали другой параметр: sign:true. Это указывает GeoCatalog на возврат подписанного href (href элемента + SAS токен), который позволяет читать указанные ресурсы из блоб-объектов хранилища Azure.
# Download one of the assets bands, band 09
asset_href = matching_items[0]['assets']['B09']['href']
print(asset_href)
response = requests.get(asset_href)
img = Image.open(BytesIO(response.content))
img
Очистите ресурсы
Удаление элементов
На этом этапе вы создали коллекцию GeoCatalog, добавили элементы и ресурсы в коллекцию и извлекли эти элементы и ресурсы с помощью API STAC GeoCatalog. На последнем этапе этого руководства вы собираетесь удалить эти элементы и удалить коллекцию.
# Delete all items
for item in matching_items:
response = requests.delete(
f"{items_endpoint}/{item['id']}",
headers=getBearerToken(),
params={"api-version": api_version}
)
Вы можете подтвердить удаление всех элементов, выполнив следующую команду. Обратите внимание, что для полного удаления элементов и связанных с ними ресурсов может потребоваться несколько минут.
# Confirm that all the items have been deleted
response = requests.post(
stac_search_endpoint,
json={"collections":[stac_collection['id']],
"bbox": bbox_aoi
},
headers=getBearerToken(),
params={"api-version": api_version, "sign": "true"}
)
matching_items = response.json()['features']
print(len(matching_items))
Удаление коллекции
Теперь в качестве последнего шага может потребоваться полностью удалить коллекцию из экземпляра GeoCatalog.
# Delete the collection
response = requests.delete(
f"{collections_endpoint}/{collection_id}",
headers=getBearerToken(),
params={"api-version": api_version}
)
raise_for_status(response)
print(f"STAC Collection deleted: {collection_id}")
Дальнейшие шаги
Связанный контент
В этом комплексном руководстве описан процесс создания новой коллекции STAC, приема образов Sentinel-2 в коллекцию и отправки запросов к этим изображениям с помощью API GeoCatalog. Если вы хотите узнать больше о каждой из этих тем, изучите следующие материалы: