Py.Cafe

petar-qb/

issue-1062

Iris Species Histogram and Scatter Plot with Theme Toggle

DocsPricing
  • assets/
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from pathlib import Path
from typing import Literal

import vizro.plotly.express as px
from dash import clientside_callback, ClientsideFunction, dcc, html, Input, Output, State, get_asset_url
from vizro import Vizro
import vizro.models as vm
from vizro.models.types import capture

UNDERLYING_HIST_CHART_ID = "underlying_hist_chart"


df = px.data.iris()


# Custom figure that returns dcc.Graph with a histogram figure.
# It takes a display_mode_bar parameter from the UI Dashboard to show/hide the mode bar.
@capture("figure")
def plot_histogram(data_frame, display_mode_bar=True):
    fig = px.histogram(data_frame, x="sepal_width", color="species")

    return dcc.Graph(
        id=UNDERLYING_HIST_CHART_ID,
        figure=fig,
        config={
            "displayModeBar": display_mode_bar,
        },
    )


# clientside callback hack that updates the "dcc.Graph" even though it's not created using the "vm.Graph" component.
clientside_callback(
    ClientsideFunction(namespace="dashboard", function_name="update_graph_theme"),
    output=[
        Output(UNDERLYING_HIST_CHART_ID, "figure"),
        Output(UNDERLYING_HIST_CHART_ID, "style")
    ],
    inputs=[
        Input(UNDERLYING_HIST_CHART_ID, "figure"),
        Input("theme-selector", "value"),
        State("vizro_themes", "data"),
    ],
)


# Custom Vizro component that serves two images but only one is visible based on the theme.
# See the "hack" of showing/hiding the content based on selected theme within the "assets/custom.css".
class ThemedImage(vm.VizroBaseModel):
    """New custom component `ThemedImage`."""

    type: Literal["themed_image"] = "themed_image"
    src_dark: str
    src_light: str

    def build(self):
        assets_url_dark = get_asset_url(self.src_dark)
        assets_url_light = get_asset_url(self.src_light)

        return html.Div(
            id=self.id,
            children=[
                html.Img(id=f"my_image_dark", src=assets_url_dark),
                html.Img(id=f"my_image_light", src=assets_url_light)
            ]
        )


# Enabling custom component to be used within the "vm.Page.components".
vm.Page.add_type("components", ThemedImage)


page = vm.Page(
    title="Vizro on PyCafe",
    components=[
        ThemedImage(src_dark="google-dark.png", src_light="google-light.png"),
        vm.Graph(id="scatter_chart", figure=px.scatter(df, x="sepal_length", y="petal_width", color="species")),
        vm.Figure(id="hist_chart", figure=plot_histogram(data_frame=df)),
    ],
    controls=[
        vm.Filter(column="species"), vm.Filter(column="petal_length"), vm.Filter(column="sepal_width"),
        vm.Parameter(
            targets=["hist_chart.display_mode_bar"],
            selector=vm.RadioItems(
                id="display_mode_bar",
                options=[{"label": "True", "value": True}, {"label": "False", "value": False}],
                value=True,
            )
        )
    ],
)

dashboard = vm.Dashboard(pages=[page])
Vizro().build(dashboard).run()