Que fait datalad ?
Présentation
DataLad est une couche de gestion de données basée sur Git et git-annex. Git suit la structure du jeu de données, les petits fichiers texte et l'historique. git-annex suit le contenu des fichiers volumineux, en stockant chaque fichier sous forme de clé et en conservant les octets ailleurs que dans le dépôt local.
Cette séparation est la chose la plus importante à intérioriser, car elle signifie qu'un jeu de données fraîchement cloné contient l'historique complet et la liste complète des fichiers tout en ne contenant presque aucune donnée. Un jeu de données de 100 To se clone en quelques secondes et n'occupe que quelques mégaoctets. Les octets n'arrivent que lorsqu'on les demande, fichier par fichier, avec datalad get.
La deuxième chose qu'ajoute DataLad est la provenance. datalad run exécute une commande et valide le résultat avec un enregistrement lisible par machine de la commande, de ses entrées et de ses sorties. datalad rerun relit cet enregistrement et le réexécute. Cela transforme « comment cette figure a-t-elle été produite » d'un problème d'archéologie en une simple commande.
Quand utiliser DataLad plutôt que Git seul
Utilisez DataLad lorsque l'une des situations suivantes s'applique :
- Les fichiers sont trop volumineux pour que Git les gère confortablement, ou le total dépasse ce que chaque collaborateur souhaite avoir sur son disque.
- Les données vivent à plusieurs endroits (un serveur de laboratoire, un espace de calcul temporaire, S3, un supercalculateur) et vous devez savoir quelles copies existent.
- L'analyse doit être réexécutable, et un simple message de validation ne constitue pas une preuve suffisante.
- Vous consommez des jeux de données publiés depuis OpenNeuro, DANDI ou
datasets.datalad.org, qui sont distribués sous forme de jeux de données DataLad. - Le projet imbrique d'autres jeux de données en son sein et vous souhaitez que chacun conserve son propre historique indépendant.
Utilisez Git seul lorsque le dépôt ne contient que du code et du texte, que tout tient confortablement dans Git et que personne n'a besoin d'extractions partielles. DataLad au-dessus d'un petit dépôt de code pur ajoute une indirection sans apporter de bénéfice.
Installation
# git-annex n'est PAS écrit en Python mais est disponible via PyPI si vous avez
# déjà git d'installé :
uv pip install git-annex
# Vous pouvez aussi l'installer d'abord via le système
# (Debian/Ubuntu : apt install git-annex ; macOS : brew install git-annex ;
# conda-forge : conda install -c conda-forge git-annex)
uv pip install datalad
uv pip install datalad-container # seulement pour containers-run
datalad wtf --section dependencies # confirmer que la version de git-annex est visible
Le paquet PyPI git-annex fournit le binaire pré-compilé sous forme de wheel pour Linux, macOS et Windows plutôt que de compiler les sources Haskell, donc il s'installe comme n'importe quelle autre dépendance Python et peut être épinglé dans le même environnement que DataLad. Il n'inclut pas git avec lui.
datalad wtf affiche l'environnement résolu et est la première chose à exécuter lorsque le comportement semble impossible. Un git-annex ancien ou manquant est à l'origine d'une grande partie des erreurs déroutantes.
DataLad lui-même est sous licence MIT. git-annex est un outil séparé sous AGPL, ce qui n'a d'importance que si vous redistribuez un git-annex modifié plutôt que de l'appeler.
L'échec qui frappe en premier : les pointeurs ne sont pas des données
Après datalad clone, les fichiers annexés existent sous forme de liens symboliques vers .git/annex/objects/ (ou sous forme de petits fichiers pointeurs là où les liens symboliques ne sont pas disponibles, comme sous Windows ou un système de fichiers limité). Rien n'a encore téléchargé le contenu.
datalad clone https://github.com/OpenNeuroDatasets/ds000001.git
cd ds000001
ls sub-01/anat/ # le fichier est listé
python -c "import nibabel; nibabel.load('sub-01/anat/sub-01_T1w.nii.gz')" # échoue
datalad get sub-01/anat/sub-01_T1w.nii.gz # maintenant ça fonctionne
Le mode d'échec à reconnaître : un outil signale le fichier comme vide, tronqué, corrompu, « n'est pas un fichier gzip », ou comme un lien symbolique cassé, et la taille du fichier sur le disque est de quelques centaines d'octets. C'est un pointeur, pas un téléchargement corrompu. Exécutez datalad get avant de lire les données, et considérez « le fichier existe » comme une preuve insuffisante que son contenu est présent.
Avant qu'une analyse ne touche un répertoire, récupérez-le explicitement :
datalad get sub-01/ # tout ce qui se trouve sous un chemin
datalad get -r . # tout, y compris les sous-jeux de données
datalad get -n -r . # structure des sous-jeux de données uniquement, pas le contenu des fichiers
datalad status --annex indique la quantité de contenu présente localement, et git annex whereis <chemin> indique quels dépôts contiennent un fichier donné. whereis lit l'état enregistré et ne contacte pas les dépôts distants, donc il vous dit ce que git-annex a appris la dernière fois plutôt que ce qui est vrai maintenant.
Voir data-access.md pour trouver des jeux de données, le comportement des sous-jeux de données, supprimer du contenu en toute sécurité et réparer un jeu de données.
Enregistrement de la provenance avec datalad run
datalad run est la raison d'utiliser DataLad dans un contexte méthodologique. Il enregistre la commande avec son effet, dans la même validation :
datalad run -m "extraire le masque cérébral" \
--input "sub-01/anat/sub-01_T1w.nii.gz" \
--output "derivatives/sub-01_brain.nii.gz" \
"bet {inputs} {outputs} -m"
Ce que fait chaque partie, et pourquoi l'ignorer est problématique :
--inputrécupère le contenu avant l'exécution, afin que la commande n'échoue pas sur un pointeur. Il enregistre aussi la dépendance, ce qui permet àrerunde récupérer les mêmes entrées sur une machine différente.--outputdéverrouille ou supprime d'abord la cible, afin que git-annex ne refuse pas d'écrire sur un contenu qu'il protège. Sans cela, une deuxième exécution de la même commande échoue généralement avec une erreur de permission sur un fichier annexé qui semble en lecture seule.{inputs}et{outputs}sont développés en ces valeurs.{pwd},{dspath}et{tmpdir}sont également disponibles, et{inputs[0]}indexe les entrées individuelles.- Le message de validation contient un enregistrement JSON de l'exécution entre les lignes
=== Do not change lines below ===et^^^ Do not change lines above ^^^. Ne modifiez pas ce bloc à la main ;rerunle parse.
datalad run refuse de démarrer lorsque le jeu de données comporte des modifications non enregistrées, car un état de départ non net rend l'enregistrement peu fiable. Enregistrez ou écartez d'abord, ou passez --explicit pour déclarer que les entrées et sorties listées sont l'histoire complète. Vérifiez une commande avant de la valider avec --dry-run basic ou --dry-run command.
Une exécution qui ne change rien ne produit aucune validation, exactement comme datalad save.
Réexécution
datalad rerun # refaire l'exécution enregistrée à HEAD
datalad rerun --report # montrer ce qui serait fait, ne rien changer
datalad rerun --script recompute.sh # extraire les commandes au lieu de les exécuter
datalad rerun --since <validation> -b verification <révision> # rejouer une plage sur une nouvelle branche
Rejouer sur une branche (-b) est la façon sûre de tester la reproductibilité : la relecture atterrit ailleurs, et un diff avec la branche originale répond si les sorties sont identiques.
Conteneurs
Avec l'extension datalad-container, enregistrez une image une fois et chaque exécution ultérieure enregistre quelle image a produit les sorties :
datalad containers-add fsl --url docker://brainlife/fsl:6.0.4
datalad containers-run -n fsl -m "masque cérébral en conteneur" \
--input "sub-01/anat/sub-01_T1w.nii.gz" \
--output "derivatives/sub-01_brain.nii.gz" \
"bet {inputs} {outputs} -m"
L'image elle-même est suivie dans le jeu de données, donc l'environnement logiciel voyage avec les données et l'enregistrement de provenance plutôt que de vivre dans l'historique de shell de quelqu'un. Lorsqu'un seul conteneur est configuré, -n peut être omis.
Voir provenance.md pour les principes STAMPED et la disposition de projet YODA, le format d'enregistrement d'exécution, les sémantiques --explicit et --assume-ready, et l'export de la provenance vers W3C PROV.
Enregistrement et inspection des modifications
datalad status # ce qui a changé, y compris l'état des sous-jeux de données
datalad save -m "ajouter le rapport QC" chemin/vers/fichier
datalad save -m "point de contrôle" -r # récursif dans les sous-jeux de données
datalad save -m "petit fichier texte" --to-git notes.md
datalad save décide fichier par fichier si le contenu va dans Git ou dans git-annex, en suivant le .gitattributes du jeu de données. Forcez un fichier dans Git avec --to-git, ce qui est le bon choix pour le code et les petits fichiers texte qui doivent rester directement lisibles. La procédure yoda (datalad create -c yoda) configure cela pour code/, README.md et CHANGELOG.md automatiquement.
Création d'un jeu de données
datalad create mon_jeu_de_donnees # jeu de données simple
datalad create -c yoda mon_analyse # disposition d'analyse (code/ suivi dans Git,
# README.md et CHANGELOG.md préconfigurés)
datalad create -d . inputs/brutes # enregistrer un nouveau sous-jeu de données sous un existant
-c yoda applique la disposition de projet d'analyse décrite dans provenance.md. -d . est ce qui enregistre un nouveau jeu de données comme sous-jeu de données du parent plutôt que de laisser un dépôt non lié à l'intérieur.
Publication
Un jeu de données DataLad est généralement publié à deux endroits à la fois : un service d'hébergement Git pour l'historique, et un dépôt distant de stockage pour le contenu annexé.
datalad create-sibling-github moncompte/monjeudedonnees
git annex initremote stock type=S3 bucket=mon-bucket encryption=none autoenable=true
datalad siblings configure -s github --publish-depends stock
datalad push --to github
Le sibling Git et le sibling de stockage sont créés par des outils différents à dessein. Un sibling Git est un dépôt distant Git, et datalad create-sibling-* gère ceux des services d'hébergement. Un bucket S3 (ou WebDAV, ou un répertoire SSH) est un dépôt distant spécial git-annex, pas un dépôt distant Git, donc il est créé avec git annex initremote. datalad siblings récupère le dépôt distant spécial ensuite et le traite comme n'importe quel autre. Utiliser datalad siblings add --url s3://... ici est l'erreur que cette section vise à prévenir : --url est une URL de dépôt distant Git, S3 n'en est pas une, et le push --to github ci-dessous échoue alors sur le saut --publish-depends.
--publish-depends est ce qui empêche la publication cassée courante : un dépôt Git dont l'historique référence un contenu qui n'a jamais été téléchargé, de sorte que les collaborateurs clonent avec succès puis voient chaque datalad get échouer. Déclarer la dépendance fait publier le sibling de stockage en premier, à chaque fois.
datalad push envoie à la fois l'historique Git et, par défaut (--data auto-if-wanted), le contenu annexé que la cible est configurée pour vouloir. Passez --data anything pour pousser tout le contenu indépendamment des préférences de la cible.
Voir publishing.md pour les magasins RIA, les dépôts distants spéciaux, la gestion des identifiants et la configuration de quel sibling contient quoi.
Libération d'espace disque
git annex whereis sub-01/ # confirmer d'abord qu'une autre copie existe
datalad drop sub-01/ # supprimer le contenu local, garder le pointeur
datalad drop --what all --reckless kill <chemin> # dernier recours, détruit les données
datalad drop refuse par défaut lorsqu'il ne peut pas vérifier qu'une autre copie du contenu existe, ce qui est une vérification de sécurité plutôt qu'un obstacle. --nocheck et --if-dirty sont obsolètes ; l'orthographe actuelle est --reckless availability, et elle signifie ce qu'elle dit. --what sélectionne entre filecontent (le défaut), allkeys, datasets et all.
Modes d'échec à connaître
| Symptôme | Cause | Correctif |
|---|---|---|
| Le fichier se lit comme vide, tronqué ou comme un lien symbolique cassé | Contenu non récupéré ; seul le pointeur est présent | datalad get <chemin> |
| « Permission denied » en écrivant une sortie existante | git-annex protège en écriture le contenu annexé | Déclarez-la avec --output, ou datalad unlock <chemin> |
datalad run refuse de démarrer | Le jeu de données a des modifications non enregistrées | datalad save d'abord, ou passez --explicit |
datalad drop refuse | Aucune deuxième copie vérifiée du contenu | Poussez d'abord vers un sibling, ou acceptez --reckless availability |
Un collaborateur clone mais chaque get échoue | Historique publié sans le contenu | Publiez le sibling de stockage et définissez --publish-depends |
| Le clonage réussit, les répertoires des sous-jeux de données sont vides | Les sous-jeux de données ne sont pas installés par défaut | datalad get -n -r ., puis get les chemins dont vous avez besoin |
| Les commandes se comportent de manière impossible | git-annex manquant ou trop ancien | datalad wtf --section dependencies |
Références détaillées
- data-access.md : trouver des jeux de données publiés (
registry.datalad.org, OpenNeuro, DANDI,datasets.datalad.orget le raccourci///), options de clone et get, gestion des sous-jeux de données, états du contenu annexé, suppression et retrait, et réparationfsck. - provenance.md : les principes STAMPED et la disposition YODA, le format d'enregistrement d'exécution, les options complètes de
runetrerun,containers-run, et l'état actuel de l'export de la provenance DataLad vers W3C PROV. - publishing.md : siblings et leurs actions, variantes de
create-sibling-*, magasins RIA, dépôts distants spéciaux, sémantiques depush, et gestion des identifiants.
Compétences associées
La compétence bids couvre la structure d'imagerie de données cérébrales (BIDS) dans laquelle sont organisés la plupart des jeux de données de neuro-imagerie distribués via DataLad. Un flux de travail typique clone un jeu de données BIDS avec DataLad, le valide avec les outils BIDS, puis exécute une BIDS-App sous datalad containers-run afin que les dérivés portent la provenance.
Sources principales
- Documentation DataLad : https://docs.datalad.org/en/stable/
- Manuel DataLad : https://handbook.datalad.org/en/latest/
- Chapitre sur
datalad run: https://handbook.datalad.org/en/latest/basics/101-108-run.html - Principes YODA : https://handbook.datalad.org/en/latest/basics/101-127-yoda.html
- Principes STAMPED (opérationnalisés à partir de YODA) : https://stamped-principles.org
- datalad-container : https://docs.datalad.org/projects/container/en/stable/
- git-annex : https://git-annex.branchable.com/
- Registre de jeux de données : https://registry.datalad.org
Remerciements
Le périmètre thématique de cette compétence a été en partie informé par le dépôt sous licence MIT de @bcmcpher datalad-cli