def CreateGauge(percentage, scaleInfo):
    gaugeFig = Plot(x_range=Range1d(start=-1.25, end=1.25), y_range=Range1d(start=-1.25, end=1.25), plot_width=250, plot_height=250)
    gaugeFig.title.text = "Scale " + str(scaleInfo.Num) + ": " + scaleInfo.Name
    gaugeFig.title.align = 'center'
    gaugeFig.toolbar_location = None

    gaugeFig.border_fill_color = "#101010"
    gaugeFig.background_fill_color = "#101010"
    gaugeFig.title.text_color = "white"
    gaugeFig.outline_line_color = None

    glyph = AnnularWedge(x=0, y=0, inner_radius=.7, outer_radius=1, start_angle=math.pi / 2 - (2 * math.pi),
                         end_angle=math.pi / 2, fill_color="#444444", name="back")
    glyph2 = AnnularWedge(x=0, y=0, inner_radius=.7, outer_radius=1, start_angle=math.pi / 2 - (2 * math.pi * percentage),
                          end_angle=math.pi / 2, fill_color=gaugeColors[(scaleInfo.Num - 1) % len(gaugeColors)], name="front")
    PercentageText = Label(text_align='center', text=str(round((percentage * scaleInfo.MaxCapacity), 1)),text_color = 'white',
                           text_font_size="35px")
    lowerText = Label(text_align='center', y=-0.25, text=scaleInfo.Units, text_color='white')
    lowerText2 = Label(text_align='center', y=-0.48, text="Of " + str(scaleInfo.MaxCapacity), text_color='white')
    gaugeFig.add_glyph(glyph)
    gaugeFig.add_glyph(glyph2)
    gaugeFig.add_layout(PercentageText)
    gaugeFig.add_layout(lowerText)
    gaugeFig.add_layout(lowerText2)

    return gaugeFig
示例#2
0
    def drawgraph(self, ds, filterMin, filterMax, layout):
        G = nx.Graph()  # create an empty graph with no nodes and no edges

        # nodes = []
        # for i in range(len(ds.getNodes())):
        #     nodes.append([])
        #     # print(ds.getNodes()[i].getName())
        #     for j in range(len(ds.getNodes())):
        #         nodes[i].append(ds.getNodes()[i].getLinks()[j][1])
        #         # print("   " + str(ds.getNodes()[i].getLinks()[j][1]))

        # ds.toMinSpanTree()
        nodes = ds.getDoubleList(filterMin, filterMax, False)

        x = filterMin

        adj = np.array(nodes)
        G = nx.from_numpy_matrix(adj)

        for i in range(len(G.node)):
            G.node[i]['name'] = ds.getNames()[i]
        #pos = nx.drawing.layout.circular_layout(G, 1, None, 2)

        #nx.draw_networkx(G, pos, with_labels=True)
        # pt.show()
        #plt.show()
        plot = Plot(plot_width=500, plot_height=500,
                    x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))

        node_hover_tool = HoverTool(tooltips=[("Name of this node", "@name")])

        # plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool())
        plot.add_tools(node_hover_tool, TapTool(), BoxSelectTool(), BoxZoomTool(), UndoTool(), RedoTool(), SaveTool(),
                       ResetTool())
        plot.toolbar_location = 'left'
        if layout == 0:
            graph_renderer = from_networkx(G, nx.circular_layout, scale=1, center=(0, 0))
        elif layout == 1:
            graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))
        else:
            graph_renderer = from_networkx(G, nx.random_layout)
        graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
        graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
        graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])

        graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5)
        graph_renderer.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
        graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)

        graph_renderer.selection_policy = NodesAndLinkedEdges()
        #graph_renderer.inspection_policy = EdgesAndLinkedNodes()

        plot.renderers.append(graph_renderer)

        output_file("interactive_graphs.html")
        return plot
示例#3
0
def plotGauge(speedvalue, offset = 0,
              name = '', unit = '', color = '', maxValue = 0,
              major_step = 2, minor_step = .5):
    '''
    draw a gauge for show online data
    :param speedvalue: data value for a especific channel
    :param offset: offset is the minimum value of the channel
    :param name: name of the channel
    :param unit: units of the data value
    :param color: color of the gauge
    :param maxValue: max value of the chaneel
    :param major_step: step for points inside the gauge
    :param minor_step: step for points inside the gauge
    :return: figure plot in bokeh engine
    '''

    maxValue = maxValue - offset
    xdr = Range1d(start=-1.25, end=1.25)
    ydr = Range1d(start=-1.25, end=1.25)

    renderer = 'webgl'
    plt = Plot(x_range=xdr, y_range=ydr, plot_width=300, plot_height=300, output_backend=renderer,)
    plt.toolbar_location = None
    plt.outline_line_color = None

    plt.add_glyph(Circle(x=0, y=0, radius=1.00, fill_color="white", line_color="black"))
    plt.add_glyph(Circle(x=0, y=0, radius=0.05, fill_color="gray", line_color="black"))

    plt.add_glyph(Text(x=0, y=+0.15, text=[unit], text_color=color, text_align="center", text_baseline="bottom",
                        text_font_style="bold"))

    plt.add_glyph(Text(x=0, y=-0.15, text=[name], text_color="black", text_align="center", text_baseline="top",
                        text_font_style="bold"))

    add_gauge(plt, 0.75, maxValue, 0.05, +1, color, major_step, minor_step, offset = offset)

    valueGliph = Text(x=0, y=-0.6, text=["0"], text_color=color, text_align="center", text_baseline="top")

    plt.add_glyph(valueGliph)

    a, b = add_needle(plt, speedvalue, offset = offset, max_value = maxValue)
    return plt, a, b, valueGliph
示例#4
0
from bokeh.document import Document
from bokeh.embed import file_html
from bokeh.models import (AnnularWedge, ColumnDataSource, ImageURL, Plot,
                          Range1d, Text, Wedge)
from bokeh.resources import INLINE
from bokeh.sampledata.browsers import browsers_nov_2013, icons
from bokeh.util.browser import view

df = browsers_nov_2013

xdr = Range1d(start=-2, end=2)
ydr = Range1d(start=-2, end=2)

plot = Plot(x_range=xdr, y_range=ydr, width=800, height=800)
plot.title.text = "Web browser market share (November 2013)"
plot.toolbar_location = None

colors = {
    "Chrome": seagreen,
    "Firefox": tomato,
    "Safari": orchid,
    "Opera": firebrick,
    "IE": skyblue,
    "Other": lightgray
}

aggregated = df.groupby("Browser").agg(sum)
selected = aggregated[aggregated.Share >= 1].copy()
selected.loc["Other"] = aggregated[aggregated.Share < 1].sum()
browsers = selected.index.tolist()
示例#5
0
source = ColumnDataSource(dict(
    url = [url]*N,
    x1  = np.linspace(  0, 150, N),
    y1  = np.linspace(  0, 150, N),
    w1  = np.linspace( 10,  50, N),
    h1  = np.linspace( 10,  50, N),
    x2  = np.linspace(-50, 150, N),
    y2  = np.linspace(  0, 200, N),
))

xdr = Range1d(start=-100, end=200)
ydr = Range1d(start=-100, end=200)

plot = Plot(x_range=xdr, y_range=ydr)
plot.title.text = "ImageURL"
plot.toolbar_location = None

image1 = ImageURL(url="url", x="x1", y="y1", w="w1", h="h1", anchor="center", global_alpha=0.2)
plot.add_glyph(source, image1)

image2 = ImageURL(url="url", x="x2", y="y2", w=20, h=20, anchor="top_left")
plot.add_glyph(source, image2)

image3 = ImageURL(url=dict(value=url), x=200, y=-100, anchor="bottom_right")
plot.add_glyph(image3)

xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')

yaxis = LinearAxis()
plot.add_layout(yaxis,'left')
N = 9

x = np.linspace(-2, 2, N)
y = x**2

source1 = ColumnDataSource(dict(x=x, y=y, size=[20] * N))
xdr1 = DataRange1d(sources=[source1.columns("x")])
ydr1 = DataRange1d(sources=[source1.columns("y")])
plot1 = Plot(title="Plot1",
             x_range=xdr1,
             y_range=ydr1,
             plot_width=400,
             plot_height=400)
plot1.tools.append(TapTool(plot=plot1))
plot1.add_glyph(source1, Circle(x="x", y="y", size="size", fill_color="red"))
plot1.toolbar_location = None

source2 = ColumnDataSource(dict(x=x, y=y, color=["blue"] * N))
xdr2 = DataRange1d(sources=[source2.columns("x")])
ydr2 = DataRange1d(sources=[source2.columns("y")])
plot2 = Plot(title="Plot2",
             x_range=xdr2,
             y_range=ydr2,
             plot_width=400,
             plot_height=400)
plot2.tools.append(TapTool(plot=plot2))
plot2.add_glyph(source2, Circle(x="x", y="y", size=20, fill_color="color"))
plot2.toolbar_location = None


def on_selection_change1(obj, attr, _, inds):
示例#7
0
def visualize_graph_html(nx_graph,
                         output_dir=None,
                         title_text='',
                         layout='kamada_kawai',
                         should_show=False):
    """
    This method visualizes a NetworkX graph using Bokeh.

    :param nx_graph: NetworkX graph with node attributes containing image filenames.
    :param output_dir: Optional output directory for saving html.
    :param title_text: String to be displayed above the visualization.
    :param layout: Which layout function to use.
    :param should_show: Open the browser to look at the graph.
    """
    from bokeh import palettes
    from bokeh.io import output_file, show
    from bokeh.models import Circle, HoverTool, MultiLine, Plot, Range1d, TapTool
    # noinspection PyProtectedMember
    from bokeh.models.graphs import from_networkx, NodesAndLinkedEdges, NodesOnly

    pos = parse_layout(nx_graph, layout)

    hover_tool = HoverTool(
        tooltips='<img src="@imgs" height="200" alt="@imgs" width="200"></img>',
        show_arrow=False)

    plot = Plot(plot_width=800,
                plot_height=800,
                x_range=Range1d(-1.1, 1.1),
                y_range=Range1d(-1.1, 1.1))
    if title_text != '':
        plot.title.text = title_text
    plot.title.align = 'center'
    plot.min_border = 0
    plot.outline_line_color = None

    plot.add_tools(hover_tool, TapTool())
    plot.toolbar.logo = None
    plot.toolbar_location = None

    graph_renderer = from_networkx(nx_graph, pos)

    graph_renderer.node_renderer.data_source.data['imgs'] = [
        n[1]['img'] for n in nx_graph.nodes(data=True)
    ]

    graph_renderer.node_renderer.glyph = Circle(
        size=10, fill_color=palettes.Spectral4[0], line_color=None)
    graph_renderer.node_renderer.selection_glyph = Circle(
        size=10, fill_color=palettes.Spectral4[2], line_color=None)
    graph_renderer.node_renderer.hover_glyph = Circle(
        size=10, fill_color=palettes.Spectral4[1], line_color=None)

    graph_renderer.edge_renderer.glyph = MultiLine(line_color='#CCCCCC',
                                                   line_alpha=0.8,
                                                   line_width=1.5)
    graph_renderer.edge_renderer.selection_glyph = MultiLine(
        line_color=palettes.Spectral4[2], line_width=2)

    graph_renderer.selection_policy = NodesAndLinkedEdges()
    graph_renderer.inspection_policy = NodesOnly()

    plot.renderers.append(graph_renderer)

    if output_dir:
        ensure_dir_exists(output_dir)
        output_file(join(output_dir, 'visualize_graph.html'))

    if should_show:
        show(plot)
示例#8
0
文件: app.py 项目: mmc366/GitCapstone
def survey():
    if request.method == "GET":
        return render_template('survey.html')
 
    else: #Request was a POST
        
        user_input = pd.DataFrame(data=[[request.form['Average_Sleep'],
                                         request.form['Sex'],
                                         request.form['Marital'],
                                         request.form['Employment'],
                                         request.form['Physical_QoL'],
                                         request.form['Mental_QoL'],
                                         request.form['Physical_Activity'],
                                         request.form['Race'],
                                         request.form['Age'],
                                         request.form['Weight'], 
                                         request.form['Height_feet'],
                                         request.form['Height_inches'],                                           
                                         request.form['Education'],
                                         request.form['Income'],
                                         request.form['Soda_Consumption'], 
                                         request.form['Sugary_Drink_Consumption'],                                          
                                         request.form['ALCDAY5'], 
                                         request.form['AVEDRNK2'],
                                         request.form['Smoker_Status'], 
                                         request.form['Marijuana_Use'],   
                                         request.form['Calorie_Informed_Choices'], 
                                         request.form['HeartAttackOutcomeDummy'],
                                         request.form['AnginaCoronaryHDOutcomeDummy'], 
                                         request.form['StrokeOutcomeDummy'],
                                         request.form['AsthmaLifetimeOutcomeDummy'], 
                                         request.form['SkinCancerOutcomeDummy'],
                                         request.form['OtherCancerOutcomeDummy'], 
                                         request.form['COPDEmphysemaChronicBroncOutcomeDummy'],
                                         request.form['ArthritisOutcomeDummy'], 
                                         request.form['DepressionOutcomeDummy'], 
                                         request.form['KidneyDiseaseOutcomeDummy'], 
                                         request.form['Life_Satisfaction']]],                        
                    columns=['Average Sleep', 'Sex', 'Marital', 'Employment', 
                             'Physical QoL', 'Mental QoL', 'Physical Activity',
                             'Race', 'Age', 'Weight', 'Height_feet','Height_inches',
                             'Education', 'Income', 'Soda Consumption', 
                             'Sugary Drink Consumption', 
                             'Alcohol Days', 'Alcohol Drinks','Smoker Status',
                             'Marijuana Use', 'Calorie Informed Choices', 
                             'HeartAttackOutcomeDummy', 'AnginaCoronaryHDOutcomeDummy', 
                             'StrokeOutcomeDummy', 'AsthmaLifetimeOutcomeDummy',
                             'SkinCancerOutcomeDummy', 'OtherCancerOutcomeDummy', 
                             'COPDEmphysemaChronicBroncOutcomeDummy',
                             'ArthritisOutcomeDummy', 'DepressionOutcomeDummy', 
                             'KidneyDiseaseOutcomeDummy', 'Life Satisfaction'], dtype=np.float)#.astype(float)
        
        
        #return model1.predict(transform(user_input))
       # print(user_input.values)
        prediction=model1.predict_proba(transform(user_input).values)[-1][-1]
        
        def risk_category(risk_probability):
            """
            Takes a risk probability (e.g., "prediction") as a float and returns
            the corresponding risk level category as a string.
            
            @risk_probably: float
            @reutnr: str
            """
            if risk_probability < 0.25:
                return "Low Risk"
            if risk_probability >= 0.25 and risk_probability < 0.50:
                return "Low Moderate Risk"
            if risk_probability >=.50 and risk_probability < 0.75:
                return "High Moderate Risk"
            else:
                return "High Risk"
            
        def adjusted_risk(user_input): #Need to test this function
            """
            Takes DataFrame of user_input, transforms it, and calculates
            adjusted predicted risk based on changes to modifible health
            behaviors. Returns a new adjusted probability (float) and
            the list of suggested health behavior changes contributing
            to the reduced risk.
            
            @user_input: DataFrame
            @return: float, list<str>
            """
            transformed_df = transform(user_input)
            
            suggested_modifications = [] #Append to suggested modification list
            
            #Sets sleep to average sleep recommended for adults 18 - 64 yrs 
            #(7-9 hrs), adults 65+ (7-8 hrs) by National Sleep Foundation
            if transformed_df['Average Sleep'].values[0] < 7.0 or transformed_df['Average Sleep'].values[0] > 9.0:
                orig_sleep = transformed_df['Average Sleep'].values[0]
                transformed_df['Average Sleep'].values[0] = 8.0
                suggested_modifications.append("Get an average of 8.0 hours of sleep per night instead of "+ str(orig_sleep)+ " hours.")
            
            #Sets Physical Activity to had physical activity in past 30 days
            if transformed_df['Physical Activity'].values[0] == 0:
                transformed_df['Physical Activity'].values[0] = 1
                suggested_modifications.append("Incorporate a regular exercise routine into your schedule – this could be as simple as walking versus driving to the corner store or  taking the stairs instead of the elevator.")
            
            #Sets Obese -> Overweight and Overweight -> Normal weight
            if transformed_df['BMI'].values[0] == 3.0 or transformed_df['BMI'].values[0] == 4.0:
                orig_BMI = transformed_df['BMI'].values[0]
                transformed_df['BMI'].values[0] = transformed_df['BMI'].values[0] - 1.0
                
                if orig_BMI == 3.0:
                    orig_BMI = "Overweight (BMI: 25 –  < 30)"
                    suggested_BMI = "Normal Weight (BMI: 18.5 - < 25)"
                    suggested_modifications.append("Reduce BMI through gradual, healthy weight loss from "+ orig_BMI+ " to "+ suggested_BMI+ ".")
                    
                if orig_BMI == 4.0:
                    orig_BMI = "Obese (BMI: >= 30)"
                    suggested_BMI = "Overweight (BMI: 25 –  < 30)"
                    suggested_modifications.append("Reduce BMI through gradual, healthy weight loss from "+ orig_BMI+ " to "+ suggested_BMI+ ".")
            
            #Sets Underweight -> Normal weight
            if transformed_df['BMI'].values[0] == 1:
                transformed_df['BMI'].values[0] = transformed_df['BMI'].values[0] + 1.0
                orig_BMI = "Underweight (BMI: < 18.5)"
                suggested_BMI = "Normal Weight (BMI: 18.5 - < 25)"
                suggested_modifications.append("Reduce BMI through gradual, healthy weight loss from "+ orig_BMI+ " to "+ suggested_BMI+ ".")
            
            #Sets Daily smokers -> Occasional smokers and Occasional smokers -> Former smokers  
            if transformed_df['Smoker Status'].values[0] == 1.0 or transformed_df['Smoker Status'].values[0] == 2.0:
                orig_smoker = transformed_df['Smoker Status'].values[0]
                transformed_df['Smoker Status'].values[0] = transformed_df['Smoker Status'].values[0] + 1.0
                
                if orig_smoker == 1.0:
                    orig_smoker = "smoking every day"
                    suggested_smoker = "smoking some days"
                    suggested_modifications.append("Reduce smoking frequency from "+orig_smoker+" to "+suggested_smoker+ ".")
                    
                if orig_smoker == 2.0:
                    orig_smoker = "smoking some days"
                    suggested_smoker = "former smoker (quit)"
                    suggested_modifications.append("Reduce smoking frequency from "+orig_smoker+" to "+suggested_smoker+ ".")
            
            #Reduces weekly alcohol consumption by 25% (cutoff arbitrary)
            if transformed_df['Alcohol Consumption'].values[0] >= 1.0:
                orig_alcohol = transformed_df['Alcohol Consumption'].values[0]
                suggested_alcohol = transformed_df['Alcohol Consumption'].values[0]*0.25
                transformed_df['Alcohol Consumption'].values[0] = transformed_df['Alcohol Consumption'].values[0]*0.25
                suggested_modifications.append("Reduce average weekly alcohol consumption from " +str(orig_alcohol)+ " drink(s) per week to " +str(suggested_alcohol)+ " drink(s) per week.")
                
            #Sets 1-13 days poor Mental QoL -> 0 days and 14+ poor days -> 1-13 days
            if transformed_df['Mental QoL'].values[0] == 2.0 or transformed_df['Mental QoL'].values[0] == 3.0:
                #orig_mental = transformed_df['Mental QoL'].values[0]
                transformed_df['Mental QoL'].values[0] = transformed_df['Mental QoL'].values[0] - 1.0
                suggested_modifications.append("Consider consulting a psychologist/psychiatrist to learn tools for coping with stress and emotional difficulties in order to improve your mental health.")
                    
                
            return (transformed_df, suggested_modifications)
          
        adjusted_prediction=model1.predict_proba(adjusted_risk(user_input)[0].values)[-1][-1]
        
        modification_list=adjusted_risk(user_input)[1]
        
                
#Gauge Chart Rendering        
        xdr = Range1d(start=-1.25, end=1.25)
        ydr = Range1d(start=-1.25, end=1.25)
        
        plot = Plot(x_range=xdr, y_range=ydr, plot_width=500, plot_height=500)
        plot.title.text = "Predicted Diabetes Risk"
        plot.toolbar_location = None
        
        start_angle = pi + pi/4
        end_angle = -pi/4
        
        max_kmh = 1.0
        max_mph = 1.0
        
        major_step, minor_step = .25, .05
        
        plot.add_glyph(Circle(x=0, y=0, radius=1.00, fill_color="white", line_color="black"))
        plot.add_glyph(Circle(x=0, y=0, radius=0.05, fill_color="gray", line_color="black"))
        
        plot.add_glyph(Text(x=0, y=+0.15, text=["Current Risk Probability"], text_color="red", text_align="center", text_baseline="bottom", text_font_style="bold"))
        plot.add_glyph(Text(x=0, y=-0.15, text=["Adjusted Risk Probability"], text_color="blue", text_align="center", text_baseline="top", text_font_style="bold"))
        
        def data(value):
            """Shorthand to override default units with "data", for e.g. `Ray.length`. """
            return dict(value=value, units="data")
        
        def speed_to_angle(speed, units):
            max_speed = max_kmh
            speed = min(max(speed, 0), max_speed)
            total_angle = start_angle - end_angle
            angle = total_angle*float(speed)/max_speed
            return start_angle - angle
        
        def add_needle(speed, units, color_choice, line_weight):
            angle = speed_to_angle(speed, units)
            plot.add_glyph(Ray(x=0, y=0, length=data(0.75), angle=angle,    line_color=color_choice, line_width=line_weight))
            plot.add_glyph(Ray(x=0, y=0, length=data(0.10), angle=angle-pi, line_color=color_choice, line_width=line_weight))
        
        def polar_to_cartesian(r, alpha):
            return r*cos(alpha), r*sin(alpha)
        
        def add_gauge(radius, max_value, length, direction, color, major_step, minor_step):
            major_angles, minor_angles = [], []
            major_labels, minor_labels = [], []
        
            total_angle = start_angle - end_angle
        
            major_angle_step = float(major_step)/max_value*total_angle
            minor_angle_step = float(minor_step)/max_value*total_angle
        
            major_angle = 0
        
            while major_angle <= total_angle:
                major_angles.append(start_angle - major_angle)
                major_angle += major_angle_step
        
            minor_angle = 0
        
            while minor_angle <= total_angle:
                minor_angles.append(start_angle - minor_angle)
                minor_angle += minor_angle_step
        
            major_labels = [ major_step*i for i, _ in enumerate(major_angles) ]
            minor_labels = [ minor_step*i for i, _ in enumerate(minor_angles) ]
        
            n = major_step/minor_step
            minor_angles = [ x for i, x in enumerate(minor_angles) if i % n != 0 ]
            minor_labels = [ x for i, x in enumerate(minor_labels) if i % n != 0 ]
        
            glyph = Arc(x=0, y=0, radius=radius, start_angle=start_angle, end_angle=end_angle, direction="clock", line_color=color, line_width=2)
            plot.add_glyph(glyph)
        
            rotation = 0 if direction == 1 else -pi
        
            x, y = zip(*[ polar_to_cartesian(radius, angle) for angle in major_angles ])
            angles = [ angle + rotation for angle in major_angles ]
            source = ColumnDataSource(dict(x=x, y=y, angle=angles))
        
            glyph = Ray(x="x", y="y", length=data(length), angle="angle", line_color=color, line_width=2)
            plot.add_glyph(source, glyph)
        
            x, y = zip(*[ polar_to_cartesian(radius, angle) for angle in minor_angles ])
            angles = [ angle + rotation for angle in minor_angles ]
            source = ColumnDataSource(dict(x=x, y=y, angle=angles))
        
            glyph = Ray(x="x", y="y", length=data(length/2), angle="angle", line_color=color, line_width=1)
            plot.add_glyph(source, glyph)
        
            x, y = zip(*[ polar_to_cartesian(radius+2*length*direction, angle) for angle in major_angles ])
            text_angles = [ angle - pi/2 for angle in major_angles ]
            source = ColumnDataSource(dict(x=x, y=y, angle=text_angles, text=major_labels))
        
            glyph = Text(x="x", y="y", angle="angle", text="text", text_align="center", text_baseline="middle")
            plot.add_glyph(source, glyph)
        
        add_gauge(0.75, max_kmh, 0.05, +1, "red", major_step, minor_step)
        add_gauge(0.70, max_mph, 0.05, -1, "blue", major_step, minor_step)
        
        add_needle(prediction, "Current Risk", "red", 6)
        add_needle(adjusted_prediction, "Adjusted Risk", "blue", 3)
        
        script, div = components(plot)
        
        return render_template('orig_output.html', script=script, div=div, prediction=prediction, adjusted_prediction=adjusted_prediction, risk_level=risk_category(prediction), adjusted_risk_level=risk_category(adjusted_prediction), modifications=modification_list)
session = Session()
session.use_doc('linked_tap_server')
session.load_document(document)

N = 9

x = np.linspace(-2, 2, N)
y = x**2

source1 = ColumnDataSource(dict(x = x, y = y, size = [20]*N))
xdr1 = DataRange1d(sources=[source1.columns("x")])
ydr1 = DataRange1d(sources=[source1.columns("y")])
plot1 = Plot(title="Plot1", x_range=xdr1, y_range=ydr1, plot_width=400, plot_height=400)
plot1.tools.append(TapTool(plot=plot1))
plot1.add_glyph(source1, Circle(x="x", y="y", size="size", fill_color="red"))
plot1.toolbar_location=None

source2 = ColumnDataSource(dict(x = x, y = y, color = ["blue"]*N))
xdr2 = DataRange1d(sources=[source2.columns("x")])
ydr2 = DataRange1d(sources=[source2.columns("y")])
plot2 = Plot(title="Plot2", x_range=xdr2, y_range=ydr2, plot_width=400, plot_height=400)
plot2.tools.append(TapTool(plot=plot2))
plot2.add_glyph(source2, Circle(x="x", y="y", size=20, fill_color="color"))
plot2.toolbar_location=None

def on_selection_change1(obj, attr, _, inds):
    color = ["blue"]*N
    if inds:
        [index] = inds
        color[index] = "red"
    source2.data["color"] = color