C2MV commited on
Commit
0496f09
1 Parent(s): 7f0e5b8

Update bioprocess_model.py

Browse files
Files changed (1) hide show
  1. 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
- @staticmethod
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
- Configures the model based on the type, equation, and parameters.
34
-
35
- :param model_type: Type of the model ('biomass', 'substrate', 'product')
36
- :param equation: The equation as a string
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
- expr = sympify(equation)
 
 
 
 
 
 
 
44
  except Exception as e:
45
- raise ValueError(f"Error al parsear la ecuación '{equation}': {e}")
46
-
47
- params = [param.strip() for param in params_str.split(',')]
48
- params_symbols = symbols(params)
49
 
50
- # Extraer símbolos utilizados en la expresión
51
- used_symbols = expr.free_symbols
52
- # Convertir símbolos a strings
53
- used_params = [str(s) for s in used_symbols if s != t_symbol]
54
-
55
- # Verificar que todos los parámetros en params_str estén usados en la ecuación
56
- for param in params:
57
- if param not in used_params:
58
- raise ValueError(f"El parámetro '{param}' no se usa en la ecuación '{equation}'.")
59
-
60
- if model_type == 'biomass':
61
- # Biomasa como función de tiempo y parámetros
62
- func_expr = expr
63
- func = lambdify((t_symbol, *params_symbols), func_expr, 'numpy')
64
- self.models['biomass'] = {
65
- 'function': func,
66
- 'params': params
67
  }
68
- elif model_type in ['substrate', 'product']:
69
- # Estos modelos dependen de biomasa, que ya debería estar establecida
70
- if 'biomass' not in self.models:
71
- raise ValueError("Biomasa debe estar configurada antes de Sustrato o Producto.")
72
- biomass_func = self.models['biomass']['function']
73
- # Reemplazar 'X(t)' por la función de biomasa
74
- func_expr = expr.subs('X(t)', biomass_func)
75
- func = lambdify((t_symbol, *params_symbols), func_expr, 'numpy')
76
- self.models[model_type] = {
77
- 'function': func,
78
- 'params': params
 
 
 
 
 
 
 
 
79
  }
80
- else:
81
- raise ValueError(f"Tipo de modelo no soportado: {model_type}")
82
 
83
  def fit_model(self, model_type, time, data, bounds=([-np.inf], [np.inf])):
84
  """
85
- Fits the model to the data.
86
-
87
- :param model_type: Type of the model ('biomass', 'substrate', 'product')
88
- :param time: Time data
89
- :param data: Observed data to fit
90
- :param bounds: Bounds for the parameters
91
- :return: Predicted data from the model
92
  """
93
  if model_type not in self.models:
94
- raise ValueError(f"Model type '{model_type}' is not set. Please use set_model first.")
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 = func(t, *args)
103
- return y
 
 
 
 
 
104
  except Exception as e:
105
  raise RuntimeError(f"Error en fit_func: {e}")
106
 
107
- # Definir una estimación inicial para los parámetros
108
  p0 = [1.0] * len(params) # Puedes ajustar estos valores según sea necesario
109
 
110
  try:
111
- # Definir los límites correctamente
112
- lower_bounds, upper_bounds = bounds
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 while fitting {model_type} model: {str(e)}")
 
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}")