Fernando Moreno commited on
Commit
86ab63d
·
1 Parent(s): 17b0b49

Updated application for corneal analysis with improved UI/UX and features

Browse files
Files changed (3) hide show
  1. README.md +47 -5
  2. app.py +163 -259
  3. requirements.txt +5 -5
README.md CHANGED
@@ -1,12 +1,54 @@
1
  ---
2
- title: Retina AI OCT
3
- emoji: 📉
4
- colorFrom: gray
5
- colorTo: gray
6
  sdk: streamlit
7
- sdk_version: 1.41.1
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Cornea AI Pentacam Analyzer
3
+ emoji: 👁️
4
+ colorFrom: blue
5
+ colorTo: indigo
6
  sdk: streamlit
7
+ sdk_version: 1.31.0
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
+
14
+ # Cornea AI Pentacam Analyzer
15
+
16
+ Advanced corneal analysis and diagnostics tool developed by Dr. Verónica Gómez Calleja, cornea specialist.
17
+
18
+ ## Features
19
+
20
+ - Comprehensive Pentacam scan analysis
21
+ - Support for multiple file formats (PDF, PNG, JPG, JPEG)
22
+ - Patient history and clinical data management
23
+ - Comparative analysis between timepoints
24
+ - Advanced corneal disease diagnostics including:
25
+ - Keratoconus assessment using ABCD staging
26
+ - Fuchs Endothelial Corneal Dystrophy (FECD) evaluation
27
+ - Subclinical corneal edema detection using Sun criteria
28
+
29
+ ## Setup
30
+
31
+ 1. Install Python 3.8 or higher
32
+ 2. Install dependencies:
33
+ ```bash
34
+ pip install -r requirements.txt
35
+ ```
36
+ 3. Create a `.env` file with your Google API key:
37
+ ```
38
+ GOOGLE_API_KEY=your_api_key_here
39
+ ```
40
+ 4. Run the application:
41
+ ```bash
42
+ streamlit run app.py
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ 1. Enter patient information and clinical history
48
+ 2. Upload Pentacam scans (supported formats: PDF, PNG, JPG, JPEG)
49
+ 3. Choose between single timepoint analysis or comparison between timepoints
50
+ 4. Review the AI-powered analysis results
51
+
52
+ ## Note
53
+
54
+ This tool is designed to assist medical professionals in their analysis and decision-making process. It should not replace professional medical judgment.
app.py CHANGED
@@ -7,9 +7,9 @@ import PyPDF2
7
  import io
8
  from datetime import datetime
9
 
10
- # Page configuration must be the first Streamlit command
11
  st.set_page_config(
12
- page_title="OCT Retina Analysis Assistant",
13
  page_icon="👁️",
14
  layout="wide",
15
  initial_sidebar_state="expanded"
@@ -30,147 +30,100 @@ st.markdown("""
30
  }
31
  .stButton>button {
32
  width: 100%;
33
- background-color: #FF4B4B;
34
  color: white;
35
  padding: 0.5rem;
36
  margin-top: 1rem;
37
  }
38
  .credit-box {
39
  background-color: #f0f2f6;
40
- padding: 1rem;
41
  border-radius: 0.5rem;
42
  margin: 1rem 0;
 
43
  }
44
  .header-box {
45
- background-color: #FF4B4B;
46
  padding: 2rem;
47
  border-radius: 0.5rem;
48
  color: white;
49
  margin-bottom: 2rem;
50
  text-align: center;
 
51
  }
52
  .image-container {
53
  margin: 1rem 0;
54
  padding: 1rem;
55
  border-radius: 0.5rem;
56
- background-color: #f0f2f6;
 
57
  }
58
  .analysis-container {
59
  margin-top: 1rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  padding: 1rem;
61
  border-radius: 0.5rem;
62
- background-color: #f0f2f6;
 
63
  }
64
  </style>
65
  """, unsafe_allow_html=True)
66
 
67
  # System prompts
68
- SINGLE_TIMEPOINT_PROMPT = """You are an expert ophthalmologist specializing in interpreting macular Optical Coherence Tomography (OCT) scans. Your goal is to provide an accurate description and a possible diagnosis, supported by clear medical reasoning. These scans are from the same patient at a single timepoint. Please provide a comprehensive analysis.
69
-
70
- Step 1: Image Quality Assessment
71
- For each scan, describe the overall image quality, noting any artifacts or limitations that may affect your analysis.
72
-
73
- Step 2: Layer-by-Layer Analysis Across All Scans
74
- Analyze each of the retinal layers across all provided scans, describing:
75
- • Thickness patterns: Note any variations or consistencies in layer thickness
76
- • Morphological changes: Compare layer appearance across scans
77
- • Reflectivity patterns: Identify any recurring patterns or changes
78
- • Document abnormalities and their distribution across scans
79
-
80
- Step 3: Comprehensive Foveal Analysis
81
- Analyze the foveal region across all scans:
82
- • Compare foveal contour and thickness
83
- • Note any consistent or varying abnormalities
84
- • Identify patterns of foveal involvement
85
-
86
- Step 4: Integrated Abnormality Assessment
87
- Provide a unified analysis of abnormalities across all scans:
88
- • Distribution patterns
89
- • Progression or variation in appearance
90
- • Relationship between findings in different scans
91
-
92
- Step 5: Differential Diagnoses
93
- Based on the comprehensive analysis:
94
- • List potential diagnoses supported by findings across multiple scans
95
- • Explain how the pattern of findings supports each diagnosis
96
- • Note any temporal or spatial progression that helps narrow the diagnosis
97
-
98
- Step 6: Most Likely Diagnosis
99
- Provide a unified diagnosis considering all scans:
100
- • Explain how the combined findings support this diagnosis
101
- • Discuss any progression or pattern that confirms the diagnosis
102
- • Address any variations or inconsistencies
103
-
104
- Step 7: Recommendations
105
- Suggest:
106
- • Additional tests or imaging if needed
107
- • Follow-up scanning recommendations
108
- • Treatment considerations based on the comprehensive analysis"""
109
-
110
- COMPARISON_PROMPT = """You are an expert ophthalmologist specializing in interpreting macular Optical Coherence Tomography (OCT) scans. Your goal is to provide an accurate description and a possible diagnosis, supported by clear medical reasoning. These scans are from the same patient at two different timepoints. Please provide a comprehensive analysis and comparison.
111
 
112
- Step 1: Image Quality Assessment
113
- For each set of scans, describe the overall image quality, noting any artifacts or limitations that may affect your analysis.
 
 
 
114
 
115
- Step 2: Layer-by-Layer Comparison
116
- Compare the retinal layers between timepoints:
117
- Changes in thickness patterns
118
- Evolution of morphological features
119
- Alterations in reflectivity patterns
120
- Progression or regression of abnormalities
121
 
122
- Step 3: Foveal Evolution Analysis
123
- Compare the foveal region between timepoints:
124
- • Changes in contour and thickness
125
- • Evolution of abnormalities
126
- • Progression or improvement patterns
127
 
128
- Step 4: Disease Progression Assessment
129
- Analyze changes between timepoints:
130
- • Quantify and describe changes in abnormalities
131
- • Identify new or resolved findings
132
- • Assess overall disease progression or improvement
133
 
134
- Step 5: Treatment Response Evaluation
135
- If treatment was administered:
136
- Evaluate effectiveness
137
- Identify areas of improvement
138
- Note resistant or worsening areas
139
 
140
- Step 6: Updated Diagnosis and Prognosis
141
- Based on the temporal comparison:
142
- Confirm or revise previous diagnosis
143
- Assess disease trajectory
144
- • Provide prognostic insights
145
 
146
- Step 7: Recommendations
147
- Suggest:
148
- Treatment modifications if needed
149
- Follow-up interval
150
- • Additional testing if required
151
- • Preventive measures"""
152
-
153
- TREATMENT_GUIDELINES_PROMPT = """Based on the current diagnosis and findings, please provide evidence-based treatment recommendations following established ophthalmological guidelines. Consider:
154
-
155
- 1. Standard of Care
156
- • First-line treatments
157
- • Alternative options
158
- • Contraindications
159
-
160
- 2. Treatment Plan
161
- • Immediate interventions
162
- • Long-term management
163
- • Follow-up schedule
164
-
165
- 3. Monitoring Parameters
166
- • Key metrics to track
167
- • Warning signs
168
- • Success indicators
169
-
170
- 4. Patient Education
171
- • Lifestyle modifications
172
- • Self-monitoring instructions
173
- • Prevention strategies"""
174
 
175
  def extract_pdf_text(pdf_file):
176
  """Extract text from uploaded PDF file"""
@@ -180,45 +133,39 @@ def extract_pdf_text(pdf_file):
180
  text += page.extract_text()
181
  return text
182
 
183
- def analyze_oct_images(images, timepoint=None, patient_data=None):
184
- """Analyze OCT images with optional timepoint and patient data"""
185
  if timepoint:
186
- prompt = f"{SINGLE_TIMEPOINT_PROMPT}\n\nTimepoint: {timepoint}\n"
187
  else:
188
- prompt = f"{SINGLE_TIMEPOINT_PROMPT}\n"
189
 
190
  if patient_data:
191
  prompt += f"\nPatient Information:\n{patient_data}\n"
192
 
193
- prompt += "\nPlease analyze these OCT scans:"
194
  content = [prompt] + images
195
  response = model.generate_content(content)
196
  return response.text
197
 
198
- def compare_oct_timepoints(images1, date1, images2, date2, patient_data=None):
199
- """Compare OCT images from two timepoints"""
200
  prompt = f"{COMPARISON_PROMPT}\n\nTimepoint 1: {date1}\nTimepoint 2: {date2}\n"
201
 
202
  if patient_data:
203
  prompt += f"\nPatient Information:\n{patient_data}\n"
204
 
205
- prompt += "\nPlease compare these OCT scans:"
206
  content = [prompt] + images1 + images2
207
  response = model.generate_content(content)
208
  return response.text
209
 
210
- def get_treatment_recommendations(diagnosis, findings):
211
- """Get treatment recommendations based on guidelines"""
212
- prompt = f"{TREATMENT_GUIDELINES_PROMPT}\n\nDiagnosis: {diagnosis}\nFindings: {findings}"
213
- response = model.generate_content(prompt)
214
- return response.text
215
-
216
  def main():
217
- # Header with custom styling
218
  st.markdown("""
219
  <div class="header-box">
220
- <h1>OCT Retina Analysis Assistant</h1>
221
-
222
  </div>
223
  """, unsafe_allow_html=True)
224
 
@@ -226,9 +173,10 @@ def main():
226
  st.markdown("""
227
  <div class="credit-box">
228
  <h3>About</h3>
229
- <p>Developed by Dr. Fernando Ly</p>
230
- <p>This tool assists in the analysis of OCT retina scans using advanced AI technology.
231
- It provides detailed layer analysis and potential diagnoses to support clinical decision-making.</p>
 
232
  <p><strong>Note:</strong> This tool is for assistance only and should not replace professional medical judgment.</p>
233
  </div>
234
  """, unsafe_allow_html=True)
@@ -237,153 +185,109 @@ def main():
237
  col1, col2 = st.columns([1, 1])
238
 
239
  with col1:
240
- # Patient Data Section
241
  st.markdown("### Patient Information")
242
- patient_pdf = st.file_uploader("Upload Patient Data (PDF)", type=['pdf'])
243
- patient_data = None
244
- if patient_pdf:
245
- patient_data = extract_pdf_text(patient_pdf)
246
- with st.expander("View Patient Data"):
247
- st.text(patient_data)
248
-
249
- # Scan Upload Section
250
- st.markdown("### Upload OCT Scans")
251
- timepoint_option = st.radio(
252
- "Select scan type:",
253
- ["Single Timepoint", "Two Timepoints for Comparison"]
254
- )
 
 
 
 
 
 
 
 
 
 
 
255
 
256
- if timepoint_option == "Single Timepoint":
257
- uploaded_files = st.file_uploader(
258
- "Choose OCT scans",
259
- type=['png', 'jpg', 'jpeg'],
260
- accept_multiple_files=True,
261
- key="single_timepoint"
262
- )
263
 
264
  if uploaded_files:
265
- scan_date = st.date_input("Scan Date")
266
- st.markdown("### Uploaded Scans")
267
  images = []
268
- for idx, uploaded_file in enumerate(uploaded_files):
269
- with st.expander(f"OCT Scan {idx + 1}", expanded=True):
270
- image = Image.open(uploaded_file)
271
  images.append(image)
272
- st.image(image, use_container_width=True, caption=f"OCT Scan {idx + 1}")
 
 
273
 
274
- if st.button("🔍 Analyze Scans"):
275
- with st.spinner("Analyzing OCT scans... Please wait."):
276
- try:
277
- analysis = analyze_oct_images(images, scan_date, patient_data)
278
- treatment_recs = get_treatment_recommendations(
279
- "Based on the analysis above",
280
- "See detailed findings above"
 
 
 
 
 
 
281
  )
282
-
283
- with col2:
284
- st.markdown("### Analysis Results")
285
- st.markdown(f"""
286
- <div class="analysis-container">
287
- {analysis.replace(chr(10), '<br>')}
288
- </div>
289
- """, unsafe_allow_html=True)
290
-
291
- st.markdown("### Treatment Recommendations")
292
- st.markdown(f"""
293
- <div class="analysis-container">
294
- {treatment_recs.replace(chr(10), '<br>')}
295
- </div>
296
- """, unsafe_allow_html=True)
297
-
298
- except Exception as e:
299
- st.error(f"An error occurred during analysis: {str(e)}")
300
 
301
- else: # Two Timepoints
302
- st.markdown("#### First Timepoint")
303
- files1 = st.file_uploader(
304
- "Choose first set of OCT scans",
305
- type=['png', 'jpg', 'jpeg'],
306
- accept_multiple_files=True,
307
- key="timepoint1"
308
- )
309
- date1 = st.date_input("First Scan Date")
310
 
311
- st.markdown("#### Second Timepoint")
312
- files2 = st.file_uploader(
313
- "Choose second set of OCT scans",
314
- type=['png', 'jpg', 'jpeg'],
315
- accept_multiple_files=True,
316
- key="timepoint2"
317
- )
318
- date2 = st.date_input("Second Scan Date")
319
 
320
  if files1 and files2:
321
- st.markdown("### Uploaded Scans")
322
- images1 = []
323
- images2 = []
324
-
325
- st.markdown("#### First Timepoint Scans")
326
- for idx, uploaded_file in enumerate(files1):
327
- with st.expander(f"OCT Scan {idx + 1} - First Timepoint", expanded=False):
328
- image = Image.open(uploaded_file)
329
- images1.append(image)
330
- st.image(image, use_container_width=True)
331
-
332
- st.markdown("#### Second Timepoint Scans")
333
- for idx, uploaded_file in enumerate(files2):
334
- with st.expander(f"OCT Scan {idx + 1} - Second Timepoint", expanded=False):
335
- image = Image.open(uploaded_file)
336
- images2.append(image)
337
- st.image(image, use_container_width=True)
338
 
339
- if st.button("🔍 Compare Timepoints"):
340
- with st.spinner("Analyzing and comparing OCT scans... Please wait."):
341
- try:
342
- comparison = compare_oct_timepoints(
343
- images1, date1,
344
- images2, date2,
345
- patient_data
 
 
 
 
 
 
 
 
 
 
 
 
346
  )
347
- treatment_recs = get_treatment_recommendations(
348
- "Based on the comparison above",
349
- "See detailed findings above"
350
- )
351
-
352
- with col2:
353
- st.markdown("### Comparison Results")
354
- st.markdown(f"""
355
- <div class="analysis-container">
356
- {comparison.replace(chr(10), '<br>')}
357
- </div>
358
- """, unsafe_allow_html=True)
359
-
360
- st.markdown("### Treatment Recommendations")
361
- st.markdown(f"""
362
- <div class="analysis-container">
363
- {treatment_recs.replace(chr(10), '<br>')}
364
- </div>
365
- """, unsafe_allow_html=True)
366
-
367
- except Exception as e:
368
- st.error(f"An error occurred during analysis: {str(e)}")
369
-
370
- # Instructions in col2 if no files uploaded
371
- if not (patient_pdf or (timepoint_option == "Single Timepoint" and uploaded_files) or
372
- (timepoint_option == "Two Timepoints for Comparison" and files1 and files2)):
373
- with col2:
374
- st.markdown("### Instructions")
375
- st.markdown("""
376
- 1. Upload patient data PDF (optional)
377
- 2. Choose analysis type (single timepoint or comparison)
378
- 3. Upload OCT scans for selected timepoint(s)
379
- 4. Set scan dates
380
- 5. Click analyze/compare button
381
- 6. Review analysis and treatment recommendations
382
-
383
- Supported formats:
384
- - Patient Data: PDF
385
- - OCT Scans: PNG, JPG, JPEG
386
- """)
387
 
388
  if __name__ == "__main__":
389
  main()
 
7
  import io
8
  from datetime import datetime
9
 
10
+ # Page configuration
11
  st.set_page_config(
12
+ page_title="Cornea AI Pentacam Analyzer",
13
  page_icon="👁️",
14
  layout="wide",
15
  initial_sidebar_state="expanded"
 
30
  }
31
  .stButton>button {
32
  width: 100%;
33
+ background-color: #2E86C1;
34
  color: white;
35
  padding: 0.5rem;
36
  margin-top: 1rem;
37
  }
38
  .credit-box {
39
  background-color: #f0f2f6;
40
+ padding: 1.5rem;
41
  border-radius: 0.5rem;
42
  margin: 1rem 0;
43
+ border-left: 5px solid #2E86C1;
44
  }
45
  .header-box {
46
+ background: linear-gradient(135deg, #2E86C1, #3498DB);
47
  padding: 2rem;
48
  border-radius: 0.5rem;
49
  color: white;
50
  margin-bottom: 2rem;
51
  text-align: center;
52
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
53
  }
54
  .image-container {
55
  margin: 1rem 0;
56
  padding: 1rem;
57
  border-radius: 0.5rem;
58
+ background-color: #f8f9fa;
59
+ border: 1px solid #e9ecef;
60
  }
61
  .analysis-container {
62
  margin-top: 1rem;
63
+ padding: 1.5rem;
64
+ border-radius: 0.5rem;
65
+ background-color: #f8f9fa;
66
+ border: 1px solid #e9ecef;
67
+ }
68
+ .patient-info {
69
+ background-color: #fff;
70
+ padding: 1.5rem;
71
+ border-radius: 0.5rem;
72
+ border: 1px solid #e9ecef;
73
+ margin-bottom: 1rem;
74
+ }
75
+ .upload-section {
76
+ background-color: #f8f9fa;
77
+ padding: 1.5rem;
78
+ border-radius: 0.5rem;
79
+ border: 1px dashed #2E86C1;
80
+ margin: 1rem 0;
81
+ }
82
+ .info-box {
83
+ background-color: #e1f5fe;
84
  padding: 1rem;
85
  border-radius: 0.5rem;
86
+ margin: 0.5rem 0;
87
+ border-left: 3px solid #03a9f4;
88
  }
89
  </style>
90
  """, unsafe_allow_html=True)
91
 
92
  # System prompts
93
+ CORNEA_ANALYSIS_PROMPT = """You are an expert ophthalmologist specializing in corneal diseases. A user will ask you questions about interpreting corneal imaging, specifically Pentacam, and about subclinical corneal edema.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ **Part 1: Pentacam Interpretation**
96
+ Analyze Pentacam imaging for diagnosing and monitoring corneal diseases
97
+ • Assess key parameters: corneal shape, thickness, and elevation
98
+ • Evaluate anterior and posterior corneal surfaces
99
+ • Consider ABCD staging system and Cruces University Hospital progression score
100
 
101
+ **Part 2: Subclinical Corneal Edema Analysis**
102
+ Evaluate for Fuchs Endothelial Corneal Dystrophy (FECD)
103
+ Apply Sun criteria for subclinical corneal edema
104
+ Assess displacement of thinnest point
105
+ Check for loss of parallel isopachs
106
+ Evaluate focal depression of posterior surface
107
 
108
+ Please analyze the provided images and provide a detailed assessment."""
 
 
 
 
109
 
110
+ COMPARISON_PROMPT = """Compare the provided Pentacam scans from different timepoints, focusing on:
 
 
 
 
111
 
112
+ 1. Changes in corneal parameters:
113
+ Thickness variations
114
+ Topographic changes
115
+ Elevation differences
116
+ Progression indicators
117
 
118
+ 2. Clinical significance:
119
+ Disease progression/stability
120
+ Treatment response
121
+ Risk assessment
 
122
 
123
+ 3. Recommendations:
124
+ • Follow-up interval
125
+ Treatment modifications
126
+ Additional testing needs"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  def extract_pdf_text(pdf_file):
129
  """Extract text from uploaded PDF file"""
 
133
  text += page.extract_text()
134
  return text
135
 
136
+ def analyze_cornea_images(images, timepoint=None, patient_data=None):
137
+ """Analyze corneal images with optional timepoint and patient data"""
138
  if timepoint:
139
+ prompt = f"{CORNEA_ANALYSIS_PROMPT}\n\nTimepoint: {timepoint}\n"
140
  else:
141
+ prompt = f"{CORNEA_ANALYSIS_PROMPT}\n"
142
 
143
  if patient_data:
144
  prompt += f"\nPatient Information:\n{patient_data}\n"
145
 
146
+ prompt += "\nPlease analyze these corneal scans:"
147
  content = [prompt] + images
148
  response = model.generate_content(content)
149
  return response.text
150
 
151
+ def compare_timepoints(images1, date1, images2, date2, patient_data=None):
152
+ """Compare corneal images from two timepoints"""
153
  prompt = f"{COMPARISON_PROMPT}\n\nTimepoint 1: {date1}\nTimepoint 2: {date2}\n"
154
 
155
  if patient_data:
156
  prompt += f"\nPatient Information:\n{patient_data}\n"
157
 
158
+ prompt += "\nPlease compare these corneal scans:"
159
  content = [prompt] + images1 + images2
160
  response = model.generate_content(content)
161
  return response.text
162
 
 
 
 
 
 
 
163
  def main():
164
+ # Header
165
  st.markdown("""
166
  <div class="header-box">
167
+ <h1>Cornea AI Pentacam Analyzer</h1>
168
+ <p style="font-size: 1.2em; margin-top: 1rem;">Advanced Corneal Analysis & Diagnostics</p>
169
  </div>
170
  """, unsafe_allow_html=True)
171
 
 
173
  st.markdown("""
174
  <div class="credit-box">
175
  <h3>About</h3>
176
+ <p>Developed by Dr. Verónica Gómez Calleja</p>
177
+ <p>Cornea Specialist</p>
178
+ <p>This advanced tool assists in the analysis of Pentacam scans and corneal conditions using state-of-the-art AI technology.
179
+ It provides comprehensive analysis of corneal parameters and supports clinical decision-making in keratoconus, FECD, and other corneal conditions.</p>
180
  <p><strong>Note:</strong> This tool is for assistance only and should not replace professional medical judgment.</p>
181
  </div>
182
  """, unsafe_allow_html=True)
 
185
  col1, col2 = st.columns([1, 1])
186
 
187
  with col1:
188
+ # Patient Information Section
189
  st.markdown("### Patient Information")
190
+ with st.container():
191
+ st.markdown('<div class="patient-info">', unsafe_allow_html=True)
192
+ patient_name = st.text_input("Patient Name")
193
+ patient_id = st.text_input("Patient ID")
194
+ dob = st.date_input("Date of Birth")
195
+ diagnosis = st.text_input("Previous Diagnosis (if any)")
196
+
197
+ # Clinical History
198
+ st.markdown("#### Clinical History")
199
+ history_text = st.text_area("Enter relevant clinical history")
200
+
201
+ # Multiple PDF uploads for patient records
202
+ st.markdown("#### Additional Patient Records (PDF)")
203
+ patient_pdfs = st.file_uploader("Upload Patient Records", type=['pdf'], accept_multiple_files=True)
204
+ if patient_pdfs:
205
+ for pdf in patient_pdfs:
206
+ with st.expander(f"View {pdf.name}"):
207
+ st.text(extract_pdf_text(pdf))
208
+ st.markdown('</div>', unsafe_allow_html=True)
209
+
210
+ # Pentacam Scan Upload Section
211
+ st.markdown("### Upload Pentacam Scans")
212
+ st.markdown('<div class="upload-section">', unsafe_allow_html=True)
213
+ scan_type = st.radio("Select Analysis Type", ["Single Timepoint", "Compare Timepoints"])
214
 
215
+ if scan_type == "Single Timepoint":
216
+ scan_date = st.date_input("Scan Date")
217
+ uploaded_files = st.file_uploader("Upload Pentacam Scans", type=['png', 'jpg', 'jpeg', 'pdf'], accept_multiple_files=True)
 
 
 
 
218
 
219
  if uploaded_files:
 
 
220
  images = []
221
+ for file in uploaded_files:
222
+ if file.type.startswith('image'):
223
+ image = Image.open(file)
224
  images.append(image)
225
+ elif file.type == 'application/pdf':
226
+ # Handle PDF files here if needed
227
+ st.warning(f"PDF processing for {file.name} will be implemented soon")
228
 
229
+ if images:
230
+ st.markdown("#### Preview Uploaded Scans")
231
+ cols = st.columns(len(images))
232
+ for idx, (col, img) in enumerate(zip(cols, images)):
233
+ with col:
234
+ st.image(img, caption=f"Scan {idx + 1}", use_column_width=True)
235
+
236
+ if st.button("Analyze Scans"):
237
+ with st.spinner("Analyzing..."):
238
+ analysis = analyze_cornea_images(
239
+ images,
240
+ timepoint=scan_date.strftime("%Y-%m-%d"),
241
+ patient_data=f"Name: {patient_name}\nID: {patient_id}\nDOB: {str(dob)}\nDiagnosis: {diagnosis}\nHistory: {history_text}"
242
  )
243
+ st.markdown("### Analysis Results")
244
+ st.markdown('<div class="analysis-container">', unsafe_allow_html=True)
245
+ st.markdown(analysis)
246
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
+ else: # Compare Timepoints
249
+ col1, col2 = st.columns(2)
250
+
251
+ with col1:
252
+ st.markdown("#### First Timepoint")
253
+ date1 = st.date_input("Date of First Scan")
254
+ files1 = st.file_uploader("Upload First Scans", type=['png', 'jpg', 'jpeg', 'pdf'], accept_multiple_files=True)
 
 
255
 
256
+ with col2:
257
+ st.markdown("#### Second Timepoint")
258
+ date2 = st.date_input("Date of Second Scan")
259
+ files2 = st.file_uploader("Upload Second Scans", type=['png', 'jpg', 'jpeg', 'pdf'], accept_multiple_files=True)
 
 
 
 
260
 
261
  if files1 and files2:
262
+ images1 = [Image.open(f) for f in files1 if f.type.startswith('image')]
263
+ images2 = [Image.open(f) for f in files2 if f.type.startswith('image')]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
+ if images1 and images2:
266
+ st.markdown("#### Preview First Timepoint")
267
+ cols1 = st.columns(len(images1))
268
+ for idx, (col, img) in enumerate(zip(cols1, images1)):
269
+ with col:
270
+ st.image(img, caption=f"Scan {idx + 1}", use_column_width=True)
271
+
272
+ st.markdown("#### Preview Second Timepoint")
273
+ cols2 = st.columns(len(images2))
274
+ for idx, (col, img) in enumerate(zip(cols2, images2)):
275
+ with col:
276
+ st.image(img, caption=f"Scan {idx + 1}", use_column_width=True)
277
+
278
+ if st.button("Compare Scans"):
279
+ with st.spinner("Analyzing..."):
280
+ comparison = compare_timepoints(
281
+ images1, date1.strftime("%Y-%m-%d"),
282
+ images2, date2.strftime("%Y-%m-%d"),
283
+ patient_data=f"Name: {patient_name}\nID: {patient_id}\nDOB: {str(dob)}\nDiagnosis: {diagnosis}\nHistory: {history_text}"
284
  )
285
+ st.markdown("### Comparison Results")
286
+ st.markdown('<div class="analysis-container">', unsafe_allow_html=True)
287
+ st.markdown(comparison)
288
+ st.markdown('</div>', unsafe_allow_html=True)
289
+
290
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
  if __name__ == "__main__":
293
  main()
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
- streamlit==1.32.0
2
- google-generativeai==0.3.2
3
- Pillow==10.2.0
4
- python-dotenv==1.0.1
5
- PyPDF2==3.0.1
 
1
+ streamlit>=1.31.0
2
+ google-generativeai>=0.3.2
3
+ Pillow>=10.2.0
4
+ python-dotenv>=1.0.0
5
+ PyPDF2>=3.0.0