| | import gradio as gr |
| | import pandas as pd |
| | import numpy as np |
| | import matplotlib.pyplot as plt |
| | import seaborn as sns |
| | from huggingface_hub import InferenceClient |
| |
|
| | |
| | questions = [ |
| | {"id": "Q1", "text": "How would you rate your quality of life?", "domain": "Overall QOL", "scores": ["Very poor", "Poor", "Neither poor nor good", "Good", "Very good"]}, |
| | {"id": "Q2", "text": "How satisfied are you with your health?", "domain": "Overall Health", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q3", "text": "To what extent do you feel that physical pain prevents you from doing what you need to do?", "domain": "Physical", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "An extreme amount"], "reverse": True}, |
| | {"id": "Q4", "text": "How much do you need any medical treatment to function in your daily life?", "domain": "Physical", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "An extreme amount"], "reverse": True}, |
| | {"id": "Q5", "text": "How much do you enjoy life?", "domain": "Psychological", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "An extreme amount"]}, |
| | {"id": "Q6", "text": "To what extent do you feel your life to be meaningful?", "domain": "Psychological", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "An extreme amount"]}, |
| | {"id": "Q7", "text": "How well are you able to concentrate?", "domain": "Psychological", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "Extremely"]}, |
| | {"id": "Q8", "text": "How safe do you feel in your daily life?", "domain": "Environment", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "Extremely"]}, |
| | {"id": "Q9", "text": "How healthy is your physical environment?", "domain": "Environment", "scores": ["Not at all", "A little", "A moderate amount", "Very much", "Extremely"]}, |
| | {"id": "Q10", "text": "Do you have enough energy for everyday life?", "domain": "Physical", "scores": ["Not at all", "A little", "Moderately", "Mostly", "Completely"]}, |
| | {"id": "Q11", "text": "Are you able to accept your bodily appearance?", "domain": "Psychological", "scores": ["Not at all", "A little", "Moderately", "Mostly", "Completely"]}, |
| | {"id": "Q12", "text": "Have you enough money to meet your needs?", "domain": "Environment", "scores": ["Not at all", "A little", "Moderately", "Mostly", "Completely"]}, |
| | {"id": "Q13", "text": "How available to you is the information that you need in your day-to-day life?", "domain": "Environment", "scores": ["Not at all", "A little", "Moderately", "Mostly", "Completely"]}, |
| | {"id": "Q14", "text": "To what extent do you have the opportunity for leisure activities?", "domain": "Environment", "scores": ["Not at all", "A little", "Moderately", "Mostly", "Completely"]}, |
| | {"id": "Q15", "text": "How well are you able to get around?", "domain": "Physical", "scores": ["Very poor", "Poor", "Neither poor nor good", "Good", "Very good"]}, |
| | {"id": "Q16", "text": "How satisfied are you with your sleep?", "domain": "Physical", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q17", "text": "How satisfied are you with your ability to perform your daily living activities?", "domain": "Physical", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q18", "text": "How satisfied are you with your capacity for work?", "domain": "Physical", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q19", "text": "How satisfied are you with yourself?", "domain": "Psychological", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q20", "text": "How satisfied are you with your personal relationships?", "domain": "Social", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q21", "text": "How satisfied are you with your sex life?", "domain": "Social", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q22", "text": "How satisfied are you with the support you get from your friends?", "domain": "Social", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q23", "text": "How satisfied are you with the conditions of your living place?", "domain": "Environment", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q24", "text": "How satisfied are you with your access to health services?", "domain": "Environment", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q25", "text": "How satisfied are you with your transport?", "domain": "Environment", "scores": ["Very dissatisfied", "Dissatisfied", "Neither satisfied nor dissatisfied", "Satisfied", "Very satisfied"]}, |
| | {"id": "Q26", "text": "How often do you have negative feelings such as blue mood, despair, anxiety, depression?", "domain": "Psychological", "scores": ["Never", "Seldom", "Quite often", "Very often", "Always"], "reverse": True} |
| | ] |
| |
|
| | |
| | domain_info = { |
| | "Physical": { |
| | "questions": ["Q3", "Q4", "Q10", "Q15", "Q16", "Q17", "Q18"], |
| | "transform": lambda raw: (raw - 7) * (100/28) |
| | }, |
| | "Psychological": { |
| | "questions": ["Q5", "Q6", "Q7", "Q11", "Q19", "Q26"], |
| | "transform": lambda raw: (raw - 6) * (100/24) |
| | }, |
| | "Social": { |
| | "questions": ["Q20", "Q21", "Q22"], |
| | "transform": lambda raw: (raw - 3) * (100/12) |
| | }, |
| | "Environment": { |
| | "questions": ["Q8", "Q9", "Q12", "Q13", "Q14", "Q23", "Q24", "Q25"], |
| | "transform": lambda raw: (raw - 8) * (100/32) |
| | }, |
| | "Overall QOL": { |
| | "questions": ["Q1"], |
| | "transform": lambda raw: (raw - 1) * (100/4) |
| | }, |
| | "Overall Health": { |
| | "questions": ["Q2"], |
| | "transform": lambda raw: (raw - 1) * (100/4) |
| | } |
| | } |
| |
|
| | |
| | domain_full_names = { |
| | "Physical": "Physical Health", |
| | "Psychological": "Psychological Well-being", |
| | "Social": "Social Relationships", |
| | "Environment": "Environment", |
| | "Overall QOL": "Overall Quality of Life", |
| | "Overall Health": "Overall Health Satisfaction" |
| | } |
| |
|
| | |
| | interpretation_ranges = { |
| | "Physical Health": { |
| | "high_range": 70, |
| | "medium_range": (50, 69), |
| | "low_range": 49, |
| | "high_inference": "Good physical well-being, minimal limitations, good energy and mobility.", |
| | "medium_inference": "Mild to moderate physical limitations, some pain, or reduced energy.", |
| | "low_inference": "Significant physical health limitations, pain, fatigue, poor mobility.", |
| | "high_intervention": "Maintain a healthy lifestyle, regular exercise, balanced nutrition.", |
| | "medium_intervention": "Increase physical activity, improve sleep, manage minor pain.", |
| | "low_intervention": "Medical intervention, physical therapy, chronic disease management." |
| | }, |
| | "Psychological Health": { |
| | "high_range": 75, |
| | "medium_range": (50, 74), |
| | "low_range": 49, |
| | "high_inference": "Strong emotional resilience, positive self-esteem, low anxiety or stress.", |
| | "medium_inference": "Moderate psychological health, occasional stress, some mood fluctuations.", |
| | "low_inference": "High emotional distress, anxiety, depression, low self-worth.", |
| | "high_intervention": "Continue positive mental health practices, social engagement.", |
| | "medium_intervention": "Use stress reduction techniques, engage in self-care routines.", |
| | "low_intervention": "Psychological counseling, cognitive behavioral therapy, medication if needed." |
| | }, |
| | "Social Relationships": { |
| | "high_range": 70, |
| | "medium_range": (50, 69), |
| | "low_range": 49, |
| | "high_inference": "Strong social connections, good interpersonal support, high satisfaction.", |
| | "medium_inference": "Moderate social interactions, may experience loneliness or minor conflicts.", |
| | "low_inference": "Weak social relationships, lack of support, loneliness, or isolation.", |
| | "high_intervention": "Sustain social connections, participate in group/community activities.", |
| | "medium_intervention": "Strengthen personal relationships, seek social support groups.", |
| | "low_intervention": "Social integration programs, mental health support, relationship therapy." |
| | }, |
| | "Environment": { |
| | "high_range": 70, |
| | "medium_range": (50, 69), |
| | "low_range": 49, |
| | "high_inference": "Safe and stable environment, access to resources and healthcare, financial security.", |
| | "medium_inference": "Some dissatisfaction with living conditions, financial constraints, or safety concerns.", |
| | "low_inference": "Unstable living conditions, financial stress, poor healthcare access, safety concerns.", |
| | "high_intervention": "Maintain financial stability, ensure continuous access to healthcare.", |
| | "medium_intervention": "Identify key environmental issues, seek financial or housing support.", |
| | "low_intervention": "Government or NGO assistance for financial/housing needs, healthcare access." |
| | } |
| | } |
| |
|
| | |
| | client = InferenceClient("HuggingFaceH4/zephyr-7b-beta") |
| |
|
| |
|
| | |
| | def get_llm_interpretation(domain, score, interpretation_ranges): |
| | if domain not in interpretation_ranges: |
| | return "No interpretation available." |
| |
|
| | range_info = interpretation_ranges[domain] |
| |
|
| | if score >= range_info["high_range"]: |
| | inference = range_info["high_inference"] |
| | intervention = range_info["high_intervention"] |
| | level = "High" |
| | elif range_info["medium_range"][0] <= score <= range_info["medium_range"][1]: |
| | inference = range_info["medium_inference"] |
| | intervention = range_info["medium_intervention"] |
| | level = "Medium" |
| | else: |
| | inference = range_info["low_inference"] |
| | intervention = range_info["low_intervention"] |
| | level = "Low" |
| |
|
| | prompt = f""" |
| | Based on the WHOQOL-BREF assessment results for {domain}, the score is {score}, which is categorized as {level}. |
| | The inference is: {inference} |
| | Suggested intervention: {intervention} |
| | |
| | Provide a more detailed and personalized interpretation, including potential causes and specific recommendations. |
| | |
| | Response should be concise, empathetic, and helpful. |
| | """ |
| |
|
| | try: |
| | |
| | interpretation = client.text_generation(prompt, max_new_tokens=200) |
| | return interpretation |
| | except Exception as e: |
| | return f"Error getting interpretation from LLM: {e}" |
| |
|
| |
|
| | |
| | def calculate_scores(responses): |
| | domain_scores = {} |
| |
|
| | for domain, info in domain_info.items(): |
| | domain_questions = info["questions"] |
| | total_score = 0 |
| |
|
| | for q_id in domain_questions: |
| | q_index = next((i for i, q in enumerate(questions) if q["id"] == q_id), None) |
| | if q_index is not None and responses.get(q_id) is not None: |
| | if questions[q_index].get("reverse", False): |
| | total_score += 6 - responses[q_id] |
| | else: |
| | total_score += responses[q_id] |
| |
|
| | transformed_score = info["transform"](total_score) |
| | domain_scores[domain] = round(transformed_score, 2) |
| |
|
| | return domain_scores |
| |
|
| |
|
| | |
| | def interpret_score(domain, score): |
| | if domain not in interpretation_ranges: |
| | return "Unknown", "No interpretation available." |
| |
|
| | range_info = interpretation_ranges[domain] |
| | high_range = range_info["high_range"] |
| | medium_range = range_info["medium_range"] |
| | low_range = range_info["low_range"] |
| |
|
| | if score >= high_range: |
| | return ( |
| | "High", |
| | f"{range_info['high_inference']} {range_info['high_intervention']}" |
| | ) |
| | elif range_info["medium_range"][0] <= score <= range_info["medium_range"][1]: |
| | return ( |
| | "Medium", |
| | f"{range_info['medium_inference']} {range_info['medium_intervention']}" |
| | ) |
| | else: |
| | return ( |
| | "Low", |
| | f"{range_info['low_inference']} {range_info['low_intervention']}" |
| | ) |
| |
|
| | |
| | def whoqol_assessment(*responses): |
| |
|
| | |
| | responses_dict = {q["id"]: int(r) for q, r in zip(questions, responses)} |
| |
|
| | |
| | scores = calculate_scores(responses_dict) |
| |
|
| | if scores is None: |
| | return "Please answer all questions." |
| |
|
| | |
| | main_domains = ["Physical", "Psychological", "Social", "Environment"] |
| | main_scores = [scores[domain] for domain in main_domains] |
| |
|
| | |
| | fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True)) |
| |
|
| | |
| | angles = np.linspace(0, 2 * np.pi, len(main_domains), endpoint=False).tolist() |
| | angles += angles[:1] |
| |
|
| | |
| | values = main_scores + [main_scores[0]] |
| |
|
| | |
| | ax.plot(angles, values, 'o-', linewidth=2, color='blue') |
| | ax.fill(angles, values, color='blue', alpha=0.25) |
| |
|
| | |
| | domain_labels = [domain_full_names[domain] for domain in main_domains] |
| | ax.set_xticks(angles[:-1]) |
| | ax.set_xticklabels(domain_labels, fontsize=10) |
| |
|
| | |
| | ax.set_ylim(0, 100) |
| | ax.set_yticks([0, 25, 50, 75, 100]) |
| | ax.set_yticklabels(['0', '25', '50', '75', '100'], fontsize=8) |
| |
|
| | |
| | ax.grid(True, linestyle='-', alpha=0.7) |
| |
|
| | |
| | ax.set_title('WHOQOL-BREF Domain Scores', size=12, y=1.1) |
| |
|
| | |
| | interpretations_text = "" |
| | for domain in ["Physical", "Psychological", "Social", "Environment", "Overall QOL", "Overall Health"]: |
| | score = scores[domain] |
| | llm_interpretation = get_llm_interpretation(domain_full_names[domain], score, interpretation_ranges) |
| | interpretations_text += f"**{domain_full_names[domain]}**: {llm_interpretation}\n\n" |
| |
|
| | return fig, interpretations_text |
| |
|
| |
|
| | |
| | inputs = [] |
| | for q in questions: |
| | inputs.append(gr.Radio(choices=q["scores"], label=q["text"])) |
| |
|
| | |
| | radar_chart_output = gr.Plot() |
| | interpretations_output = gr.Markdown() |
| |
|
| | |
| | iface = gr.Interface( |
| | fn=whoqol_assessment, |
| | inputs=inputs, |
| | outputs=[radar_chart_output, interpretations_output], |
| | title="WHOQOL-BREF Quality of Life Assessment", |
| | description="Complete the questionnaire to receive your quality of life assessment across different domains.", |
| | ) |
| |
|
| | |
| | iface.launch() |