Update app.py
Browse files
app.py
CHANGED
@@ -1,73 +1,16 @@
|
|
1 |
import gradio as gr
|
2 |
import json
|
|
|
3 |
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
"Note": "The image shows a new triangular opacity in the right lung apex, which indicates an abnormality in that area. The fullness of the right hilum, which is the area where the main bronchus, blood vessels, and nerves enter and exit the lung, is also new. The remainder of the lungs appears to be clear. The heart size is within the normal range. The blunting of bilateral costophrenic angles, with the right greater than the left, may be secondary to small effusions, which are fluid collections in the pleural space surrounding the lungs.",
|
8 |
-
"Summary": {
|
9 |
-
"chest_xray_summary": [
|
10 |
-
{
|
11 |
-
"topic": "Right Lung Apex",
|
12 |
-
"description": "A new triangular opacity is observed in the right lung apex, indicating an abnormality in this area."
|
13 |
-
},
|
14 |
-
{
|
15 |
-
"topic": "Right Hilum",
|
16 |
-
"description": "There is fullness of the right hilum, which is a new finding. The hilum is where the main bronchus, blood vessels, and nerves enter and exit the lung."
|
17 |
-
},
|
18 |
-
{
|
19 |
-
"topic": "Lung Parenchyma",
|
20 |
-
"description": "The remainder of the lungs appears clear, aside from the noted abnormalities."
|
21 |
-
},
|
22 |
-
{
|
23 |
-
"topic": "Heart Size",
|
24 |
-
"description": "The heart size is within the normal range."
|
25 |
-
},
|
26 |
-
{
|
27 |
-
"topic": "Costophrenic Angles",
|
28 |
-
"description": "There is blunting of bilateral costophrenic angles, with the right side more affected than the left."
|
29 |
-
},
|
30 |
-
{
|
31 |
-
"topic": "Pleural Effusions",
|
32 |
-
"description": "The blunting of costophrenic angles may be secondary to small effusions in the pleural space surrounding the lungs."
|
33 |
-
}
|
34 |
-
]
|
35 |
-
},
|
36 |
-
"MCQS": [
|
37 |
-
{
|
38 |
-
"category": "Diagnostic Accuracy",
|
39 |
-
"question": "What finding is observed in the right lung apex on this chest X-ray?",
|
40 |
-
"options": [
|
41 |
-
"A) A circular opacity",
|
42 |
-
"B) A triangular opacity",
|
43 |
-
"C) A linear opacity",
|
44 |
-
"D) No new opacity"
|
45 |
-
],
|
46 |
-
"correct_answer": "B) A triangular opacity",
|
47 |
-
"location_in_text": "The image shows a new triangular opacity in the right lung apex"
|
48 |
-
},
|
49 |
-
{
|
50 |
-
"category": "Anatomical Detailing",
|
51 |
-
"question": "Which anatomical structure shows fullness in this chest X-ray?",
|
52 |
-
"options": [
|
53 |
-
"A) Left hilum",
|
54 |
-
"B) Right hilum",
|
55 |
-
"C) Left lung base",
|
56 |
-
"D) Right lung base"
|
57 |
-
],
|
58 |
-
"correct_answer": "B) Right hilum",
|
59 |
-
"location_in_text": "The fullness of the right hilum, which is the area where the main bronchus, blood vessels, and nerves enter and exit the lung, is also new."
|
60 |
-
}
|
61 |
-
],
|
62 |
-
"image": "https://huggingface.co/spaces/aaditya/demo_app/resolve/main/chest_xray.jpg"
|
63 |
-
}
|
64 |
-
]
|
65 |
|
66 |
-
def display_data(index):
|
67 |
item = data[index]
|
68 |
note = item.get('Note', 'No note available')
|
69 |
summary = item.get('Summary', {})
|
70 |
-
mcqs = item.get('MCQS',
|
71 |
image_path = item.get('image', '')
|
72 |
|
73 |
summary_html = "<h3>Summary</h3>"
|
@@ -78,45 +21,92 @@ def display_data(index):
|
|
78 |
summary_html += "<p>No summary available</p>"
|
79 |
|
80 |
mcqs_html = "<h3>MCQs</h3>"
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
-
return note, summary_html, mcqs_html, image_path
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
summary = gr.HTML(label="Summary")
|
103 |
-
mcqs = gr.HTML(label="MCQs")
|
104 |
-
|
105 |
-
index = gr.Slider(0, len(data) - 1, step=1, label="Item Index")
|
106 |
-
|
107 |
-
def update_display(index):
|
108 |
-
return display_data(int(index))
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
|
116 |
-
|
117 |
-
|
118 |
-
inputs=[index],
|
119 |
-
outputs=[note, summary, mcqs, image]
|
120 |
-
)
|
121 |
|
122 |
-
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
import json
|
3 |
+
from pathlib import Path
|
4 |
|
5 |
+
def load_json(file_path):
|
6 |
+
with open(file_path, 'r') as file:
|
7 |
+
return json.load(file)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
+
def display_data(index, data):
|
10 |
item = data[index]
|
11 |
note = item.get('Note', 'No note available')
|
12 |
summary = item.get('Summary', {})
|
13 |
+
mcqs = item.get('MCQS', {})
|
14 |
image_path = item.get('image', '')
|
15 |
|
16 |
summary_html = "<h3>Summary</h3>"
|
|
|
21 |
summary_html += "<p>No summary available</p>"
|
22 |
|
23 |
mcqs_html = "<h3>MCQs</h3>"
|
24 |
+
if isinstance(mcqs, dict) and 'questions' in mcqs:
|
25 |
+
for i, q in enumerate(mcqs['questions'], 1):
|
26 |
+
mcqs_html += f"<p><strong>Q{i}: {q['question']}</strong></p>"
|
27 |
+
mcqs_html += "<ul>"
|
28 |
+
for option in q['options']:
|
29 |
+
mcqs_html += f"<li>{option}</li>"
|
30 |
+
mcqs_html += "</ul>"
|
31 |
+
mcqs_html += f"<p>Correct Answer: {q['correct_answer']}</p>"
|
32 |
+
if 'location_in_text' in q:
|
33 |
+
mcqs_html += f"<p><em>Location in text: {q['location_in_text']}</em></p>"
|
34 |
+
mcqs_html += "<hr>"
|
35 |
+
elif isinstance(mcqs, list):
|
36 |
+
for i, q in enumerate(mcqs, 1):
|
37 |
+
mcqs_html += f"<p><strong>Q{i}: {q['question']}</strong></p>"
|
38 |
+
mcqs_html += "<ul>"
|
39 |
+
for option in q['options']:
|
40 |
+
mcqs_html += f"<li>{option}</li>"
|
41 |
+
mcqs_html += "</ul>"
|
42 |
+
mcqs_html += f"<p>Correct Answer: {q['correct_answer']}</p>"
|
43 |
+
if 'location_in_text' in q:
|
44 |
+
mcqs_html += f"<p><em>Location in text: {q['location_in_text']}</em></p>"
|
45 |
+
mcqs_html += "<hr>"
|
46 |
+
else:
|
47 |
+
mcqs_html += "<p>No MCQs available for this item.</p>"
|
48 |
|
49 |
+
return note, summary_html, mcqs_html, image_path, f"Item {index + 1} of {len(data)}"
|
50 |
|
51 |
+
def next_item(index, data):
|
52 |
+
return min(index + 1, len(data) - 1)
|
53 |
+
|
54 |
+
def prev_item(index, data):
|
55 |
+
return max(index - 1, 0)
|
56 |
+
|
57 |
+
def create_app(json_path):
|
58 |
+
data = load_json(json_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
+
with gr.Blocks() as app:
|
61 |
+
gr.Markdown("# Chest X-Ray Analysis Viewer")
|
62 |
+
|
63 |
+
with gr.Row():
|
64 |
+
with gr.Column(scale=1):
|
65 |
+
image = gr.Image(label="X-Ray Image")
|
66 |
+
with gr.Column(scale=2):
|
67 |
+
note = gr.Textbox(label="Note", lines=4)
|
68 |
+
summary = gr.HTML(label="Summary")
|
69 |
+
mcqs = gr.HTML(label="MCQs")
|
70 |
+
|
71 |
+
index = gr.State(0)
|
72 |
+
item_count = gr.Textbox(label="Item Count")
|
73 |
+
|
74 |
+
with gr.Row():
|
75 |
+
prev_btn = gr.Button("Previous")
|
76 |
+
next_btn = gr.Button("Next")
|
77 |
+
|
78 |
+
def update_display(index):
|
79 |
+
return display_data(index, data)
|
80 |
+
|
81 |
+
next_btn.click(
|
82 |
+
next_item,
|
83 |
+
inputs=[index, gr.State(data)],
|
84 |
+
outputs=[index]
|
85 |
+
).then(
|
86 |
+
update_display,
|
87 |
+
inputs=[index],
|
88 |
+
outputs=[note, summary, mcqs, image, item_count]
|
89 |
+
)
|
90 |
+
|
91 |
+
prev_btn.click(
|
92 |
+
prev_item,
|
93 |
+
inputs=[index, gr.State(data)],
|
94 |
+
outputs=[index]
|
95 |
+
).then(
|
96 |
+
update_display,
|
97 |
+
inputs=[index],
|
98 |
+
outputs=[note, summary, mcqs, image, item_count]
|
99 |
+
)
|
100 |
+
|
101 |
+
app.load(
|
102 |
+
update_display,
|
103 |
+
inputs=[index],
|
104 |
+
outputs=[note, summary, mcqs, image, item_count]
|
105 |
+
)
|
106 |
|
107 |
+
return app
|
108 |
+
|
|
|
|
|
|
|
109 |
|
110 |
+
json_path = Path("mimic_data.json")
|
111 |
+
app = create_app(json_path)
|
112 |
+
app.launch()
|