subscribe to this blog

Logilab.org - en VF

Des nouvelles de Logilab et de nos projets sous licences libres, ainsi que des sujets qui nous tiennent à cœur (Python, Linux, Debian, le web sémantique, le calcul scientifique...)

Open Science à Toulouse : barcamp sur les Biens Communs

2014/04/16 by Anthony Truchet

Le deuxième apéritif et barcamp de la communauté Open Science Toulousaine aura lieu le 24 avril à 19h00 au bar El Deseo, 11 rue des Lois, à deux pas du Capitole et de St Sernin sur le thème des biens communs.

Plus d'informations sur http://hackyourphd.org/2014/04/aperitif-open-science-toulouse-les-biens-communs/


Deuxième hackathon codes libres de mécanique

2014/04/07 by Nicolas Chauvat

Organisation

Le 27 mars 2014, Logilab a accueilli un hackathon consacré aux codes libres de simulation des phénomènes mécaniques. Etaient présents:

  • Patrick Pizette, Sébastien Rémond (Ecole des Mines de Douai / DemGCE)
  • Frédéric Dubois, Rémy Mozul (LMGC Montpellier / LMGC90)
  • Mickaël Abbas, Mathieu Courtois (EDF R&D / Code_Aster)
  • Alexandre Martin (LAMSID / Code_Aster)
  • Luca Dall'Olio, Maximilien Siavelis (Alneos)
  • Florent Cayré, Nicolas Chauvat, Denis Laxalde, Alain Leufroy (Logilab)

DemGCE et LMGC90

Patrick Pizette et Sébastien Rémond des Mines de Douai sont venus parler de leur code de modélisation DemGCE de "sphères molles" (aussi appelé smooth DEM), des potentialités d'intégration de leurs algorithmes dans LMGC90 avec Frédéric Dubois du LMGC et de l'interface Simulagora développée par Logilab. DemGCE est un code DEM en 3D développé en C par le laboratoire des Mines de Douai. Il effectuera bientôt des calculs parallèles en mémoire partagée grâce à OpenMP. Après une présentation générale de LMGC90, de son écosystème et de ses applications, ils ont pu lancer leurs premiers calculs en mode dynamique des contacts en appelant via l'interface Python leurs propres configurations d'empilements granulaires.

Ils ont grandement apprécié l'architecture logicielle de LMGC90, et en particulier son utilisation comme une bibliothèque de calcul via Python, la prise en compte de particules de forme polyhédrique et les aspects visualisations avec Paraview. Il a été discuté de la réutilisation de la partie post/traitement visualisation via un fichier standard ou une bibliothèque dédiée visu DEM.

Frédéric Dubois semblait intéressé par l'élargissement de la communauté et du spectre des cas d'utilisation, ainsi que par certains algorithmes mis au point par les Mines de Douai sur la génération géométrique d'empilements. Il serait envisageable d'ajouter à LMGC90 les lois d'interaction de la "smooth DEM" en 3D, car elles ne sont aujourd'hui implémentées dans LMGC90 que pour les cas 2D. Cela permettrait de tester en mode "utilisateur" le code LMGC90 et de faire une comparaison avec le code des Mines de Douai (efficacité parallélisation, etc.).

Florent Cayré a fait une démonstration du potentiel de Simulagora.

LMGC90 et Code_Aster dans Debian

Denis Laxalde de Logilab a travaillé d'une part avec Rémy Mozul du LMGC sur l'empaquetage Debian de LMGC90 (pour intégrer en amont les modifications nécessaires), et d'autre part avec Mathieu Courtois d'EDF R&D, pour finaliser l'empaquetage de Code_Aster et notamment discuter de la problématique du lien avec la bibliothèque Metis: la version actuellement utilisée dans Code_Aster (Metis 4), n'est pas publiée dans une licence compatible avec la section principale de Debian. Pour cette raison, Code_Aster n'est pas compilé avec le support MED dans Debian actuellement. En revanche la version 5 de Metis a une licence compatible et se trouve déjà dans Debian. Utiliser cette version permettrait d'avoir Code_Aster avec le support Metis dans Debian. Cependant, le passage de la version 4 à la version 5 de Metis ne semble pas trivial.

Voir les tickets:

Replier LibAster dans Code_Aster

Alain Leufroy et Nicolas Chauvat de Logilab ont travaillé à transformer LibAster en une liste de pull request sur la forge bitbucket de Code_Aster. Ils ont présenté leurs modifications à Mathieu Courtois d'EDF R&D ce qui facilitera leur intégration.

Voir les tickets:

Suppression du superviseur dans Code_Aster

En fin de journée, Alain Leufroy, Nicolas Chauvat et Mathieu Courtois ont échangé leurs idées sur la simplification/suppression du superviseur de commandes actuel de Code_Aster. Il est souhaitable que la vérification de la syntaxe (choix des mots-clés) soit dissociée de l'étape d'exécution.

La vérification pourrait s'appuyer sur un outil comme pylint, la description de la syntaxe des commandes de Code_Aster pour pylint pourrait également permettre de produire un catalogue compréhensible par Eficas.

L'avantage d'utiliser pylint serait de vérifier le fichier de commandes avant l'exécution même si celui-ci contient d'autres instructions Python.

Allocation mémoire dans Code_Aster

Mickaël Abbas d'EDF R&D s'est intéressé à la modernisation de l'allocation mémoire dans Code_Aster et a listé les difficultés techniques à surmonter ; l'objectif visé est un accès facilité aux données numériques du Fortran depuis l'interface Python. Une des difficultés est le partage des types dérivés Fortran en Python. Rémy Mozul du LMGC et Denis Laxalde de Logilab ont exploré une solution technique basée sur Cython et ISO-C-Bindings. De son côté Mickaël Abbas a contribué à l'avancement de cette tâche directement dans Code_Aster.

Doxygen pour documentation des sources de Code_Aster

Luca Dall'Olio d'Alneos et Mathieu Courtois ont testé la mise en place de Doxygen pour documenter Code_Aster. Le fichier de configuration pour doxygen a été modifié pour extraire les commentaires à partir de code Fortran (les commentaires doivent se trouver au dessus de la déclaration de la fonction, par exemple). La configuration doxygen a été restituée dans le depôt Bitbucket. Reste à évaluer s'il y aura besoin de plusieurs configurations (pour la partie C, Python et Fortran) ou si une seule suffira. Une configuration particulière permet d'extraire, pour chaque fonction, les points où elle est appelée et les autres fonctions utilisées. Un exemple a été produit pour montrer comment écrire des équations en syntaxe Latex, la génération de la documentation nécessite plus d'une heure (seule la partie graphique peut être parallélisée). La documentation produite devrait être publiée sur le site de Code_Aster.

La suite envisagée est de coupler Doxygen avec Breathe et Sphinx pour compléter la documentation extraite du code source de textes plus détaillés.

La génération de cette documentation devrait être une cible de waf, par exemple waf doc. Un aperçu rapide du rendu de la documentation d'un module serait possible par waf doc file1.F90 [file2.c [...]].

Voir Code Aster #18 configure doxygen to comment the source files

Catalogue d'éléments finis

Maximilien Siavelis d'Alneos et Alexandre Martin du LAMSID, rejoints en fin de journée par Frédéric Dubois du LMGC ainsi que Nicolas Chauvat et Florent Cayré de Logilab, ont travaillé à faciliter la description des catalogues d'éléments finis dans Code_Aster. La définition de ce qui caractérise un élément fini a fait l'objet de débats passionnés. Les points discutés nourriront le travail d'Alexandre Martin sur ce sujet dans Code_Aster. Alexandre Martin a déjà renvoyé aux participants un article qu'il a écrit pour résumer les débats.

Remontée d'erreurs de fortran vers Python

Mathieu Courtois d'EDF R&D a montré à Rémy Mozul du LMGC un mécanisme de remontée d'exception du Fortran vers le Python, qui permettra d'améliorer la gestion des erreurs dans LMGC90, qui a posé problème dans un projet réalisé par Denis Laxalde de Logilab pour la SNCF.

Voir aster_exceptions.c

Conclusion

Tous les participants semblaient contents de ce deuxième hackathon, qui faisait suite à la première édition de mars 2013 . La prochaine édition aura lieu à l'automne 2014 ou au printemps 2015, ne la manquez pas !


Naissance de la communauté Open Science Toulousaine

2014/04/02 by Anthony Truchet

Ils étaient une vingtaine à se (re)trouver à l’occasion du premier apéritif & barcamp Open Science à Toulouse organisé par Logilab et Hack your PhD. La plupart étaient avant tout curieux de voir qui et quoi se cachaient derrière cette annonce :

un rendez-vous périodique, informel et sympathique a pour but de favoriser les échanges entre tous les acteurs intéressés par un aspect de l’Open Science : Open Data, les rapports Sciences & Société, Open Source, Open Access, Big Data & Data Science, etc.

Curieux souvent parce qu’ils s’étaient reconnus dans l’une ou l’autre – et souvent plusieurs – de ces facettes de l’Open Science sans avoir déjà rencontré l’étiquette Open Science pour autant.

Les échangent se nouent dans la communauté Open Science

Mais alors l’Open Science : c’est quoi ?

Heureusement personne n’a asséné de définition définitive. J’ai tenté de montrer, à travers une brève présentation de Hack your PhD et de Logilab comment l’Open Science est avant tout une démarche d’ouverture dans la pratique de la recherche scientifique qui s’étend au delà du cadre du laboratoire.

L’objectif de la soirée était de permettre à la communauté Open Science locale de se découvrir ; aux acteurs de science ou d’ouverture de faire connaissance. De fait les discussions et prises de contacts informelles allaient bon train autour d’un verre et quelques tapas… et c’est donc à chacun des participants de partager ses échanges sur le thème que fait-on à Toulouse ?

Le fournisseur d’accès associatif tetaneutral nous met à disposition une liste de diffusion à l’adresse open-science-toulouse@lists.tetaneutral.net. Merci à eux ! J’invite vivement les participants à l’apéro à s’y présenter en quelques mots : faites nous part de votre perception de cet événement et partager vos intérêts et projets.

On se retrouvera bientôt pour un prochain événement qui tiendra plus de l’atelier. Quelques suggestion qui sont dores et déjà apparues : un atelier sur les outils pratiques pour être ouvert, un séminaire dans un centre de recherche universitaire, un atelier sur les alignements de données publiques et l’évolutivité des schéma de données avec CubicWeb, …

Vos propositions sont très bienvenues : la communauté Open Science Toulousaine deviendra ce qu’ensemble nous en ferons !

Ce compte rendu a été initialement publié sur le site de hackyourphd : http://hackyourphd.org/2014/02/naissance-de-la-communaute-toulousaine/


Ecriture de liaisons C++ pour Python

2014/03/13 by Laura Médioni

Dans le cadre des travaux d'interfaçage de l'application Code_TYMPAN avec du code Python, nous avons réalisé l'étude ci-dessous sur les différents moyens de générer des liaisons Python pour du code C++. Cette étude n'a pas vocation à être exhaustive et s'est concentrée sur les aspects qui nous intéressaient directement pour les travaux susmentionnés.

Solutions existantes

Une recherche des solutions existantes a été effectuée, qui a permis d'obtenir la liste suivante pour une écriture manuelle du code d'interfaçage :

  • Cython, un langage de programmation inspiré de Python, basé sur Pyrex
  • Boost.Python, une librairie C++ de la collection Boost permettant d'écrire des liaisons Python
  • PyBindGen, un outil implémenté en Python et permettant de décrire des liaisons C++ directement dans ce langage
  • Swig, un outil permettant de générer des liaisons C++ pour plusieurs langages de programmation
  • Shiboken, un générateur de code d'enrobage pour des bibliothèques C/C++ basé sur du CPython

Des solutions existent pour automatiser cette écriture. Ce sont des outils qui se basent sur des compilateurs (gcc, clang) pour faire l'analyse grammaticale du code C++ et générer le code d'interfaçage correspondant. Par exemple :

  • XDress, qui permet de générer des fichiers Cython (.pyx, .pxd) à partir de gcc-xml ou de libclang
  • PyBindGen dispose de fonctionnalités permettant de générer des liaisons python à partir de gcc
  • Ce billet explique comment utiliser libclang pour parcourir l'AST d'un code C++ et générer des liaisons Boost.Python

Aspects pris en compte

Cet article est intéressant car il aborde de façon très complète les problématiques découlant de l'écriture de liaisons C++ pour des langages de haut niveau. Il a été écrit lors des travaux de développement de Shiboken.

Dans notre cas, les critères pour le choix d'une solution finale portaient sur différents aspects :

  • Le coût de développement : prise en main de l'outil, quantité de code à écrire pour enrober une classe C++ donnée, coût de l'intégration dans le système de build, degré d'automatisation de la solution, lisibilité du code généré, etc.
  • La gestion de la mémoire : comptage de référence, gestion de la propriété des objets
  • La qualité et l'exhaustivité du support C++ : compatibilité STL, gestion des références et pointeurs, des templates, surcharges d'opérateurs, etc.
  • La pérennité de la solution : technologies mises en œuvre par l'outil, qualité de la documentation, support, taille et degré d'activité de la communauté de développeurs

Solutions envisagées

Swig n'a pas été retenu partant de l'a priori que c'était une solution plutôt lourde et davantage orientée C que C++, constat tiré lors de travaux réalisés par Logilab il y a quelques mois de cela. La solution Boost.Python n'a pas été explorée car notre souhait était de nous rapprocher davantage du Python que du C++. Shiboken semble prometteur, bien que peu documenté et mal référencé (les premières recherches tombent sur d'anciennes pages du projet, donnant l'impression que la dernière release date d'il y a plusieurs années, alors qu'en fait, non). Il a été écarté par manque de temps.

PyBindGen et Cython ont fait l'objet de tests.

La cible des tests a été l'interfaçage de smart pointers, puisque cela correspond à un de nos besoins sur le projet Code_TYMPAN.

Les essais ont été réalisés sur des classes simplifiées:

  • MyElement, classe qui représente un élément à encapsuler dans un smart pointer et hérite de IRefCount qui implémente un comptage de référence
  • SmartPtr, classe smart pointer "maison" de l'application
  • Quelques fonctions de test manipulant des smart pointers SmartPtr

Voici un extrait des en-têtes du code C++:

#ifndef MY_ELEMENT_H
#define MY_ELEMENT_H
#include <iostream>
using namespace std;
#include "SmartPtr.h"

class MyElement : public IRefCount
{
    public:
        MyElement ();
        MyElement (string);
            string Name(){ return _name; }
            virtual ~MyElement ();

    protected:
        string _name;
};
typedef SmartPtr<MyElement> SPMyElement;
#endif

#ifndef SMART_PTR_H
#define SMART_PTR_H
template <class T> class SmartPtr
{
    public:
        SmartPtr();
        SmartPtr(T*);
        const T* getRealPointer() const;

    protected:
        T* _pObj;
}
#endif

SPMyElement BuildElement();
void UseElement(SPMyElement elt);

Cython

Cet outil offre maintenant un bon support du C++ (globalement depuis la version 0.17). Son avantage est qu'il permet la manipulation d'objets à la fois C++ et Python dans des fichiers Cython.

Utilisation
  • Écriture (facultative) d'un fichier .pxd qui contient une recopie des headers à enrober (avec un lien vers les fichiers): déclarations des types, classes, fonctions...
  • Écriture d'un fichier .pyx qui contient des appels de fonctions, constructions d'objets C ou python. Les fonctions et classes de ce module sont utilisables depuis un script Python
  • Compilation du code Cython décrivant les interfaçages C++, génération et compilation du code C++ correspondant et production d'une librairie Python.

Cython offre un support pour les conteneurs de la STL, les templates, la surcharge de la plupart des opérateurs ("->" non supporté), le passage d'arguments par référence et par pointeur, etc.

Actuellement en version 0.20.1, la dernière release date du 11 février 2014. Les outils Cython sont relativement bien documentés et sa communauté de développeurs est active.

Exemple

Voici le code d'interfaçage Cython correspondant à l'exemple exposé ci-dessus:

setup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(name='smartptr',
    ext_modules=cythonize('*.pyx',
        ),
)

smartptr.pxd:

from libcpp.string cimport string

cdef extern from "src/SmartPtr.h":
    cdef cppclass SmartPtr[T]:
        SmartPtr()
        SmartPtr(T *)
        T *getRealPointer() # Pas de surcharge de ->. L'accès à l'objet ne peut être qu'explicite

cdef extern from "src/MyElement.h":
    cdef cppclass MyElement:
        MyElement()
        MyElement(string)
        string Name()

cdef extern from "src/Test.h":
    SmartPtr[MyElement] BuildSPElement()
    void UseSPElement(SmartPtr[MyElement])

smartptr.pyx:

# distutils: language = c++
# distutils: libraries = element

cimport smartptr
cimport cython

cdef class PySPMyElement:
    cdef SmartPtr[MyElement] thisptr

    def __cinit__(self, name=""):
        """ PySPMyElement constructor """
        if name == "":
            self.thisptr = SmartPtr[MyElement](new MyElement())
        else:
            self.thisptr = SmartPtr[MyElement](new MyElement(name))

    def get_name(self):
        """ Returns the name of the element """
        return self.thisptr.getRealPointer().Name()

@cython.locals(elt=PySPMyElement)
def build_sp_elt():
    """ Calls the C++ API to build an element """
    elt = PySPMyElement.__new__(PySPMyElement)
    elt.thisptr = BuildSPElement()
    return elt

@cython.locals(elt=PySPMyElement)
def use_sp_elt(elt):
    """ Lends elt to the C++ API """
    UseSPElement(elt.thisptr)

XDress

XDress est un générateur automatique de code d'interfaçage C/C++ écrit en Python, basé sur Cython.

Utilisation
  • On liste dans un fichier xdressrc.py les classes et fonctions à envelopper (il n'est pas nécessaire de mettre la signature, le nom suffit. On peut choisir d'envelopper seulement certaines classes d'un .h).
  • On exécute xdress qui génère les .pyx et .pxd correspondants

XDress permet d'envelopper des conteneurs STL via son générateur stlwrap (les conteneurs à enrober doivent être listés dans le xdressrc.py). A titre d'exemple, les vecteurs sont convertis en numpy array du type contenu.

Ce projet est récent et pas très documenté, mais il semble prometteur.

PyBindGen

Utilisation
  • Écriture d'un script Python qui décrit les classes/fonctions C++ à enrober en s'appuyant sur le module PyBindGen (1) → permet de générer un fichier .cpp
  • Compilation du code C++ généré, avec la librairie du programme à envelopper et génération d'une librairie Python.

Ce processus peut être automatisé:

  • Écriture d'un script Python qui utilise les outils PyBindGen pour lister les modules (headers) à envelopper, les lire et lancer la génération automatique des liaisons c++

ou:

  • Écriture d'un script Python qui utilise les outils PyBindGen pour lister les modules (headers) à envelopper et générer le script Python décrit en (1) (ce qui permettrait une étape intermédiaire pour personnaliser les liaisons)

PyBindGen offre un support pour la STL, l'héritage (multiple), la gestion des exceptions C++ côté Python, la surcharge d'opérateurs, le comptage de référence, la gestion de la propriété des objets. Mais il supporte mal les templates.

Actuellement en version 0.17, la dernière release date du 15 février 2014 (entre autres ajout de la compatibilité Python 3.3).

Exemple

PyBindGen, en l'état, n'offre pas la possibilité d'envelopper simplement des templates, ni des smart pointers "maison" par extension.

Une classe de ce package permet d'envelopper des shared pointers de Boost (boost::shared_ptr). Il serait à priori possible de la modifier légèrement pour enrober les smart pointers de l'application Code_TYMPAN (non testé).

Voici néanmoins à titre d'exemple le code permettant d'envelopper la classe MyElement et des fonctions manipulant non plus des smart pointers mais des 'MyElement *'

Test.h :

MyElement *BuildElement();
void UseElement(MyElement *elt);

smartptr.py :

import pybindgen
import sys
from pybindgen import retval
from pybindgen import param

mod = pybindgen.Module('smartptr')

# File includes
mod.add_include('"src/MyElement.h"')
mod.add_include('"src/Test.h"')

# Class MyElement
MyElement = mod.add_class('MyElement')
MyElement.add_constructor([])
MyElement.add_method('Name', retval('std::string'), [])


# Test functions
# transfer_ownership=False : here Python program keeps the ownership of the element it passes to the C++ API
mod.add_function('UseElement', None, [param('MyElement *', 'elt', transfer_ownership=False)])
# caller_owns_return=True : here Python program will be responsible for destructing the element returned by BuildElement
mod.add_function('BuildElement', retval('MyElement *',  caller_owns_return=True), [])

if __name__ == '__main__':
    mod.generate(sys.stdout)

Boost.Python

Les liaisons Python s'écrivent directement en C++.

C'est un outil très fiable et pérenne, avec de par sa nature un très bon support C++ : gestion de la mémoire, templates, surcharges d'opérateurs, comptage de référence, smart pointers, héritage, etc.

Inconvénient : la syntaxe (en mode templates C++) n'est pas très intuitive.

Conclusion

Les solutions Cython et PyBindGen ont été explorées autour de la problématique d'enrobage de smart pointers. Il en est ressorti que:

  • Il est possible d'enrober facilement des smart pointers Code_TYMPAN en Cython. L'approche qui a été choisie est de manipuler depuis Python les objets C++ directement au travers de smart pointers (les objets Python contenus dans le .pyx encapsulent des objets SmartPtr[T *], agissant donc comme des proxys vers les objets). De cette façon, l'utilisation depuis Python d'un objet C++ incrémente le compteur de référence côté C++ et cela garantit qu'on ne perdra pas la référence à un objet au cours de son utilisation côté Python. Un appel à getRealPointer() pour enrober des fonctions manipulant directement des T * sera toujours possible dans le code Cython au besoin.
  • PyBindGen présente l'intérêt d'offrir des moyens de gérer l'attribution de la propriété des éléments entre C++ et Python (transfer_ownership, caller_owns_return). Malheureusement, il n'offre pas la possibilité d'enrober des smart pointers sans modification de classes PyBindGen, ni d'envelopper des templates.

Par ailleurs, après utilisation de PyBindGen, il nous a semblé que bien qu'il présente des idées intéressantes, sa documentation, ses tutoriels et son support sont trop succints. Le projet est développé par une seule personne et sa viabilité est difficile à déterminer. Cython en revanche offre un meilleur support et plus de fiabilité.

Le choix final s'est donc porté sur Cython. Il a été motivé par un souci d'utiliser un outil fiable limitant les coûts de développement (élimination de PyBindGen), aussi proche de Python que possible (élimination de Boost.Python). Cet outil semble fournir un support C++ suffisant par rapport à nos besoins tels que perçus à ce stade du projet.

De plus si on cherche un moyen de générer automatiquement les liaisons Python, XDress présente l'avantage de permettre l'utilisation de libclang comme alternative à gcc-xml (PyBindGen est basé sur gcc-xml uniquement). Une possibilité serait par ailleurs d'utiliser XDress pour générer uniquement le .pxd et d'écrire le .pyx manuellement.

Une question qui n'a pas été abordée au cours de cette étude car elle ne correspondait pas à un besoin interne, mais qui est néanmoins intéressante est la suivante: est-il possible de dériver depuis Python des classes de base définies en C++ et enveloppées en Cython, et d'utiliser les objets résultants dans l'application C++ ?


Mini compte rendu Meetup Debian à Nantes

2014/03/13 by Arthur Lutz

Hier soir, je suis allé au premier meetup Debian à Nantes. C'était bien sympatique, une vingtaine de personnes ont répondu présent à l'appel de Damien Raude-Morvan et Thomas Vincent. Merci à eux d'avoir lancé l'initiative (le pad d'organisation).

//www.logilab.org/file/228927/raw/debian-france.jpg

Après un tour de table des participants, et de quelques discussions sur debian en général (et une explication par Damien de l'état de Java dans Debian), Damien a présenté l'association Debian France ainsi que le concours du nouveau contributeur Debian. La liste d'idées est longue et sympatique n'hésitez pas à aller jeter un oeil et faire une contribution.

Ensuite Thomas nous a présenté l'équipe de traduction francaise de debian et ses principles de fonctionnement (qualité avant quantité, listes de discussion, IRC, processus de traduction, etc.).

//www.logilab.org/file/228931/raw/saltstack_logo.jpg

Finalement, j'ai rapidement présenté Salt et sa place dans Debian. Pour l'archive publique : les diapos de la présentation.

À la prochaine !

Pour faire un commentaire, il faut s'authentifier ou s'enregistrer.


Retour sur MiniDebConf Paris 2014

2014/03/05 by Arthur Lutz
http://www.logilab.org/file/226609/raw/200px-Mini-debconf-paris.png

Nous sommes heureux d'avoir participé à la MiniDebConf Paris.

Nous avons sponsorisé l'évenement mais aussi effectué deux présentations :

Avec une cinquantaine de participants sur les deux jours, c'est toujours agréable de rencontrer la communauté francaise autour de Debian. Merci donc à l'association Debian France d'avoir organisé cette conférence.


InfoLab Rennes - 17 décembre

2013/12/18 by Arthur Lutz

InfoLab Rennes - 17 décembre

Le mardi 17 décembre, nous avons participé à la 4ème rencontre du groupe national infolab à Rennes. Voici quelques notes et reflexions prises à cette occasion. La journée a été dense, donc vous ne trouverez que des bribes des sujets dans ce compte rendu.

http://www.fing.org/local/cache-vignettes/L680xH165/_info_lab_V3_logo_petit-d6f63.jpg

Présentation générale le matin

Une présentation générale de la mission "infolab" menée par le Fing a permis d'initier la réflexion et la discussion sur ce qu'est un infolab. Sarah Labelle (Université Paris XIII), Amandine Brugières (Poitiers), Claire Gallon (Nantes, Libertic), Simon Chignard (Rennes), Charles Nepote (Marseille), et Thierry Marcou (Paris) se sont succédé pour expliquer les réflexions et outils en cours d'élaboration. Nous avons noté :

  • une liste de 150 outils répertoriés pour aider à manipuler les données,
  • un prototype de méthodologie,
  • des documents récapitulatifs sur les différents métiers autour de la donnée.

L'assemblée se pose la question de comment rendre accessible les technologies, les données, les outils. Il nous semble qe cette démarche n'est possible qu'en ayant des mécanismes transparents, reproductibles et collaboratifs. Nous y voyons donc les principes de "logiciel libre", des "standards" et des "outils collaboratifs". Comment rendre le traitement de la donnée reproductible et transparent ?

À Logilab, nous avons adoptés les outils suivants pour traiter la données :

  • CubicWeb (en python) avec un certain nombre de cubes (modules type plugins)
  • les standards du web sémantique pour faire de la publication et de l'échange de données (publication de dumps, negociation de contenu et sparql endpoints),
  • les outils de versionning et de collaboration (en logiciel libre) : mercurial qui permettent une co-construction décentralisée sur du code source, mais aussi sur certaines données (voir par exemple les jeux de données publié sur github).

Au sujet de l'annuaire des outils : comporte-t-il une évaluation de l'accessibilité ? D'un outil WYSIWYG à un outil de programmation... quelle grille de notation ? Faut-il faire son propre graphisme ou est-ce "configurable" sans compétence... Grille d'évaluation aussi sur l'autonomie de l'outil ? Par exemple utiliser Google Drive pose des questions des droits sur les données (exemple récent sur la propriété des données lorsqu'elles sont affichées sur une carte google à travers l'API). Dans le domaine du logiciel libre, avec lequel nous pouvons établir un bon nombre de parallèles, il existe des méthodes formelles d'évaluation.

D'autres questions ont été abordées :

  • stockage et pérennité des démarches et des données : dans l'industrie logicielle une formalisation pertinente en rapport avec cette question est le semantic versionning qui permet d'établir une traçabilité. Sur l'archivage, de nombreuses solutions sont envisageables mais pas forcément formalisées (stockage P2P, hébergement mutualisé, etc).
  • le contrôle d'accès : qui accède comment, comment partage-t-on de manière sécurisée ? Ceci nous fait penser aux études menées par le MIT sur leur projet OpenPDS.
  • comment rendre le crowdsourcing efficace ? Des outils comme CrowdCarfting (PyBossa en Python) permettraient de "simplement" définir une application de crowdsourcing (eg. cartographie, annotation d'image, classement d'image, OCR collaboratif, etc.) mais comment faire le lien avec les données "officielles" ?

Atelier l'après-midi

Suite à une visite du labfab de Rennes, nous avons participé aux ateliers, étant deux personnes de chez Logilab, nous avons pu participer à trois ateliers :

  • travail sur la charte des infolabs,
  • datavisualisation et réflexions autour des données,
  • comment mener une campagne de crowdsourcing et sur quels types de données.

Dans l'atelier sur le crowdsourcing, nous avons parlé rapidement de CKAN et http://datahub.io/ qui sont des moteurs de recherche sur les jeux de données ouverts.

La suite

Nous avons participé à DataPride (à Nantes) et comptons participer dans le futur à DataLab (à Nantes) et DataShacker (à Paris), s'agit-il d'initiatives "compatibles" avec les principes des infolabs ? Sont-ce des infolabs ? La suite de l'initiative nous le dira sûrement.

Les prochaines rencontres Infolab auront probablement lieu à Bordeaux en janvier et à Paris lors de Futur en Seine (du 12 au 15 juin : au CNAM, à la Gaité Lyrique, au Square Emile Chautemps).


Lecture de données tabulées avec Numpy -- Retour d'expérience sur dtype

2013/12/17 by Damien Garaud

Ce billet est un petit retour d'expérience sur l'utilisation de Numpy pour lire et extraire des données tabulées depuis des fichiers texte.

Chaque section, hormis les objectifs ou la conclusion, correspond soit à une difficulté rencontrée, une remarque technique, des explications et références vers la documentation officielle sur un point précis qui m'a fait patauger quelques temps. Il y a de forte chance, pour certains d'entre vous, que les points décrits ici vous paraissent évidents, que vous vous disiez "mais qui ne sait pas ça ?!". J'étais moi-même le premier étonné, depuis que je connais Numpy, de ne pas savoir ce genre de choses. Je l'étais moins quand autour de moi, mes camarades ne semblaient pas non plus connaître les petites histoires numpysiennes que je vais vous conter.

http://www.logilab.org/file/203839/raw/numpylogo.png

Objectifs

Le Pourquoi et le Où on va au fait ?

J'avais sous la main des fichiers aux données tabulées, type CSV, où les types de données par colonne étaient clairement identifiés. Je ne souhaitais pas passer du temps avec le module csv de la bibliothèque standard à convertir chaque élément en type de base, str, flottants ou dates. Numpy étant déjà une dépendance du projet, et connaissant la fonction np.genfromtxt, j'ai évidemment souhaité l'utiliser.

Il était nécessaire de ne lire que certaines colonnes. Je souhaitais associer un nom à chaque colonne. L'objectif était ensuite d'itérer sur ces données ligne par ligne et les traiter dans des générateurs Python. Je n'utilise pas ici Numpy pour faire des opérations mathématiques sur ces tableaux à deux dimensions avec des types hétérogènes. Et je ne pense d'ailleurs pas qu'il soit pertinent d'utiliser ce type de tableau pour faire ces opérations.

dtypes différents, str et extraction de chaînes vides

On utilise ici l'argument dtype des fonctions telles que np.genfromtxt pour lire des fichiers tabulés dont les colonnes sont de types différents.

Attention au dtype à passer à np.genfromtxt ou np.recfromtxt quand on parse des données tabulée (file ou stream). Pour parser une colonne de chaînes de caratères, lui passer [('colname', str)] renvoie des chaînes vides si les autres dtypes sont de types différents.

Il faut préciser la taille :

dtype=[('colname', str, 10)]
# or
dtype=[('colname', 'S10')]

Ou alors prendre un "vrai" objet str Python :

dtype=[('colname', object)]

aussi équivalent à:

dtype=[('colname', 'object')]

Et oui, je suis littéralement tombé sur l'évidence, les "types Numpy", c'est du type C. Et les chaînes, c'est du char * et il y a donc besoin de la taille. La solitude s'est fait moindre quand j'ai su que je n'étais pas le seul à être tombé sur des données tronquées voire vides.

dtype et tableau à zéro dimension

Attention au tableau Numpy 0D quand le contenu tabulé à parser n'a qu'une seule ligne (cas d'un np.[rec]array avec plusieurs dtypes). Impossible d'itérer sur les éléments puisque dimension nulle.

Supposons que vous ayez un fichier tabulé d'une seule ligne :

Name,Play,Age
Coltrane,Saxo,28

J'utilise np.genfromtxt en précisant le type des colonnes que je souhaite récupérer (je ne prends pas en compte ici la première ligne).

data = np.genfromtxt(filename, delimiter=',',
                     dtype=[('name', 'S12'), ('play', object), ('age', int)],
                     skip_header=1)

Voici la représentation de mon array :

array(('Coltrane', 'Saxo', 28),
    dtype=[('name', 'S12'), ('play', 'O'), ('age', '<i8')])

Si dans votre code, vous avez eu la bonne idée de parcourir vos données avec :

for name, instrument, age in data:
    # ...

vous pourrez obenir un malheureux TypeError: 'numpy.int64' object is not iterable par exemple. Vous n'avez pas eu de chance, votre tableau Numpy est à zéro dimension et une shape nulle (i.e. un tuple vide). Effectivement, itérer sur un objet de dimension nulle n'est pas chose aisée. Ce que je veux, c'est un tableau à une dimension avec un seul élément (ici un tuple avec mes trois champs) sur lequel il est possible d'itérer.

Pour cela, faire:

>>> print data
array(('Coltrane', 'Saxo', 28),
      dtype=[('name', 'S12'), ('play', 'O'), ('age', '<i8')])array(('babar', 42.), dytpe=[('f0', 'S5'), ('f1', '<f8')])
>>> print data.shape, data.ndim
(), 0
>>> data = data[np.newaxis]
>>> print data.shape, data.ndim
(1,), 1

dtype et str : chararray ou ndarray de strings ?

Pour les chararray, lire help(np.chararray) ou http://docs.scipy.org/doc/numpy/reference/generated/numpy.chararray.html. En particulier:

The chararray class exists for backwards compatibility with Numarray, it is not recommended for new development. Starting from numpy 1.4, if one needs arrays of strings, it is recommended to use arrays of dtype object_, string_ or unicode_, and use the free functions in the numpy.char module for fast vectorized string operations.

On fera donc la distinction entre:

# ndarray of str
na = np.array(['babar', 'celeste'], dtype=np.str_)
# chararray
ca = np.chararray(2)
ca[0], ca[1] = 'babar', 'celeste'

Le type de tableau est ici différent : np.ndarray pour le premier et np.chararray pour le second. Malheureusement pour np.recfromtxt et en particulier pour np.recarray, si on transpose le label de la colonne en tant qu'attribut, np.recarray il est transformé en chararray avec le bon type Numpy --- |S7 dans notre cas --- au lieu de conserver un np.ndarray de type |S7.

Exemple :

from StringIO import StringIO
rawtxt = 'babar,36\nceleste,12'
a = np.recfromtxt(StringIO(rawtxt), delimiter=',', dtype=[('name', 'S7'), ('age', int)])
print(type(a.name))

Le print rend bien un objet de type chararray. Alors que :

a = np.genfromtxt(StringIO(rawtxt), delimiter=',', dtype=[('name', 'S7'), ('age', int)])
print(type(a['name']))

affiche ndarray. J'aimerais que tout puisse être du même type, peu importe la fonction utilisée. Au vue de la documentation et de l'aspect déprécié du type charray, on souhaiterait avoir que du ndarray de type np.str. J'ai par ailleurs ouvert le ticket Github 3993 qui n'a malheureusement que peu de succès :-(

Tableau de chaînes : quel dtype ?

Si certains se demandent quoi mettre pour représenter le type "une chaîne de caractères" dans un tableau numpy, ils ont le choix :

np.array(['coltrane', 'hancock'], dtype=np.str)
np.array(['coltrane', 'hancock'], dtype=np.str_)
np.array(['coltrane', 'hancock'], dtype=np.string_)
np.array(['coltrane', 'hancock'], dtype='S')
np.array(['coltrane', 'hancock'], dtype='S10')
np.array(['coltrane', 'hancock'], dtype='|S10')

Les questions peuvent être multiples : est-ce la même chose ? pourquoi tant de choses différentes ? Pourquoi tant de haine quand on lit la doc Numpy et que l'info ne saute pas aux yeux ? À savoir que le tableau construit sera identique dans chacun des cas. Il existe peut-être même d'autres moyens de construire un tableau de type identique en lui passant encore un n-ième argument dtype différent.

  • np.str représente le type str de Python. Il est converti automatiquement en type chaines de caractère Numpy dont la longueur correspond à la longueur maximale rencontrée.
  • np.str_ et np.string_ sont équivalents et représentent le type "chaîne de caractères" pour Numpy (longueur = longueur max.).
  • Les trois autres utilisent la représentation sous forme de chaîne de caractères du type np.string_.
    • S ne précise pas la taille de la chaîne (Numpy prend donc la chaîne la plus longue)
    • S10 précise la taille de la chaîne (données tronquées si la taille est plus petite que la chaîne la plus longue)
    • |S10 est strictement identique au précédent. Il faut savoir qu'il existe cette notation <f8 ou >f8 pour représenter un flottant. Les chevrons signifient little endian ou big endian respectivement. Le | sert à dire "pas pertinent". Source: la section typestr sur la page http://docs.scipy.org/doc/numpy/reference/arrays.interface.html

À noter que j'ai particulièrement apprécié l'utilisation d'un symbole pour spécifier une information non pertinente --- depuis le temps que je me demandais ce que voulait bien pouvoir dire ce pipe devant le 'S'.

Conclusion (et pourquoi pas pandas ?)

http://www.logilab.org/file/203841/raw/pandas_logo.png

Pandas, bibliothèque Python d'analyse de données basée sur Numpy, propose, via sa fonction read_csv, le même genre de fonctionnalités. Il a l'avantage de convertir les types par colonne sans lui donner d'information de type, qu'on lise toutes les colonnes ou seulement quelques unes. Pour les colonnes de type "chaîne de caractères", il prend un dtype=object et n'essaie pas de deviner la longueur maximale pour le type np.str_. Vous ne rencontrerez donc pas "le coup des chaînes vides/tronquées" comme avec dtype='S'.

Je ne m'étalerai pas sur tout le bien que je pense de cette bibliothèque. Je vous invite par ailleurs à lire/ parcourir un billet de novembre qui expose un certain nombre de fonctionnalités croustillantes et accompagné d'un IPython Notebook.

Et pourquoi pas Pandas ? Il ne me semble pas pertinent de dépendre d'une nouvelle bibliothèque, aussi bien soit-elle, pour une fonction, aussi utile soit-elle. Pandas est un projet intéressant, mais jeune, qui ne se distribue pas aussi bien que Numpy pour l'instant. De plus, le projet sur lequel je travaillais utilisait déjà Numpy. Je n'avais besoin de rien d'autre pour réaliser mon travail, et dépendre de Pandas ne me semblait pas très pertinent. Je me suis donc contenté des fonctions np.{gen,rec}fromtxt qui font très bien le boulot, avec un dtype comme il faut, tout en retenant les boulettes que j'ai faites.


PyConFr

2013/10/28 by Alain Leufroy
http://www.pycon.fr/2013_static/pyconfr/images/banner.png

Logilab était au rendez-vous annuel des pythonistes de tous genres : la conférence PYCONFR organisée par l'AFPy, qui avait lieu cette année à l'université de Strasbourg.

Si vous n'y étiez pas, voici un petit aperçu de ce que vous avez raté, sachant que le programme était chargé.

Où en est le packaging ?

Nos amis de Unlish ont fait une présentation de l'état actuel de la distribution de paquets python.

Après une présentation générale de PyPI, ils ont décrit les derniers changements qui ont permis d'améliorer la disponibilité des paquets python.

L'information la plus importante concernait Wheel qui est le format désormais recommandé pour fournir des binaires précompilés. Fini les .egg de setuptools ! Ceci devrait faire sourir plus d'un mainteneur de paquet ou administrateur système.

Wheel est un format de fichier de distribution. Ce format clair et succinct est décrit par la PEP427. Il vise à simplifier la fabrication des paquets pour les distributions de vos OS favoris.

Les versions récentes de l'installeur pip peuvent gérer les paquets Wheel qui sont compatibles avec le système d'installation décrit dans la PEP376. Il faut toutefois, pour l'instant, dire explicitement à pip de prendre en compte ces fichiers dès qu'ils sont disponibles, grâce à l'option --use-wheel.

Vous disposez ainsi des avantages de pip (gestion claire et simple des dépendances, freeze, désinstallation, etc.) et ceux d'une distribution de paquets précompilés (installation rapide et simple, environnement de développement non requis, etc.).

Les paquets Wheel prennent en compte les implementations de python et leurs ABIs. Vous pouvez donc fournir des paquets Wheel (et les signer) facilement pour des versions spécifiques de Jython, Pypy, IronPython, etc.

$ python setup.py bdist_wheel
$ pypy setup.py bdist_wheel

Cela ne vous dispense pas de distribuer les sources de votre paquet ;)

$ python setup.py sdist

Python dans Mercurial

http://www.selenic.com/hg-logo/logo-droplets-50.png

Pierre-Yves David et Alexis Métaireau ont fait un petit rappel des trucs vraiment géniaux dans Mercurial comme les revsets et les templates.

Le coeur de leur présentation concernait l'utilisation de Python pour écrire Mercurial.

D'après son auteur, Mercurial existe aujourd'hui grâce à Python. En effet Python a permis à Matt Mackall d'écrire une preuve de son concept en à peine deux semaines -- il n'avait pas plus de temps à y dédier donc l'implementation en C n'était pas envisageable.

Rappelons qu'avant de changer le langage d'implementation il est toujours intéressant de se poser des questions sur les algorithmes utilisés. Nous avons vu quelques exemples d'optimisation en Python qui ont permis de d'accélérer Mercurial, et quelques astuces pour contourner les lenteurs que l'on rencontre avec l'interpréteur CPython (lazy import, low-level access, etc.).

Les autres avantages notables de l'utilisation de Python viennent de sa flexibilité. Les extensions pour Mercurial peuvent grâce à cela changer le comportement interne de Mercurial. Par exemple largefiles et watchman améliorent grandement la gestion des gros fichiers et la mise à jour des informations du dépôt.

Hy, lisp on Python

http://docs.hylang.org/en/latest/_images/hy_logo-smaller.png

Julien Danjou a présenté une implémentation de Lisp basé sur la VM de Python. En effet Python peut être vu comme un sous-ensemble de Lisp.

Hy interprète un script écrit dans un dialecte de Lisp et le convertit en arbre syntaxique Python classique, qui est ensuite exécuté par l'interpréteur Python.

[Python] .py -(parse)---> AST -(compile)-> .pyc -(run)-> python vm
                      /
[Lisp]   .hy -(parse)/

tip

hy2py permet de montrer l'équivalent Python d'un script Lisp.

Il y a donc une grande interopérabilité entre ce qui est implémenté en Hy et ce qui l'est en Python. Aucun souci pour importer les autres modules Python, quels qu'ils soient.

Hy supporte presque toutes les versions de Python et beaucoup d'interpréteurs, notamment pypy.

De nombreuses fonctions de common Lisp sont disponibles, et Hy se rapproche de Clojure pour la définition des classes.

Pour ceux qui sont intéressés par Hy, notez qu'il manque encore quelques petites choses :

  • les cons cells sont en cours de discussion
  • il faudra faire sans les macroexpand pour vous aider dans vos macros
  • les fonctions de Common Lisp ne sont pas toutes présentes
  • le dialect de Lisp nécessite, pour l'instant, de mixer les [...]` et les (...)`, mais ceci devrait changer.
  • Hy n'est pas présent à l'exécution, il y a donc forcément des limitations.

Python pour la Robotique

Il y avait une présentation bien sympathique d'une équipe qui participe régulièrement aux championnats de france de robotique.

Ils utilisent une carte basée sur un SoC ARM sur laquelle ils disposent d'un Gnu/Linux et d'un interpréteur Python (2.7).

Ils ont codé en C/C++ quelques routines de bas niveau pour un maximum de réactivité. Mise à part cela, tout le reste est en Python, notamment leurs algorithmes pour gérer la stratégie de leurs robots.

Python leur facilite énormément la vie grâce au prototypage rapide, à la rapidité pour corriger leur code (surtout avec le manque de sommeil durant la compétition), à la souplesse pour simuler en amont, analyser des logs, etc.

Un Python dans la maison

http://hackspark.fr/skin/frontend/base/default/images/logo3d_hackspark_small.png

Il y avait aussi la présentation d'un projet (Hack'Spark!) jeune mais déjà fonctionnel de domotique. La petite démonstration en direct du système était du plus bel effet ;)

Et, pour moins de 100 euros vous pourrez allumer la lumière chez vous depuis une interface web ! Perso, je m'y mets ce mois ;)

Framework Graphique Kivy

http://kivy.org/logos/kivy-logo-black-64.png

Kivy est entièrement écrit en Python/Cython et utilise OpenGL. Il a donc un très bon support sur les machines récentes (Linux, BSD, MacOs, Android, iOS, Rpi, etc.). Et il n'a rien a envier aux autres frameworks.

Kivy semble particulièrment pratique pour mener à bien des projets sur les plateformes mobiles comme les téléphones portables et les tablettes (Android et iOS).

De plus, parmi les outils fournis avec Kivy vous pourrez trouver quelques trucs pour simplifier votre développement :

  • PyJNIus utilise l'interface JNI de la VM Java (via Cython). Il sert de proxy sur les classes Java et vous donne donc accès à l'ensemble de l'API Android.
  • PyObjus est le pendant de PyJNIus pour ObjectiveC sous iOS.
  • Plyer essaie de rassembler en une API commune de plus haut niveau PyJNIus et PyObjus, ce qui permet de coder une seule fois pour les deux plateformes.
  • Buildozer aide à la compilation de projet pour Android de manière plus simple qu'avec Python for Android.

Nous avons eu droit à une présentation des concepts et comment les mettre en œuvre en direct. Je sens que ça va me simplifier la vie !


Rencontre autour de SaltStack lors de l'OpenWorldForum

2013/09/25 by Arthur Lutz

Suite à l'organisation du sprint français autour de SaltStack, nous continuons d'essayer de fédérer la communauté française utilisatrice (ou tout simplement curieuse) de solutions de gestion centralisées autour de la technologie Salt (qui est écrit en Python et que nous pouvons donc facilement adapter à nos besoins en contribuant au projet).

http://openworldforum.org/static/pictures/Calque1.pnghttp://saltstack.com/images/SaltStack-Logo.png

Au sein de l'OpenWorldForum nous animons un SaltStack meetup / BOF le jeudi 3 octobre de 18h30 à 20h30 avec Thomas Hatch fondateur de SaltStack. La totalité de l’événement (dont le meetup) est gratuit, il suffit de s'inscrire.

Logilab tiendra un stand le jeudi et le vendredi lors du forum, n'hésitez pas à venir discuter avec nous. Le TDI (Test-Driven Infrastructure), qui consiste à appliquer le TDD (Test-driven development) (développement piloté par les tests) à l'administration système sera un des thèmes de notre présence.