Exemplo n.º 1
0
def build_tab(label, value, additional_style=None, **kwargs):
    """
    Builds a :dash:`dash_core_components.Tab <dash-core-components/tab>` with standard styling settings.
    """
    base_style = {"borderBottom": "1px solid #d6d6d6", "padding": "6px"}
    return dcc.Tab(label=label,
                   value=value,
                   style=dict_merge(base_style, {"fontWeight": "bold"},
                                    additional_style or {}),
                   disabled_style=dict_merge(
                       base_style,
                       {
                           "fontWeight": "bold",
                           "backgroundColor": "LightGray",
                           "color": "black",
                           "cursor": "not-allowed",
                       },
                       additional_style or {},
                   ),
                   selected_style=dict_merge(
                       base_style,
                       {
                           "borderTop": "1px solid #d6d6d6",
                           "backgroundColor": "#2a91d1",
                           "color": "white",
                       },
                       additional_style or {},
                   ),
                   **kwargs)
Exemplo n.º 2
0
def scatter_builder(data, x, y, axes_builder, wrapper, group=None, z=None, agg=None):
    """
    Builder function for :plotly:`plotly.graph_objects.Scatter <plotly.graph_objects.Scatter>`

    :param data: raw data to be represented within scatter chart
    :type data: dict
    :param x: column to use for the X-Axis
    :type x: str
    :param y: columns to use for the Y-Axes
    :type y: list of str
    :param axes_builder: function for building axis configurations
    :type axes_builder: func
    :param wrapper: wrapper function returned by :meth:`dtale.charts.utils.chart_wrapper`
    :type wrapper: func
    :param z: column to use for the Z-Axis
    :type z: str
    :param group: column(s) to use for grouping
    :type group: list of str or str
    :param agg: points to a specific function that can be applied to
                :func: pandas.core.groupby.DataFrameGroupBy.  Possible values are: count, first, last mean,
                median, min, max, std, var, mad, prod, sum
    :type agg: str
    :return: scatter chart
    :rtype: :plotly:`plotly.graph_objects.Scatter <plotly.graph_objects.Scatter>`
    """

    def layout(axes):
        if z is not None:
            return {'height': 700, 'margin': {'l': 0, 'r': 0, 'b': 0},
                    'scene': dict_merge(axes, dict(aspectmode='data'))}
        return axes

    def marker(series):
        if z is not None:
            return {'size': 8, 'color': series[z], 'colorscale': 'Blackbody', 'opacity': 0.8,
                    'showscale': True, 'colorbar': {'thickness': 15, 'len': 0.5, 'x': 0.8, 'y': 0.6}}
        return {'size': 15, 'line': {'width': 0.5, 'color': 'white'}}

    scatter_func = go.Scatter3d if z is not None else go.Scatter
    return [
        wrapper(dcc.Graph(
            id='scatter-{}-{}'.format(group or 'all', y2),
            figure={'data': [
                scatter_func(**dict_merge(
                    dict(x=d['x'], y=d[y2], mode='markers', opacity=0.7, name=series_key, marker=marker(d)),
                    dict(z=d[z]) if z is not None else dict())
                )
                for series_key, d in data['data'].items() if y2 in d and (group is None or group == series_key)
            ], 'layout': build_layout(dict_merge(build_title(x, y2, group, z=z, agg=agg), layout(axes_builder([y2]))))}
        ))
        for y2 in y
    ]
Exemplo n.º 3
0
def build_grouped_bars_with_multi_yaxis(series_cfgs, y):
    """
    This generator is a hack for the lack of support plotly has for sorting
    :plotly:`plotly.graph_objects.Bar <plotly.graph_objects.Bar>` charts by an axis other than 'y'.  This
    also helps with issues around displaying multiple y-axis.

    :param series_cfgs: configurations for all the series within a bar chart
    :type series_cfgs: list of dict
    :param y: columns to use for the Y-Axes
    :type y: list of str
    :return: updated series configurations
    :type: generator
    """
    for i, y2 in enumerate(y, 1):
        for series in series_cfgs:
            curr_y = series.get('yaxis')
            yaxis = 'y{}'.format(i)
            if (i == 1 and curr_y is None) or (yaxis == curr_y):
                yield series
            else:
                yield dict_merge(
                    {
                        k: v
                        for k, v in series.items()
                        if k in ['x', 'name', 'type']
                    }, dict(hoverinfo='none', showlegend=False, y=[0]),
                    dict(yaxis=yaxis) if i > 1 else {})
Exemplo n.º 4
0
 def main_input_class(
     ts_, ts2_, _ts3, _ts4, pathname, inputs, map_inputs, cs_inputs, treemap_inputs
 ):
     return main_inputs_and_group_val_display(
         dict_merge(inputs, map_inputs, cs_inputs, treemap_inputs),
         get_data_id(pathname),
     )
Exemplo n.º 5
0
    def test_client(self,
                    reaper_on=False,
                    port=None,
                    app_root=None,
                    *args,
                    **kwargs):
        """
        Overriding Flask's implementation of test_client so we can specify ports for testing and
        whether auto-reaper should be running

        :param reaper_on: whether to run auto-reaper subprocess
        :type reaper_on: bool
        :param port: port number of flask application
        :type port: int
        :param args: Optional arguments to be passed to :meth:`flask:flask.Flask.test_client`
        :param kwargs: Optional keyword arguments to be passed to :meth:`flask:flask.Flask.test_client`
        :return: Flask's test client
        :rtype: :class:`dtale.app.DtaleFlaskTesting`
        """
        self.reaper_on = reaper_on
        self.app_root = app_root
        if app_root is not None:
            self.config["APPLICATION_ROOT"] = app_root
            self.jinja_env.globals["url_for"] = self.url_for
        self.test_client_class = DtaleFlaskTesting
        return super(DtaleFlask,
                     self).test_client(*args,
                                       **dict_merge(kwargs, dict(port=port)))
Exemplo n.º 6
0
 def on_data(
     _ts1,
     _ts2,
     _ts3,
     _ts4,
     pathname,
     inputs,
     chart_inputs,
     yaxis_data,
     map_data,
     last_chart_inputs,
 ):
     """
     dash callback controlling the building of dash charts
     """
     all_inputs = dict_merge(inputs, chart_inputs,
                             dict(yaxis=yaxis_data or {}), map_data)
     if all_inputs == last_chart_inputs:
         raise PreventUpdate
     if is_app_root_defined(dash_app.server.config.get("APPLICATION_ROOT")):
         all_inputs["app_root"] = dash_app.server.config["APPLICATION_ROOT"]
     charts, range_data, code = build_chart(get_data_id(pathname),
                                            **all_inputs)
     return (
         charts,
         all_inputs,
         range_data,
         "\n".join(make_list(code)),
         get_yaxis_type_tabs(make_list(inputs.get("y") or [])),
     )
Exemplo n.º 7
0
    def build_pies():
        for series_key, series in data['data'].items():
            for y2 in y:
                negative_values = []
                for x_val, y_val in zip(series['x'], series[y2]):
                    if y_val < 0:
                        negative_values.append('{} ({})'.format(x_val, y_val))

                chart = wrapper(dcc.Graph(
                    id='pie-{}-graph'.format(series_key),
                    figure={
                        'data': [go.Pie(**dict_merge(
                            dict(labels=series['x'], values=series[y2]), name_builder(y2, series_key)
                        ))],
                        'layout': build_layout(build_title(x, y2, group=series_key, agg=inputs.get('agg')))
                    }
                ))
                if len(negative_values):
                    error_title = (
                        'The following negative values could not be represented within the {}Pie chart'
                    ).format('' if series_key == 'all' else '{} '.format(series_key))
                    error_div = html.Div([
                        html.I(className='ico-error'),
                        html.Span(error_title),
                        html.Div(html.Pre(', '.join(negative_values)), className='traceback')
                    ], className='dtale-alert alert alert-danger')
                    yield html.Div(
                        [html.Div(error_div, className='col-md-12'), html.Div(chart, className='col-md-12')],
                        className='row'
                    )
                else:
                    yield chart
Exemplo n.º 8
0
 def main_input_class(
     _ts,
     _ts2,
     _ts3,
     _ts4,
     _ts5,
     _ts6,
     _ts7,
     inputs,
     map_inputs,
     cs_inputs,
     treemap_inputs,
     funnel_inputs,
     clustergram_inputs,
     pareto_inputs,
 ):
     return main_inputs_and_group_val_display(
         dict_merge(
             inputs,
             map_inputs,
             cs_inputs,
             treemap_inputs,
             funnel_inputs,
             clustergram_inputs,
             pareto_inputs,
         ))
Exemplo n.º 9
0
def build_show_options(options=None):

    defaults = dict(
        host=None,
        port=None,
        debug=False,
        subprocess=True,
        reaper_on=True,
        open_browser=False,
        notebook=False,
        force=False,
        ignore_duplicate=False,
        app_root=None,
        allow_cell_edits=True,
        inplace=False,
        drop_index=False,
        precision=2,
    )
    config_options = {}
    config = get_config()
    if config and config.has_section("show"):
        config_options["host"] = get_config_val(config, defaults, "host")
        config_options["port"] = get_config_val(config, defaults, "port")
        config_options["debug"] = get_config_val(
            config, defaults, "debug", "getboolean"
        )
        config_options["subprocess"] = get_config_val(
            config, defaults, "subprocess", "getboolean"
        )
        config_options["reaper_on"] = get_config_val(
            config, defaults, "reaper_on", "getboolean"
        )
        config_options["open_browser"] = get_config_val(
            config, defaults, "open_browser", "getboolean"
        )
        config_options["notebook"] = get_config_val(
            config, defaults, "notebook", "getboolean"
        )
        config_options["force"] = get_config_val(
            config, defaults, "force", "getboolean"
        )
        config_options["ignore_duplicate"] = get_config_val(
            config, defaults, "ignore_duplicate", "getboolean"
        )
        config_options["app_root"] = get_config_val(config, defaults, "app_root")
        config_options["allow_cell_edits"] = get_config_val(
            config, defaults, "allow_cell_edits", "getboolean"
        )
        config_options["inplace"] = get_config_val(
            config, defaults, "inplace", "getboolean"
        )
        config_options["drop_index"] = get_config_val(
            config, defaults, "drop_index", "getboolean"
        )
        config_options["precision"] = get_config_val(
            config, defaults, "precision", "getint"
        )

    return dict_merge(defaults, config_options, options)
Exemplo n.º 10
0
 def _format_dtype(col_index, col):
     dtype = dtypes[col]
     dtype_data = dict(name=col, dtype=dtype, index=col_index)
     if classify_type(dtype) == 'F' and not data[col].isnull().all():  # floats
         col_ranges = ranges[col]
         if not any((np.isnan(v) or np.isinf(v) for v in col_ranges.values())):
             dtype_data = dict_merge(ranges[col], dtype_data)
     return dtype_data
Exemplo n.º 11
0
def graph_wrapper(modal=False, export=False, **kwargs):
    global CHART_IDX

    curr_style = kwargs.pop("style", None) or {}
    if modal or export:
        id = "{}-chart".format("modal" if modal else "export")
        return dcc.Graph(id=id,
                         style=dict_merge({"height": "100%"}, curr_style),
                         **kwargs)

    CHART_IDX += 1
    graph = dcc.Graph(id="chart-{}".format(CHART_IDX),
                      style=dict_merge({"height": "100%"}, curr_style),
                      **kwargs)
    graph.figure["id"] = "chart-figure-{}".format(CHART_IDX)
    click_data_store = dcc.Store(id="chart-click-data-{}".format(CHART_IDX))
    return [graph, click_data_store, build_drilldown_modal(CHART_IDX)]
Exemplo n.º 12
0
 def on_data(_ts1, _ts2, _ts3, pathname, inputs, chart_inputs, yaxis_data, last_chart_inputs):
     """
     dash callback controlling the building of dash charts
     """
     all_inputs = dict_merge(inputs, chart_inputs, dict(yaxis=yaxis_data or {}))
     if all_inputs == last_chart_inputs:
         raise PreventUpdate
     charts, range_data = build_chart(get_data_id(pathname), **all_inputs)
     return charts, all_inputs, range_data
Exemplo n.º 13
0
def combine_inputs(dash_app, inputs, chart_inputs={}, yaxis_data={}, map_data={}):
    """
    Combines all managed state (inputs, chart inputs, map inputs & yaxis inputs) within Dash into one dictionary.
    """
    all_inputs = dict_merge(
        inputs, chart_inputs, dict(yaxis=yaxis_data or {}), map_data
    )
    if is_app_root_defined(dash_app.server.config.get("APPLICATION_ROOT")):
        all_inputs["app_root"] = dash_app.server.config["APPLICATION_ROOT"]
    return all_inputs
Exemplo n.º 14
0
def build_tab(label, value, additional_style=None, **kwargs):
    """
    Builds a :dash:`dash_core_components.Tab <dash-core-components/tab>` with standard styling settings.
    """
    base_style = {'borderBottom': '1px solid #d6d6d6', 'padding': '6px'}
    return dcc.Tab(
        label=label,
        value=value,
        style=dict_merge(base_style, {'fontWeight': 'bold'}, additional_style or {}),
        disabled_style=dict_merge(
            base_style,
            {'fontWeight': 'bold', 'backgroundColor': 'LightGray', 'color': 'black', 'cursor': 'not-allowed'},
            additional_style or {}
        ),
        selected_style=dict_merge(
            base_style,
            {'borderTop': '1px solid #d6d6d6', 'backgroundColor': '#2a91d1', 'color': 'white'},
            additional_style or {}
        ), **kwargs)
Exemplo n.º 15
0
def build_layout(cfg):
    """
    Wrapper function for :plotly:`plotly.graph_objects.Layout <plotly.graph_objects.Layout>`

    :param cfg: layout configuration
    :type cfg: dict
    :return: layout object
    :rtype: :plotly:`plotly.graph_objects.Layout <plotly.graph_objects.Layout>`
    """
    return go.Layout(**dict_merge(dict(legend=dict(orientation='h', y=1.2)), cfg))
Exemplo n.º 16
0
 def layout(axes):
     if z is not None:
         return {
             'height': 700,
             'margin': {
                 'l': 0,
                 'r': 0,
                 'b': 0
             },
             'scene': dict_merge(axes, dict(aspectmode='data'))
         }
     return axes
Exemplo n.º 17
0
 def on_data(_ts1, _ts2, _ts3, _ts4, pathname, inputs, chart_inputs,
             yaxis_data, map_data, last_chart_inputs):
     """
     dash callback controlling the building of dash charts
     """
     all_inputs = dict_merge(inputs, chart_inputs,
                             dict(yaxis=yaxis_data or {}), map_data)
     if all_inputs == last_chart_inputs:
         raise PreventUpdate
     charts, range_data, code = build_chart(get_data_id(pathname),
                                            **all_inputs)
     return charts, all_inputs, range_data, code, get_yaxis_type_tabs(
         make_list(inputs.get('y') or []))
Exemplo n.º 18
0
 def _build_axes(y):
     axes = {'xaxis': dict(title=update_label_for_freq(x))}
     positions = []
     for i, y2 in enumerate(y, 0):
         right = i % 2 == 1
         axis_ct = int(i / 2)
         title = update_label_for_freq(y2)
         if z is None and agg is not None:
             title = '{} ({})'.format(title, AGGS[agg])
         value = dict(title=title)
         if i == 0:
             key = 'yaxis'
         else:
             key = 'yaxis{}'.format(i + 1)
             value = dict_merge(
                 value,
                 dict(overlaying='y', side='right' if right else 'left'))
             value['anchor'] = 'free' if axis_ct > 0 else 'x'
             if axis_ct > 0:
                 pos = axis_ct / 20.0
                 value['position'] = (1 - pos) if right else pos
                 positions.append(value['position'])
         if y2 in axis_inputs and not (axis_inputs[y2]['min'],
                                       axis_inputs[y2]['max']) == (
                                           mins[y2], maxs[y2]):
             value['range'] = [
                 axis_inputs[y2]['min'], axis_inputs[y2]['max']
             ]
         if classify_type(dtypes.get(y2)) == 'I':
             value['tickformat'] = '.0f'
         axes[key] = value
     if len(positions):
         if len(positions) == 1:
             domain = [positions[0] + 0.05, 1]
         elif len(positions) == 2:
             domain = sorted(positions)
             domain = [domain[0] + 0.05, domain[1] - 0.05]
         else:
             lower, upper = divide_chunks(sorted(positions), 2)
             domain = [lower[-1] + 0.05, upper[0] - 0.05]
         axes['xaxis']['domain'] = domain
     if classify_type(dtypes.get(x)) == 'I':
         axes['xaxis']['tickformat'] = '.0f'
     if z is not None:
         axes['zaxis'] = dict(
             title=z if agg is None else '{} ({})'.format(z, AGGS[agg]))
         if classify_type(dtypes.get(z)) == 'I':
             axes['zaxis']['tickformat'] = '.0f'
     return axes
Exemplo n.º 19
0
 def main_input_class(
     _ts,
     _ts2,
     _ts3,
     _ts4,
     _ts5,
     inputs,
     map_inputs,
     cs_inputs,
     treemap_inputs,
     funnel_inputs,
 ):
     return main_inputs_and_group_val_display(
         dict_merge(inputs, map_inputs, cs_inputs, treemap_inputs,
                    funnel_inputs))
Exemplo n.º 20
0
 def _callback(selected_value, selected_label, group, data_id, **kwargs):
     label_value_data = {
         "{}_value".format(prop): selected_value,
         "{}_label".format(prop): selected_label,
     }
     if group is not None:
         label_value_data["{}_group".format(prop)] = group
     label_value_data = dict_merge(label_value_data, kwargs)
     df = global_state.get_data(data_id)
     value_options, label_options = build_label_value_options(
         df,
         selected_value=selected_value,
         selected_label=selected_label,
     )
     return label_value_data, value_options, label_options
Exemplo n.º 21
0
    def execute(self):
        from dtale.views import startup

        data = global_state.get_data(self.data_id)
        try:
            df, code = self.checker.remove(data)
            instance = startup(data=df, **self.checker.startup_kwargs)
            curr_settings = global_state.get_settings(instance._data_id)
            global_state.set_settings(
                instance._data_id,
                dict_merge(curr_settings, dict(startup_code=code)),
            )
            return instance._data_id
        except NoDuplicatesException:
            return self.data_id
Exemplo n.º 22
0
def surface_builder(data, x, y, z, axes_builder, wrapper, agg=None):
    """
    Builder function for :plotly:`plotly.graph_objects.Surface <plotly.graph_objects.Surface>`

    :param data: raw data to be represented within surface chart
    :type data: dict
    :param x: column to use for the X-Axis
    :type x: str
    :param y: columns to use for the Y-Axes
    :type y: list of str
    :param z: column to use for the Z-Axis
    :type z: str
    :param axes_builder: function for building axis configurations
    :type axes_builder: func
    :param wrapper: wrapper function returned by :meth:`dtale.charts.utils.chart_wrapper`
    :type wrapper: func
    :param group: column(s) to use for grouping
    :type group: list of str or str
    :param agg: points to a specific function that can be applied to
                :func: pandas.core.groupby.DataFrameGroupBy.  Possible values are: count, first, last mean,
                median, min, max, std, var, mad, prod, sum
    :type agg: str
    :return: surface chart
    :rtype: :plotly:`plotly.graph_objects.Surface <plotly.graph_objects.Surface>`
    """
    scene = dict(aspectmode='data', camera={'eye': {'x': 2, 'y': 1, 'z': 1.25}})

    df = pd.DataFrame({k: v for k, v in data['data']['all'].items() if k in ['x', y[0], z]})
    df = df.set_index(['x', y[0]]).unstack(0)[z]
    x_vals = df.columns
    y_vals = df.index.values
    z_data = df.values

    axes = axes_builder([y[0]])
    layout = {'height': 700, 'autosize': True, 'margin': {'l': 0, 'r': 0, 'b': 0}, 'scene': dict_merge(axes, scene)}
    return [
        wrapper(dcc.Graph(
            id='surface-{}'.format(y2),
            figure={'data': [
                go.Surface(x=x_vals, y=y_vals, z=z_data, opacity=0.8, name='all', colorscale='YlGnBu',
                           colorbar={'title': layout['scene']['zaxis']['title'], 'thickness': 15, 'len': 0.5,
                                     'x': 0.8, 'y': 0.6})
            ], 'layout': build_layout(dict_merge(build_title(x, y2, z=z, agg=agg), layout))}
        ))
        for y2 in y
    ]
Exemplo n.º 23
0
 def on_data(
     _ts1,
     _ts2,
     _ts3,
     _ts4,
     _ts5,
     _ts6,
     load,
     inputs,
     chart_inputs,
     yaxis_data,
     map_data,
     cs_data,
     treemap_data,
     last_chart_inputs,
     auto_load,
     prev_load_clicks,
 ):
     """
     dash callback controlling the building of dash charts
     """
     all_inputs = dict_merge(
         inputs,
         chart_inputs,
         dict(yaxis=yaxis_data or {}),
         map_data,
         cs_data,
         treemap_data,
     )
     if not auto_load and load == prev_load_clicks:
         raise PreventUpdate
     if all_inputs == last_chart_inputs:
         raise PreventUpdate
     if is_app_root_defined(dash_app.server.config.get("APPLICATION_ROOT")):
         all_inputs["app_root"] = dash_app.server.config["APPLICATION_ROOT"]
     charts, range_data, code = build_chart(**all_inputs)
     return (
         charts,
         all_inputs,
         range_data,
         "\n".join(make_list(code) + [CHART_EXPORT_CODE]),
         get_yaxis_type_tabs(make_list(inputs.get("y") or [])),
         load,
         dict(display="block" if valid_chart(**all_inputs) else "none"),
     )
Exemplo n.º 24
0
def update_settings(data_id):
    """
    :class:`flask:flask.Flask` route which updates global SETTINGS for current port

    :param data_id: integer string identifier for a D-Tale process's data
    :type data_id: str
    :param settings: JSON string from flask.request.args['settings'] which gets decoded and stored in SETTINGS variable
    :return: JSON
    """
    try:
        global SETTINGS

        curr_settings = SETTINGS.get(data_id, {})
        updated_settings = dict_merge(curr_settings, get_json_arg(request, 'settings', {}))
        SETTINGS[data_id] = updated_settings
        return jsonify(dict(success=True))
    except BaseException as e:
        return jsonify(dict(error=str(e), traceback=str(traceback.format_exc())))
Exemplo n.º 25
0
    def save_chart(*args):
        args = list(args)
        save_clicks = args.pop(0)
        current_deletes = [args.pop(0) or 0 for _ in range(MAX_SAVED_CHARTS)]
        inputs = args.pop(0)
        chart_inputs = args.pop(0)
        yaxis_data = args.pop(0)
        map_data = args.pop(0)
        cs_data = args.pop(0)
        treemap_data = args.pop(0)
        prev_save_clicks = args.pop(0)
        updated_configs = [args.pop(0) for _ in range(MAX_SAVED_CHARTS)]
        prev_deletes = [args.pop(0) or 0 for _ in range(MAX_SAVED_CHARTS)]

        delete_idx = None
        for i, (curr_delete,
                prev_delete) in enumerate(zip(current_deletes, prev_deletes)):
            if curr_delete > prev_delete:
                delete_idx = i

        if delete_idx is None:
            if save_clicks == prev_save_clicks:
                raise PreventUpdate

            config = dict_merge(
                inputs,
                chart_inputs,
                dict(yaxis=yaxis_data or {}),
                map_data,
                cs_data,
                treemap_data,
            )

            if not valid_chart(**config):
                raise PreventUpdate

            for index, saved_config in enumerate(updated_configs):
                if saved_config is None:
                    updated_configs[index] = config
                    break
        else:
            updated_configs[delete_idx] = None

        return tuple([save_clicks] + updated_configs + current_deletes)
Exemplo n.º 26
0
def update_settings():
    """
    Flask route which updates global SETTINGS for current port

    :param port: number string from flask.request.environ['SERVER_PORT']
    :param settings: JSON string from flask.request.args['settings'] which gets decoded and stored in SETTINGS variable
    :return: JSON
    """
    try:
        global SETTINGS

        port = get_port()
        curr_settings = SETTINGS.get(port, {})
        updated_settings = dict_merge(
            curr_settings, json.loads(get_str_arg(request, 'settings', '{}')))
        SETTINGS[port] = updated_settings
        return jsonify(dict(success=True))
    except BaseException as e:
        return jsonify(
            dict(error=str(e), traceback=str(traceback.format_exc())))
Exemplo n.º 27
0
def build_chart(data_id=None, **inputs):
    """
    Factory method that forks off into the different chart building methods (heatmaps are handled separately)
        - line
        - bar
        - scatter
        - pie
        - wordcloud
        - 3D scatter
        - surface

    :param data_id: identifier of data to build axis configurations against
    :type data_id: str
    :param inputs: Optional keyword arguments containing the following information:
        - x: column to be used as x-axis of chart
        - y: column to be used as y-axis of chart
        - z: column to use for the Z-Axis
        - agg: points to a specific function that can be applied to :func: pandas.core.groupby.DataFrameGroupBy
    :return: plotly chart object(s)
    :rtype: type of (:dash:`dash_core_components.Graph <dash-core-components/graph>`, dict)
    """
    try:
        if inputs.get('chart_type') == 'heatmap':
            data = make_timeout_request(threaded_heatmap_builder,
                                        kwargs=dict_merge(
                                            dict(data_id=data_id), inputs))
            data = data.pop()
            return data, None

        data = make_timeout_request(threaded_build_figure_data,
                                    kwargs=dict_merge(dict(data_id=data_id),
                                                      inputs))
        data = data.pop()
        if data is None:
            return None, None

        if 'error' in data:
            return build_error(data['error'], data['traceback']), None

        range_data = dict(min=data['min'], max=data['max'])
        axis_inputs = inputs.get('yaxis', {})
        chart_builder = chart_wrapper(data_id, data, inputs)
        chart_type, x, y, z, agg = (
            inputs.get(p) for p in ['chart_type', 'x', 'y', 'z', 'agg'])
        z = z if chart_type in ZAXIS_CHARTS else None
        chart_inputs = {
            k: v
            for k, v in inputs.items()
            if k not in ['chart_type', 'x', 'y', 'z', 'group']
        }

        if chart_type == 'wordcloud':
            return (chart_builder(
                dash_components.Wordcloud(id='wc',
                                          data=data,
                                          y=y,
                                          group=inputs.get('group'))),
                    range_data)

        axes_builder = build_axes(data_id,
                                  x,
                                  axis_inputs,
                                  data['min'],
                                  data['max'],
                                  z=z,
                                  agg=agg)
        if chart_type == 'scatter':
            if inputs['cpg']:
                scatter_charts = flatten_lists([
                    scatter_builder(data,
                                    x,
                                    y,
                                    axes_builder,
                                    chart_builder,
                                    group=group,
                                    agg=agg) for group in data['data']
                ])
            else:
                scatter_charts = scatter_builder(data,
                                                 x,
                                                 y,
                                                 axes_builder,
                                                 chart_builder,
                                                 agg=agg)
            return cpg_chunker(scatter_charts), range_data

        if chart_type == '3d_scatter':
            return scatter_builder(data,
                                   x,
                                   y,
                                   axes_builder,
                                   chart_builder,
                                   z=z,
                                   agg=agg), range_data

        if chart_type == 'surface':
            return surface_builder(data,
                                   x,
                                   y,
                                   z,
                                   axes_builder,
                                   chart_builder,
                                   agg=agg), range_data

        if chart_type == 'bar':
            return bar_builder(data, x, y, axes_builder, chart_builder,
                               **chart_inputs), range_data

        if chart_type == 'line':
            return line_builder(data, x, y, axes_builder, chart_builder,
                                **chart_inputs), range_data

        if chart_type == 'pie':
            return pie_builder(data, x, y, chart_builder,
                               **chart_inputs), range_data
        raise NotImplementedError('chart type: {}'.format(chart_type))
    except BaseException as e:
        return build_error(str(e), str(traceback.format_exc())), None
Exemplo n.º 28
0
 def main_input_class(ts_, ts2_, inputs, map_inputs):
     return main_inputs_and_group_val_display(dict_merge(
         inputs, map_inputs))
Exemplo n.º 29
0
def test_dict_merge():
    assert utils.dict_merge(dict(a=1), dict(b=2)) == dict(a=1, b=2)
    assert utils.dict_merge(dict(a=1), dict(a=2)) == dict(a=2)
    assert utils.dict_merge(None, dict(b=2)) == dict(b=2)
    assert utils.dict_merge(dict(a=1), None) == dict(a=1)
Exemplo n.º 30
0
 def on_data(
     _ts1,
     _ts2,
     _ts3,
     _ts4,
     _ts5,
     _ts6,
     _ts7,
     _ts8,
     load_clicks,
     inputs,
     chart_inputs,
     yaxis_data,
     map_data,
     cs_data,
     treemap_data,
     funnel_data,
     last_chart_inputs,
     auto_load,
     prev_load_clicks,
     ext_aggs,
 ):
     """
     dash callback controlling the building of dash charts
     """
     all_inputs = dict_merge(
         inputs,
         chart_inputs,
         dict(yaxis=yaxis_data or {}),
         map_data,
         cs_data,
         treemap_data,
         funnel_data,
         dict(extended_aggregation=ext_aggs or [])
         if inputs.get("chart_type") not in NON_EXT_AGGREGATION else {},
     )
     if not auto_load and load_clicks == prev_load_clicks:
         raise PreventUpdate
     if all_inputs == last_chart_inputs:
         raise PreventUpdate
     if is_app_root_defined(dash_app.server.config.get("APPLICATION_ROOT")):
         all_inputs["app_root"] = dash_app.server.config["APPLICATION_ROOT"]
     charts, range_data, code = build_chart(**all_inputs)
     agg_disabled = len(ext_aggs) > 0
     ext_agg_tt = text("ext_agg_desc")
     ext_agg_warning = show_style(agg_disabled)
     if agg_disabled:
         ext_agg_tt = html.Div([
             html.Span(text("ext_agg_desc")),
             html.Br(),
             html.Ul([
                 html.Li(
                     extended_aggregations.build_extended_agg_desc(ext_agg),
                     className="mb-0",
                 ) for ext_agg in ext_aggs
             ]),
         ])
     final_cols = build_final_cols(
         make_list(inputs.get("y")),
         inputs.get("z"),
         inputs.get("agg"),
         ext_aggs
         if inputs.get("chart_type") not in NON_EXT_AGGREGATION else [],
     )
     return (
         charts,
         all_inputs,
         range_data,
         "\n".join(make_list(code) + [CHART_EXPORT_CODE]),
         get_yaxis_type_tabs(final_cols),
         load_clicks,
         dict(display="block" if valid_chart(**all_inputs) else "none"),
         agg_disabled,
         ext_agg_tt,
         ext_agg_warning,
     )