import os from flask import Flask, request, jsonify, render_template from flask_pymongo import PyMongo from flask_bcrypt import Bcrypt import secrets import google.generativeai as genai import markdown from PIL import Image import pytesseract # For OCR import fitz # PyMuPDF for reading PDFs import io # --- Basic Flask App Setup --- app = Flask(__name__) # --- Configurations --- app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') or secrets.token_hex(16) app.config['MONGO_URI'] = os.getenv('MONGODB_URI') or os.getenv('MONGO_URI') # --- Gemini API Configuration --- GOOGLE_API_KEY = os.getenv('GEMINI_API_KEY') or os.getenv('GOOGLE_API_KEY') try: if GOOGLE_API_KEY: genai.configure(api_key=GOOGLE_API_KEY) else: print("Warning: GEMINI_API_KEY/GOOGLE_API_KEY not set; analysis will fail until configured.") except Exception as e: print(f"Error configuring Gemini API: {e}\nPlease make sure the GEMINI_API_KEY or GOOGLE_API_KEY environment variable is set.") # --- Initialize Extensions --- mongo = PyMongo(app) bcrypt = Bcrypt(app) # --- User Model for Flask-Login --- # Authentication removed: no user model or login manager # --- Helper function for Gemini Analysis --- def get_simplified_report(report_text): """Sends text to Gemini and returns a simplified, markdown-formatted report.""" if not report_text or not report_text.strip(): raise ValueError("Extracted text is empty.") model = genai.GenerativeModel('gemini-2.0-flash') prompt = f""" You are an expert medical assistant. Your task is to translate the following medical report into simple, clear, and easy-to-understand language for a patient with no medical background. Instructions: 1. Start with a one-sentence summary of the main finding. 2. Create a "Key Findings" section using bullet points. 3. For each technical term or measurement, first state the term from the report, then explain what it means in simple words and whether the result is normal, high, or low. 4. Maintain a reassuring and professional tone. 5. Conclude with a clear disclaimer: "This is a simplified summary and not a substitute for professional medical advice. Please discuss the full report with your doctor." 6. Format the entire output in Markdown. Medical Report to Analyze: --- {report_text} --- """ response = model.generate_content(prompt) return markdown.markdown(response.text) # --- Authentication routes removed; app is public --- # --- Main Application Routes --- @app.route('/') def index(): # Publicly accessible page return render_template('report_analyzer.html') @app.route('/analyze_report_text', methods=['POST']) def analyze_report_text(): """Analyzes a report submitted as plain text.""" try: data = request.get_json() report_text = data.get('report_text') if not report_text or not report_text.strip(): return jsonify({'error': 'Report text cannot be empty.'}), 400 html_response = get_simplified_report(report_text) return jsonify({'simplified_report': html_response}) except Exception as e: print(f"Error during text report analysis: {e}") return jsonify({'error': 'An internal error occurred during report analysis.'}), 500 @app.route('/analyze_report_file', methods=['POST']) def analyze_report_file(): """Analyzes a report submitted as a PDF or Image file.""" try: if 'report_file' not in request.files: return jsonify({'error': 'No file part in the request.'}), 400 file = request.files['report_file'] if file.filename == '': return jsonify({'error': 'No file selected.'}), 400 report_text = "" # Check file extension if file.filename.lower().endswith('.pdf'): pdf_document = fitz.open(stream=file.read(), filetype="pdf") for page in pdf_document: report_text += page.get_text() pdf_document.close() elif file.filename.lower().endswith(('.png', '.jpg', '.jpeg')): image = Image.open(file.stream) report_text = pytesseract.image_to_string(image) else: return jsonify({'error': 'Unsupported file type. Please upload a PDF or an image.'}), 400 html_response = get_simplified_report(report_text) return jsonify({'simplified_report': html_response}) except Exception as e: print(f"Error during file report analysis: {e}") return jsonify({'error': 'An internal error occurred during file analysis.'}), 500 # --- Run the Application --- if __name__ == '__main__': app.run(port=5001, debug=True)