E3SM-Project / e3sm_diags

E3SM Diagnostics package
https://e3sm-project.github.io/e3sm_diags
BSD 3-Clause "New" or "Revised" License
42 stars 32 forks source link

[Bug]: CDAT Migration error: RuntimeError: Could not determine `Z` bounds in dataset. #863

Closed chengzhuzhang closed 1 month ago

chengzhuzhang commented 1 month ago

What happened?

I'm testing a run script for EAMXX decadal run: Compare to the run with main branch (viewer), the CDAT migration branch (viewer) failed to generate sets that require vertical remapping, with following error:

2024-10-03 13:50:25,512 [INFO]: meridional_mean_2d_driver.py(run_diag:60) >> Variable: U
2024-10-03 13:50:26,555 [ERROR]: core_parameter.py(_run_diag:343) >> Error in e3sm_diags.driver.meridional_mean_2d_driver
Traceback (most recent call last):
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/xcdat/regridder/xgcm.py", line 233, in _get_grid_positions
    bounds_z = self._input_grid.bounds.get_bounds("Z")
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/xcdat/bounds.py", line 247, in get_bounds
    raise KeyError(
KeyError: "No bounds data variables were found for the 'Z' axis. Make sure the dataset has bound data vars and their names match the 'bounds' attributes found on their related time coordinate variables. Alternatively, you can add bounds with `ds.bounds.add_missing_bounds()` or `ds.bounds.add_bounds()`."

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/e3sm_diags/parameter/core_parameter.py", line 340, in _run_diag
    single_result = module.run_diag(self)
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/e3sm_diags/driver/meridional_mean_2d_driver.py", line 87, in run_diag
    _run_diags_3d(parameter, ds_test, ds_ref, season, var_key, ref_name)
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/e3sm_diags/driver/meridional_mean_2d_driver.py", line 102, in _run_diags_3d
    ds_t_plevs = regrid_z_axis_to_plevs(ds_test, var_key, plevs)
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/e3sm_diags/driver/utils/regrid.py", line 526, in regrid_z_axis_to_plevs
    ds_plevs = _hybrid_to_plevs(ds, var_key, plevs)
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/e3sm_diags/driver/utils/regrid.py", line 586, in _hybrid_to_plevs
    result = ds.regridder.vertical(
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/xcdat/regridder/accessor.py", line 400, in vertical
    output_ds = regridder.vertical(data_var, self._ds)
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/xcdat/regridder/xgcm.py", line 155, in vertical
    grid_coords = self._get_grid_positions()
  File "/global/cfs/cdirs/e3sm/zhang40/conda_envs/e3sm_diags_dev_654_zonal_mean_xy/lib/python3.10/site-packages/xcdat/regridder/xgcm.py", line 235, in _get_grid_positions
    raise RuntimeError("Could not determine `Z` bounds in dataset.")
RuntimeError: Could not determine `Z` bounds in dataset.

What did you expect to happen? Are there are possible answers you came across?

No response

Minimal Complete Verifiable Example (MVCE)

Command line:
python run_script.py -d U.cfg

# run_script.py

import os
from e3sm_diags.parameter.core_parameter import CoreParameter
from e3sm_diags.run import runner

param = CoreParameter()

#param.reference_data_path = '/global/cfs/cdirs/e3sm/diagnostics/observations/Atm/climatology'
#param.test_data_path = '/global/cfs/cdirs/e3sm/zhang40/e3sm_diags_for_EAMxx/data/Cess'
param.reference_data_path = '/global/cfs/cdirs/e3sm/diagnostics/observations/Atm/climatology'
param.test_data_path = '/global/cfs/cdirs/e3sm/chengzhu/eamxx/post/data/rgr'
param.test_name = 'eamxx_decadal'
param.seasons = ["ANN"]
#param.save_netcdf = True

prefix = '/global/cfs/cdirs/e3sm/www/zhang40/tests/eamxx'
param.results_dir = os.path.join(prefix, 'eamxx_decadal_edv3')

runner.sets_to_run = ["zonal_mean_2d"]

runner.run_diags([param])

configuration file, U.cfg:

[#]
sets = ["zonal_mean_2d"]
case_id = "MERRA2"
variables = ["U"]
ref_name = "MERRA2"
reference_name = "MERRA2 Reanalysis"
seasons = ["ANN"]
test_colormap = "PiYG_r"
reference_colormap = "PiYG_r"
contour_levels = [-40,-30,-25,-20,-15,-10,-5,-2.5,2.5,5,10,15,20,25,30,40]
diff_levels = [-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7]


### Relevant log output

_No response_

### Anything else we need to know?

_No response_

### Environment

latest cdat-migration branch
tomvothecoder commented 1 month ago

Related input file: '/global/cfs/cdirs/e3sm/chengzhu/eamxx/post/data/rgr/eamxx_decadal_ANN_199601_199612_climo.nc'

A few things I found:

  1. The input file is missing Z bounds.
    • I think the CDAT codebase automatically generates bounds.
    • Solution: Update _open_climo_dataset() to add bounds for "Z" axis (lev)
  2. The input file is missing CF attributes for the Z axis (lev).
    • xCDAT can't map to Z axis bounds ("lev_bnds") for "lev" because "lev" does not have the required CF attributes.
    • Opened an issue on xCDAT repo: https://github.com/xCDAT/xcdat/issues/707
    • I think CDAT can map to lev without CF attributes.

We can either 1) wait for xCDAT to have a new release with PR 708 or 2) add temporary code in e3sm_diags to make sure the input dataset object's Z axis has CF attributes to retrieve bounds.

tomvothecoder commented 1 month ago

Closed by #865