Пример #1
0
    def _set_figure(cls, ax: axes.Axes, index: dict, range: Sequence):
        """set figure and axes for plotting

        :params ax: matplotlib.axes.Axes object
        :params index: dict of label of points of x-axis and its index in data file. Range of x-axis based on index.value()
        :params range: range of y-axis
        """

        keys = []
        values = []
        for t in index:
            if isinstance(t, tuple):
                keys.append(t[0])
                values.append(t[1])
            elif isinstance(t, (int, float)):
                keys.append('')
                values.append(t)

        # x-axis
        ax.set_xticks(values)
        ax.set_xticklabels(keys)
        ax.set_xlim(values[0], values[-1])
        ax.set_xlabel("Wave Vector")

        # y-axis
        if range:
            ax.set_ylim(range[0], range[1])
        ax.set_ylabel(r"$E-E_{fermi}(eV)$")

        # others
        ax.grid(axis='x', lw=1.2)
        ax.axhline(0, linestyle="--", c='b', lw=1.0)
        handles, labels = ax.get_legend_handles_labels()
        by_label = OrderedDict(zip(labels, handles))
        ax.legend(by_label.values(), by_label.keys())
Пример #2
0
    def _plot(
        self,
        ax: Axes,
        ylabel: Optional[str] = None,
        color: Optional[str] = None,
        channel: Optional[Channel] = None,
        label: str = "",
        start_t: int = 0,
    ) -> None:
        ax.set_xlabel("t (ns)")
        samples = (self.samples
                   if channel is None else self.modulated_samples(channel))
        ts = np.arange(len(samples)) + start_t
        if not channel and start_t:
            # Adds zero on both ends to show rise and fall
            samples = np.pad(samples, 1)
            # Repeats the times on the edges once
            ts = np.pad(ts, 1, mode="edge")

        if color:
            color_dict = {"color": color}
            hline_color = color
            ax.tick_params(axis="y", labelcolor=color)
        else:
            color_dict = {}
            hline_color = "black"

        if ylabel:
            ax.set_ylabel(ylabel, fontsize=14, **color_dict)
        ax.plot(ts, samples, label=label, **color_dict)
        ax.axhline(0, color=hline_color, linestyle=":", linewidth=0.5)

        if label:
            plt.legend()
Пример #3
0
    def add_stat_line(
            ax: Axes,
            series_input: SeriesPlotIn,
            stat: Callable[[Iterable[float]], float] = np.mean,
            vert: bool = True,
            **kwargs
    ) -> Axes:
        
        if "linestyle" not in kwargs.keys():
            kwargs.update({"linestyle": "--"})
            
        stat_val: float = stat(series_input.data)
        
        if vert:
            ax.axvline(x=stat_val, color=series_input.color, **kwargs)
        else:
            ax.axhline(y=stat_val, color=series_input.color, **kwargs)

        return ax
Пример #4
0
def plot_residuals(y_true: Data,
                   y_pred: Data,
                   title: str = None,
                   ax: Axes = None) -> Axes:
    """
    Plots residuals from a regression.

    :param y_true:
        True values

    :param y_pred:
        Models predicted value

    :param title:
        Plot title

    :param ax:
        Pass your own ax

    :return:
        matplotlib.Axes
    """
    title = f'Residual Plot' if title is None else title

    residuals = y_pred - y_true
    r2 = r2_score(y_true, y_pred)

    if ax is None:
        fig, ax = plt.subplots()

    ax.scatter(y_pred, residuals, label=f'$R^2 = {r2:0.3f}$')
    ax.axhline(y=0, color='grey', linestyle='--')
    ax.set_ylabel('Residuals')
    ax.set_xlabel('Predicted Value')
    ax.set_title(title)
    ax.legend(loc='best')
    return ax
Пример #5
0
def plot_residuals(
    y_true: DataType, y_pred: DataType, title: str = None, ax: Axes = None
) -> Axes:
    """
    Plots residuals from a regression.

    :param y_true:
        True values

    :param y_pred:
        Models predicted value

    :param title:
        Plot title

    :param ax:
        Pass your own ax

    :return:
        matplotlib.Axes
    """
    title = "Residual Plot" if title is None else title

    residuals = y_pred - y_true
    r2 = r2_score(y_true, y_pred)

    if ax is None:
        fig, ax = plt.subplots()

    ax.scatter(y_pred, residuals, label=f"$R^2 = {r2:0.3f}$")
    ax.axhline(y=0, color="grey", linestyle="--")
    ax.set_ylabel("Residuals")
    ax.set_xlabel("Predicted Value")
    ax.set_title(title)
    ax.legend(loc="best")
    return ax
Пример #6
0
 def plot_envelope_dist(self, ax: Axes):
     yrange = self.e_t.span
     sample = choice(self.e_t, 5000)
     kde = KernelDensity(bandwidth=0.02 * yrange)
     kde.fit(as_data_matrix(sample))
     e_dom = linspace(*self.e_t.range, 500)
     density = exp(kde.score_samples(as_data_matrix(e_dom)))
     ax.fill_betweenx(e_dom, density, color=envelope_color)
     ax.axhline(0, color="gray", lw=thin_lw)
     rm = self.reference_maker
     threshold_extent = 1.21
     kwargs = dict(
         xmin=0,
         xmax=threshold_extent,
         color=threshold_color,
         lw=thin_lw,
         clip_on=False,
     )
     ax.axhline(rm.ripple_threshold_high, **kwargs)
     ax.axhline(rm.ripple_threshold_low, **kwargs)
     ax.axhline(rm.envelope_median, linestyle=":", **kwargs)
     ax.set_xticks([])
     ax.set_yticks([])
     add_title(ax,
               "Empirical\ndistribution of $n_t$",
               envelope_color,
               x=0.1,
               y=0.8)
     text_kwargs = dict(
         x=threshold_extent + 0.05,
         color=threshold_color,
         transform=ax.get_yaxis_transform(),
         fontsize=0.69 * annotation_text_size,
         va="center",
     )
     ax.text(y=rm.ripple_threshold_high, s="$T_{high}$", **text_kwargs)
     ax.text(y=rm.ripple_threshold_low, s="$T_{low}$", **text_kwargs)
     ax.text(y=rm.envelope_median, s="Median", **text_kwargs)
Пример #7
0
def growth_curve(ax: Axes,
                 plate: Plate,
                 scatter_color: str,
                 line_color: str = None,
                 growth_params: bool = True):
    """
    Add a growth curve scatter plot, with median, to an axis

    :param ax: a Matplotlib Axes object to add a plot to
    :param plate: a Plate instance
    :param scatter_color: a Colormap color
    :param line_color: a Colormap color for the median
    """
    from statistics import median

    if line_color is None:
        line_color = scatter_color

    for colony in plate.items:
        ax.scatter(
            # Matplotlib does not yet support timedeltas so we have to convert manually to float
            [
                td.total_seconds() / 3600
                for td in sorted(colony.growth_curve.data.keys())
            ],
            list(colony.growth_curve.data.values()),
            color=scatter_color,
            marker="o",
            s=1,
            alpha=0.25)

    # Plot the median
    ax.plot([
        td.total_seconds() / 3600
        for td in sorted(plate.growth_curve.data.keys())
    ], [median(val) for _, val in sorted(plate.growth_curve.data.items())],
            color=line_color,
            label="Median" if growth_params else f"Plate {plate.id}",
            linewidth=2)

    if growth_params:
        # Plot lag, vmax and carrying capacity lines
        if plate.growth_curve.lag_time.total_seconds() > 0:
            line = ax.axvline(plate.growth_curve.lag_time.total_seconds() /
                              3600,
                              color="grey",
                              linestyle="dashed",
                              alpha=0.5)
            line.set_label("Lag time")

        if plate.growth_curve.carrying_capacity > 0:
            line = ax.axhline(plate.growth_curve.carrying_capacity,
                              color="blue",
                              linestyle="dashed",
                              alpha=0.5)
            line.set_label("Carrying\ncapacity")

        if plate.growth_curve.growth_rate > 0:
            y0, y1 = 0, plate.growth_curve.carrying_capacity
            x0 = plate.growth_curve.lag_time.total_seconds() / 3600
            x1 = ((y1 - y0) / (plate.growth_curve.growth_rate * 3600)) + x0
            ax.plot([x0, x1], [y0, y1],
                    color="red",
                    linestyle="dashed",
                    alpha=0.5,
                    label="Maximum\ngrowth rate")
Пример #8
0
def convergence_boxplot(targets: pd.DataFrame, results: pd.DataFrame, filter_func: Callable[[pd.Series], pd.Series],
                        adjust_target: bool = True, percentage: bool = True, band: Tuple[float, float] = None,
                        simple_labels: bool = True, ax: Axes = None, fp: Path = None, title: str = None) -> Axes:
    """Measures convergence of constrained location-choice models (such as work-location choice). Can be used to
    produce multiple box plots for different sub-sets of zones, usually based on size.

    Args:
        targets (pandas.DataFrame):
        results (pandas.DataFrame):
        filter_func (Callable[[pandas.Series], pandas.Series]):
        adjust_target (bool, optional):
        percentage (bool, optional):
        band (Tuple[float, float], optional):
        simple_labels (bool, optional):
        ax (Axes, optional):
        fp (Path, optional):
        title (str, optional):

    Returns:
        matplotlib.Axes
    """

    assert results.columns.equals(targets.columns)

    columns, filters, n = [], [], 0
    for colname in targets:
        filter_ = filter_func(targets[colname])
        filters.append(filter_)
        n = max(n, filter_.sum())
        columns.append(colname)

    unlabelled_zones = np.full([n, len(columns)], np.nan, dtype=np.float64)
    model_sums, target_sums = [], []

    for i, (colname, filter_) in enumerate(zip(columns, filters)):
        m = filter_.sum()

        model_vector = results.loc[filter_, colname]
        target_vector = targets.loc[filter_, colname]

        if adjust_target and target_vector.sum() > 0:
            factor = model_vector.sum() / target_vector.sum()
            target_vector = target_vector * factor

        model_sums.append(model_vector.sum())
        target_sums.append(target_vector.sum())

        err = model_vector - target_vector
        if percentage:
            err /= target_vector

        unlabelled_zones[:m, i] = err.values

    if not simple_labels:
        columns = [
            "{}\n{} workers\n{} jobs\n{} zones".format(c, model_sums[i], int(target_sums[i]), filters[i].sum())
            for i, c in enumerate(columns)
        ]
    unlabelled_zones = pd.DataFrame(unlabelled_zones, columns=columns)

    with np.errstate(invalid='ignore'):
        ax = unlabelled_zones.plot.box(ax=ax, figsize=[12, 6])
        ax.axhline(0)

        if percentage:
            ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: "{}%".format(np.round(x, 2) * 100)))
            ax.set_ylabel("Relative error ((Model - Target) / Target)")
        else:
            ax.set_ylabel("Error (Model - Target)")

        xlabel = "Occupation & Employment Status"
        if adjust_target:
            xlabel += "\n(Targets adjusted to match model totals)"
        ax.set_xlabel(xlabel)

        if band is not None:
            lower, upper = band
            ax.axhline(lower, color='black', linewidth=1, alpha=0.5)
            ax.axhline(upper, color='black', linewidth=1, alpha=0.5)

        if title:
            ax.set_title(title)

        if fp is not None:
            plt.savefig(str(fp))

        return ax
Пример #9
0
def plot_lift_curve(
    y_true: DataType,
    y_proba: DataType,
    title: str = None,
    ax: Axes = None,
    labels: List[str] = None,
    threshold: float = 0.5,
) -> Axes:
    """
    Plot a lift chart from results. Also calculates lift score based on a .5 threshold

    Parameters
    ----------
    y_true: DataType
        True labels

    y_proba: DataType
        Model's predicted probability

    title: str
        Plot title

    ax: Axes
        Pass your own ax

    labels: List of str
        Labels to use per class

    threshold: float
        Threshold to use when determining lift score

    Returns
    -------
    matplotlib.Axes
    """

    if ax is None:
        fig, ax = plt.subplots()

    title = "Lift Curve" if title is None else title
    classes = np.unique(y_true)
    binarized_labels = label_binarize(y_true, classes=classes)

    if labels and len(labels) != len(classes):
        raise VizError("Number of labels must match number of classes: "
                       f"got {len(labels)} labels and {len(classes)} classes")

    if binarized_labels.shape[1] == 1:
        # Binary classification case
        percents, gains = _cum_gain_curve(binarized_labels, y_proba[:, 1])
        score = lift_score(binarized_labels.ravel(), y_proba[:, 1] > threshold)
        ax.plot(percents, gains / percents, label=f"$Lift = {score:.2f}$")
    else:
        # Multi-class case
        for class_ in classes:
            percents, gains = _cum_gain_curve(binarized_labels[:, class_],
                                              y_proba[:, class_])
            score = lift_score(binarized_labels[:, class_],
                               y_proba[:, class_] > threshold)
            ax.plot(
                percents,
                gains / percents,
                label=f"Class {labels[class_] if labels else class_} "
                f"$Lift = {score:.2f}$ ",
            )

    ax.axhline(y=1, color="grey", linestyle="--", label="Baseline")
    ax.set_title(title)
    ax.set_ylabel("Lift")
    ax.set_xlabel("% of Data")
    formatter = PercentFormatter(xmax=1)
    ax.xaxis.set_major_formatter(formatter)
    ax.legend()
    return ax
Пример #10
0
def plot_areas(
    fig: Figure,
    ax: Axes,
    samples: SampleList,
    compound_names: List[str],
    include_none: bool = False,
    show_scores: bool = False,
    legend_cols: int = 6,
    mz_range=None,
    show_score_in_legend: bool = False,
) -> Tuple[Figure, Axes]:
    """
	Plot the peak area and score for the compounds with the given names

	:param fig:
	:param ax:
	:param samples: A list of samples to plot on the chart
	:param compound_names: A list of compounds to plot
	:param include_none: Whether samples where the compound was not found should be plotted.
	:param show_scores: Whether the scores should be shown on the chart.
	:param legend_cols:
	:param mz_range:
	:param show_score_in_legend:
	"""

    areas_dict, scores_dict = samples.get_areas_and_scores_for_compounds(
        compound_names, include_none)

    if show_scores:
        ax2 = ax.twiny()

    y_positions = numpy.arange(len(areas_dict))
    y_positions = [x * 1.5 for x in y_positions]

    # n_samples = areas_dict.n_samples
    n_compounds = len(compound_names)

    bar_width = 1.5 / (n_compounds + 1)

    # TODO: bar_spacing = bar_width / (n_samples + 1)

    bar_offsets = list(
        numpy.arange((0 - ((bar_width / 2) * (n_compounds - 1))),
                     (0 + ((bar_width / 2) * n_compounds)),
                     bar_width))[::-1]  # Reverse order

    sample_names = areas_dict.sample_names

    divider_positions = set()

    for cpd_idx, compound_name in enumerate(compound_names):
        compound_y_positions = []
        compound_areas = areas_dict.get_compound_areas(compound_name)
        compound_scores = scores_dict.get_compound_scores(compound_name)

        for sample_idx, sample_name in enumerate(sample_names):
            compound_y_positions.append(y_positions[sample_idx] +
                                        bar_offsets[cpd_idx])
            divider_positions.add((y_positions[sample_idx] + bar_offsets)[0] +
                                  bar_width)
            divider_positions.add((y_positions[sample_idx] + bar_offsets)[-1] -
                                  bar_width)

        ax.barh(compound_y_positions,
                compound_areas,
                label=compound_name,
                height=bar_width,
                edgecolor="black",
                linewidth=0.25)

        if show_scores:
            score_scatter = ax2.scatter(
                [x if x else None for x in compound_scores],
                compound_y_positions,
                color=[
                    "black" if s >= 75 else "orange" for s in compound_scores
                ],
                s=bar_width * 50)
        # for area, ypos in zip(compound_areas, compound_y_positions):
        # 	score_text = ax.text(area, ypos, "Score", va='center')

    for pos in divider_positions:
        ax.axhline(pos,
                   color="black",
                   linewidth=0.5,
                   xmin=-0.01,
                   clip_on=False)

    loc = plticker.MultipleLocator(base=bar_width)
    ax.yaxis.set_minor_locator(loc)
    ax.grid(which="minor", axis='y', linestyle='-')
    ax.set_ylim(bottom=min(divider_positions), top=max(divider_positions))
    ax.set_yticks(y_positions)
    ax.set_xscale("log")
    ax.set_xlabel("Log$_{10}$(Peak Area)", labelpad=0)
    ax.set_yticklabels(sample_names)

    if show_scores:
        min_score = 40
        ax2.set_xlim(
            left=min_score, right=100
        )  # Compounds with scores below 50 were excluded by MassHunter
        ax2.grid(False)
        ax2.set_xlabel("Score", ha="center")
        ax2.set_xticks(numpy.arange(min_score, 110, 10))
        # ax2.set_xticks([0, 10, 20, 30, 40, 60, 70, 80, 90, 100])
        ax.scatter([], [], label="Score", color="black")

    legend(fig,
           loc="lower center",
           ncol=legend_cols,
           mz_range=mz_range,
           show_score=show_score_in_legend)

    return fig, ax
Пример #11
0
def plot_head2tail(
		ax: Axes,
		top_mass_spec: MassSpectrum,
		bottom_mass_spec: MassSpectrum,
		top_spec_kwargs: Optional[Dict] = None,
		bottom_spec_kwargs: Optional[Dict] = None,
		) -> Tuple[BarContainer, BarContainer]:
	"""
	Plots two mass spectra head to tail.

	:param ax: The axes to plot the MassSpectra on

	:param top_mass_spec: The Mass Spectrum to plot on top
	:param bottom_mass_spec: The Mass Spectrum to plot on the bottom
	:param top_spec_kwargs: A dictionary of keyword arguments for the top mass spectrum.
		Defaults to red with a line width of 0.5
	:no-default top_spec_kwargs:
	:param bottom_spec_kwargs: A dictionary of keyword arguments for the bottom mass spectrum.
		Defaults to blue with a line width of 0.5
	:no-default bottom_spec_kwargs:

	`top_spec_kwargs` and `bottom_spec_kwargs` are used to specify properties like a line label
		(for auto legends), linewidth, antialiasing, marker face color.

		See https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.lines.Line2D.html
		for the list of possible kwargs

	:return: A tuple of container with all the bars and optionally errorbars for the top and bottom spectra.
	:rtype: tuple of :class:`matplotlib.container.BarContainer`
	"""

	if not isinstance(top_mass_spec, MassSpectrum):
		raise TypeError("'top_mass_spec' must be a MassSpectrum")

	if not isinstance(bottom_mass_spec, MassSpectrum):
		raise TypeError("'bottom_mass_spec' must be a MassSpectrum")

	if top_spec_kwargs is None:
		top_spec_kwargs = dict(color="red", width=0.5)
	elif not isinstance(top_spec_kwargs, dict):
		raise TypeError("'top_spec_kwargs' must be a dictionary of keyword arguments for the top mass spectrum.")

	if bottom_spec_kwargs is None:
		bottom_spec_kwargs = dict(color="blue", width=0.5)
	elif not isinstance(bottom_spec_kwargs, dict):
		raise TypeError(
				"'bottom_spec_kwargs' must be a dictionary of keyword arguments for the bottom mass spectrum."
				)

	# Plot a line at y=0 with same width and colour as Spines
	ax.axhline(y=0, color=ax.spines["bottom"].get_edgecolor(), linewidth=ax.spines["bottom"].get_linewidth())

	# Normalize the mass spectra
	top_mass_spec = normalize_mass_spec(top_mass_spec)
	bottom_mass_spec = normalize_mass_spec(bottom_mass_spec)

	# Invert bottom mass spec
	invert_mass_spec(bottom_mass_spec, inplace=True)

	top_plot = plot_mass_spec(ax, top_mass_spec, **top_spec_kwargs)
	bottom_plot = plot_mass_spec(ax, bottom_mass_spec, **bottom_spec_kwargs)

	# Set ylim to 1.1 times max/min values
	ax.set_ylim(
			bottom=min(bottom_mass_spec.intensity_list) * 1.1,
			top=max(top_mass_spec.intensity_list) * 1.1,
			)

	# ax.spines['bottom'].set_position('zero')

	return top_plot, bottom_plot
def show_perf_vs_size(
    x_list: List[np.ndarray],
    y_list: List[np.ndarray],
    label_list: List[str],
    *,
    xlabel: str = None,
    ylabel: str = None,
    title: str = None,
    ax: Axes = None,
    xticks=(0, 25, 50, 75, 100),
    yticks=(0, 0.5, 1),
    xlim=(0, 100),
    ylim=(0, 1),
    xticklabels=('0', '25', '50', '75', '100'),
    yticklabels=('0', '0.5', '1'),
    style_list=None,
    linewidth=1,
    show_legend=True,
    legend_param=None,
    vline=None,
    hline=None,
    xlabel_param=None,
    # letter=None,
):
    """x being model size, number of parameter, dataset size, etc.
    y being performance.
    """

    if style_list is None:
        # should give a default set
        raise NotImplementedError

    if xlabel_param is None:
        xlabel_param = dict()

    # if letter is not None:
    #     ax.text(0, 1, letter, horizontalalignment='left', verticalalignment='top',
    #             transform=ax.get_figure().transFigure, fontweight='bold')

    assert len(x_list) == len(y_list) == len(label_list)
    for idx, (x_this, y_this,
              label_this) in enumerate(zip(x_list, y_list, label_list)):
        linestyle, color, marker = style_list[idx]
        ax.plot(x_this,
                y_this,
                linestyle=linestyle,
                color=color,
                marker=marker,
                label=label_this,
                linewidth=linewidth)

    if vline is not None:
        # color maybe adjusted later
        ax.axvline(vline, color='black', linewidth=linewidth, linestyle='--')

    if hline is not None:
        # color maybe adjusted later
        ax.axhline(hline, color='black', linewidth=linewidth, linestyle='--')

    # ax.set_xlim(0, 1)
    ax.set_xlim(*xlim)
    ax.set_ylim(*ylim)
    ax.set_xticks(xticks)
    ax.set_yticks(yticks)
    ax.set_xticklabels(xticklabels, **xlabel_param)
    ax.set_yticklabels(yticklabels)

    if xlabel is not None:
        ax.set_xlabel(xlabel)
    if ylabel is not None:
        ax.set_ylabel(ylabel)
    if title is not None:
        ax.set_title(title)

    if show_legend:
        if legend_param is None:
            ax.legend()
        else:
            ax.legend(**legend_param)
Пример #13
0
    def plot_z_trends(self, axis: Axes = None) -> None:

        if axis is None:
            axis = self.figure.add_subplot(111)

        cluster = Cluster(simulation_name=self.simulation.simulation_name,
                          clusterID=0,
                          redshift='z000p000')
        aperture_float = self.get_apertures(cluster)[
            self.aperture_id] / cluster.r200

        if not os.path.isfile(
                os.path.join(
                    self.path,
                    f'redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy'
                )):
            warnings.warn(
                f"File redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy not found."
            )
            print("self.make_simbootstrap() activated.")
            self.make_simbootstrap()

        print(
            f"Retrieving npy files: redshift_rot0rot4_bootstrap_aperture_{self.aperture_id}.npy"
        )
        sim_bootstrap = np.load(os.path.join(
            self.path, f'redshift_rot0rot4_bootstrap_aperture_'
            f'{self.aperture_id}.npy'),
                                allow_pickle=True)
        sim_bootstrap = np.asarray(sim_bootstrap)

        items_labels = f""" REDSHIFT TRENDS
							Number of clusters: {self.simulation.totalClusters:d}
							$z$ = 0.0 - 1.8
							Aperture radius = {aperture_float:.2f} $R_{{200\ true}}$"""
        print(items_labels)

        sim_colors = {
            'ceagle': 'pink',
            'celr_e': 'lime',
            'celr_b': 'orange',
            'macsis': 'aqua',
        }

        axis.axhline(90, linestyle='--', color='k', alpha=0.5, linewidth=2)

        axis.plot(sim_bootstrap[0, 0],
                  sim_bootstrap[3, 0],
                  color=sim_colors[self.simulation.simulation_name],
                  alpha=1,
                  linestyle='none',
                  marker='^',
                  markersize=10)
        axis.plot(sim_bootstrap[0, 0],
                  sim_bootstrap[2, 0],
                  color=sim_colors[self.simulation.simulation_name],
                  alpha=1,
                  linestyle='none',
                  marker='o',
                  markersize=10)
        axis.plot(sim_bootstrap[0, 0],
                  sim_bootstrap[1, 0],
                  color=sim_colors[self.simulation.simulation_name],
                  alpha=1,
                  linestyle='none',
                  marker='v',
                  markersize=10)

        for marker_index in range(len(sim_bootstrap[0, 0])):

            if marker_index is 0:
                align_toggle = 'edge'
                x_edge_left = sim_bootstrap[0, 0][marker_index]
                x_edge_right = sim_bootstrap[
                    0, 0][marker_index] + sim_bootstrap[0, 1][marker_index]
            else:
                align_toggle = 'center'
                x_edge_left = sim_bootstrap[
                    0, 0][marker_index] - sim_bootstrap[0, 1][marker_index] / 2
                x_edge_right = sim_bootstrap[
                    0, 0][marker_index] + sim_bootstrap[0, 1][marker_index] / 2

            axis.plot([x_edge_left, x_edge_right], [
                sim_bootstrap[3, 0][marker_index],
                sim_bootstrap[3, 0][marker_index]
            ],
                      color=sim_colors[self.simulation.simulation_name],
                      alpha=0.8,
                      linestyle='--',
                      lw=1.5)

            axis.plot([x_edge_left, x_edge_right], [
                sim_bootstrap[2, 0][marker_index],
                sim_bootstrap[2, 0][marker_index]
            ],
                      color=sim_colors[self.simulation.simulation_name],
                      alpha=0.8,
                      linestyle='-',
                      lw=1.5)

            axis.plot([x_edge_left, x_edge_right], [
                sim_bootstrap[1, 0][marker_index],
                sim_bootstrap[1, 0][marker_index]
            ],
                      color=sim_colors[self.simulation.simulation_name],
                      alpha=0.8,
                      linestyle='-.',
                      lw=1.5)

            axis.bar(sim_bootstrap[0, 0][marker_index],
                     2 * sim_bootstrap[3, 1][marker_index],
                     bottom=sim_bootstrap[3, 0][marker_index] -
                     sim_bootstrap[3, 1][marker_index],
                     width=sim_bootstrap[0, 1][marker_index],
                     align=align_toggle,
                     color=sim_colors[self.simulation.simulation_name],
                     alpha=0.2,
                     edgecolor='none',
                     linewidth=0)
            axis.bar(sim_bootstrap[0, 0][marker_index],
                     2 * sim_bootstrap[2, 1][marker_index],
                     bottom=sim_bootstrap[2, 0][marker_index] -
                     sim_bootstrap[2, 1][marker_index],
                     width=sim_bootstrap[0, 1][marker_index],
                     align=align_toggle,
                     color=sim_colors[self.simulation.simulation_name],
                     alpha=0.2,
                     edgecolor='none',
                     linewidth=0)
            axis.bar(sim_bootstrap[0, 0][marker_index],
                     2 * sim_bootstrap[1, 1][marker_index],
                     bottom=sim_bootstrap[1, 0][marker_index] -
                     sim_bootstrap[1, 1][marker_index],
                     width=sim_bootstrap[0, 1][marker_index],
                     align=align_toggle,
                     color=sim_colors[self.simulation.simulation_name],
                     alpha=0.2,
                     edgecolor='none',
                     linewidth=0)

        perc84 = Line2D([], [],
                        color='k',
                        marker='^',
                        linestyle='--',
                        markersize=10,
                        label=r'$84^{th}$ percentile')
        perc50 = Line2D([], [],
                        color='k',
                        marker='o',
                        linestyle='-',
                        markersize=10,
                        label=r'median')
        perc16 = Line2D([], [],
                        color='k',
                        marker='v',
                        linestyle='-.',
                        markersize=10,
                        label=r'$16^{th}$ percentile')
        patch_ceagle = Patch(facecolor=sim_colors['ceagle'],
                             label='C-EAGLE',
                             edgecolor='k',
                             linewidth=1)
        patch_celre = Patch(facecolor=sim_colors['celr_e'],
                            label='CELR-E',
                            edgecolor='k',
                            linewidth=1)
        patch_celrb = Patch(facecolor=sim_colors['celr_b'],
                            label='CELR-B',
                            edgecolor='k',
                            linewidth=1)
        patch_macsis = Patch(facecolor=sim_colors['macsis'],
                             label='MACSIS',
                             edgecolor='k',
                             linewidth=1)

        leg1 = axis.legend(handles=[perc84, perc50, perc16],
                           loc='lower right',
                           handlelength=3,
                           fontsize=20)
        leg2 = axis.legend(
            handles=[patch_ceagle, patch_celre, patch_celrb, patch_macsis],
            loc='lower left',
            handlelength=1,
            fontsize=20)
        axis.add_artist(leg1)
        axis.add_artist(leg2)
        axis.text(0.03,
                  0.97,
                  items_labels,
                  horizontalalignment='left',
                  verticalalignment='top',
                  transform=axis.transAxes,
                  size=15)

        axis.set_xlabel(r"$z$", size=25)
        axis.set_ylabel(
            r"$\Delta \theta \equiv (\mathbf{L},\mathrm{\widehat{CoP}},\mathbf{v_{pec}})$\quad[degrees]",
            size=25)
        axis.set_ylim(0, 180)