Skip to content

Commit

Permalink
Add sublabel_index and sublabel_skip option for matplotlib backend (
Browse files Browse the repository at this point in the history
#6375)

Co-authored-by: Simon Høxbro Hansen <simon.hansen@me.com>
  • Loading branch information
LecrisUT and hoxbro authored Sep 25, 2024
1 parent 37c6417 commit 90f56c8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
27 changes: 21 additions & 6 deletions holoviews/plotting/mpl/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,18 @@ class MPLPlot(DimensionedPlot):
Allows labeling the subaxes in each plot with various formatters
including {Alpha}, {alpha}, {numeric} and {roman}.""")

sublabel_offset = param.Number(default=0, bounds=(0, None), doc="""
Allows offsetting the sublabel index.""")

sublabel_position = param.NumericTuple(default=(-0.35, 0.85), doc="""
Position relative to the plot for placing the optional subfigure label.""")

sublabel_size = param.Number(default=18, doc="""
Size of optional subfigure label.""")

sublabel_skip = param.List(default=None, item_type=int, doc="""
List of elements to skip when labeling subplots. Numbering starts at 1.""")

projection = param.Parameter(default=None, doc="""
The projection of the plot axis, default of None is equivalent to
2D plot, '3d' and 'polar' are also supported by matplotlib by default.
Expand Down Expand Up @@ -207,20 +213,29 @@ def _get_fontsize_defaults(self):


def _subplot_label(self, axis):
if self.sublabel_skip and self.layout_num in self.sublabel_skip:
return
layout_num = self.layout_num if self.subplot else 1
if self.sublabel_format and not self.adjoined and layout_num > 0:
if self.sublabel_skip:
if any(n < 1 for n in self.sublabel_skip):
raise ValueError('sublabel_skip values must be greater than 0')
sublabel_num = len(set(range(layout_num)) - set(self.sublabel_skip))
else:
sublabel_num = layout_num
sublabel_num += self.sublabel_offset
if self.sublabel_format and not self.adjoined and sublabel_num > 0:
from matplotlib.offsetbox import AnchoredText
labels = {}
if '{Alpha}' in self.sublabel_format:
labels['Alpha'] = int_to_alpha(layout_num-1)
labels['Alpha'] = int_to_alpha(sublabel_num-1)
elif '{alpha}' in self.sublabel_format:
labels['alpha'] = int_to_alpha(layout_num-1, upper=False)
labels['alpha'] = int_to_alpha(sublabel_num-1, upper=False)
elif '{numeric}' in self.sublabel_format:
labels['numeric'] = self.layout_num
labels['numeric'] = sublabel_num
elif '{Roman}' in self.sublabel_format:
labels['Roman'] = int_to_roman(layout_num)
labels['Roman'] = int_to_roman(sublabel_num)
elif '{roman}' in self.sublabel_format:
labels['roman'] = int_to_roman(layout_num).lower()
labels['roman'] = int_to_roman(sublabel_num).lower()
at = AnchoredText(self.sublabel_format.format(**labels), loc=3,
bbox_to_anchor=self.sublabel_position, frameon=False,
prop=dict(size=self.sublabel_size, weight='bold'),
Expand Down
22 changes: 22 additions & 0 deletions holoviews/tests/plotting/matplotlib/test_layoutplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,25 @@ def test_layout_shared_axes_disabled(self):
cp1, cp2 = plot.traverse(lambda x: x, [CurvePlot])
self.assertTrue(cp1.handles['axis'].get_ylim(), (1, 3))
self.assertTrue(cp2.handles['axis'].get_ylim(), (10, 30))

def test_layout_sublabel_offset(self):
from holoviews.plotting.mpl import CurvePlot
layout = Curve([]) + Curve([]) + Curve([]) + Curve([])
layout.opts(sublabel_offset=1)
plot = mpl_renderer.get_plot(layout)
cps = plot.traverse(lambda x: x, [CurvePlot])
assert cps[0].handles["sublabel"].get_text() == "B"
assert cps[1].handles["sublabel"].get_text() == "C"
assert cps[2].handles["sublabel"].get_text() == "D"
assert cps[3].handles["sublabel"].get_text() == "E"

def test_layout_sublabel_skip(self):
from holoviews.plotting.mpl import CurvePlot
layout = Curve([]) + Curve([]) + Curve([]) + Curve([])
layout.opts(sublabel_skip=[1, 3])
plot = mpl_renderer.get_plot(layout)
cps = plot.traverse(lambda x: x, [CurvePlot])
assert "sublabel" not in cps[0].handles
assert cps[1].handles["sublabel"].get_text() == "A"
assert "sublabel" not in cps[2].handles
assert cps[3].handles["sublabel"].get_text() == "B"

0 comments on commit 90f56c8

Please sign in to comment.