{ "cells": [ { "cell_type": "markdown", "id": "f30aa9dc", "metadata": {}, "source": [ "# ocnBgchem: 2D\n", "\n", "2D ocnBgchem data\n", "\n", "```{dropdown} **Branding suffix of datasets**\n", "Datasets with the folloing branding suffix are shown in this page: \\\n", "[time]-[vertical]-[horizontal]-[domain]\n", "```\n", "* tavg-ols-hxy-sea\n", "* tavg-u-hxy-sea\n", "* tmax-op20bar-hxy-sea\n", "* tavg-d100m-hxy-sea\n", "* tavg-d1000m-hxy-sea\n", " - tavg: time average\n", " - u: ocean surface\n", " - ols: ocean surface\n", " - op20bar: 20.2bar depth\n", " - d100m: layer at 100m depth\n", " - d1000m: layer at 1000m depth\n", " - hxy: horizontal curvlinear grids\n", " - sea: ocean domain" ] }, { "cell_type": "code", "execution_count": null, "id": "f1f107ce", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "## Import libraries\n", "import glob\n", "import logging\n", "import os\n", "import sys\n", "\n", "import cartopy.crs as ccrs\n", "import cartopy.feature as cfeature\n", "import cmocean\n", "import matplotlib as mpl\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import xarray as xr\n", "from IPython.display import HTML, display\n", "from matplotlib.colors import BoundaryNorm, ListedColormap\n", "from xarray.coders import CFDatetimeCoder\n", "\n", "sys.path.append(os.path.dirname(os.getcwd()))\n", "from utils import read_compound_names, read_variables\n", "\n", "logging.basicConfig(\n", " filename=\"execute.log\",\n", " level=logging.INFO,\n", " format=\"%(asctime)s %(message)s\",\n", " force=True,\n", ")\n", "log = logging.getLogger(\"ocnBgchem_2D\")\n", "log.info(\"Starting ocnBgchem_2D.ipynb\")" ] }, { "cell_type": "code", "execution_count": null, "id": "2eb83f3b", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# load parameters\n", "import yaml\n", "\n", "with open('params.yml', 'r') as f:\n", " param = yaml.safe_load(f)\n", " cmorout = param['cmorout']\n", " source_id = param['source_id']\n", " experiment_id = param['experiment_id']\n", " variant_label = param['variant_label']\n", " version = param['version']" ] }, { "cell_type": "code", "execution_count": null, "id": "8314513c", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# grid label\n", "grid_label = 'g202' # grid label, e.g., 'gn', 'gr', 'g999'\n", "\n", "# data path\n", "data_path = os.path.join(cmorout, source_id, experiment_id, version)\n", "\n", "# load grid\n", "grid_file = f\"areacello_ti-u-hxy-u_fx_glb_{grid_label}_{source_id}_{experiment_id}_{variant_label}.nc\"\n", "if os.path.exists(os.path.join(data_path, grid_file)):\n", " grid_file = os.path.join(data_path, grid_file)\n", " with xr.open_dataset(grid_file) as ds:\n", " parea = ds['areacello']\n", "else:\n", " grid_file = 'assets/grid.nc'\n", " with xr.open_dataset(grid_file) as ds:\n", " parea = ds['parea']\n", " parea = parea.rename({'y': 'j', 'x': 'i'})\n", "\n", "grid_file = f\"sftof_ti-u-hxy-u_fx_glb_{grid_label}_{source_id}_{experiment_id}_{variant_label}.nc\"\n", "if os.path.exists(os.path.join(data_path, grid_file)):\n", " grid_file = os.path.join(data_path, grid_file)\n", " with xr.open_dataset(grid_file) as ds:\n", " pmask = ds['sftof']\n", "else:\n", " grid_file = 'assets/grid.nc'\n", " with xr.open_dataset(grid_file) as ds:\n", " pmask = ds['pmask']\n", " pmask = pmask.rename({'y': 'j', 'x': 'i'})\n", "\n", "# load methods for plotting and set defaults\n", "methods =read_variables('assets/methods.txt')\n", "#print(methods.keys())" ] }, { "cell_type": "markdown", "id": "f06c51b7", "metadata": {}, "source": [ "---\n", "```{dropdown} **List of datasets:** \n", "List of compound names of datasets that needs to be cmorized. \\\n", "Those datasets which are not cmorized have no link.\n", "``" ] }, { "cell_type": "code", "execution_count": null, "id": "67a5a359", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# load compound names\n", "grid_label = 'g???'\n", "coords = ('tavg-u-hxy-sea', 'tavg-ols-hxy-sea', 'tavg-d100m-hxy-sea', 'tavg-d1000m-hxy-sea', 'tavg-op20bar-hxy-sea')\n", "cnames = read_compound_names('assets/variables.nml')\n", "# examples of compound names:\n", "# cnames = ['ocnBgchem.chl.tavg-ols-hxy-sea.mon.glb']\n", "for cname in cnames:\n", " log.info(f\"processing {cname}\")\n", " realm = cname.split('.')[0]\n", " var = cname.split('.')[1]\n", " coord = cname.split('.')[2]\n", " freq = cname.split('.')[3]\n", " region = cname.split('.')[4]\n", "\n", " if realm != 'ocnBgchem' or coord not in coords:\n", " continue\n", " else:\n", " file_pattern = f\"{var}_{coord}_{freq}_{region}_{grid_label}_{source_id}_{experiment_id}_{variant_label}_*.nc\"\n", " if not glob.glob(os.path.join(data_path, file_pattern)):\n", " print(cname)\n", " continue\n", " else:\n", " display(HTML(f'{cname}'))" ] }, { "cell_type": "markdown", "id": "8691c6c2", "metadata": {}, "source": [ "---\n", "```{dropdown} **Dataset validated:**\n", "Each validated dataset has some text information and some plots (2D and/or 1D)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "25072041", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "\n", "# loop through compound names and plot\n", "for cname in cnames:\n", "# mth_vert = 'mean'\n", " mth_ts = 'mean'\n", " mth_cmap = 'mpl.colormaps[\"viridis\"]'\n", " if cname not in methods:\n", " print(f\"{cname} not found in methods.txt, using default methods for plotting.\")\n", " else:\n", " if methods[cname] is not None:\n", "# if 'vertical' in methods[cname].keys():\n", "# mth_vert = methods[cname]['vertical']\n", " if 'timeseries' in methods[cname]:\n", " mth_ts = methods[cname]['timeseries']\n", "\n", " if 'cmap' in methods[cname]:\n", " mth_cmap = methods[cname]['cmap']\n", "\n", " realm = cname.split('.')[0]\n", " var = cname.split('.')[1]\n", " coord = cname.split('.')[2]\n", " freq = cname.split('.')[3]\n", " region = cname.split('.')[4]\n", "\n", " if realm != 'ocnBgchem' or coord not in coords:\n", " continue\n", "\n", " file_pattern = f\"{var}_{coord}_{freq}_{region}_{grid_label}_{source_id}_{experiment_id}_{variant_label}_*.nc\"\n", " data_files = sorted(glob.glob(os.path.join(data_path, file_pattern)))\n", " if data_files:\n", " log.info(f\"{cname}\")\n", " with xr.open_mfdataset(data_files, decode_times=CFDatetimeCoder(use_cftime=True)) as ds:\n", " if var in ds:\n", " data = ds[var]\n", " lat = ds['latitude']\n", " lon = ds['longitude']\n", " else:\n", " continue\n", " else:\n", " continue\n", "\n", " data2d = data.mean(dim='time')\n", " data2d.attrs = data.attrs.copy()\n", " # remove the last row of grid info if the data has not the last row\n", " if data2d.sizes['j'] == 384:\n", " parea = parea.isel(j=slice(0, 384))\n", " pmask = pmask.isel(j=slice(0, 384))\n", "\n", " display(HTML(f'
'))\n", " print(f'\\033[1m{cname}\\033[0m')\n", " print(f'long name: {data2d.long_name} ({data2d.units})')\n", "# print(f'vertical aggregation method for 3D->2D plot: {mth_vert}')\n", " print(f'timeseries aggregation method for 2D->1D plot: {mth_ts}')\n", " print(f'original_name: {data2d.attrs[\"original_name\"]} -> {var}')\n", " if 'history' in data2d.attrs:\n", " print(f'history: {data2d.attrs[\"history\"]}')\n", " if 'comment' in data2d.attrs:\n", " print(f'comment: {data2d.attrs[\"comment\"]}')\n", "\n", " #ax1 = fig.add_subplot(1, 2, 1, projection=proj)\n", " #fig, (ax1, ax2) = plt.subplots( nrows=1, ncols=2, figsize=(12, 5), gridspec_kw={'width_ratios': [2, 1]}, subplot_kw={'projection': proj})\n", "\n", " fig = plt.figure(figsize=(16, 3), dpi=96)\n", " gs = fig.add_gridspec(nrows=1, ncols=2, width_ratios=[2, 1]) \n", " proj = ccrs.PlateCarree(central_longitude=90.0)\n", "\n", " # plot 2D map\n", " ax1 = fig.add_subplot(gs[0], projection=proj)\n", " # rescale\n", " vmin, vmax = data2d.quantile([0.01, 0.99], dim=None).values\n", " if mth_cmap == 'cmocean.cm.balance':\n", " vmax = max(abs(vmin),abs(vmax))\n", " vmin = -vmax\n", " # Define the discrete levels (boundaries) and the corresponding colors\n", " levels = np.linspace(vmin, vmax, 21)\n", " n_levels = 20\n", " colors = eval(mth_cmap)(np.linspace(0,1,n_levels))\n", " cmap = ListedColormap(colors)\n", "\n", " # Create a BoundaryNorm to map data to discrete color indices\n", " norm = BoundaryNorm(levels, ncolors=len(cmap.colors), clip=False)\n", "\n", " if vmin == vmax:\n", " pm = ax1.pcolormesh(lon, lat, data2d, cmap=cmap,\n", " transform=ccrs.PlateCarree(), shading='auto', rasterized=True)\n", " else:\n", " pm = ax1.pcolormesh(lon, lat, data2d, cmap=cmap, norm=norm,\n", " transform=ccrs.PlateCarree(), shading='auto', rasterized=True)\n", "\n", " # Add map features\n", " #ax1.stock_img()\n", " ax1.coastlines(resolution='110m')\n", " ax1.add_feature(cfeature.LAND, facecolor='lightgray')\n", "\n", " gl = ax1.gridlines(ylocs=range(-90, 90, 30), draw_labels=True)\n", " gl.ylocator = mpl.ticker.FixedLocator(range(-90,90,30))\n", "\n", " # Add colorbar\n", " cb = plt.colorbar(pm, ax=ax1, fraction=0.4, shrink=0.8, label='[yr]', extend='both')\n", " cb.set_label(label=data.units, size=14)\n", " cb.ax.tick_params(labelsize=12)\n", " plt.tight_layout()\n", " \n", " #fig, ax = plot_map2d(lon, lat, data2d.mean(dim='time'), proj='PlateCarree', norm=None, cmap=eval(mth_cmap))\n", " plt.suptitle(data2d.long_name, y=1.1)\n", "\n", " # plot 1D timeseries\n", " if mth_ts == 'mean':\n", " data1d = (data*parea).mean(dim=['j', 'i'], keep_attrs=True) / \\\n", " parea.mean(dim=['j', 'i'])\n", " elif mth_ts == 'sum':\n", " data1d = (data*parea).sum(dim=['j', 'i'], keep_attrs=True) / \\\n", " parea.sum(dim=['j', 'i'])\n", " else:\n", " raise ValueError(f'Unsupported timeseries method: {mth_ts}')\n", " \n", " data1d.attrs = data.attrs.copy()\n", "\n", " ax2 = fig.add_subplot(gs[1])\n", " if data1d.sizes[\"time\"] < 2:\n", " ax2.text(0.1, 0.8, (f\"global {mth_ts} value: {data1d.values[0]} {data1d.units}\"))\n", " ax2.text(0.1, 0.6, (\"less than 2 time steps.\"))\n", " ax2.text(0.1, 0.4, (\"skipping timeseries plot.\"))\n", " else:\n", " data1d.plot(ax=ax2)\n", "\n", " plt.show()\n", "\n", " del data, data2d, data1d\n", " del ax1, ax2, pm, cb, gl, fig" ] } ], "metadata": { "kernelspec": { "display_name": "cmip7validate-env", "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.13.3" } }, "nbformat": 4, "nbformat_minor": 5 }