|
|
|
|
|
import numpy as np |
|
from scipy.optimize import curve_fit |
|
from sklearn.metrics import mean_squared_error |
|
|
|
class BioprocessModel: |
|
def __init__(self): |
|
self.params = {} |
|
self.r2 = {} |
|
self.rmse = {} |
|
self.models = {} |
|
|
|
@staticmethod |
|
def logistic(time, xo, xm, um): |
|
return (xo * np.exp(um * time)) / (1 - (xo / xm) * (1 - np.exp(um * time))) |
|
|
|
def set_model_biomass(self, equation, params_str): |
|
""" |
|
Configura el modelo de Biomasa. |
|
|
|
:param equation: La ecuaci贸n de Biomasa como cadena de texto |
|
:param params_str: Cadena de par谩metros separados por comas |
|
""" |
|
try: |
|
|
|
def biomass_func(t, xo, xm, um): |
|
return (xo * np.exp(um * t)) / (1 - (xo / xm) * (1 - np.exp(um * t))) |
|
|
|
self.models['biomass'] = { |
|
'function': biomass_func, |
|
'params': [param.strip() for param in params_str.split(',')] |
|
} |
|
except Exception as e: |
|
raise ValueError(f"Error al configurar el modelo de biomasa: {e}") |
|
|
|
def set_model_substrate(self, equation, params_str): |
|
""" |
|
Configura el modelo de Sustrato. |
|
|
|
:param equation: La ecuaci贸n de Sustrato como cadena de texto (no usada en este enfoque) |
|
:param params_str: Cadena de par谩metros separados por comas |
|
""" |
|
try: |
|
|
|
def substrate_func(t, so, p, q, xo, xm, um): |
|
X_t = self.models['biomass']['function'](t, xo, xm, um) |
|
return so - p * X_t - q * np.log(1 - (xo / xm) * (1 - np.exp(um * t))) |
|
|
|
self.models['substrate'] = { |
|
'function': substrate_func, |
|
'params': [param.strip() for param in params_str.split(',')] |
|
} |
|
except Exception as e: |
|
raise ValueError(f"Error al configurar el modelo de sustrato: {e}") |
|
|
|
def set_model_product(self, equation, params_str): |
|
""" |
|
Configura el modelo de Producto. |
|
|
|
:param equation: La ecuaci贸n de Producto como cadena de texto (no usada en este enfoque) |
|
:param params_str: Cadena de par谩metros separados por comas |
|
""" |
|
try: |
|
|
|
def product_func(t, po, alpha, beta, xo, xm, um): |
|
X_t = self.models['biomass']['function'](t, xo, xm, um) |
|
return po + alpha * X_t + beta * np.log(1 - (xo / xm) * (1 - np.exp(um * t))) |
|
|
|
self.models['product'] = { |
|
'function': product_func, |
|
'params': [param.strip() for param in params_str.split(',')] |
|
} |
|
except Exception as e: |
|
raise ValueError(f"Error al configurar el modelo de producto: {e}") |
|
|
|
def fit_model(self, model_type, time, data, bounds=([-np.inf], [np.inf])): |
|
""" |
|
Ajusta el modelo a los datos. |
|
|
|
:param model_type: Tipo de modelo ('biomass', 'substrate', 'product') |
|
:param time: Datos de tiempo |
|
:param data: Datos observados para ajustar |
|
:param bounds: L铆mites para los par谩metros |
|
:return: Datos predichos por el modelo |
|
""" |
|
if model_type not in self.models: |
|
raise ValueError(f"Tipo de modelo '{model_type}' no est谩 configurado. Usa set_model primero.") |
|
|
|
func = self.models[model_type]['function'] |
|
params = self.models[model_type]['params'] |
|
|
|
|
|
def fit_func(t, *args): |
|
try: |
|
|
|
if model_type in ['substrate', 'product']: |
|
|
|
xo, xm, um = self.params['biomass']['xo'], self.params['biomass']['xm'], self.params['biomass']['um'] |
|
return func(t, *args, xo, xm, um) |
|
else: |
|
return func(t, *args) |
|
except Exception as e: |
|
raise RuntimeError(f"Error en fit_func: {e}") |
|
|
|
|
|
p0 = [1.0] * len(params) |
|
|
|
try: |
|
popt, _ = curve_fit(fit_func, time, data, p0=p0, bounds=bounds, maxfev=10000) |
|
|
|
self.params[model_type] = {param: val for param, val in zip(params, popt)} |
|
y_pred = fit_func(time, *popt) |
|
self.r2[model_type] = 1 - (np.sum((data - y_pred) ** 2) / np.sum((data - np.mean(data)) ** 2)) |
|
self.rmse[model_type] = np.sqrt(mean_squared_error(data, y_pred)) |
|
return y_pred |
|
except Exception as e: |
|
raise RuntimeError(f"Error al ajustar el modelo '{model_type}': {e}") |
|
|