\documentclass[twoside,a4paper,10pt]{amsbook}
\usepackage[french]{babel} %% Use your own babel language
\usepackage[top=3cm,bottom=3cm,left=2.5cm,right=2.5cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage{pslatex}
\usepackage{hyperref}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{supertabular}
\usepackage{pdflscape} %% Used for very big table
\usepackage{moreverb}
\usepackage{color}
\usepackage{listings}
\usepackage{lastpage}
\usepackage{fancyhdr}
\usepackage{ulem}
\usepackage{textcomp}
\usepackage{wasysym}
\usepackage{wrapfig} %%Usefull for image 
%%\usepackage{fguill} %%Use this package for guillemot[left|right] useless with babel set to french
\usepackage{eso-pic} %% Background
\pagestyle{fancy}%
\renewcommand{\headrulewidth}{0.1pt}
\renewcommand{\footrulewidth}{0pt}
\renewcommand{\chaptermark}[1]{%
	\markboth{\chaptername\ \thechapter.\ #1}{}}

\renewcommand{\sectionmark}[1]{%
	\markright{#1}{}}

\fancypagestyle{plain}{%
\fancyhf{}
\fancyfoot[R]{\thepage/\pageref{LastPage}}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}}
\fancyhf{}
\fancyhead[L]{\rightmark}
\fancyhead[R]{\leftmark}
\fancyfoot[R]{\thepage/\pageref{LastPage}}
\renewcommand{\headrulewidth}{0.1pt}
\renewcommand{\footrulewidth}{0pt}

\definecolor{codegray}{gray}{.95}
\lstset{language=C,
	numbers=left,
	tabsize=2,
	basicstyle=\scriptsize,
	stringstyle=\textrm,
	showstringspaces=false,
	frame=none,
	xleftmargin=3pt,
	backgroundcolor=\color{codegray}}

\newcommand{\settexitref}[2]{(\ref{#1}p\pageref{#1})}
\newcommand{\dokutitlelevelone}[1]{\chapter{#1}}
\newcommand{\dokutitleleveltwo}[1]{\section{#1}}
\newcommand{\dokutitleleveltree}[1]{\subsection{#1}}
\newcommand{\dokutitlelevelfour}[1]{\subsubsection{#1}}
\newcommand{\dokutitlelevelfive}[1]{\paragraph{#1}}
\newcommand{\dokufootnote}[1]{\footnote{#1}}
\newcommand{\dokufootmark}[1]{\footnotemark[#1]}
\newcommand{\dokubold}[1]{\textbf{#1}}
\newcommand{\dokuitalic}[1]{\textsl{#1}}
\newcommand{\dokumonospace}[1]{\texttt{#1}}
\newcommand{\dokuunderline}[1]{\underline{#1}}
\newcommand{\dokuoverline}[1]{\sout{#1}}
\newcommand{\dokusupscript}[1]{\textsuperscript{#1}}
\newcommand{\dokusubscript}[1]{$_{#1}$}
\newcommand{\dokuhline}{\line(1,0){400}}
\newcommand{\dokulabel}[1]{\label{#1}}
\newcommand{\dokuitem}{\item}
\newcommand{\dokuquoting}{\textbar}
\newcommand{\dokutabularwidth}{\textwidth}
\newcommand{\dokusupertabularheadbreak}{\small\sl continued from previous page}
\newcommand{\dokusupertabulartailbreak}{\small\sl continued on next page}
\newcommand{\dokuheadingstyle}[1]{\textbf{#1}}
\definecolor{dokuheadingcolor}{rgb}{0,0,0.60}
\newcommand{\dokubackground}[1]{%
\AddToShipoutPicture{%
  \AtTextCenter{%
    \makebox(0,0)[c]{\resizebox{\textwidth}{!}{%
      \rotatebox{25}{\textsf{\textbf{\textcolor[gray]{0.90}{#1}}}}}}%
  }%
 }%
}

\hypersetup{
pdftitle = {Projet L2 (S41) - 2013/2014 - Extraction et transformation},
pdfauthor = {E. Bruno},
pdfcreator = {DokuTeXit},
pdfproducer = {dokuwiki + TeXit + pdflatex}
}
\title{Projet L2 (S41) - 2013/2014 - Extraction et transformation}
\author{E. Bruno}
\dokubackground{http://bruno.lsis.univ-tln.fr/}
\begin{document}
\thispagestyle{empty}
\maketitle
\thispagestyle{empty}
\cleardoublepage
\tableofcontents
\newpage
\thispagestyle{plain}
\cleardoublepage
\newpage



\dokutitlelevelone{Extraction et transformation des données}
\label{297f28c99d2184a1f3861634864fa04e}%% extraction_et_transformation_des_donnees
\label{868994937b1c6f12924fa744402f419e}%%Start: extraction => /home/bruno/public_html/data/pages/extraction.txt
Les données sont produites par la station météo sous la forme d'une séquence de caractère (pour commencer nous le simulerons avec un fichier texte) dont la forme est la suivante :


\small
\begin{verbatimtab}

20.9degC
RHT03 : 	H=55% 		T=19.5degC
BMP085 :	P=998hPa	T=21degC
LDR :  		23.0%
Anemometre : 	0.0m/s
Girouette : 	90degres
Pluviometre : 	0mm


[HRTCC :		21/01/2014     09:25:37
Solaire :	Vpan=0.00V
Batterie :	Vbat=0.00V	Ibat=0.00A
Duty cycle :	R=50%
DS18S20 : 	20.9degC
RHT03 : 	H=55% 		T=19.5degC
BMP085 :	P=998hPa	T=21degC
LDR :  		23.0%
Anemometre : 	0.3m/s
Girouette : 	90degres
Pluviometre : 	0mm


[HRTCC :		21/01/2014     09:25:39
Solaire :	Vpan=0.00V
Batterie :	Vbat=0.00V	Ibat=0.00A
Duty cycle :	R=50%
DS18S20 : 	20.9degC
RHT03 : 	H=55% 		T=20.5degC
BMP085 :	P=998hPa	T=22degC
LDR :  		23.0%
Anemometre : 	0.5m/s
Girouette : 	45degres
Pluviometre : 	0mm

\end{verbatimtab}
\normalsize
Le fichier \hyperref[5e18a89b5a97114a329297f38b4e68b3]{data.txt} contient une capture d'envoie d'un station météo.

On remarque que :


\begin{itemize}
\dokuitem  la station envoie régulièrement le même bloc d'information (la date en premier et le pluviomètre en dernier). En réalité \dokubold{chaque bloc d'information commence toujours par deux caractères : le caractère d'échappement (code ASCII\dokufootnote{American Standard Code for Information Interchange} 27, invisible sur un écran) et le caractère '['.} Cela permet de trouver le début du prochain bloc.
\dokuitem  Il y a un ensemble d'information fournie par un capteur par ligne, elle commence par une \dokubold{ étiquette } (Solaire, Batterie, \ldots{}) suivie de ':'
\dokuitem  Après le ':' se trouvent des informations qui sont :
\begin{itemize}
\dokuitem  soit une date (21/01/2014) puis une heure (09:25:39)
\dokuitem  soit des listes de couples nom=valeur (H=55\% 		T=19.5degC) séparées par des espaces et des tabulations
\dokuitem  soit simplement une valeur (23.0\%). 
\end{itemize}

\dokuitem  Toutes les valeurs (55\%) sont composées d'une nombre (55) et d'une unité (\%)
\end{itemize}
Dans le bloc précédent, il y a donc deux mesures utilisables (la première est incomplète).


\dokutitleleveltwo{Structure de données}
\label{7537eb1b48bd8de590e7d80be598ef09}%% structure_de_donnees
Après extraction, toutes les informations seront stockées dans une liste dont chaque élément est un dictionnaire (un par groupe de mesures à un moment donné). L'entrée du dictionnaire est indexé par l'étiquette de la ligne. A l'intérieur, chaque mesure est représentée par un tableau à deux éléments (valeur et unité). Dans le cas où plusieurs mesures existent pour un label, elles sont stockées dans un dictionnaire. 

Les dates est stockée dans datetime (\href{http://docs.python.org/2/library/datetime.html\#datetime-objects}{http://docs.python.org/2/library/datetime.html{\textbackslash}\#datetime-objects}). Pour les utiliser il faut importer la class datetime du module datetime :

Voilà un exemple d'affectation de deux mesures construites 'à la main':


\lstset{language=python}
\begin{lstlisting}
data=[{'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
  'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre':
[0.0, 'mm'],
  'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']},
  'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 37),
  'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'],
'LDR': [23.0, '%'],
                                     'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']},
'Anemometre': [0.0, 'm/s'],
                                     'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']},
                                     'BMP085': {'P': [998.0, 'hPa'], 'T': [22.0, 'degC']},
                                     'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']},
                                     'HRTCC': datetime(2014, 1, 21, 9, 25, 39),
                                     'Solaire': {'Vpan': [0.0, 'V']}},
 {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
  'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre':
[0.0, 'mm'],
  'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [23.0, 'degC']},
  'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 41),
  'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'],
'LDR': [23.0, '%'],
                                     'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']},
'Anemometre': [0.0, 'm/s'],
                                     'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']},
                                     'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']},
                                     'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']},
                                     'HRTCC': datetime(2014, 1, 21, 9, 25, 43),
                                     'Solaire': {'Vpan': [0.0, 'V']}}]                              
      

\end{lstlisting}
Le fichier \hyperref[92214223f239eb7726e007d4cfe9ac7d]{data.py} contient la déclaration python des mesures précédentes. 

En haut de chaque module qui doit utiliser \dokumonospace{datetime} ajouter :


\lstset{language=python}
\begin{lstlisting}
from datetime import datetime

\end{lstlisting}
L’intérêt est ensuite de pouvoir accéder simplement aux valeurs :


\lstset{language=python}
\begin{lstlisting}
print("Nombre de mesures:", len(data))
print('Les deux premieres mesures ', data[:3])
print('La pression donnee par le capteur BMP085 de la 5eme mesure ', data[4]['BMP085']['P'])

\end{lstlisting}
Créer un projet python \dokumonospace{pymeteo}. Créer un module \dokumonospace{main.py}. Déclarer une variable \dokumonospace{data} qui contient quelques mesures. Tester les expressions précédentes. Afficher la valeur \dokumonospace{R} sans l'unité de l'étiquette \dokumonospace{Duty cycle} de la seconde mesure. 


\dokutitleleveltwo{Extraction du label d'une ligne}
\label{c013fb6382d0cdb72e2698c79b34d5d3}%% extraction_du_label_d_une_ligne
 Lire la section chaîne de caractères de la page \hyperref[fae93ac617ad0a5c6341a261d3f2478f]{Traitement simple des chaînes de caractère en python} avant de faire cet exercice.

Créer un module \dokumonospace{parser.py} et la fonction \dokumonospace{def extract{\textunderscore}label(ligne)}.
Cette fonction retourne l'étiquette de la ligne passée en paramètre comme une chaîne de caractères.

Ajouter dans le module \dokumonospace{main.py} le test de la fonction précédente :


\lstset{language=python}
\begin{lstlisting}
print(parser.extract_label("HRTCC :		21/1/14     9:25:37"))

\end{lstlisting}
Il doit retourner \dokumonospace{HRTCC}.


\dokutitleleveltwo{Extraction de la date et de l'heure}
\label{a9179968a8aa2d0fa0805a0524cd7061}%% extraction_de_la_date_et_de_l_heure
Lire la section expression régulière de la page \hyperref[fae93ac617ad0a5c6341a261d3f2478f]{Traitement simple des chaînes de caractère en python} avant de faire cet exercice et les suivants.

Ajouter la fonction \dokumonospace{extract{\textunderscore}datetime(data)} au module \dokumonospace{parser}. Elle doit retourner un datetime à partir d'une chaîne de caractère qui contient une date et une heure (comme dans les données de HRTCC). Pour créer un datetime, vous utiliserez la fonction \dokumonospace{datetime(int(annee), int(mois), int(jour), int(heure), int(minute), int(seconde))}.

Vous tester votre fonction dans le module \dokumonospace{main.py}:


\lstset{language=python}
\begin{lstlisting}
 print(parser.extract_datetime("21/1/2014     9:25:37"))
 print(parser.extract_datetime("21/01/14     9:25:37"))

\end{lstlisting}
qui doit retourner 


\small
\begin{verbatimtab}

2014-01-21 09:25:37
2014-01-21 09:25:37

\end{verbatimtab}
\normalsize

\dokutitleleveltwo{Séparation des valeurs et des unités}
\label{6beebfd83c023700b3da64160486e8c8}%% separation_des_valeurs_et_des_unites
Dans le module \dokumonospace{parser} ajouter la fonction \dokumonospace{extract{\textunderscore}unit(data)} qui prend en paramètre une chaîne de caractères qui contient un nombre et une unité et qui retourne un tableau avec deux éléments (la valeur et l'unité).

Vous testerez votre fonction :


\lstset{language=python}
\begin{lstlisting}
print(parser.extract_unit("23deg"))
print(parser.extract_unit("+23°"))
print(parser.extract_unit("-23P"))
print(parser.extract_unit("23.4%"))
print(parser.extract_unit("+23.4E-3%"))

\end{lstlisting}
ce qui doit retourner :


\lstset{language=python}
\begin{lstlisting}
[23.0, 'deg']
[23.0, '°']
[-23.0, 'P']
[23.4, '%']
[0.0234, '%']

\end{lstlisting}

\dokutitleleveltwo{Extraction des séquences de couple attribut/valeur}
\label{901230d2433ff88d55fcef8c20b0f428}%% valeur
Dans le module \dokumonospace{parser} ajouter la fonction \dokumonospace{attribute{\textunderscore}value(data)} qui prend en paramètre une chaîne de caractères contenant des couple de la forme NOM=MESURE et retourne un dictionnaire indexé par les noms et contenant un tableau séparant la valeur et l'unité.

Vous testerez votre fonction :


\small
\begin{verbatimtab}

print(parser.attribute_value("H=55% 		T=19.5degC"))
print(parser.attribute_value("R=50%"))

\end{verbatimtab}
\normalsize
ce qui doit retourner :


\small
\begin{verbatimtab}

{'H': [55.0, '%'], 'T': [19.5, 'degC']}
{'R': [50.0, '%']}

\end{verbatimtab}
\normalsize

\dokutitleleveltwo{Analyse complète des données}
\label{ae1752d88dce71a65eaf160e9b639c44}%% analyse_complete_des_donnees
Ecrire la fonction \dokumonospace{parse(filename)} qui retourne le tableau complet des données en utilisant les fonctions précédentes et en analysant le fichier dont le nom est passé en paramètre. 

La démarche suivante est conseillée :


\begin{enumerate}\dokuitem  chercher une ligne qui commence une nouvelle mesure, c'est à dire qui débute par les caractères escape (dont le code ASCII\dokufootmark{1} est 27) et "[". La fonction \dokumonospace{ord(ch[i])} retourne le code ASCII\dokufootmark{1} du ième caractère de la chaîne ch), la fonction \dokumonospace{chr(i)} retourne le caractère dont le code ascii est passé en paramètre.
\dokuitem  pour chaque ligne extraire l'étiquette et exécuter la bonne fonction pour extraire les données, l'ajouter à un dictionnaire temporaire qui sera ajouté à un tableau à chaque fois que l'on trouve le début d'un nouveau groupe de mesure (le caractère escape).   
\end{enumerate}

\dokutitleleveltwo{Exploitation des résultats}
\label{05eb99837679c87612a9559dbdd78db6}%% exploitation_des_resultats
Ecrire les fonctions qui permettent de créer simplement des tableaux de valeurs à partir des clés 


\lstset{language=python}
\begin{lstlisting}
extractMesures(data, key, subkey)
extractMesures(data, key)
extractValues(data, key, subkey)
extractValues(data, key)

\end{lstlisting}

\lstset{language=python}
\begin{lstlisting}
print('Le tableau des 3 premières temperatures données par BMP085',
parser.extractMesures(data,'BMP085', 'T')[:3])
print('Le tableau des 3 premières temperatures données par BMP085 (sans unité)',
parser.extractValues(data,'BMP085', 'T')[:3])

\end{lstlisting}

\dokutitlelevelone{Un défi (optionnel) Création d'un tableur à partir des données}
\label{001e0d4b2d849acea4e5620583a3e0a9}%% un_defi_optionnel_creation_d_un_tableur_a_partir_des_donnees
En vous inspirant de \hyperref[bf745b448a208130be6946fb2db72f24]{Lien avec OpenOffice}, ecrire un module \dokumonospace{libreoffice.py} qui permet d'exporter toutes les mesures dans différents onglets d'un tableur. 

\end{document}

