Spaces:
Sleeping
Sleeping
update
Browse files- .gitignore +3 -0
- app.py +16 -67
- config.py +58 -0
- interface.py +145 -0
- model_utils.py +79 -0
- requirements.txt +5 -1
- styles.py +80 -0
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
venv
|
| 2 |
+
**/__pycache__
|
| 3 |
+
.gradio
|
app.py
CHANGED
|
@@ -1,71 +1,20 @@
|
|
| 1 |
-
import
|
| 2 |
-
|
| 3 |
-
import shap
|
| 4 |
-
import pandas as pd
|
| 5 |
-
import numpy as np
|
| 6 |
-
import matplotlib.pyplot as plt
|
| 7 |
-
import io
|
| 8 |
-
import base64
|
| 9 |
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
model =
|
| 13 |
-
|
| 14 |
-
# Example features - replace with actual features your model uses
|
| 15 |
-
feature_names = ["Age",
|
| 16 |
-
"weight",
|
| 17 |
-
"height",
|
| 18 |
-
"BMI",
|
| 19 |
-
"gravidity",
|
| 20 |
-
"parity",
|
| 21 |
-
"H.Abortion",
|
| 22 |
-
"living.Child",
|
| 23 |
-
"Gestational.Age",
|
| 24 |
-
"Hemoglobin",
|
| 25 |
-
"hematocrit",
|
| 26 |
-
"platelet",
|
| 27 |
-
"MPV.mean.platelet.volume",
|
| 28 |
-
"PDW.platelet.distribution.width",
|
| 29 |
-
"neutrophil",
|
| 30 |
-
"lymphocyte",
|
| 31 |
-
"NLR.neutrophil.to.lymphocyte",
|
| 32 |
-
"PLR.platelet.to.lymphocyte.ratio"
|
| 33 |
-
]
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
def predict_and_explain(*inputs):
|
| 38 |
-
# Create a DataFrame for the input
|
| 39 |
-
input_data = pd.DataFrame([inputs], columns=feature_names)
|
| 40 |
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
shap_html = shap.plots.force(shap_values[0], matplotlib=False)
|
| 52 |
-
return f"Risk Prediction: {'High' if prediction else 'Low'}", shap_html
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
# Build the Gradio interface
|
| 56 |
-
input_components = [gr.Number(label=feat) for feat in feature_names]
|
| 57 |
-
output_components = [
|
| 58 |
-
gr.Textbox(label="Prediction"),
|
| 59 |
-
gr.HTML(label="Feature Importance")
|
| 60 |
-
]
|
| 61 |
-
|
| 62 |
-
demo = gr.Interface(
|
| 63 |
-
fn=predict_and_explain,
|
| 64 |
-
inputs=input_components,
|
| 65 |
-
outputs=output_components,
|
| 66 |
-
title="Pregnancy Risk Analyzer",
|
| 67 |
-
description="Enter patient data to analyze pregnancy risk and see important features using SHAP"
|
| 68 |
-
)
|
| 69 |
|
| 70 |
if __name__ == "__main__":
|
| 71 |
-
|
|
|
|
| 1 |
+
from interface import create_interface
|
| 2 |
+
from model_utils import load_model
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
+
def main():
|
| 5 |
+
print("Loading model...")
|
| 6 |
+
model = load_model()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
+
if model is None:
|
| 9 |
+
print("Warning: Model could not be loaded. Please ensure 'best_model.pkl' exists.")
|
| 10 |
+
else:
|
| 11 |
+
print("Model loaded successfully!")
|
| 12 |
+
|
| 13 |
+
print("Creating interface...")
|
| 14 |
+
demo = create_interface()
|
| 15 |
+
|
| 16 |
+
print("Launching application...")
|
| 17 |
+
demo.launch(share=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
if __name__ == "__main__":
|
| 20 |
+
main()
|
config.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MODEL_PATH = 'best_model.pkl'
|
| 2 |
+
|
| 3 |
+
FEATURE_NAMES = [
|
| 4 |
+
'Age', 'weight', 'height', 'BMI', 'gravidity', 'parity', 'H.Abortion',
|
| 5 |
+
'living.Child', 'Gestational.Age', 'Hemoglobin', 'hematocrit', 'platelet',
|
| 6 |
+
'MPV.mean.platelet.volume', 'PDW.platelet.distribution.width',
|
| 7 |
+
'neutrophil', 'lymphocyte', 'NLR.neutrophil.to.lymphocyte',
|
| 8 |
+
'PLR.platelet.to.lymphocyte.ratio'
|
| 9 |
+
]
|
| 10 |
+
|
| 11 |
+
FEATURE_NAMES_FA = [
|
| 12 |
+
'سن', 'وزن', 'قد', 'BMI', 'تعداد بارداری', 'تعداد زایمان', 'تعداد سقط',
|
| 13 |
+
'فرزند زنده', 'سن بارداری', 'هموگلوبین', 'هماتوکریت', 'پلاکت',
|
| 14 |
+
'MPV', 'PDW', 'نوتروفیل', 'لنفوسیت', 'NLR', 'PLR'
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
APP_TITLE = "🩺 سیستم پیشبینی سلامت جنین"
|
| 18 |
+
MODEL_ACCURACY = "95.8%"
|
| 19 |
+
MODEL_AUC = "99.3%"
|
| 20 |
+
|
| 21 |
+
DEFAULT_VALUES = {
|
| 22 |
+
'age': None, 'weight': None, 'height': None, 'gravidity': None, 'parity': None,
|
| 23 |
+
'h_abortion': None, 'living_child': None, 'gestational_age': None,
|
| 24 |
+
'hemoglobin': None, 'hematocrit': None, 'platelet': None, 'mpv': None,
|
| 25 |
+
'pdw': None, 'neutrophil': None, 'lymphocyte': None
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
FIELD_RANGES = {
|
| 29 |
+
'age': {'min': 15, 'max': 60}, 'weight': {'min': 35, 'max': 150},
|
| 30 |
+
'height': {'min': 130, 'max': 200}, 'gravidity': {'min': 0, 'max': 15},
|
| 31 |
+
'parity': {'min': 0, 'max': 12}, 'h_abortion': {'min': 0, 'max': 10},
|
| 32 |
+
'living_child': {'min': 0, 'max': 12}, 'gestational_age': {'min': 1, 'max': 44},
|
| 33 |
+
'hemoglobin': {'min': 6.0, 'max': 20.0}, 'hematocrit': {'min': 20.0, 'max': 60.0},
|
| 34 |
+
'platelet': {'min': 50, 'max': 1000}, 'mpv': {'min': 5.0, 'max': 20.0},
|
| 35 |
+
'pdw': {'min': 8.0, 'max': 30.0}, 'neutrophil': {'min': 0.5, 'max': 15.0},
|
| 36 |
+
'lymphocyte': {'min': 0.2, 'max': 8.0}
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
EXAMPLE_CASES = {
|
| 40 |
+
"مثال ۱: بیمار کمخطر": {
|
| 41 |
+
'age': 28, 'weight': 68, 'height': 165, 'gravidity': 2, 'parity': 1,
|
| 42 |
+
'h_abortion': 0, 'living_child': 1, 'gestational_age': 32,
|
| 43 |
+
'hemoglobin': 12.5, 'hematocrit': 38.0, 'platelet': 280,
|
| 44 |
+
'mpv': 8.5, 'pdw': 15.2, 'neutrophil': 4.2, 'lymphocyte': 2.1
|
| 45 |
+
},
|
| 46 |
+
"مثال ۲: بیمار پرخطر": {
|
| 47 |
+
'age': 42, 'weight': 85, 'height': 158, 'gravidity': 5, 'parity': 3,
|
| 48 |
+
'h_abortion': 1, 'living_child': 3, 'gestational_age': 28,
|
| 49 |
+
'hemoglobin': 9.2, 'hematocrit': 28.5, 'platelet': 450,
|
| 50 |
+
'mpv': 11.8, 'pdw': 18.7, 'neutrophil': 7.8, 'lymphocyte': 1.2
|
| 51 |
+
},
|
| 52 |
+
"مثال ۳: بیمار جوان": {
|
| 53 |
+
'age': 22, 'weight': 58, 'height': 162, 'gravidity': 1, 'parity': 0,
|
| 54 |
+
'h_abortion': 0, 'living_child': 0, 'gestational_age': 24,
|
| 55 |
+
'hemoglobin': 11.8, 'hematocrit': 35.2, 'platelet': 220,
|
| 56 |
+
'mpv': 9.2, 'pdw': 16.1, 'neutrophil': 3.8, 'lymphocyte': 2.5
|
| 57 |
+
}
|
| 58 |
+
}
|
interface.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from model_utils import predict_outcome
|
| 3 |
+
from styles import RTL_CSS, HTML_HEAD
|
| 4 |
+
from config import (
|
| 5 |
+
APP_TITLE, MODEL_ACCURACY, MODEL_AUC,
|
| 6 |
+
DEFAULT_VALUES, FIELD_RANGES, EXAMPLE_CASES
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
def create_patient_info_section():
|
| 10 |
+
with gr.Column():
|
| 11 |
+
gr.Markdown("### 📝 اطلاعات بیمار")
|
| 12 |
+
|
| 13 |
+
age = gr.Number(label="سن", value=DEFAULT_VALUES['age'],
|
| 14 |
+
minimum=FIELD_RANGES['age']['min'], maximum=FIELD_RANGES['age']['max'])
|
| 15 |
+
weight = gr.Number(label="وزن (کیلوگرم)", value=DEFAULT_VALUES['weight'],
|
| 16 |
+
minimum=FIELD_RANGES['weight']['min'], maximum=FIELD_RANGES['weight']['max'])
|
| 17 |
+
height = gr.Number(label="قد (سانتیمتر)", value=DEFAULT_VALUES['height'],
|
| 18 |
+
minimum=FIELD_RANGES['height']['min'], maximum=FIELD_RANGES['height']['max'])
|
| 19 |
+
|
| 20 |
+
with gr.Row():
|
| 21 |
+
gravidity = gr.Number(label="تعداد بارداری", value=DEFAULT_VALUES['gravidity'],
|
| 22 |
+
minimum=FIELD_RANGES['gravidity']['min'], maximum=FIELD_RANGES['gravidity']['max'])
|
| 23 |
+
parity = gr.Number(label="تعداد زایمان", value=DEFAULT_VALUES['parity'],
|
| 24 |
+
minimum=FIELD_RANGES['parity']['min'], maximum=FIELD_RANGES['parity']['max'])
|
| 25 |
+
|
| 26 |
+
with gr.Row():
|
| 27 |
+
h_abortion = gr.Number(label="تعداد سقط", value=DEFAULT_VALUES['h_abortion'],
|
| 28 |
+
minimum=FIELD_RANGES['h_abortion']['min'], maximum=FIELD_RANGES['h_abortion']['max'])
|
| 29 |
+
living_child = gr.Number(label="فرزند زنده", value=DEFAULT_VALUES['living_child'],
|
| 30 |
+
minimum=FIELD_RANGES['living_child']['min'], maximum=FIELD_RANGES['living_child']['max'])
|
| 31 |
+
|
| 32 |
+
gestational_age = gr.Number(label="سن بارداری (هفته)", value=DEFAULT_VALUES['gestational_age'],
|
| 33 |
+
minimum=FIELD_RANGES['gestational_age']['min'], maximum=FIELD_RANGES['gestational_age']['max'])
|
| 34 |
+
|
| 35 |
+
return age, weight, height, gravidity, parity, h_abortion, living_child, gestational_age
|
| 36 |
+
|
| 37 |
+
def create_lab_tests_section():
|
| 38 |
+
with gr.Column():
|
| 39 |
+
gr.Markdown("### 🧪 آزمایشات خون")
|
| 40 |
+
|
| 41 |
+
hemoglobin = gr.Number(label="هموگلوبین", value=DEFAULT_VALUES['hemoglobin'],
|
| 42 |
+
minimum=FIELD_RANGES['hemoglobin']['min'], maximum=FIELD_RANGES['hemoglobin']['max'])
|
| 43 |
+
hematocrit = gr.Number(label="هماتوکریت", value=DEFAULT_VALUES['hematocrit'],
|
| 44 |
+
minimum=FIELD_RANGES['hematocrit']['min'], maximum=FIELD_RANGES['hematocrit']['max'])
|
| 45 |
+
platelet = gr.Number(label="پلاکت", value=DEFAULT_VALUES['platelet'],
|
| 46 |
+
minimum=FIELD_RANGES['platelet']['min'], maximum=FIELD_RANGES['platelet']['max'])
|
| 47 |
+
|
| 48 |
+
with gr.Row():
|
| 49 |
+
mpv = gr.Number(label="MPV", value=DEFAULT_VALUES['mpv'],
|
| 50 |
+
minimum=FIELD_RANGES['mpv']['min'], maximum=FIELD_RANGES['mpv']['max'])
|
| 51 |
+
pdw = gr.Number(label="PDW", value=DEFAULT_VALUES['pdw'],
|
| 52 |
+
minimum=FIELD_RANGES['pdw']['min'], maximum=FIELD_RANGES['pdw']['max'])
|
| 53 |
+
|
| 54 |
+
with gr.Row():
|
| 55 |
+
neutrophil = gr.Number(label="نوتروفیل", value=DEFAULT_VALUES['neutrophil'],
|
| 56 |
+
minimum=FIELD_RANGES['neutrophil']['min'], maximum=FIELD_RANGES['neutrophil']['max'])
|
| 57 |
+
lymphocyte = gr.Number(label="لنفوسیت", value=DEFAULT_VALUES['lymphocyte'],
|
| 58 |
+
minimum=FIELD_RANGES['lymphocyte']['min'], maximum=FIELD_RANGES['lymphocyte']['max'])
|
| 59 |
+
|
| 60 |
+
return hemoglobin, hematocrit, platelet, mpv, pdw, neutrophil, lymphocyte
|
| 61 |
+
|
| 62 |
+
def predict_with_explanation(age, weight, height, gravidity, parity, h_abortion,
|
| 63 |
+
living_child, gestational_age, hemoglobin, hematocrit,
|
| 64 |
+
platelet, mpv, pdw, neutrophil, lymphocyte):
|
| 65 |
+
|
| 66 |
+
required_fields = [age, weight, height, gravidity, parity, h_abortion,
|
| 67 |
+
living_child, gestational_age, hemoglobin, hematocrit,
|
| 68 |
+
platelet, mpv, pdw, neutrophil, lymphocyte]
|
| 69 |
+
|
| 70 |
+
if any(field is None or field == "" for field in required_fields):
|
| 71 |
+
return "⚠️ لطفاً تمام فیلدها را پر کنید", "برای پیشبینی دقیق، تمام اطلاعات مورد نیاز است.", None
|
| 72 |
+
|
| 73 |
+
result, detailed_report = predict_outcome(
|
| 74 |
+
age, weight, height, gravidity, parity, h_abortion,
|
| 75 |
+
living_child, gestational_age, hemoglobin, hematocrit,
|
| 76 |
+
platelet, mpv, pdw, neutrophil, lymphocyte
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
return result, detailed_report
|
| 80 |
+
|
| 81 |
+
def clear_all_fields():
|
| 82 |
+
return tuple([None] * 17)
|
| 83 |
+
|
| 84 |
+
def load_example(example_name):
|
| 85 |
+
example_data = EXAMPLE_CASES[example_name]
|
| 86 |
+
return tuple(example_data[key] for key in [
|
| 87 |
+
'age', 'weight', 'height', 'gravidity', 'parity', 'h_abortion',
|
| 88 |
+
'living_child', 'gestational_age', 'hemoglobin', 'hematocrit',
|
| 89 |
+
'platelet', 'mpv', 'pdw', 'neutrophil', 'lymphocyte'
|
| 90 |
+
])
|
| 91 |
+
|
| 92 |
+
def create_interface():
|
| 93 |
+
with gr.Blocks(title=APP_TITLE, theme=gr.themes.Soft(), css=RTL_CSS, head=HTML_HEAD) as demo:
|
| 94 |
+
|
| 95 |
+
gr.Markdown(f"""
|
| 96 |
+
# {APP_TITLE}
|
| 97 |
+
|
| 98 |
+
این سیستم با استفاده از مدل هوش مصنوعی **AdaBoost**، احتمال بروز عوارض در بارداری را پیشبینی میکند.
|
| 99 |
+
|
| 100 |
+
**📊 عملکرد مدل:** دقت {MODEL_ACCURACY} | AUC {MODEL_AUC}
|
| 101 |
+
|
| 102 |
+
🔍 **ویژگیهای سیستم:**
|
| 103 |
+
- پیشبینی دقیق با استفاده از هوش مصنوعی
|
| 104 |
+
- تحلیل SHAP برای توضیح تأثیر هر ویژگی
|
| 105 |
+
- گزارش تفصیلی و قابل فهم برای پزشکان
|
| 106 |
+
|
| 107 |
+
📝 **راهنما:** تمام فیلدها را پر کنید یا از مثالهای آماده استفاده کنید.
|
| 108 |
+
""")
|
| 109 |
+
|
| 110 |
+
with gr.Row():
|
| 111 |
+
patient_inputs = create_patient_info_section()
|
| 112 |
+
lab_inputs = create_lab_tests_section()
|
| 113 |
+
|
| 114 |
+
with gr.Row():
|
| 115 |
+
predict_btn = gr.Button("🔍 پیشبینی", variant="primary", size="lg")
|
| 116 |
+
clear_btn = gr.Button("🗑️ پاک کردن", variant="secondary")
|
| 117 |
+
|
| 118 |
+
with gr.Row():
|
| 119 |
+
with gr.Column(scale=2):
|
| 120 |
+
result_text = gr.Textbox(label="نتیجه پیشبینی", lines=2)
|
| 121 |
+
detailed_report = gr.Markdown(label="گزارش تفصیلی")
|
| 122 |
+
|
| 123 |
+
gr.Markdown("---")
|
| 124 |
+
gr.Markdown("## 📚 مثالهای آماده")
|
| 125 |
+
|
| 126 |
+
with gr.Row():
|
| 127 |
+
for example_name in EXAMPLE_CASES.keys():
|
| 128 |
+
example_btn = gr.Button(f"📋 {example_name}", variant="secondary")
|
| 129 |
+
example_btn.click(
|
| 130 |
+
fn=lambda name=example_name: load_example(name),
|
| 131 |
+
outputs=list(patient_inputs) + list(lab_inputs)
|
| 132 |
+
)
|
| 133 |
+
|
| 134 |
+
predict_btn.click(
|
| 135 |
+
fn=predict_with_explanation,
|
| 136 |
+
inputs=list(patient_inputs) + list(lab_inputs),
|
| 137 |
+
outputs=[result_text, detailed_report]
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
clear_btn.click(
|
| 141 |
+
fn=clear_all_fields,
|
| 142 |
+
outputs=list(patient_inputs) + list(lab_inputs) + [result_text, detailed_report]
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
return demo
|
model_utils.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import joblib
|
| 3 |
+
import warnings
|
| 4 |
+
from config import MODEL_PATH
|
| 5 |
+
|
| 6 |
+
warnings.filterwarnings('ignore')
|
| 7 |
+
|
| 8 |
+
model = None
|
| 9 |
+
|
| 10 |
+
def load_model():
|
| 11 |
+
global model
|
| 12 |
+
try:
|
| 13 |
+
model = joblib.load(MODEL_PATH)
|
| 14 |
+
return model
|
| 15 |
+
except Exception as e:
|
| 16 |
+
print(f"Error loading model: {e}")
|
| 17 |
+
return None
|
| 18 |
+
|
| 19 |
+
def calculate_derived_features(age, weight, height, neutrophil, lymphocyte, platelet):
|
| 20 |
+
height_m = height / 100
|
| 21 |
+
bmi = weight / (height_m ** 2)
|
| 22 |
+
nlr = neutrophil / lymphocyte if lymphocyte > 0 else 0
|
| 23 |
+
plr = platelet / lymphocyte if lymphocyte > 0 else 0
|
| 24 |
+
return bmi, nlr, plr
|
| 25 |
+
|
| 26 |
+
def predict_outcome(age, weight, height, gravidity, parity, h_abortion,
|
| 27 |
+
living_child, gestational_age, hemoglobin, hematocrit,
|
| 28 |
+
platelet, mpv, pdw, neutrophil, lymphocyte):
|
| 29 |
+
global model
|
| 30 |
+
|
| 31 |
+
if model is None:
|
| 32 |
+
model = load_model()
|
| 33 |
+
if model is None:
|
| 34 |
+
return "خطا: مدل بارگذاری نشد", ""
|
| 35 |
+
|
| 36 |
+
try:
|
| 37 |
+
bmi, nlr, plr = calculate_derived_features(age, weight, height, neutrophil, lymphocyte, platelet)
|
| 38 |
+
|
| 39 |
+
input_data = np.array([[
|
| 40 |
+
age, weight, height, bmi, gravidity, parity, h_abortion,
|
| 41 |
+
living_child, gestational_age, hemoglobin, hematocrit, platelet,
|
| 42 |
+
mpv, pdw, neutrophil, lymphocyte, nlr, plr
|
| 43 |
+
]])
|
| 44 |
+
|
| 45 |
+
prediction_proba = model.predict_proba(input_data)[0]
|
| 46 |
+
prediction = model.predict(input_data)[0]
|
| 47 |
+
|
| 48 |
+
if prediction == 0:
|
| 49 |
+
result = f"🟢 پیشبینی: سالم (احتمال سالم بودن: {prediction_proba[0]*100:.1f}%)"
|
| 50 |
+
risk_level = "کم"
|
| 51 |
+
else:
|
| 52 |
+
result = f"🔴 پیشبینی: پرخطر (احتمال عوارض: {prediction_proba[1]*100:.1f}%)"
|
| 53 |
+
risk_level = "بالا"
|
| 54 |
+
|
| 55 |
+
detailed_report = f"""
|
| 56 |
+
📊 **گزارش تفصیلی پیشبینی**
|
| 57 |
+
|
| 58 |
+
**نتیجه کلی:** {result}
|
| 59 |
+
|
| 60 |
+
**سطح ریسک:** {risk_level}
|
| 61 |
+
|
| 62 |
+
**ویژگیهای محاسبه شده:**
|
| 63 |
+
- BMI: {bmi:.2f}
|
| 64 |
+
- NLR (نسبت نوتروفیل به لنفوسیت): {nlr:.2f}
|
| 65 |
+
- PLR (نسبت پلاکت به لنفوسیت): {plr:.2f}
|
| 66 |
+
|
| 67 |
+
⚠️ **توجه:** این پیشبینی صرفاً جهت کمک به تشخیص است و نباید جایگزین نظر پزشک شود.
|
| 68 |
+
"""
|
| 69 |
+
|
| 70 |
+
return result, detailed_report
|
| 71 |
+
|
| 72 |
+
except Exception as e:
|
| 73 |
+
return f"خطا در پردازش: {str(e)}", ""
|
| 74 |
+
|
| 75 |
+
def get_model():
|
| 76 |
+
global model
|
| 77 |
+
if model is None:
|
| 78 |
+
model = load_model()
|
| 79 |
+
return model
|
requirements.txt
CHANGED
|
@@ -1,6 +1,10 @@
|
|
| 1 |
gradio
|
| 2 |
-
scikit-learn
|
| 3 |
pandas
|
| 4 |
numpy
|
|
|
|
|
|
|
| 5 |
shap
|
| 6 |
matplotlib
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
gradio
|
|
|
|
| 2 |
pandas
|
| 3 |
numpy
|
| 4 |
+
scikit-learn
|
| 5 |
+
joblib
|
| 6 |
shap
|
| 7 |
matplotlib
|
| 8 |
+
xgboost
|
| 9 |
+
catboost
|
| 10 |
+
lightgbm
|
styles.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
RTL_CSS = """
|
| 2 |
+
/* RTL Support for Persian/Arabic */
|
| 3 |
+
.gradio-container {
|
| 4 |
+
direction: rtl !important;
|
| 5 |
+
text-align: right !important;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
/* Fix input fields alignment */
|
| 9 |
+
.gr-textbox, .gr-number, .gr-slider {
|
| 10 |
+
direction: rtl !important;
|
| 11 |
+
text-align: right !important;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
/* Fix labels */
|
| 15 |
+
label {
|
| 16 |
+
direction: rtl !important;
|
| 17 |
+
text-align: right !important;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
/* Fix buttons */
|
| 21 |
+
.gr-button {
|
| 22 |
+
direction: rtl !important;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/* Fix markdown content */
|
| 26 |
+
.gr-markdown {
|
| 27 |
+
direction: rtl !important;
|
| 28 |
+
text-align: right !important;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
/* Fix specific input elements */
|
| 32 |
+
input[type="number"], input[type="text"], textarea {
|
| 33 |
+
direction: rtl !important;
|
| 34 |
+
text-align: right !important;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
/* Fix column layouts */
|
| 38 |
+
.gr-column {
|
| 39 |
+
direction: rtl !important;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
/* Fix row layouts */
|
| 43 |
+
.gr-row {
|
| 44 |
+
direction: rtl !important;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
/* Fix slider component */
|
| 48 |
+
.gr-slider input {
|
| 49 |
+
direction: ltr !important;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
/* Ensure proper spacing for Persian text */
|
| 53 |
+
body {
|
| 54 |
+
font-family: 'Tahoma', 'Arial', sans-serif !important;
|
| 55 |
+
direction: rtl !important;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* Fix any remaining LTR elements */
|
| 59 |
+
* {
|
| 60 |
+
direction: inherit;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/* Special fixes for gradio components */
|
| 64 |
+
.wrap.svelte-1116kco {
|
| 65 |
+
direction: rtl !important;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
.container.svelte-1116kco {
|
| 69 |
+
direction: rtl !important;
|
| 70 |
+
}
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
HTML_HEAD = """
|
| 74 |
+
<meta charset="UTF-8">
|
| 75 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 76 |
+
<style>
|
| 77 |
+
@import url('https://fonts.googleapis.com/css2?family=Vazir:wght@300;400;500;600&display=swap');
|
| 78 |
+
body { font-family: 'Vazir', 'Tahoma', Arial, sans-serif !important; }
|
| 79 |
+
</style>
|
| 80 |
+
"""
|