Spaces:
Sleeping
Sleeping
import streamlit as st | |
import google.generativeai as genai | |
# from google import genai | |
from PIL import Image | |
import os | |
from typing import Tuple, Optional | |
import logging | |
# Configure logging | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
class MRIScanAnalyzer: | |
def __init__(self, api_key: str): | |
"""Initialize the MRI Scan Analyzer with API key and configuration.""" | |
self.client = genai.Client(api_key=api_key) | |
self.setup_page_config() | |
self.apply_custom_styles() | |
def setup_page_config() -> None: | |
"""Configure Streamlit page settings.""" | |
st.set_page_config( | |
page_title="MRI Scan Analytics", | |
page_icon="π§ ", | |
layout="wide" | |
) | |
def apply_custom_styles() -> None: | |
"""Apply custom CSS styles with improved dark theme.""" | |
st.markdown(""" | |
<style> | |
:root { | |
--background-color: #1a1a1a; | |
--secondary-bg: #2d2d2d; | |
--text-color: #e0e0e0; | |
--accent-color: #4CAF50; | |
--border-color: #404040; | |
--hover-color: #45a049; | |
} | |
.main { background-color: var(--background-color); } | |
.stApp { background-color: var(--background-color); } | |
.stButton>button { | |
width: 100%; | |
background-color: var(--accent-color); | |
color: white; | |
padding: 0.75rem; | |
border-radius: 6px; | |
border: none; | |
font-weight: 600; | |
transition: background-color 0.3s ease; | |
} | |
.stButton>button:hover { | |
background-color: var(--hover-color); | |
} | |
.report-container { | |
background-color: var(--secondary-bg); | |
padding: 2rem; | |
border-radius: 12px; | |
margin: 1rem 0; | |
border: 1px solid var(--border-color); | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
def analyze_image(self, img: Image.Image) -> Tuple[Optional[str], Optional[str]]: | |
""" | |
Analyze MRI scan image using Gemini AI. | |
Returns a tuple of (doctor_analysis, patient_analysis). | |
""" | |
try: | |
prompts = { | |
"doctor": """ | |
Provide a structured analysis of this MRI scan for medical professionals without including any introductory or acknowledgment phrases. | |
Follow the structure below: | |
1. Imaging Observations | |
- Describe key anatomical structures, signal intensities, and any contrast differences | |
2. Diagnostic Findings | |
- Identify abnormalities and potential areas of concern | |
3. Clinical Correlation | |
- Suggest possible differential diagnoses and recommendations for further evaluation | |
4. Technical Quality | |
- Comment on image quality, positioning, and any artifacts present | |
""", | |
"patient": """ | |
Explain the findings of this MRI scan in clear, simple terms for a patient without including any introductory or acknowledgment phrases. | |
Follow the structure below: | |
1. What We See | |
- Describe the part of the body shown and any notable features in everyday language | |
2. What It Means | |
- Provide a simple explanation of the findings and their potential implications | |
3. Next Steps | |
- Outline any recommendations or follow-up actions in a patient-friendly manner | |
""" | |
} | |
responses = {} | |
for audience, prompt in prompts.items(): | |
response = self.client.models.generate_content( | |
model="gemini-2.0-flash", | |
contents=[prompt, img] | |
) | |
responses[audience] = response.text if hasattr(response, 'text') else None | |
return responses["doctor"], responses["patient"] | |
except Exception as e: | |
logger.error(f"Analysis failed: {str(e)}") | |
return None, None | |
def run(self): | |
"""Run the Streamlit MRI scan analysis application.""" | |
st.title("π§ MRI Scan Analytics") | |
st.markdown(""" | |
Advanced MRI scan analysis powered by AI. Upload your scan for instant | |
insights tailored for both medical professionals and patients. | |
""") | |
col1, col2 = st.columns([1, 1.5]) | |
with col1: | |
uploaded_file = self.handle_file_upload() | |
with col2: | |
if uploaded_file: | |
self.process_analysis(uploaded_file) | |
else: | |
self.show_instructions() | |
self.show_footer() | |
def handle_file_upload(self) -> Optional[object]: | |
"""Handle file upload and display image preview.""" | |
uploaded_file = st.file_uploader( | |
"Upload MRI Scan Image", | |
type=["png", "jpg", "jpeg"], | |
help="Supported formats: PNG, JPG, JPEG" | |
) | |
if uploaded_file: | |
img = Image.open(uploaded_file) | |
st.image(img, caption="Uploaded MRI Scan", use_container_width =True) | |
with st.expander("Image Details"): | |
st.write(f"**Filename:** {uploaded_file.name}") | |
st.write(f"**Size:** {uploaded_file.size/1024:.2f} KB") | |
st.write(f"**Format:** {img.format}") | |
st.write(f"**Dimensions:** {img.size[0]}x{img.size[1]} pixels") | |
return uploaded_file | |
def process_analysis(self, uploaded_file: object) -> None: | |
"""Process the uploaded MRI image and display analysis.""" | |
if st.button("π Analyze MRI Scan", key="analyze_button"): | |
with st.spinner("Analyzing MRI scan..."): | |
img = Image.open(uploaded_file) | |
doctor_analysis, patient_analysis = self.analyze_image(img) | |
if doctor_analysis and patient_analysis: | |
tab1, tab2 = st.tabs(["π Medical Report", "π₯ Patient Summary"]) | |
with tab1: | |
st.markdown("### Medical Professional's Report") | |
st.markdown(f"<div class='report-container'>{doctor_analysis}</div>", | |
unsafe_allow_html=True) | |
with tab2: | |
st.markdown("### Patient-Friendly Explanation") | |
st.markdown(f"<div class='report-container'>{patient_analysis}</div>", | |
unsafe_allow_html=True) | |
else: | |
st.error("Analysis failed. Please try again.") | |
def show_instructions() -> None: | |
"""Display instructions when no image is uploaded.""" | |
st.info("π Upload an MRI scan image to begin analysis") | |
with st.expander("βΉοΈ How it works"): | |
st.markdown(""" | |
1. **Upload** your MRI scan image | |
2. Click **Analyze** | |
3. Receive two detailed reports: | |
- Technical analysis for medical professionals | |
- Patient-friendly explanation | |
""") | |
def show_footer() -> None: | |
"""Display the application footer.""" | |
st.markdown("---") | |
st.markdown( | |
""" | |
<div style='text-align: center'> | |
<p style='color: #888888; font-size: 0.8em;'> | |
UNDER DEVELOPMENT | |
</p> | |
</div> | |
""", | |
unsafe_allow_html=True | |
) | |
if __name__ == "__main__": | |
# Get API key from environment variable or set directly here | |
api_key = os.getenv("GEMINI_API_KEY") | |
if not api_key: | |
st.error("Please set GEMINI_API_KEY environment variable") | |
else: | |
analyzer = MRIScanAnalyzer(api_key) | |
analyzer.run() | |