Tests de l environnement python pour des traitements SIG Transport Contact : Patrick GENDRE / département DCEDI pat.gendre@developpement-durable.gouv.fr 04 4224 7687 http://www.cete-mediterranee.fr/tt13/www Décembre 2011
NOTICE ANALYTIQUE Organisme commanditaire : CETE Méditerranée Titre : Tests de l environnement python pour des traitements SIG Transport Sous-titre : Date d achèvement : Langue : Organismes auteurs : CETE Méditerranée 01/12/11 Rédacteurs : Cyrille BOITEL (vacataire) Français Relecteur assurance qualité : Patrick GENDRE Résumé : En liaison avec le projet Potimart (boite à outils open source pour les SIG transport), cette action R&D réalisée dans le cadre d une vacation en novembre 2011 a permis de tester la faisabilité d utiliser les librairies disponibles dans l environnement du langage python pour des traitements SIG Transport : - lecture de données routières OSM ou BD TOPO : ogr/gdal - lecture de données transport collectif GTFS : transitfeed - traitements géométriques : shapely - calcul sur des graphes : networkx - visualisation de graphes : Gephi (logiciel libre en java) Le rapport présentant les résultats encourageants qui ont été obtenus, décrit la mise en oeuvre des outils et librairies, et propose quelques perspectives. Ce rapport est publié sur le web en même qu un jeu de données de test et que les scripts python qui permettront au lecteur de vérifier concrètement comment mettre en oeuvre ces outils : http://www.cete-mediterranee.fr/tt13/www/article.php3?id_article=317 Remarques complémentaires éventuelles (rubrique facultative) : Mots clés : SIG transport, logiciel libre, open source, réseaux de transport, python Nombre de pages : 10 Diffusion : Publique Confidentialité : Non Bibliographie : oui Tests de l environnement python pour des traitements SIG Transport 1
Sommaire I. INTRODUCTION 3 A. CONTEXTE 3 B. OBJET DU DOCUMENT 3 C. CONTENU DU RAPPORT 3 II. LANGAGES, LOGICIELS ET FORMATS 4 A. PYTHON 4 B. BIBLIOTHEQUES PYTHON UTILISEES 4 C. SHAPE 5 D. GEPHI 5 E. GEXF 5 III. CREATION D UN GRAPHE ROUTIER 5 A. SOURCES DES DONNEES 5 B. FONCTION NATIVE DE NETWORKX 5 C. ADAPTATION DE LA FONCTION A DES DONNEES SPECIFIQUES 6 D. NOUVELLE IDENTIFICATION DES NOEUDS ET DES ARCS 6 IV. INTEGRATION DE DONNEES TRANSPORT EN COMMUN 7 A. IMPORT DES DONNEES GTFS 7 V. CALCUL DE PLUS COURTS CHEMINS 8 VI. VISUALISATION DU GRAPHE AVEC GEPHI 9 VII. PERSPECTIVES 9 Tests de l environnement python pour des traitements SIG Transport 2
I. INTRODUCTION A. Contexte Le CETE (Centre d Etudes Techniques de l Equipement) Méditerranée est un service technique du ministère du développement durable, dont le service DCEDI/MIM travaille dans le domaine des systèmes d information sur les transports. Ses activités sont décrites sur les pages http://www.cetemediterranee.fr/tt13/www/ Le CETE contribue aux programmes nationaux relatifs au développement des systèmes d information sur tous les modes de transport (site www.predim.org), et dans ce cadre, en particulier au développement d outils d analyse de réseaux de transport à base de logiciels open source : Projet www.potimart.org L objectif de POTIMART est de fournir une boîte à outils SIG transport à base de logiciels libres. Actuellement, les outils sont centrés autour du SGBD postgis. Python semble bien adapté comme outil d études car c est un langage interprété et qui dispose d un grand nombre de librairies répondant aux besoins d analyse de réseaux de transport : - environnement interactif pythonxy - lecture de fichiers et conversions ogr/gdal, shapefile, osm (routes), transitfeed (transport collectifs) - analyse spatiale shapely - analyse de graphes networkx Par ailleurs, python se connecte facilement aux bases de données (y compris postgis) et aux SIG (et notamment avec QGIS), ainsi qu à des outils de visualisation de données (mapnik, etc.). L objectif de la présente réflexion est d étudier la faisabilité d avoir une boîte à outils centrée autour du langage python, sans nécessairement s appuyer sur une base de données, et de publier les résultats obtenues sous forme de rapport technique sur le web. B. Objet du document Ce document présente les résultats des travaux effectués par Cyrille BOITEL dans le cadre d une vacation pour le CETE Méditerranée, en vue d évaluer les potentialités du langage de programmation python dans l univers du SIG transport. Il s adresse aux développeurs, chercheurs et chargés d études du domaine de l analyse géospatiale de réseaux de transport. Ce rapport est publié sur le web en même qu un jeu de données de test et que les scripts python qui permettront au lecteur de vérifier concrètement comment mettre en oeuvre ces outils : http://www.cete-mediterranee.fr/tt13/www/article.php3?id_article=317 C. Contenu du rapport Le rapport vise à tester si les différentes librairies existantes sont bien adaptées pour remplir les différentes fonctions : - savoir lire un fichier décrivant un réseau routier (couche SIG de tronçons routiers, pour des données IGN BD TOPO ou OpenStreetMap) - créer un graphe routier (détection des mailles et des impasses, plus court chemin) - savoir lire fichier décrivant un réseau TC (format Google Transit GTFS ou XML/Neptune) et créer un graphe TC - produire divers indicateurs spatiaux (mailles, impasses, densité d arrêts, etc.) - visualiser les résultats. CETE Med. Décembre 2011 3
Le rapport décrit comment les outils et librairies ont été mis en œuvre (ou adaptés) en pratique, et doit permettre à un lecteur intéressé de rejouer les tests décrits : - installer l environnement : environnement interactif pythonxy, librairies networkx, shapely, ogr - importer un fichier OSM Shapefile - créer un graphe pour Networkx à partir de ce fichier - importer un fichier Shapefile BD TOPO couche Routes et créer un graphe pour networkx - tester la librairie networkx, en particulier produire un arbre des plus courts chemins depuis un noeud - importer un fichier GTFS (librairie python) - créer un graphe à partir des données GTFS - proposer une procédure similaire pour des données Neptune - visualiser les données depuis python (sans réexporter en SHP pour visualiser depuis un SIG) Le rapport se termine par quelques propositions de développements qui permettraient d améliorer l environnement SIG Transport python, qu on pourrait baptiser Trython... II. LANGAGES, LOGICIELS ET FORMATS A. Python Python est un langage de programmation interprété. C est la version 2.7 de python qui a été utilisée au cours de cette étude. Pour installer Python et les bibliothèques nécessaires, le framework Python(x,y) a été installé. PYTHON(X,Y) est un framework dont la principale utilité dans ce projet est que lors de son installation, on peut installer aisément et proprement la plupart des bibliothèques python dont nous avons besoin (l installation n est pas forcément simple sinon, notamment par exemple gdal sous Windows). B. Bibliothèques python utilisées NETWORKX est un module python dédié à l analyse, la création et la manipulation de graphes. Ce module est disponible sur : http://networkx.lanl.gov/. Networkx est installé avec Python(x,y). OGR est une bibliothèque de manipulation de données vecteur dont il existe une version en python. Ogr est installé avec Python(x,y). SHAPELY est un module python créé à partir de la bibliothèque C GEOS, elle même basée sur la bibliothèque java JTS. Shapely a pour but d effectuer des opérations spatiales sur des objets géométriques. Shapely devrait être intégré comme plug-in de Pythonx,y d ici fin 2011, mais est sinon assez simple à installer. TRANSITFEED est un module python rassemblant un ensemble de fonctions pour la validation la lecture, la création et la manipulation d objet au format GTFS (Google Transit Feed Specification). L installation n est pas proposée avec Python(x,y), mais le simple téléchargement des sources python de transitfeed ici 1, puis la copie du dossier TransitFeed contenant les fichiers python dans Python27/Lib suffisent à rendre le module disponible. 1 http://code.google.com/p/googletransitdatafeed/downloads/detail?name=transitfeed-1.2.10.tar.gz&can=2&q= CETE Med. Décembre 2011 4
C. Shape Les fichiers shape ou ESRI shapefile sont des fichiers contenant des objets géométriques. Développé par ESRI, ce format est devenu un standard. D. Gephi Gephi est un logiciel de visualisation et d analyse de graphes complexes. Dans le cadre de cette étude, Gephi est utilisé comme visualisateur des graphes. Comme ceux-ci sont géographiquement positionnés, l algorithme de spatialisation utilisé dans Gephi est le Geo-Layout. E. GEXF GEXF est un format de données XML ayant pour but de décrire la structure de réseaux complexes et les données associées. Il s agit du format natif de Gephi. III. CREATION D UN GRAPHE ROUTIER A. Sources des données L extraction des données routières d Open Street Map nous fournit un fichier shape dont les entités (features) sont les tronçons de routes, donc de géométrie linéaire. Chaque entité possède certains attributs. Le détail est donné sur le site de geofabrik, fournisseur de données provenant d Open Street Map 2. De même, les données routières issues de la composante ROUTE de la BD_TOPO de l IGN sont des données linéaires dont les spécifications sont données sur le site de l IGN 3. Ces données sont au format shapefile et ne comportent pas les géométries des intersections de routes. Celles-ci sont déduites des découpages de la voirie en tronçons. B. Fonction native de Networkx Networkx propose une fonction de lecture des fichiers shape : read_shp 4. Cette fonction s appuie sur ogr, la bibliothèque de fonctions dédiées aux données vecteurs de gdal. La fonction read_shp prend en paramètre un chemin vers un fichier shape ou un dossier et renvoie une structure de graphe networkx. Si le paramètre fourni est un dossier, la fonction bouclera sur tous les fichiers shape présents dans ce dossier. Read_shp se comportera différemment en fonction de la géométrie des entités présentes dans le ShapeFile. Si celles-ci sont du type linéaire, elles seront importées comme arcs et leurs extrémités comme nœuds du graphe. Si les entités sont ponctuelles, elles seront importées en tant que nœuds du graphe. Nous sommes ici dans le 1 er cas : les fichiers.shp OSM ou IGN contiennent les tronçons routiers. Tous les attributs liés aux entités seront importés avec les entités. Si un fichier shape comporte des tronçons de route avec le nom de la rue associé à chaque tronçon, ce nom sera lié aux arcs du graphe networkx. Cependant, la géométrie des arcs n est pas importée de façon native dans la version 1.5 de NetworkX et cette information est perdue lors de l import. 2 http://www.geofabrik.de/data/geofabrik-osm-gis-standard-0.6.pdf 3 http://professionnels.ign.fr/display/000/506/447/5064472/dc_bdtopo_2_1.pdf 4 http://networkx.lanl.gov/reference/generated/networkx.readwrite.nx_shp.read_shp.html CETE Med. Décembre 2011 5
Les nœuds sont créés par extraction des extrémités et ne comportent aucun attribut (toutes les données métier étant associées aux tronçons du shapefile, comme attributs des arcs). Pour les identifier, networkx utilise les seules informations dont il dispose qui permettent d identifier un nœud de manière unique, c'est-à-dire ses coordonnées. Cela permet en outrs de ne pas enregistrer le même nœud plusieurs fois, si celui-ci est extrémité de plusieurs arcs. >>#Lecture et transformation d'un graphe OSM >>import networkx as nx >>G = nx.read_shp('//chemin/vers/fichier.shp') >>#acces au noeud en position 0: >>G.nodes(data=True)[0] ((376833.20436283946, 6554156.092785932), {}) Cette limitation impacte aussi les arcs créés, car les identifiants des arcs sont générés par Networkx comme des des couples (nœud origine, nœud destination). >>#acces à l'arc en position 0: >>G.edges(data=True)[0] ((376833.20436283946, 6554156.092785932), (377086.8010868877, 6553919.142526276), {'bridge':0, 'maxspeed': 0, 'AR_AUTO': 'N', 'SourceOID': 4993, 'SPEED_CAT': 7, 'ToPos': 1.0, 'FromLevel': 0, 'FID_1': 4993, 'osm_id': 39790524.0, 'Shape_Leng': 455.699752702, 'ST_NAME': None, 'ref': None, 'name': None, 'ObjectID': 34470, 'oneway': 0, 'SourceID': 1, 'AR_PEDEST': 'Y', 'ToLevel': 0, 'DIR_TRAVEL': 'B','ShpName': 'test_osm', 'FromPos': 0.0, 'type': 'footway'}) C. Adaptation de la fonction à des données spécifiques Comme décrit précédemment, la fonction read_shp récupère tous les attributs des arcs. Or tous ne nous intéressent pas forcément. EN surchargeant la fonction read_shp, nous pouvons sélectionner les attributs utiles et en rajouter d autres, notamment la géométrie des arcs. Pour récupérer la géométrie des arcs, qui n est pas encore disponible dans networkx 1.5, il nous suffit d utiliser une implémentation plus récente de read_shp disponible à partir du code source de la version «latest» (changeset : 1840:c31fd9b80325) de la bibliothèque NetworkX. Nous avons ensuite complété le code pour créer 2 fonctions dédiées respectivement à l import dans networkx de données BD_TOPO (read_shp_ign) et OSM (read_shp_osm). Le fichier readshp_ign.py illustre cette possibilité. La fonction read_shp_ign, basée sur le code source de la fonction read_shp de networkx, permet ainsi de lire un shape de la composante ROUTE de la BD_TOPO et d extraire les attributs suivant pour les arcs : gid, importance et nom_rue_d. De plus cette fonction extrait la géométrie de chaque arc en trois formats : WKB, WKT et Json et les lie à chaque arc dans les attributs : Wkt, Wkb, Json. La redondance de ces formats est certaine mais elle illustre les diverses possibilités pour récupérer une géométrie linéaire dans un chaîne de caractères. De plus, cette fonction permet d orienter le graphe non plus en fonction de la seule géométrie de l arc (origine vers destination), mais prend un paramètre de l entité du shape (dans le cas de la BD_TOPO, le champ sens ) pour orienter l arc du graphe NetworkX dans un sens, dans l autre ou encore le doubler dans le cas d une voie à double sens. Comme les données BD TOPO ne sont pas libres de droit, nous n avons pas inclus de jeu de données dans le jeu de test livré avec ce rapport. D. Nouvelle identification des noeuds et des arcs Pour manipuler plus aisément le graphe généré, il est intéressant d attribuer un identifiant unique à chaque nœud (sous forme d un attribut supplémentaire nommée id ). Ensuite on attribue à chaque arc deux nouveaux attributs o et d, qui correspondent respectivement aux attributs id des nœuds origine et destination de l arc. Un nouveau graphe est créé, dont les nœuds ont cette fois pour identifiant un entier unique et pour attributs deux champs lon et lat correspondant à leurs coordonnées. Cette manipulation est décrite dans le fichier joint readshp_transformgraph.py. et peut être exécutée une fois le graphe importé dans networkx. CETE Med. Décembre 2011 6
IV. INTEGRATION DE DONNEES TRANSPORT EN COMMUN A. Import des données GTFS La bibliothèque TransitFeed permet d importer des données GTFS valides. Nous l utilisons pour écrire une fonction de création de graphe Networkx : import_gtfs. Pour cela, on parcourt les objets python créés par l import Transitfeed afin de créer un graphe NetworkX correspondant au réseau importé. L algorithme est le suivant : - Parcours de toutes les courses (trips) circulant le jour souhaité - Pour chaque course : - Fin pour. o Parcours de tous les horaires, o Pour chaque horaire (stop_time) : o Fin pour, ajout de l arc reliant l arrêt à son successeur s il n existe pas encore (NB : l ajout de l arc ajoute implicitement les nœuds s ils n existent pas encore), ajout du numéro de ligne comme attribut de l arc, ajout de l horaire comme attribut du nœud correspondant à l arrêt Comme les horaires sont classés par ordre au sein de l itinéraire (route), nous pouvons créer un arc associant un arrêt à l arrêt successeur au sein de la course. Une seconde boucle parcourt ensuite les arrêts (stops) : si un arrêt correspond à un nœud du graphe, la longitude, la latitude et son nom sont ajoutés comme attribut du nœud. Cette procédure est située dans le fichier import_gtfs.py. Nous obtenons donc la structure de graphe suivante : un arc par tronçon de ligne et un nœud par arrêt, avec les attributs des arcs et des nœuds qui permettent de reconstruire les horaires et les courses. En effet, s il n y a qu un un arc entre deux nœuds, par contre, son attribut ['routes'] est un dictionnaire python qui comporte comme clef le numéro de ligne et comme valeur 'true'. Un exemple sera plus parlant : - pour l'arc allant du nœud 1 au nœud 2, les attributs sont : - {'routes': {'21': 'true'}} Chaque arrêt a pour attribut : longitude, latitude, nom et spells. Spells est une liste de tuples (arrivées, départs) correspondant aux passages à cet arrêt. (spell au sens d «intervalle de temps») Exemple : - >>> G.node[5641] - {'lat': 44.9023, 'lon': -0.50749, 'name': u'place Meignan', 'spells': [[(121747.0, 121747.0)], [(195 130.0, 195130.0)], [(250047.0, 250047.0)], [(211247.0, 211247.0)], [(81747.0, 81747.0)], [(161830.0, 161830.0)], [(110430.0, 110430.0)], [(74347.0, 74347.0)], [(62703.0, 62703.0)], [(153430.0, 153430.0)], [(183213.0, 183213.0)], [(140247.0, 140247.0)], [(202730.0, 202730.0)], [(123247.0, 123247.0)], [(141747.0, 141747.0)], [(191147.0, 191147.0)], [(133330.0, 133330.0)], [(120430.0, 120430.0)]...]} CETE Med. Décembre 2011 7
V. CALCUL DE PLUS COURTS CHEMINS fait avec données routières, pas TC? Un des intérêts d un outil SIG Transport est de permettre de produire des cartes d accessibilité, sous forme de cartes d isochrones, permettant de comparer par exemple l accessibilité de plusieurs modes de transport (vélo, marche, voiture, TC...) ou de leurs combinaisons. Il nous semble pertinent par conséquent d illustrer les possibilités de networkx (qui compte bien d autres fonctions de calcul sur un graphe) à travers la fonction de calcul d un arbre de plus courts chemins, qui est une représentation concrète de l accessibilité peut-être plus parlante que les isochrones. La création d un arbre des plus courts chemins correspond à la fonction de NetworkX : single_source_dijkstra_path. Celle-ci prend en paramètre un graphe NetworkX ainsi qu un nœud source. Optionnellement, un attribut des arcs peut servir à pondérer les chemins (paramètre weight ) et un seuil maximal peut être défini (paramètre cutoff ). Ce dernier permet de ne retourner que les chemins dont le poids ne dépasse pas le seuil. Les chemins résultants sont donnés sous forme d une liste de nœuds, correspondant au chemin entre la source et un nœud destination. Sans le paramètre cutoff, la fonction retourne donc les plus courts chemins à partir de la source vers tous les nœuds du graphe. Si cette fonction semble fonctionner correctement sans le paramètre cutoff, l ajout de celui-ci ne semble pas fonctionner. Il n est pas pris en compte et la fonction retourne tous les plus courts chemins, même ceux dont le poids dépasse le seuil. Cependant, la fonction single_source_dijkstra_path_length, qui ne retourne pas les plus courts chemins mais la distance du plus court chemin entre la source et les nœuds destinations fonctionne avec le seuil : le paramètre cutoff est pris en compte et seuls les nœuds dont la distance (par plus court chemin) à la source sont retournées (avec leur distance en attribut). On peut combiner single_source_dijkstra_path_length et single_source_dijkstra_path pour renseigne les arcs et les noeuds, en vue d une représentation graphique plus parlante de l accessibilité à partir d un point. Ci-dessous (et dans le fichier de tests joint à ce rapport), on ne montre que le calcul sur un réseau routier mais l algorithme fonctionnerait de la même façon sur un réseau TC tel que créée à partir d un import GTFS (sachant que le plus court chemin n est alors pas un vrai plus court chemin prenant en compte tous les horaires de passage, mais un plus court chemin routier basique s appuyant sur des temps de parcours moyens des tronçons de ligne). Evidemment, il serait souhaitable de fusionner les graphes TC et routier en vue de calculer des chemins multimodaux combinant voiture, TC (et marche à pied), néanmoins ce point ne sera pas traité dans ce rapport. Exemple : >>path=nx.single_source_dijkstra_path_length(g,g.nodes()[0],cutoff=10) >>path {(377468.5739441365, 6554480.065540515): 8, (377264.0487763658, 6554422.445071515): 8, (377203.36003082246, 6554805.756834678): 9, (376960.948384285, 6554693.14744173): 8, 377125.9067510888, 6554247.087343145): 6, (377079.8272196129, 6554291.761942603): 5, 376913.8316273317, 6554527.209797122): 8, (377039.45789186656, 6554395.407393176): 7, 376964.4603084922, 6554296.3120944165): 3, (377063.59098146856, 6554503.089481521): 8, 377065.3424349725, 6554107.537679326): 2, (377019.26095642895, 6554294.322796788): 4, 377159.4412580952, 6554468.18030059): 7, (377266.5943151489, 6554516.268083323): 7, 377117.33725722134, 6554376.52843193): 6, (377043.39789361507, 6553985.294052847): 4, 377171.1160528064, 6554204.405272208): 7, (377050.1082389802, 6554110.023207732): 3, 377314.41507554054, 6554338.834480334): 10, (376833.20436283946, 6554156.092785932): 0, 377187.9747409299, 6554325.917430893): 9, (377076.00220225006, 6554147.752672527): 7, 377303.3357321024, 6554318.780695096): 9, (376980.02876325697, 6554642.750617053): 7, 376945.85680262, 6554396.859786037): 4, (377002.8504826203, 6554627.452557467): 6, 377248.3346135393, 6554265.119623981): 8, (376990.5105082914, CETE Med. Décembre 2011 8
6554525.2070194185): 5, 377238.456182532, 6554390.370473817): 9, (377086.8010868877, 6553919.142526276): 1} Cette fonction retourne les nœuds (identifiés par leurs coordonnées), distant de moins de 10 du premier nœud du graphe G. Comme les arcs ne sont pas pondérés, la distance d un arc est de 1. VI. VISUALISATION DU GRAPHE AVEC GEPHI Afin de visualiser les graphes de NetworkX dans Gephi, le graphe est enregistré dans un fichier au format GEXF. Ensuite, il faut ouvrir ce fichier GEXF dans Gephi, le spatialiser à l aide du plug-in GeoLayout. Pour pouvoir utiliser cette spatialisation, il est nécessaire que les nœuds du graphe aient deux attributs renseignant leurs coordonnées. Le GeoLayout prendra par défaut les attributs lon et lat des nœuds, mais il est possible de spécifier n importe quel attribut des nœuds comme coordonnées. VII. PERSPECTIVES Les tests effectués dans le cadre de ce travail ont montré que l environnement python était un choix pertinent pour une boîte à outil SIG Transport, grâce aux librairies disponibles. Au-delà des principes présentés et mis en pratique avec quelques données tests, il reste bien sûr à mettre en oeuvre ces outils dans le cadre d une application concrète en vraie grandeur. Les principales améliorations seraient les suivantes : - améliorer les méthodes dédiées à l import OSM, BDTOPO, GTFS ; - lier les graphes VP et TC ; - ajouter un vrai algorithme de recherche d itinéraire TC dans networkx ; - simplifier l aller retour entre l environnement Python pour les calculs et l environnement Gephi pour la visualisation, envisager d autres outils alternatifs pour cela ; - envisager une méthode permettant de lire nativement du XML/Neptune (le format normalisé similaire à GTFS, sachant néanmoins que l on peut passer de l un à l autre via le logiciel Chouette) ; - intégrer des données INSEE à l IRIS ou à la commune, permettant des analyses spatiales (avec shapely) : corrélation entre offre de transport et données socio-économiques, etc. - compléter la batterie d outils : connexion à une base données (postgis ou autre), à un SIG (QGis ou autre), à un site web, etc. -... Vaste programme, qui pourrait être menées dans le cadre d un projet (Trython?) qui reste à construire, dans la suite logique du projet Potimart soutenu par la PREDIM en 2008 et 2009. Néanmoins ce rapport a montré selon nous que les outils disponibles depuis Python sont déjà utilisables concrètement pour produire des résultats utiles en analyse de réseaux de transport, dès aujourd hui. CETE Med. Décembre 2011 9