import json
import pandas as pd
import vizro.models as vm
import yaml
from vizro import Vizro
from vizro.tables import dash_ag_grid
from custom_components import (
NGPTree,
calculate_price_scoring_table,
create_cluster_kpi,
create_cluster_table,
create_group_level_table,
create_sku_avg_price_adj_kpi,
create_sku_review_kpi,
create_sku_table,
create_stepped_scatter,
create_table_with_price_increase,
create_table_with_reviews,
create_violin_chart,
scatter_with_quadrants,
)
from custom_control_components import ControlGroup, CustomUserInput
## ADDING Customer Control components
vm.Parameter.add_type("selector", CustomUserInput)
vm.Page.add_type("controls", ControlGroup)
vm.Container.add_type("components", ControlGroup)
vm.Page.add_type("components", NGPTree)
## LOADING TREE STRUCTURE
with open("input_data//tree_definition.yaml", "r") as file:
# Load the YAML content
tree = yaml.safe_load(file)
## LOAding feature importance
feature_importance_df = pd.read_csv("input_data//global_feature_importances.csv")
## LOADING IMPACT SUMMARY
impact_summary = pd.read_csv("input_data//dummy_synthetic_data.csv")
print(impact_summary.shape)
weight = 1
scoring_metric_col_list = [
"Price sensitivity",
"Commodity vs Functional",
"Contribution to subsidiaries",
"Indicative market share",
"Price gap",
"Price trend",
"Sales volume trend",
"Cost trend",
"Claims data",
]
default_col1_name_value = scoring_metric_col_list[0]
default_col1_direction_value = "Ascending"
default_col1_weight_value = 0.5
default_col2_name_value = scoring_metric_col_list[1]
default_col2_direction_value = "Ascending"
default_col2_weight_value = 0.5
default_percentile_range_value_dict = {
1: 10,
2: 20,
3: 40,
4: 60,
5: 100,
}
default_price_adjustment_value_dict = {
1: 2,
2: 4,
3: 6,
4: 8,
5: 9,
}
## CREATING PARAMETERS FOR SCORING METRICS
def create_scoring_metric_params(i):
if i == 1:
param_list = [
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_name",
"enhanced_scatter_table.col" + str(i) + "_name",
# "enhanced_scatter_2_table.col" + str(i) + "_name",
# "enhanced_scatter_2.col" + str(i) + "_name",
# "sku_table.col" + str(i) + "_name",
# "cluster_table.col" + str(i) + "_name",
"group_table.col" + str(i) + "_name",
"violin_chart.col" + str(i) + "_name",
"kpi_card.col" + str(i) + "_name",
"kpi_card_2.col" + str(i) + "_name",
"kpi_card_3.col" + str(i) + "_name",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_selector",
# title="METRIC " + str(i),
title="Name",
options=scoring_metric_col_list + ["NONE"],
multi=False,
value=default_col1_name_value,
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_direction",
"enhanced_scatter_table.col" + str(i) + "_direction",
# "enhanced_scatter_2_table.col" + str(i) + "_direction",
# "enhanced_scatter_2.col" + str(i) + "_direction",
# "sku_table.col" + str(i) + "_direction",
# "cluster_table.col" + str(i) + "_direction",
"group_table.col" + str(i) + "_direction",
"violin_chart.col" + str(i) + "_direction",
"kpi_card.col" + str(i) + "_direction",
"kpi_card_2.col" + str(i) + "_direction",
"kpi_card_3.col" + str(i) + "_direction",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_direction_selector",
title="Direction",
options=["Ascending", "Descending", "NONE"],
multi=False,
value=default_col1_direction_value,
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_weight",
"enhanced_scatter_table.col" + str(i) + "_weight",
# "enhanced_scatter_2_table.col" + str(i) + "_weight",
# "enhanced_scatter_2.col" + str(i) + "_weight",
# "sku_table.col" + str(i) + "_weight",
# "cluster_table.col" + str(i) + "_weight",
"group_table.col" + str(i) + "_weight",
"violin_chart.col" + str(i) + "_weight",
"kpi_card.col" + str(i) + "_weight",
"kpi_card_2.col" + str(i) + "_weight",
"kpi_card_3.col" + str(i) + "_weight",
],
selector=vm.Slider(
id="col" + str(i) + "_name_weight_selector",
title="Weight",
min=0,
max=1,
step=0.1,
value=default_col1_weight_value,
),
),
]
elif i == 2:
param_list = [
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_name",
"enhanced_scatter_table.col" + str(i) + "_name",
# "enhanced_scatter_2_table.col" + str(i) + "_name",
# "enhanced_scatter_2.col" + str(i) + "_name",
# "sku_table.col" + str(i) + "_name",
# "cluster_table.col" + str(i) + "_name",
"group_table.col" + str(i) + "_name",
"violin_chart.col" + str(i) + "_name",
"kpi_card.col" + str(i) + "_name",
"kpi_card_2.col" + str(i) + "_name",
"kpi_card_3.col" + str(i) + "_name",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_selector",
title="Name",
options=scoring_metric_col_list + ["NONE"],
multi=False,
value=default_col2_name_value,
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_direction",
"enhanced_scatter_table.col" + str(i) + "_direction",
# "enhanced_scatter_2_table.col" + str(i) + "_direction",
# "enhanced_scatter_2.col" + str(i) + "_direction",
# "sku_table.col" + str(i) + "_direction",
# "cluster_table.col" + str(i) + "_direction",
"group_table.col" + str(i) + "_direction",
"violin_chart.col" + str(i) + "_direction",
"kpi_card.col" + str(i) + "_direction",
"kpi_card_2.col" + str(i) + "_direction",
"kpi_card_3.col" + str(i) + "_direction",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_direction_selector",
title="Direction",
options=["Ascending", "Descending", "NONE"],
multi=False,
value=default_col2_direction_value,
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_weight",
"enhanced_scatter_table.col" + str(i) + "_weight",
# "enhanced_scatter_2_table.col" + str(i) + "_weight",
# "enhanced_scatter_2.col" + str(i) + "_weight",
# "sku_table.col" + str(i) + "_weight",
# "cluster_table.col" + str(i) + "_weight",
"group_table.col" + str(i) + "_weight",
"violin_chart.col" + str(i) + "_weight",
"kpi_card.col" + str(i) + "_weight",
"kpi_card_2.col" + str(i) + "_weight",
"kpi_card_3.col" + str(i) + "_weight",
],
selector=vm.Slider(
id="col" + str(i) + "_name_weight_selector",
title="Weight",
min=0,
max=1,
step=0.1,
value=default_col2_weight_value,
),
),
]
else:
param_list = [
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_name",
"enhanced_scatter_table.col" + str(i) + "_name",
# "enhanced_scatter_2_table.col" + str(i) + "_name",
# "enhanced_scatter_2.col" + str(i) + "_name",
# "sku_table.col" + str(i) + "_name",
# "cluster_table.col" + str(i) + "_name",
"group_table.col" + str(i) + "_name",
"violin_chart.col" + str(i) + "_name",
"kpi_card.col" + str(i) + "_name",
"kpi_card_2.col" + str(i) + "_name",
"kpi_card_3.col" + str(i) + "_name",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_selector",
title="Name",
options=scoring_metric_col_list + ["NONE"],
multi=False,
value="NONE",
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_direction",
"enhanced_scatter_table.col" + str(i) + "_direction",
# "enhanced_scatter_2_table.col" + str(i) + "_direction",
# "enhanced_scatter_2.col" + str(i) + "_direction",
# "sku_table.col" + str(i) + "_direction",
# "cluster_table.col" + str(i) + "_direction",
"group_table.col" + str(i) + "_direction",
"violin_chart.col" + str(i) + "_direction",
"kpi_card.col" + str(i) + "_direction",
"kpi_card_2.col" + str(i) + "_direction",
"kpi_card_3.col" + str(i) + "_direction",
],
selector=vm.Dropdown(
id="col" + str(i) + "_name_direction_selector",
title="Direction",
options=["Ascending", "Descending", "NONE"],
multi=False,
value="NONE",
),
),
vm.Parameter(
targets=[
"my_table.col" + str(i) + "_weight",
"enhanced_scatter_table.col" + str(i) + "_weight",
# "enhanced_scatter_2_table.col" + str(i) + "_weight",
# "enhanced_scatter_2.col" + str(i) + "_weight",
# "sku_table.col" + str(i) + "_weight",
# "cluster_table.col" + str(i) + "_weight",
"group_table.col" + str(i) + "_weight",
"violin_chart.col" + str(i) + "_weight",
"kpi_card.col" + str(i) + "_weight",
"kpi_card_2.col" + str(i) + "_weight",
"kpi_card_3.col" + str(i) + "_weight",
],
selector=vm.Slider(
id="col" + str(i) + "_name_weight_selector",
title="Weight",
min=0,
max=1,
step=0.1,
value=0.5,
),
),
]
return param_list
def create_percentile_period_params(i):
param_list = [
vm.Parameter(
targets=[
"enhanced_scatter.period_" + str(i) + "_range",
"enhanced_scatter_table.period_" + str(i) + "_range",
# "enhanced_scatter_2_table.period_" + str(i) + "_range",
# "enhanced_scatter_2.period_" + str(i) + "_range",
# "sku_table.period_" + str(i) + "_range",
# "cluster_table.period_" + str(i) + "_range",
"group_table.period_" + str(i) + "_range",
"violin_chart.period_" + str(i) + "_range",
"kpi_card.period_" + str(i) + "_range",
"kpi_card_2.period_" + str(i) + "_range",
"kpi_card_3.period_" + str(i) + "_range",
],
selector=CustomUserInput(
id="period_" + str(i) + "_range_selector",
title="Range Upper Limit",
value=default_percentile_range_value_dict[i],
),
),
vm.Parameter(
targets=[
"enhanced_scatter.period_" + str(i) + "_price_adjustment",
"enhanced_scatter_table.period_" + str(i) + "_price_adjustment",
# "enhanced_scatter_2_table.period_" + str(i) + "_price_adjustment",
# "enhanced_scatter_2.period_" + str(i) + "_price_adjustment",
# "sku_table.period_" + str(i) + "_price_adjustment",
# "cluster_table.period_" + str(i) + "_price_adjustment",
"group_table.period_" + str(i) + "_price_adjustment",
"violin_chart.period_" + str(i) + "_price_adjustment",
"kpi_card.period_" + str(i) + "_price_adjustment",
"kpi_card_2.period_" + str(i) + "_price_adjustment",
"kpi_card_3.period_" + str(i) + "_price_adjustment",
],
selector=vm.Slider(
id="period_" + str(i) + "_price_adjustment_selector",
title="Price Adjustment %",
min=1,
max=10,
step=1,
value=default_price_adjustment_value_dict[i],
),
),
]
return param_list
#### Dashboard Definition starts here
# PAGE 1 - Decision Tree
decision_tree_page = vm.Page(
title="Decision Tree View",
components=[
NGPTree(tree_id="vizro-adapted-tree", payload=json.dumps(tree)),
],
)
## Page 2 - Feature Importance
feature_importance_page = vm.Page(
title="Global Feature Importance View",
components=[vm.AgGrid(figure=dash_ag_grid(data_frame=feature_importance_df))],
)
results_page = vm.Page(
# title="Tabs",
title="Price Adjustment Dashboard",
layout=vm.Layout(grid=[[0, 1, 2], [3, 3, 3], [3, 3, 3], [3, 3, 3]]),
components=[
vm.Figure(
id="kpi_card",
figure=create_cluster_kpi(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
x="revenue",
y="Price Adjustment %",
x_ref_quantile=0.5,
y_ref_quantile=0.5,
),
),
vm.Figure(
id="kpi_card_2",
figure=create_sku_avg_price_adj_kpi(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
x="revenue",
y="Price Adjustment %",
x_ref_quantile=0.5,
y_ref_quantile=0.5,
),
),
vm.Figure(
id="kpi_card_3",
figure=create_sku_review_kpi(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
x="revenue",
y="Price Adjustment %",
x_ref_quantile=0.5,
y_ref_quantile=0.5,
),
),
vm.Tabs(
tabs=[
vm.Container(
title="Step 1: Adjustment score",
components=[
vm.AgGrid(
id="my_table",
title="Adjustment Score Calculation",
figure=calculate_price_scoring_table(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
),
),
],
),
vm.Container(
title="Step 2: Adjustment curve",
layout=vm.Layout(
grid=[[0, 1]],
),
components=[
vm.Graph(
figure=create_stepped_scatter(
data_frame=impact_summary,
period_1_range=10,
period_1_price_adjustment=2,
period_2_range=20,
period_2_price_adjustment=4,
period_3_range=40,
period_3_price_adjustment=6,
period_4_range=60,
period_4_price_adjustment=8,
period_5_range=100,
period_5_price_adjustment=9,
),
id="enhanced_scatter",
),
vm.AgGrid(
id="enhanced_scatter_table",
figure=create_table_with_price_increase(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
period_1_range=10,
period_1_price_adjustment=2,
period_2_range=20,
period_2_price_adjustment=4,
period_3_range=40,
period_3_price_adjustment=6,
period_4_range=60,
period_4_price_adjustment=8,
period_5_range=100,
period_5_price_adjustment=9,
),
),
],
),
vm.Container(
title="Step 3: Final price list",
components=[
vm.AgGrid(
id="group_table",
figure=create_group_level_table(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
period_1_range=10,
period_1_price_adjustment=2,
period_2_range=20,
period_2_price_adjustment=4,
period_3_range=40,
period_3_price_adjustment=6,
period_4_range=60,
period_4_price_adjustment=8,
period_5_range=100,
period_5_price_adjustment=9,
x="revenue",
y="Price Adjustment %",
x_ref_quantile=0.5,
y_ref_quantile=0.5,
group_level="SKU",
),
),
],
),
vm.Container(
title="Step 4: Visualizations",
components=[
vm.Graph(
id="violin_chart",
figure=create_violin_chart(
data_frame=impact_summary,
col1_name=default_col1_name_value,
col1_direction=default_col1_direction_value,
col1_weight=default_col1_weight_value,
col2_name=default_col2_name_value,
col2_direction=default_col2_direction_value,
col2_weight=default_col2_weight_value,
period_1_range=10,
period_1_price_adjustment=2,
period_2_range=20,
period_2_price_adjustment=4,
period_3_range=40,
period_3_price_adjustment=6,
period_4_range=60,
period_4_price_adjustment=8,
period_5_range=100,
period_5_price_adjustment=9,
x="revenue",
y="Price Adjustment %",
x_ref_quantile=0.5,
y_ref_quantile=0.5,
# group_level="SKU",
),
),
],
),
],
),
],
controls=[
ControlGroup(
control_group_title="SCORING METRICS",
controls=[
(
"METRIC 1",
create_scoring_metric_params(1),
),
(
"METRIC 2",
create_scoring_metric_params(2),
),
(
"METRIC 3",
create_scoring_metric_params(3),
),
(
"METRIC 4",
create_scoring_metric_params(4),
),
(
"METRIC 5",
create_scoring_metric_params(5),
),
(
"METRIC 6",
create_scoring_metric_params(6),
),
(
"METRIC 7",
create_scoring_metric_params(7),
),
(
"METRIC 8",
create_scoring_metric_params(8),
),
(
"METRIC 9",
create_scoring_metric_params(9),
),
(
"METRIC 10",
create_scoring_metric_params(10),
),
],
),
ControlGroup(
control_group_title="PERCENTILE BAND PRICE ADJUSTMENT",
controls=[
(
"PERCENTILE BAND 1",
create_percentile_period_params(1),
),
(
"PERCENTILE BAND 2",
create_percentile_period_params(2),
),
(
"PERCENTILE BAND 3",
create_percentile_period_params(3),
),
(
"PERCENTILE BAND 4",
create_percentile_period_params(4),
),
(
"PERCENTILE BAND 5",
create_percentile_period_params(5),
),
],
),
ControlGroup(
control_group_title="SELECT OUTPUT GROUP LEVEL",
controls=[
(
"GROUP LEVEL",
[
vm.Parameter(
targets=[
"group_table.group_level",
],
selector=vm.Dropdown(
id="group_level",
title="Group Level",
options=["SKU", "CLUSTER", "NCC1"],
multi=False,
value="SKU",
),
),
],
),
],
),
],
)
dashboard = vm.Dashboard(
pages=[
feature_importance_page,
decision_tree_page,
results_page,
],
title="MICRO SEGMENTATION",
theme="vizro_light",
navigation=vm.Navigation(
nav_selector=vm.NavBar(
items=[
vm.NavLink(
label="Global Feature Importance View",
icon="Drag Indicator",
pages=["Global Feature Importance View"],
),
vm.NavLink(
label="Decision Tree View",
icon="Leaderboard",
pages=["Decision Tree View"],
),
vm.NavLink(
label="Price Adjustment Dashboard",
icon="Home",
pages=["Price Adjustment Dashboard"],
),
]
)
),
)
app = Vizro().build(dashboard)
server = app.dash.server
if __name__ == "__main__":
app.run(debug=True)