<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<?xml-stylesheet type="text/css" href="http://blog.madpowah.org/"?>


<title type="html">cloud's Blog</title>
<subtitle type="html">Security / FreeBSD / *NIX blog</subtitle>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org"/>
<link rel="self" type="application/atom+xml" href="http://blog.madpowah.org/atom.xml"/>
<updated>2022-04-02T18:11:39+02:00</updated>
<author>
<name>cloud</name>
<uri>http://blog.madpowah.org</uri>
</author>
<id>http://blog.madpowah.org/</id>
<generator uri="http://nanoblogger.sourceforge.net" version="3.5-RC1">
NanoBlogger
</generator>

<entry>
<title type="html">[Data Analytics] Analyse python Population francaise </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2022/04/index.html#e2022-04-02T17_54_25.txt"/>

<id>http://blog.madpowah.org/archives/2022/04/index.html#e2022-04-02T17_54_25.txt</id>
<published>2022-04-02T17:54:25+02:00</published>
<updated>2022-04-02T17:54:25+02:00</updated>
<category term="Fun / Divers" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Je me suis amus&eacute; &agrave; faire un peu de Data Analytics en python pour voir les infos qu'on pouvait tirer de l'ensemble des d&eacute;c&egrave;s en France depuis 1970.
J'en ai fait un article que vous pouvez trouver sur <a href="https://medium.com/@madpowah/france-population-analysis-with-python-9c2999150ace" target="_blank">Medium ici.</a>
<br /><br />
Et si quelqu'un a la raison pour laquelle les 2 personnes de 144ans n'ont jamais &eacute;t&eacute; identifi&eacute;es comme les plus vieilles du monde, je suis preneur :)
<br /><br />
Have fun.
</div>
</content>

</entry>
<entry>
<title type="html">Configuration Reverse Proxy pour Streamlit </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2022/04/index.html#e2022-04-02T17_33_43.txt"/>

<id>http://blog.madpowah.org/archives/2022/04/index.html#e2022-04-02T17_33_43.txt</id>
<published>2022-04-02T17:33:43+02:00</published>
<updated>2022-04-02T17:33:43+02:00</updated>
<category term="OpenSource" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>Streamlit int&eacute;grant un serveur web d&eacute;di&eacute;, il n&eacute;cessite un port propre &agrave; lui. Il peut donc etre pratique de le mettre derri&egrave;re un Reverse Proxy pour y acc&eacute;der sur le port 80 ou 443.</p>
<p>Ayant un peu bataill&eacute; car il faut le mettre en place pour les requete HTTP mais &eacute;galement les Websocket, je partage donc une conf op&eacute;rationnelle<p>
<p>Cot&eacute; Apache, on va activer les mods suivants :<p>
<pre>
a2enmod proxy proxy_http proxy_wstunnel
</pre>
<p>Ensuite on va cr&eacute;er un fichier /etc/apache2/sites-available/proxy_perso.conf contenant notre conf</p>
<pre>
&lt;VirtualHost *:80&gt;
        ServerName      ml.madpowah.org
        ServerAdmin     admin@mail.com

        ErrorLog        ${APACHE_LOG_DIR}/error-streamlit.log
        CustomLog       ${APACHE_LOG_DIR}/access-streamlit.log combined
        ProxyPreserveHost       On
        ProxyRequests           Off
        &lt;Proxy *&gt;
                order deny,allow
                Allow from all
        &lt;/Proxy&gt;
        ProxyPass	 / "http://127.0.0.1:8501/"
        ProxypassReverse / "http://127.0.0.1:8501/"
        &lt;Location "/stream"&gt;
                ProxyPass		ws://127.0.0.1:8501/stream
                ProxyPassReverse        ws://127.0.0.1:8501/stream
        &lt;/Location&gt;
&lt;/VirtualHost&gt;
</pre>
<p>
On red&eacute;marre Apache et si on n'a pas de retour c'est que c'est bon.
</p>
<pre>
systemctl restart apache2
</pre>
<br/>
J'en profite pour mettre du coup <a href="http://ml.madpowah.org" target="_blank">l'adresse pour quelques démo de ML avec streamlit.</a><br /><br />
Have Fun !
</div>
</content>

</entry>
<entry>
<title type="html">Streamlit Framework Python pour DataScience </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2020/06/index.html#e2020-06-02T22_48_53.txt"/>

<id>http://blog.madpowah.org/archives/2020/06/index.html#e2020-06-02T22_48_53.txt</id>
<published>2020-06-02T22:48:53+02:00</published>
<updated>2020-06-02T22:48:53+02:00</updated>
<category term="OpenSource" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Le Data Science est un domaine int&eacute;ressant permettant d'observer ce qui se d&eacute;roule dans de divers secteurs et d'en &eacute;mettre ses hypoth&egrave;ses. Pour pouvoir en discuter, il faut 
aussi pouvoir les pr&eacute;senter. C'est pour cela que j'ai test&eacute; et adopt&eacute; <a href="https://www.streamlit.io/" target="_blank">le framework Streamlit</a>.
<br /><br />
Streamlit est un framework python offrant des outils permettant d'afficher via un serveur web ses graphiques ainsi que les r&eacute;sultats des dataframes. Il permet d'afficher 
directement via la lib matplotlib mais poss&egrave;de &eacute;galement ses propres librairie permettant de cr&eacute;er rapidement des boutons, graphiques en tous genres.
<br /><br />
Pour ma part j'ai donc mis en page mes tests de code pour le suivi du Covid-19 sur la page <a href="http://ml.madpowah.org" target="_blank">http://ml.madpowah.org</a>. Vous y trouverez :<br />
<ul>
	<li>Suivi du Covid-19 en France
		<ul>
			<li>Evolution nombre de cas / gu&eacute;ris / d&eacute;c&egrave;s</li>
			<li>Evolution quotidienne filtr&eacute; via un filtre gaussien pour lisser le tout</li>
			<li>Evolution par age / sexe</li>
			<li>Hospitalisations / R&eacute;animations</li>
		</ul>
	</li>
	<li>Suivi dans le monde avec choix du pays</li>
	<li>D&eacute;monstration d'un syst&egrave;me pr&eacute;dictif en Time s&eacute;ries avec mod&egrave;le ARIMA</li>
	<li>D&eacute;mo d'un Sentiment Analysis sur des termes #covid #stopcovid analys&eacute; sur twitter via tweepy. La base des avis a &eacute;t&eacute; cr&eacute;&eacute;e par mes soins et stock&eacute;e via MongoDB</li>
	<li>Page de test du moteur de Sentiment Analysis (TFIDF + Naive Bay&eacute;sienne)</li>
</ul>
<br />
Il me reste pas mal de choses &agrave; tester dans ce domaine donc sujet &agrave suivre !
</div>
</content>

</entry>
<entry>
<title type="html">Exemple de Data Science sur Covid-19 et Predictions</title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2020/05/index.html#e2020-05-03T00_38_35.txt"/>

<id>http://blog.madpowah.org/archives/2020/05/index.html#e2020-05-03T00_38_35.txt</id>
<published>2020-05-03T00:38:35+02:00</published>
<updated>2020-05-03T00:38:35+02:00</updated>
<category term="Fun / Divers" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
La p&eacute;riode est propice &agrave; analyser les choses donc c'est ce que je vais proposer via quelques courbes grace aux donn&eacute;es 
mise &agrave; disposition. L'occasion de d&eacute;couvrir les data sciences.
<p>
Je pr&eacute;viens avant, je ne suis ni &eacute;pid&eacute;miologiste ou quoi que ce soit donc ce que je dis n'engage que moi et j'interprete selon mes pens&eacute;es.
</p>
<p>
Tout d'abord nous allons commencer par utiliser <a href="https://www.data.gouv.fr/fr/datasets/donnees-des-urgences-hospitalieres-et-de-sos-medecins-relatives-a-lepidemie-de-covid-19/" target="_blank"> les donn&eacute;es mises &agrave; disposition par le gouvernement.</a>
.
</p>
<p>
<b>Analyse globale</b><br />
Commencons par regarder globalement l'&eacute;volution des personnes hospitalis&eacute;es pour Covid. Pour cela on va charger notre fichier CSV avec la librairie Pandas puis utiliser Seaborn 
pour mettre tout ca en graphique.

<pre>
import matplotlib.pyplot as plt
import pandas as pd

pd.plotting.register_matplotlib_converters()
import seaborn as sns

# Fichier de data sur data.gouv.fr
file = "sursaud-covid19-quotidien-2020-04-30-19h00-France.csv"

# On va utiliser Pandas pour traiter ca et on va selectionner de maniere differenciee chaque age (y a plus propre mais c'est plus lisible je trouve)
txt = pd.read_csv(file)

# On choisi tous les cas quels que soit leur age
data = txt[txt['sursaud_cl_age_corona'] == '0']
# On va reduire l'index de chaque en divisant par 6 vu qu'il y a une donnee toute les 6 lignes
data.index = data.index.map(lambda x: int(x / 6))
plt.figure(figsize=(24, 10))
# Vous pouvez commentez le moins visuel des 2 selon vos gouts
sns.barplot(x=data.index, y=data['nbre_hospit_corona'], label="Nb hospit corona")
sns.lineplot(data=data['nbre_hospit_corona'], label="Nb hospit corona") 

plt.xlabel('Nb jour')
plt.show()
</pre>
<br />
<center><img src="images/hospit.JPG" width="60%" height="60%"></center>
<br /><br />
Le confinement a d&eacute;but&eacute; le 14 Mars, ce qui correspond au jour 19 ici. On voit que le pic est arriv&eacute; Jour 32, donc le 27 Mars ce qui semble coh&eacute;rent au 6 / 7 jour d'incubation avant les 1ers symptomes 
puis ici des aggravations entrainant le pic. On voit bien que cette phase de courbe est exponentielle et qu'attendre plus aurait explos&eacute; le syst&egrave;me hospitalier. On voit ici qu'il a 
&eacute;t&eacute; efficace car pas de but&eacute;e sur plusieurs jours &agrave; un meme niveau.<br />
On observe une d&eacute;croissance des hospitalisations qui semble un peu ralentir mais on se rapproche de la limite basse qui va etre compliqu&eacute;e &agrave; r&eacute;duire sans nouvelle mesure sanitaire 
sachant que la fin du confinement approche.

<p>
<b>Analyse par age</b><br />
Regardons maintenant cette courbe mais par age. Les donn&eacute;es fournies nous permettent d'analyser 5 tranches d'ages :<br />
- les moins de 15ans<br />
- de 15 &agrave; 44ans<br />
- de 45 &agrave; 64ans<br />
- de 65 &agrave; 74ans<br />
- + de 74ans<br />
<br />
<pre>
import matplotlib.pyplot as plt
import pandas as pd

pd.plotting.register_matplotlib_converters()
import seaborn as sns

# Fichier de data sur data.gouv.fr
file = "sursaud-covid19-quotidien-2020-04-30-19h00-France.csv"

# On va utiliser Pandas pour traiter ca et on va selectionner de maniere differenciee chaque age (y a plus propre mais c'est plus lisible je trouve)
txt = pd.read_csv(file)
data = txt[txt['sursaud_cl_age_corona'] == '0']
data15 = txt[txt['sursaud_cl_age_corona'] == 'A']
data44 = txt[txt['sursaud_cl_age_corona'] == 'B']
data64 = txt[txt['sursaud_cl_age_corona'] == 'C']
data74 = txt[txt['sursaud_cl_age_corona'] == 'D']
data99 = txt[txt['sursaud_cl_age_corona'] == 'E']

# On va reduire l'index de chaque en divisant par 6 vu qu'il y a une donnee toute les 6 lignes
data.index = data.index.map(lambda x: int(x / 6))
data15.index = data15.index.map(lambda x: int(x / 6))
data44.index = data44.index.map(lambda x: int(x / 6))
data64.index = data64.index.map(lambda x: int(x / 6))
data74.index = data74.index.map(lambda x: int(x / 6))
data99.index = data99.index.map(lambda x: int(x / 6))

plt.figure(figsize=(24, 10))

# Evolution des hospitalisations pour COVID par age
# sns.lineplot(data=data, x=data.index, y=data['nbre_hospit_corona'], hue='sursaud_cl_age_corona', label=["Nb hospitalisation corona"]) # Fait tout en 1 ligne mais reste a voir les labels
sns.lineplot(data=data['nbre_hospit_corona'], label="Nb hospitalisation corona")
sns.lineplot(data=data15['nbre_hospit_corona'], label="Nb hospitalisation corona - 15ans")
sns.lineplot(data=data44['nbre_hospit_corona'], label="Nb hospitalisation corona 15 - 44ans")
sns.lineplot(data=data64['nbre_hospit_corona'], label="Nb hospitalisation corona 45 - 64ans")
sns.lineplot(data=data74['nbre_hospit_corona'], label="Nb hospitalisation corona 65 - 74ans")
sns.lineplot(data=data99['nbre_hospit_corona'], label="Nb hospitalisation corona + 74ans")

plt.xlabel('Date')
plt.show()

</pre>
<br />
<center><img src="images/age.JPG" width="60%" height="60%"></center>
<br /><br />
<p>
Ici on voit bien que les cas de jeunes est tr&egrave;s faible. Pour le reste, &agrave; partir de 15ans je reste moins cat&eacute;gorique. L'age ne semble pas vraiment impacter le taux d'hospitalisation. 
Celui-ci semble plus li&eacute; &agrave; un facteur autre, telle une comorbidit&eacute; qui peut etre diverse selon l'age. Bien sur cela est vrai pour la tranche 15-74ans. Apr&egrave;s on voit quand meme bien que cette population est bien plus atteinte et fragile.<br /><br />
On entend tr&egrave;s souvent que le Covid est une maladie qui impacte les plus ag&eacute;s. C'est peut etre vrai pour l'aspect l&eacute;thal mais pour ce qui est de l'hospitalisation, je serai moins cat&eacute;gorique.
<p>
<b>Analyse par sexe</b><br />
R&eacute;cup&eacute;rons maintenant les donn&eacute;es pour afficher toujours ce taux d'hospitalisation mais cette fois par sexe pour voir s'il y a une diff&eacute;rence.<br/>
<pre>
import matplotlib.pyplot as plt
import pandas as pd

pd.plotting.register_matplotlib_converters()
import seaborn as sns

# Fichier de data sur data.gouv.fr
file = "sursaud-covid19-quotidien-2020-04-30-19h00-France.csv"

# On va utiliser Pandas pour traiter ca et on va selectionner de maniere differenciee chaque age (y a plus propre mais c'est plus lisible je trouve)
txt = pd.read_csv(file)
data = txt[txt['sursaud_cl_age_corona'] == '0']

# On va reduire l'index de chaque en divisant par 6 vu qu'il y a une donnee toute les 6 lignes
data.index = data.index.map(lambda x: int(x / 6))

plt.figure(figsize=(24, 10))

# Evolution des hospitalisations pour COVID par sexe
sns.lineplot(data=data['nbre_hospit_corona'], label="Nb hospitalisation corona")
sns.lineplot(data=data['nbre_hospit_corona_h'], label="Nb hospitalisation corona homme")
sns.lineplot(data=data['nbre_hospit_corona_f'], label="Nb hospitalisation corona femme")

plt.xlabel('Date')
plt.show()

</pre>
<br />
<center><img src="images/sexe.JPG" width="60%" height="60%"></center>
<br /><br />
On observe principalement une diff&eacute;rence au moment du pic. Une fois que celui-ci est pass&eacute;, les courbes Hommes / Femmes finissent par s'entrecroiser r&eacute;guli&egrave;rement montrant 
qu'au final il n'y a pas vraiment de diff&eacute;rence d'impact. Le pic pr&eacute;alable pourrait etre du au fait par exemple que les hommes ont tendance &agrave; avoir plus de contacts physiques 
avec le serrage de main ou autre. Une fois les gestes barri&egrave;res et le confinement mis en place, cette diff&eacute;renciation disparait alors.<br />
<p>
<b>Analyse des taux de nouveaux cas / gu&eacute;ris et d&eacute;c&egrave;s</b><br />
Nous allons maintenant utiliser <a href="https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_time_series" target="_blank">les donn&eacute;es du CSSE de l'Universite de John Hopkins</a> 
afin de r&eacute;cup&eacute;rer les donn&eacute;es sur les nouveaux cas / gu&eacute;ris et d&eacute;c&egrave;s en France et comparer cela avec la Cor&eacute;e du Sud pour tenter de pr&eacute;dire une date de fin de confinement.<br /><br />
Nous allons afficher cela via barplot() en stackant les 3 donn&eacute;es.Pour cela on va concat&eacute;ner les 3 dataframes puis cr&eacute;er une colonne qui va soustraire les d&eacute;c&egrave;s et cas gu&eacute;ris aux cas d&eacute;tect&eacute;s 
afin d'avoir le nombre r&eacute;el de cas actuel en France.
<pre>
import matplotlib.pyplot as plt
import pandas as pd

pd.plotting.register_matplotlib_converters()
import seaborn as sns
import warnings                                  # `do not disturbe` mode
warnings.filterwarnings('ignore')

fileconfirmed = "confirmed_global_29-04.csv"
filedeath = "deaths_global_29-04.csv"
filerecovered = "recovered_global_29-04.csv"
# On charge le fichier via Pandas
data = pd.read_csv(fileconfirmed)
# On recupere les donnees de la France
data['Province/State'] = data['Province/State'].fillna(0)
dataconfirmed = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]
data = pd.read_csv(filedeath)
data['Province/State'] = data['Province/State'].fillna(0)
datadeaths = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]
data = pd.read_csv(filerecovered)
data['Province/State'] = data['Province/State'].fillna(0)
datarecovered = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]

# On supprime les colonnes qui ne nous servent pas
dataconfirmed = dataconfirmed.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
# On va inverser les colonnes et lignes pour pouvoir analyser ligne par ligne
dataconfirmed = pd.np.transpose(dataconfirmed)
cols = dataconfirmed.columns
dataconfirmed = dataconfirmed.rename(columns={cols[0]: 'Confirmed'})

# On refait de meme pour les deces et les gueris
datadeaths = datadeaths.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datadeaths = pd.np.transpose(datadeaths)
cols = datadeaths.columns
datadeaths = datadeaths.rename(columns={cols[0]: 'Deaths'})

datarecovered = datarecovered.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datarecovered = pd.np.transpose(datarecovered)
cols = datarecovered.columns
datarecovered = datarecovered.rename(columns={cols[0]: 'Recovered'})

# On concatene les Dataframes
datacomplete = pd.concat([dataconfirmed, datadeaths, datarecovered], axis=1, sort=False)
# On cree une colone au Dataframe de cas reels actuels
datacomplete['Restant'] = datacomplete['Confirmed'] - datacomplete['Recovered'] - datacomplete['Deaths']

# On n'affiche du 45e jour a la fin pour supprimer les 1ers jours quasi nuls
datacomplete = datacomplete[45:]

# On affiche cette fois en barplot()
sns.barplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Confirmed'], label="Nb confirme", color="blue")
sns.barplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Recovered'], label="Nb gueris", color="green")
sns.barplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Deaths'], label="Nb morts", color="black")

plt.xlabel('Date')
plt.show()

</pre>
<br />
<center><img src="images/stack.JPG" width="60%" height="60%"></center>
<br /><br />
Rien &agrave; dire de particulier. La courbe des d&eacute;c&egrave;s semble s'aplanir ce qui est bon signe. Celle des gu&eacute;ris l&eacute;g&egrave;rement aussi, mais en comparant avec la Cor&eacute;e du Sud, on constate que c'est pareil donc cela semble normal.
<p>
Nous allons ensuite afficher le nombre de cas r&eacute;els actuels. Pour cela nous allons concat&eacute;ner les 3 dataframes puis cr&eacute;er une colonne qui va soustraire les d&eacute;c&egrave;s et cas gu&eacute;ris aux cas d&eacute;tect&eacute;s 
afin d'avoir le nombre r&eacute;el de cas actuel en France.<br />
<pre>
import matplotlib.pyplot as plt
import pandas as pd

pd.plotting.register_matplotlib_converters()
import seaborn as sns
import warnings                                  # `do not disturbe` mode
warnings.filterwarnings('ignore')

fileconfirmed = "confirmed_global_29-04.csv"
filedeath = "deaths_global_29-04.csv"
filerecovered = "recovered_global_29-04.csv"
# On charge le fichier via Pandas
data = pd.read_csv(fileconfirmed)
# On recupere les donnees de la France
data['Province/State'] = data['Province/State'].fillna(0)
dataconfirmed = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]
data = pd.read_csv(filedeath)
data['Province/State'] = data['Province/State'].fillna(0)
datadeaths = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]
data = pd.read_csv(filerecovered)
data['Province/State'] = data['Province/State'].fillna(0)
datarecovered = data[((data['Country/Region'] == 'France') & (data['Province/State'] == 0))]

# On supprime les colonnes qui ne nous servent pas
dataconfirmed = dataconfirmed.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
# On va inverser les colonnes et lignes pour pouvoir analyser ligne par ligne
dataconfirmed = pd.np.transpose(dataconfirmed)
cols = dataconfirmed.columns
dataconfirmed = dataconfirmed.rename(columns={cols[0]: 'Confirmed'})

# On refait de meme pour les deces et les gu&eacute;ris
datadeaths = datadeaths.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datadeaths = pd.np.transpose(datadeaths)
cols = datadeaths.columns
datadeaths = datadeaths.rename(columns={cols[0]: 'Deaths'})

datarecovered = datarecovered.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datarecovered = pd.np.transpose(datarecovered)
cols = datarecovered.columns
datarecovered = datarecovered.rename(columns={cols[0]: 'Recovered'})

# On concatene les Dataframes
datacomplete = pd.concat([dataconfirmed, datadeaths, datarecovered], axis=1, sort=False)
# On cree une colone au Dataframe de cas reels actuels
datacomplete['Restant'] = datacomplete['Confirmed'] - datacomplete['Recovered'] - datacomplete['Deaths']

# On n'affiche du 45e jour a la fin pour supprimer les 1ers jours quasi nuls
datacomplete = datacomplete[45:]

# On affiche cette fois en barplot() les cas reels
sns.barplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Restant'], label="Nb confirme", color="blue")

plt.xlabel('Date')
plt.show()


</pre>
<br />
<center><img src="images/restantFR.JPG" width="60%" height="60%"></center>
<br /><br />
On constate que l'on est sur un plateau montrant une stabilisation de la situation mais pas encore un changement de tendance &agrave; la baisse, ce qui pourrait etre un crit&egrave;re 
&eacute;vident avant d'envisager un d&eacute;confinement. Y a du mieux mais cela ne semble pas suffisant. Il reste 1 semaine pour donc retourner cette tendance.
</p>
<p>
<b> Comparaison France / Cor&eacute;e du Sud</b><br />
Pour imaginer le fonctionnement d'un mod&egrave;le, le mieux reste d'en avoir un qui s'est d&eacute;j&agrave; produit pour ensuite faire des pr&eacute;dictions sur l'actuel. Le Covid-19 est une maladie r&eacute;cente 
et du coup pour comparer j'ai d&eacute;cid&eacute; arbitrairement de prendre la Cor&eacute;e du Sud. Certes la Cor&eacute;e n'a pas choisie notre m&eacute;thode mais elle est sur une bonne dynamique de fin d'&eacute;pid&eacute;mie. 
Pour information pour ceux qui n'ont pas suivi leur m&eacute;thode, ils n'ont pas confin&eacute; mais ont impos&eacute; drastiquement la mise en place de gestes barri&egrave;res comme les masques, de tester massivement 
et de mettre en place un syst&egrave;me via smartphone de suivi et tracabilit&eacute; des malades pour d&eacute;tecter tous les cas &agrave; risque au plus vite.<br /><br />

Ici je d&eacute;cide donc d'afficher la France et la Cor&eacute;e du Sud en multipliant volontairement les donn&eacute;es de la Cor&eacute;e pour avoir une taille visuelle &agrave; peu pret semblable &agrave; la France.
<pre>
# -*- coding: utf-8 -*-

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings  # `do not disturbe` mode

warnings.filterwarnings('ignore')

# Les DATA
fileconfirmed = "confirmed_global_29-04.csv"
filedeath = "deaths_global_29-04.csv"
filerecovered = "recovered_global_29-04.csv"

# On Cree le Dataframe en recuperant la France et la Coree du Sud qui servira de comparaison
data = pd.read_csv(fileconfirmed)
data['Province/State'] = data['Province/State'].fillna(0)
dataconfirmed = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]
data = pd.read_csv(filedeath)
data['Province/State'] = data['Province/State'].fillna(0)
datadeaths = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]
data = pd.read_csv(filerecovered)
data['Province/State'] = data['Province/State'].fillna(0)
datarecovered = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]

# Au vu du format de la Time Serie, on va transformer les colonnes en ligne
cols = dataconfirmed.columns

dataconfirmed = dataconfirmed.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
dataconfirmed = pd.np.transpose(dataconfirmed)
cols = dataconfirmed.columns
dataconfirmed = dataconfirmed.rename(columns={cols[0]: 'Confirmed France', cols[1]: 'Confirmed Coree'})

datadeaths = datadeaths.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datadeaths = pd.np.transpose(datadeaths)
cols = datadeaths.columns
datadeaths = datadeaths.rename(columns={cols[0]: 'Deaths France', cols[1]: 'Deaths Coree'})

datarecovered = datarecovered.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datarecovered = pd.np.transpose(datarecovered)
cols = datarecovered.columns
datarecovered = datarecovered.rename(columns={cols[0]: 'Recovered France', cols[1]: 'Recovered Coree'})

# On concat&egrave;ne les Dataframe pour n'en faire qu'un
datacomplete = pd.concat([dataconfirmed, datadeaths, datarecovered], axis=1, sort=False)

# On cree une colone au Dataframe de cas reels actuels
datacomplete['Restant France'] = datacomplete['Confirmed France'] - datacomplete['Recovered France'] - datacomplete[
    'Deaths France']
datacomplete['Restant Coree'] = datacomplete['Confirmed Coree'] - datacomplete['Recovered Coree'] - datacomplete[
    'Deaths Coree']


# On va renommer les dates pour etre au format Pandas (pas utile ici mais vous saurez comment modifier les valeurs des lignes
def formatDate(row):
    dates = row
    datesplit = dates.split('/')
    row = "2020-" + str(datesplit[0]) + "-" + str(datesplit[1])
    return row


datacomplete.index.names = ['Date']
datacomplete = datacomplete.reset_index()
datacomplete['Date'] = datacomplete['Date'].apply(formatDate)

# On affiche les 2 courbes des pays, en bleu la France et en rouge la Coree
plt.figure(figsize=(24, 10))
sns.lineplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Restant France'], label="Nb confirme France",
             color="blue")
sns.lineplot(data=datacomplete, x=datacomplete.index, y=datacomplete['Restant Coree'] * 12, label="Nb confirme Coree",
             color="red")
plt.show()

</pre><br />
<center><img src="images/france-coree.JPG" width="60%" height="60%"></center>
<br /><br />
On voit donc bien le retournement de tendance de la Cor&eacute;e qu'il nous reste &agrave; amorcer en France pour ensuite attaquer une r&eacute;elle baisse de l'&eacute;pid&eacute;mie.
</p>
<p> 
<b>Pr&eacute;diction de Time Series</b><br />
On voit qu'en 46 jours depuis le d&eacute;but de la baisse en Cor&eacute;e, celle-ci &agrave; diminuer de 65% son nombre de cas. Par ailleurs on voit qu'on obtient une tendance actuelle assez 
lin&eacute;aire. L'objectif va donc etre de r&eacute;cup&eacute;rer le d&eacute;but de cette tendance baissi&egrave;re et d'appliquer un mod&egrave;le de pr&eacute;diction autant de fois que n&eacute;cessaire pour arriver &agrave; 0 cas en Cor&eacute;e.
<br /><br />
Pour cela nous allons utiliser le mod&egrave;le ARIMA (Autoregressive Integrated Moving Average) qui m&eacute;lange de l'Autor&eacute;gression et les moyennes mobiles avec une phase de pr&eacute;processing 
appel&eacute; Int&eacute;gration.
<pre>
# -*- coding: utf-8 -*-

import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima_model import ARIMA
import warnings                                  # `do not disturbe` mode
warnings.filterwarnings('ignore')

# Les DATA
fileconfirmed = "confirmed_global_29-04.csv"
filedeath = "deaths_global_29-04.csv"
filerecovered = "recovered_global_29-04.csv"

# Je repars du meme code precedent meme s'il pourrait etre allege

# On cree le Dataframe en recuperant la France et la Coree du Sud qui servira de comparaison
data = pd.read_csv(fileconfirmed)
data['Province/State'] = data['Province/State'].fillna(0)
dataconfirmed = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]
data = pd.read_csv(filedeath)
data['Province/State'] = data['Province/State'].fillna(0)
datadeaths = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]
data = pd.read_csv(filerecovered)
data['Province/State'] = data['Province/State'].fillna(0)
datarecovered = data[(((data['Country/Region'] == 'France') | (data['Country/Region'] == 'Korea, South')) & (
        data['Province/State'] == 0))]

# Au vu du format de la Time Serie, on va transformer les colonnes en ligne
cols = dataconfirmed.columns

dataconfirmed = dataconfirmed.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
dataconfirmed = pd.np.transpose(dataconfirmed)
cols = dataconfirmed.columns
dataconfirmed = dataconfirmed.rename(columns={cols[0]: 'Confirmed France', cols[1]: 'Confirmed Coree'})

datadeaths = datadeaths.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datadeaths = pd.np.transpose(datadeaths)
cols = datadeaths.columns
datadeaths = datadeaths.rename(columns={cols[0]: 'Deaths France', cols[1]: 'Deaths Coree'})

datarecovered = datarecovered.drop(columns=['Province/State', 'Country/Region', 'Lat', 'Long'])
datarecovered = pd.np.transpose(datarecovered)
cols = datarecovered.columns
datarecovered = datarecovered.rename(columns={cols[0]: 'Recovered France', cols[1]: 'Recovered Coree'})

# On concatene les Dataframe pour n'en faire qu'un
datacomplete = pd.concat([dataconfirmed, datadeaths, datarecovered], axis=1, sort=False)
datacomplete['Restant France'] = datacomplete['Confirmed France'] - datacomplete['Recovered France'] - datacomplete[
    'Deaths France']
datacomplete['Restant Coree'] = datacomplete['Confirmed Coree'] - datacomplete['Recovered Coree'] - datacomplete[
    'Deaths Coree']
datacomplete = datacomplete.reset_index()

# La prediction Time Series prend une serie en entree, ici les donnees de la Coree.
data = datacomplete['Restant Coree']

data = data[66:]

# Nous allons faire une boucle qui va appeler le modele ARIMA pour faire une prediction, puis ajouter celle-ci et relancer la prediction 30fois pour avoir 30jours de prediction
for a in range(1,30):
    model = ARIMA(data, order=(1, 1, 1))
    model_fit = model.fit(disp=False)
    yhat = model_fit.predict(len(data), len(data), typ='levels')
    data = data.append(yhat)
    # On affiche la prediction pour voir quand elle passe le 0
    print(yhat)

plt.figure(figsize=(24, 10))
# On affiche le tout avec matplotlib cette fois
plt.plot(data.index, data, 'r-', label='Prediction')

plt.show()

</pre>
<br />
<center><img src="images/predict.JPG" width="60%" height="60%"></center>
<br /><br />
Et voil&agrave;, on obtient une droite de pr&eacute;diction et on constate qu'elle passe les 0 au bout de 16 jours (voir dans les logs affich&eacute;s par le print(yhat)). La cassure est survenue au 60e jour et nous en sommes au 98e jour.<br /><br />
Nous arrivons donc &agrave; une fin des cas de Covid-19 en Cor&eacute;e approximativement au bout de 54 jours apr&egrave;s le retournement de tendance (autour du 18 Mai donc pour la Cor&eacute;e).
<br /><br />
Nous pouvons donc esp&eacute;rer au mieux, &agrave; mon avis, si la rupture est effective au 11 mai, &agrave; une fin de crise Covid-19 en France au 04 Juillet.
</p>
<p>
<b>Conclusion :</b><br />
La mod&eacute;lisation est un &eacute;l&eacute;ment tr&egrave;s int&eacute;ressant afin de constater ce que les chiffres pr&eacute;sentent afin d'affirmer ou infirmer des hypoth&egrave;ses. La pr&eacute;diction permet &eacute;galement 
de se projeter mais rester sujette &agrave; &eacute;norm&eacute;ment de facteurs externes qui la rende peu fiable dans le cas pr&eacute;sent mais peut devenir tr&egrave;s robuste dans des cas avec plus 
d'information et des tendances saisonni&egrave;res. Dans le cas pr&eacute;sent, la m&eacute;thode de traitement de la France est bien plus laxiste que celle de la Cor&eacute;e du Sud donc la date annonc&eacute;e 
me parait ultra optimiste mais l'avenir nous le dira :)
<br /><br />
Have fun !

</p>
</div>
</content>

</entry>
<entry>
<title type="html">Web Application COVID-19</title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2020/03/index.html#e2020-03-27T16_06_41.txt"/>

<id>http://blog.madpowah.org/archives/2020/03/index.html#e2020-03-27T16_06_41.txt</id>
<published>2020-03-27T16:06:41+02:00</published>
<updated>2020-03-27T16:06:41+02:00</updated>
<category term="FreeBSD" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Ce blog n'est pas totalement tomb&eacute; dans l'oubli !<br /><br />
Un petit post juste pour indiquer une petite appli que j'ai dev pour suivre statistiquement l'&eacute;volution du COVID dans le monde : <a href="http://covid.madpowah.org" target="_blank">http://covid.madpowah.org</a>. J'essai de peaufiner cela donc ne vous &eacute;tonnez pas de le voir &eacute;voluer.
<br /><br />
Bon courage a tous pour le passage de cette crise.
</div>
</content>

</entry>
<entry>
<title type="html">[Tool] ForensicPCAP, un outil d'analyse de PCAP en python </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2014/12/index.html#e2014-12-08T16_43_42.txt"/>

<id>http://blog.madpowah.org/archives/2014/12/index.html#e2014-12-08T16_43_42.txt</id>
<published>2014-12-08T16:43:42+02:00</published>
<updated>2014-12-08T16:43:42+02:00</updated>

<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Un petit sujet concernant un script python que j'ai mis en ligne pour se faciliter la vie lors de besoins d'analyse rapide d'un PCAP. 
Il utilise la librairie Cmd2 de python donc cela s'utilise sous forme de shell et permet de lancer des commandes shell ou d'&eacute;crire 
directement dans des fichiers via &gt; .
<br /><br />
<a href="https://github.com/madpowah/ForensicPCAP" target="_blank">ForensicPCAP est disponible sur Github</a>. Je vais l'am&eacute;liorer pour ajouter des dumps automatiques d'images ou autres petites id&eacute;es. Si 
vous avez un besoin particulier n'h&eacute;sitez pas &agrave; m'en parler, je suis ouvert &agrave; toute proposition d'&eacute;volution.
<br />
Exemple :
<pre>
user@puf:~$ ./forensicPCAP.py exemple.pcap 
## Loading PCAP /home/user/exemple.pcap ... OK.
ForPCAP >>> dns
## Listing all DNS requests ...OK.
## Result : 34 DNS request(s)
ForPCAP >>> show
1 | blog.madpowah.org
ForPCAP >>> mail
## Searching mail's request ... OK.
## Result : Mail's request : 0
## Saving mails ... OK
ForPCAP >>> web
## Searching web's request ... .................OK.

Web's request : 17
ForPCAP >>> show
GET / HTTP/1.1
Cache-Control: max-age = 4624
Connection: Keep-Alive
Accept: */*
If-Modified-Since: Sat, 22 Nov 2014 07:49:38 GMT
ForPCAP >>> followtcpstream 50
## Searching TCP Stream in PCAP ... OK
ForPCAP >>> show
44 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http S
46 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 SA
47 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http A
50 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http PA / Raw
51 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 A
56 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 PA / Raw
62 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http PA / Raw
63 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 A
84 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 PA / Raw
94 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http A
159 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http PA / Raw
160 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 A
170 | Ether / IP / TCP 10.0.2.100:http > 10.0.2.15:49163 PA / Raw
174 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http A
195 | Ether / IP / TCP 10.0.2.15:49163 > 10.0.2.100:http RA
ForPCAP >>> show raw
GET / HTTP/1.1
Accept: */*
If-Modified-Since: Mon, 24 Nov 2014 18:08:00 GMT
If-None-Match: 1416852480000
A-IM: feed
Accept-Language: en-US
Accept-Encoding: gzip, deflate
</pre>

Have fun !
</div>
</content>

</entry>
<entry>
<title type="html">[Secu] Blocage compte avec Pwpolicy sous MacOSX </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2014/05/index.html#e2014-05-03T21_40_01.txt"/>

<id>http://blog.madpowah.org/archives/2014/05/index.html#e2014-05-03T21_40_01.txt</id>
<published>2014-05-03T21:40:01+02:00</published>
<updated>2014-05-03T21:40:01+02:00</updated>
<category term="Security" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Voulant impl&eacute;menter une politique de mot de passe sur un MacOSX, 
je tombe sur la commande pwpolicy. Je regarde la doc, le man et je met 
en place 
une r&egrave;gle basique de blocage au bout de 3 &eacute;checs 
d'authentification.<br />
Je test : OK ca marche sauf que ... le compte se d&eacute;bloque au bout 
d'1mn. Pas d'info sur le sujet dans le man. Rien non plus dans le guide 
s&eacute;cu 
de Apple ... Super.
<br /><br />
Bref au bout de quelques temps de recherche voici la commande pour 
configurer cette dur&eacute;e de d&eacute;blocage (par exemple 90 mn)  :
<pre>
pwpolicy -n /Local/Default -setglobalpolicy 
"minutesUntilFailedLoginReset=90" 
</pre>

Have fun.
</div>
</content>

</entry>
<entry>
<title type="html">[Tuto] Probleme installation Cobradroid </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-09T20_27_12.txt"/>

<id>http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-09T20_27_12.txt</id>
<published>2013-10-09T20:27:12+02:00</published>
<updated>2013-10-09T20:27:12+02:00</updated>
<category term="Security" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Toujours suite au Brucon et ayant quelques applis Android &agrave; 
regarder, j'ai voulu tester CobraDroid pour me faciliter le travail.<br 
/>
<br />
1&egrave;re &eacute;tape l'installation (sous Linux). Je suis donc <a 
href="http://thecobraden.com/projects/cobradroid/start/" 
target="_blank">la doc du site officiel</a> 
et l&agrave; ... c'est le drame. Impossible d'utiliser l'API Cobra 
lorsque je cr&eacute;e un AVD.
<br /><br />
L'astuce est que contrairement &agrave; ce qui est indiqu&eacute; il ne 
faut pas d&eacute;poser les fichiers sous :
<pre>
~/android-sdk-linux/addon-cobradroid-beta
</pre>
mais sous :
<pre>
~/android-sdk-linux/add-ons/addon-cobradroid-beta
</pre>
On relance l'&eacute;mulateur et on cr&eacute;e un AVD et la dans Target 
on peut bien maintenant choisir CobraDroid.
<br /><br />
Apr&egrave;s en th&eacute;orie cela peut tr&egrave;s pratique mais 
personnellement le gros probl&egrave;me que j'ai rencontr&eacute; est 
qu'il n'int&egrave;gre pas la Google API (utilis&eacute; par exemple par 
maps) 
et donc cela emp&egrave;che l'installation de pas mal d'applis.<br />
2e inconv&eacute;nient est qu'il ne propose pour l'instant une version 
2.3.7 (qu'il faut d'ailleurs penser &agrave; installer / mettre &agrave; 
jour avant d'utiliser CobraDroid) 
mais bon une mise &agrave; jour est dans les tuyaux donc cela sera 
&agrave; suivre !
<br /><br />
Have fun !
</div>
</content>

</entry>
<entry>
<title type="html">[Tuto] Changement de lecteur PDF avec Cuckoo </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-09T20_10_53.txt"/>

<id>http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-09T20_10_53.txt</id>
<published>2013-10-09T20:10:53+02:00</published>
<updated>2013-10-09T20:10:53+02:00</updated>
<category term="Security" />
<category term="Coding" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Cuckoo est un outils tr&egrave;s pratique pour analyser des codes. Pour 
que cela soit vraiment utile, il faut que l'analyse soit faite sur un 
environnement 
proche de celui que utilise et non pas avec les applications 
g&eacute;r&eacute;es par d&eacute;faut par Cuckoo.<br />
Par exemple pour l'ouverture d'un fichier PDF, si on souhaite 
&eacute;valuer un code sur un autre logiciel que Adobe Reader, il va 
falloir modifier 
un tout petit peu le code de Cuckoo. En effet mme si la VM est 
configur&eacute;e par exemple pour ouvrir les PDF avec Foxit, Cuckoo ne 
le sachant 
pas va tenter de lancer l'analyse avec Adobe qui lui est 
configur&eacute; et afficher un message d'erreur.
<br /><br />
Pour int&eacute;grer donc Foxit, rien de bien compliqu&eacute;. 
D&eacute;j&agrave; on commence par l'installer dans la VM et &agrave; la 
cloner. Ensuite on va ouvrir le fichier 
cuckoo/analyzer/windows/modules/packages/pdf.py et ajouter le chemin 
d'installation de Foxit &agrave; la liste path comme cela :
<pre>
paths = [
            os.path.join(os.getenv("ProgramFiles"), "Adobe", "Reader 
8.0", "Reader", "AcroRd32.exe"),
            os.path.join(os.getenv("ProgramFiles"), "Adobe", "Reader 
9.0", "Reader", "AcroRd32.exe"),
            os.path.join(os.getenv("ProgramFiles"), "Adobe", "Reader 
10.0", "Reader", "AcroRd32.exe"),
            os.path.join(os.getenv("ProgramFiles"), "Adobe", "Reader 
11.0", "Reader", "AcroRd32.exe"),
            os.path.join(os.getenv("ProgramFiles"), "Foxit Software", 
"Foxit Reader", "Foxit Reader.exe")
        ]
</pre>
On relance Cuckoo et le tour est jou&eacute; !
</div>
</content>

</entry>
<entry>
<title type="html">[Bug] Correction bug Browse Cuckoo </title>
<author>
<name>cloud</name>
</author>
<link rel="alternate" type="text/html" href="http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-05T00_27_06.txt"/>

<id>http://blog.madpowah.org/archives/2013/10/index.html#e2013-10-05T00_27_06.txt</id>
<published>2013-10-05T00:27:06+02:00</published>
<updated>2013-10-05T00:27:06+02:00</updated>
<category term="OpenSource" />
<category term="Security" />
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
Suite &agrave; la conf Brucon j'ai voulu jouer un peu avec Cuckoo. En testant l'application web fourni par web.py, je tombais sur 
une erreur 
500 Internal Server Error en testant de cliquer sur le lien Browse et ma console crachais une trace du genre :
<pre>
IP - - [05/Oct/2013 02:18:30] "GET / HTTP/1.1" 200 161508
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/bottle.py", line 737, in _handle
    return route.call(**args)
  File "/usr/lib/python2.7/dist-packages/bottle.py", line 1504, in wrapper
    rv = callback(*a, **ka)
  File "/usr/lib/python2.7/dist-packages/bottle.py", line 1454, in wrapper
    rv = callback(*a, **ka)
  File "./cuckoo/utils/web.py", line 71, in browse
    sample = db.view_sample(row.sample_id)
  File "~/secu/cuckoo/utils/../lib/cuckoo/core/database.py", line 824, in view_sample
    session.expunge(sample)
UnboundLocalError: local variable 'sample' referenced before assignment
</pre>
Pour corriger cela, il faut ouvrir web.py et modifier la ligne 
<pre>
sample = db.view_sample(row.sample_id)
</pre>
par 
<pre>
sample = db.view_sample(row.id)
</pre>
Le serveur web red&eacute;marre automatiquement &agrave; l'enregistrement de la modif et le Browse marche niquel !
<br />
<br />
Have fun :)
</div>
</content>

</entry>

</feed>
