Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix convert_units() not keeping attrs #916

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import os
import numpy
from e3sm_diags.parameter.core_parameter import CoreParameter
from e3sm_diags.parameter.lat_lon_land_parameter import LatLonLandParameter


from e3sm_diags.run import runner

short_name = "v3.LR.historical_0051"

param = CoreParameter()

# Model
param.test_name = "v3.LR.historical_0051"


# Ref

# Output dir
param.results_dir = "/lcrc/group/e3sm/public_html/ac.tvo/zppy_weekly_comprehensive_v3_output/test_zppy_pr651_20250115/v3.LR.historical_0051/post/"

# Additional settings
param.run_type = "model_vs_model"
param.diff_title = "Difference"
param.multiprocessing = True
param.num_workers = 8
param.seasons = ["ANN"]
# param.fail_on_incomplete = True
params = [param]

# Model land
land_param = LatLonLandParameter()
land_param.test_data_path = "/lcrc/group/e3sm/ac.zhang40/zppy_weekly_comprehensive_v3_output/test_zppy_pr651_20250115/v3.LR.historical_0051/post/lnd/180x360_aave/clim/2yr"

# Reference
land_param.reference_data_path = "/lcrc/group/e3sm/ac.zhang40/zppy_weekly_comprehensive_v3_output/test_zppy_pr651_20250115/v3.LR.historical_0051/post/lnd/180x360_aave/clim/2yr"
land_param.ref_name = "v3.LR.historical_0051"
land_param.short_ref_name = "same simulation"
# Optionally, swap test and reference model
if False:
land_param.test_data_path, param.reference_data_path = (
param.reference_data_path,
param.test_data_path,
)
land_param.test_name, param.ref_name = param.ref_name, param.test_name
land_param.short_test_name, param.short_ref_name = (
param.short_ref_name,
param.short_test_name,
)
params.append(land_param)
# Run
runner.sets_to_run = ["lat_lon_land"]
runner.run_diags(params)
167 changes: 102 additions & 65 deletions e3sm_diags/derivations/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,71 +24,108 @@ def aplusb(var1: xr.DataArray, var2: xr.DataArray, target_units=None):
return var1 + var2


def convert_units(var: xr.DataArray, target_units: str): # noqa: C901
if var.attrs.get("units") is None:
if var.name == "SST":
var.attrs["units"] = target_units
elif var.name == "ICEFRAC":
var.attrs["units"] = target_units
var = 100.0 * var
elif var.name == "AODVIS":
var.attrs["units"] = target_units
elif var.name == "AODDUST":
var.attrs["units"] = target_units
elif var.name == "FAREA_BURNED":
var = var * 1e9
var.attrs["units"] = target_units
elif var.attrs["units"] == "gC/m^2":
var = var / 1000.0
var.attrs["units"] = target_units
elif var.name == "FLOODPLAIN_VOLUME" and target_units == "km3":
var = var / 1.0e9
var.attrs["units"] = target_units
elif var.name == "AOD_550_ann":
var.attrs["units"] = target_units
elif var.name == "AOD_550":
var.attrs["units"] = target_units
elif var.attrs["units"] == "C" and target_units == "DegC":
var.attrs["units"] = target_units
elif var.attrs["units"] == "N/m2" and target_units == "N/m^2":
var.attrs["units"] = target_units
elif var.name == "AODVIS" or var.name == "AOD_550_ann" or var.name == "TOTEXTTAU":
var.attrs["units"] = target_units
elif var.attrs["units"] == "fraction":
var = 100.0 * var
var.attrs["units"] = target_units
elif var.attrs["units"] == "mb":
var.attrs["units"] = target_units
elif var.attrs["units"] == "gpm": # geopotential meter
var = var / 9.8 / 100 # convert to hecto meter
var.attrs["units"] = target_units
elif var.attrs["units"] == "Pa/s":
var = var / 100.0 * 24 * 3600
var.attrs["units"] = target_units
elif var.attrs["units"] == "mb/day":
var = var
var.attrs["units"] = target_units
elif var.name == "prw" and var.attrs["units"] == "cm":
var = var * 10.0 # convert from 'cm' to 'kg/m2' or 'mm'
var.attrs["units"] = target_units
elif var.attrs["units"] in ["gC/m^2/s"] and target_units == "g*/m^2/day":
var = var * 24 * 3600
var.attrs["units"] = var.attrs["units"][0:7] + "day"
elif (
var.attrs["units"] in ["gN/m^2/s", "gP/m^2/s"] and target_units == "mg*/m^2/day"
):
var = var * 24 * 3600 * 1000.0
var.attrs["units"] = "m" + var.attrs["units"][0:7] + "day"
elif var.attrs["units"] in ["gN/m^2/day", "gP/m^2/day", "gC/m^2/day"]:
pass
else:
original_udunit = cf_units.Unit(var.attrs["units"])
target_udunit = cf_units.Unit(target_units)

var.values = original_udunit.convert(var.values, target_udunit)
var.attrs["units"] = target_units

return var
def convert_units(var: xr.DataArray, target_units: str) -> xr.DataArray: # noqa: C901
"""Convert the units of a variable to the target units.

Parameters
----------
var : xr.DataArray
The input data array with units to be converted.
target_units : str
The target units to convert the data array to.

Returns
-------
xr.DataArray
A new data array with the units converted to the target units.

Notes
-----
The function handles various specific non-CF compliant unit conversions
based on the variable name and current units. Otherwise it will use the
``cf_units`` library to attempt to perform the conversion if the units are
recognized by UDUNITS-2 (must be CF-compliant).
"""
var_new = var.copy()

with xr.set_options(keep_attrs=True):
if var_new.attrs.get("units") is None:
if var_new.name == "SST":
var_new.attrs["units"] = target_units
elif var_new.name == "ICEFRAC":
var_new.attrs["units"] = target_units
var_new = 100.0 * var_new
elif var_new.name == "AODVIS":
var_new.attrs["units"] = target_units
elif var_new.name == "AODDUST":
var_new.attrs["units"] = target_units
elif var_new.name == "FAREA_BURNED":
var_new = var_new * 1e9
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "gC/m^2":
var_new = var_new / 1000.0
var_new.attrs["units"] = target_units
elif var_new.name == "FLOODPLAIN_VOLUME" and target_units == "km3":
var_new = var_new / 1.0e9
var_new.attrs["units"] = target_units
elif var_new.name == "AOD_550_ann":
var_new.attrs["units"] = target_units
elif var_new.name == "AOD_550":
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "C" and target_units == "DegC":
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "N/m2" and target_units == "N/m^2":
var_new.attrs["units"] = target_units
elif (
var_new.name == "AODVIS"
or var_new.name == "AOD_550_ann"
or var_new.name == "TOTEXTTAU"
):
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "fraction":
var_new = 100.0 * var_new
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "mb":
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "gpm": # geopotential meter
var_new = var_new / 9.8 / 100 # convert to hecto meter
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "Pa/s":
var_new = var_new / 100.0 * 24 * 3600
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "mb/day":
var_new.attrs["units"] = target_units
elif var_new.name == "prw" and var_new.attrs["units"] == "cm":
var_new = var_new * 10.0 # convert from 'cm' to 'kg/m2' or 'mm'
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] in ["gC/m^2/s"] and target_units == "g*/m^2/day":
var_new = var_new * 24 * 3600
var_new.attrs["units"] = var_new.attrs["units"][0:7] + "day"
elif (
var_new.attrs["units"] in ["gN/m^2/s", "gP/m^2/s"]
and target_units == "mg*/m^2/day"
):
var_new = var_new * 24 * 3600 * 1000.0
var_new.attrs["units"] = "m" + var_new.attrs["units"][0:7] + "day"
elif var_new.attrs["units"] in ["gN/m^2/day", "gP/m^2/day", "gC/m^2/day"]:
pass
elif var_new.attrs["units"] == "gC/m^2" and target_units == "kgC/m^2":
var_new = var_new / 1000.0
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "gC/m^2/s" and target_units == "kgC/m^2":
var_new = var_new / 1000.0
var_new.attrs["units"] = target_units
elif var_new.attrs["units"] == "gC/m^2/s" and target_units == "kgC/m^2/s":
var_new = var_new / 1000.0
var_new.attrs["units"] = target_units
else:
original_udunit = cf_units.Unit(var_new.attrs["units"])
target_udunit = cf_units.Unit(target_units)

var_new.values = original_udunit.convert(var_new.values, target_udunit)
var_new.attrs["units"] = target_units

return var_new


def _apply_land_sea_mask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,6 @@ regions = ["global"]
test_colormap = "WhiteBlueGreenYellowRed.rgb"
reference_colormap = "WhiteBlueGreenYellowRed.rgb"
diff_colormap = "BrBG"
contour_levels = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
[#]
sets = ["lat_lon_land"]
case_id = "model_vs_model"
Expand All @@ -450,7 +449,6 @@ regions = ["global"]
test_colormap = "WhiteBlueGreenYellowRed.rgb"
reference_colormap = "WhiteBlueGreenYellowRed.rgb"
diff_colormap = "BrBG"
contour_levels = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
[#]
sets = ["lat_lon_land"]
case_id = "model_vs_model"
Expand All @@ -460,7 +458,6 @@ regions = ["global"]
test_colormap = "WhiteBlueGreenYellowRed.rgb"
reference_colormap = "WhiteBlueGreenYellowRed.rgb"
diff_colormap = "BrBG"
contour_levels = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
[#]
sets = ["lat_lon_land"]
case_id = "model_vs_model"
Expand Down
Loading