rajsecrets0 commited on
Commit
5775ecb
·
verified ·
1 Parent(s): 1cb2498

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -0
app.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import json
4
+ from PIL import Image
5
+ import base64
6
+ from io import BytesIO
7
+ import pandas as pd
8
+ from datetime import datetime
9
+ import time
10
+ import logging
11
+ import os
12
+ from typing import Dict, Any, Optional
13
+ import re
14
+ from reportlab.lib import colors
15
+ from reportlab.lib.pagesizes import letter
16
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
17
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
18
+ import io
19
+ import pytesseract # Tesseract OCR
20
+ from dotenv import load_dotenv # For .env file
21
+
22
+ # Load environment variables
23
+ load_dotenv()
24
+
25
+ # Configure logging
26
+ logging.basicConfig(
27
+ level=logging.INFO,
28
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
29
+ )
30
+ logger = logging.getLogger(__name__)
31
+
32
+ # Configuration and Constants
33
+ class Config:
34
+ GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent"
35
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") # Load from .env
36
+ MAX_RETRIES = 3
37
+ TIMEOUT = 30
38
+ MAX_IMAGE_SIZE = (1600, 1600)
39
+ ALLOWED_MIME_TYPES = ["image/jpeg", "image/png"]
40
+ MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB
41
+
42
+ # Custom Exceptions
43
+ class APIError(Exception):
44
+ pass
45
+
46
+ class ImageProcessingError(Exception):
47
+ pass
48
+
49
+ # Initialize session state
50
+ def init_session_state():
51
+ if 'processing_history' not in st.session_state:
52
+ st.session_state.processing_history = []
53
+ if 'current_document' not in st.session_state:
54
+ st.session_state.current_document = None
55
+ if 'pdf_history' not in st.session_state:
56
+ st.session_state.pdf_history = []
57
+
58
+ # Page setup and styling
59
+ def setup_page():
60
+ st.set_page_config(
61
+ page_title="Medical Document Processor",
62
+ page_icon="🏥",
63
+ layout="wide",
64
+ initial_sidebar_state="expanded"
65
+ )
66
+
67
+ st.markdown("""
68
+ <style>
69
+ .main {padding: 2rem; max-width: 1200px; margin: 0 auto;}
70
+ .stCard {
71
+ background-color: white;
72
+ padding: 2rem;
73
+ border-radius: 10px;
74
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
75
+ margin: 1rem 0;
76
+ }
77
+ .header-container {
78
+ background-color: #f8f9fa;
79
+ padding: 2rem;
80
+ border-radius: 10px;
81
+ margin-bottom: 2rem;
82
+ }
83
+ .stButton>button {
84
+ background-color: #007bff;
85
+ color: white;
86
+ border: none;
87
+ padding: 0.5rem 1rem;
88
+ border-radius: 5px;
89
+ transition: all 0.3s ease;
90
+ }
91
+ .stButton>button:hover {
92
+ background-color: #0056b3;
93
+ transform: translateY(-2px);
94
+ }
95
+ .element-container {opacity: 1 !important;}
96
+ .pdf-history-item {
97
+ background-color: #f8f9fa;
98
+ padding: 1rem;
99
+ border-radius: 8px;
100
+ margin: 0.5rem 0;
101
+ border: 1px solid #dee2e6;
102
+ }
103
+ .metric-card {
104
+ background-color: #f8f9fa;
105
+ padding: 1rem;
106
+ border-radius: 8px;
107
+ border: 1px solid #dee2e6;
108
+ margin: 0.5rem 0;
109
+ }
110
+ </style>
111
+ """, unsafe_allow_html=True)
112
+
113
+ # Rest of the code remains the same as in the previous version...
114
+ # (Include all classes and functions from the previous code here)
115
+
116
+ def main():
117
+ init_session_state()
118
+ setup_page()
119
+
120
+ st.title("🏥 Advanced Medical Document Processor")
121
+ st.markdown("Upload medical documents for automated processing and analysis.")
122
+
123
+ # Sidebar
124
+ with st.sidebar:
125
+ st.header("📋 Processing History")
126
+ if st.session_state.pdf_history:
127
+ for idx, pdf_record in enumerate(st.session_state.pdf_history):
128
+ with st.expander(f"Document {idx + 1}: {pdf_record['timestamp']}"):
129
+ st.download_button(
130
+ "📄 Download PDF",
131
+ pdf_record['data'],
132
+ file_name=pdf_record['filename'],
133
+ mime="application/pdf",
134
+ key=f"sidebar_{pdf_record['timestamp']}"
135
+ )
136
+ else:
137
+ st.info("No documents processed yet")
138
+
139
+ # Main content
140
+ uploaded_file = st.file_uploader(
141
+ "Choose a medical document",
142
+ type=['png', 'jpg', 'jpeg'],
143
+ help="Upload a clear image of a medical document (max 5MB)"
144
+ )
145
+
146
+ if uploaded_file:
147
+ try:
148
+ # Validate image
149
+ is_valid, message = ImageProcessor.validate_image(uploaded_file)
150
+ if not is_valid:
151
+ st.error(message)
152
+ return
153
+
154
+ # Display image
155
+ image = Image.open(uploaded_file)
156
+ col1, col2 = st.columns([1, 2])
157
+
158
+ with col1:
159
+ st.image(image, caption="Uploaded Document", use_column_width=True)
160
+
161
+ # Process document
162
+ if st.button("🔍 Process Document"):
163
+ with st.spinner("Processing document..."):
164
+ processor = DocumentProcessor()
165
+ results = processor.process_document(image)
166
+
167
+ # Generate PDF
168
+ pdf_bytes = PDFGenerator.create_pdf(results['structured_data'])
169
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
170
+ pdf_filename = f"medical_report_{timestamp}.pdf"
171
+
172
+ # Store in session state
173
+ st.session_state.current_document = {
174
+ 'timestamp': timestamp,
175
+ 'results': results
176
+ }
177
+ st.session_state.processing_history.append(
178
+ st.session_state.current_document
179
+ )
180
+ st.session_state.pdf_history.append({
181
+ 'timestamp': timestamp,
182
+ 'filename': pdf_filename,
183
+ 'data': pdf_bytes
184
+ })
185
+
186
+ # Display results
187
+ with col2:
188
+ st.success("Document processed successfully!")
189
+ st.markdown(f"**Document Type:** {results['document_type']}")
190
+
191
+ with st.expander("View Extracted Text"):
192
+ st.text_area(
193
+ "Raw Text",
194
+ results['extracted_text'],
195
+ height=200
196
+ )
197
+
198
+ # Display EHR View
199
+ if results['structured_data']:
200
+ EHRViewer.display_ehr(results['structured_data'])
201
+
202
+ # Download options
203
+ st.markdown("### 📥 Download Options")
204
+ col1, col2 = st.columns(2)
205
+
206
+ with col1:
207
+ json_str = json.dumps(results['structured_data'], indent=2)
208
+ st.download_button(
209
+ "⬇️ Download JSON",
210
+ json_str,
211
+ file_name=f"medical_data_{timestamp}.json",
212
+ mime="application/json"
213
+ )
214
+
215
+ with col2:
216
+ st.download_button(
217
+ "📄 Download PDF Report",
218
+ pdf_bytes,
219
+ file_name=pdf_filename,
220
+ mime="application/pdf"
221
+ )
222
+
223
+ # Display PDF History
224
+ st.markdown("### 📚 PDF History")
225
+ if st.session_state.pdf_history:
226
+ for pdf_record in st.session_state.pdf_history:
227
+ col1, col2 = st.columns([3, 1])
228
+ with col1:
229
+ st.write(f"Report from {pdf_record['timestamp']}")
230
+ with col2:
231
+ st.download_button(
232
+ "📄 View PDF",
233
+ pdf_record['data'],
234
+ file_name=pdf_record['filename'],
235
+ mime="application/pdf",
236
+ key=f"history_{pdf_record['timestamp']}"
237
+ )
238
+ else:
239
+ st.info("No PDF history available")
240
+
241
+ except Exception as e:
242
+ st.error(f"An error occurred: {str(e)}")
243
+ logger.exception("Error in main processing loop")
244
+
245
+ if __name__ == "__main__":
246
+ try:
247
+ main()
248
+ except Exception as e:
249
+ st.error("An unexpected error occurred. Please try again later.")
250
+ logger.exception("Unhandled exception in main application")