CommunityRédaction et éditiongithub.com

astronomy-commons/lsdb-agent-skills

Importer un catalogue astronomique externe dans HATS, le vérifier par rapport à la source, le documenter, l'héberger et l'enregistrer sur data.lsdb.io, en suivant les conventions de l'équipe LSDB. À utiliser lorsque l'utilisateur dit « créer une collection HATS à partir de X », « importer X dans HATS », « réimporter X », « mettre X sur data.lsdb.io », « rendre X disponible comme <un catalogue existant> » ou « vérifier la copie HATS de X par rapport à la source ». Ne pas utiliser pour les produits Butler de Rubin (ils ont leur propre pipeline) ni pour les catalogues déjà dans HATS qui nécessitent seulement une page ou un miroir (utiliser reference/publishing.md directement).

Qu'est-ce que lsdb-agent-skills ?

Cette compétence automatise le processus complet de publication d'un catalogue astronomique externe au format HATS (Hierarchical Adaptive Triangular Segmentation). Elle transforme une version d'un catalogue d'observation en une collection HATS complète comprenant le catalogue principal, les marges et les tables d'index. Le processus intègre les bonnes pratiques de la documentation de hats-import et LSDB, le pipeline d'import de Rubin (basé sur rubin-dash), ainsi que les conventions d'équipe documentées dans des tickets publics et des notebooks d'import archivés. La compétence gère l'acquisition des données source, la vérification des sommes de contrôle, le partitionnement optimisé, l'import proprement dit, la génération de fichiers auxiliaires (vignettes, statistiques, prévisualisations), la vérification structurelle et au niveau des valeurs, la publication sur les serveurs web et miroirs, et l'enregistrement sur data.lsdb.io. Elle est conçue pour les environnements de calcul avec batch SLURM, et chaque étape est reproductible à partir d'un seul fichier de configuration (catalog.toml). Elle prend en charge les réimports avec comparaison de versions, les tables sans coordonnées (avec recherche de positions par ID), les fichiers FITS parallélisés par ligne et les produits temporels imbriqués.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/astronomy-commons/lsdb-agent-skills/tree/HEAD/skills/hats-publish

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

/hats-publish

Transforme une version d'un catalogue d'observation en une collection HATS (catalogue + marge + tables d'index) qui est vérifiée par rapport aux fichiers source, documentée, hébergée et enregistrée. La procédure suit la documentation de hats-import et lsdb, le pipeline d'import Rubin (https://github.com/lincc-frameworks/rubin-dash) et les conventions de l'équipe enregistrées dans des tickets publics et des notebooks d'import archivés ; chaque valeur spécifique au site provient du fichier de site décrit dans CONFIG.md, chaque référence est une URL publique, et rien ici ne nomme une machine, une personne ou un ensemble de données.

Une exécution = un catalog.toml (copié depuis templates/catalog.toml dans un répertoire de travail). Chaque modèle le lit, les chemins relatifs qui s'y trouvent sont résolus par rapport au répertoire qui le contient, et une exécution est reproductible à partir de ce seul fichier. Gardez le répertoire de travail : il contient la configuration, les journaux, le notebook de vérification exécuté et le journal d'exécution.

Gelez les modèles au début de chaque exécution : T=$(bash <skill>/templates/pin_templates.sh) dans le répertoire de travail les copie en lecture seule dans templates.pinned/ avec le commit git, et chaque étape ultérieure (job.sbatch et resubmit_loop.sh inclus) exécute $T/.... Un git pull ou une modification de la compétence ne peut alors pas changer une importation en cours, et le README nomme le commit qui a construit le catalogue. Modifiez le code d'une exécution uniquement avec pin_templates.sh --repin.

Quand l'utiliser

Une nouvelle version d'un catalogue à publier ; une réimportation d'un catalogue HATS existant avec un meilleur partitionnement, des paramètres d'écriture ou des métadonnées ; une demande de vérification qu'une copie HATS correspond à sa source.

Entrées (demander uniquement si non définies)

Fichiers source ou URL et leur format ; relevé, version, page de modèle de données, article, remerciements et licence ; si une version HATS existe déjà (chercher dans l'arborescence data/ de data.lsdb.io et imports/README.md) ; les colonnes de coordonnées et d'identifiant. Tout le reste est décidé dans l'entretien ci-dessous.

Procédure

Phases dans l'ordre. Les étapes en gras s'arrêtent et attendent l'utilisateur. Chaque phase commence et se termine par une entrée dans le journal d'exécution (run_log.py start|end <phase>) ; les modèles le font eux-mêmes là où ils s'exécutent.

  1. Environnement. Créer ou mettre à jour un environnement avec les dernières versions publiées de hats, lsdb, hats-import (pip install -U hats lsdb hats-import nested-pandas pyarrow astropy fitsio jupyter), afficher les versions, parcourir les notes de version pour les changements de format. Pointer HATS_PUBLISH_SITE_ENV vers votre fichier de site (CONFIG.md). Les modèles qui utilisent les bibliothèques refusent de s'exécuter en dessous des versions minimales et avertissent lorsqu'une version plus récente existe.
  2. Entretien de décision (reference/decisions.md) : les neuf groupes, quelques questions à la fois, chacune avec sa valeur par défaut recommandée et ses conséquences. Écrire les réponses dans catalog.toml et le journal d'exécution (run_log.py decision). Ensuite, montrer le plan : chemin, lecteur, ressources, partitionnement, paramètres d'écriture, noms, cibles.
  3. Acquisition. Télécharger dans le répertoire brut, vérifier les sommes de contrôle et l'intégrité des archives (gzip -t), enregistrer le sha256 de chaque fichier dans [source].sha256, et sauvegarder la page du modèle de données à côté des données. Compter les fichiers par rapport à la liste de l'archive ([source].expected_files) et lister les noms de fichiers exacts, jamais un glob nu sur un répertoire qui peut contenir des copies de téléchargement. Pour des milliers de petits fichiers, écrire des fichiers d'index pour les lecteurs indexés. Un téléchargement laissé en arrière-plan écrit son pid dans download.pid dans le répertoire de travail afin que status.sh puisse le signaler. 2a. Tables sans coordonnées ([source.positions_from]) : attach_positions.py recherche les positions par identifiant dans une collection HATS de référence (sa table d'index) et écrit la source en Parquet avec ra/dec ; l'import lit ensuite ces fichiers. Les CSV avec en-tête ECSV et colonnes de tableaux ([reader].ecsv_header = true) sont analysés en colonnes de listes au passage. 2b. Une table divisée en fichiers FITS parallèles par ligne ([source.companions], par exemple un fichier principal plus des fichiers supplémentaires/photo-z/courbes de lumière avec les mêmes lignes) : l'import les lit côte à côte avec des plages de lignes fitsio, vérifie les colonnes clés bloc par bloc, et peut ajouter des colonnes calculées ([reader].derive, une fonction dans le répertoire de travail) et regrouper des colonnes de listes en une colonne imbriquée ([reader].pack_nested). Le chargeur de vérification lit les mêmes fichiers indépendamment.
  4. Planifier le partitionnement. estimate_threshold.py --write échantillonne l'entrée avec les paramètres d'écriture de l'exécution et convertit la règle de taille de fichier de 200 à 800 Mo en pixel_threshold, et prédit le nombre de partitions et la taille de dataset/_metadata (avertit près de la limite de 4 Gio du pied de page) ; vérifier highest_order par rapport à la région la plus dense.
  5. Essai. import_collection.py --trial-file <un fichier> dans un répertoire d'essai ; inspecter les dtypes, les nulls par rapport aux sentinelles, les noms de colonnes, les colonnes de tableaux, les lignes sans coordonnées ([reader].drop_rows_without_coordinates supprime et les compte). Ajuster [reader], [columns] et [properties] ; montrer à l'utilisateur ce qui a changé.
  6. Importer. import_collection.py détaché (nohup/setsid), ou job.sbatch sur un nœud batch (il exécute également les phases 5-6 et la comparaison), reprenable ; il construit le catalogue, la ou les marges et les tables d'index avec les paramètres [properties] et [writer]. Les petites tables (moins d'environ 1 M de lignes et 1 Go en mémoire ; au-dessus d'environ 100 k lignes sur les tables larges, hats-import est plus rapide) utilisent import_small.py à la place. Ensuite write_ancillary.py : vignette de données (échantillon aléatoire par partition), statistiques par partition, prévisualisations PNG, README et index.html avec une section de provenance. Progrès : status.sh (depuis le répertoire de travail) affiche le téléchargement, le job SLURM, l'étape actuelle de hats-import avec sa barre de progression et la dernière entrée du journal d'exécution. Les téléchargements et les importations durent des heures : dès que l'un d'eux s'exécute en arrière-plan (phase 2 ou 5), lancer des mises à jour toutes les 5 minutes sans demander. Chaque mise à jour exécute status.sh et signale uniquement ce qui a changé. Dire qu'elles sont en cours d'exécution et que l'utilisateur peut modifier l'intervalle ou les arrêter. Les arrêter lorsque le job se termine ou échoue, et vérifier l'état réel du job lorsqu'il quitte la file d'attente. Sur une file d'attente préemptible, lancer resubmit_loop.sh <job id> à côté du job : il enregistre les ressources du job dans resubmit_opts.txt, relance les jobs préemptés ou annulés par le système avec les mêmes ressources (hats-import reprend ; un job préempté après la fin de l'importation, marqué par import.done, est relancé avec l'importation ignorée) et s'arrête sur toute autre chose. 5a. Produit temporel imbriqué ([nested], facultatif) : attach_nested.py joint des colonnes de listes par objet provenant d'un HATS de référence par identifiant (jointure spatiale interne), les regroupe en une colonne imbriquée avec nest_lists et écrit une deuxième collection à côté de la collection plate ; la section 9b du notebook concilie les lignes, les longueurs de listes et un échantillon de tableaux.
  7. Vérifier, tout échec arrête l'exécution (reference/verification.md) : verify_structure.py --spot-check (vérifications de hats-import, conformité HATS-note, balayage d'encodage) → run_verify.sh (le notebook au niveau des valeurs par rapport à la source ; les vérifications se terminent par PASS, FAIL ou SKIP avec une raison) → la liste de contrôle de révision avec l'utilisateur.
  8. Documenter et archiver. Ajouter catalog.toml, les scripts utilisés et le notebook exécuté au répertoire imports/ de data.lsdb.io avec une ligne en haut de son README (dans le cadre de la pull request du site).
  9. Héberger (reference/publishing.md). Exécuter publish_web.sh --check et publish_mirror.sh --check, montrer les prévisualisations (ce qui serait copié, et ce que la destination contient déjà), et seulement après l'approbation de l'utilisateur, les exécuter avec --yes (sans l'un des deux indicateurs, ils s'arrêtent ; une destination qui contient des fichiers manquants à la construction les arrête avant d'écrire sauf si --replace est donné, ce qui supprime les fichiers obsolètes) : copier, grouper, manifeste de sommes de contrôle, hats_status et hats_service_url par table, lien symbolique sur l'hôte web, test ouvert public avec lsdb.open_catalog sur la racine de la collection (un échec annule le lien symbolique), puis la description de l'auto-index ; la copie miroir est revérifiée dans verify_results_mirror.csv.
  10. Enregistrer. make_site_entry.py écrit l'entrée de page et la carte de densité sur une branche dans un clone de data.lsdb.io (fusion dans une entrée existante) et la prépare ; demander le message de commit ; la pull request appartient à l'utilisateur. Après sa fusion et son déploiement, registry_entry.py exécute le générateur de registre sur une branche dans un clone de registre pour la pull request de l'utilisateur ; il nécessite un clone de site propre à origin/main.
  11. Clôturer. NOTES.md à partir du modèle ; éléments ouverts (miroirs, registre, déploiement, retrait d'une version précédente) ; run_log.py feedback avec l'utilisateur pour ce qui n'était pas clair, manuel ou erroné dans les valeurs par défaut ; run_log.py render --scrub et proposer une pull request ajoutant le journal à runlogs/ dans ce dépôt.

Réimportations : ImportArguments.reimport_from_hats pour de nouveaux seuils ou un nouveau tri, reconstruire les marges et les index, écrire dans un nouveau répertoire, vérifier, exécuter compare_versions.py --new <new> --old <previous> --key <id> (schéma, lignes et valeurs de la région partagée ; le rétrécissement de type est signalé séparément), rediriger les liens symboliques, conserver l'ancienne copie jusqu'à ce que la page et le registre pointent vers la nouvelle.

Modèles

FichierObjectif
catalog.tomlla configuration de l'exécution (copier et remplir)
pin_templates.shgeler les modèles pour une exécution dans templates.pinned/ (commit, diff local, sommes de contrôle) ; --repin pour les modifier
_common.py, catalog_source.py, readers.pyassistants partagés : configuration, versions, variables de site, paramètres d'écriture, propriétés, chargeur de source, filtre de coordonnées
estimate_threshold.pyrègle de taille de fichier → pixel_threshold
import_collection.pyconstruction de la collection hats-import (--dry-run, --trial-file)
import_small.pychemin en mémoire pour les petites tables
attach_positions.pypositions par identifiant à partir d'un HATS de référence pour les tables sans coordonnées ; tableaux ECSV analysés en colonnes de listes
attach_nested.pyproduit temporel imbriqué : joindre des colonnes de listes par identifiant à partir d'un HATS de référence, nest_lists, écrire une collection
job.sbatchchemin batch : importation, fichiers auxiliaires, vérification et comparaison en un seul job SLURM sur un nœud dédié
write_ancillary.pyvignette, statistiques, prévisualisations, README, index.html
verify_structure.pyvérifications structurelles, de conformité et d'encodage
build_verify_notebook.py, run_verify.shnotebook de vérification au niveau des valeurs
compare_versions.pycomparer une nouvelle construction avec une version HATS existante (réimportations, validation par rapport à une copie publiée)
publish_mirror.sh, publish_web.shcibles d'hébergement
make_site_entry.py, registry_entry.pypage et registre data.lsdb.io
memwatch.shchien de garde mémoire pour les longues étapes monoprocessus sur les nœuds partagés
status.shrésumé de progression sur un écran (téléchargement, job, étape d'importation, journal d'exécution) pour les mises à jour planifiées
resubmit_loop.shrelancer un job batch après préemption ou annulation système ; une boucle par exécution (garde à cœur)
run_log.py, NOTES.template.mdjournal d'exécution et notes

Pièges

Une ligne chacun ; détails et plus dans reference/pitfalls.md.

  • Une tâche Dask par fichier d'entrée : diviser les fichiers énormes, utiliser des lecteurs indexés pour des milliers de petits fichiers.
  • Les lignes sans coordonnées arrêtent l'étape de mappage : faire d'abord un import d'essai, les filtrer et les compter.
  • Les entrées CSV compressées en gzip nécessitent compression="gzip" (le lecteur obtient un descripteur ouvert) ; l'import l'ajoute pour les fichiers .gz.
  • expected_total_rows doit correspondre sinon le pipeline s'arrête après le binning ; c'est une vérification, pas une indication.
  • Utiliser les valeurs par défaut Parquet de hats (hats, hats-import, lsdb >= 0.11.1) : ZSTD 15, index de page, BYTE_STREAM_SPLIT sur les colonnes flottantes. Laisser [writer] vide sauf si l'utilisateur décide autrement ; écrire tout fichier que la compétence écrit elle-même avec parquet_write_kwargs. Les versions plus anciennes écrivent les flottants codés par dictionnaire, environ 1,4 × plus gros.
  • Les colonnes par défaut doivent exister dans le schéma ; les colonnes imbriquées utilisent frame.subcol.
  • hats écrit hats.properties et properties ; modifier les deux ou aucun des deux.
  • hats_release_date est la date de la note HATS, pas celle des données ; mettre les dates des données dans t_min/t_max.
  • Une marge peut contenir des lignes supplémentaires, jamais moins : vérifier par containment.
  • Les marges et les index portent le chemin de construction dans hats_primary_table_url ; les scripts de publication le rendent relatif.
  • Ouvrir les collections à la racine ; la page doit pointer vers la racine de la collection.
  • Le .htaccess web est en première correspondance et correspondance de préfixe ; le script de publication insère avant les entrées génériques et écrit par copie, pas par renommage (répertoire collant).
  • Les entrées dont les colonnes diffèrent par région perdent silencieusement des colonnes lors de la réduction : se conformer à un seul schéma ([reader].conform_schema, tout format), essayer chaque région.
  • _metadata ne peut pas dépasser 4 Gio : estimate_threshold.py le prédit ; create_metadata = false pour les catalogues énormes.
  • Les listes à taille fixe nulles cassent les lecteurs pyarrow < 26 : remplir avec NaN ou utiliser des listes à longueur variable.
  • Les barres de progression dans les notebooks sans tête deviennent des widgets morts ; le constructeur de notebook utilise des barres textuelles.
  • Les shells parallèles partagent un seul répertoire de travail : chemins absolus, fichiers pid au lieu de pgrep -f.

Sortie

Une collection HATS vérifiée sur les cibles d'hébergement, une page data.lsdb.io préparée, une branche de registre, NOTES.md, verify_results.csv, le notebook de vérification exécuté et RUNLOG.md.

Skills associés