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)
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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