Community写作与编辑github.com

astronomy-commons/lsdb-agent-skills

将外部天文星表导入 HATS,验证其与原始数据的一致性,编写文档,托管并在 data.lsdb.io 上注册,遵循 LSDB 团队的约定。

lsdb-agent-skills 是什么?

该技能(/hats-publish)能够将外部巡天星表发布版本完整转换为 HATS 集合(包括星表、边缘表和索引表),并自动完成与源文件的验证、文档编写、托管和注册。它整合了 hats-import 和 LSDB 文档、Rubin 导入流程以及团队公共议题和导入笔记本中记录的约定,所有站点特定值都来自 `CONFIG.md` 所述的站点文件,所有引用均为公开 URL。 该技能主要支持在 HATS 框架下工作,适用于 Claude Code 等 AI Agent 平台。其工作流包括环境准备、决策访谈、数据获取、分区规划、试导入、正式导入、验证、文档归档、托管发布和注册等十个阶段,每个阶段都会在运行日志中记录起止。 该技能特别擅长处理各种复杂情况,例如:无坐标表格通过参考 HATS 集合按 ID 查找位置、并行 FITS 文件的逐行读取与合并、嵌套时间序列产品的连接、以及通过自动重提任务和内存监控应对计算节点抢占或系统取消。重新导入时,它会比较新旧版本的模式、行和共享区域的值,并逐步更新符号链接。 用户输入源文件或 URL 及其格式、巡天、发布版本、数据模型页面、论文、致谢和许可等信息,技能通过决策访谈引导完成所有配置,并将其写入 `catalog.toml` 文件中,确保每次运行可重现。

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

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

/hats-publish

将巡天星表发布版本转换为 HATS 集合(星表 + 边缘表 + 索引表),并与源文件进行验证、编写文档、托管和注册。该流程整合了 hats-import 和 lsdb 文档、Rubin 导入流程(https://github.com/lincc-frameworks/rubin-dash)以及团队在公开议题和归档导入笔记本中记录的约定; 每个站点特定值均来自 CONFIG.md 中描述的站点文件,每个引用均为公开 URL,且此处不涉及任何机器、人员或数据集的名称。

一次运行 = 一个 catalog.toml(从 templates/catalog.toml 复制到工作目录)。每个模板都会读取它,其中相对路径相对于存放它的目录解析,且一次运行可完全由此文件重现。请保留工作目录:其中包含配置、日志、执行的验证笔记本和运行日志。

每次运行开始时固定模板:在工作目录中执行 T=$(bash <skill>/templates/pin_templates.sh),将其以只读方式及其 git 提交记录复制到 templates.pinned/,之后每一步(包括 job.sbatch 和 resubmit_loop.sh)都运行 $T/...。这样,git pull 或技能的编辑不会更改正在运行的导入,并且 README 会注明构建该星表的提交。若要更改运行中的代码,请使用 pin_templates.sh --repin。

何时使用

要发布新的巡天数据版本;使用更好的分区、写入器设置或元数据重新导入已有的 HATS 星表;或请求验证 HATS 副本是否与源数据匹配。

输入(仅当未设置时询问)

源文件或 URL 及其格式;巡天名称、发布版本、数据模型页面、论文、致谢和许可;是否已有 HATS 版本(查看 data.lsdb.io 的 data/ 目录树和 imports/README.md);坐标列和 ID 列。其他所有内容均在下面的访谈中确定。

流程

按顺序的阶段。加粗步骤会暂停并等待用户。每个阶段以运行日志条目(run_log.py start|end <phase>)开始和结束;模板在自身运行时自动执行此操作。

  1. 环境。 创建或更新环境,安装最新发布的 hats、lsdb、hats-import(pip install -U hats lsdb hats-import nested-pandas pyarrow astropy fitsio jupyter),打印版本,简要阅读发布说明以了解格式变更。将 HATS_PUBLISH_SITE_ENV 指向您的站点文件(CONFIG.md)。使用这些库的模板在低于最低版本时会拒绝运行,并在有新版本发布时发出警告。
  2. 决策访谈(reference/decisions.md):九个组,每次几个问题,每个问题都有推荐默认值和后果。将答案写入 catalog.toml 和运行日志(run_log.py decision)。然后展示计划:路径、读取器、资源、分区、写入器设置、名称、目标。
  3. 获取数据。下载到原始目录,验证校验和和归档完整性(gzip -t),记录每个文件的 sha256 到 [source].sha256,并将数据模型页面保存在数据旁边。对照归档的文件列表([source].expected_files)统计文件数量,列出确切文件名,切勿对整个可能包含重新下载副本的目录使用简单通配符。对于数千个小文件,为索引式读取器编写索引文件。后台运行的下载会将其 PID 写入工作目录中的 download.pid,以便 status.sh 报告其状态。 2a. 无坐标的表([source.positions_from]):attach_positions.py 在参考 HATS 集合(其索引表)中按 ID 查找坐标位置,并将源数据写为带有 ra/dec 的 Parquet 文件;然后导入读取这些文件。带有 ECSV 头部的 CSV 文件中的数组列([reader].ecsv_header = true)在读取时解析为列表列。 2b. 被分割成行并行 FITS 文件的单个表([source.companions],例如,一个主文件加上包含相同行的额外/光红移/光变曲线文件):导入使用 fitsio 行范围并行读取它们,逐块检查键列,并可以添加计算列([reader].derive,工作目录中的一个函数),并将列表列打包为一个嵌套列([reader].pack_nested)。验证加载器独立读取相同的文件。
  4. 规划分区。estimate_threshold.py --write 使用运行时的写入器设置对输入进行采样,并将 200–800 MB 文件大小规则转换为 pixel_threshold,并预测分区数和 dataset/_metadata 的大小(接近 4 GiB 页脚限制时发出警告);对照最密集区域检查 highest_order。
  5. 试导入。import_collection.py --trial-file <一个文件> 到试导入目录;检查数据类型、空值与哨兵值、列名、数组列、无坐标行([reader].drop_rows_without_coordinates 删除并计数)。调整 [reader]、[columns] 和 [properties];向用户展示更改内容。
  6. 正式导入。import_collection.py 后台运行(nohup/setsid),或者使用 job.sbatch 在批处理节点上运行(它同时运行阶段 5–6 和比较),可恢复执行;它构建星表、边缘表和索引表,使用 [properties] 和 [writer] 设置。对于小型表(内存中约 1 M 行和 1 GB 以下;对于宽表,超过约 100 k 行时 hats-import 更快),使用 import_small.py 代替。然后运行 write_ancillary.py:数据缩略图(每个分区的随机样本)、每个分区统计信息、PNG 预览、README 和带有来源部分 的 index.html。 进度:status.sh(从工作目录运行)打印下载状态、SLURM 作业、当前 hats-import 阶段及其进度条,以及最新的运行日志条目。下载和导入可能运行数小时:一旦有任务在后台运行(阶段 2 或 5),立即开始每 5 分钟无询问更新一次。每次更新运行 status.sh 并仅报告更改的内容。告知用户任务正在运行,并且可以更改间隔或停止它们。当任务完成或失败时停止更新,并在任务离开队列时检查其实际状态。在可抢占队列上,在作业旁边启动 resubmit_loop.sh <job id>:它记录作业的资源到 resubmit_opts.txt,以相同资源重新提交被抢占或系统取消的作业(hats-import 可恢复;如果在导入完成后被抢占,由 import.done 标记,则重新提交时跳过导入),并在遇到其他情况时停止。 5a. 嵌套时间序列产品([nested],可选):attach_nested.py 通过 ID(空间内连接)从参考 HATS 连接每个对象的列表列,使用 nest_lists 打包为一个嵌套列,并写入扁平集合旁边的第二个集合;笔记本的第 9b 节会协调行数、列表长度和数组样本。
  7. 验证,任何失败都会停止运行(reference/verification.md): verify_structure.py --spot-check(hats-import 的检查、HATS 备注合规性、编码扫描)→ run_verify.sh(针对源数据的值级笔记本;检查结果为 PASS、FAIL 或 SKIP,并附有原因)→ 与用户一起查看检查清单。
  8. 文档和归档。将 catalog.toml、使用的脚本和执行的笔记本添加到 data.lsdb.io 的 imports/ 目录,并在其 README 顶部添加一行(作为站点拉取请求的一部分)。
  9. 托管(reference/publishing.md)。运行 publish_web.sh --check 和 publish_mirror.sh --check,显示预览(将复制什么,以及目标上已有哪些内容),仅在用户批准后使用 --yes 运行它们(如果没有这两个标志之一,它们会停止;如果目标包含构建所缺少的文件,它们会在写入前停止,除非给出 --replace 来删除过时文件):复制、分组、校验和清单、每个表的 hats_status 和 hats_service_url、Web 主机上的符号链接、使用 lsdb.open_catalog 在集合根目录上进行公开开放测试(失败则回滚符号链接),然后是自动索引描述;镜像副本会重新验证到 verify_results_mirror.csv。
  10. 注册。 make_site_entry.py 在 data.lsdb.io 克隆的一个分支上写入页面条目和密度图(合并到现有条目中)并暂存更改;询问提交信息;拉取请求由用户创建。在合并并部署后,registry_entry.py 在注册表克隆的一个分支上运行注册表生成器,以供用户创建拉取请求;它需要一个指向 origin/main 的干净站点克隆。
  11. 收尾。从模板生成 NOTES.md;开放事项(镜像、注册表、部署、旧版本的退役);与用户一起运行 run_log.py feedback,了解默认值中哪些不清晰、手动或错误;run_log.py render --scrub 并提供拉取请求,将日志添加到此仓库的 runlogs/ 目录。

重新导入:使用 ImportArguments.reimport_from_hats 设置新的阈值或排序,重建边缘表和索引,写入新目录,验证,运行 compare_versions.py --new <new> --old <previous> --key <id>(共享区域的模式、行和值;类型收窄单独报告),重新指向符号链接,在页面和注册表指向新版本之前保留旧副本。

模板

文件用途
catalog.toml运行配置(复制并填写)
pin_templates.sh为单次运行固定模板到 templates.pinned/(提交、本地差异、校验和);使用 --repin 更改
_common.py、catalog_source.py、readers.py共享帮助程序:配置、版本、站点变量、写入器设置、属性、源加载器、坐标过滤器
estimate_threshold.py文件大小规则 → pixel_threshold
import_collection.pyhats-import 集合构建(--dry-run、--trial-file)
import_small.py小型表的内存中路径
attach_positions.py对于无坐标表,从参考 HATS 按 ID 查找位置;将 ECSV 数组解析为列表列
attach_nested.py嵌套时间序列产品:按 ID 从参考 HATS 连接列表列,nest_lists,写入集合
job.sbatch批处理路径:导入、辅助文件、验证和比较作为一个 SLURM 作业在专用节点上运行
write_ancillary.py缩略图、统计信息、预览、README、index.html
verify_structure.py结构、合规性和编码检查
build_verify_notebook.py、run_verify.sh值级验证笔记本
compare_versions.py比较新构建与现有 HATS 版本(重新导入、与已发布副本的验证)
publish_mirror.sh、publish_web.sh托管目标
memwatch.sh共享节点上长时间单进程步骤的内存监控
status.sh单屏进度摘要(下载、作业、导入阶段、运行日志),用于定期更新
resubmit_loop.sh在抢占或系统取消后重新提交批处理作业;每次运行一个循环(心跳防护)
run_log.py、NOTES.template.md运行日志和笔记

注意事项

每条一行;详细信息和更多内容请参阅 reference/pitfalls.md。

  • 每个输入文件一个 Dask 任务:拆分巨大文件,对数千个小文件使用索引读取器。
  • 无坐标行会停止映射阶段:先试导入,然后过滤并计数。
  • Gzip 压缩的 CSV 输入需要 compression="gzip"(读取器会获得一个已打开的文件句柄);导入会为 .gz 文件自动添加。
  • expected_total_rows 必须匹配,否则流程在分箱后停止;它是一个检查,而非提示。
  • 使用 hats Parquet 默认值(hats、hats-import、lsdb >= 0.11.1):ZSTD 15、页面索引、对浮点列使用 BYTE_STREAM_SPLIT。除非用户另有决定,否则将 [writer] 留空;技能自身写入的任何文件都使用 parquet_write_kwargs。旧版本将浮点数使用字典编码,大约大 1.4 倍。
  • 默认列必须存在于模式中;嵌套列使用 frame.subcol。
  • hats 写入 hats.properties 和 properties;两者都编辑或都不编辑。
  • hats_release_date 是 HATS 备注的日期,而非数据日期;将数据日期放在 t_min/t_max 中。
  • 边缘表可能包含额外行,但绝不能少:通过包含关系验证。
  • 边缘表和索引表在 hats_primary_table_url 中包含构建路径;发布脚本会使其变为相对路径。
  • 在根目录打开集合;页面必须指向集合根目录。
  • Web 的 .htaccess 是首次匹配和前缀匹配;发布脚本在通用条目之前插入,并通过复制而非重命名写入(粘滞目录)。
  • 输入中按区域不同的列会在归并时静默丢失:统一为一种模式([reader].conform_schema,任何格式),对每个区域进行试导入。
  • _metadata 不能超过 4 GiB:estimate_threshold.py 会预测其大小;对于巨大的星表,设置 create_metadata = false。
  • 空值的固定长度列表会破坏 pyarrow < 26 的读取器:用 NaN 填充或使用可变长度列表。
  • 无头笔记本中的进度条会变成死控件;笔记本构建器使用文本进度条。
  • 并行的 shell 共享一个工作目录:使用绝对路径,使用 PID 文件而非 pgrep -f。

输出

托管目标上的一个经过验证的 HATS 集合、一个暂存的 data.lsdb.io 页面、一个注册表分支、NOTES.md、verify_results.csv、执行的验证笔记本和 RUNLOG.md。

相关技能