def test_save_func(tmpdir): plot.save_func(str(tmpdir) + 'test.png', False)
def panel_plot_malhi(table_data, wmm=180, hmm=120, names=['CTL', 'EXP'], save=None, transparent=False): """Panels version of `plot_malhi`. Here we separate several regions we have defined in COORD_REGION2 within the plasim_t21.py module. REGION LOCATION ---------------------------------------------- R1: North America R2: Central America and Northern South America R3: Central South America (Amazonia) R4: Eurasia R5: East Africa R6: Australia Parameters ---------- See `plot_malhi` parameters. Returns ------- matplotlib.figure.Figure object with panel plots. """ # noqa # settings oplot.plot_settings() # check if df or text file if isinstance(table_data, str): table = pd.read_csv(table_data, index_col=0) elif isinstance(table_data, pd.core.frame.DataFrame): table = table_data # check it was the output from composite_map colnames = [ 'lon', 'lat', 'ctl_map', 'exp_map', 'ctl_mcwd', 'exp_mcwd', 'comp' ] for x in colnames: if x in table.columns: pass else: msg = 'table missing \'' + x + '\' column' raise ValueError(msg) nrows = table.index.size # colors dictionary cmap_base = matplotlib.cm.get_cmap('BrBG') cmap = [cmap_base(x) for x in [0., 0.2, 0.28, 0.38, 0.8, 1.]] cnorm = oplot.BoundaryNorm(range(7), ncolors=6, clip=True) cdict = { '0.5': cmap[0], '1.5': cmap[1], '2.5': cmap[2], '3.5': cmap[3], '4.5': cmap[4], '5.5': cmap[5] } # create figure fig = oplot.plt.figure(figsize=(wmm / 25.4, hmm / 25.4)) # create axes for continents axes = fig.subplots(2, 3, sharey=True) # to guess xlim later xp1, xp2, xp3, xp4, xp5, xp6 = [], [], [], [], [], [] for i in range(nrows): row = table.loc[i] lat = row.lat lon = row.lon # get marker based on region key = '(%8.5f, %g)' % (lat, lon) reg = COORD_REGION2[key] mark = REG_MARK2[reg] x = [row.ctl_mcwd, row.exp_mcwd] y = [row.ctl_map, row.exp_map] c = cdict[str(row.comp)] if reg == 'R1': axes[0, 0].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[0, 0].plot(x[1], y[1], mark, color=c, ms=2) xp1.extend(x) elif reg == 'R2': axes[0, 1].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[0, 1].plot(x[1], y[1], mark, color=c, ms=2) xp2.extend(x) elif reg == 'R3': axes[0, 2].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[0, 2].plot(x[1], y[1], mark, color=c, ms=2) xp3.extend(x) elif reg == 'R4': axes[1, 0].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[1, 0].plot(x[1], y[1], mark, color=c, ms=2) xp4.extend(x) elif reg == 'R5': axes[1, 1].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[1, 1].plot(x[1], y[1], mark, color=c, ms=2) xp5.extend(x) elif reg == 'R6': axes[1, 2].plot(x, y, color=c, linewidth=1, alpha=0.5) axes[1, 2].plot(x[1], y[1], mark, color=c, ms=2) xp6.extend(x) else: pass # plot settings for ax in axes[1, :]: ax.set_xlabel('MCWD (mm)') for ax in axes[:, 0]: ax.set_ylabel(oplot.replace_minus('MAP (mm year$^{-1}$)')) # ylim and change hyphen for ax in axes.flatten(): ax.set_ylim([0, 3500]) ax.xaxis.set_major_formatter(oplot.FuncFormatter(oplot.no_hyphen)) # fix xlim for (x, ax) in zip([xp1, xp2, xp3, xp4, xp5, xp6], axes.flatten()): positive_minx = abs(min(x)) positive_minx -= positive_minx % -100 xlim = [-positive_minx, 0] ax.set_xlim(xlim) # titles axes[0, 0].set_title('(a) North America') axes[0, 1].set_title('(b) Central America/Northern South America') axes[0, 2].set_title('(c) Central South America') axes[1, 0].set_title('(d) Eurasia') axes[1, 1].set_title('(e) South East Africa') axes[1, 2].set_title('(f) Australia') # legend custom_names = ['Distance to ' + names[0], names[1]] custom_lines = [ Line2D([0], [0], color='black', lw=1, alpha=0.5), Line2D([0], [0], linestyle='', marker='^', color='black', ms=2) ] axes[0, 0].legend(custom_lines, custom_names, loc=2, fontsize=6) axes[0, 1].legend(custom_lines, custom_names, loc=4, fontsize=6) axes[0, 2].legend(custom_lines, custom_names, loc=4, fontsize=6) axes[1, 0].legend(custom_lines, custom_names, loc=3, fontsize=6) axes[1, 1].legend(custom_lines, custom_names, loc=2, fontsize=6) axes[1, 2].legend(custom_lines, custom_names, loc=2, fontsize=6) # maximize oplot.plt.tight_layout() # save if given filename oplot.save_func(save, transparent) return fig
def plot_mcwd_composite(composite, wmm=100, hmm=80, axes=None, proj=None, lon0=0, save=None, transparent=False): """Plot results from `mcwd_composite_map`. This is a custom map that combines significant differences in both mean annual precipitation (MAP) and maximum climatological water deficit (MCWD). To do this we first find significant differences. Then we ask whether this significan differences are above 10% of a control value. Based on this, each grid cell is assigned either numpy.nan or a value. Here we define how to plot those values in such composite map. Parameters ---------- composite: xarray.DataArray This must be the output of function `mcwd_composite_map`. wmm: float, optional Width of the figure to plot in units of mm. Default is 100 mm. hmm: float, optional Height of the figure to plot in units of mm. Default is 80 mm. axes: cartopy.mpl.geoaxes.GeoAxes, optional This axes should have some projection from Cartopy. If it is not provided, brand new axes will be created with default projection `proj`. proj: cartopy.crs.Projection, optional Map projection to be used to create the axes if not provided. By default we use the Mollweide projection. lon0: float, optional Central longitude to create the projection in the axes. By default the central longitudes is the Greenwich meridian. This argument is only meaningfull for the default projection which is Mollweide. Otherwise it is unused. save: bool or str, optional This can be a boolean flag to create a PDF file with the plotted map, in which case the file will be named `output.pdf`, or a string with a specific name for the file. Default is only show the plot. transparent: bool, optional If `save` is True or some str object with a name, this keyword controls how the background is plotted. If True, then background will be transparent. This is useful if the image is to be used in slideshows. Default is False. Returns ------- matplotlib.axes.Axes with plot attached. """ # noqa # plot settings oplot.plot_settings() # get cyclic values and coords cval, clon = oplot.get_cyclic_values(composite) lat = composite.latitude.values # get projection if none given if proj is None: proj = oplot.moll(central_longitude=lon0) # in case we plot a single plot if axes is None: oplot.plt.figure(figsize=(wmm / 25.4, hmm / 25.4)) axes = oplot.plt.axes(projection=proj) maximize = 1 else: maximize = 0 # colormap # cmap = oplot.ListedColormap(['FireBrick', 'Chocolate', 'Orange', # 'Yellow', 'YellowGreen', 'DarkGreen']) cmap_base = matplotlib.cm.get_cmap('BrBG') cmap = oplot.ListedColormap( [cmap_base(x) for x in [0., 0.2, 0.28, 0.38, 0.8, 1.]]) # levels lev = range(7) # normalize to number of colors cnorm = oplot.BoundaryNorm(lev, ncolors=cmap.N, clip=True) # add shorelines axes.coastlines(resolution='110m') # set global axes.set_global() # add gridlines oplot.add_gridlines(axes) # fix coords corlon, corlat = oplot.corner_coords(clon, lat) # plot map fmap = axes.pcolor(corlon, corlat, cval, cmap=cmap, norm=cnorm, transform=oplot.pcar()) # add colorbar cb = oplot.plt.colorbar(fmap, orientation='horizontal', pad=0.15, shrink=0.8, ax=axes, extend='both') # colorbar ticks and labels fsize = 7 bottom = [ 'much\ngreater', 'greater', 'much\ngreater', 'greater', 'less', 'much\nless' ] top = [ 'much\nless', 'much\nless', 'less', 'less', 'greater', 'much\ngreater' ] cb.set_ticks(np.arange(0.5, 6.5, 1)) cb.ax.tick_params(top=True) cb.ax.set_xticklabels(bottom, multialignment='center', fontsize=fsize) # add top ticklabels with custom text tickpos = cb.ax.get_xticks() for i, x in enumerate(tickpos): cb.ax.text(x, 1.8, top[i], fontsize=fsize, ha='center', multialignment='center') # add titles at top and bottom cb.ax.text(-0.05, 2, r' \textbf{MAP}', fontsize=fsize, ha='center', va='bottom') cb.ax.text(-0.07, -2, r'\textbf{MCWD}', fontsize=fsize, ha='center', va='bottom') # maximize if only one if maximize == 1: oplot.plt.tight_layout() # savefig if provided name oplot.save_func(save, transparent) return axes
def plot_malhi(table_data, wmm=90, hmm=90, names=['CTL', 'EXP'], axes=None, ylim=[0, 4000], title='', bounds=None, legend=True, ylabel=r'MAP (mm year$^{-1}$)', xlabel=r'MCWD (mm)', save=None, transparent=False): """Plot output CSV file from `mcwd_composite_map`. This function will plot the table in comma separated values (CSV) format that the function `mcwd_composite_map` creates. It will read it as a dataframe and plot it, or you can go ahead and give the data frame directly. Since `mcwd_composite_map` only considers 2 experiments, one control and one experimental simulation, this plot will do the same. Parameters ---------- table_data: str or pandas.DataFrame If this is a string, it must be the name of the CSV file that `mcwd_composite_map` creates. But it can also be the pandas.DataFrame directly, without need of creating file. wmm: float, optional Width of the figure to plot in units of mm. Default is 90 mm. hmm: float, optional Height of the figure to plot in units of mm. Default is 90 mm. names: list List with only 2 str names for two experiments. One of them is usually control. Default is ['CTL', 'EXP']. axes: matplotlib.axes.Axes, optional If this is going to be part of another bigger figure, a subplot axes can be provided for this plot to attach the ONI plot. ylim: list, optional List object with two float values to define the limits in the y axis. Default is [0, 4000]. title: str, optional Center top title if desired. Default is empty. bounds: tuple or list, optional Bounds must have the sequence: [x0, x1, y0, y1], using x for longitudes and y for latitudes. Default is None. legend: bool, optional Whether to show legend or not. xlabel: str, optional Title for the x axis. Default is 'MCWD (mm)'. ylabel: str, optional Title for the y axis. Default is 'MAP (mm year-1)'. save: bool or str, optional This can be a boolean flag to create a PDF file with the plotted map, in which case the file will be named `output.pdf`, or a string with a specific name for the file. Default is only show the plot. transparent: bool, optional If `save` is True or some str object with a name, this keyword controls how the background is plotted. If True, then background will be transparent. This is useful if the image is to be used in slideshows. Default is False. Returns ------- matplotlib.axes.Axes with plot attached. """ # noqa # plot settings oplot.plot_settings() # check if df or text file if isinstance(table_data, str): table = pd.read_csv(table_data, index_col=0) elif isinstance(table_data, pd.core.frame.DataFrame): table = table_data # check it was the output from composite_map colnames = [ 'lon', 'lat', 'ctl_map', 'exp_map', 'ctl_mcwd', 'exp_mcwd', 'comp' ] for x in colnames: if x in table.columns: pass else: msg = 'table missing \'' + x + '\' column' raise ValueError(msg) nrows = table.index.size # in case we plot a single plot if axes is None: oplot.plt.figure(figsize=(wmm / 25.4, hmm / 25.4)) axes = oplot.plt.axes() maximize = 1 else: maximize = 0 # colors dictionary cmap_base = matplotlib.cm.get_cmap('BrBG') cmap = [cmap_base(x) for x in [0., 0.2, 0.28, 0.38, 0.8, 1.]] cdict = { '0.5': cmap[0], '1.5': cmap[1], '2.5': cmap[2], '3.5': cmap[3], '4.5': cmap[4], '5.5': cmap[5] } # custom legend lines regions = [] markers = [] custom_names = ['Distance to ' + names[0]] custom_lines = [Line2D([0], [0], color='black', lw=0.5, alpha=0.5)] # to guess xlim later xplotted = [] for i in range(nrows): row = table.loc[i] lat = row.lat lon = row.lon # get marker based on region key = '(%8.5f, %g)' % (lat, lon) reg = COORD_REGION1[key] mark = REG_MARK1[reg] if reg not in regions: regions.append(reg) if mark not in markers: markers.append(mark) # fix lon to be -180 - 180 if lon > 180: lon = lon - 360 x = [row.ctl_mcwd, row.exp_mcwd] y = [row.ctl_map, row.exp_map] c = cdict[str(row.comp)] if bounds is not None: # check bounds utils.check_bounds(bounds) # unpack bounds x0, x1, y0, y1 = bounds if (lon > x0) and (lon <= x1): if (lat > y0) and (lat <= y1): axes.plot(x, y, color=c) axes.plot(row.exp_mcwd, row.exp_map, '^', color=c) xplotted.extend(x) else: axes.plot(x, y, color=c, linewidth=0.5, alpha=0.5) axes.plot(row.exp_mcwd, row.exp_map, mark, color=c, ms=2) xplotted.extend(x) # guess min xlim if xplotted != []: positive_minx = abs(min(xplotted)) positive_minx -= positive_minx % -100 xlim = [-positive_minx, 0] axes.set_xlim(xlim) # plot settings axes.set_xlabel(xlabel) axes.set_ylabel(oplot.replace_minus(ylabel)) axes.set_ylim(ylim) axes.set_title(title) axes.xaxis.set_major_formatter(oplot.FuncFormatter(oplot.no_hyphen)) if legend is True: for r in regions: custom_names.append(r) for m in markers: custom_lines.append( Line2D([0], [0], linestyle='', marker=m, color='black', ms=2)) axes.legend(custom_lines, custom_names, loc=2, ncol=3, fontsize=6) # maximize plot if only one if maximize == 1: oplot.plt.tight_layout() # savefig if provided name oplot.save_func(save, transparent) return axes
def plot_regions(composite, bnds, regname, xloc, yloc, wmm=30, hmm=30, axes=None, proj=None, lon0=0, save=None, transparent=False): # plot settings oplot.plot_settings() # copy data compcopy = composite.copy() # select region x0, x1, y0, y1 = bnds reg = compcopy.sel(latitude=slice(y0, y1), longitude=slice(x0, x1)) # get coords lon = reg.longitude.values lat = reg.latitude.values # shape nlat, mlon = reg.shape for i in range(nlat): ii = lat[i] for j in range(mlon): jj = lon[j] # get marker based on region key = '(%8.5f, %g)' % (ii, jj) try: region = COORD_REGION2[key] except: region = 'OTHER' if region != regname: reg.values[i, j] = np.nan # get projection if none given if proj is None: proj = oplot.pcar(central_longitude=lon0) # in case we plot a single plot if axes is None: oplot.plt.figure(figsize=(wmm / 25.4, hmm / 25.4)) axes = oplot.plt.axes(projection=proj) maximize = 1 else: maximize = 0 # colormap cmap_base = matplotlib.cm.get_cmap('BrBG') cmap = oplot.ListedColormap( [cmap_base(x) for x in [0., 0.2, 0.28, 0.38, 0.8, 1.]]) # levels lev = range(7) # normalize to number of colors cnorm = oplot.BoundaryNorm(lev, ncolors=cmap.N, clip=True) # add shorelines axes.coastlines(resolution='110m') # set global axes.set_extent(bnds) # add gridlines oplot.pcar_gridliner(axes, bnds, xloc, yloc) # fix coords corlon, corlat = oplot.corner_coords(lon, lat) # plot map fmap = axes.pcolor(corlon, corlat, reg.values, cmap=cmap, norm=cnorm, transform=oplot.pcar()) # maximize if only one if maximize == 1: oplot.plt.tight_layout() # savefig if provided name oplot.save_func(save, transparent) return axes