Source code for dtale.dash_application.layout.layout
import json
import dash_bootstrap_components as dbc
import dash_colorscales as dcs
import dash_daq as daq
import os
import plotly
from pkg_resources import parse_version
from dtale.dash_application import dcc, html
import dtale.dash_application.custom_geojson as custom_geojson
import dtale.dash_application.extended_aggregations as extended_aggregations
import dtale.global_state as global_state
from dtale.charts.utils import (
AGGS,
ANIMATION_CHARTS,
ANIMATE_BY_CHARTS,
YAXIS_CHARTS,
ZAXIS_CHARTS,
NON_EXT_AGGREGATION,
build_final_cols,
find_group_vals,
)
from dtale.column_builders import get_cleaner_configs
from dtale.dash_application.layout.utils import (
build_input,
build_option,
build_tab,
build_cols,
build_hoverable,
build_selections,
show_style,
FREQS,
FREQ_LABELS,
)
from dtale.translations import text
from dtale.query import build_query, handle_predefined, inner_build_query, run_query
from dtale.utils import (
ChartBuildingError,
classify_type,
coord_type,
get_dtypes,
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 = "../../dtale/static/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 = "{}/dtale/static/images/favicon.png".format(app_root)
grid_links = []
for id in global_state.keys():
label = global_state.get_name(id)
if label:
label = " ({})".format(label)
else:
label = ""
grid_links.append(
(
"""<a href="../main/{id}" class="dropdown-item data-grid-link" target="{target}">"""
"""<span class="ml-3">{id}{label}</span>"""
"""</a>"""
).format(
id=id,
label=label,
target="_self"
if os.environ.get("VSCODE_PID") is not None
else "_blank",
)
)
language = global_state.get_app_settings()["language"]
language_links = []
for value, label in [("en", "English"), ("cn", "Chinese"), ("pt", "Portuguese")]:
if value == language:
language_links.append(
"""<span class="dropdown-item active">{}</span>""".format(
"✓ {}".format(text(label))
)
)
else:
language_links.append(
"""<a href="{}" class="dropdown-item lang-link">{}</a>""".format(
value, text(label)
)
)
main_title = global_state.get_app_settings().get("main_title") or "D-TALE"
main_title_font = global_state.get_app_settings().get("main_title_font")
main_title_class = "title-font-base"
main_title_style = ""
if main_title_font:
main_title_style = "font-family: {main_title_font}".format(
main_title_font=main_title_font
)
else:
main_title_class = "title-font title-font-base"
page_title = global_state.get_app_settings().get("main_title") or "D-Tale"
return """
<!DOCTYPE html>
<html>
<head>
{webroot_html}
{metas}
<title>{page_title} Charts</title>
<link rel="shortcut icon" href="{favicon_path}">
{css}
</head>
<body class="{theme}-mode">
<header class="app-header">
<span class="{main_title_class}" style="{main_title_style}">{main_title}</span>
<span style="font-size: 16px" class="pl-5 mt-4">{title}</span>
<nav class="app-header__nav--secondary">
<ul class="nav-menus">
<li>
<div class="dropdown">
<span class="dropbtn nav-link dropdown-toggle">
{back_to_data}
</span>
<div class="dropdown-content">{grid_links}</div>
</div>
</li>
<li>
<div class="dropdown">
<span class="dropbtn nav-link dropdown-toggle">
{languages}
</span>
<div class="dropdown-content">{language_links}</div>
</div>
</li>
</ul>
</nav>
</header>
<div class="container-fluid charts">
{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);
</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,
title=text("Charts"),
back_to_data=text("Back To Data"),
grid_links="".join(grid_links),
languages=text("Languages"),
language_links="".join(language_links),
main_title=main_title,
main_title_class=main_title_class,
main_title_style=main_title_style,
page_title=page_title,
theme=global_state.get_app_settings()["theme"],
)
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"),
dict(value="candlestick"),
dict(value="treemap"),
dict(value="funnel"),
]
if has_dashbio():
CHARTS.append(dict(value="clustergram"))
CHARTS.append(dict(value="pareto"))
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),
),
"funnel": 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=False),
funnel_group=dict(display=True),
),
"clustermap": 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=False),
funnel_group=dict(display=False),
clustergram_group=dict(display=True),
),
"pareto": 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=False),
funnel_group=dict(display=False),
clustergram_group=dict(display=False),
),
}
LOAD_TYPES = ["random", "head", "tail"]
MAP_TYPES = [
dict(value="choropleth", image=True),
dict(value="scattergeo", label="ScatterGeo", image=True),
dict(value="mapbox", label="Detailed", image=True),
]
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 load_type_msg():
return [
html.Div(
[
html.H3(
text("Load Types"), style=dict(display="inline"), className="pr-3"
),
]
),
html.Ul(
[
html.Li(
[
html.B(text("Random")),
html.Span(": {}".format(text("load_random"))),
],
className="mb-0",
),
html.Li(
[
html.B(text("Head")),
html.Span(": {}".format(text("load_head"))),
],
className="mb-0",
),
html.Li(
[
html.B(text("Tail")),
html.Span(": {}".format(text("load_tail"))),
],
className="mb-0",
),
],
className="mb-0",
),
]
[docs]def bin_type_msg():
return [
html.Div(
[
html.H3(
text("Bin Types"), style=dict(display="inline"), className="pr-3"
),
html.A(
"({})".format(text("Binning in Data Mining")),
href="https://www.geeksforgeeks.org/binning-in-data-mining/",
),
html.Br(),
]
),
html.Ul(
[
html.Li(
[
html.B(text("Equal Width")),
html.Span(
": {}".format(text("the bins are of equal sized ranges"))
),
],
className="mb-0",
),
html.Li(
[
html.B(text("Equal Frequency")),
html.Span(
": {}".format(
text("the bins contain an equal amount of values")
)
),
],
className="mb-0",
),
],
className="mb-0",
),
]
[docs]def build_img_src(proj, img_type="projections"):
return "../static/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(
[
text("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 = text("To access additional styles enter a token here...")
if get_mapbox_token() is None:
msg = text("Change your token here...")
return [
html.I(className="ico-help-outline", style=dict(color="white")),
html.Div(
[
html.Span("{}:".format("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(
[
text("Style"),
html.Div(
build_mapbox_token_children(),
className="ml-3 hoverable",
style=dict(borderBottom="none"),
id="token-hover",
),
],
className="input-group-addon",
)
[docs]def loc_mode_info():
return {
"ISO-3": dict(
url=html.A(
text("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(
text("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(
text("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=text("Load custom geojson into D-Tale")
),
}
[docs]def build_loc_mode_hover_children(loc_mode):
if loc_mode is None:
return None
loc_modes = loc_mode_info()
loc_mode_cfg = loc_modes[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(text("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(text("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",
]
YLGRBL = ["#ffffd9", "#d5efb3", "#73c9bc", "#1b99c2", "#1c4ea2", "#081d58"]
DEFAULT_CSALES = {"heatmap": JET, "maps": REDS, "3d_Scatter": YLORRD, "surface": YLGRBL}
[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 get_group_types(inputs, group_cols=None):
def _flags(group_prop):
final_group_cols = group_cols or make_list(inputs.get(group_prop))
if len(final_group_cols):
dtypes = global_state.get_dtypes(inputs["data_id"])
for dtype_info in dtypes:
if dtype_info["name"] in final_group_cols:
classifier = classify_type(dtype_info["dtype"])
if classifier == "F":
return ["bins"]
if classifier == "I":
return ["groups", "bins"]
return ["groups"]
for fgc in final_group_cols:
col, freq = fgc.split("|")
col_exists = (
next(
(
dtype_info
for dtype_info in dtypes
if dtype_info["name"] == col
),
None,
)
is not None
)
if col_exists and freq in FREQS:
return ["groups"]
return []
chart_type = inputs.get("chart_type")
if show_input_handler(chart_type)("group"):
return _flags("group")
elif show_input_handler(chart_type)("map_group"):
return _flags("map_group")
elif show_input_handler(chart_type)("cs_group"):
return _flags("cs_group")
elif show_input_handler(chart_type)("treemap_group"):
return _flags("treemap_group")
elif show_input_handler(chart_type)("funnel_group"):
return _flags("funnel_group")
elif show_input_handler(chart_type)("clustergram_group"):
return _flags("clustergram_group")
elif show_input_handler(chart_type)("pareto_group"):
return _flags("pareto_group")
return False, False
[docs]def update_label_for_freq_and_agg(val):
"""
Formats sub-values contained within 'val' to display date frequencies & aggregatioms if included.
- (val=['a', 'b', 'c']) => 'a, b, c'
- (val=['a|H', 'b|mean', 'c']) => 'a (Hour), Mean of b, c'
"""
def _freq_handler(sub_val):
selected_agg = None
for agg in AGGS:
if sub_val.endswith("|{}".format(agg)):
selected_agg = "{} of".format(text(AGGS[agg]))
sub_val = sub_val.split("|{}".format(agg))[0]
break
selected_freq = None
for freq in FREQS:
if sub_val.endswith("|{}".format(freq)):
col, freq = sub_val.split("|")
if freq in FREQS:
sub_val = sub_val.split("|{}".format(freq))[0]
if freq in FREQ_LABELS:
selected_freq = "({})".format(text(FREQ_LABELS[freq]))
break
return " ".join(list(filter(None, [selected_agg, sub_val, selected_freq])))
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, extended_aggregation=[], **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)
]
final_cols = build_final_cols(
y,
z,
inputs.get("agg"),
extended_aggregation if chart_type not in NON_EXT_AGGREGATION else [],
)
barsort_options = [build_option(o) for o in build_selections(x, final_cols)]
yaxis_options = [build_option(y2) for y2 in final_cols 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())
lat_cols, lon_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)
coord = coord_type(df[c])
if coord == "lat":
lat_cols.append(c)
elif coord == "lon":
lon_cols.append(c)
lat_options = [
build_option(c) for c in lat_cols if c not in build_selections(lon, map_val)
]
lon_options = [
build_option(c) for c in lon_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_label_value_options(
df, selected_value=None, selected_label=None, all_value=False
):
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(selected_label)
]
if all_value:
value_options = [build_option("_all_columns_", "All Columns")] + value_options
label_options = [
build_option(c) for c in cols if c not in build_selections(selected_value)
]
return value_options, label_options
[docs]def build_label_value_store(prop, inputs):
return dcc.Store(
id="{}-input-data".format(prop),
data={
k: v
for k, v in inputs.items()
if k
in [
"{}_value".format(prop),
"{}_label".format(prop),
"{}_group".format(prop),
]
},
)
[docs]def build_label_value_inputs(
prop,
inputs,
df,
group_options,
additional_inputs=[],
multi_value=False,
all_option=False,
):
show_inputs = inputs.get("chart_type") == prop
props = ["{}_value", "{}_label", "{}_group"]
selected_value, selected_label, selected_group = (
inputs.get(p.format(prop)) for p in props
)
(value_options, label_options,) = build_label_value_options(
df,
selected_value=selected_value,
selected_label=selected_label,
all_value=multi_value and all_option,
)
return html.Div(
[
build_input(
text("Value(s)" if multi_value else "Value"),
dcc.Dropdown(
id="{}-value-dropdown".format(prop),
options=value_options,
placeholder=text(
"Select Column(s)" if multi_value else "Select Column"
),
style=dict(width="inherit"),
value=selected_value,
multi=multi_value,
),
),
build_input(
text("Labels"),
dcc.Dropdown(
id="{}-label-dropdown".format(prop),
options=label_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=selected_label,
),
),
]
+ additional_inputs
+ [
build_input(
text("Group"),
dcc.Dropdown(
id="{}-group-dropdown".format(prop),
options=group_options,
multi=True,
placeholder=text("Select Group(s)"),
value=selected_group,
style=dict(width="inherit"),
),
className="col",
id="{}-group-input".format(prop),
),
],
id="{}-inputs".format(prop),
className="row charts-filters",
style={} if show_inputs else {"display": "none"},
)
[docs]def build_funnel_inputs(inputs, df, group_options):
stacked_toggle = build_input(
"{}?".format(text("Stack")),
html.Div(
daq.BooleanSwitch(
id="funnel-stack-toggle",
on=False,
),
className="toggle-wrapper",
),
id="funnel-stack-input",
style=show_style(inputs.get("funnel_group") is not None),
className="col-auto",
)
return build_label_value_inputs(
"funnel", inputs, df, group_options, additional_inputs=[stacked_toggle]
)
[docs]def build_pareto_options(df, x=None, bars=None, line=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)
x_options = [build_option(c) for c in cols if c not in [bars, line]]
bars_options = [build_option(c) for c in num_cols if c not in [x, line]]
line_options = [build_option(c) for c in num_cols if c not in [x, bars]]
sort_options = [build_option(c) for c in cols]
return x_options, bars_options, line_options, sort_options
[docs]def build_pareto_inputs(inputs, df, group_options):
show_inputs = inputs.get("chart_type") == "pareto"
x, bars, line, sort, sort_dir, group = (
inputs.get("pareto_{}".format(prop))
for prop in ["x", "bars", "line", "sort", "dir", "group"]
)
x_options, bar_options, line_options, sort_options = build_pareto_options(
df, x, bars, line
)
return html.Div(
[
build_input(
[
html.Div(text("X")),
html.Small("({})".format(text("Agg By"))),
],
dcc.Dropdown(
id="pareto-x-dropdown",
options=x_options,
placeholder="{} (1, 2, ..., N)".format(text("Default Index")),
value=x,
style=dict(width="inherit"),
),
label_class="input-group-addon d-block pt-1 pb-0",
),
build_input(
text("Bars"),
dcc.Dropdown(
id="pareto-bars-dropdown",
options=bar_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=bars,
),
),
build_input(
text("Line"),
dcc.Dropdown(
id="pareto-line-dropdown",
options=line_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=line,
),
),
build_input(
text("Sort"),
dcc.Dropdown(
id="pareto-sort-dropdown",
options=sort_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=sort,
),
),
build_input(
text("Dir"),
dcc.Dropdown(
id="pareto-dir-dropdown",
options=[build_option(d, d.capitalize()) for d in ["ASC", "DESC"]],
style=dict(width="inherit"),
value=sort_dir or "DESC",
placeholder=None,
clearable=False,
),
),
build_input(
text("Group"),
dcc.Dropdown(
id="pareto-group-dropdown",
options=group_options,
multi=True,
placeholder=text("Select Group(s)"),
value=group,
style=dict(width="inherit"),
),
className="col",
id="pareto-group-input",
),
],
id="pareto-inputs",
style={} if show_inputs else {"display": "none"},
className="row p-0 charts-filters",
)
[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", "surface", "clustergram"]
else "none"
)
[docs]def animate_styles(df, **inputs):
chart_type, agg, cpg, cpy = (
inputs.get(p) for p in ["chart_type", "agg", "cpg", "cpy"]
)
opts = []
if cpg or cpy 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", textTransform="none")
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", "funnel", "clustergram"]
return (
show_input_handler(chart_type)("group")
and len(group or [])
and not invalid_type
)
[docs]def show_chart_per_y(**inputs):
"""
Boolean function to determine whether "Chart Per Y-Axis" toggle should be displayed or not
"""
chart_type, y = (inputs.get(p) for p in ["chart_type", "y"])
return show_input_handler(chart_type)("y", "multi") and len(y or []) > 1
[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(text("Default"), "default", {"padding": "2px", "minWidth": "4em"}),
build_tab(text("Single"), "single", {"padding": "2px", "minWidth": "4em"}),
]
if len(y) <= 1:
return tabs
return tabs + [
build_tab(text("Multi"), "multi", {"padding": "2px", "minWidth": "4em"})
]
[docs]def get_yaxis_scale_tabs():
return [
build_tab(text("Linear"), "linear", {"padding": "2px", "minWidth": "4em"}),
build_tab(text("Log"), "log", {"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_map_type_hoverable():
for t in MAP_TYPES:
if t.get("image", False):
yield html.Div(
[
html.Span(text(t.get("label", t["value"].capitalize()))),
html.Img(src=build_img_src(t["value"], img_type="map_type")),
],
className="col-md-4",
)
return html.Div(
[
dcc.Tabs(
id="map-type-tabs",
value=map_type or "choropleth",
children=[
build_tab(text(t.get("label", t["value"].capitalize())), t["value"])
for t in MAP_TYPES
],
style=dict(height="36px"),
),
html.Div(
html.Div(list(_build_map_type_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):
group_types = get_group_types(inputs)
if len(group_types):
is_groups = ["groups"] == group_types or (
"groups" in group_types and inputs.get("group_type") == "groups"
)
is_bins = ["bins"] == group_types or (
"bins" in group_types and inputs.get("group_type") == "bins"
)
return (
dict(display="block" if len(group_types) > 1 else "none"),
dict(display="block" if is_groups else "none"),
dict(display="block" if is_bins else "none"),
"col-md-8",
dict(display="block"),
)
return (
dict(display="none"),
dict(display="none"),
dict(display="none"),
"col-md-12",
dict(display="none"),
)
[docs]def build_slider_counts(df, data_id, query_value):
record_ct = len(
run_query(
handle_predefined(data_id, df=df),
build_query(data_id, query_value),
global_state.get_context_variables(data_id),
)
)
slider_counts = {
v * 20: {"label": "{}% ({:,.0f})".format(v * 20, (v * 2) / 10 * record_ct)}
for v in range(1, 6)
}
slider_counts[100]["style"] = {"white-space": "nowrap"}
return slider_counts
[docs]def collapse_btn_text(is_open, label):
return "{} {}".format("\u25BC" if is_open else "\u25B6", label)
[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, load, load_type = (
inputs.get(p)
for p in ["chart_type", "x", "y", "z", "group", "agg", "load", "load_type"]
)
loc_modes = loc_mode_info()
y = y or []
show_input = show_input_handler(chart_type)
show_cpg = show_chart_per_group(**inputs)
show_cpy = show_chart_per_y(**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 = "{} (ex: col1 == 1)".format(text("Enter pandas query"))
query_value = inputs.get("query") or inner_build_query(
settings, settings.get("query")
)
query_label = html.Div(
[
html.Span(text("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,
)
cscale_style = colorscale_input_style(**inputs)
default_cscale = DEFAULT_CSALES.get(chart_type, REDS)
(
group_type_style,
group_val_style,
bins_style,
main_input_class,
show_groups,
) = 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", "cpy", "barmode", "barsort"]
},
),
dcc.Store(
id="chart-input-data",
data={
k: v
for k, v in inputs.items()
if k in ["cpg", "cpy", "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"]
},
),
build_label_value_store("treemap", inputs),
build_label_value_store("funnel", inputs),
build_label_value_store("clustergram", inputs),
dcc.Store(
id="pareto-input-data",
data={
k: v
for k, v in inputs.items()
if k
in [
"pareto_x",
"pareto_bars",
"pareto_line",
"pareto_sort",
"pareto_dir",
"pareto_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.Store(id="load-clicks", data=0),
dcc.Store(id="save-clicks", data=0),
dcc.Input(id="chart-code", type="hidden"),
html.Div(
[
html.Div(
dbc.Button(
collapse_btn_text(False, text("Data Selection")),
id="collapse-data-btn",
),
className="col-auto pr-0",
),
html.Div(
dbc.Collapse(
dbc.Card(
dbc.CardBody(
[
dcc.Tabs(
id="data-tabs",
value=inputs["data_id"],
children=[
build_tab(
global_state.get_name(k) or k,
str(k),
id="data-tab-{}".format(k),
)
for k in global_state.keys()
],
style=dict(height="36px"),
)
]
+ [
dbc.Tooltip(
global_state.get_name(k) or k,
target="data-tab-{}".format(k),
)
for k in global_state.keys()
]
)
),
id="collapse-data",
),
className="col",
),
],
className="row pb-3 charts-filters",
style=dict(display="none" if len(global_state.keys()) < 2 else "block"),
),
html.Div(
html.Div(
[
dcc.Tabs(
id="chart-tabs",
value=chart_type or "line",
children=[
build_tab(
text(t.get("label", t["value"].capitalize())),
t["value"],
id="chart-type-tab-{}".format(i),
)
for i, t in enumerate(CHARTS)
],
style=dict(height="36px"),
),
]
+ [
dbc.Tooltip(
text(t.get("label", t["value"].capitalize())),
target="chart-type-tab-{}".format(i),
)
for i, t in enumerate(CHARTS)
],
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_hoverable(
html.Span(text("Load")),
load_type_msg(),
additional_classes="load-types-tooltip mb-auto mt-auto",
top="100%",
),
dcc.Dropdown(
id="load-type-dropdown",
options=[
build_option(v, v.capitalize()) for v in LOAD_TYPES
],
className="pl-5",
value=load_type or "random",
clearable=False,
),
dcc.Slider(
id="load-input",
min=10,
max=100,
step=10,
value=100 if load is None else load,
className="w-100",
marks=build_slider_counts(
df, inputs["data_id"], query_value
),
tooltip={
"always_visible": False,
"placement": "left",
},
),
],
className="input-group mr-3",
)
],
className="col",
),
className="row pt-3 pb-0 charts-filters",
),
html.Div(
[
html.Div(
[
dbc.Button(
collapse_btn_text(False, text("Cleaners")),
id="collapse-cleaners-btn",
),
html.Span(
"",
id="selected-cleaners",
className="pl-3",
style=dict(fontSize="85%"),
),
],
className="col-auto pr-0",
),
html.Div(
dbc.Collapse(
dbc.Card(
dbc.CardBody(
dcc.Dropdown(
id="cleaners-dropdown",
options=[
build_option(c["value"], c["label"])
for c in get_cleaner_configs()
],
multi=True,
placeholder=text("Select Cleaner(s)"),
value=group,
style=dict(width="inherit"),
),
)
),
id="collapse-cleaners",
),
className="col",
),
],
className="row pb-3 charts-filters",
style=dict(display="block"),
),
html.Div(
[
html.Div(
[
html.Div(
[
build_input(
[
html.Div(text("X")),
html.Small("({})".format(text("Agg By"))),
],
dcc.Dropdown(
id="x-dropdown",
options=x_options,
placeholder="{} (1, 2, ..., N)".format(
text("Default Index")
),
value=x,
style=dict(width="inherit"),
),
label_class="input-group-addon d-block pt-1 pb-0",
),
build_input(
text("Y"),
dcc.Dropdown(
id="y-multi-dropdown",
options=y_multi_options,
multi=True,
placeholder=text("Select 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(text("Y")),
html.Small("({})".format(text("Agg By"))),
],
dcc.Dropdown(
id="y-single-dropdown",
options=y_single_options,
placeholder=text("Select 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(
text("Z"),
dcc.Dropdown(
id="z-dropdown",
options=z_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=z,
),
className="col",
id="z-input",
style=show_style(show_input("z")),
),
build_input(
text("Group"),
dcc.Dropdown(
id="group-dropdown",
options=group_options,
multi=True,
placeholder=text("Select 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 chart_type not in ["treemap", "funnel", "clustergram"]
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_modes[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(text("Locations")),
html.Small("({})".format(text("Agg By"))),
],
dcc.Dropdown(
id="map-loc-dropdown",
options=loc_options,
placeholder=text("Select 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(text("Lat")),
html.Small("({})".format(text("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(text("Lon")),
html.Small("({})".format(text("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(
text("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(
text("Value"),
dcc.Dropdown(
id="map-val-dropdown",
options=map_val_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=map_val,
),
),
build_input(
text("Group"),
dcc.Dropdown(
id="map-group-dropdown",
options=group_options,
multi=True,
placeholder=text("Select 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(
text("X"),
dcc.Dropdown(
id="candlestick-x-dropdown",
options=cs_x_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=cs_x,
),
),
build_input(
text("Open"),
dcc.Dropdown(
id="candlestick-open-dropdown",
options=open_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=cs_open,
),
),
build_input(
text("High"),
dcc.Dropdown(
id="candlestick-high-dropdown",
options=high_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=cs_high,
),
),
build_input(
text("Low"),
dcc.Dropdown(
id="candlestick-low-dropdown",
options=low_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=cs_low,
),
),
build_input(
text("Close"),
dcc.Dropdown(
id="candlestick-close-dropdown",
options=close_options,
placeholder=text("Select Column"),
style=dict(width="inherit"),
value=cs_close,
),
),
build_input(
text("Group"),
dcc.Dropdown(
id="candlestick-group-dropdown",
options=group_options,
multi=True,
placeholder=text("Select 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"},
),
build_label_value_inputs("treemap", inputs, df, group_options),
build_funnel_inputs(inputs, df, group_options),
build_label_value_inputs(
"clustergram",
inputs,
df,
group_options,
multi_value=True,
all_option=True,
),
build_pareto_inputs(inputs, df, group_options),
html.Div(
[
html.Div(
[
build_input(
text("Aggregation"),
dcc.Dropdown(
id="agg-dropdown",
options=[
build_option(v, text(AGGS[v]))
for v in [
"count",
"pctct",
"nunique",
"sum",
"mean",
"rolling",
"corr",
"first",
"last",
"drop_duplicates",
"median",
"min",
"max",
"std",
"var",
"mad",
"prod",
"pctsum",
]
],
placeholder=text("No Aggregation"),
style=dict(width="inherit"),
value=agg or "raw",
disabled=len(
inputs.get(
"extended_aggregation", []
)
)
> 0,
),
),
html.Span(
"* {}".format(
text(
"Extended Aggregation is currently populated."
)
),
id="ext-agg-warning",
style=show_style(
len(
inputs.get(
"extended_aggreation", []
)
)
> 0
),
className="ext-agg-warning",
),
]
),
]
+ extended_aggregations.build_modal(
inputs.get("extended_aggregation", []), chart_type, y
)
+ [
html.Div(
[
build_input(
text("Window"),
dcc.Input(
id="window-input",
type="number",
placeholder=text("Enter Days"),
className="form-control text-center",
style={"lineHeight": "inherit"},
value=inputs.get("window"),
),
),
build_input(
text("Computation"),
dcc.Dropdown(
id="rolling-comp-dropdown",
options=[
build_option(
"corr", text("Correlation")
),
build_option(
"count", text("Count")
),
build_option(
"cov", text("Covariance")
),
build_option(
"kurt", text("Kurtosis")
),
build_option(
"max", text("Maximum")
),
build_option("mean", text("Mean")),
build_option(
"median", text("Median")
),
build_option(
"min", text("Minimum")
),
build_option("skew", text("Skew")),
build_option(
"std",
text("Standard Deviation"),
),
build_option("sum", text("Sum")),
build_option(
"var", text("Variance")
),
],
placeholder=text("Select Computation"),
style=dict(width="inherit"),
value=inputs.get("rolling_comp"),
),
),
],
id="rolling-inputs",
style=show_style(agg == "rolling"),
),
build_input(
text("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",
),
],
id="main-inputs",
className=main_input_class,
),
html.Div(
[
html.Div(
html.Div(
html.Div(
[
html.Span(
text("Group Type"),
className="input-group-addon",
),
html.Div(
dcc.Tabs(
id="group-type",
value=inputs.get("group_type")
or "groups",
children=[
build_tab(
text("Values"),
"groups",
{
"padding": "2px",
"minWidth": "4em",
},
),
build_tab(
text("Bins"),
"bins",
{
"padding": "2px",
"minWidth": "4em",
},
),
],
),
id="group-type-div",
className="form-control col-auto pt-3",
),
],
className="input-group",
),
className="addon-min-width",
),
className="col-md-12 p-0 pb-5",
id="group-type-input",
style=group_type_style,
),
build_input(
text("Group(s)"),
dcc.Dropdown(
id="group-val-dropdown",
multi=True,
placeholder=text("Select Group Value(s)"),
value=group_val,
style=dict(width="inherit"),
),
className="col-md-12 p-0 pb-5",
id="group-val-input",
style=group_val_style,
),
build_input(
text("Bins"),
[
daq.NumericInput(
id="bins-val-input",
min=1,
max=30,
value=inputs.get("bins_val") or 5,
),
html.Div(
html.Div(
[
html.Span(
text("Binning"),
className="input-group-addon",
),
html.Div(
build_hoverable(
dcc.Tabs(
id="bin-type",
value=inputs.get("bin_type")
or "width",
children=[
build_tab(
text("Width"),
"width",
{
"padding": "2px",
"minWidth": "4em",
},
),
build_tab(
text("Freq"),
"freq",
{
"padding": "2px",
"minWidth": "4em",
},
),
],
),
bin_type_msg(),
"",
top="120%",
),
id="bin-type-div",
className="form-control col-auto pt-3",
),
],
className="input-group",
),
className="col-auto addon-min-width",
id="bin-type-input",
),
],
className="col-md-12 p-0",
id="bins-input",
style=bins_style,
),
],
id="group-inputs-row",
className="col-md-4 row pt-3 pb-5",
style=show_groups,
),
],
className="row",
),
html.Div(
[
build_input(
text("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(
text("Chart Per\nY"),
html.Div(
daq.BooleanSwitch(
id="cpy-toggle",
on=inputs.get("cpy") or False,
),
className="toggle-wrapper",
),
id="cpy-input",
style=show_style(show_cpy),
className="col-auto",
),
build_input(
text("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(
text("Barmode"),
dcc.Dropdown(
id="barmode-dropdown",
options=[
build_option("group", text("Group")),
build_option("stack", text("Stack")),
build_option("relative", text("Relative")),
],
value=inputs.get("barmode") or "group",
placeholder=text("Select Mode"),
),
className="col-auto addon-min-width",
style=bar_style,
id="barmode-input",
),
build_input(
text("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",
),
build_input(
text("Top"),
dcc.Dropdown(
id="top-bars",
options=[build_option(v) for v in [5, 10, 20, 50]],
value=inputs.get("top_bars"),
placeholder=None,
),
className="col-auto",
style=barsort_input_style,
id="top-bars-input",
),
html.Div(
html.Div(
[
html.Span(
text("Y-Axis"),
className="input-group-addon",
),
html.Div(
[
dcc.Tabs(
id="yaxis-scale",
value=inputs.get("scale") or "linear",
children=get_yaxis_scale_tabs(),
className="pr-5",
),
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(
"{}:".format(text("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(
"{}:".format(text("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(
text("Colorscale"),
dcs.DashColorscales(
id="colorscale-picker",
colorscale=inputs.get("colorscale") or default_cscale,
),
className="col-auto addon-min-width pr-0",
style=cscale_style,
id="colorscale-input",
),
build_input(
text("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(
text("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(
text("Lock Zoom"),
id="lock-zoom-btn",
className="ml-auto",
style=lock_zoom_style(chart_type),
),
build_input(
build_hoverable(
html.Div(text("Auto-Load"), style=dict(color="white")),
auto_load_msg(),
"",
top="120%",
),
html.Div(
daq.BooleanSwitch(
id="auto-load-toggle",
on=True,
color="green",
),
className="toggle-wrapper",
),
id="auto-load-input",
className="ml-auto col-auto",
),
dbc.Button(
text("Load"),
id="load-btn",
color="primary",
style=dict(display="none"),
),
build_hoverable(
dbc.Button(
text("Save"),
id="save-btn",
color="primary",
style=dict(display="none"),
),
text("save_msg"),
"",
top="120%",
),
],
className="row pt-3 pb-5 charts-filters",
id="chart-inputs",
),
dcc.Loading(
html.Div(id="chart-content", style={"max-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(
text("Fork me on Github"), href="https://github.com/man-group/dtale"
),
id="forkongithub",
)
)
return body_items