def _plot_model_point(model, psi_cube, ecs_cube, lambda_cube): """Plot a single model point for emergent relationship.""" col = _get_model_color(model, lambda_cube) style = plot.get_dataset_style(model, 'cox18nature') AXES.plot(psi_cube.extract(iris.Constraint(dataset=model)).data, ecs_cube.extract(iris.Constraint(dataset=model)).data, linestyle='none', marker=style['mark'], markeredgecolor=col, markerfacecolor=col, markersize=style['size'])
def plot_temperature_anomaly(cfg, tas_cubes, lambda_cube, obs_name): """Plot temperature anomaly versus time.""" for cube in tas_cubes.values(): cube.data -= np.mean( cube.extract( iris.Constraint(year=lambda cell: 1961 <= cell <= 1990)).data) # Save netcdf file and provenance filename = 'temperature_anomaly_{}'.format(obs_name) netcdf_path = get_diagnostic_filename(filename, cfg) io.save_1d_data(tas_cubes, netcdf_path, 'year', TASA_ATTRS) project = _get_project(cfg) provenance_record = get_provenance_record( "Simulated change in global temperature from {} models (coloured " "lines), compared to the global temperature anomaly from the {} " "dataset (black dots). The anomalies are relative to a baseline " "period of 1961-1990.".format(project, obs_name), ['anomaly'], ['times'], _get_ancestor_files(cfg, obs_name)) # Plot if cfg['write_plots']: models = lambda_cube.coord('dataset').points # Plot lines for model in models: cube = tas_cubes[model] AXES.plot(cube.coord('year').points, cube.data, color=_get_model_color(model, lambda_cube)) obs_style = plot.get_dataset_style('OBS', 'cox18nature') obs_cube = tas_cubes[obs_name] AXES.plot(obs_cube.coord('year').points, obs_cube.data, linestyle='none', marker='o', markeredgecolor=obs_style['color'], markerfacecolor=obs_style['color']) # Plot appearance AXES.set_title('Simulation of global warming record') AXES.set_xlabel('Year') AXES.set_ylabel('Temperature anomaly / K') legend = _get_line_plot_legend() # Save plot provenance_record['plot_file'] = _save_fig(cfg, filename, legend) # Write provenance with ProvenanceLogger(cfg) as provenance_logger: provenance_logger.log(netcdf_path, provenance_record)
def plot_data(cfg, cube): """Create scatterplot for cube.""" if not cfg['write_plots']: return None logger.debug("Plotting scatterplot for cube %s", cube.summary(shorten=True)) (_, axes) = plt.subplots() project = cube.attributes.get('project') # Plot for (idx, dataset_name) in enumerate(cube.coord('dataset').points): style = plot.get_dataset_style(dataset_name, cfg.get('dataset_style')) y_data = cube.extract(iris.Constraint(dataset=dataset_name)).data axes.plot(idx + 1, y_data, marker=style['mark'], linestyle='none', markeredgecolor=style['color'], markerfacecolor=style['facecolor'], label=dataset_name) # Plot appearance title = cube.long_name if project is not None: title += f' for {project}' axes.set_title(title) axes.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False) axes.set_ylabel(f"{cube.var_name.upper()} / {cube.units}") axes.set_ylim(cfg.get('y_range')) legend = axes.legend(loc='center left', bbox_to_anchor=[1.05, 0.5], borderaxespad=0.0, ncol=2) # Save plot plot_path = get_plot_filename(cube.var_name, cfg) plt.savefig(plot_path, orientation='landscape', bbox_inches='tight', additional_artists=[legend]) logger.info("Wrote %s", plot_path) plt.close() return plot_path
def plot_psi(cfg, psi_cubes, lambda_cube, obs_name): """Plot temperature variability metric psi versus time.""" filename = 'temperature_variability_metric_{}'.format(obs_name) netcdf_path = get_diagnostic_filename(filename, cfg) io.save_1d_data(psi_cubes, netcdf_path, 'year', PSI_ATTRS) project = _get_project(cfg) provenance_record = get_provenance_record( "Psi metric of variability versus time, from the {0} models " "(coloured lines), and the {1} observational data (black circles). " "The psi values are calculated for windows of width {2} yr, after " "linear de-trending in each window. These {2}-yr windows are shown " "for different end times.".format(project, obs_name, cfg.get('window_length', 55)), ['corr', 'var'], ['times'], _get_ancestor_files(cfg, obs_name)) # Plot if cfg['write_plots']: models = lambda_cube.coord('dataset').points # Plot lines for model in models: cube = psi_cubes[model] AXES.plot(cube.coord('year').points, cube.data, color=_get_model_color(model, lambda_cube)) obs_style = plot.get_dataset_style('OBS', 'cox18nature') obs_cube = psi_cubes[obs_name] AXES.plot(obs_cube.coord('year').points, obs_cube.data, linestyle='none', marker='o', markeredgecolor=obs_style['color'], markerfacecolor=obs_style['color']) # Plot appearance AXES.set_title('Metric of variability versus time') AXES.set_xlabel('Year') AXES.set_ylabel(r'$\Psi$ / K') legend = _get_line_plot_legend() # Save plot provenance_record['plot_file'] = _save_fig(cfg, filename, legend) # Write provenance with ProvenanceLogger(cfg) as provenance_logger: provenance_logger.log(netcdf_path, provenance_record)
def _get_line_plot_legend(): """Add legend for line plots.""" color_obs = plot.get_dataset_style('OBS', 'cox18nature')['color'] handles = [ mlines.Line2D([], [], color=COLOR_SMALL_LAMBDA, label=r'$\lambda < 1.0$ Wm$^{-2}$K$^{-1}$'), mlines.Line2D([], [], color=COLOR_LARGE_LAMBDA, label=r'$\lambda > 1.0$ Wm$^{-2}$K$^{-1}$'), mlines.Line2D([], [], linestyle='none', marker='o', markeredgecolor=color_obs, markerfacecolor=color_obs, label='Observations'), ] return AXES.legend(handles=handles, loc='upper left')
def _get_style(dataset_name, cfg): """Get style for individual data points.""" style = plot.get_dataset_style(dataset_name, cfg.get('dataset_style')) if not cfg.get('marker_file'): return style marker_file = os.path.expanduser(cfg['marker_file']) if not os.path.isabs(marker_file): marker_file = io.get_ancestor_file(cfg, marker_file) data_frame = pd.read_csv(marker_file) marker_column = cfg['marker_column'] for column in ('dataset', marker_column): if column not in data_frame.columns: raise ValueError( f"Marker file '{marker_file}' does not contain necessary " f"column '{column}'") marker = data_frame[marker_column][data_frame['dataset'] == dataset_name] if len(marker) != 1: raise ValueError( f"Expected exactly one entry for marker of '{dataset_name}' in " f"file '{marker_file}', got {len(marker):d}") style['mark'] = marker.values[0] return style
def plot_data(cfg, ecs_cube, tcr_cube): """Plot data.""" if not cfg['write_plots']: return None logger.debug("Plotting Fig. 9.42b of IPCC AR5") (_, axes) = plt.subplots() project = ecs_cube.attributes['project'] # Apply logarithms if desired if cfg.get('log_x'): ecs_cube.data = np.ma.log(ecs_cube.data) if cfg.get('log_y'): tcr_cube.data = np.ma.log(tcr_cube.data) # Plot scatterplot for dataset_name in ecs_cube.coord('dataset').points: style = plot.get_dataset_style(dataset_name, cfg.get('dataset_style')) ecs = ecs_cube.extract(iris.Constraint(dataset=dataset_name)).data tcr = tcr_cube.extract(iris.Constraint(dataset=dataset_name)).data # Plot single point axes.plot(ecs, tcr, marker=style['mark'], linestyle='none', markeredgecolor=style['color'], markerfacecolor=style['facecolor'], label=dataset_name) # Plot regression line and MMM (reg_line, mmm, r_value) = _get_reg_line(ecs_cube, tcr_cube) axes.plot(reg_line[0], reg_line[1], 'k-') axes.plot(mmm[0], mmm[1], 'ro', label=f'{project} mean') # Plot appearance axes.set_title(f"TCR vs. ECS for {project} models") if cfg.get('log_x'): axes.set_xlim([0.8, 2.0]) axes.set_xlabel('log(ECS / K)') else: axes.set_xlim([1.5, 6.0]) axes.set_xlabel('ECS / K') if cfg.get('log_y'): axes.set_ylim([0.3, 1.2]) axes.set_ylabel('log(TCR / K)') else: axes.set_ylim([0.5, 3.5]) axes.set_ylabel('TCR / K') legend = axes.legend(loc='center left', bbox_to_anchor=[1.05, 0.5], borderaxespad=0.0, ncol=2) axes.text(0.05, 0.9, f'$R^2$ = {r_value**2:.2f}', transform=axes.transAxes) # Save plot plot_path = get_plot_filename('ch09_fig09_42b', cfg) plt.savefig(plot_path, dpi=300, orientation='landscape', bbox_inches='tight', additional_artists=[legend]) logger.info("Wrote %s", plot_path) plt.close() return plot_path
def plot_deangelis_fig3b4(cfg, data_model, reg_prw_obs): """Plot DeAngelis Fig. 3b and prepare 4.""" # Fig 4 # model_scheme_name = dict([(1, ['Correlated-k-distribution, N >= 20', # 'dodgerblue']), # (2, ['Correlated-k-distribution, 10 < N < 20', # 'limegreen']), # (3, ['Pseudo-k-distribution, N >= 20', # 'gold']), # (4, ['Pseudo-k-distribution, 10 < N < 20', # 'darkorange']), # (5, ['7-band parameterization (N = 7)', # 'crimson']), # (6, ['Pade approximants, higher res.', # 'slategrey']), # (7, ['Pade approximants, lower res.', # 'silver']), # (8, ['unknown', # 'xkcd:pale purple'])]) # Plot data fig, axx = plt.subplots(figsize=(8, 8)) mdrsnstdts = np.zeros((len(data_model.keys()), 3)) for iii, modelkey in enumerate(data_model.keys()): mdrsnstdts[iii, 0] = (list(data_model[modelkey]))[0] mdrsnstdts[iii, 1] = (list(data_model[modelkey]))[2] mdrsnstdts[iii, 2] = (list(data_model[modelkey]))[3] axx.fill([ mdrsnstdts[iii, 1] - 2.0 * mdrsnstdts[iii, 2], mdrsnstdts[iii, 1] + 2.0 * mdrsnstdts[iii, 2], mdrsnstdts[iii, 1] + 2.0 * mdrsnstdts[iii, 2], mdrsnstdts[iii, 1] - 2.0 * mdrsnstdts[iii, 2] ], [ mdrsnstdts[iii, 0] - 0.01, mdrsnstdts[iii, 0] - 0.01, mdrsnstdts[iii, 0] + 0.01, mdrsnstdts[iii, 0] + 0.01 ], color=(0.8, 0.8, 0.8)) style = (select_metadata(cfg['input_data'].values(), dataset=modelkey))[0]['project'] style = plot.get_dataset_style(modelkey, style_file=style.lower()) axx.plot(mdrsnstdts[iii, 1], mdrsnstdts[iii, 0], marker=style['mark'], color=style['color'], markerfacecolor=style['facecolor'], linestyle='none', markersize=10, markeredgewidth=2.0, label=modelkey) prw = {} if reg_prw_obs: prw["min"] = np.zeros(len(reg_prw_obs.keys())) prw["max"] = np.zeros(len(reg_prw_obs.keys())) for iii, modelkey in enumerate(reg_prw_obs.keys()): (prw["min"])[iii] = reg_prw_obs[modelkey].slope - 2.0 * \ reg_prw_obs[modelkey].stderr (prw["max"])[iii] = reg_prw_obs[modelkey].slope + 2.0 * \ reg_prw_obs[modelkey].stderr prw["mean"] = (np.min(prw["min"]) + np.max(prw["max"])) / 2.0 prw["diff"] = np.max(prw["max"]) - prw["mean"] else: prw["mean"] = 0.0 prw["diff"] = 0.0 axx = set_axx_deangelis3b(axx, prw["mean"], prw["diff"]) # Regression line reg = stats.linregress(mdrsnstdts[:, 1], mdrsnstdts[:, 0]) axx.plot(np.linspace(0.0, 0.15, 2), reg.slope * np.linspace(0.0, 0.15, 2) + reg.intercept, linestyle='solid', color='r', label='Fit (r ={:.2f})'.format(reg.rvalue)) axx.legend(ncol=2, loc=2) fig.tight_layout() fig.savefig(get_plot_filename('fig3b', cfg), dpi=300) plt.close() caption = 'Scatter plot and regression line the between the ratio ' + \ 'of the change of ' + \ 'netto short wave radiation (rsnst) and the change of the ' + \ 'Water Vapor Path (prw) against the ratio of the change of ' + \ 'netto short wave radiation for clear skye (rsnstcs) and the ' + \ 'the change of surface temperature (tas).' + \ 'The width of horizontal ' + \ 'shading for models and the vertical dashed lines for ' + \ 'observations (Obs.) represent statistical uncertainties of ' + \ 'the ratio, as the 95% confidence interval (CI) of the regression ' + \ 'slope to the rsnst versus prw curve. For the observations ' + \ 'the minimum of the lower bounds of all CIs to the maximum of ' + \ 'the upper bounds of all CIs is shown.' provenance_record = get_provenance_record( _get_sel_files_var(cfg, ['prw', 'tas', 'rsnst', 'rsnstcs']), caption, ['other'], ['global']) diagnostic_file = get_diagnostic_filename('fig3b', cfg) logger.info("Saving analysis results to %s", diagnostic_file) iris.save(cube_to_save_matrix( mdrsnstdts, { 'var_name': 'mdrsnstdts', 'long_name': 'Change of Netto' + 'Short Wave ' + 'Radiation ' + 'with Change ' + 'of the ' + 'Water Vapor Path', 'units': '% kg-1 m2' }), target=diagnostic_file) logger.info("Recording provenance of %s:\n%s", diagnostic_file, pformat(provenance_record)) with ProvenanceLogger(cfg) as provenance_logger: provenance_logger.log(diagnostic_file, provenance_record) # Fig 4 plot_deangelis_fig4(cfg, data_model, mdrsnstdts, prw)