Python bokeh.models.Range1d() Examples

The following are 30 code examples of bokeh.models.Range1d(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module bokeh.models , or try the search function .
Example #1
Source File: testoverlayplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def test_points_errorbars_text_ndoverlay_categorical_xaxis(self):
        overlay = NdOverlay({i: Points(([chr(65+i)]*10,np.random.randn(10)))
                             for i in range(5)})
        error = ErrorBars([(el['x'][0], np.mean(el['y']), np.std(el['y']))
                           for el in overlay])
        text = Text('C', 0, 'Test')
        plot = bokeh_renderer.get_plot(overlay*error*text)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, FactorRange)
        factors = ['A', 'B', 'C', 'D', 'E']
        self.assertEqual(x_range.factors, ['A', 'B', 'C', 'D', 'E'])
        self.assertIsInstance(y_range, Range1d)
        error_plot = plot.subplots[('ErrorBars', 'I')]
        for xs, factor in zip(error_plot.handles['source'].data['base'], factors):
            self.assertEqual(factor, xs) 
Example #2
Source File: domain.py    From memex-explorer with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def create(self):
        self.source = self.update_source()

        max_data = max(max(self.source.data['relevant']), max(self.source.data['crawled']))
        xdr = Range1d(start=0, end=max_data)

        p = figure(plot_width=400, plot_height=400,
                   title="Domains Sorted by %s" % self.sort, x_range = xdr,
                   y_range = FactorRange(factors=self.source.data['domain']),
                   tools='reset, resize, save')

        p.rect(y='domain', x='crawled_half', width="crawled", height=0.75,
               color=DARK_GRAY, source =self.source, legend="crawled")
        p.rect(y='domain', x='relevant_half', width="relevant", height=0.75,
               color=GREEN, source =self.source, legend="relevant")

        p.ygrid.grid_line_color = None
        p.xgrid.grid_line_color = '#8592A0'
        p.axis.major_label_text_font_size = "8pt"

        script, div = components(p)

        if os.path.exists(self.crawled_data) and os.path.exists(self.relevant_data):
            return (script, div) 
Example #3
Source File: utils.py    From choochoo with GNU General Public License v2.0 5 votes vote down vote up
def make_range(column, lo=None, hi=None):
    column = column.dropna()
    mn, mx = column.min() if lo is None else lo, column.max() if hi is None else hi
    delta = mx - mn
    return Range1d(start=mn - 0.1 * delta, end=mx + 0.1 * delta) 
Example #4
Source File: visualization.py    From minian with GNU General Public License v3.0 5 votes vote down vote up
def _twinx(self, plot, element):
        # Setting the second y axis range name and range
        start, end = (element.range(1))
        label = element.dimensions()[1].pprint_label
        plot.state.extra_y_ranges = {"foo": Range1d(start=start, end=end)}
        # Adding the second axis to the plot.
        linaxis = LinearAxis(axis_label=label, y_range_name='foo')
        plot.state.add_layout(linaxis, 'right') 
Example #5
Source File: testheatmapplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_heatmap_points_categorical_axes_string_int_inverted(self):
        hmap = HeatMap([('A',1, 1), ('B', 2, 2)]).opts(invert_axes=True)
        points = Points([('A', 2), ('B', 1),  ('C', 3)])
        plot = bokeh_renderer.get_plot(hmap*points)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, Range1d)
        self.assertEqual(x_range.start, 0.5)
        self.assertEqual(x_range.end, 3)
        self.assertIsInstance(y_range, FactorRange)
        self.assertEqual(y_range.factors, ['A', 'B', 'C']) 
Example #6
Source File: testheatmapplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_heatmap_points_categorical_axes_string_int(self):
        hmap = HeatMap([('A', 1, 1), ('B', 2, 2)])
        points = Points([('A', 2), ('B', 1),  ('C', 3)])
        plot = bokeh_renderer.get_plot(hmap*points)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, FactorRange)
        self.assertEqual(x_range.factors, ['A', 'B', 'C'])
        self.assertIsInstance(y_range, Range1d)
        self.assertEqual(y_range.start, 0.5)
        self.assertEqual(y_range.end, 3) 
Example #7
Source File: testheatmapplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_heatmap_categorical_axes_string_int_inverted(self):
        hmap = HeatMap([('A',1, 1), ('B', 2, 2)]).opts(invert_axes=True)
        plot = bokeh_renderer.get_plot(hmap)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, Range1d)
        self.assertEqual(x_range.start, 0.5)
        self.assertEqual(x_range.end, 2.5)
        self.assertIsInstance(y_range, FactorRange)
        self.assertEqual(y_range.factors, ['A', 'B']) 
Example #8
Source File: testheatmapplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_heatmap_categorical_axes_string_int(self):
        hmap = HeatMap([('A', 1, 1), ('B', 2, 2)])
        plot = bokeh_renderer.get_plot(hmap)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, FactorRange)
        self.assertEqual(x_range.factors, ['A', 'B'])
        self.assertIsInstance(y_range, Range1d)
        self.assertEqual(y_range.start, 0.5)
        self.assertEqual(y_range.end, 2.5) 
Example #9
Source File: testoverlayplot.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_points_errorbars_text_ndoverlay_categorical_xaxis_invert_axes(self):
        overlay = NdOverlay({i: Points(([chr(65+i)]*10,np.random.randn(10)))
                             for i in range(5)})
        error = ErrorBars([(el['x'][0], np.mean(el['y']), np.std(el['y']))
                           for el in overlay]).opts(plot=dict(invert_axes=True))
        text = Text('C', 0, 'Test')
        plot = bokeh_renderer.get_plot(overlay*error*text)
        x_range = plot.handles['x_range']
        y_range = plot.handles['y_range']
        self.assertIsInstance(x_range, Range1d)
        self.assertIsInstance(y_range, FactorRange)
        self.assertEqual(y_range.factors, ['A', 'B', 'C', 'D', 'E']) 
Example #10
Source File: testcallbacks.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_server_callback_resolve_attr_spec_range1d_end(self):
        range1d = Range1d(start=0, end=10)
        msg = Callback.resolve_attr_spec('x_range.attributes.end', range1d)
        self.assertEqual(msg, {'id': range1d.ref['id'], 'value': 10}) 
Example #11
Source File: testcallbacks.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_server_callback_resolve_attr_spec_range1d_start(self):
        range1d = Range1d(start=0, end=10)
        msg = Callback.resolve_attr_spec('x_range.attributes.start', range1d)
        self.assertEqual(msg, {'id': range1d.ref['id'], 'value': 0}) 
Example #12
Source File: gui.py    From pysdr with GNU General Public License v3.0 5 votes vote down vote up
def utilization_bar(max_y):
    plot = Figure(plot_width = 150, # this is more for the ratio, because we have auto-width scaling
                  plot_height = 150,
                  tools = [], # no tools needed for this one
                  title = 'Utilization')
    plot.toolbar.logo = None  # hides logo
    plot.x_range = Range1d(0, 1) 
    plot.y_range = Range1d(0, max_y)  # sometimes you want it to be way less than 1, to see it move
    plot.xaxis.visible = False # hide x axis
    # Add input buffer
    manager = Manager()
    plot._input_buffer = manager.dict()
    return plot 
Example #13
Source File: stream.py    From memex-explorer with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def init_plot(crawl_name):
    session = Session()
    document = Document()
    session.use_doc(crawl_name)
    session.load_document(document)

    if document.context.children:
        plot = document.context.children[0]
    else:
        output_server(crawl_name)
        # TODO: Remove these when Bokeh is upgraded
        # placeholders or Bokeh can't inject properly
        current = np.datetime64(datetime.now())
        xdr = Range1d(current, current + 1)
        ydr = ["urls"]

        # styling suggested by Bryan
        plot = figure(title="Crawler Monitor", tools="hover",
                      x_axis_type="datetime", y_axis_location="right", x_range=xdr, y_range=ydr,
                      width=1200, height=600)
        plot.toolbar_location = None
        plot.xgrid.grid_line_color = None

        # temporarily turn these off
        plot.ygrid.grid_line_color = None
        plot.xaxis.minor_tick_line_color = None
        plot.xaxis.major_tick_line_color = None
        plot.xaxis.major_label_text_font_size = '0pt'
        plot.yaxis.minor_tick_line_color = None
        plot.yaxis.major_tick_line_color = None
        plot.yaxis.major_label_text_font_size = '0pt'

    document.add(plot)
    session.store_document(document)
    script = autoload_server(plot, session)

    #TODO: Looks like a Bokeh bug, probably not repeatable with current code
    script = script.replace("'modelid': u'", "'modelid': '")
    return script 
Example #14
Source File: figure.py    From neon with Apache License 2.0 5 votes vote down vote up
def deconv_figs(layer_name, layer_data, fm_max=8, plot_size=120):
    """
    Helper function to generate deconv visualization figures

    Arguments:
        layer_name (str): Layer name
        layer_data (list): Layer data to plot
        fm_max (int): Max layers to process
        plot_size (int, optional): Plot size

    Returns:
        tuple if vis_keys, img_keys, fig_dict
    """
    vis_keys = dict()
    img_keys = dict()
    fig_dict = dict()

    for fm_num, (fm_name, deconv_data, img_data) in enumerate(layer_data):

        if fm_num >= fm_max:
            break

        img_h, img_w = img_data.shape
        x_range = Range1d(start=0, end=img_w)
        y_range = Range1d(start=0, end=img_h)
        img_fig = image_fig(img_data, img_h, img_w, x_range, y_range, plot_size)
        deconv_fig = image_fig(deconv_data, img_h, img_w, x_range, y_range, plot_size)

        title = "{}_fmap_{:04d}".format(layer_name, fm_num)
        vis_keys[fm_num] = "vis_" + title
        img_keys[fm_num] = "img_" + title

        fig_dict[vis_keys[fm_num]] = deconv_fig
        fig_dict[img_keys[fm_num]] = img_fig

    return vis_keys, img_keys, fig_dict 
Example #15
Source File: __init__.py    From marconibot with GNU General Public License v3.0 5 votes vote down vote up
def plotVolume(p, df, plotwidth=800, upcolor='green',
               downcolor='red', colname='volume'):
    candleWidth = (df.iloc[2]['date'].timestamp() -
                   df.iloc[1]['date'].timestamp()) * plotwidth
    # create new y axis for volume
    p.extra_y_ranges = {colname: Range1d(start=min(df[colname].values),
                                         end=max(df[colname].values))}
    p.add_layout(LinearAxis(y_range_name=colname), 'right')
    # Plot green candles
    inc = df.close > df.open
    p.vbar(x=df.date[inc],
           width=candleWidth,
           top=df[colname][inc],
           bottom=0,
           alpha=0.1,
           fill_color=upcolor,
           line_color=upcolor,
           y_range_name=colname)

    # Plot red candles
    dec = df.open > df.close
    p.vbar(x=df.date[dec],
           width=candleWidth,
           top=df[colname][dec],
           bottom=0,
           alpha=0.1,
           fill_color=downcolor,
           line_color=downcolor,
           y_range_name=colname) 
Example #16
Source File: __init__.py    From marconibot with GNU General Public License v3.0 5 votes vote down vote up
def plotCCI(p, df, plotwidth=800, upcolor='orange', downcolor='yellow'):
    # create y axis for rsi
    p.extra_y_ranges = {"cci": Range1d(start=min(df['cci'].values),
                                       end=max(df['cci'].values))}
    p.add_layout(LinearAxis(y_range_name="cci"), 'right')
    candleWidth = (df.iloc[2]['date'].timestamp() -
                   df.iloc[1]['date'].timestamp()) * plotwidth
    # plot green bars
    inc = df.cci >= 0
    p.vbar(x=df.date[inc],
           width=candleWidth,
           top=df.cci[inc],
           bottom=0,
           fill_color=upcolor,
           line_color=upcolor,
           alpha=0.5,
           y_range_name="cci",
           legend='cci')
    # Plot red bars
    dec = df.cci < 0
    p.vbar(x=df.date[dec],
           width=candleWidth,
           top=0,
           bottom=df.cci[dec],
           fill_color=downcolor,
           line_color=downcolor,
           alpha=0.5,
           y_range_name="cci",
           legend='cci') 
Example #17
Source File: viz2.py    From scipy2015-blaze-bokeh with MIT License 5 votes vote down vote up
def legend():
    # Set ranges
    xdr = Range1d(0, 100)
    ydr = Range1d(0, 500)
    # Create plot
    plot = Plot(
        x_range=xdr,
        y_range=ydr,
        title="",
        plot_width=100,
        plot_height=500,
        min_border=0,
        toolbar_location=None,
        outline_line_color="#FFFFFF",
    )

    # For each color in your palette, add a Rect glyph to the plot with the appropriate properties
    palette = RdBu11
    width = 40
    for i, color in enumerate(palette):
        rect = Rect(
            x=40, y=(width * (i + 1)),
            width=width, height=40,
            fill_color=color, line_color='black'
        )
        plot.add_glyph(rect)

    # Add text labels and add them to the plot
    minimum = Text(x=50, y=0, text=['-6 ºC'])
    plot.add_glyph(minimum)
    maximum = Text(x=50, y=460, text=['6 ºC'])
    plot.add_glyph(maximum)

    return plot 
Example #18
Source File: viz.py    From scipy2015-blaze-bokeh with MIT License 5 votes vote down vote up
def legend():
    # Set ranges
    xdr = Range1d(0, 100)
    ydr = Range1d(0, 500)
    # Create plot
    plot = Plot(
        x_range=xdr,
        y_range=ydr,
        title="",
        plot_width=100,
        plot_height=500,
        min_border=0,
        toolbar_location=None,
        outline_line_color="#FFFFFF",
    )

    # For each color in your palette, add a Rect glyph to the plot with the appropriate properties
    palette = RdBu11
    width = 40
    for i, color in enumerate(palette):
        rect = Rect(
            x=40, y=(width * (i + 1)),
            width=width, height=40,
            fill_color=color, line_color='black'
        )
        plot.add_glyph(rect)

    # Add text labels and add them to the plot
    minimum = Text(x=50, y=0, text=['-6 ºC'])
    plot.add_glyph(minimum)
    maximum = Text(x=50, y=460, text=['6 ºC'])
    plot.add_glyph(maximum)

    return plot 
Example #19
Source File: viz2.py    From scipy2015-blaze-bokeh with MIT License 5 votes vote down vote up
def legend():
    # Set ranges
    xdr = Range1d(0, 100)
    ydr = Range1d(0, 500)
    # Create plot
    plot = Plot(
        x_range=xdr,
        y_range=ydr,
        title="",
        plot_width=100,
        plot_height=500,
        min_border=0,
        toolbar_location=None,
        outline_line_color="#FFFFFF",
    )

    # For each color in your palette, add a Rect glyph to the plot with the appropriate properties
    palette = RdBu11
    width = 40
    for i, color in enumerate(palette):
        rect = Rect(
            x=40, y=(width * (i + 1)),
            width=width, height=40,
            fill_color=color, line_color='black'
        )
        plot.add_glyph(rect)

    # Add text labels and add them to the plot
    minimum = Text(x=50, y=0, text=['-6 ºC'])
    plot.add_glyph(minimum)
    maximum = Text(x=50, y=460, text=['6 ºC'])
    plot.add_glyph(maximum)

    return plot 
Example #20
Source File: main.py    From REINVENT with MIT License 5 votes vote down vote up
def create_bar_plot(init_data, title):
    init_data = downsample(init_data, 50)
    x = range(len(init_data))
    source = ColumnDataSource(data=dict(x= [], y=[]))
    fig = figure(title=title, plot_width=300, plot_height=300)
    fig.vbar(x=x, width=1, top=init_data, fill_alpha=0.05)
    fig.vbar('x', width=1, top='y', fill_alpha=0.3, source=source)
    fig.y_range = Range1d(min(0, 1.2 * min(init_data)), 1.2 * max(init_data))
    return fig, source 
Example #21
Source File: whisker_quantiles.py    From CAVE with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def whisker_quantiles(data):
    """
    Data is expected as a dictionary {budget : {parameter : {folder : importance }}}
    """
    hyperparameters = []
    for hp2folders in data.values():
        for hp in hp2folders.keys():
            if not hp in hyperparameters:
                hyperparameters.append(hp)

    # Bokeh plot
    colors = itertools.cycle(d3['Category10'][10])

    # Create data to plot the error-bars (whiskers)
    whiskers_data = {}
    for budget in data.keys():
        whiskers_data.update({'base_' + str(budget): [], 'lower_' + str(budget): [], 'upper_' + str(budget): []})

    # Generate whiskers data in bokeh-ColumnDataSource
    for (budget, imp_dict) in data.items():
        for p, imp in imp_dict.items():
            mean = np.nanmean(np.array(list(imp.values())))
            std = np.nanstd(np.array(list(imp.values())))
            if not np.isnan(mean) and not np.isnan(std):
                whiskers_data['lower_' + str(budget)].append(mean - std)
                whiskers_data['upper_' + str(budget)].append(mean + std)
                whiskers_data['base_' + str(budget)].append(p)
    whiskers_datasource = ColumnDataSource(whiskers_data)

    plot = figure(x_range=FactorRange(factors=hyperparameters, bounds='auto'),
                  y_range=Range1d(0, 1, bounds='auto'),
                  plot_width=800, plot_height=300,
                  )
    dodgies = np.linspace(-0.25, 0.25, len(data)) if len(data) > 1 else [0]  # No dodge if only one budget
    # Plot
    for (budget, imp_dict), d, color in zip(data.items(), dodgies, colors):
        for p, imp in imp_dict.items():
            for i in imp.values():
                if np.isnan(i):
                    continue
                plot.circle(x=[(p, d)], y=[i], color=color, fill_alpha=0.4,
                            legend="Budget %s" % str(budget) if len(data) > 1 else '')

        if not 'base_' + str(budget) in whiskers_data:
            continue
        plot.add_layout(Whisker(source=whiskers_datasource,
                                base=dodge('base_' + str(budget), d, plot.x_range),
                                lower='lower_' + str(budget),
                                upper='upper_' + str(budget),
                                line_color=color))
    plot.yaxis.axis_label = "Importance"

    return plot 
Example #22
Source File: cost_over_time.py    From CAVE with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def _get_avg(self, validator, runs, rh):
        # If there is more than one run, we average over the runs
        means, times = [], []
        for run in runs:
            # Ignore variances as we plot variance over runs
            mean, _, time, _ = self._get_mean_var_time(validator, run.trajectory, not run.validated_runhistory, rh)
            means.append(mean.flatten())
            times.append(time)
        all_times = np.array(sorted([a for b in times for a in b]))  # flatten times
        means = np.array(means)
        times = np.array(times)
        at = [0 for _ in runs]      # keep track at which timestep each trajectory is
        m = [np.nan for _ in runs]  # used to compute the mean over the timesteps
        mean  = np.ones((len(all_times), 1)) * -1
        var, upper, lower = np.copy(mean), np.copy(mean), np.copy(mean)
        for time_idx, t in enumerate(all_times):
            for traj_idx, entry_idx in enumerate(at):
                try:
                    if t == times[traj_idx][entry_idx]:
                        m[traj_idx] = means[traj_idx][entry_idx]
                        at[traj_idx] += 1
                except IndexError:
                    pass  # Reached the end of one trajectory. No need to check it further
            # var[time_idx][0] = np.nanvar(m)
            u, l, m_ = np.nanpercentile(m, 75), np.nanpercentile(m, 25), np.nanpercentile(m, 50)
            # self.logger.debug((mean[time_idx][0] + np.sqrt(var[time_idx][0]), mean[time_idx][0],
            #                    mean[time_idx][0] - np.sqrt(var[time_idx][0])))
            # self.logger.debug((l, m_, u))
            upper[time_idx][0] = u
            mean[time_idx][0] = m_
            lower[time_idx][0] = l

        mean = mean[:, 0]
        upper = upper[:, 0]
        lower = lower[:, 0]

        # Determine clipping point for y-axis from lowest legal value
        clip_y_lower = False
        if self.scenario.run_obj == 'runtime':  # y-axis on log -> clip plot
            clip_y_lower = min(list(lower[lower > 0]) + list(mean)) * 0.8
            lower[lower <= 0] = clip_y_lower * 0.9
        #if clip_y_lower:
        #    p.y_range = Range1d(clip_y_lower, 1.2 * max(upper))

        return Line('average', all_times, mean, upper, lower, [None for _ in range(len(mean))]) 
Example #23
Source File: showMatLabFig._spatioTemporal.py    From python-urbanPlanning with MIT License 4 votes vote down vote up
def interactiveG(G):
    from bokeh.models.graphs import NodesAndLinkedEdges,from_networkx
    from bokeh.models import Circle, HoverTool, MultiLine,Plot,Range1d,StaticLayoutProvider
    from bokeh.plotting import figure, output_file, show, ColumnDataSource
    from bokeh.io import output_notebook, show
    output_notebook()
    # We could use figure here but don't want all the axes and titles  
    #plot=Plot(plot_width=1600, plot_height=300, tooltips=TOOLTIPS,title="PHmi+landmarks+route+power(10,-5)",x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
    
    output_file("PHMI_network")
    source=ColumnDataSource(data=dict(
        x=locations[0].tolist(),
        #x=[idx for idx in range(len(PHMIList))],
        #y=locations[1].tolist(),
        y=PHMIList,
        #desc=[str(i) for i in PHMIList],
        #PHMI_value=PHMI_dic[0][0].tolist(),    
    ))
    TOOLTIPS=[
        ("index", "$index"),
        ("(x,y)", "($x, $y)"),
        #("desc", "@desc"),
        #("PHMI", "$PHMI_value"),
    ]
    
    
    plot=figure(x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1),plot_width=2200, plot_height=500,tooltips=TOOLTIPS,title="PHMI_network")
    
    #G_position={key:(G.position[key][1],G.position[key][0]) for key in G.position.keys()}
    graph = from_networkx(G,nx.spring_layout,scale=1, center=(0,0))  
    #plot.renderers.append(graph) 
    
    fixed_layout_provider = StaticLayoutProvider(graph_layout=G.position)
    graph.layout_provider = fixed_layout_provider
    plot.renderers.append(graph)
    
    # Blue circles for nodes, and light grey lines for edges  
    graph.node_renderer.glyph = Circle(size=5, fill_color='#2b83ba')  
    graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=2)  
      
    # green hover for both nodes and edges  
    graph.node_renderer.hover_glyph = Circle(size=25, fill_color='#abdda4')  
    graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=4)  
      
    # When we hover over nodes, highlight adjecent edges too  
    graph.inspection_policy = NodesAndLinkedEdges()  
      
    plot.add_tools(HoverTool(tooltips=None))  
     
    colors=('aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen')
    ScalePhmi=math.pow(10,1)
    i=0
    for val,idx in zip(phmi_breakPtsNeg, plot_x):
        plot.line(idx,np.array(val)*ScalePhmi,line_color=colors[i])
        i+=1    
        
    show(plot)
    
#06-single landmarks pattern 无人车位置点与对应landmarks栅格图
#convert location and corresponding landmarks to raster data format using numpy.histogram2d 
Example #24
Source File: driverlessCityProject_spatialPointsPattern_association_basic.py    From python-urbanPlanning with MIT License 4 votes vote down vote up
def interactiveG(G):
    from bokeh.models.graphs import NodesAndLinkedEdges,from_networkx
    from bokeh.models import Circle, HoverTool, MultiLine,Plot,Range1d,StaticLayoutProvider
    from bokeh.plotting import figure, output_file, show, ColumnDataSource
    from bokeh.io import output_notebook, show
    output_notebook()
    # We could use figure here but don't want all the axes and titles  
    #plot=Plot(plot_width=1600, plot_height=300, tooltips=TOOLTIPS,title="PHmi+landmarks+route+power(10,-5)",x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
    
    output_file("PHMI_network")
    source=ColumnDataSource(data=dict(
        x=locations[0].tolist(),
        #x=[idx for idx in range(len(PHMIList))],
        #y=locations[1].tolist(),
        y=PHMIList,
        #desc=[str(i) for i in PHMIList],
        #PHMI_value=PHMI_dic[0][0].tolist(),    
    ))
    TOOLTIPS=[
        ("index", "$index"),
        ("(x,y)", "($x, $y)"),
        #("desc", "@desc"),
        #("PHMI", "$PHMI_value"),
    ]
    
    
    plot=figure(x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1),plot_width=2200, plot_height=500,tooltips=TOOLTIPS,title="PHMI_network")
    
    #G_position={key:(G.position[key][1],G.position[key][0]) for key in G.position.keys()}
    graph = from_networkx(G,nx.spring_layout,scale=1, center=(0,0))  
    #plot.renderers.append(graph) 
    
    fixed_layout_provider = StaticLayoutProvider(graph_layout=G.position)
    graph.layout_provider = fixed_layout_provider
    plot.renderers.append(graph)
    
    # Blue circles for nodes, and light grey lines for edges  
    graph.node_renderer.glyph = Circle(size=5, fill_color='#2b83ba')  
    graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=2)  
      
    # green hover for both nodes and edges  
    graph.node_renderer.hover_glyph = Circle(size=25, fill_color='#abdda4')  
    graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=4)  
      
    # When we hover over nodes, highlight adjecent edges too  
    graph.inspection_policy = NodesAndLinkedEdges()  
      
    plot.add_tools(HoverTool(tooltips=None))  
     
    colors=('aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen')
    ScalePhmi=math.pow(10,1)
    i=0
    for val,idx in zip(phmi_breakPtsNeg, plot_x):
        plot.line(idx,np.array(val)*ScalePhmi,line_color=colors[i])
        i+=1    
        
    show(plot)
    
#05-single landmarks pattern 无人车位置点与对应landmarks栅格图
#convert location and corresponding landmarks to raster data format using numpy.histogram2d 
Example #25
Source File: driverlessCityProject_spatialPointsPattern_association_basic.py    From python-urbanPlanning with MIT License 4 votes vote down vote up
def interactiveG(G):
    from bokeh.models.graphs import NodesAndLinkedEdges,from_networkx
    from bokeh.models import Circle, HoverTool, MultiLine,Plot,Range1d,StaticLayoutProvider
    from bokeh.plotting import figure, output_file, show, ColumnDataSource
    from bokeh.io import output_notebook, show
    output_notebook()
    # We could use figure here but don't want all the axes and titles  
    #plot=Plot(plot_width=1600, plot_height=300, tooltips=TOOLTIPS,title="PHmi+landmarks+route+power(10,-5)",x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
    
    output_file("PHMI_network")
    source=ColumnDataSource(data=dict(
        x=locations[0].tolist(),
        #x=[idx for idx in range(len(PHMIList))],
        #y=locations[1].tolist(),
        y=PHMIList,
        #desc=[str(i) for i in PHMIList],
        #PHMI_value=PHMI_dic[0][0].tolist(),    
    ))
    TOOLTIPS=[
        ("index", "$index"),
        ("(x,y)", "($x, $y)"),
        #("desc", "@desc"),
        #("PHMI", "$PHMI_value"),
    ]
    
    
    plot=figure(x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1),plot_width=2200, plot_height=500,tooltips=TOOLTIPS,title="PHMI_network")
    
    #G_position={key:(G.position[key][1],G.position[key][0]) for key in G.position.keys()}
    graph = from_networkx(G,nx.spring_layout,scale=1, center=(0,0))  
    #plot.renderers.append(graph) 
    
    fixed_layout_provider = StaticLayoutProvider(graph_layout=G.position)
    graph.layout_provider = fixed_layout_provider
    plot.renderers.append(graph)
    
    # Blue circles for nodes, and light grey lines for edges  
    graph.node_renderer.glyph = Circle(size=5, fill_color='#2b83ba')  
    graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=2)  
      
    # green hover for both nodes and edges  
    graph.node_renderer.hover_glyph = Circle(size=25, fill_color='#abdda4')  
    graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=4)  
      
    # When we hover over nodes, highlight adjecent edges too  
    graph.inspection_policy = NodesAndLinkedEdges()  
      
    plot.add_tools(HoverTool(tooltips=None))  
     
    colors=('aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen')
    ScalePhmi=math.pow(10,1)
    i=0
    for val,idx in zip(phmi_breakPtsNeg, plot_x):
        plot.line(idx,np.array(val)*ScalePhmi,line_color=colors[i])
        i+=1    
        
    show(plot)
    
#05-single landmarks pattern 无人车位置点与对应landmarks栅格图
#convert location and corresponding landmarks to raster data format using numpy.histogram2d 
Example #26
Source File: gui.py    From pysdr with GNU General Public License v3.0 4 votes vote down vote up
def base_plot(x_label, y_label, title, **kwargs):
    
    # This allows disabling of horizontal zooming, which gets annoying in most dsp plots
    # e.g. usage: fft_plot = pysdr.base_plot('Freq', 'PSD', 'Frequency', disable_horizontal_zooming=True)
    if 'disable_horizontal_zooming' in kwargs and kwargs['disable_horizontal_zooming']: # if it's specified and is set True
        tools = [WheelZoomTool(dimensions='height')]
    else:
        tools = [WheelZoomTool()]

    # Similar to above, except disable all zooming, perfect for waterfall plots
    if 'disable_all_zooming' in kwargs and kwargs['disable_all_zooming']: # if it's specified and is set True
        tools = [] # removes the WheelZoomTool we just added above
    
    if 'plot_height' in kwargs:
        plot_height = kwargs['plot_height']
    else:
        plot_height = 200
    
    # Create the Bokeh figure
    plot = Figure(plot_width = 300, # this is more for the ratio, because we have auto-width scaling
                  plot_height = plot_height,
                  y_axis_label = y_label,
                  x_axis_label = x_label,
                  tools = tools + [BoxZoomTool(), ResetTool(), SaveTool()], # all the other tools we want- reference http://bokeh.pydata.org/en/0.10.0/docs/reference/models/tools.html
                  title = title)  # use min_border=30 to add padding between plots, if we ever want it
    
    # sets wheel zoom active by default (tools[0] is the wheelzoom), unless zooming was disabled
    if 'disable_all_zooming' not in kwargs:
        plot.toolbar.active_scroll = plot.toolbar.tools[0] 
    
    # hides stupid bokeh logo
    plot.toolbar.logo = None 
    
    # add more intuitive functions to set x and y ranges
    def _set_x_range(min_x, max_x): # without the underscore it wont work, bokeh/core/has_props.py overloads __setattr__ to intercept attribute setting that is not private
        plot.x_range = Range1d(min_x, max_x)
    def _set_y_range(min_y, max_y):
        plot.y_range = Range1d(min_y, max_y)
    plot._set_x_range = _set_x_range # add functions to object
    plot._set_y_range = _set_y_range
    
    # Add input buffer
    manager = Manager()
    plot._input_buffer = manager.dict()

    # return the bokeh figure object
    return plot  



# The idea behind this utilization bar is to have an "included by default" widget to show
#    how well the process_samples is keeping up with the incoming samples, in a realtime manner 
Example #27
Source File: bokeh_timeline.py    From pyglet with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def make_plot(info, outfile):
    # prepare some data
    (wall_times, pyglet_times, audio_times,
     current_times, frame_nums, rescheds,
     x_vnones, y_vnones,
     x_anones, y_anones) = info

    # output to static HTML file
    output_file(outfile)

    # main plot
    p = figure(
       tools="pan,wheel_zoom,reset,save",
       y_axis_type="linear", y_range=[0.000, wall_times[-1]], title="timeline",
       x_axis_label='wall_time', y_axis_label='time',
       plot_width=600, plot_height=600
    )

    # add some renderers
    p.line(wall_times, wall_times, legend="wall_time")
    #p.line(wall_times, pyglet_times, legend="pyglet_time", line_width=3)
    p.line(wall_times, current_times, legend="current_times", line_color="red")
    p.line(wall_times, audio_times, legend="audio_times", line_color="orange", line_dash="4 4")

    p.circle(x_vnones, y_vnones, legend="current time nones", fill_color="green", size=8)
    p.circle(x_anones, y_anones, legend="audio time nones", fill_color="red", size=6)

    # secondary y-axis for frame_num
    p.extra_y_ranges = {"frame_num": Range1d(start=0, end=frame_nums[-1])}
    p.line(wall_times, frame_nums, legend="frame_num",
           line_color="black", y_range_name="frame_num")
    p.add_layout(LinearAxis(y_range_name="frame_num", axis_label="frame num"), 'left')

    p.legend.location = "bottom_right"
    # show the results
    #show(p)

    # secondary plot for rescheduling times
    q = figure(
       tools="pan,wheel_zoom,reset,save",
       y_axis_type="linear", y_range=[-0.3, 0.3], title="rescheduling time",
       x_axis_label='wall_time', y_axis_label='rescheduling time',
       plot_width=600, plot_height=150
    )
    q.line(wall_times, rescheds)

    show(column(p, q)) 
Example #28
Source File: interact_bls.py    From lightkurve with MIT License 4 votes vote down vote up
def make_lightcurve_figure_elements(lc, model_lc, lc_source, model_lc_source, help_source):
    """Make a figure with a simple light curve scatter and model light curve line.

    Parameters
    ----------
    lc : lightkurve.LightCurve
        Light curve to plot
    model_lc :  lightkurve.LightCurve
        Model light curve to plot
    lc_source : bokeh.plotting.ColumnDataSource
        Bokeh style source object for plotting light curve
    model_lc_source : bokeh.plotting.ColumnDataSource
        Bokeh style source object for plotting model light curve
    help_source : bokeh.plotting.ColumnDataSource
        Bokeh style source object for rendering help button

    Returns
    -------
    fig : bokeh.plotting.figure
        Bokeh figure object
    """
    # Make figure
    fig = figure(title='Light Curve', plot_height=300, plot_width=900,
                 tools="pan,box_zoom,reset",
                 toolbar_location="below",
                 border_fill_color="#FFFFFF", active_drag="box_zoom")
    fig.title.offset = -10
    fig.yaxis.axis_label = 'Flux (e/s)'
    if lc.time.format == 'bkjd':
        fig.xaxis.axis_label = 'Time - 2454833 (days)'
    elif lc.time.format == 'btjd':
        fig.xaxis.axis_label = 'Time - 2457000 (days)'
    else:
        fig.xaxis.axis_label = 'Time (days)'
    ylims = [np.nanmin(lc.flux.value), np.nanmax(lc.flux.value)]
    fig.y_range = Range1d(start=ylims[0], end=ylims[1])

    # Add light curve
    fig.circle('time', 'flux', line_width=1, color='#191919',
               source=lc_source, nonselection_line_color='#191919', size=0.5,
               nonselection_line_alpha=1.0)
    # Add model
    fig.step('time', 'flux', line_width=1, color='firebrick',
             source=model_lc_source, nonselection_line_color='firebrick',
             nonselection_line_alpha=1.0)

    # Help button
    question_mark = Text(x="time", y="flux", text="helpme", text_color="grey",
                         text_align='center', text_baseline="middle",
                         text_font_size='12px', text_font_style='bold',
                         text_alpha=0.6)
    fig.add_glyph(help_source, question_mark)
    help = fig.circle('time', 'flux', alpha=0.0, size=15, source=help_source,
                      line_width=2, line_color='grey', line_alpha=0.6)
    tooltips = help_source.data['help'][0]
    fig.add_tools(HoverTool(tooltips=tooltips, renderers=[help],
                            mode='mouse', point_policy="snap_to_data"))
    return fig 
Example #29
Source File: __init__.py    From marconibot with GNU General Public License v3.0 4 votes vote down vote up
def plotRSI(p, df, plotwidth=800, upcolor='green',
            downcolor='red', yloc='right', limits=(30, 70)):
    # create y axis for rsi
    p.extra_y_ranges = {"rsi": Range1d(start=0, end=100)}
    p.add_layout(LinearAxis(y_range_name="rsi"), yloc)

    p.add_layout(Span(location=limits[0],
                      dimension='width',
                      line_color=upcolor,
                      line_dash='dashed',
                      line_width=2,
                      y_range_name="rsi"))

    p.add_layout(Span(location=limits[1],
                      dimension='width',
                      line_color=downcolor,
                      line_dash='dashed',
                      line_width=2,
                      y_range_name="rsi"))

    candleWidth = (df.iloc[2]['date'].timestamp() -
                   df.iloc[1]['date'].timestamp()) * plotwidth
    # plot green bars
    inc = df.rsi >= 50
    p.vbar(x=df.date[inc],
           width=candleWidth,
           top=df.rsi[inc],
           bottom=50,
           fill_color=upcolor,
           line_color=upcolor,
           alpha=0.5,
           y_range_name="rsi")
    # Plot red bars
    dec = df.rsi <= 50
    p.vbar(x=df.date[dec],
           width=candleWidth,
           top=50,
           bottom=df.rsi[dec],
           fill_color=downcolor,
           line_color=downcolor,
           alpha=0.5,
           y_range_name="rsi") 
Example #30
Source File: plot.py    From arlpy with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def freqz(b, a=1, fs=2.0, worN=None, whole=False, degrees=True, style='solid', thickness=1, title=None, xlabel='Frequency (Hz)', xlim=None, ylim=None, width=None, height=None, hold=False, interactive=None):
    """Plot frequency response of a filter.

    This is a convenience function to plot frequency response, and internally uses
    :func:`scipy.signal.freqz` to estimate the response. For further details, see the
    documentation for :func:`scipy.signal.freqz`.

    :param b: numerator of a linear filter
    :param a: denominator of a linear filter
    :param fs: sampling rate in Hz (optional, normalized frequency if not specified)
    :param worN: see :func:`scipy.signal.freqz`
    :param whole: see :func:`scipy.signal.freqz`
    :param degrees: True to display phase in degrees, False for radians
    :param style: line style ('solid', 'dashed', 'dotted', 'dotdash', 'dashdot')
    :param thickness: line width in pixels
    :param title: figure title
    :param xlabel: x-axis label
    :param ylabel1: y-axis label for magnitude
    :param ylabel2: y-axis label for phase
    :param xlim: x-axis limits (min, max)
    :param ylim: y-axis limits (min, max)
    :param width: figure width in pixels
    :param height: figure height in pixels
    :param interactive: enable interactive tools (pan, zoom, etc) for plot
    :param hold: if set to True, output is not plotted immediately, but combined with the next plot

    >>> import arlpy
    >>> arlpy.plot.freqz([1,1,1,1,1], fs=120000);
    """
    w, h = _sig.freqz(b, a, worN, whole)
    Hxx = 20*_np.log10(abs(h)+_np.finfo(float).eps)
    f = w*fs/(2*_np.pi)
    if xlim is None:
        xlim = (0, fs/2)
    if ylim is None:
        ylim = (_np.max(Hxx)-50, _np.max(Hxx)+10)
    figure(title=title, xlabel=xlabel, ylabel='Amplitude (dB)', xlim=xlim, ylim=ylim, width=width, height=height, interactive=interactive)
    _hold_enable(True)
    plot(f, Hxx, color=color(0), style=style, thickness=thickness, legend='Magnitude')
    fig = gcf()
    units = 180/_np.pi if degrees else 1
    fig.extra_y_ranges = {'phase': _bmodels.Range1d(start=-_np.pi*units, end=_np.pi*units)}
    fig.add_layout(_bmodels.LinearAxis(y_range_name='phase', axis_label='Phase (degrees)' if degrees else 'Phase (radians)'), 'right')
    phase = _np.angle(h)*units
    fig.line(f, phase, line_color=color(1), line_dash=style, line_width=thickness, legend_label='Phase', y_range_name='phase')
    _hold_enable(hold)