Example #1
0
def _plot_single_map(plot_path, _dat, _datglobal, _name, provenance_record,
                     diag_config):
    """
    Plot a map for a given variable.

    Argument:
    --------
        diag_config - nested dictionary of metadata
        cube - the cube to plot
        dataset - name of the dataset to plot
    """
    # figure configuration
    fig_config = _get_fig_config(diag_config)

    # colormap configuration
    cb_info = _get_diagonal_colorbar_info()

    # define the figure and axis
    plt.figure(figsize=(5, 3))
    _ax = plt.axes([0.1, 0.1, 0.9, 0.9],
                   projection=ccrs.Robinson(central_longitude=0),
                   frameon=False)
    # plot data over the map
    plt.imshow(_get_data_to_plot(_dat.data),
               norm=mpl.colors.BoundaryNorm(cb_info['tickBounds'],
                                            len(cb_info['tickBounds'])),
               cmap=cb_info['colMap'],
               origin='upper',
               vmin=cb_info['tickBounds'][0],
               vmax=cb_info['tickBounds'][-1],
               transform=ccrs.PlateCarree())
    _fix_map(_ax)

    # get the data and set the title of the map

    _dat_median = np.nanmedian(
        _remove_invalid(_dat.data, fill_value=fig_config['fill_value']))
    title_str = (f'{_dat.long_name} ({_dat.units}), {_name},\n'
                 f'global = {_datglobal:.2f}, median = {_dat_median:.2f}')

    plt.title(title_str, fontsize=0.98 * fig_config['ax_fs'])

    # draw the colorbar
    _axcol_dia = [0.254, fig_config['y_colo_single'], 0.6, 0.035]
    plut.mk_colo_tau(_axcol_dia,
                     cb_info['tickBounds'],
                     cb_info['colMap'],
                     tick_locs=cb_info['ticksLoc'],
                     cbfs=0.86 * fig_config['ax_fs'],
                     cbtitle='',
                     cbrt=90)

    # save and close figure
    t_x = plt.figtext(0.5, 0.5, ' ', transform=plt.gca().transAxes)
    plut.save_figure(plot_path, _extr_art=[t_x])
    plt.close()
    with ProvenanceLogger(diag_config) as provenance_logger:
        provenance_logger.log(plot_path, provenance_record)
Example #2
0
def _plot_multimodel_agreement(plot_path_multimodel, global_tau_mod,
                               global_tau_obs, diag_config):
    """
    Plot map of multimodel bias and multimodel agreement.

    Argument:
    --------
        global_tau_mod - dictionary of all model data
        global_tau_obs - dictionary of observed data
        diag_config - nested dictionary of metadata
    """
    # get the settings for plotting figure
    fig_config = _get_fig_config(diag_config)

    # get the observation data needed to calculate the bias and multimodel
    # agreement
    obs_var = diag_config.get('obs_variable')[0]
    tau_obs = global_tau_obs['grid'][obs_var].data
    tau_obs_5 = global_tau_obs['grid'][obs_var + '_5'].data
    tau_obs_95 = global_tau_obs['grid'][obs_var + '_95'].data

    # set the information of the colormap used for plotting bias
    cb_info = _get_ratio_colorbar_info()

    # calculate the bias of multimodel median turnover time
    models = list(global_tau_mod['grid'].keys())

    # remove multimodel estimates from the list of models
    multimodel_stats = 'MultiModelMedian MultiModelMean'.split()
    for _mm in multimodel_stats:
        if _mm in models:
            models.remove(_mm)

    nmodels = len(models)
    dat_tau_full = np.ones((nmodels, np.shape(tau_obs)[0],
                            np.shape(tau_obs)[1])) * fig_config['fill_value']
    for row_m in range(nmodels):
        row_mod = models[row_m]
        dat_tau = global_tau_mod['grid'][row_mod]
        dat_tau_full[row_m] = _remove_invalid(
            dat_tau.data, fill_value=fig_config['fill_value'])

    mm_tau = _remove_invalid(np.nanmedian(dat_tau_full, axis=0),
                             fill_value=fig_config['fill_value'])
    mm_bias_tau = mm_tau / tau_obs
    mm_bias_tau = _remove_invalid(mm_bias_tau,
                                  fill_value=fig_config['fill_value'])

    # define figure and main axis to plot the map
    plt.figure(figsize=(5, 3))
    _ax = plt.axes([0.1, 0.1, 0.9, 0.9],
                   projection=ccrs.Robinson(central_longitude=0),
                   frameon=False)

    # plot the data of multimodel bias (=bias of multimodel median turnover
    # time)
    _ax.imshow(_get_data_to_plot(mm_bias_tau),
               norm=mpl.colors.BoundaryNorm(cb_info['tickBounds'],
                                            len(cb_info['tickBounds'])),
               interpolation='none',
               vmin=cb_info['tickBounds'][0],
               vmax=cb_info['tickBounds'][-1],
               cmap=cb_info['colMap'],
               origin='upper',
               transform=ccrs.PlateCarree())
    _fix_map(_ax)

    # get the model agreement mask (less than quarter of the model within the
    # observational uncertainty)
    agreement_mask_tau = _get_agreement_mask(dat_tau_full,
                                             tau_obs_5,
                                             tau_obs_95,
                                             nmodel_reject=int(nmodels / 4))

    # plot the hatches for uncertainty/multimodel agreement
    lats = global_tau_obs['coords']['latitude']
    lons = global_tau_obs['coords']['longitude']
    latint = abs(lats[1] - lats[0])
    lonint = abs(lons[1] - lons[0])
    x_lat, y_lon = np.meshgrid(lons - lonint / 2, lats - latint / 2)

    _ax.contourf(x_lat,
                 y_lon,
                 agreement_mask_tau,
                 levels=[0, 0.5, 1],
                 alpha=0.,
                 hatches=['', '//////'],
                 linewidth=0.2,
                 transform=ccrs.PlateCarree())

    title_str = ('multimodel bias and agreement (-)\n{title}'.format(
        title=global_tau_obs['grid']['tau_ctotal'].long_name))
    plt.title(title_str, fontsize=0.98 * fig_config['ax_fs'])

    # plot colorbar using extraUtils
    _axcol_rat = [0.254, fig_config['y_colo_single'], 0.6, 0.035]

    col_bar = plut.mk_colo_cont(_axcol_rat,
                                cb_info['tickBounds'],
                                cb_info['colMap'],
                                cbfs=0.8 * fig_config['ax_fs'],
                                cbrt=90,
                                col_scale='log',
                                cbtitle='',
                                tick_locs=cb_info['ticksLoc'])
    col_bar.ax.set_xticklabels(cb_info['ticksLab'],
                               fontsize=0.9586 * fig_config['ax_fs'],
                               ha='center',
                               rotation=0)

    # save and close figure
    t_x = plt.figtext(0.5, 0.5, ' ', transform=plt.gca().transAxes)
    plut.save_figure(plot_path_multimodel, _extr_art=[t_x])
    plt.close()
def _plot_zonal_correlation(plot_path, zonal_correlation_mod,
                            zonal_correlation_obs, diag_config):
    """
    Make the line plots of zonal correlations from all models.

    Argument:
    --------
        diag_config - nested dictionary of metadata
        zonal_correlation_mod - dictionary of correlations from all models
        zonal_correlation_obs - dictionary of correlations and ranges from
        observation
    """
    fig_config = _get_fig_config(diag_config)
    models = list(zonal_correlation_mod.keys())
    nmodels = len(models)
    models = sorted(models, key=str.casefold)
    multimodel_stats = 'MultiModelMedian MultiModelMean'.split()
    for _mm in multimodel_stats:
        if _mm in models:
            models.append(models.pop(models.index(_mm)))

    plt.figure(figsize=(5, 4))
    # tau-tas correlations
    sp1 = plt.subplot(1, 2, 1)

    # get the observations out of the dictionary
    lats_obs = zonal_correlation_obs['latitude']
    obs_var = diag_config.get('obs_variable')[0]
    r_tau_ctotal_tas = zonal_correlation_obs[obs_var]
    r_tau_ctotal_tas_5 = zonal_correlation_obs[obs_var + '_5']
    r_tau_ctotal_tas_95 = zonal_correlation_obs[obs_var + '_95']
    # plot the correlations from observation

    _fix_axis(obs_var, fig_config)
    plt.ylabel('{name}\n({unit})'.format(name=lats_obs.long_name,
                                         unit=lats_obs.units),
               fontsize=fig_config['ax_fs'],
               ma='center')

    sp1.plot(r_tau_ctotal_tas.data,
             lats_obs.points,
             color='k',
             lw=1.1,
             label=diag_config['obs_info']['source_label'])
    sp1.fill_betweenx(lats_obs.points,
                      r_tau_ctotal_tas_5.data,
                      r_tau_ctotal_tas_95.data,
                      facecolor='grey',
                      alpha=0.40)

    # tau-pr correlations
    sp2 = plt.subplot(1, 2, 2)

    # get the observations out of the dictionary
    obs_var = diag_config.get('obs_variable')[1]
    r_tau_ctotal_pr = zonal_correlation_obs[obs_var]
    r_tau_ctotal_pr_5 = zonal_correlation_obs[obs_var + '_5']
    r_tau_ctotal_pr_95 = zonal_correlation_obs[obs_var + '_95']
    _fix_axis(obs_var, fig_config)

    # plot the correlations from observation
    sp2.plot(r_tau_ctotal_pr.data,
             lats_obs.points,
             color='k',
             lw=1.1,
             label=diag_config['obs_info']['source_label'])
    sp2.fill_betweenx(lats_obs.points,
                      r_tau_ctotal_pr_5.data,
                      r_tau_ctotal_pr_95.data,
                      facecolor='grey',
                      alpha=0.40)

    # PLOTTING for models

    # loop over models and plot zonal correlations
    for row_m in range(nmodels):
        row_mod = models[row_m]
        r_mod = zonal_correlation_mod[row_mod]['data']
        lats_mod = zonal_correlation_mod[row_mod]['latitude']
        r_tau_tas_c_pr_mod = r_mod[:, 0]
        r_tau_pr_c_tas_mod = r_mod[:, 1]
        if row_mod in ['MultiModelMedian', 'MultiModelMean']:
            sp1.plot(np.ma.masked_equal(r_tau_tas_c_pr_mod, np.nan),
                     lats_mod.points,
                     lw=1.1,
                     color='blue',
                     label=row_mod)
            sp2.plot(np.ma.masked_equal(r_tau_pr_c_tas_mod, np.nan),
                     lats_mod.points,
                     lw=1.1,
                     color='blue',
                     label=row_mod)
        else:
            sp1.plot(np.ma.masked_equal(r_tau_tas_c_pr_mod, np.nan),
                     lats_mod.points,
                     lw=0.3,
                     label=row_mod)
            sp2.plot(np.ma.masked_equal(r_tau_pr_c_tas_mod, np.nan),
                     lats_mod.points,
                     lw=0.3,
                     label=row_mod)

    # normalized mean correlations from model

    # remove the multimodel estimates
    models = list(zonal_correlation_mod.keys())
    for _mm in multimodel_stats:
        if _mm in models:
            models.remove(_mm)

    nmodels = len(models)

    r_tau_pr_c_tas_all = np.ones((len(lats_obs.points), nmodels)) * np.nan
    r_tau_tas_c_pr_all = np.ones((len(lats_obs.points), nmodels)) * np.nan
    for row_m in range(nmodels):
        row_mod = models[row_m]
        r_mod = zonal_correlation_mod[row_mod]['data']
        lats_mod = zonal_correlation_mod[row_mod]['latitude']
        r_tau_tas_c_pr_all[:, row_m] = r_mod[:, 0]
        r_tau_pr_c_tas_all[:, row_m] = r_mod[:, 1]

    r_mmod, r_mmod_std_low, r_mmod_std_hi = _get_multimodel_stats(
        r_tau_tas_c_pr_all)
    sp1.plot(np.ma.masked_equal(r_mmod, np.nan),
             lats_mod.points,
             color='red',
             ls='--',
             lw=1,
             label='Norm. Mean r')
    sp1.fill_betweenx(lats_mod.points,
                      np.ma.masked_equal(r_mmod_std_low, np.nan),
                      np.ma.masked_equal(r_mmod_std_hi, np.nan),
                      facecolor='#42d4f4',
                      alpha=0.25)

    r_mmod, r_mmod_std_low, r_mmod_std_hi = _get_multimodel_stats(
        r_tau_pr_c_tas_all)

    sp2.plot(np.ma.masked_equal(r_mmod, np.nan),
             lats_mod.points,
             color='red',
             ls='--',
             lw=1,
             label='Norm. Mean r')
    sp2.fill_betweenx(lats_mod.points,
                      np.ma.masked_equal(r_mmod_std_low, np.nan),
                      np.ma.masked_equal(r_mmod_std_hi, np.nan),
                      facecolor='#42d4f4',
                      alpha=0.25)

    plt.gca().yaxis.set_label_position("right")

    # draw the legend
    leg = plut.draw_line_legend(ax_fs=fig_config['ax_fs'])

    plut.save_figure(plot_path, _extr_art=[leg])
    plt.close()
Example #4
0
def _plot_matrix_map(plot_path_matrix, global_tau_mod, global_tau_obs,
                     diag_config):
    """
    Plot the matrix of maps model-observation full factorial comparison.

    Argument:
    --------
        diag_config - nested dictionary of metadata
        cube - the cube to plot
        dataset - name of the dataset to plot
    """
    fig_config = _get_fig_config(diag_config)
    models = list(global_tau_mod['grid'].keys())
    models = sorted(models, key=str.casefold)
    multimodel_stats = 'MultiModelMedian MultiModelMean'.split()
    for _mm in multimodel_stats:
        if _mm in models:
            models.append(models.pop(models.index(_mm)))
    models.insert(0, 'obs')

    global_tau_mod['grid']['obs'] = global_tau_obs['grid']['tau_ctotal']
    global_tau_mod['global']['obs'] = global_tau_obs['global']['tau_ctotal']
    nmodels = len(models)

    # define the data and information for plotting ratios
    cb_info_ratio = _get_ratio_colorbar_info()

    # get the colormap for diagonal maps
    cb_info_diagonal = _get_diagonal_colorbar_info()

    plt.figure(figsize=(9, 6))
    for row_m in range(nmodels):
        dat_row = global_tau_mod['grid'][models[row_m]].data
        for col_m in range(nmodels):
            dat_col = global_tau_mod['grid'][models[col_m]].data
            _ax = _get_matrix_map_axes(row_m, col_m, fig_config)
            # plot the maps along the diagonal
            if row_m == col_m:
                plt.imshow(_get_data_to_plot(dat_row),
                           norm=mpl.colors.BoundaryNorm(
                               cb_info_diagonal['tickBounds'],
                               len(cb_info_diagonal['tickBounds'])),
                           cmap=cb_info_diagonal['colMap'],
                           origin='upper',
                           vmin=cb_info_diagonal['tickBounds'][0],
                           vmax=cb_info_diagonal['tickBounds'][-1],
                           transform=ccrs.PlateCarree())
                _fix_map(_ax)

            # plot the scatterplot/density plot below the diagonal
            if row_m < col_m:
                dat1h, dat2h = _get_hex_data(dat_col, dat_row, fig_config)
                _ax.hexbin(dat1h,
                           dat2h,
                           bins='log',
                           mincnt=3,
                           gridsize=40,
                           cmap='viridis_r',
                           linewidths=0)
                plt.ylim(fig_config['valrange_sc'][0],
                         fig_config['valrange_sc'][1] * 1.05)
                plt.xlim(fig_config['valrange_sc'][0],
                         fig_config['valrange_sc'][1] * 1.05)
                _draw_121_line()
                if fig_config['correlation_method'] == 'pearson':
                    corr = (stats.pearsonr(dat1h, dat2h)[0])**2
                else:
                    corr = (stats.spearmanr(dat1h, dat2h)[0])**2
                plt.title('$R^2$={corr:.2f}'.format(corr=corr),
                          fontsize=fig_config['ax_fs'] * 0.953,
                          ma='left',
                          y=fig_config['tx_y_corr'],
                          va="top")

            # plot the maps of ratio of models and observation above the
            # diagonal
            if row_m > col_m:
                plot_dat = _remove_invalid(dat_row / dat_col,
                                           fill_value=fig_config['fill_value'])
                _ax.imshow(_get_data_to_plot(plot_dat),
                           norm=mpl.colors.BoundaryNorm(
                               cb_info_ratio['tickBounds'],
                               len(cb_info_ratio['tickBounds'])),
                           interpolation='none',
                           vmin=cb_info_ratio['tickBounds'][0],
                           vmax=cb_info_ratio['tickBounds'][-1],
                           cmap=cb_info_ratio['colMap'],
                           origin='upper',
                           transform=ccrs.PlateCarree())
                _fix_map(_ax)
            t_x = _fix_matrix_axes(row_m, col_m, models, nmodels, diag_config,
                                   fig_config)

    # plot the colorbar for maps along the diagonal
    y_colo = fig_config['y0'] + fig_config['hp'] + fig_config['cb_off_y']
    _axcol_dia = [
        fig_config['x_colo_d'], y_colo, fig_config['wcolo'],
        fig_config['hcolo']
    ]
    cb_tit_d = '{name} ({unit})'.format(
        name=global_tau_mod['grid'][models[col_m]].long_name,
        unit=global_tau_mod['grid'][models[col_m]].units)
    col_bar = plut.mk_colo_tau(_axcol_dia,
                               cb_info_diagonal['tickBounds'],
                               cb_info_diagonal['colMap'],
                               tick_locs=cb_info_diagonal['ticksLoc'],
                               cbfs=0.86 * fig_config['ax_fs'],
                               cbtitle=cb_tit_d,
                               cbrt=90)

    # plot the colorbar for maps above the diagonal
    y_colo = fig_config['y0'] + fig_config['hp'] + fig_config['cb_off_y']
    _axcol_rat = [
        fig_config['x_colo_r'], y_colo, fig_config['wcolo'],
        fig_config['hcolo']
    ]
    col_bar = plut.mk_colo_cont(
        _axcol_rat,
        cb_info_ratio['tickBounds'],
        cb_info_ratio['colMap'],
        cbfs=0.7 * fig_config['ax_fs'],
        cbrt=90,
        col_scale='log',
        cbtitle='ratio ($model_{column}$/$model_{row}$)',
        tick_locs=cb_info_ratio['ticksLoc'])
    col_bar.ax.set_xticklabels(cb_info_ratio['ticksLab'],
                               fontsize=0.86 * fig_config['ax_fs'],
                               ha='center',
                               rotation=0)

    # save and close figure
    plut.save_figure(plot_path_matrix, _extr_art=[t_x])
    plt.close()
Example #5
0
def _plot_zonal_tau(plot_path, all_mod_dat, all_obs_dat, diag_config):
    """
    Plot the zonal distribution of turnover time.

    Argument:
    --------
        diag_config - nested dictionary of metadata
        cube - the cube to plot
        dataset - name of the dataset to plot
    """
    fig_config = _get_fig_config(diag_config)
    models = list(all_mod_dat.keys())
    models = sorted(models, key=str.casefold)
    for _mm in ['MultiModelMedian', 'MultiModelMean']:
        if _mm in models:
            models.append(models.pop(models.index(_mm)))
    nmodels = len(models)

    lats_obs = all_obs_dat['latitude']
    obs_var = diag_config.get('obs_variable')[0]
    tau_obs = all_obs_dat[obs_var]
    tau_obs_5 = all_obs_dat[obs_var + '_5']
    tau_obs_95 = all_obs_dat[obs_var + '_95']

    plt.figure(figsize=(3, 5))

    sp0 = plt.subplot(1, 1, 1)
    sp0.plot(tau_obs.data,
             lats_obs.points,
             color='k',
             lw=1.5,
             label=diag_config['obs_info']['source_label'])
    sp0.fill_betweenx(lats_obs.points,
                      tau_obs_5.data,
                      tau_obs_95.data,
                      facecolor='grey',
                      alpha=0.40)

    for row_m in range(nmodels):
        row_mod = models[row_m]
        dat_mod_tau = all_mod_dat[row_mod]
        if row_mod in ['MultiModelMedian', 'MultiModelMean']:
            sp0.plot(dat_mod_tau.data,
                     dat_mod_tau.coord('latitude').points,
                     lw=1.5,
                     color='blue',
                     label=row_mod)
        else:
            sp0.plot(dat_mod_tau.data,
                     dat_mod_tau.coord('latitude').points,
                     lw=0.5,
                     label=row_mod)

    leg = plut.draw_line_legend(ax_fs=fig_config['ax_fs'])

    plt.gca().set_xscale('log')
    plt.xlim(fig_config['valrange_x'][0], fig_config['valrange_x'][1])
    plt.ylim(fig_config['valrange_y'][0], fig_config['valrange_y'][1])
    plt.axhline(y=0, lw=0.48, color='grey')
    plt.xlabel(f'{tau_obs.long_name} ({tau_obs.units})',
               fontsize=fig_config['ax_fs'],
               ma='center')
    plt.ylabel(f'{lats_obs.long_name} ({lats_obs.units})',
               fontsize=fig_config['ax_fs'],
               ma='center')
    plut.rem_ax_line(['top', 'right'])

    plut.save_figure(plot_path, _extr_art=[leg])
    plt.close()