File size: 6,092 Bytes
d0ed1b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224e3c9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import gradio as gr 
import pandas as pd 
import numpy as np 
from xgboost import XGBRegressor 
import joblib 
import os 
import logging 

# -----------------------------
# 1️⃣ File paths
# -----------------------------
MODEL_PATH = "xgb_model_corn_final.json"
SCALER_PATH = "minmax_scaler.pkl"
EXCEL_PATH = "microalgae_pot_experiment_corrected_doses.xlsx"

# Check files exist
for path in [MODEL_PATH, SCALER_PATH, EXCEL_PATH]:
    if not os.path.exists(path):
        raise FileNotFoundError(f"File not found: {path}")

# -----------------------------
# 2️⃣ Load model, scaler, and data
# -----------------------------
xgb_model = XGBRegressor()
xgb_model.load_model(MODEL_PATH)
scaler = joblib.load(SCALER_PATH)
df = pd.read_excel(EXCEL_PATH)

# Only one strain exists
strain_names = df['Microalgae_Strain'].unique().tolist()
single_strain_value = 0  # training used LabelEncoder -> 0

# -----------------------------
# 3️⃣ Prediction function
# -----------------------------
def predict_dose(crop, microalgae_strain, soil_n, soil_p, soil_k, soil_ec, soil_moisture,
                 chlorophyll, shoot_length, root_length, yield_g, relative_yield,
                 actual_dose):
    logs = []  # Capture all debug info

    # 1️⃣ Validate inputs
    required = [soil_n, soil_p, soil_k, soil_ec, soil_moisture,
                chlorophyll, shoot_length, root_length, yield_g, relative_yield]
    if any(v is None for v in required):
        logs.append("[DEBUG] Missing numeric inputs!")
        return "⚠️ Please fill all numeric input fields.", None, None, "\n".join(logs)
    logs.append("[DEBUG] All inputs received.")

    # 2️⃣ Encode strain
    strain_encoded = single_strain_value
    logs.append(f"[DEBUG] Using Microalgae_Strain encoded value: {strain_encoded}")

    # 3️⃣ Create DataFrame
    feature_cols = ['Soil_N_ppm','Soil_P_ppm','Soil_K_ppm','Soil_EC_dS_m',
                    'Soil_Moisture_%','Chlorophyll_SPAD','Shoot_Length_cm',
                    'Root_Length_cm','Yield_g_per_pot','Relative_Yield_%','Microalgae_Strain']
    X_input_df = pd.DataFrame([[soil_n, soil_p, soil_k, soil_ec, soil_moisture,
                                chlorophyll, shoot_length, root_length, yield_g,
                                relative_yield, strain_encoded]],
                              columns=feature_cols).astype(float)
    logs.append(f"[DEBUG] Input DataFrame:\n{X_input_df}")

    # 4️⃣ Scale
    X_input_scaled = scaler.transform(X_input_df)
    logs.append(f"[DEBUG] Scaled Input:\n{X_input_scaled}")

    # 5️⃣ Predict
    predicted_dose = xgb_model.predict(X_input_scaled)[0]
    logs.append(f"[DEBUG] Predicted dose (raw): {predicted_dose}")

    # 6️⃣ Compute error
    if actual_dose is not None:
        abs_error = abs(predicted_dose - actual_dose)
        logs.append(f"[DEBUG] Actual dose: {actual_dose}")
        logs.append(f"[DEBUG] Absolute Error: {abs_error}")
        return (f"🌱 **Predicted Dose:** {predicted_dose:.2f} g/pot",
                f"📏 **Actual Dose:** {actual_dose:.2f} g/pot",
                f"❌ **Absolute Error:** {abs_error:.2f} g/pot",
                "\n".join(logs))
    else:
        logs.append("[DEBUG] Actual dose not provided.")
        return (f"🌱 **Predicted Dose:** {predicted_dose:.2f} g/pot",
                "📏 Actual Dose: Not provided",
                "❌ Absolute Error: N/A",
                "\n".join(logs))

# -----------------------------
# 4️⃣ Gradio Interface
# -----------------------------
with gr.Blocks(
    theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime", neutral_hue="gray"),
    title="EcoGrowAI — Microalgae Dose Inference"
) as demo:
    gr.Markdown(
        """
        <div style='text-align:center'>
        <h1 style='color:#00b16a; margin-bottom:8px;'>🌿 EcoGrowAI — Inference App</h1>
        <p style='color:#555;'>Predict the optimal <b>microalgae dose (g/pot)</b> for Corn based on soil and growth parameters.</p>
        </div>
        <hr style='margin: 10px 0;'>
        """
    )
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### 🌾 Crop & Microalgae Selection")
            crop = gr.Dropdown(["Corn"], label="Select Crop", value="Corn")
            strain = gr.Dropdown(strain_names, label="Microalgae Strain", value=strain_names[0])
            gr.Markdown("### 🌱 Soil Parameters")
            soil_n = gr.Number(label="Soil N (ppm)")
            soil_p = gr.Number(label="Soil P (ppm)")
            soil_k = gr.Number(label="Soil K (ppm)")
            soil_ec = gr.Number(label="Soil EC (dS/m)")
            soil_moisture = gr.Number(label="Soil Moisture (%)")
            gr.Markdown("### 🌾 Plant Growth Parameters")
            chlorophyll = gr.Number(label="Chlorophyll (SPAD)")
            shoot_length = gr.Number(label="Shoot Length (cm)")
            root_length = gr.Number(label="Root Length (cm)")
            yield_g = gr.Number(label="Yield (g/pot)")
            relative_yield = gr.Number(label="Relative Yield (%)")
            gr.Markdown("### 📏 Actual Dose (optional)")
            actual_dose = gr.Number(label="Actual Dose (g/pot)")
            predict_btn = gr.Button("🔍 Predict Dose", variant="primary")
        with gr.Column(scale=1):
            gr.Markdown("### 📊 Inference Result")
            pred_box = gr.Markdown("Awaiting prediction...")
            actual_box = gr.Markdown("")
            abs_box = gr.Markdown("")
            log_box = gr.Textbox(label="Debug Logs", lines=15)  # <-- Add this
            predict_btn.click(
                fn=predict_dose,
                inputs=[crop, strain, soil_n, soil_p, soil_k, soil_ec, soil_moisture,
                        chlorophyll, shoot_length, root_length, yield_g, relative_yield,
                        actual_dose],
                outputs=[pred_box, actual_box, abs_box, log_box]
            )

# -----------------------------
# 5️⃣ Launch
# -----------------------------
if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=7860)