Pour créer les graphiques avec Python, nous avons utilisé jusqu'à présent matplotlib mais il y a énormément d'autres possibilités (pypi.python.org/pypi).
Parmi celles-ci, il y en a qui utilisent des services web dynamiques comme Google Chart.
Le blog.thematicmapping.org/2008/04/using-google-charts-with-kml.html montre comment utiliser Google Chart dans un fichier kml pour fournir des cartes dynamiques. Cette particularité est exploitée par Luis Apiolaza qui illustre sur son site comment le faire avec Python. C'est cette démarche que nous allons analyser (apiolaza.net/code/dynamic-maps-python.html).
Google Charts
Créé en 2007, Google Charts est une API qui renvoie une image au format PNG à partir d'une URL simple avec une série de paramètres. Plusieurs types de graphiques sont possibles en fonction des paramètres choisis (code.google.com/intl/fr/apis/chart/).
exemple:
http://chart.apis.google.com/chart?cht=p3&chd=t:10.0,10.0,10.0&chs=450x200&chl=Premier|Deuxième|Troisième&chco=ff0000,00ff00,0000ff
- http://chart.apis.google.com/chart? sert à appeler l'API;
- Le paramètre cht spécifie le type de graphique. Dans ce cas-ci, un digramme circulaire en 3D ("p3") ;
- chd sert à transférer les données, ici au format texte;
- chs est la taille du graphique ( en pixels);
- chl sert à spécifier les étiquettes par rapport à l'ordre des données fournies avec chd;
- chco sert à indiquer les couleurs à afficher;
- d'autres éléments peuvent être spécifiés comme les axes etc.
En tant qu'API REST, les données sont envoyées directement dans l'URL dont la longueur est limitée par le GET (2k). C'est pourquoi Google a créé des formats « condensés » pour les données (Simple Encoding Format, s, et Extended Encoding Format, e, voir code.google.com/intl/fr/apis/chart/docs/data_formats.html). Une autre solution proposée est d'utiliser POST à partir de langages comme PHP ou Python, voir code.google.com/intl/fr/apis/chart/docs/post_requests.html).
http://chart.apis.google.com/chart?cht=p3&chd=s:UUU&chs=450x200&chl=Premier|Deuxième|Troisième&chco=ff0000,00ff00,0000ff
Le gros avantage de cette solution est qu'il est donc possible de créer un graphique et de l'utiliser dans n'importe quelle page HTML sans nécessiter de fichier « physique » puisque ce n'est qu'un lien. Tous les exemples de graphiques figurent dans code.google.com/intl/fr/apis/chart/docs/gallery/chart_gall.html
Python et Google Charts
Sachant comment est construite une URL, il est alors très facile d'automatiser le processus en Python et même, de télécharger le fichier résultant:
linechart
>>> import urllib2 >>> #fonction pour créer des lineCharts simples (de http://apiolaza.net/code/dynamic-maps-python.html, légèrement modifiée) >>> def lineChart(data, size): ... baseURL = 'http://chart.apis.google.com/chart?cht=lc&chs=' ... baseData = '&chd=t:' #lineChart ... newData = ','.join(data) ... baseData = baseData + newData ... URL = baseURL + size + baseData ... return URL >>> #entrée des éléments >>> data = ['27','76.5','92','34','65','81','82','80','63','24','70.54','45.89','29.75','27'] >>> size = '250x100' >>> #création de l'URL Google Chart >>> chart = lineChart(data,size) >>> chart 'http://chart.apis.google.com/chart?cht=lc&chs=250x100&chd=t:27,76.5,92,34,65,81,82,80,63,24,70.54,45.89,29.75,27' >>> #écriture du fichier png résultant >>> res = urllib2.urlopen(chart) >>> open('chartpy.png','wb').write(res.read())
- 3964 lectures
et le résultat est :
Comme toujours avec Python, des modules ont été créés pour automatiser le processus comme « Python Google Chart » (pygooglechart), « Python Google Chart Wrapper » (GChartWrapper) ou Graphy.
L'exemple précédent traité avec GChartWrapper:
avec GchartWrapper
>>> from GChartWrapper import * >>> G = Line('27,76.5,92,34,65,81,82,80,63,24,70.54,45.89,29.75,27',encoding='text') >>> G.size(250,100) >>> G.axes.type('xy') >>> G.url 'http://chart.apis.google.com/chart?chxt=x,y&chd=t:27,76.5,92,34,65,81,82,80,63,24,70.54,45.89,29.75,27&chma=0,0,30,0&chs=250x100&cht=lc' >>> G.show() #montre le graphique dans le butineur par défaut >>> import urllib2 >>> fichier = urllib2.urlopen(G.url) >>> open('chartGchart.png','wb').write(fichier.read())
- 5152 lectures
Quelques exemples de graphiques crées avec GChartWrapper ou pygooglechart:
De nombreux autres exemples sont fournis à:
- code.google.com/p/google-chartwrapper/wiki/ChartExamples
- pygooglechart.slowchop.com/pygooglechart/browser/trunk/examples
- code.google.com/p/graphy/wiki/UserGuide
D'autres possibilités d'utilisation sont données dans :
- wordaligned.org/articles/scatter-pictures-with-google-charts montre comment, à l'aide de PIL (Python Imaging Library), convertir n'importe quelle image en une URL Google Charts (indépendante du fichier d'origine);
- positivelyglorious.com/software-media/rose-diagrams-with-google-chart/ montre comment créer des diagrammes en rosaces (« rose diagram ») avec Python (github.com/mettadore/PyGoogleRose)
- code.google.com/intl/fr-FR/apis/maps/documentation/elevation/ montre comment créer des graphiques représentant les profils topographiques à partir de Google Maps (gmaps-samples.googlecode.com/svn/trunk/elevation/python/ElevationChartCreator.py)
- Puisque GChartWrapper permet l'utilisation des tableaux (array) de numpy, il est aussi possible d'employer Google Chart pour dessiner les objets géométriques Shapely (voir www.portailsig.org/content/python-le-module-shapely-geometries-predicats-spatiaux-analyse-spatiale-matrices-de-clementi):
- exemple: limites (boundary) de POLYGON ((1 2, 2 5, 6 5, 7 2, 5 1, 1 2))
avec matplotlib chart.apis.google.com/chart
Création de cartes Google Maps dynamiques
Google Charts permet donc de créer une multitude de graphiques sous forme d'une URL relativement simple qui peut être utilisée dans un fichier kml pour créer des cartes dynamiques. Examinons la démarche de Luis Apiolaza, précédemment cité.
La première démarche est l'obtention de l'URL du ou des graphiques que l'on veut utiliser:
graphique
from GChartWrapper import * # création d'un graphique Google Chart et renvoi de l'URL def macharte(data): G = Line(data) G.size(250,100) G.color('76A4FB') G.axes.type('xy') G.grid(20.0,25.0,1,0) return G.url
- 4833 lectures
Ensuite, pour la démonstration, j'utilise mon serveur Dropbox (www.dropbox.com/)
lecture
import urllib # Lecture des données: connection à mon serveur Dropbox et extraction des lignes. f = urllib.urlopen('http://dl.dropbox.com/u/678636/test3.csv') stations = f.readlines()
- 4615 lectures
Les données dans le fichier csv sont sous la forme nom (0), long (1), lat (2) et propriété (3). Pour la démonstration, l'auteur génère des données aléatoires.
création du fichier kml
'''script de http://apiolaza.net/code/dynamic-maps-python.html,légèrement modifié''' import random: #création du fichier kml kmlBody = ('') for s in stations: data = s.split(',') # Géneration de données aléatoires a = [] for r in range(60): a.append(round(random.gauss(50,10), 1)) chart = macharte(a) kml = ( '<Placemark>\n' '<name>%s</name>\n' '<description>\n' '<![CDATA[\n' '<p>Valeur: %s</p>\n' '<p><img src="%s" width="250" height="100" /></p>\n' ']]>\n' '</description>\n' '<Point>\n' '<coordinates>%f,%f</coordinates>\n' '</Point>\n' '</Placemark>\n' ) %(data[0], data[3], chart, float(data[1]), float(data[2])) kmlBody = kmlBody + kml #"morceaux" du fichier KML kmlHeader = ('<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n' '<kml xmlns=\"http://earth.google.com/kml/2.2\">\n' '<Document>\n') kmlFooter = ('</Document>\n' '</kml>\n') kmlfinal = kmlHeader + kmlBody + kmlFooter print kmlfinal open('mon.kml','wb').write(kmlfinal)
- 5445 lectures
Le résultat est:
fichier kml
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.2"> <Document> <Placemark> <name>Arnao</name> <description> <![CDATA[ <p>Valeur: marea </p> <p><img src="http://chart.apis.google.com/chart?chxt=x,y&chd=t:46.6,34.3,54.6,41.7,35.6,47.6,64.9,47.1,29.6,57.1,63.7,63.5,44.1,54.5,61.8,43.4,55.6,43.7,61.5,52.0,60.7,57.7,73.9,53.1,42.0,49.1,41.5,47.3,58.7,41.8,50.8,67.0,47.6,51.8,53.0,61.7,48.3,51.6,45.0,47.3,71.2,60.0,48.3,68.5,56.6,42.9,54.7,47.5,44.6,63.7,41.2,52.4,40.6,57.7,41.2,60.8,37.5,32.9,59.6,33.8&chg=20.0,25.0,1.0,0.0&chco=76a4fb&chs=250x100&cht=lc" width="250" height="100" /></p> ]]> </description> <Point> <coordinates>-5.981755,43.576785</coordinates> </Point> </Placemark> <Placemark> <name>Salinas</name> <description> <![CDATA[ <p>Valeur: marea </p> <p><img src="http://chart.apis.google.com/chart?chxt=x,y&chd=t:47.2,49.8,66.1,37.1,41.6,53.9,54.2,56.9,42.6,50.2,45.7,62.5,53.3,45.8,64.7,44.0,50.5,47.5,43.4,59.1,36.9,44.4,51.6,64.8,47.2,60.9,44.2,32.1,49.6,46.1,48.0,60.4,43.7,42.6,49.6,39.0,45.3,66.4,60.3,72.5,52.2,48.6,68.8,36.9,53.4,52.3,66.1,47.9,48.3,44.9,74.1,35.6,28.2,61.3,46.6,54.1,43.0,50.3,40.8,63.2&chg=20.0,25.0,1.0,0.0&chco=76a4fb&chs=250x100&cht=lc" width="250" height="100" /></p> ]]> </description> <Point> <coordinates>-5.959396,43.578401</coordinates> </Point> </Placemark> <Placemark> <name>Bayas</name> <description> <![CDATA[ <p>Valeur: marea</p> <p><img src="http://chart.apis.google.com/chart?chxt=x,y&chd=t:53.3,49.6,59.7,31.9,44.5,43.7,62.7,65.6,53.7,37.5,70.6,65.0,43.4,46.3,49.8,61.3,52.8,54.1,51.8,61.1,61.1,50.8,50.8,63.2,47.2,56.3,53.1,60.3,36.0,46.1,73.4,35.8,43.6,52.7,53.4,61.2,39.4,56.2,66.0,32.1,51.7,55.1,58.9,50.2,29.2,51.8,49.4,53.5,63.7,66.5,45.5,40.3,45.6,38.5,46.4,49.2,29.5,58.4,56.6,58.8&chg=20.0,25.0,1.0,0.0&chco=76a4fb&chs=250x100&cht=lc" width="250" height="100" /></p> ]]> </description> <Point> <coordinates>-6.046944,43.573365</coordinates> </Point> </Placemark> </Document> </kml>
- 5154 lectures
Ce fichier kml pourrait aussi être créé avec les modules permettant de traiter les fichiers XML (Elementtree etc.). Le résultat peut être vu (toujours en utilisant mon serveur Dropbox)
- sur Google Maps.
ouverture avec le butineur par défaut
import webbrowser url="http://maps.google.com/maps?q=http://dl.dropbox.com/u/678636/"+"mon.kml" import webbrowser webbrowser.open_new(url)
- 4722 lectures
- ou directement:
- ou avec Google Earth:
En pratique, il suffit donc de mettre à jour le fichier kml avec le script Python. L'application résultante de Luis Apiolaza, maps.google.com/maps, est là pour le montrer.
Conclusions
Comme nous venons de le voir, les possibilités de Google Chart sont très intéressantes.
Cependant, l'API a aussi des contraintes:
- les données sont envoyées directement dans l'URL (taille !), mais les modules Python permettent de les « compresser » suivant les algorithmes de Google;
exemple: Extended Encoding Format (chd=e)
- >>> from pygooglechart import SimpleLineChart
- >>> chart = SimpleLineChart(200,200, y_range=(0, 10))
- >>> chart.add_data([1.0, 2.0, 6.0, 7.0, 5.0, 1.0])
- >>> chart.add_data([2.0, 5.0, 5.0, 2.0, 1.0, 2.0])
- >>> chart.get_url()
- 'http://chart.apis.google.com/chart?cht=lc&chs=200x200&chd=e:GaMzmZszgAGa,MzgAgAMzGaMz'
- 3846 lectures
- la taille des images résultantes est limitée à un maximum de 300000 pixels;
- la résolution des images PNG résultantes est bonne pour être visualisées (72 x 72 ppi) mais faible pour autre chose.
Nonobstant ces quelques désagréments, c'est toujours un plaisir de travailler en Python, sans logiciel payant ou non, sans serveur cartographique et ce, quelques soient les réserves exprimées sur Google.
Tous les traitements ont été effectués sur Mac OS X avec Python 2.5.4. Hormis les captures d'écran (Google Maps, Google Earth) et l'image matplotlib, toutes les images ont été créées avec Python et Google Chart.
Site officiel : pygooglechart (PyPI)
Site officiel : pygooglechart (Python Google Chart)
Site officiel : GChartWrapper (PyPI)
Site officiel : GChartWrapper (Python Google Chart Wrapper)
Site officiel : Graphy (PyPI)
Site officiel : Graphy
Commentaires
open() pour kml
bjr,
je souhaite utiliser votre code pour générer un kml à partir de mon site, mais cela ne fonctionne pas.
il n'y a pas d'erreur mais aucun fichier ne se lance.
voila mon code :
kmlBody = ('test')
kmlHeader = ('\n'\n'\n')
'
'
kmlFooter = ('\n'
'\n')
kmlfinal = kmlHeader + kmlBody + kmlFooter
print kmlfinal
open('mon.kml','wb').write(kmlfinal)
je souhaite que quand ce code est sollicité, le fichier kml se télécharge.
en changeant les attributs de la fonction open (wb) cela met une erreur I/O seul 'wb' ne me donne pas d'erreur mais ne me génère pas non plus de fichier.
merci de votre aide.
www.forumsig.org
Bonjour
Pour toutes questions techniques, préférez le forumsig pour les poser.
Poster un nouveau commentaire