Sprint Review 15W19: Exports

Voici le support de la Sprint Review n°11, concernant les exports.

Tâches

  • 19 tâches prévues
  • 16 tâches effectuées (dont 11 avaient été prévues)
  • 24 tâches au total
  • plus de 38 points de complexité prévus
  • 38 points de complexité effectués (un peu plus que la moyenne)

VSST 2015

ezVIS a été présenté à VSST 2015 par Anne-Marie BADOLATO, le 13 mai 2015.
À l’occasion, une instance protégée par login/mot de passe a été présentée, qui concernait une étude réelle pour l’IRSTV. Cette instance tournait sur la machine virtuelle d’intégration, car nous n’avons pas été en mesure de mettre en place la machine de production et de la tester dans les temps.

forever

En effet, une des différences entre la machine de production et la machine d’intégration est que la machine de production utilise forever pour s’assurer qu’ezmaster est relancé automatiquement si jamais il plante.

Ce qui a retardé l’utilisation de la machine de production est qu’ezmaster s’est révélé incapable, quand il était lancé par forever, de créer des fichiers temporaires dans le répertoire courant. Ceci a donné lieu à une correction d’ezmaster, mais pas assez tôt pour que ce soit la machine de production qu’on utilise.

ezMaster

En plus de la correction apportée pour fonctionner avec forever, ezMaster a connu plusieurs changements:

  1. une optimisation de la fonction reverse-proxy, ce qui a éliminé les ralentissements observés après quelques utilisations des instances qu’ezmaster surveillait 11fba01,
  2. l’affichage de l’app utilisée par une instance, et de sa version #30
  3. ajout d’une prévisualisation de l’URL que va donner le nom technique d’une instance qu’on est en train de créer #32
  4. le numéro de version d’une instance a été rendu optionnel (dans le but de simplifier les URL résultantes) #18

ezVIS

La plupart des tâches de ce sprint étaient liées à ezvis.

Bug

Nous avons corrigé un bug qui se produisait dans un réseau avec des facettes: quand on cliquait sur une facette, les restrictions apportées pour la création du réseau (en particulier selector, mais aussi maxItems et threshold) n’étaient pas appliquées.
Cela posait un problème quand le nombre de liens du réseau non restreint était trop important pour que le réseau puisse s’afficher dans le navigateur, gelant ainsi le navigateur.

Toutefois, cette correction ne touche que selector car les autres restrictions, appliquées en plus de celle de la facette, mène souvent à des graphes vides, ce qui est difficilement compréhensible.

Voir issue #39.

Améliorations mineures

  • #38: ajout de la possibilité de rendre les labels sur les graphiques plus courts (sur le même principe que ce qui avait déjà été fait pour les horizontalbars), pour les histograms, et pour les pies. Pour ce dernier, ce ne sont pas les labels eux-mêmes qui sont raccourcis, mais leur équivalent dans la légende du camembert,
  • #31: la référence à amCharts qui apparaissait comme un petit lien js Charts en haut à gauche des graphiques a été déplacé en bas à droite des graphiques, emplacement jugé moins gênant (il est moins souvent placé sur une barre sur laquelle on clique). Rappel: cette référence est nécessaire, car l’enlever requerrait de payer la société qui produit cette bibliothèque,
  • #28: les labels des camemberts (qui apparaissent autour des parts du graphique) sont maintenant désactivables (pour ne plus voir que les nombres). Il faut utiliser removeLabels: true,
  • #37: nous avons ajouté un exemple de configuration ezvis pour des fichiers .tsv dans le showcase.

Chargement de .TSV

Après l’écriture de la mini-configuration de déclaration du loader pour charger des .tsv minimaux, nous avons voulu créer un exemple réel de chargement de fichiers tirés du WoS (Web of Science).
Il s’est trouvé que les fichiers tels quels ne se chargeaient pas dans ezvis, même après avoir utilisé des options peu courantes de castor-load-csv.

Après investigation, le nœud du problème se trouvait dans la bibliothèque csv-string qui analyse le TSV dans castor-load-csv. L’auteur de la bibliothèque l’a améliorée pour qu’elle prenne aussi en compte ces fichiers TSV (il n’y a pas vraiment de norme concernant la manière d’encoder les doubles quotes (guillemets anglais) dans ces fichiers). Voir les tests proposés pour plus de détails.

Exports

Le thème de ce sprint était l’export en général. Il se spécialise en:

  • export des images des graphiques
  • export des documents associés aux graphiques
  • export des données des graphiques (ce n’était pas demandé)

graphiques

amCharts

Les graphiques horizontalbars, histogram, pie et map utilisent la même bibliothèque qui vient d’être mise à jour. Surprise: le thème de cette mise à jour est l’export. Cette version améliore une fonctionnalité qui existait déjà, en l’étendant à d’autres formats et aussi aux données qui ont permis la création du graphique.

Ces graphiques simples sont donc désormais exportables à partir d’un menu présent en haut à droite. Ils permettent:

  • l’annotation (dessin sur l’image, à la souris),
  • la sauvegarde de l’image (avec son éventuelle annotation), aux formats JPG, PNG, SVG et même PDF,
  • la sauvegarde des données ayant permis la construction du graphique (sauf pour les cartes, que nous n’avons pas réussi à activer), aux formats CSV, XLSX et JSON.

Lors des tests, nous nous sommes aperçus que l’export CSV exportait toutes les valeurs sauf la première (en général la plus grande). La déclaration d’un problème dans leur système de support a provoqué une mise à jour dans la journée. Bravo à amCharts.

cytoscape

Nous avions reperé qu’il existait aussi une fonction d’export dans la bibliothèque Cytoscape que nous utilisons pour la représentation graphique des réseaux. Il s’est avéré que cette fonction était beaucoup moins clé-en-main que celle d’amCharts.

Le menu d’export des réseaux se résume donc à un bouton qui exporte une image PNG.

Pour le détails des exports des graphiques, voir le ticket #36.

documents

L’export des documents était déjà présent dans ezvis, mais uniquement sur la page des documents, où on exporte tous les documents présents sur la page, avec une sélection basique, par filtrage.

Il est désormais présent aussi sur la page des graphiques, et prend aussi en compte les filtres venant du graphique et des facettes. Voir #20.

http dans les documentFields / nosave

Lors de la dernière Sprint Review, nous avions montré un usage des flyingFields qui était certes visuel, mais qui s’est avéré non pertinent: nous modifiions à la volée (flying) les identifiants du graphique.
Ce faisant, nous avions rendu les filtres inopérants (cliquer sur un pays ne retournait plus les documents publiés dans ces pays).
Cela n’invalide pas l’utilité des flyingFields, puisque leur utilisation reste valable quand on modifie les valeurs projetées dans les graphiques (par exemple, pour afficher un taux de citation par année, et pas seulement un nombre de citations).

Mais le besoin d’externaliser des tables de références (ici, une correspondance entre les noms de pays et leur code ISO) perdure, donc nous avons implémenté l’utilisation de sources extérieures (comme dans les corpusFields) depuis les documentFields.

Comme nous ne voulons pas surcharger la base en dupliquant des tables dans chaque document, nous avons introduit une propriété pour ces documentFields que nous voulons utiliser, mais pas sauvegarder dans la base: nosave. Il suffit de positionner cette propriété à true pour que le champ ne soit pas sauvegardé mais tout de même disponible pour le calcul d’autres documentFields.

Voir #40, et nosave.

JBJ

zip

Pour calculer des expressions impliquant les valeurs de deux tableaux (comme pour normaliser des valeurs par années), il nous fallait être capable de fusionner deux tableaux de même longueur.

Exemple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"publiPerYear": [
{"_id":"2007","value":538},
{"_id":"2008","value":577},
{"_id":"2009","value":611},
{"_id":"2010","value":548},
{"_id":"2011","value":567},
{"_id":"2012","value":608}],

"citationsPerYear": [
{"_id":"2007","value":7681},
{"_id":"2008","value":5479},
{"_id":"2009","value":5043},
{"_id":"2010","value":3698},
{"_id":"2011","value":2927},
{"_id":"2012","value":2049}]
}

En divisant citationsPerYear[i] par publiPerYear[i]:

1
2
3
4
5
6
{
"zip": [ "citationsPerYear", "publiPerYear" ],
"foreach": {
"compute": "citationsPerYear / publiPerYear"
}

}

Dans cet exemple, "zip": [ "citationsPerYear", "publiPerYear" ] renvoie, en JBJ:

1
2
3
4
5
6
7
[
{"_id":"2007","citationsPerYear":7681, "publiPerYear": 538},
{"_id":"2008","citationsPerYear":5479, "publiPerYear": 577},
{"_id":"2009","citationsPerYear":5043, "publiPerYear": 611},
{"_id":"2010","citationsPerYear":3698, "publiPerYear": 548},
{"_id":"2011","citationsPerYear":2927, "publiPerYear": 567},
{"_id":"2012","citationsPerYear":2049, "publiPerYear": 608}]

Voir JBJ#8

getproperty

De plus, il manquait une action capable de retourner la valeur d’un tableau associatif correspondant à une clé:

Ex:

1
2
3
4
{
"set": [ "a", "b", "c" ],
"getProperty": "0"
}

renvoie

1
"a"

et

1
2
3
4
{
"set": { "a": 0, "b": 1, "c":2 },
"getProperty": "b"
}

renvoie

1
1

Voir JBJ#9

commande ezref

La version 1.0.0 d’ezref devait être lancée de manière non triviale quand ce n’était pas par ezmaster. Nous avons donc publié la version 1.1.0 qui ajoute une commande ezref quand on l’installe via:

1
$ npm install -g ezref

Installation / mise à jour

Après l’écriture de tests via dalekjs, l’installation d’ezvis ramenait des modules utiles uniquement pour le développement (pour ces tests).

Pour éviter de grossir les fichiers d’ezvis, on peut l’installer en utilisant l’option --production:

1
$ npm install --production -g ezvis

C’est la même commande qui permet de mettre à jour ezvis en installant la dernière version à la place de l’éventuelle version installée, quelle qu’elle soit.

À ce jour, c’est la version 6.6.0.

Sprint Review #15W14: ressources externes

Voici venue la revue de sprint numéro 10, qui a pour thème principal les ressources externes.

Tâches

  • 18 tâches prévues
  • 10 tâches effectuées
  • 22 tâches au total
  • plus de 46 points de complexité prévus (avec des incertitudes)
  • 36,5 points de complexité résolus (avec des tâches non prévues): dans la moyenne

madec-project.github.io

J’ai créé un page pour l’organisation madec-project sur GitHub, celle qui contient tous les programmes liés au projet MADEC. GitHub offrant l’hébergement d’un site statique, nous avions déjà opté pour Hexo pour ce blog.

Pour obtenir une URL relativement courte (en tout cas plus courte que http://madec-project.github.io/blogfr), il a fallu nommer le dépôt contenant ce site madec-project.github.io, ce qui nous autorise une URL sans le nom du dépôt: http://madec-project.github.io/

Twitter

Un compte Twitter ezvis_project a aussi été créé (en ces temps de communication autour d’ezVIS, ça peut servir).

vimadec / vpmadec / puppet

Le travail avec Patrice, Martial et Philippe porte ses fruits:

  • ajout d’un script d’installation d’une app ezmaster à partir de l’URL de son .tar.gz,
  • mise sous surveillance du processus ezmaster afin de le relancer automatiquement quand il s’arrête (via forever),
  • création d’une machine virtuelle de production vpmadec,
  • création d’un accélérateur sécurisé vers cette machine virtuelle.

ezVIS

Test sous node v0.12

En utilisant nvm, nous avons lancé et testé à la main ezVIS, et tout a marché.

Il a néanmoins fallu passer par un npm rebuild pour recompiler/récupérer les modules binaires correspondant à cette version (principalement bson et kerberos)

Affichage de la version

Pour faciliter les échanges avec les utilisateurs (il y en a eu avec une personne d’Orléans, par mél), on affiche la version d’ezVIS dans le navigateur:

mais aussi lors du lancement d’une instance ezVIS:

login/password

On peut maintenant limiter l’accès à un rapport ezVIS en utilisant la clé access, contenant un login et un mot de passe soit plain, soit sha1:

1
2
3
4
"access": {
"login": "user",
"sha1" : "37fa265330ad83eaa879efb1e2db6380896cf639"
}

Le mot de passe sous forme plain est simplement le mot de passe en clair.
Mais comme ce n’est pas une bonne pratique, on peut remplacer son usage par celui de sha1 qui remplace un mot de passe par son empreinte SHA-1.

Ainsi, on connaît l’empreinte du mot de passe, mais pas le mot de passe lui-même.

Pour obtenir l’empreinte SHA-1 d’un mot de passe, on peut utiliser des commandes comme shasum ou sha1sum (en n’incluant pas de passage à la ligne dans le mot de passe), ou bien des sites de génération comme SHA1 online.

Accès aux ressources externes

ezref

On peut avoir besoin de ressources externes à ezvis (parce que de simples fichiers), mais avec la possibilité de remplacer ces fichiers de référence (tables de correspondance, listes, …).

Utiliser ezref, l’application pour ezMaster qui met à disposition via le protocole http des fichiers qu’ezMaster vous permet de déposer est la solution.

Pour pouvoir stocker les ressources: ezref (serveur web statique).

flyingFields

Les flyingFields sont les cousins des documentFields et des corpusFields. Ils sont un croisement, dans le sens où ils permettent l’interopérabilité des uns et des autres.

JBJ

Pour pouvoir appliquer une table de correspondance présente dans les corpusFields, on a ajouté une action mappingVar à JBJ, qui fonctionne comme mapping, mais dont les arguments sont différents.

Exemple: externaliser la table de correspondance d’une carte géographique

Pour projeter des données sur la carte du monde, jusqu’ici, on était obligé de traduire les noms des pays en codes ISO (c’est ainsi que sont identifiés les pays sur la carte):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"$fields.country" : {
"label": "Pays d'affiliation",
"path" : "content.json.Pays",
"parseCSV": ";",
"foreach": {
"mapping": {
"Albania" : "ALB",
"Algeria" : "DZA",

"Zaire" : "COD",
"Zambia" : "ZMB"
}
}
}

Nous avons amélioré l’opérateur mapping de JBJ pour qu’il puisse traiter directement tout un tableau:

1
2
3
4
5
6
7
8
9
10
11
12
"$fields.country" : {
"label": "Pays d'affiliation",
"path" : "content.json.Pays",
"parseCSV": ";",
"mapping": {
"Albania" : "ALB",
"Algeria" : "DZA",

"Zaire" : "COD",
"Zambia" : "ZMB"
}
}

Puis, nous avons créé un opérateur similaire à mapping qui, au lieu de prendre en entrée l’objet courant et en paramètre la table de correspondance, permet de mettre en paramètre deux noms de variable: l’entrée et la table.
Il s’appelle mappingVar (ou combine).

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"set": {
"arg": {
"a": "Aha!",
"b": "Baby"
}
,

"input": "a"
}
,

"mappingVar": [
"input",
"arg"
]
}

Ceci renvoie "Aha!".

Donc, grâce à ezref, on peut mettre la table de correspondance sur un serveur externe, et le charger dans un corpusFields, accessible comme une variable dans les flyingFields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"documentFields": {
"$fields.country" : {
"label": "Pays d'affiliation",
"path" : "content.json.Pays",
"parseCSV": ";",
"foreach": {
"trim": true
}
}
},
"corpusFields": {
"$country2iso": {
"$?" : "http://localhost:35000/country2iso3.json",
"parseJSON": true
}
},
"flyingFields": {
"$country2": {
"$_id": {
"combine" : ["_id", "country2iso"]
},
"mask": "_id,value"
}
}

Quand on veut avoir le nombre de valeurs distinctes de fields.country, on peut utiliser l’URL http://localhost:3000/compute.json?operator=distinct&field=fields.country :

1
2
3
4
5
6
7
8
9
10
11
12
13
{

data: [
{
_id: "Albania",
value: 2
},
{
_id: "Algeria",
value: 15
}
]
}

Mais en utilisant &flying=country2 en plus, on applique le JBJ correspondant à ce champ:
http://localhost:3000/compute.json?operator=distinct&field=fields.country&flying=country2

1
2
3
4
5
6
7
8
9
10
11
12
13
{

data: [
{
_id: "ALB",
value: 2
},
{
_id: "DZA",
value: 15
}
]
}