Blog entries

  • SciviJS

    2016/10/10 by Martin Renou

    Introduction

    The goal of my work at Logilab is to create tools to visualize scientific 3D volumic-mesh-based data (mechanical data, electromagnetic...) in a standard web browser. It's a part of the european OpenDreamKit project. Franck Wang has been working on this subject last year. I based my work on his results and tried to improve them.

    Our goal is to create widgets to be used in Jupyter Notebook (formerly IPython) for easy 3D visualization and analysis. We also want to create a graphical user interface in order to enable users to intuitively compute multiple effects on their meshes.

    As Franck Wang worked with X3DOM, which is an open source JavaScript framework that makes it possible to display 3D scenes using HTML nodes, we first thought it was a good idea to keep on working with this framework. But X3DOM is not very well maintained these days, as can be seen on their GitHub repository.

    As a consequence, we decided to take a look at another 3D framework. Our best candidates were:

    • ThreeJS
    • BabylonJS

    ThreeJS and BabylonJS are two well-known Open Source frameworks for 3D web visualization. They are well maintained by hundreds of contributors since several years. Even if BabylonJS was first thought for video games, these two engines are interesting for our project. Some advantages of ThreeJS are:

    Finally, the choice of using ThreeJS was quite obvious because of its Nodes feature, contributed by Sunag Entertainment. It allows users to compose multiple effects like isocolor, threshold, clip plane, etc. As ThreeJS is an Open Source framework, it is quite easy to propose new features and contributors are very helpful.

    ThreeJS

    As we want to compose multiple effects like isocolor and threshold (the pixel color correspond to a pressure but if this pressure is under a certain threshold we don't want to display it), it seems a good idea to compose shaders instead of creating a big shader with all the features we want to implement. The problem is that WebGL is still limited (as of the 1.x version) and it's not possible for shaders to exchange data with other shaders. Only the vertex shader can send data to the fragment shader through varyings.

    So it's not really possible to compose shaders, but the good news is we can use the new node system of ThreeJS to easily compute and compose a complex material for a mesh.

    alternate text

    It's the graphical view of what you can do in your code, but you can see that it's really simple to implement effects in order to visualize your data.

    SciviJS

    With this great tools as a solid basis, I designed a first version of a javascript library, SciviJS, that aims at loading, displaying and analyzing mesh data in a standard web browser (i.e. without any plugin).

    You can define your visualization in a .yml file containing urls to your mesh and data and a hierarchy of effects (called block structures).

    See https://demo.logilab.fr/SciviJS/ for an online demo.

    You can see the block structure like following:

    https://www.logilab.org/file/8719790/raw

    Data blocks are instantiated to load the mesh and define basic parameters like color, position etc. Blocks are connected together to form a tree that helps building a visual analysis of your mesh data. Each block receives data (like mesh variables, color and position) from its parent and can modify them independently.

    Following parameters must be set on dataBlocks:

    • coordURL: URL to the binary file containing coordinate values of vertices.
    • facesURL: URL to the binary file containing indices of faces defining the skin of the mesh.
    • tetrasURL: URL to the binary file containing indices of tetrahedrons. Default is ''.
    • dataURL: URL to the binary file containing data that you want to visualize for each vertices.

    Following parameters can be set on dataBlocks or plugInBlocks:

    • type: type of the block, which is dataBlock or the name of the plugInBlock that you want.
    • colored: define whether or not the 3D object is colored. Default is false, object is rendered gray.
    • colorMap: color map used for coloration, available values are rainbow and gray. Default is rainbow.
    • colorMapMin and colorMapMax: bounds for coloration scaled in [0, 1]. Default is (0, 1).
    • visualizedData: data used as input for coloration. If data are 3D vectors available values are magnitude, X, Y, Z, and default is magnitude. If data are scalar values you don't need to set this parameter.
    • position, rotation, scale: 3D vectors representing position, rotation and scale of the object. Default are [0., 0., 0.], [0., 0., 0.] and [1., 1., 1.].
    • visible: define whether or not the object is visible. Default is true if there's no childrenBlock, false otherwise.
    • childrenBlocks: array of children blocks. Default is empty.

    As of today, there are 6 types of plug-in blocks:

    • Threshold: hide areas of your mesh based on a variable's value and bound parameters

      • lowerBound: lower bound used for threshold. Default is 0 (representing dataMin). If inputData is under lowerBound, then it's not displayed.
      • upperBound: upper bound used for threshold. Default is 1 (representing dataMax). If inputData is above upperBound, then it's not displayed.
      • inputData: data used for threshold effect. Default is visualizedData, but you can set it to magnitude, X, Y or Z.
    • ClipPlane: hide a part of the mesh by cutting it with a plane

      • planeNormal: 3D array representing the normal of the plane used for section. Default is [1., 0., 0.].
      • planePosition: position of the plane for the section. It's a scalar scaled bewteen -1 and 1. Default is 0.
    • Slice: make a slice of your mesh

      • sliceNormal
      • slicePosition
    • Warp: deform the mesh along the direction of an input vector data

      • warpFactor: deformation factor. Default is 1, can be negative.
      • inputData: vector data used for warp effect. Default is data, but you can set it to X, Y or Z to use only one vector component.
    • VectorField: represent the input vector data with arrow glyphs

      • lengthFactor: factor of length of vectors. Default is 1, can be negative.
      • inputData
      • nbVectors: max number of vectors. Default is the number of vertices of the mesh (which is the maximum value).
      • mode: mode of distribution. Default is volume, you can set it to surface.
      • distribution: type of distribution. Default is regular, you can set it to random.
    • Points: represent the data with points

      • pointsSize: size of points in pixels. Default is 3.
      • nbPoints
      • mode
      • distribution

    Using those blocks you can easily render interesting 3D scenes like this:

    https://www.logilab.org/file/8571787/raw https://www.logilab.org/file/8572007/raw

    Future works

    • Integration to Jupyter Notebook
    • As of today you only can define a .yml file defining the tree of blocks, we plan to develop a Graphical User Interface to enable users to define this tree interactively with drag and drop
    • Support of most file types (for now it only supports binary files)

  • Mon Hackathon à la BnF

    2016/11/24 by Adrien Di Mascio

    J'ai eu la chance de participer au premier hackathon BnF qui s'est déroulé les samedi 19 et dimanche 20 novembre. Alors, c'est quoi un hackathon BnF ?

    C'est d'abord un lieu ! Un lieu insiprant qui a été ma deuxième maison mon deuxième lieu de travail pendant ces 5 dernières années où j'ai travaillé sur data.bnf.fr.

    https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/BNF_FM_Hall_Est.jpg/512px-BNF_FM_Hall_Est.jpg

    Et puis une thématique : mettre en avant le patrimoine de la BnF et inventer de nouveaux usages numériques autour de ses ressources. Pas beaucoup de contraintes si ce n'est de rendre le code disponible sous une licence libre.

    Je ne connais pas bien toutes les applications de la BnF et en particulier je ne maîtrise pas tous les services de Gallica (honte à moi !) mais je commence à avoir une certaine idée de ce que sont les données à la BnF, de comment elles sont rangées (je finis même par connaître les zones intermarc et pouvoir comprendre des 100$blagues). Au-delà du projet data.bnf.fr lui-même, la connaissance de ces données, de leur récupération et de leur usage s'est affinée avec mes travaux sur les projets OpenCat, reliures, bp16, et tous les autres passés ou en cours où on a relié des bases de données extérieures aux notices d'autorité de la BnF comme human-music , andrebreton, les registres de la Comédie-Française, libretheatre, prototype biblissima, bientôt des morceaux d'Archives départementales et nationales et j'en oublie certainement. Je partais donc avec l'idée qu'à défaut de réaliser quelque chose, je saurai a minima servir de facilitateur dans la récupération et le traitement des données.

    Le hackathon, c'est aussi une ambiance conviviale portée par les quelques 70 participants qui sont venus, la dizaine d'équipes ainsi constituées et tous les agents BnF qui se sont relayés pendant plus de 24h pour répondre à nos questions, nous guider ou redonner un petit coup de boost lorsque la fatigue ou la frustration commençaient à gagner du terrain. Oui parce qu'en fait, on était quand même là pour tenter de produire quelque chose… Pour ma part, j'ai rejoint en début de hackathon le projet porté par Carmen Brando et Francesca Frontini dont le but était de pouvoir extraire de Gallica les tables des matières et les textes OCRisés et procéder à de la reconnaissance d'entités nommées. Plus précisément, il s'agissait de pouvoir retrouver les lieux et personnes cités dans les textes numérisés pour les aligner vers les données de data.bnf.fr. À la différence d'autres projets, nous voulions donc créer de la nouvelle donnée et l'exploiter plutôt que de réutiliser des relations ou indexations déjà présentes dans les catalogues. Si ce chantier aboutissait, les intérêts pourraient être multiples puisqu'on pourrait imaginer une navigation enrichie de cartes ou de nouveaux rebonds, de nouvelles visualisations à partir de statistiques et possiblement soulever de nouvelles questions de recherche sur les textes eux-mêmes.

    Relations entre auteurs / visualisation créée par Marine Riguet

    Relations entre auteurs / visualisation créée par Marine Riguet

    Nous nous sommes plus ou moins répartis en sous-groupes de travail (je simplifie car chacun a en réalité participé de près ou de loin à tout) :

    • Paule, Delphine et Marc qui étaient nos experts littéraires et nous ont aidé à déterminer des corpus de travail pertinents pour tester nos outils,
    • Frédéric, qui avait développé l'outil de traitement linguistique Alix, et qui s'est donc occupé du traitement initial et des annotations linguistiques des textes,
    • Carmen et Francesca, qui avaient écrit le moteur de reconnaissance d'entités nommées REDEN, se sont occupées d'améliorer l'outil pour permettre le traitement du texte annoté et retrouver les concepts databnf et dbpedia de personnes et de lieux,
    • Gaétan, Mehdi (issus de l'équipe Prevu), Jean-Baptiste se sont plus concentrés sur le développement d'une appli JS pour naviguer et visualiser les résultats obtenus,
    • Bruno et moi-même voguions de sous-groupe en sous-groupe pour faciliter la récupération de données, réaliser les divers pré/post-traitements et aussi taper un peu sur la visu.

    Le résultat ? Je crois que nous avons été un peu trop ambitieux et il n'est malheureusement pas encore consultable en ligne mais on va tenter d'y travailler dans les jours qui viennent et de rendre le code accessible. Même si ce n'est encore qu'une preuve de concept, on a malgré tout obtenu quelques jolis résultats comme l'affichage d'une carte des lieux mentionnés dans une œuvre avec rebonds interactifs vers les pages correspondantes dans Gallica ou encore des pages de statistiques sur les personnes citées. Tout ça est encore loin d'être industrialisé et il y a évidemment plein de problèmes comme la résilience face à un mauvais OCR (on s'est concentrés sur les textes dont la qualité d'OCRisation était supérieure à 80% d'après Gallica), à l'ancien français ou encore à la gestion propre des personnes ou lieux fictifs vs. réels.

    Exemple d'écran de navigation obtenu qui fait le lien entre une carte et un texte OCRisé de Gallica

    En tout cas, j'ai eu la chance de tomber sur des co-équipiers de luxe et je garderai un excellent souvenir de ces 24h. Pour conclure, j'adresse un grand bravo à gallicarte qui a remporté le prix du jury et à diderotbot qui a trouvé de belles perles dans Gallica qui résonnaient particulièrement bien avec l'actualité.

    À l'année prochaine pour la suite j'espère !