C2MV commited on
Commit
a689c79
1 Parent(s): 65a427d

Create bioprocess_model.py

Browse files
Files changed (1) hide show
  1. bioprocess_model.py +148 -0
bioprocess_model.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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