Visualiser tous les livres du monde dans l’espace ISBN
(phiresky.github.io)- Pour explorer sur un seul écran les données de plus de 100 millions de livres traitées par Anna’s Archive, il faut transformer l’espace limité d’identifiants qu’est l’ISBN en carte
- Si l’on exclut les préfixes
978-/979-et le dernier chiffre de contrôle, l’ISBN13 forme un espace unidimensionnel d’environ 2 milliards d’emplacements, où les plages de pays et d’éditeurs sont attribuées par préfixe - Une disposition simple ligne par ligne ou une courbe de Hilbert peuvent rendre la structure de l’ISBN difficile à voir ; la visualisation utilise donc une Bookshelf-Curve, qui transpose les chiffres décimaux en coordonnées 2D
- Les tuiles de la carte sont fournies sous forme de fichiers statiques PNG et JSON, et des shaders WebGL/GLSL gèrent instantanément le rendu et le filtrage, comme l’année de publication, le taux de possession, la comparaison de jeux de données ou la mise en évidence des éditeurs
- Le frontend statique est implémenté avec ThreeJS, React, MobX et react-threejs-fiber ; le rendu massif de texte et l’optimisation des performances de zoom et de déplacement déterminent l’utilisabilité réelle
Pourquoi prendre l’espace ISBN comme objet de visualisation
- Les bibliothèques rassemblent depuis longtemps le savoir de l’humanité, et à l’ère numérique il peut devenir possible de collecter de manière exhaustive les œuvres répondant à certains critères
- Anna’s Archive, l’une des bibliothèques fantômes, avait besoin d’une visualisation permettant d’explorer d’un seul coup plus de 100 millions de livres
- Les données ciblées incluent le titre, l’auteur, le pays, l’éditeur, la période de publication, le nombre de bibliothèques qui possèdent l’ouvrage et la disponibilité numérique
- La visualisation interactive prend en charge le choix du jeu de données, la recherche de livres individuels, le filtrage par année de publication et des visualisations composées basées sur des shaders personnalisés
- Au niveau de zoom maximal, l’affichage bascule vers une représentation où chaque livre semble rangé sur une étagère
Structure de l’ISBN
- L’ISBN13 est un numéro à 13 chiffres attribué à presque tous les livres publiés
- Aujourd’hui, les trois premiers chiffres de l’ISBN13 sont fixés à
978-ou979-, et le dernier chiffre est une somme de contrôle - L’espace ISBN13 réel peut donc être vu comme environ 2 milliards d’emplacements
- Les préfixes
978-et979-existent parce que l’ISBN13 est un sous-ensemble de l’European Article Number ; ce préfixe fixe est appelé Bookland - Les grands blocs ISBN sont attribués par l’International ISBN Agency à des organisations internationales, puis chaque pays subdivise son bloc par éditeur
- Les blocs ISBN sont toujours attribués par préfixe
978-4est attribué au Japon- Le Japon attribue
978-4-312à un éditeur - Cet éditeur peut attribuer des éléments dans la plage
000000-99999pour créer des ISBN comme978-4-312-99999-X
- Plus le préfixe d’un pays est long, moins il reste de livres attribuables à l’intérieur
- Le Japon dispose d’un espace de 100 millions d’ISBN
- Singapour commence par le préfixe
978-9971-et ne peut avoir que 100 000 ISBN
Déplier l’ISBN unidimensionnel en deux dimensions
- Une fois retirés les préfixes
978-/979-et la somme de contrôle, l’ISBN devient une valeur décimale unidimensionnelle comprise entre 0 et 2 milliards - La méthode la plus simple consiste à remplir les pixels ligne par ligne depuis le haut, mais les petites zones s’étirent alors horizontalement, ce qui rend la structure de l’ISBN difficile à lire
- Une courbe de Hilbert rend les petites zones plus proches du carré, mais peut introduire des artefacts de structure spatiale qui n’existent pas dans les données
- Pour éviter d’ajouter une structure absente des données, cette visualisation utilise une Bookshelf-Curve fondée sur la nature décimale de l’ISBN
Bookshelf-Curve
- La Bookshelf-Curve place les chiffres
0-9de la première position décimale côte à côte, puis les chiffres0-9de la position suivante de haut en bas, et répète ce procédé récursivement - Pour conserver le rapport des rectangles entre deux niveaux, le ratio largeur/hauteur de chaque bloc devient
√10, soit environ 3,16:1 - Cette structure ressemble au concept de rapport récursif du papier A4, mais au lieu de diviser par deux, elle divise en 10 intervalles
- La transformation de coordonnées est simple : elle utilise un chiffre sur deux de l’ISBN comme coordonnées
- Le code d’implémentation atteint 50 lignes à cause d’une tentative de généralisation, mais le principe reste assez facile à comprendre pour suivre à la main l’emplacement d’un ISBN donné
Tuiles de carte et encodage des données
- Une image de tuile est générée pour chaque préfixe ISBN
- La taille cible des tuiles était d’environ
100kB, ce qui a donné des tuiles de2000 × 633pixels - Les informations stockées dans les pixels varient selon le jeu de données
- Le jeu de données des années de publication stocke la valeur après soustraction de
1800dans une plage 8 bits - Le canal rouge contient l’année de publication moyenne des livres présents dans ce pixel
- Le canal bleu contient la proportion de livres existants
- Par exemple, si 50 % des livres existent, la valeur du canal bleu est
127/255
- Le jeu de données des années de publication stocke la valeur après soustraction de
- Au niveau de zoom maximal, 1 livre est mappé à 1 pixel pour garantir la précision
Rendu basé sur des shaders GLSL
- Au départ, les données RGB étaient stockées directement dans les tuiles, mais pour gagner en flexibilité, des données plus abstraites sont stockées et le rendu réel est effectué sur le GPU par un fragment shader GLSL
- Cette approche permet de choisir une palette après coup, d’appliquer instantanément des transformations et filtres arbitraires, ou de combiner plusieurs jeux de données à la volée
- Les données d’année de publication stockent la plage
1800-2055, mais 95 % des données se trouvent dans1985-2024, si bien que le shader peut les compresser dans cet intervalle pour l’affichage - La fonction
heatmapColor(float)convertit une valeur0-1vers l’échelle de couleurs choisie par l’utilisateur - La syntaxe
$dataset_xn’est pas une syntaxe GLSL native, mais une simple syntaxe de template basée sur des expressions régulières destinée à ne charger que les images effectivement lues par le shader - Dans l’option ⚙️ Advanced de la visualisation, il est possible de modifier directement le shader, et les changements sont appliqués en temps réel
- La signification des pixels de chaque jeu de données est documentée dans le README
Donner un aspect d’étagère lors du zoom
- Dans la vue entièrement zoomée, chaque pixel reçoit un style qui le fait ressembler à un livre
- Chaque livre reçoit une largeur, une hauteur et un motif aléatoires
- Ce n’est pas parfaitement fidèle à l’apparence d’un vrai livre, mais cela rend l’écran au zoom maximal plus vivant
- Tout ce styling est implémenté dans le shader
- Comme il fallait obtenir les mêmes résultats de génération aléatoire en GLSL et en JavaScript, la partie qui calcule la hauteur des livres pour aligner les limites du texte a été délicate
- En passant la valeur de zoom actuelle comme uniform et en effectuant un fondu entre deux niveaux de zoom, le style d’étagère peut apparaître en douceur
Texte, structure arborescente et performances
- Comme les tuiles d’image, le texte est rendu sous forme de structure hiérarchique selon le niveau de zoom et le culling du frustum de vue
- L’implémentation utilise react-threejs-fiber
- Lorsque la vue se déplace, React ajoute récursivement des éléments à la scène et construit, pour chaque préfixe, un Plane, du texte HTML et des nœuds de préfixes enfants
- Le rendu d’une grande quantité de texte a d’abord posé d’importants problèmes de performance
- La meilleure approche consistait à placer le HTML dans un
<foreignObject />SVG, à le rendre ensuite dans un canvas avecdrawImage, puis à le charger comme texture - Cette méthode fonctionnait, mais introduisait à chaque fois un délai synchrone de 20 ms pendant le rendu
- Comme il n’est pas possible de dessiner le SVG dans un WebWorker, il était difficile de déplacer ce travail vers un WebWorker
- Les vrais problèmes de performance ont été en grande partie résolus en réduisant le nombre d’éléments HTML, en limitant le contenu DOM ajouté par frame et surtout en supprimant la pile de filtres CSS
text-shadow
Codes-barres et plages d’éditeurs
- Au zoom maximal, chaque livre affiche un code-barres
- Le code-barres a été ajouté pour renforcer l’idée que les livres sont triés dans l’ordre ISBN
- Au lieu d’une bibliothèque de rendu de codes-barres, le projet utilise la police TTF Libre Barcode, qui rend des nombres à 13 chiffres en code-barres et calcule aussi le chiffre de contrôle
- Grâce aux optimisations de rendu de texte du système d’exploitation, cette méthode était pratique et performante
- Chaque groupe possède généralement une grande plage au niveau du pays, et les éditeurs disposent de plages plus petites à l’intérieur
- Une couleur aléatoire unique est attribuée à chaque groupe et à chaque éditeur
- Lorsqu’un éditeur possède plusieurs plages, la même couleur est utilisée
- Pour mettre en évidence simultanément toutes les plages, un identifiant unique est attribué à chaque éditeur et stocké dans les composantes RGB
- La couleur des éditeurs laisse encore quelques points insatisfaisants
- Les couleurs des éditeurs entrent en conflit avec l’échelle de couleurs de la heatmap
- Les plages de pays sont difficiles à distinguer
Déplacement par recherche et trajectoires de vol
- Lorsqu’on recherche un livre ou qu’on clique sur la mini-carte, la vue vole jusqu’à l’emplacement correspondant
- Calculer une trajectoire de vol agréable à regarder s’est révélé plus difficile que prévu
- L’ajustement parabolique donnait des résultats ordinaires, puis une approche utilisant un espace de transformation séparé a été essayée
- Le résultat final n’est pas parfait et paraît quelque peu surconçu avec environ 500 lignes de code, mais fonctionne mieux que l’approche initiale
Architecture et pipeline de traitement
- Aucun backend n’est nécessaire
- Les tuiles d’image sont stockées en PNG
- L’arbre de données est stocké en JSON
- Il suffit de placer le HTML, le JS, le CSS, les PNG et les JSON sur un hébergeur de fichiers statiques comme GitHub Pages
- Le frontend utilise ThreeJS, React et MobX
- Cette combinaison était pratique pour créer des scènes 2D/3D réactives, déclaratives et accélérées par GPU à partir de composants réutilisables
- Les scripts de traitement sont principalement écrits en JS et produisent directement du JSON et du PNG
- Certains scripts devaient lire des fichiers sources de 250 Go et produire du SQLite ; ils ont donc été écrits en Rust
Résultat et code
- Le résultat est une méthode flexible pour visualiser les livres publiés ayant reçu un ISBN
- Ce projet a été rendu possible parce que l’ISBN a été conçu comme un espace d’identifiants juste assez petit
- Faire la même chose avec des UUID aurait surtout produit un immense espace vide
- Le code source est publié dans isbn-visualization
1 commentaires
Avis sur Hacker News
Au lancement d’Amazon, c’était exactement le genre de chose que je voulais faire, mais en utilisant la triple classification de la Library of Congress au lieu de l’ISBN
Au final, nos fournisseurs de données, Baker & Taylor et Books In Print, avaient aplati cette triple classification en une seule chaîne, ce qui rendait impossible d’en retrouver les limites de manière fiable, et nous avons dû abandonner avant même de vraiment commencer
Mettre en œuvre ce type d’exploration « en vol » sur le web version 1994-1995 n’aurait certainement pas été facile non plus ; c’est un très beau travail
J’ai pas mal étudié la LoC Classification et les LoC Subject Headings, et je trouve dommage qu’aucune des deux ne soit librement disponible dans un format utile et lisible par machine. Avec les PDF, on peut bricoler un peu
En particulier, la section de la Classification consacrée au droit des États présentait une densité de classement très inégale selon les États : de mémoire, NY et CA étaient de loin les plus complexes, PA arrivait assez loin en troisième position, et beaucoup d’États « flyover » étaient presque ridiculement simples et similaires entre eux. Cela semble refléter la complexité des lois codifiées, des réglementations et de la jurisprudence de chaque État
Autre fait historique intéressant : le système de classification et les grandes divisions alphabétiques semblent venir directement de la bibliothèque personnelle de Thomas Jefferson, à l’origine de la LoC
Si cela vous intéresse, les rapports annuels soumis au Congrès par le Librarian of Congress, disponibles sur Hathi Trust, permettent de suivre une grande partie de l’histoire du développement et de l’extension de la Classification
Classification : <https://www.loc.gov/catdir/cpso/lcco/>
Subject headings : <https://id.loc.gov/authorities/subjects.html>
Rapports annuels — récents : <https://www.loc.gov/about/reports-and-budgets/annual-reports...> / archives historiques jusqu’à ~1866 : <https://catalog.hathitrust.org/Record/000072049>
C’était l’une des entreprises les plus en retard techniquement avec lesquelles j’ai travaillé, et jusqu’à la fermeture de notre compte début 2020, les bons de commande et les règlements se faisaient encore sur papier, en PDF et par e-mail. Il me semble même qu’à une époque ils nous faisaient envoyer des documents par fax
Comme il n’est pas rare que des ISBN soient attribués en double à des livres différents [0], l’expression « tous les livres de l’espace ISBN » est peut-être exagérée
Il existe aussi des livres avec un ISBN invalide, dont le chiffre de contrôle ne correspond pas au reste de l’ISBN. Si corriger le chiffre de contrôle le fait correspondre à un autre livre, il se retrouve alors en dehors de l’espace ISBN supposé par l’article de blog
[0] https://scis.edublogs.org/2017/09/28/the-dreaded-case-of-dup...
En regardant les ISBN les plus bas connus d’éditeurs tchèques, je suis tombé sur une couleur différente : https://books.google.cz/books?vid=ISBN9788000000015&redir_es... ne semble pas être un ISBN valide :-) Reste à savoir si le livre contient vraiment cet ISBN manifestement faux, ou s’il s’agit d’une erreur dans les données de Google Books
Présentation impressionnante
Cela dit, cet écran ne reflète pas le catalogue ISBN complet, mais seulement les contenus détenus par Anna’s Archive. En raison des biais de collecte d’Anna, on observe un biais vers certaines plages linguistiques, et les zones en noir correspondent à des éléments absents de l’archive
La base de métadonnées provient de plusieurs sources et, à ma connaissance, elle est assez complète. Les zones noires sont probablement, pour la plupart, des zones sans livres attribués
C’est vraiment superbe, un étonnant projet passion et une excellente ressource
En zoomant, on voit les titres et les codes-barres, et au survol de la souris apparaissent la couverture et les détails. Il y a presque tout ce qu’on pourrait souhaiter
Comme idée d’amélioration, ce serait bien d’avoir une case à cocher pour masquer le panneau blanc flottant en haut à gauche et les éléments en haut à droite. J’aime m’« immerger » dans ce type de visualisation, et ces éléments flottants m’en sortent un peu, ce qui réduit légèrement le plaisir et la fonctionnalité
C’est exactement le cas d’usage auquel convenait Microsoft Silverlight PivotViewer, une excellente interface web utilisée en neuro-imagerie avant que Microsoft ne l’abandonne
Il existe une présentation TED impressionnante où Gary W. Flake en montre l’utilisation
https://m.youtube.com/watch?v=LT_x9s67yWA
Il y a aussi un article IEEE de 2011. C’est vraiment dommage que ce ne soit pas devenu un standard du web
https://www.dropbox.com/scl/fi/bl8zkjs3y47q3377hh3ya/Yan_Wil...
Très belle visualisation
Il y a d’autres contributions encore plus chouettes ici : https://software.annas-archive.li/AnnaArchivist/annas-archiv...
Mon travail est disponible sur https://isbnviz.pages.dev
Quand on zoome, cela ressemble à des étagères de livres. Vraiment superbe
Excellent. On dirait une version réelle de la Library of Babel : https://libraryofbabel.info/
Parmi toutes les absurdités autour de la VR, je pourrais presque payer pour une bibliothèque infinie ou un musée infini dans le monde réel
Le projet aurait été bien plus intéressant s’il donnait accès à tous les textes téléchargeables proposés légalement. Par exemple sous forme d’interface pour ce genre de site :
https://onlinebooks.library.upenn.edu/
La présentation dans son format actuel m’a paru un peu écrasante
Il m’a fallu un moment pour comprendre que la zone des préréglages en haut à gauche donnait en fait accès à des axes de visualisation de données supplémentaires, comme l’inclusion ou non d’AA, la rareté, ou l’inclusion ou non de Google Books. Cela dit, la visualisation et la profondeur des données sont très riches
J’ai aussi apprécié https://archive.anarchy.cool/blog/all-isbns.html#visualizing, qui montre l’aspect des clusters régionaux
Le préréglage par année était intéressant en soi pour observer l’activité éditoriale par région. La Poland est très active récemment, tandis que la Norway semble relativement calme. La China semble augmenter depuis autour de 2005 et avoir énormément grossi au cours des dix dernières années
Il y a aussi quelque chose d’étrange aux United States. Je n’en avais jamais entendu parler, mais Blackstone Audio, Blurb Inc. et Draft2Digital ont publié un nombre énorme d’ISBN
Une vue un peu plus minimaliste (moins de couleurs, et un seul niveau de texte affiché à la fois) est disponible ici :
https://phiresky.github.io/isbn-visualization/?dataset=all&g...
Il serait sans doute possible d’ajuster encore, par exemple en masquant certains textes comme la partie N publishers, ou en réduisant les informations au survol
Les trajectoires de vol peuvent se modéliser de manière assez raisonnable comme un mouvement sur le demi-plan supérieur hyperbolique. On peut prendre x comme position sur le chemin linéaire entre les points d’extrémité, et y comme longueur d’un côté du viewport
J’ai envisagé deux métriques qui finissent par coïncider. La première suppose une carte hiérarchique en tuiles et cherche à minimiser le nombre de tuiles chargées. Si y est la longueur d’un côté du viewport, le coût d’un déplacement horizontal de x est de x/y tuiles, et un zoom de y_0 à y_1 charge abs(log_2(y_1/y_0)) tuiles, ce qui correspond à ds = dy/y. En combinant les deux, on obtient ds^2 = (dx^2 + dy^2)/y^2, exactement la métrique du demi-plan supérieur
Une autre façon de voir les choses est de minimiser, en un certain sens, le « flux optique » du viewport. On retrouve là aussi la même métrique, à un facteur d’échelle près. Si l’on panote de x sans zoomer, tout se déplace de x/y, c’est-à-dire d’une fraction du viewport. Si l’on zoome d’un facteur k, un pixel en (u,v) va en (ku,kv), donc le déplacement est (u,v)(k-1). Quand la longueur d’un côté passe de y à y+dy, cela donne (u,v)dy/y ; selon la façon dont on moyenne le déplacement, on obtient donc une constante fois dy/y
La géodésique souhaitée est alors un horocycle, un cercle centré sur y=0, mais il faut un peu de travail pour calculer le mouvement le long de la courbe. Si l’on prend un arc de θ_0 à θ_1, le temps total s’obtient en intégrant dtheta/y = dθ/sin(θ) ; pour le faire exactement, il faut donc inverser t = ln(csc(θ)-cot(θ)). Je pensais qu’il vaudrait mieux l’approximer, mais Mathematica indique θ = atan2(1-2e^(2t), 2e^t), ce qui n’est pas si mal
Par comparaison avec la logique de “blub space”, sa métrique effective semble être ds^2 = dz^2 + (z+1)^2 dx^2. C’est un système de coordonnées polaires où z=1/y représente le niveau de zoom ; en utilisant dz=dy/y^2, on obtient ds^2 = dy^2/y^4 + dx^2*(1/y^2 + ...). Autrement dit, l’implémentation existante semble passer beaucoup plus de temps à panoter à fort niveau de zoom que le modèle hyperbolique. Le coût pour passer de 4× à 2× est le double de celui pour passer de 2× à 1×, alors que visuellement c’est la même chose
Leur zoom n’est pas un facteur d’échelle, mais correspond à mon “y”, donc la métrique devient ds^2 = dy^2 + (C-y)^2 dx^2, où C est légèrement supérieur au niveau de zoom maximal. Il existe aussi un traitement spécial pour les cas où cette courbe voudrait dézoomer plus loin
Si l’on normalise de sorte que, en état complètement dézoomé (zoom=1), le coût pour panoter jusqu’au bout soit le même, alors à très fort zoom le coût du panning est presque plat, tandis qu’à un niveau de zoom relativement moindre il est plus élevé que dans le modèle hyperbolique. Cela semble contribuer au fait que, sur de courtes distances, le viewport donne l’impression de se déplacer très vite, tandis que sur de longues distances il semble dézoomer presque jusqu’au bout. Comme les niveaux de zoom intermédiaires sont défavorisés, il vaut mieux quasiment aller jusqu’au bout