def setUp(self): if not plotly_renderer: raise SkipTest("Plotly required to test plot instantiation") self.previous_backend = Store.current_backend Store.set_current_backend('plotly') self.comm_manager = plotly_renderer.comm_manager plotly_renderer.comm_manager = comms.CommManager
def setUp(self): if not plotly_renderer: raise SkipTest("Plotly required to test plot instantiation") self.previous_backend = Store.current_backend Store.set_current_backend('plotly') self.comm_manager = plotly_renderer.comm_manager plotly_renderer.comm_manager = comms.CommManager self._padding = {} for plot in concrete_descendents(ElementPlot).values(): self._padding[plot] = plot.padding plot.padding = 0
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.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.x_range)) if fig.y_range.tags: range_map[fig.y_range.tags[0]].append((fig, p, fig.y_range)) for tag, axes in range_map.items(): fig, p, axis = axes[0] for fig, p, _ in axes[1:]: if tag in fig.x_range.tags and not axis is fig.x_range: fig.x_range = axis p.handles['x_range'] = axis if tag in fig.y_range.tags and not axis is fig.y_range: fig.y_range = axis p.handles['y_range'] = axis
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.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], plot.root.ref['id'])].append( (fig, p, fig.x_range)) if fig.y_range.tags: range_map[(fig.y_range.tags[0], plot.root.ref['id'])].append( (fig, p, fig.y_range)) for (tag, _), axes in range_map.items(): fig, p, axis = axes[0] for fig, p, _ in axes[1:]: changed = [] if tag in fig.x_range.tags and not axis is fig.x_range: 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: 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 _update_layout(self): from holoviews.core import DynamicMap, Store from holoviews.plotting.util import initialize_dynamic loc = self.widget_location if not len(self.widget_box): widgets = [] elif loc in ('left', 'right'): widgets = Column(VSpacer(), self.widget_box, VSpacer()) elif loc in ('top', 'bottom'): widgets = Row(HSpacer(), self.widget_box, HSpacer()) elif loc in ('top_left', 'bottom_left'): widgets = Row(self.widget_box, HSpacer()) elif loc in ('top_right', 'bottom_right'): widgets = Row(HSpacer(), self.widget_box) elif loc in ('left_top', 'right_top'): widgets = Column(self.widget_box, VSpacer()) elif loc in ('left_bottom', 'right_bottom'): widgets = Column(VSpacer(), self.widget_box) # Do not center if content is responsive backend = self.backend or Store.current_backend if self.object is None: opts = {} else: initialize_dynamic(self.object) obj = self.object.last if isinstance(self.object, DynamicMap) else self.object try: opts = Store.lookup_options(backend, obj, 'plot').kwargs except: opts = {} responsive_modes = ('stretch_width', 'stretch_both', 'scale_width', 'scale_both') center = self.center if ((opts.get('responsive') and not (opts.get('width') or opts.get('frame_width'))) or opts.get('sizing_mode') in responsive_modes): center = False self._widget_container = widgets if not widgets: if center: components = [HSpacer(), self, HSpacer()] else: components = [self] elif center: if loc.startswith('left'): components = [widgets, HSpacer(), self, HSpacer()] elif loc.startswith('right'): components = [HSpacer(), self, HSpacer(), widgets] elif loc.startswith('top'): components = [ HSpacer(), Column(widgets, Row(HSpacer(), self, HSpacer())), HSpacer() ] elif loc.startswith('bottom'): components = [ HSpacer(), Column(Row(HSpacer(), self, HSpacer()), widgets), HSpacer() ] else: if loc.startswith('left'): components = [widgets, self] elif loc.startswith('right'): components = [self, widgets] elif loc.startswith('top'): components = [Column(widgets, self)] elif loc.startswith('bottom'): components = [Column(self, widgets)] self.layout[:] = components
rotation=rotation, **opts)] # Register plots with HoloViews Store.register({LineContours: LineContourPlot, FilledContours: FilledContourPlot, Image: GeoImagePlot, Feature: FeaturePlot, WMTS: WMTSPlot, Tiles: WMTSPlot, Points: GeoPointPlot, Labels: GeoLabelsPlot, VectorField: GeoVectorFieldPlot, Text: GeoTextPlot, Layout: LayoutPlot, NdLayout: LayoutPlot, Overlay: GeoOverlayPlot, Polygons: GeoPolygonPlot, Path: GeoPathPlot, Contours: GeoContourPlot, RGB: GeoRGBPlot, Shape: GeoShapePlot, Graph: GeoGraphPlot, TriMesh: GeoTriMeshPlot, Nodes: GeoPointPlot, EdgePaths: GeoPathPlot, HexTiles: GeoHexTilesPlot, QuadMesh: GeoQuadMeshPlot}, 'matplotlib') # Define plot and style options options = Store.options(backend='matplotlib')
class GeoTextPlot(GeoAnnotationPlot, TextPlot): "Draw the Text annotation object" def draw_annotation(self, axis, data, crs, opts): (x,y, text, fontsize, horizontalalignment, verticalalignment, rotation) = data opts['fontsize'] = fontsize x, y = axis.projection.transform_point(x, y, src_crs=crs) return [axis.text(x, y, text, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=rotation, **opts)] # Register plots with HoloViews Store.register({Contours: GeoContourPlot, Image: GeoImagePlot, GeoFeature: GeoFeaturePlot, WMTS: WMTSPlot, GeoTiles: GeoTilePlot, Points: GeoPointPlot, Text: GeoTextPlot, Layout: LayoutPlot, Overlay: OverlayPlot}, 'matplotlib') # Define plot and style options opts = Store.options(backend='matplotlib') OverlayPlot.aspect = 'equal'
opts['fontsize'] = fontsize x, y = axis.projection.transform_point(x, y, src_crs=crs) return [ axis.text(x, y, text, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=rotation, **opts) ] # Register plots with HoloViews Store.register( { Contours: GeoContourPlot, Image: GeoImagePlot, GeoFeature: GeoFeaturePlot, WMTS: WMTSPlot, GeoTiles: GeoTilePlot, Points: GeoPointPlot, Text: GeoTextPlot, Layout: LayoutPlot, Overlay: OverlayPlot }, 'matplotlib') # Define plot and style options opts = Store.options(backend='matplotlib') OverlayPlot.aspect = 'equal'
horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=rotation, **opts) ] # Register plots with HoloViews Store.register( { LineContours: LineContourPlot, FilledContours: FilledContourPlot, Image: GeoImagePlot, Feature: FeaturePlot, WMTS: WMTSPlot, Tiles: TilePlot, Points: GeoPointPlot, Text: GeoTextPlot, Layout: LayoutPlot, NdLayout: LayoutPlot, Overlay: OverlayPlot, Polygons: GeoPolygonPlot, Path: GeoPathPlot, Shape: GeoShapePlot }, 'matplotlib') # Define plot and style options options = Store.options(backend='matplotlib') options.Shape = Options('style', edgecolor='black', facecolor='#30A2DA')
rotation=rotation, **opts)] # Register plots with HoloViews Store.register({LineContours: LineContourPlot, FilledContours: FilledContourPlot, Image: GeoImagePlot, Feature: FeaturePlot, WMTS: WMTSPlot, Tiles: WMTSPlot, Points: GeoPointPlot, Labels: GeoLabelsPlot, VectorField: GeoVectorFieldPlot, Text: GeoTextPlot, Layout: LayoutPlot, NdLayout: LayoutPlot, Overlay: GeoOverlayPlot, Polygons: GeoPolygonPlot, Path: GeoPathPlot, Contours: GeoContourPlot, RGB: GeoRGBPlot, Shape: GeoShapePlot, Graph: GeoGraphPlot, TriMesh: GeoTriMeshPlot, Nodes: GeoPointPlot, EdgePaths: GeoPathPlot, HexTiles: GeoHexTilesPlot, QuadMesh: GeoQuadMeshPlot}, 'matplotlib') # Define plot and style options options = Store.options(backend='matplotlib')
import numpy as np import holoviews as hv hv.extension('bokeh', logo=False) import param import panel as pn import matplotlib.pyplot as plt from holoviews.operation.datashader import rasterize from bokeh.models import WheelZoomTool from holoviews.core import Store valid_rgb_options = [ k for group in ['style', 'plot', 'norm', 'output'] for k in Store.options(backend='bokeh')['RGB'][group].allowed_keywords ] valid_rgb_options.remove( 'alpha') # remove option set by sliders on individual channels # TODO move to color module import colorcet as cc # repeat colormap to handle unint16 values # needed to handle non continuous labels because colormap is stretched (and not cycled) label_cmap = cc.b_glasbey_hv * 256 # bokeh hook workaround --> remove if holoviews finally handle this def zoom_bounds_hook(bounds): '''restrict zooming out to given bounds''' def _hook(plot, element): plot.state.x_range.bounds = (bounds[0], bounds[2])