import streamlit as st import numpy as np import scipy.stats as stats from fpdf import FPDF import base64 import os from plots import test_profile import matplotlib.pyplot as plt from PIL import Image # Function to calculate z-score def calculate_z_score(test_score, mean, std_dev): return (test_score - mean) / std_dev def z_score_calculator(value, norm_mean, norm_sd): z_value = (value - norm_mean) / norm_sd stanine_value = round(1.25 * z_value + 5.5) z_score = round(z_value, 2) return z_score, stanine_value def bnt_calculator(age, education, bnt): if age <= 60 and education <= 12: norm_mean = 54.5 norm_sd = 3.2 z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age <= 60 and education > 12: norm_mean = 54.0 norm_sd = 4.4 z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age > 60 and education <= 12: norm_mean = 54.8 norm_sd = 3.3 z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age > 60 and education > 12: norm_mean = 56.2 norm_sd = 3.4 z_score, stanine_value = z_score_calculator(bnt, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value else: print("missing value/ wrong format") def fas_calculator(age, education, fas): if age <= 60 and education <= 12: norm_mean = 42.7 norm_sd = 13.7 z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age <= 60 and education > 12: norm_mean = 46.7 norm_sd = 13.7 z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age > 60 and education <= 12: norm_mean = 46.9 norm_sd = 10.4 z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value elif age > 60 and education > 12: norm_mean = 51.6 norm_sd = 12.6 z_score, stanine_value = z_score_calculator(fas, norm_mean, norm_sd) return norm_mean, norm_sd, z_score, stanine_value else: print("missing value/ wrong format") def generate_graph(BNT_stanine, FAS_stanine): # Create a plot fig, ax = plt.subplots() # Set axis labels and title ax.set_xlabel('Stanine values') ax.set_ylabel('Test') # Set the y-axis to display the tests ax.set_yticks([1, 2]) ax.set_yticklabels(['BNT', 'FAS']) # Set the range of the x-axis ax.set_xlim([0, 10]) # Add dots for BNT and FAS scores ax.scatter(BNT_stanine, 1, s=100, label='BNT') ax.scatter(FAS_stanine, 2, s=100, label='FAS') # Add legend ax.legend() # Show the plot # plt.show() # Save the graph as a png file fig.savefig('test_profile.png') return 'test_profile.png' def create_pdf(z_score, mean, std_dev, logo_path, plot_path): pdf = FPDF() pdf.add_page() pdf.set_xy(0, 0) pdf.set_font("Arial", size=12) # Add logos x_positions = [25, 85, 145] for i, logo_path in enumerate(logo_paths): pdf.image(logo_path, x=x_positions[i], y=8, w=40) pdf.set_xy(10, 50) # Add title and center it title = "Z-Score Report" pdf.set_font("Arial", style="B", size=16) title_width = pdf.get_string_width(title) + 6 pdf.cell((210 - title_width) / 2) pdf.cell(title_width, 10, title, 0, 1, "C") # Add z-score and center it pdf.set_font("Arial", size=12) z_score_text = "Your z-score is: {:.2f}".format(z_score) z_score_width = pdf.get_string_width(z_score_text) + 6 pdf.cell((210 - z_score_width) / 2) pdf.cell(z_score_width, 10, z_score_text, 0, 1, "C") # Add mean and standard deviation and center it mean_std_text = "Mean: {}, Standard Deviation: {}".format(mean, std_dev) mean_std_width = pdf.get_string_width(mean_std_text) + 6 pdf.cell((210 - mean_std_width) / 2) pdf.cell(mean_std_width, 10, mean_std_text, 0, 1, "C") # Add logo pdf.image(plot_path, x=10, y=80, w=200) # pdf.set_xy(10, 40) # Add tool description and center it pdf.set_xy(10, 230) pdf.set_font("Arial", size=10) description = "This PDF report was generated using the Z-Score Calculator Streamlit App." pdf.multi_cell(0, 10, description, 0, "C") # Add explanatory text about the collaboration between KI and KTH pdf.set_xy(10, 255) pdf.set_font("Arial", size=8) collaboration_text = ( "Den här PDF:en är en del av ett samarbetsprojekt mellan Karolinska Institutet (KI) och " "Kungliga Tekniska Högskolan (KTH) med målsättningen att använda artificiell intelligens (AI) och " "teknik för att minska administration i sjukhusarbete. Projektet fokuserar på att utveckla och " "implementera AI-baserade lösningar för att förbättra arbetsflöden, öka effektiviteten och " "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." ) line_width = 190 line_height = pdf.font_size_pt * 0.6 lines = collaboration_text.split(' ') current_line = '' for word in lines: if pdf.get_string_width(current_line + word) < line_width: current_line += word + ' ' else: pdf.cell(line_width, line_height, current_line, 0, 1) current_line = word + ' ' pdf.cell(line_width, line_height, current_line, 0, 1) return pdf def pdf_to_base64(pdf): with open(pdf, "rb") as file: return base64.b64encode(file.read()).decode('utf-8') # Title and description st.title("Z-Score Calculator") st.write("Enter your test score, age, and education level to calculate the z-score.") # Input fields #test_score = st.number_input("Test Score", min_value=0, value=0, step=1) age = st.number_input("Age", min_value=0, value=18, step=1) education_level = st.number_input("Education Level in years", min_value=0, value=18, step=1) isw = st.number_input("ISW", min_value=0, value=0, step=1) bnt = st.number_input("BNT", min_value=0, value=0, step=1) fas = st.number_input("FAS", min_value=0, value=0, step=1) animal = st.number_input("Animal", min_value=0, value=0, step=1) verb = st.number_input("Verb", min_value=0, value=0, step=1) repetition = st.number_input("Repetition", min_value=0, value=0, step=1) logicogrammatic = st.number_input("Logicogrammatic", min_value=0, value=0, step=1) inference = st.number_input("Inference", min_value=0, value=0, step=1) reading_speed = st.number_input("Reading Speed", min_value=0, value=0, step=1) decoding_words = st.number_input("Decoding Words", min_value=0, value=0, step=1) decoding_non_words = st.number_input("Decoding Non-Words", min_value=0, value=0, step=1) months_backward = st.number_input("Months Backward", min_value=0, value=0, step=1) pataka = st.number_input("Pataka", min_value=0, value=0, step=1) # add all the tests # Calculate mean and standard deviation based on age and education level # For simplicity, we will use made-up values for mean and std_dev mean = np.random.randint(50, 100) std_dev = np.random.randint(10, 30) # Calculate z-score and display result if st.button("Calculate Z-Score"): profile = test_profile(age, education_level, isw, bnt, fas) # for each value in the profile, calculate the z-score bnt_mean, bnt_std, z_bnt, stanine_bnt = bnt_calculator(age, education_level, bnt) fas_mean, fas_std, z_fas, stanine_fas = fas_calculator(age, education_level, fas) # z_score = calculate_z_score(test_score, mean, std_dev) st.write(f"Your bnt z-score is: {z_bnt:.2f}") st.write(f"Mean: {bnt_mean}, Standard Deviation: {bnt_std}") st.write(f"Your fas z-score is: {z_fas:.2f}") st.write(f"Mean: {fas_mean}, Standard Deviation: {fas_std}") # Create PDF # logo_path="logo.jpg" logo_paths = ["logo.jpg", "logo2.jpg", "logo3.jpg"] # create the plot from the dataframe # check if education level is more than 12 years, if more than 12, set value to one, otherwise zero education_level = 1 if education_level > 12 else 0 plot_path = generate_graph(stanine_bnt, stanine_fas) # create an image from the plot and add to streamlit display image = Image.open(plot_path) st.image(image, caption='Stanine plot', use_column_width=True) pdf_filename = "z_score_report.pdf" pdf = create_pdf(z_bnt, bnt_mean, bnt_std, logo_paths, plot_path) pdf.output(name=pdf_filename) # Download PDF with open(pdf_filename, "rb") as file: base64_pdf = base64.b64encode(file.read()).decode('utf-8') pdf_display = f'Download PDF' st.markdown(pdf_display, unsafe_allow_html=True) # Remove PDF file after download if os.path.exists(pdf_filename): os.remove(pdf_filename)