From 318ba2c450b56ce72b7af193ef4b5a88e61a5f5c Mon Sep 17 00:00:00 2001 From: Charles Turner Date: Tue, 26 Nov 2024 19:14:22 +1100 Subject: [PATCH 1/3] Add simplified catalog building example --- building_a_catalog_simplified.ipynb | 8011 +++++++++++++++++++++++++++ 1 file changed, 8011 insertions(+) create mode 100644 building_a_catalog_simplified.ipynb diff --git a/building_a_catalog_simplified.ipynb b/building_a_catalog_simplified.ipynb new file mode 100644 index 0000000..134332a --- /dev/null +++ b/building_a_catalog_simplified.ipynb @@ -0,0 +1,8011 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c8329b54-462c-4a3a-a963-40422bef8902", + "metadata": {}, + "source": [ + "## Getting to grips with the ACCESS-NRI Intake Catalog\n", + "\n", + "There are three potential use cases for the ACCESS-NRI Intake Catalog:\n", + "1. You want to access some data someone else has *generated and catalogued*.\n", + "2. You want to *catalogue* some data you've generated.\n", + "3. You want to *access* some data you've catalogued.\n", + "\n", + "\n", + "Cases 2 & 3 can seem daunting - how do you build or access a custom catalog? This notebook should get you started, and will show you how to get to an ESM Datastore.\n", + "\n", + "___\n", + "#### This notebook contains a basic example of how catalog an experiment & access the data in it using a simple wrapper function, and should get you up to speed with cataloging your experiments.\n", + "___" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "dc8f78cb-c560-4a03-a699-6cd7dc383196", + "metadata": {}, + "outputs": [], + "source": [ + "### Imports, make sure we are in our home directory (don't change this until you're sure you know why you want to)\n", + "!cd \n", + "from pathlib import Path\n", + "import intake \n", + "from access_nri_intake.source.builders import AccessOm2Builder, AccessOm3Builder, AccessEsm15Builder, AccessCm2Builder\n" + ] + }, + { + "cell_type": "markdown", + "id": "bdd4b7ef-4206-4d13-8c4a-fe7cccfaaf5c", + "metadata": {}, + "source": [ + "## Case 1: Accessing an experiment in the standard catalog" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "28697aa8-4635-4b43-aad6-ac198751c107", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

01deg_jra55v13_ryf9091 catalog with 34 dataset(s) from 11947 asset(s):

\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", + "
unique
path11947
realm2
variable178
frequency5
start_date3361
end_date3360
variable_long_name181
variable_standard_name36
variable_cell_methods3
variable_units50
filename3469
file_id33
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# We've picked a demo experiment name here. You can find all available experiments in the standard catalog by calling `intake.cat.access_nri`.\n", + "experiment_name='01deg_jra55v13_ryf9091'\n", + "\n", + "cat = intake.cat.access_nri\n", + "esm_ds = cat[experiment_name]\n", + "# Note: We call this esm_ds as this object is an `esm_datastore`: see https://intake-esm.readthedocs.io/en/v2021.8.17/user-guide/overview.html#loading-a-catalog for more details\n", + "esm_ds" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4fbe5438-dd9f-4697-937f-668b2647ae99", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 3GB\n",
+       "Dimensions:       (time: 1, d2: 2, nj: 2700, ni: 3600, nc: 5)\n",
+       "Coordinates:\n",
+       "  * time          (time) object 8B 1900-02-01 00:00:00\n",
+       "    TLON          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    TLAT          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ULON          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ULAT          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    NCAT          (nc) float32 20B dask.array<chunksize=(5,), meta=np.ndarray>\n",
+       "Dimensions without coordinates: d2, nj, ni, nc\n",
+       "Data variables: (12/49)\n",
+       "    time_bounds   (time, d2) object 16B dask.array<chunksize=(1, 2), meta=np.ndarray>\n",
+       "    tmask         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    blkmask       (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    tarea         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    uarea         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    dxt           (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ...            ...\n",
+       "    fmeltt_ai_m   (time, nj, ni) float32 39MB dask.array<chunksize=(1, 675, 900), meta=np.ndarray>\n",
+       "    opening_m     (time, nj, ni) float32 39MB dask.array<chunksize=(1, 675, 900), meta=np.ndarray>\n",
+       "    aicen_m       (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    vicen_m       (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    fmelttn_ai_m  (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    flatn_ai_m    (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "Attributes: (12/24)\n",
+       "    title:                                    sea ice model output for CICE\n",
+       "    contents:                                 Diagnostic and Prognostic Varia...\n",
+       "    source:                                   Los Alamos Sea Ice Model (CICE)...\n",
+       "    comment:                                  This Year Has 365 days\n",
+       "    comment2:                                 File written on model date 1900...\n",
+       "    comment3:                                 seconds elapsed into model date...\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_cell_methods:   ,,,,,,,,,,,,,,,,,,time: mean,ti...\n",
+       "    intake_esm_attrs:variable_units:          days since 1900-01-01 00:00:00,...\n",
+       "    intake_esm_attrs:filename:                iceh.1900-01.nc\n",
+       "    intake_esm_attrs:file_id:                 iceh_XXXX_XX\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   iceh_XXXX_XX.1mon
" + ], + "text/plain": [ + " Size: 3GB\n", + "Dimensions: (time: 1, d2: 2, nj: 2700, ni: 3600, nc: 5)\n", + "Coordinates:\n", + " * time (time) object 8B 1900-02-01 00:00:00\n", + " TLON (nj, ni) float32 39MB dask.array\n", + " TLAT (nj, ni) float32 39MB dask.array\n", + " ULON (nj, ni) float32 39MB dask.array\n", + " ULAT (nj, ni) float32 39MB dask.array\n", + " NCAT (nc) float32 20B dask.array\n", + "Dimensions without coordinates: d2, nj, ni, nc\n", + "Data variables: (12/49)\n", + " time_bounds (time, d2) object 16B dask.array\n", + " tmask (nj, ni) float32 39MB dask.array\n", + " blkmask (nj, ni) float32 39MB dask.array\n", + " tarea (nj, ni) float32 39MB dask.array\n", + " uarea (nj, ni) float32 39MB dask.array\n", + " dxt (nj, ni) float32 39MB dask.array\n", + " ... ...\n", + " fmeltt_ai_m (time, nj, ni) float32 39MB dask.array\n", + " opening_m (time, nj, ni) float32 39MB dask.array\n", + " aicen_m (time, nc, nj, ni) float32 194MB dask.array\n", + " vicen_m (time, nc, nj, ni) float32 194MB dask.array\n", + " fmelttn_ai_m (time, nc, nj, ni) float32 194MB dask.array\n", + " flatn_ai_m (time, nc, nj, ni) float32 194MB dask.array\n", + "Attributes: (12/24)\n", + " title: sea ice model output for CICE\n", + " contents: Diagnostic and Prognostic Varia...\n", + " source: Los Alamos Sea Ice Model (CICE)...\n", + " comment: This Year Has 365 days\n", + " comment2: File written on model date 1900...\n", + " comment3: seconds elapsed into model date...\n", + " ... ...\n", + " intake_esm_attrs:variable_cell_methods: ,,,,,,,,,,,,,,,,,,time: mean,ti...\n", + " intake_esm_attrs:variable_units: days since 1900-01-01 00:00:00,...\n", + " intake_esm_attrs:filename: iceh.1900-01.nc\n", + " intake_esm_attrs:file_id: iceh_XXXX_XX\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: iceh_XXXX_XX.1mon" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now, if we wanted to subset and load some data, we could with, for example...\n", + "first_result = esm_ds.df.head(1).path\n", + "esm_ds.search(path=first_result).to_dask()" + ] + }, + { + "cell_type": "markdown", + "id": "3b388be4-2535-4e60-8397-159c80fe5811", + "metadata": {}, + "source": [ + "## Case 2: Generating a custom catalog for your experiment\n", + "\n", + "We imported the builders above: pick from the one of these that matches the data you want to catalog. If you think you need a new builder, open an issue at https://github.com/ACCESS-NRI/access-nri-intake-catalog\n", + "\n", + "Pick a builder from the following to set as `\"builder\"` below:\n", + "```python\n", + "from access_nri_intake.source.builders import AccessOm2Builder, AccessOm3Builder, AccessEsm15Builder, AccessCm2Builder\n", + "```\n", + "eg:\n", + "```python\n", + "catalog_config = {\n", + " ...\n", + " \"builder\" : AccessESM15Builder, \n", + " ...\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1a90873e-16e5-49e2-b1d4-edb05f510db8", + "metadata": {}, + "outputs": [], + "source": [ + "# Set Config in this cell\n", + "catalog_config = {\n", + " \"experiment_output_path\" : \"/g/data/ik11/outputs/access-om2/1deg_iamip2_CMCC-ESM2ssp126\", # Point this to your model output\n", + " \"builder\" : AccessOm2Builder, # This must be one of the builders imported above. If you need a new builder, get in touch!\n", + " \"catalog_directory\" : \"./catalog_demo\",\n", + " \"catalog_name\" : \"demo_datastore\",\n", + " \"description\" : \"An example datastore for ACCESS-OM2 1deg_iamip2_CMCC-ESM2ssp126\",\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b958a0de-940d-4289-aa9e-5c4ba317b3ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No catalog found at specified output location: catalog_demo/demo_datastore.json. Building catalog...\n", + "This could take a few minutes...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n", + "/home/189/ct1163/access-nri-intake-catalog/src/access_nri_intake/source/utils.py:111: UserWarning: Time coordinate does not include bounds information. Guessing start and end times.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Successfully wrote ESM catalog json file to: file:///home/189/ct1163/catalog_demo/demo_datastore.json\n", + "Catalog built successfully!\n" + ] + } + ], + "source": [ + "# This cell defines and runs a function which will build and save our catalog.\n", + "def create_catalog(catalog_config):\n", + " \"\"\"\n", + " Takes the `catalog_config` dictionary in the cell above and builds a catalog with the specified options\n", + " \"\"\"\n", + " \n", + " catalog_fname = Path(catalog_config[\"catalog_directory\"]) / f\"{catalog_config['catalog_name']}.json\"\n", + "\n", + " catalog_written = catalog_fname.exists()\n", + " \n", + " parent_dir = catalog_fname.parent\n", + " if not parent_dir.exists():\n", + " parent_dir.mkdir(parents=True)\n", + "\n", + " if not catalog_written:\n", + " print(f\"No catalog found at specified output location: {catalog_fname}. Building catalog...\")\n", + " print(\"This could take a few minutes...\")\n", + " \n", + " builder = AccessOm2Builder(\n", + " path=catalog_config[\"experiment_output_path\"]\n", + " ).build()\n", + " \n", + " builder.save(\n", + " name=catalog_config[\"catalog_name\"],\n", + " directory=catalog_config[\"catalog_directory\"],\n", + " description=catalog_config[\"description\"],\n", + " )\n", + " print(\"Catalog built successfully!\")\n", + " else:\n", + " print(f\"Catalog alerady found at specified output location: {catalog_fname}. Did you mean to open it?\")\n", + " \n", + "\n", + "# Now run it!\n", + "create_catalog(catalog_config)" + ] + }, + { + "cell_type": "markdown", + "id": "18cf2c20-f4a2-4189-9ba6-c6910c3b6c6e", + "metadata": {}, + "source": [ + "## Case 3: Using a custom catalog\n", + "\n", + "Once we've built a custom catalog, we can open it using the convenience function defined below - it uses the same configuration dictionary `catalog_config`, and so *nothing needs to be changed - just run the cell*. This will give us the same type of object that we got in __Case 1__ above, so from this point onwards, we can use it as if it were the standard catalog.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "122745d5-d4e0-4f48-ad93-857093b7eef7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Catalog found at specified output location: catalog_demo/demo_datastore.json. Opening catalog...\n" + ] + } + ], + "source": [ + "# This cell defines and runs a function which will open our catalog.\n", + "def open_catalog(catalog_config):\n", + " \"\"\"\n", + " Looks for a catalog in the specified output location & attempts to open it\n", + " \"\"\"\n", + " \n", + " catalog_fname = Path(catalog_config[\"catalog_directory\"]) / f\"{catalog_config['catalog_name']}.json\"\n", + "\n", + " if not catalog_fname.exists():\n", + " print(f\"No catalog found at specified output location: {catalog_fname}. Did you mean to build a catalog?\")\n", + " else:\n", + " print(f\"Catalog found at specified output location: {catalog_fname}. Opening catalog...\")\n", + " \n", + " cat = intake.open_esm_datastore(\n", + " catalog_fname,\n", + " columns_with_iterables=[\"variable\"] # We need to tell the datastore that the variable_column contains iterables or it won't work correctly\n", + " )\n", + "\n", + " return cat\n", + "\n", + "# Now run it!\n", + "custom_esm_ds = open_catalog(catalog_config)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f6c1613b-ee19-4da2-bd65-643c7a0185c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 2GB\n",
+       "Dimensions:      (time: 365, d2: 2, nj: 300, ni: 360, nc: 5)\n",
+       "Coordinates:\n",
+       "  * time         (time) datetime64[ns] 3kB 2015-01-02 2015-01-03 ... 2016-01-01\n",
+       "    TLON         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    TLAT         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ULON         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ULAT         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "Dimensions without coordinates: d2, nj, ni, nc\n",
+       "Data variables: (12/24)\n",
+       "    time_bounds  (time, d2) datetime64[ns] 6kB dask.array<chunksize=(1, 2), meta=np.ndarray>\n",
+       "    NCAT         (nc) float32 20B dask.array<chunksize=(5,), meta=np.ndarray>\n",
+       "    tmask        (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    blkmask      (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    tarea        (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    dxt          (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ...           ...\n",
+       "    algal_N      (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    skl_Nit      (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    ml_Nit       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    fNO_ai       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    fN_ai        (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    PP_net       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "Attributes: (12/27)\n",
+       "    title:                                    sea ice model output for CICE\n",
+       "    contents:                                 Diagnostic and Prognostic Varia...\n",
+       "    source:                                   Los Alamos Sea Ice Model (CICE)...\n",
+       "    time_period_freq:                         day_1\n",
+       "    comment:                                  This year has 365 days\n",
+       "    comment2:                                 File written on model date 2015...\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_standard_name:  ['', '', '', '', '', '', '', ''...\n",
+       "    intake_esm_attrs:variable_cell_methods:   ['', '', '', '', '', '', '', ''...\n",
+       "    intake_esm_attrs:variable_units:          ['days since 2015-01-01 00:00:0...\n",
+       "    intake_esm_attrs:realm:                   seaIce\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   iceh_XXX_daily.1day
" + ], + "text/plain": [ + " Size: 2GB\n", + "Dimensions: (time: 365, d2: 2, nj: 300, ni: 360, nc: 5)\n", + "Coordinates:\n", + " * time (time) datetime64[ns] 3kB 2015-01-02 2015-01-03 ... 2016-01-01\n", + " TLON (nj, ni) float32 432kB dask.array\n", + " TLAT (nj, ni) float32 432kB dask.array\n", + " ULON (nj, ni) float32 432kB dask.array\n", + " ULAT (nj, ni) float32 432kB dask.array\n", + "Dimensions without coordinates: d2, nj, ni, nc\n", + "Data variables: (12/24)\n", + " time_bounds (time, d2) datetime64[ns] 6kB dask.array\n", + " NCAT (nc) float32 20B dask.array\n", + " tmask (nj, ni) float32 432kB dask.array\n", + " blkmask (nj, ni) float32 432kB dask.array\n", + " tarea (nj, ni) float32 432kB dask.array\n", + " dxt (nj, ni) float32 432kB dask.array\n", + " ... ...\n", + " algal_N (time, nj, ni) float32 158MB dask.array\n", + " skl_Nit (time, nj, ni) float32 158MB dask.array\n", + " ml_Nit (time, nj, ni) float32 158MB dask.array\n", + " fNO_ai (time, nj, ni) float32 158MB dask.array\n", + " fN_ai (time, nj, ni) float32 158MB dask.array\n", + " PP_net (time, nj, ni) float32 158MB dask.array\n", + "Attributes: (12/27)\n", + " title: sea ice model output for CICE\n", + " contents: Diagnostic and Prognostic Varia...\n", + " source: Los Alamos Sea Ice Model (CICE)...\n", + " time_period_freq: day_1\n", + " comment: This year has 365 days\n", + " comment2: File written on model date 2015...\n", + " ... ...\n", + " intake_esm_attrs:variable_standard_name: ['', '', '', '', '', '', '', ''...\n", + " intake_esm_attrs:variable_cell_methods: ['', '', '', '', '', '', '', ''...\n", + " intake_esm_attrs:variable_units: ['days since 2015-01-01 00:00:0...\n", + " intake_esm_attrs:realm: seaIce\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: iceh_XXX_daily.1day" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now, if we wanted to subset and load some data, we could with, for example...\n", + "first_result = custom_esm_ds.df.head(1).path\n", + "custom_esm_ds.search(path=first_result).to_dask()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:analysis3-unstable]", + "language": "python", + "name": "conda-env-analysis3-unstable-py" + }, + "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.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From b89a1bc8acb94788ae4df73ed93f74e6be8663fd Mon Sep 17 00:00:00 2001 From: Charles Turner Date: Tue, 3 Dec 2024 12:53:31 +0800 Subject: [PATCH 2/3] Added Recipe Template --- catalog_user_recipe.ipynb | 10598 ++++++++++++++++++++++++++++++++++++ 1 file changed, 10598 insertions(+) create mode 100644 catalog_user_recipe.ipynb diff --git a/catalog_user_recipe.ipynb b/catalog_user_recipe.ipynb new file mode 100644 index 0000000..1949564 --- /dev/null +++ b/catalog_user_recipe.ipynb @@ -0,0 +1,10598 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c8329b54-462c-4a3a-a963-40422bef8902", + "metadata": {}, + "source": [ + "## Using an Intake Catalog to analyse data\n", + "\n", + "There are two ways you might want to access & use an Intake Catalog:\n", + "1. You want to open a *datastore* for an experiment - and you know where it is.\n", + "2. You want to *search for and access a catalog* - from the ACCESS-NRI Intake Catalog.\n", + "\n", + "#### These two workflows will both lead you to the same data format: an xarray dataset.\n", + "\n", + "This tutorial demonstrates how to access the data you're after in either of these scenarios.\n", + "___\n", + "*This notebook was originally run on a large ARE instance. \n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "dc8f78cb-c560-4a03-a699-6cd7dc383196", + "metadata": {}, + "outputs": [], + "source": [ + "# For now, we only need to import intake.\n", + "import intake" + ] + }, + { + "cell_type": "markdown", + "id": "bdd4b7ef-4206-4d13-8c4a-fe7cccfaaf5c", + "metadata": {}, + "source": [ + "## Case 1: Opening a datastore when you know where the experiment data is." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "28697aa8-4635-4b43-aad6-ac198751c107", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

demo_datastore catalog with 48 dataset(s) from 4128 asset(s):

\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", + "
unique
filename2853
file_id48
path4128
filename_timestamp430
frequency4
start_date174
end_date173
variable116
variable_long_name112
variable_standard_name8
variable_cell_methods6
variable_units104
realm2
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# We've picked a demo experiment name here. You can find all available experiments in the standard catalog by calling `intake.cat.access_nri`.\n", + "demo_datastore_path = \"/home/189/ct1163/catalog_demo/demo_datastore.json\"\n", + "\n", + "esm_ds = intake.open_esm_datastore(demo_datastore_path,\n", + " columns_with_iterables=[\n", + " 'variable', # We need to tell the datastore that the variable_column contains iterables or it won't work correctly. \n", + " 'variable_long_name', # In fact, all the variable_* columns contain iterables - but we're just going to search for names\n", + " 'variable_standard_name',\n", + " ]\n", + ")\n", + "\n", + "# Note: We call this esm_ds as this object is an `esm_datastore`: see https://intake-esm.readthedocs.io/en/v2021.8.17/user-guide/overview.html#loading-a-catalog for more details\n", + "esm_ds" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4fbe5438-dd9f-4697-937f-668b2647ae99", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 2GB\n",
+       "Dimensions:      (time: 365, d2: 2, nj: 300, ni: 360, nc: 5)\n",
+       "Coordinates:\n",
+       "  * time         (time) datetime64[ns] 3kB 2015-01-02 2015-01-03 ... 2016-01-01\n",
+       "    TLON         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    TLAT         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ULON         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ULAT         (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "Dimensions without coordinates: d2, nj, ni, nc\n",
+       "Data variables: (12/24)\n",
+       "    time_bounds  (time, d2) datetime64[ns] 6kB dask.array<chunksize=(1, 2), meta=np.ndarray>\n",
+       "    NCAT         (nc) float32 20B dask.array<chunksize=(5,), meta=np.ndarray>\n",
+       "    tmask        (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    blkmask      (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    tarea        (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    dxt          (nj, ni) float32 432kB dask.array<chunksize=(150, 180), meta=np.ndarray>\n",
+       "    ...           ...\n",
+       "    algal_N      (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    skl_Nit      (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    ml_Nit       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    fNO_ai       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    fN_ai        (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "    PP_net       (time, nj, ni) float32 158MB dask.array<chunksize=(1, 150, 180), meta=np.ndarray>\n",
+       "Attributes: (12/27)\n",
+       "    title:                                    sea ice model output for CICE\n",
+       "    contents:                                 Diagnostic and Prognostic Varia...\n",
+       "    source:                                   Los Alamos Sea Ice Model (CICE)...\n",
+       "    time_period_freq:                         day_1\n",
+       "    comment:                                  This year has 365 days\n",
+       "    comment2:                                 File written on model date 2015...\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_standard_name:  ,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n",
+       "    intake_esm_attrs:variable_cell_methods:   ['', '', '', '', '', '', '', ''...\n",
+       "    intake_esm_attrs:variable_units:          ['days since 2015-01-01 00:00:0...\n",
+       "    intake_esm_attrs:realm:                   seaIce\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   iceh_XXX_daily.1day
" + ], + "text/plain": [ + " Size: 2GB\n", + "Dimensions: (time: 365, d2: 2, nj: 300, ni: 360, nc: 5)\n", + "Coordinates:\n", + " * time (time) datetime64[ns] 3kB 2015-01-02 2015-01-03 ... 2016-01-01\n", + " TLON (nj, ni) float32 432kB dask.array\n", + " TLAT (nj, ni) float32 432kB dask.array\n", + " ULON (nj, ni) float32 432kB dask.array\n", + " ULAT (nj, ni) float32 432kB dask.array\n", + "Dimensions without coordinates: d2, nj, ni, nc\n", + "Data variables: (12/24)\n", + " time_bounds (time, d2) datetime64[ns] 6kB dask.array\n", + " NCAT (nc) float32 20B dask.array\n", + " tmask (nj, ni) float32 432kB dask.array\n", + " blkmask (nj, ni) float32 432kB dask.array\n", + " tarea (nj, ni) float32 432kB dask.array\n", + " dxt (nj, ni) float32 432kB dask.array\n", + " ... ...\n", + " algal_N (time, nj, ni) float32 158MB dask.array\n", + " skl_Nit (time, nj, ni) float32 158MB dask.array\n", + " ml_Nit (time, nj, ni) float32 158MB dask.array\n", + " fNO_ai (time, nj, ni) float32 158MB dask.array\n", + " fN_ai (time, nj, ni) float32 158MB dask.array\n", + " PP_net (time, nj, ni) float32 158MB dask.array\n", + "Attributes: (12/27)\n", + " title: sea ice model output for CICE\n", + " contents: Diagnostic and Prognostic Varia...\n", + " source: Los Alamos Sea Ice Model (CICE)...\n", + " time_period_freq: day_1\n", + " comment: This year has 365 days\n", + " comment2: File written on model date 2015...\n", + " ... ...\n", + " intake_esm_attrs:variable_standard_name: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n", + " intake_esm_attrs:variable_cell_methods: ['', '', '', '', '', '', '', ''...\n", + " intake_esm_attrs:variable_units: ['days since 2015-01-01 00:00:0...\n", + " intake_esm_attrs:realm: seaIce\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: iceh_XXX_daily.1day" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now, if we wanted to subset and load some data, we could with, for example...\n", + "first_result = esm_ds.df.head(1).path\n", + "esm_ds.search(path=first_result).to_dask()" + ] + }, + { + "cell_type": "markdown", + "id": "3b388be4-2535-4e60-8397-159c80fe5811", + "metadata": {}, + "source": [ + "## Case 2: Search for and access a datastore - from the ACCESS-NRI Intake Catalog." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1a90873e-16e5-49e2-b1d4-edb05f510db8", + "metadata": {}, + "outputs": [], + "source": [ + "# We imported intake above. To get the ACCESS-NRI Intake catalog, we use the following line:\n", + "access_nri_catalog = intake.cat.access_nri" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b958a0de-940d-4289-aa9e-5c4ba317b3ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

01deg_jra55v13_ryf9091 catalog with 34 dataset(s) from 11947 asset(s):

\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", + "
unique
path11947
realm2
variable178
frequency5
start_date3361
end_date3360
variable_long_name181
variable_standard_name36
variable_cell_methods3
variable_units50
filename3469
file_id33
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# We've picked a demo experiment name here. You can find all available experiments in the standard catalog by calling `intake.cat.access_nri`.\n", + "experiment_name='01deg_jra55v13_ryf9091'\n", + "\n", + "cat = intake.cat.access_nri\n", + "esm_ds = cat[experiment_name]\n", + "\n", + "# Note: Again, we call this esm_ds as this object is an `esm_datastore`: see https://intake-esm.readthedocs.io/en/v2021.8.17/user-guide/overview.html#loading-a-catalog for more details\n", + "\n", + "# Once we have our esm datastore, we can interact with it the same way we did above.\n", + "\n", + "esm_ds" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "44713a18-40a5-4f57-a50b-cc6c5dd70fd6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 3GB\n",
+       "Dimensions:       (time: 1, d2: 2, nj: 2700, ni: 3600, nc: 5)\n",
+       "Coordinates:\n",
+       "  * time          (time) object 8B 1900-02-01 00:00:00\n",
+       "    TLON          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    TLAT          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ULON          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ULAT          (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    NCAT          (nc) float32 20B dask.array<chunksize=(5,), meta=np.ndarray>\n",
+       "Dimensions without coordinates: d2, nj, ni, nc\n",
+       "Data variables: (12/49)\n",
+       "    time_bounds   (time, d2) object 16B dask.array<chunksize=(1, 2), meta=np.ndarray>\n",
+       "    tmask         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    blkmask       (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    tarea         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    uarea         (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    dxt           (nj, ni) float32 39MB dask.array<chunksize=(675, 900), meta=np.ndarray>\n",
+       "    ...            ...\n",
+       "    fmeltt_ai_m   (time, nj, ni) float32 39MB dask.array<chunksize=(1, 675, 900), meta=np.ndarray>\n",
+       "    opening_m     (time, nj, ni) float32 39MB dask.array<chunksize=(1, 675, 900), meta=np.ndarray>\n",
+       "    aicen_m       (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    vicen_m       (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    fmelttn_ai_m  (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "    flatn_ai_m    (time, nc, nj, ni) float32 194MB dask.array<chunksize=(1, 1, 675, 900), meta=np.ndarray>\n",
+       "Attributes: (12/24)\n",
+       "    title:                                    sea ice model output for CICE\n",
+       "    contents:                                 Diagnostic and Prognostic Varia...\n",
+       "    source:                                   Los Alamos Sea Ice Model (CICE)...\n",
+       "    comment:                                  This Year Has 365 days\n",
+       "    comment2:                                 File written on model date 1900...\n",
+       "    comment3:                                 seconds elapsed into model date...\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_cell_methods:   ,,,,,,,,,,,,,,,,,,time: mean,ti...\n",
+       "    intake_esm_attrs:variable_units:          days since 1900-01-01 00:00:00,...\n",
+       "    intake_esm_attrs:filename:                iceh.1900-01.nc\n",
+       "    intake_esm_attrs:file_id:                 iceh_XXXX_XX\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   iceh_XXXX_XX.1mon
" + ], + "text/plain": [ + " Size: 3GB\n", + "Dimensions: (time: 1, d2: 2, nj: 2700, ni: 3600, nc: 5)\n", + "Coordinates:\n", + " * time (time) object 8B 1900-02-01 00:00:00\n", + " TLON (nj, ni) float32 39MB dask.array\n", + " TLAT (nj, ni) float32 39MB dask.array\n", + " ULON (nj, ni) float32 39MB dask.array\n", + " ULAT (nj, ni) float32 39MB dask.array\n", + " NCAT (nc) float32 20B dask.array\n", + "Dimensions without coordinates: d2, nj, ni, nc\n", + "Data variables: (12/49)\n", + " time_bounds (time, d2) object 16B dask.array\n", + " tmask (nj, ni) float32 39MB dask.array\n", + " blkmask (nj, ni) float32 39MB dask.array\n", + " tarea (nj, ni) float32 39MB dask.array\n", + " uarea (nj, ni) float32 39MB dask.array\n", + " dxt (nj, ni) float32 39MB dask.array\n", + " ... ...\n", + " fmeltt_ai_m (time, nj, ni) float32 39MB dask.array\n", + " opening_m (time, nj, ni) float32 39MB dask.array\n", + " aicen_m (time, nc, nj, ni) float32 194MB dask.array\n", + " vicen_m (time, nc, nj, ni) float32 194MB dask.array\n", + " fmelttn_ai_m (time, nc, nj, ni) float32 194MB dask.array\n", + " flatn_ai_m (time, nc, nj, ni) float32 194MB dask.array\n", + "Attributes: (12/24)\n", + " title: sea ice model output for CICE\n", + " contents: Diagnostic and Prognostic Varia...\n", + " source: Los Alamos Sea Ice Model (CICE)...\n", + " comment: This Year Has 365 days\n", + " comment2: File written on model date 1900...\n", + " comment3: seconds elapsed into model date...\n", + " ... ...\n", + " intake_esm_attrs:variable_cell_methods: ,,,,,,,,,,,,,,,,,,time: mean,ti...\n", + " intake_esm_attrs:variable_units: days since 1900-01-01 00:00:00,...\n", + " intake_esm_attrs:filename: iceh.1900-01.nc\n", + " intake_esm_attrs:file_id: iceh_XXXX_XX\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: iceh_XXXX_XX.1mon" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now, if we wanted to subset and load some data, we could with, for example...\n", + "first_result = esm_ds.df.head(1).path\n", + "esm_ds.search(path=first_result).to_dask()" + ] + }, + { + "cell_type": "markdown", + "id": "88b8951f-98ff-48da-ae7a-929b194fdeac", + "metadata": {}, + "source": [ + "___\n", + "# Using a Datastore - applies to datastores from 1. & 2. \n", + "___" + ] + }, + { + "cell_type": "markdown", + "id": "27b46641-0de8-412d-aaa1-bb5933950b3e", + "metadata": {}, + "source": [ + "## Searching a datastore\n", + "\n", + "ESM Datastores contain a lot of useful information that lets us search for the data we're after, before we load it into dask/xarray. Lets look at some examples." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "38e5f86f-f5da-4399-a439-f5e91a4de645", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Client

\n", + "

Client-7afac66b-b12f-11ef-8206-000007cdfe80

\n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
Connection method: Cluster objectCluster type: distributed.LocalCluster
\n", + " Dashboard: /proxy/8787/status\n", + "
\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "

Cluster Info

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

LocalCluster

\n", + "

f22edfa7

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "\n", + " \n", + "
\n", + " Dashboard: /proxy/8787/status\n", + " \n", + " Workers: 7\n", + "
\n", + " Total threads: 7\n", + " \n", + " Total memory: 32.00 GiB\n", + "
Status: runningUsing processes: True
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-22bd2e94-42ab-467f-b23e-8bdfc90fcd73

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://127.0.0.1:43579\n", + " \n", + " Workers: 7\n", + "
\n", + " Dashboard: /proxy/8787/status\n", + " \n", + " Total threads: 7\n", + "
\n", + " Started: Just now\n", + " \n", + " Total memory: 32.00 GiB\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 0

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:33687\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/46001/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:46467\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-gf8vo9lz\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 1

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:45257\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/35963/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:35487\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-r8pdwszn\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 2

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:40103\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/44275/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:37115\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-g7o3_xof\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 3

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:45143\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/37669/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:39899\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-_sctlqc1\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 4

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:40513\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/37813/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:46597\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-lzof_0q0\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 5

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:32865\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/34691/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:43811\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-leffdmxa\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 6

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:39425\n", + " \n", + " Total threads: 1\n", + "
\n", + " Dashboard: /proxy/35937/status\n", + " \n", + " Memory: 4.57 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:41435\n", + "
\n", + " Local directory: /jobfs/129999899.gadi-pbs/dask-scratch-space/worker-4ngybr46\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now, we import the Dask client, so we can get a bit more control over loadign variables\n", + "from dask.distributed import Client\n", + "client = Client(threads_per_worker=1)\n", + "client" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "23ff97f1-e9c6-4c8f-9a82-f4b7e3024d90", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

01deg_jra55v13_ryf9091 catalog with 34 dataset(s) from 11947 asset(s):

\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", + "
unique
path11947
realm2
variable178
frequency5
start_date3361
end_date3360
variable_long_name181
variable_standard_name36
variable_cell_methods3
variable_units50
filename3469
file_id33
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "esm_ds" + ] + }, + { + "cell_type": "markdown", + "id": "9c023f93-5492-4cd3-bf86-067e1edf36df", + "metadata": {}, + "source": [ + "We can see that we have a number of different fields in our esm datastore:\n", + "- filename\n", + "- file id\n", + "- ...\n", + "- realm\n", + "- derived_variable\n", + "\n", + "Other than `derived_variable`, we can use any of these to search for data. Lets say we are interested in temperature and salinity: lets search for anything where `variable` contains the string `temp`. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "23e08f63-1b5c-49f0-b7b1-8227f8744cc2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

01deg_jra55v13_ryf9091 catalog with 5 dataset(s) from 1593 asset(s):

\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", + "
unique
path1593
realm1
variable29
frequency4
start_date1403
end_date1404
variable_long_name29
variable_standard_name11
variable_cell_methods2
variable_units16
filename15
file_id4
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "temp_ds = esm_ds.search(variable='temp')\n", + "temp_ds" + ] + }, + { + "cell_type": "markdown", + "id": "8d38dada-6ad7-4c4e-8f59-a3eebc1ab7e4", + "metadata": {}, + "source": [ + "This gives us 5 datasets, with 4 frequencies. We can load them all at once with `.to_dataset_dict()`.\n", + "\n", + "We won't run the cell below - it uses an awful lot of memory." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a874830-1d5a-4e9f-bc43-ea8f4d5e5f95", + "metadata": {}, + "outputs": [], + "source": [ + "temp_ds.to_dataset_dict()" + ] + }, + { + "cell_type": "markdown", + "id": "cc82d6a3-3c8d-46d1-bb86-e04ee4115df9", + "metadata": {}, + "source": [ + "-> The keys in the returned dictionary of datasets are constructed as follows:\n", + "\t'file_id.frequency'\n", + "\n", + " 60.00% [3/5 00:37<00:25]" + ] + }, + { + "cell_type": "markdown", + "id": "5497a309-58d8-4a88-8d30-10ededda0a02", + "metadata": {}, + "source": [ + "We can see from the ways that the keys have been constructed (`file_id.frequency`) that we should be able to get a single dataset if we pick out the right combination of file_id and frequency. \n", + "\n", + "Lets do that." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f5ce5320-bdd5-4431-b7e4-9544a7cd92a9", + "metadata": {}, + "outputs": [], + "source": [ + "# We can search in a couple of ways - by chaining searches, or one at a time.\n", + "temp_ds_chained = esm_ds.search(variable='temp').search(frequency='3mon')\n", + "temp_ds_one_search = esm_ds.search(variable='temp',frequency='3mon')\n", + "\n", + "# We can also search for multiple queries at once: eg.\n", + "\n", + "temp_salt_ds = esm_ds.search(variable=['temp','salt'],frequency='3mon')\n", + "# or\n", + "temp_ds_multifreq = esm_ds.search(variable='temp',frequency=['1mon','3mon'])\n", + "# or even (the following two are equivalent)\n", + "temp_salt_ds_multifreq = esm_ds.search(variable=['temp','salt'],frequency=['1mon','3mon'])\n", + "temp_salt_ds_multifreq = esm_ds.search(variable=['temp','salt']).search(frequency=['1mon','3mon'])\n", + "\n", + "# We can search for any combination of the fields in our esm datastore\n", + "# and if we want to search for multiple possible variables/frequencies/ dates, etc etc, we can use lists.\n", + "\n", + "# We can also use regular expressions (regex's) to search for patterns: eg\n", + "temp_ds_1990s = esm_ds.search(variable='temp',start_date='199.*')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1da84f71-1605-4add-9129-ba9088fa6cb5", + "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", + "
pathrealmvariablefrequencystart_dateend_datevariable_long_namevariable_standard_namevariable_cell_methodsvariable_unitsfilenamefile_id
0/g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output356/ocean/ocean.ncocean[temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo...1mon1990-01-01, 00:00:001990-04-01, 00:00:00[Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar...[sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w...[time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim...[K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:...ocean.ncocean
1/g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output357/ocean/ocean.ncocean[temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo...1mon1990-04-01, 00:00:001990-07-01, 00:00:00[Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar...[sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w...[time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim...[K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:...ocean.ncocean
2/g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output358/ocean/ocean.ncocean[temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo...1mon1990-07-01, 00:00:001990-10-01, 00:00:00[Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar...[sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w...[time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim...[K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:...ocean.ncocean
\n", + "
" + ], + "text/plain": [ + " path \\\n", + "0 /g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output356/ocean/ocean.nc \n", + "1 /g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output357/ocean/ocean.nc \n", + "2 /g/data/ik11/outputs/access-om2-01/01deg_jra55v13_ryf9091/output358/ocean/ocean.nc \n", + "\n", + " realm \\\n", + "0 ocean \n", + "1 ocean \n", + "2 ocean \n", + "\n", + " variable \\\n", + "0 [temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo... \n", + "1 [temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo... \n", + "2 [temp, pot_temp, salt, age_global, u, v, wt, dzt, pot_rho_2, pot_rho_0, tx_trans, ty_trans, ty_trans_submeso, tx_trans_rho, ty_trans_rho, ty_trans_nrho_submeso, temp_xflux_adv, temp_yflux_adv, buo... \n", + "\n", + " frequency start_date end_date \\\n", + "0 1mon 1990-01-01, 00:00:00 1990-04-01, 00:00:00 \n", + "1 1mon 1990-04-01, 00:00:00 1990-07-01, 00:00:00 \n", + "2 1mon 1990-07-01, 00:00:00 1990-10-01, 00:00:00 \n", + "\n", + " variable_long_name \\\n", + "0 [Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar... \n", + "1 [Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar... \n", + "2 [Conservative temperature, Potential temperature, Practical Salinity, Age (global), i-current, j-current, dia-surface velocity T-points, t-cell thickness, potential density referenced to 2000 dbar... \n", + "\n", + " variable_standard_name \\\n", + "0 [sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w... \n", + "1 [sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w... \n", + "2 [sea_water_conservative_temperature, sea_water_potential_temperature, sea_water_salinity, sea_water_age_since_surface_contact, sea_water_x_velocity, sea_water_y_velocity, , cell_thickness, , sea_w... \n", + "\n", + " variable_cell_methods \\\n", + "0 [time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim... \n", + "1 [time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim... \n", + "2 [time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, time: mean, tim... \n", + "\n", + " variable_units \\\n", + "0 [K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:... \n", + "1 [K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:... \n", + "2 [K, K, psu, yr, m/sec, m/sec, m/sec, m, kg/m^3, kg/m^3, kg/s, kg/s, kg/s, kg/s, kg/s, kg/s, Watts, Watts, 1/s^2, 1/sec^3, (kg/m^3)*(m^2/s^2), (kg/m^3)*(m^2/s^2), 1/sec^4, days since 1900-01-01 00:... \n", + "\n", + " filename file_id \n", + "0 ocean.nc ocean \n", + "1 ocean.nc ocean \n", + "2 ocean.nc ocean " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# We can turn our datastore into a pandas dataframe to look at it in more detail with the .df method:\n", + "temp_ds_1990s.df.head(3)\n", + "# This confirms that we have the dates we wanted. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "81335536-143c-4379-8293-e7c418a4f9eb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

01deg_jra55v13_ryf9091 catalog with 1 dataset(s) from 40 asset(s):

\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", + "
unique
path40
realm1
variable27
frequency1
start_date40
end_date40
variable_long_name27
variable_standard_name11
variable_cell_methods2
variable_units14
filename1
file_id1
derived_variable0
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# It turns out this only gives us one dataset, with 196 files - lets load it and take a look.\n", + "temp_ds_1990s" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "4f546fc4-d0f5-4a33-96dd-8d9c38801f2c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 350GB\n",
+       "Dimensions:   (time: 120, st_ocean: 75, yt_ocean: 2700, xt_ocean: 3600)\n",
+       "Coordinates:\n",
+       "  * xt_ocean  (xt_ocean) float64 29kB -279.9 -279.8 -279.7 ... 79.75 79.85 79.95\n",
+       "  * yt_ocean  (yt_ocean) float64 22kB -81.11 -81.07 -81.02 ... 89.89 89.94 89.98\n",
+       "  * st_ocean  (st_ocean) float64 600B 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n",
+       "  * time      (time) object 960B 1990-01-16 12:00:00 ... 1999-12-16 12:00:00\n",
+       "Data variables:\n",
+       "    temp      (time, st_ocean, yt_ocean, xt_ocean) float32 350GB dask.array<chunksize=(1, 7, 300, 400), meta=np.ndarray>\n",
+       "Attributes: (12/16)\n",
+       "    filename:                                 ocean.nc\n",
+       "    title:                                    ACCESS-OM2-01\n",
+       "    grid_type:                                mosaic\n",
+       "    grid_tile:                                1\n",
+       "    intake_esm_vars:                          ['temp']\n",
+       "    intake_esm_attrs:realm:                   ocean\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_cell_methods:   time: mean,time: mean,time: mea...\n",
+       "    intake_esm_attrs:variable_units:          K,K,psu,yr,m/sec,m/sec,m/sec,m,...\n",
+       "    intake_esm_attrs:filename:                ocean.nc\n",
+       "    intake_esm_attrs:file_id:                 ocean\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   ocean.1mon
" + ], + "text/plain": [ + " Size: 350GB\n", + "Dimensions: (time: 120, st_ocean: 75, yt_ocean: 2700, xt_ocean: 3600)\n", + "Coordinates:\n", + " * xt_ocean (xt_ocean) float64 29kB -279.9 -279.8 -279.7 ... 79.75 79.85 79.95\n", + " * yt_ocean (yt_ocean) float64 22kB -81.11 -81.07 -81.02 ... 89.89 89.94 89.98\n", + " * st_ocean (st_ocean) float64 600B 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n", + " * time (time) object 960B 1990-01-16 12:00:00 ... 1999-12-16 12:00:00\n", + "Data variables:\n", + " temp (time, st_ocean, yt_ocean, xt_ocean) float32 350GB dask.array\n", + "Attributes: (12/16)\n", + " filename: ocean.nc\n", + " title: ACCESS-OM2-01\n", + " grid_type: mosaic\n", + " grid_tile: 1\n", + " intake_esm_vars: ['temp']\n", + " intake_esm_attrs:realm: ocean\n", + " ... ...\n", + " intake_esm_attrs:variable_cell_methods: time: mean,time: mean,time: mea...\n", + " intake_esm_attrs:variable_units: K,K,psu,yr,m/sec,m/sec,m/sec,m,...\n", + " intake_esm_attrs:filename: ocean.nc\n", + " intake_esm_attrs:file_id: ocean\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: ocean.1mon" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# If we have one dataset in our search results, we can use `.to_dask()` on our dataset to load it.\n", + "temp_ds_1990s.to_dask()" + ] + }, + { + "cell_type": "markdown", + "id": "4efc0cba-8ee0-4aef-88f1-e5bd9a39b22d", + "metadata": {}, + "source": [ + "If we look at this output, we an see that our entire array is 235 GiB, but we have 688 'chunks', each of which are 2.57 MiB. This means that when we load our dataset, dask will have to combine 106920 __very small__ chunks. Things would be much faster if it didn't have to do that: so lets tell dask the chunks we want to use.\n", + "\n", + "This is also the cause of the warnings above (NB. lots of them have been cleared for readability)\n", + "\n", + "___\n", + "### What is a Chunk?\n", + "\n", + "Dask is designed to handle *distributed* datasets. What this means is essentially it can load lots of files (more than would fit in memory), operate on them separately, and then combine them all later to get a result that fits in memory. \n", + "\n", + "In this instance, our chunks are way smaller than they need to be - and this is inefficient \n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3e2d0b09-d3ef-4bbe-95ac-293177a3ba73", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset> Size: 350GB\n",
+       "Dimensions:   (time: 120, st_ocean: 75, yt_ocean: 2700, xt_ocean: 3600)\n",
+       "Coordinates:\n",
+       "  * xt_ocean  (xt_ocean) float64 29kB -279.9 -279.8 -279.7 ... 79.75 79.85 79.95\n",
+       "  * yt_ocean  (yt_ocean) float64 22kB -81.11 -81.07 -81.02 ... 89.89 89.94 89.98\n",
+       "  * st_ocean  (st_ocean) float64 600B 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n",
+       "  * time      (time) object 960B 1990-01-16 12:00:00 ... 1999-12-16 12:00:00\n",
+       "Data variables:\n",
+       "    temp      (time, st_ocean, yt_ocean, xt_ocean) float32 350GB dask.array<chunksize=(1, 75, 900, 1200), meta=np.ndarray>\n",
+       "Attributes: (12/16)\n",
+       "    filename:                                 ocean.nc\n",
+       "    title:                                    ACCESS-OM2-01\n",
+       "    grid_type:                                mosaic\n",
+       "    grid_tile:                                1\n",
+       "    intake_esm_vars:                          ['temp']\n",
+       "    intake_esm_attrs:realm:                   ocean\n",
+       "    ...                                       ...\n",
+       "    intake_esm_attrs:variable_cell_methods:   time: mean,time: mean,time: mea...\n",
+       "    intake_esm_attrs:variable_units:          K,K,psu,yr,m/sec,m/sec,m/sec,m,...\n",
+       "    intake_esm_attrs:filename:                ocean.nc\n",
+       "    intake_esm_attrs:file_id:                 ocean\n",
+       "    intake_esm_attrs:_data_format_:           netcdf\n",
+       "    intake_esm_dataset_key:                   ocean.1mon
" + ], + "text/plain": [ + " Size: 350GB\n", + "Dimensions: (time: 120, st_ocean: 75, yt_ocean: 2700, xt_ocean: 3600)\n", + "Coordinates:\n", + " * xt_ocean (xt_ocean) float64 29kB -279.9 -279.8 -279.7 ... 79.75 79.85 79.95\n", + " * yt_ocean (yt_ocean) float64 22kB -81.11 -81.07 -81.02 ... 89.89 89.94 89.98\n", + " * st_ocean (st_ocean) float64 600B 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n", + " * time (time) object 960B 1990-01-16 12:00:00 ... 1999-12-16 12:00:00\n", + "Data variables:\n", + " temp (time, st_ocean, yt_ocean, xt_ocean) float32 350GB dask.array\n", + "Attributes: (12/16)\n", + " filename: ocean.nc\n", + " title: ACCESS-OM2-01\n", + " grid_type: mosaic\n", + " grid_tile: 1\n", + " intake_esm_vars: ['temp']\n", + " intake_esm_attrs:realm: ocean\n", + " ... ...\n", + " intake_esm_attrs:variable_cell_methods: time: mean,time: mean,time: mea...\n", + " intake_esm_attrs:variable_units: K,K,psu,yr,m/sec,m/sec,m/sec,m,...\n", + " intake_esm_attrs:filename: ocean.nc\n", + " intake_esm_attrs:file_id: ocean\n", + " intake_esm_attrs:_data_format_: netcdf\n", + " intake_esm_dataset_key: ocean.1mon" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# We have 120 files - one for each time step. Because we have lots of data in the x & y dimensions, we will\n", + "# still need to split them up on these\n", + "# Luckily, we can pass `.to_dask()` a chunk specification - and make sure we get sensible sized chunks.\n", + "\n", + "# As a rule of thumb, 300MiB chunks are a good target.\n", + "\n", + "chunk_spec = {\n", + " # 'time' : 120, We dont need to pass a time chunk - it defaults to one per file anyway - but this is how we would tell it to.\n", + " 'st_ocean' : -1, # We can also use -1 to mean '1 chunk for the whole dimension - we could have done this for time too & it would be the exact same.\n", + " 'yt_ocean' : 900, \n", + " 'xt_ocean': 1200\n", + " \n", + "}\n", + "\n", + "temp_ds_1990s.to_dask(\n", + " xarray_open_kwargs = {'chunks': chunk_spec} \n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "a39e7ff1-9d6e-4d39-8126-cc73adb4a6ad", + "metadata": {}, + "source": [ + "## Now we have more sensible chunks, we can easily operate on our data. \n", + "### Lets average over time first to get a climatological state, & then plot the zonal mean temperature structure around the Southern Ocean.\n", + "\n", + "This all uses standard xarray operations now, which you are hopefully familiar with.\n", + "\n", + "For a brief intro to xarray, see the excellent notes at https://cmip6moap.github.io/resources/loading-data-xarray/" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "0f2326d4-dae1-4b30-923b-831b3061d03b", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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kCFDAAAFBQXo378/6tatq+5LTExEixYt8Otf/9r1BhIREZE5N4bFOKwWyHZwNHXqVABAixYtcNddd6kJ2URERESXEsc5RzfffDOOHj2qvt+8eTPGjx+PV1991dWGERERUXA+IeCN8MWeo0COg6Phw4fjs88+AwAUFxejb9++2Lx5M/70pz/hySefdL2BREREZM6//EekT6tV91XEHsfB0c6dO/GLX/wCAPDWW2+hY8eO2LBhA958800sXrzY7fYRERERVSnHs1RduHBBzTdau3YtBg8eDAC46qqrUFRU5G7riIiIyBKfVosOxz1HV199NV555RV88cUXWLNmjfr4/n//+1+kpqa63kAiIiIyx0kgo8NxcPTss89i/vz56N27N+6++251PbX33ntPHW4jIiKi6Is0GVt5kZ7jYbXevXvj2LFjKC0tRYMGDdTtDzzwAGrXru1q48g9ew/+N2BbdvOmztZTi/Z6ZG6u03aJsLOWmtNjwl57zer+Cp8r62pp1xkLtQabI258X5id03ifze5rqHO7tA5ZVNZoA8K7d1brJbrFTpuicV6rtd6sVNHaahQdjr/zn3zySaxfv14XGAHAFVdcgVdeecW1hhEREVFwPihPrEXwqu6LiEGOg6Np06Zh4MCBmDVrlm77mTNnMH36dNcaRkRERMF5fcKVF+mF1Re7dOlS5ObmYtSoUSgvL3e7TURERETVJqzg6KabbsLGjRuxefNm9O7dG4cPH3a7XURERBSCcOFJNcGE7ACOgyOpIgmxVatW2LhxI5KTk9GtWzds3brV9cYRERGRNa9w50V6joMjbYSZnJyMDz/8EHfccQeGDBniZruIiIiIqoXjZw0XLVqElJQU9b0sy/jb3/6GLl264PPPP3e1cURERGTNjUkcOQlkIMfB0ciRI02333vvvbj33nsjbhARERHZ48bTZnxaLdClN2seERERUQQ4hScREVGc4rBadLDniIiIKE7F+tNqLVq0gCRJutdjjz0WvRO6hD1Hl7G9B360VS47q7njum2v9aRdl+sSEM5aaFXNqo2urLkW7LOs4nXEHK/BFrQyk3MGrENmcl9D3dPq/N43uT/hrtFmea+r6/pcWOvPtTZEWTz0HD355JMYPXq0+r5u3bpRPZ8bbAVHpaWltitMTk4OuzFERER0aalXrx7S09OruxmO2AqO6tevr07+aEUIAUmS4PV6XWkYERERBefzCfgifNpMOd7YEZKUlISkpKSI6gaAZ599Fk899RQyMzPx29/+Fo8++igSExMjrjeabAVHn332WbTbQURERA75XMgZUmKrzMxM3fapU6di2rRpEdX98MMP49prr0WDBg2wefNmTJkyBYWFhXjttdciqjfabAVHvXr1inY7iIiIqBodOnRIlxpj1Ws0bdo0TJ8+PWhdW7ZsQbdu3fDII4+o2zp16oQGDRrgN7/5DZ599lmkpqa60/AosBUc/ec//7FdYadOncJuDBEREdnnZkJ2cnKyrbzhsWPH4q677gpapkWLFqbbe/ToAQDYt29f/AdHnTt3hiRJIVfujSTnKDc3F3/605/w8MMPY86cOQD8eUzTp0/Hq6++ipMnT6J79+74+9//jquvvlo9rqysDJMmTcI//vEPnDt3Dn369MFLL72Epk2bqmVOnjyJcePG4b333gMADB48GC+++CLq168fVluJiIhigVcIeCMMjpwe36hRIzRq1Cisc23btg0A0KRJk7COryq2gqPCwsKoNmLLli149dVXA3qdnnvuOcyaNQuLFy9GmzZt8PTTT+OWW27Bnj17UK9ePQDA+PHj8f7772P58uVITU3FxIkTMWjQIOTn58Pj8QAAhg8fjh9//BGrVq0CADzwwAMYMWIE3n///aheFxER0eUqLy8PGzduxE033YSUlBRs2bIFjzzyCAYPHoxmzZpVd/OCshUcNW/ufJ4bu86cOYN77rkHCxYswNNPP61uF0Jgzpw5ePzxxzF06FAAwJIlS5CWloY333wTDz74IEpKSrBw4UIsW7YMffv2BQC8/vrryMzMxNq1a9G/f3/s3r0bq1atwsaNG9G9e3cAwIIFC5CTk4M9e/agbdu2Ubs2IiKiaHLzaTW3JSUlYcWKFZg+fTrKysrQvHlzjB49GpMnT47K+dwU1ixVy5Ytw/XXX4+MjAwcOHAAADBnzhz861//clzXH/7wB9x6661qcKMoLCxEcXEx+vXrp25LSkpCr169sGHDBgBAfn4+Lly4oCuTkZGBDh06qGXy8vKQkpKiBkaAf8wzJSVFLWOmrKwMpaWluhcREVEs8cKFGbKj1LZrr70WGzduxKlTp3Du3Dl8++23mDZtGmrXrh2lM7rHcXD08ssvY8KECfjVr36FU6dOqTlG9evXV3OF7Fq+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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "xr_ds = temp_ds_1990s.to_dask(\n", + " xarray_open_kwargs = {'chunks' : chunk_spec}\n", + ")\n", + "\n", + "SOU_OCN_DS = xr_ds.sel(yt_ocean=slice(-90,-40)) # Just get south of 40 South\n", + "\n", + "SOU_ZM = SOU_OCN_DS.mean(dim=['time','xt_ocean']) # Average over time & longitude\n", + "\n", + "SOU_ZM['temp_c'] = SOU_ZM['temp'] - 273\n", + "\n", + "# Create the plot\n", + "fig, ax = plt.subplots()\n", + "\n", + "SOU_ZM['temp_c'].plot(yincrease=False, ax = ax)\n", + "\n", + "# Set the background color\n", + "ax.set_facecolor('lightgrey')\n", + "\n", + "plt.show()\n", + "\n" + ] + } + ], + "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.11.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From e2408067485fb3c14f68939af6732ae419dd3796 Mon Sep 17 00:00:00 2001 From: anton-seaice Date: Wed, 4 Dec 2024 15:58:58 +1100 Subject: [PATCH 3/3] add a few words --- catalog_user_recipe.ipynb | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/catalog_user_recipe.ipynb b/catalog_user_recipe.ipynb index 1949564..b9283f3 100644 --- a/catalog_user_recipe.ipynb +++ b/catalog_user_recipe.ipynb @@ -37,6 +37,14 @@ "## Case 1: Opening a datastore when you know where the experiment data is." ] }, + { + "cell_type": "markdown", + "id": "7461ec38-9cc8-4523-8339-43c72cb30057", + "metadata": {}, + "source": [ + "In this case, we've run an access-model (say ACCESS-OM3) and we've already generated an intake esm datastore for the model run. (The user-script configured in payu generates an intake-esm datastore automatically at the end of the model run for ACCESS-OM3 , typically named `intake_datastore.json` and stored in the archive folder of the model run. )" + ] + }, { "cell_type": "code", "execution_count": 2, @@ -138,7 +146,7 @@ ], "source": [ "# We've picked a demo experiment name here. You can find all available experiments in the standard catalog by calling `intake.cat.access_nri`.\n", - "demo_datastore_path = \"/home/189/ct1163/catalog_demo/demo_datastore.json\"\n", + "demo_datastore_path = \"/home/189/ct1163/catalog_demo/intake_datastore.json\"\n", "\n", "esm_ds = intake.open_esm_datastore(demo_datastore_path,\n", " columns_with_iterables=[\n", @@ -2915,6 +2923,14 @@ "## Case 2: Search for and access a datastore - from the ACCESS-NRI Intake Catalog." ] }, + { + "cell_type": "markdown", + "id": "9dace72c-318a-4b72-b33e-ce7550ee335f", + "metadata": {}, + "source": [ + "We might want to compare to some existing model results from access-om2. This data can be found in the access-nri intake catalog." + ] + }, { "cell_type": "code", "execution_count": 4, @@ -10576,9 +10592,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python [conda env:analysis3-24.04] *", "language": "python", - "name": "python3" + "name": "conda-env-analysis3-24.04-py" }, "language_info": { "codemirror_mode": { @@ -10590,7 +10606,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.10.14" } }, "nbformat": 4,