Source code for pygpc.Visualization

import numpy as np
import os
import sys
import scipy.stats
import matplotlib as mpl
import matplotlib.pyplot as plt


[docs] class Visualization: """ Creates a new visualization in a new window. Any added sub-charts will be added to this window. Visualisation(dims=(10, 10)) Attributes ---------- Visualisation.figure_number: int, begin=0 Number of figures that have been created Visualisation.horizontal_padding: float, default=0.4 Horizontal padding of plot Visualisation.font_size_label: int, default=12 Font size of title Visualisation.font_size_label: int, default=12 Font size of label Visualisation.graph_lind_width: int, default 2 Line width of graph fig: mpl.figure Handle of figure created by matplotlib.pyplot Parameters ---------- dims: list of int, optional, default=(10,10) Size of the newly created window """ figure_number = 0 horizontal_padding = 0.4 font_size_label = 12 font_size_title = 12 graph_line_width = 2 def __init__(self, dims=(10, 10)): self.fig = plt.figure(Visualization.figure_number, figsize=(dims[0], dims[0]), facecolor=[1, 1, 1]) Visualization.figure_number += 1 # add some horizontal spacing to avoid overlap with labels plt.subplots_adjust(hspace=Visualization.horizontal_padding) mpl.rcParams['text.usetex'] = True
[docs] def create_new_chart(self, layout_id=None): """ Add a new subplot to the current visualization, so that multiple graphs can be overlaid onto one chart (e.g. scatterplot over heatmap). create_new_chart(layout_id=None) Parameters ---------- layout_id: (3-digit) int, optional, default=None Denoting the position of the graph in figure (xyn : 'x'=width, 'y'=height of grid, 'n'=position within grid) """ self.fig.add_subplot(layout_id)
[docs] def add_line_plot(self, title, labels, data, x_lim=None, y_lim=None): """ Draw a 1D line graph into the current figure. add_line_plot(title, labels, data, x_lim=None, y_lim=None) Parameters ---------- title: str Title of the graph labels: {str:str} dict {'x': name of x-axis, 'y': name of y-axis} x_lim: list of float [2], optional, default=None x-limits for the function argument or value y_lim: list of float [2], optional, default=None y-limits for the function argument or value data: ndarray of float Data that should be plotted """ self.create_sub_plot(title, labels, x_lim=x_lim, y_lim=y_lim) for i in range(len(data['pointSets'])): plt.plot(data['pointSets'][i]['x'], data['pointSets'][i]['y'], linestyle=data['linestyle'][i], color=data['color'][i], linewidth=Visualization.graph_line_width) plt.legend(data['names'], loc="upper left") plt.grid()
[docs] def add_heat_map(self, title, labels, grid_points, data_points, v_lim=(None, None), x_lim=None, y_lim=None, colormap=None): """ Draw a 2D heatmap into the current figure. add_heat_map(title, labels, grid_points, data_points, v_lim=(None, None), x_lim=None, y_lim=None, colormap=None) Parameters ---------- title: str Title of the graph labels: {str:str} dict {'x': name of x-axis, 'y': name of y-axis} grid_points: list of ndarray of float [2] Arrays of the x and y positions of the grid points e.g.: [np.array(x_points), np.array(y_points)] data_points: np.ndarray of the data points that are placed into the grid x_lim: list of float [2], optional, default=None x-limits for the function argument or value y_lim: list of float [2], optional, default=None y-limits for the function argument or value v_lim: list of float [2], optional, default=(None,None) Limits of the color scale colormap: str, optional, default=None The colormap to use """ self.create_sub_plot(title, labels, x_lim=x_lim, y_lim=y_lim) plt.pcolormesh(grid_points[0], grid_points[1], data_points, vmin=v_lim[0], vmax=v_lim[1], cmap=colormap) plt.colorbar()
[docs] @staticmethod def add_scatter_plot(shape, plot_size, color_sequence, colormap=None, v_lim=(None, None)): """ Draw a scatter plot onto the current chart. add_scatter_plot(shape, plot_size, color_sequence, colormap=None, v_lim=(None, None)) Parameters ---------- shape: {str: np.ndarray} dict {'x': positions on x-axis, 'y': positions on y-axis} plot_size: ndarray of float The marker size in the squared number of points color_sequence: str or list of str Marker colors colormap: str, optional, default=None The colormap to use v_lim: list of float [2], optional, default=(None,None) Limits of the color scale """ plt.scatter(shape['x'], shape['y'], s=plot_size, c=color_sequence, vmin=v_lim[0], vmax=v_lim[1], cmap=colormap)
[docs] @staticmethod def create_sub_plot(title, labels, x_lim, y_lim): """ Set the title, labels and the axis limits of a plot. create_sub_plot(title, labels, x_lim, y_lim) Parameters ---------- title: str Title of the plot labels: {str:str} dict {'x': name of x-axis, 'y': name of y-axis} x_lim: list of float [2] x-limits for the function argument or value y_lim: list of float [2] y-limits for the function argument or value """ plt.title(title, fontsize=Visualization.font_size_title) plt.ylabel(labels['y'], fontsize=Visualization.font_size_label) plt.xlabel(labels['x'], fontsize=Visualization.font_size_label) ax = plt.gca() if x_lim is not None: ax.set_xlim(x_lim[0], x_lim[1]) if y_lim is not None: ax.set_ylim(y_lim[0], y_lim[1])
[docs] @staticmethod def show(): """ Show plots. """ plt.show()
[docs] def b2rcw(cmin_input, cmax_input): """ Blue, white, and red color map. This function is designed to generate a blue to red colormap. The color of the colorbar is from blue to white and then to red, corresponding to the data values from negative to zero to positive, respectively. The color white always corresponds to value zero. The brightness of blue and red will change according to your setting, so that the brightness of the color corresponded to the color of his opposite number. Parameters ---------- cmin_input: float Minimum value of data cmax_input: float Maximum value of data Returns ------- newmap: ndarray of float [N_RGB x 3] Colormap Examples -------- >>> b2rcw_cmap_1 = make_cmap(b2rcw(-3, 6)) # is from light blue to deep red >>> b2rcw_cmap_2 = make_cmap(b2rcw(-3, 3)) # is from deep blue to deep red """ # check the input if cmin_input >= cmax_input: raise ValueError('input error, the color range must be from a smaller one to a larger one') # color configuration : from blue to light blue to white until to red red_top = np.array([1, 0, 0]) white_middle = np.array([1, 1, 1]) blue_bottom = np.array([0, 0, 1]) # color interpolation color_num = 250 color_input = np.vstack((blue_bottom, white_middle, red_top)) oldsteps = np.array([-1, 0, 1]) newsteps = np.linspace(-1, 1, color_num) newmap_all = np.zeros((color_num, 3))*np.nan for j in range(3): newmap_all[:, j] = np.min(np.vstack((np.max( np.vstack((np.interp(newsteps, oldsteps, color_input[:, j]), np.zeros(color_num))), axis=0), np.ones(color_num))), axis=0) if (cmin_input < 0) & (cmax_input > 0): if np.abs(cmin_input) < cmax_input: # |--------|---------|--------------------| # -cmax cmin 0 cmax [cmin,cmax] start_point = int(np.ceil((cmin_input+cmax_input)/2.0/cmax_input*color_num)-1) newmap = newmap_all[start_point:color_num, :] elif np.abs(cmin_input) >= cmax_input: # |------------------|------|--------------| # cmin 0 cmax -cmin [cmin,cmax] end_point = int(np.round((cmax_input-cmin_input)/2.0/np.abs(cmin_input)*color_num)-1) newmap = newmap_all[1:end_point, :] elif cmin_input >= 0: # |-----------------|-------|-------------| # -cmax 0 cmin cmax [cmin,cmax] start_point = int(np.round((cmin_input+cmax_input)/2.0/cmax_input*color_num)-1) newmap = newmap_all[start_point:color_num, :] elif cmax_input <= 0: # |------------|------|--------------------| # cmin cmax 0 -cmin [cmin,cmax] end_point = int(np.round((cmax_input-cmin_input)/2.0/np.abs(cmin_input)*color_num)-1) newmap = newmap_all[1:end_point, :] else: newmap = None return newmap
[docs] def make_cmap(colors, position=None, bit=False): """ make_cmap takes a list of tuples which contain RGB values. The RGB values may either be in 8-bit [0 to 255] (in which bit must be set to True when called) or arithmetic [0 to 1] (default). make_cmap returns a cmap with equally spaced colors. Arrange your tuples so that the first color is the lowest value for the colorbar and the last is the highest. Parameters ---------- colors: list of 3-tuples [n_rgb] RGB values. The RGB values may either be in 8-bit [0 to 255] (in which bit must be set to True when called) or arithmetic [0 to 1] (default). position: ndarray of float [n_rgb], optional, default=None Contains values from 0 to 1 to dictate the location of each color. bit: boolean, optional, default=False Defines if colors are in 8-bit [0 to 255] (True) or arithmetic [0 to 1] (False) Returns ------- cmap: mpl.colors instance Colormap """ bit_rgb = np.linspace(0, 1, 256) if position is None: position = np.linspace(0, 1, len(colors)) else: if len(position) != len(colors): sys.exit("position length must be the same as colors") elif position[0] != 0 or position[-1] != 1: sys.exit("position must start with 0 and end with 1") if bit: for i in range(len(colors)): colors[i] = (bit_rgb[colors[i][0]], bit_rgb[colors[i][1]], bit_rgb[colors[i][2]]) cdict = {'red': [], 'green': [], 'blue': []} for pos, color in zip(position, colors): cdict['red'].append((pos, color[0], color[0])) cdict['green'].append((pos, color[1], color[1])) cdict['blue'].append((pos, color[2], color[2])) cmap = mpl.colors.LinearSegmentedColormap('my_colormap',cdict,256) return cmap
[docs] def plot_sobol_indices(sobol_rel_order_mean, sobol_rel_1st_order_mean, fn_plot, random_vars): """ Plot the Sobol indices into different sub-plots. plot_sobol_indices(sobol_rel_order_mean, sobol_rel_1st_order_mean, fn_plot, random_vars) Parameters ---------- sobol_rel_order_mean: ndarray of float [n_sobol] Average proportion of the Sobol indices of the different order to the total variance (1st, 2nd, etc..,) over all output quantities sobol_rel_1st_order_mean: ndarray of float [dim] Average proportion of the random variables of the 1st order Sobol indices to the total variance over all output quantities fn_plot: str Filename of plot random_vars: [dim] list of str String labels of the random variables """ # combine parameters < "perc_limit_show" in % perc_limit_show = 0.03 # set the global colors mpl.rcParams['text.color'] = '000000' mpl.rcParams['figure.facecolor'] = '111111' # set a global style plt.style.use('seaborn-talk') cmap = plt.cm.rainbow # make pie plot of order ratios labels = ['order=' + str(i) for i in range(1, len(sobol_rel_order_mean) + 1)] mask = np.where(sobol_rel_order_mean >= perc_limit_show)[0] mask_not = np.where(sobol_rel_order_mean < perc_limit_show)[0] labels = [labels[idx] for idx in mask] if mask_not.any(): labels.append('misc.') values = np.hstack((sobol_rel_order_mean[mask], np.sum(sobol_rel_order_mean[mask_not]))) else: values = sobol_rel_order_mean colors = cmap(np.linspace(0.1, 0.9, len(labels))) fig = plt.figure() ax = fig.add_subplot(111, aspect='equal') ax.set_title('Sobol indices (order)') ax.pie(values, labels=labels, colors=colors, autopct='%1.2f%%', shadow=True, explode=[0.1] * len(labels)) plt.savefig(os.path.splitext(fn_plot)[0] + '_order.png', facecolor='#ffffff') # make pie plot of 1st order parameter ratios mask = np.where(sobol_rel_1st_order_mean >= perc_limit_show)[0] mask_not = np.where(sobol_rel_1st_order_mean < perc_limit_show)[0] labels = [random_vars[idx] for idx in mask] if mask_not.any(): labels.append('misc.') values = np.hstack((sobol_rel_1st_order_mean[mask], np.sum(sobol_rel_1st_order_mean[mask_not]))) else: values = sobol_rel_1st_order_mean colors = cmap(np.linspace(0., 1., len(labels))) fig = plt.figure() ax = fig.add_subplot(111, aspect='equal') ax.set_title('Sobol indices 1st order (parameters)') ax.pie(values, labels=labels, colors=colors, autopct='%1.2f%%', shadow=True, explode=[0.1] * len(labels)) plt.savefig(os.path.splitext(fn_plot)[0] + '_parameters.png', facecolor='#ffffff')
[docs] def plot_2d_grid(coords, weights=None, fn_plot=None): """ Plot 2D grid and save it as fn_plot.pdf Parameters ---------- coords: ndarray of float [n_grid, 2] Grid points weights: ndarray of float [n_grid], optional, default=None Integration weights fn_plot: str Filename of plot so save (.pdf) Returns ------- <file> .pdf file Plot of grid-points """ if weights is not None: weights = np.abs(weights) else: weights = np.ones(coords.shape[0]) # mpl.rc('text', usetex=True) mpl.rc('xtick', labelsize=12) mpl.rc('ytick', labelsize=12) fig1, ax1 = plt.subplots(nrows=1, ncols=1, squeeze=True, figsize=(5.5, 5)) ax1.scatter(coords[:, 0], coords[:, 1], s=weights/np.max(weights)*20) ax1.grid() ax1.set_xlabel('$x_1$', fontsize=16) ax1.set_ylabel('$x_2$', fontsize=16) fn = os.path.splitext(fn_plot)[0] plt.tight_layout() plt.savefig(fn, facecolor='#ffffff', format="pdf")
[docs] def plot_beta_pdf_fit(data, a_beta, b_beta, p_beta, q_beta, a_uni=None, b_uni=None, interactive=True, fn_plot=None, xlabel="$x$", ylabel="$p(x)$"): """ Plot data, fitted beta pdf (and corresponding uniform) distribution Parameters ---------- data: ndarray of float Data to fit beta distribution on a_beta: float Lower limit of beta distribution b_beta: float Upper limit of beta distribution p_beta: float First shape parameter of beta distribution q_beta: float Second shape parameter of beta distribution a_uni: float (optional) Lower limit of uniform distribution b_uni: float (optional) Upper limit of uniform distribution interactive: bool, default = True Show plot (True/False) fn_plot: Filename of plot so save (as .png and .pdf) xlabel: str (optional) Label of x-axis ylabel: str (optional) Label of y-axis Returns ------- <file> .png and .pdf files Plots """ #if not interactive: # plt.ioff() #else: # plt.ion() plt.figure(1) plt.clf() plt.rc('text', usetex=False) plt.rc('font', size=18) ax = plt.gca() # legendtext = [r"e-pdf", r"$\beta$-pdf"] legendtext = ["$\\beta$-pdf"] # plot histogram of data n, bins, patches = plt.hist(data, bins=16, density=1, color=[1, 1, 0.6], alpha=0.5) # plot beta pdf (kernel density estimate) # plt.plot(kde_x, kde_y, 'r--', linewidth=2) # plot beta pdf (fitted) beta_x = np.linspace(a_beta, b_beta, 100) beta_y = scipy.stats.beta.pdf(beta_x, p_beta, q_beta, loc=a_beta, scale=b_beta - a_beta) plt.plot(beta_x, beta_y, linewidth=2, color=[0, 0, 1]) # plot uniform pdf uni_y = 0 if a_uni is not None and b_uni is not None: uni_x = np.hstack([a_beta, a_uni - 1E-6 * (b_uni - a_uni), np.linspace(a_uni, b_uni, 100), b_uni + 1E-6 * (b_uni - a_uni), b_beta]) uni_y = np.hstack([0, 0, 1.0 / (b_uni - a_uni) * np.ones(100), 0, 0]) plt.plot(uni_x, uni_y, linewidth=2, color='r') legendtext.append("u-pdf") # configure plot plt.legend(legendtext, fontsize=18, loc="upper left") plt.grid(True) plt.xlabel(xlabel, fontsize=22) plt.ylabel(ylabel, fontsize=22) ax.set_xlim(a_beta - 0.05 * (b_beta - a_beta), b_beta + 0.05 * (b_beta - a_beta)) # ax.set_ylim(0, 1.1 * max([max(n), max(beta_y[np.logical_not(beta_y == np.inf)]), max(uni_y)])) if interactive > 0: plt.show() # save plot if fn_plot is not None: plt.savefig(fn_plot + ".pdf", format='pdf', bbox_inches='tight', pad_inches=0.01 * 4) plt.savefig(fn_plot + ".png", format='png', bbox_inches='tight', pad_inches=0.01 * 4, dpi=600)