% Template GRASS newsletter - Article
% Language: Latex
%

% Head
\title{Traitement g\'eospatial sur des serveurs distants via internet
-- PyWPS}
\subtitle{PyWPS et Embrio}
\author{J\'achym  \v{C}epick\'y et Lorenzo Becchi, traduit par Vincent Picavet}

\maketitle

% Abstract
\emph{Le document 05-007r4\footnote{OGC Web Processing Service (WPS):
\url{http://www.opengeospatial.org/standards/requests/28}} de l'OGC  décrit un
procédé pour mettre à disposition des opérations géospatiales à travers des
r\'esaux en utilisant des Web Services. Cet article présente une
implémentation -- PyWPS. Même si la cible originelle de PyWPS était de rendre
accessible depuis des applications Web les modules du SIG GRASS, en pratique il
est possible d'utiliser n'importe quel outil en ligne de commande ou qui possède
une interface avec le langage de programmation Python. Avec l'aide de WPS il est
possible de réaliser des opérations couteuses en temps de calcul côté serveur,
ou construire votre propre application de WebSIG tournant dans un navigateur
web. Décrivons maintenant la façon dont PyWPS fonctionne et déterminons s'il
peut répondre à vos besoins.}

\section{OGC Web Processing Service}
\label{sec:ogc_wps}
Le standard OGC WPS (Web Processing Service) est relativement jeune et
pas encore aussi connu que son cousin le WMS (Web Map Service). Nous
commencerons donc par en donner un bref aperçu. L'unité de base du WPS est le
\emph{process}, une opération géospatiale, avec des entrées et des sorties de
type définies. Le client communique avec le serveur à l'aide de trois types de
requêtes. La requête peut être envoyée au serveur par HTTP GET avec des
paramètres donnés sous la forme de paires clés-valeurs (Key-Value Pairs, KVP) ou
par HTTP POST, avec des paramètres données dans un fichier XML. Les trois types
de requêtes pouvant être envoyées au serveur sont :

\begin{description}
    \item[GetCapabilities] -- Le serveur répond avec du XML, décrivant le
    serveur, les coûts, une description générale et donnant une liste de process,
    prêts à être exécutés.

    \item[DescribeProcess] -- Le serveur répond avec du XML, décrivant en détail
    les types des entrées et des sorties, pour que le client soit capable
    d'écrire la requête \textit{Execute}.
    
    \item[Execute] -- Le client demande l'exécution d'une opération géospatiale,
    avec toutes les données nécessaires. Le serveur lance le process et informe
    le client (l'utilisateur) de l'avancement.
\end{description}

La suite donne quelques exemples pour illustrer l'utilisation de ces requêtes.
Disons que nous voulons faire un calcul de ligne de vue à partir de
coordonnées x et y sur un fichier raster, disponible à partir d'un
serveur distant. Le nom du process sera \textit{visibility}.

\section{Utilisation basique de l'OGC WPS}
Tout d'abord nous avons besoin de déterminer quelles opérations le serveur propose
(voir ce lien 
\footnote{\url{http://pywps.ominiverdi.org/cgi-bin/wps.py?service=WPS&request=GetCapabilities}}).
A partir du XML renvoyé, il apparait clairement que le process \emph{visibility}
est disponible sur le serveur, et le résumé nous dit qu'il correspond au service
que nous recherchons. Ensuite, nous avons besoin de savoir quel type d'entrée et
de sortie le process nécessite et renvoie. (voir ce lien
\footnote{\url{http://pywps.ominiverdi.org/cgi-bin/wps.py?service=WPS&request=DescribeProcess&version=0.4.0&identifier=visibility}}).

\begin{itemize}
    \item $x$ de type \textit{LiteralValue}
    \item $y$ de type \textit{LiteralValue} 
    \item $maxdist$ -- distance maximale de l'observateur. De type
    \textit{LiteralValue}, valeur minimale 0, maximale 5000 metres. 
    \item $observer$ -- hauteur de l'observateur. De type
    \textit{LiteralValue}, valeur minimale 0, maximale 50 meters.
    
    \item $dem$ -- de type \textit{ComplexValue} -- carte raster de modèle
    numérique de terrain, sur laquelle la ligne de vue doit être calculée.
\end{itemize}

Maintenant nous pouvons écrire la requête d'exécution, l'envoyer au serveur et
attendre les résultats de
calcul\footnote{\url{http://pywps.ominiverdi.org/cgi-bin/wps.py?service=WPS&version=0.4.0&request=Execute&identifier=visibility&datainputs=x,602829.1875,y,4925326.875,maxdist=2000,observer=1.2,dem,http://somewhere/?some&service}}.
Le serveur va télécharger le modèle numérique de terrain, faire le calcul de
ligne de vue et renvoyer le raster de résultat au client.

\section{Introduction à PyWPS}

%\includegraphics[width=0.15\columnwidth]{integration/cepicky/pywps}}
PyWPS est un projet relativement jeune, commencé en avril 2006.
Le but premier du projet était de faire la connexion entre UMN-MapServer et le
SIG GRASS de la manière la plus simple possible, afin de pouvoir créer une
véritable application WebSIG, capable d'effectuer par exemple de l'interpolation
de données raster, ou diverses analyses de modèles numériques de terrain. Avec
le temps, il s'est avéré que même si GRASS est un outil puissant, il n'est pas
forcément le meilleur ou le seul choix possible pour toutes les tâches.
La conception de PyWPS a changé de telle sorte qu'il puisse être utilisé sans
GRASS en arrière plan, mais avec n'importe quel autre outil, ou même juste avec
Python.
PyWPS est une implémentation du standart WPS de l'OGC comme défini dans le
document OGC 05-007r4. Actuellement, le support de tout le standard n'est pas
complet, mais presque 95\% du standard est implémenté et utilisable.

Le projet est construit sur un simple script CGI, afin de rendre la vie des
développeurs de WebSIG la plus simple possible. Il met à disposition les
fonctionnalités pour :

\begin{itemize}
    \item Analyser toutes les entrées et créer toutes les sorties,
    \item Réaliser des validations basiques sur les entrées, comme vérifier le
    type d'entrées LiteralValue ou la taille maximale de fichier pour une entrée
    de type ComplexValue, etc.
    \item Créer et supprimer à la volée des fichiers et répertoires temporaires,
    comme des région et mapsets de GRASS, ou d'autres fichiers créés pour
    pouvoir effectuer le calcul.
    \item Lancer d'autres opérations utiles.
\end{itemize}

Le développeur n'a qu'une seule chose à faire : définir les entrées et sorties,
ce qui est simplement un script en Python. Le process est une classe
\emph{Process}, avec une méthode requise nommée \emph{execute}, dans laquelle le
calcul est effectué. Les données d'entrée et de sortie sont définies d'une
manière similaire, dans une structure de dictionnaire complexe\footnote{Ceci a
été remplacé par des appels de méthodes \emph{Add*Input()} dans la version 
\emph{svn} actuelle}:

\begin{small}
\begin{smallverbatim}
{
    'Identifier':'maxdist',
    'Title': 'Maximal distance',
    'Abstract':'Maximal distance of visibility',
    'LiteralData': {
        'values':[ [0.,5000] ],
    },
    'dataType': type(0.0),
},
{
    'Identifier': 'dem',
    'Title': 'Digital elevation mode'
    'Abstract': 'Raster map with elevation model',
    'ComplexValueReference': {
        'Formats':["image/tiff"],
    }
},
\end{smallverbatim}
\end{small}

La méthode \emph{execute()} peut ensuite utiliser par exemple directement des modules de GRASS :

\begin{small}
\begin{smallverbatim}
def execute(self):
    # importation de dem
    os.system("r.in.gdal in=%s out=dem" %\
                    (self.datainputs['dem']))
    # reglage de la region à partir du fichier dem
    file os.system("g.region rast=dem")
    # module de ligne de visee
    os.system("r.los input=dem output=output \
               coordinate=%s,%s max_dist=%f \
               obs_elev=%d" % \
               (self.datainputs['x'],
               self.datainputs['y'],
               self.datainputs['maxdist'],
               self.datainputs['observer']))
    # export du raster de sortie
    os.system("r.out.gdal in=output out=out.tif")
    # reglage de la valeur de retour
    self.dataoutputs['output'] = "out.tif"
    return
\end{smallverbatim}
\end{small}

Comme le code source est la meilleure documentation, environ dix exemples de
process sont distribués avec le code source de PyWPS, pour que l'utilisateur
puisse avoir une idée générale de la définition d'un process.
Il y a aussi une documentation disponible en ligne et hors ligne, qui tente de
décrire le mieux possible le processus d'installation et la mise en place de vos
propres process.

Récemment, une nouvelle classe a été définie, qui permet une définition facile
des entrées et sorties de process, ainsi qu'un meilleur support pour les modules
de GRASS.
Toute interface web sera désormais capable de suivre l'avancement des imports
dérivés directement du module \texttt{r.in.gdal}. Cette amélioration sera
disponible dans la prochaine version de PyWPS.

\subsection{Avancées du développement}
La première version ``stable'' de PyWPS avec cle numéro de version 1.0.0 est
sortie en Novembre 2006. Actuellement, l'équipe de développement de PyWPS
projette de sortir la version 2.0.0 prochainement, avec de nouvelles
fonctionnalités et quelques corrections de bogues. L'effort général de
développement est effectué dans trois directions :

\begin{itemize}
    \item Implémentation du standard OGC WPS complet,
    \item Sécuriser l'application au maximum afin d'éviter la compromission de serveur,
    \item Rendre la vie du développeur de process la plus simple possible.
\end{itemize}

L'équipe de développement de PyWPS voudrait également engager des discussions
avec la communauté géospatiale pour définir des métadonnées de process. Le
standard OGC WPS définit les types d'entrée d'un point de vue du process, mais
n'aborde pas le sujet des types d'entrée (et de sortie) d'un point de vue
utilisateur (c'est à dire de l'interface). Par exemple, la coordonnée $x$ est de
type \emph{LiteralValue}, mais cela ne définit pas $x$ comme une coordonnée. Il
serait cependant utile de définir cette entrée avec un clic de souris sur une
carte, plutôt qu'en tapant au clavier dans un champs de texte.
Si vous voulez jeter un oeil de plus près à PyWPS, vous pouvez visiter la page
du projet\footnote{Page du projet PyWPS :
\url{http://pywps.wald.intevation.org}}, où
le code source est disponible, ainsi que des liens vers des
projets utilisant déjà PyWPS.

\section{Utiliser ka-Map \& PyWPS pour créer un WebSIG GRASS}
Ominiverdi\footnote{Site d'Ominiverdi : \url{http://www.ominiverdi.org}} a rejoint
le développement de PyWPS après la première version. Notre premier but était de
créer un client Web libre (FOSS : Free Open Source Software) pour accéder aux
fonctions de GRASS. PyWPS n'était pas la première tentative de créer une
connexion entre GRASS et le Web, mais aucune autre n'était basée sur des standards
ouverts, rendant impossible la création d'une plateforme partagée. Dès le départ
nous voulions travailler à deux différents projets : \textbf{Embrio} et \textbf{Wuiw}.

\subsection{Embrio}
Embrio est la première implémentation que nous avions à l'esprit : utiliser
PyWPS pour faire interagir UMN~MAPSERVER et l'API MapScript avec GRASS.

Un autre but important était un client web riche, et c'est pourquoi nous avons
décidé de baser nos efforts sur ka-Map. Ka-Map utilise Mapscript pour accéder à
l'ensemble de puissantes fonctionnalités de UMN~Mapserver et offrir une
expérience de navigation à la Google Maps.
La sortie de PyWPS, une fois que le Process retourne une carte, peut être en
GeoTiff, pour une sortie raster, ou en GML pour une sortie vecteur. Les deux
formats sont accessibles nativements par UMN~MapServer et peuvent être
facilement couplés avec d'autres environnements cartographiques. Ainsi, une
requête au module \textit{Visibility} peut retourner un GeoTiff, qui est gardé
par ka-Map et inséré dans le vrai système de coordonnées de la carte. Ensuite un
style, qui peut être un SLD, est appliqué aux valeurs du raster, et un cache
temporaire est créé à la volée pendant que les tuiles sont renvoyées au client.
Le cache temporaire est lié au \textit{sessionId}.

Ce système permet à différents modules de s'exécuter en parallèle et de comparer
leurs sorties en utilisant l'interface de ka-Map. Le contrôle de la transparence
et de la position du layer peuvent être utiles pour comprendre le resultat
final. La fonction requête est également synchronisée si la sortie est
requêtable. Le module \textit{Visibility} peut produire l'angle incident avec le
point de visibilité, et la fonction de requête peut retourner la valeur de chaque pixel
cliqué.\\ 

\begin{figure}[htbp]
   \centering
   %name of your graphic, without the path AND in PNG (screnshots etc)/PDF (drawings) format:
   \includegraphics[width=1\columnwidth]{integration/cepicky/embrio}
   %caption of the figure
   \caption{Copie d'écran de l'interface Embrio la plus récente.} 
   %label of the figure, which has to correspond to \ref{}:
   \label{fig:label_of_your_image}
\end{figure}


\subsection{Wuiw}
Wuiw est encore aujourd'hui plus un concept qu'une réelle application. Il a pour
objectif de fournir une API Javascript qui connecte le service WPS à des sources
de données en OWS, et de faire un rendu de la sortie indépendamment d'une
quelconque application de serveur cartographique.

Nous sommes encore en train d'évaluer les limites actuelles du brouillon WPS,
qui ne relient pas encore les définitions des entrées avec la définition d'un
type complexe. La première idée était d'utiliser des informations en métadonnées
pour créer ce type de relation, mais le risque existe de créer un dialecte
parallèle qui viendrait amoindrir les avantages de l'intéropérabilité par les
standards.
Nous espérons que le chemin de WPS vers une version 1.0 apportera une solution
adaptée à cette limitation.

\section{Développements futur}

Il est clair que WPS, PyWPS, Embrio et Wuiw ont tous une histoire courte.
Même si la plupart des choses sont encore à faire, le début est prometteur.
Concernant Embrio, nous prévoyons d'améliorer l'interaction avec les retours des
scripts de process WPS afin d'afficher une barre de progression. Beaucoup
d'autres modules de GRASS peuvent être développés, et nous espérons recevoir de
l'aide de la communauté GRASS pour les réaliser.

Un autre objectif important est d'ajouter plus d'interaction avec les
applications en ligne de commande (CLI : Command Line Interface), comme R,
GDAL/OGR, etc. pour réaliser des géostatistiques, des conversions de format, et
beaucoup, beaucoup d'autres fonctionnalités.

Nous espérons aussi ajouter une ligne de commande en AJAX pour intéragir avec
un système protégé utilisant WPS.

\section{Licenses}

Il est important de noter que ce projet utilise beaucoup de logiciels avec au
moins deux licences différentes :

\begin{itemize}
    \item GNU/GPL: GRASS, PyWPS, R
    \item MIT/BSD: UMN MapServer, MapScript, ka-Map, Embrio 
\end{itemize}

\section{Références}
\begin{itemize}
	\item OGC Web Processing Service \footnote{\url{http://www.opengeospatial.org/standards/requests/28}}
	\item Site web de PyWPS : \footnote{PyWPS Home page:
	\url{http://pywps.wald.intevation.org}}
	\item Dernière démonstration d'embrio: \footnote{ Démonstration:\\
\url{http://pywps.ominiverdi.org/demo/embrio/ka-map/htdocs/index\_wps\_qgis.html}}
	\item Site web d'Embrio\footnote{\url{http://pywps.ominiverdi.org/}}
\end{itemize}

\address{J\'achym \v{C}epick\'y\\
  \url{http://les-ejk.cz}\\
  \email{jachym AT les-ejk cz}}

\address{Lorenzo Becchi\\
  \url{http://ominiverdi.org}\\
  \email{lorenzo AT ominiverdi com}}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: main_document.tex
%%% End: 

