Blog entries

jupyterlab-friendly-traceback

24/05/2022 by Olivier Giorgis

Temps de lecture ~1 min (100 mots)

Dans le cadre de ses formations, Logilab à créé jupyterlab-friendly-traceback, une extension JupyterLab qui permet d'utiliser friendly-traceback de façon interactive dans les calepins Jupyter.

Le but du module Friendly-traceback est de remplacer les messages d'erreurs standards de Python par des messages plus complets et plus faciles à comprendre. Ce module permet, entre autre, d'expliquer ce qui a provoqué la levée d'une exception dans un programme.

Les informations données par Friendly-traceback ont une grande valeur pédagogique et permettent aux développeurs Python débutants, voir confirmés, de mieux comprendre les erreurs présentes dans leur code.

Pour utiliser l'extension jupyterlab-friendly-traceback, il suffit de la pip-installer dans votre environnement de la façon suivante:

$> pip install jupyterlab-friendly-traceback

Il est ensuite possible d'activer et de désactiver l'extension JupyterLab en cliquant sur un bouton qui apparaît dans la barre d'outils du calepin Jupyter.


Logilab au JDLL 2022

13/05/2022 by Arnaud Vergnet

Temps de lecture 4min (~800 mots)

Nous poursuivons notre participation au libre en envoyant deux nouveaux logilabiens, Yoelis et Arnaud aux JDLL de Lyon, le rendez-vous annuel de celles et ceux qui sont curieux·ses et passionné·e·s de numérique libre et émancipé. Ils y ont découvert l'actualité économique et les enjeux politiques inhérents à la pratique du libre. Ils ont également été surpris par la richesse de l'innovation qui se déploie dans ces espaces.

Ce week-end fût riche en idées et les résumer en quelques lignes n'est pas tâche aisée. Nous nous sommes concentrés sur quelques conférences, mais vous trouverez la liste complète de toutes les conférences. Les différentes discussions auxquelles ont participé nos Logilabiens tournent autour de trois grandes questions.

Comment défendre nos droits et s'organiser en dehors des structures verticales et traditionnelle du pouvoir ?

Le collectif des chatons avait des choses à en dire. Les CHATONS, l'acronyme de Collectif des Hébergeurs Alternatifs, Transparents, Ouverts, Neutres et Solidaires, est un collectif d'hébergeurs citoyens. Ils permettent à chacun d'accéder à différents services hébergés (email, sites web, outils collaboratifs) près de chez eux afin que chacun puisse se réapproprier ses données et réduire sa dépendance aux GAFAM.

Les étudiants de Compiègne qui ont lancé Picasoft ont parlé de leur expérience de mise en œuvre d'un CHATONS et de la façon qu'ils ont eu de déconstruire progressivement au cours de cette expérience les structures classiques de l'organisation d'une association. Ils sont parvenus, non sans peine, à un mode de fonctionnement organique où celles et ceux qui font sont les décideurs, dans la bienveillance et l'écoute mutuelle.

Comment promouvoir la notion de commun, l'open-data et la réappropriation des données par les collectifs ?

Le langage n'est pas neutre et les dictionnaires sont imprégnés de la vision du monde de leurs auteurs et affectés par leurs conditions de production. S'il est le fruit d'un travail institutionnel, il y a un risque qu'il soit stoppé si les financements devaient s'arrêter ou si la situation politique changeait. La communauté est moins impliquée et le travail laissé à quelques sachants. La ligne éditoriale encourt un risque de censure et le contenu peut-être daté ou anachronique. Même si les projets issus de communautés ne sont pas concernés par ces problèmes, ils ont souvent du mal à atteindre les communautés érudites et ne sont pas toujours à la pointe en ergonomie et design.

Le Dictionnaire Des Francophones (DDF) a ainsi essayé de lier ces deux mondes. Basé sur les données du projet ouvert du Wiktionnaire (projet de la Fondation Wikimedia), le DDF est une initiative du ministère de la Culture pour représenter la diversité de la langue Française à travers toute la francophonie. Comparé au Wiktionnaire, le DDF possède une meilleure ergonomie et est plus facilement utilisable par d'autres applications grâce à la publication de ses données aux formats du Web Sémantique comme le RDF.

La métropole de Lyon a bien compris l'enjeu d'impliquer la communauté et mène un projet ambitieux d'ouverture de ses données. Cette initiative multiplie ainsi les possibilités de valorisation des données par les scientifiques et les journalistes. En revanche, contrairement au DDF, les données publiées ne sont pas au format du Web Sémantique, limitant les possibles utilisations. La perspective est tout de même envisagée sur le long terme.

Quels outils innovants pour l'ingénierie logicielle ?

En parallèle des conférences, nos logilabiens ont assisté à des ateliers techniques, tels que l'atelier d'initiation à Rust et à la conception d'un jeu avec Rust.

Rust est un langage de programmation à typage fort, garantissant l'absence d'erreurs de mémoire au moment de la compilation. Il est fortement inspiré de la famille du C avec une syntaxe moderne. Il permet différents styles de programmation, notamment fonctionnel. Contrairement au C et au C++, Rust utilise le gestionnaire de dépendances Cargo, similaire à Pip pour Python et NPM pour JavaScript. Rust est donc un langage système moderne possédant de nombreuses qualités pour simplifier le travail de ses utilisateurs, expliquant sa popularité en hausse.

Pijul est un nouveau système de contrôle de version ayant pour objectif de résoudre de multiples problèmes existants dans les solutions actuelles. Contrairement à Git et Mercurial qui se basent sur la théorie des snapshots, Pijul suit les pas de Darcs en s'appuyant sur la théorie des patchs. Historiquement, l'approche par snapshot possède de bien meilleures performances que celle par patchs, mais possède de nombreux problèmes lors d'opérations complexes (merge ambigus). L'objectif de Pijul est de résoudre les problèmes de performances présents chez Darcs pour créer un système performant à la Git, fiable et simple à utiliser à la Darcs.

Bilan

Participer à de tels événements est toujours une source d'inspiration pour nos logilabiens. La découverte de nouvelles technologies et de nouveaux projets libres est ce qui nourrit notre activité au quotidien. Grâce aux JDLL, Logilab sera sûrement amenée à utiliser une de ces technologies lors de projets. Nous avons hâte de retrouver tout ce joli monde à la prochaine édition !


Participation à l'atelier RoCED à la conférence KGC : Apprentissage automatique de règles de transformation entre formats bibliographiques

29/04/2022

(Titre en anglais: Learning Transformation Rules Between Bibliographical Formats Using Genetic Programming)

Temps de lecture 2 minute (~300 mots)

Nous avons l'honneur d'avoir été invités à parler de nos travaux à l'atelier RoCED qui aura lieu durant la conférence KGC 2022, en ligne, le 2 mai entre 9h et 12h EST (New-York) ou entre 15h et 18h heure française.

Cet atelier est spécialisé dans l'étude de la complexité, l'hétérogénéité, l'incertitude et l'évolution des données et des connaissances. Pour faire face à l'accroissement constant de la quantité de données et connaissances générées, il devient primordial d'appréhender ce volume pour pouvoir exploiter la connaissance sous-jacente. Cet atelier propose d'apporter des éléments de réponse à ce problème en explorant des applications d'apprentissage automatique, de fouille de données, ou de raisonnement sur des graphes de connaissance.

Dans ce cadre, Logilab (par l'intervention d'Élodie Thiéblin) présentera les résultats préliminaires d'une étude commanditée par la BnF (Bibliothèque nationale de France). La BnF est actuellement en train de migrer son catalogue de données du format Intermarc (variante du MARC) vers le format Intermarc-NG (distingant notamment Oeuvre, Expression, Manifestation, Item). Cette migration est faite grâce à des règles écrites manuellement. Pour préserver l'interopérabilité avec les applications qui ne traitent que le format Intermarc, il est envisagé d'apprendre la transformation inverse (Intermac-NG vers Intermarc) automatiquement. Comme la migration de données n'a pas eu complètement lieu, l'étude s'est concentrée sur l'apprentissage de règles de transformation de l'Intermarc vers le Dublin Core, basé sur un ensemble de notices bibliographiques disponibles dans les deux formats. Une preuve de concept a été développée en utilisant la programmation génétique, dont les résultats sont des règles plus ou moins complexes. Notre hypothèse est que cet apprentissage peut être appliqué à d'autres formats de données structurées.

Si vous souhaitez suivre cette présentation (et les autres présentations passionnantes prévues durant ces journées KGC) ne tardez pas à vous inscrire ici : https://www.knowledgegraph.tech/

Merci beaucoup à Nathalie Hernandez, Fathia Sais et Catherine Roussey de nous permettre de présenter nos travaux durant cet atelier.


Logilab been invited to participate in the RoCED workshop, occuring during KGC 2022.

This workshop focuses on contributions describing methods and uses-cases that rely on the application of reasoning and machine learning on complex, uncertain and evolving knowledge graphs.

We will present the preliminary results of a study commissioned by the National French Library (BnF). The National French Library (BnF) is migrating its catalogue data from the Intermarc bibliographic format (similar to UniMARC) to Intermarc-NG with manually created rules. To keep their data interoperable with applications which can only deal with Intermarc data for now, they would like to automatically learn the inverse transformation (Intermarc-NG to Intermarc). The catalogue data has not been entirely migrated so far, therefore, the study focused on learning transformation rules from Intermarc to Dublin Core, based on a corpus of bibliographic records in both formats. A proof of concept has been developed using genetic programming resulting in more or less complex rules. We argue that this transformation rule learning algorithm could be applied to other structured data formats.

If you want to follow this presentation and other interesting talks, register here: https://www.knowledgegraph.tech/

We thank Nathalie Hernandez, Fathia Sais and Catherine Roussey for their invitation to this workshop.


Partenariat Logilab/TotalEnergies Semantic Framework : Interopérabilité sémantique des modèles et des données de l’industrie

22/04/2022

Temps de lecture 1 minute (~250 mots)

La onzième conférence pour l'interopérabilité des systèmes et applications d'entreprise, I-ESA 2022 a eu lieu en mars 2022 à Valence en Espagne.

Logilab y a co-présenté, avec les partenaires du projet TotalEnergies Semantic Framework, un article intitulé "Intégrer les données et les modèles dans l'industrie grâce à l'interopérabilité sémantique obtenue en utilisant les standards du domaine" (New ways of using standards for semantic interoperability towards integration of data and models in industry).

Le résumé de cet article est le suivant.

De récents groupements européens du programme H2020, des projets collaboratifs dans le domaine industriel et des avancées des organisations de standardisation convergent vers de nouvelles utilisations des standards internationaux pour intégrer les données et permettre de nouveaux types de collaboration le long des cycles de vies et au sein des écosystèmes des produits et installations industrielles.

Dans cet article, nous décrivons l'approche innovante adoptée par TotalEnergies pour pallier le manque d'interopérabilité entre les données produites au cours du cycle de vie d'une installation industrielle. Le résultat est le TotalEnergies Semantic Framework, qui se fonde sur des standards pour formaliser la sémantique des données échangées entre les partenaires et s'assurer que chacun peut opérer à son tour et dans ses propres applications les traitements associés à son rôle dans le processus global de conception, construction, exploitation, maintenance et démantellement des installations.

Une architecture centrée sur des données décentralisées partagées par de multiples acteurs ayant chacun une spécialité et un point de vue sur un système complexe ? C'est bien évidemment un cas d'usage idéal pour les techniques du Web sémantique que maîtrise Logilab !

Vous pourrez lire l'article complet ici


Resourcecode

12/04/2022 by Simon Chabot

400 mots - Temps de lecture 2 min

Le 10 mars 2022 a eu lieu le lancement de la « boite-à-outils Resourcecode » devant plus d’une centaine de partenaires du projet. Logilab est fière d’avoir pu participer à ce projet.

Resourcecode est un projet visant à soutenir les investissements et la croissance dans le secteur de l’énergie houlomotrice et maréomotrice par la création d’une boîte à outils intégrée de données marines.

Concrètement, des données décrivant l’état de la mer (vitesse du vent, hauteur des vagues, direction du courant, etc) sont enregistrées par des bouées de l’IFREMER (Institut Français de Recherche pour l'Exploitation de la Mer) et de ses partenaires. Des données de 1994 à 2020 sont disponibles pour des milliers de points de l’océan Atlantique et de la mer du Nord avec une résolution temporelle de l’ordre de l’heure. Une fois ces données enregistrées, elles peuvent être interpolées sur les points d’un maillage triangulaire.

Logilab a remporté un appel d’offre, déposé par l’Ifremer, dans le cadre de ce projet. Nous avons eu la charge de réaliser :

  • une application web resourcecode.ifremer.fr permettant la visualisation des points où les données sont accessibles et proposant des outils statiques ou interactifs basés sur des calepins Jupyter afin d’étudier la mer au point considéré.
  • produire une bibliothèque python resourcecode permettant de télécharger localement les données d’un point sous forme de DataFrame Pandas. L'intégration continue de la forge GitLab de l'IFREMER génère avec Sphinx la documentation de cette bibliothèque.
  • intégrer à cette bibliothèque des codes de calculs écrits par l’IFREMER et ses partenaires (codes écrits en R, MATLAB ou Python)
  • mettre en place une architecture permettant à l’IFREMER et ses partenaires de construire des nouveaux outils (statiques ou interactifs). Ces outils sont développés et maintenus par l’IFREMER et ses partenaires, et automatiquement intégré à l’application web. Ils sont développés sur l’instance GitLab de l’Ifremer.

Lors de cet événement de lancement de Resourcecode, une démonstration en direct a pu être effectuée auprès du public : la bibliothèque a été installée et un dépôt de code contenant un calepin Jupyter a été cloné puis exécuté. Cela a permis de démontrer la facilité d'utilisation de cet outil, ainsi que la répétabilité offerte par ce type d’architecture, qui correspond aux attentes actuelles en matière de science ouverte (Open Science).


Logilab au FOSDEM 2022

30/03/2022

Temps de lecture = 3 minutes (~ 600 mots)

Cette année, comme l'année dernière, le FOSDEM s'est déroulé intégralement en ligne en s'appuyant sur une infrastructure technique constituée de logiciels libres :

  • matrix qui est un outil décentralisé de communication en temps réel qui repose sur un standard ouvert. Chaque session thématique avait son propre salon de discussion Matrix. Vous pouvez créer votre compte matrix sur joinmatrix.org.
  • jitsi qui est une application libre et multiplateforme de visioconférence, VoIP et messagerie instantanée. Vous pouvez utiliser le service offert par un des chatons.

Au cours de cette édition du FOSDEM, nous avons participé aux sessions concernant Python et les plateformes de tests et d'intégration, au cours desquelles nous avons eu la chance de présenter CubicWeb et notre utilisation de GitLab.

CubicWeb: bootstraping a web-application from RDF data

Voici la page, le support et la vidéo

Le Web s'est d'abord développé comme un ensemble de documents connectés par des liens hypertexte, mais depuis quelques années, on assiste à une explosion du nombre de jeux de données publiées sur le Web en utilisant le standard RDF et les URLs pour désigner les objets représentés.

Publier ces données en permettant la négociation de contenu pour obtenir soit les données, soit du HTML à la même adresse (URL) est rarement effectué. Selon nous, cela s'explique par le fait qu'il n'existe pas de solution toute prête, ni d'interface d'administration de données RDF offrant les opérations CRUD habituelles associées à la définition fine de permissions.

CubicWeb est un système de gestion de contenu sémantique pour le Web de données liées, qui répond à ce besoin en offrant les fonctionnalités attendues d'un CMS et en rendant accessibles les données et pas uniquement une interface de consultation.

Nous avons présenté au FOSDEM l'utilisation de OWL2YAMS pour initialiser une nouvelle application CubicWeb à partir d'une ontologie OWL. L'application est ensuite directement utilisable pour publier les données RDF et l'ontologie utilisée, mais aussi pour parcourir, visualiser et administrer ces données avec une interface autogénérée.

How to improve the developer experience in Heptapod/GitLab

Voici la page, le support et la vidéo de cette présentation.

Logilab utilise depuis maintenant deux ans Heptapod, un fork amical de GitLab en achetant du support à Octobus.

Dans notre instance d'Heptapod, nous maintenons CubicWeb, les sous-composant les «cubes», nos projets clients, nos projets open-sources et nos projets internes.

Nous avons plusieurs centaines de projets dépendants les uns des autres dans Heptapod. À cette échelle, il nous paraît impossible d'assurer une cohérence des bonnes pratiques sans avoir recours à l'automatisation.

Dans cette présentation, nous avons détaillé les outils d'automatisation qui nous aident pour maintenir l'ensemble de nos projets, en particulier AssignBot et Code-Doctor. Certains de ces outils sont spécifiques à Mercurial, mais la plupart peuvent être utilisés avec Git dans GitLab.

Ils nous permettent de :

  • Créer des demandes de fusion automatiquement dans les dépôts en fonction de certaines règles, comme les avertissements de dépréciation (un peu comme dependabot).
  • Choisir un reviewer pour les demandes de fusion en fonction des préférences des développeurs.
  • S'assurer de commiter, tagger, mettre à jour le changelog, publier sur PyPi lors de la sortie d'une nouvelle version.
  • Mutualiser les configurations GitLab CI avec des templates.
  • Héberger des images docker sur la forge.
  • Avoir des sites web statiques, de la documentation ou des applications web à jour.

Chaque cas d'utilisation peut être résolu facilement, mais c'est en les combinant que l'on facilite vraiment la vie des développeurs et que l'on gagne vraiment en efficacité.

Le mot de la fin

Merci beaucoup à toutes les personnes qui ont aidé à organiser cette nouvelle édition !


Logilab à SWIB 2021

18/03/2022

Temps de lecture = 3 min (650 mots)

Logilab a participé à l'édition 2021 de la conférence SWIB (Semantic Web in Librairies), dédiée à l'étude des technologies du Web Sémantique appliquées aux bibliothèques, pour y présenter deux projets qui ont reçu des retours positifs.

SparqlExplorer

Elodie Thiéblin a présenté la dernière version de SparqlExplorer. L'enregistrement est disponible sur youtube.

Le projet SparqlExplorer permet d'explorer un entrepôt SPARQL en appliquant des vues qui s'adaptent au type de la ressource à afficher.

Chaque ressource étant identifiée par une URI, il est possible de récupérer le type d'une resource en cherchant dans l'entrepôt SPARQL un triplet RDF de la forme <uri_ma_ressource> rdf:type <uri_du_type>. Une fois le type connu, le SparqlExplorer sélectionne parmi toutes les vues fournies par un serveur de vues, la vue la plus adaptée pour afficher la resource. Cette vue sélectionnée récupère les données nécessaires dans l'entrepôt SPARQL et génère un morceau de page HTML qui est inséré dans l'affichage du SparqlExplorer. Lorsqu'un lien vers l'URI d'une autre ressource est suivi, le processus est appliqué de nouveau pour obtenir le type, détermier la vue la plus adaptée puis calculer l'affichage de la ressource. Il est ainsi possible de naviguer d'une ressource à une autre au sein d'un entrepôt SPARQL en suivant des liens dans des pages HTML plutôt qu'en écrivant des requêtes SPARQL.

En mettant à disposition des vues adaptées aux vocabulaires standardisés du domaine des bibliothèques, le SparqlExplorer devient un outil générique qui permet naviguer dans de multiples catalogues publiés sous forme d'entrepôts RDF interrogeables en SPARQL, sans qu'il soit nécessaire de développer une application web spécifique à chacun de ces catalogues en ligne.

OWL2YAMS

La deuxième intervention était un atelier pratique animé par Fabien Amarger et consacré à OWL2YAMS, lequel permet de publier des données RDF facilement avec CubicWeb.

Le cadriciel CubicWeb est utilisé dans la majorité des projets à Logilab. Son développement a toujours été orienté pour profiter au maximum des concepts du Web Sémantique. Depuis plusieurs années, CubicWeb se positionne comme un cadriciel de développement d'application pour le Web de données liées. La négociation de contenu est par exemple disponible par défaut dans CubicWeb, ce qui permet, pour chaque ressource, de télécharger les données au format RDF avec une simple requête HTTP.

L'outil OWL2YAMS permet de créer une application CubicWeb à partir d'une ontologie OWL avec une seule commande. Il suffit ensuite de déployer cette application pour publier cette ontologie en ligne. Un script générique permet d'importer dans l'application des données RDF utilisant le vocabulaire de cette même ontologie.

A notre connaissance, OWL2YAMS et CubicWeb constituent la méthode la plus simple et la plus directe pour mettre en ligne des données liées sur le web en utilisant les standards du Web sémantique et en disposant d'une application web moderne qui permet à la fois l'affichage et la navigation en HTML, le téléchargement du RDF par négociation de contenu et l'utilisation d'une interface d'administration pour la gestion du contenu et des droits d'accès.

Conclusion

Nous sommes très contents d'avoir pu proposer ces deux outils durant la conférence SWIB21. Les retours ont été très positifs et nous confortent dans l'idée que, autant le SparlExplorer que CubicWeb, représentent des solutions efficaces qui répondent à de réels besoins, en particulier dans le domaine de la gestion documentaire ou patrimoniale et des archives.


Logilab à l'Open Source Experience 2021

08/03/2022

Temps de lecture = 2 min (~ 300 mots)

Open Source Experience est le rendez-vous européen de la communauté Open Source qui a eu lieu le 8 et 9 novembre 2021 à Paris. Au programme, il y eut des conférences, tables rondes et sessions plénières riches en retours d’expérience et en innovations réunissant la communauté de l'Open Source et du Logiciel Libre, ainsi que les entreprises utilisatrices en recherche d’informations.

Nous y avons présenté notre travail lors des sessions Could DevOps et Full Stack Web.

FranceArchives, les archives sur une infrastructure du 21e siècle

Le site FranceArchives développé par Logilab pour le Service interministériel des Archives de France (SIAF) permet aux professionnels et aux amateurs d'explorer les archives publiques de France.

Arthur Lutz et Carine Dengler ont présenté notre dernier grand chantier en date pour ce site, à savoir, la migration vers Kubernetes, en détaillant la pile technique et en résumant notre retour d'expérience.

L'enregistrement vidéo est disponible: FranceArchives sur Kubernetes (avec l'original sur youtube).

Transformation continue des applications en production

Certains considèrent qu’une application a une durée de vie de quelques années et qu’à ce terme, l’application doit être réécrite avec les outils du moment. Nous préférons faire évoluer en continu nos applications en production et préserver l’investissement qu’elles constituent.

Nicolas Chauvat a décrit ce processus de transformation qui touche à tous les aspects des projets: la gouvernance du logiciel libre sous-jacent, l’architecture des applications, les bibliothèques et composants libres employés, le stockage des données, l’interface utilisateur, l’API externe, les langages de programmation utilisés, les méthodes de test et de déploiement, les outils de supervision, etc.

Il a terminé en présentant nos innovations en cours, qui visent à augmenter la fréquence des déploiements sans compromettre la qualité, grâce à une automatisation croissante des processus, y compris pour la modification du code source.

L'enregistrement vidéo est disponible: Transformation continue des applications (avec l'original sur youtube).

Rendez-vous à la fin de l'année 2022 pour la prochaine édition !


Typage du paquet RQL

18/02/2022

Temps de lecture = 4 min (~700 mots)

Contexte

Le projet RQL est l'implémentation d'un parser pour un langage de requête du même nom permettant d'interroger une base de données qui a été créée avec un schéma YAMS. Ce langage de requête est au coeur de CubicWeb.

Le cadriciel CubicWeb est très largement utilisé dans nos projets à Logilab, et donc nous continuons à maintenir CubicWeb et ses dépendances en le faisant évoluer suivant nos besoins. Parfois ce besoin concerne le langage d'interrogation RQL lui-même. Nous aimerions par exemple ajouter les chemins de propriétés qui existent en SPARQL (voir SPARQL property paths) ou encore la possibilité d'avoir des propriétés calculées dans les attributs de projection.

Mise en oeuvre

Pour faciliter ces évolutions, nous avons décidé de profiter des progrès récents de Python et d'enrichir la base code avec des annotations de type et de nous appuyer sur MyPy pour valider nos remaniements.

Le projet de typage de RQL a été un projet de longue haleine. Nous pensions que quelques semaines suffiraient mais il a été nécessaire d'y passer plusieurs mois pour arriver à un résultat satisfaisant. Typer l'ensemble d'un projet nécessite de comprendre son fonctionnement global, ce qui peut très vite être chronophage, surtout quand les pratiques de développement ont bien évolué.

Au lieu de s'attaquer au monolithe d'un seul coup, nous avons commencé par typer les modules séparémment les uns des autres, en ajoutant des commentaires #type: ignore aux endroits ne pouvant pas encore être typés, et sans forcémment essayer de détailler les interactions entre les différents modules. Les # type: ignore ont ensuite peu a peu disparu.

Problèmes rencontrés

Le typage aura permis de déceler des soucis de conception du projet RQL et de voir les limites du typage en Python.

Principe de Substitution de Liskov

Ce principe dit qu'une sous-classe doit pouvoir être utilisée là où une classe parente est attendue. Celui-ci n'est pas toujours respecté dans RQL. Par exemple, la méthode copy de la classe Insert ne prend pas d'argument alors que la même méthode sur la classe BaseNode en prend un. Cette différence de signature pourrait causer des problèmes dans du code client.

Le problème a été signalé par mypy:

rql/stmts.py:1283: error: Signature of "copy" incompatible with supertype "BaseNode"  [override]
rql/stmts.py:1283: note:          def copy(self, stmt: Optional[Statement] = ...) -> BaseNode
rql/stmts.py:1283: note:          def copy(self) -> Insert
Found 3 errors in 1 file (checked 1 source file)

Mixins difficilement typables

L'implémentation de l'arbre syntaxique qui a été choisie utilise beaucoup de mixins. Ces mixins ne sont pas typables de manière élégante.

Prenons par exemple le mixin OperatorExpressionMixin suivant:

class OperatorExpressionMixin:

    ...

    def is_equivalent(self: Self, other: Any) -> bool:
        if not Node.is_equivalent(self, other):
            return False
        return self.operator == other.operator

    ...

Il ne s'applique que sur des classes qui héritent de BaseNode et qui ont un attribut "operator" mais ce type ne peut pas être exprimé, car on aurait besoin de l'intersection de deux types, dont un classe, ce qui n'existe pas en Python (https://github.com/python/typing/issues/213).

En Typescript par exemple on aurait écrit:

type Self = BaseNode & {operator: string}

Covariance/Contravariance/...

Les types génériques, List par exemple, sont définis comme acceptant des paramètres de type. Lorsqu'on déclare ces paramètres de type (en utilisant TypeVar), il faut être attentif à choisir la variance appropriée, ce qui n'est pas trivial quand on vient de langages où ce n'est pas nécessaire (ni Typescript, ni C++, ni Java n'y font référence).

Conclusion

Nous avons publié une version 0.38 de RQL qui contient l'ajout des types et ne casse pas l'API utilisée. Ceci va nous aider à ajouter de nouvelles fonctionnalités et à remanier le code pour le simplifier. L'introduction du typage nous a également permis de déceler du code buggé ou jamais utilisé et de mieux documenter le code de RQL.

Merci à Patrick pour le temps qu'il a consacré à ce sujet important. Vous pouvez consulter son article de blog sur ce sujet ici


Pandas, Plotly et Jupyter : De l'analyse de données à l'application en ligne (1/3)

04/02/2022 by Simon Chabot

Temps de lecture estimé 10 minutes.

Nous proposons une série de quelques articles où nous allons utiliser la bibliothèque Pandas pour analyser les licences sportives en France. En chemin, nous réaliserons une interface utilisateur avec des widgets.

Cette série sera découpée en trois articles. Dans le premier, nous allons explorer le jeu de données à notre disposition en utilisant la bibliothèque Pandas. Dans le second, nous introduirons Jupyter et les ipywidgets qui nous permettront de faire une interface utilisateur. Nous terminerons la série en présentant Voilà ainsi que le thème jupyter-flex.

Pandas, jupyter, ipywidgets, voilà ? De quoi parle-t-on ?

  • Pandas est une bibliothèque Python très connue, qui permet d’analyser et d’étudier des jeux de données. Elle est conçue pour traiter des jeux de données tabulaires (ceux pouvant être lus par un tableur). Les données peuvent être de différents types (nombres, dates, chaînes de caractères, etc). Pandas est, comme nous le verrons, très efficace. Les fonctions coûteuses de Pandas sont généralement écrites en C, et Python est utilisé pour manipuler et appeler ces fonctions.
  • Jupyter est une plateforme, utilisable dans un navigateur web qui permet d’exécuter des calepins (notebooks). Un calepin est un fichier qui combine des cellules de différents types : du code exécutable, du texte, des visualisations, etc.
  • Les Ipywidgets sont des éléments graphiques interactifs que l’on peut ajouter à des calepins Jupyter. Ils vont nous permettre de proposer aux utilisateurs de choisir un fichier, choisir un élément dans une liste, cliquer sur un bouton, etc. Chacune des actions de l’utilisateur peut être associée à une fonction Python, et donc rendre le calepin interactif.
  • Voilà est une application qui permet d’exécuter des calepins, mais sans afficher le code source − qui est visible par défaut dans Jupyter. L’énorme intérêt à cela est qu’un calepin Jupyter devient alors une application web à part entière, utilisable dans le navigateur, et seuls les éléments indispensables à son utilisation sont visibles.

Après cette petite phase de présentation, découvrons les données que nous allons manipuler aujourd’hui.

Présentation des données

Dans cette série d’articles nous utilisons des données issues de https://data.gouv.fr. Il s’agit du nombre de licences sportives, par sexe, par catégorie d’âges, par municipalité pour les années 2012 à 2018. Les données brutes peuvent être téléchargées ici.

Nous avons réalisé une opération de nettoyage sur ces données, afin de nous assurer d’avoir une structure cohérente pour chaque année. Nous avons également remplacé les municipalités par leur département, ce qui permet d’alléger les données à manipuler. Au final, nous obtenons six fichiers csv, un par année, dont la structure est la suivante :

dep_code,dep_name,fed_code,fed_name,gender,age,lic_holders
01,Ain,101,Fédération Française d'athlétisme,F,00-04,0
01,Ain,101,Fédération Française d'athlétisme,F,05-09,75
01,Ain,101,Fédération Française d'athlétisme,F,10-14,251
01,Ain,101,Fédération Française d'athlétisme,F,15-19,130
01,Ain,101,Fédération Française d'athlétisme,F,20-29,39
01,Ain,101,Fédération Française d'athlétisme,F,30-44,105
01,Ain,101,Fédération Française d'athlétisme,F,45-59,105
01,Ain,101,Fédération Française d'athlétisme,F,60-74,23
01,Ain,101,Fédération Française d'athlétisme,F,75+,0
01,Ain,101,Fédération Française d'athlétisme,M,00-04,0
01,Ain,101,Fédération Française d'athlétisme,M,05-09,106
01,Ain,101,Fédération Française d'athlétisme,M,10-14,278
[…]
Nom de colonne Description
dep_code Code (unique) du département
dep_name Nom du département
fed_code Code (unique) de la fédération sportive
fed_name Nom de la fédération sportive
gender Genre (peut être M ou F)
age La tranche d’âge considérée (peut être 00-04, 05-09, 10-14, 15-19, 20-29, 30-44, 44-59, 60-74, 75+)
lic_holders Le nombre de licenciés dans le département, enregistrés dans cette fédération, de ce genre et de cette tranche d’âge.

Chargement de données pour une année

Pandas offre un nombre important de fonctions permettant de charger des données depuis différents formats: CSV, Excel, tableaux HTML, JSON, bases SQL, HDF5, etc. Nous allons utiliser la fonction read_csv. Cette fonction utilise les éléments de la première ligne comme noms de colonnes. Pandas essaie également de détecter les types de colonnes à utiliser (nombre, date, chaîne de caractères) en se basant sur les premiers éléments lus. Nous spécifions donc à Pandas que la colonne dep_code est de type str, pour prendre en compte les départements Corse (2A et 2B), sans quoi Pandas émettra un avertissement.

from pathlib import Path
import pandas as pd

DATA_DIR = Path().resolve() / "data"  # en supposant que les données sont dans le dossier data

d2012 = pd.read_csv(
    DATA_DIR / "sport_license_holders_2012.csv", dtype={"dep_code": str}
)

Nous obtenons alors la DataFrame suivante :

Premières analyses

À partir de là, nous pouvons commencer à étudier le jeu de données. Par exemple, en demandant le nom de chaque fédération :

>>> d2012["fed_name"].unique()
array(["Fédération Française d'athlétisme",
       "Fédération Française des sociétés d'aviron",
       'Fédération Française de badminton',
       'Fédération Française de basketball',
       'Fédération Française de boxe',
       'Fédération Française de canoë-kayak',
       'Fédération Française de cyclisme',
       "Fédération Française d'équitation",
       "Fédération Française d'escrime",
       […],
       'Fédération française de pentathlon moderne',
       'Fédération Française de javelot tir sur cible',
       'Fédération Flying Disc France', 'Fédération Française Maccabi',
       'Fédération Française de la course camarguaise',
       'Fédération Française de la course landaise',
       'Fédération Française de ballon au poing'], dtype=object)

Nous pouvons facilement compter le nombre total, toutes catégories confondues, de licenciés :

>>> d2012["lic_holders"].sum()
12356101

Une des forces de Pandas réside dans la possibilité de créer des filtres, ou des groupes simplement. Par exemple, pour compter le nombre de licenciés hommes, nous pouvons créer un masque (True si le genre est M et False sinon), puis appliquer ce masque à notre DataFrame.

>>> mask_male = d2012["gender"] == "M"
>>> d2012[mask_male]["lic_holders"].sum()
7806235

Ainsi, en 2012, il y avait 7 806 235 licenciés masculins de sport en France.

Combien y a-t-il de licenciés, en 2012, par tranche d’âge ? Pour répondre à cette question, nous utilisons la méthode groupby de Pandas, en donnant le nom de la colonne sur laquelle nous souhaitons faire le groupe :

>>> d2012.groupby("age")["lic_holders"].sum()

Cette méthode permet de constituer des groupes, selon une clé (généralement le nom d’une ou plusieurs colonnes), puis d’appliquer sur chaque groupe partageant la même clé une fonction d’agrégation. Dans notre exemple, la clé de chaque groupe est l’âge, et la fonction d’agrégation la somme sur la colonne lic_holders.

Nous pouvons effectuer le même type de calcul, mais en groupant cette fois-ci sur le genre et l’âge, ce qui donne le résultat suivant :

>>> d2012.groupby(["gender", "age"])["lic_holders"].sum()

Les deux résultats que nous venons d’obtenir sont ce qu’on appelle des Series. C’est-à-dire, des DataFrames mais constituées d’une seule colonne. On observe que les groupes sont directement constitués par l’index. Dans le cas d’un groupby() avec une seule colonne, nous avons un index simple et dans le cas où plusieurs colonnes sont utilisées, nous obtenons ce qu’on appelle un index multiple ou un index hiérarchique. Nous allons étudier cela un peu plus en profondeur dans la suite.

Créer un index sur mesure

Dans la DataFrame que nous avons chargée, de très nombreuses données sont répétées et ne sont utilisées que pour définir des groupes (dep_code, dep_name, gender, age etc). Nous allons mettre toutes ces données dans l’index de la DataFrame. Cela permet d’avoir dans l’index les données de chaque groupe, et dans la DataFrame les données desdits groupes (ici le nombre de licenciés sportifs).

Pour ce faire, nous utilisons la méthode set_index :

>>> d2012.set_index(
   ["dep_code", "dep_name", "fed_code", "fed_name", "gender", "age"], inplace=True
)
>>> d2012

Nous avons ainsi une DataFrame à une seule colonne, et avec un index à six niveaux. Nous pouvons toujours grouper par genre et par âge, en utilisant le mot-clé level, indiquant qu’il faut grouper en utilisant l’index :

>>> d2012.groupby(level=["gender", "age"]).sum()

Dans quels départements la course camarguaise est-elle pratiquée ?

La course camarguaise est un sport traditionnel dans lequel les participants tentent d'attraper des attributs primés fixés au frontal et aux cornes d'un bœuf. Pour savoir dans quels départements ce sport est le plus pratiqué, nous allons :

  1. Filtrer sur l’index pour n’avoir que les enregistrements correspondant à ce sport (le code de la fédération est 215) ;
  2. Grouper par code et nom de département, et compter le nombre de licenciés ;
  3. Afficher les groupes triés par ordre décroissant de licenciés.
>>> d2012_camarg = d2012.xs(
    215, level="fed_code"
)  # Only keep the rows with index equal to 215 at level ``fed_code``
>>> d2012_camarg_depts = d2012_camarg.groupby(
    ["dep_code", "dep_name"]
).sum()  # Group the data by department (only keep departments with non-null values)
>>> d2012_camarg_depts.sort_values(
    by="lic_holders", ascending=False
)  # Sort the data in decreasing order

Sans trop de surprise, on observe que c’est le Gard (où est la Camargue), les Bouches-du-Rhône, l’Hérault et le Vaucluse (départements qui entourent le Gard) qui ont le plus de licenciés dans ce sport.

Quels sont les sports les plus pratiqués par les femmes ?

Nous allons :

  1. Sélectionner les enregistrements correspondant à gender = 'F' ;
  2. Grouper par fédération et compter le nombre de licenciées ;
  3. Afficher les dix sports avec le plus de licenciées.
>>> d2012_females_top_10 = d2012.xs("F", level="gender")
    .groupby(["fed_code", "fed_name"])
    .sum()
    .nlargest(10, "lic_holders")
>>> d2012_females_top_10

Pandas permet également de faire des graphiques. Par défaut c’est la bibliothèque matplotlib qui est utilisée. Nous pouvons par exemple utiliser un diagramme en bâtons pour afficher le top 10 des sports pratiqués par les femmes :

>>> d2012_females_top_10.plot(
    kind="bar",
    legend=False,
    xlabel="Sport federation",
    ylabel="Number of license holders",
    color="#CC0066",
    title="Female sport license holders in 2012 (top 10)",
)

Charger les données pour toutes les années

Dans la section précédente, nous avons chargé uniquement les données de l’année 2012. Mais nous avons bien plus de données que cela. Nous allons donc charger chaque fichier, puis renommer la colonne lic_holders en fonction de l’année en cours. Nous aurons ainsi une DataFrame, avec en colonne le nombre de licenciés par année, et en index les différents groupes.

Nous allons faire une liste years_dfs qui va contenir toutes les DataFrames, une par année, puis nous allons simplement les concaténer. Cela donne donc :

>>> years_dfs = []
>>> for year in range(2012, 2019):
...    fname = f"sport_license_holders_{year}.csv"
...    yr_df = pd.read_csv(
...        DATA_DIR / fname,
...        dtype={"dep_code": str},
...        index_col=["dep_code", "dep_name", "fed_code", "fed_name", "gender", "age"],
...    )
...    yr_df.rename(columns={"lic_holders": str(year)}, inplace=True)
...    year_dfs.append(yr_df)
>>>

On concatène toutes les DataFrames, en fonction de l’index (axis=1) :

>>> data = pd.concat(years_df, axis=1)
>>> data

Nous avons ainsi une DataFrame avec plus de 1.6 million de lignes, et 7 colonnes.

On peut maintenant afficher, par exemple, les 10 sports les plus pratiqués en fonction des années :

>>> data_sport = data.groupby(level=["fed_code", "fed_name"]).sum()
>>> data_sport.nlargest(10, "2012")

Nous avons ainsi le nombre de licenciés, par fédération et par année pour les 10 plus grosses fédérations de 2012. Le tri est effectué par rapport aux données de 2012.

On notera qu’en 2018 il y a 0 licencié de Karaté. Cela est probablement une erreur dans les données, ce qui peut arriver.

Tracer l'évolution du nombre de licenciés avec Plotly

Nous pouvons maintenant suivre l’évolution du nombre de licenciés dans certaines disciplines. Nous sélectionnons les sports dont le code de fédération est 109, 115, 242, 117.

>>> sel_data_sports = data_sports.loc[
...    [109, 115, 242, 117]
... ] # Select the rows whose value at the first level of the index (``fed_code``)
... # is one of the list items
>>> # Drop the first level of the index (``fed_code``)
>>> sel_data_sports = sel_data_sports.droplevel(0)
>>> # Will be used as the title of the legend
>>> sel_data_sports.index.name = "Federations"
>>> sel_data_sports.transpose().plot(
...    title="Sport license holders", xlabel="year", ylabel="number of license holders"
...)  # Transpose to have the years as the index (will be the X axis)

Comme nous le disions, par défaut Pandas utilise la bibliothèque matplotlib pour générer les graphiques. La figure produite ici est statique, elle peut facilement être insérée dans un rapport par exemple, mais cela présente des difficultés lors de la phase d’exploration.

Depuis quelque temps maintenant, Pandas est compatible avec plusieurs bibliothèques de visualisation. Il y a notamment Plotly, qui permet de faire des graphiques interactifs utilisables dans le navigateur web.

Pour utiliser Plotly, il est nécessaire de changer la bibliothèque utilisée par défaut.

# Choose Plotly as the plotting back-end
# this has to be done only once, usually at the begining of the code
>>> pd.options.plotting.backend = "plotly"

Une fois Plotly configurée, nous pouvons retracer le graphique, comme précédemment :

>>> fig = sel_data_sports.transpose().plot(title="Sport license holders")
>>> fig.update_layout(xaxis_title="year", yaxis_title="number of license holders")
>>> fig

Dans un environnement Jupyter, la figure produite est celle-ci, et il est possible de sélectionner/désélectionner les courbes à afficher :

Quelle est la prochaine étape ?

Nous avons dans ce premier article, chargé avec Pandas des données textuelles au format CSV. Nous avons vu comment et pourquoi utiliser un index multiple. Cela nous a permis de calculer quelques statistiques simples sur des groupes d’individus. Nous avons également produit des visualisations avec matplotlib et avec Plotly.

Dans le prochain article, nous utiliserons des widgets Jupyter pour manipuler dynamiquement les données à afficher sur les graphiques.