Source code for dtale.dash_application.layout.layout

import json

import dash_bootstrap_components as dbc
import dash_colorscales as dcs
import dash_core_components as dcc
import dash_daq as daq
import dash_html_components as html
import plotly
from pkg_resources import parse_version

import dtale.dash_application.custom_geojson as custom_geojson
from dtale.charts.utils import YAXIS_CHARTS, ZAXIS_CHARTS, find_group_vals
from dtale.dash_application.layout.utils import (
    build_input,
    build_option,
    build_tab,
    build_cols,
    build_selections,
    show_style,
    AGGS,
    FREQS,
    FREQ_LABELS,
)
from dtale.utils import (
    ChartBuildingError,
    classify_type,
    get_dtypes,
    inner_build_query,
    is_app_root_defined,
    make_list,
)


[docs]def test_plotly_version(version_num): if "unknown" in plotly.__version__: return True return parse_version(plotly.__version__) >= parse_version(version_num)
[docs]def base_layout(app_root, **kwargs): """ Base layout to be returned by :meth:`dtale.dash_application.views.DtaleDash.interpolate_index` :param kwargs: Optional keyword arguments to be passed to 'dash.Dash.interplolate_index' :type kwargs: dict :return: HTML :rtype: str """ webroot_html = "" favicon_path = "../../images/favicon.png" if is_app_root_defined(app_root): webroot_html = """ <script type="text/javascript"> window.resourceBaseUrl = '{app_root}'; </script> """.format( app_root=app_root ) favicon_path = "{}/images/favicon.png".format(app_root) return """ <!DOCTYPE html> <html> <head> {webroot_html} {metas} <title>D-Tale Charts</title> <link rel="shortcut icon" href="{favicon_path}"> {css} </head> <body> <div class="container-fluid charts"> <div class="row" style="margin: 0"> <div class="col-auto"> <header> <span class="title-font">D-TALE</span> <span style="font-size: 16px" class="pl-4">Charts</span> </header> </div> <div class="col"></div> <div class="col-auto mt-4"> <a href="#" onclick="javascript:backToData()"> <i class="fas fa-th mr-4"></i> <span>Back To Data</span> </a> </div> </div> {app_entry} </div> <footer> {config} {scripts} <script type="text/javascript"> const pathSegs = window.location.pathname.split('/'); const dataId = pathSegs[pathSegs.length - 1]; const backToData = () => window.open('{app_root}/dtale/main/' + dataId); const goToLegacy = () => location.replace('{app_root}/dtale/popup/charts/' + dataId); </script> {renderer} {css} </footer> </body> </html> """.format( metas=kwargs["metas"], css=kwargs["css"], app_entry=kwargs["app_entry"], config=kwargs["config"], scripts=kwargs["scripts"], renderer=kwargs["renderer"], webroot_html=webroot_html, app_root=app_root if is_app_root_defined(app_root) else "", favicon_path=favicon_path, )
CHARTS = [ dict(value="line"), dict(value="bar"), dict(value="scatter"), dict(value="pie"), dict(value="wordcloud"), dict(value="heatmap"), dict(value="3d_scatter", label="3D Scatter"), dict(value="surface"), dict(value="maps", label="Maps"), dict(value="candlestick"), dict(value="treemap"), ] CHART_INPUT_SETTINGS = { "line": dict( x=dict(type="single"), y=dict(type="multi"), z=dict(display=False), group=dict(display=True, type="single"), ), "bar": dict( x=dict(type="single"), y=dict(type="multi"), z=dict(display=False), group=dict(display=True, type="single"), ), "scatter": dict( x=dict(type="single"), y=dict(type="multi"), z=dict(display=False), group=dict(display=True, type="single"), ), "pie": dict( x=dict(type="single"), y=dict(type="multi"), z=dict(display=False), group=dict(display=True, type="single"), ), "wordcloud": dict( x=dict(type="single"), y=dict(type="multi"), z=dict(display=False), group=dict(display=True, type="single"), ), "heatmap": dict( x=dict(type="single"), y=dict(type="single"), z=dict(display=True, type="single"), group=dict(display=False), ), "3d_scatter": dict( x=dict(type="single"), y=dict(type="single"), z=dict(display=True, type="single"), group=dict(display=True), ), "surface": dict( x=dict(type="single"), y=dict(type="single"), z=dict(display=True, type="single"), group=dict(display=False), ), "maps": dict( x=dict(display=False), y=dict(display=False), z=dict(display=False), group=dict(display=False), map_group=dict(display=True), ), "candlestick": dict( x=dict(display=False), y=dict(display=False), z=dict(display=False), group=dict(display=False), map_group=dict(display=False), cs_group=dict(display=True), ), "treemap": dict( x=dict(display=False), y=dict(display=False), z=dict(display=False), group=dict(display=False), map_group=dict(display=False), cs_group=dict(display=False), treemap_group=dict(display=True), ), } MAP_TYPES = [ dict(value="choropleth", image=True), dict(value="scattergeo", label="ScatterGeo", image=True), dict(value="mapbox"), ] SCOPES = ["world", "usa", "europe", "asia", "africa", "north america", "south america"] PROJECTIONS = [ "equirectangular", "mercator", "orthographic", "natural earth", "kavrayskiy7", "miller", "robinson", "eckert4", "azimuthal equal area", "azimuthal equidistant", "conic equal area", "conic conformal", "conic equidistant", "gnomonic", "stereographic", "mollweide", "hammer", "transverse mercator", "albers usa", "winkel tripel", "aitoff", "sinusoidal", ]
[docs]def build_img_src(proj, img_type="projections"): return "../images/{}/{}.png".format(img_type, "_".join(proj.split(" ")))
[docs]def build_proj_hover_children(proj): if proj is None: return None return [ html.I(className="ico-help-outline", style=dict(color="white")), html.Div( [html.Div(proj), html.Img(src=build_img_src(proj))], className="hoverable__content", style=dict(width="auto"), ), ]
[docs]def build_proj_hover(proj): return html.Span( [ "Projection", html.Div( build_proj_hover_children(proj), className="ml-3 hoverable", style=dict(display="none") if proj is None else dict(borderBottom="none"), id="proj-hover", ), ], className="input-group-addon", )
[docs]def build_mapbox_token_children(): from dtale.charts.utils import get_mapbox_token msg = "To access additional styles enter a token here..." if get_mapbox_token() is None: msg = "Change your token here..." return [ html.I(className="ico-help-outline", style=dict(color="white")), html.Div( [ html.Span("Mapbox Access Token:"), dcc.Input( id="mapbox-token-input", type="text", placeholder=msg, className="form-control", value="", style={"lineHeight": "inherit"}, ), ], className="hoverable__content", style=dict(width="20em", right="-1.45em"), ), ]
[docs]def build_mapbox_token_hover(): return html.Span( [ "Style", html.Div( build_mapbox_token_children(), className="ml-3 hoverable", style=dict(borderBottom="none"), id="token-hover", ), ], className="input-group-addon", )
LOC_MODE_INFO = { "ISO-3": dict( url=html.A( "ISO-3", href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3", target="_blank", ), examples=["USA (United States)", "CAN (Canada)", "GBR (United Kingdom)"], ), "USA-states": dict( url=html.A( "USA-states (use ISO)", href="https://en.wikipedia.org/wiki/List_of_U.S._state_abbreviations", target="_blank", ), examples=["NY (New York)", "CA (California)", "MA (Massachusetts)"], ), "country names": dict( url=html.A( "country names (case-insensitive)", href="https://simple.wikipedia.org/wiki/List_of_countries", target="_blank", ), examples=["United States", "United Kingdom", "Germany"], ), "geojson-id": dict(label="Custom GeoJSON", desc="Load custom geojson into D-Tale"), }
[docs]def build_loc_mode_hover_children(loc_mode): if loc_mode is None: return None loc_mode_cfg = LOC_MODE_INFO[loc_mode] url, examples, desc = (loc_mode_cfg.get(p) for p in ["url", "examples", "desc"]) body = [] if url is not None: body.append( html.Div([html.Span("View", className="mr-3"), loc_mode_cfg["url"]]) ) if examples is not None: body.append( html.Ul( [ html.Li(e, style={"listStyleType": "disc"}, className="mb-3") for e in loc_mode_cfg["examples"] ], className="pt-3 mb-0", ) ) if desc is not None: body.append(html.Span(desc)) return [ html.I(className="ico-help-outline", style=dict(color="white")), html.Div( body, className="hoverable__content build-code", style=dict(width="auto", whiteSpace="nowrap", left="-2em", top="auto"), ), ]
[docs]def build_loc_mode_hover(loc_mode): return html.Span( [ html.Span("Location Mode", style=dict(whiteSpace="pre-line")), html.Div( build_loc_mode_hover_children(loc_mode), className="ml-3 hoverable", style=dict(display="none") if loc_mode is None else dict(borderBottom="none"), id="loc-mode-hover", ), ], className="input-group-addon pt-1 pb-0", )
JET = ["#000083", "#003CAA", "#05FFFF", "#FFFF00", "#FA0000", "#800000"] REDS = ["#fff5f0", "#fdcab4", "#fc8a6a", "#f24632", "#bc141a", "#67000d"] YLORRD = [ "#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026", ] DEFAULT_CSALES = {"heatmap": JET, "maps": REDS, "3d_Scatter": YLORRD} ANIMATION_CHARTS = ["line"] ANIMATE_BY_CHARTS = ["bar", "3d_scatter", "heatmap", "maps"]
[docs]def show_input_handler(chart_type): settings = CHART_INPUT_SETTINGS.get(chart_type or "line") or {} def _show_input(input_id, input_type="single"): cfg = settings.get(input_id, {}) return cfg.get("display", True) and cfg.get("type", "single") == input_type return _show_input
[docs]def show_group_input(inputs, group_cols=None): chart_type = inputs.get("chart_type") if show_input_handler(chart_type)("group"): return len(group_cols or make_list(inputs.get("group"))) elif show_input_handler(chart_type)("map_group"): return len(group_cols or make_list(inputs.get("map_group"))) elif show_input_handler(chart_type)("cs_group"): return len(group_cols or make_list(inputs.get("cs_group"))) elif show_input_handler(chart_type)("treemap_group"): return len(group_cols or make_list(inputs.get("treemap_group"))) return False
[docs]def update_label_for_freq(val): """ Formats sub-values contained within 'val' to display date frequencies if included. - (val=['a', 'b', 'c']) => 'a, b, c' - (val=['a|H', 'b', 'c']) => 'a (Hour), b, c' """ def _freq_handler(sub_val): for freq in FREQS: if sub_val.endswith("|{}".format(freq)): col, freq = sub_val.split("|") if freq in FREQ_LABELS: return "{} ({})".format(col, FREQ_LABELS[freq]) return col return sub_val return ", ".join([_freq_handler(sub_val) for sub_val in make_list(val)])
[docs]def build_error(error, tb): """ Returns error/traceback information in standard component with styling :param error: execption message :type error: str :param tb: tracebackF :type tb: str :return: error component :rtype: :dash:`dash_html_components.Div <dash-html-components/div>` """ if isinstance(error, ChartBuildingError): if error.details: tb = error.details error = error.error return html.Div( [ html.I(className="ico-error"), html.Span(str(error)), html.Div(html.Pre(str(tb)), className="traceback"), ], className="dtale-alert alert alert-danger", )
[docs]def build_input_options(df, **inputs): """ Builds dropdown options for (X, Y, Z, Group, Barsort & Y-Axis Ranges) with filtering based on currently selected values for the following inputs: x, y, z, group. """ chart_type, x, y, z, group = ( inputs.get(p) for p in ["chart_type", "x", "y", "z", "group"] ) col_opts = list(build_cols(df.columns, get_dtypes(df))) group_val, z_val = (None, z) if chart_type in ZAXIS_CHARTS else (group, None) x_options = [ build_option(c, l) for c, l in col_opts if c not in build_selections(y, z_val, group_val) ] y_filter = build_selections(x, group_val, z_val) y_multi_options = [build_option(c, l) for c, l in col_opts if c not in y_filter] y_single_options = [build_option(c, l) for c, l in col_opts if c not in y_filter] z_options = [ build_option(c) for c in df.columns if c not in build_selections(x, y, group_val) ] group_options = [ build_option(c, l) for c, l in col_opts if c not in build_selections(x, y, z_val) ] barsort_options = [build_option(o) for o in build_selections(x, y)] yaxis_options = [build_option(y2) for y2 in y or []] return ( x_options, y_multi_options, y_single_options, z_options, group_options, barsort_options, yaxis_options, )
[docs]def build_map_options( df, type="choropleth", loc=None, lat=None, lon=None, map_val=None ): dtypes = get_dtypes(df) cols = sorted(dtypes.keys()) float_cols, str_cols, num_cols = [], [], [] for c in cols: dtype = dtypes[c] classification = classify_type(dtype) if classification == "S": str_cols.append(c) continue if classification in ["F", "I"]: num_cols.append(c) if classification == "F": float_cols.append(c) lat_options = [ build_option(c) for c in float_cols if c not in build_selections(lon, map_val) ] lon_options = [ build_option(c) for c in float_cols if c not in build_selections(lat, map_val) ] loc_options = [ build_option(c) for c in str_cols if c not in build_selections(map_val) ] if type == "choropleth": val_options = [ build_option(c) for c in num_cols if c not in build_selections(loc) ] else: val_options = [ build_option(c) for c in num_cols if c not in build_selections(lon, lat) ] return loc_options, lat_options, lon_options, val_options
[docs]def build_candlestick_options( df, cs_x=None, cs_open=None, cs_close=None, cs_high=None, cs_low=None ): dtypes = get_dtypes(df) cols = sorted(dtypes.keys()) num_cols, x_cols = [], [] for c in cols: dtype = dtypes[c] classification = classify_type(dtype) if classification in ["S", "D"]: x_cols.append(c) if classification in ["F", "I"]: num_cols.append(c) x_options = [build_option(c) for c in x_cols] close_options = [ build_option(c) for c in num_cols if c not in build_selections(cs_x, cs_open, cs_low, cs_high) ] open_options = [ build_option(c) for c in num_cols if c not in build_selections(cs_x, cs_close, cs_low, cs_high) ] low_options = [ build_option(c) for c in num_cols if c not in build_selections(cs_x, cs_open, cs_close, cs_high) ] high_options = [ build_option(c) for c in num_cols if c not in build_selections(cs_x, cs_open, cs_close, cs_low) ] return x_options, close_options, open_options, low_options, high_options
[docs]def build_treemap_options(df, treemap_value=None, treemap_label=None): dtypes = get_dtypes(df) cols = sorted(dtypes.keys()) num_cols = [] for c in cols: dtype = dtypes[c] classification = classify_type(dtype) if classification in ["F", "I"]: num_cols.append(c) value_options = [ build_option(c) for c in num_cols if c not in build_selections(treemap_label) ] label_options = [ build_option(c) for c in cols if c not in build_selections(treemap_value) ] return value_options, label_options
[docs]def build_mapbox_style_options(): from dtale.charts.utils import get_mapbox_token free_styles = [ "open-street-map", "carto-positron", "carto-darkmatter", "stamen-terrain", "stamen-toner", "stamen-watercolor", ] token_styles = [ "basic", "streets", "outdoors", "light", "dark", "satellite", "satellite-streets", ] styles = free_styles if get_mapbox_token() is not None: styles += token_styles return [build_option(v) for v in styles]
[docs]def bar_input_style(**inputs): """ Sets display CSS property for bar chart inputs """ chart_type, group_col = (inputs.get(p) for p in ["chart_type", "group"]) show_bar = chart_type == "bar" show_barsort = show_bar and group_col is None return ( dict(display="block" if show_bar else "none"), dict(display="block" if show_barsort else "none"), )
[docs]def colorscale_input_style(**inputs): return dict( display="block" if inputs.get("chart_type") in ["heatmap", "maps", "3d_scatter"] else "none" )
[docs]def animate_styles(df, **inputs): chart_type, agg, cpg = (inputs.get(p) for p in ["chart_type", "agg", "cpg"]) opts = [] if cpg or agg in ["pctsum", "pctct"]: return dict(display="none"), dict(display="none"), opts if chart_type in ANIMATION_CHARTS: return dict(display="block"), dict(display="none"), opts if chart_type in ANIMATE_BY_CHARTS: opts = [build_option(v, l) for v, l in build_cols(df.columns, get_dtypes(df))] if len(opts): return dict(display="none"), dict(display="block"), opts return dict(display="none"), dict(display="none"), []
[docs]def lock_zoom_style(chart_type): return ( dict(display="block") if chart_type in ["3d_scatter", "surface"] else dict(display="none") )
[docs]def show_chart_per_group(**inputs): """ Boolean function to determine whether "Chart Per Group" toggle should be displayed or not """ [chart_type, group] = [inputs.get(p) for p in ["chart_type", "group"]] invalid_type = chart_type in ["pie", "wordcloud", "maps"] return ( show_input_handler(chart_type)("group") and len(group or []) and not invalid_type )
[docs]def show_yaxis_ranges(**inputs): """ Boolean function to determine whether "Y-Axis Range" inputs should be displayed or not """ chart_type, y = (inputs.get(p) for p in ["chart_type", "y"]) return chart_type in YAXIS_CHARTS and len(y or [])
[docs]def get_yaxis_type_tabs(y): tabs = [ build_tab("Default", "default", {"padding": "2px", "minWidth": "4em"}), build_tab("Single", "single", {"padding": "2px", "minWidth": "4em"}), ] if len(y) <= 1: return tabs return tabs + [build_tab("Multi", "multi", {"padding": "2px", "minWidth": "4em"})]
[docs]def build_group_val_options(df, group_cols): group_vals = find_group_vals(df, group_cols) return [ build_option( json.dumps(gv), "|".join([str(gv.get(p, "NaN")) for p in group_cols]) ) for gv in group_vals ]
[docs]def build_map_type_tabs(map_type): def _build_hoverable(): for t in MAP_TYPES: if t.get("image", False): yield html.Div( [ html.Span(t.get("label", t["value"].capitalize())), html.Img(src=build_img_src(t["value"], img_type="map_type")), ], className="col-md-6", ) return html.Div( [ dcc.Tabs( id="map-type-tabs", value=map_type or "choropleth", children=[ build_tab(t.get("label", t["value"].capitalize()), t["value"]) for t in MAP_TYPES ], style=dict(height="36px"), ), html.Div( html.Div(list(_build_hoverable()), className="row"), className="hoverable__content map-types", ), ], style=dict(paddingLeft=15, borderBottom="none", width="20em"), className="hoverable", )
[docs]def main_inputs_and_group_val_display(inputs): if show_group_input(inputs): return dict(display="block"), "col-md-8" return dict(display="none"), "col-md-12"
[docs]def charts_layout(df, settings, **inputs): """ Builds main dash inputs with dropdown options populated with the columns of the dataframe associated with the page. Inputs included are: chart tabs, query, x, y, z, group, aggregation, rolling window/computation, chart per group toggle, bar sort, bar mode, y-axis range editors :param df: dataframe to drive the charts built on page :type df: :class:`pandas:pandas.DataFrame` :param settings: global settings associated with this dataframe (contains properties like "query") :type param: dict :return: dash markup """ chart_type, x, y, z, group, agg = ( inputs.get(p) for p in ["chart_type", "x", "y", "z", "group", "agg"] ) y = y or [] show_input = show_input_handler(chart_type) show_cpg = show_chart_per_group(**inputs) show_yaxis = show_yaxis_ranges(**inputs) scatter_input = dict(display="block" if chart_type == "scatter" else "none") bar_style, barsort_input_style = bar_input_style(**inputs) animate_style, animate_by_style, animate_opts = animate_styles(df, **inputs) options = build_input_options(df, **inputs) ( x_options, y_multi_options, y_single_options, z_options, group_options, barsort_options, yaxis_options, ) = options query_placeholder = "Enter pandas query (ex: col1 == 1)" query_value = inputs.get("query") or inner_build_query( settings, settings.get("query") ) query_label = html.Div( [ html.Span("Query"), html.A( html.I(className="fa fa-info-circle ml-4"), href="https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#indexing-query", target="_blank", style={"color": "white"}, ), ], className="input-group-addon", style={"minWidth": "7em"}, ) yaxis_type = (inputs.get("yaxis") or {}).get("type") or "default" yaxis_type_style = ( {"borderRadius": "0 0.25rem 0.25rem 0"} if yaxis_type == "default" else None ) show_map = chart_type == "maps" map_props = ["map_type", "loc_mode", "loc", "lat", "lon", "map_val"] map_type, loc_mode, loc, lat, lon, map_val = (inputs.get(p) for p in map_props) map_scope, proj, mapbox_style = ( inputs.get(p) for p in ["scope", "proj", "mapbox_style"] ) loc_options, lat_options, lon_options, map_val_options = build_map_options( df, type=map_type, loc=loc, lat=lat, lon=lon, map_val=map_val ) show_candlestick = chart_type == "candlestick" cs_props = ["cs_x", "cs_open", "cs_close", "cs_high", "cs_low", "cs_group"] cs_x, cs_open, cs_close, cs_high, cs_low, cs_group = ( inputs.get(p) for p in cs_props ) ( cs_x_options, open_options, close_options, high_options, low_options, ) = build_candlestick_options( df, cs_x=cs_x, cs_open=cs_open, cs_close=cs_close, cs_high=cs_high, cs_low=cs_low, ) show_treemap = chart_type == "treemap" treemap_props = ["treemap_value", "treemap_label", "treemap_group"] treemap_value, treemap_label, treemap_group = (inputs.get(p) for p in treemap_props) (treemap_value_options, treemap_label_options,) = build_treemap_options( df, treemap_value=treemap_value, treemap_label=treemap_label, ) cscale_style = colorscale_input_style(**inputs) default_cscale = DEFAULT_CSALES.get(chart_type, REDS) group_val_style, main_input_class = main_inputs_and_group_val_display(inputs) group_val = [json.dumps(gv) for gv in inputs.get("group_val") or []] def show_map_style(show): return {} if show else {"display": "none"} body_items = [ dcc.Store(id="query-data", data=inputs.get("query")), dcc.Store( id="input-data", data={ k: v for k, v in inputs.items() if k not in ["cpg", "barmode", "barsort"] }, ), dcc.Store( id="chart-input-data", data={ k: v for k, v in inputs.items() if k in ["cpg", "barmode", "barsort"] }, ), dcc.Store( id="map-input-data", data={ k: v for k, v in inputs.items() if k in [ "map_type", "map_code", "loc_mode", "lat", "lon", "map_val", "scope", "proj", ] }, ), dcc.Store( id="candlestick-input-data", data={ k: v for k, v in inputs.items() if k in ["cs_x", "cs_open", "cs_close", "cs_high", "cs_low", "cs_group"] }, ), dcc.Store( id="treemap-input-data", data={ k: v for k, v in inputs.items() if k in ["treemap_value", "treemap_label", "treemap_group"] }, ), dcc.Store(id="range-data"), dcc.Store(id="yaxis-data", data=inputs.get("yaxis")), dcc.Store(id="last-chart-input-data", data=inputs), dcc.Input(id="chart-code", type="hidden"), html.Div( html.Div( dcc.Tabs( id="chart-tabs", value=chart_type or "line", children=[ build_tab(t.get("label", t["value"].capitalize()), t["value"]) for t in CHARTS ], style=dict(height="36px"), ), className="col-md-12", ), className="row pt-3 pb-3 charts-filters", ), html.Div( html.Div( [ html.Div( [ query_label, dcc.Input( id="query-input", type="text", placeholder=query_placeholder, className="form-control", value=query_value, style={"lineHeight": "inherit"}, ), ], className="input-group mr-3", ) ], className="col", ), className="row pt-3 pb-3 charts-filters", ), html.Div( [ html.Div( [ html.Div( [ build_input( [html.Div("X"), html.Small("(Agg By)")], dcc.Dropdown( id="x-dropdown", options=x_options, placeholder="Select a column", value=x, style=dict(width="inherit"), ), label_class="input-group-addon d-block pt-1 pb-0", ), build_input( "Y", dcc.Dropdown( id="y-multi-dropdown", options=y_multi_options, multi=True, placeholder="Select a column(s)", style=dict(width="inherit"), value=y if show_input("y", "multi") else None, ), className="col", id="y-multi-input", style=show_style(show_input("y", "multi")), ), build_input( [html.Div("Y"), html.Small("(Agg By)")], dcc.Dropdown( id="y-single-dropdown", options=y_single_options, placeholder="Select a column", style=dict(width="inherit"), value=y[0] if show_input("y") and len(y) else None, ), className="col", label_class="input-group-addon d-block pt-1 pb-0", id="y-single-input", style=show_style(show_input("y")), ), build_input( "Z", dcc.Dropdown( id="z-dropdown", options=z_options, placeholder="Select a column", style=dict(width="inherit"), value=z, ), className="col", id="z-input", style=show_style(show_input("z")), ), build_input( "Group", dcc.Dropdown( id="group-dropdown", options=group_options, multi=True, placeholder="Select a group(s)", value=group, style=dict(width="inherit"), ), className="col", id="group-input", style=show_style(show_input("group")), ), ], id="standard-inputs", style={} if not show_map and not show_candlestick and not show_treemap else {"display": "none"}, className="row p-0 charts-filters", ), html.Div( [ build_map_type_tabs(map_type), html.Div( [ html.Div( [ build_loc_mode_hover(loc_mode), dcc.Dropdown( id="map-loc-mode-dropdown", options=[ build_option( v, LOC_MODE_INFO[v].get( "label" ), ) for v in [ "ISO-3", "USA-states", "country names", "geojson-id", ] ], style=dict(width="inherit"), value=loc_mode, ), ], className="input-group mr-3", ) ], id="map-loc-mode-input", style=show_map_style(map_type == "choropleth"), className="col-auto", ), custom_geojson.build_modal(map_type, loc_mode), build_input( [html.Div("Locations"), html.Small("(Agg By)")], dcc.Dropdown( id="map-loc-dropdown", options=loc_options, placeholder="Select a column", value=loc, style=dict(width="inherit"), ), id="map-loc-input", label_class="input-group-addon d-block pt-1 pb-0", style=show_map_style(map_type == "choropleth"), ), build_input( [html.Div("Lat"), html.Small("(Agg By)")], dcc.Dropdown( id="map-lat-dropdown", options=lat_options, placeholder="Select a column", value=lat, style=dict(width="inherit"), ), id="map-lat-input", label_class="input-group-addon d-block pt-1 pb-0", style=show_map_style( map_type in ["scattergeo", "mapbox"] ), ), build_input( [html.Div("Lon"), html.Small("(Agg By)")], dcc.Dropdown( id="map-lon-dropdown", options=lon_options, placeholder="Select a column", style=dict(width="inherit"), value=lon, ), id="map-lon-input", label_class="input-group-addon d-block pt-1 pb-0", style=show_map_style( map_type in ["scattergeo", "mapbox"] ), ), build_input( "Scope", dcc.Dropdown( id="map-scope-dropdown", options=[build_option(v) for v in SCOPES], style=dict(width="inherit"), value=map_scope or "world", ), id="map-scope-input", style=show_map_style(map_type == "scattergeo"), ), html.Div( [ html.Div( [ build_mapbox_token_hover(), dcc.Dropdown( id="map-mapbox-style-dropdown", options=build_mapbox_style_options(), style=dict(width="inherit"), value=mapbox_style or "open-street-map", ), ], className="input-group mr-3", ) ], id="map-mapbox-style-input", className="col-auto", style=show_map_style(map_type == "mapbox"), ), html.Div( [ html.Div( [ build_proj_hover(proj), dcc.Dropdown( id="map-proj-dropdown", options=[ build_option(v) for v in PROJECTIONS ], style=dict(width="inherit"), value=proj, ), ], className="input-group mr-3", ) ], id="map-proj-input", style=show_map_style(map_type == "scattergeo"), className="col-auto", ), build_input( "Value", dcc.Dropdown( id="map-val-dropdown", options=map_val_options, placeholder="Select a column", style=dict(width="inherit"), value=map_val, ), ), build_input( "Group", dcc.Dropdown( id="map-group-dropdown", options=group_options, multi=True, placeholder="Select a group(s)", value=inputs.get("map_group"), style=dict(width="inherit"), ), className="col", id="map-group-input", ), ], id="map-inputs", className="row charts-filters", style={} if show_map else {"display": "none"}, ), html.Div( [ build_input( "X", dcc.Dropdown( id="candlestick-x-dropdown", options=cs_x_options, placeholder="Select a column", style=dict(width="inherit"), value=cs_x, ), ), build_input( "Open", dcc.Dropdown( id="candlestick-open-dropdown", options=open_options, placeholder="Select a column", style=dict(width="inherit"), value=cs_open, ), ), build_input( "High", dcc.Dropdown( id="candlestick-high-dropdown", options=high_options, placeholder="Select a column", style=dict(width="inherit"), value=cs_high, ), ), build_input( "Low", dcc.Dropdown( id="candlestick-low-dropdown", options=low_options, placeholder="Select a column", style=dict(width="inherit"), value=cs_low, ), ), build_input( "Close", dcc.Dropdown( id="candlestick-close-dropdown", options=close_options, placeholder="Select a column", style=dict(width="inherit"), value=cs_close, ), ), build_input( "Group", dcc.Dropdown( id="candlestick-group-dropdown", options=group_options, multi=True, placeholder="Select a group(s)", value=inputs.get("cs_group"), style=dict(width="inherit"), ), className="col", id="candlestick-group-input", ), ], id="candlestick-inputs", className="row charts-filters", style={} if show_candlestick else {"display": "none"}, ), html.Div( [ build_input( "Value", dcc.Dropdown( id="treemap-value-dropdown", options=treemap_value_options, placeholder="Select a column", style=dict(width="inherit"), value=treemap_value, ), ), build_input( "Labels", dcc.Dropdown( id="treemap-label-dropdown", options=treemap_label_options, placeholder="Select a column", style=dict(width="inherit"), value=treemap_label, ), ), build_input( "Group", dcc.Dropdown( id="treemap-group-dropdown", options=group_options, multi=True, placeholder="Select a group(s)", value=inputs.get("treemap_group"), style=dict(width="inherit"), ), className="col", id="treemap-group-input", ), ], id="treemap-inputs", className="row charts-filters", style={} if show_treemap else {"display": "none"}, ), html.Div( [ build_input( "Aggregation", dcc.Dropdown( id="agg-dropdown", options=[ build_option(v, AGGS[v]) for v in [ "raw", "count", "nunique", "sum", "mean", "rolling", "corr", "first", "last", "median", "min", "max", "std", "var", "mad", "prod", "pctsum", "pctct", ] ], placeholder="Select an aggregation", style=dict(width="inherit"), value=agg or "raw", ), ), html.Div( [ build_input( "Window", dcc.Input( id="window-input", type="number", placeholder="Enter days", className="form-control text-center", style={"lineHeight": "inherit"}, value=inputs.get("window"), ), ), build_input( "Computation", dcc.Dropdown( id="rolling-comp-dropdown", options=[ build_option("corr", "Correlation"), build_option("count", "Count"), build_option("cov", "Covariance"), build_option("kurt", "Kurtosis"), build_option("max", "Maximum"), build_option("mean", "Mean"), build_option("median", "Median"), build_option("min", "Minimum"), build_option("skew", "Skew"), build_option( "std", "Standard Deviation" ), build_option("sum", "Sum"), build_option("var", "Variance"), ], placeholder="Select an computation", style=dict(width="inherit"), value=inputs.get("rolling_comp"), ), ), ], id="rolling-inputs", style=show_style(agg == "rolling"), ), build_input( "Drilldowns", html.Div( daq.BooleanSwitch( id="drilldown-toggle", on=False, ), className="toggle-wrapper", ), id="drilldown-input", style=show_style((agg or "raw") != "raw"), className="col-auto", ), ], className="row pt-3 pb-3 charts-filters", ), html.Div( [ build_input( "Chart Per\nGroup", html.Div( daq.BooleanSwitch( id="cpg-toggle", on=inputs.get("cpg") or False, ), className="toggle-wrapper", ), id="cpg-input", style=show_style(show_cpg), className="col-auto", ), build_input( "Trendline", dcc.Dropdown( id="trendline-dropdown", options=[ build_option("ols"), build_option("lowess"), ], value=inputs.get("trendline"), ), className="col-auto addon-min-width", style=scatter_input, id="trendline-input", ), build_input( "Barmode", dcc.Dropdown( id="barmode-dropdown", options=[ build_option("group", "Group"), build_option("stack", "Stack"), build_option("relative", "Relative"), ], value=inputs.get("barmode") or "group", placeholder="Select a mode", ), className="col-auto addon-min-width", style=bar_style, id="barmode-input", ), build_input( "Barsort", dcc.Dropdown( id="barsort-dropdown", options=barsort_options, value=inputs.get("barsort"), ), className="col-auto addon-min-width", style=barsort_input_style, id="barsort-input", ), html.Div( html.Div( [ html.Span( "Y-Axis", className="input-group-addon", ), html.Div( dcc.Tabs( id="yaxis-type", value=yaxis_type, children=get_yaxis_type_tabs(y), ), id="yaxis-type-div", className="form-control col-auto pt-3", style=yaxis_type_style, ), dcc.Dropdown( id="yaxis-dropdown", options=yaxis_options, ), html.Span( "Min:", className="input-group-addon col-auto", id="yaxis-min-label", ), dcc.Input( id="yaxis-min-input", type="number", className="form-control col-auto", style={"lineHeight": "inherit"}, ), html.Span( "Max:", className="input-group-addon col-auto", id="yaxis-max-label", ), dcc.Input( id="yaxis-max-input", type="number", className="form-control col-auto", style={"lineHeight": "inherit"}, ), ], className="input-group", id="yaxis-min-max-options", ), className="col-auto addon-min-width", id="yaxis-input", style=show_style(show_yaxis), ), build_input( "Colorscale", dcs.DashColorscales( id="colorscale-picker", colorscale=inputs.get("colorscale") or default_cscale, ), className="col-auto addon-min-width", style=cscale_style, id="colorscale-input", ), build_input( "Animate", html.Div( daq.BooleanSwitch( id="animate-toggle", on=inputs.get("animate") or False, ), className="toggle-wrapper", ), id="animate-input", style=animate_style, className="col-auto", ), build_input( "Animate By", dcc.Dropdown( id="animate-by-dropdown", options=animate_opts, value=inputs.get("animate_by"), ), className="col-auto addon-min-width", style=animate_by_style, id="animate-by-input", ), dbc.Button( "Lock Zoom", id="lock-zoom-btn", className="ml-auto", style=lock_zoom_style(chart_type), ), ], className="row pt-3 pb-5 charts-filters", id="chart-inputs", ), ], id="main-inputs", className=main_input_class, ), build_input( "Group(s)", dcc.Dropdown( id="group-val-dropdown", multi=True, placeholder="Select a group value(s)", value=group_val, style=dict(width="inherit"), ), className="col-md-4 pt-3 pb-5", id="group-val-input", style=group_val_style, ), ], className="row", ), dcc.Loading( html.Div(id="chart-content", style={"height": "69vh"}), type="circle" ), dcc.Textarea(id="copy-text", style=dict(position="absolute", left="-110%")), ] if settings.get("github_fork", False): body_items.append( html.Span( html.A("Fork me on Github", href="https://github.com/man-group/dtale"), id="forkongithub", ) ) return html.Div(body_items, className="charts-body")