diff --git a/lib/adf_diag.py b/lib/adf_diag.py index 0053e278b..aa3c3954c 100644 --- a/lib/adf_diag.py +++ b/lib/adf_diag.py @@ -353,6 +353,7 @@ def call_ncrcat(cmd): start_years = [self.climo_yrs["syear_baseline"]] end_years = [self.climo_yrs["eyear_baseline"]] case_type_string = "baseline" + hist_str_list = [self.hist_string["base_hist_str"]] else: # Use test case settings, which are already lists: @@ -364,13 +365,13 @@ def call_ncrcat(cmd): start_years = self.climo_yrs["syears"] end_years = self.climo_yrs["eyears"] case_type_string="case" + hist_str_list = self.hist_string["test_hist_str"] # Notify user that script has started: # End if # Read hist_str (component.hist_num) from the yaml file, or set to default - hist_str_list = self.get_cam_info("hist_str") dmsg = f"reading from {hist_str_list} files" self.debug_log(dmsg) diff --git a/lib/adf_info.py b/lib/adf_info.py index 3b35495f7..7f10a64cb 100644 --- a/lib/adf_info.py +++ b/lib/adf_info.py @@ -124,13 +124,6 @@ def __init__(self, config_file, debug=False): self.__cam_climo_info[conf_var] = [conf_val] #End if #End for - - #If hist_str (component.hist_num) was not in yaml file, set to default - hist_str = self.__cam_climo_info['hist_str'] - if not hist_str: - hist_str = [['cam.h0a']]*self.__num_cases - #End if - #------------------------------------------- #Initialize ADF variable list: @@ -240,11 +233,20 @@ def __init__(self, config_file, debug=False): # Check if history file path exists: if any(baseline_hist_locs): - if not isinstance(baseline_hist_str, list): - baseline_hist_str = [baseline_hist_str] - hist_str = baseline_hist_str[0] + #Check if user provided + if not baseline_hist_str: + baseline_hist_str = ['cam.h0a'] + else: + #Make list if not already + if not isinstance(baseline_hist_str, list): + baseline_hist_str = [baseline_hist_str] + #Initialize baseline history string list + self.__base_hist_str = baseline_hist_str + + #Grab first possible hist string, just looking for years of run + base_hist_str = baseline_hist_str[0] starting_location = Path(baseline_hist_locs) - file_list = sorted(starting_location.glob("*" + hist_str + ".*.nc")) + file_list = sorted(starting_location.glob("*" + base_hist_str + ".*.nc")) # Partition string to find exactly where h-number is # This cuts the string before and after the `{hist_str}.` sub-string # so there will always be three parts: @@ -252,7 +254,7 @@ def __init__(self, config_file, debug=False): #Since the last part always includes the time range, grab that with last index (2) #NOTE: this is based off the current CAM file name structure in the form: # $CASE.cam.h#.YYYY.nc - base_climo_yrs = [int(str(i).partition(f"{hist_str}.")[2][0:4]) for i in file_list] + base_climo_yrs = [int(str(i).partition(f"{base_hist_str}.")[2][0:4]) for i in file_list] base_climo_yrs = sorted(np.unique(base_climo_yrs)) base_found_syr = int(base_climo_yrs[0]) @@ -337,8 +339,17 @@ def __init__(self, config_file, debug=False): #Extract cam history files location: cam_hist_locs = self.get_cam_info('cam_hist_loc') - # Read hist_str (component.hist_num, eg cam.h0) from the yaml file - cam_hist_str = self.get_cam_info('hist_str') + #Get cleaned nested list of hist_str for test case(s) (component.hist_num, eg cam.h0) + cam_hist_str = self.__cam_climo_info.get('hist_str', None) + + if not cam_hist_str: + hist_str = [['cam.h0a']]*self.__num_cases + else: + hist_str = cam_hist_str + #End if + + #Initialize CAM history string nested list + self.__hist_str = hist_str #Check if using pre-made ts files cam_ts_done = self.get_cam_info("cam_ts_done") @@ -392,8 +403,9 @@ def __init__(self, config_file, debug=False): #End if #Check if history file path exists: - hist_str_case = cam_hist_str[case_idx] + hist_str_case = hist_str[case_idx] if any(cam_hist_locs): + #Grab first possible hist string, just looking for years of run hist_str = hist_str_case[0] #Get climo years for verification or assignment if missing @@ -633,8 +645,11 @@ def case_nicknames(self): @property def hist_string(self): - """ Return the history string name to the user if requested.""" - return self.get_cam_info('hist_str') + """ Return the CAM history string list to the user if requested.""" + cam_hist_strs = copy.copy(self.__hist_str) + base_hist_strs = copy.copy(self.__base_hist_str) + hist_strs = {"test_hist_str":cam_hist_strs, "base_hist_str":base_hist_strs} + return hist_strs ######### @@ -807,4 +822,4 @@ def get_climo_yrs_from_ts(self, input_ts_loc, case_name): #++++++++++++++++++++ #End Class definition -#++++++++++++++++++++ +#++++++++++++++++++++ \ No newline at end of file diff --git a/scripts/plotting/tape_recorder.py b/scripts/plotting/tape_recorder.py index 2ec3048e0..e2e9dd09e 100644 --- a/scripts/plotting/tape_recorder.py +++ b/scripts/plotting/tape_recorder.py @@ -36,15 +36,26 @@ def tape_recorder(adfobj): plot_location = adfobj.plot_location plot_loc = Path(plot_location[0]) - #Grab history string: - hist_str = adfobj.hist_string - #Grab test case name(s) case_names = adfobj.get_cam_info('cam_case_name', required=True) #Grab test case time series locs(s) case_ts_locs = adfobj.get_cam_info("cam_ts_loc", required=True) + #Grab history strings: + cam_hist_strs = adfobj.hist_string["test_hist_str"] + + # Filter the list to include only strings that are exactly in the possible h0 strings + # - Search for either h0 or h0a + substrings = {"cam.h0","cam.h0a"} + case_hist_strs = [] + for cam_case_str in cam_hist_strs: + # Check each possible h0 string + for string in cam_case_str: + if string in substrings: + case_hist_strs.append(string) + break + #Grab test case climo years start_years = adfobj.climo_yrs["syears"] end_years = adfobj.climo_yrs["eyears"] @@ -72,8 +83,25 @@ def tape_recorder(adfobj): data_end_year = adfobj.climo_yrs["eyear_baseline"] start_years = start_years+[data_start_year] end_years = end_years+[data_end_year] + + #Grab history string: + baseline_hist_strs = adfobj.hist_string["base_hist_str"] + # Filter the list to include only strings that are exactly in the substrings list + base_hist_strs = [string for string in baseline_hist_strs if string in substrings] + hist_strs = case_hist_strs + base_hist_strs #End if + if not case_ts_locs: + exitmsg = "WARNING: No time series files in any case directory." + exitmsg += " No tape recorder plots will be made." + print(exitmsg) + logmsg = "create tape recorder:" + logmsg += f"\n Tape recorder plots require monthly mean h0 time series files." + logmsg += f"\n None were found for any case. Please check the time series paths." + adfobj.debug_log(logmsg) + #End tape recorder plotting script: + return + # Default colormap cmap='precip_nowhite' @@ -110,10 +138,10 @@ def tape_recorder(adfobj): elif (redo_plot) and plot_name.is_file(): plot_name.unlink() - #Make dictionary for case names and associated timeseries file locations + #Make dictionary for case names and associated timeseries file locations and hist strings runs_LT2={} for i,val in enumerate(test_nicknames): - runs_LT2[val] = case_ts_locs[i] + runs_LT2[val] = [case_ts_locs[i], hist_strs[i]] # MLS data mls = xr.open_dataset(obs_loc / "mls_h2o_latNpressNtime_3d_monthly_v5.nc") @@ -133,11 +161,15 @@ def tape_recorder(adfobj): alldat=[] runname_LT=[] for idx,key in enumerate(runs_LT2): - fils= sorted(Path(runs_LT2[key]).glob(f'*{hist_str}.{var}.*.nc')) + # Search for files + ts_loc = Path(runs_LT2[key][0]) + hist_str = runs_LT2[key][1] + fils= sorted(ts_loc.glob(f'*{hist_str}.{var}.*.nc')) dat = pf.load_dataset(fils) if not dat: - dmsg = f"No data for `{var}` found in {fils}, case will be skipped in tape recorder plot." + dmsg = f"\t No data for `{var}` found in {fils}, case will be skipped in tape recorder plot." print(dmsg) + adfobj.debug_log(dmsg) continue dat = fixcesmtime(dat,start_years[idx],end_years[idx]) datzm = dat.mean('lon') @@ -146,8 +178,16 @@ def tape_recorder(adfobj): alldat.append(dat_mon) runname_LT.append(key) - runname_LT=xr.DataArray(runname_LT, dims='run', coords=[np.arange(0,len(runname_LT),1)], name='run') - alldat_concat_LT = xr.concat(alldat, dim=runname_LT) + #Check to see if any cases were successful + if runname_LT: + runname_LT=xr.DataArray(runname_LT, dims='run', coords=[np.arange(0,len(runname_LT),1)], name='run') + alldat_concat_LT = xr.concat(alldat, dim=runname_LT) + else: + msg = f"WARNING: No cases seem to be available, please check time series files for {var}." + msg += "\n\tNo tape recorder plots will be made." + print(msg) + #End tape recorder plotting script: + return fig = plt.figure(figsize=(16,16)) x1, x2, y1, y2 = get5by5coords_zmplots() @@ -166,7 +206,7 @@ def tape_recorder(adfobj): - #Start count at 2 to account for MLS and ERA5 plots above + #Loop over case(s) and start count at 2 to account for MLS and ERA5 plots above count=2 for irun in np.arange(0,alldat_concat_LT.run.size,1): title = f"{alldat_concat_LT.run.isel(run=irun).values}" @@ -175,16 +215,13 @@ def tape_recorder(adfobj): x1[count],x2[count],y1[count],y2[count],cmap=cmap, paxis='lev', taxis='month',climo_yrs=f"{start_years[irun]}-{end_years[irun]}") count=count+1 - + #Shift colorbar if there are less than 5 subplots # There will always be at least 2 (MLS and ERA5) - if len(case_ts_locs) == 0: - print("Seems like there are no simulations to plot, exiting script.") - return - if len(case_ts_locs) == 1: + if len(runname_LT) == 1: x1_loc = (x1[1]-x1[0])/2 x2_loc = ((x2[2]-x2[1])/2)+x2[1] - elif len(case_ts_locs) == 2: + elif len(runname_LT) == 2: x1_loc = (x1[1]-x1[0])/2 x2_loc = ((x2[3]-x2[2])/2)+x2[2] else: