Spaces:
Runtime error
Runtime error
Birger Moell
commited on
Commit
•
0de5d5b
1
Parent(s):
199ef5a
Added files for HF
Browse files
app.py
ADDED
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import numpy as np
|
3 |
+
import scipy.stats as stats
|
4 |
+
from fpdf import FPDF
|
5 |
+
import base64
|
6 |
+
import os
|
7 |
+
from plots import test_profile
|
8 |
+
import matplotlib.pyplot as plt
|
9 |
+
from PIL import Image
|
10 |
+
|
11 |
+
test_dict = {
|
12 |
+
"animal": {
|
13 |
+
"low_age_low_education": {
|
14 |
+
"mean": 21.0,
|
15 |
+
"std": 7.0
|
16 |
+
}, "low_age_high_education": {
|
17 |
+
"mean": 22.4,
|
18 |
+
"std": 6.8
|
19 |
+
}, "high_age_low_education": {
|
20 |
+
"mean": 22.1,
|
21 |
+
"std": 5.7
|
22 |
+
}, "high_age_high_education": {
|
23 |
+
"mean": 25.6,
|
24 |
+
"std": 5.6
|
25 |
+
}
|
26 |
+
}, "verb": {
|
27 |
+
"low_age_low_education": {
|
28 |
+
"mean": 17.6,
|
29 |
+
"std": 4.3
|
30 |
+
}, "low_age_high_education": {
|
31 |
+
"mean": 20.5,
|
32 |
+
"std": 5.4
|
33 |
+
}, "high_age_low_education": {
|
34 |
+
"mean": 16.7,
|
35 |
+
"std": 6.1
|
36 |
+
}, "high_age_high_education": {
|
37 |
+
"mean": 22.7,
|
38 |
+
"std": 5.1
|
39 |
+
}
|
40 |
+
}, "repetition": {
|
41 |
+
"low_age_low_education": {
|
42 |
+
"mean": 24.8,
|
43 |
+
"std": 4.8
|
44 |
+
}, "low_age_high_education": {
|
45 |
+
"mean": 25.9,
|
46 |
+
"std": 3.7
|
47 |
+
}, "high_age_low_education": {
|
48 |
+
"mean": 24.0,
|
49 |
+
"std": 4.9
|
50 |
+
}, "high_age_high_education": {
|
51 |
+
"mean": 25.8,
|
52 |
+
"std": 3.8
|
53 |
+
}
|
54 |
+
}, "months_backward": {
|
55 |
+
"low_age_low_education": {
|
56 |
+
"mean": 10.3,
|
57 |
+
"std": 4.5
|
58 |
+
}, "low_age_high_education": {
|
59 |
+
"mean": 9.8,
|
60 |
+
"std": 3.2
|
61 |
+
}, "high_age_low_education": {
|
62 |
+
"mean": 10.0,
|
63 |
+
"std": 3.2
|
64 |
+
}, "high_age_high_education": {
|
65 |
+
"mean": 9.9,
|
66 |
+
"std": 3.5
|
67 |
+
}
|
68 |
+
},
|
69 |
+
"logicogrammatic": {
|
70 |
+
"low_age_low_education": {
|
71 |
+
"mean": 27.2,
|
72 |
+
"std": 3.8
|
73 |
+
}, "low_age_high_education": {
|
74 |
+
"mean": 27.4,
|
75 |
+
"std": 3.1
|
76 |
+
}, "high_age_low_education": {
|
77 |
+
"mean": 23.5,
|
78 |
+
"std": 4.2
|
79 |
+
}, "high_age_high_education": {
|
80 |
+
"mean": 27.2,
|
81 |
+
"std": 3.3
|
82 |
+
}
|
83 |
+
},"inference": {
|
84 |
+
"low_age_low_education": {
|
85 |
+
"mean": 28.2,
|
86 |
+
"std": 2.4
|
87 |
+
}, "low_age_high_education": {
|
88 |
+
"mean": 28.4,
|
89 |
+
"std": 2.8
|
90 |
+
}, "high_age_low_education": {
|
91 |
+
"mean": 25.2,
|
92 |
+
"std": 3.9
|
93 |
+
}, "high_age_high_education": {
|
94 |
+
"mean": 27.3,
|
95 |
+
"std": 2.9
|
96 |
+
}
|
97 |
+
}, "reading_speed": {
|
98 |
+
"low_age_low_education": {
|
99 |
+
"mean": 21.5,
|
100 |
+
"std": 5.4
|
101 |
+
}, "low_age_high_education": {
|
102 |
+
"mean": 27.3,
|
103 |
+
"std": 5.5
|
104 |
+
}, "high_age_low_education": {
|
105 |
+
"mean": 23.0,
|
106 |
+
"std": 7.2
|
107 |
+
}, "high_age_high_education": {
|
108 |
+
"mean": 28.8,
|
109 |
+
"std": 5.2
|
110 |
+
}
|
111 |
+
}, "decoding_words": {
|
112 |
+
"low_age_low_education": {
|
113 |
+
"mean": 107.6,
|
114 |
+
"std": 27.8
|
115 |
+
}, "low_age_high_education": {
|
116 |
+
"mean": 112.9,
|
117 |
+
"std": 22.7
|
118 |
+
}, "high_age_low_education": {
|
119 |
+
"mean": 111.4,
|
120 |
+
"std": 26.1
|
121 |
+
}, "high_age_high_education": {
|
122 |
+
"mean": 122.9,
|
123 |
+
"std": 28.2
|
124 |
+
}
|
125 |
+
}, "decoding_non_words": {
|
126 |
+
"low_age_low_education": {
|
127 |
+
"mean": 95.8,
|
128 |
+
"std": 26.6
|
129 |
+
}, "low_age_high_education": {
|
130 |
+
"mean": 105.4,
|
131 |
+
"std": 29.5
|
132 |
+
}, "high_age_low_education": {
|
133 |
+
"mean": 103.4,
|
134 |
+
"std": 25.2
|
135 |
+
}, "high_age_high_education": {
|
136 |
+
"mean": 118.0,
|
137 |
+
"std": 26.8
|
138 |
+
}
|
139 |
+
},
|
140 |
+
# jönsson och winnerstam 2012
|
141 |
+
"pataka": {
|
142 |
+
"low_age_low_education": {
|
143 |
+
"mean": 5.8,
|
144 |
+
"std": 1.0
|
145 |
+
}, "low_age_high_education": {
|
146 |
+
"mean": 5.8,
|
147 |
+
"std": 1.0
|
148 |
+
}, "high_age_low_education": {
|
149 |
+
"mean": 5.8,
|
150 |
+
"std": 1.0
|
151 |
+
}, "high_age_high_education": {
|
152 |
+
"mean": 5.8,
|
153 |
+
"std": 1.0
|
154 |
+
}
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
# Function to calculate z-score
|
160 |
+
def calculate_z_score(test_score, mean, std_dev):
|
161 |
+
return (test_score - mean) / std_dev
|
162 |
+
|
163 |
+
def z_score_calculator(value, norm_mean, norm_sd):
|
164 |
+
z_value = (value - norm_mean) / norm_sd
|
165 |
+
stanine_value = round(1.25 * z_value + 5.5)
|
166 |
+
z_score = round(z_value, 2)
|
167 |
+
return z_score, stanine_value
|
168 |
+
|
169 |
+
def test_calculator(age, education, values, test):
|
170 |
+
if age <= 60 and education <= 12:
|
171 |
+
norm_mean = test_dict[test]["low_age_low_education"]["mean"]
|
172 |
+
norm_sd = test_dict[test]["low_age_low_education"]["std"]
|
173 |
+
z_score, stanine_value = z_score_calculator(values, norm_mean, norm_sd)
|
174 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
175 |
+
elif age <= 60 and education > 12:
|
176 |
+
norm_mean = test_dict[test]["low_age_high_education"]["mean"]
|
177 |
+
norm_sd = test_dict[test]["low_age_high_education"]["std"]
|
178 |
+
z_score, stanine_value = z_score_calculator(values, norm_mean, norm_sd)
|
179 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
180 |
+
elif age > 60 and education <= 12:
|
181 |
+
norm_mean = test_dict[test]["high_age_low_education"]["mean"]
|
182 |
+
norm_sd = test_dict[test]["high_age_low_education"]["std"]
|
183 |
+
z_score, stanine_value = z_score_calculator(values, norm_mean, norm_sd)
|
184 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
185 |
+
elif age > 60 and education > 12:
|
186 |
+
norm_mean = test_dict[test]["high_age_high_education"]["mean"]
|
187 |
+
norm_sd = test_dict[test]["high_age_high_education"]["std"]
|
188 |
+
z_score, stanine_value = z_score_calculator(values, norm_mean, norm_sd)
|
189 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
190 |
+
else:
|
191 |
+
print("missing value/ wrong format")
|
192 |
+
|
193 |
+
|
194 |
+
def bnt_calculator(age, education, bnt):
|
195 |
+
if age <= 60 and education <= 12:
|
196 |
+
norm_mean = 54.5
|
197 |
+
norm_sd = 3.2
|
198 |
+
z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd)
|
199 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
200 |
+
elif age <= 60 and education > 12:
|
201 |
+
norm_mean = 54.0
|
202 |
+
norm_sd = 4.4
|
203 |
+
z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd)
|
204 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
205 |
+
elif age > 60 and education <= 12:
|
206 |
+
norm_mean = 54.8
|
207 |
+
norm_sd = 3.3
|
208 |
+
z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd)
|
209 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
210 |
+
elif age > 60 and education > 12:
|
211 |
+
norm_mean = 56.2
|
212 |
+
norm_sd = 3.4
|
213 |
+
z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd)
|
214 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
215 |
+
else:
|
216 |
+
print("missing value/ wrong format")
|
217 |
+
|
218 |
+
def fas_calculator(age, education, fas):
|
219 |
+
if age <= 60 and education <= 12:
|
220 |
+
norm_mean = 42.7
|
221 |
+
norm_sd = 13.7
|
222 |
+
z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd)
|
223 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
224 |
+
elif age <= 60 and education > 12:
|
225 |
+
norm_mean = 46.7
|
226 |
+
norm_sd = 13.7
|
227 |
+
z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd)
|
228 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
229 |
+
elif age > 60 and education <= 12:
|
230 |
+
norm_mean = 46.9
|
231 |
+
norm_sd = 10.4
|
232 |
+
z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd)
|
233 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
234 |
+
elif age > 60 and education > 12:
|
235 |
+
norm_mean = 51.6
|
236 |
+
norm_sd = 12.6
|
237 |
+
z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd)
|
238 |
+
return norm_mean, norm_sd, z_score, stanine_value
|
239 |
+
else:
|
240 |
+
print("missing value/ wrong format")
|
241 |
+
|
242 |
+
def generate_graph(test_dict):
|
243 |
+
# Create a plot
|
244 |
+
fig, ax = plt.subplots()
|
245 |
+
|
246 |
+
# Adjust the margins to fix the labels being cut off
|
247 |
+
fig.subplots_adjust(left=0.25)
|
248 |
+
|
249 |
+
# Set axis labels and title
|
250 |
+
ax.set_xlabel('Stanine values')
|
251 |
+
ax.set_ylabel('Test')
|
252 |
+
|
253 |
+
# Set the x-axis to display the stanine values
|
254 |
+
ax.set_xticks([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
255 |
+
ax.set_xticklabels(['1', '2', '3', '4', '5', '6', '7', '8', '9'])
|
256 |
+
|
257 |
+
# Set the y-axis to display the tests
|
258 |
+
ax.set_yticks([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
|
259 |
+
|
260 |
+
# Set the test labels to the keys in test_dict (in reverse order)
|
261 |
+
ax.set_yticklabels(reversed(list(test_dict.keys())))
|
262 |
+
|
263 |
+
# Set the range of the x-axis
|
264 |
+
ax.set_xlim([0, 10])
|
265 |
+
|
266 |
+
i = 1
|
267 |
+
|
268 |
+
for test in reversed(list(test_dict.keys())):
|
269 |
+
#print("the test is", test)
|
270 |
+
ax.scatter(test_dict[test][4], i, s=50, color='black', label=test)
|
271 |
+
i = i + 1
|
272 |
+
|
273 |
+
# Save the graph as a png file
|
274 |
+
fig.savefig('test_profile.png')
|
275 |
+
return 'test_profile.png'
|
276 |
+
|
277 |
+
|
278 |
+
def create_pdf(test_dict, logo_path, plot_path):
|
279 |
+
pdf = FPDF()
|
280 |
+
pdf.add_page()
|
281 |
+
pdf.set_xy(0, 0)
|
282 |
+
pdf.set_font("Arial", size=12)
|
283 |
+
|
284 |
+
# Add logos
|
285 |
+
x_positions = [25, 85, 145]
|
286 |
+
for i, logo_path in enumerate(logo_paths):
|
287 |
+
pdf.image(logo_path, x=x_positions[i], y=8, w=40)
|
288 |
+
pdf.set_xy(10, 50)
|
289 |
+
|
290 |
+
|
291 |
+
# Add title and center it
|
292 |
+
title = "Patient Summary"
|
293 |
+
pdf.set_font("Times", style="B", size=12)
|
294 |
+
title_width = pdf.get_string_width(title) + 6
|
295 |
+
pdf.cell((210 - title_width) / 2)
|
296 |
+
pdf.cell(title_width, 10, title, 0, 1, "C")
|
297 |
+
|
298 |
+
# Add z-score and center it
|
299 |
+
|
300 |
+
pdf.set_font("Times", size=12)
|
301 |
+
|
302 |
+
tests_per_line = 1
|
303 |
+
tests_count = len(test_dict)
|
304 |
+
line_count = tests_count // tests_per_line + (1 if tests_count % tests_per_line > 0 else 0)
|
305 |
+
|
306 |
+
test_index = 0
|
307 |
+
left_margin = 15
|
308 |
+
col_width = (210 - 2 * left_margin) / tests_per_line
|
309 |
+
|
310 |
+
for line in range(line_count):
|
311 |
+
pdf.set_x(left_margin)
|
312 |
+
for test in list(test_dict.keys())[test_index:test_index + tests_per_line]:
|
313 |
+
# Set the font to bold for the test value
|
314 |
+
pdf.set_font("Arial", style="B", size=8)
|
315 |
+
test_text = "{}: ".format(test)
|
316 |
+
test_width = pdf.get_string_width(test_text)
|
317 |
+
pdf.cell(test_width, 6, test_text, 0, 0, "C") # Changed the line height to 6
|
318 |
+
|
319 |
+
# Set the font to normal for the rest of the text
|
320 |
+
pdf.set_font("Arial", size=8)
|
321 |
+
z_score_text = "{:.2f} (Mean: {:.2f}, Std: {:.2f})".format(
|
322 |
+
test_dict[test][3], test_dict[test][1], test_dict[test][2]
|
323 |
+
)
|
324 |
+
z_score_width = pdf.get_string_width(z_score_text) + 2 # Reduced the additional width to 2
|
325 |
+
pdf.cell((210 / tests_per_line - test_width - z_score_width) / 2)
|
326 |
+
pdf.cell(z_score_width, 6, z_score_text, 0, 0, "C") # Changed the line height to 6
|
327 |
+
|
328 |
+
test_index += 1
|
329 |
+
pdf.ln(12) # Reduced the line spacing to 12
|
330 |
+
|
331 |
+
# Add logo
|
332 |
+
pdf.add_page()
|
333 |
+
|
334 |
+
pdf.image(plot_path, x=10, y=20, w=200)
|
335 |
+
# pdf.set_xy(10, 40)
|
336 |
+
|
337 |
+
# Add tool description and center it
|
338 |
+
pdf.set_xy(10, 200)
|
339 |
+
pdf.set_font("Arial", size=10)
|
340 |
+
description = "This PDF report was generated using the Patient Summary App."
|
341 |
+
pdf.multi_cell(0, 10, description, 0, "C")
|
342 |
+
|
343 |
+
# Add explanatory text about the collaboration between KI and KTH
|
344 |
+
pdf.set_xy(10, 220)
|
345 |
+
pdf.set_font("Arial", size=8)
|
346 |
+
collaboration_text = (
|
347 |
+
"Den här PDF:en är en del av ett samarbetsprojekt mellan Karolinska Institutet (KI) och "
|
348 |
+
"Kungliga Tekniska Högskolan (KTH) med målsättningen att använda artificiell intelligens (AI) och "
|
349 |
+
"teknik för att minska administration i sjukhusarbete. Projektet fokuserar på att utveckla och "
|
350 |
+
"implementera AI-baserade lösningar för att förbättra arbetsflöden, öka effektiviteten och "
|
351 |
+
"minska den administrativa bördan för sjukvårdspersonal. För frågor om formuläret kontakta Fredrik Sand fredrik.sand-aronsson@regionstockholm.se, för frågor om teknik kontakta Birger Moëll bmoell@kth.se."
|
352 |
+
)
|
353 |
+
line_width = 190
|
354 |
+
line_height = pdf.font_size_pt * 0.6
|
355 |
+
lines = collaboration_text.split(' ')
|
356 |
+
current_line = ''
|
357 |
+
for word in lines:
|
358 |
+
if pdf.get_string_width(current_line + word) < line_width:
|
359 |
+
current_line += word + ' '
|
360 |
+
else:
|
361 |
+
pdf.cell(line_width, line_height, current_line, 0, 1)
|
362 |
+
current_line = word + ' '
|
363 |
+
pdf.cell(line_width, line_height, current_line, 0, 1)
|
364 |
+
|
365 |
+
return pdf
|
366 |
+
|
367 |
+
def pdf_to_base64(pdf):
|
368 |
+
with open(pdf, "rb") as file:
|
369 |
+
return base64.b64encode(file.read()).decode('utf-8')
|
370 |
+
|
371 |
+
|
372 |
+
# Title and description
|
373 |
+
st.title("Z-Score Calculator")
|
374 |
+
st.write("Enter your test score, age, and education level to calculate the z-score.")
|
375 |
+
|
376 |
+
# Input fields
|
377 |
+
#test_score = st.number_input("Test Score", min_value=0, value=0, step=1)
|
378 |
+
age = st.number_input("Age", min_value=0, value=18, step=1)
|
379 |
+
education_level = st.number_input("Education Level in years", min_value=0, value=18, step=1)
|
380 |
+
isw = st.number_input("ISW", min_value=0.0, value=0.0, step=0.01)
|
381 |
+
bnt = st.number_input("BNT", min_value=0, value=0, step=1)
|
382 |
+
fas = st.number_input("FAS", min_value=0, value=0, step=1)
|
383 |
+
animal = st.number_input("Animal", min_value=0, value=0, step=1)
|
384 |
+
verb = st.number_input("Verb", min_value=0, value=0, step=1)
|
385 |
+
repetition = st.number_input("Repetition", min_value=0, value=0, step=1)
|
386 |
+
logicogrammatic = st.number_input("Logicogrammatic", min_value=0, value=0, step=1)
|
387 |
+
inference = st.number_input("Inference", min_value=0, value=0, step=1)
|
388 |
+
reading_speed = st.number_input("Reading Speed", min_value=0, value=0, step=1)
|
389 |
+
decoding_words = st.number_input("Decoding Words", min_value=0.0, value=0.0, step=0.01)
|
390 |
+
decoding_non_words = st.number_input("Decoding Non-Words", min_value=0.0, value=0.0, step=0.01)
|
391 |
+
months_backward = st.number_input("Months Backward", min_value=0.0, value=0.0, step=0.01)
|
392 |
+
pataka = st.number_input("Pataka", min_value=0.0, value=0.0, step=0.01)
|
393 |
+
|
394 |
+
|
395 |
+
# add all the tests
|
396 |
+
|
397 |
+
|
398 |
+
# Calculate mean and standard deviation based on age and education level
|
399 |
+
# For simplicity, we will use made-up values for mean and std_dev
|
400 |
+
mean = np.random.randint(50, 100)
|
401 |
+
std_dev = np.random.randint(10, 30)
|
402 |
+
|
403 |
+
# Calculate z-score and display result
|
404 |
+
if st.button("Calculate Z-Score"):
|
405 |
+
profile = test_profile(age, education_level, isw, bnt, fas)
|
406 |
+
|
407 |
+
|
408 |
+
# for each value in the profile, calculate the z-score
|
409 |
+
bnt_mean, bnt_std, z_bnt, stanine_bnt = bnt_calculator(age, education_level, bnt)
|
410 |
+
fas_mean, fas_std, z_fas, stanine_fas = fas_calculator(age, education_level, fas)
|
411 |
+
|
412 |
+
animal_mean, animal_std, animal_z, animal_stanine = test_calculator(age, education_level, animal, "animal")
|
413 |
+
verb_mean, verb_std, verb_z, verb_stanine = test_calculator(age, education_level, verb, "verb")
|
414 |
+
repetition_mean, repetition_std, repetition_z, repetition_stanine = test_calculator(age, education_level, repetition, "repetition")
|
415 |
+
months_backward_mean, months_backward_std, months_backward_z, months_backward_stanine = test_calculator(age, education_level, months_backward, "months_backward")
|
416 |
+
logicogrammatic_mean, logicogrammatic_std, logicogrammatic_z, logicogrammatic_stanine = test_calculator(age, education_level, logicogrammatic, "logicogrammatic")
|
417 |
+
inference_mean, inference_std, inference_z, inference_stanine = test_calculator(age, education_level, inference, "inference")
|
418 |
+
reading_speed_mean, reading_speed_std, reading_speed_z, reading_speed_stanine = test_calculator(age, education_level, reading_speed, "reading_speed")
|
419 |
+
decoding_words_mean, decoding_words_std, decoding_words_z, decoding_words_stanine = test_calculator(age, education_level, decoding_words, "decoding_words")
|
420 |
+
decoding_non_words_mean, decoding_non_words_std, decoding_non_words_z, decoding_non_words_stanine = test_calculator(age, education_level, decoding_non_words, "decoding_non_words")
|
421 |
+
pataka_mean, pataka_std, pataka_z, pataka_stanine = test_calculator(age, education_level, pataka, "pataka")
|
422 |
+
|
423 |
+
## add all the tests with their values to an array
|
424 |
+
|
425 |
+
## CREATA A DICTORINARY WITH ALL THE TESTS AND THEIR Z-SCORES AND STANINE VALUES
|
426 |
+
test_dict = {
|
427 |
+
"bnt": [bnt, bnt_mean, bnt_std, z_bnt, stanine_bnt],
|
428 |
+
"fas": [fas, fas_mean, fas_std, z_fas, stanine_fas],
|
429 |
+
"animal": [animal, animal_mean, animal_std, animal_z, animal_stanine],
|
430 |
+
"verb": [verb, verb_mean, verb_std, verb_z, verb_stanine],
|
431 |
+
"repetition": [repetition, repetition_mean, repetition_std, repetition_z, repetition_stanine],
|
432 |
+
"months_backward": [months_backward, months_backward_mean, months_backward_std, months_backward_z, months_backward_stanine],
|
433 |
+
"logicogrammatic": [logicogrammatic, logicogrammatic_mean, logicogrammatic_std, logicogrammatic_z, logicogrammatic_stanine],
|
434 |
+
"inference": [inference, inference_mean, inference_std, inference_z, inference_stanine],
|
435 |
+
"reading_speed": [reading_speed, reading_speed_mean, reading_speed_std, reading_speed_z, reading_speed_stanine],
|
436 |
+
"decoding_words": [decoding_words, decoding_words_mean, decoding_words_std, decoding_words_z, decoding_words_stanine],
|
437 |
+
"decoding_non_words": [decoding_non_words, decoding_non_words_mean, decoding_non_words_std, decoding_non_words_z, decoding_non_words_stanine],
|
438 |
+
"pataka": [pataka, pataka_mean, pataka_std, pataka_z, pataka_stanine]
|
439 |
+
}
|
440 |
+
|
441 |
+
# z_values = [z_bnt, z_fas, animal_z, verb_z, repetition_z, months_backward_z, logicogrammatic_z, inference_z, reading_speed_z, decoding_words_z, decoding_non_words_z, pataka_z]
|
442 |
+
|
443 |
+
# ## add all the stanines to a list
|
444 |
+
# stanine_values = [stanine_bnt, stanine_fas, animal_stanine, verb_stanine, repetition_stanine, months_backward_stanine, logicogrammatic_stanine, inference_stanine, reading_speed_stanine, decoding_words_stanine, decoding_non_words_stanine, pataka_stanine]
|
445 |
+
|
446 |
+
# loop over and write out all the z values
|
447 |
+
|
448 |
+
# loop over all the values in test dict and print out the z-score, mean and std_dev and stanine
|
449 |
+
for key, value in test_dict.items():
|
450 |
+
st.write(f"Your {key} z-score is: {value[3]:.2f}")
|
451 |
+
st.write(f"Mean: {value[1]}, Standard Deviation: {value[2]}")
|
452 |
+
st.write(f"Stanine: {value[4]}")
|
453 |
+
|
454 |
+
# Create PDF
|
455 |
+
|
456 |
+
logo_paths = ["logo.jpg", "logo2.jpg", "logo3.jpg"]
|
457 |
+
|
458 |
+
# create the plot from the dataframe
|
459 |
+
|
460 |
+
# check if education level is more than 12 years, if more than 12, set value to one, otherwise zero
|
461 |
+
|
462 |
+
plot_path = generate_graph(test_dict)
|
463 |
+
|
464 |
+
# create an image from the plot and add to streamlit display
|
465 |
+
image = Image.open(plot_path)
|
466 |
+
st.image(image, caption='Stanine plot', use_column_width=True)
|
467 |
+
|
468 |
+
pdf_filename = "z_score_report.pdf"
|
469 |
+
pdf = create_pdf(test_dict, logo_paths, plot_path)
|
470 |
+
pdf.output(name=pdf_filename)
|
471 |
+
|
472 |
+
# Download PDF
|
473 |
+
with open(pdf_filename, "rb") as file:
|
474 |
+
base64_pdf = base64.b64encode(file.read()).decode('utf-8')
|
475 |
+
pdf_display = f'<a href="data:application/octet-stream;base64,{base64_pdf}" download="{pdf_filename}">Download PDF</a>'
|
476 |
+
st.markdown(pdf_display, unsafe_allow_html=True)
|
477 |
+
|
478 |
+
# Remove PDF file after download
|
479 |
+
if os.path.exists(pdf_filename):
|
480 |
+
os.remove(pdf_filename)
|
logo.jpg
ADDED
logo2.jpg
ADDED
logo3.jpg
ADDED
plots.py
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import matplotlib.pyplot as plt
|
2 |
+
|
3 |
+
class test_profile:
|
4 |
+
def __init__(self, age, education, bnt, fas, isw):
|
5 |
+
self.age = age
|
6 |
+
self.education = education
|
7 |
+
self.bnt = bnt
|
8 |
+
self.fas = fas
|
9 |
+
self.isw = isw
|
10 |
+
|
11 |
+
def mean_bnt(self):
|
12 |
+
if self.age <= 60 and self.education <= 12:
|
13 |
+
self.norm_mean = 54.5
|
14 |
+
self.norm_sd = 3.2
|
15 |
+
elif self.age <= 60 and self.education > 12:
|
16 |
+
self.norm_mean = 54.0
|
17 |
+
self.norm_sd = 4.4
|
18 |
+
elif self.age > 60 and self.education <= 12:
|
19 |
+
self.norm_mean = 54.8
|
20 |
+
self.norm_sd = 3.3
|
21 |
+
elif self.age > 60 and self.education > 12:
|
22 |
+
self.norm_mean = 56.2
|
23 |
+
self.norm_sd = 3.4
|
24 |
+
else:
|
25 |
+
print("missing value/ wrong format")
|
26 |
+
|
27 |
+
def z_bnt(self):
|
28 |
+
self.mean_bnt()
|
29 |
+
z_bnt = (self.bnt - self.norm_mean) / self.norm_sd
|
30 |
+
stanine_bnt = round(1.25 * z_bnt + 5.5)
|
31 |
+
return round(z_bnt, 2), stanine_bnt
|
32 |
+
|
33 |
+
def z_to_stanine(self, z_score):
|
34 |
+
stanine = round(1.25 * z_score + 5.5)
|
35 |
+
return stanine
|
36 |
+
|
37 |
+
|
38 |
+
def mean_fas(self):
|
39 |
+
if self.age <= 60 and self.education <= 12:
|
40 |
+
self.norm_mean = 42.7
|
41 |
+
self.norm_sd = 13.7
|
42 |
+
elif self.age <= 60 and self.education > 12:
|
43 |
+
self.norm_mean = 46.7
|
44 |
+
self.norm_sd = 13.7
|
45 |
+
elif self.age > 60 and self.education <= 12:
|
46 |
+
self.norm_mean = 46.9
|
47 |
+
self.norm_sd = 10.4
|
48 |
+
elif self.age > 60 and self.education > 12:
|
49 |
+
self.norm_mean = 51.6
|
50 |
+
self.norm_sd = 12.6
|
51 |
+
else:
|
52 |
+
print("missing value/ wrong format")
|
53 |
+
|
54 |
+
|
55 |
+
def z_fas(self):
|
56 |
+
self.mean_fas()
|
57 |
+
z_fas = (self.fas - self.norm_mean) / self.norm_sd
|
58 |
+
stanine_fas = round(1.25 * z_fas + 5.5)
|
59 |
+
return round(z_fas, 2), stanine_fas
|
60 |
+
|
61 |
+
|
62 |
+
def calculate_isw(self):
|
63 |
+
isw_score = 74.38 + self.isw*0.66 - self.age*0.20 + self.education*1.77
|
64 |
+
return round(isw_score, 2)
|
65 |
+
|
66 |
+
def generate_graph(self):
|
67 |
+
BNT_z, _ = self.z_bnt()
|
68 |
+
FAS_z, _ = self.z_fas()
|
69 |
+
|
70 |
+
BNT_stanine = self.z_to_stanine(BNT_z)
|
71 |
+
FAS_stanine = self.z_to_stanine(FAS_z)
|
72 |
+
|
73 |
+
# Create a plot
|
74 |
+
fig, ax = plt.subplots()
|
75 |
+
|
76 |
+
# Set axis labels and title
|
77 |
+
ax.set_xlabel('Stanine values')
|
78 |
+
ax.set_ylabel('Test')
|
79 |
+
|
80 |
+
# Set the y-axis to display the tests
|
81 |
+
ax.set_yticks([1, 2])
|
82 |
+
ax.set_yticklabels(['BNT', 'FAS'])
|
83 |
+
|
84 |
+
# Set the range of the x-axis
|
85 |
+
ax.set_xlim([0, 10])
|
86 |
+
|
87 |
+
# Add dots for BNT and FAS scores
|
88 |
+
ax.scatter(BNT_stanine, 1, s=100, label='BNT')
|
89 |
+
ax.scatter(FAS_stanine, 2, s=100, label='FAS')
|
90 |
+
|
91 |
+
# Add legend
|
92 |
+
ax.legend()
|
93 |
+
|
94 |
+
# Show the plot
|
95 |
+
# plt.show()
|
96 |
+
|
97 |
+
# Save the graph as a png file
|
98 |
+
fig.savefig('test_profile.png')
|
99 |
+
return 'test_profile.png'
|
100 |
+
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
numpy
|
2 |
+
scipy
|
3 |
+
matplotlib
|
4 |
+
fpdf
|
5 |
+
Pillow
|