Esempio n. 1
0
    def get_data(self, element, ranges, style):
        if self.static_source:
            data = {}
        else:
            if self.geographic and element.crs != DEFAULT_PROJ:
                element = project_shape(element)
            xs, ys = geom_to_array(element.geom()).T
            if self.invert_axes: xs, ys = ys, xs
            data = dict(xs=[xs], ys=[ys])

        mapping = dict(self._mapping)
        dim = element.vdims[0].name if element.vdims else None
        if element.level is not None:
            cmap = style.get('palette', style.get('cmap', None))
            if cmap and dim:
                cdim = element.vdims[0]
                dim_name = util.dimension_sanitizer(cdim.name)
                cmapper = self._get_colormapper(cdim, element, ranges, style)
                data[dim_name] = [element.level]
                mapping['fill_color'] = {'field': dim_name,
                                         'transform': cmapper}

        if 'hover' in self.tools+self.default_tools:
            if dim:
                dim_name = util.dimension_sanitizer(dim)
                data[dim_name] = [element.level]
            for k, v in self.overlay_dims.items():
                dim = util.dimension_sanitizer(k.name)
                data[dim] = [v for _ in range(len(xs))]
        return data, mapping, style
Esempio n. 2
0
    def get_data(self, element, ranges=None, empty=False):
        geoms = element.geom()
        if self.geographic and element.crs != DEFAULT_PROJ:
            try:
                geoms = DEFAULT_PROJ.project_geometry(geoms, element.crs)
            except:
                empty = True
        xs, ys = ([], []) if empty else geom_to_array(geoms)
        data = dict(xs=xs, ys=ys)

        style = self.style[self.cyclic_index]
        cmap = style.get('palette', style.get('cmap', None))
        mapping = dict(self._mapping)
        dim = element.vdims[0].name if element.vdims else None
        if cmap and dim and element.level is not None:
            cdim = element.vdims[0]
            dim_name = util.dimension_sanitizer(cdim.name)
            cmapper = self._get_colormapper(cdim, element, ranges, style)
            data[dim_name] = [] if empty else [
                element.level for _ in range(len(xs))
            ]
            mapping['fill_color'] = {'field': dim_name, 'transform': cmapper}

        if 'hover' in self.tools + self.default_tools:
            if dim:
                dim_name = util.dimension_sanitizer(dim)
                data[dim_name] = [element.level for _ in range(len(xs))]
            for k, v in self.overlay_dims.items():
                dim = util.dimension_sanitizer(k.name)
                data[dim] = [v for _ in range(len(xs))]
        return data, mapping
Esempio n. 3
0
    def get_data(self, element, ranges, style):
        if not self.geographic:
            return super(GeometryPlot, self).get_data(element, ranges, style)

        if self.static_source:
            data = {}
        else:
            geoms = element.geom()
            if element.crs:
                geoms = DEFAULT_PROJ.project_geometry(geoms, element.crs)
            xs, ys = geom_to_array(geoms)
            data = dict(xs=ys, ys=xs) if self.invert_axes else dict(xs=xs,
                                                                    ys=ys)

        mapping = dict(self._mapping)
        if element.vdims and getattr(element, 'level', None) is not None:
            cdim = element.vdims[0]
            dim_name = util.dimension_sanitizer(cdim.name)
            data[dim_name] = [element.level for _ in range(len(xs))]
            cmapper = self._get_colormapper(cdim, element, ranges, style)
            color_prop = 'fill_color' if isinstance(element,
                                                    Polygons) else 'line_color'
            mapping[color_prop] = {'field': dim_name, 'transform': cmapper}

        if any(isinstance(t, HoverTool) for t in self.state.tools):
            dim_name = util.dimension_sanitizer(element.vdims[0].name)
            for k, v in self.overlay_dims.items():
                dim = util.dimension_sanitizer(k.name)
                data[dim] = [v for _ in range(len(xs))]
            data[dim_name] = [element.level for _ in range(len(xs))]

        self._get_hover_data(data, element)
        return data, mapping, style
Esempio n. 4
0
 def _postprocess_hover(self, renderer, source):
     super(GeoPlot, self)._postprocess_hover(renderer, source)
     hover = self.handles.get('hover')
     try:
         from bokeh.models import CustomJSHover
     except:
         CustomJSHover = None
     if (not self.geographic or None in (hover, CustomJSHover)
             or isinstance(hover.tooltips, basestring)
             or self.projection is not GOOGLE_MERCATOR
             or hover.tooltips is None):
         return
     element = self.current_frame
     xdim, ydim = [dimension_sanitizer(kd.name) for kd in element.kdims]
     formatters, tooltips = {}, []
     xhover = CustomJSHover(code=self._hover_code % 0)
     yhover = CustomJSHover(code=self._hover_code % 1)
     for name, formatter in hover.tooltips:
         customjs = None
         if formatter in ('@{%s}' % xdim, '$x'):
             dim = xdim
             customjs = xhover
         elif formatter in ('@{%s}' % ydim, '$y'):
             dim = ydim
             customjs = yhover
         if customjs:
             key = formatter if formatter in ('$x', '$y') else dim
             formatters[key] = customjs
             formatter += '{custom}'
         tooltips.append((name, formatter))
     hover.tooltips = tooltips
     hover.formatters = formatters
Esempio n. 5
0
 def _postprocess_hover(self, renderer, source):
     super(GeoPlot, self)._postprocess_hover(renderer, source)
     hover = self.handles.get('hover')
     try:
         from bokeh.models import CustomJSHover
     except:
         CustomJSHover = None
     if (not self.geographic or None in (hover, CustomJSHover)
             or isinstance(hover.tooltips, basestring)):
         return
     element = self.current_frame
     xdim, ydim = [dimension_sanitizer(kd.name) for kd in element.kdims]
     code = """
     var projections = require("core/util/projections");
     var x = special_vars.data_x
     var y = special_vars.data_y
     var coords = projections.wgs84_mercator.inverse([x, y])
     return "" + (coords[%d]).toFixed(4)
     """
     formatters = {
         xdim: CustomJSHover(formatter=code % 0),
         ydim: CustomJSHover(formatter=code % 1),
     }
     tooltips = []
     for name, formatter in hover.tooltips:
         if formatter in ('@{%s}' % xdim, '@{%s}' % ydim):
             formatter += '{custom}'
         tooltips.append((name, formatter))
     hover.tooltips = tooltips
     hover.formatters = formatters
Esempio n. 6
0
def visits_plot_per_metric(df, x, y, hover_columns=None, filt=0):
    """
    * x: name of the column for x-axis
    * y: name of the column for y-axis
    * hover_columns: list of column names for hover information
    """
    from bokeh.models import HoverTool
    from holoviews.core.util import dimension_sanitizer

    if hover_columns:
        _tt = [(n, "@{%s}" % dimension_sanitizer(n)) for n in hover_columns]
        hover = HoverTool(tooltips=_tt)
    else:
        hover = "hover"

    # 'x' must be renamed for Hv/Pn link axes with equal name/label;
    # in here, it will cause plots on different filter to have their
    # x-axis values merged (producing big blank areas in each plot)
    x_renamed = "visits ({filt})".format(filt=filt)
    df = df.sort_values(x)
    df[x_renamed] = df[x].astype(str)

    curve = hv.Curve(df, x_renamed, y)

    points = hv.Scatter(df, [x_renamed, y],
                        hover_columns).opts(size=8,
                                            line_color="white",
                                            tools=[hover, "tap"],
                                            toolbar="above")

    return (curve * points).redim(y=hv.Dimension(y, range=(-1, 1)))
Esempio n. 7
0
 def __init__(self, source, target, **params):
     if 'vertex_columns' not in params:
         dimensions = [
             dimension_sanitizer(d.name) for d in target.dimensions()[:2]
         ]
         params['vertex_columns'] = dimensions
     super(VertexTableLink, self).__init__(source, target, **params)
Esempio n. 8
0
 def _postprocess_hover(self, renderer, source):
     super(GeoPlot, self)._postprocess_hover(renderer, source)
     hover = self.handles.get('hover')
     try:
         from bokeh.models import CustomJSHover
     except:
         CustomJSHover = None
     if (not self.geographic or None in (hover, CustomJSHover) or
         isinstance(hover.tooltips, basestring) or self.projection is not GOOGLE_MERCATOR
         or hover.tooltips is None):
         return
     element = self.current_frame
     xdim, ydim = [dimension_sanitizer(kd.name) for kd in element.kdims]
     formatters, tooltips = {}, []
     xhover = CustomJSHover(code=self._hover_code % 0)
     yhover = CustomJSHover(code=self._hover_code % 1)
     for name, formatter in hover.tooltips:
         customjs = None
         if formatter in ('@{%s}' % xdim, '$x'):
             dim = xdim
             customjs = xhover
         elif formatter in ('@{%s}' % ydim, '$y'):
             dim = ydim
             customjs = yhover
         if customjs:
             key = formatter if formatter in ('$x', '$y') else dim
             formatters[key] = customjs
             formatter += '{custom}'
         tooltips.append((name, formatter))
     hover.tooltips = tooltips
     hover.formatters = formatters
Esempio n. 9
0
 def _update_hover(self, element):
     tooltips, hover_opts = self._hover_opts(element)
     hover = self.handles['hover']
     tooltips = [(ttp.pprint_label, '@{%s}' % dimension_sanitizer(ttp.name))
                 if isinstance(ttp, Dimension) else ttp for ttp in tooltips]
     tooltips = [(l, t + '{custom}' if t in hover.formatters else t)
                 for l, t in tooltips]
     self.handles['hover'].tooltips = tooltips
Esempio n. 10
0
 def _update_hover(self, element):
     tooltips, hover_opts = self._hover_opts(element)
     hover = self.handles['hover']
     if 'hv_created' in hover.tags:
         tooltips = [
             (ttp.pprint_label, '@{%s}' % dimension_sanitizer(ttp.name))
             if isinstance(ttp, Dimension) else ttp for ttp in tooltips
         ]
         if self.geographic and tooltips[2:] == hover.tooltips[2:]:
             return
         tooltips = [(l, t + '{custom}' if t in hover.formatters else t)
                     for l, t in tooltips]
         hover.tooltips = tooltips
     else:
         super(GeoPlot, self)._update_hover(element)
Esempio n. 11
0
def draw(G, pos=None, **kwargs):
    """
    Draw the graph G using hvPlot.

    Draw the graph with hvPlot with options for node positions,
    labeling, titles, and many other drawing features.

    Parameters
    ----------
    G : graph
       A networkx graph
    pos : dictionary, optional
       A dictionary with nodes as keys and positions as values.
       If not specified a spring layout positioning will be computed.
       See :py:mod:`networkx.drawing.layout` for functions that
       compute node positions.
    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.
       Note: Arrows will be the same color as edges.
    arrowhead_length : float, optional (default=0.025)
       The length of the arrows as fraction of the overall extent of
       the graph
    with_labels :  bool, optional (default=True)
       Set to True to draw labels on the nodes.
    nodelist : list, optional (default G.nodes())
       Draw only specified nodes
    edgelist : list, optional (default=G.edges())
       Draw only specified edges
    node_size : scalar or array, optional (default=300)
       Size of nodes.  If an array is specified it must be the
       same length as nodelist.
    node_color : color string, node attribute, or array of floats, (default='r')
       Can be a single color, the name of an attribute on the nodes or
       sequence of colors with the same length as nodelist.  If the
       node_color references an attribute on the nodes or is a list of
       values they will be colormapped using the cmap and vmin, vmax
       parameters.
    node_shape :  string, optional (default='o')
       The shape of the node. Specification is as valid bokeh marker.
    alpha : float, optional (default=1.0)
       The node and edge transparency
    cmap : Colormap, optional (default=None)
       Colormap for mapping intensities of nodes
    vmin,vmax : float, optional (default=None)
       Minimum and maximum for node colormap scaling
    linewidths : [None | scalar | sequence]
       Line width of symbol border (default =1.0)
    edge_width : float, optional (default=1.0)
       Line width of edges
    edge_color : color string, or array of floats (default='r')
       Can be a single color, the name of an attribute on the edges or
       sequence of colors with the same length as the edges.  If the
       edge_color references an attribute on the edges or is a list of
       values they will be colormapped using the edge_cmap and
       edge_vmin, edge_vmax parameters.
    edge_cmap : Matplotlib colormap, optional (default=None)
       Colormap for mapping intensities of edges
    edge_vmin,edge_vmax : floats, optional (default=None)
       Minimum and maximum for edge colormap scaling
    style : string, optional (default='solid')
       Edge line style (solid|dashed|dotted,dashdot)
    labels : dictionary or string, optional (default=None)
       Node labels in a dictionary keyed by node of text labels or
       a string referencing a node attribute
    font_size : int, optional (default=12)
       Font size for text labels
    font_color : string, optional (default='black')
       Font color string
    font_family : string, optional (default='sans-serif')
       Font family
    label : string, optional
       Label for graph legend
    selection_policy : string, optional (default='nodes')
       Whether to select 'nodes', 'edges' or None on tap and selection
       events.
    inspection_policy : string, optional (default='nodes')
       Whether to select 'nodes', 'edges' or None on tap and selection
       events.
    geo : boolean, optional (default=False)
       Whether to return a GeoViews graph
    crs : cartopy.crs.CRS
       A cartopy coordinate reference system (enables a geographic plot)
    height : int, optional (default=400)
       The height of the plot in pixels
    width : int, optional (default=400)
       The width of the plot in pixels
    """
    if pos is None:
        pos = nx.drawing.spring_layout

    if not isinstance(pos, dict):
        pos = pos(G, **kwargs.get('layout_kwargs', {}))

    params, label_params = {}, {}
    label_element = Labels
    if kwargs.get('geo', False) or 'crs' in kwargs:
        try:
            import geoviews
        except ImportError:
            raise ImportError('In order to use geo-related features '
                              'the geoviews library must be available. '
                              'It can be installed with:\n  conda '
                              'install -c pyviz geoviews')
        crs = process_crs(kwargs.get('crs'))
        label_element = geoviews.Labels
        params['cls'] = geoviews.Graph
        params['crs'] = crs
        label_params['crs'] = crs

    # Construct Graph object
    g = _from_networkx(G, pos, **params)

    if 'nodelist' in kwargs:
        g.nodes.data = g.nodes.data.iloc[list(kwargs['nodelist'])]

    if 'edgelist' in kwargs:
        edges = g.array([0, 1])
        comparisons = []
        for edge in kwargs['edgelist']:
            comparisons.append(edges == edge)
        if len(comparisons):
            selector = np.logical_and(*np.logical_or.reduce(comparisons).T)
            g = g.iloc[selector]
        else:
            g = g.iloc[:0]

    # Compute options
    inspection_policy = kwargs.pop('inspection_policy', 'nodes')
    opts = dict(
        axiswise=True,
        arrowhead_length=kwargs.get('arrowhead_length', 0.025),
        directed=kwargs.pop('arrows', isinstance(G, nx.DiGraph)),
        colorbar=kwargs.pop('colorbar', False),
        padding=kwargs.get('padding', 0.1),
        width=kwargs.pop('width', 400),
        height=kwargs.pop('height', 400),
        selection_policy=kwargs.pop('selection_policy', 'nodes'),
        inspection_policy=inspection_policy,
        node_fill_color='red')

    if '_axis_defaults':
        opts.update(xaxis=None, yaxis=None, show_frame=False)

    opts.update({k: kwargs.pop(k) for k in list(kwargs) if k in GraphPlot.style_opts})
    if 'node_size' in opts:
        if isinstance(opts['node_size'], str):
            opts['node_size'] = dim(opts['node_size'])
        opts['node_size'] = np.sqrt(opts['node_size'])
    if 'node_color' in opts:
        opts['node_fill_color'] = opts.pop('node_color')
    if 'edge_color' in opts:
        opts['edge_line_color'] = opts.pop('edge_color')
    if 'node_shape' in kwargs:
        marker = kwargs.pop('node_shape')
        if marker in markers:
            marker_opts = markers[marker]
            marker = marker_opts['marker']
            if 'angle' in marker_opts:
                Store.add_style_opts(Graph, ['node_angle'], 'bokeh')
                opts['node_angle'] = marker_opts['angle']
        opts['node_marker'] = marker
    if 'alpha' in kwargs:
        alpha = kwargs.pop('alpha')
        opts['node_alpha'] = alpha
        opts['edge_alpha'] = alpha
    if 'linewidths' in kwargs:
        opts['node_line_width'] = kwargs.pop('linewidths')
    if 'edge_width' in kwargs:
        opts['edge_line_width'] = kwargs.pop('edge_width')
    if 'style' in kwargs:
        opts['edge_line_dash'] = kwargs.pop('style')

    node_styles = ('node_fill_color', 'node_size', 'node_alpha', 'node_line_width')
    for node_style in node_styles:
        if isinstance(opts.get(node_style), (np.ndarray, list, range)):
            g = g.clone((g.data, g.nodes.add_dimension(node_style, len(g.nodes.vdims), opts[node_style], True)))
            opts[node_style] = node_style

    edge_styles = ('edge_line_color', 'edge_line_alpha', 'edge_alpha', 'edge_line_width')
    for edge_style in edge_styles:
        if isinstance(opts.get(edge_style), (np.ndarray, list, range)):
            g = g.add_dimension(edge_style, len(g.vdims), opts[edge_style], True)
            opts[edge_style] = edge_style

    if opts.get('node_fill_color') in g.nodes.dimensions():
        lims = (kwargs.get('vmin', None), kwargs.get('vmax', None))
        if lims != (None, None):
            dimension = g.nodes.get_dimension(opts.get('node_fill_color'))
            dimension.range = lims

    if opts.get('edge_line_color') in g.dimensions():
        lims = (kwargs.get('edge_vmin', None), kwargs.get('edge_vmax', None))
        if lims != (None, None):
            dimension = g.get_dimension(opts.get('edge_line_color'))
            dimension.range = lims

    if inspection_policy == 'nodes':
        tooltip_dims = [(d.label, 'index_hover' if d in g.nodes.kdims else d.name)
                        for d in g.nodes.kdims[2:] + g.nodes.vdims]
    else:
        tooltip_dims = [(d.label, d.name+'_values' if d in g.kdims else d.name)
                        for d in g.kdims + g.vdims]
    tooltips = [(label, '@{%s}' % dimension_sanitizer(name))
                for label, name in tooltip_dims if name not in node_styles + edge_styles]
    opts['tools'] = [HoverTool(tooltips=tooltips), 'tap']

    g.opts(**opts)

    # Construct Labels
    if kwargs.get('with_labels', kwargs.get('labels', False)):
        label_opts = {k: kwargs.pop(k) for k in list(kwargs) if k in LabelsPlot.style_opts}
        if 'xoffset' in kwargs:
            label_opts['xoffset'] = kwargs.pop('xoffset')
        if 'yoffset' in kwargs:
            label_opts['yoffset'] = kwargs.pop('yoffset')
        if 'font_size' in kwargs:
            label_opts['text_font_size'] = kwargs.pop('font_size')
        if 'font_color' in kwargs:
            label_opts['text_color'] = kwargs.pop('font_color')
        if 'font_family' in kwargs:
            label_opts['text_font'] = kwargs.pop('font_family')
        labels = kwargs.get('labels', g.nodes.kdims[2])
        if isinstance(labels, dict):
            values = g.nodes.array(g.nodes.kdims)
            data = [(x, y, labels[i]) for (x, y, i) in values if i in labels]
            labels = label_element(data, g.nodes.kdims[:2], 'text', **label_params)
        else:
            labels = label_element(g.nodes, g.nodes.kdims[:2], labels, **label_params)
        g = g * labels.opts(**label_opts)

    # Apply label
    if 'label' in kwargs:
        g = g.relabel(kwargs.pop('label'))

    return g