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 systemThe
spell
magicsAdding 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
os.chdir('/glade/u/home/fengzhu/Github/x4c/docsrc/notebooks')
import x4c
print(x4c.__version__)
2025.6.22
[2]:
# dirpath = '/glade/campaign/cesm/community/palwg/MCO_LongSims/b.e13.B1850C5.ne16_g16.icesm131_d18O_fixer.Miocene.3xCO2.005'
# case = x4c.Timeseries(dirpath, grid_dict={'atm': 'ne16np4'})
dirpath = '/glade/campaign/cesm/development/cross-wg/diagnostic_framework/x4c/timeseries/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1_32'
case = x4c.Timeseries(
dirpath,
casename='b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1',
grid_dict={'atm': 'ne30gp3'},
)
>>> case.root_dir: /glade/campaign/cesm/development/cross-wg/diagnostic_framework/x4c/timeseries/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1_32
>>> case.path_pattern: comp/proc/tseries/*/casename.hstr.vn.timespan.nc
>>> case.grid_dict: {'atm': 'ne30gp3', 'ocn': 'g16', 'lnd': 'ne30gp3', 'rof': 'ne30gp3', 'ice': 'g16'}
>>> case.casename: b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1
>>> case.paths["atm"]["cam.h0a"] created
>>> case.paths["atm"][".e30_beta06.B1850C_"] created
>>> case.paths["atm"]["cam.h2a"] created
>>> case.paths["atm"]["cam.h1a"] created
>>> case.paths["ocn"]["mom6.h.sfc"] created
>>> case.paths["ocn"]["mom6.h.z"] created
>>> case.paths["ocn"][".e30_beta06.B1850C_L"] created
>>> case.paths["ocn"]["mom6"] created
>>> case.paths["ocn"]["mom6.h.rho2"] created
>>> case.paths["ocn"][""] created
>>> case.paths["ocn"]["mom6.h.native"] created
>>> case.paths["lnd"]["clm2.h0"] created
>>> case.paths["rof"]["mosart.h0"] created
>>> case.paths["ice"]["cice.h"] created
>>> case.paths["ice"]["cice.h1"] created
>>> case.vns["atm"]["cam.h0a"] created
>>> case.vns["atm"][".e30_beta06.B1850C_"] created
>>> case.vns["atm"]["cam.h2a"] created
>>> case.vns["atm"]["cam.h1a"] created
>>> case.vns["ocn"]["mom6.h.sfc"] created
>>> case.vns["ocn"]["mom6.h.z"] created
>>> case.vns["ocn"][".e30_beta06.B1850C_L"] created
>>> case.vns["ocn"]["mom6"] created
>>> case.vns["ocn"]["mom6.h.rho2"] created
>>> case.vns["ocn"][""] created
>>> case.vns["ocn"]["mom6.h.native"] created
>>> case.vns["lnd"]["clm2.h0"] created
>>> case.vns["rof"]["mosart.h0"] created
>>> case.vns["ice"]["cice.h"] created
>>> case.vns["ice"]["cice.h1"] created
[3]:
case.vns['ice']['cice.h1']
[3]:
['hpondn_d',
'hi_d',
'apeff_ai_d',
'meltsliq_d',
'daidtt_d',
'meltt_d',
'fswabs_d',
'meltb_d',
'aice_d',
'rdpnd_d',
'mipnd_d',
'fresh_d',
'hpond_ai_d',
'frazil_d',
'ilpndn_d',
'snowfracn_d',
'expnd_d',
'apondn_d',
'meltl_d',
'melts_d',
'flpnd_d',
'rfpndn_d',
'fswthru_d',
'vsnon_d',
'ilpnd_d',
'aicen_d',
'fswup_d',
'hs_d',
'apeffn_d',
'vicen_d',
'dvidtt_d',
'snoice_d',
'frpndn_d',
'flpndn_d',
'apeff_d',
'rfpnd_d',
'apond_ai_d',
'fswdn_d',
'fsalt_ai_d',
'rhos_cmp_d',
'rhos_cnt_d',
'daidtd_d',
'smassice_d',
'congel_d',
'hpond_d',
'frpnd_d',
'fsloss_d',
'rsnw_d',
'fresh_ai_d',
'expndn_d',
'dvidtd_d',
'apond_d',
'fsalt_d',
'rsnwn_d',
'smassliq_d']
[5]:
case.load('aice_d')
case.ds['aice_d']['time_bounds']
>>> case.ds["aice_d"] already loaded; to reload, run case.load("aice_d", ..., reload=True).
[5]:
<xarray.DataArray 'time_bounds' (time: 3650, nbnd: 2)> Size: 58kB [7300 values with dtype=object] Coordinates: * time (time) object 29kB 0001-01-01 12:00:00 ... 0010-12-31 12:00:00 Dimensions without coordinates: nbnd
[7]:
case.load('TS', comp='atm', hstr='cam.h0a')
case.ds['TS']['time_bounds']
>>> case.ds["TS"] created
[7]:
<xarray.DataArray 'time_bounds' (time: 120, nbnd: 2)> Size: 2kB [240 values with dtype=object] Coordinates: * time (time) object 960B 0001-01-16 12:00:00 ... 0010-12-16 12:00:00 Dimensions without coordinates: nbnd Attributes: long_name: time interval endpoints
[68]:
case.paths['atm']['cam.h0a']['CH4']
[68]:
['/glade/campaign/cesm/development/cross-wg/diagnostic_framework/x4c/timeseries/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1_32/atm/proc/tseries/cam.h0a/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1.cam.h0a.CH4.000101-001012.nc']
[69]:
case.get_comp_hstr('U')
[69]:
[('atm', 'cam.h0a')]
[70]:
case.vns['atm']['cam.new'] = ['U']
[71]:
case.get_comp_hstr('U')
[71]:
[('atm', 'cam.h0a'), ('atm', 'cam.new')]
[72]:
case.get_comp_hstr('V')
[72]:
[('atm', 'cam.h0a')]
[73]:
case.paths['atm']['cam.h0a']['U']
[73]:
['/glade/campaign/cesm/development/cross-wg/diagnostic_framework/x4c/timeseries/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1_32/atm/proc/tseries/cam.h0a/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1.cam.h0a.U.000101-001012.nc']
[74]:
case.get_paths('atm', 'cam.h0a', 'U')
[74]:
['/glade/campaign/cesm/development/cross-wg/diagnostic_framework/x4c/timeseries/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1_32/atm/proc/tseries/cam.h0a/b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1.cam.h0a.U.000101-001012.nc']
[112]:
case.load('TS', reload=True)
case.ds['TS']
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[112], line 1
----> 1 case.load('TS', reload=True)
2 case.ds['TS']
File <string>:16, in load(self, vn, comp, hstr, timespan, load_idx, verbose, reload, **kws)
ValueError: The input variable name belongs to multiple (comp, hstr) pairs: [('atm', 'cam.h0a'), ('atm', 'cam.h1a')]. Please specify via the argument `comp` and `hstr`.
[121]:
case.load('TS', comp='atm', hstr='cam.h0a', reload=True)
case.ds['TS']
>>> case.ds["TS"] created
[121]:
<xarray.Dataset> Size: 25MB Dimensions: (time: 120, ncol: 48600, ilev: 59, lev: 58, nbnd: 2, trop_cld_lev: 58, trop_pref: 58, trop_prefi: 59) Coordinates: * ilev (ilev) float64 472B 2.055 3.98 6.909 ... 987.4 995.1 1e+03 * lev (lev) float64 464B 3.018 5.445 9.087 ... 983.2 991.2 997.5 * time (time) object 960B 0001-01-16 12:00:00 ... 0010-12-16 12:00:00 * trop_cld_lev (trop_cld_lev) float64 464B 3.018 5.445 9.087 ... 991.2 997.5 * trop_pref (trop_pref) float64 464B 3.018 5.445 9.087 ... 991.2 997.5 * trop_prefi (trop_prefi) float64 472B 2.055 3.98 6.909 ... 995.1 1e+03 Dimensions without coordinates: ncol, nbnd Data variables: (12/19) TS (time, ncol) float32 23MB ... area (ncol) float64 389kB ... areawt (ncol) float64 389kB ... date (time) int32 480B ... date_written (time) |S8 960B ... datesec (time) int32 480B ... ... ... nbdate int32 4B ... nbsec int32 4B ... ndbase int32 4B ... nsbase int32 4B ... time_bounds (time, nbnd) object 2kB ... time_written (time) |S8 960B ... Attributes: (12/19) ne: 30 fv_nphys: 3 Conventions: CF-1.0 source: CAM case: b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.192.wrkflw.1 logname: cmip7 ... ... comp: atm hstr: cam.h0a grid: ne30gp3 gw: <xarray.DataArray 'area' (ncol: 48600)> Size: 389kB\n[... lat: <xarray.DataArray 'lat' (ncol: 48600)> Size: 389kB\n[4... lon: <xarray.DataArray 'lon' (ncol: 48600)> Size: 389kB\n[4...
[ ]:
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"] already loaded; to reload, run case.load("LANDFRAC", ..., reload=True).
>>> case.ds["LST"] created
<xarray.DataArray 'LST' (time: 120, ncol: 48600)> Size: 23MB array([[ nan, nan, nan, ..., 281.56094, nan, nan], [ nan, nan, nan, ..., 281.35333, nan, nan], [ nan, nan, nan, ..., 282.2262 , nan, nan], ..., [ nan, nan, nan, ..., 295.93307, nan, nan], [ nan, nan, nan, ..., 289.19916, nan, nan], [ nan, nan, nan, ..., 283.95468, nan, nan]], shape=(120, 48600), dtype=float32) Coordinates: * time (time) object 960B 0001-01-16 12:00:00 ... 0010-12-16 12:00:00 lat (ncol) float64 389kB -35.03 -35.48 -35.92 ... 36.66 36.2 35.74 lon (ncol) float64 389kB 315.5 316.5 317.5 315.5 ... 137.0 136.0 135.0 Dimensions without coordinates: ncol Attributes: units: K long_name: Land Surface Temperature cell_methods: time: mean path: /glade/campaign/cesm/development/cross-wg/diagnostic_frame... gw: <xarray.DataArray 'area' (ncol: 48600)> Size: 389kB\narray... lat: <xarray.DataArray 'lat' (ncol: 48600)> Size: 389kB\n[48600... lon: <xarray.DataArray 'lon' (ncol: 48600)> Size: 389kB\n[48600... comp: atm grid: ne30gp3 vn: LST
[ ]: