Le présent document présente les résultats ainsi que le processus technique et intellectuel qui a abouti à l'organisation de l'atelier du lors de la conférence annuelle 2022 de Groupe de recherche matérialités comparatives : Médias, littérature et théorie | Comparative Materialities: Media, Literature, Theory Research Group au congrès annuel 2022 de l'Association Canadienne de Littérature Comparée (ACLC). Antoine Fauchié et Marcello Vitali-Rosati de la Chaire de Recherche du Canada sur les écritures numériques ont également participé à l'organisation de l'évènement (voir la page Credits qui liste toutes les participations).
Les lignes qui suivent décrivent ma contribution à cet événement et expliquent le code que j'ai conçu pour l'atelier sous la forme d'une code review.
L'atelier Graph our Research est la continuation de l'atelier d'écriture collaborative présenté lors de la conférence annuelle de l'ACLC 2021 : il reprend le même cadre que celui élaboré lors de cette conférence et s'inspire des idées qui ont émergé depuis lors. Au cours du premier atelier, les participant·e·s ont été invité·e·s à écrire en collaboration sur le bloc-notes et à répondre aux questions ensemble. Cette expérience d'une groupe collectif d'écriture composé à partir de la communauté de l'ACLC nous a incités à explorer une pratique d'écriture plus technique. L'atelier visait à concevoir un espace permettant à la communauté d'ACLC de coder de manière collaborative et, conformément au thème du Groupe de recherche matérialités comparatives : Médias, littérature et théorie | Comparative Materialities: Media, Literature, Theory Research Group, de jouer avec les données de recherche1.
Une répétition de l'atelier a été organisée quelques mois avant la conférence de l'ACLC par la Chaire de recherche du Canada sur les écritures numériques : elle nous a permis d'identifier le principal défi de notre projet.La problématique principale de l'atelier a été de trouver un outil pour l'édition et la visualisation du code qui permette une collaboration synchrone (pour voir en même temps le résultat de son code et celui des autres). Si des solutions existent pour coder de manière collaborative (via l'installation d'un serveur), nous souhaitions éviter autant que possible une installation complexe pour les participant·e·s. Nous avons donc élaboré une solution alternative pour l'atelier afin de contourner cette difficulté.
Cela nous a conduit non seulement à concevoir le site web Graph Ta Recherche / Graph our Research et à le structurer non seulement comme un espace commun pour organiser les informations nécessaires à l'atelier, mais également comme un outil : Graph Ta Recherche (GTR) peut être utilisé par d'autres communautés de chercheur·e·s au-delà de l'atelier.
Les données avec lesquelles jouer devaient représenter une utilité claire pour la communauté des chercheur·e·s, et il était préférable qu'elles soient déjà organisées dans les environnements numériques. Les références bibliographiques réunissaient ces conditions : de nombreux outils en ligne tels que Zotero permettent de les organiser, de les éditer, de les exporter et même de les partager. Par conséquent, le corpus de l'atelier est une bibliothèque ouverte éditée dans l'outil de gestion bibliographique Zotero.
Dans le cadre de l'atelier, les références ne sont pas seulement des données avec lesquelles jouer, mais elles représentent également les dépositaires de notre identité en tant que chercheur·e·s individuels et en tant que communauté de recherche. Parce qu'elles intitulent nos recherches ou ancrent notre réflexion dans des courants de pensée et relient nos recherches à d'autres recherches, il est essentiel de structurer sémantiquement ces données textuelles : il ne s'agit plus d'éditer les références comme du texte brut avec des informations (titre, auteur, édition, date, etc.) indifférenciées au-delà du style du traitement de texte ; il s'agit de les organiser sémantiquement, de les encoder pour donner à chaque type d'information sa valeur dans le contexte de la référence.
Cette conception technique des références des chercheur·e·s est associée à la prise en compte du média comme une composante active de notre savoir : comme le souligne les formules “Media is the message” (McLuhan 2010), et “Matter matters” (Barad 2007), l'environnement technique “détermine” (Kittler 1999) la fabrique de nos références et donc de notre communauté de recherche. Cette idée constitue le fil rouge de l'atelier et de notre groupe de recherche.
Pour l'atelier, nous avons créer une bibliothèque Zotero conçue comme un espace collaboratif pour l'interaction et la discussion à partir des références qu'elle contient ; c'est à partir de ce corpus que seront représentés les liens entre les travaux de recherche, entre les chercheur·e·s et entre d'autres types de données. Pour visualiser les liens qui nous lient à travers nos recherches, la structure sémantique des informations composant les références était essentielle. Si l'atelier a impliqué pour certain·e·s participant·e·s un apprentissage (tant théorique que pratique) important, la démarche de demander aux chercheur·e·s d'établir eux-mêmes les liens entre leurs données de recherche est un choix politique. En effet, de cette façon, les chercheur·e·s sont au cœur des schémas de pensée qui structurent leurs recherches. De plus, l'implémentation technique de leurs besoins ou de leurs intérêts de recherche n'est ainsi pas laissée aux mains d'entreprises privées étrangères au domaine de la recherche académique.
Au-delà de l'usage personnel, le dispositif d'une bibliothèque de références peut être abordé comme un espace collectif de connaissances, et ses outils comme faisant partie d'une connaissance collective. Pour souligner cette dimension collective dans la gestion des références, une bibliothèque publique Zotero, CCLA-Graph, a été créée spécifiquement pour l'atelier et un protocole a été mis à disposition pour aider les participant·e·s à éditer les références.
L'atelier a été structuré comme suit :
À la suite de cette présentation, plusieurs sessions (3 d'environ 15 minutes chacune) ont permis aux chercheur·e·s de participer de manière collaborative à la bibliothèque et de produire les graphs tout en observant les modifications dues à l'enrichissement de la bibliothèque. Les résultats de l'atelier et notamment l'historique des graphs a été documenté dans la page Workshop.
Outre la part collaborative de l'atelier sur Zotero, nous avons dû imaginer une méthodologie pour produire des visualisations à partir des références de la bibliothèque afin de faire apparaître les liens qui peuvent être établis entre les chercheur·e·s, entre les références, entre leurs thèmes. Pour ce faire, le langage de programmation Python nous a semblé être le meilleur choix du fait de sa syntaxe simple et de la lisibilité de son code. Le script développé en Python pour produire des graphs à partir de la collection Zotero a été mis en place dans un Jupyter Notebook (plateformes web interactives permettant de créer des notebooks qui pour combiner notamment du code en direct et des visualisations de celui-ci) et les principales étapes sont disponibles dans la page Documentation du site.
Je présente ici en détail le processus de réflexion théorique et les étapes techniques du script qui a permis aux utilisateur·trice·s de jouer avec les données et qui a ensuite permis d'automatiser la production de graphs sous la forme d'un outil.
La première étape consiste à aller chercher les informations contenues dans notre bibliographie en utilisant la librairie pyzotero (un wrapper de l'API Zotero (v3)) et notamment le module zotero.
.# First step: to fetch the information contained in our bibliography with pyzotero (a wrapper of the Zotero API (v3))
from pyzotero import zotero
# I write informations of the collection I want to fetch (library_id, library_type, api_key)
bibliography = zotero.Zotero(4592469, 'group', 'fCmiRRXSChwNGKoiw8lYlTKe')
# In this bibliography, I assign the variable *items* and give the parameter "limit=None" to display all the references
items = bibliography.top(limit=None)
Mon script va alors pouvoir accéder à la bibliothèque que je lui indiquerai et récupérer les données des références. Pour cibler une bibliographie en particulier, je lui fournis les informations nécessaires que sont les identifiants de la bibliographie (library_id ou l'identifiant de la bibliothèque, library_type qui dans ce cas est "group"
, api_key qui est la clef que je génère à partir de mon profil utilisatrice Zotero lorsque j'accède à la bibliothèque).
Je lui demande ensuite d'aller chercher des éléments (ou des références individuelles) dans ma bibliographie, en ne lui imposant aucune limite quant au nombre de références.
La deuxième étape implique de réorganiser et de structurer les données afin de pouvoir jouer facilement avec elles.
# Second step: to structure data
# I define my Reference class (capitalized because it's an object)
class Reference:
# I define the signature of my object (the parameters needed to instantiate it, here the entry variable)
def __init__(self, entry):
# I define an attribute (entry which will take the value of the variable entry)
self.entry = entry
# I define each attribute by retrieving the value of their corresponding keys
# I assign them default values and modify the value if necessary
# for the title value, I retrieve the value of the "title" key from "data"
# then I replace the ":" in titles with "-" because the ":" make noise
self.title = entry.get("data", {}).get("title", "No title").replace(":", "-")
# for the author value, I get the value of the keys "firstName" and "lastName" from "data"
# to reconstitute the names of the authors in a list
self.author = [f"{t.get('firstName', 'No firstName')} {t.get('lastName', 'No lastName')}" for t in entry.get("data", {}).get("creators", [])]
# for the date value, I get the value of the "date" key from "data"
self.date = entry.get("data", {}).get("date", "No date")
# for the type value, I get the value of the "itemType" key from "data"
self.type = entry.get("data", {}).get("itemType", "No type")
# for the tag value, I get the value of the "tag" key of "tags" of "data"
self.tags = [t.get("tag") for t in entry.get("data", {}).get("tags", [])]
# I define my Tag class the same way
class Tag:
def __init__(self, entry):
self.entry = entry
self.title = entry.get("data", {}).get("title", "No title").replace(":", "-")
self.author = [f"{t.get('firstName', 'No firstName')} {t.get('lastName', 'No lastName')}" for t in entry.get("data", {}).get("creators", [])]
self.date = entry.get("data", {}).get("date", "No date")
self.type = entry.get("data", {}).get("itemType", "No type")
self.tags = [t.get("tag") for t in entry.get("data", {}).get("tags", [])]
# In my bibliography, for each entry:
for entry in bibliography.top(limit=None):
# I instantiate a Reference to the variable reference
reference = Reference(entry)
# I instantiate an empty list
list_reference = []
# In my bibliography, for each entry :
for entry in bibliography.top(limit=None):
# I instantiate a Reference that I add to my list of references
list_reference.append(Reference(entry))
Par exemple, si je voulais produire une visualisation où figurent tous les chercheur·e·s qui ont travaillé ensemble (et donc relier les noms des chercheur·e·s en fonction des références), ces informations (nom de l'auteur·e et titre de la référence) doivent être structurées de manière appropriée pour me permettre d'y accéder et donc d'établir le lien.
Je définis ici une structure pour les types d'informations qui seront utiles dans les graphs (ici le titre de la référence, le nom de l'auteur·e, le tag associé à la référence)2. Pour structurer mes données, j'ai décidé de procéder avec une liste d'objets (les objets de classe comme Reference
sont des moyens de regrouper des données et des fonctionnalités).
Les listes sont mutables, elles peuvent donc être modifiées. L'objet est un moyen de définir les données afin d'y accéder facilement. Dans les objets, je peux définir chaque type d'information (titre, auteur, balises) comme attributs de mon objet. Chaque objet a sa propre identité, une signature. Je décide ici de ce qui compose mon objet Référence, et comment il est organisé.
Pour implémenter techniquement, par exemple, le Groupe de recherche matérialités comparatives : Médias, littérature et théorie | Comparative Materialities: Media, Literature, Theory Research Group, je peux choisir de le modélier sous la forme d'une liste d'objets où chaque membre constitue un objet. L'objet Marcello Vitali-Rosati
et l'objet Markus Reisenleitner
n'auront pas la même signature mais auront des attributs en communs (self
). Pour l'attibut des cheveux (qu'on définirait comme self.hair
), Marcello et Markus auront des valeurs et une organisation de cet attribut différentes :
l'attribut self.hair
de l'objet Markus Reisenleitner
aura pour la clef "hair color"
la valeur "brown"
et sera organisé de telle façon que la donnée est obligatoire ("hair color, {}
);
l'attribut self.hair
de l'objet Marcello Vitali-Rosati
aura pour la clef "hair color"
la valeur "blond"
et sera organisé de telle façon que la donnée n'est pas obligatoire ("hair color, "No hair"
)3.
Pour résumer, les objets sont des moyens de définir des entités.
Puisque les valeurs des attributs sont récoltées depuis les données de Zotero, il est impératif que je connaisse la structure de données de l'API Zotero : je dois connaître la carte des correspondances entre les clefs et les valeurs des données. Par exemple, les auteur·e·s de la références sont notés par Zotero par la clef "creators"
. Pour certains cas de figure, il me faut restructurer la donnée : pour l'attribut self.author
, je recréé le nom de l'auteur·e en demandant à Python de récupérer le prénom ou la valeur de la clef "firstName"
et de l'associer au nom de famille ou la valeur de la clef "lastName"
.
Je regroupe ensuite les différents objets (ici Reference
et Tag
) en une liste (list_reference
) qui est la structure qui va me permettre d'interroger ma base de données pour chaque entrée : je peux obtenir la valeur de l'attribut défini comme title
de toutes les références ; en d'autres termes, je peux jouer avec mes données.
La troisième étape consiste à mettre en place le modèle de graphiques. Comme je l'avais fait avec la librairie Python Pyzotero, j'importe ici la librairie graphviz qui me permet de construire des graphs. Les graphs seront générés automatiquement à partir de mes données structurées plus haut et se mettront à jour au fil des ajouts des participant·e·s à la bibliothèque Zotero, mais je dois dans un premier temps définir une chartre graphique pour le rendu visuel de mes graphs. Selon le type d'informations et le cadre, j'ai établi deux styles :
# Third step: to build the graph
# I import the library for graphs
import graphviz
# I define the visual charter of my graph
network = graphviz.Digraph(filename="MyTitle",
node_attr={'color': 'lightsalmon',
'style': 'filled',
'shape':'doublecircle',
'fontname':'Arial',
'fontsize':'13.0',
'margin':'0.05',
'fixedsize':'margin'},
edge_attr={'arrowhead':'none',
'style': 'filled',
'color':'deeppink',
'fontname':'Arial',
'fontsize':'10.0'})
network = graphviz.Digraph(filename="MyTitle",
node_attr={'color': 'mediumturquoise',
'width':'2.5',
'style': 'filled',
'shape':'signature',
'margin':'0.05',
'fixedsize':'margin',
'fontname':'Courier New',
'fontsize':'12.0'},
edge_attr={'arrowhead':'none',
'style': 'filled',
'color':'tomato',
'fontname':'Courier New',
'fontsize':'10.0'},)
La dernière étape concerne l'architecture des graphs : pour automatiser les visualisations selon la structure des données établie. Actuellement, six architectures de graphs ont été établies, fondées sur les trois types de données importés (author
, title
, tag
) pour visualiser les liens entre chercheur·e·s, entre les thèmes ou les références selon un de ces trois critères. Chaque graph a sa propre signification : le graph Author by title montre sous la forme de clusters les chercheur·e·s qui ont collaboré ensemble à la publication d'une document, le graph Title by tag montre les références qui partagent le même thème, le graph Author by tag montre également sous la forme de clusters les chercheur·e·s réuni·e·s par thèmatiques, etc.
# Finally : the graph architecture with our data
# To avoid creating the same link several times
# I instantiate an empty set()
already_existing_links = set()
# I go through my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of tags in reference1 with the loop variable tags
for tag1 in reference1.tags:
for tag2 in reference2.tags:
title1 = reference1.title
# if title1 is the same as reference2 title and tag1 is different from tag2
if title1 == reference2.title and tag1 != tag2:
# then I instantiate edge which is a tuple
#(immutable iterator i.e once created, it cannot be changed)
# of the following elements ordered :
# tag1, tag2, title1
edge = tuple(sorted((tag1, tag2, title1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my tags_by_title graph with
# tag1 as module1 or node1
# tag2 as module2 or node2
# title1 as the label of the link
tags_by_title.edge(tag1, tag2, label = title1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I display links that make up my graph
# I run my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of tags for reference1 with the tags loop variable
for tag1 in reference1.tags:
# if the title of reference1 is different from the title of reference2
# and the tag of reference1 is present in the list of tags of reference2
if reference1.title != reference2.title and tag1 in reference2.tags:
# then I instantiate edge which is a tuple
#(immutable iterable i.e. once created, it cannot be changed)
# of the following elements ordered :
# title of reference1, title of reference2, tag of reference1
edge = tuple(sorted((reference1.title, reference2.title, tag1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my title_by_tag graph with
# the title of reference1 as module1 or node1
# the title of reference2 as module2 or node2
# the tag of reference1 as the link label
title_by_tag.edge(reference1.title, reference2.title, label = tag1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I can display the relationships that make up my graph
# I run my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of tags for reference1 with the tags loop variable
for tag1 in reference1.tags:
for tag2 in reference2.tags:
for author1 in reference1.author:
# if the author of reference 1 is in reference 2 and tag1 is different from tag2
if author1 in reference2.author and tag1 != tag2:
# then I instantiate edge which is a tuple
#(immutable iterator i.e. once created, it cannot be changed)
# of the following elements ordered :
# tag1, tag2, author1
edge = tuple(sorted((tag1, tag2, author1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my tag_by_author graph with
# the tag1 as module1 or node1
# the tag2 as module2 or node2
# the author1 as the label of the link
tag_by_author.edge(tag1, tag2, label = author1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I can display the relationships that make up my graph
# to visualize
#tag_by_author
# to download
tag_by_author
# I run my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of authors for reference1 with the authors loop variable
for author1 in reference1.author:
for author2 in reference2.author:
for tag1 in reference1.tags:
# if tag1 is in tags of reference2 and author1 is different from author2
if tag1 in reference2.tags and author1 != author2:
# then I instantiate edge which is a tuple
#(immutable iterable i.e. once created, it cannot be changed)
# of the following elements ordered :
# author1, author2, tag1
edge = tuple(sorted((author1, author2, tag1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my author_by_title graph with
# the author1 as module1 or node1
# the author2 as module2 or node2
# the tag1 as the link label
author_by_tag.edge(author1, author2, label = tag1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I can display the relationships that make up my graph
# I run my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of authors for reference1 with the authors loop variable
for author1 in reference1.author:
for author2 in reference2.author:
title1 = reference1.title
# if the title1 is the same as the title of reference2 and author1 is different from author2
if title1 == reference2.title and author1 != author2:
# then I instantiate edge which is a tuple
#(immutable iterable i.e. once created, it cannot be changed)
# of the following elements ordered :
# author1, author2, title of reference1
edge = tuple(sorted((author1, author2, title1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my author_by_title graph with
# the author1 as module1 or node1
# the author2 as module2 or node2
# the title of reference1 as the link label
author_by_title.edge(author1, author2, label = title1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I can display the relationships that make up my graph
# I run my reference list once with the reference1 loop variable
for reference1 in list_reference:
# I run my reference list the first time with the loop variable reference2
for reference2 in list_reference:
# I run the list of tags for reference1 with the tags loop variable
for author1 in reference1.author:
# if the title of reference1 is different from the title of reference2
# and the author of reference1 is present in the list of authors of reference2
if reference1.title != reference2.title and author1 in reference2.author:
# then I instantiate edge which is a tuple
#(immutable iterable i.e once created, it cannot be changed)
# of the following elements ordered :
# title of reference1, title of reference2, author of reference1
edge = tuple(sorted((reference1.title, reference2.title, author1)))
# if edge is not a link already in my already_existing_links set
if edge not in already_existing_links:
# I create the link in my title_by_author graph with
# the title of reference1 as module1 or node1
# the title of reference2 as module2 or node2
# the author of reference1 as the link label
title_by_author.edge(reference1.title, reference2.title, label = author1)
# I add the link(edge) to my set
already_existing_links.add(edge)
# as a precaution, I can display the relationships that make up my graph
# to visualize
MyTitle
# to download
MyTitle.view()
J'ai créé un script Python pour chaque type d'architecture, donc chacun des six graphs. Chaque script commence avec la déclaration d'une liste vide (already_existing_links
) qui me permettra d'indexer les liens entre les données et ainsi, comme liste de références des liens répertoriés, d'éviter les doublons dans le graph.
Pour donner un aperçu de la logique théorique des scripts, je vais en décrire un en détail : le script du graph Tag by title qui montre les thématiques associées selon les références qu'elles taguent.
Le script se structure comme une boucle (une série d'actions que le script va répéter dans l'ensemble des données). Partant du principe qu'un lien est ici bidirectionnel (qu'il implique deux éléments), je fonde ma boucle sur deux references : reference1
et reference2
(qu'importe le titre de ces références puisque mon script va réitérer la boucle entre toutes les références). Pour chaque référence, je me concentre sur les tags : tag1
et tag2
. Je définis ensuite la condition (if
) qui me permet de distinguer le type de lien que je souhaite visualiser parmi les autres : si le title
de la reference1
associée au tag1
est le même que le title
de la reference2
associée au tag2
mais que le nom du tag1
est différent du nom du tag2
, j'ai un lien. Autrement dit, le script identifie un lien si deux tags différents sont associés à une même référence. Cela se traduira dans mon graph par deux noeuds (chacun contenant le nom d'un tag, tag1
et tag2
) et un lien entre avec le title
de la référence en commun. Pour éviter les duplications, avant de créer visuellement le lien, le script s'assure que le lien identifié n'est pas déjà présent dans ma liste initiée au début : si le lien est répertorié, le script ne créé pas visuellement le lien, si le lien est inédit, le script créé le lien et l'indexe dans la liste.
Les autres scripts des autres graphs suivent la même logique, avec des différences dues aux types de données.
Les dernières lignes (communes à tous les graphs) permettent soit de télécharger, soit d'afficher le résultat obtenu.
Ce qui devait initialement être une expérience ponctuelle dans le cadre d'un atelier, s'est progressivement transformé en un véritable outil de recherche. En effet, le script Python avait été implémenté dans la plateforme de manière à produire une page de résultats présentant le graphique et le code qui l'a produit. Par conséquent, il était désormais assez simple de définir les informations de la collection Zotero à extraire comme des valeurs que l'utilisateur·trice pouvait indiquer. Le code Graph our Research qui a été conçu à l'origine pour récupérer uniquement les informations de la bibliothèque Zotero CCLA-Graph pouvait alors être utilisé pour produire des graphs pour d'autres bibliothèques Zotero. Les utilisateur·trice·s de la plateforme peuvent maintenant remplir les informations de leur bibliothèque Zotero pour produire des graphs personnalisés ou pour créer d'autres réseaux de recherche pour d'autres communautés4.
Dans l'environnement de l'outil, une page d'alerte a été prévue dans le cas où l'utilisateur ne remplirait pas correctement le champ d'information sur la bibliothèque Zotero. Si l'utilisateur·trice sélectionne deux fois le même type de données (Title par Title par exemple), la page de résultats mènera à une page de bug qui est une référence à la culture numérique : l'image de fond de cette page est une photographie du "first actual case of bug being found" dans l'histoire du code et de l'informatique par Grace Hopper (Université de Harvard, 9 septembre 1947), alors informaticienne sur le projet Mark II de Harvard.
Notre jeu a consisté à révéler les liens entre nos données de recherche afin de concevoir les références comme des supports de réseaux de connaissances et d'identités communautaires insoupçonnées, et à concevoir un espace où le code ou l'aspect technique de l'écriture est un principe actif pour la conception et la mise en œuvre visuelle d'une théorie par une communauté de chercheur·e·s.
Barad, Karen Michelle. 2007. Meeting the universe halfway: quantum physics and the entanglement of matter and meaning. Durham: Duke University Press.
Kittler, Friedrich A. 1999. Gramophone, film, typewriter. Writing science. Stanford, Calif: Stanford University Press.
McLuhan, Marshall. 2010. Understanding media: the extensions of man. Repr. Routledge classics. London: Routledge.
Le processus de réflexion à l'origine de cette idée a été décrit dans un post de mon site : Graph ta recherche.
Un possible développement du projet serait d'étendre le travail de structuration à d'autres types d'informations de la référence Zotero (comme la date, le type de publication, l'édition, la langue de la publication, etc.).↩
La logique ici est la suivante : s'il n'y a pas de couleur de cheveux identifiée alors il n'y a pas de cheveux..↩
Notez que pour l'instant GTR ne fonctionne que sur les bibliothèques qui sont publiques sur Zotero.↩