O que DataLad faz?
Visão Geral
DataLad é uma camada de gerenciamento de dados sobre Git e git-annex. O Git rastreia a estrutura do dataset, arquivos de texto pequenos e o histórico. O git-annex rastreia o conteúdo de arquivos grandes, armazenando cada arquivo como uma chave e mantendo os bytes em algum lugar que não seja necessariamente o repositório local.
Essa divisão é a coisa mais importante a internalizar, porque significa que um dataset recém-clonado contém o histórico completo e a listagem completa de arquivos, mas contém quase nenhum dado. Um dataset de 100 TB é clonado em segundos e ocupa alguns megabytes. Os bytes chegam apenas quando solicitados, por arquivo, com datalad get.
A segunda coisa que o DataLad adiciona é a proveniência. O datalad run executa um comando e confirma o resultado junto com um registro legível por máquina do comando, suas entradas e suas saídas. O datalad rerun lê esse registro e o reexecuta. Isso transforma "como esta figura foi produzida" de um problema de arqueologia em um comando.
Quando usar DataLad em vez de Git puro
Use DataLad quando qualquer um dos seguintes for verdadeiro:
- Arquivos são grandes demais para o Git lidar confortavelmente, ou o total excede o que todo colaborador deseja em disco.
- Os dados vivem em mais de um lugar (um servidor de laboratório, um scratch de cluster, S3, um supercomputador) e você precisa saber quais cópias existem.
- A análise deve ser reexecutável, e uma mensagem de commit simples não é evidência suficiente.
- Você está consumindo datasets publicados do OpenNeuro, DANDI ou
datasets.datalad.org, que são distribuídos como datasets do DataLad. - O projeto aninha outros datasets dentro de si e você deseja que cada um mantenha seu próprio histórico independente.
Use Git puro quando o repositório contém apenas código e texto, tudo cabe confortavelmente no Git e ninguém precisa de checkouts parciais. DataLad sobre um pequeno repositório de código puro adiciona indireção sem trazer benefícios.
Instalação
# git-annex NÃO é escrito em Python, mas está disponível no PyPI se você já
# tiver o git instalado:
uv pip install git-annex
# Você também pode instalá-lo primeiro do sistema
# (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 # apenas para containers-run
datalad wtf --section dependencies # confirme que a versão do git-annex está visível
O pacote git-annex do PyPI envia o binário pré-compilado como uma wheel para Linux, macOS e Windows, em vez de compilar as fontes Haskell, então ele instala como qualquer outra dependência Python e pode ser fixado no mesmo ambiente que o DataLad. Ele não traz o git junto.
datalad wtf imprime o ambiente resolvido e é a primeira coisa a executar quando o comportamento parece impossível. Um git-annex antigo ou ausente está por trás de uma grande parte dos erros confusos.
O DataLad em si é licenciado sob MIT. O git-annex é uma ferramenta separada sob AGPL, o que importa apenas se você redistribuir um git-annex modificado em vez de apenas chamá-lo.
O erro que mais aparece: ponteiros não são dados
Após datalad clone, arquivos anexados existem como links simbólicos para .git/annex/objects/ (ou como pequenos arquivos de ponteiro onde links simbólicos não estão disponíveis, como no Windows ou em um sistema de arquivos limitado). Nada baixou o conteúdo ainda.
datalad clone https://github.com/OpenNeuroDatasets/ds000001.git
cd ds000001
ls sub-01/anat/ # o arquivo está listado
python -c "import nibabel; nibabel.load('sub-01/anat/sub-01_T1w.nii.gz')" # falha
datalad get sub-01/anat/sub-01_T1w.nii.gz # agora funciona
O modo de falha a reconhecer: uma ferramenta relata que o arquivo está vazio, truncado, corrompido, "não é um arquivo gzip" ou é um link simbólico quebrado, e o tamanho do arquivo em disco é de algumas centenas de bytes. Isso é um ponteiro, não um download corrompido. Execute datalad get antes de ler dados e trate "arquivo existe" como evidência insuficiente de que seu conteúdo está presente.
Antes de uma análise tocar em um diretório, busque-o explicitamente:
datalad get sub-01/ # tudo sob um caminho
datalad get -r . # tudo, incluindo subdatasets
datalad get -n -r . # apenas estrutura do subdataset, sem conteúdo de arquivo
datalad status --annex relata quanto conteúdo está presente localmente, e git annex whereis <caminho> relata quais repositórios contêm um determinado arquivo. whereis lê o estado registrado e não contata os remotos, então ele informa o que o git-annex aprendeu por último, e não o que é verdade agora.
Consulte data-access.md para encontrar datasets, comportamento de subdatasets, remover conteúdo com segurança e reparar um dataset.
Registrando proveniência com datalad run
datalad run é a razão para usar DataLad em um contexto de métodos. Ele salva o comando junto com seu efeito, no mesmo commit:
datalad run -m "extrair máscara cerebral" \
--input "sub-01/anat/sub-01_T1w.nii.gz" \
--output "derivatives/sub-01_brain.nii.gz" \
"bet {inputs} {outputs} -m"
O que cada parte faz e por que pular dói:
--inputrecupera o conteúdo antes de executar, para que o comando não falhe em um ponteiro. Também registra a dependência, que é o que permite quererunbusque as mesmas entradas em uma máquina diferente.--outputdesbloqueia ou remove o destino primeiro, para que o git-annex não se recuse a escrever sobre conteúdo que está protegendo. Sem ele, uma segunda execução do mesmo comando geralmente falha com um erro de permissão em um arquivo anexado que parece somente leitura.{inputs}e{outputs}expandem para esses valores.{pwd},{dspath}e{tmpdir}também estão disponíveis, e{inputs[0]}indexa entradas individuais.- A mensagem de commit carrega um registro JSON de execução entre
=== Não altere as linhas abaixo ===e^^^ Não altere as linhas acima ^^^. Não edite manualmente esse bloco; oreruno analisa.
datalad run se recusa a iniciar quando o dataset tem modificações não salvas, porque um estado inicial sujo torna o registro não confiável. Salve ou descarte primeiro, ou passe --explicit para declarar que as entradas e saídas listadas são a história completa. Verifique um comando antes de confirmá-lo com --dry-run basic ou --dry-run command.
Uma execução que não muda nada não produz commit, exatamente como datalad save faz.
Reexecutando
datalad rerun # refazer a execução registrada em HEAD
datalad rerun --report # mostrar o que seria feito, não mudar nada
datalad rerun --script recompute.sh # extrair os comandos em vez de executá-los
datalad rerun --since <commit> -b check <revision> # reproduzir um intervalo em um novo branch
Reexecutar em um branch (-b) é a maneira segura de testar a reprodutibilidade: a reprodução vai para outro lugar, e um diff contra o branch original responde se as saídas voltaram idênticas.
Containers
Com a extensão datalad-container, registre uma imagem uma vez e cada execução subsequente registra qual imagem produziu as saídas:
datalad containers-add fsl --url docker://brainlife/fsl:6.0.4
datalad containers-run -n fsl -m "máscara cerebral no container" \
--input "sub-01/anat/sub-01_T1w.nii.gz" \
--output "derivatives/sub-01_brain.nii.gz" \
"bet {inputs} {outputs} -m"
A imagem em si é rastreada no dataset, então o ambiente de software viaja com os dados e o registro de proveniência, em vez de viver no histórico de shell de alguém. Quando apenas um container está configurado, -n pode ser omitido.
Consulte provenance.md para os princípios STAMPED e o layout de projeto YODA, o formato do registro de execução, semânticas de --explicit e --assume-ready, e exportação de proveniência para W3C PROV.
Salvando e inspecionando alterações
datalad status # o que mudou, incluindo estado do subdataset
datalad save -m "adicionar relatório de QC" caminho/para/arquivo
datalad save -m "checkpoint" -r # recorrer em subdatasets
datalad save -m "arquivo de texto pequeno" --to-git notes.md
datalad save decide por arquivo se o conteúdo vai para o Git ou para o git-annex, seguindo o .gitattributes do dataset. Force um arquivo para o Git com --to-git, que é a escolha certa para código e arquivos de texto pequenos que devem permanecer diretamente legíveis. O procedimento yoda (datalad create -c yoda) configura isso para code/, README.md e CHANGELOG.md automaticamente.
Criando um dataset
datalad create my_dataset # dataset simples
datalad create -c yoda my_analysis # layout de análise (code/ rastreado no Git,
# README.md e CHANGELOG.md pré-configurados)
datalad create -d . inputs/raw # registrar um novo subdataset sob um existente
-c yoda aplica o layout de projeto de análise descrito em provenance.md. -d . é o que registra um novo dataset como subdataset do pai, em vez de deixar um repositório não relacionado dentro dele.
Publicando
Um dataset do DataLad geralmente é publicado em dois lugares ao mesmo tempo: um serviço de hospedagem Git para o histórico e um remote de armazenamento para o conteúdo anexado.
datalad create-sibling-github myaccount/mydataset
git annex initremote store type=S3 bucket=my-bucket encryption=none autoenable=true
datalad siblings configure -s github --publish-depends store
datalad push --to github
O sibling Git e o sibling de armazenamento são criados por ferramentas diferentes de propósito. Um sibling Git é um remote Git, e datalad create-sibling-* lida com os de serviços de hospedagem. Um bucket S3 (ou WebDAV, ou um diretório SSH) é um remote especial do git-annex, não um remote Git, então é criado com git annex initremote. datalad siblings pega o remote especial depois e o trata como qualquer outro. Usar datalad siblings add --url s3://... aqui é o erro que esta seção existe para prevenir: --url é uma URL de remote Git, S3 não é, e o push --to github abaixo falha no salto --publish-depends.
--publish-depends é o que impede a publicação quebrada comum: um repositório Git cujo histórico referencia conteúdo que nunca foi enviado, então os colaboradores clonam com sucesso e depois descobrem que cada datalad get falha. Declarar a dependência faz com que o sibling de armazenamento publique primeiro, sempre.
datalad push envia tanto o histórico Git quanto, por padrão (--data auto-if-wanted), o conteúdo anexado que o destino está configurado para querer. Passe --data anything para enviar todo o conteúdo, independentemente das preferências do destino.
Consulte publishing.md para armazenamentos RIA, remotes especiais, gerenciamento de credenciais e configuração de qual sibling contém o quê.
Liberando espaço em disco
git annex whereis sub-01/ # confirme que outra cópia existe primeiro
datalad drop sub-01/ # remover conteúdo local, manter o ponteiro
datalad drop --what all --reckless kill <caminho> # último recurso, destrói dados
datalad drop recusa por padrão quando não pode verificar outra cópia do conteúdo existe, o que é uma verificação de segurança, não um obstáculo. --nocheck e --if-dirty estão obsoletos; a grafia atual é --reckless availability, e significa o que diz. --what seleciona entre filecontent (padrão), allkeys, datasets e all.
Modos de falha que vale a pena conhecer
| Sintoma | Causa | Correção |
|---|---|---|
| Arquivo lê como vazio, truncado ou link simbólico quebrado | Conteúdo não recuperado; apenas o ponteiro está presente | datalad get <caminho> |
| "Permissão negada" ao escrever uma saída existente | git-annex protege contra escrita o conteúdo anexado | Declare-o com --output, ou datalad unlock <caminho> |
datalad run recusa iniciar | Dataset tem alterações não salvas | datalad save primeiro, ou passe --explicit |
datalad drop recusa | Nenhuma segunda cópia verificada do conteúdo | Envie para um sibling primeiro, ou aceite --reckless availability |
Colaborador clona, mas todo get falha | Histórico publicado sem o conteúdo | Publique o sibling de armazenamento e configure --publish-depends |
| Clone bem-sucedido, diretórios de subdataset vazios | Subdatasets não são instalados por padrão | datalad get -n -r ., depois get nos caminhos que precisa |
| Comandos se comportam de forma impossível | git-annex ausente ou muito antigo | datalad wtf --section dependencies |
Referências detalhadas
- data-access.md: encontrando datasets publicados (
registry.datalad.org, OpenNeuro, DANDI,datasets.datalad.orge o atalho///), opções de clone e get, manipulação de subdatasets, estados de conteúdo anexado, remoção efsckde reparo. - provenance.md: os princípios STAMPED e o layout YODA, o formato do registro de execução, opções completas de
runererun,containers-rune o estado atual da exportação de proveniência do DataLad para W3C PROV. - publishing.md: siblings e suas ações, variantes de
create-sibling-*, armazenamentos RIA, remotes especiais, semântica depushe gerenciamento de credenciais.
Habilidades relacionadas
A habilidade bids cobre a Brain Imaging Data Structure (Estrutura de Dados de Imagem Cerebral) na qual a maioria dos datasets de neuroimagem distribuídos através do DataLad está organizada. Um fluxo de trabalho típico clona um dataset BIDS com DataLad, valida-o com as ferramentas BIDS e, em seguida, executa um BIDS-App sob datalad containers-run para que os derivados carreguem proveniência.
Fontes primárias
- Documentação do DataLad: https://docs.datalad.org/en/stable/
- Manual do DataLad: https://handbook.datalad.org/en/latest/
- Capítulo sobre
datalad run: https://handbook.datalad.org/en/latest/basics/101-108-run.html - Princípios YODA: https://handbook.datalad.org/en/latest/basics/101-127-yoda.html
- Princípios STAMPED (operacionalizados a partir do YODA): https://stamped-principles.org
- datalad-container: https://docs.datalad.org/projects/container/en/stable/
- git-annex: https://git-annex.branchable.com/
- Registro de datasets: https://registry.datalad.org
Agradecimento
O escopo do tópico desta habilidade foi informado em parte pelo datalad-cli licenciado sob MIT por @bcmcpher.