Overview: x4c as a CESM Diagnostic System

Overview: x4c as a CESM Diagnostic System#

x4c provides a high-level diagnositc system for CESM output analysis and visualization. In this tutorial, we show some simple examples to give a quick glance of the major features, including:

  • The Timeseries case system

  • The spell magics

  • Adding new diagnostic variables

More detailed explainations of each feature can be found in later sections.

Example Datasets: Zhu, F. & Zhu, J. Long simulations of the Miocene Climatic Optimum, DOI: 10.5065/3QFN-GN70 (2025). https://rda.ucar.edu/datasets/d010026/.

[1]:
%load_ext autoreload
%autoreload 2

import os
import x4c
import datetime

os.chdir('/glade/u/home/fengzhu/Github/x4c/docsrc/notebooks')
print(x4c.__version__)
print(f'Last Update: {datetime.date.today()}')
2026.3.9
Last Update: 2026-03-09
[ ]:
dirpath = './b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO2.005'
case = x4c.Timeseries(dirpath, grid_dict={'atm': 'ne16np4'}, cesm_ver=1)
>>> case.root_dir: /glade/u/home/fengzhu/Github/x4c/docsrc/notebooks/b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO2.005
>>> case.path_pattern: comp/proc/tseries/*/casename.hstr.vn.timespan.nc
>>> case.grid_dict: {'atm': 'ne16np4', 'ocn': 'g16', 'lnd': 'ne16np4', 'rof': 'ne16np4', 'ice': 'g16'}
>>> case.casename: b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO2.005
>>> case.paths["atm"]["cam.h0"] created
>>> case.paths["ocn"]["pop.h"] created
>>> case.paths["lnd"]["clm2.h0"] created
>>> case.paths["rof"]["rtm.h0"] created
>>> case.paths["ice"]["cice.h"] created
>>> case.vns["atm"]["cam.h0"] created
>>> case.vns["ocn"]["pop.h"] created
>>> case.vns["lnd"]["clm2.h0"] created
>>> case.vns["rof"]["rtm.h0"] created
>>> case.vns["ice"]["cice.h"] created

Now let’s load the surface temperature (TS).

[3]:
case.load('TS')
case.ds['TS']
>>> case.ds["TS"] created
[3]:
<xarray.Dataset> Size: 34MB
Dimensions:       (lev: 30, ilev: 31, ncol: 13826, time: 600, nbnd: 2)
Coordinates:
  * lev           (lev) float64 240B 3.643 7.595 14.36 ... 957.5 976.3 992.6
  * ilev          (ilev) float64 248B 2.255 5.032 10.16 ... 967.5 985.1 1e+03
  * time          (time) object 5kB 8951-02-01 00:00:00 ... 9001-01-01 00:00:00
Dimensions without coordinates: ncol, nbnd
Data variables: (12/31)
    hyam          (lev) float64 240B ...
    hybm          (lev) float64 240B ...
    P0            float64 8B ...
    hyai          (ilev) float64 248B ...
    hybi          (ilev) float64 248B ...
    lat           (ncol) float64 111kB ...
    ...            ...
    n2ovmr        (time) float64 5kB ...
    f11vmr        (time) float64 5kB ...
    f12vmr        (time) float64 5kB ...
    sol_tsi       (time) float64 5kB ...
    nsteph        (time) int32 2kB ...
    TS            (time, ncol) float32 33MB ...
Attributes: (12/20)
    np:               4
    ne:               16
    Conventions:      CF-1.0
    source:           CAM
    case:             b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO...
    title:            UNSET
    ...               ...
    comp:             atm
    hstr:             cam.h0
    grid:             ne16np4
    gw:               <xarray.DataArray 'area' (ncol: 13826)> Size: 111kB\n[1...
    lat:              <xarray.DataArray 'lat' (ncol: 13826)> Size: 111kB\n[13...
    lon:              <xarray.DataArray 'lon' (ncol: 13826)> Size: 111kB\n[13...

Note that the same variable name could exist for multiple history strings (h-strings). In which case we should specify the component and h-string:

[4]:
case.load('TS', comp='atm', hstr='cam.h0a')
case.ds['TS']
>>> case.ds["TS"] already loaded; to reload, run case.load("TS", ..., reload=True).
[4]:
<xarray.Dataset> Size: 34MB
Dimensions:       (lev: 30, ilev: 31, ncol: 13826, time: 600, nbnd: 2)
Coordinates:
  * lev           (lev) float64 240B 3.643 7.595 14.36 ... 957.5 976.3 992.6
  * ilev          (ilev) float64 248B 2.255 5.032 10.16 ... 967.5 985.1 1e+03
  * time          (time) object 5kB 8951-02-01 00:00:00 ... 9001-01-01 00:00:00
Dimensions without coordinates: ncol, nbnd
Data variables: (12/31)
    hyam          (lev) float64 240B ...
    hybm          (lev) float64 240B ...
    P0            float64 8B ...
    hyai          (ilev) float64 248B ...
    hybi          (ilev) float64 248B ...
    lat           (ncol) float64 111kB ...
    ...            ...
    n2ovmr        (time) float64 5kB ...
    f11vmr        (time) float64 5kB ...
    f12vmr        (time) float64 5kB ...
    sol_tsi       (time) float64 5kB ...
    nsteph        (time) int32 2kB ...
    TS            (time, ncol) float32 33MB ...
Attributes: (12/20)
    np:               4
    ne:               16
    Conventions:      CF-1.0
    source:           CAM
    case:             b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO...
    title:            UNSET
    ...               ...
    comp:             atm
    hstr:             cam.h0
    grid:             ne16np4
    gw:               <xarray.DataArray 'area' (ncol: 13826)> Size: 111kB\n[1...
    lat:              <xarray.DataArray 'lat' (ncol: 13826)> Size: 111kB\n[13...
    lon:              <xarray.DataArray 'lon' (ncol: 13826)> Size: 111kB\n[13...

All derived variables should follow the same idea of specifying component and h-strings if the underlying variables exist for multiple h-strings:

[5]:
case.load('LST', comp='atm', hstr='cam.h0a')
case.ds['LST']
>>> LST is a supported derived variable.
>>> case.ds["TS"] already loaded; to reload, run case.load("TS", ..., reload=True).
>>> case.ds["LANDFRAC"] created
>>> case.ds["LST"] created
[5]:
<xarray.DataArray 'LST' (time: 600, ncol: 13826)> Size: 33MB
array([[nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       ...,
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan],
       [nan, nan, nan, ..., nan, nan, nan]],
      shape=(600, 13826), dtype=float32)
Coordinates:
  * time     (time) object 5kB 8951-02-01 00:00:00 ... 9001-01-01 00:00:00
    lat      (ncol) float64 111kB -35.26 -35.98 -37.07 ... 37.91 37.91 36.74
    lon      (ncol) float64 111kB 315.0 316.6 319.1 320.6 ... 132.5 137.5 135.0
Dimensions without coordinates: ncol
Attributes:
    units:         K
    long_name:     Land Surface Temperature
    cell_methods:  time: mean
    path:          /glade/u/home/fengzhu/Github/x4c/docsrc/notebooks/b.e13.B1...
    gw:            <xarray.DataArray 'area' (ncol: 13826)> Size: 111kB\narray...
    lat:           <xarray.DataArray 'lat' (ncol: 13826)> Size: 111kB\n[13826...
    lon:           <xarray.DataArray 'lon' (ncol: 13826)> Size: 111kB\n[13826...
    comp:          atm
    grid:          ne16np4
    vn:            LST
[ ]: