Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
ADDED
@@ -0,0 +1,467 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
from scipy.integrate import odeint
|
3 |
+
import emcee
|
4 |
+
import panel as pn
|
5 |
+
import param
|
6 |
+
import plotly.graph_objects as go
|
7 |
+
from plotly.subplots import make_subplots
|
8 |
+
import plotly.io as pio
|
9 |
+
|
10 |
+
|
11 |
+
# Définition du thème sombre
|
12 |
+
pio.templates.default = "plotly_dark"
|
13 |
+
|
14 |
+
# Initialiser l'extension Panel
|
15 |
+
pn.extension('katex', 'mathjax', 'plotly')
|
16 |
+
|
17 |
+
# Informations personnelles
|
18 |
+
photo_url = "PPFB.png"
|
19 |
+
prenom = "Yaya"
|
20 |
+
nom = "Toure"
|
21 |
+
email = "[email protected]"
|
22 |
+
whatsapps_url = "https://wa.me/message/GW7RWRW3GR4WN1"
|
23 |
+
linkedin_url = "https://www.linkedin.com/in/yaya-toure-8251a4280/"
|
24 |
+
github_url = "https://github.com/CodingYayaToure"
|
25 |
+
universite = "UNCHK"
|
26 |
+
formation = "Licence Analyse Numerique et Modelisation | Master Calcul scientifique et Modelisation"
|
27 |
+
certificat = "Collecte et Fouille de Donnees (UADB-CNAM Paris)"
|
28 |
+
TP_Scilab = "https://codingyayatoure.github.io/Equation_de_Transport_en_1D_par_la_Methode_des_Differences_Finis/"
|
29 |
+
|
30 |
+
# Créer le template du tableau de bord
|
31 |
+
template = pn.template.ReactTemplate(title='Progiciel de Simulation des Interactions Microbiennes en Fermentation de Jus de Légumes. | Approche Modélisation mathématique ')
|
32 |
+
|
33 |
+
# Classe pour la dynamique Consumer-Resource
|
34 |
+
class ConsumerResourceApp(param.Parameterized):
|
35 |
+
# Paramètres du modèle
|
36 |
+
r = param.Number(10.0, bounds=(0.1, 20.0), step=0.1, doc="Taux d'approvisionnement en ressources")
|
37 |
+
d = param.Number(0.1, bounds=(0.01, 1.0), step=0.01, doc="Taux de mortalité des consommateurs")
|
38 |
+
c = param.Number(0.1, bounds=(0.01, 1.0), step=0.01, doc="Coefficient de consommation")
|
39 |
+
K = param.Number(1.0, bounds=(0.1, 10.0), step=0.1, doc="Concentration à laquelle la croissance est à moitié maximale")
|
40 |
+
X0 = param.Number(1.0, bounds=(0.1, 10.0), step=0.1, doc="Population initiale des consommateurs")
|
41 |
+
S0 = param.Number(5.0, bounds=(0.1, 20.0), step=0.1, doc="Concentration initiale de la ressource")
|
42 |
+
|
43 |
+
@param.depends('r', 'd', 'c', 'K', 'X0', 'S0')
|
44 |
+
def view(self):
|
45 |
+
# Fonction de croissance dépendante de la ressource (Monod)
|
46 |
+
def mu(S):
|
47 |
+
return S / (self.K + S)
|
48 |
+
|
49 |
+
# Équations différentielles
|
50 |
+
def model(y, t):
|
51 |
+
X, S = y
|
52 |
+
dXdt = mu(S) * X - self.d * X # Dynamique des consommateurs
|
53 |
+
dSdt = self.r - self.c * mu(S) * X # Dynamique des ressources
|
54 |
+
return [dXdt, dSdt]
|
55 |
+
|
56 |
+
# Conditions initiales
|
57 |
+
y0 = [self.X0, self.S0]
|
58 |
+
|
59 |
+
# Temps pour la simulation (en heures)
|
60 |
+
t_hours = np.linspace(0, 100, 500)
|
61 |
+
|
62 |
+
# Résoudre le système d'équations différentielles
|
63 |
+
solution = odeint(model, y0, t_hours)
|
64 |
+
|
65 |
+
# Créer les graphiques avec Plotly en utilisant des sous-graphiques
|
66 |
+
fig = make_subplots(
|
67 |
+
rows=1, cols=3,
|
68 |
+
specs=[[{'type': 'scatter'}, {'type': 'scatter'}, {'type': 'scatter'}]],
|
69 |
+
subplot_titles=["Population des Consommateurs (X)", "Concentration de la Ressource (S)", "Population et Ressource sur le même repère"]
|
70 |
+
)
|
71 |
+
|
72 |
+
# Ajouter la trace pour les consommateurs
|
73 |
+
fig.add_trace(go.Scatter(x=t_hours, y=solution[:, 0], mode='lines', name='Population des Consommateurs (X)', line=dict(color='blue')), row=1, col=1)
|
74 |
+
|
75 |
+
# Ajouter la trace pour les ressources
|
76 |
+
fig.add_trace(go.Scatter(x=t_hours, y=solution[:, 1], mode='lines', name='Concentration de la Ressource (S)', line=dict(color='green')), row=1, col=2)
|
77 |
+
|
78 |
+
# Ajouter la trace pour les consommateurs et les ressources sur le même graphique
|
79 |
+
fig.add_trace(go.Scatter(x=t_hours, y=solution[:, 0], mode='lines', name='Population des Consommateurs (X)', line=dict(color='blue')), row=1, col=3)
|
80 |
+
fig.add_trace(go.Scatter(x=t_hours, y=solution[:, 1], mode='lines', name='Concentration de la Ressource (S)', line=dict(color='green')), row=1, col=3)
|
81 |
+
|
82 |
+
# Mettre à jour la mise en page du graphique
|
83 |
+
fig.update_layout(
|
84 |
+
title='Dynamique du Modèle Consumer-Resource',
|
85 |
+
xaxis_title='Temps',
|
86 |
+
yaxis_title='Population / Concentration',
|
87 |
+
legend_title='Légende',
|
88 |
+
height=400,
|
89 |
+
width=1500,
|
90 |
+
font_color="white",
|
91 |
+
template='plotly_dark'
|
92 |
+
)
|
93 |
+
|
94 |
+
return pn.pane.Plotly(fig)
|
95 |
+
|
96 |
+
def panel_view(self):
|
97 |
+
return pn.Column(
|
98 |
+
pn.Row(pn.Param(self, width=400), self.formulas()), # Aligner les widgets et les formules sur la même ligne
|
99 |
+
self.view # Appeler la vue pour qu'elle se mette à jour dynamiquement
|
100 |
+
)
|
101 |
+
|
102 |
+
def formulas(self):
|
103 |
+
return pn.Column(
|
104 |
+
pn.pane.LaTeX(r"""
|
105 |
+
$$
|
106 |
+
\text{Fonction de croissance : } \mu(S) = \frac{S}{K + S}
|
107 |
+
$$
|
108 |
+
""", styles={'font-size': '16pt'}),
|
109 |
+
pn.pane.LaTeX(r"""
|
110 |
+
$$
|
111 |
+
\text{Dynamique des consommateurs : } \frac{dX}{dt} = \mu(S) \times X - d \times X
|
112 |
+
$$
|
113 |
+
""", styles={'font-size': '16pt'}),
|
114 |
+
pn.pane.LaTeX(r"""
|
115 |
+
$$
|
116 |
+
\text{Dynamique des ressources : } \frac{dS}{dt} = r - c \times \mu(S) \times X
|
117 |
+
$$
|
118 |
+
""", styles={'font-size': '16pt'})
|
119 |
+
)
|
120 |
+
|
121 |
+
# Classe pour la dynamique des populations microbiennes
|
122 |
+
class MicrobialDynamicsApp(param.Parameterized):
|
123 |
+
# Paramètres du modèle pour la dynamique des populations microbiennes
|
124 |
+
r1 = param.Number(0.5, bounds=(0.1, 1.0), step=0.01, doc="Taux de croissance espèce 1")
|
125 |
+
r2 = param.Number(0.3, bounds=(0.1, 1.0), step=0.01, doc="Taux de croissance espèce 2")
|
126 |
+
K1 = param.Number(100, bounds=(10, 200), step=1, doc="Capacité de charge espèce 1")
|
127 |
+
K2 = param.Number(80, bounds=(10, 200), step=1, doc="Capacité de charge espèce 2")
|
128 |
+
alpha = param.Number(0.01, bounds=(0.001, 0.1), step=0.001, doc="Compétition espèce 2 sur espèce 1")
|
129 |
+
beta = param.Number(0.01, bounds=(0.001, 0.1), step=0.001, doc="Compétition espèce 1 sur espèce 2")
|
130 |
+
|
131 |
+
@param.depends('r1', 'r2', 'K1', 'K2', 'alpha', 'beta')
|
132 |
+
def view(self):
|
133 |
+
# Équations différentielles pour les populations microbiennes
|
134 |
+
def model(y, t):
|
135 |
+
X1, X2 = y
|
136 |
+
dX1dt = self.r1 * X1 * (1 - (X1 + self.alpha * X2) / self.K1)
|
137 |
+
dX2dt = self.r2 * X2 * (1 - (X2 + self.beta * X1) / self.K2)
|
138 |
+
return [dX1dt, dX2dt]
|
139 |
+
|
140 |
+
# Conditions initiales
|
141 |
+
y0 = [10, 5] # Population initiale des deux espèces
|
142 |
+
|
143 |
+
# Temps pour la simulation
|
144 |
+
t = np.linspace(0, 50, 500)
|
145 |
+
|
146 |
+
# Résoudre le système d'équations différentielles
|
147 |
+
solution = odeint(model, y0, t)
|
148 |
+
|
149 |
+
# Créer le graphique avec Plotly
|
150 |
+
fig = go.Figure()
|
151 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 0], mode='lines', name='Espèce 1', line=dict(color='red')))
|
152 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 1], mode='lines', name='Espèce 2', line=dict(color='purple')))
|
153 |
+
|
154 |
+
# Mettre à jour la mise en page du graphique
|
155 |
+
fig.update_layout(
|
156 |
+
title='Dynamique des Populations Microbiennes',
|
157 |
+
xaxis_title='Temps',
|
158 |
+
yaxis_title='Population',
|
159 |
+
legend_title='Légende',
|
160 |
+
height=400,
|
161 |
+
width=1500,
|
162 |
+
font_color="white",
|
163 |
+
template='plotly_dark'
|
164 |
+
)
|
165 |
+
|
166 |
+
return pn.pane.Plotly(fig)
|
167 |
+
|
168 |
+
def panel_view(self):
|
169 |
+
return pn.Column(
|
170 |
+
pn.Row(pn.Param(self, width=400), self.formulas()), # Aligner les widgets et les formules sur la même ligne
|
171 |
+
self.view # Appeler la vue pour qu'elle se mette à jour dynamiquement
|
172 |
+
)
|
173 |
+
|
174 |
+
def formulas(self):
|
175 |
+
return pn.Column(
|
176 |
+
pn.pane.LaTeX(r"""
|
177 |
+
$$
|
178 |
+
\frac{{dX_1}}{{dt}} = r_1 X_1 \left( 1 - \frac{{X_1 + \alpha X_2}}{{K_1}} \right)
|
179 |
+
$$
|
180 |
+
""", styles={'font-size': '16pt'}),
|
181 |
+
pn.pane.LaTeX(r"""
|
182 |
+
$$
|
183 |
+
\frac{{dX_2}}{{dt}} = r_2 X_2 \left( 1 - \frac{{X_2 + \beta X_1}}{{K_2}} \right)
|
184 |
+
$$
|
185 |
+
""", styles={'font-size': '16pt'})
|
186 |
+
)
|
187 |
+
|
188 |
+
# Classe pour la modélisation de la fermentation
|
189 |
+
class FermentationModelApp(param.Parameterized):
|
190 |
+
# Paramètres du modèle de fermentation
|
191 |
+
mu_max = param.Number(0.8, bounds=(0.1, 2.0), step=0.1, doc="Taux de croissance maximal")
|
192 |
+
Ks = param.Number(10.0, bounds=(1.0, 50.0), step=1.0, doc="Constante de demi-saturation")
|
193 |
+
Yxs = param.Number(0.5, bounds=(0.1, 1.0), step=0.1, doc="Rendement de croissance sur substrat")
|
194 |
+
Sin = param.Number(20.0, bounds=(10.0, 100.0), step=1.0, doc="Concentration initiale en substrat")
|
195 |
+
X0 = param.Number(0.1, bounds=(0.01, 5.0), step=0.01, doc="Concentration initiale en biomasse")
|
196 |
+
P0 = param.Number(0.0, bounds=(0.0, 5.0), step=0.1, doc="Concentration initiale en produit")
|
197 |
+
|
198 |
+
@param.depends('mu_max', 'Ks', 'Yxs', 'Sin', 'X0', 'P0')
|
199 |
+
def view(self):
|
200 |
+
# Équations différentielles pour la fermentation
|
201 |
+
def model(y, t):
|
202 |
+
X, S, P = y
|
203 |
+
mu = self.mu_max * S / (self.Ks + S)
|
204 |
+
dXdt = mu * X
|
205 |
+
dSdt = -dXdt / self.Yxs
|
206 |
+
dPdt = 0.1 * dXdt # Production de produit proportionnelle à la croissance
|
207 |
+
return [dXdt, dSdt, dPdt]
|
208 |
+
|
209 |
+
# Conditions initiales
|
210 |
+
y0 = [self.X0, self.Sin, self.P0]
|
211 |
+
|
212 |
+
# Temps pour la simulation
|
213 |
+
t = np.linspace(0, 50, 500)
|
214 |
+
|
215 |
+
# Résoudre le système d'équations différentielles
|
216 |
+
solution = odeint(model, y0, t)
|
217 |
+
|
218 |
+
# Créer le graphique avec Plotly
|
219 |
+
fig = go.Figure()
|
220 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 0], mode='lines', name='Biomasse (X)', line=dict(color='blue')))
|
221 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 1], mode='lines', name='Substrat (S)', line=dict(color='green')))
|
222 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 2], mode='lines', name='Produit (P)', line=dict(color='orange')))
|
223 |
+
|
224 |
+
# Mettre à jour la mise en page du graphique
|
225 |
+
fig.update_layout(
|
226 |
+
title='Modélisation de la Fermentation',
|
227 |
+
xaxis_title='Temps',
|
228 |
+
yaxis_title='Concentration',
|
229 |
+
legend_title='Légende',
|
230 |
+
height=400,
|
231 |
+
width=1500,
|
232 |
+
font_color="white",
|
233 |
+
template='plotly_dark'
|
234 |
+
)
|
235 |
+
|
236 |
+
return pn.pane.Plotly(fig)
|
237 |
+
|
238 |
+
|
239 |
+
def formulas(self):
|
240 |
+
return pn.Column(
|
241 |
+
pn.pane.LaTeX(r"""
|
242 |
+
$$
|
243 |
+
\mu = \frac{{\mu_{{\text{{max}}}} \cdot S}}{{K_s + S}}
|
244 |
+
$$
|
245 |
+
""", styles={'font-size': '16pt'}),
|
246 |
+
pn.pane.LaTeX(r"""
|
247 |
+
$$
|
248 |
+
\frac{{dX}}{{dt}} = \mu \cdot X
|
249 |
+
$$
|
250 |
+
""", styles={'font-size': '16pt'}),
|
251 |
+
pn.pane.LaTeX(r"""
|
252 |
+
$$
|
253 |
+
\frac{{dS}}{{dt}} = -\frac{1}{{Y_{{xs}}}} \cdot \frac{{dX}}{{dt}}
|
254 |
+
$$
|
255 |
+
""", styles={'font-size': '16pt'}),
|
256 |
+
pn.pane.LaTeX(r"""
|
257 |
+
$$
|
258 |
+
\frac{{dP}}{{dt}} = 0.1 \cdot \frac{{dX}}{{dt}}
|
259 |
+
$$
|
260 |
+
""", styles={'font-size': '16pt'})
|
261 |
+
)
|
262 |
+
|
263 |
+
|
264 |
+
|
265 |
+
def panel_view(self):
|
266 |
+
return pn.Column(
|
267 |
+
pn.Row(pn.Param(self, width=400), self.formulas()), # Aligner les widgets et les formules sur la même ligne
|
268 |
+
self.view # Appeler la vue pour qu'elle se mette à jour dynamiquement
|
269 |
+
)
|
270 |
+
|
271 |
+
# Classe pour l'estimation des paramètres par MCMC
|
272 |
+
class EstimationParametresFermentation(param.Parameterized):
|
273 |
+
# Paramètres pour l'estimation MCMC
|
274 |
+
n_marcheurs = param.Integer(32, bounds=(10, 100), doc="Nombre de marcheurs MCMC")
|
275 |
+
n_etapes = param.Integer(1000, bounds=(100, 5000), doc="Nombre d'étapes MCMC")
|
276 |
+
niveau_bruit = param.Number(0.1, bounds=(0.01, 0.5), doc="Niveau de bruit dans les données synthétiques")
|
277 |
+
|
278 |
+
def __init__(self, **params):
|
279 |
+
super().__init__(**params)
|
280 |
+
self.parametres_reels = {
|
281 |
+
'mu_max': 0.8,
|
282 |
+
'Ks': 10.0,
|
283 |
+
'Yxs': 0.5
|
284 |
+
}
|
285 |
+
|
286 |
+
def generer_donnees_synthetiques(self, t):
|
287 |
+
def modele(y, t, mu_max, Ks, Yxs):
|
288 |
+
X, S, P = y
|
289 |
+
mu = mu_max * S / (Ks + S)
|
290 |
+
dXdt = mu * X
|
291 |
+
dSdt = -dXdt / Yxs
|
292 |
+
dPdt = 0.1 * dXdt
|
293 |
+
return [dXdt, dSdt, dPdt]
|
294 |
+
|
295 |
+
y0 = [0.1, 20.0, 0.0]
|
296 |
+
solution = odeint(modele, y0, t, args=(self.parametres_reels['mu_max'], self.parametres_reels['Ks'], self.parametres_reels['Yxs']))
|
297 |
+
bruit = np.random.normal(0, self.niveau_bruit, solution.shape)
|
298 |
+
return solution + bruit
|
299 |
+
|
300 |
+
def log_vraisemblance(self, theta, t, donnees):
|
301 |
+
mu_max, Ks, Yxs = theta
|
302 |
+
|
303 |
+
def modele(y, t, mu_max, Ks, Yxs):
|
304 |
+
X, S, P = y
|
305 |
+
mu = mu_max * S / (Ks + S)
|
306 |
+
dXdt = mu * X
|
307 |
+
dSdt = -dXdt / Yxs
|
308 |
+
dPdt = 0.1 * dXdt
|
309 |
+
return [dXdt, dSdt, dPdt]
|
310 |
+
|
311 |
+
y0 = [0.1, 20.0, 0.0]
|
312 |
+
try:
|
313 |
+
solution = odeint(modele, y0, t, args=(mu_max, Ks, Yxs))
|
314 |
+
sigma2 = self.niveau_bruit ** 2
|
315 |
+
return -0.5 * np.sum((donnees - solution) ** 2 / sigma2 + np.log(2 * np.pi * sigma2))
|
316 |
+
except:
|
317 |
+
return -np.inf
|
318 |
+
|
319 |
+
def log_apriori(self, theta):
|
320 |
+
mu_max, Ks, Yxs = theta
|
321 |
+
if 0.1 < mu_max < 2.0 and 1.0 < Ks < 50.0 and 0.1 < Yxs < 1.0:
|
322 |
+
return 0.0
|
323 |
+
return -np.inf
|
324 |
+
|
325 |
+
def log_probabilite(self, theta, t, donnees):
|
326 |
+
lp = self.log_apriori(theta)
|
327 |
+
if not np.isfinite(lp):
|
328 |
+
return -np.inf
|
329 |
+
return lp + self.log_vraisemblance(theta, t, donnees)
|
330 |
+
|
331 |
+
def lancer_mcmc(self):
|
332 |
+
t = np.linspace(0, 50, 50)
|
333 |
+
donnees = self.generer_donnees_synthetiques(t)
|
334 |
+
ndim = 3
|
335 |
+
pos = [
|
336 |
+
[self.parametres_reels['mu_max'], self.parametres_reels['Ks'], self.parametres_reels['Yxs']] + 1e-4 * np.random.randn(ndim)
|
337 |
+
for i in range(self.n_marcheurs)
|
338 |
+
]
|
339 |
+
sampler = emcee.EnsembleSampler(self.n_marcheurs, ndim, self.log_probabilite, args=(t, donnees))
|
340 |
+
sampler.run_mcmc(pos, self.n_etapes, progress=True)
|
341 |
+
return sampler, t, donnees
|
342 |
+
|
343 |
+
@param.depends('n_marcheurs', 'n_etapes', 'niveau_bruit')
|
344 |
+
def vue(self):
|
345 |
+
sampler, t, donnees = self.lancer_mcmc()
|
346 |
+
|
347 |
+
fig = make_subplots(rows=2, cols=2,
|
348 |
+
subplot_titles=('Chaînes MCMC', 'Distribution postérieure', 'Ajustement du modèle', 'Corrélations des paramètres'))
|
349 |
+
|
350 |
+
echantillons = sampler.get_chain()
|
351 |
+
|
352 |
+
# Tracer les chaînes MCMC
|
353 |
+
for i in range(3):
|
354 |
+
fig.add_trace(go.Scatter(y=echantillons[:, 0, i], mode='lines', name=f'Paramètre {i+1}'), row=1, col=1)
|
355 |
+
|
356 |
+
echantillons_plats = sampler.get_chain(discard=100, thin=15, flat=True)
|
357 |
+
|
358 |
+
# Tracer les distributions postérieures
|
359 |
+
for i in range(3):
|
360 |
+
fig.add_trace(go.Histogram(x=echantillons_plats[:, i], name=f'Paramètre {i+1}', nbinsx=30), row=1, col=2)
|
361 |
+
|
362 |
+
params_med = np.median(echantillons_plats, axis=0)
|
363 |
+
y0 = [0.1, 20.0, 0.0]
|
364 |
+
|
365 |
+
# Définir une fonction de modèle pour odeint
|
366 |
+
def modele(y, t):
|
367 |
+
mu_max, Ks, Yxs = params_med
|
368 |
+
X, S, P = y
|
369 |
+
mu = mu_max * S / (Ks + S)
|
370 |
+
dXdt = mu * X
|
371 |
+
dSdt = -dXdt / Yxs
|
372 |
+
dPdt = 0.1 * dXdt
|
373 |
+
return [dXdt, dSdt, dPdt]
|
374 |
+
|
375 |
+
# Utiliser la fonction de modèle dans odeint
|
376 |
+
solution = odeint(modele, y0, t)
|
377 |
+
|
378 |
+
fig.add_trace(go.Scatter(x=t, y=donnees[:, 0], mode='markers', name='Données (X)', marker=dict(color='blue')), row=2, col=1)
|
379 |
+
fig.add_trace(go.Scatter(x=t, y=solution[:, 0], mode='lines', name='Modèle (X)', line=dict(color='red')), row=2, col=1)
|
380 |
+
|
381 |
+
# Tracer les corrélations des paramètres
|
382 |
+
fig.add_trace(go.Scatter(x=echantillons_plats[:, 0], y=echantillons_plats[:, 1],
|
383 |
+
mode='markers', marker=dict(size=2),
|
384 |
+
name='mu_max vs Ks'), row=2, col=2)
|
385 |
+
|
386 |
+
fig.update_layout(height=400, width=1200,
|
387 |
+
showlegend=True,
|
388 |
+
template='plotly_dark')
|
389 |
+
|
390 |
+
return pn.pane.Plotly(fig)
|
391 |
+
|
392 |
+
def vue_panneau(self):
|
393 |
+
return pn.Column(
|
394 |
+
pn.Row(
|
395 |
+
pn.Param(self.param,
|
396 |
+
widgets={
|
397 |
+
'n_marcheurs': pn.widgets.IntSlider,
|
398 |
+
'n_etapes': pn.widgets.IntSlider,
|
399 |
+
'niveau_bruit': pn.widgets.FloatSlider}),
|
400 |
+
self.description_mcmc()
|
401 |
+
),
|
402 |
+
self.vue # Correction pour supprimer '()' et référencer dynamiquement
|
403 |
+
)
|
404 |
+
|
405 |
+
def description_mcmc(self):
|
406 |
+
return pn.pane.Markdown("""
|
407 |
+
# Estimation des paramètres par MCMC
|
408 |
+
## Cette section permet d'estimer les paramètres du modèle de fermentation en utilisant l'algorithme MCMC (Markov Chain Monte Carlo).
|
409 |
+
- ## **n_marcheurs**: Nombre de chaînes MCMC parallèles.
|
410 |
+
- ## **n_etapes**: Nombre d'itérations pour chaque chaîne.
|
411 |
+
- ## **niveau_bruit**: Niveau de bruit dans les données synthétiques.
|
412 |
+
## Les graphiques montrent:
|
413 |
+
### 1. L'évolution des chaînes MCMC.
|
414 |
+
### 2. Les distributions postérieures des paramètres.
|
415 |
+
### 3. L'ajustement du modèle aux données.
|
416 |
+
### 4. Les corrélations entre les paramètres.
|
417 |
+
""")
|
418 |
+
|
419 |
+
# Informations personnelles et photo
|
420 |
+
photo = pn.pane.PNG(photo_url, width=200, height=200)
|
421 |
+
info = pn.Column(
|
422 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Prénom</strong>: {prenom}</div>"),
|
423 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Nom</strong>: {nom}</div>"),
|
424 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Email</strong>: <a href='mailto:{email}'>{email}</a></div>"),
|
425 |
+
#pn.pane.Markdown(f"<div style='font-size:16px'><strong>WhatsApp</strong>: <a href='{whatsapps_url}'>WhatsApp</a></div>"),
|
426 |
+
#pn.pane.Markdown(f"<div style='font-size:16px'><strong>LinkedIn</strong>: <a href='{linkedin_url}'>LinkedIn</a></div>"),
|
427 |
+
# pn.pane.Markdown(f"<div style='font-size:16px'><strong>GitHub</strong>: <a href='{github_url}'>GitHub</a></div>"),
|
428 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Université</strong>: {universite}</div>"),
|
429 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Formation</strong>: {formation}</div>"),
|
430 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Certificat</strong>: {certificat}</div>"),
|
431 |
+
pn.pane.Markdown(f"<div style='font-size:16px'><strong>Autre Projet </strong>: <a href='{TP_Scilab}'>Pour comprendre l'équation de Transport en 1D avec Scilab</a></div>"),
|
432 |
+
sizing_mode='stretch_width'
|
433 |
+
)
|
434 |
+
|
435 |
+
|
436 |
+
|
437 |
+
# Créer les applications
|
438 |
+
consumer_app = ConsumerResourceApp()
|
439 |
+
microbial_app = MicrobialDynamicsApp()
|
440 |
+
ferm_app = FermentationModelApp()
|
441 |
+
|
442 |
+
# Créer l'application
|
443 |
+
application_estimation_parametres = EstimationParametresFermentation()
|
444 |
+
|
445 |
+
# Afficher l'application Panel
|
446 |
+
#template = pn.template.ReactTemplate(title='Estimation des paramètres par MCMC')
|
447 |
+
#template.main[0, 0] = application_estimation_parametres.vue_panneau()
|
448 |
+
|
449 |
+
|
450 |
+
# Créer la mise en page
|
451 |
+
layout = pn.Row(
|
452 |
+
pn.Column(photo, info, width=300), # Ajouter la photo et les informations personnelles à gauche
|
453 |
+
pn.Column(
|
454 |
+
pn.Tabs(
|
455 |
+
('Consumer-Resource Dynamics', consumer_app.panel_view()),
|
456 |
+
('Microbial Dynamics', microbial_app.panel_view()),
|
457 |
+
(' Fermentation', ferm_app.panel_view()),
|
458 |
+
('Estimation Parametres', application_estimation_parametres.vue_panneau())
|
459 |
+
)
|
460 |
+
)
|
461 |
+
)
|
462 |
+
|
463 |
+
# Ajouter le layout au template principal
|
464 |
+
template.main[0, 0] = layout
|
465 |
+
|
466 |
+
# Exécuter l'application
|
467 |
+
template.servable()
|