Update bioprocess_model.py
Browse files- bioprocess_model.py +71 -77
bioprocess_model.py
CHANGED
@@ -1,11 +1,8 @@
|
|
1 |
# bioprocess_model.py
|
2 |
|
3 |
import numpy as np
|
4 |
-
import pandas as pd
|
5 |
-
import matplotlib.pyplot as plt
|
6 |
from scipy.optimize import curve_fit
|
7 |
from sklearn.metrics import mean_squared_error
|
8 |
-
from sympy import symbols, lambdify, sympify, Function
|
9 |
|
10 |
class BioprocessModel:
|
11 |
def __init__(self):
|
@@ -18,107 +15,104 @@ class BioprocessModel:
|
|
18 |
def logistic(time, xo, xm, um):
|
19 |
return (xo * np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time)))
|
20 |
|
21 |
-
|
22 |
-
def substrate(time, so, p, q, xo, xm, um):
|
23 |
-
return so - (p * xo * ((np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time))) - 1)) - \
|
24 |
-
(q * (xm / um) * np.log(1 - (xo / xm) * (1 - np.exp(um * time))))
|
25 |
-
|
26 |
-
@staticmethod
|
27 |
-
def product(time, po, alpha, beta, xo, xm, um):
|
28 |
-
return po + (alpha * xo * ((np.exp(um * time) / (1 - (xo / xm) * (1 - np.exp(um * time))) - 1))) + \
|
29 |
-
(beta * (xm / um) * np.log(1 - (xo / xm) * (1 - np.exp(um * time))))
|
30 |
-
|
31 |
-
def set_model(self, model_type, equation, params_str):
|
32 |
"""
|
33 |
-
|
34 |
-
|
35 |
-
:param
|
36 |
-
:param
|
37 |
-
:param params_str: Comma-separated string of parameter names
|
38 |
"""
|
39 |
-
t_symbol = symbols('t')
|
40 |
-
X = Function('X') # Definir 'X(t)' como una función simbólica
|
41 |
-
|
42 |
try:
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
except Exception as e:
|
45 |
-
raise ValueError(f"Error al
|
46 |
-
|
47 |
-
params = [param.strip() for param in params_str.split(',')]
|
48 |
-
params_symbols = symbols(params)
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
'
|
66 |
-
'params': params
|
67 |
}
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
}
|
80 |
-
|
81 |
-
raise ValueError(f"
|
82 |
|
83 |
def fit_model(self, model_type, time, data, bounds=([-np.inf], [np.inf])):
|
84 |
"""
|
85 |
-
|
86 |
-
|
87 |
-
:param model_type:
|
88 |
-
:param time:
|
89 |
-
:param data:
|
90 |
-
:param bounds:
|
91 |
-
:return:
|
92 |
"""
|
93 |
if model_type not in self.models:
|
94 |
-
raise ValueError(f"
|
95 |
|
96 |
func = self.models[model_type]['function']
|
97 |
params = self.models[model_type]['params']
|
98 |
|
99 |
-
# Definir la función de ajuste
|
100 |
def fit_func(t, *args):
|
101 |
try:
|
102 |
-
y
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
104 |
except Exception as e:
|
105 |
raise RuntimeError(f"Error en fit_func: {e}")
|
106 |
|
107 |
-
#
|
108 |
p0 = [1.0] * len(params) # Puedes ajustar estos valores según sea necesario
|
109 |
|
110 |
try:
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
# Ajustar el modelo usando curve_fit con p0
|
115 |
-
popt, _ = curve_fit(fit_func, time, data, p0=p0, bounds=(lower_bounds, upper_bounds), maxfev=10000)
|
116 |
-
|
117 |
-
# Guardar los parámetros ajustados en el modelo
|
118 |
self.params[model_type] = {param: val for param, val in zip(params, popt)}
|
119 |
y_pred = fit_func(time, *popt)
|
120 |
self.r2[model_type] = 1 - (np.sum((data - y_pred) ** 2) / np.sum((data - np.mean(data)) ** 2))
|
121 |
self.rmse[model_type] = np.sqrt(mean_squared_error(data, y_pred))
|
122 |
return y_pred
|
123 |
except Exception as e:
|
124 |
-
raise RuntimeError(f"Error
|
|
|
1 |
# bioprocess_model.py
|
2 |
|
3 |
import numpy as np
|
|
|
|
|
4 |
from scipy.optimize import curve_fit
|
5 |
from sklearn.metrics import mean_squared_error
|
|
|
6 |
|
7 |
class BioprocessModel:
|
8 |
def __init__(self):
|
|
|
15 |
def logistic(time, xo, xm, um):
|
16 |
return (xo * np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time)))
|
17 |
|
18 |
+
def set_model_biomass(self, equation, params_str):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
"""
|
20 |
+
Configura el modelo de Biomasa.
|
21 |
+
|
22 |
+
:param equation: La ecuación de Biomasa como cadena de texto
|
23 |
+
:param params_str: Cadena de parámetros separados por comas
|
|
|
24 |
"""
|
|
|
|
|
|
|
25 |
try:
|
26 |
+
# Define la función de Biomasa directamente
|
27 |
+
def biomass_func(t, xo, xm, um):
|
28 |
+
return (xo * np.exp(um * t)) / (1 - (xo / xm) * (1 - np.exp(um * t)))
|
29 |
+
|
30 |
+
self.models['biomass'] = {
|
31 |
+
'function': biomass_func,
|
32 |
+
'params': [param.strip() for param in params_str.split(',')]
|
33 |
+
}
|
34 |
except Exception as e:
|
35 |
+
raise ValueError(f"Error al configurar el modelo de biomasa: {e}")
|
|
|
|
|
|
|
36 |
|
37 |
+
def set_model_substrate(self, equation, params_str):
|
38 |
+
"""
|
39 |
+
Configura el modelo de Sustrato.
|
40 |
+
|
41 |
+
:param equation: La ecuación de Sustrato como cadena de texto (no usada en este enfoque)
|
42 |
+
:param params_str: Cadena de parámetros separados por comas
|
43 |
+
"""
|
44 |
+
try:
|
45 |
+
# Define la función de Sustrato que depende de Biomasa
|
46 |
+
def substrate_func(t, so, p, q, xo, xm, um):
|
47 |
+
X_t = self.models['biomass']['function'](t, xo, xm, um)
|
48 |
+
return so - p * X_t - q * np.log(1 - (xo / xm) * (1 - np.exp(um * t)))
|
49 |
+
|
50 |
+
self.models['substrate'] = {
|
51 |
+
'function': substrate_func,
|
52 |
+
'params': [param.strip() for param in params_str.split(',')]
|
|
|
53 |
}
|
54 |
+
except Exception as e:
|
55 |
+
raise ValueError(f"Error al configurar el modelo de sustrato: {e}")
|
56 |
+
|
57 |
+
def set_model_product(self, equation, params_str):
|
58 |
+
"""
|
59 |
+
Configura el modelo de Producto.
|
60 |
+
|
61 |
+
:param equation: La ecuación de Producto como cadena de texto (no usada en este enfoque)
|
62 |
+
:param params_str: Cadena de parámetros separados por comas
|
63 |
+
"""
|
64 |
+
try:
|
65 |
+
# Define la función de Producto que depende de Biomasa
|
66 |
+
def product_func(t, po, alpha, beta, xo, xm, um):
|
67 |
+
X_t = self.models['biomass']['function'](t, xo, xm, um)
|
68 |
+
return po + alpha * X_t + beta * np.log(1 - (xo / xm) * (1 - np.exp(um * t)))
|
69 |
+
|
70 |
+
self.models['product'] = {
|
71 |
+
'function': product_func,
|
72 |
+
'params': [param.strip() for param in params_str.split(',')]
|
73 |
}
|
74 |
+
except Exception as e:
|
75 |
+
raise ValueError(f"Error al configurar el modelo de producto: {e}")
|
76 |
|
77 |
def fit_model(self, model_type, time, data, bounds=([-np.inf], [np.inf])):
|
78 |
"""
|
79 |
+
Ajusta el modelo a los datos.
|
80 |
+
|
81 |
+
:param model_type: Tipo de modelo ('biomass', 'substrate', 'product')
|
82 |
+
:param time: Datos de tiempo
|
83 |
+
:param data: Datos observados para ajustar
|
84 |
+
:param bounds: Límites para los parámetros
|
85 |
+
:return: Datos predichos por el modelo
|
86 |
"""
|
87 |
if model_type not in self.models:
|
88 |
+
raise ValueError(f"Tipo de modelo '{model_type}' no está configurado. Usa set_model primero.")
|
89 |
|
90 |
func = self.models[model_type]['function']
|
91 |
params = self.models[model_type]['params']
|
92 |
|
93 |
+
# Definir la función de ajuste para curve_fit
|
94 |
def fit_func(t, *args):
|
95 |
try:
|
96 |
+
# Para Sustrato y Producto, se necesitan los parámetros de Biomasa
|
97 |
+
if model_type in ['substrate', 'product']:
|
98 |
+
# Extraer los parámetros de Biomasa
|
99 |
+
xo, xm, um = self.params['biomass']['xo'], self.params['biomass']['xm'], self.params['biomass']['um']
|
100 |
+
return func(t, *args, xo, xm, um)
|
101 |
+
else:
|
102 |
+
return func(t, *args)
|
103 |
except Exception as e:
|
104 |
raise RuntimeError(f"Error en fit_func: {e}")
|
105 |
|
106 |
+
# Estimación inicial de los parámetros
|
107 |
p0 = [1.0] * len(params) # Puedes ajustar estos valores según sea necesario
|
108 |
|
109 |
try:
|
110 |
+
popt, _ = curve_fit(fit_func, time, data, p0=p0, bounds=bounds, maxfev=10000)
|
111 |
+
# Guardar los parámetros ajustados
|
|
|
|
|
|
|
|
|
|
|
112 |
self.params[model_type] = {param: val for param, val in zip(params, popt)}
|
113 |
y_pred = fit_func(time, *popt)
|
114 |
self.r2[model_type] = 1 - (np.sum((data - y_pred) ** 2) / np.sum((data - np.mean(data)) ** 2))
|
115 |
self.rmse[model_type] = np.sqrt(mean_squared_error(data, y_pred))
|
116 |
return y_pred
|
117 |
except Exception as e:
|
118 |
+
raise RuntimeError(f"Error al ajustar el modelo '{model_type}': {e}")
|