def test_holomap_slider_bad_default(self): dim = Dimension('X', default=42) hmap = HoloMap({i: Curve([1, 2, 3]) for i in range(1, 9)}, dim) with self.assertRaises(ValueError): bokeh_renderer.get_widget(hmap, 'widgets').get_widgets()
def from_records(cls, records, dataset=None, on=None, value=None, index=[], drop_missing=False, **kwargs): """ Load data from a collection of ``cartopy.io.shapereader.Record`` objects and optionally merge it with a dataset to assign values to each polygon and form a chloropleth. Supplying just records will return an NdOverlay of Shape Elements with a numeric index. If a dataset is supplied, a mapping between the attribute names in the records and the dimension names in the dataset must be supplied. The values assigned to each shape file can then be drawn from the dataset by supplying a ``value`` and keys the Shapes are indexed by specifying one or index dimensions. * records - An iterator of cartopy.io.shapereader.Record objects. * dataset - Any HoloViews Dataset type. * on - A mapping between the attribute names in the records and the dimensions in the dataset. * value - The value dimension in the dataset the values will be drawn from. * index - One or more dimensions in the dataset the Shapes will be indexed by. * drop_missing - Whether to drop shapes which are missing from the provided dataset. Returns an NdOverlay of Shapes. """ if dataset is not None and not on: raise ValueError('To merge dataset with shapes mapping ' 'must define attribute(s) to merge on.') if pd and isinstance(dataset, pd.DataFrame): dataset = Dataset(dataset) if not isinstance(on, (dict, list)): on = [on] if on and not isinstance(on, dict): on = {o: o for o in on} if not isinstance(index, list): index = [index] kdims = [] for ind in (index if index else ['Index']): if dataset and dataset.get_dimension(ind): dim = dataset.get_dimension(ind) else: dim = Dimension(ind) kdims.append(dim) ddims = [] if dataset: vdim = dataset.get_dimension(value) kwargs['vdims'] = [vdim] if not vdim: raise ValueError('Value dimension not found ' 'in dataset: {}'.format(vdim)) ddims = dataset.dimensions() data = [] notfound = False for i, rec in enumerate(records): if dataset: selection = { dim: rec.attributes.get(attr, None) for attr, dim in on.items() } row = dataset.select(**selection) if len(row): value = row[vdim.name][0] elif drop_missing: continue else: value = np.NaN kwargs['level'] = value if index: key = [] for kdim in kdims: if kdim in ddims and len(row): k = row[kdim.name][0] elif kdim.name in rec.attributes: k = rec.attributes[kdim.name] else: k = None notfound = True key.append(k) key = tuple(key) else: key = (i, ) data.append((key, Shape(rec.geometry, **kwargs))) if notfound: kdims = ['Index'] + kdims data = [((i, ) + subk, v) for i, (subk, v) in enumerate(data)] return NdOverlay(data, kdims=kdims)
def test_dimension_init(self): Dimension('Test dimension') Dimension('Test dimension', cyclic=True) Dimension('Test dimension', cyclic=True, type=int) Dimension('Test dimension', cyclic=True, type=int, unit='Twilight zones')
def widgets_from_dimensions(cls, object, widget_types={}, widgets_type='individual'): from holoviews.core import Dimension from holoviews.core.util import isnumeric, unicode, datetime_types, unique_iterator from holoviews.core.traversal import unique_dimkeys from holoviews.plotting.util import get_dynamic_mode from ..widgets import Widget, DiscreteSlider, Select, FloatSlider, DatetimeInput dynamic, bounded = get_dynamic_mode(object) dims, keys = unique_dimkeys(object) if dims == [Dimension('Frame')] and keys == [(0, )]: return [], {} nframes = 1 values = dict() if dynamic else dict(zip(dims, zip(*keys))) dim_values = OrderedDict() widgets = [] for i, dim in enumerate(dims): widget_type, widget, widget_kwargs = None, None, {} if widgets_type == 'individual': if i == 0 and i == (len(dims) - 1): margin = (20, 20, 20, 20) elif i == 0: margin = (20, 20, 5, 20) elif i == (len(dims) - 1): margin = (5, 20, 20, 20) else: margin = (0, 20, 5, 20) kwargs = {'margin': margin, 'width': 250} else: kwargs = {} vals = dim.values or values.get(dim, None) if vals is not None: vals = list(unique_iterator(vals)) dim_values[dim.name] = vals if widgets_type == 'scrubber': if not vals: raise ValueError( 'Scrubber widget may only be used if all dimensions define values.' ) nframes *= len(vals) elif dim.name in widget_types: widget = widget_types[dim.name] if isinstance(widget, Widget): widgets.append(widget) continue elif isinstance(widget, dict): widget_type = widget.get('type', widget_type) widget_kwargs = dict(widget) elif isinstance(widget, type) and issubclass(widget, Widget): widget_type = widget else: raise ValueError('Explicit widget definitions expected ' 'to be a widget instance or type, %s ' 'dimension widget declared as %s.' % (dim, widget)) widget_kwargs.update(kwargs) if vals: if all( isnumeric(v) or isinstance(v, datetime_types) for v in vals) and len(vals) > 1: vals = sorted(vals) labels = [unicode(dim.pprint_value(v)) for v in vals] options = OrderedDict(zip(labels, vals)) widget_type = widget_type or DiscreteSlider else: options = list(vals) widget_type = widget_type or Select default = vals[0] if dim.default is None else dim.default widget_kwargs = dict( dict(name=dim.label, options=options, value=default), **widget_kwargs) widget = widget_type(**widget_kwargs) elif dim.range != (None, None): if dim.range[0] == dim.range[1]: continue default = dim.range[0] if dim.default is None else dim.default step = 0.1 if dim.step is None else dim.step widget_type = widget_type or FloatSlider if isinstance(default, datetime_types): widget_type = DatetimeInput widget_kwargs = dict( dict(step=step, name=dim.label, start=dim.range[0], end=dim.range[1], value=default), **widget_kwargs) widget = widget_type(**widget_kwargs) if widget is not None: widgets.append(widget) if widgets_type == 'scrubber': widgets = [Player(length=nframes, width=550)] return widgets, dim_values
def from_records(cls, records, dataset=None, on=None, value=None, index=[], drop_missing=False, element=None, **kwargs): """ Load data from a collection of `cartopy.io.shapereader.Record` objects and optionally merge it with a dataset to assign values to each polygon and form a chloropleth. Supplying just records will return an NdOverlayof Shape Elements with a numeric index. If a dataset is supplied, a mapping between the attribute names in the records and the dimension names in the dataset must be supplied. The values assigned to each shape file can then be drawn from the dataset by supplying a ``value`` and keys the Shapes are indexed by specifying one or index dimensions. Parameters ---------- records: list of cartopy.io.shapereader.Record Iterator containing Records. dataset: holoviews.Dataset Any HoloViews Dataset type. on: str or list or dict A mapping between the attribute names in the records and the dimensions in the dataset. value: str The value dimension in the dataset the values will be drawn from. index: str or list One or more dimensions in the dataset the Shapes will be indexed by. drop_missing: boolean Whether to drop shapes which are missing from the provides dataset. Returns ------- shapes: Polygons or Path object A Polygons or Path object containing the geometries """ if dataset is not None and not on: raise ValueError('To merge dataset with shapes mapping ' 'must define attribute(s) to merge on.') if util.pd and isinstance(dataset, util.pd.DataFrame): dataset = Dataset(dataset) if not isinstance(on, (dict, list)): on = [on] if on and not isinstance(on, dict): on = {o: o for o in on} if not isinstance(index, list): index = [index] kdims = [] for ind in index: if dataset and dataset.get_dimension(ind): dim = dataset.get_dimension(ind) else: dim = Dimension(ind) kdims.append(dim) ddims = [] if dataset: if value: vdims = [dataset.get_dimension(value)] else: vdims = dataset.vdims ddims = dataset.dimensions() if None in vdims: raise ValueError('Value dimension %s not found ' 'in dataset dimensions %s' % (value, ddims)) else: vdims = [] data = [] for i, rec in enumerate(records): geom = {} if dataset: selection = { dim: rec.attributes.get(attr, None) for attr, dim in on.items() } row = dataset.select(**selection) if len(row): values = { k: v[0] for k, v in row.iloc[0].columns().items() } elif drop_missing: continue else: values = {vd.name: np.nan for vd in vdims} geom.update(values) if index: for kdim in kdims: if kdim in ddims and len(row): k = row[kdim.name][0] elif kdim.name in rec.attributes: k = rec.attributes[kdim.name] else: k = None geom[kdim.name] = k geom['geometry'] = rec.geometry data.append(geom) if element is not None: pass elif data and data[0]: if isinstance(data[0]['geometry'], poly_types): element = Polygons else: element = Path else: element = Polygons return element(data, vdims=kdims + vdims, **kwargs).opts(color=value)
def test_dimensionsed_redim_dimension(self): dimensioned = Dimensioned('Arbitrary Data', kdims=['x']) redimensioned = dimensioned.clone(kdims=['Test']) self.assertEqual(redimensioned, dimensioned.redim(x=Dimension('Test')))
def test_hex_tiles_hover_weighted(self): tiles = HexTiles([(0, 0, 0.1), (0.5, 0.5, 0.2), (-0.5, -0.5, 0.3)], vdims='z').options(aggregator=np.mean) plot = bokeh_renderer.get_plot(tiles) dims, opts = plot._hover_opts(tiles) self.assertEqual(dims, [Dimension('z')]) self.assertEqual(opts, {})
def test_dimension_values_list_duplicates2(self): dim = Dimension('test', values=self.duplicates2) self.assertEqual(dim.values, self.values2)
def test_dimension_values_array1(self): dim = Dimension('test', values=np.array(self.values1)) self.assertEqual(dim.values, self.values1)
def widgets_from_dimensions(cls, object, widget_types={}, widgets_type='individual'): from holoviews.core import Dimension from holoviews.core.util import isnumeric, unicode from holoviews.core.traversal import unique_dimkeys from .widgets import Widget, DiscreteSlider, Select, FloatSlider dims, keys = unique_dimkeys(object) if dims == [Dimension('Frame')] and keys == [(0, )]: return [], {} nframes = 1 values = dict(zip(dims, zip(*keys))) dim_values = OrderedDict() widgets = [] for dim in dims: widget_type, widget = None, None vals = dim.values or values.get(dim, None) dim_values[dim.name] = vals if widgets_type == 'scrubber': if not vals: raise ValueError( 'Scrubber widget may only be used if all dimensions define values.' ) nframes *= len(vals) elif dim.name in widget_types: widget = widget_types[dim.name] if isinstance(widget, Widget): widgets.append(widget) continue elif isinstance(widget, type) and issubclass(widget, Widget): widget_type = widget else: raise ValueError('Explicit widget definitions expected ' 'to be a widget instance or type, %s ' 'dimension widget declared as %s.' % (dim, widget)) if vals: if all(isnumeric(v) for v in vals): vals = sorted(vals) labels = [unicode(dim.pprint_value(v)) for v in vals] options = OrderedDict(zip(labels, vals)) widget_type = widget_type or DiscreteSlider else: options = list(vals) widget_type = widget_type or Select default = vals[0] if dim.default is None else dim.default widget = widget_type(name=dim.label, options=options, value=default) elif dim.range != (None, None): default = dim.range[0] if dim.default is None else dim.default step = 0.1 if dim.step is None else dim.step widget_type = widget_type or FloatSlider widget = widget_type(step=step, name=dim.label, start=dim.range[0], end=dim.range[1], value=default) if widget is not None: widgets.append(widget) if widgets_type == 'scrubber': widgets = [Player(length=nframes)] return widgets, dim_values
def test_dimension_values_list1(self): dim = Dimension('test', values=self.values1) self.assertEqual(dim.values, self.values1)
def test_dynamicmap_unsorted_numeric_values_slider_plot_initialization(self): dims = [Dimension('N', values=[10, 5, 0])] dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) widgets = bokeh_renderer.get_widget(dmap, 'widgets') widgets.get_widgets() self.assertEqual(widgets.plot.current_key, (0,))
def test_dynamicmap_default_value_slider_plot_initialization(self): dims = [Dimension('N', default=5, range=(0, 10))] dmap = DynamicMap(lambda N: Curve([1, N, 5]), kdims=dims) widgets = bokeh_renderer.get_widget(dmap, 'widgets') widgets.get_widgets() self.assertEqual(widgets.plot.current_key, (5,))
def test_holomap_dropdown_bad_default(self): dim = Dimension('X', default='Z') hmap = HoloMap({chr(65+i): Curve([1, 2, 3]) for i in range(10)}, dim) with self.assertRaises(ValueError): bokeh_renderer.get_widget(hmap, 'widgets').get_widgets()
def test_dimension_comparison_equal2(self): self.assertEqual(self.dimension1, Dimension('dim1', range=(0, 1)))
def test_dimension_values_array_duplicates2(self): dim = Dimension('test', values=np.array(self.duplicates2)) self.assertEqual(dim.values, self.values2)
def test_dimension_comparison_equal3(self): self.assertEqual( self.dimension7, Dimension('dim1', cyclic=True, range=(0, 1), unit='ms'))
def test_dimension_values_series_duplicates2(self): if pd is None: raise SkipTest("Pandas not available") df = pd.DataFrame({'col': self.duplicates2}) dim = Dimension('test', values=df['col']) self.assertEqual(dim.values, self.values2)
def test_hex_tiles_hover_count(self): tiles = HexTiles([(0, 0), (0.5, 0.5), (-0.5, -0.5), (-0.4, -0.4)]).options(tools=['hover']) plot = bokeh_renderer.get_plot(tiles) dims, opts = plot._hover_opts(tiles) self.assertEqual(dims, [Dimension('Count')]) self.assertEqual(opts, {})
def test_element_formatter_yaxis(self): def formatter(x): return '%s' % x curve = Curve(range(10), vdims=[Dimension('y', value_format=formatter)]) plot = bokeh_renderer.get_plot(curve).state self.assertIsInstance(plot.yaxis[0].formatter, FuncTickFormatter)
def test_layout_axis_not_linked_mismatching_unit(self): layout = (Curve([1, 2, 3], vdims=Dimension('length', unit='m')) + Curve([1, 2, 3], vdims=Dimension('length', unit='cm'))) plot = bokeh_renderer.get_plot(layout) p1, p2 = (sp.subplots['main'] for sp in plot.subplots.values()) self.assertIsNot(p1.handles['y_range'], p2.handles['y_range'])
def test_value_dimension_in_element(self): self.assertTrue(Dimension('C') in self.element)
class RGB(_Element, HvRGB): """ An RGB element is a Image containing channel data for the the red, green, blue and (optionally) the alpha channels. The values of each channel must be in the range 0.0 to 1.0. In input array may have a shape of NxMx4 or NxMx3. In the latter case, the defined alpha dimension parameter is appended to the list of value dimensions. """ group = param.String(default='RGB', constant=True) vdims = param.List(default=[ Dimension('R', range=(0, 1)), Dimension('G', range=(0, 1)), Dimension('B', range=(0, 1)), Dimension('A', range=(0, 1)) ], bounds=(3, 4), doc=""" The dimension description of the data held in the matrix. If an alpha channel is supplied, the defined alpha_dimension is automatically appended to this list.""") @classmethod def load_tiff(cls, filename, crs=None, apply_transform=False, nan_nodata=False, **kwargs): """ Returns an RGB or Image element loaded from a geotiff file. The data is loaded using xarray and rasterio. If a crs attribute is present on the loaded data it will attempt to decode it into a cartopy projection otherwise it will default to a non-geographic HoloViews element. Parameters ---------- filename: string Filename pointing to geotiff file to load crs: Cartopy CRS or EPSG string (optional) Overrides CRS inferred from the data apply_transform: boolean Whether to apply affine transform if defined on the data nan_nodata: boolean If data contains nodata values convert them to NaNs **kwargs: Keyword arguments passed to the HoloViews/GeoViews element Returns ------- element: Image/RGB/QuadMesh element """ return load_tiff(filename, crs, apply_transform, **kwargs) @classmethod def from_xarray(cls, da, crs=None, apply_transform=False, nan_nodata=False, **kwargs): """ Returns an RGB or Image element given an xarray DataArray loaded using xr.open_rasterio. If a crs attribute is present on the loaded data it will attempt to decode it into a cartopy projection otherwise it will default to a non-geographic HoloViews element. Parameters ---------- da: xarray.DataArray DataArray to convert to element crs: Cartopy CRS or EPSG string (optional) Overrides CRS inferred from the data apply_transform: boolean Whether to apply affine transform if defined on the data nan_nodata: boolean If data contains nodata values convert them to NaNs **kwargs: Keyword arguments passed to the HoloViews/GeoViews element Returns ------- element: Image/RGB/QuadMesh element """ return from_xarray(da, crs, apply_transform, **kwargs)
def test_dimension_not_in_element(self): self.assertFalse(Dimension('D') in self.element)
class Shape(_Element): """ Shape wraps any shapely geometry type. """ group = param.String(default='Shape') level = param.Number(default=None, doc=""" Optional level associated with the set of Contours.""") vdims = param.List(default=[Dimension('Level')], doc=""" Contours optionally accept a value dimension, corresponding to the supplied values.""", bounds=(1, 1)) def __init__(self, data, kdims=None, vdims=None, **params): if not isinstance(data, BaseGeometry): raise TypeError('%s data has to be a shapely geometry type.' % type(data).__name__) super(Shape, self).__init__(data, kdims=kdims, vdims=vdims, **params) @classmethod def from_shapefile(cls, shapefile, *args, **kwargs): """ Loads a shapefile from disk and optionally merges it with a dataset. See ``from_records`` for full signature. """ reader = Reader(shapefile) return cls.from_records(reader.records(), *args, **kwargs) @classmethod def from_records(cls, records, dataset=None, on=None, value=None, index=[], drop_missing=False, **kwargs): """ Load data from a collection of ``cartopy.io.shapereader.Record`` objects and optionally merge it with a dataset to assign values to each polygon and form a chloropleth. Supplying just records will return an NdOverlay of Shape Elements with a numeric index. If a dataset is supplied, a mapping between the attribute names in the records and the dimension names in the dataset must be supplied. The values assigned to each shape file can then be drawn from the dataset by supplying a ``value`` and keys the Shapes are indexed by specifying one or index dimensions. * records - An iterator of cartopy.io.shapereader.Record objects. * dataset - Any HoloViews Dataset type. * on - A mapping between the attribute names in the records and the dimensions in the dataset. * value - The value dimension in the dataset the values will be drawn from. * index - One or more dimensions in the dataset the Shapes will be indexed by. * drop_missing - Whether to drop shapes which are missing from the provided dataset. Returns an NdOverlay of Shapes. """ if dataset is not None and not on: raise ValueError('To merge dataset with shapes mapping ' 'must define attribute(s) to merge on.') if pd and isinstance(dataset, pd.DataFrame): dataset = Dataset(dataset) if not isinstance(on, (dict, list)): on = [on] if on and not isinstance(on, dict): on = {o: o for o in on} if not isinstance(index, list): index = [index] kdims = [] for ind in (index if index else ['Index']): if dataset and dataset.get_dimension(ind): dim = dataset.get_dimension(ind) else: dim = Dimension(ind) kdims.append(dim) ddims = [] if dataset: vdim = dataset.get_dimension(value) kwargs['vdims'] = [vdim] if not vdim: raise ValueError('Value dimension not found ' 'in dataset: {}'.format(vdim)) ddims = dataset.dimensions() data = [] notfound = False for i, rec in enumerate(records): if dataset: selection = { dim: rec.attributes.get(attr, None) for attr, dim in on.items() } row = dataset.select(**selection) if len(row): value = row[vdim.name][0] elif drop_missing: continue else: value = np.NaN kwargs['level'] = value if index: key = [] for kdim in kdims: if kdim in ddims and len(row): k = row[kdim.name][0] elif kdim.name in rec.attributes: k = rec.attributes[kdim.name] else: k = None notfound = True key.append(k) key = tuple(key) else: key = (i, ) data.append((key, Shape(rec.geometry, **kwargs))) if notfound: kdims = ['Index'] + kdims data = [((i, ) + subk, v) for i, (subk, v) in enumerate(data)] return NdOverlay(data, kdims=kdims) def dimension_values(self, dimension): """ Shapes do not support convert to array values. """ dim = self.get_dimension(dimension) if dim in self.vdims: return [self.level] else: return [] def range(self, dim, data_range=True): dim = self.get_dimension(dim) if dim.range != (None, None): return dim.range idx = self.get_dimension_index(dim) if idx == 2 and data_range: return self.level, self.level if idx in [0, 1] and data_range: l, b, r, t = self.data.bounds lower, upper = (b, t) if idx else (l, r) return dimension_range(lower, upper, dim) else: return super(Shape, self).range(dim, data_range) def geom(self): """ Returns Shape as a shapely geometry """ return self.data def __len__(self): return len(self.data)
def test_key_dimension_in_element(self): self.assertTrue(Dimension('A') in self.element)
def test_dimension_pprint(self): dim = Dimension('Test dimension', cyclic=True, type=float, unit='Twilight zones') self.assertEqual(dim.pprint_value_string(3.2345), 'Test dimension: 3.23 Twilight zones') self.assertEqual(dim.pprint_value_string(4.2344), 'Test dimension: 4.23 Twilight zones')
def setUp(self): super(DimensionsComparisonTestCase, self).setUp() self.dimension1 = Dimension('dim1', range=(0, 1)) self.dimension2 = Dimension('dim2', range=(0, 1)) self.dimension3 = Dimension('dim1', range=(0, 2)) self.dimension4 = Dimension('dim1') self.dimension5 = Dimension('dim1', cyclic=True) self.dimension6 = Dimension('dim1', cyclic=True, range=(0, 1)) self.dimension7 = Dimension('dim1', cyclic=True, range=(0, 1), unit='ms') self.dimension8 = Dimension('dim1', values=['a', 'b']) self.dimension9 = Dimension('dim1', type=int) self.dimension10 = Dimension('dim1', type=float) self.dimension11 = Dimension(('dim1', 'Test Dimension'), range=(0, 1)) self.dimension12 = Dimension('dim1', value_format=lambda x: x) self.dimension13 = Dimension('dim1', value_format=lambda x: x)
def widgets_from_dimensions(cls, object, widget_types=None, widgets_type='individual'): from holoviews.core import Dimension, DynamicMap from holoviews.core.options import SkipRendering from holoviews.core.util import isnumeric, unicode, datetime_types, unique_iterator from holoviews.core.traversal import unique_dimkeys from holoviews.plotting.plot import Plot, GenericCompositePlot from holoviews.plotting.util import get_dynamic_mode from ..widgets import Widget, DiscreteSlider, Select, FloatSlider, DatetimeInput, IntSlider if widget_types is None: widget_types = {} if isinstance(object, GenericCompositePlot): object = object.layout elif isinstance(object, Plot): object = object.hmap if isinstance(object, DynamicMap) and object.unbounded: dims = ', '.join('%r' % dim for dim in object.unbounded) msg = ('DynamicMap cannot be displayed without explicit indexing ' 'as {dims} dimension(s) are unbounded. ' '\nSet dimensions bounds with the DynamicMap redim.range ' 'or redim.values methods.') raise SkipRendering(msg.format(dims=dims)) dynamic, bounded = get_dynamic_mode(object) dims, keys = unique_dimkeys(object) if dims == [Dimension('Frame')] and keys == [(0,)]: return [], {} nframes = 1 values = dict() if dynamic else dict(zip(dims, zip(*keys))) dim_values = OrderedDict() widgets = [] dims = [d for d in dims if values.get(d) is not None or d.values or d.range != (None, None)] for i, dim in enumerate(dims): widget_type, widget, widget_kwargs = None, None, {} if widgets_type == 'individual': if i == 0 and i == (len(dims)-1): margin = (20, 20, 20, 20) elif i == 0: margin = (20, 20, 5, 20) elif i == (len(dims)-1): margin = (5, 20, 20, 20) else: margin = (0, 20, 5, 20) kwargs = {'margin': margin, 'width': 250} else: kwargs = {} vals = dim.values or values.get(dim, None) if vals is not None: vals = list(unique_iterator(vals)) dim_values[dim.name] = vals if widgets_type == 'scrubber': if not vals: raise ValueError('Scrubber widget may only be used if all dimensions define values.') nframes *= len(vals) elif dim.name in widget_types: widget = widget_types[dim.name] if isinstance(widget, Widget): widget.set_param(**kwargs) if not widget.name: widget.name = dim.label widgets.append(widget) continue elif isinstance(widget, dict): widget_type = widget.get('type', widget_type) widget_kwargs = dict(widget) elif isinstance(widget, type) and issubclass(widget, Widget): widget_type = widget else: raise ValueError('Explicit widget definitions expected ' 'to be a widget instance or type, %s ' 'dimension widget declared as %s.' % (dim, widget)) widget_kwargs.update(kwargs) if vals: if all(isnumeric(v) or isinstance(v, datetime_types) for v in vals) and len(vals) > 1: vals = sorted(vals) labels = [unicode(dim.pprint_value(v)) for v in vals] options = OrderedDict(zip(labels, vals)) widget_type = widget_type or DiscreteSlider else: options = list(vals) widget_type = widget_type or Select default = vals[0] if dim.default is None else dim.default widget_kwargs = dict(dict(name=dim.label, options=options, value=default), **widget_kwargs) widget = widget_type(**widget_kwargs) elif dim.range != (None, None): start, end = dim.range if start == end: continue default = start if dim.default is None else dim.default if widget_type is not None: pass elif all(isinstance(v, int) for v in (start, end, default)): widget_type = IntSlider step = 1 if dim.step is None else dim.step elif isinstance(default, datetime_types): widget_type = DatetimeInput else: widget_type = FloatSlider step = 0.1 if dim.step is None else dim.step widget_kwargs = dict(dict(step=step, name=dim.label, start=dim.range[0], end=dim.range[1], value=default), **widget_kwargs) widget = widget_type(**widget_kwargs) if widget is not None: widgets.append(widget) if widgets_type == 'scrubber': widgets = [Player(length=nframes, width=550)] return widgets, dim_values
def test_dynamicmap_int_range_slider_with_step(self): dimension = Dimension('X', range=(0, 10), step=2) hmap = DynamicMap(lambda x: Curve([1, 2, 3]), kdims=[dimension]) widgets = bokeh_renderer.get_widget(hmap, 'widgets') widgets, dimensions, init_dim_vals = widgets.get_widgets() self.assertEqual(widgets[0]['step'], 2)