Source code for projplot.projplot

import numpy as np
import pandas as pd
import seaborn as sns


[docs]def proj_xvals(x_opt, x_lims, n_pts): """ Generate a matrix of projection plot x-values. Args: x_opt (NumPy array): An array of parameter values. x_lims (NumPy array): An array of limits or a 2 x x_opt.shape[0] matrix of lower and upper limits for each parameter. n_pts (int): The number of points to plot. Returns: (NumPy array): An array of all possible combinations of the x-values based on the limits (x_lims) and optimal values (x_opt). Example: >>> proj_xvals(np.array([1,15]), np.array([[0,2], [10, 20]]), 3) array([[ 0., 15.], [ 1., 15.], [ 2., 15.], [ 1., 10.], [ 1., 15.], [ 1., 20.]]) """ x_space = np.linspace(x_lims[:, 0], x_lims[:, 1], n_pts).T n_x = x_lims.shape[0] x_vals = np.concatenate([x_opt[None].astype(float)] * n_x * n_pts) for i in range(n_x): x_vals[i*n_pts:(i+1)*n_pts, i] = x_space[i] return x_vals
[docs]def proj_plot_show(plot_data, vlines=None): """ Create a projection plot based on the output of ``proj_data()``. Args: plot_data (DataFrame): A DataFrame that contains columns for the calculated y-value, varying x value and the respective `x_opt` name associated with the varying x. vlines (optional Array): An array of x-values to plot a vertical line at for each projection plot. The length of this array should equal the number of parameters being optimized. Returns: A plot for each unique `x_opt` using the x and y values in `plot_data` with optional vertical lines. """ grid = sns.relplot( data=plot_data, kind="line", x="x", y="y", col="variable", facet_kws=dict(sharex=False, sharey=False)) # grid.set_titles("{col_name}") if vlines is not None: for i in range(len(grid.axes.flat)): ax = grid.axes.flat[i] ax.axvline(x=vlines[i], color='red') return grid
[docs]def proj_data(fun, x_vals, x_names=[], vectorized=False): """ Generate projection plot data from the objective function and an x-value matrix returned by ``proj_xvals()``. Args: fun (Python function): The objective function that is being optimized. x_vals (NumPy array): A matrix of the x_vals, this should be outputted from proj_xvals(). x_names (optional List): A list of the names respective to varying x-values for plotting. vectorized (Bool): True if the objective function is vectorized, else False. Returns: (pandas.DataFrame): DataFrame with columns `y`, `x`, and `variable` containing: the y-value in each projection plot; the corresponding x-values; and the name of the variables in `x_names`. """ n_x = x_vals.shape[0] n_param = x_vals.shape[1] n_pts = int(n_x/n_param) # If x_names is NONE, default list to ["x1", "x2", ..] if x_names is None: x_names = ['x' + str(i) for i in range(n_param)] # Initialize empty y vector y_vals = np.zeros(n_x) varying_x = np.concatenate( [x_vals[i*n_pts:(i+1)*n_pts, i] for i in range(n_param)]) # Function is not vectorized if vectorized == False: for i in range(n_x): y_vals[i] = fun(x_vals[i]) # Function is vectorized else: y_vals = fun(x_vals) # Append the y_values to the dataframe plot_df = pd.DataFrame(varying_x, y_vals) plot_df.reset_index(inplace=True) plot_df.columns = ['y', 'x'] plot_df['variable'] = np.repeat(x_names, n_pts) return plot_df
[docs]def proj_plot(fun, x_opt, x_lims, x_names=None, n_pts=100, vectorized=False, plot=True, opt_vlines=False): """ Generate projection plots. Args: fun (Python function): The objective function that is being optimized x_opt (NumPy array): An array of parameter values x_lims (NumPy array): An array of limits or a 2 x x_opt.shape[0] matrix of lower and upper limits for each parameter x_names (anyof List None): A list of the names respective to varying x-values for plotting n_pts (int): The number of points to plot vectorized (Bool): TRUE if the objective function is vectorized, else FALSE plot (Bool): TRUE if the user wants a plot outputted, else FALSE opt_vlines (Bool): If this parameter is set to True, then a vertical line is plotted at each parameter's optimal value. The default is set to False. Returns: If ``plot=False``, the y-value in each projection plot appended to the x-values in a DataFrame format that's amenable to plotting is returned. If ``plot=True``, a plot handle of the projection plots, which is a plot for each varying `x_opt` is returned and the plot is displayed. """ # Get the x-value matrix x_vals = proj_xvals(x_opt, x_lims, n_pts) # Get the projection data plot_df = proj_data(fun, x_vals, x_names, vectorized) # n_x = x_vals.shape[0] # n_param = x_vals.shape[1] # n_pts = int(n_x/n_param) # # If x_names is NONE, default list to ["x1", "x2", ..] # if x_names is None: # x_names = ['x' + str(i) for i in range(n_param)] # # Initialize empty y vector # y_vals = np.zeros(n_x) # # Function is not vectorized # if vectorized == False: # for i in range(n_x): # y_vals[i] = fun(x_vals[i]) # # Function is vectorized # else: # y_vals = fun(x_vals) # # Get the x-values that vary for each parameter # varying_x = np.concatenate( # [x_vals[i*n_pts:(i+1)*n_pts, i] for i in range(n_param)]) # # Append the y_values to the dataframe # plot_df = pd.DataFrame(varying_x, y_vals) # plot_df.reset_index(inplace=True) # plot_df.columns = ['y', 'x'] # plot_df['x_opt'] = np.repeat(x_names, n_pts) if plot == True: if opt_vlines == True: grid = proj_plot_show(plot_df, vlines=x_opt) else: grid = proj_plot_show(plot_df) return grid else: return plot_df
if __name__ == "__main__": import doctest doctest.testmod()