def get_diff_levels(key_to_data, ncolors=20, varname=""): """ get nice levels for the contourf plot :param field: :type key_to_data: dict """ locator = MaxNLocator(nbins=ncolors, symmetric=True) if varname in [ "TT", ]: return locator.tick_values(-7, 7) elif varname in [ "PR", ]: return locator.tick_values(-3, 3) delta = -1 for k, field in key_to_data.items(): if hasattr(field, "mask"): good_data = field[~field.mask] else: good_data = field.flatten() delta = max(np.round(np.percentile(np.abs(good_data), 95)), delta) return locator.tick_values(-delta, delta)
def set_xticks(self, ticks=None): if ticks: super(Radialplot, self).set_xticks(ticks) else: if self.transform == "linear": loc = MaxNLocator(5) ticks = loc.tick_values(0., self.max_x) ticks2 = loc.tick_values(min(self.sez), max(self.sez)) ticks2 = ticks2[::-1] ticks2[-1] = min(self.sez) super(Radialplot, self).set_xticks(1.0 / ticks2) labels = [str(int(val * 1e-6)) for val in ticks2] self.xaxis.set_ticklabels(labels) self.spines["bottom"].set_bounds(0., 1. / ticks2[-1]) self.set_xlabel(r'$\sigma$ (Myr)') elif self.transform == "logarithmic": loc = MaxNLocator(5) ticks = loc.tick_values(0., self.max_x) super(Radialplot, self).set_xticks(ticks) self.spines["bottom"].set_bounds(ticks[0], ticks[-1]) self.set_xlabel(r'$t / \sigma$') self._second_axis() elif self.transform == "arcsine": loc = MaxNLocator(5) ticks = loc.tick_values(0., self.max_x) super(Radialplot, self).set_xticks(ticks) labels = [str(int(val**2 / 4.0)) for val in ticks] self.xaxis.set_ticklabels(labels) self.spines["bottom"].set_bounds(ticks[0], ticks[-1]) self.set_xlabel("Ns + Ni")
def _second_axis(self): def tick_function(x): with np.errstate(divide='ignore'): v = 1. / x return [ "{0}%".format(int(val * 100)) if val != np.inf else "" for val in v ] twin_axis = self.twiny() twin_axis.set_xlim(self.get_xlim()) loc = MaxNLocator(5) ticks = loc.tick_values(0, self.max_x) twin_axis.spines["bottom"].set_bounds(ticks[0], ticks[-1]) twin_axis.xaxis.set_ticks_position("bottom") twin_axis.xaxis.set_label_position("bottom") twin_axis.tick_params(axis="x", direction="in", pad=-15) twin_axis.spines["bottom"].set_position(("axes", 0.)) twin_axis.set_frame_on(True) twin_axis.patch.set_visible(False) for key, sp in twin_axis.spines.items(): sp.set_visible(False) twin_axis.spines["bottom"].set_visible(True) twin_axis.set_xticks(ticks) twin_axis.set_xticklabels(tick_function(ticks)) twin_axis.set_xlabel(r'$\sigma / t$', labelpad=-30) self.taxis = twin_axis return
def ticks_locator(self, ticks=None): if not ticks: ages = self.ax._z2t(self.ax.z) start, end = np.int(np.rint(min(ages))), np.int(np.rint(max(ages))) loc = MaxNLocator() ticks = loc.tick_values(start, end) return ticks
def plot_comparisons_of_seasonal_sst_with_homa_obs(self, start_year=None, end_year=None, season_to_months=None, exp_label=""): model_data = self.get_seasonal_mean_lst(season_to_months=season_to_months, start_year=start_year, end_year=end_year) obs_sst_path = os.path.expanduser("~/skynet3_rech1/nemo_obs_for_validation/GreatLakes_2003_5km-2/sst-glk.nc") obs_data = self.read_and_interpolate_homa_data(path=obs_sst_path, start_year=start_year, end_year=end_year, season_to_months=season_to_months) plot_utils.apply_plot_params(font_size=10, width_pt=None, width_cm=20, height_cm=10) # calculate climatologic differences diff = {} for season in list(season_to_months.keys()): diff[season] = np.mean( [model_data[y][season] - obs_data[y][season] for y in range(start_year, end_year + 1)], axis=0) diff[season] = np.ma.masked_where(~self.lake_mask, diff[season]) the_field = diff[season] print("diff stats({}): min={}; max={}; avg={}".format( season, the_field.min(), the_field.max(), the_field.mean())) # plot seasonal biases xx, yy = self.basemap(self.lons.copy(), self.lats.copy()) # calculate difference ranges diff_max = 0 for season, the_diff in diff.items(): diff_max = max(np.percentile(np.abs(the_diff[~the_diff.mask]), 90), diff_max) diff_max = 5 locator = MaxNLocator(nbins=12, symmetric=True) bounds = locator.tick_values(-diff_max, diff_max) bn = BoundaryNorm(bounds, len(bounds) - 1) cmap = cm.get_cmap("RdBu_r", len(bounds) - 1) im = None fig = plt.figure() ncols = 2 # fig.suptitle(r"LST $\left({\rm ^\circ C}\right)$", font_properties=FontProperties(weight="bold")) gs = GridSpec(len(season_to_months) // ncols, ncols + 1, width_ratios=[1.0, ] * ncols + [0.05, ]) for i, season in enumerate(season_to_months.keys()): ax = fig.add_subplot(gs[i // ncols, i % ncols]) im = self.basemap.pcolormesh(xx, yy, diff[season][:], ax=ax, cmap=cmap, norm=bn) ax.set_title(season) self.basemap.drawcoastlines(ax=ax, linewidth=0.5) if not i: ax.set_ylabel("NEMO - Obs") cb = plt.colorbar(im, ticks=locator, cax=fig.add_subplot(gs[:, -1]), extend="both") nemo_img_dir = "nemo" if not os.path.isdir(nemo_img_dir): os.mkdir(nemo_img_dir) plt.tight_layout() fig.savefig(os.path.join(nemo_img_dir, "sst_homa_validation_{}.pdf".format(exp_label))) plt.show()
def get_boundary_norm(vmin, vmax, ncolors, exclude_zero=False, varname=None, difference=False): bounds = None # custom variable norms if difference: pass else: if varname == "TRAF": bounds = [0, 0.1, 0.5] + list(range(1, ncolors - 3)) + [ vmax, ] # temperature # Do not do anything if bounds were already calculated if bounds is None: if vmin * vmax >= 0: locator = MaxNLocator(ncolors) bounds = np.asarray(locator.tick_values(vmin, vmax)) elif exclude_zero: # implies that this is the case for difference delta = max(abs(vmax), abs(vmin)) assert ncolors % 2 == 1 d = 2.0 * delta / float(ncolors) print(d, np.log10(d)) ndec = -int(np.floor(np.log10(d))) print(ndec) d = np.round(d, decimals=ndec) assert d > 0 print("ncolors = {0}".format(ncolors)) negats = [-d / 2.0 - d * i for i in range((ncolors - 1) / 2)] bounds = negats[::-1] + [-the_bound for the_bound in negats] assert 0 not in bounds assert bounds[0] == -bounds[-1] else: locator = MaxNLocator(nbins=ncolors, symmetric=True) bounds = np.asarray(locator.tick_values(vmin, vmax)) return BoundaryNorm(bounds, ncolors=ncolors), bounds, bounds[0], bounds[-1]
def get_boundary_norm(vmin, vmax, ncolors, exclude_zero=False, varname = None, difference = False): bounds = None # custom variable norms if difference: pass else: if varname == "TRAF": bounds = [0, 0.1, 0.5] + list(range(1, ncolors - 3)) + [vmax, ] # temperature # Do not do anything if bounds were already calculated if bounds is None: if vmin * vmax >= 0: locator = MaxNLocator(ncolors) bounds = np.asarray(locator.tick_values(vmin, vmax)) elif exclude_zero: # implies that this is the case for difference delta = max(abs(vmax), abs(vmin)) assert ncolors % 2 == 1 d = 2.0 * delta / float(ncolors) print(d, np.log10(d)) ndec = -int(np.floor(np.log10(d))) print(ndec) d = np.round(d, decimals=ndec) assert d > 0 print("ncolors = {0}".format(ncolors)) negats = [-d / 2.0 - d * i for i in range((ncolors - 1) / 2)] bounds = negats[::-1] + [-the_bound for the_bound in negats] assert 0 not in bounds assert bounds[0] == -bounds[-1] else: locator = MaxNLocator(nbins=ncolors, symmetric=True) bounds = np.asarray(locator.tick_values(vmin, vmax)) return BoundaryNorm(bounds, ncolors=ncolors), bounds, bounds[0], bounds[-1]
def get_boundary_norm_using_all_vals(to_plot, ncolors): vmin = np.percentile(to_plot[~to_plot.mask], 5) vmax = np.percentile(to_plot[~to_plot.mask], 95) med = np.median(to_plot[~to_plot.mask]) locator = MaxNLocator(ncolors) bounds = locator.tick_values(vmin, vmax) return BoundaryNorm(bounds, ncolors=ncolors), bounds, bounds[0], bounds[-1]
def get_best_map_ticks(ax, transform=None): """ Use the matplotlib.ticker class to automatically set nice values for the major and minor ticks. Log axes generally come out nicely spaced without needing manual intervention. For particularly narrow latitude vs longitude plots the ticks can come out overlapped, so an exception is included to deal with this. """ from matplotlib.ticker import MaxNLocator max_x_bins = 9 max_y_bins = 7 # as plots are wider rather than taller lon_steps = [1, 3, 6, 9, 10] lat_steps = [1, 3, 6, 9, 10] variable_step = [1, 2, 4, 5, 10] xmin, xmax, ymin, ymax = ax.get_extent(crs=transform) # ymin, ymax = ax.get_ylim() if (xmax - xmin) < 5: lon_steps = variable_step if (ymax - ymin) < 5: lat_steps = variable_step # We need to make a special exception for particularly narrow and wide plots, which will be lat vs lon # preserving the aspect ratio. This gives more options for the spacing to try and find something that can use # the maximum number of bins. if (ymax - ymin) > 2.2 * (xmax - xmin): max_x_bins = 4 max_y_bins = 11 elif (xmax - xmin) > 2.2 * (ymax - ymin): max_x_bins = 14 max_y_bins = 4 lon_locator = MaxNLocator(nbins=max_x_bins, steps=lon_steps) lat_locator = MaxNLocator(nbins=max_y_bins, steps=lat_steps) lon_ticks = lon_locator.tick_values(xmin, xmax) # Prune any large longitude ticks lon_ticks = [t for t in lon_ticks if abs(t) <= 360.0] lat_ticks = lat_locator.tick_values(ymin, ymax) # Prune any large latitude ticks lat_ticks = [t for t in lat_ticks if abs(t) <= 90.0] return lon_ticks, lat_ticks
def get_diff_levels(key_to_data, ncolors=20, varname=""): """ get nice levels for the contourf plot :param field: :type key_to_data: dict """ locator = MaxNLocator(nbins=ncolors, symmetric=True) if varname in ["TT", ]: return locator.tick_values(-7, 7) elif varname in ["PR", ]: return locator.tick_values(-3, 3) delta = -1 for k, field in key_to_data.items(): if hasattr(field, "mask"): good_data = field[~field.mask] else: good_data = field.flatten() delta = max(np.round(np.percentile(np.abs(good_data), 95)), delta) return locator.tick_values(-delta, delta)
def get_colormap_and_norm_for(var_name, to_plot=None, ncolors=10, vmin=None, vmax=None): """ If vmin or vmax is None then to_plot parameter is required :param var_name: :param ncolors: Number of discrete colors in the colorbar, try to take a good number like 10, 5, ... :return: Note: when `var_name` is STFL, the parameter ncolors is ignored """ if None in [vmin, vmax]: vmin, vmax = to_plot.min(), to_plot.max() locator = MaxNLocator(ncolors) clevs = locator.tick_values(vmin, vmax) if var_name in ["STFL", "STFA"]: upper = 1000 bounds = [0, 100, 200, 500, 1000] while upper <= vmax: upper += 1000 bounds.append(upper) ncolors = len(bounds) - 1 cmap = cm.get_cmap("Blues", ncolors) norm = BoundaryNorm( bounds, ncolors=ncolors ) # LogNorm(vmin=10 ** (pmax - ncolors), vmax=10 ** pmax) else: reverse = True # if var_name in ["PR"]: # reverse = False cmap = cm.get_cmap("Spectral_r" if reverse else "Spectral", len(clevs) - 1) # norm, bounds, vmin_nice, vmax_nice = get_boundary_norm_using_all_vals(to_plot, ncolors) norm = BoundaryNorm(clevs, len(clevs) - 1) return cmap, norm
class mpl_breaks: """ Compute breaks using MPL's default locator See :class:`~matplotlib.ticker.MaxNLocator` for the parameter descriptions Examples -------- >>> x = range(10) >>> limits = (0, 9) >>> mpl_breaks()(limits) array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) >>> mpl_breaks(nbins=2)(limits) array([ 0., 5., 10.]) """ def __init__(self, *args, **kwargs): self.locator = MaxNLocator(*args, **kwargs) def __call__(self, limits): """ Compute breaks Parameters ---------- limits : tuple Minimum and maximum values Returns ------- out : array_like Sequence of breaks points """ if any(np.isinf(limits)): return [] if limits[0] == limits[1]: return np.array([limits[0]]) return self.locator.tick_values(limits[0], limits[1])
def get_colormap_and_norm_for(var_name, to_plot=None, ncolors=10, vmin=None, vmax=None): """ If vmin or vmax is None then to_plot parameter is required :param var_name: :param ncolors: Number of discrete colors in the colorbar, try to take a good number like 10, 5, ... :return: Note: when `var_name` is STFL, the parameter ncolors is ignored """ if None in [vmin, vmax]: vmin, vmax = to_plot.min(), to_plot.max() locator = MaxNLocator(ncolors) clevs = locator.tick_values(vmin, vmax) if var_name in ["STFL", "STFA"]: upper = 1000 bounds = [0, 100, 200, 500, 1000] while upper <= vmax: upper += 1000 bounds.append(upper) ncolors = len(bounds) - 1 cmap = cm.get_cmap("Blues", ncolors) norm = BoundaryNorm(bounds, ncolors=ncolors) # LogNorm(vmin=10 ** (pmax - ncolors), vmax=10 ** pmax) else: reverse = True # if var_name in ["PR"]: # reverse = False cmap = cm.get_cmap("Spectral_r" if reverse else "Spectral", len(clevs) - 1) # norm, bounds, vmin_nice, vmax_nice = get_boundary_norm_using_all_vals(to_plot, ncolors) norm = BoundaryNorm(clevs, len(clevs) - 1) return cmap, norm
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 main(): start_year_c = 1980 end_year_c = 2010 img_folder = "cc_paper" current_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/cc-canesm2-driven/quebec_0.1_crcm5-hcd-rl-intfl-cc-canesm2-1980-2010.hdf5" base_label = "CRCM5-LI" # Need to read land fraction geo_file_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/pm1979010100_00000000p" r_obj = RPN(geo_file_path) mg_field = r_obj.get_first_record_for_name("MG") lons, lats = r_obj.get_longitudes_and_latitudes_for_the_last_read_rec() r_obj.close() future_shift_years = 90 params = dict(data_path=current_path, start_year=start_year_c, end_year=end_year_c, label=base_label) base_config_c = RunConfig(**params) base_config_f = base_config_c.get_shifted_config(future_shift_years) varname = "INTF" level = 0 daily_dates, intf_c = analysis.get_daily_climatology( path_to_hdf_file=base_config_c.data_path, var_name=varname, level=level, start_year=base_config_c.start_year, end_year=base_config_c.end_year) _, intf_f = analysis.get_daily_climatology( path_to_hdf_file=base_config_f.data_path, var_name=varname, level=level, start_year=base_config_f.start_year, end_year=base_config_f.end_year) mg_fields = np.asarray([mg_field for d in daily_dates]) mg_crit = 0.0001 the_mask = mg_fields <= mg_crit # Convert to mm/day as well intf_c = _avg_along_lon(intf_c, the_mask) * 24 * 3600 intf_f = _avg_along_lon(intf_f, the_mask) * 24 * 3600 lats_agg = lats.mean(axis=0) num_dates = date2num(daily_dates) lats_agg_2d, num_dates_2d = np.meshgrid(lats_agg, num_dates) # Do the plotting fig = plt.figure() gs = GridSpec(2, 3, width_ratios=[1, 1, 0.05]) norm = SymLogNorm(5e-5) all_axes = [] # Current ax = fig.add_subplot(gs[0, 0]) cs = ax.contourf(num_dates_2d, lats_agg_2d, intf_c[:], 60, norm=norm) ax.set_title("Current ({}-{})".format(base_config_c.start_year, base_config_c.end_year)) all_axes.append(ax) # Future ax = fig.add_subplot(gs[0, 1]) ax.set_title("Future ({}-{})".format(base_config_f.start_year, base_config_f.end_year)) cs = ax.contourf(num_dates_2d, lats_agg_2d, intf_f[:], levels=cs.levels, norm=norm) all_axes.append(ax) # Colorbar for value plots cax = fig.add_subplot(gs[0, 2]) sfmt = ScalarFormatter(useMathText=True) sfmt.set_powerlimits((-1, 2)) plt.colorbar(cs, cax=cax, format=sfmt) cax.set_xlabel("mm/day") cax.yaxis.get_offset_text().set_position((-2, 10)) # CC diff_cmap = cm.get_cmap("RdBu_r", 20) diff = (intf_f - intf_c) / (0.5 * (intf_c + intf_f)) * 100 diff[(intf_f == 0) & (intf_c == 0)] = 0 print(np.min(diff), np.max(diff)) print(np.any(diff.mask)) print(np.any(intf_c.mask)) print(np.any(intf_f.mask)) delta = 200 vmin = -delta vmax = delta locator = MaxNLocator(nbins=20, symmetric=True) clevs = locator.tick_values(vmin=vmin, vmax=vmax) ax = fig.add_subplot(gs[1, 1]) cs = ax.contourf(num_dates_2d, lats_agg_2d, diff, cmap=diff_cmap, levels=clevs, extend="both") ax.set_title("Future - Current") # ax.set_aspect("auto") all_axes.append(ax) cb = plt.colorbar(cs, cax=fig.add_subplot(gs[1, -1])) cb.ax.set_xlabel(r"%") for i, the_ax in enumerate(all_axes): the_ax.xaxis.set_minor_formatter( FuncFormatter(lambda d, pos: num2date(d).strftime("%b")[0])) the_ax.xaxis.set_major_formatter(FuncFormatter(lambda d, pos: "")) the_ax.xaxis.set_minor_locator(MonthLocator(bymonthday=15)) the_ax.xaxis.set_major_locator(MonthLocator()) the_ax.grid() if i != 1: the_ax.set_ylabel(r"Latitude ${\rm \left(^\circ N \right)}$") # identify approximately the melting period and lower latitudes march1 = date2num(datetime(daily_dates[0].year, 3, 1)) june1 = date2num(datetime(daily_dates[0].year, 6, 1)) sel_mask = (num_dates_2d >= march1) & (num_dates_2d < june1) & (lats_agg_2d <= 50) print("Mean interflow decrease in the southern regions: {}%".format( diff[sel_mask].mean())) # identify the regions of max interflow rates in current and future climates lat_min = 55 lat_max = 57.5 may1 = date2num(datetime(daily_dates[0].year, 5, 1)) july1 = date2num(datetime(daily_dates[0].year, 7, 1)) mean_max_current = intf_c[(lats_agg_2d >= lat_min) & (lats_agg_2d <= lat_max) & (num_dates_2d <= july1) & (num_dates_2d >= june1)].mean() mean_max_future = intf_f[(lats_agg_2d >= lat_min) & (lats_agg_2d <= lat_max) & (num_dates_2d <= june1) & (num_dates_2d >= may1)].mean() print("Mean change in the maximum interflow rate: {} %".format( (mean_max_future - mean_max_current) * 100 / mean_max_current)) img_file = Path(img_folder).joinpath("INTF_rate_longit_avg.png") fig.tight_layout() from crcm5.analyse_hdf import common_plot_params fig.savefig(str(img_file), bbox_inches="tight", transparent=True, dpi=common_plot_params.FIG_SAVE_DPI)
def main(): start_year_c = 1980 end_year_c = 2010 img_folder = "cc_paper" current_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/cc-canesm2-driven/quebec_0.1_crcm5-hcd-rl-cc-canesm2-1980-2010.hdf5" base_label = "CRCM5-L" # Need to read land fraction geo_file_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/pm1979010100_00000000p" r_obj = RPN(geo_file_path) mg_field = r_obj.get_first_record_for_name("MG") lons, lats = r_obj.get_longitudes_and_latitudes_for_the_last_read_rec() r_obj.close() future_shift_years = 75 params = dict(data_path=current_path, start_year=start_year_c, end_year=end_year_c, label=base_label) base_config_c = RunConfig(**params) base_config_f = base_config_c.get_shifted_config(future_shift_years) data_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/cc-canesm2-driven/quebec_0.1_crcm5-hcd-rl-intfl-cc-canesm2-1980-2010.hdf5" params.update(dict(data_path=data_path, label="CRCM5-LI")) modif_config_c = RunConfig(**params) modif_config_f = modif_config_c.get_shifted_config(future_shift_years) varnames = ["I1+I2", "I0", "PR", "TRAF", "AV", "I0_max", "I0_min"] levels = [0, 0, 0, 0, 0, 0, 0] var_labels = ["SM", "ST", "PR", "TRAF", "LHF", "STmin", "STmax"] # width of the first soil layer in mm multipliers = [100, 1, 1000 * 24 * 3600, 24 * 3600, 1, 1, 1] offsets = [ 0, ] * len(varnames) units = ["mm", "K", "mm/day", "mm/day", r"${\rm W/m^2}$", "K", "K"] SimData = collections.namedtuple("SimData", "base_c base_f modif_c modif_f") mg_fields = None fig = plt.figure() gs = GridSpec(len(varnames), 5, width_ratios=2 * [ 1, ] + [0.05, 1, 0.05]) lats_agg = lats.mean(axis=0) diff_cmap = cm.get_cmap("RdBu_r", 10) the_zip = zip(varnames, levels, var_labels, multipliers, offsets, units) row = 0 for vname, level, var_label, multiplier, offset, unit_label in the_zip: daily_dates, base_data_c = analysis.get_daily_climatology( path_to_hdf_file=base_config_c.data_path, var_name=vname, level=level, start_year=base_config_c.start_year, end_year=base_config_c.end_year) _, base_data_f = analysis.get_daily_climatology( path_to_hdf_file=base_config_f.data_path, var_name=vname, level=level, start_year=base_config_f.start_year, end_year=base_config_f.end_year) _, modif_data_c = analysis.get_daily_climatology( path_to_hdf_file=modif_config_c.data_path, var_name=vname, level=level, start_year=modif_config_c.start_year, end_year=modif_config_c.end_year) _, modif_data_f = analysis.get_daily_climatology( path_to_hdf_file=modif_config_f.data_path, var_name=vname, level=level, start_year=modif_config_f.start_year, end_year=modif_config_f.end_year) if mg_fields is None: mg_fields = np.asarray([mg_field for d in daily_dates]) num_dates = date2num(daily_dates) # create 2d dates and latitudes for the contour plots lats_agg_2d, num_dates_2d = np.meshgrid(lats_agg, num_dates) sim_data = SimData(_avg_along_lon(base_data_c, mg_fields), _avg_along_lon(base_data_f, mg_fields), _avg_along_lon(modif_data_c, mg_fields), _avg_along_lon(modif_data_f, mg_fields)) # Unit conversion sim_data = SimData(*[multiplier * si + offset for si in sim_data]) # Plot the row for the variable all_axes = [] # Calculate nice color levels delta = np.percentile( np.abs([ sim_data.modif_c - sim_data.base_c, sim_data.modif_f - sim_data.base_f ]), 99) vmin = -delta vmax = delta locator = MaxNLocator(nbins=10, symmetric=True) clevs = locator.tick_values(vmin=vmin, vmax=vmax) # Current ax = fig.add_subplot(gs[row, 0]) cs = ax.contourf(num_dates_2d, lats_agg_2d, sim_data.modif_c - sim_data.base_c, extend="both", levels=clevs, cmap=diff_cmap) if row == 0: ax.set_title("Current ({}-{})".format(base_config_c.start_year, base_config_c.end_year)) all_axes.append(ax) # Future ax = fig.add_subplot(gs[row, 1]) if row == 0: ax.set_title("Future ({}-{})".format(base_config_f.start_year, base_config_f.end_year)) cs = ax.contourf(num_dates_2d, lats_agg_2d, sim_data.modif_f - sim_data.base_f, levels=cs.levels, extend="both", cmap=diff_cmap) all_axes.append(ax) # Colorbar for value plots cax = fig.add_subplot(gs[row, 2]) plt.colorbar(cs, cax=cax) cax.set_title("{} ({})\n".format(var_label, unit_label)) diff = (sim_data.modif_f - sim_data.base_f) - (sim_data.modif_c - sim_data.base_c) delta = np.percentile(np.abs(diff), 99) vmin = -delta vmax = delta locator = MaxNLocator(nbins=10, symmetric=True) clevs = locator.tick_values(vmin=vmin, vmax=vmax) ax = fig.add_subplot(gs[row, 3]) cs = ax.contourf(num_dates_2d, lats_agg_2d, diff, cmap=diff_cmap, levels=clevs, extend="both") all_axes.append(ax) cb = plt.colorbar(cs, cax=fig.add_subplot(gs[row, 4])) if row == 0: ax.set_title("Future - Current") cb.ax.set_title("{}\n".format(unit_label)) for i, the_ax in enumerate(all_axes): the_ax.xaxis.set_major_formatter(DateFormatter("%b")) the_ax.xaxis.set_major_locator(MonthLocator(interval=2)) the_ax.grid() if i == 0: the_ax.set_ylabel("Latitude") row += 1 fig.tight_layout() img_path = Path(img_folder).joinpath( "{}_long_avg_intf_impact_{}-{}_vs_{}-{}.png".format( "_".join(varnames), base_config_f.start_year, base_config_f.end_year, base_config_c.start_year, base_config_c.end_year)) fig.savefig(str(img_path), bbox_inches="tight")
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 auto_set_ticks(self): """ Use the matplotlib.ticker class to automatically set nice values for the major and minor ticks. Log axes generally come out nicely spaced without needing manual intervention. For particularly narrow latitude vs longitude plots the ticks can come out overlapped, so an exception is included to deal with this. """ from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter y_variable = self.plot_args['y_variable'].lower() x_variable = self.plot_args['x_variable'].lower() ymin, ymax = self.matplotlib.ylim() # Matplotlib xlim doesn't work with cartopy plots xmin, xmax = self.xmin, self.xmax # xmin, xmax = self.matplotlib.xlim() max_x_bins = 9 max_y_bins = 9 xsteps = self.plot_args['xrange'].get('xstep', None) ysteps = self.plot_args['yrange'].get('ystep', None) lon_steps = [1, 3, 6, 9, 10] lat_steps = [1, 3, 6, 9, 10] variable_step = [1, 2, 4, 5, 10] if (xmax - xmin) < 5: lon_steps = variable_step if (ymax - ymin) < 5: lat_steps = variable_step # We need to make a special exception for particularly narrow and wide plots, which will be lat vs lon # preserving the aspect ratio. This gives more options for the spacing to try and find something that can use # the maximum number of bins. if x_variable.startswith('lon') and y_variable.startswith('lat'): max_y_bins = 7 # as plots are wider rather than taller if (ymax - ymin) > 2.2 * (xmax - xmin): max_x_bins = 4 max_y_bins = 11 elif (xmax - xmin) > 2.2 * (ymax - ymin): max_x_bins = 14 max_y_bins = 4 lat_or_lon = 'lat', 'lon' if xsteps is None and not self.plot_args['logx']: if self.plot_args['x_variable'].lower().startswith(lat_or_lon): lon_locator = MaxNLocator(nbins=max_x_bins, steps=lon_steps) if self.is_map(): self.cartopy_axis.set_xticks(lon_locator.tick_values(xmin, xmax), crs=self.transform) self.cartopy_axis.xaxis.set_major_formatter(LongitudeFormatter()) else: self.matplotlib.axes().xaxis.set_major_locator(lon_locator) else: self.matplotlib.axes().xaxis.set_major_locator(MaxNLocator(nbins=max_x_bins, steps=variable_step)) if not self.is_map(): self.matplotlib.axes().xaxis.set_minor_locator(AutoMinorLocator()) self.matplotlib.axes().xaxis.grid(False, which='minor') if ysteps is None and not self.plot_args['logy']: if y_variable.startswith(lat_or_lon): lat_locator = MaxNLocator(nbins=max_y_bins, steps=lat_steps) if self.is_map(): self.cartopy_axis.set_yticks(lat_locator.tick_values(ymin, ymax), crs=self.transform) self.cartopy_axis.yaxis.set_major_formatter(LatitudeFormatter()) else: self.matplotlib.axes().yaxis.set_major_locator(lat_locator) else: self.matplotlib.axes().yaxis.set_major_locator(MaxNLocator(nbins=max_y_bins, steps=variable_step)) if not self.is_map(): self.matplotlib.axes().yaxis.set_minor_locator(AutoMinorLocator()) self.matplotlib.axes().yaxis.grid(False, which='minor')
def plot_profiles(): obs_base_dir = Path("/home/huziy/skynet3_rech1/nemo_obs_for_validation/data_from_Ram_Yerubandi/ADCP-profiles") obs_dir_list = [ str(obs_base_dir.joinpath("105.317")), str(obs_base_dir.joinpath("155.289")) ] obs_var_col = AdcpProfileObs.vmag_col model_var_name = FLOW_SPEED model_folder = "/home/huziy/skynet3_rech1/offline_glk_output_daily_1979-2012" manager_nemo_u = NemoYearlyFilesManager(folder=model_folder, suffix="_U.nc") manager_nemo_v = NemoYearlyFilesManager(folder=model_folder, suffix="_V.nc") manager_nemo_w = NemoYearlyFilesManager(folder=model_folder, suffix="_W.nc") fig = plt.figure() gs = GridSpec(len(obs_dir_list), 5, width_ratios=[1, 1, 0.05, 1, 0.05]) cmap = cm.get_cmap("jet", 10) diff_cmap = cm.get_cmap("RdBu_r", 10) for i, obs_dir in enumerate(obs_dir_list): adcp = AdcpProfileObs() dates, levels, obs_data = adcp.get_acdp_profiles(folder=obs_dir, data_column=obs_var_col) dates_m, levs_m, u_cs = manager_nemo_u.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vozocrtx", zlist=levels ) dates_m, levs_m, v_cs = manager_nemo_v.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vomecrty", zlist=levels ) dates_m, levs_m, w_cs = manager_nemo_w.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vovecrtz", zlist=levels ) numdates = date2num(dates.tolist()) print("Obs dates are: {} ... {}".format(dates[0], dates[-1])) print([num2date([n for n in numdates if n not in dates_m])]) zz, tt = np.meshgrid(levels, numdates) umag_mod_cs = (u_cs ** 2 + v_cs ** 2 + w_cs ** 2) ** 0.5 * 100.0 all_axes = [] # Obs ax = fig.add_subplot(gs[i, 0]) ax.set_title("Obs") cs = ax.contourf(tt, zz, obs_data, cmap=cmap) ax.set_ylabel("({:.1f}, {:.1f})".format(adcp.longitude, adcp.latitude)) all_axes.append(ax) # Model ax = fig.add_subplot(gs[i, 1]) ax.set_title("NEMO-offline") cs = ax.contourf(tt, zz, umag_mod_cs, levels=cs.levels, cmap=cmap) all_axes.append(ax) plt.colorbar(cs, cax=fig.add_subplot(gs[i, 2])) # Bias ax = fig.add_subplot(gs[i, 3]) ax.set_title("Model - Obs.") delta = umag_mod_cs - obs_data vmax = np.abs(delta).max() vmin = -vmax locator = MaxNLocator(nbins=diff_cmap.N, symmetric=True) cs = ax.contourf(tt, zz, delta, levels=locator.tick_values(vmin, vmax), cmap=diff_cmap) plt.colorbar(cs, cax=fig.add_subplot(gs[i, 4])) all_axes.append(ax) for the_ax in all_axes: the_ax.xaxis.set_major_formatter(DateFormatter("%b")) the_ax.xaxis.set_major_locator(MonthLocator()) the_ax.invert_yaxis() img_folder = Path("nemo/adcp") if not img_folder.is_dir(): img_folder.mkdir(parents=True) img_file = img_folder.joinpath("adcp_profiles.pdf") fig.tight_layout() fig.savefig(str(img_file), bbox_inches="tight")
def plot_comparisons_of_seasonal_sst_with_homa_obs(self, start_year=None, end_year=None, season_to_months=None, exp_label=""): model_data = self.get_seasonal_mean_lst( season_to_months=season_to_months, start_year=start_year, end_year=end_year) obs_sst_path = os.path.expanduser( "~/skynet3_rech1/nemo_obs_for_validation/GreatLakes_2003_5km-2/sst-glk.nc" ) obs_data = self.read_and_interpolate_homa_data( path=obs_sst_path, start_year=start_year, end_year=end_year, season_to_months=season_to_months) plot_utils.apply_plot_params(font_size=10, width_pt=None, width_cm=20, height_cm=10) # calculate climatologic differences diff = {} for season in list(season_to_months.keys()): diff[season] = np.mean([ model_data[y][season] - obs_data[y][season] for y in range(start_year, end_year + 1) ], axis=0) diff[season] = np.ma.masked_where(~self.lake_mask, diff[season]) the_field = diff[season] print("diff stats({}): min={}; max={}; avg={}".format( season, the_field.min(), the_field.max(), the_field.mean())) # plot seasonal biases xx, yy = self.basemap(self.lons.copy(), self.lats.copy()) # calculate difference ranges diff_max = 0 for season, the_diff in diff.items(): diff_max = max(np.percentile(np.abs(the_diff[~the_diff.mask]), 90), diff_max) diff_max = 5 locator = MaxNLocator(nbins=12, symmetric=True) bounds = locator.tick_values(-diff_max, diff_max) bn = BoundaryNorm(bounds, len(bounds) - 1) cmap = cm.get_cmap("RdBu_r", len(bounds) - 1) im = None fig = plt.figure() ncols = 2 # fig.suptitle(r"LST $\left({\rm ^\circ C}\right)$", font_properties=FontProperties(weight="bold")) gs = GridSpec(len(season_to_months) // ncols, ncols + 1, width_ratios=[ 1.0, ] * ncols + [ 0.05, ]) for i, season in enumerate(season_to_months.keys()): ax = fig.add_subplot(gs[i // ncols, i % ncols]) im = self.basemap.pcolormesh(xx, yy, diff[season][:], ax=ax, cmap=cmap, norm=bn) ax.set_title(season) self.basemap.drawcoastlines(ax=ax, linewidth=0.5) if not i: ax.set_ylabel("NEMO - Obs") cb = plt.colorbar(im, ticks=locator, cax=fig.add_subplot(gs[:, -1]), extend="both") nemo_img_dir = "nemo" if not os.path.isdir(nemo_img_dir): os.mkdir(nemo_img_dir) plt.tight_layout() fig.savefig( os.path.join(nemo_img_dir, "sst_homa_validation_{}.pdf".format(exp_label))) plt.show()
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 _get_ticks_by_num(vmin, vmax, numticks): from matplotlib.ticker import MaxNLocator locator = MaxNLocator(nbins=numticks, steps=[1,1.5,2,2.5,3,4,5,6,7.5,8,10], prune=None) return locator.tick_values(vmin, vmax)
def plot_profiles(): obs_base_dir = Path("/home/huziy/skynet3_rech1/nemo_obs_for_validation/data_from_Ram_Yerubandi/ADCP-profiles") obs_dir_list = [ str(obs_base_dir.joinpath("105.317")), str(obs_base_dir.joinpath("155.289")) ] obs_var_col = AdcpProfileObs.vmag_col model_var_name = FLOW_SPEED # model_folder = "/home/huziy/skynet3_rech1/offline_glk_output_daily_1979-2012" model_folder = "/RESCUE/skynet3_rech1/huziy/NEMO_OFFICIAL/dev_v3_4_STABLE_2012/NEMOGCM/CONFIG/GLK_LIM3/EXP_GLK_LIM3_1980/zdf_gls_dt_and_sbc_5min" manager_nemo_u = NemoYearlyFilesManager(folder=model_folder, suffix="_U.nc") manager_nemo_v = NemoYearlyFilesManager(folder=model_folder, suffix="_V.nc") manager_nemo_w = NemoYearlyFilesManager(folder=model_folder, suffix="_W.nc") fig = plt.figure() gs = GridSpec(len(obs_dir_list), 5, width_ratios=[1, 1, 0.05, 1, 0.05]) cmap = cm.get_cmap("jet", 10) diff_cmap = cm.get_cmap("RdBu_r", 10) for i, obs_dir in enumerate(obs_dir_list): adcp = AdcpProfileObs() dates, levels, obs_data = adcp.get_acdp_profiles(folder=obs_dir, data_column=obs_var_col) dates_m, levs_m, u_cs = manager_nemo_u.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vozocrtx", zlist=levels ) dates_m, levs_m, v_cs = manager_nemo_v.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vomecrty", zlist=levels ) dates_m, levs_m, w_cs = manager_nemo_w.get_tz_crosssection_for_the_point( lon=adcp.longitude, lat=adcp.latitude, start_date=dates[0], end_date=dates[-1], var_name="vovecrtz", zlist=levels ) numdates = date2num(dates.tolist()) print("Obs dates are: {} ... {}".format(dates[0], dates[-1])) print([num2date([n for n in numdates if n not in dates_m])]) zz, tt = np.meshgrid(levels, numdates) umag_mod_cs = (u_cs ** 2 + v_cs ** 2 + w_cs ** 2) ** 0.5 * 100.0 all_axes = [] # Obs ax = fig.add_subplot(gs[i, 0]) ax.set_title("Obs") cs = ax.contourf(tt, zz, obs_data, cmap=cmap) ax.set_ylabel("({:.1f}, {:.1f})".format(adcp.longitude, adcp.latitude)) all_axes.append(ax) # Model ax = fig.add_subplot(gs[i, 1]) ax.set_title("NEMO-offline") cs = ax.contourf(tt, zz, umag_mod_cs, levels=cs.levels, cmap=cmap) all_axes.append(ax) plt.colorbar(cs, cax=fig.add_subplot(gs[i, 2])) # Bias ax = fig.add_subplot(gs[i, 3]) ax.set_title("Model - Obs.") delta = umag_mod_cs - obs_data vmax = np.abs(delta).max() vmin = -vmax locator = MaxNLocator(nbins=diff_cmap.N, symmetric=True) cs = ax.contourf(tt, zz, delta, levels=locator.tick_values(vmin, vmax), cmap=diff_cmap) plt.colorbar(cs, cax=fig.add_subplot(gs[i, 4])) all_axes.append(ax) for the_ax in all_axes: the_ax.xaxis.set_major_formatter(DateFormatter("%b")) the_ax.xaxis.set_major_locator(MonthLocator()) the_ax.invert_yaxis() img_folder = Path("nemo/adcp/zdf_gls_dt_and_sbc_5min") if not img_folder.is_dir(): img_folder.mkdir(parents=True) img_file = img_folder.joinpath("adcp_profiles.pdf") fig.tight_layout() print("Saving plots to {}".format(img_file)) fig.savefig(str(img_file), bbox_inches="tight")
def validate_seas_mean_lswt_from_hostetler_and_nemo_with_homa( hl_data_path="/home/huziy/skynet3_rech1/CRCM_GL_simulation/all_files", start_year=2003, end_year=2006): crcm5_model_manager = Crcm5ModelDataManager(samples_folder_path=hl_data_path, all_files_in_samples_folder=True) varname = "L1" season = "Fall" season_to_months = {season: range(9, 11)} season_months = list(season_to_months[season]) print(season_months, season_to_months) hl_lake_temp_clim = crcm5_model_manager.get_mean_field(start_year=start_year, end_year=end_year, var_name=varname, level=1.1, months=season_months) hl_lake_temp_clim = hl_lake_temp_clim[13:-13, 13:-13] print("hl_lake_temp_clim.shape = ", hl_lake_temp_clim.shape) lon_hl, lat_hl = crcm5_model_manager.lons2D, crcm5_model_manager.lats2D print("lon_hl.shape = ", lon_hl.shape) print(lon_hl.min(), lon_hl.max()) print(lat_hl.min(), lat_hl.max()) # Get Nemo manager here only for coordinates and mask nemo_manager = NemoYearlyFilesManager(folder="/home/huziy/skynet3_rech1/offline_glk_output_daily_1979-2012", suffix="icemod.nc") lon2d, lat2d, bmp = nemo_manager.get_coords_and_basemap() # Interpolate hostetler's lake fraction to the model's grid hl_lake_temp_clim -= 273.15 xs, ys, zs = lat_lon.lon_lat_to_cartesian(lon_hl.flatten(), lat_hl.flatten()) print(xs.shape) ktree = cKDTree(data=list(zip(xs, ys, zs))) xt, yt, zt = lat_lon.lon_lat_to_cartesian(lon2d.flatten(), lat2d.flatten()) dists, inds = ktree.query(np.asarray(list(zip(xt, yt, zt)))) print(inds[:20]) print(type(inds)) print(inds.min(), inds.max()) hl_lake_temp_clim = hl_lake_temp_clim.flatten()[inds].reshape(lon2d.shape) # get nemo and observed sst obs_sst, nemo_sst, _, _, _ = nemo_manager.get_nemo_and_homa_seasonal_mean_sst(start_year=start_year, end_year=end_year, season_to_months=season_to_months) obs_sst_clim = np.ma.mean([obs_sst[y][season] for y in range(start_year, end_year + 1)], axis=0) nemo_sst_clim = np.ma.mean([nemo_sst[y][season] for y in range(start_year, end_year + 1)], axis=0) obs_sst_clim = np.ma.masked_where(~nemo_manager.lake_mask, obs_sst_clim) nemo_sst_clim = np.ma.masked_where(~nemo_manager.lake_mask, nemo_sst_clim) hl_lake_temp_clim = np.ma.masked_where(~nemo_manager.lake_mask, hl_lake_temp_clim) # plt.figure() xx, yy = bmp(lon2d.copy(), lat2d.copy()) # im = bmp.pcolormesh(xx, yy, model_yearmax_ice_conc) # bmp.colorbar(im) vmin = min(obs_sst_clim.min(), nemo_sst_clim.min(), hl_lake_temp_clim.min()) vmax = max(obs_sst_clim.max(), nemo_sst_clim.max(), hl_lake_temp_clim.max()) print("vmin={}; vmax={}".format(vmin, vmax)) # plt.figure() # b = Basemap() # xx, yy = b(lons_obs, lats_obs) # im = b.pcolormesh(xx, yy, obs_yearmax_ice_conc) # b.colorbar(im) # b.drawcoastlines() # Plot as usual: model, obs, model - obs img_folder = Path("nemo/hostetler") if not img_folder.is_dir(): img_folder.mkdir() img_file = img_folder.joinpath("validate_{}_lswt_hostetler_nemo_vs_homa_{}-{}.png".format( season, start_year, end_year)) fig = plt.figure() gs = GridSpec(1, 4, width_ratios=[1, 1, 1, 0.05]) all_axes = [] cmap = cm.get_cmap("jet", 10) locator = MaxNLocator(nbins=10) ticks = locator.tick_values(vmin=vmin, vmax=vmax) norm = BoundaryNorm(boundaries=ticks, ncolors=len(ticks) - 1) # Model, Hostetler ax = fig.add_subplot(gs[0, 0]) ax.set_title("Hostetler+CRCM5") bmp.pcolormesh(xx, yy, hl_lake_temp_clim, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) all_axes.append(ax) # ax = fig.add_subplot(gs[0, 1]) ax.set_title("NEMO-offline") im = bmp.pcolormesh(xx, yy, nemo_sst_clim, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) all_axes.append(ax) # Obs: Homa ax = fig.add_subplot(gs[0, 2]) ax.set_title("MODIS") im = bmp.pcolormesh(xx, yy, obs_sst_clim, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) all_axes.append(ax) plt.colorbar(im, cax=fig.add_subplot(gs[0, -1]), ticks=ticks) for the_ax in all_axes: bmp.drawcoastlines(ax=the_ax) fig.savefig(str(img_file), bbox_inches="tight") plt.close(fig)
def validate_seas_mean_lswt_from_hostetler_and_nemo_with_homa( hl_data_path="/home/huziy/skynet3_rech1/CRCM_GL_simulation/all_files", start_year=2003, end_year=2009): crcm5_model_manager = Crcm5ModelDataManager(samples_folder_path=hl_data_path, all_files_in_samples_folder=True) varname = "sohefldo" season = "Summer" season_to_months = {season: range(6, 9)} season_months = list(season_to_months[season]) # Get Nemo manager here only for coordinates and mask nemo_offline_manager = NemoYearlyFilesManager(folder="/home/huziy/skynet3_rech1/offline_glk_output_daily_1979-2012", suffix="grid_T.nc") nemo_crcm5_manager = NemoYearlyFilesManager( folder="/home/huziy/skynet3_rech1/one_way_coupled_nemo_outputs_1979_1985", suffix="grid_T.nc") lon2d, lat2d, bmp = nemo_offline_manager.get_coords_and_basemap() # Interpolate # get nemo sst nemo_offline_sst = nemo_offline_manager.get_seasonal_clim_field(start_year=start_year, end_year=end_year, season_to_months=season_to_months, varname=varname) nemo_crcm5_sst = nemo_crcm5_manager.get_seasonal_clim_field(start_year=start_year, end_year=end_year, season_to_months=season_to_months, varname=varname) nemo_offline_sst = np.ma.masked_where(~nemo_offline_manager.lake_mask, nemo_offline_sst[season]) nemo_crcm5_sst = np.ma.masked_where(~nemo_offline_manager.lake_mask, nemo_crcm5_sst[season]) # plt.figure() xx, yy = bmp(lon2d.copy(), lat2d.copy()) # im = bmp.pcolormesh(xx, yy, model_yearmax_ice_conc) # bmp.colorbar(im) vmin = min(nemo_offline_sst.min(), nemo_crcm5_sst.min()) vmax = max(nemo_offline_sst.max(), nemo_crcm5_sst.max()) # plt.figure() # b = Basemap() # xx, yy = b(lons_obs, lats_obs) # im = b.pcolormesh(xx, yy, obs_yearmax_ice_conc) # b.colorbar(im) # b.drawcoastlines() # Plot as usual: model, obs, model - obs img_folder = Path("nemo") if not img_folder.is_dir(): img_folder.mkdir() img_file = img_folder.joinpath("{}_{}_nemo-offline_vs_nemo-crcm5_{}-{}.png".format(season.lower(), varname, start_year, end_year)) fig = plt.figure() gs = GridSpec(1, 3, width_ratios=[1, 1, 0.05]) all_axes = [] cmap = cm.get_cmap("jet", 10) locator = MaxNLocator(nbins=10) ticks = locator.tick_values(vmin=vmin, vmax=vmax) norm = BoundaryNorm(boundaries=ticks, ncolors=len(ticks) - 1) # Model, Hostetler ax = fig.add_subplot(gs[0, 0]) ax.set_title("NEMO+CRCM5") bmp.pcolormesh(xx, yy, nemo_crcm5_sst, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) all_axes.append(ax) # ax = fig.add_subplot(gs[0, 1]) ax.set_title("NEMO-offline") im = bmp.pcolormesh(xx, yy, nemo_offline_sst, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) all_axes.append(ax) # Obs: Homa # ax = fig.add_subplot(gs[0, 2]) # ax.set_title("MODIS") # im = bmp.pcolormesh(xx, yy, obs_sst_clim, cmap=cmap, vmin=vmin, vmax=vmax, norm=norm) # all_axes.append(ax) plt.colorbar(im, cax=fig.add_subplot(gs[0, -1]), ticks=ticks) for the_ax in all_axes: bmp.drawcoastlines(ax=the_ax) fig.savefig(str(img_file), bbox_inches="tight") plt.close(fig)
class AxisLocator(object): """Determine the location of ticks in a view. Constructor ----------- nbinsx : int Number of ticks on the x axis. nbinsy : int Number of ticks on the y axis. data_bounds : 4-tuple Initial coordinates of the viewport, as (xmin, ymin, xmax, ymax), in data coordinates. These are the data coordinates of the lower left and upper right points of the window. """ _default_nbinsx = 24 _default_nbinsy = 16 # ticks are extended beyond the viewport for smooth transition # when panzooming: -2, -1, 0, +1, +2 _bins_margin = 5 _default_steps = (1, 2, 2.5, 5, 10) def __init__(self, nbinsx=None, nbinsy=None, data_bounds=None): """data_bounds is the initial bounds of the view in data coordinates.""" self.data_bounds = data_bounds self._tr = Range(from_bounds=NDC, to_bounds=self.data_bounds) self._tri = self._tr.inverse() self.set_nbins(nbinsx, nbinsy) def set_nbins(self, nbinsx=None, nbinsy=None): """Change the number of bins on the x and y axes.""" nbinsx = self._bins_margin * nbinsx if _is_integer(nbinsx) else self._default_nbinsx nbinsy = self._bins_margin * nbinsy if _is_integer(nbinsy) else self._default_nbinsy self.locx = MaxNLocator(nbins=nbinsx, steps=self._default_steps) self.locy = MaxNLocator(nbins=nbinsy, steps=self._default_steps) def _transform_ticks(self, xticks, yticks): """Transform ticks from data coordinates to view coordinates.""" nx, ny = len(xticks), len(yticks) arr = np.zeros((nx + ny, 2)) arr[:nx, 0] = xticks arr[nx:, 1] = yticks out = self._tri.apply(arr) return out[:nx, 0], out[nx:, 1] def set_view_bounds(self, view_bounds=None): """Set the view bounds in normalized device coordinates. Used when panning and zooming. This method updates the following attributes: * xticks : the position of the ticks on the x axis * yticks : the position of the ticks on the y axis * xtext : the text of the ticks on the x axis * ytext : the text of the ticks on the y axis """ view_bounds = view_bounds or NDC x0, y0, x1, y1 = view_bounds dx = 2 * (x1 - x0) dy = 2 * (y1 - y0) # Get the bounds in data coordinates. ((dx0, dy0), (dx1, dy1)) = self._tr.apply([ [x0 - dx, y0 - dy], [x1 + dx, y1 + dy]]) # Compute the ticks in data coordinates. self.xticks = self.locx.tick_values(dx0, dx1) self.yticks = self.locy.tick_values(dy0, dy1) # Get the ticks in view coordinates. self.xticks_view, self.yticks_view = self._transform_ticks(self.xticks, self.yticks) # Get the text in data coordinates. fmt = '%.9g' self.xtext = [fmt % v for v in self.xticks] self.ytext = [fmt % v for v in self.yticks]
def main(): start_year_c = 1980 end_year_c = 2010 img_folder = "cc_paper" current_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/cc-canesm2-driven/quebec_0.1_crcm5-hcd-rl-intfl-cc-canesm2-1980-2010.hdf5" base_label = "CRCM5-LI" # Need to read land fraction geo_file_path = "/RESCUE/skynet3_rech1/huziy/hdf_store/pm1979010100_00000000p" r_obj = RPN(geo_file_path) mg_field = r_obj.get_first_record_for_name("MG") lons, lats = r_obj.get_longitudes_and_latitudes_for_the_last_read_rec() r_obj.close() future_shift_years = 90 params = dict( data_path=current_path, start_year=start_year_c, end_year=end_year_c, label=base_label ) base_config_c = RunConfig(**params) base_config_f = base_config_c.get_shifted_config(future_shift_years) varname = "INTF" level = 0 daily_dates, intf_c = analysis.get_daily_climatology(path_to_hdf_file=base_config_c.data_path, var_name=varname, level=level, start_year=base_config_c.start_year, end_year=base_config_c.end_year) _, intf_f = analysis.get_daily_climatology(path_to_hdf_file=base_config_f.data_path, var_name=varname, level=level, start_year=base_config_f.start_year, end_year=base_config_f.end_year) mg_fields = np.asarray([mg_field for d in daily_dates]) mg_crit = 0.0001 the_mask = mg_fields <= mg_crit # Convert to mm/day as well intf_c = _avg_along_lon(intf_c, the_mask) * 24 * 3600 intf_f = _avg_along_lon(intf_f, the_mask) * 24 * 3600 lats_agg = lats.mean(axis=0) num_dates = date2num(daily_dates) lats_agg_2d, num_dates_2d = np.meshgrid(lats_agg, num_dates) # Do the plotting fig = plt.figure() gs = GridSpec(2, 3, width_ratios=[1, 1, 0.05]) norm = SymLogNorm(5e-5) all_axes = [] # Current ax = fig.add_subplot(gs[0, 0]) cs = ax.contourf(num_dates_2d, lats_agg_2d, intf_c[:], 60, norm=norm) ax.set_title("Current ({}-{})".format( base_config_c.start_year, base_config_c.end_year)) all_axes.append(ax) # Future ax = fig.add_subplot(gs[0, 1]) ax.set_title("Future ({}-{})".format( base_config_f.start_year, base_config_f.end_year)) cs = ax.contourf(num_dates_2d, lats_agg_2d, intf_f[:], levels=cs.levels, norm=norm) all_axes.append(ax) # Colorbar for value plots cax = fig.add_subplot(gs[0, 2]) sfmt = ScalarFormatter(useMathText=True) sfmt.set_powerlimits((-1, 2)) plt.colorbar(cs, cax=cax, format=sfmt) cax.set_xlabel("mm/day") cax.yaxis.get_offset_text().set_position((-2, 10)) # CC diff_cmap = cm.get_cmap("RdBu_r", 20) diff = (intf_f - intf_c) / (0.5 * (intf_c + intf_f)) * 100 diff[(intf_f == 0) & (intf_c == 0)] = 0 print(np.min(diff), np.max(diff)) print(np.any(diff.mask)) print(np.any(intf_c.mask)) print(np.any(intf_f.mask)) delta = 200 vmin = -delta vmax = delta locator = MaxNLocator(nbins=20, symmetric=True) clevs = locator.tick_values(vmin=vmin, vmax=vmax) ax = fig.add_subplot(gs[1, 1]) cs = ax.contourf(num_dates_2d, lats_agg_2d, diff, cmap=diff_cmap, levels=clevs, extend="both") ax.set_title("Future - Current") # ax.set_aspect("auto") all_axes.append(ax) cb = plt.colorbar(cs, cax=fig.add_subplot(gs[1, -1])) cb.ax.set_xlabel(r"%") for i, the_ax in enumerate(all_axes): the_ax.xaxis.set_minor_formatter(FuncFormatter(lambda d, pos: num2date(d).strftime("%b")[0])) the_ax.xaxis.set_major_formatter(FuncFormatter(lambda d, pos: "")) the_ax.xaxis.set_minor_locator(MonthLocator(bymonthday=15)) the_ax.xaxis.set_major_locator(MonthLocator()) the_ax.grid() if i != 1: the_ax.set_ylabel(r"Latitude ${\rm \left(^\circ N \right)}$") # identify approximately the melting period and lower latitudes march1 = date2num(datetime(daily_dates[0].year, 3, 1)) june1 = date2num(datetime(daily_dates[0].year, 6, 1)) sel_mask = (num_dates_2d >= march1) & (num_dates_2d < june1) & (lats_agg_2d <= 50) print("Mean interflow decrease in the southern regions: {}%".format(diff[sel_mask].mean())) # identify the regions of max interflow rates in current and future climates lat_min = 55 lat_max = 57.5 may1 = date2num(datetime(daily_dates[0].year, 5, 1)) july1 = date2num(datetime(daily_dates[0].year, 7, 1)) mean_max_current = intf_c[(lats_agg_2d >= lat_min) & (lats_agg_2d <= lat_max) & (num_dates_2d <= july1) & (num_dates_2d >= june1)].mean() mean_max_future = intf_f[(lats_agg_2d >= lat_min) & (lats_agg_2d <= lat_max) & (num_dates_2d <= june1) & (num_dates_2d >= may1)].mean() print("Mean change in the maximum interflow rate: {} %".format((mean_max_future - mean_max_current) * 100 / mean_max_current)) img_file = Path(img_folder).joinpath("INTF_rate_longit_avg.png") fig.tight_layout() from crcm5.analyse_hdf import common_plot_params fig.savefig(str(img_file), bbox_inches="tight", transparent=True, dpi=common_plot_params.FIG_SAVE_DPI)