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( """

🌿 EcoGrowAI — Inference App

Predict the optimal microalgae dose (g/pot) for Corn based on soil and growth parameters.


""" ) 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)