From 5c9bf4b368ae9aab7eb05b1df996bfcb2a73508b Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Thu, 9 Feb 2023 13:08:19 -0500 Subject: [PATCH 1/3] Rework logic in compare_varnames gcpy.util.py - In function compare_varnames - Add variable names to commonvarsData if they have lon/Xdim or lat/Ydim coordinates. Plottable data variables need at least these dimensions. - commonvarsOther are variables that are not in commonvarsData - commonvars2D and commonvars3D are plottable data variables that either do not have lev/ilev dimensions, or do have them. This fixes an issue where 2D plottable data variables were getting lumped together with the index variables. Signed-off-by: Bob Yantosca --- gcpy/util.py | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/gcpy/util.py b/gcpy/util.py index e6a85033..4b765496 100644 --- a/gcpy/util.py +++ b/gcpy/util.py @@ -843,7 +843,8 @@ def compare_varnames( refdata and devdata, and that have lat, lon, and level dimensions. commonvarsData List of all commmon 2D or 3D data variables, - excluding index variables. + excluding index variables. This is the + list of "plottable" variables. refonly List of 2D or 3D variables that are only present in refdata. devonly List of 2D or 3D variables that are only @@ -855,37 +856,29 @@ def compare_varnames( refonly = [v for v in refvars if v not in devvars] devonly = [v for v in devvars if v not in refvars] dimmismatch = [v for v in commonvars if refdata[v].ndim != devdata[v].ndim] - commonvarsOther = [ + # Assume plottable data has lon and lat + # This is OK for purposes of benchmarking + # -- Bob Yantosca (09 Feb 2023) + commonvarsData = [ v for v in commonvars if ( - ( - ("lat" not in refdata[v].dims or "Xdim" not in refdata[v].dims) - and - ("lon" not in refdata[v].dims or "Ydim" not in refdata[v].dims) + ("lat" in refdata[v].dims or "Ydim" in refdata[v].dims) and - ("lev" not in refdata[v].dims) - ) - or - ( - ("hyam" in v or "hybm" in v) # Omit these from plottable data - ) + ("lon" in refdata[v].dims or "Xdim" in refdata[v].dims) ) + ] + commonvarsOther = [ + v for v in commonvars if ( + v not in commonvarsData + ) ] commonvars2D = [ v for v in commonvars if ( - ("lat" in refdata[v].dims or "Xdim" in refdata[v].dims) - and - ("lon" in refdata[v].dims or "Ydim" in refdata[v].dims) - and - ("lev" not in refdata[v].dims) + (v in commonvarsData) and ("lev" not in refdata[v].dims) ) ] commonvars3D = [ v for v in commonvars if ( - ("lat" in refdata[v].dims or "Xdim" in refdata[v].dims) - and - ("lon" in refdata[v].dims or "Ydim" in refdata[v].dims) - and - ("lev" in refdata[v].dims) + (v in commonvarsData) and ("lev" in refdata[v].dims) ) ] From 5a34ff6aa46b426daad42c7c971558ddd21b01bf Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Thu, 9 Feb 2023 13:55:46 -0500 Subject: [PATCH 2/3] Fixed incorrect logic in util.array_equals; updates in benchmark.py gcpy/util.py - In routine array_equals: - Add dtype parameter to select numeric type for the comparison - Return the inverse of ABS(devsum-refsum) > 0, since this is the condition for not equals. gcpy/benchmark.py - Skip reading "AREA" when computing the summary table - Pass dtype=np.float32 to util.array_equals Signed-off-by: Bob Yantosca --- gcpy/benchmark.py | 12 ++++++++---- gcpy/util.py | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/gcpy/benchmark.py b/gcpy/benchmark.py index c92bc03b..fc5c07c9 100644 --- a/gcpy/benchmark.py +++ b/gcpy/benchmark.py @@ -4513,8 +4513,7 @@ def create_benchmark_summary_table( # Variables to skip skip_vars = gcon.skip_these_vars - skip_vars.append("corner_lats") - skip_vars.append("corner_lons") + skip_vars.append("AREA") # Pick the proper function to read the data reader = util.dataset_reader( @@ -4569,9 +4568,14 @@ def create_benchmark_summary_table( diff_list = [] # Keep track of which variables are different - # Loop over the common variables + # NOTE: Use 32-point float for comparisons since this is + # the precision used for History diagnostics. for v in vardict["commonvarsData"]: - if not util.array_equals(refdata[v], devdata[v]): + if not util.array_equals( + refdata[v], + devdata[v], + dtype=np.float32 + ): diff_list.append(v) # Drop duplicate values from diff_list diff --git a/gcpy/util.py b/gcpy/util.py index 4b765496..d9590f9c 100644 --- a/gcpy/util.py +++ b/gcpy/util.py @@ -2264,7 +2264,8 @@ def insert_text_into_file( def array_equals( refdata, - devdata + devdata, + dtype=np.float64 ): """ Tests two arrays for equality. Useful for checking which @@ -2276,6 +2277,9 @@ def array_equals( The first array to be checked. devdata: xarray DataArray or numpy ndarray The second array to be checked. + dtype : np.float32 or np.float64 + The precision that will be used to make the evaluation. + Default: np.float64 Returns: -------- @@ -2298,6 +2302,6 @@ def array_equals( # This method will work if the arrays hve different dimensions # but an element-by-element search will not! - refsum = np.sum(refdata, dtype=np.float64) - devsum = np.sum(devdata, dtype=np.float64) - return np.abs(devsum - refsum) > np.float64(0.0) + refsum = np.nansum(refdata, dtype=dtype) + devsum = np.nansum(devdata, dtype=dtype) + return (not np.abs(devsum - refsum) > dtype(0.0)) From feddbf8afe4ef0aeaf2dd106a79847235b779d7a Mon Sep 17 00:00:00 2001 From: Bob Yantosca Date: Thu, 9 Feb 2023 14:27:14 -0500 Subject: [PATCH 3/3] Update the messages at the top of tables to just show one line gcpy/benchmark.py: - Updated routine diff_list_to_text so that it also accepts refstr & devstr args. It now returns either line saying "dev & ref are identical" or "dev & ref show X differences" - Now pass devstr and refstr in calls to diff_list_to_text - Trimmed whitespace Signed-off-by: Bob Yantosca --- gcpy/benchmark.py | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/gcpy/benchmark.py b/gcpy/benchmark.py index fc5c07c9..89735343 100644 --- a/gcpy/benchmark.py +++ b/gcpy/benchmark.py @@ -184,11 +184,7 @@ def create_total_emissions_table( # Write a placeholder to the file that denotes where # the list of species with differences will be written - placeholder = "@%% insert diff_list here %%@" - if "Inv" in template: - print(f"Inventories that differ btw {refstr} and {devstr}:", file=f) - else: - print(f"Species that differ btw {refstr} and {devstr}:", file=f) + placeholder = "@%% insert diff status here %%@" print(f"{placeholder}\n\n", file=f) # Define a list for differences @@ -355,7 +351,10 @@ def create_total_emissions_table( util.insert_text_into_file( filename=outfilename, search_text=placeholder, - replace_text=diff_list_to_text(diff_list), + replace_text=diff_list_to_text( + refstr, + devstr, + diff_list), width=90 ) @@ -464,19 +463,16 @@ def create_global_mass_table( if trop_only: title1 = f"### Global mass (Gg) {label} (Trop only)" title2 = f"### Ref = {refstr}; Dev = {devstr}" - title3 = f"### Species that differ btw {refstr} and {devstr}:" # Write a placeholder to the file that denotes where # the list of species with differences will be written - placeholder = "@%% insert diff_list here %%@" - title4 = f"{placeholder}" + placeholder = "@%% insert diff status here %%@" # Print header to file print("#" * 89, file=f) print(f"{title1 : <86}{'###'}", file=f) print(f"{title2 : <86}{'###'}", file=f) print(f"{'###' : <86}{'###'}", file=f) - print(f"{title3 : <86}{'###'}", file=f) print(f"{placeholder}", file=f) print("#" * 89, file=f) @@ -577,6 +573,8 @@ def create_global_mass_table( filename=outfilename, search_text=placeholder, replace_text=diff_list_to_text( + refstr, + devstr, diff_list, fancy_format=True ), @@ -4604,6 +4602,8 @@ def create_benchmark_summary_table( def diff_list_to_text( + refstr, + devstr, diff_list, fancy_format=False ): @@ -4629,13 +4629,21 @@ def diff_list_to_text( # Strip out duplicates from diff_list # Prepare a message about species differences (or alternate msg) diff_list = util.unique_values(diff_list, drop=[None]) - diff_text = util.wrap_text(diff_list, width=85) - if len(diff_text) > 85: - diff_text = "... Too many diffs to print (see below for details)" + # Print the text + n_diff = len(diff_list) + if n_diff > 0: + diff_text = f"{devstr} and {refstr} show {n_diff} differences" + else: + diff_text = f"{devstr} and {refstr} are identical" + diff_text = util.wrap_text( + diff_text, + width=83 + ) + if fancy_format: diff_text = f"### {diff_text : <82}{'###'}" - + return diff_text.strip()