—
Carbon Bridge Analysis — Dash Dashboard.
Imports the data pipeline and figure builder from carbon_bridge_analysis, then wraps them in an interactive Dash application with live filter controls.
Run with:
python examples/carbon_bridge_analysis_dash.py
Then open http://127.0.0.1:8050 in your browser.
For a standalone (non-Dash) Plotly chart instead:
python examples/carbon_bridge_analysis.py
import sys
from pathlib import Path
from typing import Any, cast
# Ensure the examples/ folder is on sys.path so the sibling module is importable
# regardless of the working directory the user launches from.
sys.path.insert(0, str(Path(__file__).parent))
from carbon_bridge_analysis import build_dataframe, build_figure # noqa: E402
from dash import Dash, Input, Output, dcc, html # noqa: E402
# ── Build the data once at startup ───────────────────────────────────────────
df_all = build_dataframe()
ALL_TESTS_IN_DATA = sorted(df_all["Test"].unique().tolist())
ALL_GENS_IN_DATA = sorted(df_all["generator"].unique().tolist())
# ── Layout helpers ────────────────────────────────────────────────────────────
_BTN_STYLE = {"fontSize": "11px", "padding": "2px 7px", "cursor": "pointer"}
_SECTION_HEADER = {
"marginTop": "14px",
"marginBottom": "6px",
"fontSize": "13px",
"fontWeight": "bold",
"color": "#333",
}
def _filter_section(
title: str, btn_all_id: str, btn_none_id: str, checklist_id: str, options: list[str]
) -> html.Div:
return html.Div(
[
html.Div(title, style=_SECTION_HEADER),
html.Span(
[
html.Button(
"All",
id=btn_all_id,
n_clicks=0,
style={**_BTN_STYLE, "marginRight": "4px"},
),
html.Button("None", id=btn_none_id, n_clicks=0, style=_BTN_STYLE),
]
),
html.Hr(style={"margin": "8px 0"}),
dcc.Checklist(
id=checklist_id,
options=cast(Any, [{"label": f" {v}", "value": v} for v in options]),
value=options,
labelStyle={
"display": "block",
"fontSize": "12px",
"marginBottom": "3px",
},
inputStyle={"marginRight": "5px"},
),
]
)
# ── Dash application ──────────────────────────────────────────────────────────
app = Dash(__name__, title="Carbon Bridge Analysis")
app.layout = html.Div(
style={"display": "flex", "fontFamily": "sans-serif", "height": "100vh"},
children=[
# ── Left panel: filters ──────────────────────────────────────────────
html.Div(
style={
"width": "190px",
"minWidth": "190px",
"padding": "14px 14px 14px 12px",
"borderRight": "1px solid #ddd",
"overflowY": "auto",
"background": "#fafafa",
},
children=[
html.H4(
"Filters",
style={"marginTop": 0, "marginBottom": "4px", "fontSize": "15px"},
),
_filter_section(
"Tests",
"btn-test-all",
"btn-test-none",
"test-checklist",
ALL_TESTS_IN_DATA,
),
_filter_section(
"Generator",
"btn-gen-all",
"btn-gen-none",
"gen-checklist",
ALL_GENS_IN_DATA,
),
],
),
# ── Main panel: graph ────────────────────────────────────────────────
html.Div(
style={"flex": "1", "padding": "16px", "overflowY": "auto"},
children=[
dcc.Graph(
id="main-graph",
figure=build_figure(df_all, ALL_TESTS_IN_DATA, ALL_GENS_IN_DATA),
style={"height": "calc(100vh - 40px)"},
config={"displayModeBar": True, "scrollZoom": True},
),
],
),
],
)
# ── Callbacks ─────────────────────────────────────────────────────────────────
@app.callback(
Output("test-checklist", "value"),
Input("btn-test-all", "n_clicks"),
Input("btn-test-none", "n_clicks"),
prevent_initial_call=True,
)
def _toggle_tests(n_all, n_none):
from dash import ctx
return ALL_TESTS_IN_DATA if ctx.triggered_id == "btn-test-all" else []
@app.callback(
Output("gen-checklist", "value"),
Input("btn-gen-all", "n_clicks"),
Input("btn-gen-none", "n_clicks"),
prevent_initial_call=True,
)
def _toggle_gens(n_all, n_none):
from dash import ctx
return ALL_GENS_IN_DATA if ctx.triggered_id == "btn-gen-all" else []
@app.callback(
Output("main-graph", "figure"),
Input("test-checklist", "value"),
Input("gen-checklist", "value"),
)
def _update_graph(selected_tests, selected_gens):
return build_figure(df_all, selected_tests or [], selected_gens or [])
# ── Entry-point ───────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("\nStarting Dash app at http://127.0.0.1:8050")
app.run(debug=False, port=8050)