Ceci est un workshop créé par l’auteur pour le laboratoire d’architecture ALICE (EPFL-ENAC) dans le cadre du projet de recherche et d’enseignement POLIPHILO.

Nous allons apprendre à interroger une base de données et à projeter des images prises sur le terrain dans divers espaces paramétriques pour une analyse en termes de phénoménologie spatiale. Le workshop vise à améliorer vos compétences technique et à vous permettre à articuler entre informatique et pensée de l’espace vécu.

Installer les logiciels nécessaires

Si ce n’est pas encore fait, installez les logiciels Visual Studio CodeDB Browser for SQ Lite et Cytoscape. Le premier sert à éditer des données brutes et à programmer, le second à extraire des données structurées d’une base de données relationnelle. Le troisième sert à visualiser des réseaux.

Visual Studio Code

Pour éditer des données de manière propre, vous avez besoin d’un éditeur de texte pur. Word ou LibreOffice ne sont pas des éditeurs de texte pur, pas plus que le logiciel TextEditinstallé d’office sur MacOS. Tous ces logiciels ajoutent des annotations cachées aux données. Ces annotations servent au formatage d’affichage et d’impression. Pour l’édition WYSIWYG, ces logiciels sont utiles, pour la programmation, il faut les éviter absolument.

Si ce n’est pas déjà fait et si vous n’avez pas déjà installé un autre éditeur de texte pur (Notepad++, Geany,.. ), téléchargez et installez Visual Studio Code.

DB Browser for SQLite

Les bases de données relationnelles (BDDR) stockent l’information sous la forme de plusieurs tableaux interconnectés. Elles permettent notamment d’extraire des sous-ensembles d’informations par le moyen de requêtes.

Il existe un grand nombre de formats de BDDs et de logiciels pour y accéder. Nous allons travailler avec un format de BDD très simple, nommé sqlite. Son avantage est de tenir dans un seul fichier de petite taille et de se passer d’installation d’un serveur SQL. Un fichier sqlite contenant les données produites en cours est prêt à votre usage.

Si ce n’est pas déjà fait, téléchargez et installez la dernière version de DB Browser.

Cytoscape

Pourquoi l’approche réseau?

Le logiciel Cytoscape sert à visualiser des réseaux.

Les réseaux sont “l’autre” espace géographique, souvent négligé dans les approches classiques trop focalisées sur l’espace topographique des étendues euclidiennes des surfaces projetées du globe. Avant d’être utilisé pour modéliser un espace concret, un réseau gagne à être compris en tant que graphe, objet mathématique abstrait décrit dans la théorie des graphes. Une connaissance approfondie de cette théorie n’est pas nécessaire pour ce workshop, mais il faut au moins connaître quelques notions fondamentales, utiles pour la description d’un réseau. Elles seront présentées en cours.

Pour l’usage concret des modèles réseau, songez aussi que du point de vue réseau, tout espace, y compris celui d’un texte, peut être traité comme un espace géographique. Si vous vous intéressez à la représentation des flux (migration, matières premières, énergie etc.) voir aussi: “Visualisation de flux géographiques” (PDF, 10MB). Quelques autres exemples d’usage sont donnés sur la page Visualiser des réseaux géographiques.

Le logiciel

Le logiciel Cytoscape a été développé par des biologistes pour l’étude de génomes. Il peut cependant être utilisé pour analyser n’importe quel réseau, comme les réseaux de mobilité, les réseaux politiques ou les réseaux sémantiques.

Si ce n’est pas déjà fait, téléchargez et installez la dernière version de Cytoscape, a priori la 3.7.1.

Tâche 1: ouvrir la base de données SQLite avec DB Browser

  1. Menu: Fichier > Ouvrir une base de données
  2. Naviguez vers le fichier poliphilo.sqlite que vous avez reçu et ouvrez le (Open).

Vérifiez si toutes les tables de données sont disponibles dans la fenêtre de navigation des données:

Tâche 2: Premières extractions de données

Pour visualiser des données, vous avez d’abord besoin de comprendre comment les extraire de la base.

Commençons par une requête simple qui sélectionne tous les enregistrements (*) de la table ref_images.

SELECT * FROM ref_images

Copiez le code ci-dessus et collez-le dans le champ de l’onglet Exécuter le SQL. Puis exécutez-le en appuyant sur le bouton ▶

Vous devriez voir ceci:

Ajoutons une condition WHERE permettant de ne retenir que les enregistrements correspondant à un critère. Vous dites à la base: “donne-moi tous les enregistrements de la table ref_images où (where) la catégorie est ‘photography'” :

SELECT * FROM ref_images WHERE category = 'photography'Code language: JavaScript (javascript)

Vous devriez voir ceci:

Une base de données permet de joindre des données depuis plusieurs tables sur la base d’un identifiant unique de vos enregistrements (1 enregistrement = une ligne dans une table de données). Pour cette raison, il est de première importance, lors de la construction de vos données, de faire en sorte que vos identifiants d’enregistrements soient cohérents et uniques.

Dans la requête suivante, nous récupérons les colonnes ref_imageIDcategory et titel de la table ref_imageset la colonne boardID de la table boards:

SELECT ref_images.ref_imageID, ref_images.category, ref_images.titel, boards.boardID
FROM ref_images
LEFT JOIN boards ON ref_images.ref_imageID = boards.imageID

Vous devriez voir ceci:

Remarquez le mot clef LEFT JOIN. En effet, votre première table (ref_images) est par définition à gauche (left) de la liste des tables jointes suivantes, dans notre cas la table boards. On dit:

“Prend tous les enregistrements de la table ref_images et ajoute leur les données correspondantantes en te basant sur l’équivalence des identifiants uniques ref_imageID et imageID.”

Remarquez que la colonne boardID possède de nombreuses entrées NULL. Cela signifie que nombreuses enregistrements de la table de gauche ref_images ne possèdent pas d’équivalent dans la table de droite boards. Pour ne retenir que les enregistrements présents dans les deux tables, remplacez LEFT JOIN par INNER JOIN.

SELECT ref_images.ref_imageID, ref_images.category, ref_images.titel, boards.boardID
FROM ref_images
INNER JOIN boards ON ref_images.ref_imageID = boards.imageID

Il est bien sûr aussi possible de filtrer les résultats d’une requête comportant une jointure, c’est-à-dire sélectionner seulement les enregistrements correspondant à un critère:

SELECT ref_images.ref_imageID, ref_images.category, ref_images.titel, boards.boardID
FROM ref_images
INNER JOIN boards ON ref_images.ref_imageID = boards.imageID
WHERE boards.boardID = 'D4' OR ref_images.category = 'photography'Code language: JavaScript (javascript)

À présent, concaténez plusieurs requêtes à l’aide de l’instruction UNION :

SELECT ref_images.ref_imageID AS imageID, ref_images.category AS category, ref_images.titel AS titel, boards.boardID
FROM ref_images
LEFT JOIN boards ON ref_images.ref_imageID = boards.imageID
UNION
SELECT geo_images.geo_imageID AS imageID, 'geoimage' AS category, geo_images.keyword_e1 AS titel, boards.boardID
FROM geo_images
LEFT JOIN boards ON geo_images.geo_imageID = boards.imageIDCode language: PHP (php)

Remarquez qu’il est essentiel, pour la commande UNION, que les deux sélections (SELECT) retournent le même nombre de colonnes et que ces colonnes soient dans le même ordre. En effet, UNION ajoute simplement le résultat du second SELECTà la suite du résultat du premier SELECT. Si ces deux résultats de requête n’avaient pas le même nombre de colonnes, vous auriez des colonnes dépourvues de nom à la fin de vos données. Si l’ordre des colonnes n’était pas le même dans les deux requêtes, les données dans chaque colonne seraient incohérentes:

Remarquez aussi la présence des mots clefs AS. Ils permettent de renommer une colonne “en passant”. Par exemple, nous renommons ref_imageID en imageID

ref_images.ref_imageID AS imageIDCode language: CSS (css)

et ref_imageID aussi en imageID

geo_images.geo_imageID AS imageIDCode language: CSS (css)

De cette manière, les deux colonnes sont réunies sous un seul nom.

Tâche 3: extraire les données nécessaires pour la visualisation d’un réseau et les importer dans Cytoscape

Extrayons maintenant les données qui vous permettront de visualiser votre réseau d’images. Comme nous l’avons vu en cours, un réseau est composé de nœuds (nodes) et de liens (edges).

Extraire la structure du réseau de la BDD et l’importer dans Cytoscape

  1. Extrayez la structure du réseau, c’est à dire, l’ensemble de la table des liens:
SELECT * FROM links
  1. Exportez-la sous forme d’un tableau CSV. Si vous sauvegardez ce fichier dans l’espace Google Drivepartagé, donnez lui un nom unique, faute de quoi, vous seriez en train d’écrire par-dessus le fichier de quelqu’un d’autre.
  1. Ouvrez Cytoscape.
  2. Importez la table CSV en glissant le fichier dans la zone “Drag network files here
  1. Identifiez les sources et les destinations du réseau
  1. Laissez telles quelles les colonnes décrivant la nature du lien
  1. Appuyez sur OK

Vous devriez voir ceci:

L’image paraît décevante, tant qu’on n’a pas visuellement agencé la structure du réseau. Nous avons vu en cours les divers agencements visuels (layouts). Choisissez Layout > Prefuse Force Directed Layout. Vous devriez voir ceci:

Pour l’heure, vous voyez bien la structure du réseau, mais vous ne voyez que les titres des images. Il faut à présent ajouter les images.

Extraire les données rattachées aux noeuds

  1. Dans la requête SQL suivante remplacez les deux occurences de file:///Users/ourednik/Documents/GoogleDrive/POLIPHILO_printemps_2019/01_RENDU/01_IMAGES/ref/00_ref_images par l’adresse effective du dossier où se trouvent vos images et exécutez-la.
SELECT ref_images.ref_imageID AS imageID, ref_images.category AS category, ref_images.titel AS titel, boards.boardID, 'file:///Users/ourednik/Documents/GoogleDrive/POLIPHILO_printemps_2019/01_RENDU/01_IMAGES/ref/00_ref_images/' || ref_imageID || ".jpg" AS imageURL
FROM ref_images
LEFT JOIN boards ON ref_images.ref_imageID = boards.imageID
UNION
SELECT geo_images.geo_imageID AS imageID, 'geoimage' AS category, geo_images.keyword_e1 AS titel, boards.boardID, 'file:///Users/ourednik/Documents/GoogleDrive/POLIPHILO_printemps_2019/01_RENDU/01_IMAGES/geo/00_geo_images/' || geo_imageID || ".jpg" AS imageURL
FROM geo_images
LEFT JOIN boards ON geo_images.geo_imageID = boards.imageIDCode language: PHP (php)
  1. Exportez le résultat de la requête dans un fichier csv, comme vous savez désormais le faire nommé. Nommez ce fichier, par exemple, “places_votre_nom.csv”.
  2. Dans Cytoscape, cliquez sur le bouton “Import data from table”.
  1. Choisissez votre fichier “places_votre_nom.csv” et cliquez Open.
  2. Dans le menu déroulant “Where to import table data“, assurez-vous que soit choisie l’option Into a network collection. Dans le menu déroulant “Import data as“, assurez-vous que soit choisie l’option Node table columns. Assurez-vous qu’un symbole de clef s’affiche à côté du nom de colonne “imageID”.
  1. Cliquez sur OK. La table des données importées devrait figurer dans la table des données associées aux nœuds de votre réseau:
  1. Dans l’onglet Control Panel :: Style :: Properties :: Paint :: Custom Paint 1 sélectionnez Image/Chart 1, ainsi que Image/Chart/Position 1
  1. Dans l’onglet Control Panel :: Style :: Properties sélectionnez Label position.
  2. Cliquez sur le carré marqué en gris foncé pour ci-dessous pour révéler les option de mapping Image/Chart. Dans le menu déroulant face à Column choisissez imageURL. Dans le menu déroulant face à Mapping Type choisissez Passthrough Mapping.
  1. Pour mieux voir les images, donner la couleur blanche aux remplissage des marqueurs de nœuds.

Vous allez voir une un graphique similaire à celui-ci:

Réseau Cytoscape avec images

Sans doute verrez-vous que certaines des images associées aux nœuds sont des points d’interrogation; d’autres sont des images de remplacement. Si vous ne retrouvez pas vos images sur le diagramme, cela signifie que vous n’avez pas travaillé avec suffisamment de rigueur. Par exemple:

  • ref_190224_bg_fontaine_03.jpg n’existe pas dans le dossier d’images POLIPHILO_printemps_2019/01_RENDU/01_IMAGES/ref/00_ref_images
  • ref_190224_gj_reseau_routes.jpg ≠ ref_190224_gj_reseau_route.jpg
  • Dans certains cas, imageIDsource ou imageIDDestination du tableau links ne possèdent simplement pas d’entrée correspondante dans les tableaux ref_images ou geo_images.
  • l’extension de votre fichier image n’est pas .jpg, mais .jpeg
  • etc.

Le logiciel ne vous jugera jamais; il est amoral; il fait tout simplement exactement ce que vous lui dites de faire, par exemple, chercher une image qui n’existe pas. Si vous souhaitez la voir, il faudra corriger le type de problèmes cités ci-haut dans la suite de votre travail.

Pour l’heure, ajoutons un aspect à la visualisation: donnez une couleur aux liens en fonction de leur type. Laissez vous guider par l’image suivante:

Modifiez à présent d’autres mappings entre les variables de votre BDD et les variables visuelles modifiables dans Cytoscape. Testez aussi d’autres agencements visuels (layouts). Essayez d’éliminer des nœuds qui vous dérangent (sélection, puis touche delete ou backspace de votre clavier).

Quand l’image obtenue vous convient, exportez-la: File>Export>Network to image.

À présent, si l’on vous demande d’interpréter l’image obtenue, que diriez-vous?

Tâche 4: Démarrez un serveur (ou baissez la sécurité de votre navigateur)

Les prochaines visualisations seront faites dans la fenêtre de votre navigateur avec HTML/JavaScript. Cette approche facilitera la publication en ligne de votre travail. Vous ne devrez pas programmer mais éditer un peu le code.

Tout d’abord, cependant, il faut faire en sorte que JavaScript s’exécute correctement sur votre machine locale.

En effet, il fut un temps où les navigateurs web comme Chrome ou Safari exécutaient des codes javascript indifféremment de leur emplacement. Aujourd’hui, les normes de sécurité ont augmenté. Un code javaScript n’est plus autorisé à lire des données locales (stockées sur votre machine). Pour y accéder il doit passer par un protocole http. Si vous utilisez Firefox, peut-être que le script marchera d’emblée.

Avec Firefox, essayez d’ouvrir le fichier poliphilo_alice_1.html

Après un moment d’attente de 10 secondes (le navigateur doit charger 60 images de haute résolution et les convertir au format dataURI intégrable dans un SVG) vous devriez voir ceci:

Si vous ne voyez rien de tel, vous devez démarrer un serveur. Ceci est moins difficile qu’il n’y paraît.

Sur MacOS

Il suffit d’ouvrir l’invite de commandes (_/Applications/Utilities/Terminal), vous rendre dans le dossier où se trouvent les fichiers portant le nom poliphilo*.html et démarrer le serveur avec cet emplacement pour racine.

La commande ls liste les fichiers dans le dossier actuel

ls

La commande cd permet de naviguer dans les dossiers. Par exemple:

cd /Users/ourednik/Documents/ALICE

Pour remonter d’un dossier, un utilise la commande:

cd ..

Naviguez ainsi jusque dans le dossier où se trouvent les fichiers portant le nom poliphilo*.html et démarrez le serveur avec la commande suivante:

python3 -m http.serverCode language: CSS (css)

Le terminal de votre MacOS répondra:

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...Code language: JavaScript (javascript)

S’il ne répond pas cela, essayez avec la commande python2suivante:

python -m SimpleHTTPServer 8000

Rendez-vous sur http://0.0.0.0:8000/ avec votre navigateur préféré.

Sur Linux

En tant qu’utilisateur de Linux, vous savez où se situe l’invite de commande (le “Terminal”). Utilisez les mêmes commandes que celles des instructions pour MacOS pour démarrer un mini-serveur python.

Sur Windows

Sur Windows, ce sera plus dur. Des solutions sont proposées sur GitHub:

J’ai besoin d’une autre solution

Si vous n’y arrivez vraiment pas, vous pouvez baisser le niveau de sécurité de votre navigateur.

NB: Si vous recourez à cette option, songez à rétablir les paramètres d’origine à la fin du travail et surtout avant d’aller naviguer partout sur le web ! Faute de quoi, vous vous exposez à l’exploitation de votre ordinateur par un code malveillant!

Tâche 5. Exportez les données pour voir les images dans un espace signifiant

Nous allons désormais quitter l’espace réseau pour analyser les images dans un espace signifiant, notion vue au début du cours.

Positionner les images sur les coordonnées cartésiennes

  1. Sélectionnez les données dont nous aurons besoin:
SELECT  
	ref_imageID AS imageID, 
	'01_RENDU/01_IMAGES/ref/00_ref_images/' || ref_imageID || ".jpg" AS imageURL, 
	*
FROM ref_images
INNER JOIN infolder_ref_images on ref_imageID = Filename
WHERE creationdate / 100 > 10Code language: PHP (php)
  1. Exportez-les en format CSV. Nommez le fichier “signifiant_votre_nom.csv”
  2. Déposez le fichier dans le dossier POLIPHILO_printemps_2019/htmldata.
  3. Faites une copie du fichier poliphilo_alice_espace_signifiant.html en lui ajoutant un suffixe personnel, par exemple en le nommant poliphilo_alice_espace_signifiant_votre_nom.html
  4. ouvrez le fichier poliphilo_alice_espace_signifiant_votre_nom.html avec Visual Studio Code retrouvez les lignes ci-dessous et vérifier si la configuration correspond :
/////////////////////////////
// Changez les variables x et y ici
var variable_axe_x = "creationdate";
var variable_axe_y = "category";
var y_ordinale = true; // l'échelle y est-elle ordinale?
var y_flip = false; // inversez l'échelle des y?
var custom_dimensions = false; // prendre en compte width & height dans le csv?
var show_axes = true; // montrer les axes?

///////////////
// Changez la source des données csv deux lignes en dessous
Promise.all([
    d3.csv("htmldata/signifiant_votre_nom.csv"),
])Code language: JavaScript (javascript)
  1. Ouvrez le fichier poliphilo_alice_espace_signifiant_votre_nom.html dans un navigateur web.

Vous devriez voir ceci:

Exportez cette image avec le bouton “Save Board SVG” et vérifiez que le fichier généré s’ouvre dans Adobe Illustrator ou dans Inkscape.

Reconstruire un panneau

Pour reconstruire un panneau, le procédé est identique.

  1. Sélectionnez les données dont nous aurons besoin:
SELECT  
	*,
	pBotR_X - pTopL_X AS 'width',
	pTopL_Y - pBotR_Y AS 'height',
	CASE
		WHEN imageID LIKE ('ref%') THEN '01_RENDU/01_IMAGES/ref/00_ref_images/' || imageID || ".jpg"
		ELSE '01_RENDU/01_IMAGES/geo/00_geo_images/' || imageID || ".jpg"
	END imageURL
FROM boards
WHERE boardID = "D1"Code language: PHP (php)

Remarquez la constellation de mots clefs CASEWHENELSE et END. Cette construction vous permet de retourner une valeur différente en fonction d’une condition (ici imageID commence-t-ellle par “ref” : imageID LIKE ('ref%')). Nous en avons besoin pour indiquer dans quel sous-dossier (ref/00_ref_images/ ou geo/00_geo_images/) se trouvent les images. En exécutant cette requête vous devriez voir ceci:

Remarquez la présence de valeurs calculées “en passant” pBotR_X - pTopL_X AS 'width'. La requête calcule la taille (widthheight) des images à partir de leurs coordonnées. Certains résultats de cette requête sont étranges, hélas, donnant des dimensions négatives. Toutes les co-ordonnées ont-elles été bien enregistrées? À vous de le vérifier et de corriger vos données par la suite. Pour l’heure, contentons-nous de filter les données non-plausibles en ajoutant deux conditions: width > 0 et (ANDheight > 0à la clause WHERE.

SELECT  
	*,
	pBotR_X - pTopL_X AS 'width',
	pTopL_Y - pBotR_Y AS 'height',
	CASE
		WHEN imageID LIKE ('ref%') THEN '01_RENDU/01_IMAGES/ref/00_ref_images/' || imageID || ".jpg"
		ELSE '01_RENDU/01_IMAGES/geo/00_geo_images/' || imageID || ".jpg"
	END imageURL
FROM boards
WHERE boardID = "D1" AND width > 0 AND height > 0Code language: PHP (php)
  1. Exportez le résultat de la requête en format CSV. Nommez le fichier “board01_votre_nom.csv”
  2. Déposez le fichier dans le dossier POLIPHILO_printemps_2019/htmldata.
  3. ouvrez le fichier poliphilo_alice_espace_signifiant_votre_nom.htmlavec Visual Studio Code et modifiez la source des données comme suit:
/////////////////////////////
// Changez les variables x et y ici
var variable_axe_x = "pTopL_X";
var variable_axe_y = "pTopL_Y";
var y_ordinale = true; // l'échelle y est-elle ordinale?
var y_flip = false; // inversez l'échelle des y?
var custom_dimensions = true; // prendre en compte width & height dans le csv?
var show_axes = false; // montrer les axes?

///////////////
// Changez la source des données csv deux lignes en dessous
Promise.all([
    d3.csv("htmldata/boardD1_votre_nom.csv"),
])Code language: JavaScript (javascript)
  1. ouvrez le fichier poliphilo_alice_espace_signifiant.htmlavec un navigateur web.

Vous devriez voir ceci:

Exportez cette image avec le bouton “Save Board SVG” et vérifiez que le fichier généré s’ouvre dans Adobe Illustrator ou dans Inkscape.

L’image correspond-elle à votre panneau? Avez-vous bien enregistré toutes les coordonnées? Tous les fichiers référencés dans votre base de données existent-ils?

Répétez le processus ci-haut en remplaçant “D1” par un autre numéro de panneau.

Tâche 6. Exportez les données pour voir les images dans un espace topographique

À présent, nous allons analyser les images dans un espace topographique, notion vue au début du cours.

  1. Sélectionnez les données dont nous aurons besoin:
SELECT
	geo_images.*,
	boards.boardID,
	'01_RENDU/01_IMAGES/geo/00_geo_images/' || geo_imageID || ".jpg" AS imageURL
FROM geo_images
LEFT JOIN boards ON geo_images.geo_imageID = boards.imageIDCode language: PHP (php)
  1. Exportez-les en format CSV. Nommez le fichier “topographique.csv”
  2. Déposez le fichier dans le dossier POLIPHILO_printemps_2019/htmldata.
  3. Ouvrez le fichier POLIPHILO_printemps_2019/poliphilo_alice_espace_topographique.html
  4. Explorez la carte en cliquant sur diverses POIs (points of interest) et analysez le contenu global de la carte.

Modifiez la requête SQL initiale en ajoutant, par exemple, une clause WHERE pour analyser une sous-partie de votre banque d’images.

Corriger vos données et recommencer ce workshop depuis la tâche 3

Nous voilà arrivés au bout. Corrigez à présent vos noms d’images et votre base de données pour que toutes les images puissent s’afficher dans l’espace réseau, l’espace signifiant et l’espace topographique.

Pour éditer la base de données, il suffit de choisir l’onglet Parcourir les données dans DB Browser, de cliquer sur un champ et de le modifier dans la fenêtre de droite

Notez que, le fichier étant partagé, vos modifications auront un impact sur le travail de tout le monde. Mettez-vous d’accord parmi vous qui mène ces modifications.