def plot3_stacked_per_bank( ax: matplotlib.axes.Axes, km_mid: numpy.ndarray, km_step: float, dv: List[List[numpy.ndarray]], banklabel: str, wfrac: float, ) -> None: """ Add a stacked plot of bank erosion with total eroded volume subdivided per bank to the selected axes. Arguments --------- fig : matplotlib.figure.Figure Figure object. ax : matplotlib.axes.Axes Axes object. km_mid : numpy.ndarray Array containing the mid points for the chainage bins. km_step : float Bin width. dv : List[List[numpy.ndarray]] List of nQ lists of N arrays containing the total erosion distance values banklabel : str Label for bank id. wfrac : float Width fraction for the stacked column. Results ------- None """ n_banklines = len(dv[0]) clrs = get_colors("plasma", n_banklines + 1) for ib in range(n_banklines): for iq in range(len(dv)): if iq == 0: dvq = dv[iq][ib].copy() else: dvq = dvq + dv[iq][ib] if ib == 0: ax.bar( km_mid, dvq, width=wfrac * km_step, color=clrs[ib], label=banklabel.format(ib=ib + 1), ) cumdv = dvq else: ax.bar( km_mid, dvq, width=wfrac * km_step, bottom=cumdv, color=clrs[ib], label=banklabel.format(ib=ib + 1), ) cumdv = cumdv + dvq
def plot_single_reliability_diagram(ax: mpl.axes.Axes, binned: Dict[str, np.ndarray], **bar_kwargs): """Plots a reliability diagram into ax.""" bin_widths = np.diff(binned["edges"]) bin_centers = binned["edges"][:-1] + bin_widths / 2 ax.bar(x=bin_centers, height=binned["acc"], width=bin_widths, color="royalblue", edgecolor="k", linewidth=0.5, **bar_kwargs) ax.bar(x=bin_centers, bottom=binned["acc"], height=binned["conf"] - binned["acc"], width=bin_widths, fc=(1, 0, 0, 0.1), edgecolor=(1, 0.3, 0.3), linewidth=0.5, **bar_kwargs)
def _plot_data(ax: mpl.axes.Axes, data: PlotData) -> Optional[List[mpl.lines.Line2D]]: x, y = None, None lines = None # Return line objects so we can add legends disp = data.display_attributes if isinstance(data, XYData) or isinstance(data, TimeSeries): x, y = (data.x, data.y) if isinstance(data, XYData) else (np.arange(len(data.timestamps)), data.values) if isinstance(disp, LinePlotAttributes): lines, = ax.plot(x, y, linestyle=disp.line_type, linewidth=disp.line_width, color=disp.color) if disp.marker is not None: # type: ignore ax.scatter(x, y, marker=disp.marker, c=disp.marker_color, s=disp.marker_size, zorder=100) elif isinstance(disp, ScatterPlotAttributes): lines = ax.scatter(x, y, marker=disp.marker, c=disp.marker_color, s=disp.marker_size, zorder=100) elif isinstance(disp, BarPlotAttributes): lines = ax.bar(x, y, color=disp.color) # type: ignore elif isinstance(disp, FilledLinePlotAttributes): x, y = np.nan_to_num(x), np.nan_to_num(y) pos_values = np.where(y > 0, y, 0) neg_values = np.where(y < 0, y, 0) ax.fill_between(x, pos_values, color=disp.positive_color, step='post', linewidth=0.0) ax.fill_between(x, neg_values, color=disp.negative_color, step='post', linewidth=0.0) else: raise Exception(f'unknown plot combination: {type(data)} {type(disp)}') # For scatter and filled line, xlim and ylim does not seem to get set automatically if isinstance(disp, ScatterPlotAttributes) or isinstance(disp, FilledLinePlotAttributes): xmin, xmax = _adjust_axis_limit(ax.get_xlim(), x) if not np.isnan(xmin) and not np.isnan(xmax): ax.set_xlim((xmin, xmax)) ymin, ymax = _adjust_axis_limit(ax.get_ylim(), y) if not np.isnan(ymin) and not np.isnan(ymax): ax.set_ylim((ymin, ymax)) elif isinstance(data, TradeSet) and isinstance(disp, ScatterPlotAttributes): lines = ax.scatter(np.arange(len(data.timestamps)), data.values, marker=disp.marker, c=disp.marker_color, s=disp.marker_size, zorder=100) elif isinstance(data, TradeBarSeries) and isinstance(disp, CandleStickPlotAttributes): draw_candlestick(ax, np.arange(len(data.timestamps)), data.o, data.h, data.l, data.c, data.v, data.vwap, colorup=disp.colorup, colordown=disp.colordown) elif isinstance(data, BucketedValues) and isinstance(disp, BoxPlotAttributes): draw_boxplot( ax, data.bucket_names, data.bucket_values, disp.proportional_widths, disp.notched, # type: ignore disp.show_outliers, disp.show_means, disp.show_all) # type: ignore elif isinstance(data, XYZData) and (isinstance(disp, SurfacePlotAttributes) or isinstance(disp, ContourPlotAttributes)): display_type: str = 'contour' if isinstance(disp, ContourPlotAttributes) else 'surface' draw_3d_plot(ax, data.x, data.y, data.z, display_type, disp.marker, disp.marker_size, disp.marker_color, disp.interpolation, disp.cmap) else: raise Exception(f'unknown plot combination: {type(data)} {type(disp)}') return lines
def plot_total_sample_numbers(histories: Union[List, History], labels: Union[List, str] = None, rotation: int = 0, title: str = "Total required samples", yscale: str = 'lin', size: tuple = None, ax: mpl.axes.Axes = None): """ Bar plot of total required sample number over all iterations, i.e. a single-colored bar per history, in contrast to `plot_sample_numbers`, which visually distinguishes iterations. Parameters ---------- histories: Union[List, History] The histories to plot from. History ids must be set correctly. labels: Union[List ,str], optional Labels corresponding to the histories. If None are provided, indices are used as labels. rotation: int, optional (default = 0) Rotation to apply to the plot's x tick labels. For longer labels, a tilting of 45 or even 90 can be preferable. title: str, optional (default = "Total required samples") Title for the plot. yscale: str, optional (default = 'lin') The scale on which to plot the counts. Can be one of 'lin', 'log' (basis e) or 'log10' size: tuple of float, optional The size of the plot in inches. ax: matplotlib.axes.Axes, optional The axis object to use. Returns ------- ax: Axis of the generated plot. """ # preprocess input histories = to_lists(histories) labels = get_labels(labels, len(histories)) # create figure if ax is None: fig, ax = plt.subplots() else: fig = ax.get_figure() n_run = len(histories) # extract sample numbers samples = [] for history in histories: # note: the first entry corresponds to the calibration and should # be included here to be fair against methods not requiring # calibration samples.append(np.sum(history.get_all_populations()['samples'])) samples = np.array(samples) # apply scale ylabel = "Total samples" if yscale == 'log': samples = np.log(samples) ylabel = "log(" + ylabel + ")" elif yscale == 'log10': samples = np.log10(samples) ylabel = "log10(" + ylabel + ")" # plot bars ax.bar(x=np.arange(n_run), height=samples) # add labels ax.set_xticks(np.arange(n_run)) ax.set_xticklabels(labels, rotation=rotation) ax.set_title(title) ax.set_ylabel(ylabel) ax.set_xlabel("Run") # set size if size is not None: fig.set_size_inches(size) fig.tight_layout() return ax
def plot_sample_numbers(histories: Union[List, History], labels: Union[List, str] = None, rotation: int = 0, title: str = "Required samples", size: tuple = None, ax: mpl.axes.Axes = None): """ Stacked bar plot of required numbers of samples over all iterations. Parameters ---------- histories: Union[List, History] The histories to plot from. History ids must be set correctly. labels: Union[List ,str], optional Labels corresponding to the histories. If None are provided, indices are used as labels. rotation: int, optional (default = 0) Rotation to apply to the plot's x tick labels. For longer labels, a tilting of 45 or even 90 can be preferable. title: str, optional (default = "Total required samples") Title for the plot. size: tuple of float, optional The size of the plot in inches. ax: matplotlib.axes.Axes, optional The axis object to use. Returns ------- ax: Axis of the generated plot. """ # preprocess input histories = to_lists(histories) labels = get_labels(labels, len(histories)) # create figure if ax is None: fig, ax = plt.subplots() else: fig = ax.get_figure() n_run = len(histories) # extract sample numbers samples = [] for history in histories: # note: the first entry corresponds to the calibration and should # be included here to be fair against methods not requiring # calibration samples.append(np.array(history.get_all_populations()['samples'])) # create matrix n_pop = max(len(sample) for sample in samples) matrix = np.zeros((n_pop, n_run)) for i_sample, sample in enumerate(samples): matrix[:len(sample), i_sample] = sample # plot bars for i_pop in reversed(range(n_pop)): ax.bar(x=np.arange(n_run), height=matrix[i_pop, :], bottom=np.sum(matrix[:i_pop, :], axis=0), label=f"Generation {i_pop-1}") # add labels ax.set_xticks(np.arange(n_run)) ax.set_xticklabels(labels, rotation=rotation) ax.set_title(title) ax.set_ylabel("Samples") ax.set_xlabel("Run") ax.legend() # set size if size is not None: fig.set_size_inches(size) fig.tight_layout() return ax
def plot_total_walltime(histories: Union[List[History], History], labels: Union[List, str] = None, unit: str = 's', rotation: int = 0, title: str = "Total walltimes", size: tuple = None, ax: mpl.axes.Axes = None) -> mpl.axes.Axes: """Plot total walltimes, for each history one single-color bar. Parameters ---------- histories: The histories to plot from. History ids must be set correctly. labels: Labels corresponding to the histories. If None are provided, indices are used as labels. unit: Time unit to use ('s', 'm', 'h', 'd' as seconds, minutes, hours, days). rotation: Rotation to apply to the plot's x tick labels. For longer labels, a tilting of 45 or even 90 can be preferable. title: Title for the plot. size: tuple of float, optional The size of the plot in inches. ax: matplotlib.axes.Axes, optional The axis object to use. Returns ------- ax: Axis of the generated plot. """ # preprocess input histories = to_lists(histories) labels = get_labels(labels, len(histories)) n_run = len(histories) # check time unit if unit not in TIME_UNITS: raise AssertionError(f"`unit` must be in {TIME_UNITS}") # create figure if ax is None: fig, ax = plt.subplots() else: fig = ax.get_figure() # extract total walltimes walltimes = [] for h in histories: abc = h.get_abc() walltimes.append((abc.end_time - abc.start_time).total_seconds()) walltimes = np.asarray(walltimes) # apply time unit if unit == MINUTE: walltimes /= 60 elif unit == HOUR: walltimes /= (60 * 60) elif unit == DAY: walltimes /= (60 * 60 * 24) # plot bars ax.bar(x=np.arange(n_run), height=walltimes, label=labels) # prettify plot ax.set_xticks(np.arange(n_run)) ax.set_xticklabels(labels, rotation=rotation) ax.set_title(title) ax.set_xlabel("Run") ax.set_ylabel(f"Time [{unit}]") if size is not None: fig.set_size_inches(size) fig.tight_layout() return ax
def plot_walltime_lowlevel(end_times: List, start_times: Union[List, None] = None, labels: Union[List, str] = None, show_calibration: bool = None, unit: str = 's', rotation: int = 0, title: str = "Walltime by generation", size: tuple = None, ax: mpl.axes.Axes = None) -> mpl.axes.Axes: """Low-level access to `plot_walltime`. Directly define `end_times` and `start_times`.""" # preprocess input end_times = to_lists(end_times) labels = get_labels(labels, len(end_times)) n_run = len(end_times) # check start times if start_times is None: if show_calibration: raise AssertionError( "To plot the calibration iteration, start times are needed.") # fill in dummy times which will not be used anyhow start_times = [datetime.datetime.now() for _ in range(n_run)] # check time unit if unit not in TIME_UNITS: raise AssertionError(f"`unit` must be in {TIME_UNITS}") # create figure if ax is None: fig, ax = plt.subplots() else: fig = ax.get_figure() # extract relative walltimes walltimes = [] for start_t, end_ts in zip(start_times, end_times): times = [start_t, *end_ts] # compute stacked differences diffs = [end - start for start, end in zip(times[:-1], times[1:])] # as seconds diffs = [diff.total_seconds() for diff in diffs] # append walltimes.append(diffs) walltimes = np.asarray(walltimes) # create matrix n_pop = max(len(wt) for wt in walltimes) matrix = np.zeros((n_pop, n_run)) for i_run, wt in enumerate(walltimes): matrix[:len(wt), i_run] = wt if not show_calibration: matrix = matrix[1:, :] # apply time unit if unit == MINUTE: matrix /= 60 elif unit == HOUR: matrix /= (60 * 60) elif unit == DAY: matrix /= (60 * 60 * 24) # plot bars for i_pop in reversed(range(matrix.shape[0])): pop_ix = i_pop - 1 if not show_calibration: pop_ix = i_pop ax.bar(x=np.arange(n_run), height=matrix[i_pop, :], bottom=np.sum(matrix[:i_pop, :], axis=0), label=f"Generation {pop_ix}") # prettify plot ax.set_xticks(np.arange(n_run)) ax.set_xticklabels(labels, rotation=rotation) ax.set_title(title) ax.set_xlabel("Run") ax.set_ylabel(f"Time [{unit}]") ax.legend() if size is not None: fig.set_size_inches(size) fig.tight_layout() return ax