bokeh.embed.json_item

Here are the examples of the python api bokeh.embed.json_item taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

11 Examples 7

3 View Source File : usage.py
License : MIT License
Project Creator : plotly

def bokeh_fig(year):
    df = gapminder.query("year == %d" % (year or 1952))
    return json_item( hv.render( hv.Points(df, kdims=["gdpPercap", "lifeExp"])
        .opts( color="continent", size=hv.dim("pop") ** (0.5) / 800,
            logx=True, height=330, width=530, cmap="Category10",tools=["hover"],
            legend_position="bottom_right", title="HoloViews / Bokeh") ))

@app.callback(Output("seaborn", "contents"), [Input("year", "value")])

0 View Source File : __init__.py
License : MIT License
Project Creator : ash2shukla

def streamlit_bokeh_events(bokeh_plot=None, events="", key=None, debounce_time=1000, refresh_on_update=True, override_height=None):
    """Returns event dict

    Keyword arguments:
    bokeh_plot -- Bokeh figure object (default None)
    events -- Comma separated list of events dispatched by bokeh eg. "event1,event2,event3" (default "")
    debounce_time -- Time in ms to wait before dispatching latest event (default 1000)
    refresh_on_update -- Should the chart be re-rendered on refresh (default False)
        : Set to False if you are not updating the datasource at runtime
    override_height -- Override plot viewport height
    """
    if key is None:
        raise ValueError("key can not be None.")

    div_id = "".join(choices(ascii_letters, k=16))
    fig_dict = json_item(bokeh_plot, div_id)
    json_figure = json.dumps(fig_dict)
    component_value = _component_func(
        bokeh_plot=json_figure,
        events=events,
        key=key,
        _id=div_id,
        default=None,
        debounce_time=debounce_time,
        refresh_on_update=refresh_on_update,
        override_height=override_height
    )
    return component_value


if not _RELEASE:

0 View Source File : test_clustergram.py
License : MIT License
Project Creator : martinfleis

def test_bokeh():
    clustergram = Clustergram(range(1, 8), backend="sklearn", random_state=random_state)
    clustergram.fit(data)

    f = clustergram.bokeh(pca_kwargs=dict(random_state=random_state))
    out = str(json_item(f, "clustergram"))

    assert out.count("data") == 60
    assert "cluster_labels" in out
    assert "count" in out
    assert "ratio" in out
    assert "size" in out

    f = clustergram.bokeh(pca_weighted=False)
    out = str(json_item(f, "clustergram"))

    assert out.count("data") == 60
    assert "cluster_labels" in out
    assert "count" in out
    assert "ratio" in out
    assert "size" in out


@pytest.mark.skipif(

0 View Source File : test_clustergram.py
License : MIT License
Project Creator : martinfleis

def test_bokeh_cuml():
    n_samples = 10
    n_features = 2

    n_clusters = 5
    random_state = 0

    device_data, device_labels = cuml.make_blobs(
        n_samples=n_samples,
        n_features=n_features,
        centers=n_clusters,
        random_state=random_state,
        cluster_std=0.1,
    )

    data = cudf.DataFrame(device_data)

    clustergram = Clustergram(range(1, 8), backend="cuML", random_state=random_state)
    clustergram.fit(data)

    f = clustergram.bokeh()
    out = str(json_item(f, "clustergram"))

    assert out.count("data") == 58
    assert "cluster_labels" in out
    assert "count" in out
    assert "ratio" in out
    assert "size" in out

0 View Source File : outputs.py
License : MIT License
Project Creator : PSLmodels

def aggregate_plot(tb):
    """
    Function for creating a bokeh plot that shows aggregate tax liabilities for
    each year the TaxBrain instance was run
    Parameters
    ----------
    tb: An instance of the TaxBrain object
    Returns
    -------
    Bokeh figure
    """
    # Pull aggregate data by year and transpose it for plotting
    varlist = ["iitax", "payrolltax", "combined"]
    base_data = tb.multi_var_table(varlist, "base").transpose()
    base_data["calc"] = "Base"
    reform_data = tb.multi_var_table(varlist, "reform").transpose()
    reform_data["calc"] = "Reform"
    base_cds = ColumnDataSource(base_data)
    reform_cds = ColumnDataSource(reform_data)
    num_ticks = len(base_data)
    del base_data, reform_data

    fig = figure(title="Aggregate Tax Liability by Year",
                 width=700, height=500, tools="save")
    ii_base = fig.line(x="index", y="iitax", line_width=4,
                       line_color="#12719e", legend_label="Income Tax - Base",
                       source=base_cds)
    ii_reform = fig.line(x="index", y="iitax", line_width=4,
                         line_color="#73bfe2", legend_label="Income Tax - Reform",
                         source=reform_cds)
    proll_base = fig.line(x="index", y="payrolltax", line_width=4,
                          line_color="#408941", legend_label="Payroll Tax - Base",
                          source=base_cds)
    proll_reform = fig.line(x="index", y="payrolltax", line_width=4,
                            line_color="#98cf90", legend_label="Payroll Tax - Reform",
                            source=reform_cds)
    comb_base = fig.line(x="index", y="combined", line_width=4,
                         line_color="#a4201d", legend_label="Combined - Base",
                         source=base_cds)
    comb_reform = fig.line(x="index", y="combined", line_width=4,
                           line_color="#e9807d", legend_label="Combined - Reform",
                           source=reform_cds)

    # format figure
    fig.legend.location = "top_left"
    fig.yaxis.formatter = NumeralTickFormatter(format="$0.00a")
    fig.yaxis.axis_label = "Aggregate Tax Liability"
    fig.xaxis.minor_tick_line_color = None
    fig.xaxis[0].ticker.desired_num_ticks = num_ticks

    # Add hover tool
    tool_str = """
          <  p> < b>@calc - {} < /b> < /p>
         < p>${} < /p>
    """
    ii_hover = HoverTool(
        tooltips=tool_str.format("Individual Income Tax", "@iitax{0,0}"),
        renderers=[ii_base, ii_reform]
    )
    proll_hover = HoverTool(
        tooltips=tool_str.format("Payroll Tax", "@payrolltax{0,0}"),
        renderers=[proll_base, proll_reform]
    )
    combined_hover = HoverTool(
        tooltips=tool_str.format("Combined Tax", "@combined{0,0}"),
        renderers=[comb_base, comb_reform]
    )
    fig.add_tools(ii_hover, proll_hover, combined_hover)

    # toggle which lines are shown
    plot_js = """
    object1.visible = toggle.active
    object2.visible = toggle.active
    object3.visible = toggle.active
    """
    base_callback = CustomJS(code=plot_js, args={})
    base_toggle = Toggle(label="Base", button_type="primary",
                         active=True)
    base_callback.args = {"toggle": base_toggle, "object1": ii_base,
                          "object2": proll_base, "object3": comb_base}
    base_toggle.js_on_change('active', base_callback)

    reform_callback = CustomJS(code=plot_js, args={})
    reform_toggle = Toggle(label="Reform", button_type="primary",
                           active=True)
    reform_callback.args = {"toggle": reform_toggle, "object1": ii_reform,
                            "object2": proll_reform, "object3": comb_reform}
    fig_layout = layout([fig], [base_toggle, reform_toggle])
    reform_toggle.js_on_change('active', reform_callback)

    # Components needed to embed the figure
    data = json_item(fig_layout)
    outputs = {
        "media_type": "bokeh",
        "title": "",
        "data": data,
    }

    return outputs


def create_layout(data, start_year, end_year):

0 View Source File : outputs.py
License : MIT License
Project Creator : PSLmodels

def create_layout(data, start_year, end_year):
    """
    Function for creating a bokeh layout with all of the data tables
    """

    agg_data = data["aggr_outputs"]
    # create aggregate table
    clt_title = f"  <  h3>{agg_data['current']['title']} < /h3>"
    current_law_table = Div(text=clt_title + agg_data["current"]["renderable"],
                            width=1000)
    rt_title = f" < h3>{agg_data['reform']['title']} < /h3>"
    reform_table = Div(text=rt_title + agg_data["reform"]["renderable"],
                       width=1000)
    ct_title = f" < h3>{agg_data['change']['title']} < /h3>"
    change_table = Div(text=ct_title + agg_data["change"]["renderable"],
                       width=1000)

    current_tab = Panel(child=current_law_table,
                        title="Current Law")
    reform_tab = Panel(child=reform_table,
                       title="Reform")
    change_tab = Panel(child=change_table,
                       title="Change")
    agg_tabs = Tabs(tabs=[current_tab, reform_tab, change_tab])

    key_map = {
        "current": "Current",
        "reform": "Reform",
        "ind_income": "Income Tax",
        "payroll": "Payroll Tax",
        "combined": "Combined Tax",
        "dist": "Distribution Table",
        "diff": "Differences Table"
    }

    tbl_data = data["tbl_outputs"]
    yr_panels = []
    # loop through each year (start - end year)
    for yr in range(start_year, end_year + 1):
        # loop through each table type: dist, idff
        tbl_panels = []
        for tbl_type, content in tbl_data.items():
            # loop through sub tables: current, reform for dist
            # ind_income, payroll, combined for diff
            content_panels = []
            for key, value in content.items():
                # loop through each grouping: bins, deciles
                grp_panels = []
                for grp, grp_data in value.items():
                    _data = grp_data[yr]
                    # create a data table for this tab
                    title = f" < h3>{_data['title']} < /h3>"
                    note = (" < p> < i>All monetary totals are in billions. "
                            "All counts are in millions. "
                            "Averages and shares are as shown. < /i> < /p>")
                    tbl = Div(text=title + note + _data["renderable"],
                              width=1000)
                    grp_panel = Panel(child=tbl, title=grp.title())
                    grp_panels.append(grp_panel)
                grp_tab = Tabs(tabs=grp_panels)
                # panel for the sub tables
                content_panel = Panel(child=grp_tab, title=key_map[key])
                content_panels.append(content_panel)
            content_tab = Tabs(tabs=content_panels)
            # panel for the table types
            tbl_panel = Panel(child=content_tab,
                              title=key_map[tbl_type])
            tbl_panels.append(tbl_panel)
        type_tab = Tabs(tabs=tbl_panels)
        # panel for the year
        yr_panel = Panel(child=type_tab, title=str(yr))
        yr_panels.append(yr_panel)

    yr_tabs = Tabs(tabs=yr_panels)

    agg_layout = layout(
        children=[agg_tabs]
    )
    table_layout = layout(
        children=[yr_tabs]
    )
    agg_data = json_item(agg_layout)
    table_data = json_item(table_layout)

    # return a dictionary of outputs ready for COMP
    agg_outputs = {
        "media_type": "bokeh",
        "title": "Aggregate Results",
        "data": agg_data,
    }
    table_outputs = {
        "media_type": "bokeh",
        "title": "Tables",
        "data": table_data,
    }

    # return js, div, cdn_js, cdn_css, widget_js, widget_css
    return agg_outputs, table_outputs

0 View Source File : outputs.py
License : MIT License
Project Creator : PSLmodels

def liability_plot(df_base, df_reform, span, mtr_opt):
    df_base = ColumnDataSource(df_base)
    df_reform = ColumnDataSource(df_reform)
    tools = "pan, zoom_in, zoom_out, reset"
    fig = figure(plot_width=600, plot_height=500,
                 x_range=(-10000, 300000), y_range=(-20000, 100000), tools=tools, active_drag="pan")
    fig.yaxis.axis_label = "Tax Liabilities"
    fig.yaxis.formatter = NumeralTickFormatter(format="$0,000")

    filer_income = Span(location=span, dimension='height',
                        line_color='black', line_dash='dotted', line_width=1.5)
    fig.add_layout(filer_income)
    label_format = f'{span:,}'
    filer_income_label = Label(x=span, y=25, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format,
                               text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt")
    fig.add_layout(filer_income_label)
    axis = Span(location=0, dimension='width',
                line_color='#bfbfbf', line_width=1.5)
    fig.add_layout(axis)

    iitax_base = fig.line(x="Axis", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba',
                          line_width=2, legend_label="Individual Income Tax Liability", muted_alpha=0.1, source=df_base)
    payroll_base = fig.line(x="Axis", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4',
                            line_width=2, legend_label='Payroll Tax Liability', muted_alpha=0.1, source=df_base)

    iitax_reform = fig.line(x="Axis", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba',
                            line_width=2, line_dash='dashed', legend_label="Individual Income Tax Liability", muted_alpha=0.1, source=df_reform)
    payroll_reform = fig.line(x="Axis", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4',
                              line_width=2, line_dash='dashed', legend_label='Payroll Tax Liability', muted_alpha=0.1, source=df_reform)

    iitax_base.muted = False
    payroll_base.muted = False
    iitax_reform.muted = False
    payroll_reform.muted = False

    plot_js = """
    object1.visible = toggle.active
    object2.visible = toggle.active
    """
    base_callback = CustomJS(code=plot_js, args={})
    base_toggle = Toggle(label="Base (Solid)", button_type="default",
                         active=True)
    base_callback.args = {"toggle": base_toggle, "object1": iitax_base,
                          "object2": payroll_base}
    base_toggle.js_on_change('active', base_callback)

    reform_callback = CustomJS(code=plot_js, args={})
    reform_toggle = Toggle(label="Reform (Dashed)", button_type="default",
                           active=True)
    reform_callback.args = {"toggle": reform_toggle, "object1": iitax_reform,
                            "object2": payroll_reform}
    reform_toggle.js_on_change('active', reform_callback)

    fig.xaxis.formatter = NumeralTickFormatter(format="$0,000")
    fig.xaxis.axis_label = mtr_opt
    fig.xaxis.minor_tick_line_color = None

    fig.legend.click_policy = "mute"

    layout = column(fig, row(base_toggle, reform_toggle))

    data = json_item(layout)

    outputs = {
        "media_type": "bokeh",
        "title": "Tax Liabilities by {} (Holding Other Inputs Constant)".format(mtr_opt),
        "data": data
    }

    return outputs


def rate_plot(df_base, df_reform, span, mtr_opt):

0 View Source File : outputs.py
License : MIT License
Project Creator : PSLmodels

def rate_plot(df_base, df_reform, span, mtr_opt):
    df_base = ColumnDataSource(df_base)
    df_reform = ColumnDataSource(df_reform)
    tools = "pan, zoom_in, zoom_out, reset"
    fig = figure(plot_width=600, plot_height=500,
                 x_range=(-10000, 300000), y_range=(-0.3, 0.5), tools=tools, active_drag="pan")
    fig.yaxis.axis_label = "Tax Rate"
    fig.yaxis.formatter = NumeralTickFormatter(format="0%")

    filer_income = Span(location=span, dimension='height',
                        line_color='black', line_dash='dotted', line_width=1.5)
    fig.add_layout(filer_income)
    label_format = f'{span:,}'
    filer_income_label = Label(x=span, y=25, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format,
                               text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt")
    fig.add_layout(filer_income_label)
    axis = Span(location=0, dimension='width',
                line_color='#bfbfbf', line_width=1.5)
    fig.add_layout(axis)

    iitax_atr_base = fig.line(x="Axis", y="IATR", line_color='#2b83ba', muted_color='#2b83ba',
                              line_width=2, legend_label="Income Tax Average Rate", muted_alpha=0.1, source=df_base)
    payroll_atr_base = fig.line(x="Axis", y="PATR", line_color='#abdda4', muted_color='#abdda4',
                                line_width=2, legend_label='Payroll Tax Average Rate', muted_alpha=0.1, source=df_base)
    iitax_mtr_base = fig.line(x="Axis", y="Income Tax MTR", line_color='#fdae61', muted_color='#fdae61',
                              line_width=2, legend_label="Income Tax Marginal Rate", muted_alpha=0.1, source=df_base)
    payroll_mtr_base = fig.line(x="Axis", y="Payroll Tax MTR", line_color='#d7191c', muted_color='#d7191c',
                                line_width=2, legend_label='Payroll Tax Marginal Rate', muted_alpha=0.1, source=df_base)

    iitax_atr_reform = fig.line(x="Axis", y="IATR", line_color='#2b83ba', muted_color='#2b83ba', line_width=2,
                                line_dash='dashed', legend_label="Income Tax Average Rate", muted_alpha=0.1, source=df_reform)
    payroll_atr_reform = fig.line(x="Axis", y="PATR", line_color='#abdda4', muted_color='#abdda4', line_width=2,
                                  line_dash='dashed', legend_label='Payroll Tax Average Rate', muted_alpha=0.1, source=df_reform)
    iitax_mtr_reform = fig.line(x="Axis", y="Income Tax MTR", line_color='#fdae61', muted_color='#fdae61',
                                line_width=2, line_dash='dashed', legend_label="Income Tax Marginal Rate", muted_alpha=0.1, source=df_reform)
    payroll_mtr_reform = fig.line(x="Axis", y="Payroll Tax MTR", line_color='#d7191c', muted_color='#d7191c',
                                  line_width=2, line_dash='dashed', legend_label='Payroll Tax Marginal Rate', muted_alpha=0.1, source=df_reform)

    iitax_atr_base.muted = False
    iitax_mtr_base.muted = True
    payroll_atr_base.muted = True
    payroll_mtr_base.muted = True
    iitax_atr_reform.muted = False
    iitax_mtr_reform.muted = True
    payroll_atr_reform.muted = True
    payroll_mtr_reform.muted = True

    plot_js = """
    object1.visible = toggle.active
    object2.visible = toggle.active
    object3.visible = toggle.active
    object4.visible = toggle.active
    """
    base_callback = CustomJS(code=plot_js, args={})
    base_toggle = Toggle(label="Base (Solid)", button_type="default",
                         active=True)
    base_callback.args = {"toggle": base_toggle, "object1": iitax_atr_base,
                          "object2": payroll_atr_base, "object3": iitax_mtr_base,
                          "object4": payroll_mtr_base}
    base_toggle.js_on_change('active', base_callback)

    reform_callback = CustomJS(code=plot_js, args={})
    reform_toggle = Toggle(label="Reform (Dashed)", button_type="default",
                           active=True)
    reform_callback.args = {"toggle": reform_toggle, "object1": iitax_atr_reform,
                            "object2": payroll_atr_reform, "object3": iitax_mtr_reform,
                            "object4": payroll_mtr_reform}
    reform_toggle.js_on_change('active', reform_callback)

    fig.xaxis.formatter = NumeralTickFormatter(format="$0,000")
    fig.xaxis.axis_label = mtr_opt
    fig.xaxis.minor_tick_line_color = None

    fig.legend.click_policy = "mute"

    layout = column(fig, row(base_toggle, reform_toggle))

    data = json_item(layout)

    outputs = {
        "media_type": "bokeh",
        "title": "Tax Rates by {} (Holding Other Inputs Constant)".format(mtr_opt),
        "data": data
    }

    return outputs


def credit_plot(df_base, df_reform, span, mtr_opt):

0 View Source File : outputs.py
License : MIT License
Project Creator : PSLmodels

def credit_plot(df_base, df_reform, span, mtr_opt):
    df_base = ColumnDataSource(df_base)
    df_reform = ColumnDataSource(df_reform)
    tools = "pan, zoom_in, zoom_out, reset"
    fig = figure(plot_width=600, plot_height=500, x_range=(
        -2500, 70000), tools=tools, active_drag="pan")

    filer_income = Span(location=span, dimension='height',
                        line_color='black', line_dash='dotted', line_width=1.5)
    fig.add_layout(filer_income)
    label_format = f'{span:,}'
    filer_income_label = Label(x=span, y=45, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format,
                               text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt")
    fig.add_layout(filer_income_label)
    axis = Span(location=0, dimension='width',
                line_color='#bfbfbf', line_width=1.5)
    fig.add_layout(axis)

    eitc_base = fig.line(x="Axis", y="EITC", line_color='#2b83ba', muted_color='#2b83ba',
                         line_width=2, legend_label="Earned Income Tax Credit", muted_alpha=0.1, source=df_base)
    ctc_base = fig.line(x="Axis", y="CTC", line_color='#abdda4', muted_color='#abdda4',
                        line_width=2, legend_label='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_base)
    ctc_refund_base = fig.line(x="Axis", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61',
                               line_width=2, legend_label='Refundable Child Tax Credit', muted_alpha=0.1, source=df_base)
    cdcc_base = fig.line(x="Axis", y="Child care credit", line_color='#d7191c', muted_color='#d7191c',
                         line_width=2, legend_label='Child and Dependent Care Credit', muted_alpha=0.1, source=df_base)

    eitc_reform = fig.line(x="Axis", y="EITC", line_color='#2b83ba', muted_color='#2b83ba', line_width=2,
                           line_dash='dashed', legend_label="Earned Income Tax Credit", muted_alpha=0.1, source=df_reform)
    ctc_reform = fig.line(x="Axis", y="CTC", line_color='#abdda4', muted_color='#abdda4', line_width=2,
                          line_dash='dashed', legend_label='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_reform)
    ctc_refund_reform = fig.line(x="Axis", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61',
                                 line_width=2, line_dash='dashed', legend_label='Refundable Child Tax Credit', muted_alpha=0.1, source=df_reform)
    cdcc_reform = fig.line(x="Axis", y="Child care credit", line_color='#d7191c', muted_color='#d7191c', line_width=2,
                           line_dash='dashed', legend_label='Child and Dependent Care Credit', muted_alpha=0.1, source=df_reform)

    ctc_base.muted = True
    ctc_refund_base.muted = True
    cdcc_base.muted = True
    ctc_reform.muted = True
    ctc_refund_reform.muted = True
    cdcc_reform.muted = True

    plot_js = """
    object1.visible = toggle.active
    object2.visible = toggle.active
    object3.visible = toggle.active
    object4.visible = toggle.active
    """
    base_callback = CustomJS(code=plot_js, args={})
    base_toggle = Toggle(label="Base (Solid)", button_type="default",
                         active=True)
    base_callback.args = {"toggle": base_toggle, "object1": eitc_base,
                          "object2": cdcc_base, "object3": ctc_base,
                          "object4": ctc_refund_base}
    base_toggle.js_on_change('active', base_callback)

    reform_callback = CustomJS(code=plot_js, args={})
    reform_toggle = Toggle(label="Reform (Dashed)", button_type="default",
                           active=True)
    reform_callback.args = {"toggle": reform_toggle, "object1": eitc_reform,
                            "object2": cdcc_reform, "object3": ctc_reform,
                            "object4": ctc_refund_reform}
    reform_toggle.js_on_change('active', reform_callback)

    fig.yaxis.formatter = NumeralTickFormatter(format="$0,000")
    fig.yaxis.axis_label = "Tax Credits"
    fig.xaxis.formatter = NumeralTickFormatter(format="$0,000")
    fig.xaxis.axis_label = mtr_opt
    fig.xaxis.minor_tick_line_color = None

    fig.legend.click_policy = "mute"

    layout = column(fig, row(base_toggle, reform_toggle))

    data = json_item(layout)

    outputs = {
        "media_type": "bokeh",
        "title": "Tax Credits by {} (Holding Other Inputs Constant)".format(mtr_opt),
        "data": data
    }

    return outputs

0 View Source File : restservice.py
License : Apache License 2.0
Project Creator : scaleoutsystems

    def run(self):
        """

        :return:
        """
        app = Flask(__name__)
        app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
        app.config['SECRET_KEY'] = self.SECRET_KEY

        @app.route('/')
        def index():
            """

            :return:
            """
            not_configured = self.check_configured()
            if not_configured:
                return not_configured
            events = self.control.get_events()
            message = request.args.get('message', None)
            message_type = request.args.get('message_type', None)
            return render_template('events.html', client=self.name, state=ReducerStateToString(self.control.state()),
                                   events=events,
                                   logs=None, refresh=True, configured=True, message=message, message_type=message_type)

        # http://localhost:8090/add?name=combiner&address=combiner&port=12080&token=e9a3cb4c5eaff546eec33ff68a7fbe232b68a192
        @app.route('/status')
        def status():
            """

            :return:
            """
            return {'state': ReducerStateToString(self.control.state())}

        @app.route('/netgraph')
        def netgraph():
            """
            Creates nodes and edges for network graph

            :return: nodes and edges as keys
            :rtype: dict
            """
            result = {'nodes': [], 'edges': []}

            result['nodes'].append({
                "id": "reducer",
                "label": "Reducer",
                "role": 'reducer',
                "status": 'active',
                "name": 'reducer', #TODO: get real host name
                "type": 'reducer',
            })
            
            combiner_info = combiner_status()
            client_info = client_status()

            if len(combiner_info)   <   1:
                return result
       
            for combiner in combiner_info:
                print("combiner info {}".format(combiner_info), flush=True)
                try:
                    result['nodes'].append({
                        "id": combiner['name'],  # "n{}".format(count),
                        "label": "Combiner ({} clients)".format(combiner['nr_active_clients']),
                        "role": 'combiner',
                        "status": 'active', #TODO: Hard-coded, combiner_info does not contain status
                        "name": combiner['name'],
                        "type": 'combiner',
                    })
                except Exception as err:
                    print(err)

            for client in client_info['active_clients']:
                try:
                    result['nodes'].append({
                        "id": str(client['_id']),
                        "label": "Client",
                        "role": client['role'],
                        "status": client['status'],
                        "name": client['name'],
                        "combiner": client['combiner'],
                        "type": 'client',
                    })
                except Exception as err:
                    print(err)
                
            count = 0
            for node in result['nodes']:
                try:
                    if node['type'] == 'combiner':
                        result['edges'].append(
                            {
                                "id": "e{}".format(count),
                                "source": node['id'],
                                "target": 'reducer',
                            }
                        )
                    elif node['type'] == 'client':
                        result['edges'].append(
                            {
                                "id": "e{}".format(count),
                                "source": node['combiner'],
                                "target": node['id'],
                            }
                        )
                except Exception as e:
                    pass
                count = count + 1
            return result

        @app.route('/networkgraph')
        def network_graph():
            from bokeh.embed import json_item
            try:
                plot = Plot(self.control.statestore)
                result = netgraph()
                df_nodes = pd.DataFrame(result['nodes'])
                df_edges = pd.DataFrame(result['edges'])
                graph = plot.make_netgraph_plot(df_edges, df_nodes)
                return json.dumps(json_item(graph, "myplot"))
            except:
                return ''

        @app.route('/events')
        def events():
            """

            :return:
            """
            import json
            from bson import json_util

            json_docs = []
            for doc in self.control.get_events():
                json_doc = json.dumps(doc, default=json_util.default)
                json_docs.append(json_doc)

            json_docs.reverse()
            return {'events': json_docs}

        @app.route('/add')
        def add():
            """ Add a combiner to the network. """
            if self.token_auth_enabled:
                self.authorize(request, app.config.get('SECRET_KEY'))
            if self.control.state() == ReducerState.setup:
                return jsonify({'status': 'retry'})

            # TODO check for get variables
            name = request.args.get('name', None)
            address = str(request.args.get('address', None))
            port = request.args.get('port', None)
            # token = request.args.get('token')
            # TODO do validation

            if port is None or address is None or name is None:
                return "Please specify correct parameters."

            # Try to retrieve combiner from db
            combiner = self.control.network.get_combiner(name)
            if not combiner:
                # Create a new combiner
                import base64
                certificate, key = self.certificate_manager.get_or_create(address).get_keypair_raw()
                cert_b64 = base64.b64encode(certificate)
                key_b64 = base64.b64encode(key)

                # TODO append and redirect to index.
                import copy
                combiner = CombinerInterface(self, name, address, port, copy.deepcopy(certificate), copy.deepcopy(key),
                                             request.remote_addr)
                self.control.network.add_combiner(combiner)

            combiner = self.control.network.get_combiner(name)

            ret = {
                'status': 'added',
                'certificate': combiner['certificate'],
                'key': combiner['key'],
                'storage': self.control.statestore.get_storage_backend(),
                'statestore': self.control.statestore.get_config(),
            }

            return jsonify(ret)

        @app.route('/eula', methods=['GET', 'POST'])
        def eula():
            """

            :return:
            """
            for r in request.headers:
                print("header contains: {}".format(r), flush=True)

            return render_template('eula.html', configured=True)

        @app.route('/models', methods=['GET', 'POST'])
        def models():
            """

            :return:
            """
            if request.method == 'POST':
                # upload seed file
                uploaded_seed = request.files['seed']
                if uploaded_seed:
                    from io import BytesIO
                    a = BytesIO()
                    a.seek(0, 0)
                    uploaded_seed.seek(0)
                    a.write(uploaded_seed.read())
                    helper = self.control.get_helper()
                    model = helper.load_model_from_BytesIO(a.getbuffer())
                    self.control.commit(uploaded_seed.filename, model)
            else:
                not_configured = self.check_configured()
                if not_configured:
                    return not_configured
                h_latest_model_id = self.control.get_latest_model()

                model_info = self.control.get_model_info()
                return render_template('models.html', h_latest_model_id=h_latest_model_id, seed=True,
                                       model_info=model_info, configured=True)

            seed = True
            return redirect(url_for('models', seed=seed))

        @app.route('/delete_model_trail', methods=['GET', 'POST'])
        def delete_model_trail():
            """

            :return:
            """
            if request.method == 'POST':
                from fedn.common.tracer.mongotracer import MongoTracer
                statestore_config = self.control.statestore.get_config()
                self.tracer = MongoTracer(statestore_config['mongo_config'], statestore_config['network_id'])
                try:
                    self.control.drop_models()
                except:
                    pass

                # drop objects in minio
                self.control.delete_bucket_objects()
                return redirect(url_for('models'))
            seed = True
            return redirect(url_for('models', seed=seed))

        @app.route('/drop_control', methods=['GET', 'POST'])
        def drop_control():
            """

            :return:
            """
            if request.method == 'POST':
                self.control.statestore.drop_control()
                return redirect(url_for('control'))
            return redirect(url_for('control'))

        # http://localhost:8090/control?rounds=4&model_id=879fa112-c861-4cb1-a25d-775153e5b548
        @app.route('/control', methods=['GET', 'POST'])
        def control():
            """ Main page for round control. Configure, start and stop global training rounds. """

            not_configured = self.check_configured()
            if not_configured:
                return not_configured
            client = self.name
            state = ReducerStateToString(self.control.state())
            logs = None
            refresh = True

            if self.remote_compute_context:
                try:
                    self.current_compute_context = self.control.get_compute_context()
                except:
                    self.current_compute_context = None
            else:
                self.current_compute_context = "None:Local"
            if self.control.state() == ReducerState.monitoring:
                return redirect(
                    url_for('index', state=state, refresh=refresh, message="Reducer is in monitoring state"))

            if request.method == 'POST':
                timeout = float(request.form.get('timeout', 180))
                rounds = int(request.form.get('rounds', 1))
                task = (request.form.get('task', ''))
                clients_required = request.form.get('clients_required', 1)
                clients_requested = request.form.get('clients_requested', 8)

                # checking if there are enough clients connected to start!
                clients_available = 0
                for combiner in self.control.network.get_combiners():
                    try: 
                        combiner_state = combiner.report()
                        nac = combiner_state['nr_active_clients']
                        clients_available = clients_available + int(nac)
                    except Exception as e:
                        pass

                if clients_available  <  clients_required:
                    return redirect(url_for('index', state=state,
                                            message="Not enough clients available to start rounds! "
                                                    "check combiner client capacity",
                                            message_type='warning'))

                validate = request.form.get('validate', False)
                if validate == 'False':
                    validate = False
                helper_type = request.form.get('helper', 'keras')
                # self.control.statestore.set_framework(helper_type)

                latest_model_id = self.control.get_latest_model()

                config = {'round_timeout': timeout, 'model_id': latest_model_id,
                          'rounds': rounds, 'clients_required': clients_required,
                          'clients_requested': clients_requested, 'task': task,
                          'validate': validate, 'helper_type': helper_type}

                import threading
                threading.Thread(target=self.control.instruct, args=(config,)).start()
                # self.control.instruct(config)
                return redirect(url_for('index', state=state, refresh=refresh, message="Sent execution plan.",
                                        message_type='SUCCESS'))

            else:
                seed_model_id = None
                latest_model_id = None
                try:
                    seed_model_id = self.control.get_first_model()[0]
                    latest_model_id = self.control.get_latest_model()
                except Exception as e:
                    pass

                return render_template('index.html', latest_model_id=latest_model_id,
                                       compute_package=self.current_compute_context,
                                       seed_model_id=seed_model_id,
                                       helper=self.control.statestore.get_framework(), validate=True, configured=True)

            client = self.name
            state = ReducerStateToString(self.control.state())
            logs = None
            refresh = False
            return render_template('index.html', client=client, state=state, logs=logs, refresh=refresh,
                                   configured=True)

        @app.route('/assign')
        def assign():
            """Handle client assignment requests. """
            if self.token_auth_enabled:
                self.authorize(request, app.config.get('SECRET_KEY'))

            response = self.check_configured_response()

            if response:
                return response


            name = request.args.get('name', None)
            combiner_preferred = request.args.get('combiner', None)

            if combiner_preferred:
                combiner = self.control.find(combiner_preferred)
            else:
                combiner = self.control.find_available_combiner()

            if combiner is None:
                return jsonify({'status': 'retry',
                                'package': self.package,
                                'msg': "Failed to assign to a combiner, try again later."})

            client = {
                'name': name,
                'combiner_preferred': combiner_preferred,
                'combiner': combiner.name,
                'ip': request.remote_addr,
                'status': 'available'
            }

            # Add client to database 
            self.control.network.add_client(client)

            # Return connection information to client
            import base64
            cert_b64 = base64.b64encode(combiner.certificate)
            response = {
                'status': 'assigned',
                'host': combiner.address,
                'package': self.package,
                'ip': combiner.ip,
                'port': combiner.port,
                'certificate': str(cert_b64).split('\'')[1],
                'model_type': self.control.statestore.get_framework()
            }

            return jsonify(response)

        @app.route('/infer')
        def infer():
            """

            :return:
            """
            if self.control.state() == ReducerState.setup:
                return "Error, not configured"
            result = ""
            try:
                self.control.set_model_id()
            except fedn.exceptions.ModelError:
                print("Failed to seed control.")

            return result

        def combiner_status():
            """ Get current status reports from all combiners registered in the network. 

            :return:
            """
            combiner_info = []
            for combiner in self.control.network.get_combiners():
                try:
                    report = combiner.report()
                    combiner_info.append(report)
                except:
                    pass
            return combiner_info

        def client_status():
            """
            Get current status of clients (available) from DB compared with client status from all combiners,
            update client status to DB and add their roles.
            """
            client_info = self.control.network.get_client_info()
            combiner_info = combiner_status()
            try:
                all_active_trainers = []
                all_active_validators = []

                for client in combiner_info:
                    active_trainers_str = client['active_trainers']
                    active_validators_str = client['active_validators']
                    active_trainers_str = re.sub('[^a-zA-Z0-9-:\n\.]', '', active_trainers_str).replace('name:', ' ')
                    active_validators_str = re.sub('[^a-zA-Z0-9-:\n\.]', '', active_validators_str).replace('name:', ' ')
                    all_active_trainers.extend(' '.join(active_trainers_str.split(" ")).split())
                    all_active_validators.extend(' '.join(active_validators_str.split(" ")).split())

                active_trainers_list = [client for client in client_info if client['name'] in all_active_trainers]
                active_validators_list = [cl for cl in client_info if cl['name'] in all_active_validators]
                all_clients = [cl for cl in client_info]

                for client in all_clients:
                    status = 'offline'
                    role = 'None'
                    self.control.network.update_client_data(client, status, role)

                all_active_clients = active_validators_list + active_trainers_list
                for client in all_active_clients:
                    status = 'active'
                    if client in active_trainers_list and client in active_validators_list:
                        role = 'trainer-validator'
                    elif client in active_trainers_list:
                        role = 'trainer'
                    elif client in active_validators_list:
                        role = 'validator'
                    else:
                        role = 'unknown'
                    self.control.network.update_client_data(client, status, role)

                return {'active_clients': all_clients,
                        'active_trainers': active_trainers_list,
                        'active_validators': active_validators_list
                        }
            except:
                 pass

            return {'active_clients': [],
                    'active_trainers': [],
                    'active_validators': []
                    }

        @app.route('/metric_type', methods=['GET', 'POST'])
        def change_features():
            """

            :return:
            """
            feature = request.args['selected']
            plot = Plot(self.control.statestore)
            graphJSON = plot.create_box_plot(feature)
            return graphJSON

        @app.route('/dashboard')
        def dashboard():
            """

            :return:
            """
            not_configured = self.check_configured()
            if not_configured:
                return not_configured

            plot = Plot(self.control.statestore)
            try:
                valid_metrics = plot.fetch_valid_metrics()
                box_plot = plot.create_box_plot(valid_metrics[0])
            except Exception as e:
                valid_metrics = None
                box_plot = None
                print(e, flush=True)
            table_plot = plot.create_table_plot()
            # timeline_plot = plot.create_timeline_plot()
            timeline_plot = None
            clients_plot = plot.create_client_plot()
            return render_template('dashboard.html', show_plot=True,
                                   box_plot=box_plot,
                                   table_plot=table_plot,
                                   timeline_plot=timeline_plot,
                                   clients_plot=clients_plot,
                                   metrics=valid_metrics,
                                   configured=True
                                   )

        @app.route('/network')
        def network():
            """

            :return:
            """
            not_configured = self.check_configured()
            if not_configured:
                return not_configured
            plot = Plot(self.control.statestore)
            round_time_plot = plot.create_round_plot()
            mem_cpu_plot = plot.create_cpu_plot()
            combiners_plot = plot.create_combiner_plot()
            combiner_info = combiner_status()
            active_clients = client_status()
            return render_template('network.html', network_plot=True,
                                   round_time_plot=round_time_plot,
                                   mem_cpu_plot=mem_cpu_plot,
                                   combiners_plot=combiners_plot,
                                   combiner_info=combiner_info,
                                   active_clients=active_clients['active_clients'],
                                   active_trainers=active_clients['active_trainers'],
                                   active_validators=active_clients['active_validators'],
                                   configured=True
                                   )

        @app.route('/config/download', methods=['GET'])
        def config_download():
            """

            :return:
            """
            chk_string = ""
            name = self.control.get_compute_context()
            if name is None or name == '':
                chk_string = ''
            else:
                file_path = os.path.join(UPLOAD_FOLDER, name)
                print("trying to get {}".format(file_path))
                from fedn.utils.checksum import md5

                try:
                    sum = str(md5(file_path))
                except FileNotFoundError as e:
                    sum = ''
                chk_string = "checksum: {}".format(sum)

            network_id = self.network_id
            discover_host = self.name
            discover_port = self.port
            ctx = """network_id: {network_id}
controller:
    discover_host: {discover_host}
    discover_port: {discover_port}
    {chk_string}""".format(network_id=network_id,
                           discover_host=discover_host,
                           discover_port=discover_port,
                           chk_string=chk_string)

            from io import BytesIO
            from flask import send_file
            obj = BytesIO()
            obj.write(ctx.encode('UTF-8'))
            obj.seek(0)
            return send_file(obj,
                             as_attachment=True,
                             attachment_filename='client.yaml',
                             mimetype='application/x-yaml')

        @app.route('/context', methods=['GET', 'POST'])
        def context():
            """

            :return:
            """
            # if self.control.state() != ReducerState.setup or self.control.state() != ReducerState.idle:
            #    return "Error, Context already assigned!"
            reset = request.args.get('reset', None)  # if reset is not empty then allow context re-set
            if reset:
                return render_template('context.html')

            if request.method == 'POST':

                if 'file' not in request.files:
                    flash('No file part')
                    return redirect(url_for('context'))

                file = request.files['file']
                helper_type = request.form.get('helper', 'keras')
                # if user does not select file, browser also
                # submit an empty part without filename
                if file.filename == '':
                    flash('No selected file')
                    return redirect(url_for('context'))

                if file and allowed_file(file.filename):
                    filename = secure_filename(file.filename)
                    file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
                    file.save(file_path)

                    if self.control.state() == ReducerState.instructing or self.control.state() == ReducerState.monitoring:
                        return "Not allowed to change context while execution is ongoing."

                    self.control.set_compute_context(filename, file_path)
                    self.control.statestore.set_framework(helper_type)
                    return redirect(url_for('control'))

            from flask import send_from_directory
            name = request.args.get('name', '')

            if name == '':
                name = self.control.get_compute_context()
                if name == None or name == '':
                    return render_template('context.html')

            # There is a potential race condition here, if one client requests a package and at
            # the same time another one triggers a fetch from Minio and writes to disk. 
            try:
                mutex = Lock()
                mutex.acquire()
                return send_from_directory(app.config['UPLOAD_FOLDER'], name, as_attachment=True)
            except:
                try:
                    data = self.control.get_compute_package(name)
                    file_path = os.path.join(app.config['UPLOAD_FOLDER'], name)
                    with open(file_path, 'wb') as fh:
                        fh.write(data)
                    return send_from_directory(app.config['UPLOAD_FOLDER'], name, as_attachment=True)
                except:
                    raise
            finally:
                mutex.release()

            return render_template('context.html')

        @app.route('/checksum', methods=['GET', 'POST'])
        def checksum():
            """

            :return:
            """
            # sum = ''
            name = request.args.get('name', None)
            if name == '' or name is None:
                name = self.control.get_compute_context()
                if name == None or name == '':
                    return jsonify({})

            file_path = os.path.join(UPLOAD_FOLDER, name)
            print("trying to get {}".format(file_path))
            from fedn.utils.checksum import md5

            try:
                sum = str(md5(file_path))
            except FileNotFoundError as e:
                sum = ''

            data = {'checksum': sum}
            from flask import jsonify
            return jsonify(data)

        if self.certificate:
            print("trying to connect with certs {} and key {}".format(str(self.certificate.cert_path),
                                                                      str(self.certificate.key_path)), flush=True)
            app.run(host="0.0.0.0", port=self.port,
                    ssl_context=(str(self.certificate.cert_path), str(self.certificate.key_path)))
        
        return app

0 View Source File : analyze.py
License : GNU General Public License v3.0
Project Creator : varadaio

def main():
    p = argparse.ArgumentParser()
    p.add_argument(
        "-i",
        "--input-file",
        type=pathlib.Path,
        help="Path to the extracted JSONL file (the output of extract.py)",
    )
    p.add_argument(
        "-o",
        "--output-file",
        type=pathlib.Path,
        default="./output.zip",
        help="Path to the resulting zipped HTML report",
    )
    p.add_argument("-l", "--limit", type=int)
    p.add_argument("--filter", type=str)
    p.add_argument("--fail-on-error", action="store_true", default=False)
    p.add_argument("--high-contrast-mode", action="store_true", default=False)
    p.add_argument("-q", "--quiet", action="store_true", default=False)
    args = p.parse_args()

    log.info(
        "loading {} = {:.3f} MB", args.input_file, args.input_file.stat().st_size / 1e6
    )
    if args.input_file.name.endswith(".gz"):
        lines = gzip.open(args.input_file.open("rb"), "rt")
    else:
        lines = args.input_file.open("rt")

    if args.limit:
        lines = itertools.islice(lines, args.limit)

    lines = list(lines)
    stats = []
    for line in tqdm(lines, unit="files", disable=args.quiet):
        s = json.loads(line)
        if s["state"] == "FAILED":
            continue
        stats.append(s)
    log.info("{} queries loaded", len(stats))

    metrics = collect_metrics(stats)
    charts = []
    scripts = []
    for func in tqdm(_ANALYZERS, unit="graphs", disable=args.quiet):
        graph_id = func.__name__
        if args.filter is None or args.filter == func.__name__:
            try:
                if 'colorblind' in signature(func).parameters:
                    p = func(stats, colorblind=args.high_contrast_mode)
                else:
                    p = func(stats)

                if p is None:
                    log.warn("not enough data for {}", graph_id)
                    continue
                item = json_item(model=p, target=graph_id)
                item["doc"]["roots"]["references"].sort(key=lambda r: (r["type"], r["id"]))

                item = json.dumps({"doc": item["doc"]})
                scripts.append(
                    '  <  script type="application/json" id="{}">\n{}\n < /script>\n'.format(
                        graph_id, item
                    )
                )
                charts.append(
                    {
                        "title": p.title.text or graph_id,
                        "description": func.__doc__.strip(),
                        "id": graph_id,
                    }
                )
            except Exception:
                log.exception("failed to generate {}", graph_id)
                if args.fail_on_error:
                    raise

    scripts.append(
        " < script>\nconst structure = {} < /script>".format(
            json.dumps({"metrics": metrics, "charts": charts}, indent=4)
        )
    )

    template = pathlib.Path(__file__).parent / "output.template.html"
    placeholder = " < !-- PLACEHOLDER_FOR_BOKEH_JSONS -->"
    output = template.open().read().replace(placeholder, "\n".join(scripts))
    log.info("report is written to {}", args.output_file)
    suffix = args.output_file.suffix
    if suffix == ".zip":
        with zipfile.ZipFile(args.output_file, "w") as f:
            f.writestr("output.html", data=output, compress_type=zipfile.ZIP_DEFLATED)
    elif suffix == ".html":
        with open(args.output_file, "w") as f:
            f.write(output)
    else:
        raise ValueError("Unsupport output file extension: {}".format(args.output_file))


if __name__ == "__main__":