Create app_AD2class.py
Browse files- app_AD2class.py +157 -0
app_AD2class.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# app_AD2class.py
|
| 2 |
+
# Main application file. Builds a tabbed Gradio UI for multiple assessments.
|
| 3 |
+
|
| 4 |
+
import gradio as gr
|
| 5 |
+
|
| 6 |
+
# Import the separated modules
|
| 7 |
+
import MMSE
|
| 8 |
+
import CDRM # <-- Import the new placeholder module
|
| 9 |
+
import utils
|
| 10 |
+
|
| 11 |
+
# --- MMSE UI and Logic ---
|
| 12 |
+
def build_mmse_tab(mmse_score_state):
|
| 13 |
+
"""Builds the UI components for the MMSE tab."""
|
| 14 |
+
with gr.Blocks() as mmse_tab:
|
| 15 |
+
gr.Markdown("## Mini Mental State Exam (MMSE)")
|
| 16 |
+
question_index = gr.State(0)
|
| 17 |
+
answers = gr.State([""] * MMSE.TOTAL_QUESTIONS)
|
| 18 |
+
|
| 19 |
+
jump_nav = gr.Dropdown(choices=MMSE.QUESTION_CHOICES, value=MMSE.QUESTION_CHOICES[0], label="Jump to Question")
|
| 20 |
+
|
| 21 |
+
initial_q = MMSE.STRUCTURED_QUESTIONS[0]
|
| 22 |
+
progress_text = gr.Markdown(f"## {initial_q['main_cat']} - Q{initial_q['main_num']}{initial_q['sub_letter']} ({1} of {MMSE.TOTAL_QUESTIONS})")
|
| 23 |
+
instruction_display = gr.Markdown(initial_q["instruction"])
|
| 24 |
+
question_button = gr.Button(f"Say 🔊 {initial_q['question']}", variant="secondary")
|
| 25 |
+
|
| 26 |
+
with gr.Group():
|
| 27 |
+
answer_text = gr.Textbox(label="Your Answer (type or record below)")
|
| 28 |
+
audio_input = gr.Audio(sources=["microphone"], label="🎤 Record Your Answer Here")
|
| 29 |
+
image_upload = gr.Image(type="filepath", label="Upload Drawing for Drawing Question", visible=(initial_q['main_num'] == 11))
|
| 30 |
+
|
| 31 |
+
with gr.Row():
|
| 32 |
+
prev_btn = gr.Button("⬅️ Previous Question")
|
| 33 |
+
next_btn = gr.Button("Next Question ➡️")
|
| 34 |
+
|
| 35 |
+
tts_audio = gr.Audio(autoplay=True, visible=False)
|
| 36 |
+
score_lines = gr.Textbox(label="Score by Question", lines=15, interactive=False)
|
| 37 |
+
total = gr.Textbox(label="Total Score", interactive=False)
|
| 38 |
+
|
| 39 |
+
submit_btn = gr.Button("✅ Submit MMSE Answers")
|
| 40 |
+
start_over_btn = gr.Button("🔄 Start Over", visible=False)
|
| 41 |
+
|
| 42 |
+
# --- Event Handler Functions specific to this tab ---
|
| 43 |
+
def process_evaluation_MMSE(answers, image_upload):
|
| 44 |
+
score_lines_out, total_out = MMSE.evaluate_MMSE(answers, image_upload)
|
| 45 |
+
return score_lines_out, total_out, gr.update(visible=False), gr.update(visible=True), total_out
|
| 46 |
+
|
| 47 |
+
# Wire up event listeners
|
| 48 |
+
audio_input.change(utils.transcribe, inputs=audio_input, outputs=answer_text)
|
| 49 |
+
question_button.click(MMSE.speak_question, inputs=question_index, outputs=tts_audio)
|
| 50 |
+
|
| 51 |
+
outputs_list = [question_button, answer_text, question_index, progress_text,
|
| 52 |
+
instruction_display, jump_nav, image_upload, audio_input, answers]
|
| 53 |
+
|
| 54 |
+
next_btn.click(lambda *args: utils.save_and_navigate("next", *args, module=MMSE),
|
| 55 |
+
inputs=[question_index, answer_text, answers], outputs=outputs_list)
|
| 56 |
+
prev_btn.click(lambda *args: utils.save_and_navigate("prev", *args, module=MMSE),
|
| 57 |
+
inputs=[question_index, answer_text, answers], outputs=outputs_list)
|
| 58 |
+
jump_nav.change(lambda *args: utils.jump_to_question(*args, module=MMSE),
|
| 59 |
+
inputs=[jump_nav, question_index, answer_text, answers], outputs=outputs_list)
|
| 60 |
+
|
| 61 |
+
submit_btn.click(
|
| 62 |
+
utils.save_final_answer, inputs=[question_index, answer_text, answers], outputs=answers
|
| 63 |
+
).then(
|
| 64 |
+
fn=process_evaluation_MMSE, inputs=[answers, image_upload], outputs=[score_lines, total, submit_btn, start_over_btn, mmse_score_state]
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
start_over_btn.click(lambda: utils.reset_app(MMSE), outputs=[
|
| 68 |
+
question_index, answers, score_lines, total, question_button, progress_text,
|
| 69 |
+
instruction_display, answer_text, jump_nav, audio_input, image_upload,
|
| 70 |
+
start_over_btn, submit_btn, tts_audio, mmse_score_state
|
| 71 |
+
])
|
| 72 |
+
|
| 73 |
+
return mmse_tab
|
| 74 |
+
|
| 75 |
+
# --- CDRM UI and Logic (Placeholder) ---
|
| 76 |
+
def build_cdrm_tab(cdrm_score_state):
|
| 77 |
+
"""Builds the UI components for the CDR Memory tab."""
|
| 78 |
+
with gr.Blocks() as cdrm_tab:
|
| 79 |
+
gr.Markdown("## CDR Memory Assessment")
|
| 80 |
+
gr.Markdown("This is a placeholder for the CDR Memory test interface. The UI will be similar to the MMSE tab.")
|
| 81 |
+
|
| 82 |
+
# Dummy components to show structure
|
| 83 |
+
answer_text = gr.Textbox(label="Your Answer")
|
| 84 |
+
submit_btn = gr.Button("✅ Submit CDRM Answers")
|
| 85 |
+
total_score_output = gr.Textbox(label="Total Score", interactive=False)
|
| 86 |
+
|
| 87 |
+
def process_evaluation_CDRM(ans):
|
| 88 |
+
# In a real scenario, this would take more inputs
|
| 89 |
+
_, total_score = CDRM.evaluate_CDRM(None)
|
| 90 |
+
cdrm_score_state.value = total_score # Manually update state for placeholder
|
| 91 |
+
return total_score, total_score
|
| 92 |
+
|
| 93 |
+
submit_btn.click(process_evaluation_CDRM, inputs=[answer_text], outputs=[total_score_output, cdrm_score_state])
|
| 94 |
+
|
| 95 |
+
return cdrm_tab
|
| 96 |
+
|
| 97 |
+
# --- Joint Outcome UI ---
|
| 98 |
+
def build_joint_outcome_tab(mmse_score_state, cdrm_score_state):
|
| 99 |
+
"""Builds the UI for the Joint Outcome analysis tab."""
|
| 100 |
+
with gr.Blocks() as joint_tab:
|
| 101 |
+
gr.Markdown("## Joint Outcome Analysis")
|
| 102 |
+
gr.Markdown("This tab will use the results from the MMSE and CDR Memory tabs to provide a combined analysis.")
|
| 103 |
+
|
| 104 |
+
with gr.Row():
|
| 105 |
+
mmse_result = gr.Textbox(label="MMSE Final Score", interactive=False)
|
| 106 |
+
cdrm_result = gr.Textbox(label="CDR Memory Final Score", interactive=False)
|
| 107 |
+
|
| 108 |
+
analyze_btn = gr.Button("Analyze Joint Outcome")
|
| 109 |
+
outcome_display = gr.Textbox(label="Combined Analysis Result", interactive=False)
|
| 110 |
+
|
| 111 |
+
def analyze_outcomes(mmse_score, cdrm_score):
|
| 112 |
+
# Placeholder logic for joint analysis
|
| 113 |
+
if not mmse_score and not cdrm_score:
|
| 114 |
+
return "Please complete both assessments first."
|
| 115 |
+
|
| 116 |
+
# Example:
|
| 117 |
+
# mmse_val = int(mmse_score.split('/')[0].strip())
|
| 118 |
+
# cdrm_val = int(cdrm_score.split('/')[0].strip())
|
| 119 |
+
# some_logic...
|
| 120 |
+
|
| 121 |
+
return f"Analysis based on MMSE score: '{mmse_score}' and CDRM score: '{cdrm_score}'.\n\n(Full analysis logic to be implemented)"
|
| 122 |
+
|
| 123 |
+
analyze_btn.click(analyze_outcomes, inputs=[mmse_score_state, cdrm_score_state], outputs=outcome_display)
|
| 124 |
+
|
| 125 |
+
# Link state changes to the textboxes for display
|
| 126 |
+
mmse_score_state.change(lambda x: x, inputs=mmse_score_state, outputs=mmse_result)
|
| 127 |
+
cdrm_score_state.change(lambda x: x, inputs=cdrm_score_state, outputs=cdrm_result)
|
| 128 |
+
|
| 129 |
+
return joint_tab
|
| 130 |
+
|
| 131 |
+
# --- Main Application Build ---
|
| 132 |
+
def build_ui():
|
| 133 |
+
"""Builds the main Gradio interface with tabs."""
|
| 134 |
+
with gr.Blocks(theme=gr.themes.Soft(), title="Cognitive Assessment Suite") as demo:
|
| 135 |
+
gr.Markdown("# Cognitive Assessment Suite")
|
| 136 |
+
|
| 137 |
+
# State objects to share results between tabs
|
| 138 |
+
mmse_score_state = gr.State("")
|
| 139 |
+
cdrm_score_state = gr.State("")
|
| 140 |
+
|
| 141 |
+
with gr.Tabs():
|
| 142 |
+
with gr.TabItem("MMSE"):
|
| 143 |
+
build_mmse_tab(mmse_score_state)
|
| 144 |
+
with gr.TabItem("CDR Memory"):
|
| 145 |
+
build_cdrm_tab(cdrm_score_state)
|
| 146 |
+
with gr.TabItem("Joint Outcome"):
|
| 147 |
+
build_joint_outcome_tab(mmse_score_state, cdrm_score_state)
|
| 148 |
+
return demo
|
| 149 |
+
|
| 150 |
+
if __name__ == "__main__":
|
| 151 |
+
# Perform one-time setup for all modules
|
| 152 |
+
MMSE.pregenerate_audio()
|
| 153 |
+
CDRM.pregenerate_audio()
|
| 154 |
+
|
| 155 |
+
app = build_ui()
|
| 156 |
+
app.launch()
|
| 157 |
+
|