Skip to content

Instantly share code, notes, and snippets.

@LinuxIsCool
Last active April 5, 2023 02:42
Show Gist options
  • Select an option

  • Save LinuxIsCool/f16502108765993ea820819fa143067f to your computer and use it in GitHub Desktop.

Select an option

Save LinuxIsCool/f16502108765993ea820819fa143067f to your computer and use it in GitHub Desktop.
Overriding Default Value Formatting in Panel Param
"""
This class automatically formats numbers to be pretty with commas, and also automatically applies steps to number params.
Is there a better way to do this?
Inspiration from here: https://discourse.holoviz.org/t/return-int-value-but-show-labels-on-the-screen-insead-of-int-for-param-integer/2141/2
See also here for formatting: https://docs.bokeh.org/en/latest/docs/reference/models/formatters.html#bokeh.models.NumeralTickFormatter
"""
import numbers
from bokeh.models.formatters import NumeralTickFormatter
from math import floor, log10
import param as pm
import panel as pn
pn.extension()
class FormattedParam(pm.Parameterized):
example_param = pm.Number(1e6)
def __init__(self, **params):
super(FormattedParam, self).__init__(**params)
self.autostep()
def widgets(self, large_number_format="‘0,0.0’"):
"""Return formatters for numeric parameters greater than or equal to absolute value of 100."""
number_params = [k for k,v in self.param.values().items() if isinstance(v, numbers.Number) and abs(v) >= 100]
number_format = {"format": NumeralTickFormatter(format=large_number_format)}
widgets={a: number_format for a in number_params}
return widgets
def autostep_value(self, x):
"""Generate a step that is 1% of the default value, rounded to the most significant digit."""
x = abs(x/100)
return round(x, -int(floor(log10(abs(x)))))
def autostep(self):
"""Generate step value for all numeric parameters that do not yet have one defined."""
for k,v in self.param.values().items():
if hasattr(self.param[k], 'step') and (self.param[k].step is None):
# No bounds or only lower bound. use default value for autostep
if (self.param[k].bounds is None) or self.param[k].bounds[1] is None:
self.param[k].step = self.autostep_value(v)
# Upper bound exists. Use upper bound for autostep
elif self.param[k].bounds[0] is None:
v = self.param[k].bounds[1]
self.param[k].step = self.autostep_value(v)
# Bounds exist. Use bounds range for autostep
else:
v = self.param[k].bounds[1] - self.param[k].bounds[0]
self.param[k].step = self.autostep_value(v)
def view(self, large_number_format="‘0,0.0’"):
return pn.Param(self, widgets=self.widgets(large_number_format=large_number_format))
a = FormattedParam()
a.view()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment