C2MV commited on
Commit
f03d840
verified
1 Parent(s): 39cf1b1

Update bioprocess_model.py

Browse files
Files changed (1) hide show
  1. bioprocess_model.py +52 -148
bioprocess_model.py CHANGED
@@ -1,148 +1,52 @@
1
- # bioprocess_model.py
2
-
3
- import numpy as np
4
- import pandas as pd
5
- import matplotlib.pyplot as plt
6
- from scipy.integrate import odeint
7
- from scipy.optimize import curve_fit
8
- from sklearn.metrics import mean_squared_error
9
- import seaborn as sns
10
-
11
- class BioprocessModel:
12
- def __init__(self):
13
- self.params = {}
14
- self.r2 = {}
15
- self.rmse = {}
16
- self.datax = []
17
- self.datas = []
18
- self.datap = []
19
- self.dataxp = []
20
- self.datasp = []
21
- self.datapp = []
22
- self.datax_std = []
23
- self.datas_std = []
24
- self.datap_std = []
25
-
26
- @staticmethod
27
- def logistic(time, xo, xm, um):
28
- return (xo * np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time)))
29
-
30
- @staticmethod
31
- def substrate(time, so, p, q, xo, xm, um):
32
- return so - (p * xo * ((np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time))) - 1)) - \
33
- (q * (xm / um) * np.log(1 - (xo / xm) * (1 - np.exp(um * time))))
34
-
35
- @staticmethod
36
- def product(time, po, alpha, beta, xo, xm, um):
37
- return po + (alpha * xo * ((np.exp(um * time) / (1 - (xo / xm) * (1 - np.exp(um * time)))) - 1)) + \
38
- (beta * (xm / um) * np.log(1 - (xo / xm) * (1 - np.exp(um * time))))
39
-
40
- @staticmethod
41
- def logistic_diff(X, t, params):
42
- xo, xm, um = params
43
- dXdt = um * X * (1 - X / xm)
44
- return dXdt
45
-
46
- def substrate_diff(self, S, t, params, biomass_params, X_func):
47
- so, p, q = params
48
- xo, xm, um = biomass_params
49
- X_t = X_func(t)
50
- dSdt = -p * (um * X_t * (1 - X_t / xm)) - q * X_t
51
- return dSdt
52
-
53
- def product_diff(self, P, t, params, biomass_params, X_func):
54
- po, alpha, beta = params
55
- xo, xm, um = biomass_params
56
- X_t = X_func(t)
57
- dPdt = alpha * (um * X_t * (1 - X_t / xm)) + beta * X_t
58
- return dPdt
59
-
60
- def process_data(self, df):
61
- biomass_cols = [col for col in df.columns if 'Biomasa' in col]
62
- substrate_cols = [col for col in df.columns if 'Sustrato' in col]
63
- product_cols = [col for col in df.columns if 'Producto' in col]
64
-
65
- time_col = [col for col in df.columns if 'Tiempo' in col][0]
66
- time = df[time_col].values
67
-
68
- data_biomass = np.array([df[col].values for col in biomass_cols])
69
- self.datax.append(data_biomass)
70
- self.dataxp.append(np.mean(data_biomass, axis=0))
71
- self.datax_std.append(np.std(data_biomass, axis=0, ddof=1))
72
-
73
- data_substrate = np.array([df[col].values for col in substrate_cols])
74
- self.datas.append(data_substrate)
75
- self.datasp.append(np.mean(data_substrate, axis=0))
76
- self.datas_std.append(np.std(data_substrate, axis=0, ddof=1))
77
-
78
- data_product = np.array([df[col].values for col in product_cols])
79
- self.datap.append(data_product)
80
- self.datapp.append(np.mean(data_product, axis=0))
81
- self.datap_std.append(np.std(data_product, axis=0, ddof=1))
82
-
83
- self.time = time
84
-
85
- def fit_model(self, model_type='logistic'):
86
- if model_type == 'logistic':
87
- self.fit_biomass = self.fit_biomass_logistic
88
- self.fit_substrate = self.fit_substrate_logistic
89
- self.fit_product = self.fit_product_logistic
90
-
91
- def fit_biomass_logistic(self, time, biomass, bounds):
92
- popt, _ = curve_fit(self.logistic, time, biomass, bounds=bounds, maxfev=10000)
93
- self.params['biomass'] = {'xo': popt[0], 'xm': popt[1], 'um': popt[2]}
94
- y_pred = self.logistic(time, *popt)
95
- self.r2['biomass'] = 1 - (np.sum((biomass - y_pred) ** 2) / np.sum((biomass - np.mean(biomass)) ** 2))
96
- self.rmse['biomass'] = np.sqrt(mean_squared_error(biomass, y_pred))
97
- return y_pred
98
-
99
- def fit_substrate_logistic(self, time, substrate, biomass_params, bounds):
100
- popt, _ = curve_fit(lambda t, so, p, q: self.substrate(t, so, p, q, *biomass_params.values()),
101
- time, substrate, bounds=bounds)
102
- self.params['substrate'] = {'so': popt[0], 'p': popt[1], 'q': popt[2]}
103
- y_pred = self.substrate(time, *popt, *biomass_params.values())
104
- self.r2['substrate'] = 1 - (np.sum((substrate - y_pred) ** 2) / np.sum((substrate - np.mean(substrate)) ** 2))
105
- self.rmse['substrate'] = np.sqrt(mean_squared_error(substrate, y_pred))
106
- return y_pred
107
-
108
- def fit_product_logistic(self, time, product, biomass_params, bounds):
109
- popt, _ = curve_fit(lambda t, po, alpha, beta: self.product(t, po, alpha, beta, *biomass_params.values()),
110
- time, product, bounds=bounds)
111
- self.params['product'] = {'po': popt[0], 'alpha': popt[1], 'beta': popt[2]}
112
- y_pred = self.product(time, *popt, *biomass_params.values())
113
- self.r2['product'] = 1 - (np.sum((product - y_pred) ** 2) / np.sum((product - np.mean(product)) ** 2))
114
- self.rmse['product'] = np.sqrt(mean_squared_error(product, y_pred))
115
- return y_pred
116
-
117
- def plot_combined_results(self, time, biomass, substrate, product,
118
- y_pred_biomass, y_pred_substrate, y_pred_product,
119
- biomass_std=None, substrate_std=None, product_std=None,
120
- experiment_name='', legend_position='best', params_position='upper right',
121
- show_legend=True, show_params=True,
122
- style='whitegrid', line_color='#0000FF', point_color='#000000',
123
- line_style='-', marker_style='o'):
124
- sns.set_style(style)
125
-
126
- fig, ax1 = plt.subplots(figsize=(10, 7))
127
- ax1.set_xlabel('Tiempo')
128
- ax1.set_ylabel('Biomasa', color=line_color)
129
-
130
- ax1.plot(time, biomass, marker=marker_style, linestyle='', color=point_color, label='Biomasa (Datos)')
131
- ax1.plot(time, y_pred_biomass, linestyle=line_style, color=line_color, label='Biomasa (Modelo)')
132
- ax1.tick_params(axis='y', labelcolor=line_color)
133
-
134
- ax2 = ax1.twinx()
135
- ax2.set_ylabel('Sustrato', color='green')
136
- ax2.plot(time, substrate, marker=marker_style, linestyle='', color='green', label='Sustrato (Datos)')
137
- ax2.plot(time, y_pred_substrate, linestyle=line_style, color='green', label='Sustrato (Modelo)')
138
- ax2.tick_params(axis='y', labelcolor='green')
139
-
140
- ax3 = ax1.twinx()
141
- ax3.spines["right"].set_position(("axes", 1.1))
142
- ax3.set_ylabel('Producto', color='red')
143
- ax3.plot(time, product, marker=marker_style, linestyle='', color='red', label='Producto (Datos)')
144
- ax3.plot(time, y_pred_product, linestyle=line_style, color='red', label='Producto (Modelo)')
145
- ax3.tick_params(axis='y', labelcolor='red')
146
-
147
- fig.tight_layout()
148
- return fig
 
1
+ def set_model(self, model_type, equation, params_str):
2
+ """
3
+ Configura el modelo basado en el tipo, ecuaci贸n y par谩metros.
4
+
5
+ :param model_type: Tipo de modelo ('biomass', 'substrate', 'product')
6
+ :param equation: La ecuaci贸n como cadena de texto
7
+ :param params_str: Cadena de texto con los nombres de los par谩metros separados por comas
8
+ """
9
+ t_symbol = symbols('t')
10
+ # Definir 'X' como una funci贸n simb贸lica en sympy
11
+ X = Function('X')
12
+
13
+ try:
14
+ expr = sympify(equation)
15
+ except Exception as e:
16
+ raise ValueError(f"Error al parsear la ecuaci贸n '{equation}': {e}")
17
+
18
+ params = [param.strip() for param in params_str.split(',')]
19
+ params_symbols = symbols(params)
20
+
21
+ # Extraer s铆mbolos utilizados en la expresi贸n
22
+ used_symbols = expr.free_symbols
23
+ # Convertir s铆mbolos a strings
24
+ used_params = [str(s) for s in used_symbols if s != t_symbol]
25
+
26
+ # Verificar que todos los par谩metros en params_str est茅n usados en la ecuaci贸n
27
+ for param in params:
28
+ if param not in used_params:
29
+ raise ValueError(f"El par谩metro '{param}' no se usa en la ecuaci贸n '{equation}'.")
30
+
31
+ if model_type == 'biomass':
32
+ # Biomasa como funci贸n de tiempo y par谩metros
33
+ func_expr = expr
34
+ func = lambdify((t_symbol, *params_symbols), func_expr, 'numpy')
35
+ self.models['biomass'] = {
36
+ 'function': func,
37
+ 'params': params
38
+ }
39
+ elif model_type in ['substrate', 'product']:
40
+ # Estos modelos dependen de biomasa, que ya deber铆a estar establecida
41
+ if 'biomass' not in self.models:
42
+ raise ValueError("Biomasa debe estar configurada antes de Sustrato o Producto.")
43
+ biomass_func = self.models['biomass']['function']
44
+ # Reemplazar 'X(t)' por la funci贸n de biomasa
45
+ func_expr = expr.subs('X(t)', biomass_func)
46
+ func = lambdify((t_symbol, *params_symbols), func_expr, 'numpy')
47
+ self.models[model_type] = {
48
+ 'function': func,
49
+ 'params': params
50
+ }
51
+ else:
52
+ raise ValueError(f"Tipo de modelo no soportado: {model_type}")