def plot_panel(n, fig, proj, var, clevels, cmap, title, parameters, stats=None): var = add_cyclic(var) lon = var.getLongitude() lat = var.getLatitude() var = ma.squeeze(var.asma()) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # ax.set_global() region_str = parameters.regions[0] region = regions_specs[region_str] global_domain = True full_lon = True if "domain" in region.keys(): # type: ignore # Get domain to plot domain = region["domain"] # type: ignore global_domain = False else: # Assume global domain domain = cdutil.region.domain(latitude=(-90.0, 90, "ccb")) kargs = domain.components()[0].kargs lon_west, lon_east, lat_south, lat_north = (0, 360, -90, 90) if "longitude" in kargs: full_lon = False lon_west, lon_east, _ = kargs["longitude"] # Note cartopy Problem with gridlines across the dateline:https://github.com/SciTools/cartopy/issues/821. Region cross dateline is not supported yet. if lon_west > 180 and lon_east > 180: lon_west = lon_west - 360 lon_east = lon_east - 360 if "latitude" in kargs: lat_south, lat_north, _ = kargs["latitude"] lon_covered = lon_east - lon_west lon_step = determine_tick_step(lon_covered) xticks = np.arange(lon_west, lon_east, lon_step) # Subtract 0.50 to get 0 W to show up on the right side of the plot. # If less than 0.50 is subtracted, then 0 W will overlap 0 E on the left side of the plot. # If a number is added, then the value won't show up at all. if global_domain or full_lon: xticks = np.append(xticks, lon_east - 0.50) proj = ccrs.PlateCarree(central_longitude=180) else: xticks = np.append(xticks, lon_east) lat_covered = lat_north - lat_south lat_step = determine_tick_step(lat_covered) yticks = np.arange(lat_south, lat_north, lat_step) yticks = np.append(yticks, lat_north) # Contour plot ax = fig.add_axes(panel[n], projection=proj) ax.set_extent([lon_west, lon_east, lat_south, lat_north], crs=proj) cmap = get_colormap(cmap, parameters) p1 = ax.contourf( lon, lat, var, transform=ccrs.PlateCarree(), norm=norm, levels=levels, cmap=cmap, extend="both", ) # ax.set_aspect('auto') # Full world would be aspect 360/(2*180) = 1 ax.set_aspect((lon_east - lon_west) / (2 * (lat_north - lat_south))) ax.coastlines(lw=0.3) if not global_domain and "RRM" in region_str: ax.coastlines(resolution="50m", color="black", linewidth=1) state_borders = cfeature.NaturalEarthFeature( category="cultural", name="admin_1_states_provinces_lakes", scale="50m", facecolor="none", ) ax.add_feature(state_borders, edgecolor="black") if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) if title[2] is not None: ax.set_title(title[2], loc="right", fontdict=plotSideTitle) ax.set_xticks(xticks, crs=ccrs.PlateCarree()) ax.set_yticks(yticks, crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True, number_format=".0f") lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) ax.tick_params(labelsize=8.0, direction="out", width=1) ax.xaxis.set_ticks_position("bottom") ax.yaxis.set_ticks_position("left") # Color bar cbax = fig.add_axes( (panel[n][0] + 0.6635, panel[n][1] + 0.0215, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax) w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % level for level in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha="right") cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0) # Min, Mean, Max fig.text( panel[n][0] + 0.6635, panel[n][1] + 0.2107, "Max\nMean\nMin", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] + 0.2107, "%.2f\n%.2f\n%.2f" % stats[0:3], ha="right", fontdict=plotSideTitle, ) # RMSE, CORR if len(stats) == 5: fig.text( panel[n][0] + 0.6635, panel[n][1] - 0.0105, "RMSE\nCORR", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] - 0.0105, "%.2f\n%.2f" % stats[3:5], ha="right", fontdict=plotSideTitle, ) # grid resolution info: if n == 2 and "RRM" in region_str: dlat = lat[2] - lat[1] dlon = lon[2] - lon[1] fig.text( panel[n][0] + 0.4635, panel[n][1] - 0.04, "Resolution: {:.2f}x{:.2f}".format(dlat, dlon), ha="left", fontdict=plotSideTitle, )
def plot_panel(n, fig, _, var, clevels, cmap, title, parameters, stats=None): # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n]) var.getAxis(1) var.getAxis(0) cmap = get_colormap(cmap, parameters) p1 = plt.pcolormesh(var, cmap=cmap, norm=norm) # Calculate 3 x 3 grids for cloud fraction for nine cloud class # Place cloud fraction of each cloud class in plot: cld_3x3 = np.zeros((3, 3)) for j in range(3): for i in range(3): if var.id.find("MISR") != -1: if j == 0: cld_3x3[j, i] = var[0:6, 2 * i : 2 * i + 2].sum() ax.text( i * 2 + 1, 3, "%.1f" % cld_3x3[j, i], horizontalalignment="center", verticalalignment="center", fontsize=25, ) elif j == 1: cld_3x3[j, i] = var[6:9, 2 * i : 2 * i + 2].sum() ax.text( i * 2 + 1, 7.5, "%.1f" % cld_3x3[j, i], horizontalalignment="center", verticalalignment="center", fontsize=25, ) elif j == 2: cld_3x3[j, i] = var[9:, 2 * i : 2 * i + 2].sum() ax.text( i * 2 + 1, 12, "%.1f" % cld_3x3[j, i], horizontalalignment="center", verticalalignment="center", fontsize=25, ) else: if j == 2: cld_3x3[j, i] = var[4:7, 2 * i : 2 * i + 2].sum() ax.text( i * 2 + 1, j * 2 + 1.5, "%.1f" % cld_3x3[j, i], horizontalalignment="center", verticalalignment="center", fontsize=25, ) else: cld_3x3[j, i] = var[2 * j : 2 * j + 2, 2 * i : 2 * i + 2].sum() ax.text( i * 2 + 1, j * 2 + 1, "%.1f" % cld_3x3[j, i], horizontalalignment="center", verticalalignment="center", fontsize=25, ) cld_3x3.sum() # Place vertical/horizonal line to separate cloud class plt.axvline(x=2, linewidth=2, color="k") plt.axvline(x=4, linewidth=2, color="k") if var.id.find("MISR") != -1: plt.axhline(y=6, linewidth=2, color="k") plt.axhline(y=9, linewidth=2, color="k") yticks = [0, 0.5, 1, 1.5, 2, 2.5, 3, 4, 5, 7, 9, 11, 13, 15, 17, 23] ylabels = ["%.1f" % i for i in yticks] yticks_position = np.linspace(0, 15, 16) plt.yticks(yticks_position, ylabels) ax.set_ylabel("Cloud Top Height (km)") else: plt.axhline(y=2, linewidth=2, color="k") plt.axhline(y=4, linewidth=2, color="k") yticks = [1000.0, 800.0, 680.0, 560.0, 440.0, 310.0, 180.0, 0.0] ylabels = ["%.1f" % i for i in yticks] ax.set_yticklabels(ylabels) ax.set_ylabel("Cloud Top Pressure (mb)") xticks = [0.3, 1.3, 3.6, 9.4, 23, 60, 379] xlabels = ["%.1f" % i for i in xticks] ax.set_xticklabels(xlabels) ax.set_xlabel("Cloud Optical Thickness") # xlabels = ['%.1f' %i for i in x.getBounds()[:,0]]+['%.1f' %x.getBounds()[-1,-1]] # ylabels = ['%.1f' %i for i in y.getBounds()[:,0]]+['%.1f' %y.getBounds()[-1,-1]] # ax.set_xticklabels(xlabels) # ax.set_yticklabels(ylabels) if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) # ax.set_title('cloud frac: %.1f'%total_cf+'%', loc='right', fontdict=plotSideTitle) ax.set_title("%", loc="right", fontdict=plotSideTitle) # if title[2] != None: ax.set_title(title[2], loc='right', fontdict=plotSideTitle) # ax.set_ylabel('Cloud Top Height (km)') # Color bar cbax = fig.add_axes((panel[n][0] + 0.6635, panel[n][1] + 0.0215, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax, extend="both") w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: cbar.set_ticks(levels[1:-1]) labels = ["%4.1f" % level for level in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha="right") # cbar.ax.set_yticklabels(labels,ha='right') cbar.ax.tick_params(labelsize=9.0, pad=25, length=0)
def plot_panel_map( n, fig, proj, var, clevels, cmap, title, parameter, conf=None, stats={} ): var = add_cyclic(var) lon = var.getLongitude() lat = var.getLatitude() var = ma.squeeze(var.asma()) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n], projection=proj) region_str = parameter.regions[0] region = regions_specs[region_str] if "domain" in region.keys(): # type: ignore # Get domain to plot domain = region["domain"] # type: ignore else: # Assume global domain domain = cdutil.region.domain(latitude=(-90.0, 90, "ccb")) kargs = domain.components()[0].kargs lon_west, lon_east, lat_south, lat_north = (0, 360, -90, 90) if "longitude" in kargs: lon_west, lon_east, _ = kargs["longitude"] if "latitude" in kargs: lat_south, lat_north, _ = kargs["latitude"] lon_covered = lon_east - lon_west lon_step = determine_tick_step(lon_covered) xticks = np.arange(lon_west, lon_east, lon_step) # Subtract 0.50 to get 0 W to show up on the right side of the plot. # If less than 0.50 is subtracted, then 0 W will overlap 0 E on the left side of the plot. # If a number is added, then the value won't show up at all. xticks = np.append(xticks, lon_east - 0.50) lat_covered = lat_north - lat_south lat_step = determine_tick_step(lat_covered) yticks = np.arange(lat_south, lat_north, lat_step) yticks = np.append(yticks, lat_north) ax.set_extent([lon_west, lon_east, lat_south, lat_north], crs=proj) cmap = get_colormap(cmap, parameter) contours = ax.contourf( lon, lat, var, transform=ccrs.PlateCarree(), norm=norm, levels=levels, cmap=cmap, extend="both", ) if conf is not None: conf = add_cyclic(conf) conf = ma.squeeze(conf.asma()) # Values in conf will be either 0 or 1. Thus, there are only two levels - # represented by the no-hatching and hatching levels. ax.contourf( lon, lat, conf, 2, transform=ccrs.PlateCarree(), norm=norm, colors="none", extend="both", hatches=[None, "//"], ) # Full world would be aspect 360/(2*180) = 1 ax.set_aspect((lon_east - lon_west) / (2 * (lat_north - lat_south))) ax.coastlines(lw=0.3) if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) if title[2] is not None: ax.set_title(title[2], loc="right", fontdict=plotSideTitle) ax.set_xticks(xticks, crs=ccrs.PlateCarree()) ax.set_yticks(yticks, crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True, number_format=".0f") lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) ax.tick_params(labelsize=8.0, direction="out", width=1) ax.xaxis.set_ticks_position("bottom") ax.yaxis.set_ticks_position("left") # Place a vertical line in the middle of the plot - i.e. 180 degrees ax.axvline(x=0.5, color="k", linewidth=0.5) # Color bar cbax = fig.add_axes((panel[n][0] + 0.6635, panel[n][1] + 0.0115, 0.0326, 0.1792)) cbar = fig.colorbar(contours, cax=cbax) w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 1.0: fmt = "%5.3f" pad = 30 elif maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % level for level in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha="right") cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0) # Display stats if stats: top_stats = (stats["max"], stats["min"], stats["mean"], stats["std"]) top_text = "Max\nMin\nMean\nSTD" fig.text( panel[n][0] + 0.6635, panel[n][1] + 0.2107, top_text, ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] + 0.2107, "%.2f\n%.2f\n%.2f\n%.2f" % top_stats, ha="right", fontdict=plotSideTitle, ) if "rmse" in stats.keys(): bottom_stats = (stats["rmse"], stats["corr"]) bottom_text = "RMSE\nCORR" fig.text( panel[n][0] + 0.6635, panel[n][1] - 0.0205, bottom_text, ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] - 0.0205, "%.2f\n%.2f" % bottom_stats, ha="right", fontdict=plotSideTitle, ) # Hatch text if conf is not None: hatch_text = "Hatched when pvalue < 0.05" fig.text( panel[n][0] + 0.25, panel[n][1] - 0.0355, hatch_text, ha="right", fontdict=plotSideTitle, )
def plot_panel(n, fig, proj, pole, var, clevels, cmap, title, parameters, stats=None): var = add_cyclic(var) lon = var.getLongitude() lat = var.getLatitude() var = ma.squeeze(var.asma()) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n], projection=proj) ax.set_global() ax.gridlines() if pole == "N": ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree()) elif pole == "S": ax.set_extent([-180, 180, -55, -90], crs=ccrs.PlateCarree()) cmap = get_colormap(cmap, parameters) theta = np.linspace(0, 2 * np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes) p1 = ax.contourf( lon, lat, var, transform=ccrs.PlateCarree(), norm=norm, levels=levels, cmap=cmap, extend="both", ) ax.set_aspect("auto") ax.coastlines(lw=0.3) # Plot titles if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) if title[2] is not None: ax.set_title(title[2], loc="right", fontdict=plotSideTitle) # Color bar cbax = fig.add_axes( (panel[n][0] + 0.35, panel[n][1] + 0.0354, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax) w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % level for level in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha="right") cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0) # Min, Mean, Max fig.text( panel[n][0] + 0.35, panel[n][1] + 0.225, "Max\nMean\nMin", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.45, panel[n][1] + 0.225, "%.2f\n%.2f\n%.2f" % stats[0:3], ha="right", fontdict=plotSideTitle, ) # RMSE, CORR if len(stats) == 5: fig.text( panel[n][0] + 0.35, panel[n][1] + 0.0, "RMSE\nCORR", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.45, panel[n][1] + 0.0, "%.2f\n%.2f" % stats[3:5], ha="right", fontdict=plotSideTitle, )
def plot_panel(n, fig, proj, var, clevels, cmap, title, parameters, stats=None): # var_min = float(var.min()) # var_max = float(var.max()) # var_mean = cdutil.averager(var, axis='xy', weights='generate') var = add_cyclic(var) lon = var.getLongitude() # lat = var.getLatitude() plev = var.getLevel() var = ma.squeeze(var.asma()) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n], projection=proj) cmap = get_colormap(cmap, parameters) p1 = ax.contourf( lon, plev, var, # transform=ccrs.PlateCarree(), norm=norm, levels=levels, cmap=cmap, extend="both", ) ax.set_aspect("auto") # ax.coastlines(lw=0.3) if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) if title[2] is not None: ax.set_title(title[2], loc="right", fontdict=plotSideTitle) ax.set_xticks([0, 60, 120, 180, 240, 300, 359.99]) # , crs=ccrs.PlateCarree()) ax.set_xticklabels(["0", "60E", "120E", 180, "120W", "60W", "0"]) # ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree()) # ax.set_xticks([-90, -60, -30, 0, 30, 60, 90]) # , crs=ccrs.PlateCarree()) # ax.set_xlim(-90, 90) # lon_formatter = LongitudeFormatter( # zero_direction_label=True, number_format='.0f') # LatitudeFormatter() # ax.xaxis.set_major_formatter(lon_formatter) # ax.xaxis.set_major_formatter(lat_formatter) ax.tick_params(labelsize=8.0, direction="out", width=1) ax.xaxis.set_ticks_position("bottom") ax.yaxis.set_ticks_position("left") if parameters.plot_log_plevs: ax.set_yscale("log") if parameters.plot_plevs: plev_ticks = parameters.plevs # plev_ticks = plev_ticks[::-1] plt.yticks(plev_ticks, plev_ticks) ax.invert_yaxis() ax.set_ylabel("Pressure (mb)") # Color bar cbax = fig.add_axes( (panel[n][0] + 0.6635, panel[n][1] + 0.0215, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax) w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % level for level in levels[1:-1]] cbar.ax.set_yticklabels(labels, ha="right") cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0) # Min, Mean, Max fig.text( panel[n][0] + 0.6635, panel[n][1] + 0.2107, "Max\nMean\nMin", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] + 0.2107, "%.2f\n%.2f\n%.2f" % stats[0:3], ha="right", fontdict=plotSideTitle, ) # RMSE, CORR if len(stats) == 5: fig.text( panel[n][0] + 0.6635, panel[n][1] - 0.0105, "RMSE\nCORR", ha="left", fontdict=plotSideTitle, ) fig.text( panel[n][0] + 0.7635, panel[n][1] - 0.0105, "%.2f\n%.2f" % stats[3:5], ha="right", fontdict=plotSideTitle, )
def plot_panel(n, fig, var, clevels, cmap, title, parameters, stats=None): mon = var.getTime() lat = var.getLatitude() var = np.transpose(var) # Contour levels levels = None norm = None if len(clevels) > 0: levels = [-1.0e8] + clevels + [1.0e8] norm = colors.BoundaryNorm(boundaries=levels, ncolors=256) # Contour plot ax = fig.add_axes(panel[n]) cmap = get_colormap(cmap, parameters) # p1 = ax.contourf( p1 = ax.pcolor( mon, lat, var, norm=norm, cmap=cmap, edgecolors="face", shading="auto", ) if title[0] is not None: ax.set_title(title[0], loc="left", fontdict=plotSideTitle) if title[1] is not None: ax.set_title(title[1], fontdict=plotTitle) if title[2] is not None: ax.set_title(title[2], loc="right", fontdict=plotSideTitle) mon_xticks = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"] plt.xticks(mon, mon_xticks) lat_formatter = LatitudeFormatter() ax.yaxis.set_major_formatter(lat_formatter) ax.tick_params(labelsize=8.0, direction="out", width=1) ax.xaxis.set_ticks_position("bottom") ax.yaxis.set_ticks_position("left") # Color bar cbax = fig.add_axes( (panel[n][0] + 0.6635, panel[n][1] + 0.0215, 0.0326, 0.1792)) cbar = fig.colorbar(p1, cax=cbax, extend="both") w, h = get_ax_size(fig, cbax) if levels is None: cbar.ax.tick_params(labelsize=9.0, length=0) else: maxval = np.amax(np.absolute(levels[1:-1])) if maxval < 10.0: fmt = "%5.2f" pad = 25 elif maxval < 100.0: fmt = "%5.1f" pad = 25 else: fmt = "%6.1f" pad = 30 cbar.set_ticks(levels[1:-1]) labels = [fmt % level for level in levels[1:-1]] if all(x[-2:] == ".0" for x in labels): labels = [x[:-2] for x in labels] pad = pad - 5 cbar.ax.set_yticklabels(labels, ha="right") cbar.ax.tick_params(labelsize=9.0, pad=pad, length=0)