Birger Moell commited on
Commit
0de5d5b
1 Parent(s): 199ef5a

Added files for HF

Browse files
Files changed (6) hide show
  1. app.py +480 -0
  2. logo.jpg +0 -0
  3. logo2.jpg +0 -0
  4. logo3.jpg +0 -0
  5. plots.py +100 -0
  6. requirements.txt +5 -0
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