E3SM-Project / e3sm_diags

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

`e3sm_diags.drivers.utils.climo` is not designed for `"SEASONALCYCLE"` or `"ANNUALCYCLE"` #689

Closed tomvothecoder closed 1 year ago

tomvothecoder commented 1 year ago

Just keeping this issue on record in case it ever pops up (I don't think it has or will). This climo function is being refactored anyways.

Overview

In PR #677, I am refactoring the climo() function to go from operating on cdms2.TransientVariable to xr.DataArray

I noticed that freq="SEASONALCYCLE" and freq="ANNUALCYCLE" breaks this function. However, it works if freq="ANN" or if freq is an individual month or season.

Example Script

import cdms2
from e3sm_diags.driver.utils.climo import climo

ocean_frac_path = "/p/user_pub/e3sm/e3sm_diags_data/test_model_data_for_acme_diags/time-series/E3SM_v1/OCNFRAC_185001_201312.nc"
var = "OCNFRAC"
end_time = "2013-12-01"

ds1 = cdms2.open(ocean_frac_path)
o_frac1 = ds1(var, time=("1850-01-01", end_time))(squeeze=1)
diags_climo = climo(o_frac1, "SEASONALCYCLE")

Log output

File [~/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py:85](https://vscode-remote+ssh-002dremote-002bacme1.vscode-resource.vscode-cdn.net/home/vo13/E3SM-Project/e3sm_diags/~/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py:85), in climo(var, season)
     [83](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=82) # Set the correct axis as well.
     [84](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=83) if var.getLongitude() and var.getLatitude():
---> [85](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=84)     trans_var.setAxis(0, var.getAxis(1))
     [86](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=85)     trans_var.setAxis(1, var.getAxis(2))
     [87](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=86)     if var.getLevel():
     [88](file:///home/vo13/E3SM-Project/e3sm_diags/e3sm_diags/driver/utils/climo.py?line=87)         # If it's a 3D variable, set the last axis.

File [~/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py:517](https://vscode-remote+ssh-002dremote-002bacme1.vscode-resource.vscode-cdn.net/home/vo13/E3SM-Project/e3sm_diags/~/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py:517), in TransientVariable.setAxis(self, n, axis, savegrid)
    [515](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=514) axislen = self.shape[n]
    [516](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=515) if len(axis) != axislen:
--> [517](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=516)     raise CDMSError(
    [518](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=517)         "axis length %d does not match corresponding dimension %d" %
    [519](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=518)         (len(axis), axislen))
    [520](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=519) if not isinstance(axis, AbstractAxis):
    [521](file:///home/vo13/miniconda3/envs/e3sm_diags_dev_658/lib/python3.10/site-packages/cdms2/tvariable.py?line=520)     raise CDMSError("copydimension, other not a slab.")

CDMSError: axis length 129 does not match corresponding dimension 4

Additional Context

Relevant lines of code in climo(), which only considers a singleton time coordinate that gets squeezed. Also the code statically references the climatology variable's axes positions 0 and 1 as lon and lat, which means time never exists (since it is squeezed). https://github.com/E3SM-Project/e3sm_diags/blob/48380d03f843a2996031b726e9d046cc9b20dbb4/e3sm_diags/driver/utils/climo.py#L80-L89

Solution Options

  1. Remove logic for ANNUALCYCLE and SEASONALCYCLE if these frequencies are never used -- I am already doing this in my refactored version in PR #677
  2. Add logic that considers these frequencies (but doesn't make sense if they are not used)
tomvothecoder commented 1 year ago

Just keeping this possible issue on record.