Community寫作與編輯github.com

astronomy-commons/lsdb-agent-skills

將外部天文目錄匯入 HATS,驗證其與原始資料的一致性,建立文件、託管並在 data.lsdb.io 上註冊,遵循 LSDB 團隊的慣例。

lsdb-agent-skills 是什麼?

此技能(`/hats-publish`)為自動化將天文巡天目錄發布為 HATS(Hierarchical Adaptive Survey System)集合的完整流程。它處理從原始檔案匯入、驗證、文件化、託管到在 data.lsdb.io 上註冊的所有步驟,並將 hats-import、lsdb 文件及 Rubin 匯入管線(即 lincc-frameworks/rubin-dash)的最佳實踐編碼為可重複的範本。每個執行作業由一個 `catalog.toml` 檔案驅動,並在隔離的工作目錄中執行,確保可重現性。該技能支援多種輸入格式(CSV、FITS、Parquet)、無座標表格的位置附加、巢狀時間序列產品,以及批次節點上的可恢復作業。主要適用於發布新的巡天資料、重新匯入既有 HATS 目錄以改善分割或中繼資料,以及驗證 HATS 副本是否與原始資料匹配。核心功能包括:決策訪談以引導使用者完成設定、自動下載與完整性檢查、智慧型分區估算、試匯入階段以驗證資料型別與空值、完整的匯入與邊際/索引建立、多層次驗證(結構化、數值與使用者審查),以及最終的託管與註冊步驟。它包含強大的監控與恢復機制,例如自動狀態更新、預佔用佇列的重新提交循環,以及全面的執行日誌記錄。值得注意的是,此技能不適用於 Rubin Butler 產品(因其有獨立管線),也不適用於已存在於 HATS 中、僅需建立網頁或鏡像的目錄(此類情況應直接使用 `reference/publishing.md`)。

相容平台~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) 將它們以唯讀方式複製到 templates.pinned/,並包含 git 提交 ID,後續每個步驟(包括 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)進行比對,並列出確切的檔名,切勿對可能包含重新下載副本的目錄使用裸 glob。 對於數千個小檔案,為索引讀取器寫入索引檔案。 在背景執行的下載會將其 PID 寫入工作目錄中的 download.pid,以便 status.sh 可以報告。 2a. 無座標的表([source.positions_from]):attach_positions.py 透過 ID 在參考 HATS 集合(其索引表)中查詢位置, 並將原始資料寫入包含 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 <一個檔案> 匯入到試行目錄;檢查 dtype、空值與 替代值、欄位名稱、陣列欄位、無座標的列([reader].drop_rows_without_coordinates 會丟棄並計數)。調整 [reader]、[columns] 和 [properties];向使用者顯示更改了什麼。
  6. 匯入。在背景執行 import_collection.py(nohup/setsid),或在批次節點上執行 job.sbatch(它也執行 第 5–6 階段和比較),可恢復;它使用 [properties] 和 [writer] 設定建置目錄、 邊際和索引表。小型表(約低於 1M 行且在記憶體中低於 1 GB;在寬表上 hats-import 更快,約高於 100k 行)則改用 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 note 合規性、編碼掃描)→ 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 對集合根目錄進行公開開放測試(失敗會復原符號連結),然後是 autoindex 描述; 鏡像副本會重新驗證到 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 <新> --old <舊> --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巢狀時間序列產品:從參考 HATS 透過 ID 加入列表欄位、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託管目標
make_site_entry.py、registry_entry.pydata.lsdb.io 頁面和註冊表
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 note 的日期,不是資料的日期;將資料日期放在 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。

相關技能