def set_axis_integer(ax_: plt.Axes, axis='x'): if axis == 'x': axis = ax_.get_xaxis() elif axis == 'y': axis = ax_.get_yaxis() else: raise ValueError axis.set_major_locator(MultipleLocator(1))
def _plot_overlapping(ax: pl.Axes, data: pd.DataFrame) -> None: cumulative_data = data[["WINTER_YEAR", "SNOW"]].groupby(["WINTER_YEAR"]).cumsum() cumulative_data["WINTER_YEAR"] = data["WINTER_YEAR"] # Create a new index adjusted to be all in the same year (ignore the # specific year) by normalizing to timedelta since start of winter year # then adding it to an arbitrary year. deltas = cumulative_data.index - cumulative_data["WINTER_YEAR"] index_same_year = (pd.Timestamp(year=2000, day=1, month=7) + deltas - pd.Timedelta(days=1)) # Update winter year to be just the year int, for column labels after pivot data_overlapping = cumulative_data.assign( WINTER_YEAR=cumulative_data["WINTER_YEAR"].dt.year) data_overlapping.set_index(index_same_year, inplace=True) # Pivot WINTER_YEAR to be the new columns data_overlapping = data_overlapping.pivot(columns="WINTER_YEAR", values="SNOW") # Plot data_overlapping.plot(ax=ax, legend=False) label_lines.label_all(ax, xoffset=0.0, yoffset=-0.02, fontsize=6) ax.set_xlabel("Month") ax.set_ylabel("Snowfall (inches)") # Put a major tick per month locator = mdates.MonthLocator() fmt = mdates.DateFormatter("%b") ax.get_xaxis().set_major_locator(locator) ax.get_xaxis().set_major_formatter(fmt) ax.get_xaxis().set_visible(True)
def _remove_ticklabels(axis: plt.Axes): axis.get_yaxis().set_ticklabels([]) axis.get_xaxis().set_ticklabels([])
def draw_categorical( plot_type: str, ax: plt.Axes, data: Union[list, np.ndarray, to.Tensor, pd.DataFrame], x_label: Optional[Union[str, Sequence[str]]], y_label: Optional[str], vline_level: float = None, vline_label: str = "approx. solved", palette=None, title: str = None, show_legend: bool = True, legend_kwargs: dict = None, plot_kwargs: dict = None, ) -> plt.Figure: """ Create a box or violin plot for a list of data arrays or a pandas DataFrame. The plot is neither shown nor saved. If you want to order the 4th element to the 2nd position in terms of colors use .. code-block:: python palette.insert(1, palette.pop(3)) .. note:: If you want to have a tight layout, it is best to pass axes of a figure with `tight_layout=True` or `constrained_layout=True`. :param plot_type: tye of categorical plot, pass box or violin :param ax: axis of the figure to plot on :param data: list of data sets to plot as separate boxes :param x_label: labels for the categories on the x-axis, if `data` is not given as a `DataFrame` :param y_label: label for the y-axis, pass `None` to set no label :param vline_level: if not `None` (default) add a vertical line at the given level :param vline_label: label for the vertical line :param palette: seaborn color palette, pass `None` to use the default palette :param show_legend: if `True` the legend is shown, useful when handling multiple subplots :param title: title displayed above the figure, set to None to suppress the title :param legend_kwargs: keyword arguments forwarded to pyplot's `legend()` function, e.g. `loc='best'` :param plot_kwargs: keyword arguments forwarded to seaborn's `boxplot()` or `violinplot()` function :return: handle to the resulting figure """ plot_type = plot_type.lower() if plot_type not in ["box", "violin"]: raise pyrado.ValueErr(given=plot_type, eq_constraint="box or violin") if not isinstance(data, (list, to.Tensor, np.ndarray, pd.DataFrame)): raise pyrado.TypeErr( given=data, expected_type=[list, to.Tensor, np.ndarray, pd.DataFrame]) # Set defaults which can be overwritten plot_kwargs = merge_dicts([dict(alpha=1), plot_kwargs]) # by default no transparency alpha = plot_kwargs.pop( "alpha") # can't pass the to the seaborn plotting functions legend_kwargs = dict() if legend_kwargs is None else legend_kwargs palette = sns.color_palette() if palette is None else palette # Preprocess if isinstance(data, pd.DataFrame): df = data else: if isinstance(data, list): data = np.array(data) elif isinstance(data, to.Tensor): data = data.detach().cpu().numpy() if x_label is not None and not len(x_label) == data.shape[1]: raise pyrado.ShapeErr(given=data, expected_match=x_label) df = pd.DataFrame(data, columns=x_label) if data.shape[0] < data.shape[1]: print_cbt( f"Less data samples {data.shape[0]} then data dimensions {data.shape[1]}", "y", bright=True) # Plot if plot_type == "box": ax = sns.boxplot(data=df, ax=ax, **plot_kwargs) elif plot_type == "violin": plot_kwargs = merge_dicts([ dict(alpha=0.3, scale="count", inner="box", bw=0.3, cut=0), plot_kwargs ]) ax = sns.violinplot(data=df, ax=ax, palette=palette, **plot_kwargs) # Plot larger circles for medians (need to memorize the limits) medians = df.median().to_numpy() left, right = ax.get_xlim() locs = ax.get_xticks() ax.scatter(locs, medians, marker="o", s=30, zorder=3, color="white", edgecolors="black") ax.set_xlim((left, right)) # Postprocess if alpha < 1 and plot_type == "box": for patch in ax.artists: r, g, b, a = patch.get_facecolor() patch.set_facecolor((r, g, b, alpha)) elif alpha < 1 and plot_type == "violin": for violin in ax.collections[::2]: violin.set_alpha(alpha) if vline_level is not None: # Add dashed line to mark a threshold ax.axhline(vline_level, c="k", ls="--", lw=1.0, label=vline_label) if x_label is None: ax.get_xaxis().set_ticks([]) if y_label is not None: ax.set_ylabel(y_label) if show_legend: ax.legend(**legend_kwargs) if title is not None: ax.set_title(title) return plt.gcf()
def style_axes( ax: plt.Axes, title: str = "", legend_title: str = "", xlab: str = "", ylab: str = "", title_loc: Literal["center", "left", "right"] = "center", title_pad: float = None, title_fontsize: int = 10, label_fontsize: int = 8, tick_fontsize: int = 8, change_xticks: bool = True, add_legend: bool = True, ) -> None: """Style an axes object. Parameters ---------- ax Axis object to style. title Figure title. legend_title Figure legend title. xlab Label for the x axis. ylab Label for the y axis. title_loc Position of the plot title (can be {'center', 'left', 'right'}). title_pad Padding of the plot title. title_fontsize Font size of the plot title. label_fontsize Font size of the axis labels. tick_fontsize Font size of the axis tick labels. change_xticks REmoves ticks from x axis. add_legend Font size of the axis tick labels. """ ax.set_title( title, fontdict={"fontsize": title_fontsize}, pad=title_pad, loc=title_loc ) ax.set_xlabel(xlab, fontsize=label_fontsize) # ax.set_xticklabels(ax.get_xticklabels(), fontsize=tick_fontsize) ax.set_ylabel(ylab, fontsize=label_fontsize) # ax.set_yticklabels(ax.get_yticklabels(), fontsize=tick_fontsize) ax.set_title( title, fontdict={"fontsize": title_fontsize}, pad=title_pad, loc=title_loc ) ax.set_xlabel(xlab, fontsize=label_fontsize) if change_xticks: ax.set_xticklabels( ax.get_xticklabels(), fontsize=tick_fontsize, rotation=30, ha="right" ) xax = ax.get_xaxis() xax.set_tick_params(length=0) ax.set_ylabel(ylab, fontsize=label_fontsize) ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) if add_legend: ax.legend( title=legend_title, loc="upper left", bbox_to_anchor=(1.2, 1), title_fontsize=label_fontsize, fontsize=tick_fontsize, frameon=False, ) ax.set_position([0.1, 0.3, 0.6, 0.55])
def draw_curve(plot_type: str, ax: plt.Axes, data: pd.DataFrame, x_grid: Union[list, np.ndarray, to.Tensor], x_label: Optional[Union[str, Sequence[str]]] = None, y_label: Optional[str] = None, curve_label: Optional[str] = None, area_label: Optional[str] = None, vline_level: Optional[float] = None, vline_label: str = 'approx. solved', title: Optional[str] = None, show_legend: bool = True, legend_kwargs: dict = None, plot_kwargs: dict = None) -> plt.Figure: """ Create a box or violin plot for a list of data arrays or a pandas DataFrame. The plot is neither shown nor saved. .. note:: If you want to have a tight layout, it is best to pass axes of a figure with `tight_layout=True` or `constrained_layout=True`. If you want to order the 4th element to the 2nd position in terms of colors use .. code-block:: python palette.insert(1, palette.pop(3)) :param plot_type: tye of categorical plot, pass box or violin :param ax: axis of the figure to plot on :param data: pandas DataFrame containing the columns `mean`, `std`, `min`, and `max` depending on the `plot_type` :param x_grid: values to plot the data over, e.g. time :param x_label: labels for the categories on the x-axis, if `data` is not given as a `DataFrame` :param y_label: label for the y-axis, pass `None` to set no label :param curve_label: label of the (1-dim) curve :param area_label: label of the (transparent) area :param vline_level: if not `None` (default) add a vertical line at the given level :param vline_label: label for the vertical line :param show_legend: if `True` the legend is shown, useful when handling multiple subplots :param title: title displayed above the figure, set to None to suppress the title :param legend_kwargs: keyword arguments forwarded to pyplot's `legend()` function, e.g. `loc='best'` :param plot_kwargs: keyword arguments forwarded to seaborn's `boxplot()` or `violinplot()` function :return: handle to the resulting figure """ plot_type = plot_type.lower() if plot_type not in ['mean_std', 'min_mean_max']: raise pyrado.ValueErr(given=plot_type, eq_constraint='mean_std or min_mean_max') if not isinstance(data, pd.DataFrame): raise pyrado.TypeErr(given=data, expected_type=pd.DataFrame) if x_label is not None and not isinstance(x_label, str): raise pyrado.TypeErr(given=x_label, expected_type=str) if y_label is not None and not isinstance(y_label, str): raise pyrado.TypeErr(given=y_label, expected_type=str) # Set defaults which can be overwritten by passing plot_kwargs plot_kwargs = merge_dicts([dict(alpha=0.3), plot_kwargs]) legend_kwargs = dict() if legend_kwargs is None else legend_kwargs # palette = sns.color_palette() if palette is None else palette # Preprocess if isinstance(x_grid, list): x_grid = np.array(x_grid) elif isinstance(x_grid, to.Tensor): x_grid = x_grid.detach().cpu().numpy() # Plot if plot_type == 'mean_std': if not ('mean' in data.columns and 'std' in data.columns): raise pyrado.KeyErr(keys="'mean' and 'std'", container=data) num_stds = 2 if area_label is None: area_label = rf'$\pm {num_stds}$ std' ax.fill_between(x_grid, data['mean'] - num_stds * data['std'], data['mean'] + num_stds * data['std'], label=area_label, **plot_kwargs) elif plot_type == 'min_mean_max': if not ('mean' in data.columns and 'min' in data.columns and 'max' in data.columns): raise pyrado.KeyErr(keys="'mean' and 'min' and 'max'", container=data) if area_label is None: area_label = r'min \& max' ax.fill_between(x_grid, data['min'], data['max'], label=area_label, **plot_kwargs) # plot mean last for proper z-ordering plot_kwargs['alpha'] = 1 ax.plot(x_grid, data['mean'], label=curve_label, **plot_kwargs) # Postprocess if vline_level is not None: # Add dashed line to mark a threshold ax.axhline(vline_level, c='k', ls='--', lw=1., label=vline_label) if x_label is None: ax.get_xaxis().set_ticks([]) if y_label is not None: ax.set_ylabel(y_label) if show_legend: ax.legend(**legend_kwargs) if title is not None: ax.set_title(title) return plt.gcf()
def hexplot_TEST( node_data, decimals: int = 0, var_lim: Iterable = None, c: object = None, lc: str = 'k', #edge_data: Dict=None, edge_c='r', # EDGE DATA NOT IMPLEMENTED YET ax: plt.Axes = None, scale_factor: float = 0.015): """ Plot a map of the hexagonal lattice of the megaphragma compound eye. Each ommatidium will be labelled and coloured according to the strings and (r, g, b, a) values passed with node_data. This will also take a 1-col dataframe indexed by om TODO: fix dataframe input options, type of cmap as an arg, use plt.scatter instead of all the networkx functions? :param node_data: Dict, {om: {'label': str, {'outline': matplotlib line spec, e.g. '-', {'colour': (rgba)}} :param edge_data: :param ax: plt.Axes, if None, will plot to current Axis :param scale_factor: float, controls the spacing between nodes :c: Default node colour (if node_data: colours is None) :param e_colour: Default edge colour (if edge_data is used) :return: """ if c == None: # default color c = (0.2, 0.2, 0.2, 1) if not isinstance(node_data, Dict): node_data = __from_series(node_data, c=c, var_lim=var_lim, decimals=decimals) if ax == None: ax = plt.gca() om_list = sorted([str(om) for om in node_data.keys()]) pos = [om_to_hex(o) for o in om_list] # 2D figure coords of each om node_colours = [] #dict.fromkeys(om_list) node_outline = [] #dict.fromkeys(om_list) node_labels = [] #dict.fromkeys(om_list) #name_to_ind = for om, xy in zip(om_list, pos): if node_data[om].get('label', None) == None: label = om elif isinstance(node_data.get('label'), (int, float)): label = str(round(node_data.get('label'), decimals)) else: label = node_data.get('label') if (node_data[om].get('colour') == None): fill_c = c else: fill_c = node_data[om].get('colour') x, y = (xy[0] * 0.01, xy[1] * 0.01) #y = xy[1] * 0.01 ax.scatter(xy[0], xy[1], marker='H', color=fill_c, s=100) ax.annotate(label, xy, fontsize=8, color='w', ha='center', va='center') #ax.set_xlim((-30, 4)) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) #plt.axis('off') ax.set_aspect('equal') return ax
def set_axes_properties(ax: plt.Axes, **kwargs) -> None: """ Ease the configuration of a :class:`matplotlib.axes.Axes` object. Parameters ---------- ax : matplotlib.axes.Axes The axes. Keyword arguments ----------------- fontsize : int Font size to use for the plot titles, and axes ticks and labels. Defaults to 12. title_center : str The center title. Defaults to an empty string. title_left : str The left title. Defaults to an empty string. title_right : str The right title. Defaults to an empty string. x_label : str The x-axis label. Defaults to an empty string. x_labelcolor : str Color of the x-axis label. Defaults to 'black'. x_lim : Sequence[int] Data limits for the x-axis. Defaults to `None`, i.e., the data limits will be left unchanged. invert_xaxis : bool `True` to make to invert the x-axis, `False` otherwise. Defaults to `False`. x_scale : str The x-axis scale. Defaults to 'linear'. x_ticks : sequence[float] Sequence of x-axis ticks location. Defaults to `None`. x_ticklabels : sequence[str] Sequence of x-axis ticks labels. Defaults to `None`. x_ticklabels_color : str Color for the x-axis ticks labels. Defaults to 'black'. x_ticklabels_rotation : float Rotation angle of the x-axis ticks labels. Defaults to 0. xaxis_minor_ticks_visible : bool `True` to show all ticks, either labelled or unlabelled, `False` to show only the labelled ticks. Defaults to `False`. xaxis_visible : bool `False` to make the x-axis invisible. Defaults to `True`. y_label : str The y-axis label. Defaults to an empty string. y_labelcolor : str Color of the y-axis label. Defaults to 'black'. y_lim : Sequence[int] Data limits for the y-axis. Defaults to `None`, i.e., the data limits will be left unchanged. invert_yaxis : bool `True` to make to invert the y-axis, `False` otherwise. Defaults to `False`. y_scale : str The y-axis scale. Defaults to 'linear'. y_ticks : sequence[float] Sequence of y-axis ticks location. Defaults to `None`. y_ticklabels : sequence[str] Sequence of y-axis ticks labels. Defaults to `None`. y_ticklabels_color : str Color for the y-axis ticks labels. Defaults to 'black'. y_ticklabels_rotation : float Rotation angle of the y-axis ticks labels. Defaults to 0. yaxis_minor_ticks_visible : bool `True` to show all ticks, either labelled or unlabelled, `False` to show only the labelled ticks. Defaults to :obj:`False`. yaxis_visible : bool :obj:`False` to make the y-axis invisible. Defaults to :obj:`True`. z_label : str The z-axis label. Defaults to an empty string. z_labelcolor : str Color of the z-axis label. Defaults to 'black'. z_lim : Sequence[int] Data limits for the z-axis. Defaults to :obj:`None`, i.e., the data limits will be left unchanged. invert_zaxis : bool :obj:`True` to make to invert the z-axis, :obj:`False` otherwise. Defaults to :obj:`False`. z_scale : str The z-axis scale. Defaults to 'linear'. z_ticks : sequence[float] Sequence of z-axis ticks location. Defaults to :obj:`None`. z_ticklabels : sequence[str] Sequence of z-axis ticks labels. Defaults to :obj:`None`. z_ticklabels_color : str Rotation angle of the z-axis ticks labels. Defaults to 0. z_ticklabels_rotation : float Color for the z-axis ticks labels. Defaults to 'black'. zaxis_minor_ticks_visible : bool :obj:`True` to show all ticks, either labelled or unlabelled, :obj:`False` to show only the labelled ticks. Defaults to :obj:`False`. zaxis_visible : bool :obj:`False` to make the z-axis invisible. Defaults to :obj:`True`. legend_on : bool :obj:`True` to show the legend, :obj:`False` otherwise. Defaults to :obj:`False`. legend_loc : str String specifying the location where the legend should be placed. Defaults to 'best'; please see :func:`matplotlib.pyplot.legend` for all the available options. legend_bbox_to_anchor : Sequence[float] 4-items tuple defining the box used to place the legend. This is used in conjuction with `legend_loc` to allow arbitrary placement of the legend. legend_framealpha : float Legend transparency. It should be between 0 and 1; defaults to 0.5. legend_ncol : int Number of columns into which the legend labels should be arranged. Defaults to 1. text : str Text to be added to the figure as anchored text. Defaults to :obj:`None`, meaning that no text box is shown. text_loc : str String specifying the location where the text box should be placed. Defaults to 'upper right'; please see :class:`matplotlib.offsetbox.AnchoredText` for all the available options. grid_on : bool :obj:`True` to show the plot grid, :obj:`False` otherwise. Defaults to :obj:`False`. grid_properties : dict Keyword arguments specifying various settings of the plot grid. """ fontsize = kwargs.get("fontsize", 12) # title title_center = kwargs.get("title_center", "") title_left = kwargs.get("title_left", "") title_right = kwargs.get("title_right", "") # x-axis x_label = kwargs.get("x_label", "") x_labelcolor = kwargs.get("x_labelcolor", "black") x_lim = kwargs.get("x_lim", None) invert_xaxis = kwargs.get("invert_xaxis", False) x_scale = kwargs.get("x_scale", "linear") x_ticks = kwargs.get("x_ticks", None) x_ticklabels = kwargs.get("x_ticklabels", None) x_ticklabels_color = kwargs.get("x_ticklabels_color", "black") x_ticklabels_rotation = kwargs.get("x_ticklabels_rotation", 0) x_tickformat = kwargs.get("x_tickformat", None) xaxis_minor_ticks_visible = kwargs.get("xaxis_minor_ticks_visible", False) xaxis_visible = kwargs.get("xaxis_visible", True) # y-axis y_label = kwargs.get("y_label", "") y_labelcolor = kwargs.get("y_labelcolor", "black") y_lim = kwargs.get("y_lim", None) invert_yaxis = kwargs.get("invert_yaxis", False) y_scale = kwargs.get("y_scale", "linear") y_ticks = kwargs.get("y_ticks", None) y_ticklabels = kwargs.get("y_ticklabels", None) y_ticklabels_color = kwargs.get("y_ticklabels_color", "black") y_ticklabels_rotation = kwargs.get("y_ticklabels_rotation", 0) y_tickformat = kwargs.get("y_tickformat", None) yaxis_minor_ticks_visible = kwargs.get("yaxis_minor_ticks_visible", False) yaxis_visible = kwargs.get("yaxis_visible", True) # legend legend_on = kwargs.get("legend_on", False) legend_loc = kwargs.get("legend_loc", "best") legend_bbox_to_anchor = kwargs.get("legend_bbox_to_anchor", None) legend_framealpha = kwargs.get("legend_framealpha", 0.5) legend_ncol = kwargs.get("legend_ncol", 1) legend_fontsize = kwargs.get("legend_fontsize", fontsize) # textbox text = kwargs.get("text", None) text_loc = kwargs.get("text_loc", "") # grid grid_on = kwargs.get("grid_on", False) grid_properties = kwargs.get("grid_properties", None) rcParams["font.size"] = fontsize # rcParams['text.usetex'] = True # plot titles if ax.get_title(loc="center") == "": ax.set_title(title_center, loc="center", fontsize=rcParams["font.size"] - 1) if ax.get_title(loc="left") == "": ax.set_title(title_left, loc="left", fontsize=rcParams["font.size"] - 1) if ax.get_title(loc="right") == "": ax.set_title(title_right, loc="right", fontsize=rcParams["font.size"] - 1) # axes labels if ax.get_xlabel() == "": ax.set(xlabel=x_label) if ax.get_ylabel() == "": ax.set(ylabel=y_label) # axes labelcolors if ax.get_xlabel() != "" and x_labelcolor != "": ax.xaxis.label.set_color(x_labelcolor) if ax.get_ylabel() != "" and y_labelcolor != "": ax.yaxis.label.set_color(y_labelcolor) # axes limits if x_lim is not None: ax.set_xlim(x_lim) if y_lim is not None: ax.set_ylim(y_lim) # invert the axes if invert_xaxis: ax.invert_xaxis() if invert_yaxis: ax.invert_yaxis() # axes scale if x_scale is not None: ax.set_xscale(x_scale) if y_scale is not None: ax.set_yscale(y_scale) # axes ticks if x_ticks is not None: ax.get_xaxis().set_ticks(x_ticks) if y_ticks is not None: ax.get_yaxis().set_ticks(y_ticks) # axes tick labels if x_ticklabels is not None: ax.get_xaxis().set_ticklabels(x_ticklabels) if y_ticklabels is not None: ax.get_yaxis().set_ticklabels(y_ticklabels) # axes tick labels color if x_ticklabels_color != "": ax.tick_params(axis="x", colors=x_ticklabels_color) if y_ticklabels_color != "": ax.tick_params(axis="y", colors=y_ticklabels_color) # axes tick format if x_tickformat is not None: ax.xaxis.set_major_formatter(FormatStrFormatter(x_tickformat)) if y_tickformat is not None: ax.yaxis.set_major_formatter(FormatStrFormatter(y_tickformat)) # axes tick labels rotation plt.xticks(rotation=x_ticklabels_rotation) plt.yticks(rotation=y_ticklabels_rotation) # unlabelled axes ticks if not xaxis_minor_ticks_visible: ax.get_xaxis().set_tick_params(which="minor", size=0) ax.get_xaxis().set_tick_params(which="minor", width=0) if not yaxis_minor_ticks_visible: ax.get_yaxis().set_tick_params(which="minor", size=0) ax.get_yaxis().set_tick_params(which="minor", width=0) # axes visibility if not xaxis_visible: ax.get_xaxis().set_visible(False) if not yaxis_visible: ax.get_yaxis().set_visible(False) # legend if legend_on: if legend_bbox_to_anchor is None: ax.legend( loc=legend_loc, framealpha=legend_framealpha, ncol=legend_ncol, fontsize=legend_fontsize, ) else: ax.legend( loc=legend_loc, framealpha=legend_framealpha, ncol=legend_ncol, fontsize=legend_fontsize, bbox_to_anchor=legend_bbox_to_anchor, ) # text box if text is not None: ax.add_artist(AnchoredText(text, loc=text_locations[text_loc])) # plot grid if grid_on: gps = grid_properties if grid_properties is not None else {} ax.grid(True, **gps)