Exemple #1
0
    def _postprocess_hover(self, renderer, source):
        super(RasterPlot, self)._postprocess_hover(renderer, source)
        hover = self.handles.get('hover')
        if not (hover and isinstance(hover.tooltips, list)):
            return

        element = self.current_frame
        xdim, ydim = [dimension_sanitizer(kd.name) for kd in element.kdims]
        xaxis = self.handles['xaxis']
        yaxis = self.handles['yaxis']

        code = """
        var {ax} = special_vars.{ax};
        var date = new Date({ax});
        return date.toISOString().slice(0, 19).replace('T', ' ')
        """
        tooltips, formatters = [], dict(hover.formatters)
        for (name, formatter) in hover.tooltips:
            if isinstance(xaxis, DatetimeAxis) and formatter == '$x':
                xhover = CustomJSHover(code=code.format(ax='x'))
                formatters['$x'] = xhover
                formatter += '{custom}'
            if isinstance(yaxis, DatetimeAxis) and formatter == '$y':
                yhover = CustomJSHover(code=code.format(ax='y'))
                formatters['$y'] = yhover
                formatter += '{custom}'
            tooltips.append((name, formatter))
        hover.tooltips = tooltips
        hover.formatters = formatters
Exemple #2
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
Exemple #3
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
Exemple #4
0
    def _set_tools(self):
        wheel_zoom = WheelZoomTool()
        pan = PanTool()
        box_zoom = BoxZoomTool()
        box_select = BoxSelectTool()
        crosshair = CrosshairTool()
        tap = TapTool()
        save = SaveTool()

        lasso_select = LassoSelectTool(
            select_every_mousemove=False,  # enhance performance
        )

        code = """
            var projections = require("core/util/projections");
            var x = special_vars.x
            var y = special_vars.y
            var coords = projections.wgs84_mercator.inverse([x, y])
            return coords[%d].toFixed(2)
        """

        tooltips = '''
            <style>
                .bk-tooltip>div:not(:nth-child(-n+5)) {{
                    display:none;
                }}

                .bk-tooltip>div {{
                    background-color: #dff0d8;
                    padding: 5px;
                }}
            </style>

            <b>STATION: </b> @{STNNBR} <br />
            <b>LON: </b> @X_WMTS{custom} <br />
            <b>LAT: </b> @Y_WMTS{custom} <br />
        '''

        hover = HoverTool(toggleable=True,
                          mode='mouse',
                          tooltips=tooltips,
                          renderers=[self.env.wmts_map_scatter],
                          formatters={
                              'X_WMTS': CustomJSHover(code=code % 0),
                              'Y_WMTS': CustomJSHover(code=code % 1),
                          })

        tools = (pan, box_zoom, lasso_select, hover, crosshair, tap,
                 wheel_zoom)
        self.env.wmts_map.add_tools(*tools)

        # set defaults
        self.env.wmts_map.toolbar.active_drag = pan
        self.env.wmts_map.toolbar.active_inspect = [crosshair, hover]
        self.env.wmts_map.toolbar.active_scroll = wheel_zoom
        self.env.wmts_map.toolbar.active_tap = None
Exemple #5
0
def figure(df=None, **kwargs) -> Figure:
    if df is None:
        # just have at least some defaults..
        dtypes = {
            'date': 'datetime64',
            'error': str,
        }
    else:
        dtypes = df.reset_index().dtypes.to_dict()

    tooltips = []
    formatters = {}
    for c, t in dtypes.items():
        fmt = None
        tfmt = '@' + c
        if df is None:
            dateish = 'datetime64' in str(t)
        else:
            # this is more reliable, works if there is a mix of timestamps..
            s = df.reset_index()[c].dropna()
            dateish = len(s) > 0 and s.apply(
                lambda x: isinstance(x, (pd.Timestamp, datetime))).all()
        # TODO add to tests?
        if dateish:
            fmt = 'datetime'
            # todo %T only if it's actually datetime, not date? not sure though...
            tfmt += '{%F %a %T}'
        elif 'timedelta64' in str(t):  # also meh
            fmt = CustomJSHover(code='const tick = value; ' +
                                hhmm_formatter(unit=t))
            tfmt += '{custom}'
            # eh, I suppose ok for now. would be nice to reuse in the tables...
        elif c == 'error':
            # FIXME ugh. safe here is potentially dangerous... need to figure out how to do this
            tfmt = '<pre>@error{safe}</pre>'
        if fmt is not None:
            formatters['@' + c] = fmt

        tooltips.append((c, tfmt))
    # TODO very annoying, seems that if one of the tooltips is broken, nothing works at all?? need defensive tooltips..

    # see https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#formatting-tooltip-fields
    # TODO: use html tooltip with templating
    # and https://docs.bokeh.org/en/latest/docs/reference/models/formatters.html#bokeh.models.formatters.DatetimeTickFormatter
    from bokeh.models import HoverTool
    hover = HoverTool(
        tooltips=tooltips,
        formatters=formatters,
        # display a tooltip whenever the cursor is vertically in line with a glyph
        # TODO not sure I like this, it's a bit spammy
        mode='vline')
    from bokeh.plotting import figure as F
    # todo no need to pass plot_width?
    kw = {'plot_width': 2000}
    kw.update(**kwargs)
    f = F(**kw)
    # ugh. would be nice if add_tools returned self..
    f.add_tools(hover)
    return f
Exemple #6
0
    def create_callbacks(self):
        subset = CustomJS(args=dict(source=self.sources['subset']),
                          code="""
            // get data source from Callback args
            var data = source.data;

            /// get BoxSelectTool dimensions from cb_data parameter of Callback
            var geometry = cb_data['geometry'];

            var x0 = geometry['x0'];
            var y0 = geometry['y0'];
            var x1 = geometry['x1'];
            var y1 = geometry['y1'];
            var xxs = [[[x0, x0, x1, x1]]];
            var yys = [[[y0, y1, y1, y0]]];

            /// update data source with new Rect attributes
            data['xs'].pop();
            data['ys'].pop();
            data['xs'].push(xxs);
            data['ys'].push(yys);

            // emit update of data source
            source.change.emit();
        """)

        latitude = CustomJSHover(code="""
                        var projections = require("core/util/projections");
                        var x = special_vars.x
                        var y = special_vars.y
                        var coords = projections.wgs84_mercator.inverse([x, y])
                        return "" + coords[1].toFixed(6)
                    """)

        longitude = CustomJSHover(code="""
                        var projections = require("core/util/projections");
                        var x = special_vars.x
                        var y = special_vars.y
                        var coords = projections.wgs84_mercator.inverse([x, y])
                        return "" + coords[0].toFixed(6)
                    """)

        self.callbacks.update([('subset', subset), ('latitude', latitude),
                               ('longitude', longitude)])
Exemple #7
0
def cmatrix_plot_format(plot: Figure, format_cols: List, hover_code: str) -> Figure:
    plot.toolbar.logo = None
    plot.yaxis.axis_label_text_font_size = "16px"
    plot.yaxis.axis_label_text_color = '#003566'
    plot.xaxis.major_label_text_color = '#003566'
    plot.y_range.range_padding = 0
    plot.hover.point_policy = "follow_mouse"
    plot.hover.attachment = "above"
    cust_formatters = {}
    for f in format_cols:
        code_ref = dashboard_constants.bucket_cust_format.format(field_name=f) if f == 'max_percentile_conf' else \
            dashboard_constants.scale_format_code.format(field_name=f)
        cust_formatters[f] = CustomJSHover(args=dict(source=plot.renderers[0].data_source), code=code_ref)
    custom_hover_format = CustomJS(code=hover_code)
    format_dict = {f'@{c}': cust_formatters[c] for c in format_cols}
    plot.add_tools(HoverTool(tooltips=None, callback=custom_hover_format, formatters=format_dict))
    someargs = dict(yaxis=plot.yaxis[0], xaxis=plot.xaxis[0], legend=plot.legend[0])
    fig_resize_callback = CustomJS(args=someargs, code=dashboard_constants.fig_resize_callback_code)
    plot.js_on_change('inner_width', fig_resize_callback)
    return plot
Exemple #8
0
def varstatistics(functionNode):
    logger = functionNode.get_logger()
    logger.info("==>>>> statistics " + functionNode.get_browse_path())
    progressNode = functionNode.get_child("control").get_child("progress")
    progressNode.set_value(0)
    #functionNode.get_child("control.signal").set_value(None)

    vars = functionNode.get_child("variable").get_targets()
    widget = functionNode.get_child("widget").get_target()
    bins = functionNode.get_child("bins").get_value()
    tags = functionNode.get_child("annotations").get_value()
    startTime = date2secs(widget.get_child("startTime").get_value())
    endTime = date2secs(widget.get_child("endTime").get_value())

    vars = {var.get_id(): {"node": var} for var in vars}

    #first 30% progress:
    prog = Progress(progressNode)
    progressNode.set_value(0.1)
    prog.set_offset(0.1)
    #prog.set_divisor()

    if tags:
        allAnnoNodes = widget.get_child(
            "hasAnnotation.annotations").get_leaves()
        allAnnos = []
        prog.set_divisor(len(allAnnoNodes) / 0.2)
        for index, node in enumerate(allAnnoNodes):
            prog.set_progress(index)
            if node.get_child("type").get_value() == "time":
                thisTags = node.get_child("tags").get_value()
                if any(tag in tags for tag in thisTags):
                    anno = {}
                    for child in node.get_children():
                        anno[child.get_name()] = child.get_value()
                    if date2secs(anno["startTime"]) >= startTime and date2secs(
                            anno["endTime"]
                    ) <= endTime:  #take this anno only if it is inside the current start/end time
                        allAnnos.append(anno)
        if allAnnos == []:
            give_up(functionNode, "no matching annotations in selected time")
            return False
    else:
        allAnnos = []

    progressNode.set_value(0.3)

    logger.debug(f"statistics annotations to look at: {len(allAnnos)}")
    prog.set_offset(0.3)
    totalAnnos = max(len(allAnnos), 1)
    totalCount = len(vars) * totalAnnos

    prog.set_divisor(totalCount / 0.3)
    totalValids = 0
    for varIndex, var in enumerate(vars):
        info = vars[var]
        if tags:
            #iterate over all start and end times
            values = numpy.asarray([], dtype=numpy.float64)
            for annoIndex, anno in enumerate(allAnnos):
                thisValues = info["node"].get_time_series(
                    anno["startTime"], anno["endTime"])["values"]
                values = numpy.append(values, thisValues)
                myCount = varIndex * totalAnnos + annoIndex
                prog.set_progress(myCount)
        else:
            values = info["node"].get_time_series(startTime, endTime)["values"]

        valids = numpy.count_nonzero(~numpy.isfinite(values))
        totalValids += valids
        hist, edges = numpy.histogram(values, bins=bins)
        hist = hist / len(values)  #normalize
        info["hist"] = hist
        info["edges"] = edges

    #make a plot
    if totalValids == 0:
        give_up(
            functionNode,
            "all Variables are have no data in the time and annotations selected"
        )
        return False

    progressNode.set_value(0.6)

    hover1 = HoverTool(tooltips=[('x,y', '$x,$y')], mode='mouse')
    hover1.point_policy = 'snap_to_data'
    hover1.line_policy = "nearest"

    tools = [
        PanTool(),
        WheelZoomTool(),
        BoxZoomTool(),
        ResetTool(),
        SaveTool(), hover1
    ]

    title = "Statistics of " + str(
        [info["node"].get_name() for var, info in vars.items()])
    if tags:
        title = title + " in annotation: " + str(tags)

    fig = figure(title=title, tools=tools, plot_height=300)
    fig.toolbar.logo = None

    curdoc().theme = Theme(json=themes.darkTheme)
    fig.xaxis.major_label_text_color = themes.darkTickColor
    fig.yaxis.major_label_text_color = themes.darkTickColor

    for index, var in enumerate(vars):
        info = vars[var]
        col = themes.darkLineColors[index]
        hist = info["hist"]
        edges = info["edges"]

        fig.quad(top=hist,
                 bottom=0,
                 left=edges[:-1],
                 right=edges[1:],
                 fill_color=col,
                 line_color=col,
                 alpha=0.8,
                 legend_label=info["node"].get_name())

    fig.legend.location = "top_left"
    fileName = functionNode.get_child("fileName").get_value()
    filePath = os.path.join(myDir, './../web/customui/' + fileName)

    # now make the trend box plot, but only for tags
    # for each variable we create statistics for the annotations and prepare the data
    # {"node":Node(), "boxLower":[], "boxUpper", "mean", "limitUpper", "limitLower"}
    #

    startTime = date2secs(widget.get_child("startTime").get_value(
    ))  #we only take tags that are inside the current zoom of the widgets
    endTime = date2secs(widget.get_child("endTime").get_value())

    boxPlots = []
    allTimes = []
    if tags:
        for index, var in enumerate(vars):
            info = {
                "node": vars[var]["node"],
                "boxLower": [],
                "boxUpper": [],
                "median": [],
                "time": [],
                "limitUpper": [],
                "limitLower": [],
                "mean": []
            }
            for anno in allAnnos:
                data = info["node"].get_time_series(anno["startTime"],
                                                    anno["endTime"])
                if len(data["values"]):
                    data["values"] = data["values"][numpy.isfinite(
                        data["values"])]
                    #remove the nan
                if len(data["values"]):

                    #make the statistics
                    info["time"].append(numpy.median(data["__time"]) * 1000)
                    allTimes.append(numpy.median(data["__time"]) * 1000)
                    info["limitLower"].append(
                        numpy.quantile(data["values"], 0.01))
                    info["limitUpper"].append(
                        numpy.quantile(data["values"], 0.99))
                    info["boxLower"].append(
                        numpy.quantile(data["values"], 0.25))
                    info["boxUpper"].append(
                        numpy.quantile(data["values"], 0.75))
                    info["median"].append(numpy.median(data["values"]))
                    info["mean"].append(numpy.mean(data["values"]))
            boxPlots.append(info)

        format = "%Y-%m-%d-T%H:%M:%S"
        custom = """var local = moment(value).tz('UTC'); return local.format();"""  #%self.server.get_settings()["timeZone"]

        hover = HoverTool(tooltips=[('date', '@x{%F}')],
                          formatters={'@x': CustomJSHover(code=custom)},
                          mode='mouse')
        hover.point_policy = 'snap_to_data'
        hover.line_policy = "nearest"
        tools = [
            PanTool(),
            BoxZoomTool(),
            WheelZoomTool(),
            ResetTool(), hover,
            SaveTool()
        ]

        fig2 = figure(title="trends",
                      tools=tools,
                      plot_height=300,
                      x_axis_type='datetime')
        fig2.xaxis.major_label_text_color = themes.darkTickColor
        fig2.yaxis.major_label_text_color = themes.darkTickColor

        progressNode.set_value(0.7)

        fig2.xaxis.formatter = DatetimeTickFormatter(years=format,
                                                     days=format,
                                                     months=format,
                                                     hours=format,
                                                     hourmin=format,
                                                     minutes=format,
                                                     minsec=format,
                                                     seconds=format)
        fig2.toolbar.logo = None
        #fig2.line([1,2,3],[1,2,3])
        #calc with of vbars
        if len(allAnnos) > 1:
            xTimesStart = min(allTimes)
            xTimesEnd = max(allTimes)
            width = (xTimesEnd - xTimesStart) / 2 / len(allAnnos)
        else:
            width = 1000000

        for index, info in enumerate(boxPlots):
            #each info is for one variable
            col = themes.darkLineColors[index]
            fig2.segment(info["time"],
                         info["limitUpper"],
                         info["time"],
                         info["boxUpper"],
                         line_color=col)
            fig2.segment(info["time"],
                         info["limitLower"],
                         info["time"],
                         info["boxLower"],
                         line_color=col)

            width = 20
            #fig2.vbar(info["time"],width=width,bottom=info["median"],top=info["boxUpper"],fill_color=col,line_color="black",width_units='screen')
            #fig2.vbar(info["time"],width=width,bottom=info["boxLower"],top=info["median"],fill_color=col,line_color="black",width_units='screen')
            #upper box
            sizUpper = numpy.asarray(info["boxUpper"]) - numpy.asarray(
                info["median"])
            medUpper = numpy.asarray(info["median"]) + sizUpper / 2
            fig2.rect(x=info["time"],
                      y=medUpper,
                      width_units='screen',
                      width=20,
                      height=sizUpper,
                      fill_color=col,
                      line_color="black")

            #lower box
            sizLower = numpy.asarray(info["median"]) - numpy.asarray(
                info["boxLower"])
            medLower = numpy.asarray(info["median"]) - sizLower / 2
            fig2.rect(x=info["time"],
                      y=medLower,
                      width_units='screen',
                      width=20,
                      height=sizLower,
                      fill_color=col,
                      line_color="black")

            #sort data for line
            x = numpy.asarray(info["time"])
            y = numpy.asarray(info["mean"])
            order = numpy.argsort(x)
            x = x[order]
            y = y[order]
            fig2.line(x, y, line_color=col)

        progressNode.set_value(0.8)
    else:
        #no fig2
        pass

    output_file(
        filePath, mode="inline"
    )  #inline: put the bokeh .js into this html, otherwise the default cdn will be taken, might cause CORS problems
    if tags:
        save(layout([[fig], [fig2]]))
    else:
        save(fig)

    return True
output_file("customjs_hover.html")

# range bounds supplied in web mercator coordinates
p = figure(x_range=(-2000000, 6000000),
           y_range=(-1000000, 7000000),
           x_axis_type="mercator",
           y_axis_type="mercator")
p.add_tile(CARTODBPOSITRON)

p.circle(x=[0, 2000000, 4000000], y=[4000000, 2000000, 0], size=30)

code = """
    var projections = require("core/util/projections");
    var x = special_vars.x
    var y = special_vars.y
    var coords = projections.wgs84_mercator.inverse([x, y])
    return coords[%d].toFixed(2)
"""

p.add_tools(
    HoverTool(tooltips=[
        ('lon', '@x{custom}'),
        ('lat', '@y{custom}'),
    ],
              formatters={
                  'x': CustomJSHover(code=code % 0),
                  'y': CustomJSHover(code=code % 1),
              }))

show(p)
Exemple #10
0
        <p style="font-size:1.1em; font-weight:bold; margin:0px; padding:0px;">@start_name </br>
            <span style="color:#488ebc; font-size:1.1em; font-weight:bold">@end_name</span></br>
            <span style="font-size:0.9em; white-space:nowrap;">Expr_value: @value</span>
        </p>
    </div>
    <div style="display:@display{custom};">
        <p style="font-size:1.1em; font-weight:bold; margin:0px; padding:0px;">
            <span style="color:#488ebc; font-size:1.1em; font-weight:bold; white-space:nowrap;">
                @start_name ---- @end_name
            </span></br>
        </p>
    </div>
'''
## Display disparate tooltip contents for cells-genes edges and L-R pairs edges
cus_tt = CustomJSHover(code='''
    if (value==" ") {return "none"}
    else if (value=="none") {return " "}
''')

hover = HoverTool(renderers=[graphA],
                  tooltips=TOOLTIPS,
                  show_arrow=False,
                  formatters=dict(display=cus_tt))
plot.add_tools(hover, TapTool())
graphA.selection_policy = NodesAndLinkedEdges()
graphA.inspection_policy = EdgesAndLinkedNodes()
plot.renderers.append(graphA)

labels = LabelSet(x='x',
                  y='y',
                  text='name',
                  text_color='#00cadb',
Exemple #11
0
                    ])
    return my_stats


custom = CustomJSHover(code="""
                     if (value==0) {
                         return ""
                     }
                     var modified;
                     var SI_SYMBOL = ["", "k", "m", "b", "t"];
                     modified = 100000/value;
                     
                     // what tier? (determines SI symbol)
                     var tier = Math.log10(modified) / 3 | 0;
                     
                     // if zero, we don't need a suffix
                     if(tier == 0) return "(1/" + modified.toFixed(0) + " Ppl)";
                     
                     // get suffix and determine scale
                     var suffix = SI_SYMBOL[tier];
                     var scale = Math.pow(10, tier * 3);
                     
                     // scale the number
                     var scaled = modified / scale;
                     
                     // format number and add suffix
                     return "(1/" + scaled.toFixed(1) + suffix + " Ppl)";
                     """)


def my_format(num):
    if num == 0:
Exemple #12
0
    def __init__(self,
                 image_views,
                 sv_metadata,
                 sv_streamctrl,
                 positions=POSITIONS):
        """Initialize a resolution rings overlay.

        Args:
            image_views (ImageView): Associated streamvis image view instances.
            sv_metadata (MetadataHandler): A metadata handler to report metadata issues.
            sv_streamctrl (StreamControl): A StreamControl instance of an application.
            positions (list, optional): Scattering radii in Angstroms. Defaults to
                [1.4, 1.5, 1.6, 1.8, 2, 2.2, 2.6, 3, 5, 10].
        """
        self._sv_metadata = sv_metadata
        self._sv_streamctrl = sv_streamctrl
        self.positions = np.array(positions)

        # ---- add resolution tooltip to hover tool
        self._formatter_source = ColumnDataSource(data=dict(
            detector_distance=[np.nan],
            beam_energy=[np.nan],
            beam_center_x=[np.nan],
            beam_center_y=[np.nan],
        ))

        resolution_formatter = CustomJSHover(
            args=dict(params=self._formatter_source), code=js_resolution)

        hovertool_off = HoverTool(tooltips=[("intensity", "@image")],
                                  names=["image_glyph"])
        hovertool_on = HoverTool(
            tooltips=[("intensity", "@image"),
                      ("resolution", "@x{resolution} Å")],
            formatters={"@x": resolution_formatter},
            names=["image_glyph"],
        )

        # ---- resolution rings
        self._source = ColumnDataSource(
            dict(x=[], y=[], w=[], h=[], text_x=[], text_y=[], text=[]))
        ellipse_glyph = Ellipse(x="x",
                                y="y",
                                width="w",
                                height="h",
                                fill_alpha=0,
                                line_color="white")

        text_glyph = Text(
            x="text_x",
            y="text_y",
            text="text",
            text_align="center",
            text_baseline="middle",
            text_color="white",
        )

        cross_glyph = Cross(x="beam_center_x",
                            y="beam_center_y",
                            size=15,
                            line_color="red")

        for image_view in image_views:
            image_view.plot.add_glyph(self._source, ellipse_glyph)
            image_view.plot.add_glyph(self._source, text_glyph)
            image_view.plot.add_glyph(self._formatter_source, cross_glyph)

        # ---- toggle button
        def toggle_callback(state):
            hovertool = hovertool_on if state else hovertool_off
            for image_view in image_views:
                image_view.plot.tools[-1] = hovertool

        toggle = CheckboxGroup(labels=["Resolution Rings"], default_size=145)
        toggle.on_click(toggle_callback)
        self.toggle = toggle
Exemple #13
0
def orders_by_day(days):
    df = pd.read_csv("Levia_Live_Sales.csv")
    from bokeh.core.properties import value
    from bokeh.io import show
    from bokeh.models import ColumnDataSource, HoverTool
    from bokeh.plotting import figure
    from bokeh.io import show
    from bokeh.models import ColumnDataSource, HoverTool, CustomJSHover
    from bokeh.plotting import figure
    from bokeh.io import output_file, show
    from bokeh.palettes import Category20c
    from bokeh.plotting import figure
    from bokeh.transform import cumsum
    from bokeh.palettes import Turbo256, Turbo, inferno
    from bokeh.models import LabelSet, ColumnDataSource
    from bokeh.models import ColumnDataSource, HoverTool
    #df=pd.read_csv("LeviaExpenses.csv",index_col=0)
    output_file("stacked.html")

    dff = df[df["Date"].isin(days)]
    dfn = pd.DataFrame(index=days,
                       columns=[act for act in pd.unique(dff["Account"])])
    print(dff)

    for i, d in enumerate(dfn.index):
        for act in dfn:
            dfff = dff[dff["Account"] == act]
            dfff = dfff[dfff["Date"] == d].reset_index()
            try:
                dfn[act][i] = dfff["Total"][0]
            except:
                dfn[act][i] = 0

    st.dataframe(dfn)

    data = {"Years": [x[:-5] for x in days]}

    for i, col in enumerate(dfn.columns):

        data[col] = dfn[col].to_list()

    print(data)

    #data['color'] = Category20c[len(dict)]
    colors = inferno(43)
    #st.write(colors)
    df = pd.DataFrame(data)
    df = df.set_index('Years').rename_axis(None)

    source = ColumnDataSource(data=df)
    colors = inferno(len(df.columns))
    p = figure(x_range=[x for x in df.index],
               plot_height=500,
               plot_width=750,
               title="Orders by Day by Dispensary",
               toolbar_location=None,
               tools="")
    columns = [x for x in df.columns]
    renderers = p.vbar_stack(columns,
                             x='index',
                             width=0.9,
                             color=colors,
                             source=source,
                             legend_label=columns,
                             name=columns)

    formatter = CustomJSHover(args=dict(source=source), )

    for r in renderers:
        hover = HoverTool(tooltips=[("Account", "$name"), ("Day", "@index"),
                                    ('Cases', "@$name{0}")],
                          formatters={'@%s' % r.name: formatter},
                          renderers=[r])
        p.add_tools(hover)

    # this doesn't trigger the formatter

    p.y_range.start = 0
    p.x_range.range_padding = 0.1
    p.xgrid.grid_line_color = None
    p.axis.minor_tick_line_color = None
    p.outline_line_color = None
    p.legend.location = "top_left"
    p.legend.orientation = "horizontal"

    st.bokeh_chart(p)
Exemple #14
0
def orders_by_acct(days):
    df = pd.read_csv("Levia_Live_Sales.csv")
    from bokeh.models import ColumnDataSource, HoverTool, CustomJSHover
    from bokeh.io import output_file, show
    from bokeh.plotting import figure
    from bokeh.palettes import inferno
    from bokeh.models import ColumnDataSource, HoverTool
    output_file("stacked.html")

    dff = df[df["Date"].isin(days)].sort_values(by="Total")
    dfn = pd.DataFrame(index=[act for act in pd.unique(dff["Account"])],
                       columns=["Cel", "Ach", "Dre"])
    print(dff)

    for i, act in enumerate(dfn.index):
        for flv in dfn:
            dfff = dff[dff["Account"] == act]
            try:
                dfn[flv][i] = sum(dfff[flv].to_list())
            except:
                dfn[flv][i] = 0

    st.dataframe(dfn)
    #dfn=dfn.sort_values(by="")
    data = {"Years": [x for x in dfn.index]}

    for i, col in enumerate(dfn.columns):

        data[col] = dfn[col].to_list()

    print(data)

    #data['color'] = Category20c[len(dict)]
    colors = inferno(43)
    #st.write(colors)
    df = pd.DataFrame(data)
    df = df.set_index('Years').rename_axis(None)

    source = ColumnDataSource(data=df)
    colors = inferno(len(df.columns))
    p = figure(x_range=[x for x in df.index],
               plot_height=500,
               plot_width=750,
               title="Orders By Account",
               toolbar_location=None,
               tools="")
    columns = [x for x in df.columns]
    p.xaxis.major_label_orientation = "vertical"
    renderers = p.vbar_stack(columns,
                             x='index',
                             width=0.9,
                             color=colors,
                             source=source,
                             legend_label=columns,
                             name=columns)

    formatter = CustomJSHover(args=dict(source=source), )

    for r in renderers:
        hover = HoverTool(tooltips=[("Flavor", "$name"), ("Account", "@index"),
                                    ('Cases', "@$name{0}")],
                          formatters={'@%s' % r.name: formatter},
                          renderers=[r])
        p.add_tools(hover)

    # this doesn't trigger the formatter

    p.y_range.start = 0
    p.x_range.range_padding = 0.1
    p.xgrid.grid_line_color = None
    p.axis.minor_tick_line_color = None
    p.outline_line_color = None
    p.legend.location = "top_left"
    p.legend.orientation = "horizontal"

    st.bokeh_chart(p)

    pass
Exemple #15
0
output_file("customjs_hover.html")

# range bounds supplied in web mercator coordinates
p = figure(x_range=(-2000000, 6000000),
           y_range=(-1000000, 7000000),
           x_axis_type="mercator",
           y_axis_type="mercator")
p.add_tile(get_provider(CARTODBPOSITRON))

p.circle(x=[0, 2000000, 4000000], y=[4000000, 2000000, 0], size=30)

code = """
    var projections = Bokeh.require("core/util/projections");
    var x = special_vars.x
    var y = special_vars.y
    var coords = projections.wgs84_mercator.inverse([x, y])
    return coords[%d].toFixed(2)
"""

p.add_tools(
    HoverTool(tooltips=[
        ('lon', '$x{custom}'),
        ('lat', '$y{custom}'),
    ],
              formatters={
                  '$x': CustomJSHover(code=code % 0),
                  '$y': CustomJSHover(code=code % 1),
              }))

show(p)
def make_cluster_plot(plot_data, pod, recs):

    # get x, y coordinates for pod and recs
    main_pod = pod.merge(plot_data, on=["title", "itunes_id", "genre", "subgenre"])
    recs = recs.merge(plot_data, on=["title", "itunes_id", "genre", "subgenre"])

    genre_list = list(plot_data.groupby(by="genre").groups.keys())
    show_list = recs["genre"].unique()

    p = figure(tools="wheel_zoom,pan,box_zoom,reset,tap",\
        plot_width=700, plot_height=500,\
        toolbar_location="right")
    p.toolbar.active_drag = None # disabling pan helps with scrolling on smartphones

    # plot all data points and group them by genres for the legends
    group = dict()
    legend_items = []
    for i, g in enumerate(genre_list):
        source = ColumnDataSource(plot_data.loc[plot_data["genre"] == g])
        group[g] = p.circle(x='x', y='y', size = 10,\
            color = Category20[19][-(i+1)],\
            fill_alpha=0.5,\
            line_alpha=0, muted_color="lightgray",\
            source = source, muted_alpha = 0.05)
        legend_items.append((g,[group[g]]))
        if g not in show_list: # only show genres that are in the recommendations
            group[g].muted = True

    # plot the main podcast
    p.image_url(url="artwork_url", x="x", y="y", w=50, h = 50, \
        anchor="center", global_alpha = 0.8, \
        h_units = "screen", w_units = "screen",\
        source = ColumnDataSource(main_pod))
    p.rect(main_pod['x'], main_pod['y'], width = 52, height = 52, \
        line_width = 3, height_units="screen", width_units="screen", \
        fill_alpha = 0, line_color = "red")
    # plot the recommendations on the current page
    recs_source = ColumnDataSource(recs)
    rend_main = p.rect('x', 'y', width = 18, height = 18, \
        line_width = 2, height_units="screen", width_units="screen", \
        fill_alpha = 0, line_color = "royalblue", source = recs_source)
    p.image_url(url="artwork_url", x="x", y="y", w=16, h=16, \
        anchor="center", h_units="screen", w_units="screen",\
        source=recs_source)

    # plot the recommendations on the current page
    # rend_main = p.hex('x', 'y', fill_color = 'ivory', line_color = "royalblue", \
    #     line_width = 3, size = 15, \
    #     fill_alpha = 1, source = recs_source)
    # plot the main podcast
    # p.circle(main_pod['x'], main_pod['y'], color = "red", size = 5)
    # p.circle(main_pod['x'], main_pod['y'], fill_color = "red", \
    #     fill_alpha = 0.2, radius = 10, line_color = "red", \
    #     line_alpha = 0.2)

    custom_hover = HoverTool(mode="mouse", point_policy="snap_to_data", \
        muted_policy = "ignore", renderers = [rend_main])

    # limit the hover list to 5 items in case of overlapping glyphs
    custom_formatter = CustomJSHover(code="""
        special_vars.indices = special_vars.indices.slice(0,5)
        if (special_vars.indices.indexOf(special_vars.index) >= 0)
        {
            return " "
        }
        else
        {
            return " hidden "
        }""")
    custom_hover.tooltips = """
    <div @title{custom|safe}>
        <div>
        <img
            src="@artwork_url" alt="@artwork_url" width="42"
            style="margin: 5px 5px 5px 5px;"
            border="2"
        ></img>
        <span style="font-size: 15px; font-weight: bold;">@title</span>
        </div>
    </div>
    """
    custom_hover.formatters = {'@title':custom_formatter}

    p.add_tools(custom_hover)

    p.outline_line_width = 7
    p.outline_line_alpha = 0.2
    p.outline_line_color = "navy"
    p.toolbar.autohide = True
    p.grid.visible = False

    legends = []
    for i in range(0, len(legend_items), 4):
        legends.append(Legend(items=legend_items[i:i+4], margin=2))
    for legend in legends:
        p.add_layout(legend,'below')

    p.plot_height = (600 + ((len(legend_items)-1)//4)*40)

    p.legend.click_policy="mute"
    p.legend.location = "bottom_center"
    p.legend.orientation = "horizontal"

    # url for selected recommendation
    selection_url_code = """
    var ind = source.selected.indices
    if (ind.length==1) {
        var itunes_id = source.data['itunes_id'][ind]
    } else {
        var itunes_id = source.data['itunes_id'][ind[0]]
    }
    var url = "/itunes_id=".concat(itunes_id, "&offset=0")
    window.open(url, "_self")
    """
    taptool = p.select(type=TapTool)
    taptool.renderers = [rend_main]
    taptool.callback = CustomJS(args = dict(source = recs_source), \
        code = selection_url_code)

    # make the figure responsive
    clusters = column([p], sizing_mode = "stretch_width")

    return components(clusters)
# merge the data sets
merged_df = pd.merge(arcgis_df, momo_df, left_index=True, right_index=True, how='outer')
merged_df['expected_plus_covid'] = merged_df['defunciones_esperadas'] + merged_df['deaths_covid']
merged_df["datestring"] = merged_df.index.strftime("%b %d")

# set up the figure
p = figure(plot_width=1000, plot_height=400, tools='pan,wheel_zoom,reset',
           x_axis_type="datetime", toolbar_location=None, name='COVID - Canary Islands',
           x_range=DataRange1d(bounds="auto"),
           y_range=Range1d(0, (max(merged_df['defunciones_esperadas_q99']) + 25), bounds="auto"))
p.sizing_mode = 'scale_width'

# Set up hover tooltips
covid_hover_formatter = CustomJSHover(code="""
    if (isNaN(value)) {
        return "-"
    }
    return value.toString();
""")

p.add_tools(HoverTool(
    tooltips=[("Date", '@datestring'),
              ("Expected Deaths", "@defunciones_esperadas"),
              ("Observed Deaths", "@defunciones_observadas"),
              ('COVID-19 Deaths', '@deaths_covid{custom}')],
    formatters={'@deaths_covid': covid_hover_formatter}
))

# format x axis
p.xaxis.formatter = DatetimeTickFormatter(
    hours=["%B %-d"],
    days=["%B %-d"],
class MyPlot:
    # figure
    p = None

    # palette
    palette = list(Colorblind8)

    # NaN hover formatter
    nan_hover_formatter = CustomJSHover(code="""
        if (isNaN(value)) {
            return "-"
        }
        return value.toString();                                                       
    """)

    def __init__(self,
                 figure_name,
                 x_lower_bound=None,
                 x_upper_bound=None,
                 y_lower_bound=None,
                 y_upper_bound=None):
        # set up the figure
        self.p = figure(plot_width=1000,
                        plot_height=400,
                        tools='pan,wheel_zoom,reset',
                        x_axis_type="datetime",
                        toolbar_location=None,
                        name=figure_name,
                        x_range=DataRange1d(x_lower_bound,
                                            x_upper_bound,
                                            bounds="auto"),
                        y_range=Range1d(y_lower_bound,
                                        y_upper_bound,
                                        bounds="auto"))
        self.p.sizing_mode = 'scale_width'

        # set up border
        self.p.border_fill_color = "whitesmoke"
        self.p.min_border_top = 15

        # format x axis
        self.p.xaxis.formatter = DatetimeTickFormatter(
            hours=["%B %-d"],
            days=["%B %-d"],
            months=["%B %-d"],
            years=["%B %-d"],
        )

    def add_line(self, x_column, y_column, source, name, legend):
        self.p.line(x=x_column,
                    y=y_column,
                    source=ColumnDataSource(source),
                    name=name,
                    legend_label=legend,
                    color=self.get_next_colour(),
                    line_width=1)

    def add_vertical_bar(self, date, label):
        # create and add span to figure
        # date should be created via datetime.datetime(2001,1,1) or equivalent
        span_date = date.timestamp() * 1000
        vertical_span = Span(location=span_date,
                             dimension='height',
                             line_color=self.palette.pop(),
                             line_dash='dashed',
                             line_width=2)
        span_label = Label(x=span_date,
                           y=10,
                           y_units='screen',
                           text=' ' + label,
                           text_font='helvetica',
                           text_font_size='9pt')

        self.p.add_layout(vertical_span)
        self.p.add_layout(span_label)

    def add_band(self, x_column, source, max_values_column, min_values_column):
        # add a 'confidence interval' or band to the figure
        max_min_interval = Band(base=x_column,
                                lower=max_values_column,
                                upper=min_values_column,
                                source=ColumnDataSource(source),
                                level='underlay',
                                fill_alpha=1.0,
                                line_width=1,
                                line_color='black')
        self.p.add_layout(max_min_interval)

    def add_hover_tool(self, hover_tool):
        self.p.add_tools(hover_tool)

    def create_legend(self):
        # setup legend
        self.p.legend.location = "top_left"
        self.p.legend.click_policy = "hide"
        self.p.legend.label_text_font_size = "8pt"
        self.p.legend.spacing = 0
        self.p.legend.border_line_color = None

    def create_readme_from_template(self):
        # create the legend (note this needs to be done last after all glyphs have been added)
        self.create_legend()

        # create the json data for the plot
        item_text = json.dumps(json_item(self.p, "Plot"))

        with open('../docs/page.template', 'r') as file:
            template = file.read()

        # Replace the target strings
        template = template.replace('{PLACEHOLDER}', item_text)

        now = datetime.now()
        template = template.replace('{DATE}',
                                    now.strftime("%d/%m/%Y %H:%M:%S"))

        # Write the file out again
        with open('../docs/README.md', 'w') as file:
            print("Writing new README.md.")
            file.write(template)

    def get_next_colour(self):
        return self.palette.pop()
Exemple #19
0
def expense_graph():
    from bokeh.core.properties import value
    from bokeh.io import show
    from bokeh.models import ColumnDataSource, HoverTool
    from bokeh.plotting import figure

    from bokeh.io import show
    from bokeh.models import ColumnDataSource, HoverTool, CustomJSHover
    from bokeh.plotting import figure

    from bokeh.models import ColumnDataSource, HoverTool
    df = pd.read_csv("LeviaExpenses.csv", index_col=0)
    output_file("stacked.html")

    data = {"Years": [x for x in df.index]}

    for i, col in enumerate(df.columns):

        data[col] = df[col].to_list()

    print(data)

    #data['color'] = Category20c[len(dict)]
    colors = inferno(43)
    #st.write(colors)
    df = pd.DataFrame(data)
    df = df.set_index('Years').rename_axis(None)

    source = ColumnDataSource(data=df)

    p = figure(x_range=[x for x in df.index],
               plot_height=750,
               plot_width=1900,
               title="Fruit Counts by Year",
               toolbar_location=None,
               tools="")
    columns = [x for x in df.columns]
    renderers = p.vbar_stack(columns,
                             x='index',
                             width=0.9,
                             color=colors,
                             source=source,
                             legend_label=columns,
                             name=columns)

    formatter = CustomJSHover(args=dict(source=source), )

    for r in renderers:
        hover = HoverTool(tooltips=[("Expense Class", "$name"),
                                    ("Period", "@index"),
                                    ('$', "@$name{0.00}")],
                          formatters={'@%s' % r.name: formatter},
                          renderers=[r])
        p.add_tools(hover)

    # this doesn't trigger the formatter

    p.y_range.start = 0
    p.x_range.range_padding = 0.1
    p.xgrid.grid_line_color = None
    p.axis.minor_tick_line_color = None
    p.outline_line_color = None
    p.legend.location = "top_left"
    p.legend.orientation = "horizontal"

    st.bokeh_chart(p)
Exemple #20
0
def stacked_viz(
    df: pd.DataFrame,
    x: str,
    y: str,
    grp_cnt_stats: Dict[str, int],
    plot_width: int,
    plot_height: int,
    timeunit: Optional[str] = None,
    max_lbl_len: int = 15,
) -> Panel:
    """
    Render a stacked bar chart
    """
    # pylint: disable=too-many-arguments,too-many-locals
    title = _make_title(grp_cnt_stats, x, y)
    if not timeunit:
        if grp_cnt_stats[f"{x}_shw"] > 30:
            plot_width = 32 * grp_cnt_stats[f"{x}_shw"]
    else:
        if len(df) > 30:
            plot_width = 32 * len(df)

    fig = figure(
        x_range=list(df.index),
        toolbar_location=None,
        title=title,
        tools=[],
        plot_width=plot_width,
        plot_height=plot_height,
    )
    grps = list(df.columns)
    palette = Pastel1[9] * (len(grps) // len(Pastel1) + 1)
    if "Others" in grps:
        colours = palette[0:len(grps) - 1] + ("#636363", )
    else:
        colours = palette[0:len(grps)]
    source = ColumnDataSource(data=df)
    renderers = fig.vbar_stack(
        stackers=grps,
        x="index",
        width=0.9,
        source=source,
        line_width=1,
        color=colours,
    )
    grps = [
        (grp[:(max_lbl_len - 1)] + "...") if len(grp) > max_lbl_len else grp
        for grp in grps
    ]
    legend_it = [(grp, [rend]) for grp, rend in zip(grps, renderers)]
    legend = Legend(items=legend_it)
    legend.label_text_font_size = "8pt"
    fig.add_layout(legend, "right")
    if not timeunit:
        tooltips = [("Group", "@index, $name"),
                    ("Percentage", "@$name{0.2f}%")]
        fig.add_tools(HoverTool(tooltips=tooltips))
        fig.yaxis.axis_label = "Percent"
    else:
        # below is for having percent and count in the tooltip
        formatter = CustomJSHover(
            args=dict(source=source),
            code="""
            const columns = Object.keys(source.data)
            const cur_bar = special_vars.data_x - 0.5
            var ttl_bar = 0
            for (let i = 0; i < columns.length; i++) {
                if (columns[i] != 'index'){
                    ttl_bar = ttl_bar + source.data[columns[i]][cur_bar]
                }
            }
            const cur_val = source.data[special_vars.name][cur_bar]
            return (cur_val/ttl_bar * 100).toFixed(2)+'%';
        """,
        )
        for rend in renderers:
            hover = HoverTool(
                tooltips=[
                    (y, "$name"),
                    (timeunit, "@index"),
                    ("Count", "@$name"),
                    ("Percent", "@{%s}{custom}" % rend.name),
                ],
                formatters={"@{%s}" % rend.name: formatter},
                renderers=[rend],
            )
            fig.add_tools(hover)
        fig.yaxis.axis_label = "Count"
        _format_axis(fig, 0, df.sum(axis=1).max(), "y")
        fig.xaxis.axis_label = x
        if timeunit == "Week of":
            fig.xaxis.axis_label = x + ", the week of"

    tweak_figure(fig, "stacked")

    return Panel(child=fig, title="stacked bar chart")
Exemple #21
0
def render_bar_chart(
    data: Tuple[np.ndarray, np.ndarray, np.ndarray],
    yscale: str,
    plot_width: int,
    plot_height: int,
) -> Figure:
    """
    Render a bar chart for the missing and present values
    """
    pres_cnts, null_cnts, cols = data
    df = pd.DataFrame({"Present": pres_cnts, "Missing": null_cnts}, index=cols)

    if len(df) > 20:
        plot_width = 28 * len(df)

    fig = Figure(
        x_range=list(df.index),
        y_range=[0, df["Present"][0] + df["Missing"][0]],
        plot_width=plot_width,
        plot_height=plot_height,
        y_axis_type=yscale,
        toolbar_location=None,
        tools=[],
        title=" ",
    )

    rend = fig.vbar_stack(
        stackers=df.columns,
        x="index",
        width=0.9,
        color=[CATEGORY20[0], CATEGORY20[2]],
        source=df,
        legend_label=list(df.columns),
    )

    # hover tool with count and percent
    formatter = CustomJSHover(
        args=dict(source=ColumnDataSource(df)),
        code="""
        const columns = Object.keys(source.data)
        const cur_bar = special_vars.data_x - 0.5
        var ttl_bar = 0
        for (let i = 0; i < columns.length; i++) {
            if (columns[i] != 'index'){
                ttl_bar = ttl_bar + source.data[columns[i]][cur_bar]
            }
        }
        const cur_val = source.data[special_vars.name][cur_bar]
        return (cur_val/ttl_bar * 100).toFixed(2)+'%';
    """,
    )
    for i, val in enumerate(df.columns):
        hover = HoverTool(
            tooltips=[
                ("Column", "@index"),
                (f"{val} count", "@$name"),
                (f"{val} percent", "@{%s}{custom}" % rend[i].name),
            ],
            formatters={"@{%s}" % rend[i].name: formatter},
            renderers=[rend[i]],
        )
        fig.add_tools(hover)

    fig.yaxis.axis_label = "Row Count"
    tweak_figure(fig)
    relocate_legend(fig, "left")
    fig.frame_width = plot_width

    return fig