def iloc(cls, dataset, index): from geopandas import GeoSeries from shapely.geometry import MultiPoint rows, cols = index geom_dims = cls.geom_dims(dataset) geom_col = cls.geo_column(dataset.data) scalar = False columns = list(dataset.data.columns) if isinstance(cols, slice): cols = [d.name for d in dataset.dimensions()][cols] elif np.isscalar(cols): scalar = np.isscalar(rows) cols = [dataset.get_dimension(cols).name] else: cols = [dataset.get_dimension(d).name for d in index[1]] if not all(d in cols for d in geom_dims): raise DataError( "Cannot index a dimension which is part of the " "geometry column of a spatialpandas DataFrame.", cls) cols = list( unique_iterator([ columns.index(geom_col) if c in geom_dims else columns.index(c) for c in cols ])) geom_type = dataset.data[geom_col].geom_type.iloc[0] if geom_type != 'MultiPoint': if scalar: return dataset.data.iloc[rows[0], cols[0]] elif isscalar(rows): rows = [rows] return dataset.data.iloc[rows, cols] geoms = dataset.data[geom_col] count = 0 new_geoms, indexes = [], [] for i, geom in enumerate(geoms): length = len(geom) if np.isscalar(rows): if count <= rows < (count + length): new_geoms.append(geom[rows - count]) indexes.append(i) break elif isinstance(rows, slice): if rows.start is not None and rows.start > (count + length): continue elif rows.stop is not None and rows.stop < count: break start = None if rows.start is None else max( rows.start - count, 0) stop = None if rows.stop is None else min( rows.stop - count, length) if rows.step is not None: dataset.param.warning( ".iloc step slicing currently not supported for" "the multi-tabular data format.") indexes.append(i) new_geoms.append(geom[start:stop]) elif isinstance(rows, (list, set)): sub_rows = [(r - count) for r in rows if count <= r < (count + length)] if not sub_rows: continue indexes.append(i) new_geoms.append(MultiPoint([geom[r] for r in sub_rows])) count += length new = dataset.data.iloc[indexes].copy() new[geom_col] = GeoSeries(new_geoms) return new
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,)]) or (not dynamic and len(keys) == 1)): 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.param.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 link_axes(root_view, root_model): """ Pre-processing hook to allow linking axes across HoloViews bokeh plots. """ panes = root_view.select(HoloViews) if not panes: return from holoviews.core.options import Store from holoviews.core.util import unique_iterator, max_range from holoviews.plotting.bokeh.element import ElementPlot ref = root_model.ref['id'] range_map = defaultdict(list) for pane in panes: if ref not in pane._plots: continue plot = pane._plots[ref][0] if (not pane.linked_axes or plot.renderer.backend != 'bokeh' or not getattr(plot, 'shared_axes', False)): continue for p in plot.traverse(specs=[ElementPlot]): if p.current_frame is None: continue axiswise = Store.lookup_options('bokeh', p.current_frame, 'norm').kwargs.get('axiswise') if not p.shared_axes or axiswise: continue fig = p.state if fig.x_range.tags: range_map[fig.x_range.tags[0]].append((fig, p, fig.xaxis[0], fig.x_range)) if fig.y_range.tags: range_map[fig.y_range.tags[0]].append((fig, p, fig.yaxis[0], fig.y_range)) for (tag), axes in range_map.items(): fig, p, ax, axis = axes[0] if isinstance(axis, Range1d): start, end = max_range([ (ax[-1].start, ax[-1].end) for ax in axes if isinstance(ax[-1], Range1d) ]) axis.start = start axis.end = end for fig, p, pax, _ in axes[1:]: changed = [] if type(ax) is not type(pax): continue if tag in fig.x_range.tags and not axis is fig.x_range: if hasattr(axis, 'factors'): axis.factors = list(unique_iterator(axis.factors+fig.x_range.factors)) fig.x_range = axis p.handles['x_range'] = axis changed.append('x_range') if tag in fig.y_range.tags and not axis is fig.y_range: if hasattr(axis, 'factors'): axis.factors = list(unique_iterator(axis.factors+fig.y_range.factors)) fig.y_range = axis p.handles['y_range'] = axis changed.append('y_range') # Reinitialize callbacks linked to replaced axes subplots = getattr(p, 'subplots') if subplots: plots = subplots.values() else: plots = [p] for sp in plots: for callback in sp.callbacks: if not any(c in callback.models or c in callback.extra_models for c in changed): continue if 'x_range' in changed: sp.handles['x_range'] = p.handles['x_range'] if 'y_range' in changed: sp.handles['y_range'] = p.handles['y_range'] callback.reset() callback.initialize(plot_id=p.id)
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