import numpy as np
import matplotlib as mpl
import matplotlib.font_manager as font_manager
from matplotlib.colors import LinearSegmentedColormap
import matplotlib.pyplot as plt
from .figure import Figure
from ..fun.palette import NumberLoop, ColorLoop, LineStyleLoop, MarkerStyleLoop
from .. import setreqs
CM = 1 / 2.54
FONT_SIZE = 6
LINE_SIZE = 0.5
FONT_FAMILY = "Arial"
[docs]
class Basic(Figure):
"""Basic figure style for A4 paper size.
This class is valid only if there is only one axes in Figure.
This class is used to change matplotlib's figure format in a convenient
way. The default setting is to create a quarter-width square graphic image
on an A4 size document.
Args:
reqs[0] (Figure): Figure class object.
param["size"] (list of float, optional): [width, height] of figure
image (cm). Defaults to [4.5, 4.5].
param["margin"] (list of float, optional): [left, bottom, right, top]
of figure margin (cm). Defaults to [0.9, 0.6, 0.1, 0.4].
param["limit"] (list of float, optional): [x_lower, x_upper,
y_lower, y_upper] limits of figure. If x_lower = None, skip
X limits.
param["tick"] (list of list of float, optional): Tick position
float lists for X and Y axes. :class:`numpy.ndarray` is available,
e.g., [np.arange(0, 1, 0.1), [0, 1, 2]].
param["tick_label"] (list of list of str, optional): Tick label for
[x-axis, y-axis].
param["format"] (list of str, optional): Strings for X and tick
formats, e.g. ["%.0f","%.1f"].
param["is_box"] (bool, optional): Draw box lined axis, if True.
param["line_widths"] (float or list of float, optional): Line width.
Defaults to 1.
param["line_styles"] (str or list of str, optional): Line style.
param["line_colors"] (list of RGB 0-255, optional): Line color. e.g.,
[[0, 0, 255]] is blue. Palette name is also available.
param["error_thicknesses"] (list of float, optional): Error bar line
width. Defaults to 1.
param["error_line_styles"] (list of str, optional): Error bar line
style.
param["error_cap_sizes"] (list of float, optional): Error bar
cap line width.
param["marker_styles"] (str or list of str, optional): Marker style.
param["marker_colors"] (list of list of RGB 0-255, optional): Marker
edge and face colors. e.g., [[[0,0,0]],[[100,100,100]]].
List of palette_name is also available.
param["marker_widths"] (float or list of float, optional): Marker
widths.
param["marker_sizes"] (float or list of float, optional): Marker sizes.
param["bar_widths"] (float or list of float): Width of each bar.
param["label"] (list of str, optional): [X label string, Y label
string] for axes label texts.
param["legend"] (list, optional): [list of label strings, handle
indexes of artists to create a legend, keyword arguments for
matplotlib legend]. If [None, None], then delete all legends. If
handle indexes are None, e.g. [["Label1", "Label2"], None] then
create legend for all artists. If only handle indexes are
specified, e.g. [None, [0,1]], then create legend for selected
artists with existing labels. Keyword arguments should be
dictionary, e.g. {"loc": "center"}.
param["log_scale"](list of bool): Change axes to the log scale. e.g.,
[False, True] means that the only y-axis is the log scale.
param["title"] (str, optional): String for the figure title.
param["clim"] (list of float, optional): [vmin, vmax] of colormap
limit.
param["cmap"] (str, optional): Colormap name. See also
`matplotlib.colormaps <https://matplotlib.org/stable/tutorials/colors/colormaps.html>`_.
Returns:
Figure: Styled Figure object
"""
[docs]
def save_data(self, data, path):
"""
:func:`matplotlib.pyplot.clf` is removed to avoid deleting the final
:class:`matplotlib.figure.Figure` object.
"""
super(Figure, self).save_data(data, path)
[docs]
def set_info(self, param={}):
"""Copy info from reqs[0] and add params.
"""
self.info.copy_req(0)
self.info.delete_param("size")
self.info.set_split_depth(self.reqs[0].info.split_depth())
if "size" not in param:
param["size"] = [4.5, 4.5]
self.info.add_param(
"size", param["size"], "list of cm",
"[width, height] of figure size")
if "margin" not in param:
param["margin"] = [0.9, 0.6, 0.1, 0.4]
self.info.add_param(
"margin", param["margin"], "list of cm",
"[left, bottom, right, top] of figure margin (cm)")
if "limit" in param:
self.info.add_param(
"limit", param["limit"], "list of float",
"[x_lower, x_upper, y_lower, y_upper] limits of figure")
if "tick" in param:
x_tick = param["tick"][0]
if type(x_tick).__module__ == np.__name__:
x_tick = x_tick.tolist()
y_tick = param["tick"][1]
if type(y_tick).__module__ == np.__name__:
y_tick = y_tick.tolist()
self.info.add_param(
"tick", [x_tick, y_tick], "list of float", "[x, y] of tick")
if "tick_label" in param:
self.info.add_param(
"tick_label", param["tick_label"], "list",
"[x, y] of tick label")
if "is_box" in param:
self.info.add_param(
"is_box", param["is_box"], "bool", "Whether to write box axis")
if "label" in param:
self.info.add_param(
"label", param["label"], "list of str",
"[x, y] of label string")
if "format" in param:
self.info.add_param(
"format", param["format"], "list of str",
"[x, y] of tick format string")
if "line_widths" not in param:
param["line_widths"] = 1
self.info.add_param(
"line_widths", param["line_widths"], "float or list of float",
"Line widths")
if "line_styles" in param:
self.info.add_param(
"line_styles", param["line_styles"], "list of str",
"Line styles")
if "line_colors" in param:
self.info.add_param(
"line_colors", param["line_colors"], "list of RGB 0-255",
"Line colors")
if "bar_widths" in param:
self.info.add_param(
"bar_widths", param["bar_widths"], "float or list of float",
"Width of each bar")
if "error_thicknesses" not in param:
param["error_thicknesses"] = 1
self.info.add_param(
"error_thicknesses", param["error_thicknesses"], "list of float",
"Error bar line widths")
if "error_line_styles" in param:
self.info.add_param(
"error_line_styles", param["error_line_styles"], "list of str",
"Error bar line styles")
if "error_colors" in param:
self.info.add_param(
"error_colors", param["error_colors"],
"list of RGB 0-255", "Error bar range line colors")
if "error_cap_sizes" in param:
self.info.add_param(
"error_cap_sizes", param["error_cap_sizes"],
"list of float", "Error bar cap sizes")
if "marker_styles" in param:
self.info.add_param(
"marker_styles", param["marker_styles"], "list of str",
"Marker styles")
if "marker_sizes" in param:
self.info.add_param(
"marker_sizes", param["marker_sizes"], "list of float",
"Marker size")
if "marker_colors" in param:
self.info.add_param(
"marker_colors", param["marker_colors"], "list of list of\
RGB 0-255", "Marker edge and face colors")
if "marker_widths" in param:
self.info.add_param(
"marker_widths", param["marker_widths"], "list of float",
"Marker line width")
if "legend" in param:
self.info.add_param(
"legend", param["legend"], "list",
"Legend [list of label string, indexes of artist handles,\
keyword arguments]")
if "title" in param:
self.info.add_param(
"title", param["title"], "str", "Title of figure")
if "log_scale" in param:
self.info.add_param(
"log_scale", param["log_scale"], "list of bool",
"[x, y] of log scale")
if "clim" in param:
self.info.add_param(
"clim", param["clim"], "list of int",
"[vmin, vmax] of colormap")
if "cmap" in param:
self.info.add_param(
"cmap", param["cmap"], "str", "Colormap name")
[docs]
@ staticmethod
def process(reqs, param):
"""Basic figure style for A4 paper size.
Args:
reqs[0](matplotlib.figure.Figure): Figure object.
param (dict): See class args description.
Returns:
matplotlib.figure.Figure: Styled Figure object
"""
fig = reqs[0]
fig = set_format(fig)
fig = set_size(fig, param["size"], param["margin"])
if "limit" in param:
x_lim = [param["limit"][0], param["limit"][1]]
y_lim = [param["limit"][2], param["limit"][3]]
fig = set_lim(fig, x_lim, y_lim)
if "tick" in param:
fig = set_tick(fig, param["tick"][0], param["tick"][1])
if "tick_label" in param:
fig = set_ticklabel(
fig, param["tick_label"][0], param["tick_label"][1])
if "label" in param:
fig = set_label(fig, param["label"][0], param["label"][1])
if "format" in param:
fig = set_tickformat(fig, param["format"][0], param["format"][1])
if "line_widths" in param:
fig = set_linewidth(fig, param["line_widths"])
if "line_styles" in param:
fig = set_linestyle(fig, param["line_styles"])
if "line_colors" in param:
fig = set_linecolor(fig, param["line_colors"])
if "marker_styles" in param:
fig = set_markerstyle(fig, param["marker_styles"])
if "marker_sizes" in param:
fig = set_markersize(fig, param["marker_sizes"])
if "marker_colors" in param:
fig = set_markercolor(fig, param["marker_colors"][0],
param["marker_colors"][1])
if "marker_widths" in param:
fig = set_markerwidth(fig, param["marker_widths"])
if "bar_widths" in param:
fig = set_barwidth(fig, param["bar_widths"])
if "error_thicknesses" in param:
fig = set_errorthickness(fig, param["error_thicknesses"])
if "error_line_styles" in param:
fig = set_errorlinestyle(fig, param["error_line_styles"])
if "error_colors" in param:
fig = set_errorcolor(fig, param["error_colors"])
if "error_cap_sizes" in param:
fig = set_errorcapsize(fig, param["error_cap_sizes"])
if "is_box" in param:
fig = is_boxed(fig, param["is_box"])
if "log_scale" in param:
fig = is_log_scale(fig, param["log_scale"])
if "title" in param:
fig = set_title(fig, param["title"])
if "legend" in param:
fig = set_legend(fig, *param["legend"])
if "clim" in param:
fig = set_clim(fig, param["clim"][0], param["clim"][1])
if "cmap" in param:
fig = set_cmap(fig, param["cmap"])
return fig
[docs]
class ParamTable(Basic):
"""Set figure style from the parameter table.
The parameter dictionary of :class:`Basic` is replaced as :class:`Table`
to set different style values for split figures.
Args:
reqs[0] (Figure): Figure class object.
reqs[1] (Table): Parameter table object. For required columns, please
see :class:`Basic`.
param (dict): Parameters for :class:`Basic` is available to set
common style for all figures.
Returns:
Figure: Styled Figure object
"""
[docs]
def set_reqs(self, reqs=None, param=None):
"""Drop elements that exist only in one required data.
"""
self.reqs = setreqs.allocate_data(reqs, param)
[docs]
@ staticmethod
def process(reqs, param):
"""Basic figure style for A4 paper size.
Args:
reqs[0](matplotlib.figure.Figure): Figure object.
param (dict): See class args description of :class:`Basic`.
Returns:
matplotlib.figure.Figure: Styled Figure object
"""
fig = Basic.process(reqs, param)
df = reqs[1].copy()
col_names = list(df.columns)
if "limit" in col_names:
limit = eval(df["limit"].values[0])
x_lim = [limit[0], limit[1]]
y_lim = [limit[2], limit[3]]
fig = set_lim(fig, x_lim, y_lim)
if "tick" in col_names:
tick = eval(df["tick"].values[0])
fig = set_tick(fig, tick[0], tick[1])
if "tick_label" in col_names:
tick_label = eval(df["tick_label"].values[0])
fig = set_ticklabel(
fig, tick_label[0], tick_label[1])
if "label" in col_names:
label = eval(df["label"].values[0])
fig = set_label(fig, label[0], label[1])
if "format" in col_names:
format = eval(df["format"].values[0])
fig = set_tickformat(fig, format[0], format[1])
if "line_widths" in col_names:
line_widths = eval(df["line_widths"].values[0])
fig = set_linewidth(fig, line_widths)
if "line_styles" in col_names:
line_styles = df["line_styles"].values[0]
fig = set_linestyle(fig, line_styles)
if "line_colors" in col_names:
line_colors = eval(df["line_colors"].values[0])
fig = set_linecolor(fig, line_colors)
if "marker_styles" in col_names:
marker_styles = df["marker_styles"].values[0]
fig = set_markerstyle(fig, marker_styles)
if "marker_sizes" in col_names:
marker_sizes = eval(df["marker_sizes"].values[0])
fig = set_markersize(fig, marker_sizes)
if "marker_colors" in col_names:
marker_colors = eval(df["marker_colors"].values[0])
fig = set_markercolor(fig, marker_colors[0], marker_colors[1])
if "marker_widths" in col_names:
marker_widths = eval(df["marker_widths"].values[0])
fig = set_markerwidth(fig, marker_widths)
if "bar_widths" in col_names:
bar_widths = eval(df["bar_widths"].values[0])
fig = set_barwidth(fig, bar_widths)
if "error_thicknesses" in col_names:
error_thicknesses = eval(df["error_thicknesses"].values[0])
fig = set_errorthickness(fig, error_thicknesses)
if "error_line_styles" in col_names:
error_line_styles = df["error_line_styles"].values[0]
fig = set_errorlinestyle(fig, error_line_styles)
if "error_colors" in col_names:
error_colors = eval(df["error_colors"].values[0])
fig = set_errorcolor(fig, error_colors)
if "error_cap_sizes" in col_names:
error_cap_sizes = eval(df["error_cap_sizes"].values[0])
fig = set_errorcapsize(fig, error_cap_sizes)
if "is_box" in col_names:
is_box = eval(df["is_box"].values[0])
fig = is_boxed(fig, is_box)
if "log_scale" in col_names:
log_scale = eval(df["log_scale"].values[0])
fig = is_log_scale(fig, log_scale)
if "title" in col_names:
title = df["title"].values[0]
fig = set_title(fig, title)
if "legend" in col_names:
legend = eval(df["legend"].values[0])
fig = set_legend(fig, *legend)
if "clim" in col_names:
clim = eval(df["clim"].values[0])
fig = set_clim(fig, clim[0], clim[1])
if "cmap" in col_names:
cmap = df["cmap"].values[0]
fig = set_cmap(fig, cmap)
return fig
[docs]
class ColorBar(Figure):
"""Create color bar figure from mappable figure object.
Args:
reqs[0] (Figure): Figure containing mappable object.
param["size"] (list of float, optional): [width, height] of figure
image (cm). Defaults to [4.5, 0.9].
param["margin"] (list, optional): [Left, bottom, right, top] of
figure margin (cm). Defaults to [0.2, 0.7, 0.2, 0.05].
param["is_vertical"] (bool, optional): Whether colorbar orientation is
vertical. Defaults to False.
param["label"] (str, optional): Colorbar label string.
param["tick"] (list of float, optional): List of colorbar tick values.
param["format"] (str, optional): Tick value format string. e.g. "%.0f".
Returns:
Figure: Styled colorbar Figure object
"""
[docs]
def set_info(self, param={}):
"""Copy info from reqs[0] and add params.
"""
self.info.copy_req(0)
self.info.set_split_depth(self.reqs[0].info.split_depth())
if "size" not in param:
param["size"] = [4.5, 0.9]
self.info.add_param(
"size", param["size"], "list of cm",
"[width, height] of figure size")
if "margin" not in param:
param["margin"] = [0.2, 0.7, 0.2, 0.05]
self.info.add_param(
"margin", param["margin"], "list of cm",
"[left, bottom, right, top] of figure margin (cm)")
if "is_vertical" not in param:
param["is_vertical"] = False
self.info.add_param(
"is_vertical", param["is_vertical"], "bool",
"Whether colorbar orientation is vertical")
if "label" in self.info.get_param_names():
param["label"] = self.info.get_param_value("label")
elif "label" not in param:
param["label"] = None
self.info.add_param(
"label", param["label"], "str", "Colorbar label string")
if "tick" not in param:
param["tick"] = None
self.info.add_param(
"tick", param["tick"], "list", "List of colorbar tick values")
if "format" not in param:
param["format"] = None
self.info.add_param(
"format", param["format"], "str", "Tick format string")
[docs]
@ staticmethod
def process(reqs, param):
"""Create color bar figure from mappable figure object.
Args:
reqs[0](matplotlib.figure.Figure): Figure containing mappable.
param (dict): See the class args description.
Returns:
matplotlib.figure.Figure: Styled Figure object
"""
fig = reqs[0]
ax = fig.axes[0]
if ("is_vertical", True) in param.items():
orientation = "vertical"
else:
orientation = "horizontal"
if len(ax.images) > 0:
cb = fig.colorbar(ax.images[0], ax=ax, orientation=orientation)
else:
cb = fig.colorbar(
ax.collections[0], ax=ax, orientation=orientation)
ax.set_visible(False)
fig = set_format(fig, axes_no=1)
size = param["size"]
mrgn = param["margin"]
fig = set_size(fig, size, mrgn, axes_no=1)
cax = fig.axes[1]
width = size[0] - mrgn[0] - mrgn[2]
height = size[1] - mrgn[1] - mrgn[3]
cax.set_box_aspect(height / width)
cb.outline.set_linewidth(0.5)
if param["is_vertical"]:
fig = set_label(fig, None, param["label"], axes_no=1)
fig = set_tick(fig, None, param["tick"], axes_no=1)
fig = set_tickformat(fig, None, param["format"], axes_no=1)
ytick_off = mpl.transforms.ScaledTranslation(
-0.08, 0, fig.dpi_scale_trans)
for label in cax.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + ytick_off)
ylabel_off = mpl.transforms.ScaledTranslation(
-0.05, 0, fig.dpi_scale_trans)
cax.yaxis.label.set_transform(
cax.yaxis.label.get_transform() + ylabel_off)
else:
fig = set_label(fig, param["label"], None, axes_no=1)
fig = set_tick(fig, param["tick"], None, axes_no=1)
fig = set_tickformat(fig, param["format"], None, axes_no=1)
return fig
font_dict = {"family": FONT_FAMILY, "size": FONT_SIZE}
font = font_manager.FontProperties(
family=FONT_FAMILY, style="normal", size=FONT_SIZE)
[docs]
def set_size(fig, size, margin, axes_no=0):
"""Set figure size based on centimeter scale.
"""
fig.set_size_inches(size[0] * CM, size[1] * CM)
left = margin[0] / size[0]
bottom = margin[1] / size[1]
width = (size[0] - margin[0] - margin[2]) / size[0]
height = (size[1] - margin[1] - margin[3]) / size[1]
fig.axes[axes_no].set_position([left, bottom, width, height])
return fig
[docs]
def set_legend(fig, labels=None, handle_indexes=None, kwargs={}, axes_no=0):
"""Set figure legend.
Args:
fig (matplotlib.figure.Figure): Figure object.
labels (list of str): List of label strings for each artists such as
Line2D.
handle_indexes (list of int): Index number list of artists to be
included to the legend.
kwargs (dict): Keyword arguments for :func:`matplotlib.pyplot.legend`.
Returns:
matplotlib.figure.Figure: Figure object with legend
.. caution::
All artists to be candidates for the legend should have labels during
their creation.
"""
ax = fig.axes[axes_no]
handles, labels_ = ax.get_legend_handles_labels()
if "frameon" not in kwargs:
kwargs["frameon"] = False
if (labels is None) and (handle_indexes is None):
# delete all legends
ax.legend_ = None
return fig
elif (labels is not None) and (handle_indexes is None):
# create a new legend for all artists
if type(labels) is str:
labels = [labels]
ax.legend(labels=labels, prop=font, **kwargs)
return fig
elif (labels is not None) and (handle_indexes is not None):
# add a legend for selected artists
if len(labels) != len(handle_indexes):
raise Exception("Label and handle_nos should be the same counts.")
leg = ax.legend(labels=labels,
handles=[handles[i] for i in handle_indexes],
prop=font, **kwargs)
ax.add_artist(leg)
return fig
elif (labels is None) and (handle_indexes is not None):
# add a legend for selected artists with the same labels
leg = ax.legend(labels=[labels_[i] for i in handle_indexes],
handles=[handles[i] for i in handle_indexes],
prop=font, **kwargs)
ax.add_artist(leg)
return fig
[docs]
def set_title(fig, title, axes_no=0):
"""Set title.
"""
fig.axes[axes_no].set_title(title, fontdict=font_dict)
return fig
[docs]
def set_lim(fig, x_lim=None, y_lim=None, axes_no=0):
"""Set limit without changing tick and format.
"""
ax = fig.axes[axes_no]
if x_lim is not None:
ax.set_xlim(x_lim)
ticks_loc = ax.get_xticks().tolist()
ax.xaxis.set_major_locator(mpl.ticker.FixedLocator(ticks_loc))
if y_lim is not None:
ax.set_ylim(y_lim)
ticks_loc = ax.get_yticks().tolist()
ax.yaxis.set_major_locator(mpl.ticker.FixedLocator(ticks_loc))
return fig
[docs]
def set_tick(fig, x_tick=None, y_tick=None, axes_no=0):
"""Set ticks without changing limits.
"""
ax = fig.axes[axes_no]
x_lim = ax.get_xlim()
y_lim = ax.get_ylim()
if x_tick is not None:
ax.set_xticks(x_tick)
if y_tick is not None:
ax.set_yticks(y_tick)
fig = set_lim(fig, x_lim=x_lim, y_lim=y_lim, axes_no=axes_no)
return fig
[docs]
def set_label(fig, x_label, y_label, axes_no=0):
"""Set axis labels without changing its font.
"""
ax = fig.axes[axes_no]
ax.xaxis.set_label_text(x_label, font_dict)
ax.yaxis.set_label_text(y_label, font_dict)
return fig
[docs]
def set_ticklabel(fig, x_label, y_label, axes_no=0):
"""Set tick labels without changing its font.
"""
ax = fig.axes[axes_no]
if x_label is not None:
ax.set_xticklabels(x_label, fontdict=font_dict)
if y_label is not None:
ax.set_yticklabels(y_label, fontdict=font_dict)
return fig
[docs]
def set_linewidth(fig, line_widths, axes_no=0):
"""Set widths of lines.
Args:
fig (matplotlib.figure.Figure): Figure containing line artists.
line_widths (float or list of float): Resizes line widths. All lines
are resized according to the same value if set as a float.
Returns:
matplotlib.figure.Figure: Restyled Figure object
"""
# for line style
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, width in zip(lines, NumberLoop(line_widths)):
line.set_linewidth(width)
# for error bar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, width in zip(ctns, NumberLoop(line_widths)):
ctn.lines[0].set_linewidth(width)
return fig
[docs]
def set_linestyle(fig, line_styles, axes_no=0):
"""Change line styles in bulk or individually.
"""
# for line style
gen = LineStyleLoop(line_styles)
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, style in zip(lines, gen):
line.set_linestyle(style)
# for error bar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, style in zip(ctns, gen):
ctn.lines[0].set_linestyle(style)
return fig
[docs]
def set_linecolor(fig, line_colors, axes_no=0):
"""Set colors of all line artists.
Args:
fig (matplotlib.figure.Figure): Figure object.
line_colors (list of list): [RGB values,...]. RGB values should be
[R(0-255), G(0-255), B(0-255)].
Returns:
matplotlib.figure.Figure: Restyled Figure object
"""
gen = ColorLoop(line_colors)
# for line style
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, color in zip(lines, gen):
edge_color = line.get_markeredgecolor()
face_color = line.get_markerfacecolor()
line.set_color(color)
line.set_markeredgecolor(edge_color)
line.set_markerfacecolor(face_color)
# for error bar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, color in zip(ctns, gen):
edge_color = ctn.lines[0].get_markeredgecolor()
face_color = ctn.lines[0].get_markerfacecolor()
ctn.lines[0].set_color(color)
ctn.lines[0].set_markeredgecolor(edge_color)
ctn.lines[0].set_markerfacecolor(face_color)
return fig
[docs]
def set_markerstyle(fig, marker_styles, axes_no=0):
"""Change line styles in bulk or individually.
.. caution::
Scatter plots can not change marker style.
"""
gen = MarkerStyleLoop(marker_styles)
# for line style
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, style in zip(lines, gen):
line.set_marker(style)
# for error bar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, style in zip(ctns, gen):
ctn.lines[0].set_marker(style)
return fig
[docs]
def set_markersize(fig, marker_sizes, axes_no=0):
"""Set marker sizes of all artists.
"""
gen = NumberLoop(marker_sizes)
# for line markers
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, size in zip(lines, gen):
line.set_markersize(size)
# for scatter markers
paths = [path for path in fig.axes[axes_no].get_children()
if isinstance(path, mpl.collections.PathCollection)
and (path.get_label() != "_nolegend_")]
for path, size in zip(paths, gen):
path.set_sizes([size])
# for error bar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, size in zip(ctns, gen):
ctn.lines[0].set_markersize(size)
return fig
[docs]
def set_markerwidth(fig, marker_widths, axes_no=0):
"""Set marker widths of all artists.
"""
# for line style
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, width in zip(lines, NumberLoop(marker_widths)):
line.set_markeredgewidth(width)
# for scatter markers
paths = [path for path in fig.axes[axes_no].get_children()
if isinstance(path, mpl.collections.PathCollection)
and (path.get_label() != "_nolegend_")]
for path, width in zip(paths, NumberLoop(marker_widths)):
path.set_linewidth(width)
# for bar plot
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, width in zip(ctns, NumberLoop(marker_widths)):
for rect in ctn.patches:
rect.set_linewidth(width)
# for errorbar line markers
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, width in zip(ctns, NumberLoop(marker_widths)):
ctn.lines[0].set_markeredgewidth(width)
return fig
[docs]
def set_barwidth(fig, bar_widths, axes_no=0):
"""Set bar widths.
"""
# for bar plot
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, width in zip(ctns, NumberLoop(bar_widths)):
for rect in ctn.patches:
xc = rect.get_x() + rect.get_width() / 2
rect.set_width(width)
rect.set_x(xc - width / 2)
return fig
[docs]
def set_markercolor(fig, edge_colors, face_colors, axes_no=0):
"""Set edge and face colors of all artists.
"""
# for line markers
gen_edge = ColorLoop(edge_colors)
gen_face = ColorLoop(face_colors)
lines = [line for line in fig.axes[axes_no].get_children()
if isinstance(line, mpl.lines.Line2D)
and (line.get_label() != "_nolegend_")]
for line, color in zip(lines, gen_edge):
line.set_markeredgecolor(color)
for line, color in zip(lines, gen_face):
line.set_markerfacecolor(color)
# for scatter markers
paths = [path for path in fig.axes[axes_no].get_children()
if isinstance(path, mpl.collections.PathCollection)
and (path.get_label() != "_nolegend_")]
for path, color in zip(paths, gen_edge):
path.set_edgecolor(color)
for path, color in zip(paths, gen_face):
if color is None:
pass # PathCollection.set_facecolor does not work properly
else:
path.set_facecolor(color)
# for bar plot
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, color in zip(ctns, gen_edge):
for rect in ctn.patches:
rect.set_edgecolor(color)
for ctn, color in zip(ctns, gen_face):
for rect in ctn.patches:
if color is None:
pass # Rectangle.set_facecolor does not work properly
else:
rect.set_facecolor(color)
# for errorbar line
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, color in zip(ctns, gen_edge):
ctn.lines[0].set_markeredgecolor(color)
for ctn, color in zip(ctns, gen_face):
ctn.lines[0].set_markerfacecolor(color)
return fig
[docs]
def set_errorthickness(fig, error_thicknesses, axes_no=0):
"""Set widths of lines.
Args:
fig (matplotlib.figure.Figure): Figure containing line artists.
line_widths (float or list of float): Resizes line widths. All lines
are resized according to the same value if set as a float.
Returns:
matplotlib.figure.Figure: Restyled Figure object
"""
# for line with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, thick in zip(ctns, NumberLoop(error_thicknesses)):
for line in ctn.lines[1]:
line.set_markeredgewidth(thick)
for lcoll in ctn.lines[2]:
lcoll.set_linewidth(thick)
# for bar with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, thick in zip(ctns, NumberLoop(error_thicknesses)):
if ctn.errorbar is not None:
for line in ctn.errorbar.lines[1]:
line.set_markeredgewidth(thick)
for lcoll in ctn.errorbar.lines[2]:
lcoll.set_linewidth(thick)
return fig
[docs]
def set_errorlinestyle(fig, error_line_styles, axes_no=0):
"""Change error line styles in bulk or individually.
"""
# for line with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, style in zip(ctns, LineStyleLoop(error_line_styles)):
for lcoll in ctn.lines[2]:
lcoll.set_linestyle(style)
# for bar with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, style in zip(ctns, LineStyleLoop(error_line_styles)):
if ctn.errorbar is not None:
for lcoll in ctn.errorbar.lines[2]:
lcoll.set_linestyle(style)
return fig
[docs]
def set_errorcolor(fig, error_colors, axes_no=0):
"""Set colors of all line artists.
Args:
fig (matplotlib.figure.Figure): Figure object.
line_colors (list of list): [RGB values,...]. RGB values should be
[R(0-255), G(0-255), B(0-255)].
Returns:
matplotlib.figure.Figure: Restyled Figure object
"""
# for line with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, color in zip(ctns, ColorLoop(error_colors)):
for line in ctn.lines[1]:
line.set_markeredgecolor(color)
for lcoll in ctn.lines[2]:
lcoll.set_color(color)
# for bar with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, color in zip(ctns, ColorLoop(error_colors)):
if ctn.errorbar is not None:
for line in ctn.errorbar.lines[1]:
line.set_markeredgecolor(color)
for lcoll in ctn.errorbar.lines[2]:
lcoll.set_color(color)
return fig
[docs]
def set_errorcapsize(fig, error_cap_sizes, axes_no=0):
"""Set marker sizes of all artists.
"""
# for line with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.ErrorbarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, size in zip(ctns, NumberLoop(error_cap_sizes)):
for line in ctn.lines[1]:
line.set_markersize(size)
# for bar with error
ctns = [ctn for ctn in fig.axes[axes_no].containers
if isinstance(ctn, mpl.container.BarContainer)
and (ctn.get_label() != "_nolegend_")]
for ctn, size in zip(ctns, NumberLoop(error_cap_sizes)):
if ctn.errorbar is not None:
for line in ctn.errorbar.lines[1]:
line.set_markersize(size)
return fig
[docs]
def is_boxed(fig, bool=True, axes_no=0):
"""Show a rectangle-shaped box if True. Delete axes lines if False.
"""
ax = fig.axes[axes_no]
if bool is None:
return fig
elif bool:
ax.spines["right"].set_visible(True)
ax.spines["left"].set_visible(True)
ax.spines["top"].set_visible(True)
ax.spines["bottom"].set_visible(True)
ax.spines["right"].set_linewidth(LINE_SIZE)
ax.spines["left"].set_linewidth(LINE_SIZE)
ax.spines["top"].set_linewidth(LINE_SIZE)
ax.spines["bottom"].set_linewidth(LINE_SIZE)
else:
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)
ax.spines["top"].set_visible(False)
ax.spines["bottom"].set_visible(False)
return fig
[docs]
def is_log_scale(fig, bools, axes_no=0):
"""Change X and Y axes to the log scale.
Args:
fig (matplotlib.figure.Figure): Figure object.
bools (list or bool): Change axes to the log scale. e.g.,
[False, True] means that the only y-axis is the log scale.
Returns:
matplotlib.figure.Figure: Restyled Figure object
"""
ax = fig.axes[axes_no]
if bools[0]:
ax.set_xscale("log")
if bools[1]:
ax.set_yscale("log")
return fig
[docs]
def set_cmap(fig, cmap, axes_no=0):
"""Set cmaps of all artists.
"""
for artist in fig.axes[axes_no].get_children():
if type(artist) in [mpl.collections.PathCollection,
mpl.collections.PatchCollection,
mpl.image.AxesImage]:
if type(cmap) == str:
artist.set_cmap(cmap)
elif type(cmap) == list:
linear_segmented_colormap = rgb2cmap(cmap)
artist.set_cmap(linear_segmented_colormap)
return fig
[docs]
def rgb2cmap(rgb):
cdict = {'red': ((0.0, 0.0, 0.0), (1.0, rgb[0] / 255, 1.0)),
'green': ((0.0, 0.0, 0.0), (1.0, rgb[1] / 255, 1.0)),
'blue': ((0.0, 0.0, 0.0), (1.0, rgb[2] / 255, 1.0))
}
return LinearSegmentedColormap('custom_cmap', cdict, 256)
[docs]
def set_clim(fig, vmin, vmax, axes_no=0):
"""Set clim of all artists.
"""
for artist in fig.axes[axes_no].get_children():
if type(artist) in [mpl.collections.PathCollection,
mpl.collections.PatchCollection,
mpl.image.AxesImage]:
artist.set_clim(vmin, vmax)
return fig