], style={'display': 'flex'}),
                                html.Div([
                                        html.Div([ ], id='plot4'),
                                        html.Div([ ], id='plot5')
                               ], style={'display': 'flex'})
                                # TODO3: Add a division with two empty divisions inside. See above disvision for example.
                               

# Callback function definition
# TODO4: Add 5 ouput components
@app.callback( [Output(component_id='plot1', component_property='children'),
                Output(component_id='plot2', component_property='children'),
                Output(component_id='plot3', component_property='children'),
                Output(component_id='plot4', component_property='children'),
                Output(component_id='plot5', component_property='children')],
               [Input(component_id='input-type', component_property='value'),
                Input(component_id='input-year', component_property='value')],
               # REVIEW4: Holding output state till user enters all the form information. In this case, it will be chart type and year
               [State("plot1", 'children'), State("plot2", "children"),
                State("plot3", "children"), State("plot4", "children"),
                State("plot5", "children")
])
# Add computation to callback function and return graph
def get_graph(chart, year, children1, children2, c3, c4, c5):
                                    # Select data
                                    df =  airline_data[airline_data['Year']==int(year)]
                                    if chart == 'OPT1':
                                    # Compute required information for creating graph from the data
                                    bar_data, line_data, div_data, map_data, tree_data = compute_data_choice_1(df)
                                    
                                    # Number of flights under different cancellation categories
                                    bar_fig = px.bar(bar_data, x='Month', y='Flights', color='CancellationCode', title='Monthly Flight Cancellation')
예제 #2
0
    def init_app(self):

        app = JupyterDash(__name__)
        # app = dash.Dash()
        app.css.config.serve_locally = True
        app.scripts.config.serve_locally = True

        # self.add_rec(['main', 'MLPClassifier'], 'alpha=0.1', self.icicle_data)
        # self.add_rec(['main', 'MLPClassifier'], 'alpha=0.01', self.icicle_data)

        def df_to_dict(ut):
            data = {}
            for col_name in self.hierarchy_path:
                for i, g in ut.groupby(col_name):
                    data_key = g[col_name].iloc[0]
                    data[data_key] = {}

        data = copy.deepcopy(self.icicle_data)

        icicle_plot_fig = icicle_plot.Icicle(id='icicle_plot_fig',
                                             value='main/',
                                             label='my-label',
                                             low=self.low_color,
                                             high=self.high_color,
                                             data=data)

        def make_ints(row):
            for col in self.hierarchy_path:
                if row[col] != None:
                    try:
                        row[col] = float(row[col].split("=")[1])
                    except:
                        row[col]
            return row

        pc_data_numeric = self.pc_data.apply(make_ints, axis=1)

        pc = go.Figure(data=[go.Scatter(x=[], y=[])])
        if self.pc_data is not 0 and not self.pc_data.empty:
            pc = px.parallel_coordinates(pc_data_numeric.apply(make_ints,
                                                               axis=1),
                                         color="accuracy",
                                         dimensions=self.hierarchy_path +
                                         ['accuracy'],
                                         color_continuous_scale='RdBu',
                                         height=350)
        pc_o = pc

        marks = {}
        for i in range(0, 100, 10):
            marks[i / 100] = str(i / 100)

        button_style = {
            "background-color": "#008CBA",
            "border": "none",
            "color": "white",
            "padding": "15px 32px",
            "text-align": "center",
            "display": "inline-block",
            "font-size": 16,
            "margin": "4px 2px",
            "cursor": "pointer",
            "width": "150px",
            "border-radius": "5%"
        }

        app.layout = html.Div(
            [
                html.Div(
                    [
                        html.Div(icicle_plot_fig, id='icicle-wrap'),
                        dcc.Graph(id='pc', figure=pc, style={'height': 350}),
                        dcc.Interval(
                            id='interval-component',
                            interval=1000,  # in milliseconds
                            n_intervals=0),
                        dcc.Interval(
                            id='interval-component2',
                            interval=1000,  # in milliseconds
                            n_intervals=0),
                        dcc.Interval(id='interval-loading',
                                     interval=100,
                                     n_intervals=0),
                        html.H3('Sand Box', id='sandboxtext'),
                        dcc.Textarea(id='sandbox',
                                     value='',
                                     style={
                                         'height': 120,
                                         'width': '90%'
                                     }),
                        html.Div([
                            html.Button('Execute',
                                        id='execute-button',
                                        style=button_style),
                            dcc.Loading(id="loading",
                                        children=html.Div(
                                            [html.Div(id='output')]),
                                        type="circle",
                                        style={'margin-bottom': '6%'})
                        ])
                    ],
                    style={
                        'width': '87%',
                        'height': '100%',
                        'float': 'left'
                    }),
                html.Div([
                    dcc.RangeSlider(id='metric-slider',
                                    min=0,
                                    max=1,
                                    step=0.01,
                                    value=[0, 1],
                                    marks=marks,
                                    vertical=True,
                                    verticalHeight=500)
                ],
                         style={
                             'margin-left': '90%',
                             'margin-top': '2%'
                         })
                # html.Div([
                #         html.H3('Sand Box', id='sandboxtext', style={"text-align": 'center'}),
                #         dcc.Textarea(
                #             id='sandbox',
                #             value='',
                #             style={'height': 400}
                #         ),
                #         html.Div([
                #             html.Button('Execute', id='execute-button', style=button_style),
                #             dcc.Loading(
                #                 id="loading",
                #                 children=html.Div([
                #                     html.Div(id='output')
                #                 ]),
                #                 type="circle"
                #             )
                #         ], style= {'right': 37, 'position': 'absolute'})
                #     ], style={'margin-left': '5%'})
            ],
            style={
                'height': '100%',
                'overflow': 'hidden'
            })

        @app.callback(Output('icicle-wrap', 'children'), [
            Input('metric-slider', 'value'),
            Input('interval-component', 'n_intervals')
        ])
        def update_icicle(rangeData, n):
            trigger_context = dash.callback_context.triggered[0]['prop_id']
            if len(dash.callback_context.triggered
                   ) <= 1 and self.update_available == False and (
                       trigger_context == 'interval-component.n_intervals'
                       or trigger_context == '.'):
                raise PreventUpdate

            # revert to original state
            data = copy.deepcopy(self.icicle_data)
            # print(data)
            if not self.pc_data.empty:
                # delete entries
                self.remove_nodes_out_of_range(rangeData[0], rangeData[1],
                                               data)
                filtered_accs = self.pc_data.query(
                    "accuracy >= " + str(rangeData[0]) + " and accuracy <= " +
                    str(rangeData[1]))['accuracy']
                self.low_color = filtered_accs.min()
                self.high_color = filtered_accs.max()
                if rangeData != self.rangeDataOld:
                    self.id_updater += 1
                    self.rangeDataOld = rangeData

            if self.update_available:
                # print("update vailable")
                self.id_updater += 1
                self.update_available = False

            # id is dictionary for Dash pattern matching callbacks
            return icicle_plot.Icicle(id={
                'role': 'icicle_plot_fig',
                'index': self.id_updater
            },
                                      value='main/',
                                      label='my-label',
                                      low=self.low_color,
                                      high=self.high_color,
                                      data=data)

        @app.callback(Output('pc', 'figure'), [
            Input({
                'role': 'icicle_plot_fig',
                'index': ALL
            }, 'value'),
            Input('metric-slider', 'value'),
            Input('interval-component2', 'n_intervals')
        ])
        def update_pc(clickData, rangeData, n):
            if self.pc_data.empty:
                return go.Figure(data=[go.Scatter(x=[], y=[])])
            trigger_context = dash.callback_context.triggered[0]['prop_id']
            if len(dash.callback_context.triggered
                   ) <= 1 and self.update_available == False and (
                       trigger_context == 'interval-component2.n_intervals'):
                raise PreventUpdate

            pc_data_copy = self.pc_data

            if len(clickData) == 0:
                if self.update_available:
                    pc = px.parallel_coordinates(
                        pc_data_copy.apply(make_ints, axis=1),
                        color="accuracy",
                        dimensions=self.hierarchy_path + ['accuracy'],
                        color_continuous_scale='RdBu',
                        height=350)
                    return pc
                raise PreventUpdate
                # return self.pc
                # revert to original state
            # delete entries
            pc_data_copy = pc_data_copy.query("accuracy >= " +
                                              str(rangeData[0]) +
                                              " and accuracy <= " +
                                              str(rangeData[1]))

            if isinstance(clickData, list):
                clickData = clickData[0]

            if 'recommendationval' in clickData:
                raise PreventUpdate

            if clickData.split("/")[:-2] == []:
                pc = px.parallel_coordinates(pc_data_copy.apply(make_ints,
                                                                axis=1),
                                             color="accuracy",
                                             dimensions=self.hierarchy_path +
                                             ['accuracy'],
                                             color_continuous_scale='RdBu',
                                             height=350)
                return pc
            if clickData:
                click_path = clickData.split("/")[:-1][1:]
                subset_counter = len(click_path)
                if click_path == []:
                    return pc_o

                selected_df = pc_data_copy
                j = -1
                for i in click_path:
                    j += 1
                    if "=" in i:
                        comps_name = i.split("=")
                        hyp_name = comps_name[0]
                        hyp_val = comps_name[1]
                        selected_df = selected_df[selected_df.apply(
                            lambda x: x['model_params'][hyp_name] == hyp_val
                            if hyp_name in x['model_params'] else False,
                            axis=1)]
                    else:
                        selected_df = selected_df[selected_df['model'] == i]
                sample_vals = selected_df.iloc[0]
                labels_pc = {}
                for i in self.hierarchy_path[subset_counter:]:
                    if sample_vals[i]:
                        labels_pc[i] = sample_vals[i].split("=")[0]

                selected_df = selected_df.apply(make_ints, axis=1)
                self.pc = px.parallel_coordinates(
                    selected_df,
                    color="accuracy",
                    dimensions=self.hierarchy_path[subset_counter:] +
                    ['accuracy'],
                    labels=labels_pc,
                    color_continuous_scale='RdBu',
                    height=350)
                # print(pc_data_copy.apply(make_ints, axis=1))
                return self.pc
            self.pc = px.parallel_coordinates(pc_data_copy.apply(make_ints,
                                                                 axis=1),
                                              color="accuracy",
                                              dimensions=self.hierarchy_path +
                                              ['accuracy'],
                                              color_continuous_scale='RdBu',
                                              height=350)
            return self.pc

        @app.callback(
            Output('sandbox', 'value'),
            [Input({
                'role': 'icicle_plot_fig',
                'index': ALL
            }, 'value')])
        def update_sandbox(clickData):
            if len(clickData) == 0:
                raise PreventUpdate

            if isinstance(clickData, list):
                clickData = clickData[0]
            if 'recommendationval' in clickData:
                # update the sand box
                clickData = clickData.replace(" recommendationval", "")
                model_name = ""
                params_rec = {}
                for i in clickData.split("/"):
                    if 'main' in i or not i or not i.strip():
                        continue

                    # model name
                    if '=' not in i:
                        model_name = i
                        continue

                    try:
                        params_rec[i.split("=")[0]] = float(i.split(
                            "=")[1])  # for int, long, float and complex
                        if params_rec[i.split("=")[0]].is_integer():
                            params_rec[i.split("=")[0]] = int(
                                params_rec[i.split("=")[0]])
                    except ValueError:
                        params_rec[i.split("=")[0]] = i.split("=")[1]

                code = "app.experiment(\nlibrary = 'sklearn',\nmodel = " + model_name + ",\nparams = \n" + str(
                    params_rec).replace('{', '{\n  ').replace(
                        ',', ',\n ').replace('}',
                                             '\n}') + ",\nhighlighted = True)"
                return code
            else:
                raise PreventUpdate

        @app.callback(Output('execute-button', 'style'),
                      [Input('interval-loading', 'n_intervals')])
        def check_execution(n_intervals):

            button_style = {
                "background-color": "#008CBA",
                "border": "none",
                "color": "white",
                "padding": "15px 32px",
                "text-align": "center",
                "display": "inline-block",
                "font-size": 16,
                "margin": "4px 2px",
                "cursor": "pointer",
                "width": "150px",
                "border-radius": "5%"
            }

            if not self.running_experiment and not self.running_recommendation:
                return button_style

            if self.running_recommendation:
                button_style['visibility'] = "hidden"
                button_style["cursor"] = 'not-allowed'
                button_style['pointer-events'] = "none"
                return button_style

            button_style["cursor"] = 'not-allowed'
            button_style['pointer-events'] = "none"
            button_style["opacity"] = 0.5
            return button_style

        # execute button handler
        app.callback(Output('output',
                            'value'), [Input('execute-button', 'n_clicks')],
                     [State('sandbox', 'value')])(self.execute_code)

        self.app = app