Update interface.py
Browse files- interface.py +68 -59
interface.py
CHANGED
@@ -48,6 +48,7 @@ class BioprocessModel:
|
|
48 |
self.datax_std = []
|
49 |
self.datas_std = []
|
50 |
self.datap_std = []
|
|
|
51 |
|
52 |
@staticmethod
|
53 |
def logistic(time, xo, xm, um):
|
@@ -108,36 +109,70 @@ class BioprocessModel:
|
|
108 |
|
109 |
self.time = time
|
110 |
|
111 |
-
def
|
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 |
return y_pred
|
142 |
|
143 |
def plot_combined_results(self, time, biomass, substrate, product,
|
@@ -305,8 +340,8 @@ def process_and_plot(
|
|
305 |
|
306 |
# Usa el primer modelo de biomasa para X(t)
|
307 |
biomass_model = biomass_results[0]['model']
|
308 |
-
X_t_func = biomass_model.models['biomass']['function']
|
309 |
biomass_params_values = list(biomass_model.params['biomass'].values())
|
|
|
310 |
|
311 |
# Ajusta los modelos de Sustrato
|
312 |
for i in range(len(substrate_eqs)):
|
@@ -315,20 +350,7 @@ def process_and_plot(
|
|
315 |
bounds_str = substrate_bounds[i]
|
316 |
|
317 |
model = BioprocessModel()
|
318 |
-
|
319 |
-
t_symbol = symbols('t')
|
320 |
-
expr_substrate = sympify(equation)
|
321 |
-
substrate_params_symbols = symbols([param.strip() for param in params_str.split(',')])
|
322 |
-
substrate_func_expr = expr_substrate.subs('X(t)', X_t_func(t_symbol, *biomass_params_values))
|
323 |
-
substrate_func = lambdify(
|
324 |
-
(t_symbol, *substrate_params_symbols),
|
325 |
-
substrate_func_expr,
|
326 |
-
'numpy'
|
327 |
-
)
|
328 |
-
model.models['substrate'] = {
|
329 |
-
'function': substrate_func,
|
330 |
-
'params': [param.strip() for param in params_str.split(',')]
|
331 |
-
}
|
332 |
|
333 |
params = model.models['substrate']['params']
|
334 |
lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params))
|
@@ -350,20 +372,7 @@ def process_and_plot(
|
|
350 |
bounds_str = product_bounds[i]
|
351 |
|
352 |
model = BioprocessModel()
|
353 |
-
|
354 |
-
t_symbol = symbols('t')
|
355 |
-
expr_product = sympify(equation)
|
356 |
-
product_params_symbols = symbols([param.strip() for param in params_str.split(',')])
|
357 |
-
product_func_expr = expr_product.subs('X(t)', X_t_func(t_symbol, *biomass_params_values))
|
358 |
-
product_func = lambdify(
|
359 |
-
(t_symbol, *product_params_symbols),
|
360 |
-
product_func_expr,
|
361 |
-
'numpy'
|
362 |
-
)
|
363 |
-
model.models['product'] = {
|
364 |
-
'function': product_func,
|
365 |
-
'params': [param.strip() for param in params_str.split(',')]
|
366 |
-
}
|
367 |
|
368 |
params = model.models['product']['params']
|
369 |
lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params))
|
|
|
48 |
self.datax_std = []
|
49 |
self.datas_std = []
|
50 |
self.datap_std = []
|
51 |
+
self.models = {} # Initialize the models dictionary
|
52 |
|
53 |
@staticmethod
|
54 |
def logistic(time, xo, xm, um):
|
|
|
109 |
|
110 |
self.time = time
|
111 |
|
112 |
+
def set_model(self, model_type, equation, params_str):
|
113 |
+
"""
|
114 |
+
Sets up the model based on the type, equation, and parameters.
|
115 |
+
|
116 |
+
:param model_type: Type of the model ('biomass', 'substrate', 'product')
|
117 |
+
:param equation: The equation as a string
|
118 |
+
:param params_str: Comma-separated string of parameter names
|
119 |
+
"""
|
120 |
+
t_symbol = symbols('t')
|
121 |
+
expr = sympify(equation)
|
122 |
+
params = [param.strip() for param in params_str.split(',')]
|
123 |
+
params_symbols = symbols(params)
|
124 |
+
|
125 |
+
if model_type == 'biomass':
|
126 |
+
# Assuming biomass is a function of time only for logistic
|
127 |
+
func_expr = expr
|
128 |
+
func = lambdify(t_symbol, func_expr, 'numpy')
|
129 |
+
self.models['biomass'] = {
|
130 |
+
'function': func,
|
131 |
+
'params': params
|
132 |
+
}
|
133 |
+
elif model_type in ['substrate', 'product']:
|
134 |
+
# These models depend on biomass, which should already be set
|
135 |
+
if 'biomass' not in self.models:
|
136 |
+
raise ValueError("Biomass model must be set before substrate or product models.")
|
137 |
+
biomass_func = self.models['biomass']['function']
|
138 |
+
func_expr = expr.subs('X(t)', biomass_func(t_symbol))
|
139 |
+
func = lambdify((t_symbol, *params_symbols), func_expr, 'numpy')
|
140 |
+
self.models[model_type] = {
|
141 |
+
'function': func,
|
142 |
+
'params': params
|
143 |
+
}
|
144 |
+
else:
|
145 |
+
raise ValueError(f"Unsupported model type: {model_type}")
|
146 |
+
|
147 |
+
def fit_model(self, model_type, time, data, bounds=([-np.inf], [np.inf])):
|
148 |
+
"""
|
149 |
+
Fits the model to the data.
|
150 |
+
|
151 |
+
:param model_type: Type of the model ('biomass', 'substrate', 'product')
|
152 |
+
:param time: Time data
|
153 |
+
:param data: Observed data to fit
|
154 |
+
:param bounds: Bounds for the parameters
|
155 |
+
:return: Predicted data from the model
|
156 |
+
"""
|
157 |
+
if model_type not in self.models:
|
158 |
+
raise ValueError(f"Model type '{model_type}' is not set. Please use set_model first.")
|
159 |
+
|
160 |
+
func = self.models[model_type]['function']
|
161 |
+
params = self.models[model_type]['params']
|
162 |
+
|
163 |
+
# Define the fitting function based on model type
|
164 |
+
if model_type == 'biomass':
|
165 |
+
def fit_func(t, *args):
|
166 |
+
return func(t, *args)
|
167 |
+
else:
|
168 |
+
def fit_func(t, *args):
|
169 |
+
return func(t, *args)
|
170 |
+
|
171 |
+
popt, _ = curve_fit(fit_func, time, data, bounds=bounds, maxfev=10000)
|
172 |
+
self.params[model_type] = {param: val for param, val in zip(params, popt)}
|
173 |
+
y_pred = fit_func(time, *popt)
|
174 |
+
self.r2[model_type] = 1 - (np.sum((data - y_pred) ** 2) / np.sum((data - np.mean(data)) ** 2))
|
175 |
+
self.rmse[model_type] = np.sqrt(mean_squared_error(data, y_pred))
|
176 |
return y_pred
|
177 |
|
178 |
def plot_combined_results(self, time, biomass, substrate, product,
|
|
|
340 |
|
341 |
# Usa el primer modelo de biomasa para X(t)
|
342 |
biomass_model = biomass_results[0]['model']
|
|
|
343 |
biomass_params_values = list(biomass_model.params['biomass'].values())
|
344 |
+
biomass_func = biomass_model.models['biomass']['function']
|
345 |
|
346 |
# Ajusta los modelos de Sustrato
|
347 |
for i in range(len(substrate_eqs)):
|
|
|
350 |
bounds_str = substrate_bounds[i]
|
351 |
|
352 |
model = BioprocessModel()
|
353 |
+
model.set_model('substrate', equation, params_str)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
|
355 |
params = model.models['substrate']['params']
|
356 |
lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params))
|
|
|
372 |
bounds_str = product_bounds[i]
|
373 |
|
374 |
model = BioprocessModel()
|
375 |
+
model.set_model('product', equation, params_str)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
params = model.models['product']['params']
|
378 |
lower_bounds, upper_bounds = parse_bounds(bounds_str, len(params))
|