Cosmographer commited on
Commit
80541ef
·
verified ·
1 Parent(s): d978978

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -0
app.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import gradio as gr
3
+ import plotly.graph_objects as go
4
+ import plotly.io as pio
5
+
6
+ def add_card(fig, x, y, w, h, title, subtitle=None,
7
+ fillcolor="#0f1724", border="#263145",
8
+ title_color="#ffffff", subtitle_color="#bfcbdc"):
9
+ fig.add_shape(type="rect",
10
+ x0=x - w/2, y0=y - h/2, x1=x + w/2, y1=y + h/2,
11
+ xref="x", yref="y",
12
+ line=dict(color=border, width=1),
13
+ fillcolor=fillcolor, layer="below")
14
+ fig.add_trace(go.Scatter(
15
+ x=[x], y=[y + h*0.18],
16
+ mode="text",
17
+ text=[f"<b>{title}</b>"],
18
+ textfont=dict(color=title_color, size=12),
19
+ hoverinfo="none", showlegend=False
20
+ ))
21
+ if subtitle:
22
+ fig.add_trace(go.Scatter(
23
+ x=[x], y=[y - h*0.18],
24
+ mode="text",
25
+ text=[subtitle],
26
+ textfont=dict(color=subtitle_color, size=10),
27
+ hoverinfo="none", showlegend=False
28
+ ))
29
+
30
+ def add_arrow(fig, x1, y1, x2, y2, color="#86b6ff"):
31
+ fig.add_annotation(
32
+ x=x2, y=y2,
33
+ ax=x1, ay=y1,
34
+ xref="x", yref="y",
35
+ axref="x", ayref="y",
36
+ showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1.6,
37
+ arrowcolor=color, opacity=0.95
38
+ )
39
+
40
+ def build_qids_figure():
41
+ # sample nodes (tweak/replace with your data)
42
+ nodes = [
43
+ {"id":"Intake & Consent", "row":3, "col":1, "subtitle":"Collect identity, demographics"},
44
+ {"id":"Prepare Assessment Suite", "row":3, "col":2, "subtitle":"Assemble IQ, psychometrics"},
45
+ {"id":"Baseline Data Collection", "row":3, "col":3, "subtitle":"Administer tests"},
46
+ {"id":"Standardize & Score", "row":3, "col":4, "subtitle":"Normalize results"},
47
+ {"id":"Integrated Profile Construction", "row":3, "col":5, "subtitle":"Triangulate multi-method data"},
48
+ {"id":"Scheduling & Resource Allocation", "row":2, "col":1, "subtitle":"Session calendar"},
49
+ {"id":"Module Deployment", "row":2, "col":2, "subtitle":"Deploy modules"},
50
+ {"id":"Session Data Capture", "row":2, "col":3, "subtitle":"Attendance, engagement"},
51
+ {"id":"Progress Evaluation Engine", "row":2, "col":4, "subtitle":"Progress metrics"},
52
+ {"id":"DEI Practice (EQ)", "row":2, "col":5, "subtitle":"Emotional integration"},
53
+ {"id":"Full Reassessment", "row":1, "col":2, "subtitle":"Re-run assessments"},
54
+ {"id":"Compute Outcomes", "row":1, "col":3, "subtitle":"Calculate KPIs"},
55
+ {"id":"Intervention Effectiveness", "row":1, "col":4, "subtitle":"Aggregate effectiveness"},
56
+ {"id":"Final IDP & Roadmap", "row":1, "col":5, "subtitle":"Produce final IDP"},
57
+ ]
58
+
59
+ x_spacing = 3.5
60
+ y_spacing = 2.5
61
+ for n in nodes:
62
+ n["x"] = n["col"] * x_spacing
63
+ n["y"] = n["row"] * y_spacing
64
+
65
+ fig = go.Figure()
66
+
67
+ # subtle grid
68
+ x_min, x_max = 0, 22
69
+ y_min, y_max = 0, 9
70
+ for gx in range(int(x_min), int(x_max)+1):
71
+ fig.add_shape(type="line", x0=gx, y0=y_min, x1=gx, y1=y_max,
72
+ line=dict(color="#0b1220", width=1), layer="below")
73
+ for gy in [i*0.5 for i in range(int(y_min*2), int(y_max*2)+1)]:
74
+ fig.add_shape(type="line", x0=x_min, y0=gy, x1=x_max, y1=gy,
75
+ line=dict(color="#08121c", width=1), layer="below")
76
+
77
+ card_w, card_h = 2.8, 1.0
78
+ for n in nodes:
79
+ add_card(fig, n["x"], n["y"], card_w, card_h, n["id"], n.get("subtitle"))
80
+
81
+ rows = {}
82
+ for n in nodes:
83
+ rows.setdefault(n["row"], []).append(n)
84
+ for r, row_nodes in rows.items():
85
+ row_nodes = sorted(row_nodes, key=lambda x: x["col"])
86
+ for a,b in zip(row_nodes, row_nodes[1:]):
87
+ add_arrow(fig, a["x"]+card_w/2, a["y"], b["x"]-card_w/2, b["y"])
88
+
89
+ # right panel
90
+ panel_x0 = x_max - 2.5; panel_x1 = x_max + 2.5
91
+ panel_y0 = y_min + 0.5; panel_y1 = y_max - 0.5
92
+ fig.add_shape(type="rect", x0=panel_x0, y0=panel_y0, x1=panel_x1, y1=panel_y1,
93
+ xref="x", yref="y", line=dict(color="#243445"), fillcolor="#0e1724", layer="below")
94
+ fig.add_trace(go.Scatter(x=[panel_x0+0.2], y=[panel_y1-0.4], mode="text",
95
+ text=["<b>Legal & Technical Highlights</b>"],
96
+ textfont=dict(color="#8fb4ff", size=12), showlegend=False))
97
+ panel_items = [
98
+ ("Unique IQ Measurement Model", "Four-parameter model: Verbal, Quantitative, Psychometric"),
99
+ ("Standardization Algorithm", "Unified 0-100% scale and conversion factors"),
100
+ ("Dynamic Weightage Algorithm (DWA)", "Context-sensitive weights by role/culture/mission"),
101
+ ]
102
+ y = panel_y1 - 1.0
103
+ for title, body in panel_items:
104
+ fig.add_trace(go.Scatter(x=[panel_x0+0.2], y=[y], mode="text",
105
+ text=[f"<b>{title}</b><br><span style='color:#bfcbdc;font-size:10px'>{body}</span>"],
106
+ showlegend=False, textfont=dict(size=11)))
107
+ y -= 0.9
108
+
109
+ fig.update_layout(
110
+ width=1200, height=700,
111
+ paper_bgcolor="#071021", plot_bgcolor="#071021",
112
+ margin=dict(l=20, r=20, t=20, b=20),
113
+ xaxis=dict(range=[0, x_max+3], visible=False),
114
+ yaxis=dict(range=[0, y_max+1], visible=False, scaleanchor="x"),
115
+ hovermode="closest"
116
+ )
117
+
118
+ # return a full HTML string for embedding
119
+ return pio.to_html(fig, full_html=True, include_plotlyjs='cdn')
120
+
121
+ # Build the HTML once (fast) and reuse
122
+ PLOTLY_HTML = build_qids_figure()
123
+
124
+ with gr.Blocks() as demo:
125
+ gr.Markdown("## QIDS Framework — Interactive Visualizer")
126
+ gr.HTML(PLOTLY_HTML)
127
+ gr.Markdown("---\n*Interactive Plotly visualization served with Gradio*")
128
+
129
+ if __name__ == "__main__":
130
+ demo.launch()