def plot_bfe_row_for_var(finfo_to_season_to_diff=None, ax_list=None, season_titles=False, varname="", basemap_info=None): cmap = cm.get_cmap("RdBu_r", 20) assert isinstance(basemap_info, BasemapInfo) xx, yy = None, None cs = None for finfo, season_to_diff in finfo_to_season_to_diff.items(): assert isinstance(finfo, FieldInfo) if finfo.varname != varname: continue for season in season_to_diff: season_to_diff[season] = infovar.get_to_plot(varname, season_to_diff[season], difference=True, lons=basemap_info.lons, lats=basemap_info.lats) clevs = get_diff_levels(season_to_diff, ncolors=cmap.N, varname=varname) for i, (season, diff) in enumerate(season_to_diff.items()): ax = ax_list[i] if xx is None or yy is None: xx, yy = basemap_info.get_proj_xy() print(diff.shape) cs = basemap_info.basemap.contourf(xx, yy, diff[:], cmap=cmap, levels=clevs, extend="both", ax=ax) basemap_info.basemap.drawcoastlines(ax=ax) # ax.set_aspect("auto") basemap_info.basemap.readshapefile(BASIN_BOUNDARIES_SHP[:-4], "basin", ax=ax) if season_titles: ax.set_title(season) if i == 0: ax.set_ylabel(infovar.get_long_display_label_for_var(finfo.varname)) if finfo.varname in ["I5", ] and season.lower() in ["summer"]: ax.set_visible(False) ax = ax_list[-1] # ax.set_aspect(30) ax.set_title(infovar.get_units(varname)) plt.colorbar(cs, cax=ax_list[-1])
def main(): # Define the simulations to be validated r_config = RunConfig( data_path= "/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5", start_year=1990, end_year=2010, label="CRCM5-L1") r_config_list = [r_config] r_config = RunConfig( data_path= "/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5", start_year=1990, end_year=2010, label="CRCM5-NL") r_config_list.append(r_config) bmp_info = analysis.get_basemap_info_from_hdf(file_path=r_config.data_path) bmp_info.should_draw_grey_map_background = True bmp_info.should_draw_basin_boundaries = False bmp_info.map_bg_color = "0.75" station_ids = ["104001", "093806", "093801", "081002", "081007", "080718"] # get river network information used in the model flow_directions = analysis.get_array_from_file( r_config.data_path, var_name=infovar.HDF_FLOW_DIRECTIONS_NAME) accumulation_area_km2 = analysis.get_array_from_file( path=r_config.data_path, var_name=infovar.HDF_ACCUMULATION_AREA_NAME) cell_manager = CellManager(flow_dirs=flow_directions, lons2d=bmp_info.lons, lats2d=bmp_info.lats, accumulation_area_km2=accumulation_area_km2) # Get the list of stations to indicate on the bias map stations = cehq_station.read_station_data(start_date=None, end_date=None, selected_ids=station_ids) """:type : list[Station]""" xx, yy = bmp_info.get_proj_xy() station_to_modelpoint = cell_manager.get_model_points_for_stations( station_list=stations) upstream_edges = cell_manager.get_upstream_polygons_for_points( model_point_list=station_to_modelpoint.values(), xx=xx, yy=yy) bmp_info.draw_colorbar_for_each_subplot = True # Validate temperature, precip and swe obs_path_anusplin = "/home/huziy/skynet3_rech1/anusplin_links" obs_path_swe = "data/swe_ross_brown/swe.nc" model_var_to_obs_path = OrderedDict([("TT", obs_path_anusplin), ("I5", obs_path_swe)]) model_var_to_season = OrderedDict([ ("TT", OrderedDict([("Spring", range(3, 6))])), ("I5", OrderedDict([("Winter", [1, 2, 12])])) ]) vname_to_obs_data = {} # parameters that won't change in the loop over variable names params_const = dict(rconfig=r_config, bmp_info=bmp_info) for vname, obs_path in model_var_to_obs_path.items(): season_to_obs_data = get_seasonal_clim_obs_data( vname=vname, obs_path=obs_path, season_to_months=model_var_to_season[vname], **params_const) # Comment swe over lakes, since I5 calculated only for land if vname in [ "I5", ]: for season in season_to_obs_data: season_to_obs_data[season] = maskoceans( bmp_info.lons, bmp_info.lats, season_to_obs_data[season], inlands=True) vname_to_obs_data[vname] = season_to_obs_data # Plotting plot_all_vars_in_one_fig = True fig = None gs = None if plot_all_vars_in_one_fig: plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=20) fig = plt.figure() ncols = len(model_var_to_obs_path) + 1 gs = GridSpec(len(r_config_list), ncols, width_ratios=(ncols - 1) * [ 1., ] + [ 0.05, ]) else: plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=25) station_x_list = [] station_y_list = [] mvarname_to_cs = {} for row, r_config in enumerate(r_config_list): for col, mname in enumerate(model_var_to_obs_path): row_axes = [ fig.add_subplot(gs[row, col]), ] mvarname_to_cs[mname] = compare_vars( vname_model=mname, vname_to_obs=vname_to_obs_data, r_config=r_config, season_to_months=model_var_to_season[mname], bmp_info_agg=bmp_info, axes_list=row_axes) # -1 in order to exclude colorbars for the_ax in row_axes: the_ax.set_title(the_ax.get_title() + ", {}".format( infovar.get_long_display_label_for_var(mname))) # Need titles only for the first row if row > 0: the_ax.set_title("") if col == 0: the_ax.set_ylabel(r_config.label) else: the_ax.set_ylabel("") draw_upstream_area_bounds(the_ax, upstream_edges, color="g") if len(station_x_list) == 0: for the_station in stations: xst, yst = bmp_info.basemap(the_station.longitude, the_station.latitude) station_x_list.append(xst) station_y_list.append(yst) bmp_info.basemap.scatter(station_x_list, station_y_list, c="g", ax=the_ax, s=20, zorder=10, alpha=0.5) # Save the figure if necessary if plot_all_vars_in_one_fig: if not img_folder.is_dir(): img_folder.mkdir(parents=True) fig_path = img_folder.joinpath("{}.png".format( "_".join(model_var_to_obs_path))) with fig_path.open("wb") as figfile: fig.savefig(figfile, format="png", bbox_inches="tight") plt.close(fig)
def plot_seasonal_mean_biases(season_to_error_field=None, varname="", basemap_info=None, axes_list=None): assert isinstance(basemap_info, BasemapInfo) # Set to False if you want the limits to be recalculated from data manual_limits = True d = max([np.percentile(np.abs(field[~field.mask]), 95) for s, field in season_to_error_field.items()]) if manual_limits and varname in ["PR", "TT", "I5"]: clevs = np.arange(-d, 1.1 * d, 0.1 * d) if varname == "PR": clevs = np.arange(-3, 3.5, 0.5) if varname == "TT": clevs = np.arange(-7, 8, 1) if varname == "I5": clevs = np.arange(-100, 110, 10) else: clevs = MaxNLocator(nbins=10, symmetric=True).tick_values(-d, d) cmap = cm.get_cmap("RdBu_r", len(clevs) - 1) fig = None fig_path = None if axes_list is None: fig_path = img_folder.joinpath("{}.png".format(varname)) fig = plt.figure() nrows = 2 ncols = 2 gs = GridSpec(nrows, ncols=ncols + 1, width_ratios=[1, 1, 0.05]) xx, yy = basemap_info.get_proj_xy() cs = None for i, season in enumerate(season_to_error_field): row = i // ncols col = i % ncols if axes_list is None: ax = fig.add_subplot(gs[row, col]) else: ax = axes_list[i] basemap_info.draw_map_background(ax) cs = basemap_info.basemap.contourf(xx, yy, season_to_error_field[season][:], ax=ax, cmap=cmap, levels=clevs, extend="both") basemap_info.basemap.drawcoastlines(ax=ax, linewidth=0.3) ax.set_title(season) if i == 0: ax.set_ylabel(infovar.get_long_display_label_for_var(varname=varname)) # basemap_info.basemap.colorbar(cs) if basemap_info.should_draw_basin_boundaries: basemap_info.basemap.readshapefile(BASIN_BOUNDARIES_SHP[:-4], "basin", ax=ax) # Hide snow plots for summer if varname in ["I5"] and season.lower() in ["summer"]: ax.set_visible(False) # Plot a colorbar for each subplot if required. if hasattr(basemap_info, "draw_colorbar_for_each_subplot"): if basemap_info.draw_colorbar_for_each_subplot: cb = basemap_info.basemap.colorbar(cs, ax=ax) cb.ax.set_title(infovar.get_units(var_name=varname)) cax = fig.add_subplot(gs[:, -1]) if axes_list is None else axes_list[-1] # Add the colorbar if there are additional axes supplied for it if len(axes_list) > len(season_to_error_field): cax.set_title(infovar.get_units(var_name=varname)) plt.colorbar(cs, cax=cax) if axes_list is None: with fig_path.open("wb") as figfile: fig.savefig(figfile, format="png", bbox_inches="tight") plt.close(fig) return cs
def _plot_row(vname="", level=0, config_dict=None, plot_cc_only_for=None, mark_significance=True): """ if plot_cc_only_for is not None, should be equal to the label of the simulation to be plotted """ lons, lats = config_dict.lons, config_dict.lats bmp = config_dict.basemap """ :type bmp: mpl_toolkits.basemap.Basemap """ xx, yy = bmp(lons, lats) lons[lons > 180] -= 360 fig = config_dict.fig gs = config_dict.gs """:type : matplotlib.gridspec.GridSpec """ nrows_subplots, ncols_subplots = gs.get_geometry() label_base = config_dict.label_base label_modif = config_dict.label_modif the_row = config_dict.the_row season_to_months = config_dict.season_to_months if "+" in vname or "-" in vname: op = "+" if "+" in vname else "-" vname1, vname2 = vname.split(op) vname1 = vname1.strip() vname2 = vname2.strip() current_base = {} future_base = {} current_modif = {} future_modif = {} # vname1 current_base1 = compute_seasonal_means_for_each_year(config_dict["Current"][label_base], var_name=vname1, level=level, season_to_months=season_to_months) future_base1 = compute_seasonal_means_for_each_year(config_dict["Future"][label_base], var_name=vname1, level=level, season_to_months=season_to_months) current_modif1 = compute_seasonal_means_for_each_year(config_dict["Current"][label_modif], var_name=vname1, level=level, season_to_months=season_to_months) future_modif1 = compute_seasonal_means_for_each_year(config_dict["Future"][label_modif], var_name=vname1, level=level, season_to_months=season_to_months) # vname2 current_base2 = compute_seasonal_means_for_each_year(config_dict["Current"][label_base], var_name=vname2, level=level, season_to_months=season_to_months) future_base2 = compute_seasonal_means_for_each_year(config_dict["Future"][label_base], var_name=vname2, level=level, season_to_months=season_to_months) current_modif2 = compute_seasonal_means_for_each_year(config_dict["Current"][label_modif], var_name=vname2, level=level, season_to_months=season_to_months) future_modif2 = compute_seasonal_means_for_each_year(config_dict["Future"][label_modif], var_name=vname2, level=level, season_to_months=season_to_months) for season in current_base1: current_base[season] = eval("current_base2[season]{}current_base1[season]".format(op)) future_base[season] = eval("future_base2[season]{}future_base1[season]".format(op)) current_modif[season] = eval("current_modif2[season]{}current_modif1[season]".format(op)) future_modif[season] = eval("future_modif2[season]{}future_modif1[season]".format(op)) else: current_base = compute_seasonal_means_for_each_year(config_dict["Current"][label_base], var_name=vname, level=level, season_to_months=season_to_months) future_base = compute_seasonal_means_for_each_year(config_dict["Future"][label_base], var_name=vname, level=level, season_to_months=season_to_months) current_modif = compute_seasonal_means_for_each_year(config_dict["Current"][label_modif], var_name=vname, level=level, season_to_months=season_to_months) future_modif = compute_seasonal_means_for_each_year(config_dict["Future"][label_modif], var_name=vname, level=level, season_to_months=season_to_months) # Calculate the differences in cc signal season_to_diff = OrderedDict() season_to_plot_diff = OrderedDict() diff_max = 0 print(list(current_base.keys())) # Get the ranges for colorbar and calculate p-values print("------------------ impacts on projected changes to {} -----------------------".format(vname)) season_to_pvalue = OrderedDict() for season in list(current_base.keys()): _, pvalue_current = ttest_ind(current_modif[season], current_base[season], axis=0, equal_var=False) _, pvalue_future = ttest_ind(future_modif[season], future_base[season], axis=0, equal_var=False) if plot_cc_only_for is None: season_to_pvalue[season] = np.minimum(pvalue_current, pvalue_future) season_to_diff[season] = (future_modif[season] - current_modif[season]) - \ (future_base[season] - current_base[season]) else: if plot_cc_only_for == label_base: _, season_to_pvalue[season] = ttest_ind(future_base[season], current_base[season], axis=0, equal_var=False) c_data = current_base[season] f_data = future_base[season] else: _, season_to_pvalue[season] = ttest_ind(future_modif[season], current_modif[season], axis=0, equal_var=False) c_data = current_modif[season] f_data = future_modif[season] season_to_diff[season] = f_data - c_data # Convert units if required if vname in config_dict.multipliers: season_to_diff[season] *= config_dict.multipliers[vname] field_to_plot = infovar.get_to_plot(vname, season_to_diff[season].mean(axis=0), lons=lons, lats=lats) season_to_plot_diff[season] = field_to_plot print("{}: {}".format(season, season_to_plot_diff[season].mean())) if hasattr(field_to_plot, "mask"): diff_max = max(np.percentile(np.abs(field_to_plot[~field_to_plot.mask]), 95), diff_max) else: diff_max = max(np.percentile(np.abs(field_to_plot), 95), diff_max) print("--------------------------------------------------------") img = None locator = MaxNLocator(nbins=10, symmetric=True) clevels = locator.tick_values(-diff_max, diff_max) bn = BoundaryNorm(clevels, len(clevels) - 1) cmap = cm.get_cmap("RdBu_r", len(clevels) - 1) for col, season in enumerate(current_base.keys()): ax = fig.add_subplot(gs[the_row, col]) if not col: ax.set_ylabel(infovar.get_long_display_label_for_var(vname)) if not the_row: ax.set_title(season) img = bmp.pcolormesh(xx, yy, season_to_plot_diff[season].copy(), vmin=-diff_max, vmax=diff_max, cmap=cmap, norm=bn, ax=ax) # logging good_vals = season_to_plot_diff[season] good_vals = good_vals[~good_vals.mask] print("------" * 10) print("{}: min={}; max={}; area-avg={};".format(season, good_vals.min(), good_vals.max(), good_vals.mean())) bmp.readshapefile(quebec_info.BASIN_BOUNDARIES_DERIVED_10km[:-4], "basin_edge", ax=ax) p = season_to_pvalue[season] if hasattr(season_to_plot_diff[season], "mask"): p = np.ma.masked_where(season_to_plot_diff[season].mask, p) if plot_cc_only_for is not None and mark_significance: cs = bmp.contourf(xx, yy, p, hatches=["..."], levels=[0.05, 1], colors='none') if (col == ncols_subplots - 2) and (the_row == nrows_subplots - 1): # create a legend for the contour set artists, labels = cs.legend_elements() labels = ["not significant"] ax.legend(artists, labels, handleheight=1, loc="upper right", bbox_to_anchor=(1.0, -0.05), borderaxespad=0., frameon=False) bmp.drawcoastlines(ax=ax, linewidth=0.4) if vname in ["I5"] and season.lower() in ["summer"]: ax.set_visible(False) cb = plt.colorbar(img, cax=fig.add_subplot(gs[the_row, len(current_base)]), extend="both") if hasattr(config_dict, "name_to_units") and vname in config_dict.name_to_units: cb.ax.set_title(config_dict.name_to_units[vname]) else: cb.ax.set_title(infovar.get_units(vname))
def plot_control_and_differences_in_one_panel_for_all_seasons_for_all_vars( varnames=None, levels=None, season_to_months=None, start_year=None, end_year=None): season_list = list(season_to_months.keys()) pvalue_max = 0.1 # crcm5-r vs crcm5-hcd-r # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r_spinup.hdf" # control_label = "CRCM5-R" # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r_spinup2.hdf", ] # labels = ["CRCM5-HCD-R"] # crcm5-hcd-rl vs crcm5-hcd-r # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r_spinup2.hdf" # control_label = "CRCM5-HCD-R" # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf", ] # labels = ["CRCM5-HCD-RL"] # compare simulations with and without interflow # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf" # control_label = "CRCM5-HCD-RL" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_do_not_discard_small.hdf", ] # labels = ["CRCM5-HCD-RL-INTFL"] # very high hydr cond # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_do_not_discard_small.hdf" # control_label = "CRCM5-HCD-RL-INTFL" ## # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_sani-10000.hdf", ] # labels = ["CRCM5-HCD-RL-INTFL-sani=10000"] # Interflow effect # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf" # control_label = "CRCM5-HCD-RL" # ## # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_spinup_ITFS.hdf5", ] # labels = ["ITFS"] # total lake effect # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5" # control_label = "CRCM5-NL" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5", ] # labels = ["CRCM5-L2", ] # lake effect (lake-atm interactions) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5" # control_label = "CRCM5-R" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5", ] # labels = ["CRCM5-HCD-R", ] # lake effect (lake-river interactions) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5" # control_label = "CRCM5-L1" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5", ] # labels = ["CRCM5-HCD-L2", ] # interflow effect () control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5" control_label = "CRCM5-L2" paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS.hdf5", ] labels = ["CRCM5-L2I", ] # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS_avoid_truncation1979-1989.hdf5", ] # labels = ["CRCM5-HCD-RL-INTFb", ] # interflow effect (avoid truncation and bigger slopes) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS.hdf5" # control_label = "CRCM5-HCD-RL-INTF" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS_avoid_truncation1979-1989.hdf5", ] # labels = ["CRCM5-HCD-RL-INTF-improved", ] # row_labels = [ r"{} vs {}".format(s, control_label) for s in labels ] print(labels) # varnames = ["QQ", ] # levels = [None, ] assert len(levels) == len(varnames) lons2d, lats2d, basemap = analysis.get_basemap_from_hdf(file_path=control_path) x, y = basemap(lons2d, lats2d) # save the domain properties for reuse domain_props = DomainProperties() domain_props.basemap = basemap domain_props.lons2d = lons2d domain_props.lats2d = lats2d domain_props.x = x domain_props.y = y lake_fraction = analysis.get_array_from_file(path=control_path, var_name=infovar.HDF_LAKE_FRACTION_NAME) dpth_to_bedrock = analysis.get_array_from_file(path=control_path, var_name=infovar.HDF_DEPTH_TO_BEDROCK_NAME) assert dpth_to_bedrock is not None if lake_fraction is None: lake_fraction = np.zeros(lons2d.shape) ncolors = 10 # +1 to include white diff_cmap = cm.get_cmap("RdBu", ncolors + 1) # Do the plotting for each variable fig = plt.figure() assert isinstance(fig, Figure) # plot the control data ncols = len(season_list) + 1 # +1 is for the colorbar gs = gridspec.GridSpec(len(varnames), ncols, width_ratios=[1.0, ] * (ncols - 1) + [0.07], top=0.95) lev_width_3d = np.ones(dpth_to_bedrock.shape + infovar.soil_layer_widths_26_to_60.shape) lev_width_3d *= infovar.soil_layer_widths_26_to_60[np.newaxis, np.newaxis, :] lev_bot_3d = lev_width_3d.cumsum(axis=2) correction = -lev_bot_3d + dpth_to_bedrock[:, :, np.newaxis] # Apply the correction only at points where the layer bottom is lower than # the bedrock lev_width_3d[correction < 0] += correction[correction < 0] lev_width_3d[lev_width_3d < 0] = 0 # plot the plots one file per variable for var_name, level, the_row in zip(varnames, levels, list(range(len(varnames)))): sfmt = infovar.get_colorbar_formatter(var_name) season_to_control_mean = {} label_to_season_to_difference = {} label_to_season_to_significance = {} try: # Calculate the difference for each season, and save the results to dictionaries # to access later when plotting for season, months_of_interest in season_to_months.items(): print("working on season: {0}".format(season)) control_means = analysis.get_mean_2d_fields_for_months(path=control_path, var_name=var_name, months=months_of_interest, start_year=start_year, end_year=end_year, level=level) control_mean = np.mean(control_means, axis=0) control_mean = infovar.get_to_plot(var_name, control_mean, lake_fraction=domain_props.lake_fraction, lons=lons2d, lats=lats2d, level_width_m=lev_width_3d[:, :, level]) # multiply by the number of days in a season for PR and TRAF to convert them into mm from mm/day if var_name in ["PR", "TRAF", "TDRA"]: control_mean *= get_num_days(months_of_interest) infovar.change_units_to(varnames=[var_name, ], new_units=r"${\rm mm}$") season_to_control_mean[season] = control_mean print("calculated mean from {0}".format(control_path)) # calculate the difference for each simulation for the_path, the_label in zip(paths, row_labels): modified_means = analysis.get_mean_2d_fields_for_months(path=the_path, var_name=var_name, months=months_of_interest, start_year=start_year, end_year=end_year, level=level) tval, pval = ttest_ind(modified_means, control_means, axis=0, equal_var=False) significance = ((pval <= pvalue_max) & (~control_mean.mask)).astype(int) print("pval ranges: {} to {}".format(pval.min(), pval.max())) modified_mean = np.mean(modified_means, axis=0) if the_label not in label_to_season_to_difference: label_to_season_to_difference[the_label] = OrderedDict() label_to_season_to_significance[the_label] = OrderedDict() modified_mean = infovar.get_to_plot(var_name, modified_mean, lake_fraction=domain_props.lake_fraction, lons=lons2d, lats=lats2d, level_width_m=lev_width_3d[:, :, level]) # multiply by the number of days in a season for PR and TRAF to convert them into mm from mm/day if var_name in ["PR", "TRAF", "TDRA"]: modified_mean *= get_num_days(months_of_interest) diff_vals = modified_mean - control_mean print("diff ranges: min: {0}; max: {1}".format(diff_vals.min(), diff_vals.max())) label_to_season_to_difference[the_label][season] = diff_vals label_to_season_to_significance[the_label][season] = significance print("Calculated mean and diff from {0}".format(the_path)) except NoSuchNodeError: print("Could not find {0}, skipping...".format(var_name)) continue for the_label, data in label_to_season_to_difference.items(): axes = [] for col in range(ncols): axes.append(fig.add_subplot(gs[the_row, col])) # Set season titles if the_row == 0: for the_season, ax in zip(season_list, axes): ax.set_title(the_season) _plot_row(axes, data, the_label, var_name, increments=True, domain_props=domain_props, season_list=season_list, significance=label_to_season_to_significance[the_label]) var_label = infovar.get_long_display_label_for_var(var_name) if var_name in ["I1"]: var_label = "{}\n{} layer".format(var_label, ordinal(level + 1)) axes[0].set_ylabel(var_label) fig.suptitle("({}) vs ({})".format(labels[0], control_label), font_properties=FontProperties(weight="bold")) folderpath = os.path.join(images_folder, "seasonal_mean_maps/{0}_vs_{1}_for_{2}_{3}-{4}".format( "_".join(labels), control_label, "-".join(list(season_to_months.keys())), start_year, end_year)) if not os.path.isdir(folderpath): os.mkdir(folderpath) imname = "{0}_{1}.png".format("-".join(varnames), "_".join(labels + [control_label])) impath = os.path.join(folderpath, imname) fig.savefig(impath, bbox_inches="tight")
def main(): # Define the simulations to be validated r_config = RunConfig( data_path="/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5", start_year=1990, end_year=2010, label="CRCM5-L1" ) r_config_list = [r_config] r_config = RunConfig( data_path="/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5", start_year=1990, end_year=2010, label="CRCM5-NL" ) r_config_list.append(r_config) bmp_info = analysis.get_basemap_info_from_hdf(file_path=r_config.data_path) bmp_info.should_draw_grey_map_background = True bmp_info.should_draw_basin_boundaries = False bmp_info.map_bg_color = "0.75" station_ids = [ "104001", "093806", "093801", "081002", "081007", "080718" ] # get river network information used in the model flow_directions = analysis.get_array_from_file(r_config.data_path, var_name=infovar.HDF_FLOW_DIRECTIONS_NAME) accumulation_area_km2 = analysis.get_array_from_file(path=r_config.data_path, var_name=infovar.HDF_ACCUMULATION_AREA_NAME) cell_manager = CellManager(flow_dirs=flow_directions, lons2d=bmp_info.lons, lats2d=bmp_info.lats, accumulation_area_km2=accumulation_area_km2) # Get the list of stations to indicate on the bias map stations = cehq_station.read_station_data( start_date=None, end_date=None, selected_ids=station_ids ) """:type : list[Station]""" xx, yy = bmp_info.get_proj_xy() station_to_modelpoint = cell_manager.get_model_points_for_stations(station_list=stations) upstream_edges = cell_manager.get_upstream_polygons_for_points( model_point_list=station_to_modelpoint.values(), xx=xx, yy=yy) bmp_info.draw_colorbar_for_each_subplot = True # Validate temperature, precip and swe obs_path_anusplin = "/home/huziy/skynet3_rech1/anusplin_links" obs_path_swe = "data/swe_ross_brown/swe.nc" model_var_to_obs_path = OrderedDict([ ("TT", obs_path_anusplin), ("I5", obs_path_swe) ]) model_var_to_season = OrderedDict([ ("TT", OrderedDict([("Spring", range(3, 6))])), ("I5", OrderedDict([("Winter", [1, 2, 12])])) ]) vname_to_obs_data = {} # parameters that won't change in the loop over variable names params_const = dict(rconfig=r_config, bmp_info=bmp_info) for vname, obs_path in model_var_to_obs_path.items(): season_to_obs_data = get_seasonal_clim_obs_data(vname=vname, obs_path=obs_path, season_to_months=model_var_to_season[vname], **params_const) # Comment swe over lakes, since I5 calculated only for land if vname in ["I5", ]: for season in season_to_obs_data: season_to_obs_data[season] = maskoceans(bmp_info.lons, bmp_info.lats, season_to_obs_data[season], inlands=True) vname_to_obs_data[vname] = season_to_obs_data # Plotting plot_all_vars_in_one_fig = True fig = None gs = None if plot_all_vars_in_one_fig: plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=20) fig = plt.figure() ncols = len(model_var_to_obs_path) + 1 gs = GridSpec(len(r_config_list), ncols, width_ratios=(ncols - 1) * [1., ] + [0.05, ]) else: plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=25) station_x_list = [] station_y_list = [] mvarname_to_cs = {} for row, r_config in enumerate(r_config_list): for col, mname in enumerate(model_var_to_obs_path): row_axes = [fig.add_subplot(gs[row, col]), ] mvarname_to_cs[mname] = compare_vars(vname_model=mname, vname_to_obs=vname_to_obs_data, r_config=r_config, season_to_months=model_var_to_season[mname], bmp_info_agg=bmp_info, axes_list=row_axes) # -1 in order to exclude colorbars for the_ax in row_axes: the_ax.set_title(the_ax.get_title() + ", {}".format(infovar.get_long_display_label_for_var(mname))) # Need titles only for the first row if row > 0: the_ax.set_title("") if col == 0: the_ax.set_ylabel(r_config.label) else: the_ax.set_ylabel("") draw_upstream_area_bounds(the_ax, upstream_edges, color="g") if len(station_x_list) == 0: for the_station in stations: xst, yst = bmp_info.basemap(the_station.longitude, the_station.latitude) station_x_list.append(xst) station_y_list.append(yst) bmp_info.basemap.scatter(station_x_list, station_y_list, c="g", ax=the_ax, s=20, zorder=10, alpha=0.5) # Save the figure if necessary if plot_all_vars_in_one_fig: if not img_folder.is_dir(): img_folder.mkdir(parents=True) fig_path = img_folder.joinpath("{}.png".format("_".join(model_var_to_obs_path))) with fig_path.open("wb") as figfile: fig.savefig(figfile, format="png", bbox_inches="tight") plt.close(fig)
def plot_control_and_differences_in_one_panel_for_all_seasons_for_all_vars( varnames=None, levels=None, season_to_months=None, start_year=None, end_year=None): season_list = list(season_to_months.keys()) pvalue_max = 0.1 # crcm5-r vs crcm5-hcd-r # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r_spinup.hdf" # control_label = "CRCM5-R" # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r_spinup2.hdf", ] # labels = ["CRCM5-HCD-R"] # crcm5-hcd-rl vs crcm5-hcd-r # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r_spinup2.hdf" # control_label = "CRCM5-HCD-R" # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf", ] # labels = ["CRCM5-HCD-RL"] # compare simulations with and without interflow # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf" # control_label = "CRCM5-HCD-RL" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_do_not_discard_small.hdf", ] # labels = ["CRCM5-HCD-RL-INTFL"] # very high hydr cond # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_do_not_discard_small.hdf" # control_label = "CRCM5-HCD-RL-INTFL" ## # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_sani-10000.hdf", ] # labels = ["CRCM5-HCD-RL-INTFL-sani=10000"] # Interflow effect # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl_spinup.hdf" # control_label = "CRCM5-HCD-RL" # ## # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_spinup_ITFS.hdf5", ] # labels = ["ITFS"] # total lake effect # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5" # control_label = "CRCM5-NL" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5", ] # labels = ["CRCM5-L2", ] # lake effect (lake-atm interactions) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5" # control_label = "CRCM5-R" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5", ] # labels = ["CRCM5-HCD-R", ] # lake effect (lake-river interactions) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5" # control_label = "CRCM5-L1" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5", ] # labels = ["CRCM5-HCD-L2", ] # interflow effect () control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl.hdf5" control_label = "CRCM5-L2" paths = [ "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS.hdf5", ] labels = [ "CRCM5-L2I", ] # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS_avoid_truncation1979-1989.hdf5", ] # labels = ["CRCM5-HCD-RL-INTFb", ] # interflow effect (avoid truncation and bigger slopes) # control_path = "/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS.hdf5" # control_label = "CRCM5-HCD-RL-INTF" # # paths = ["/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-rl-intfl_ITFS_avoid_truncation1979-1989.hdf5", ] # labels = ["CRCM5-HCD-RL-INTF-improved", ] # row_labels = [r"{} vs {}".format(s, control_label) for s in labels] print(labels) # varnames = ["QQ", ] # levels = [None, ] assert len(levels) == len(varnames) lons2d, lats2d, basemap = analysis.get_basemap_from_hdf( file_path=control_path) x, y = basemap(lons2d, lats2d) # save the domain properties for reuse domain_props = DomainProperties() domain_props.basemap = basemap domain_props.lons2d = lons2d domain_props.lats2d = lats2d domain_props.x = x domain_props.y = y lake_fraction = analysis.get_array_from_file( path=control_path, var_name=infovar.HDF_LAKE_FRACTION_NAME) dpth_to_bedrock = analysis.get_array_from_file( path=control_path, var_name=infovar.HDF_DEPTH_TO_BEDROCK_NAME) assert dpth_to_bedrock is not None if lake_fraction is None: lake_fraction = np.zeros(lons2d.shape) ncolors = 10 # +1 to include white diff_cmap = cm.get_cmap("RdBu", ncolors + 1) # Do the plotting for each variable fig = plt.figure() assert isinstance(fig, Figure) # plot the control data ncols = len(season_list) + 1 # +1 is for the colorbar gs = gridspec.GridSpec(len(varnames), ncols, width_ratios=[ 1.0, ] * (ncols - 1) + [0.07], top=0.95) lev_width_3d = np.ones(dpth_to_bedrock.shape + infovar.soil_layer_widths_26_to_60.shape) lev_width_3d *= infovar.soil_layer_widths_26_to_60[np.newaxis, np.newaxis, :] lev_bot_3d = lev_width_3d.cumsum(axis=2) correction = -lev_bot_3d + dpth_to_bedrock[:, :, np.newaxis] # Apply the correction only at points where the layer bottom is lower than # the bedrock lev_width_3d[correction < 0] += correction[correction < 0] lev_width_3d[lev_width_3d < 0] = 0 # plot the plots one file per variable for var_name, level, the_row in zip(varnames, levels, list(range(len(varnames)))): sfmt = infovar.get_colorbar_formatter(var_name) season_to_control_mean = {} label_to_season_to_difference = {} label_to_season_to_significance = {} try: # Calculate the difference for each season, and save the results to dictionaries # to access later when plotting for season, months_of_interest in season_to_months.items(): print("working on season: {0}".format(season)) control_means = analysis.get_mean_2d_fields_for_months( path=control_path, var_name=var_name, months=months_of_interest, start_year=start_year, end_year=end_year, level=level) control_mean = np.mean(control_means, axis=0) control_mean = infovar.get_to_plot( var_name, control_mean, lake_fraction=domain_props.lake_fraction, lons=lons2d, lats=lats2d, level_width_m=lev_width_3d[:, :, level]) # multiply by the number of days in a season for PR and TRAF to convert them into mm from mm/day if var_name in ["PR", "TRAF", "TDRA"]: control_mean *= get_num_days(months_of_interest) infovar.change_units_to(varnames=[ var_name, ], new_units=r"${\rm mm}$") season_to_control_mean[season] = control_mean print("calculated mean from {0}".format(control_path)) # calculate the difference for each simulation for the_path, the_label in zip(paths, row_labels): modified_means = analysis.get_mean_2d_fields_for_months( path=the_path, var_name=var_name, months=months_of_interest, start_year=start_year, end_year=end_year, level=level) tval, pval = ttest_ind(modified_means, control_means, axis=0, equal_var=False) significance = ((pval <= pvalue_max) & (~control_mean.mask)).astype(int) print("pval ranges: {} to {}".format( pval.min(), pval.max())) modified_mean = np.mean(modified_means, axis=0) if the_label not in label_to_season_to_difference: label_to_season_to_difference[the_label] = OrderedDict( ) label_to_season_to_significance[ the_label] = OrderedDict() modified_mean = infovar.get_to_plot( var_name, modified_mean, lake_fraction=domain_props.lake_fraction, lons=lons2d, lats=lats2d, level_width_m=lev_width_3d[:, :, level]) # multiply by the number of days in a season for PR and TRAF to convert them into mm from mm/day if var_name in ["PR", "TRAF", "TDRA"]: modified_mean *= get_num_days(months_of_interest) diff_vals = modified_mean - control_mean print("diff ranges: min: {0}; max: {1}".format( diff_vals.min(), diff_vals.max())) label_to_season_to_difference[the_label][ season] = diff_vals label_to_season_to_significance[the_label][ season] = significance print("Calculated mean and diff from {0}".format(the_path)) except NoSuchNodeError: print("Could not find {0}, skipping...".format(var_name)) continue for the_label, data in label_to_season_to_difference.items(): axes = [] for col in range(ncols): axes.append(fig.add_subplot(gs[the_row, col])) # Set season titles if the_row == 0: for the_season, ax in zip(season_list, axes): ax.set_title(the_season) _plot_row(axes, data, the_label, var_name, increments=True, domain_props=domain_props, season_list=season_list, significance=label_to_season_to_significance[the_label]) var_label = infovar.get_long_display_label_for_var(var_name) if var_name in ["I1"]: var_label = "{}\n{} layer".format(var_label, ordinal(level + 1)) axes[0].set_ylabel(var_label) fig.suptitle("({}) vs ({})".format(labels[0], control_label), font_properties=FontProperties(weight="bold")) folderpath = os.path.join( images_folder, "seasonal_mean_maps/{0}_vs_{1}_for_{2}_{3}-{4}".format( "_".join(labels), control_label, "-".join(list(season_to_months.keys())), start_year, end_year)) if not os.path.isdir(folderpath): os.mkdir(folderpath) imname = "{0}_{1}.png".format("-".join(varnames), "_".join(labels + [control_label])) impath = os.path.join(folderpath, imname) fig.savefig(impath, bbox_inches="tight")
def _plot_var(vname="", level=0, config_dict=None, data_dict=None): modif_label = config_dict.label_modif base_label = config_dict.label_base base_config_c, modif_config_c = [ config_dict["Current"][the_label] for the_label in [base_label, modif_label] ] base_config_f, modif_config_f = [ config_dict["Future"][the_label] for the_label in [base_label, modif_label] ] bmp = config_dict.basemap lons = config_dict.lons lons[lons > 180] -= 360 lats = config_dict.lats xx, yy = bmp(lons, lats) i_to_label = { 0: base_label, 1: modif_label, 2: "{}\n--\n{}".format(modif_label, base_label) } j_to_title = { 0: "Current ({}-{})".format(base_config_c.start_year, base_config_c.end_year), 1: "Future ({}-{})".format(base_config_f.start_year, base_config_f.end_year), 2: "Future - Current" } # Create a folder for images img_folder = os.path.join("cc_paper", "{}_vs_{}".format(modif_label, base_label)) if not os.path.isdir(img_folder): os.makedirs(img_folder) nrows = ncols = 3 plot_utils.apply_plot_params(font_size=10, width_pt=None, width_cm=27, height_cm=20) field_cmap = cm.get_cmap("jet", 20) diff_cmap = cm.get_cmap("RdBu_r", 20) for season in list(data_dict[base_config_c].keys()): fig = plt.figure() fig.suptitle("{} ({})".format( infovar.get_long_display_label_for_var(vname), season), font_properties=FontProperties(weight="bold")) gs = GridSpec(nrows=nrows, ncols=ncols) mean_c_base = data_dict[base_config_c][season].mean(axis=0) mean_f_base = data_dict[base_config_f][season].mean(axis=0) mean_c_modif = data_dict[modif_config_c][season].mean(axis=0) mean_f_modif = data_dict[modif_config_f][season].mean(axis=0) print("------------ {}, {} --------------".format(vname, season)) print("data_dict[base_config_c][season].shape = {}".format( data_dict[base_config_c][season].shape)) _, p_signif_base_cc = ttest_ind(data_dict[base_config_c][season], data_dict[base_config_f][season], axis=0, equal_var=False) _, p_signif_current = ttest_ind(data_dict[base_config_c][season], data_dict[modif_config_c][season], axis=0, equal_var=False) print("Base p-value ranges: {} to {}".format(p_signif_base_cc.min(), p_signif_base_cc.max())) _, p_signif_modif_cc = ttest_ind(data_dict[modif_config_c][season], data_dict[modif_config_f][season], axis=0, equal_var=False) _, p_signif_future = ttest_ind(data_dict[base_config_f][season], data_dict[modif_config_f][season], axis=0, equal_var=False) ij_to_pvalue = { (0, 2): p_signif_base_cc, (1, 2): p_signif_modif_cc, (2, 0): p_signif_current, (2, 1): p_signif_future, # (2, 2): np.minimum(p_signif_current, p_signif_future) } ij_to_data = { (0, 0): mean_c_base, (1, 0): mean_c_modif, (0, 1): mean_f_base, (1, 1): mean_f_modif } # Apply multipliers for unit conversion for k in list(ij_to_data.keys()): ij_to_data[k] *= multiplier_dict.get(vname, 1) # mask oceans mask_inland = vname in ["STFL", "STFA"] or vname.startswith("I") ij_to_data[k] = maskoceans(lonsin=lons, latsin=lats, datain=ij_to_data[k], inlands=mask_inland) # get all means to calculate the ranges of mean fields all_means = [] for vals in ij_to_data.values(): all_means.extend(vals[~vals.mask]) if vname == "PR": # mm/day minval = 0 maxval = 5 extend_val = "max" else: minval = np.percentile(all_means, 1) maxval = np.percentile(all_means, 95) extend_val = "neither" d1 = ij_to_data[0, 1] - ij_to_data[0, 0] d2 = ij_to_data[1, 1] - ij_to_data[1, 0] all_cc_diffs = np.ma.asarray([d1, d2]) mindiff_cc = np.percentile(all_cc_diffs[~all_cc_diffs.mask], 1) maxdiff_cc = np.percentile(all_cc_diffs[~all_cc_diffs.mask], 99) maxdiff_cc = max(np.ma.abs(maxdiff_cc), np.ma.abs(mindiff_cc)) # Limit the temperature change scale if vname == "TT": maxdiff_cc = min(maxdiff_cc, 10) mindiff_cc = -maxdiff_cc # Add all differences due to changed processes in a list all_proc_diffs = [] d1 = ij_to_data[1, 0] - ij_to_data[0, 0] d2 = ij_to_data[1, 1] - ij_to_data[0, 1] all_proc_diffs.extend([d1, d2]) all_proc_diffs.append(d2 - d1) all_proc_diffs = np.ma.asarray(all_proc_diffs) mindiff_proc = np.percentile(all_proc_diffs[~all_proc_diffs.mask], 1) maxdiff_proc = np.percentile(all_proc_diffs[~all_proc_diffs.mask], 95) maxdiff_proc = max(np.abs(maxdiff_proc), np.abs(mindiff_proc)) mindiff_proc = -maxdiff_proc plot_data = [] for row in range(nrows - 1): row_data = [] for col in range(ncols - 1): row_data.append(ij_to_data[row, col]) plot_data.append(row_data + [ 0, ]) # calculate differences between different model configurations row = 2 plot_data.append([0, 0, 0]) for col in range(2): plot_data[row][col] = plot_data[1][col] - plot_data[0][col] # calculate CC col = 2 for row in range(3): plot_data[row][col] = plot_data[row][1] - plot_data[row][0] # Do the plotting for i in range(nrows): for j in range(ncols): ax = fig.add_subplot(gs[i, j]) plotting_values = (i < 2) and (j < 2) if plotting_values: the_min, the_max = minval, maxval elif i == nrows - 1: the_min, the_max = mindiff_proc, maxdiff_proc else: the_min, the_max = mindiff_cc, maxdiff_cc the_cmap = field_cmap if plotting_values else diff_cmap locator = MaxNLocator(nbins=the_cmap.N // 2, symmetric=not plotting_values) bounds = locator.tick_values(the_min, the_max) if vname in ["STFA", "STFL"] and plotting_values: the_min = 1.0e-5 the_max = 1.0e4 locator = LogLocator(numticks=11) bounds = locator.tick_values(the_min, the_max) print(bounds) norm = LogNorm(vmin=bounds[0], vmax=bounds[-1]) plot_data[i][j] = np.ma.masked_where( plot_data[i][j] <= the_min, plot_data[i][j]) print("the_max = {}".format(the_max)) the_cmap = cm.get_cmap("jet", len(bounds) - 1) else: norm = BoundaryNorm(bounds, the_cmap.N) extend = "both" if not plotting_values else extend_val if plotting_values: print(i, j, the_min, the_max) im = bmp.pcolormesh(xx, yy, plot_data[i][j][:, :], cmap=the_cmap, norm=norm) if (i, j) in ij_to_pvalue: p = ij_to_pvalue[i, j] # not_signif = (p > 0.2) # not_signif = np.ma.masked_where(~not_signif, not_signif) * 0.75 # not_signif = np.ma.masked_where(plot_data[i][j].mask, not_signif) # bmp.pcolormesh(xx, yy, not_signif, vmin=0, vmax=1, cmap=cm.get_cmap("gray", 20)) p = np.ma.masked_where(plot_data[i][j].mask, p) cs = bmp.contourf(xx, yy, p, hatches=["..."], levels=[0.1, 1], colors='none') # create a legend for the contour set # artists, labels = cs.legend_elements() # ax.legend(artists, labels, handleheight=2) bmp.colorbar(im, ticks=bounds, extend=extend) bmp.drawcoastlines(ax=ax, linewidth=0.5) ax.set_title(j_to_title.get(j, "") if i == 0 else "") ax.set_ylabel(i_to_label.get(i, "") if j == 0 else "") # Save the image to the file img_name = "{}_{}_{}-{}_{}-{}.png".format(vname + str(level), season, base_config_f.start_year, base_config_f.end_year, base_config_c.start_year, base_config_c.end_year) img_path = os.path.join(img_folder, img_name) fig.savefig(img_path, bbox_inches="tight") plt.close(fig)
def _plot_var(vname="", level=0, config_dict=None, data_dict=None): modif_label = config_dict.label_modif base_label = config_dict.label_base base_config_c, modif_config_c = [config_dict["Current"][the_label] for the_label in [base_label, modif_label]] base_config_f, modif_config_f = [config_dict["Future"][the_label] for the_label in [base_label, modif_label]] bmp = config_dict.basemap lons = config_dict.lons lons[lons > 180] -= 360 lats = config_dict.lats xx, yy = bmp(lons, lats) i_to_label = { 0: base_label, 1: modif_label, 2: "{}\n--\n{}".format(modif_label, base_label) } j_to_title = { 0: "Current ({}-{})".format(base_config_c.start_year, base_config_c.end_year), 1: "Future ({}-{})".format(base_config_f.start_year, base_config_f.end_year), 2: "Future - Current" } # Create a folder for images img_folder = os.path.join("cc_paper", "{}_vs_{}".format(modif_label, base_label)) if not os.path.isdir(img_folder): os.makedirs(img_folder) nrows = ncols = 3 plot_utils.apply_plot_params(font_size=10, width_pt=None, width_cm=27, height_cm=20) field_cmap = cm.get_cmap("jet", 20) diff_cmap = cm.get_cmap("RdBu_r", 20) for season in list(data_dict[base_config_c].keys()): fig = plt.figure() fig.suptitle( "{} ({})".format(infovar.get_long_display_label_for_var(vname), season), font_properties=FontProperties(weight="bold")) gs = GridSpec(nrows=nrows, ncols=ncols) mean_c_base = data_dict[base_config_c][season].mean(axis=0) mean_f_base = data_dict[base_config_f][season].mean(axis=0) mean_c_modif = data_dict[modif_config_c][season].mean(axis=0) mean_f_modif = data_dict[modif_config_f][season].mean(axis=0) print("------------ {}, {} --------------".format(vname, season)) print("data_dict[base_config_c][season].shape = {}".format(data_dict[base_config_c][season].shape)) _, p_signif_base_cc = ttest_ind(data_dict[base_config_c][season], data_dict[base_config_f][season], axis=0, equal_var=False) _, p_signif_current = ttest_ind(data_dict[base_config_c][season], data_dict[modif_config_c][season], axis=0, equal_var=False) print("Base p-value ranges: {} to {}".format(p_signif_base_cc.min(), p_signif_base_cc.max())) _, p_signif_modif_cc = ttest_ind(data_dict[modif_config_c][season], data_dict[modif_config_f][season], axis=0, equal_var=False) _, p_signif_future = ttest_ind(data_dict[base_config_f][season], data_dict[modif_config_f][season], axis=0, equal_var=False) ij_to_pvalue = { (0, 2): p_signif_base_cc, (1, 2): p_signif_modif_cc, (2, 0): p_signif_current, (2, 1): p_signif_future, # (2, 2): np.minimum(p_signif_current, p_signif_future) } ij_to_data = { (0, 0): mean_c_base, (1, 0): mean_c_modif, (0, 1): mean_f_base, (1, 1): mean_f_modif } # Apply multipliers for unit conversion for k in list(ij_to_data.keys()): ij_to_data[k] *= multiplier_dict.get(vname, 1) # mask oceans mask_inland = vname in ["STFL", "STFA"] or vname.startswith("I") ij_to_data[k] = maskoceans(lonsin=lons, latsin=lats, datain=ij_to_data[k], inlands=mask_inland) # get all means to calculate the ranges of mean fields all_means = [] for vals in ij_to_data.values(): all_means.extend(vals[~vals.mask]) if vname == "PR": # mm/day minval = 0 maxval = 5 extend_val = "max" else: minval = np.percentile(all_means, 1) maxval = np.percentile(all_means, 95) extend_val = "neither" d1 = ij_to_data[0, 1] - ij_to_data[0, 0] d2 = ij_to_data[1, 1] - ij_to_data[1, 0] all_cc_diffs = np.ma.asarray([d1, d2]) mindiff_cc = np.percentile(all_cc_diffs[~all_cc_diffs.mask], 1) maxdiff_cc = np.percentile(all_cc_diffs[~all_cc_diffs.mask], 99) maxdiff_cc = max(np.ma.abs(maxdiff_cc), np.ma.abs(mindiff_cc)) # Limit the temperature change scale if vname == "TT": maxdiff_cc = min(maxdiff_cc, 10) mindiff_cc = -maxdiff_cc # Add all differences due to changed processes in a list all_proc_diffs = [] d1 = ij_to_data[1, 0] - ij_to_data[0, 0] d2 = ij_to_data[1, 1] - ij_to_data[0, 1] all_proc_diffs.extend([d1, d2]) all_proc_diffs.append(d2 - d1) all_proc_diffs = np.ma.asarray(all_proc_diffs) mindiff_proc = np.percentile(all_proc_diffs[~all_proc_diffs.mask], 1) maxdiff_proc = np.percentile(all_proc_diffs[~all_proc_diffs.mask], 95) maxdiff_proc = max(np.abs(maxdiff_proc), np.abs(mindiff_proc)) mindiff_proc = -maxdiff_proc plot_data = [] for row in range(nrows - 1): row_data = [] for col in range(ncols - 1): row_data.append(ij_to_data[row, col]) plot_data.append(row_data + [0, ]) # calculate differences between different model configurations row = 2 plot_data.append([0, 0, 0]) for col in range(2): plot_data[row][col] = plot_data[1][col] - plot_data[0][col] # calculate CC col = 2 for row in range(3): plot_data[row][col] = plot_data[row][1] - plot_data[row][0] # Do the plotting for i in range(nrows): for j in range(ncols): ax = fig.add_subplot(gs[i, j]) plotting_values = (i < 2) and (j < 2) if plotting_values: the_min, the_max = minval, maxval elif i == nrows - 1: the_min, the_max = mindiff_proc, maxdiff_proc else: the_min, the_max = mindiff_cc, maxdiff_cc the_cmap = field_cmap if plotting_values else diff_cmap locator = MaxNLocator(nbins=the_cmap.N // 2, symmetric=not plotting_values) bounds = locator.tick_values(the_min, the_max) if vname in ["STFA", "STFL"] and plotting_values: the_min = 1.0e-5 the_max = 1.0e4 locator = LogLocator(numticks=11) bounds = locator.tick_values(the_min, the_max) print(bounds) norm = LogNorm(vmin=bounds[0], vmax=bounds[-1]) plot_data[i][j] = np.ma.masked_where(plot_data[i][j] <= the_min, plot_data[i][j]) print("the_max = {}".format(the_max)) the_cmap = cm.get_cmap("jet", len(bounds) - 1) else: norm = BoundaryNorm(bounds, the_cmap.N) extend = "both" if not plotting_values else extend_val if plotting_values: print(i, j, the_min, the_max) im = bmp.pcolormesh(xx, yy, plot_data[i][j][:, :], cmap=the_cmap, norm=norm) if (i, j) in ij_to_pvalue: p = ij_to_pvalue[i, j] # not_signif = (p > 0.2) # not_signif = np.ma.masked_where(~not_signif, not_signif) * 0.75 # not_signif = np.ma.masked_where(plot_data[i][j].mask, not_signif) # bmp.pcolormesh(xx, yy, not_signif, vmin=0, vmax=1, cmap=cm.get_cmap("gray", 20)) p = np.ma.masked_where(plot_data[i][j].mask, p) cs = bmp.contourf(xx, yy, p, hatches=["..."], levels=[0.1, 1], colors='none') # create a legend for the contour set # artists, labels = cs.legend_elements() # ax.legend(artists, labels, handleheight=2) bmp.colorbar(im, ticks=bounds, extend=extend) bmp.drawcoastlines(ax=ax, linewidth=0.5) ax.set_title(j_to_title.get(j, "") if i == 0 else "") ax.set_ylabel(i_to_label.get(i, "") if j == 0 else "") # Save the image to the file img_name = "{}_{}_{}-{}_{}-{}.png".format( vname + str(level), season, base_config_f.start_year, base_config_f.end_year, base_config_c.start_year, base_config_c.end_year) img_path = os.path.join(img_folder, img_name) fig.savefig(img_path, bbox_inches="tight") plt.close(fig)
def plot_bfe_row_for_var(finfo_to_season_to_diff=None, ax_list=None, season_titles=False, varname="", basemap_info=None): cmap = cm.get_cmap("RdBu_r", 20) assert isinstance(basemap_info, BasemapInfo) xx, yy = None, None cs = None for finfo, season_to_diff in finfo_to_season_to_diff.items(): assert isinstance(finfo, FieldInfo) if finfo.varname != varname: continue for season in season_to_diff: season_to_diff[season] = infovar.get_to_plot( varname, season_to_diff[season], difference=True, lons=basemap_info.lons, lats=basemap_info.lats) clevs = get_diff_levels(season_to_diff, ncolors=cmap.N, varname=varname) for i, (season, diff) in enumerate(season_to_diff.items()): ax = ax_list[i] if xx is None or yy is None: xx, yy = basemap_info.get_proj_xy() print(diff.shape) cs = basemap_info.basemap.contourf(xx, yy, diff[:], cmap=cmap, levels=clevs, extend="both", ax=ax) basemap_info.basemap.drawcoastlines(ax=ax) # ax.set_aspect("auto") basemap_info.basemap.readshapefile(BASIN_BOUNDARIES_SHP[:-4], "basin", ax=ax) if season_titles: ax.set_title(season) if i == 0: ax.set_ylabel( infovar.get_long_display_label_for_var(finfo.varname)) if finfo.varname in [ "I5", ] and season.lower() in ["summer"]: ax.set_visible(False) ax = ax_list[-1] # ax.set_aspect(30) ax.set_title(infovar.get_units(varname)) plt.colorbar(cs, cax=ax_list[-1])
def plot_seasonal_mean_biases(season_to_error_field=None, varname="", basemap_info=None, axes_list=None): assert isinstance(basemap_info, BasemapInfo) # Set to False if you want the limits to be recalculated from data manual_limits = True d = max([ np.percentile(np.abs(field[~field.mask]), 95) for s, field in season_to_error_field.items() ]) if manual_limits and varname in ["PR", "TT", "I5"]: clevs = np.arange(-d, 1.1 * d, 0.1 * d) if varname == "PR": clevs = np.arange(-3, 3.5, 0.5) if varname == "TT": clevs = np.arange(-7, 8, 1) if varname == "I5": clevs = np.arange(-100, 110, 10) else: clevs = MaxNLocator(nbins=10, symmetric=True).tick_values(-d, d) cmap = cm.get_cmap("RdBu_r", len(clevs) - 1) fig = None fig_path = None if axes_list is None: fig_path = img_folder.joinpath("{}.png".format(varname)) fig = plt.figure() nrows = 2 ncols = 2 gs = GridSpec(nrows, ncols=ncols + 1, width_ratios=[1, 1, 0.05]) xx, yy = basemap_info.get_proj_xy() cs = None for i, season in enumerate(season_to_error_field): row = i // ncols col = i % ncols if axes_list is None: ax = fig.add_subplot(gs[row, col]) else: ax = axes_list[i] basemap_info.draw_map_background(ax) cs = basemap_info.basemap.contourf(xx, yy, season_to_error_field[season][:], ax=ax, cmap=cmap, levels=clevs, extend="both") basemap_info.basemap.drawcoastlines(ax=ax, linewidth=0.3) ax.set_title(season) if i == 0: ax.set_ylabel( infovar.get_long_display_label_for_var(varname=varname)) # basemap_info.basemap.colorbar(cs) if basemap_info.should_draw_basin_boundaries: basemap_info.basemap.readshapefile(BASIN_BOUNDARIES_SHP[:-4], "basin", ax=ax) # Hide snow plots for summer if varname in ["I5"] and season.lower() in ["summer"]: ax.set_visible(False) # Plot a colorbar for each subplot if required. if hasattr(basemap_info, "draw_colorbar_for_each_subplot"): if basemap_info.draw_colorbar_for_each_subplot: cb = basemap_info.basemap.colorbar(cs, ax=ax) cb.ax.set_title(infovar.get_units(var_name=varname)) cax = fig.add_subplot(gs[:, -1]) if axes_list is None else axes_list[-1] # Add the colorbar if there are additional axes supplied for it if len(axes_list) > len(season_to_error_field): cax.set_title(infovar.get_units(var_name=varname)) plt.colorbar(cs, cax=cax) if axes_list is None: with fig_path.open("wb") as figfile: fig.savefig(figfile, format="png", bbox_inches="tight") plt.close(fig) return cs