SURESHBEEKHANI commited on
Commit
667850f
Β·
verified Β·
1 Parent(s): 8c95034

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +271 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from PIL import Image
3
+ import os
4
+ import base64
5
+ import io
6
+ from dotenv import load_dotenv
7
+ from groq import Groq
8
+ from reportlab.lib.pagesizes import letter
9
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
10
+ from reportlab.lib.styles import getSampleStyleSheet
11
+
12
+ # ======================
13
+ # CONFIGURATION SETTINGS
14
+ # ======================
15
+ PAGE_CONFIG = {
16
+ "page_title": "Radiology Analyzer",
17
+ "page_icon": "🩺",
18
+ "layout": "wide",
19
+ "initial_sidebar_state": "expanded"
20
+ }
21
+
22
+ ALLOWED_FILE_TYPES = ['png', 'jpg', 'jpeg']
23
+
24
+ CSS_STYLES = """
25
+ <style>
26
+ .main { background-color: #f4f9f9; color: #000000; }
27
+ .sidebar .sidebar-content { background-color: #d1e7dd; }
28
+ .stTextInput textarea { color: #000000 !important; }
29
+ .stSelectbox div[data-baseweb="select"],
30
+ .stSelectbox option,
31
+ .stSelectbox div[role="listbox"] div {
32
+ color: black !important;
33
+ background-color: #d1e7dd !important;
34
+ }
35
+ .stSelectbox svg { fill: black !important; }
36
+ .main-title {
37
+ font-size: 88px;
38
+ font-weight: bold;
39
+ color: rgb(33, 238, 238);
40
+ }
41
+ .sub-title {
42
+ font-size: 100px;
43
+ color: #6B6B6B;
44
+ margin-top: -1px;
45
+ }
46
+ .stButton>button {
47
+ background-color: rgb(33, 225, 250);
48
+ color: white;
49
+ font-size: 69px;
50
+ }
51
+ .stImage img {
52
+ border-radius: 10px;
53
+ box-shadow: 2px 2px 10px rgba(0,0,0,0.1);
54
+ }
55
+ .logo {
56
+ text-align: center;
57
+ margin-bottom: 20px;
58
+ }
59
+ .report-container {
60
+ background-color: #ffffff;
61
+ border-radius: 15px;
62
+ padding: 25px;
63
+ margin-top: 20px;
64
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
65
+ border-left: 5px solid #21eeef;
66
+ }
67
+ .report-text {
68
+ font-family: 'Courier New', monospace;
69
+ font-size: 16px;
70
+ line-height: 1.6;
71
+ color: #2c3e50;
72
+ }
73
+ .download-btn {
74
+ background-color: #21eeef !important;
75
+ color: white !important;
76
+ border: none !important;
77
+ border-radius: 8px !important;
78
+ padding: 12px 24px !important;
79
+ }
80
+ </style>
81
+ """
82
+
83
+ # ======================
84
+ # CORE FUNCTIONS
85
+ # ======================
86
+ def configure_application():
87
+ """Initialize application settings and styling"""
88
+ st.set_page_config(**PAGE_CONFIG)
89
+ st.markdown(CSS_STYLES, unsafe_allow_html=True)
90
+
91
+ def initialize_api_client():
92
+ """Create and validate Groq API client"""
93
+ load_dotenv()
94
+ api_key = os.getenv("GROQ_API_KEY")
95
+
96
+ if not api_key:
97
+ st.error("API key not found. Please verify .env configuration.")
98
+ st.stop()
99
+
100
+ return Groq(api_key=api_key)
101
+
102
+ def encode_logo(image_path):
103
+ """Encode logo image to base64"""
104
+ try:
105
+ with open(image_path, "rb") as img_file:
106
+ return base64.b64encode(img_file.read()).decode("utf-8")
107
+ except FileNotFoundError:
108
+ st.error("Logo image not found! Using placeholder.")
109
+ return ""
110
+
111
+ def process_image_data(uploaded_file):
112
+ """Convert image to base64 encoded string"""
113
+ try:
114
+ image = Image.open(uploaded_file)
115
+ buffer = io.BytesIO()
116
+ image.save(buffer, format=image.format)
117
+ return base64.b64encode(buffer.getvalue()).decode('utf-8'), image.format
118
+ except Exception as e:
119
+ st.error(f"Image processing error: {str(e)}")
120
+ return None, None
121
+
122
+ def generate_pdf_report(report_text):
123
+ """Generate PDF document from report text"""
124
+ buffer = io.BytesIO()
125
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
126
+ styles = getSampleStyleSheet()
127
+ story = []
128
+
129
+ # Add title
130
+ title = Paragraph("<b>Radiology Report</b>", styles['Title'])
131
+ story.append(title)
132
+ story.append(Spacer(1, 12))
133
+
134
+ # Add report content
135
+ content = Paragraph(report_text.replace('\n', '<br/>'), styles['BodyText'])
136
+ story.append(content)
137
+
138
+ doc.build(story)
139
+ buffer.seek(0)
140
+ return buffer
141
+
142
+ def generate_radiology_report(uploaded_file, client):
143
+ """Generate AI-powered radiology analysis"""
144
+ base64_image, img_format = process_image_data(uploaded_file)
145
+
146
+ if not base64_image:
147
+ return None
148
+
149
+ image_url = f"data:image/{img_format.lower()};base64,{base64_image}"
150
+
151
+ try:
152
+ response = client.chat.completions.create(
153
+ model="llama-3.2-11b-vision-preview",
154
+ messages=[{
155
+ "role": "user",
156
+ "content": [
157
+ {"type": "text", "text": (
158
+ "As an AI radiologist, provide a detailed structured report including: "
159
+ "1. Imaging modality identification\n2. Anatomical structures visualized\n"
160
+ "3. Abnormal findings description\n4. Differential diagnoses\n"
161
+ "5. Clinical correlation recommendations"
162
+ )},
163
+ {"type": "image_url", "image_url": {"url": image_url}},
164
+ ]
165
+ }],
166
+ temperature=0.2,
167
+ max_tokens=400,
168
+ top_p=0.5
169
+ )
170
+ return response.choices[0].message.content
171
+ except Exception as e:
172
+ st.error(f"API communication error: {str(e)}")
173
+ return None
174
+
175
+ # ======================
176
+ # UI COMPONENTS
177
+ # ======================
178
+ def display_main_interface():
179
+ """Render primary application interface"""
180
+ # Encode logo image
181
+ logo_b64 = encode_logo("src/radiology.png")
182
+
183
+ # Center the logo and title using HTML and CSS
184
+ st.markdown(
185
+ f"""
186
+ <div style="text-align: center;">
187
+ <div class="logo">
188
+ <img src="data:image/png;base64,{logo_b64}" width="100">
189
+ </div>
190
+ <p class="main-title"> Radiology Analyzer</p>
191
+ <p class="sub-title">Advanced Medical Imaging Analysis</p>
192
+ </div>
193
+ """,
194
+ unsafe_allow_html=True
195
+ )
196
+
197
+ st.markdown("---")
198
+
199
+ # Action buttons
200
+ col1, col2 = st.columns([1, 1])
201
+ with col1:
202
+ if st.session_state.get('analysis_result'):
203
+ pdf_report = generate_pdf_report(st.session_state.analysis_result)
204
+ st.download_button(
205
+ label="πŸ“„ Download PDF Report",
206
+ data=pdf_report,
207
+ file_name="radiology_report.pdf",
208
+ mime="application/pdf",
209
+ use_container_width=True,
210
+ help="Download formal PDF version of the report",
211
+ key="download_pdf"
212
+ )
213
+
214
+ with col2:
215
+ if st.button("Clear Analysis πŸ—‘οΈ", use_container_width=True, help="Remove current results"):
216
+ st.session_state.pop('analysis_result')
217
+ st.rerun()
218
+
219
+ # Display analysis results
220
+ if st.session_state.get('analysis_result'):
221
+ st.markdown("### 🎯 Radiological Findings Report")
222
+ st.markdown(
223
+ f'<div class="report-container"><div class="report-text">{st.session_state.analysis_result}</div></div>',
224
+ unsafe_allow_html=True
225
+ )
226
+
227
+ def render_sidebar(client):
228
+ """Create sidebar interface elements"""
229
+ with st.sidebar:
230
+ st.divider()
231
+ st.markdown("### Diagnostic Capabilities")
232
+ st.markdown("""
233
+ - **Multi-Modality Analysis**: X-ray, MRI, CT, Ultrasound
234
+ - **Pathology Detection**: Fractures, tumors, infections
235
+ - **Comparative Analysis**: Track disease progression
236
+ - **Structured Reporting**: Standardized output format
237
+ - **Clinical Correlation**: Suggested next steps
238
+ """)
239
+ st.divider()
240
+
241
+ st.subheader("Image Upload Section")
242
+ uploaded_file = st.file_uploader(
243
+ "Select Medical Image",
244
+ type=ALLOWED_FILE_TYPES,
245
+ help="Supported formats: PNG, JPG, JPEG"
246
+ )
247
+
248
+ if uploaded_file:
249
+ st.image(Image.open(uploaded_file),
250
+ caption="Uploaded Medical Image",
251
+ use_container_width=True)
252
+
253
+ if st.button("Initiate Analysis πŸ”", use_container_width=True):
254
+ with st.spinner("Analyzing image. This may take 20-30 seconds..."):
255
+ report = generate_radiology_report(uploaded_file, client)
256
+ st.session_state.analysis_result = report
257
+ st.rerun()
258
+
259
+ # ======================
260
+ # APPLICATION ENTRYPOINT
261
+ # ======================
262
+ def main():
263
+ """Primary application controller"""
264
+ configure_application()
265
+ groq_client = initialize_api_client()
266
+
267
+ display_main_interface()
268
+ render_sidebar(groq_client)
269
+
270
+ if __name__ == "__main__":
271
+ main()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ groq
3
+ Pillow
4
+ python-dotenv
5
+ reportlab