Skip to content

Commit

Permalink
ENH Style: incorporate scatter-plot parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
christianbrodbeck committed Oct 17, 2021
1 parent 7ccf880 commit dd8d022
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 12 deletions.
17 changes: 9 additions & 8 deletions eelbrain/plot/_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,9 @@ class ColorList(EelFigure):
size
Size (width and height) of the color squares (the default is to
scale them to fit the font size).
h : 'auto' | float
Height of the figure in inches. If 'auto' (default), the height is
chosen to fit all labels.
shape : 'box' | 'line'
h
Height of the figure in inches (default is chosen to fit all labels).
shape
Shape for color samples (default 'box').
...
Also accepts :ref:`general-layout-parameters`.
Expand All @@ -254,16 +253,16 @@ def __init__(
cells: Sequence[CellArg] = None,
labels: Dict[CellArg, str] = None,
size: float = None,
h: Union[str, float] = 'auto',
shape: str = 'box',
h: float = None,
shape: Literal['box', 'line', 'marker'] = 'box',
**kwargs):
if cells is None:
cells = colors.keys()
elif isinstance(cells, Iterator):
cells = tuple(cells)
styles = find_cell_styles(cells, colors)

if h == 'auto':
if h is None:
if size is None:
size = matplotlib.rcParams['font.size'] * LEGEND_SIZE * POINT_SIZE
h = len(cells) * size
Expand Down Expand Up @@ -293,8 +292,10 @@ def __init__(
ax.add_patch(patch)
elif shape == 'line':
ax.plot([0, 1], [y, y], **styles[cell].line_args)
elif shape == 'marker':
ax.scatter(0.5, y, **styles[cell].scatter_args)
else:
raise ValueError(f"shape={shape!r}")
raise ValueError(f"{shape=}")
h = ax.text(1.1, y, labels.get(cell, cell), va='center', ha='left', zorder=2)
self.labels.append(h)

Expand Down
45 changes: 42 additions & 3 deletions eelbrain/plot/_styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,33 @@

@dataclass
class Style:
"""Control color/pattern by category.
"""Plotting style for :class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.patches.Patch` and :fun:`matplotlib.pyplot.scatter` plot types.
For options, see :class:`~matplotlib.lines.Line2D` and :class:`~matplotlib.patches.Patch`.
Parameters
----------
color
Line color or face-color for patches and markers.
marker
Maker shape (see :mod:`matplotlib.markers`). Use ``line_marker`` to
control whether markers are used for lines.
hatch
For patches (see :meth:`~matplotlib.patches.Patch.set_hatch`).
linestyle
For lines, see :meth:`matplotlib.lines.Line2D.set_linestyle`).
linewidth
For lines.
zorder
Z-order for plot elements, relative to object-specific default (use
positive values to bring this category to the front).
masked
Alternate style for masked elements (e.g., when plotting permutation
test results, lines that are not significant).
edgecolor
For patches and markers.
edgewidth
Line-width for the edges of patches and markers.
linemarker
Plot markers in line plots.
Examples
--------
Expand All @@ -41,16 +65,31 @@ class Style:
linewidth: float = None
zorder: float = 0 # z-order shift (relative to plot element default)
masked: Union[Any, Dict[str, Any]] = None # Any should be Style, but autodoc does not support foward reference under decorator yet https://github.com/agronholm/sphinx-autodoc-typehints/issues/76
edgecolor: Any = None
edgewidth: float = 0,
linemarker: Union[bool, str] = False

@cached_property
def line_args(self):
return {'color': self.color, 'linestyle': self.linestyle, 'linewidth': self.linewidth, 'marker': self.marker, 'markerfacecolor': self.color, 'zorder': 2 + self.zorder}
args = {'color': self.color, 'linestyle': self.linestyle, 'linewidth': self.linewidth, 'markerfacecolor': self.color, 'zorder': 2 + self.zorder}
if self.linemarker is True:
args['marker'] = self.marker
elif self.linemarker:
args['marker'] = self.linemarker
return args

def fill_args(self, alpha: float):
r, g, b, a = to_rgba(self.color)
a *= alpha
return {'color': (r, g, b, a), 'zorder': 1.5 + self.zorder}

@cached_property
def scatter_args(self):
args = {'color': self.color, 'edgecolor': self.edgecolor, 'linewidth': self.edgewidth, 'facecolor': self.color, 'zorder': 2 + self.zorder}
if self.marker:
args['marker'] = self.marker
return args

@cached_property
def patch_args(self):
return {'facecolor': self.color, 'hatch': self.hatch, 'zorder': 1 + self.zorder}
Expand Down
4 changes: 3 additions & 1 deletion eelbrain/plot/_uv.py
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,9 @@ def __init__(
label = cellname(cell)
idx = (cat == cell)
size_i = size[idx] if isinstance(size, np.ndarray) else size
legend_handles[label] = ax.scatter(x.x[idx], y.x[idx], size_i, color=styles[cell].color, marker=markers, alpha=alpha, label=label)
args = dict(styles[cell].scatter_args)
args.setdefault('marker', markers)
legend_handles[label] = ax.scatter(x.x[idx], y.x[idx], size_i, **args, alpha=alpha, label=label)

LegendMixin.__init__(self, legend, legend_handles, labels)
ColorBarMixin.__init__(self, data=color_obj, mappable=mappable)
Expand Down

0 comments on commit dd8d022

Please sign in to comment.