mfallahian commited on
Commit
232003e
·
verified ·
1 Parent(s): 01e01e5

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +84 -32
  2. radar_data.json +56 -0
app.py CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import plotly.graph_objects as go
@@ -5,6 +8,9 @@ import plotly.io as pio
5
 
6
  pio.templates.default = "plotly_white"
7
 
 
 
 
8
  def plot_spyder(scores: dict, title: str = "Group Chart", range_max: float | None = None) -> go.Figure:
9
  if not scores:
10
  raise ValueError("scores dict is empty")
@@ -38,69 +44,115 @@ def plot_spyder(scores: dict, title: str = "Group Chart", range_max: float | Non
38
 
39
  return fig
40
 
 
41
  def build_scores(df: pd.DataFrame) -> dict:
42
  df = df.dropna(subset=["label", "value"])
43
  df["label"] = df["label"].astype(str).str.strip()
44
  df = df[df["label"] != ""]
45
  return dict(zip(df["label"], df["value"].astype(float)))
46
 
47
- def make_charts(df1, t1, df2, t2, df3, t3, df4, t4, range_max):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  rm = None if range_max <= 0 else range_max
49
- return (
50
- plot_spyder(build_scores(df1), t1, rm),
51
- plot_spyder(build_scores(df2), t2, rm),
52
- plot_spyder(build_scores(df3), t3, rm),
53
- plot_spyder(build_scores(df4), t4, rm),
54
- )
55
 
56
- default_df = pd.DataFrame(
57
- {
58
- "label": [
59
- "Affordability", "Control", "Difficulty", "Energy Efficiency Gains",
60
- "Partnership Effort", "Risk Reduction", "Scale", "Adverse Outcome",
 
 
61
  ],
62
- "value": [9, 2, 8, 3, 6, 6, 5, 4],
63
  }
64
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  with gr.Blocks() as demo:
67
  gr.Markdown("## Radar Chart Builder — All 4 Groups together")
68
 
69
- range_input = gr.Number(value=10, label="Shared Range Max (0 = auto)")
70
 
71
  with gr.Row():
72
  with gr.Column():
73
- df1 = gr.Dataframe(
74
- value=default_df, headers=["label", "value"],
75
  datatype=["str", "number"], row_count=(8, "dynamic"),
76
  column_count=(2, "fixed"), interactive=True, label="Chart 1 Data"
77
  )
78
- t1 = gr.Textbox(value="Group 1 Chart", label="Chart 1 Title")
79
  with gr.Column():
80
- df2 = gr.Dataframe(
81
- value=default_df, headers=["label", "value"],
82
  datatype=["str", "number"], row_count=(8, "dynamic"),
83
  column_count=(2, "fixed"), interactive=True, label="Chart 2 Data"
84
  )
85
- t2 = gr.Textbox(value="Group 2 Chart", label="Chart 2 Title")
86
 
87
  with gr.Row():
88
  with gr.Column():
89
- df3 = gr.Dataframe(
90
- value=default_df, headers=["label", "value"],
91
  datatype=["str", "number"], row_count=(8, "dynamic"),
92
  column_count=(2, "fixed"), interactive=True, label="Chart 3 Data"
93
  )
94
- t3 = gr.Textbox(value="Group 3 Chart", label="Chart 3 Title")
95
  with gr.Column():
96
- df4 = gr.Dataframe(
97
- value=default_df, headers=["label", "value"],
98
  datatype=["str", "number"], row_count=(8, "dynamic"),
99
  column_count=(2, "fixed"), interactive=True, label="Chart 4 Data"
100
  )
101
- t4 = gr.Textbox(value="Group 4 Chart", label="Chart 4 Title")
102
 
103
- plot_button = gr.Button("Plot All")
 
104
 
105
  with gr.Row():
106
  out1 = gr.Plot(label="Chart 1")
@@ -109,10 +161,10 @@ with gr.Blocks() as demo:
109
  out3 = gr.Plot(label="Chart 3")
110
  out4 = gr.Plot(label="Chart 4")
111
 
112
- plot_button.click(
113
- fn=make_charts,
114
- inputs=[df1, t1, df2, t2, df3, t3, df4, t4, range_input],
115
- outputs=[out1, out2, out3, out4],
116
  )
117
 
118
  demo.launch()
 
1
+ import json
2
+ from pathlib import Path
3
+
4
  import gradio as gr
5
  import pandas as pd
6
  import plotly.graph_objects as go
 
8
 
9
  pio.templates.default = "plotly_white"
10
 
11
+ DATA_PATH = Path("radar_data.json")
12
+
13
+
14
  def plot_spyder(scores: dict, title: str = "Group Chart", range_max: float | None = None) -> go.Figure:
15
  if not scores:
16
  raise ValueError("scores dict is empty")
 
44
 
45
  return fig
46
 
47
+
48
  def build_scores(df: pd.DataFrame) -> dict:
49
  df = df.dropna(subset=["label", "value"])
50
  df["label"] = df["label"].astype(str).str.strip()
51
  df = df[df["label"] != ""]
52
  return dict(zip(df["label"], df["value"].astype(float)))
53
 
54
+
55
+ def load_state(path: Path):
56
+ with path.open("r", encoding="utf-8") as f:
57
+ raw = json.load(f)
58
+ return raw
59
+
60
+
61
+ def save_state(path: Path, payload: dict):
62
+ with path.open("w", encoding="utf-8") as f:
63
+ json.dump(payload, f, indent=2)
64
+
65
+
66
+ def state_to_ui(state: dict):
67
+ range_max = state.get("range_max", 10)
68
+ charts = state.get("charts", [])
69
+
70
+ def to_df(ch):
71
+ return pd.DataFrame({"label": list(ch["scores"].keys()), "value": list(ch["scores"].values())})
72
+
73
+ df1 = to_df(charts[0])
74
+ df2 = to_df(charts[1])
75
+ df3 = to_df(charts[2])
76
+ df4 = to_df(charts[3])
77
+
78
+ t1 = charts[0]["title"]
79
+ t2 = charts[1]["title"]
80
+ t3 = charts[2]["title"]
81
+ t4 = charts[3]["title"]
82
+
83
+ return df1, t1, df2, t2, df3, t3, df4, t4, range_max
84
+
85
+
86
+ def ui_to_state(df1, t1, df2, t2, df3, t3, df4, t4, range_max):
87
  rm = None if range_max <= 0 else range_max
 
 
 
 
 
 
88
 
89
+ payload = {
90
+ "range_max": range_max,
91
+ "charts": [
92
+ {"title": t1, "scores": build_scores(df1)},
93
+ {"title": t2, "scores": build_scores(df2)},
94
+ {"title": t3, "scores": build_scores(df3)},
95
+ {"title": t4, "scores": build_scores(df4)},
96
  ],
 
97
  }
98
+
99
+ figs = (
100
+ plot_spyder(payload["charts"][0]["scores"], t1, rm),
101
+ plot_spyder(payload["charts"][1]["scores"], t2, rm),
102
+ plot_spyder(payload["charts"][2]["scores"], t3, rm),
103
+ plot_spyder(payload["charts"][3]["scores"], t4, rm),
104
+ )
105
+
106
+ save_state(DATA_PATH, payload)
107
+ return (*figs, gr.update(value="Saved ✓"))
108
+
109
+
110
+ # ---- App bootstrapping ----
111
+ if not DATA_PATH.exists():
112
+ raise FileNotFoundError(f"Missing {DATA_PATH}. Create it using the sample JSON below.")
113
+
114
+ state = load_state(DATA_PATH)
115
+ df1, t1, df2, t2, df3, t3, df4, t4, range_max = state_to_ui(state)
116
 
117
  with gr.Blocks() as demo:
118
  gr.Markdown("## Radar Chart Builder — All 4 Groups together")
119
 
120
+ range_input = gr.Number(value=range_max, label="Shared Range Max (0 = auto)")
121
 
122
  with gr.Row():
123
  with gr.Column():
124
+ df1_input = gr.Dataframe(
125
+ value=df1, headers=["label", "value"],
126
  datatype=["str", "number"], row_count=(8, "dynamic"),
127
  column_count=(2, "fixed"), interactive=True, label="Chart 1 Data"
128
  )
129
+ t1_input = gr.Textbox(value=t1, label="Chart 1 Title")
130
  with gr.Column():
131
+ df2_input = gr.Dataframe(
132
+ value=df2, headers=["label", "value"],
133
  datatype=["str", "number"], row_count=(8, "dynamic"),
134
  column_count=(2, "fixed"), interactive=True, label="Chart 2 Data"
135
  )
136
+ t2_input = gr.Textbox(value=t2, label="Chart 2 Title")
137
 
138
  with gr.Row():
139
  with gr.Column():
140
+ df3_input = gr.Dataframe(
141
+ value=df3, headers=["label", "value"],
142
  datatype=["str", "number"], row_count=(8, "dynamic"),
143
  column_count=(2, "fixed"), interactive=True, label="Chart 3 Data"
144
  )
145
+ t3_input = gr.Textbox(value=t3, label="Chart 3 Title")
146
  with gr.Column():
147
+ df4_input = gr.Dataframe(
148
+ value=df4, headers=["label", "value"],
149
  datatype=["str", "number"], row_count=(8, "dynamic"),
150
  column_count=(2, "fixed"), interactive=True, label="Chart 4 Data"
151
  )
152
+ t4_input = gr.Textbox(value=t4, label="Chart 4 Title")
153
 
154
+ save_plot_button = gr.Button("Save & Plot")
155
+ status = gr.Textbox(value="", label="Status", interactive=False)
156
 
157
  with gr.Row():
158
  out1 = gr.Plot(label="Chart 1")
 
161
  out3 = gr.Plot(label="Chart 3")
162
  out4 = gr.Plot(label="Chart 4")
163
 
164
+ save_plot_button.click(
165
+ fn=ui_to_state,
166
+ inputs=[df1_input, t1_input, df2_input, t2_input, df3_input, t3_input, df4_input, t4_input, range_input],
167
+ outputs=[out1, out2, out3, out4, status],
168
  )
169
 
170
  demo.launch()
radar_data.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "range_max": 10,
3
+ "charts": [
4
+ {
5
+ "title": "Group 1 Chart",
6
+ "scores": {
7
+ "Affordability": 9.0,
8
+ "Control": 2.0,
9
+ "Difficulty": 8.0,
10
+ "Energy Efficiency Gains": 3.0,
11
+ "Partnership Effort": 6.0,
12
+ "Risk Reduction": 6.0,
13
+ "Scale": 5.0,
14
+ "Adverse Outcome": 4.0
15
+ }
16
+ },
17
+ {
18
+ "title": "Group 2 Chart",
19
+ "scores": {
20
+ "Affordability": 6.0,
21
+ "Control": 4.0,
22
+ "Difficulty": 7.0,
23
+ "Energy Efficiency Gains": 5.0,
24
+ "Partnership Effort": 7.0,
25
+ "Risk Reduction": 5.0,
26
+ "Scale": 6.0,
27
+ "Adverse Outcome": 3.0
28
+ }
29
+ },
30
+ {
31
+ "title": "Group 3 Chart",
32
+ "scores": {
33
+ "Affordability": 5.0,
34
+ "Control": 6.0,
35
+ "Difficulty": 4.0,
36
+ "Energy Efficiency Gains": 5.0,
37
+ "Partnership Effort": 4.0,
38
+ "Risk Reduction": 7.0,
39
+ "Adverse Outcome": 6.0
40
+ }
41
+ },
42
+ {
43
+ "title": "Group 4 Chart",
44
+ "scores": {
45
+ "Affordability": 7.0,
46
+ "Control": 2.0,
47
+ "Difficulty": 6.0,
48
+ "Energy Efficiency Gains": 4.0,
49
+ "Partnership Effort": 6.0,
50
+ "Risk Reduction": 5.0,
51
+ "Scale": 7.0,
52
+ "Adverse Outcome": 2.0
53
+ }
54
+ }
55
+ ]
56
+ }