ECG / app.py
sikeaditya's picture
Update app.py
674c814 verified
import os
import logging
from flask import Flask, request, render_template, redirect, flash, url_for
from werkzeug.utils import secure_filename
import PyPDF2
from PIL import Image
import io
import base64
import google.generativeai as genai
import pytesseract
import markdown
app = Flask(__name__)
app.secret_key = 'your_secret_key_here'
logging.basicConfig(level=logging.DEBUG)
# Configure upload settings
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'pdf', 'jpg', 'jpeg', 'png'}
MAX_FILE_SIZE = 20 * 1024 * 1024 # 20MB max file size
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE
# Configure Gemini API
GEMINI_MODEL = "gemini-2.0-flash" # Updated to use the correct model name
genai.configure(api_key="AIzaSyArihOGcyK5KcQR4ntIqNga6bSoq7kM7Yo")
# Ensure the upload folder exists
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def setup_gemini():
"""Initialize Gemini API with error handling"""
try:
genai.configure(api_key="AIzaSyArihOGcyK5KcQR4ntIqNga6bSoq7kM7Yo")
return True
except Exception as e:
logging.error(f"Failed to configure Gemini API: {str(e)}")
return False
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def extract_images_from_pdf(pdf_path):
"""Extract images from PDF file and convert to base64"""
images_data = []
try:
with open(pdf_path, "rb") as pdf_file:
pdf_reader = PyPDF2.PdfReader(pdf_file)
for page in pdf_reader.pages:
if hasattr(page, 'images'):
for image_file_object in page.images:
try:
image = Image.open(io.BytesIO(image_file_object.data))
buffered = io.BytesIO()
image.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode()
images_data.append(img_str)
except Exception as e:
logging.warning(f"Failed to process image: {str(e)}")
except Exception as e:
logging.error(f"Error extracting images: {str(e)}")
return images_data
def extract_text_from_image(image_path):
"""Extract text from image using OCR"""
try:
image = Image.open(image_path)
text = pytesseract.image_to_string(image)
return text
except Exception as e:
logging.error(f"Error extracting text from image: {str(e)}")
return ""
def get_scan_type(text):
"""Determine the type of scan from the text content"""
text_lower = text.lower()
scan_types = {
'electrocardiogram': 'ECG'
}
for key, value in scan_types.items():
if key in text_lower:
return value
return 'Unknown Scan Type'
def analyze_medical_scan(scan_type, combined_text, image_count):
"""Generate analysis """
try:
logging.debug(f"Initializing Gemini model with type: {GEMINI_MODEL}")
model = genai.GenerativeModel(GEMINI_MODEL)
prompt = f"""
As a professional medical imaging specialist, analyze this {scan_type} report.
Please provide a clear analysis of the following points:
1. Key findings and observations
2. Any significant abnormalities or concerns
3. Technical quality of the scan
4. Recommendations for follow-up (if any)
Report details:
- Number of images: {image_count}
- Text content: {combined_text}
Note any limitations if image quality or content is unclear.
"""
logging.debug("Sending request to Gemini API")
response = model.generate_content(prompt)
logging.debug("Received response from Gemini API")
if not response or not hasattr(response, 'text'):
raise ValueError("Invalid response from Gemini API")
return response.text
except Exception as e:
logging.error(f"Error generating analysis: {str(e)}")
raise
@app.route('/', methods=['GET', 'POST'])
def index():
if not setup_gemini():
flash('Failed to initialize AI service. Please try again later.', 'error')
return render_template("index.html", result=None)
result = None
if request.method == 'POST':
logging.debug("Received a POST request.")
# Check if the post request has the file part
if 'file' not in request.files:
logging.debug("No file part in request")
flash('No file selected', 'error')
return redirect(request.url)
file = request.files['file']
# If user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
logging.debug("No selected file")
flash('No file selected', 'error')
return redirect(request.url)
# Check file size
if request.content_length > MAX_FILE_SIZE:
logging.debug("File too large")
flash(f'File size exceeds {MAX_FILE_SIZE // (1024 * 1024)}MB limit', 'error')
return redirect(request.url)
if file and allowed_file(file.filename):
file_path = None
try:
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
logging.debug(f"Saving file to: {file_path}")
file.save(file_path)
# Process text and images
combined_text = ""
if filename.lower().endswith('.pdf'):
logging.debug("Processing PDF file")
with open(file_path, "rb") as pdf_file:
pdf_reader = PyPDF2.PdfReader(pdf_file)
for page_num, page in enumerate(pdf_reader.pages):
page_text = page.extract_text()
if page_text:
combined_text += page_text
logging.debug(f"Extracted text from page {page_num}")
images_data = extract_images_from_pdf(file_path)
else: # Image file
logging.debug("Processing image file")
combined_text = extract_text_from_image(file_path)
with open(file_path, "rb") as img_file:
img_data = base64.b64encode(img_file.read()).decode()
images_data = [img_data]
logging.debug(f"Extracted text length: {len(combined_text)}")
scan_type = get_scan_type(combined_text)
image_count = len(images_data)
logging.debug(f"Detected scan type: {scan_type}, Image count: {image_count}")
# Generate analysis
logging.debug("Generating analysis")
analysis_text = analyze_medical_scan(scan_type, combined_text, image_count)
analysis_html = markdown.markdown(analysis_text)
result = {
'analysis': analysis_text,
'analysis_html': analysis_html,
'scan_type': scan_type,
'image_count': image_count,
'images': images_data
}
logging.debug("Analysis complete")
except Exception as e:
logging.exception("Error processing file:")
flash(f"Error processing file: {str(e)}", 'error')
return redirect(request.url)
finally:
# Clean up uploaded file
if file_path and os.path.exists(file_path):
os.remove(file_path)
logging.debug("Temporary file removed after processing.")
else:
logging.debug("Invalid file type")
flash('Only PDF and image files are allowed', 'error')
return redirect(request.url)
return render_template("index.html", result=result)
if __name__ == '__main__':
app.run(debug=True)