|
|
|
import os |
|
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' |
|
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' |
|
|
|
|
|
import gradio as gr |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
from datetime import datetime |
|
import json |
|
from PIL import Image |
|
from typing import Dict, List, Tuple, Optional |
|
import warnings |
|
warnings.filterwarnings('ignore') |
|
|
|
|
|
try: |
|
import librosa |
|
import librosa.display |
|
LIBROSA_AVAILABLE = True |
|
print("β
Librosa loaded successfully") |
|
except ImportError: |
|
print("β οΈ Warning: librosa not available. Audio processing will be limited.") |
|
LIBROSA_AVAILABLE = False |
|
|
|
try: |
|
import tensorflow as tf |
|
|
|
tf.get_logger().setLevel('ERROR') |
|
TF_AVAILABLE = True |
|
print("β
TensorFlow loaded successfully") |
|
except ImportError: |
|
print("β οΈ Warning: TensorFlow not available. Using mock predictions.") |
|
TF_AVAILABLE = False |
|
|
|
try: |
|
import google.generativeai as genai |
|
GEMINI_AVAILABLE = True |
|
print("β
Google Generative AI loaded successfully") |
|
except ImportError: |
|
print("β οΈ Warning: google-generativeai not available. AI features will be limited.") |
|
GEMINI_AVAILABLE = False |
|
|
|
|
|
if GEMINI_AVAILABLE and os.getenv("GOOGLE_API_KEY"): |
|
try: |
|
genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) |
|
gemini_model = genai.GenerativeModel('gemini-2.0-flash') |
|
except Exception as e: |
|
print(f"Warning: Failed to initialize Gemini: {e}") |
|
GEMINI_AVAILABLE = False |
|
gemini_model = None |
|
else: |
|
gemini_model = None |
|
|
|
|
|
def load_heartbeat_model(): |
|
if not TF_AVAILABLE: |
|
print("π TensorFlow not available - using mock predictions") |
|
return None |
|
|
|
try: |
|
model = tf.keras.models.load_model('Heart_ResNet.h5') |
|
print("π― Heart_ResNet.h5 model loaded successfully") |
|
return model |
|
except Exception as e: |
|
print(f"π Could not load Heart_ResNet.h5 model: {e}") |
|
print("π Using mock predictions instead") |
|
return None |
|
|
|
|
|
heartbeat_model = None |
|
|
|
def get_heartbeat_model(): |
|
"""Get or load the heartbeat model (lazy loading)""" |
|
global heartbeat_model |
|
if heartbeat_model is None: |
|
heartbeat_model = load_heartbeat_model() |
|
return heartbeat_model |
|
|
|
|
|
patient_data = {} |
|
|
|
def process_audio(file_path: str) -> Tuple[np.ndarray, np.ndarray, int]: |
|
"""Process audio file and extract MFCC features.""" |
|
if not LIBROSA_AVAILABLE: |
|
print("Librosa not available - cannot process audio") |
|
return None, None, None |
|
|
|
SAMPLE_RATE = 22050 |
|
DURATION = 10 |
|
input_length = int(SAMPLE_RATE * DURATION) |
|
|
|
try: |
|
X, sr = librosa.load(file_path, sr=SAMPLE_RATE, duration=DURATION) |
|
|
|
if len(X) < input_length: |
|
pad_width = input_length - len(X) |
|
X = np.pad(X, (0, pad_width), mode='constant') |
|
|
|
mfccs = np.mean(librosa.feature.mfcc(y=X, sr=sr, n_mfcc=52, |
|
n_fft=512, hop_length=256).T, axis=0) |
|
return mfccs, X, sr |
|
except Exception as e: |
|
print(f"Error processing audio: {e}") |
|
return None, None, None |
|
|
|
def analyze_heartbeat(audio_file) -> Tuple[str, str]: |
|
"""Analyze heartbeat audio and return results with visualization.""" |
|
if audio_file is None: |
|
return "No audio file provided", None |
|
|
|
if not LIBROSA_AVAILABLE: |
|
return "Audio processing not available (librosa not installed)", None |
|
|
|
try: |
|
mfccs, waveform, sr = process_audio(audio_file) |
|
if mfccs is None: |
|
return "Error processing audio file", None |
|
|
|
|
|
model = get_heartbeat_model() |
|
|
|
if model is not None and TF_AVAILABLE: |
|
features = mfccs.reshape(1, 52, 1) |
|
preds = model.predict(features, verbose=0) |
|
class_names = ["artifact", "murmur", "normal"] |
|
|
|
results = {name: round(float(preds[0][i]) * 100, 1) for i, name in enumerate(class_names)} |
|
else: |
|
|
|
import random |
|
random.seed(42) |
|
results = { |
|
"artifact": round(random.uniform(0.5, 2.5), 1), |
|
"murmur": round(random.uniform(1.5, 3.5), 1), |
|
"normal": round(random.uniform(94.0, 98.0), 1) |
|
} |
|
|
|
total = sum(results.values()) |
|
if total != 100.0: |
|
|
|
max_key = max(results, key=results.get) |
|
results[max_key] = round(results[max_key] + (100.0 - total), 1) |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 4)) |
|
if LIBROSA_AVAILABLE: |
|
librosa.display.waveshow(waveform, sr=sr, ax=ax) |
|
else: |
|
|
|
time_axis = np.linspace(0, len(waveform)/sr, len(waveform)) |
|
ax.plot(time_axis, waveform) |
|
|
|
ax.set_title("Heartbeat Waveform Analysis", fontsize=14, fontweight='bold') |
|
ax.set_xlabel("Time (seconds)") |
|
ax.set_ylabel("Amplitude") |
|
ax.grid(True, alpha=0.3) |
|
plt.tight_layout() |
|
|
|
|
|
plot_path = f"temp_waveform_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png" |
|
plt.savefig(plot_path, dpi=150, bbox_inches='tight') |
|
plt.close() |
|
|
|
|
|
max_class = max(results, key=results.get) |
|
confidence = results[max_class] |
|
|
|
|
|
status = "Model-based analysis" if model else "Demo mode (model not loaded)" |
|
|
|
if max_class == "normal" and confidence >= 90.0: |
|
interpretation = "β
Normal heartbeat detected" |
|
elif max_class == "murmur" and confidence >= 70.0: |
|
interpretation = "β οΈ Heart murmur detected - recommend medical evaluation" |
|
elif max_class == "artifact" and confidence >= 50.0: |
|
interpretation = "π Audio artifact detected - consider re-recording" |
|
else: |
|
interpretation = "β Inconclusive result - recommend professional evaluation" |
|
|
|
|
|
results_text = f"""π©Ί HEART SOUNDS ANALYSIS RESULTS |
|
{'='*45} |
|
|
|
π Classification Probabilities: |
|
β’ Normal Heartbeat: {results['normal']}% |
|
β’ Heart Murmur: {results['murmur']}% |
|
β’ Audio Artifact: {results['artifact']}% |
|
|
|
π― Primary Classification: {max_class.upper()} ({confidence}%) |
|
π Interpretation: {interpretation} |
|
|
|
π Analysis Status: {status} |
|
π Audio Duration: {len(waveform)/sr:.1f} seconds |
|
π Sample Rate: {sr} Hz |
|
|
|
β οΈ Note: This analysis is for educational purposes only. |
|
Always consult a qualified healthcare professional.""" |
|
|
|
return results_text, plot_path |
|
|
|
except Exception as e: |
|
return f"Error analyzing heartbeat: {str(e)}", None |
|
|
|
def analyze_medical_image(image) -> str: |
|
"""Analyze medical images using Gemini Vision.""" |
|
if image is None: |
|
return "No image provided" |
|
|
|
if not GEMINI_AVAILABLE or gemini_model is None: |
|
return """π¬ MEDICAL IMAGE ANALYSIS |
|
{'='*40} |
|
|
|
β οΈ AI Analysis Not Available |
|
Gemini AI is not configured or installed. |
|
|
|
π MOCK ANALYSIS REPORT: |
|
ββββββββββββββββββββββββββββββββββββββββ |
|
|
|
π₯ Investigation Type: Medical Image/Scan |
|
π Image Quality: Acceptable for review |
|
π General Findings: Image appears to show medical investigation |
|
|
|
π RECOMMENDATIONS: |
|
β’ Ensure proper medical interpretation by qualified radiologist |
|
β’ Correlate findings with clinical presentation |
|
β’ Consider additional imaging if clinically indicated |
|
β’ Follow institutional protocols for image review |
|
|
|
β οΈ IMPORTANT: This is a demonstration mode. |
|
To enable full AI analysis: |
|
1. Install: pip install google-generativeai |
|
2. Set environment variable: GOOGLE_API_KEY |
|
3. Restart the application |
|
|
|
π©Ί Always consult qualified healthcare professionals for medical interpretation.""" |
|
|
|
try: |
|
|
|
if not isinstance(image, Image.Image): |
|
image = Image.fromarray(image) |
|
|
|
prompt = """ |
|
As a medical AI assistant, analyze this medical image/investigation result. Please provide a structured report with: |
|
|
|
1. IMAGE TYPE & QUALITY: |
|
- Type of investigation/scan |
|
- Image quality assessment |
|
|
|
2. TECHNICAL PARAMETERS: |
|
- Visible technical details |
|
- Imaging modality characteristics |
|
|
|
3. ANATOMICAL STRUCTURES: |
|
- Clearly visible structures |
|
- Anatomical landmarks |
|
|
|
4. FINDINGS: |
|
- Normal findings |
|
- Any abnormalities or areas of concern |
|
- Measurements if applicable |
|
|
|
5. CLINICAL CORRELATION: |
|
- Significance of findings |
|
- Recommendations for follow-up |
|
|
|
6. LIMITATIONS: |
|
- Any limitations of the study |
|
- Areas requiring further evaluation |
|
|
|
Please format your response professionally and remember this is for educational purposes only. Emphasize that this should not replace professional medical diagnosis by qualified healthcare professionals. |
|
""" |
|
|
|
response = gemini_model.generate_content([prompt, image]) |
|
|
|
formatted_response = f"""π¬ AI MEDICAL IMAGE ANALYSIS |
|
{'='*45} |
|
|
|
{response.text} |
|
|
|
{'='*45} |
|
β οΈ DISCLAIMER: This AI analysis is for educational purposes only. |
|
Always consult qualified healthcare professionals for definitive diagnosis.""" |
|
|
|
return formatted_response |
|
|
|
except Exception as e: |
|
return f"π¨ Error analyzing image: {str(e)}\n\nPlease check your Gemini API configuration and try again." |
|
|
|
def generate_comprehensive_assessment(patient_info: Dict) -> str: |
|
"""Generate comprehensive medical assessment using Gemini AI.""" |
|
if not GEMINI_AVAILABLE or gemini_model is None: |
|
|
|
bmi_info = "" |
|
if patient_info.get('weight') and patient_info.get('height'): |
|
try: |
|
weight = float(patient_info.get('weight')) |
|
height = float(patient_info.get('height')) / 100 |
|
bmi = weight / (height * height) |
|
bmi_info = f"BMI: {bmi:.1f} kg/mΒ²" |
|
except: |
|
bmi_info = "BMI: Unable to calculate" |
|
|
|
return f"""# π₯ COMPREHENSIVE MEDICAL ASSESSMENT |
|
|
|
## π€ PATIENT DEMOGRAPHICS |
|
**Name:** {patient_info.get('name', 'Not provided')} |
|
**Age:** {patient_info.get('age', 'Not provided')} years |
|
**Sex:** {patient_info.get('sex', 'Not provided')} |
|
**Weight:** {patient_info.get('weight', 'Not provided')} kg |
|
**Height:** {patient_info.get('height', 'Not provided')} cm |
|
{bmi_info} |
|
|
|
--- |
|
|
|
## π©Ί CLINICAL PRESENTATION |
|
|
|
### Chief Complaint |
|
{patient_info.get('complaint', 'Not provided')} |
|
|
|
### Medical History |
|
{patient_info.get('medical_history', 'Not provided')} |
|
|
|
### Physical Examination |
|
{patient_info.get('examination', 'Not provided')} |
|
|
|
--- |
|
|
|
## π¬ DIAGNOSTIC RESULTS |
|
|
|
### Heart Sounds Analysis |
|
{patient_info.get('heartbeat_analysis', 'Not performed')} |
|
|
|
### Investigations |
|
{patient_info.get('investigation_analysis', 'Not provided')} |
|
|
|
--- |
|
|
|
## β οΈ SYSTEM STATUS |
|
**AI-powered comprehensive assessment not available.** |
|
Please install google-generativeai and configure GOOGLE_API_KEY for full AI features. |
|
|
|
--- |
|
|
|
## π BASIC RECOMMENDATIONS |
|
1. **Immediate:** Review all clinical findings with qualified healthcare professional |
|
2. **Assessment:** Correlate examination findings with investigation results |
|
3. **Follow-up:** Consider appropriate follow-up based on clinical presentation |
|
4. **Documentation:** Ensure proper documentation and patient safety protocols |
|
|
|
--- |
|
|
|
## π GENERAL NUTRITION GUIDELINES |
|
- **Hydration:** Maintain adequate fluid intake (8-10 glasses water/day) |
|
- **Balanced Diet:** Include fruits, vegetables, whole grains, lean proteins |
|
- **Heart Health:** Limit sodium, saturated fats, processed foods |
|
- **Portion Control:** Maintain healthy portion sizes based on BMI |
|
|
|
--- |
|
|
|
**β οΈ DISCLAIMER:** This assessment is for educational purposes only. Always consult qualified healthcare professionals for medical decisions.""" |
|
|
|
try: |
|
|
|
bmi_calculation = "" |
|
if patient_info.get('weight') and patient_info.get('height'): |
|
try: |
|
weight = float(patient_info.get('weight')) |
|
height = float(patient_info.get('height')) / 100 |
|
bmi = weight / (height * height) |
|
|
|
if bmi < 18.5: |
|
bmi_status = "Underweight" |
|
elif 18.5 <= bmi < 25: |
|
bmi_status = "Normal weight" |
|
elif 25 <= bmi < 30: |
|
bmi_status = "Overweight" |
|
else: |
|
bmi_status = "Obese" |
|
|
|
bmi_calculation = f"BMI: {bmi:.1f} kg/mΒ² ({bmi_status})" |
|
except: |
|
bmi_calculation = "BMI: Unable to calculate" |
|
|
|
|
|
prompt = f""" |
|
**As a comprehensive medical AI, provide a detailed professional medical assessment based on the following patient data** |
|
Format your response with clear headings and professional medical language: |
|
|
|
## PATIENT DEMOGRAPHICS: |
|
-**Name:** {patient_info.get('name', 'Not provided')} |
|
- **Age:** {patient_info.get('age', 'Not provided')} years |
|
- **Sex:** {patient_info.get('sex', 'Not provided')} |
|
- **Weight:** {patient_info.get('weight', 'Not provided')} kg |
|
- **Height:** {patient_info.get('height', 'Not provided')} cm |
|
- {bmi_calculation} |
|
|
|
## CHIEF COMPLAINT: |
|
{patient_info.get('complaint', 'Not provided')} |
|
|
|
## MEDICAL HISTORY: |
|
{patient_info.get('medical_history', 'Not provided')} |
|
|
|
## PHYSICAL EXAMINATION: |
|
{patient_info.get('examination', 'Not provided')} |
|
|
|
## HEART SOUNDS ANALYSIS: |
|
{patient_info.get('heartbeat_analysis', 'Not performed')} |
|
|
|
## INVESTIGATIONS: |
|
{patient_info.get('investigation_analysis', 'Not provided')} |
|
|
|
Please provide a comprehensive medical assessment with the following structure: |
|
|
|
1. **CLINICAL SUMMARY** - Concise overview of the case |
|
2. **DIFFERENTIAL DIAGNOSIS** - List possible conditions with rationale |
|
3. **RISK FACTORS ASSESSMENT** - Identify relevant risk factors |
|
4. **RECOMMENDED TREATMENT PLAN** - Detailed treatment approach |
|
5. **FOLLOW-UP RECOMMENDATIONS** - Specific follow-up plans |
|
6. **NUTRITIONAL MANAGEMENT PLAN** - summerized nutrition recommendations based on: |
|
- Patient's current condition |
|
- Age and sex-specific requirements |
|
- Weight management if needed |
|
- Heart health considerations |
|
- Specific dietary modifications for the condition |
|
- Meal planning suggestions |
|
- Hydration recommendations |
|
7. **PATIENT EDUCATION POINTS** - Key points for patient understanding |
|
8. **PROGNOSIS** - Expected outcomes and timeline |
|
|
|
Please use professional medical terminology and format with clear headings. |
|
Make the nutritional section comprehensive and specific to this patient's needs. |
|
Remember this is for educational purposes and emphasize the need for professional medical consultation. |
|
""" |
|
|
|
response = gemini_model.generate_content(prompt) |
|
|
|
|
|
formatted_response = f"""# π₯ COMPREHENSIVE MEDICAL ASSESSMENT |
|
|
|
## π€ PATIENT INFORMATION |
|
**Name:** {patient_info.get('name', 'Not provided')} |
|
**Age:** {patient_info.get('age', 'Not provided')} years |
|
**Sex:** {patient_info.get('sex', 'Not provided')} |
|
**Weight:** {patient_info.get('weight', 'Not provided')} kg |
|
**Height:** {patient_info.get('height', 'Not provided')} cm |
|
**{bmi_calculation}** |
|
|
|
--- |
|
|
|
{response.text} |
|
|
|
--- |
|
|
|
## β οΈ IMPORTANT DISCLAIMERS |
|
- **Educational Purpose:** This assessment is for educational purposes only |
|
- **Professional Consultation:** Always consult qualified healthcare professionals |
|
- **Emergency:** Seek immediate medical attention for urgent symptoms |
|
- **AI Limitations:** AI analysis supplements but does not replace clinical judgment |
|
|
|
--- |
|
|
|
**Generated on:** {datetime.now().strftime('%Y-%m-%d at %H:%M:%S')}""" |
|
|
|
return formatted_response |
|
|
|
except Exception as e: |
|
return f"# β Error Generating Assessment\n\n**Error Details:** {str(e)}\n\nPlease check your Gemini API configuration and try again." |
|
|
|
def save_patient_data(name, age, sex, weight, height, complaint, medical_history, |
|
examination, heartbeat_results, investigation_analysis): |
|
"""Save all patient data to global storage.""" |
|
global patient_data |
|
|
|
patient_data = { |
|
'name': name if name else 'Not provided', |
|
'age': age if age else 'Not provided', |
|
'sex': sex if sex else 'Not provided', |
|
'weight': weight if weight else 'Not provided', |
|
'height': height if height else 'Not provided', |
|
'complaint': complaint if complaint else 'Not provided', |
|
'medical_history': medical_history if medical_history else 'Not provided', |
|
'examination': examination if examination else 'Not provided', |
|
'heartbeat_analysis': heartbeat_results if heartbeat_results else 'Not performed', |
|
'investigation_analysis': investigation_analysis if investigation_analysis else 'Not provided', |
|
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S') |
|
} |
|
|
|
return "Patient data saved successfully!" |
|
|
|
def process_complete_consultation(name, age, sex, weight, height, complaint, |
|
medical_history, examination, audio_file, |
|
investigation_image): |
|
"""Process complete medical consultation.""" |
|
|
|
|
|
heartbeat_results = "" |
|
waveform_plot = None |
|
if audio_file is not None: |
|
heartbeat_analysis, plot_path = analyze_heartbeat(audio_file) |
|
heartbeat_results = heartbeat_analysis if heartbeat_analysis else "" |
|
waveform_plot = plot_path |
|
|
|
|
|
investigation_analysis = "" |
|
if investigation_image is not None: |
|
investigation_analysis = analyze_medical_image(investigation_image) |
|
|
|
|
|
patient_data_dict = { |
|
'name': name if name else 'Not provided', |
|
'age': age if age else 'Not provided', |
|
'sex': sex if sex else 'Not provided', |
|
'weight': weight if weight else 'Not provided', |
|
'height': height if height else 'Not provided', |
|
'complaint': complaint if complaint else 'Not provided', |
|
'medical_history': medical_history if medical_history else 'Not provided', |
|
'examination': examination if examination else 'Not provided', |
|
'heartbeat_analysis': heartbeat_results if heartbeat_results else 'Not performed', |
|
'investigation_analysis': investigation_analysis if investigation_analysis else 'Not provided' |
|
} |
|
|
|
|
|
global patient_data |
|
patient_data = patient_data_dict.copy() |
|
patient_data['timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') |
|
|
|
|
|
comprehensive_assessment = generate_comprehensive_assessment(patient_data_dict) |
|
|
|
return comprehensive_assessment, waveform_plot, heartbeat_results, investigation_analysis |
|
|
|
|
|
def create_interface(): |
|
with gr.Blocks( |
|
title="Comprehensive Medical Consultation System", |
|
theme=gr.themes.Soft(), |
|
css=""" |
|
.medical-assessment textarea { |
|
font-size: 16px !important; |
|
line-height: 1.6 !important; |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important; |
|
} |
|
.gradio-container { |
|
font-size: 14px; |
|
} |
|
.gr-textbox textarea { |
|
font-size: 14px !important; |
|
} |
|
h1, h2, h3 { |
|
color: #2c3e50 !important; |
|
} |
|
.medical-assessment .gr-textbox { |
|
background-color: #f8f9fa !important; |
|
} |
|
""" |
|
) as demo: |
|
|
|
gr.Markdown(""" |
|
# π₯ Comprehensive Medical Consultation System |
|
### Integrated AI-Powered Medical Assessment Platform |
|
""") |
|
|
|
with gr.Tab("π Patient Information"): |
|
gr.Markdown("## Patient Demographics") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
name = gr.Textbox(label="Full Name", placeholder="Enter patient's full name") |
|
age = gr.Number(label="Age (years)", minimum=0, maximum=120) |
|
sex = gr.Radio(["Male", "Female", "Other"], label="Sex") |
|
|
|
with gr.Column(): |
|
weight = gr.Number(label="Weight (kg)", minimum=0, maximum=300) |
|
height = gr.Number(label="Height (cm)", minimum=0, maximum=250) |
|
|
|
gr.Markdown("## Chief Complaint") |
|
complaint = gr.Textbox( |
|
label="Chief Complaint", |
|
placeholder="Describe the main symptoms or reason for consultation...", |
|
lines=3 |
|
) |
|
|
|
gr.Markdown("## Medical History") |
|
medical_history = gr.Textbox( |
|
label="Past Medical History", |
|
placeholder="Include previous illnesses, surgeries, medications, allergies, family history...", |
|
lines=5 |
|
) |
|
|
|
with gr.Tab("π©Ί Physical Examination"): |
|
gr.Markdown("## Physical Examination Findings") |
|
|
|
examination = gr.Textbox( |
|
label="Examination Findings", |
|
placeholder="General appearance, vital signs, systemic examination findings...", |
|
lines=6 |
|
) |
|
|
|
gr.Markdown("## Heart Sounds Analysis") |
|
audio_file = gr.Audio( |
|
label="Heart Sounds Recording", |
|
type="filepath", |
|
sources=["upload", "microphone"] |
|
) |
|
|
|
heartbeat_analyze_btn = gr.Button("π Analyze Heart Sounds", variant="secondary") |
|
heartbeat_results = gr.Textbox(label="Heart Sounds Analysis Results", lines=4) |
|
waveform_plot = gr.Image(label="Heart Sounds Waveform") |
|
|
|
heartbeat_analyze_btn.click( |
|
fn=analyze_heartbeat, |
|
inputs=[audio_file], |
|
outputs=[heartbeat_results, waveform_plot] |
|
) |
|
|
|
with gr.Tab("π¬ Investigations"): |
|
gr.Markdown("## Medical Investigations & Imaging") |
|
|
|
investigation_image = gr.Image( |
|
label="Upload Investigation Results (X-ray, ECG, Lab reports, etc.)", |
|
type="pil" |
|
) |
|
|
|
investigate_btn = gr.Button("π Analyze Investigation", variant="secondary") |
|
investigation_results = gr.Textbox( |
|
label="Investigation Analysis", |
|
lines=6, |
|
placeholder="AI analysis of uploaded investigation will appear here..." |
|
) |
|
|
|
investigate_btn.click( |
|
fn=analyze_medical_image, |
|
inputs=[investigation_image], |
|
outputs=[investigation_results] |
|
) |
|
|
|
with gr.Tab("π€ AI Assessment"): |
|
gr.Markdown("## Comprehensive Medical Assessment") |
|
|
|
generate_btn = gr.Button( |
|
"π§ Generate Comprehensive Assessment", |
|
variant="primary", |
|
size="lg" |
|
) |
|
|
|
assessment_output = gr.Textbox( |
|
label="AI-Generated Medical Assessment", |
|
lines=20, |
|
placeholder="Complete medical assessment will be generated here based on all provided information...", |
|
elem_classes=["medical-assessment"] |
|
) |
|
|
|
|
|
hidden_heartbeat = gr.Textbox(visible=False) |
|
hidden_investigation = gr.Textbox(visible=False) |
|
hidden_waveform = gr.Image(visible=False) |
|
|
|
generate_btn.click( |
|
fn=process_complete_consultation, |
|
inputs=[name, age, sex, weight, height, complaint, medical_history, |
|
examination, audio_file, investigation_image], |
|
outputs=[assessment_output, hidden_waveform, hidden_heartbeat, |
|
hidden_investigation] |
|
) |
|
|
|
with gr.Tab("π Patient Summary"): |
|
gr.Markdown("## Patient Data Summary") |
|
|
|
refresh_btn = gr.Button("π Refresh Patient Data", variant="secondary") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
summary_demographics = gr.JSON(label="Demographics") |
|
summary_clinical = gr.JSON(label="Clinical Data") |
|
|
|
with gr.Column(): |
|
summary_results = gr.JSON(label="Investigation Results") |
|
|
|
def refresh_patient_summary(): |
|
if patient_data: |
|
demographics = { |
|
"Name": patient_data.get('name', 'N/A'), |
|
"Age": patient_data.get('age', 'N/A'), |
|
"Sex": patient_data.get('sex', 'N/A'), |
|
"Weight": f"{patient_data.get('weight', 'N/A')} kg", |
|
"Height": f"{patient_data.get('height', 'N/A')} cm" |
|
} |
|
|
|
clinical = { |
|
"Chief Complaint": patient_data.get('complaint', 'N/A'), |
|
"Medical History": patient_data.get('medical_history', 'N/A')[:100] + "..." if len(patient_data.get('medical_history', '')) > 100 else patient_data.get('medical_history', 'N/A'), |
|
"Examination": patient_data.get('examination', 'N/A')[:100] + "..." if len(patient_data.get('examination', '')) > 100 else patient_data.get('examination', 'N/A') |
|
} |
|
|
|
results = { |
|
"Heartbeat Analysis": "Completed" if patient_data.get('heartbeat_analysis') else "Not performed", |
|
"Investigation Analysis": "Completed" if patient_data.get('investigation_analysis') else "Not performed", |
|
"Last Updated": patient_data.get('timestamp', 'N/A') |
|
} |
|
|
|
return demographics, clinical, results |
|
else: |
|
return {}, {}, {} |
|
|
|
refresh_btn.click( |
|
fn=refresh_patient_summary, |
|
outputs=[summary_demographics, summary_clinical, summary_results] |
|
) |
|
|
|
gr.Markdown(""" |
|
--- |
|
### π Important Notes: |
|
- This system is for educational and research purposes only |
|
- Always consult qualified healthcare professionals for medical decisions |
|
- Ensure patient privacy and data protection compliance |
|
- AI assessments should supplement, not replace, clinical judgment |
|
""") |
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
print("\nπ₯ MEDICAL CONSULTATION SYSTEM") |
|
print("=" * 50) |
|
|
|
|
|
print("π System Status Check:") |
|
print(f"β
Gradio: Available") |
|
print(f"{'β
' if LIBROSA_AVAILABLE else 'β οΈ'} Librosa: {'Available' if LIBROSA_AVAILABLE else 'Not installed'}") |
|
print(f"{'β
' if TF_AVAILABLE else 'β οΈ'} TensorFlow: {'Available' if TF_AVAILABLE else 'Not installed'}") |
|
print(f"{'β
' if GEMINI_AVAILABLE else 'β οΈ'} Gemini AI: {'Available' if GEMINI_AVAILABLE else 'Not installed'}") |
|
|
|
|
|
if GEMINI_AVAILABLE: |
|
if os.getenv("GOOGLE_API_KEY"): |
|
print("π Gemini API Key: Configured") |
|
else: |
|
print("β οΈ Gemini API Key: Not set (AI features limited)") |
|
print(" Set with: export GOOGLE_API_KEY='your_api_key_here'") |
|
|
|
print("\nπ Starting application...") |
|
print("π The app will be available at: http://localhost:7860") |
|
print("=" * 50) |
|
|
|
try: |
|
demo = create_interface() |
|
demo.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=True, |
|
debug=False, |
|
show_error=True |
|
) |
|
except Exception as e: |
|
print(f"β Error starting application: {e}") |
|
print("Please check the error message above and ensure all dependencies are installed correctly.") |