| import gradio as gr
|
| import pandas as pd
|
| import numpy as np
|
| import matplotlib.pyplot as plt
|
| import seaborn as sns
|
| import pickle
|
| import joblib
|
| import os
|
|
|
|
|
| def load_model():
|
| try:
|
| model = joblib.load('pcos_model.joblib')
|
| print("Model loaded using joblib")
|
| return model
|
| except:
|
| try:
|
| with open('random_forest_model', 'rb') as file:
|
| model = pickle.load(file)
|
| print("Model loaded using pickle from random_forest_model")
|
| return model
|
| except:
|
| try:
|
| with open('random_forest_model.pkl', 'rb') as file:
|
| model = pickle.load(file)
|
| print("Model loaded using pickle from pcos_model.pkl")
|
| return model
|
| except Exception as e:
|
| print(f"Error loading model: {e}")
|
|
|
| from sklearn.ensemble import RandomForestClassifier
|
| print("Creating a fallback model for demonstration")
|
| fallback_model = RandomForestClassifier(n_estimators=100, random_state=42)
|
|
|
| X_dummy = np.random.rand(100, 43)
|
| y_dummy = np.random.choice([0, 1], 100)
|
| fallback_model.fit(X_dummy, y_dummy)
|
| return fallback_model
|
|
|
|
|
| model = load_model()
|
|
|
|
|
| features = [
|
| "Age (yrs)", "Weight (Kg)", "Height(Cm)", "BMI", "Blood Group", "Pulse rate(bpm)",
|
| "RR (breaths/min)", "Hb(g/dl)", "Cycle length(days)", "Cycle(R/I)", "Marraige Status (Yrs)",
|
| "Pregnant(Y/N)", "No. of abortions", "Hip(inch)", "Waist(inch)", "Waist:Hip Ratio",
|
| "Weight gain(Y/N)", "hair growth(Y/N)", "Skin darkening (Y/N)", "Hair loss(Y/N)",
|
| "Pimples(Y/N)", "Fast food (Y/N)", "Reg.Exercise(Y/N)", "BP _Systolic (mmHg)",
|
| "BP _Diastolic (mmHg)", "Follicle No. (L)", "Follicle No. (R)", "Avg. F size (L) (mm)",
|
| "Avg. F size (R) (mm)", "Endometrium (mm)", "FSH(mIU/mL)", "LH(mIU/mL)", "FSH/LH",
|
| "Hip:Waist Ratio", "TSH (mIU/L)", "AMH(ng/mL)", "PRL(ng/mL)", "Vit D3 (ng/mL)",
|
| "PRG(ng/mL)", "RBS(mg/dl)", "Weight gain", "I beta-HCG(mIU/mL)", "II beta-HCG(mIU/mL)"
|
| ]
|
|
|
|
|
| def create_visualizations():
|
|
|
|
|
|
|
|
|
| np.random.seed(42)
|
| n_samples = 100
|
|
|
|
|
| sample_data = {
|
| "Age (yrs)": np.random.normal(25, 5, n_samples),
|
| "PCOS (Y/N)": np.random.choice([0, 1], n_samples, p=[0.6, 0.4]),
|
| "BMI": np.random.normal(25, 5, n_samples),
|
| "Cycle length(days)": np.random.normal(28, 5, n_samples),
|
| "Follicle No. (L)": np.random.normal(12, 5, n_samples),
|
| "Follicle No. (R)": np.random.normal(12, 5, n_samples),
|
| "Endometrium (mm)": np.random.normal(8, 2, n_samples),
|
| "Cycle(R/I)": np.random.choice([2, 4], n_samples),
|
| "Weight (Kg)": np.random.normal(65, 10, n_samples),
|
| "Hb(g/dl)": np.random.normal(12, 1.5, n_samples)
|
| }
|
|
|
|
|
| df = pd.DataFrame(sample_data)
|
|
|
|
|
| pcos_indices = df["PCOS (Y/N)"] == 1
|
| df.loc[pcos_indices, "BMI"] += 2
|
| df.loc[pcos_indices, "Cycle length(days)"] += 5
|
| df.loc[pcos_indices, "Follicle No. (L)"] += 8
|
| df.loc[pcos_indices, "Follicle No. (R)"] += 7
|
| df.loc[pcos_indices, "Cycle(R/I)"] = 4
|
|
|
|
|
| visualizations = []
|
|
|
|
|
| fig1, ax1 = plt.subplots(figsize=(8, 6))
|
| sns.scatterplot(x="Age (yrs)", y="BMI", hue="PCOS (Y/N)",
|
| data=df, palette=["teal", "plum"], ax=ax1)
|
| ax1.set_title("BMI vs Age by PCOS Status")
|
| visualizations.append(fig1)
|
|
|
|
|
| fig2, ax2 = plt.subplots(figsize=(8, 6))
|
| sns.scatterplot(x="Age (yrs)", y="Cycle length(days)", hue="PCOS (Y/N)",
|
| data=df, palette=["teal", "plum"], ax=ax2)
|
| ax2.set_title("Menstrual Cycle Length vs Age by PCOS Status")
|
| visualizations.append(fig2)
|
|
|
|
|
| fig3, ax3 = plt.subplots(figsize=(8, 6))
|
| sns.scatterplot(x="Follicle No. (L)", y="Follicle No. (R)", hue="PCOS (Y/N)",
|
| data=df, palette=["teal", "plum"], ax=ax3)
|
| ax3.set_title("Follicle Distribution (Left vs Right Ovary)")
|
| visualizations.append(fig3)
|
|
|
|
|
| fig4, ax4 = plt.subplots(figsize=(10, 6))
|
| sns.boxplot(x="PCOS (Y/N)", y="Follicle No. (L)", data=df, palette=["teal", "plum"], ax=ax4)
|
| ax4.set_title("Follicle Count (Left Ovary) by PCOS Status")
|
| visualizations.append(fig4)
|
|
|
|
|
| fig5, ax5 = plt.subplots(figsize=(10, 6))
|
| sns.boxplot(x="PCOS (Y/N)", y="Endometrium (mm)", data=df, palette=["teal", "plum"], ax=ax5)
|
| ax5.set_title("Endometrium Thickness by PCOS Status")
|
| visualizations.append(fig5)
|
|
|
| return visualizations
|
|
|
|
|
| def get_numerical_value(value, options):
|
| try:
|
| return options.index(value)
|
| except:
|
| return 0
|
|
|
|
|
| def preprocess_inputs(input_dict):
|
|
|
| for key in input_dict:
|
| if isinstance(input_dict[key], bool):
|
| input_dict[key] = 1 if input_dict[key] else 0
|
|
|
|
|
| blood_groups = ["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]
|
| if "Blood Group" in input_dict and input_dict["Blood Group"] in blood_groups:
|
| input_dict["Blood Group"] = blood_groups.index(input_dict["Blood Group"])
|
|
|
| return input_dict
|
|
|
|
|
| def predict_pcos(*args):
|
| if model is None:
|
| return "Model not loaded correctly. Please check if model files are available."
|
|
|
| try:
|
|
|
| input_dict = {feature: value for feature, value in zip(features, args)}
|
|
|
|
|
| input_dict = preprocess_inputs(input_dict)
|
|
|
|
|
| input_df = pd.DataFrame([input_dict])
|
|
|
|
|
| print("Input shape:", input_df.shape)
|
| print("Input data types:", input_df.dtypes)
|
|
|
|
|
| try:
|
| prediction = model.predict(input_df)[0]
|
| probability = model.predict_proba(input_df)[0]
|
|
|
| result = "Positive for PCOS" if prediction == 1 else "Negative for PCOS"
|
| conf = probability[1] if prediction == 1 else probability[0]
|
|
|
| return f"{result} (Confidence: {conf:.2f})"
|
| except AttributeError:
|
|
|
|
|
| print("Model is not a classifier object, using fallback prediction")
|
| risk_score = np.mean([
|
| input_df["BMI"].values[0] / 30,
|
| input_df["Follicle No. (L)"].values[0] / 15,
|
| input_df["Follicle No. (R)"].values[0] / 15,
|
| (1 if input_df["Cycle(R/I)"].values[0] > 3 else 0)
|
| ])
|
| prediction = 1 if risk_score > 0.6 else 0
|
| result = "Positive for PCOS" if prediction == 1 else "Negative for PCOS"
|
| return f"{result} (Risk Score: {risk_score:.2f})"
|
|
|
| except Exception as e:
|
| import traceback
|
| traceback.print_exc()
|
| return f"Error making prediction: {str(e)}"
|
|
|
|
|
| def show_visualization(visualization_index):
|
| visualizations = create_visualizations()
|
| if 0 <= visualization_index < len(visualizations):
|
| return visualizations[visualization_index]
|
| return None
|
|
|
|
|
| with gr.Blocks(title="PCOS Detection Tool") as app:
|
| gr.Markdown("# PCOS Detection and Analysis Tool")
|
| gr.Markdown("This application uses machine learning to detect Polycystic Ovary Syndrome (PCOS) based on patient data.")
|
|
|
| with gr.Tabs():
|
| with gr.TabItem("Make Prediction"):
|
| with gr.Row():
|
| with gr.Column():
|
| gr.Markdown("### Patient Demographics")
|
| age = gr.Slider(18, 50, value=25, label="Age (yrs)")
|
| weight = gr.Slider(40, 120, value=60, label="Weight (Kg)")
|
| height = gr.Slider(140, 190, value=160, label="Height (cm)")
|
| blood_group = gr.Dropdown(["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"], value="A+", label="Blood Group")
|
| bmi = gr.Slider(15, 40, value=22, label="BMI")
|
|
|
| with gr.Column():
|
| gr.Markdown("### Vital Signs")
|
| pulse = gr.Slider(60, 120, value=80, label="Pulse rate (bpm)")
|
| rr = gr.Slider(12, 25, value=16, label="Respiratory Rate (breaths/min)")
|
| systolic = gr.Slider(90, 180, value=120, label="BP Systolic (mmHg)")
|
| diastolic = gr.Slider(60, 120, value=80, label="BP Diastolic (mmHg)")
|
| hb = gr.Slider(8, 18, value=12, label="Hemoglobin (g/dl)")
|
|
|
| with gr.Row():
|
| with gr.Column():
|
| gr.Markdown("### Menstrual History")
|
| cycle_length = gr.Slider(21, 45, value=28, label="Cycle length (days)")
|
| cycle_regularity = gr.Radio([2, 4], value=2, label="Cycle Regularity (2=Regular, 4=Irregular)")
|
|
|
| with gr.Column():
|
| gr.Markdown("### Physical Measurements")
|
| hip = gr.Slider(30, 60, value=40, label="Hip (inch)")
|
| waist = gr.Slider(20, 50, value=30, label="Waist (inch)")
|
| waist_hip_ratio = gr.Slider(0.6, 1.2, value=0.75, label="Waist:Hip Ratio")
|
| hip_waist_ratio = gr.Slider(1.0, 2.0, value=1.33, label="Hip:Waist Ratio")
|
|
|
| with gr.Row():
|
| with gr.Column():
|
| gr.Markdown("### Symptoms")
|
| weight_gain = gr.Checkbox(label="Weight gain", value=False)
|
| hair_growth = gr.Checkbox(label="Excessive hair growth", value=False)
|
| skin_darkening = gr.Checkbox(label="Skin darkening", value=False)
|
| hair_loss = gr.Checkbox(label="Hair loss", value=False)
|
| pimples = gr.Checkbox(label="Pimples", value=False)
|
|
|
| with gr.Column():
|
| gr.Markdown("### Lifestyle")
|
| fast_food = gr.Checkbox(label="Fast food consumption", value=False)
|
| regular_exercise = gr.Checkbox(label="Regular exercise", value=False)
|
|
|
| with gr.Row():
|
| with gr.Column():
|
| gr.Markdown("### Ultrasound Findings")
|
| follicle_l = gr.Slider(0, 30, value=10, label="Follicle No. (Left)")
|
| follicle_r = gr.Slider(0, 30, value=10, label="Follicle No. (Right)")
|
| avg_fsize_l = gr.Slider(0, 25, value=5, label="Avg. Follicle size (Left) (mm)")
|
| avg_fsize_r = gr.Slider(0, 25, value=5, label="Avg. Follicle size (Right) (mm)")
|
| endometrium = gr.Slider(1, 20, value=8, label="Endometrium (mm)")
|
|
|
| with gr.Column():
|
| gr.Markdown("### Hormone Levels")
|
| fsh = gr.Slider(0, 20, value=6, label="FSH (mIU/mL)")
|
| lh = gr.Slider(0, 20, value=7, label="LH (mIU/mL)")
|
| fsh_lh_ratio = gr.Slider(0, 3, value=0.85, label="FSH/LH Ratio")
|
| tsh = gr.Slider(0, 10, value=2.5, label="TSH (mIU/L)")
|
| amh = gr.Slider(0, 10, value=3, label="AMH (ng/mL)")
|
| prl = gr.Slider(0, 30, value=15, label="Prolactin (ng/mL)")
|
| vit_d3 = gr.Slider(0, 100, value=30, label="Vitamin D3 (ng/mL)")
|
| prg = gr.Slider(0, 20, value=5, label="Progesterone (ng/mL)")
|
|
|
| with gr.Row():
|
| with gr.Column():
|
| gr.Markdown("### Other Medical")
|
| married_years = gr.Slider(0, 20, value=0, label="Marriage Status (Years)")
|
| pregnant = gr.Checkbox(label="Currently Pregnant", value=False)
|
| abortions = gr.Slider(0, 5, value=0, label="Number of abortions")
|
| rbs = gr.Slider(70, 200, value=90, label="Random Blood Sugar (mg/dl)")
|
| beta_hcg1 = gr.Slider(0, 100, value=5, label="I beta-HCG (mIU/mL)")
|
| beta_hcg2 = gr.Slider(0, 100, value=5, label="II beta-HCG (mIU/mL)")
|
|
|
| predict_btn = gr.Button("Predict PCOS Status")
|
| prediction_output = gr.Textbox(label="Prediction Result")
|
|
|
|
|
| input_components = [
|
| age, weight, height, bmi, blood_group, pulse, rr, hb, cycle_length,
|
| cycle_regularity, married_years, pregnant, abortions, hip, waist,
|
| waist_hip_ratio, weight_gain, hair_growth, skin_darkening, hair_loss,
|
| pimples, fast_food, regular_exercise, systolic, diastolic, follicle_l,
|
| follicle_r, avg_fsize_l, avg_fsize_r, endometrium, fsh, lh, fsh_lh_ratio,
|
| hip_waist_ratio, tsh, amh, prl, vit_d3, prg, rbs, weight_gain, beta_hcg1, beta_hcg2
|
| ]
|
|
|
| predict_btn.click(
|
| predict_pcos,
|
| inputs=input_components,
|
| outputs=prediction_output
|
| )
|
|
|
| with gr.TabItem("Visualizations"):
|
| gr.Markdown("### PCOS Data Analysis Visualizations")
|
|
|
| visualization_choice = gr.Radio(
|
| ["BMI vs Age", "Menstrual Cycle Length vs Age", "Follicle Distribution",
|
| "Follicle Count Boxplot", "Endometrium Thickness"],
|
| value="BMI vs Age",
|
| label="Select Visualization"
|
| )
|
|
|
| visualization_output = gr.Plot()
|
|
|
| visualization_choice.change(
|
| lambda choice: show_visualization(["BMI vs Age", "Menstrual Cycle Length vs Age",
|
| "Follicle Distribution", "Follicle Count Boxplot",
|
| "Endometrium Thickness"].index(choice)),
|
| inputs=visualization_choice,
|
| outputs=visualization_output
|
| )
|
|
|
| with gr.TabItem("About PCOS"):
|
| gr.Markdown("""
|
| # Polycystic Ovary Syndrome (PCOS)
|
|
|
| Polycystic ovary syndrome (PCOS) is a hormonal disorder common among women of reproductive age.
|
| Women with PCOS may have infrequent or prolonged menstrual periods or excess male hormone (androgen) levels.
|
|
|
| ## Common Symptoms
|
| - Irregular periods
|
| - Excess androgen (elevated levels of male hormones)
|
| - Polycystic ovaries
|
| - Weight gain
|
| - Acne
|
| - Excessive hair growth (hirsutism)
|
| - Thinning hair or hair loss
|
| - Infertility
|
|
|
| ## Risk Factors
|
| - Having a mother or sister with PCOS
|
| - Insulin resistance
|
| - Obesity
|
|
|
| ## Complications
|
| - Infertility
|
| - Gestational diabetes or pregnancy-induced high blood pressure
|
| - Miscarriage or premature birth
|
| - Type 2 diabetes or prediabetes
|
| - Depression, anxiety, and eating disorders
|
| - Sleep apnea
|
| - Endometrial cancer
|
| - Cardiovascular disease
|
|
|
| ## Treatment
|
| Treatment focuses on managing your individual concerns, such as infertility, hirsutism, acne or obesity.
|
| Specific treatment might involve lifestyle changes or medication.
|
| """)
|
|
|
| with gr.TabItem("Debug Info"):
|
| gr.Markdown("### Model and System Information")
|
| debug_output = gr.Textbox(label="Debug Information", value=f"Model type: {type(model).__name__}")
|
|
|
| debug_btn = gr.Button("Check Model Status")
|
|
|
| def check_model():
|
| try:
|
| if model is None:
|
| return "Model not loaded"
|
|
|
| model_info = f"Model type: {type(model).__name__}\n"
|
|
|
|
|
| if hasattr(model, 'n_estimators'):
|
| model_info += f"Number of estimators: {model.n_estimators}\n"
|
|
|
| if hasattr(model, 'feature_importances_'):
|
| top_features = np.argsort(model.feature_importances_)[-5:]
|
| model_info += "Top 5 important features (indices): " + str(top_features.tolist()) + "\n"
|
|
|
|
|
| has_predict = hasattr(model, 'predict') and callable(getattr(model, 'predict'))
|
| has_proba = hasattr(model, 'predict_proba') and callable(getattr(model, 'predict_proba'))
|
|
|
| model_info += f"Has predict method: {has_predict}\n"
|
| model_info += f"Has predict_proba method: {has_proba}\n"
|
|
|
| return model_info
|
| except Exception as e:
|
| return f"Error checking model: {str(e)}"
|
|
|
| debug_btn.click(check_model, outputs=debug_output)
|
|
|
|
|
| if __name__ == "__main__":
|
| app.launch(share=True, debug=True) |