Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for cticks #6257

Merged
merged 7 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 11 additions & 23 deletions holoviews/plotting/bokeh/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
FixedTicker,
LogTicker,
MercatorTicker,
Ticker,
)
from bokeh.models.tools import Tool
from packaging.version import Version
Expand Down Expand Up @@ -76,6 +75,7 @@
get_axis_class,
get_scale,
get_tab_title,
get_ticker_axis_props,
glyph_order,
hold_policy,
match_ax_type,
Expand Down Expand Up @@ -1051,28 +1051,8 @@ def _axis_properties(self, axis, key, plot, dimension=None,
if rotation:
axis_props['major_label_orientation'] = np.radians(rotation)
ticker = self.xticks if axis == 'x' else self.yticks
if isinstance(ticker, np.ndarray):
ticker = list(ticker)
if isinstance(ticker, Ticker):
axis_props['ticker'] = ticker
elif isinstance(ticker, int):
axis_props['ticker'] = BasicTicker(desired_num_ticks=ticker)
elif isinstance(ticker, (tuple, list)):
if all(isinstance(t, tuple) for t in ticker):
ticks, labels = zip(*ticker)
# Ensure floats which are integers are serialized as ints
# because in JS the lookup fails otherwise
ticks = [int(t) if isinstance(t, float) and t.is_integer() else t
for t in ticks]
labels = [l if isinstance(l, str) else str(l)
for l in labels]
else:
ticks, labels = ticker, None
if ticks and util.isdatetime(ticks[0]):
ticks = [util.dt_to_int(tick, 'ms') for tick in ticks]
axis_props['ticker'] = FixedTicker(ticks=ticks)
if labels is not None:
axis_props['major_label_overrides'] = dict(zip(ticks, labels))
if not (self._subcoord_overlaid and axis == 'y'):
axis_props = get_ticker_axis_props(ticker)
elif self._subcoord_overlaid and axis == 'y':
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
ticks, labels = [], []
idx = 0
Expand Down Expand Up @@ -2470,6 +2450,11 @@ class ColorbarPlot(ElementPlot):
#FFFFFFFF or a length 3 or length 4 tuple specifying values in
the range 0-1 or a named HTML color.""")

cticks = param.Parameter(default=None, doc="""
hoxbro marked this conversation as resolved.
Show resolved Hide resolved
Ticks along colorbar-axis specified as an integer, explicit list of
tick locations, or bokeh Ticker object. If set to None default
bokeh ticking behavior is applied.""")

logz = param.Boolean(default=False, doc="""
Whether to apply log scaling to the z-axis.""")

Expand Down Expand Up @@ -2513,6 +2498,9 @@ def _draw_colorbar(self, plot, color_mapper, prefix=''):
if self.cformatter is not None:
self.colorbar_opts.update({'formatter': wrap_formatter(self.cformatter, 'c')})

if self.cticks is not None:
self.colorbar_opts.update(get_ticker_axis_props(self.cticks))

for tk in ['cticks', 'ticks']:
ticksize = self._fontsize(tk, common=False).get('fontsize')
if ticksize is not None:
Expand Down
33 changes: 33 additions & 0 deletions holoviews/plotting/bokeh/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@
)
from bokeh.models.formatters import PrintfTickFormatter, TickFormatter
from bokeh.models.scales import CategoricalScale, LinearScale, LogScale
from bokeh.models.tickers import (
BasicTicker,
FixedTicker,
Ticker,
)
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
from bokeh.models.widgets import DataTable, Div
from bokeh.plotting import figure
from bokeh.themes import built_in_themes
from bokeh.themes.theme import Theme
from packaging.version import Version

from ...core import util
from ...core.layout import Layout
from ...core.ndmapping import NdMapping
from ...core.overlay import NdOverlay, Overlay
Expand Down Expand Up @@ -1167,3 +1173,30 @@ def dtype_fix_hook(plot, element):
for k, v in data.items():
if hasattr(v, "dtype") and v.dtype.kind == "U":
data[k] = v.tolist()


def get_ticker_axis_props(ticker):
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
axis_props = {}
if isinstance(ticker, np.ndarray):
ticker = list(ticker)
if isinstance(ticker, Ticker):
axis_props['ticker'] = ticker
elif isinstance(ticker, int):
axis_props['ticker'] = BasicTicker(desired_num_ticks=ticker)
elif isinstance(ticker, (tuple, list)):
if all(isinstance(t, tuple) for t in ticker):
ticks, labels = zip(*ticker)
# Ensure floats which are integers are serialized as ints
# because in JS the lookup fails otherwise
ticks = [int(t) if isinstance(t, float) and t.is_integer() else t
for t in ticks]
labels = [l if isinstance(l, str) else str(l)
for l in labels]
else:
ticks, labels = ticker, None
if ticks and util.isdatetime(ticks[0]):
ticks = [util.dt_to_int(tick, 'ms') for tick in ticks]
axis_props['ticker'] = FixedTicker(ticks=ticks)
if labels is not None:
axis_props['major_label_overrides'] = dict(zip(ticks, labels))
return axis_props
22 changes: 22 additions & 0 deletions holoviews/tests/plotting/bokeh/test_elementplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
xaxis = plot.handles['xaxis']
yaxis = plot.handles['yaxis']
self.assertEqual(fig.title.text_font_size, '24pt')
self.assertEqual(xaxis.axis_label_text_font_size, '26px')

Check failure on line 46 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestElementPlot.test_element_font_scaling AssertionError: '13px' != '26px'

Check failure on line 46 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:macos-latest

TestElementPlot.test_element_font_scaling AssertionError: '13px' != '26px'

Check failure on line 46 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-numpy:ubuntu-latest

TestElementPlot.test_element_font_scaling AssertionError: '13px' != '26px'

Check failure on line 46 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:ubuntu-latest

TestElementPlot.test_element_font_scaling AssertionError: '13px' != '26px'

Check failure on line 46 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-312:macos-latest

TestElementPlot.test_element_font_scaling AssertionError: '13px' != '26px'
self.assertEqual(yaxis.axis_label_text_font_size, '26px')
self.assertEqual(xaxis.major_label_text_font_size, '22px')
self.assertEqual(yaxis.major_label_text_font_size, '22px')
Expand Down Expand Up @@ -345,13 +345,13 @@
plot = bokeh_renderer.get_plot(curve)
xaxis = plot.handles['xaxis']
self.assertEqual(xaxis.major_label_text_font_size, '6pt')
self.assertEqual(xaxis.group_text_font_size, '18pt')

Check failure on line 348 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize AssertionError: '11px' != '18pt'

Check failure on line 348 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:macos-latest

TestElementPlot.test_categorical_axis_fontsize AssertionError: '11px' != '18pt'

Check failure on line 348 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-numpy:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize AssertionError: '11px' != '18pt'

Check failure on line 348 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize AssertionError: '11px' != '18pt'

Check failure on line 348 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-312:macos-latest

TestElementPlot.test_categorical_axis_fontsize AssertionError: '11px' != '18pt'

def test_categorical_axis_fontsize_both(self):
curve = Curve([('A', 1), ('B', 2)]).opts(fontsize={'xticks': 18})
plot = bokeh_renderer.get_plot(curve)
xaxis = plot.handles['xaxis']
self.assertEqual(xaxis.major_label_text_font_size, '18pt')

Check failure on line 354 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / core:test-core:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize_both AssertionError: '11px' != '18pt'

Check failure on line 354 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:macos-latest

TestElementPlot.test_categorical_axis_fontsize_both AssertionError: '11px' != '18pt'

Check failure on line 354 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-numpy:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize_both AssertionError: '11px' != '18pt'

Check failure on line 354 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-39:ubuntu-latest

TestElementPlot.test_categorical_axis_fontsize_both AssertionError: '11px' != '18pt'

Check failure on line 354 in holoviews/tests/plotting/bokeh/test_elementplot.py

View workflow job for this annotation

GitHub Actions / unit:test-312:macos-latest

TestElementPlot.test_categorical_axis_fontsize_both AssertionError: '11px' != '18pt'
self.assertEqual(xaxis.group_text_font_size, '18pt')

def test_cftime_transform_gregorian_no_warn(self):
Expand Down Expand Up @@ -885,6 +885,28 @@
self.assertEqual(cmapper.factors, ['0', '1', '2', '3'])
self.assertEqual(cmapper.palette, ['blue', 'red', 'green', 'purple'])

def test_cticks_int(self):
img = Image(np.array([[0, 1], [2, 3]])).opts(cticks=3, colorbar=True)
plot = bokeh_renderer.get_plot(img)
colorbar = plot.handles["colorbar"]
ticker = colorbar.ticker
assert ticker.desired_num_ticks == 3

def test_cticks_list(self):
img = Image(np.array([[0, 1], [2, 3]])).opts(cticks=[1, 2], colorbar=True)
plot = bokeh_renderer.get_plot(img)
colorbar = plot.handles["colorbar"]
ticker = colorbar.ticker
assert ticker.ticks == [1, 2]

def test_cticks_labels(self):
img = Image(np.array([[0, 1], [2, 3]])).opts(cticks=[(1, "A"), (2, "B")], colorbar=True)
plot = bokeh_renderer.get_plot(img)
colorbar = plot.handles["colorbar"]
assert colorbar.major_label_overrides == {1: "A", 2: "B"}
ticker = colorbar.ticker
assert ticker.ticks == [1, 2]


class TestOverlayPlot(TestBokehPlot):

Expand Down
Loading