diff --git a/datasets/met-office/met-office-icechunk.ipynb b/datasets/met-office/met-office-icechunk.ipynb new file mode 100644 index 0000000..de50895 --- /dev/null +++ b/datasets/met-office/met-office-icechunk.ipynb @@ -0,0 +1,2454 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3ac0585d-4182-49cf-981d-023aa041c9e9", + "metadata": {}, + "source": [ + "## Loading Met Office Deterministic Forecast data into Icechunk\n", + "\n", + "The Met Office Deterministic collections have data for each variable and forecast time step stored in a separate NetCDF file. This makes querying the data somewhat cumbersome because you need to write a STAC search query then write the right incantation to load the assets of interest into an xarray Dataset. This is a perfect application for a virtual representation of the collection in Icechunk that can simply be 'opened' by xarray and queried using the `sel` and `isel` methods.\n", + "\n", + "In this tutorial you will learn how to construct a virtual copy of the forecast hour zero records from the Met Office Global Deterministic collection and how to write it to a persistent icechunk store that could be used again later. At the end there is also a performance benchmark analysis that compares query performance for the icechunk store to the \"legacy\" approach involving STAC queries and more manual file i/o operations with `xarray`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "535ee085-e17f-46bc-8db2-417e06620653", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/henry/workspace/microsoft/PlanetaryComputerExamples/.venv/bin/python3: No module named pip\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install -q icechunk pystac-client xarray dask[distributed] obstore obspec-utils pystac tqdm virtualizarr h5py h5netcdf" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e2bd4455-b9ca-4e5a-9d67-fe8da13b7793", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "from collections import defaultdict\n", + "from concurrent.futures import ThreadPoolExecutor\n", + "from contextlib import contextmanager\n", + "from dataclasses import dataclass\n", + "from datetime import UTC, datetime, timedelta\n", + "from itertools import batched\n", + "from typing import Any\n", + "from urllib.parse import urlparse\n", + "\n", + "import icechunk as ic\n", + "import pandas as pd\n", + "import pystac_client\n", + "import xarray as xr\n", + "import zarr\n", + "from icechunk.credentials import AzureRefreshableCredential\n", + "from obspec_utils.readers import BlockStoreReader\n", + "from obspec_utils.registry import ObjectStoreRegistry\n", + "from obstore.auth.planetary_computer import PlanetaryComputerCredentialProvider\n", + "from obstore.store import AzureStore\n", + "from pystac import Collection, Item, ItemCollection\n", + "from tqdm import tqdm\n", + "from virtualizarr import open_virtual_mfdataset\n", + "from virtualizarr.parsers import HDFParser\n", + "\n", + "zarr.config.set({\"async.concurrency\": 128})\n", + "pd.set_option(\"display.precision\", 2)\n", + "\n", + "STACType = dict[str, Any] | Item | ItemCollection | Collection" + ] + }, + { + "cell_type": "markdown", + "id": "534a6541-235a-478a-a9f3-eeed49cb3d02", + "metadata": {}, + "source": [ + "### Gather items in a STAC search\n", + "\n", + "The Met Office STAC items have `https` asset hrefs which work fine for basic file reads but for the smoothest integration with obspec-utils and icechunk we need to convert them to `abfs://` hrefs.\n", + "\n", + "See https://github.com/developmentseed/obspec-utils/issues/79 for a discussion on improving the handling of Azure Blob https links in obspec-utils.\n", + "\n", + "The following functions can be used to apply this modification to the asset hrefs as they are processed by pystac-client." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "6ee39406-955c-4aaa-b4b4-70efe0a3e7bb", + "metadata": {}, + "outputs": [], + "source": [ + "def https_blob_to_abfs(url: str) -> tuple[str, str, str]:\n", + " \"\"\"Convert an Azure Blob HTTPS URL to an ABFS URL.\"\"\"\n", + " parsed = urlparse(url)\n", + " if parsed.scheme != \"https\" or not parsed.netloc.endswith(\".blob.core.windows.net\"):\n", + " raise ValueError(f\"Expected an Azure Blob HTTPS URL, got {url!r}\")\n", + "\n", + " account_name = parsed.netloc.split(\".\")[0]\n", + " container, blob_path = parsed.path.lstrip(\"/\").split(\"/\", 1)\n", + " return f\"abfs://{container}/{blob_path}\", account_name, container\n", + "\n", + "\n", + "def _rewrite_asset_dict_in_place(asset: dict[str, Any]) -> None:\n", + " href = asset.get(\"href\")\n", + " if not isinstance(href, str):\n", + " return\n", + "\n", + " parsed = urlparse(href)\n", + " if parsed.scheme != \"https\" or not parsed.netloc.endswith(\".blob.core.windows.net\"):\n", + " return\n", + "\n", + " abfs_href, _, _ = https_blob_to_abfs(href)\n", + " alternate = asset.setdefault(\"alternate\", {})\n", + " if isinstance(alternate, dict):\n", + " alternate.setdefault(\"https\", {\"href\": href})\n", + " asset[\"href\"] = abfs_href\n", + "\n", + "\n", + "def _rewrite_item_dict_in_place(item: dict[str, Any]) -> None:\n", + " assets = item.get(\"assets\")\n", + " if not isinstance(assets, dict):\n", + " return\n", + "\n", + " for asset in assets.values():\n", + " if isinstance(asset, dict):\n", + " _rewrite_asset_dict_in_place(asset)\n", + "\n", + "\n", + "def _rewrite_item_in_place(item: Item) -> None:\n", + " for asset in item.assets.values():\n", + " href = asset.href\n", + " parsed = urlparse(href)\n", + " if parsed.scheme != \"https\" or not parsed.netloc.endswith(\n", + " \".blob.core.windows.net\"\n", + " ):\n", + " continue\n", + "\n", + " abfs_href, _, _ = https_blob_to_abfs(href)\n", + " alternate = asset.extra_fields.setdefault(\"alternate\", {})\n", + " if isinstance(alternate, dict):\n", + " alternate.setdefault(\"https\", {\"href\": href})\n", + " asset.href = abfs_href\n", + "\n", + "\n", + "def replace_https_with_abfs(obj: STACType) -> None:\n", + " \"\"\"Rewrite Azure Blob asset hrefs to ABFS in place for pystac-client.\"\"\"\n", + " if isinstance(obj, ItemCollection):\n", + " for item in obj.items:\n", + " _rewrite_item_in_place(item)\n", + " return\n", + "\n", + " if isinstance(obj, Item):\n", + " _rewrite_item_in_place(obj)\n", + " return\n", + "\n", + " if not isinstance(obj, dict):\n", + " return\n", + "\n", + " if obj.get(\"type\") == \"FeatureCollection\":\n", + " for feature in obj.get(\"features\", []):\n", + " if isinstance(feature, dict):\n", + " _rewrite_item_dict_in_place(feature)\n", + " return\n", + "\n", + " if obj.get(\"type\") == \"Feature\":\n", + " _rewrite_item_dict_in_place(obj)" + ] + }, + { + "cell_type": "markdown", + "id": "a7a1a231-1f89-4722-9fb4-705ae2003723", + "metadata": {}, + "source": [ + "Start by running a STAC search for a few days of historical Met Office zero-hour forecast (analysis) records from the Global Deterministic Near Surface collection (`met-office-global-deterministic-near-surface`). Each item contains a few dozen assets and each asset references a single NetCDF file with a single data variable. See the [comprehensive Met Office tutorial notebook](./met-office-forecast-data.ipynb) for a more complete description of the dataset's structure." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2f47a606-852c-4a8b-ba6b-8ea3c6ccebec", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "found 124 items\n", + "assets for 2026-05-01T00:00:00+00:00: ['rainfall_rate', 'snowfall_rate', 'wind_gust_at_10m', 'wind_speed_at_10m', 'precipitation_rate', 'height_of_orography', 'wind_direction_at_10m', 'temperature_at_surface', 'pressure_at_mean_sea_level', 'visibility_at_screen_level', 'snow_depth_water_equivalent', 'temperature_at_screen_level', 'fog_fraction_at_screen_level', 'rainfall_rate_from_convection', 'snowfall_rate_from_convection', 'relative_humidity_at_screen_level', 'radiation_flux_in_uv_downward_at_surface', 'temperature_of_dew_point_at_screen_level', 'radiation_flux_in_longwave_downward_at_surface', 'radiation_flux_in_shortwave_total_downward_at_surface', 'radiation_flux_in_shortwave_direct_downward_at_surface']\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "
\n", + "
\n", + " <Asset href=abfs://deterministic/global/near-surface/20260501T0000Z/20260501T0000Z-PT0000H00M-temperature_at_surface.nc>\n", + "
\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "catalog = pystac_client.Client.open(\n", + " \"https://planetarycomputer.microsoft.com/api/stac/v1/\",\n", + " modifier=replace_https_with_abfs,\n", + ")\n", + "\n", + "search = catalog.search(\n", + " collections=\"met-office-global-deterministic-near-surface\",\n", + " datetime=[\n", + " datetime(2026, 5, 1, tzinfo=UTC),\n", + " datetime(2026, 6, 1, tzinfo=UTC) - timedelta(seconds=1),\n", + " ],\n", + " filter_lang=\"cql2-json\",\n", + " filter={\n", + " \"op\": \"=\",\n", + " \"args\": [\n", + " {\"property\": \"forecast:horizon\"},\n", + " \"PT0000H00M\",\n", + " ],\n", + " },\n", + " sortby=\"datetime\",\n", + " limit=100,\n", + ")\n", + "\n", + "items = search.item_collection()\n", + "\n", + "print(f\"found {len(items)} items\")\n", + "\n", + "sample_item = items[0]\n", + "print(\n", + " f\"assets for {sample_item.datetime.isoformat()}:\",\n", + " list(sample_item.assets.keys()),\n", + ")\n", + "\n", + "sample_asset = sample_item.assets[\"temperature_at_surface\"]\n", + "sample_asset" + ] + }, + { + "cell_type": "markdown", + "id": "7beca6eb-0deb-4ad5-84a7-1ab40cf66cf4", + "metadata": {}, + "source": [ + "### Configure cloud storage access for VirtualiZarr\n", + "\n", + "Now use a sample asset to configure object storage access for reading the raw data. \n", + "\n", + "The `PlanetaryComputerCredentialProvider` from obstore can be used to automatically generate SAS tokens for individual asset read operations." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e6aa8953-f859-400c-9eb8-48939534d0c0", + "metadata": {}, + "outputs": [], + "source": [ + "sample_asset_https_href = sample_asset.extra_fields[\"alternate\"][\"https\"][\"href\"]\n", + "_, account_name, container_name = https_blob_to_abfs(sample_asset_https_href)\n", + "\n", + "pc_credential_provider = PlanetaryComputerCredentialProvider(\n", + " f\"abfs://{container_name}\",\n", + " account_name=account_name,\n", + ")\n", + "\n", + "base_store = AzureStore(\n", + " container_name=container_name,\n", + " account_name=account_name,\n", + " credential_provider=pc_credential_provider,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "f957484f-ed20-4a21-ae8a-6b138288af0f", + "metadata": {}, + "source": [ + "Set up the object storage registry for virtualizarr and define a `ThreadPoolExecutor` to handle parallelism while virtualizing the assets." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3c4cfdd8-802d-4068-b27a-ef3219895309", + "metadata": {}, + "outputs": [], + "source": [ + "parser = HDFParser(reader_factory=BlockStoreReader)\n", + "\n", + "registry = ObjectStoreRegistry({f\"abfs://{container_name}\": base_store})\n", + "\n", + "\n", + "class VirtualizarrThreadPool(ThreadPoolExecutor):\n", + " def __init__(self):\n", + " super().__init__(max_workers=32)" + ] + }, + { + "cell_type": "markdown", + "id": "2f9d8c45-f216-4339-88ee-e594032bf870", + "metadata": {}, + "source": [ + "Now open the assets for a single item as a virtual dataset. Each asset contains one data variable (and several other non-data variables). We are doing this so we can inspect the structure of the virtual representation." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d48aa8e7-11d6-4b68-be03-3a835d58fbe8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1 s, sys: 603 ms, total: 1.61 s\n", + "Wall time: 22.9 s\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 413MB\n",
+       "Dimensions:                                           (time: 1, latitude: 1920,\n",
+       "                                                       longitude: 2560, bnds: 2)\n",
+       "Coordinates:\n",
+       "  * time                                              (time) datetime64[ns] 8B ...\n",
+       "    latitude                                          (latitude) float32 8kB ...\n",
+       "    longitude                                         (longitude) float32 10kB ManifestArray<shape=(2560,), dtype=float32, chunks=(2560,...\n",
+       "    forecast_period                                   int32 4B ManifestArray<...\n",
+       "    forecast_reference_time                           int64 8B ManifestArray<...\n",
+       "    height                                            float32 4B ManifestArra...\n",
+       "Dimensions without coordinates: bnds\n",
+       "Data variables: (12/24)\n",
+       "    rainfall_rate                                     (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    latitude_longitude                                (time) int32 4B Manifes...\n",
+       "    latitude_bnds                                     (time, latitude, bnds) float32 15kB ManifestArray<shape=(1, 1920, 2), dtype=float32, chunks=...\n",
+       "    longitude_bnds                                    (time, longitude, bnds) float32 20kB ManifestArray<shape=(1, 2560, 2), dtype=float32, chunks...\n",
+       "    lwe_snowfall_rate                                 (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    wind_speed_of_gust                                (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    ...                                                ...\n",
+       "    relative_humidity                                 (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    surface_downwelling_ultraviolet_flux_in_air       (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    dew_point_temperature                             (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    surface_downwelling_longwave_flux_in_air          (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    surface_downwelling_shortwave_flux_in_air         (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "    surface_direct_downwelling_shortwave_flux_in_air  (time, latitude, longitude) float32 20MB ManifestArray<shape=(1, 1920, 2560), dtype=float32, chu...\n",
+       "Attributes:\n",
+       "    history:                      2026-05-01T03:21:10Z: StaGE Decoupler\n",
+       "    institution:                  Met Office\n",
+       "    mosg__forecast_run_duration:  PT168H\n",
+       "    mosg__grid_domain:            global\n",
+       "    mosg__grid_type:              standard\n",
+       "    mosg__grid_version:           1.7.0\n",
+       "    mosg__model_configuration:    gl_det\n",
+       "    source:                       Met Office Unified Model\n",
+       "    title:                        Global Model Forecast on Global 10 km Stand...\n",
+       "    um_version:                   13.8\n",
+       "    Conventions:                  CF-1.7, UKMO-1.0
" + ], + "text/plain": [ + " Size: 413MB\n", + "Dimensions: (time: 1, latitude: 1920,\n", + " longitude: 2560, bnds: 2)\n", + "Coordinates:\n", + " * time (time) datetime64[ns] 8B ...\n", + " latitude (latitude) float32 8kB ...\n", + " longitude (longitude) float32 10kB ManifestArray 0 else None)" + ] + }, + { + "cell_type": "markdown", + "id": "85a1879b-61bf-426a-bd32-7b55ee2797a5", + "metadata": {}, + "source": [ + "### Read from the Icechunk repository\n", + "\n", + "You can open a connection to the virtual array with a month's worth of forecast hour zero with xarray! " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a55f9274-c20d-482b-9c1c-fa1ee5b40093", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 51GB\n",
+       "Dimensions:                                           (time: 124,\n",
+       "                                                       latitude: 1920,\n",
+       "                                                       longitude: 2560, bnds: 2)\n",
+       "Coordinates:\n",
+       "  * time                                              (time) datetime64[ns] 992B ...\n",
+       "  * latitude                                          (latitude) float32 8kB ...\n",
+       "  * longitude                                         (longitude) float32 10kB ...\n",
+       "    forecast_period                                   int32 4B ...\n",
+       "    height                                            float32 4B ...\n",
+       "    forecast_reference_time                           datetime64[ns] 8B ...\n",
+       "Dimensions without coordinates: bnds\n",
+       "Data variables: (12/24)\n",
+       "    air_pressure_at_sea_level                         (time, latitude, longitude) float32 2GB ...\n",
+       "    lwe_snowfall_rate                                 (time, latitude, longitude) float32 2GB ...\n",
+       "    relative_humidity                                 (time, latitude, longitude) float32 2GB ...\n",
+       "    dew_point_temperature                             (time, latitude, longitude) float32 2GB ...\n",
+       "    convective_rainfall_rate                          (time, latitude, longitude) float32 2GB ...\n",
+       "    longitude_bnds                                    (time, longitude, bnds) float32 3MB ...\n",
+       "    ...                                                ...\n",
+       "    wind_from_direction                               (time, latitude, longitude) float32 2GB ...\n",
+       "    latitude_longitude                                (time) int32 496B ...\n",
+       "    latitude_bnds                                     (time, latitude, bnds) float32 2MB ...\n",
+       "    rainfall_rate                                     (time, latitude, longitude) float32 2GB ...\n",
+       "    surface_temperature                               (time, latitude, longitude) float32 2GB ...\n",
+       "    fog_area_fraction                                 (time, latitude, longitude) float32 2GB ...\n",
+       "Attributes:\n",
+       "    history:                      2026-05-24T09:21:22Z: StaGE Decoupler\n",
+       "    institution:                  Met Office\n",
+       "    mosg__forecast_run_duration:  PT69H\n",
+       "    mosg__grid_domain:            global\n",
+       "    mosg__grid_type:              standard\n",
+       "    mosg__grid_version:           1.7.0\n",
+       "    mosg__model_configuration:    gl_det\n",
+       "    source:                       Met Office Unified Model\n",
+       "    title:                        Global Model Forecast on Global 10 km Stand...\n",
+       "    um_version:                   13.8\n",
+       "    Conventions:                  CF-1.7, UKMO-1.0
" + ], + "text/plain": [ + " Size: 51GB\n", + "Dimensions: (time: 124,\n", + " latitude: 1920,\n", + " longitude: 2560, bnds: 2)\n", + "Coordinates:\n", + " * time (time) datetime64[ns] 992B ...\n", + " * latitude (latitude) float32 8kB ...\n", + " * longitude (longitude) float32 10kB ...\n", + " forecast_period int32 4B ...\n", + " height float32 4B ...\n", + " forecast_reference_time datetime64[ns] 8B ...\n", + "Dimensions without coordinates: bnds\n", + "Data variables: (12/24)\n", + " air_pressure_at_sea_level (time, latitude, longitude) float32 2GB ...\n", + " lwe_snowfall_rate (time, latitude, longitude) float32 2GB ...\n", + " relative_humidity (time, latitude, longitude) float32 2GB ...\n", + " dew_point_temperature (time, latitude, longitude) float32 2GB ...\n", + " convective_rainfall_rate (time, latitude, longitude) float32 2GB ...\n", + " longitude_bnds (time, longitude, bnds) float32 3MB ...\n", + " ... ...\n", + " wind_from_direction (time, latitude, longitude) float32 2GB ...\n", + " latitude_longitude (time) int32 496B ...\n", + " latitude_bnds (time, latitude, bnds) float32 2MB ...\n", + " rainfall_rate (time, latitude, longitude) float32 2GB ...\n", + " surface_temperature (time, latitude, longitude) float32 2GB ...\n", + " fog_area_fraction (time, latitude, longitude) float32 2GB ...\n", + "Attributes:\n", + " history: 2026-05-24T09:21:22Z: StaGE Decoupler\n", + " institution: Met Office\n", + " mosg__forecast_run_duration: PT69H\n", + " mosg__grid_domain: global\n", + " mosg__grid_type: standard\n", + " mosg__grid_version: 1.7.0\n", + " mosg__model_configuration: gl_det\n", + " source: Met Office Unified Model\n", + " title: Global Model Forecast on Global 10 km Stand...\n", + " um_version: 13.8\n", + " Conventions: CF-1.7, UKMO-1.0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "repo = ic.Repository.open(storage, config, credentials)\n", + "session = repo.readonly_session(\"main\")\n", + "\n", + "ds = xr.open_zarr(session.store, zarr_format=3, consolidated=False, chunks=None)\n", + "ds" + ] + }, + { + "cell_type": "markdown", + "id": "9392b3e1-2020-497b-8231-a8adbf815105", + "metadata": {}, + "source": [ + "Then you can perform spatial or temporal queries using the xarray API." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "f449ca97-6b78-433d-9e6e-c6f88f5b414d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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uOaaazB48GAwxrBx40b8+uuv+OWXX9w8etvk5eUhJycHZ8+eBQAcOXIExcXFSE9PNwlszpw5gwMHDuB///ufG0drv61bt+LWW2/F7Nmz0bNnT/5zSiwWY8iQIfxxx44dQ11dHQoLCyGXy/njhg0bZrahnSeaP38+vv32W3z88ccoKytDWVkZACAhIYHP9Nx8880YOHAgBg8ejLq6OqxYsQIajQZPPfWUm0dvvYqKCowdOxZ+fn547LHHcODAAf66zMxMvvblkUceQUZGBvr374/9+/djyZIleP/999GhQwe3jFsoFOLGG2/kF+vU1dXh9ddfd3kzRNBu6bYbP348nnzySVx//fVmrx8zZgwWL17MX79p0yZ8+umnqKmpwTXXXIPhw4fjvffew7Zt20x+T6fTISYmBnfddRdWrFjhksdiry1btmD16tWorKzEgAEDsHjxYpOC7ezsbHzwwQc4ffo0oqOjMWHCBNx9991e8wHKUalUeP/99/H333/Dz88PN998M+655x6TYy5duoRly5YhOzsbffr0wYIFCzyvu2grCgoKzJ79DRw4EO+88w5gOCP+5JNPsHPnTmi1WnTt2hUPPvig1xUtr127FqtWrWp2+dNPP42pU6fyP3/66af45Zdf8Ntvv3nd6xaGIuV169Y1uzwkJMQky3z33XfjypUrzY7bsmWLV9R8AMAtt9yCoqKiZpdPnz4dTz75JGD4kv3444+xa9cuiMVi9OvXz6RA1hucPXu2xUzd+++/j379+gGGjunLli3D/v37kZiYiHnz5mHEiBEuHWtCQgIWLlzIB5QymQxLlizB0aNHkZycjEceeQQvvPACFi5ciPHjxwMARowYgRUrVmDAgAH87dxxxx24+eabcdNNNzlkXBTweIgzZ84gMzMTJ0+e9Lo0KyGEEALDlFpYWBi++OILzJ49293DMUFTWm5WW1uLo0eP4pVXXsHkyZMp2CGEEOKVtm/fjnXr1iEgIADXXXedu4fTjPflatuZnJwcPP/880hJScGnn37q7uEQQgghdnnttdfAGMO///7LN0H0JDSlRQghhJB2jzI8hBBCCGn3KOAhhBBCSLtHAQ8hhBBC2j0KeAghhJB2pLCwEBUVFRaPqaysRFZWlsUtHqy5HRgaelZVVVk9vtOnT6Ompsbq4x2FAh5CiNdSqVT47rvvUF1d7e6hEOJW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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ds[\"air_temperature\"].isel(longitude=100, latitude=100).plot()" + ] + }, + { + "cell_type": "markdown", + "id": "legacy-vs-icechunk-comparisons", + "metadata": {}, + "source": [ + "### Legacy format versus Icechunk query comparisons\n", + "\n", + "With the virtual array written to Icechunk we can compare a few common query patterns against the legacy workflow. For the legacy path we re-run a STAC search for the same `PT0000H00M` global near-surface records, but now the temporal constraint is pushed down into the STAC query so the legacy path only opens the raw NetCDF assets needed for each comparison.\n", + "\n", + "The examples below time four representative access patterns for `air_temperature`: a time slice, a single point, a spatial slice, and a full-array load. To keep the comparison aligned across both approaches, each query uses `sel` with actual timestamp values rather than `isel` along the time dimension where appropriate." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "legacy-vs-icechunk-helpers", + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class Timing:\n", + " label: str\n", + " seconds: float | None = None\n", + "\n", + "\n", + "LEGACY_ASSET_KEY = \"temperature_at_screen_level\"\n", + "DATA_VARIABLE = \"air_temperature\"\n", + "\n", + "\n", + "time_slice_start = pd.Timestamp(ds.time.isel(time=10).values)\n", + "time_slice_end = pd.Timestamp(ds.time.isel(time=45).values)\n", + "single_time = pd.Timestamp(ds.time.isel(time=60).values)\n", + "full_time_start = pd.Timestamp(ds.time.min().values)\n", + "full_time_end = pd.Timestamp(ds.time.max().values)\n", + "\n", + "\n", + "@contextmanager\n", + "def timer(label=\"Task\"):\n", + " \"\"\"Time a block and expose the elapsed seconds after it exits.\"\"\"\n", + " timing = Timing(label=label)\n", + " t0 = time.perf_counter()\n", + " try:\n", + " yield timing\n", + " finally:\n", + " timing.seconds = time.perf_counter() - t0\n", + "\n", + "\n", + "def to_stac_datetime(value):\n", + " \"\"\"Convert a timestamp-like value to an RFC3339 UTC string for STAC.\"\"\"\n", + " return pd.Timestamp(value).tz_localize(\"UTC\").isoformat().replace(\"+00:00\", \"Z\")\n", + "\n", + "\n", + "@contextmanager\n", + "def open_icechunk():\n", + " \"\"\"Open the local Icechunk repository as an xarray dataset.\"\"\"\n", + " setup_timings = {}\n", + "\n", + " with timer(\"icechunk: Repository.open\") as t:\n", + " repo = ic.Repository.open(storage, config, credentials)\n", + "\n", + " setup_timings[\"repository_open_seconds\"] = t.seconds\n", + " with timer(\"icechunk: readonly_session\") as t:\n", + " session = repo.readonly_session(\"main\")\n", + "\n", + " setup_timings[\"readonly_session_seconds\"] = t.seconds\n", + " with timer(\"icechunk: xr.open_zarr\") as t:\n", + " dataset = xr.open_zarr(\n", + " session.store, zarr_format=3, consolidated=False, chunks=None\n", + " )\n", + "\n", + " setup_timings[\"open_dataset_seconds\"] = t.seconds\n", + " setup_timings[\"setup_seconds\"] = sum(setup_timings.values())\n", + " dataset.attrs[\"benchmark_setup_timings\"] = setup_timings\n", + "\n", + " try:\n", + " yield dataset\n", + " finally:\n", + " dataset.close()\n", + " if hasattr(session, \"close\"):\n", + " session.close()\n", + "\n", + "\n", + "@contextmanager\n", + "def open_legacy(datetime_query):\n", + " \"\"\"Open the legacy NetCDF assets matched by a targeted STAC query.\"\"\"\n", + " setup_timings = {}\n", + " with timer(f\"legacy: STAC item retrieval ({datetime_query})\") as t:\n", + " legacy_search = catalog.search(\n", + " collections=\"met-office-global-deterministic-near-surface\",\n", + " datetime=datetime_query,\n", + " filter_lang=\"cql2-json\",\n", + " filter={\n", + " \"op\": \"=\",\n", + " \"args\": [\n", + " {\"property\": \"forecast:horizon\"},\n", + " \"PT0000H00M\",\n", + " ],\n", + " },\n", + " sortby=\"datetime\",\n", + " limit=100,\n", + " )\n", + " legacy_items = legacy_search.item_collection()\n", + "\n", + " setup_timings[\"stac_item_retrieval_seconds\"] = t.seconds\n", + "\n", + " with timer(\"legacy: collect asset paths\") as t:\n", + " asset_paths = [\n", + " urlparse(item.assets[LEGACY_ASSET_KEY].href).path.lstrip(\"/\")\n", + " for item in legacy_items\n", + " if LEGACY_ASSET_KEY in item.assets\n", + " ]\n", + "\n", + " setup_timings[\"collect_asset_paths_seconds\"] = t.seconds\n", + "\n", + " with timer(\"legacy: xr.open_mfdataset\") as t:\n", + " dataset = xr.open_mfdataset(\n", + " [BlockStoreReader(base_store, path) for path in asset_paths],\n", + " engine=\"h5netcdf\",\n", + " chunks=None,\n", + " decode_times=True,\n", + " decode_timedelta=True,\n", + " concat_dim=\"time\",\n", + " combine=\"nested\",\n", + " parallel=False,\n", + " coords=\"minimal\",\n", + " compat=\"override\",\n", + " )\n", + "\n", + " setup_timings[\"open_dataset_seconds\"] = t.seconds\n", + " setup_timings[\"setup_seconds\"] = sum(setup_timings.values())\n", + " dataset.attrs[\"benchmark_setup_timings\"] = setup_timings\n", + "\n", + " try:\n", + " yield dataset\n", + " finally:\n", + " dataset.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c59f35b-facd-4469-8080-66f9d8d2dc93", + "metadata": {}, + "outputs": [], + "source": [ + "results = []\n", + "\n", + "with timer(\"icechunk time slice\") as total_t:\n", + " with open_icechunk() as icechunk_ds:\n", + " setup_seconds = icechunk_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"icechunk: load time slice\") as load_t:\n", + " icechunk_ds[DATA_VARIABLE].sel(\n", + " time=slice(time_slice_start, time_slice_end)\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"time slice\",\n", + " \"backend\": \"icechunk\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"legacy time slice\") as total_t:\n", + " with open_legacy(\n", + " f\"{to_stac_datetime(time_slice_start)}/{to_stac_datetime(time_slice_end)}\"\n", + " ) as legacy_ds:\n", + " setup_seconds = legacy_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"legacy: load time slice\") as load_t:\n", + " legacy_ds[DATA_VARIABLE].sel(\n", + " time=slice(time_slice_start, time_slice_end)\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"time slice\",\n", + " \"backend\": \"legacy-stac-plus-netcdf\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"icechunk random point\") as total_t:\n", + " with open_icechunk() as icechunk_ds:\n", + " setup_seconds = icechunk_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"icechunk: load random point\") as load_t:\n", + " icechunk_ds[DATA_VARIABLE].sel(\n", + " time=slice(time_slice_start, time_slice_end)\n", + " ).isel(\n", + " latitude=187,\n", + " longitude=241,\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"random point\",\n", + " \"backend\": \"icechunk\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"legacy random point\") as total_t:\n", + " with open_legacy(to_stac_datetime(single_time)) as legacy_ds:\n", + " setup_seconds = legacy_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"legacy: load random point\") as load_t:\n", + " legacy_ds[DATA_VARIABLE].sel(\n", + " time=slice(time_slice_start, time_slice_end)\n", + " ).isel(\n", + " latitude=187,\n", + " longitude=241,\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"random point\",\n", + " \"backend\": \"legacy-stac-plus-netcdf\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"icechunk spatial slice\") as total_t:\n", + " with open_icechunk() as icechunk_ds:\n", + " setup_seconds = icechunk_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"icechunk: load spatial slice\") as load_t:\n", + " icechunk_ds[DATA_VARIABLE].sel(time=single_time).isel(\n", + " latitude=slice(150, 406),\n", + " longitude=slice(200, 456),\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"spatial slice\",\n", + " \"backend\": \"icechunk\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"legacy spatial slice\") as total_t:\n", + " with open_legacy(to_stac_datetime(single_time)) as legacy_ds:\n", + " setup_seconds = legacy_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"legacy: load spatial slice\") as load_t:\n", + " legacy_ds[DATA_VARIABLE].sel(time=single_time).isel(\n", + " latitude=slice(150, 406),\n", + " longitude=slice(200, 456),\n", + " ).load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"spatial slice\",\n", + " \"backend\": \"legacy-stac-plus-netcdf\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"icechunk full array\") as total_t:\n", + " with open_icechunk() as icechunk_ds:\n", + " setup_seconds = icechunk_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"icechunk: load full array\") as load_t:\n", + " icechunk_ds[DATA_VARIABLE].load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"full array\",\n", + " \"backend\": \"icechunk\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")\n", + "\n", + "with timer(\"legacy full array\") as total_t:\n", + " with open_legacy(\n", + " f\"{to_stac_datetime(full_time_start)}/{to_stac_datetime(full_time_end)}\"\n", + " ) as legacy_ds:\n", + " setup_seconds = legacy_ds.attrs[\"benchmark_setup_timings\"][\"setup_seconds\"]\n", + " with timer(\"legacy: load full array\") as load_t:\n", + " legacy_ds[DATA_VARIABLE].load()\n", + "\n", + "results.append(\n", + " {\n", + " \"query\": \"full array\",\n", + " \"backend\": \"legacy-stac-plus-netcdf\",\n", + " \"setup_seconds\": setup_seconds,\n", + " \"load_seconds\": load_t.seconds,\n", + " \"total_seconds\": total_t.seconds,\n", + " }\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "legacy-vs-icechunk-benchmark", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
setup_secondsload_secondstotal_seconds
querybackend
full arrayicechunk1.42105.97107.39
legacy-stac-plus-netcdf76.19189.01265.24
random pointicechunk1.891.123.01
legacy-stac-plus-netcdf0.990.181.17
spatial sliceicechunk1.370.852.23
legacy-stac-plus-netcdf1.120.201.33
time sliceicechunk1.6732.6734.35
legacy-stac-plus-netcdf21.3350.8972.34
\n", + "
" + ], + "text/plain": [ + " setup_seconds load_seconds \\\n", + "query backend \n", + "full array icechunk 1.42 105.97 \n", + " legacy-stac-plus-netcdf 76.19 189.01 \n", + "random point icechunk 1.89 1.12 \n", + " legacy-stac-plus-netcdf 0.99 0.18 \n", + "spatial slice icechunk 1.37 0.85 \n", + " legacy-stac-plus-netcdf 1.12 0.20 \n", + "time slice icechunk 1.67 32.67 \n", + " legacy-stac-plus-netcdf 21.33 50.89 \n", + "\n", + " total_seconds \n", + "query backend \n", + "full array icechunk 107.39 \n", + " legacy-stac-plus-netcdf 265.24 \n", + "random point icechunk 3.01 \n", + " legacy-stac-plus-netcdf 1.17 \n", + "spatial slice icechunk 2.23 \n", + " legacy-stac-plus-netcdf 1.33 \n", + "time slice icechunk 34.35 \n", + " legacy-stac-plus-netcdf 72.34 " + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_df = pd.DataFrame(results).set_index([\"query\", \"backend\"]).sort_index()\n", + "comparison_df" + ] + }, + { + "cell_type": "markdown", + "id": "1cebfa86-de25-4770-9b26-8a1e667e1f81", + "metadata": {}, + "source": [ + "This analysis shows that highly targeted queries for small spatial and/or temporal windows can be performed very quickly with the legacy approach, but as the number of files required by a given query increases Icechunk will be much more performant! The Icechunk approach has a fixed overhead cost of the 'setup' step (opening the zarr array) that is higher than the setup cost of the legacy approach for targeted queries but for queries that involve more time steps the legacy setup cost is much higher." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04fa6e3d-7abd-493d-b8e9-fccd280a4cde", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}