Py.Cafe

vizro-official/

kedro-vizro example

Kedro-Vizro example dashboard

DocsPricing
  • data/
  • app.py
  • data_generation.py
  • kedro_pipeline.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""Vizro dashboard that parametrizes, runs and explores a Kedro pipeline."""

from functools import cached_property

import vizro.actions as va
import vizro.models as vm
import vizro.plotly.express as px
from data_generation import CATEGORIES, REGIONS, ensure_orders_data, ensure_scenario_results_file
from kedro_pipeline import build_static_catalog, load_breakdown_data, run_scenario
from vizro import Vizro
from vizro.integrations import kedro as kedro_integration
from vizro.managers import data_manager
from vizro.models._components.form._user_input import UserInput
from vizro.models.types import capture
from vizro.tables import dash_ag_grid

ensure_orders_data()
ensure_scenario_results_file()

static_catalog = build_static_catalog()
for dataset_name, dataset_loader in kedro_integration.datasets_from_catalog(static_catalog).items():
    data_manager[dataset_name] = dataset_loader

data_manager["breakdown"] = load_breakdown_data


@capture("action")
def run_kedro_scenario(scenario_name, region, categories, min_order_value):
    """Runs kedro scenario."""
    result = run_scenario(
        scenario_name=scenario_name,
        region=region,
        categories=categories,
        min_order_value=min_order_value,
    )
    message = (
        f"{result['n_orders']} orders, ${result['total_revenue']:,.0f} total revenue "
        f"(avg ${result['avg_order_value']:,.0f} per order)."
    )
    return message, ("success", message)


@capture("action")
def validate_load_scenario(selected_rows):
    """Raises an exception if no scenario is selected in the table."""
    if not selected_rows:
        raise Exception("Select a scenario in the table first.", "no_selection")


class set_controls_with_no_notifications(va.set_controls):
    """Selecting a table row sets a hidden control, so a "Controls updated." notification would only confuse."""

    @cached_property
    def notifications(self):
        """Disables the default success and error notifications of `set_controls`."""
        return {"success": None, "error": None}


vm.Container.add_type("components", UserInput)
vm.Container.add_type("components", vm.Slider)
vm.Container.add_type("components", vm.RadioItems)
vm.Container.add_type("components", vm.Checklist)


page = vm.Page(
    title="Kedro scenario planner",
    layout=vm.Grid(
        grid=[
            [0, 0, 2, 2],
            [0, 0, 2, 2],
            [1, 1, 2, 2],
            [1, 1, 2, 2],
        ]
    ),
    components=[
        vm.Container(
            title="Configure scenario",
            components=[
                UserInput(
                    id="scenario_name_input",
                    title="Scenario name",
                    placeholder="e.g. west-electronics-push",
                ),
                vm.RadioItems(id="region_input", title="Region", options=REGIONS, value=REGIONS[0]),
                vm.Checklist(
                    id="categories_input",
                    title="Categories to include",
                    options=CATEGORIES,
                    value=CATEGORIES,
                ),
                vm.Slider(
                    id="min_order_value_input",
                    title="Minimum order value ($)",
                    min=0,
                    max=500,
                    step=25,
                    value=0,
                ),
                vm.Button(
                    text="Run scenario",
                    actions=[
                        vm.Action(
                            function=run_kedro_scenario(
                                scenario_name="scenario_name_input",
                                region="region_input",
                                categories="categories_input",
                                min_order_value="min_order_value_input",
                            ),
                            outputs="pipeline_status",
                            notifications={
                                "progress": "Running scenario '{scenario_name}'...",
                                "success": "Scenario completed: {result}",
                                "error": "Scenario failed: {error_msg}",
                                "invalid_name": "{error_msg}",
                                "no_categories": "{error_msg}",
                                "duplicate_name": "{error_msg}",
                                "no_matching_orders": "{error_msg}",
                            },
                        ),
                        va.update_targets(targets=["scenario_table"]),
                    ],
                ),
                vm.Text(id="pipeline_status", text="Configure a scenario and click 'Run scenario'."),
            ],
            layout=vm.Grid(
                grid=[[0, 0, 1, 2], [0, 0, 1, 2], [3, 3, 1, 2], [3, 3, 1, 2], [5, 5, 5, -1], [4, -1, -1, -1]],
                row_gap="20px",
            ),
            variant="outlined",
        ),
        vm.Container(
            title="Load & explore existing scenarios",
            components=[
                vm.Table(
                    id="scenario_table",
                    figure=dash_ag_grid(
                        "scenario_results",
                        dashGridOptions={"rowSelection": {"mode": "singleRow"}},
                    ),
                    actions=set_controls_with_no_notifications(controls=["scenario_name_param"], value="scenario_name"),
                ),
                vm.Button(
                    text="Load Scenario",
                    actions=[
                        vm.Action(
                            function=validate_load_scenario(selected_rows="scenario_table.selectedRows"),
                            notifications={"no_selection": "{error_msg}"},
                        ),
                        va.update_targets(targets=["revenue_chart", "orders_chart"]),
                    ],
                ),
            ],
            layout=vm.Grid(grid=[[0], [0], [1]]),
        ),
        vm.Container(
            title="Selected scenario breakdown",
            layout=vm.Grid(grid=[[0], [1]]),
            components=[
                vm.Graph(
                    id="revenue_chart",
                    figure=px.bar("breakdown", x="category", y="total_revenue", title="Revenue by category"),
                ),
                vm.Graph(
                    id="orders_chart",
                    figure=px.bar("breakdown", x="category", y="n_orders", title="Orders by category"),
                ),
            ],
        ),
    ],
    controls=[
        vm.Parameter(
            id="scenario_name_param",
            targets=["revenue_chart.data_frame.scenario_name", "orders_chart.data_frame.scenario_name"],
            selector=vm.Dropdown(
                options=["(select a scenario)"], value="(select a scenario)", multi=False, actions=None
            ),
            visible=False,
        ),
    ],
)

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

if __name__ == "__main__":
    app.run()