def interpolate_esmf(obs_file, mod_file, depth, cmor_var): """The 2d interpolation with ESMF. Parameters ---------- obs_file: str path to file with observations/climatology, will be used to extract the grid to interpolate on to. mod_file: str path to the file with model data. depth: int depth to interpolate to. First the closest depth from the observations will be selected and then. """ metadata_obs = load_meta(obs_file, fxpath=None) metadata_mod = load_meta(mod_file, fxpath=None) data_obs = metadata_obs['datafile'].variables[cmor_var][:] data_model = metadata_mod['datafile'].variables[cmor_var][:] # Select depth in climatology that is closest to the desired depth target_depth, level_depth = closest_depth(metadata_obs['lev'], depth) # climatology and model data on the level data_onlev_obs = data_obs[0, level_depth, :, :] data_onlev_mod = interpolate_vert(metadata_mod['lev'], target_depth, data_model[0, :, :, :]) # prepear interpolation fields distfield = define_esmf_field(obs_file, data_onlev_obs, 'OBS') distfield.data[:] = 0.0 sourcefield = define_esmf_field(mod_file, data_onlev_mod, 'Model') sourcefield.data[...] = data_onlev_mod.T lonc, latc, data_onlev_obs_cyc, data_interpolated_cyc = esmf_regriding( sourcefield, distfield, metadata_obs, data_onlev_obs) return lonc, latc, target_depth, data_onlev_obs_cyc, data_interpolated_cyc
def plot2d_bias(cfg, plot_params): """Plot 2d maps of the bias relative to climatology. Parameters ---------- model_filenames:OrderedDict OrderedDict with model names as keys and input files as values. cmor_var: str name of the variable depth: int we will plot the data on the model level that is closest to the `depth`. diagworkdir: str path to the working directory diagplotdir: str path to the plot directory levels: tuple values to be used for vmin and vmax in the form of (vmin, vmax) dpi: int the dpi values to save the figure observations: str name of the observations projection: instance of cartopy projection (ccrs) bbox: list bounding box. It will be the input for cartopy `set_extent`. ncols: int number of columns. Retuns ------ None """ # setupa a base figure figure, axis = create_plot(plot_params['model_filenames'], ncols=plot_params['ncols'], projection=plot_params['projection']) # get the filename of observations ifilename_obs = genfilename(cfg['work_dir'], plot_params['variable'], plot_params['observations'], data_type='timmean', extension='.nc') # get the metadata for observations (we just need a size) metadata = load_meta( datapath=plot_params['model_filenames'][plot_params['observations']], fxpath=None) lon2d = metadata['lon2d'] # Create an empty array to store the mean. # One point larger along long to acount for cyclic point model_mean = np.zeros((lon2d.shape[0], lon2d.shape[1] + 1)) print("MODEL MEAN SHAPE {}".format(model_mean.shape)) # delete observations from the model list model_filenames = plot_params['model_filenames'].copy() del model_filenames[plot_params['observations']] # loop over models index = None for index, mmodel in enumerate(model_filenames): logger.info("Plot plot2d_bias %s for %s", plot_params['variable'], mmodel) # get the filename with the mean generated by the `timemean` ifilename = genfilename(cfg['work_dir'], plot_params['variable'], mmodel, data_type='timmean', extension='.nc') # do the interpolation to the observation grid # the output is lonc, latc, target_depth, data_obs, interpolated = interpolate_esmf( ifilename_obs, ifilename, plot_params['depth'], plot_params['variable']) # get the label and convert data if needed cb_label, data_obs = label_and_conversion(plot_params['variable'], data_obs) cb_label, interpolated = label_and_conversion(plot_params['variable'], interpolated) # add to the mean model model_mean = model_mean + interpolated # set the map extent left, right, down, upper = plot_params['bbox'] axis[index].set_extent([left, right, down, upper], crs=ccrs.PlateCarree()) # Only pcolormesh is working for now with cartopy, # contourf is failing to plot curvilinear meshes, # let along the unstructures ones. image = axis[index].contourf( lonc, latc, interpolated - data_obs, levels=plot_params['levels'], extend='both', # vmin=contours[0], # vmax=contours[-1], transform=ccrs.PlateCarree(), cmap=plot_params['cmap'], ) # fill continents axis[index].add_feature( cfeature.GSHHSFeature(levels=[1], scale="low", facecolor="lightgray")) axis[index].set_title("{}, {} m".format(mmodel, int(target_depth)), size=18) axis[index].set_rasterization_zorder(-1) # calculate the model mean and plot it if index: index = index else: index = 0 model_mean = model_mean / len(model_filenames) axis[index + 1].set_extent([left, right, down, upper], crs=ccrs.PlateCarree()) image = axis[index + 1].contourf( lonc, latc, model_mean - data_obs, levels=plot_params['levels'], extend='both', # vmin=contours[0], # vmax=contours[-1], transform=ccrs.PlateCarree(), cmap=cmo.balance, ) axis[index + 1].add_feature( cfeature.GSHHSFeature(levels=[1], scale="low", facecolor="lightgray")) axis[index + 1].set_title("Model mean bias, {} m".format( int(target_depth)), size=18) axis[index + 1].set_rasterization_zorder(-1) # delete the axis that are not needed for delind in range(index + 2, len(axis)): figure.delaxes(axis[delind]) # set common colorbar colorbar = figure.colorbar(image, orientation='horizontal', ax=axis, pad=0.01, shrink=0.9) colorbar.set_label(cb_label, rotation='horizontal', size=18) colorbar.ax.tick_params(labelsize=18) # save the picture pltoutname = genfilename(cfg['plot_dir'], plot_params['variable'], "MULTIMODEL", data_type='plot2d_bias_{}_level'.format( str(int(target_depth)))) plot_params['basedir'] = cfg['plot_dir'] plot_params['ori_file'] = [ifilename] plot_params['areacello'] = None plot_params['mmodel'] = None plot_params['region'] = "Global" plt.savefig(pltoutname, dpi=plot_params['dpi']) provenance_record = get_provenance_record(plot_params, 'plot2d_bias', 'png') with ProvenanceLogger(cfg) as provenance_logger: provenance_logger.log(pltoutname + '.png', provenance_record)
def plot2d_original_grid(cfg, plot_params): """Plot 2d maps on original grid using cartopy. Parameters ---------- model_filenames:OrderedDict OrderedDict with model names as keys and input files as values. cmor_var: str name of the variable depth: int we will plot the data on the model level that is closest to the `depth`. Ignored if explicit_depths is provided. levels: tuple values to be used for vmin and vmax in the form of (vmin, vmax) diagworkdir: str path to the working directory diagplotdir: str path to the plot directory cmap: matplotlib colormap colormap dpi: int the dpi values to save the figure explicit_depths: dict Output of the `aw_core` function. It's a dictionary where for each model there is a maximum temperature, depth level in the model, index of the depth level in the model. If provided the `depth` parameter is excluded. projection: instance of cartopy projection (ccrs) bbox: list bounding box. It will be the input for cartopy `set_extent`. ncols: int number of columns. Retuns ------ None """ figure, axis = create_plot(plot_params['model_filenames'], ncols=plot_params['ncols'], projection=plot_params['projection']) index = None for index, mmodel in enumerate(plot_params['model_filenames']): logger.info("Plot plot2d_original_grid %s for %s", plot_params['variable'], mmodel) ifilename = genfilename(cfg['work_dir'], plot_params['variable'], mmodel, data_type='timmean', extension='.nc') metadata = load_meta(ifilename, fxpath=None) datafile = metadata['datafile'] lon2d = metadata['lon2d'] lat2d = metadata['lat2d'] lev = metadata['lev'] if not plot_params['explicit_depths']: depth_target, level_target = closest_depth(lev, plot_params['depth']) else: level_target = plot_params['explicit_depths'][mmodel][ 'maxvalue_index'] depth_target = lev[level_target] if datafile.variables[plot_params['variable']].ndim < 4: data = datafile.variables[plot_params['variable']][ level_target, :, :] else: data = datafile.variables[plot_params['variable']][ 0, level_target, :, :] cb_label, data = label_and_conversion(plot_params['variable'], data) left, right, down, upper = plot_params['bbox'] axis[index].set_extent([left, right, down, upper], crs=ccrs.PlateCarree()) # Only pcolormesh is working for now with cartopy, # contourf is failing to plot curvilinear meshes, # let along the unstructures ones. image = axis[index].pcolormesh( lon2d, lat2d, data, vmin=plot_params['levels'][0], vmax=plot_params['levels'][-1], transform=ccrs.PlateCarree(), cmap=plot_params['cmap'], ) axis[index].add_feature( cfeature.GSHHSFeature(levels=[1], scale="low", facecolor="lightgray")) axis[index].set_title("{}, {} m".format(mmodel, np.round(depth_target, 1)), size=18) axis[index].set_rasterization_zorder(-1) # delete unused axis for delind in range(index + 1, len(axis)): figure.delaxes(axis[delind]) # set common colorbar colorbar = figure.colorbar(image, orientation='horizontal', ax=axis, pad=0.01, shrink=0.9) colorbar.set_label(cb_label, rotation='horizontal', size=18) colorbar.ax.tick_params(labelsize=18) if not plot_params['explicit_depths']: plot_type = 'plot2d_{}_depth'.format(str(plot_params['depth'])) else: plot_type = "plot2d_different_levels" # save the figure pltoutname = genfilename(cfg['plot_dir'], plot_params['variable'], "MULTIMODEL", data_type=plot_type) plot_params['basedir'] = cfg['plot_dir'] plot_params['ori_file'] = [ifilename] plot_params['areacello'] = None plot_params['mmodel'] = None plot_params['region'] = "Global" plt.savefig(pltoutname, dpi=plot_params['dpi']) provenance_record = get_provenance_record(plot_params, 'plot2d', 'png') with ProvenanceLogger(cfg) as provenance_logger: provenance_logger.log(pltoutname + '.png', provenance_record)