/hats-publish
Transforma a liberação de um catálogo de levantamento em uma coleção HATS (catálogo + margem + tabelas de índice) que é verificada
contra os arquivos fonte, documentada, hospedada e registrada. O procedimento codifica a documentação do hats-import e do
lsdb, o pipeline de importação do Rubin (https://github.com/lincc-frameworks/rubin-dash) e as convenções
da equipe registradas em issues públicas e notebooks de importação arquivados; cada
valor específico do site vem do arquivo de site descrito em CONFIG.md, cada referência é uma URL pública, e nada
aqui nomeia uma máquina, uma pessoa ou um conjunto de dados.
Uma execução = um catalog.toml (copiado de templates/catalog.toml para um diretório de trabalho). Cada modelo lê
o arquivo, caminhos relativos nele são resolvidos em relação ao diretório que o contém, e uma execução é reproduzível a partir apenas desse arquivo. Mantenha o diretório de trabalho: ele contém a configuração, os logs, o
notebook de verificação executado e o log da execução.
Fixe os modelos no início de cada execução: T=$(bash <skill>/templates/pin_templates.sh) no diretório de trabalho
os copia como somente leitura para templates.pinned/ com o commit do git, e cada etapa posterior (job.sbatch e
resubmit_loop.sh inclusos) executa $T/.... Um git pull ou uma edição da skill não pode então alterar uma importação em andamento, e
o README nomeia o commit que construiu o catálogo. Altere o código de uma execução apenas com pin_templates.sh --repin.
Quando usar
Uma nova liberação de levantamento para publicar; uma reimportação de um catálogo HATS existente com melhor particionamento, configurações de escrita ou metadados; uma solicitação para verificar se uma cópia HATS corresponde à sua fonte.
Entradas (pergunte apenas se não definido)
Arquivos fonte ou URLs e seu formato; levantamento, liberação, página do modelo de dados, artigo, agradecimento e licença;
se uma versão HATS já existe (procure na árvore data/ do data.lsdb.io e em imports/README.md); as colunas de
coordenada e id. Todo o resto é decidido na entrevista abaixo.
Procedimento
Fases em ordem. As etapas em negrito param e aguardam o usuário. Cada fase começa e termina com uma entrada do log de execução
(run_log.py start|end <phase>); os modelos fazem isso por conta própria onde executam.
- Ambiente. Crie ou atualize um ambiente com as versões mais recentes lançadas de
hats,lsdb,hats-import(pip install -U hats lsdb hats-import nested-pandas pyarrow astropy fitsio jupyter), imprima as versões, examine as notas de versão para mudanças de formato. AponteHATS_PUBLISH_SITE_ENVpara o seu arquivo de site (CONFIG.md). Os modelos que usam as bibliotecas se recusam a executar abaixo das versões mínimas e alertam quando uma versão mais nova existe. - Entrevista de decisão (
reference/decisions.md): os nove grupos, algumas perguntas por vez, cada uma com seu valor padrão recomendado e consequências. Escreva as respostas emcatalog.tomle no log de execução (run_log.py decision). Em seguida, mostre o plano: rota, leitor, recursos, particionamento, configurações de escrita, nomes, alvos. - Adquirir. Baixe para o diretório raw, verifique checksums e integridade do arquivo (
gzip -t), registre o sha256 de cada arquivo em[source].sha256, e salve a página do modelo de dados ao lado dos dados. Conte os arquivos contra a listagem do arquivo ([source].expected_files) e liste nomes de arquivos exatos, nunca um glob simples sobre um diretório que pode conter cópias de download repetido. Para milhares de arquivos pequenos, escreva arquivos de índice para os leitores indexados. Um download deixado em execução em segundo plano escreve seu pid emdownload.pidno diretório de trabalho para questatus.shpossa reportá-lo. 2a. Tabelas sem coordenadas ([source.positions_from]):attach_positions.pyprocura as posições por id em uma coleção HATS de referência (sua tabela de índice) e escreve a fonte como Parquet comra/dec; a importação então lê esses arquivos. CSV com cabeçalho ECSV com colunas de array ([reader].ecsv_header = true) é analisado em colunas de lista no caminho. 2b. Uma tabela dividida em arquivos FITS paralelos por linha ([source.companions], por exemplo, um arquivo principal mais arquivos extra/foto-z/curva de luz com as mesmas linhas): a importação os lê lado a lado com faixas de linhas do fitsio, verifica as colunas chave bloco por bloco, e pode adicionar colunas computadas ([reader].derive, uma função no diretório de trabalho) e empacotar colunas de lista em uma coluna aninhada ([reader].pack_nested). O carregador de verificação lê os mesmos arquivos independentemente. - Planejar particionamento.
estimate_threshold.py --writeamostra a entrada com as configurações de escrita da execução e converte a regra de tamanho de arquivo de 200–800 MB empixel_threshold, e prevê a contagem de partições e o tamanho dedataset/_metadata(alerta perto do limite de rodapé de 4 GiB); verifiquehighest_ordercontra a região mais densa. - Teste.
import_collection.py --trial-file <um arquivo>em um diretório de teste; inspecione dtypes, nulos versus sentinelas, nomes de colunas, colunas de array, linhas sem coordenadas ([reader].drop_rows_without_coordinatesdescarta e conta). Ajuste[reader],[columns]e[properties]; mostre ao usuário o que mudou. - Importar.
import_collection.pyem segundo plano (nohup/setsid), oujob.sbatchem um nó de lote (ele também executa as fases 5–6 e a comparação), retomável; constrói o catálogo, a(s) margem(ns) e as tabelas de índice com as configurações[properties]e[writer]. Tabelas pequenas (abaixo de cerca de 1 M de linhas e 1 GB na memória; acima de cerca de 100 k linhas em tabelas largas hats-import é mais rápido) usamimport_small.pyem vez disso. Em seguida,write_ancillary.py: miniatura de dados (amostra aleatória por partição), estatísticas por partição, pré-visualizações PNG, README eindex.htmlcom uma seção de proveniência. Progresso:status.sh(do diretório de trabalho) imprime o download, o job SLURM, o estágio atual do hats-import com sua barra de progresso, e a entrada mais recente do log de execução. Downloads e importações executam por horas: assim que um executa em segundo plano (fase 2 ou 5), inicie atualizações a cada 5 minutos sem perguntar. Cada atualização executastatus.she reporta apenas o que mudou. Diga que estão executando e que o usuário pode alterar o intervalo ou interrompê-las. Interrompa-as quando o job terminar ou falhar, e verifique o estado real do job quando ele sair da fila. Em uma fila preemptível, inicieresubmit_loop.sh <job id>ao lado do job: ele registra os recursos do job emresubmit_opts.txt, reenvia jobs preemptados ou cancelados pelo sistema com os mesmos recursos (hats-import retoma; um job preemptado após a importação terminar, marcado porimport.done, é reenviado com a importação pulada) e para em qualquer outra coisa. 5a. Produto de série temporal aninhada ([nested], opcional):attach_nested.pyjunta colunas de lista por objeto de uma referência HATS por id (junção espacial interna), empacota-as em uma coluna aninhada comnest_listse escreve uma segunda coleção ao lado da plana; a seção 9b do notebook reconcilia linhas, comprimentos de lista e uma amostra de arrays. - Verificar, qualquer falha interrompe a execução (
reference/verification.md):verify_structure.py --spot-check(verificações do hats-import, conformidade com notas HATS, varredura de codificação) →run_verify.sh(o notebook de nível de valor contra a fonte; verificações terminam PASS, FAIL ou SKIP com uma razão) → a lista de verificação de revisão com o usuário. - Documentar e arquivar. Adicione
catalog.toml, os scripts usados e o notebook executado ao diretórioimports/do data.lsdb.io com uma linha no topo de seu README (parte do pull request do site). - Hospedar (
reference/publishing.md). Executepublish_web.sh --checkepublish_mirror.sh --check, mostre as pré-visualizações (o que seria copiado, e o que o destino já contém), e somente após a aprovação do usuário execute-os com--yes(sem uma das duas flags eles param; um destino que contém arquivos que a construção não possui os impede de escrever a menos que--replaceseja fornecido, que deleta os arquivos obsoletos): copiar, agrupar, manifesto de checksum,hats_statusehats_service_urlpor tabela, link simbólico no host web, teste público aberto comlsdb.open_catalogna raiz da coleção (uma falha reverte o link simbólico), então a descrição de autoindexação; a cópia do espelho é reverificada emverify_results_mirror.csv. - Registrar.
make_site_entry.pyescreve a entrada da página e o mapa de densidade em um branch em um clone do data.lsdb.io (mesclando em uma entrada existente) e o prepara; pergunte pela mensagem de commit; o pull request é do usuário. Após ser mesclado e implantado,registry_entry.pyexecuta o gerador de registro em um branch em um clone do registro para o pull request do usuário; requer um clone limpo do site emorigin/main. - Finalizar.
NOTES.mda partir do modelo; itens em aberto (espelhos, registro, implantação, aposentadoria de uma versão anterior);run_log.py feedbackcom o usuário sobre o que não estava claro, manual ou errado nos padrões;run_log.py render --scrube ofereça um pull request adicionando o log arunlogs/neste repositório.
Reimportações: ImportArguments.reimport_from_hats para novos limites ou ordenação, reconstrua margens e índices, escreva
em um novo diretório, verifique, execute compare_versions.py --new <novo> --old <anterior> --key <id> (esquema, linhas e
valores da região compartilhada; estreitamento de tipo é reportado separadamente), redirecione os links simbólicos, mantenha a cópia
antiga até que a página e o registro apontem para a nova.
Modelos
| Arquivo | Propósito |
|---|---|
catalog.toml | a configuração da execução (copie e preencha) |
pin_templates.sh | congele os modelos para uma execução em templates.pinned/ (commit, diff local, checksums); --repin para alterá-los |
_common.py, catalog_source.py, readers.py | ajudantes compartilhados: configuração, versões, variáveis do site, configurações de escrita, propriedades, carregador de fonte, filtro de coordenada |
estimate_threshold.py | regra de tamanho de arquivo → pixel_threshold |
import_collection.py | construção de coleção hats-import (--dry-run, --trial-file) |
import_small.py | rota na memória para tabelas pequenas |
attach_positions.py | posições por id a partir de uma HATS de referência para tabelas sem coordenadas; arrays ECSV analisados em colunas de lista |
attach_nested.py | produto de série temporal aninhada: junte colunas de lista por id de uma HATS de referência, nest_lists, escreva uma coleção |
job.sbatch | rota de lote: importação, arquivos auxiliares, verificação e comparação como um único job SLURM em um nó dedicado |
write_ancillary.py | miniatura, estatísticas, pré-visualizações, README, index.html |
verify_structure.py | verificações estruturais, de conformidade e codificação |
build_verify_notebook.py, run_verify.sh | notebook de verificação de nível de valor |
compare_versions.py | compare uma nova construção com uma versão HATS existente (reimportações, validação contra uma cópia publicada) |
publish_mirror.sh, publish_web.sh | alvos de hospedagem |
make_site_entry.py, registry_entry.py | página e registro do data.lsdb.io |
memwatch.sh | vigilante de memória para etapas longas de processo único em nós compartilhados |
status.sh | resumo de progresso em uma tela (download, job, estágio de importação, log de execução) para atualizações agendadas |
resubmit_loop.sh | reenvie um job em lote após preempção ou cancelamento do sistema; um loop por execução (guarda de heartbeat) |
run_log.py, NOTES.template.md | log de execução e notas |
Pegadinhas
Uma linha cada; detalhes e mais em reference/pitfalls.md.
- Uma tarefa Dask por arquivo de entrada: divida arquivos enormes, use leitores indexados para milhares de pequenos.
- Linhas sem coordenadas param o estágio de mapeamento: teste a importação primeiro, filtre e conte-as.
- Entradas CSV gzipadas precisam
compression="gzip"(o leitor recebe um handle aberto); a importação adiciona para arquivos.gz. expected_total_rowsdeve corresponder ou o pipeline para após o binning; é uma verificação, não uma dica.- Use os padrões Parquet do hats (hats, hats-import, lsdb >= 0.11.1): ZSTD 15, índice de página, BYTE_STREAM_SPLIT em
colunas float. Deixe
[writer]vazio a menos que o usuário decida o contrário; escreva qualquer arquivo que a skill escreva comparquet_write_kwargs. Versões mais antigas escrevem floats codificados por dicionário, cerca de 1.4× maiores. - Colunas padrão devem existir no esquema; colunas aninhadas usam
frame.subcol. - hats escreve
hats.propertieseproperties; edite ambos ou nenhum. hats_release_dateé a data da nota HATS, não dos dados; coloque datas dos dados emt_min/t_max.- Uma margem pode conter linhas extras, nunca menos: verifique por contenção.
- Margens e índices carregam o caminho da construção em
hats_primary_table_url; os scripts de publicação o tornam relativo. - Abra coleções na raiz; a página deve apontar para a raiz da coleção.
- O
.htaccessweb é de primeira correspondência e prefixo; o script de publicação insere antes de entradas genéricas e escreve por cópia, não renomeação (diretório fixo). - Entradas cujas colunas diferem por região perdem colunas silenciosamente na redução: conforme a um esquema
(
[reader].conform_schema, qualquer formato), teste cada região. _metadatanão pode exceder 4 GiB:estimate_threshold.pyo prevê;create_metadata = falsepara catálogos enormes.- Listas de tamanho fixo nulas quebram leitores pyarrow < 26: preencha com NaN ou use listas de comprimento variável.
- Barras de progresso em notebooks headless se tornam widgets mortos; o construtor de notebook usa barras de texto.
- Shells paralelos compartilham um diretório de trabalho: caminhos absolutos, arquivos pid em vez de
pgrep -f.
Saída
Uma coleção HATS verificada nos alvos de hospedagem, uma página do data.lsdb.io preparada, um branch de registro, NOTES.md,
verify_results.csv, o notebook de verificação executado e RUNLOG.md.