Ayesha-Majeed commited on
Commit
334c27d
·
verified ·
1 Parent(s): 6ae020a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -166
app.py CHANGED
@@ -1,207 +1,133 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import numpy as np
4
- from xgboost import XGBRegressor
5
- import joblib
6
- import os
7
- import logging
8
 
9
  # -----------------------------
10
- # 1️⃣ File paths
11
  # -----------------------------
12
- MODEL_PATH = "xgb_model_corn_final.json"
13
- SCALER_PATH = "minmax_scaler.pkl"
14
- EXCEL_PATH = "microalgae_pot_experiment_corrected_doses.xlsx"
15
 
16
- # Check files exist
17
- for path in [MODEL_PATH, SCALER_PATH, EXCEL_PATH]:
18
- if not os.path.exists(path):
19
- raise FileNotFoundError(f"File not found: {path}")
20
-
21
- # -----------------------------
22
- # 2️⃣ Load model, scaler, and data
23
- # -----------------------------
24
- xgb_model = XGBRegressor()
25
- xgb_model.load_model(MODEL_PATH)
26
- scaler = joblib.load(SCALER_PATH)
27
  df = pd.read_excel(EXCEL_PATH)
 
28
 
29
- # Only one strain exists
30
- strain_names = df['Microalgae_Strain'].unique().tolist()
31
- single_strain_value = 0 # training used LabelEncoder -> 0
32
-
33
- # ==================== New Integration ====================
34
- # Create a list of row indices for dropdown
35
  row_options = ["None, Enter Manually"] + [str(i) for i in range(len(df))]
36
 
37
- # Function to autofill input fields from selected row
 
 
38
  def autofill_fields(row_index):
39
  if row_index == "None, Enter Manually":
40
- # Reset all fields if 'None' selected UPDATE
41
- return (None, None, None, None, None, None, None, None, None, None, None)
42
  row = df.iloc[int(row_index)]
43
  return (
44
- row['Soil_N_ppm'], row['Soil_P_ppm'], row['Soil_K_ppm'],
45
- row['Soil_EC_dS_m'], row['Soil_Moisture_%'], row['Chlorophyll_SPAD'],
46
- row['Shoot_Length_cm'], row['Root_Length_cm'], row['Yield_g_per_pot'],
47
- row['Relative_Yield_%'], row['Dose_g_per_pot'] if 'Dose_g_per_pot' in row else None
48
  )
49
 
50
-
51
  # -----------------------------
52
  # 3️⃣ Prediction function
53
  # -----------------------------
54
- def predict_dose(crop, microalgae_strain, soil_n, soil_p, soil_k, soil_ec, soil_moisture,
55
- chlorophyll, shoot_length, root_length, yield_g, relative_yield,
56
- actual_dose):
57
- logs = [] # Capture all debug info
58
-
59
- # 1️⃣ Validate inputs
60
- required = [soil_n, soil_p, soil_k, soil_ec, soil_moisture,
61
- chlorophyll, shoot_length, root_length, yield_g, relative_yield]
62
  if any(v is None for v in required):
63
  logs.append("[DEBUG] Missing numeric inputs!")
64
- return "⚠️ Please fill all numeric input fields.", None, None, "\n".join(logs)
65
- logs.append("[DEBUG] All inputs received.")
66
-
67
- # 2️⃣ Encode strain
68
- strain_encoded = single_strain_value
69
- logs.append(f"[DEBUG] Using Microalgae_Strain encoded value: {strain_encoded}")
70
-
71
- # 3️⃣ Create DataFrame
72
- feature_cols = ['Soil_N_ppm','Soil_P_ppm','Soil_K_ppm','Soil_EC_dS_m',
73
- 'Soil_Moisture_%','Chlorophyll_SPAD','Shoot_Length_cm',
74
- 'Root_Length_cm','Yield_g_per_pot','Relative_Yield_%','Microalgae_Strain']
75
- X_input_df = pd.DataFrame([[soil_n, soil_p, soil_k, soil_ec, soil_moisture,
76
- chlorophyll, shoot_length, root_length, yield_g,
77
- relative_yield, strain_encoded]],
78
- columns=feature_cols).astype(float)
79
- logs.append(f"[DEBUG] Input DataFrame:\n{X_input_df}")
80
-
81
- # 4️⃣ Scale
82
- X_input_scaled = scaler.transform(X_input_df)
83
- logs.append(f"[DEBUG] Scaled Input:\n{X_input_scaled}")
84
-
85
- # 5️⃣ Predict
86
- predicted_dose = xgb_model.predict(X_input_scaled)[0]
87
- logs.append(f"[DEBUG] Predicted dose (raw): {predicted_dose}")
88
-
89
- # # 6️⃣ Compute error
90
- # if actual_dose is not None:
91
- # abs_error = abs(predicted_dose - actual_dose)
92
- # logs.append(f"[DEBUG] Actual dose: {actual_dose}")
93
- # logs.append(f"[DEBUG] Absolute Error: {abs_error}")
94
- # return (f"**Predicted Dose:** {predicted_dose:.2f} g/pot",
95
- # f"**Actual Dose:** {actual_dose:.2f} g/pot",
96
- # f"**Absolute Error:** {abs_error:.2f} g/pot",
97
- # "\n".join(logs))
98
- # else:
99
- # logs.append("[DEBUG] Actual dose not provided.")
100
- # return (f"**Predicted Dose:** {predicted_dose:.2f} g/pot",
101
- # " Actual Dose: Not provided",
102
- # " Absolute Error: N/A",
103
- # "\n".join(logs))
104
-
105
- # 6️⃣ Compute error
106
- if actual_dose is not None:
107
  try:
108
- actual_dose_float = float(actual_dose) # <-- convert string to float
109
- abs_error = abs(predicted_dose - actual_dose_float)
110
- logs.append(f"[DEBUG] Actual dose: {actual_dose_float}")
111
  logs.append(f"[DEBUG] Absolute Error: {abs_error}")
112
- return (f"**Predicted Dose:** {predicted_dose:.2f} g/pot",
113
- f"**Actual Dose:** {actual_dose_float:.2f} g/pot",
114
- f"**Absolute Error:** {abs_error:.2f} g/pot",
115
- "\n".join(logs))
116
- except ValueError:
117
- logs.append("[DEBUG] Actual dose could not be converted to float")
118
- return (f"**Predicted Dose:** {predicted_dose:.2f} g/pot",
119
- " Actual Dose: Invalid",
120
- " Absolute Error: N/A",
121
  "\n".join(logs))
122
- else:
123
- logs.append("[DEBUG] Actual dose not provided.")
124
- return (f"**Predicted Dose:** {predicted_dose:.2f} g/pot",
125
- " Actual Dose: Not provided",
126
- " Absolute Error: N/A",
127
- "\n".join(logs))
128
 
 
 
 
 
129
 
130
  # -----------------------------
131
  # 4️⃣ Gradio Interface
132
  # -----------------------------
133
- with gr.Blocks(
134
- theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime", neutral_hue="gray"),
135
- title="Microalgae Dose Prediction"
136
- ) as demo:
137
- gr.Markdown(
138
- """
139
- <div style='text-align:center'>
140
- <h1 style='color:#00b16a; margin-bottom:8px;'>Microalgae — Dose Prediction App</h1>
141
- <p style='color:#555;'>Predict the optimal <b>microalgae dose (g/pot)</b> for Corn based on soil and growth parameters.</p>
142
- </div>
143
- <hr style='margin: 10px 0;'>
144
- """
145
- )
146
  with gr.Row():
147
  with gr.Column(scale=1):
148
- gr.Markdown("### Crop & Microalgae Selection")
149
- crop = gr.Dropdown(["Corn"], label="Select Crop", value="Corn")
150
- strain = gr.Dropdown(strain_names, label="Microalgae Strain", value=strain_names[0])
151
- row_selector = gr.Dropdown(row_options, label="Select Row (from XLSX)", value="0")
152
- gr.Markdown("### Soil Parameters")
 
153
  soil_n = gr.Number(label="Soil N (ppm)")
154
  soil_p = gr.Number(label="Soil P (ppm)")
155
  soil_k = gr.Number(label="Soil K (ppm)")
156
- soil_ec = gr.Number(label="Soil EC (dS/m)")
157
- soil_moisture = gr.Number(label="Soil Moisture (%)")
158
- gr.Markdown("### Plant Growth Parameters")
159
  chlorophyll = gr.Number(label="Chlorophyll (SPAD)")
160
- shoot_length = gr.Number(label="Shoot Length (cm)")
161
- root_length = gr.Number(label="Root Length (cm)")
162
- yield_g = gr.Number(label="Yield (g/pot)")
163
- relative_yield = gr.Number(label="Relative Yield (%)")
164
- gr.Markdown("### Actual Dose (optional)")
165
- actual_dose = gr.Number(label="Actual Dose (g/pot)")
166
- predict_btn = gr.Button("Predict Dose", variant="primary")
 
 
167
  with gr.Column(scale=1):
168
  gr.Markdown("### Inference Result")
169
  pred_box = gr.Markdown("Awaiting prediction...")
170
  actual_box = gr.Markdown("")
171
  abs_box = gr.Markdown("")
172
- log_box = gr.Textbox(label="Debug Logs", lines=15)# <-- Add this
173
- gr.Markdown(
174
- """
175
- ### Input Tips:
176
- - Select Crop and the used microalgae strain.
177
- - Select rows from XLSX or Enter manually
178
- - Enter values for N, P, K, EC, and Moisture.
179
- - Fill in Chlorophyll (SPAD), Shoot/Root length, Yield, and Relative Yield.
180
- - (Optional) Add Actual Dose if you want to compare results.
181
- - Click “Predict Dose” to get results.
182
- ### Output Tips:
183
- <div>
184
- <p style="margin:6px 0;"><strong>Predicted Dose:</strong> Model’s suggested microalgae dose (g/pot).</p>
185
- <p style="margin:6px 0;"><strong>Absolute Error:</strong> Shows how close the prediction is to your actual dose.</p>
186
- <p style="margin:6px 0;"><strong>Debug Logs:</strong> Displays detailed input and model processing info.</p>
187
- </div>
188
- """
189
- )
190
- # ✅ Autofill fields when row selected
191
- row_selector.change(fn=autofill_fields,
192
- inputs=[row_selector],
193
- outputs=[soil_n, soil_p, soil_k, soil_ec, soil_moisture,
194
- chlorophyll, shoot_length, root_length, yield_g,
195
- relative_yield, actual_dose]
196
- )
197
-
198
- predict_btn.click(
199
- fn=predict_dose,
200
- inputs=[crop, strain, soil_n, soil_p, soil_k, soil_ec, soil_moisture,
201
- chlorophyll, shoot_length, root_length, yield_g, relative_yield,
202
- actual_dose],
203
- outputs=[pred_box, actual_box, abs_box, log_box]
204
- )
205
 
206
  # -----------------------------
207
  # 5️⃣ Launch
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import joblib
 
 
 
5
 
6
  # -----------------------------
7
+ # 1️⃣ Load model and data
8
  # -----------------------------
9
+ MODEL_PATH = "linear_model.pkl"
10
+ EXCEL_PATH = "excel sheet of plant 2.xlsx"
 
11
 
12
+ linear_model = joblib.load(MODEL_PATH)
 
 
 
 
 
 
 
 
 
 
13
  df = pd.read_excel(EXCEL_PATH)
14
+ df.columns = df.columns.str.strip()
15
 
16
+ strain_names = df['pea plant strain'].unique().tolist()
 
 
 
 
 
17
  row_options = ["None, Enter Manually"] + [str(i) for i in range(len(df))]
18
 
19
+ # -----------------------------
20
+ # 2️⃣ Autofill function
21
+ # -----------------------------
22
  def autofill_fields(row_index):
23
  if row_index == "None, Enter Manually":
24
+ return [None]*11 # Dose, Soil N, P, K, pH + 6 optional yield metrics
 
25
  row = df.iloc[int(row_index)]
26
  return (
27
+ row['Dose (g/pot)'], row['Soil N (ppm)'], row['Soil P (ppm)'],
28
+ row['Soil K (ppm)'], row['pH'], row['Chlorophyll (SPAD)'],
29
+ row['Shoot Length (cm)'], row['Root Length (cm)'], row['Shoot Wt (g)'],
30
+ row['Root Wt (g)'], row['Yield (g/pot)']
31
  )
32
 
 
33
  # -----------------------------
34
  # 3️⃣ Prediction function
35
  # -----------------------------
36
+ def predict_linear(strain, dose, soil_n, soil_p, soil_k, ph,
37
+ chlorophyll, shoot_len, root_len, shoot_wt, root_wt, yield_gp,
38
+ actual_yield=None):
39
+ logs = []
40
+
41
+ # Validate required inputs
42
+ required = [dose, soil_n, soil_p, soil_k, ph]
 
43
  if any(v is None for v in required):
44
  logs.append("[DEBUG] Missing numeric inputs!")
45
+ return "⚠️ Fill all inputs", "", "", "\n".join(logs)
46
+ logs.append("[DEBUG] Inputs received.")
47
+
48
+ # Prepare DataFrame
49
+ X_input = pd.DataFrame([{
50
+ 'pea plant strain': strain,
51
+ 'Dose (g/pot)': dose,
52
+ 'Soil N (ppm)': soil_n,
53
+ 'Soil P (ppm)': soil_p,
54
+ 'Soil K (ppm)': soil_k,
55
+ 'pH': ph
56
+ }])
57
+ logs.append(f"[DEBUG] Input DataFrame:\n{X_input}")
58
+
59
+ # Predict all 7 target metrics
60
+ y_pred = linear_model.predict(X_input)[0]
61
+ logs.append(f"[DEBUG] Predicted values:\n{y_pred}")
62
+
63
+ # Optional actual_yield comparison
64
+ if actual_yield is not None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  try:
66
+ actual_val = float(actual_yield)
67
+ abs_error = np.abs(actual_val - y_pred[5]) # assuming Yield (g/pot) at index 5
68
+ logs.append(f"[DEBUG] Actual Yield: {actual_val}")
69
  logs.append(f"[DEBUG] Absolute Error: {abs_error}")
70
+ return (f"**Predicted Metrics:** {y_pred.round(2)}",
71
+ f"**Actual Yield:** {actual_val}",
72
+ f"**Absolute Error:** {abs_error:.2f}",
 
 
 
 
 
 
73
  "\n".join(logs))
74
+ except:
75
+ logs.append("[DEBUG] Actual yield invalid.")
 
 
 
 
76
 
77
+ return (f"**Predicted Metrics:** {y_pred.round(2)}",
78
+ "Actual Yield: Not provided",
79
+ "Absolute Error: N/A",
80
+ "\n".join(logs))
81
 
82
  # -----------------------------
83
  # 4️⃣ Gradio Interface
84
  # -----------------------------
85
+ with gr.Blocks(title="Linear Regression Plant Predictor") as demo:
86
+ gr.Markdown("<h1 style='text-align:center'>Linear Regression — Plant Yield Predictor</h1>")
87
+
 
 
 
 
 
 
 
 
 
 
88
  with gr.Row():
89
  with gr.Column(scale=1):
90
+ gr.Markdown("### Plant & Strain")
91
+ strain_input = gr.Dropdown(strain_names, label="Select Strain", value=strain_names[0])
92
+ row_selector = gr.Dropdown(row_options, label="Select Row", value="None, Enter Manually")
93
+
94
+ gr.Markdown("### Input Parameters")
95
+ dose = gr.Number(label="Dose (g/pot)")
96
  soil_n = gr.Number(label="Soil N (ppm)")
97
  soil_p = gr.Number(label="Soil P (ppm)")
98
  soil_k = gr.Number(label="Soil K (ppm)")
99
+ ph = gr.Number(label="pH")
100
+
101
+ gr.Markdown("### Optional Yield Metrics")
102
  chlorophyll = gr.Number(label="Chlorophyll (SPAD)")
103
+ shoot_len = gr.Number(label="Shoot Length (cm)")
104
+ root_len = gr.Number(label="Root Length (cm)")
105
+ shoot_wt = gr.Number(label="Shoot Wt (g)")
106
+ root_wt = gr.Number(label="Root Wt (g)")
107
+ yield_gp = gr.Number(label="Yield (g/pot)")
108
+
109
+ actual_yield = gr.Number(label="Actual Yield (g/pot)")
110
+ predict_btn = gr.Button("Predict", variant="primary")
111
+
112
  with gr.Column(scale=1):
113
  gr.Markdown("### Inference Result")
114
  pred_box = gr.Markdown("Awaiting prediction...")
115
  actual_box = gr.Markdown("")
116
  abs_box = gr.Markdown("")
117
+ log_box = gr.Textbox(label="Debug Logs", lines=15)
118
+
119
+ # Autofill callback
120
+ row_selector.change(fn=autofill_fields, inputs=[row_selector],
121
+ outputs=[dose, soil_n, soil_p, soil_k, ph,
122
+ chlorophyll, shoot_len, root_len,
123
+ shoot_wt, root_wt, yield_gp])
124
+
125
+ # Prediction callback
126
+ predict_btn.click(fn=predict_linear,
127
+ inputs=[strain_input, dose, soil_n, soil_p, soil_k, ph,
128
+ chlorophyll, shoot_len, root_len, shoot_wt, root_wt, yield_gp,
129
+ actual_yield],
130
+ outputs=[pred_box, actual_box, abs_box, log_box])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  # -----------------------------
133
  # 5️⃣ Launch