/hats-publish
Wandelt die Katalogversion einer Himmelsdurchmusterung in eine HATS-Sammlung um (Katalog + Margin + Indextabellen), die gegen die Quelldateien verifiziert, dokumentiert, gehostet und registriert wird. Die Prozedur kodiert die hats-import- und lsdb-Dokumentation, die Rubin-Importpipeline (https://github.com/lincc-frameworks/rubin-dash) und die in öffentlichen Issues und archivierten Import-Notebooks festgehaltenen Teamkonventionen; jeder standortspezifische Wert stammt aus der Standortdatei, die in CONFIG.md beschrieben wird, jede Referenz ist eine öffentliche URL, und nichts hier nennt eine Maschine, eine Person oder einen Datensatz.
Ein Durchlauf = eine catalog.toml (kopiert aus templates/catalog.toml in ein Arbeitsverzeichnis). Jede Vorlage liest sie, relative Pfade darin werden relativ zum Verzeichnis aufgelöst, das sie enthält, und ein Durchlauf ist allein aus dieser Datei reproduzierbar. Behalten Sie das Arbeitsverzeichnis: Es enthält die Konfiguration, die Protokolle, das ausgeführte Verifizierungs-Notebook und das Laufprotokoll.
Fixieren Sie die Vorlagen zu Beginn jedes Durchlaufs: T=$(bash <skill>/templates/pin_templates.sh) im Arbeitsverzeichnis kopiert sie schreibgeschützt nach templates.pinned/ mit dem Git-Commit, und jeder spätere Schritt (job.sbatch und resubmit_loop.sh inbegriffen) führt $T/... aus. Ein Git-Pull oder eine Bearbeitung des Skills kann dann einen laufenden Import nicht ändern, und die README nennt den Commit, der den Katalog erstellt hat. Ändern Sie den Code eines Laufs nur mit pin_templates.sh --repin.
Wann verwenden
Eine neue Durchmusterungsversion zur Veröffentlichung; ein Neuimport eines bestehenden HATS-Katalogs mit besserer Partitionierung, Writer-Einstellungen oder Metadaten; eine Anfrage zur Überprüfung, ob eine HATS-Kopie mit ihrer Quelle übereinstimmt.
Eingaben (nur fragen, wenn nicht gesetzt)
Quelldateien oder URLs und deren Format; Umfrage, Version, Datenmodellseite, Paper, Danksagung und Lizenz; ob bereits eine HATS-Version existiert (sehen Sie im data/-Baum von data.lsdb.io und in imports/README.md nach); die Koordinaten- und ID-Spalten. Alles andere wird im folgenden Interview entschieden.
Ablauf
Phasen in Reihenfolge. Fettgedruckte Schritte stoppen und warten auf den Benutzer. Jede Phase beginnt und endet mit einem Laufprotokolleintrag (run_log.py start|end <phase>); die Vorlagen erledigen dies selbst, wo sie ausgeführt werden.
- Umgebung. Erstellen oder aktualisieren Sie eine Umgebung mit den neuesten veröffentlichten
hats,lsdb,hats-import(pip install -U hats lsdb hats-import nested-pandas pyarrow astropy fitsio jupyter), geben Sie die Versionen aus, überfliegen Sie die Versionshinweise auf Formatänderungen. Setzen SieHATS_PUBLISH_SITE_ENVauf Ihre Standortdatei (CONFIG.md). Die Vorlagen, die die Bibliotheken verwenden, weigern sich, unter den Mindestversionen zu laufen, und warnen, wenn eine neuere Version existiert. - Entscheidungsinterview (
reference/decisions.md): die neun Gruppen, ein paar Fragen auf einmal, jede mit ihrer empfohlenen Voreinstellung und Konsequenzen. Schreiben Sie die Antworten incatalog.tomlund das Laufprotokoll (run_log.py decision). Zeigen Sie dann den Plan an: Route, Reader, Ressourcen, Partitionierung, Writer-Einstellungen, Namen, Ziele. - Erwerben. Laden Sie in das Rohverzeichnis herunter, überprüfen Sie Prüfsummen und Archivintegrität (
gzip -t), zeichnen Sie SHA256 jeder Datei in[source].sha256auf und speichern Sie die Datenmodellseite neben den Daten. Zählen Sie die Dateien gegen die Auflistung des Archivs ([source].expected_files) und listen Sie exakte Dateinamen auf, niemals einen einfachen Glob über ein Verzeichnis, das möglicherweise erneut heruntergeladene Kopien enthält. Für Tausende kleiner Dateien schreiben Sie Indexdateien für die indizierten Reader. Ein im Hintergrund laufender Download schreibt seine PID indownload.pidim Arbeitsverzeichnis, damitstatus.shihn melden kann. 2a. Tabellen ohne Koordinaten ([source.positions_from]):attach_positions.pysucht die Positionen anhand der ID in einer Referenz-HATS-Sammlung (ihrer Indextabelle) und schreibt die Quelle als Parquet mitra/dec; der Import liest dann diese Dateien. ECSV-überschriebene CSV mit Array-Spalten ([reader].ecsv_header = true) wird auf dem Weg in Listenspalten geparst. 2b. Eine Tabelle, die in zeilenparallele FITS-Dateien aufgeteilt ist ([source.companions], z.B. eine Hauptdatei plus Extra-/Photo-z-/Lichtkurvendateien mit denselben Zeilen): Der Import liest sie nebeneinander mit fitsio-Zeilenbereichen, überprüft die Schlüsselspalten chunkweise und kann berechnete Spalten ([reader].derive, eine Funktion im Arbeitsverzeichnis) hinzufügen und Listenspalten in eine verschachtelte Spalte packen ([reader].pack_nested). Der Verifizierungs-Loader liest dieselben Dateien unabhängig. - Planen Sie die Partitionierung.
estimate_threshold.py --writesampelt die Eingabe mit den Writer-Einstellungen des Laufs und konvertiert die 200–800 MB Dateigrößenregel inpixel_thresholdund prognostiziert die Partitionsanzahl und die Größe vondataset/_metadata(warnt in der Nähe des 4 GiB Footer-Limits); überprüfen Siehighest_ordergegen die dichteste Region. - Probelauf.
import_collection.py --trial-file <eine Datei>in ein Testverzeichnis; überprüfen Sie dtypes, Nullwerte versus Sentinelwerte, Spaltennamen, Array-Spalten, Zeilen ohne Koordinaten ([reader].drop_rows_without_coordinatesverwirft und zählt sie). Passen Sie[reader],[columns]und[properties]an; zeigen Sie dem Benutzer, was sich geändert hat. - Import.
import_collection.pyim Hintergrund (nohup/setsid) oderjob.sbatchauf einem Batch-Knoten (es führt auch die Phasen 5–6 und den Vergleich aus), wiederaufnehmbar; es erstellt den Katalog, die Margin(s) und die Indextabellen mit den[properties]- und[writer]-Einstellungen. Kleine Tabellen (unter etwa 1 M Zeilen und 1 GB im Speicher; über etwa 100 k Zeilen bei breiten Tabellen ist hats-import schneller) verwenden stattdessenimport_small.py. Dannwrite_ancillary.py: Datenminiaturansicht (Zufallsstichprobe pro Partition), Statistiken pro Partition, PNG-Vorschauen, README undindex.htmlmit einem Abschnitt zur Herkunft. Fortschritt:status.sh(aus dem Arbeitsverzeichnis) gibt den Download, den SLURM-Job, die aktuelle hats-import-Stufe mit ihrem Fortschrittsbalken und den neuesten Laufprotokolleintrag aus. Downloads und Importe laufen stundenlang: Sobald einer im Hintergrund läuft (Phase 2 oder 5), starten Sie Aktualisierungen alle 5 Minuten ohne Nachfrage. Jede Aktualisierung führtstatus.shaus und meldet nur, was sich geändert hat. Sagen Sie, dass sie laufen und dass der Benutzer das Intervall ändern oder sie stoppen kann. Stoppen Sie sie, wenn der Job beendet ist oder fehlschlägt, und überprüfen Sie den tatsächlichen Zustand des Jobs, wenn er die Warteschlange verlässt. Starten Sie in einer vorzeitig beendbaren Warteschlangeresubmit_loop.sh <Job-ID>neben dem Job: Es zeichnet die Ressourcen des Jobs inresubmit_opts.txtauf, reicht vorzeitig beendete oder systemseitig abgebrochene Jobs mit denselben Ressourcen erneut ein (hats-import setzt fort; ein Job, der nach Abschluss des Imports vorzeitig beendet wurde, gekennzeichnet durchimport.done, wird mit übersprungenem Import erneut eingereicht) und stoppt bei allem anderen. 5a. Verschachteltes Zeitreihenprodukt ([nested], optional):attach_nested.pyverbindet objektweise Listenspalten aus einem Referenz-HATS anhand der ID (räumlicher Inner Join), packt sie mitnest_listsin eine verschachtelte Spalte und schreibt eine zweite Sammlung neben der flachen; Abschnitt 9b des Notebooks gleicht Zeilen, Listenlängen und eine Stichprobe von Arrays ab. - Verifizieren, jeder Fehler stoppt den Lauf (
reference/verification.md):verify_structure.py --spot-check(hats-import-Prüfungen, HATS-Note-Konformität, Codierungsdurchlauf) →run_verify.sh(das wertbezogene Notebook gegen die Quelle; Prüfungen enden mit PASS, FAIL oder SKIP mit Begründung) → die Überprüfungs-Checkliste mit dem Benutzer. - Dokumentieren und archivieren. Fügen Sie
catalog.toml, die verwendeten Skripte und das ausgeführte Notebook zumimports/-Verzeichnis von data.lsdb.io hinzu, mit einer Zeile oben in dessen README (Teil des Site-Pull-Requests). - Hosten (
reference/publishing.md). Führen Siepublish_web.sh --checkundpublish_mirror.sh --checkaus, zeigen Sie die Vorschauen (was kopiert würde und was das Ziel bereits enthält) und führen Sie sie erst nach Zustimmung des Benutzers mit--yesaus (ohne eines der beiden Flags stoppen sie; ein Ziel, das Dateien enthält, die der Build nicht hat, stoppt sie vor dem Schreiben, es sei denn,--replacewird angegeben, was die veralteten Dateien löscht): Kopieren, gruppieren, Prüfsummen-Manifest,hats_statusundhats_service_urlpro Tabelle, Symlink auf dem Web-Host, öffentlicher offener Test mitlsdb.open_catalogauf dem Sammlungsstamm (ein Fehler macht den Symlink rückgängig), dann die Autoindex-Beschreibung; die Spiegelkopie wird erneut inverify_results_mirror.csvverifiziert. - Registrieren.
make_site_entry.pyschreibt den Seiteneintrag und die Dichtekarte in einen Branch in einem Klon von data.lsdb.io (Zusammenführung in einen vorhandenen Eintrag) und stellt es bereit; nach der Commit-Nachricht fragen; der Pull-Request liegt beim Benutzer. Nachdem er zusammengeführt und bereitgestellt wurde, führtregistry_entry.pyden Registry-Generator auf einem Branch in einem Registry-Klon für den Pull-Request des Benutzers aus; es erfordert einen sauberen Site-Klon beiorigin/main. - Abschließen.
NOTES.mdaus der Vorlage; offene Punkte (Spiegel, Registry, Bereitstellung, Stilllegung einer vorherigen Version);run_log.py feedbackmit dem Benutzer für das, was unklar, manuell oder falsch an den Voreinstellungen war;run_log.py render --scrubund einen Pull-Request anbieten, der das Protokoll zurunlogs/in diesem Repository hinzufügt.
Neuimporte: ImportArguments.reimport_from_hats für neue Schwellenwerte oder Sortierung, Margins und Indizes neu erstellen, in ein neues Verzeichnis schreiben, verifizieren, compare_versions.py --new <neu> --old <vorherig> --key <id> ausführen (Schema, Zeilen und Werte der gemeinsamen Region; Typverengung wird separat gemeldet), Symlinks neu ausrichten, die alte Kopie behalten, bis die Seite und die Registry auf die neue verweisen.
Vorlagen
| Datei | Zweck |
|---|---|
catalog.toml | die Laufkonfiguration (kopieren und ausfüllen) |
pin_templates.sh | Vorlagen für einen Lauf in templates.pinned/ fixieren (Commit, lokaler Diff, Prüfsummen); --repin, um sie zu ändern |
_common.py, catalog_source.py, readers.py | gemeinsame Helfer: Konfiguration, Versionen, Standortvariablen, Writer-Einstellungen, Eigenschaften, Quellen-Loader, Koordinatenfilter |
estimate_threshold.py | Dateigrößenregel → pixel_threshold |
import_collection.py | hats-import-Sammlungsaufbau (--dry-run, --trial-file) |
import_small.py | In-Memory-Route für kleine Tabellen |
attach_positions.py | Positionen anhand der ID aus einem Referenz-HATS für Tabellen ohne Koordinaten; ECSV-Arrays in Listenspalten geparst |
attach_nested.py | verschachteltes Zeitreihenprodukt: Listenspalten nach ID aus einem Referenz-HATS verbinden, nest_lists, eine Sammlung schreiben |
job.sbatch | Batch-Route: Import, Hilfsdateien, Verifizierung und Vergleich als ein SLURM-Job auf einem dedizierten Knoten |
write_ancillary.py | Miniaturansicht, Statistiken, Vorschauen, README, index.html |
verify_structure.py | strukturelle, Konformitäts- und Codierungsprüfungen |
build_verify_notebook.py, run_verify.sh | wertbezogenes Verifizierungs-Notebook |
compare_versions.py | Vergleich eines Neubaus mit einer bestehenden HATS-Version (Neuimporte, Validierung gegen eine veröffentlichte Kopie) |
publish_mirror.sh, publish_web.sh | Hosting-Ziele |
make_site_entry.py, registry_entry.py | data.lsdb.io-Seite und Registry |
memwatch.sh | Speicherüberwachung für lange Einzelprozess-Schritte auf gemeinsam genutzten Knoten |
status.sh | einseitige Fortschrittsübersicht (Download, Job, Importphase, Laufprotokoll) für geplante Aktualisierungen |
resubmit_loop.sh | erneutes Einreichen eines Batch-Jobs nach Preemption oder Systemabbruch; eine Schleife pro Lauf (Heartbeat-Guard) |
run_log.py, NOTES.template.md | Laufprotokoll und Notizen |
Fallstricke
Eine Zeile pro Stück; Details und mehr in reference/pitfalls.md.
- Eine Dask-Aufgabe pro Eingabedatei: riesige Dateien aufteilen, indizierte Reader für Tausende kleiner Dateien verwenden.
- Zeilen ohne Koordinaten stoppen die Mapping-Phase: zuerst Probeimport, filtern und zählen.
- Gzip-komprimierte CSV-Eingaben benötigen
compression="gzip"(der Reader erhält einen offenen Handle); der Import fügt es für.gz-Dateien hinzu. expected_total_rowsmuss übereinstimmen, sonst stoppt die Pipeline nach dem Binning; es ist eine Prüfung, kein Hinweis.- Verwenden Sie die hats-Parquet-Standardeinstellungen (hats, hats-import, lsdb >= 0.11.1): ZSTD 15, Seitenindex, BYTE_STREAM_SPLIT auf Float-Spalten. Lassen Sie
[writer]leer, es sei denn, der Benutzer entscheidet anders; schreiben Sie jede Datei, die das Skill selbst schreibt, mitparquet_write_kwargs. Ältere Versionen schreiben Floats dictionary-kodiert, etwa 1,4× größer. - Standardspalten müssen im Schema vorhanden sein; verschachtelte Spalten verwenden
frame.subcol. - hats schreibt
hats.propertiesundproperties; bearbeiten Sie beide oder keines. hats_release_dateist das Datum der HATS-Notiz, nicht das der Daten; setzen Sie Daten-Daten int_min/t_max.- Ein Margin kann zusätzliche Zeilen enthalten, niemals weniger: durch Enthaltensein verifizieren.
- Margins und Indizes tragen den Build-Pfad in
hats_primary_table_url; die Veröffentlichungsskripte machen ihn relativ. - Öffnen Sie Sammlungen am Stamm; die Seite muss auf den Sammlungsstamm zeigen.
- Die Web-
.htaccessist First-Match und Prefix-Match; das Veröffentlichungsskript fügt vor generischen Einträgen ein und schreibt durch Kopie, nicht durch Umbenennung (sticky directory). - Eingaben, deren Spalten sich nach Region unterscheiden, verlieren beim Reduzieren stillschweigend Spalten: an ein Schema anpassen (
[reader].conform_schema, beliebiges Format), jede Region probeweise importieren. _metadatadarf 4 GiB nicht überschreiten:estimate_threshold.pyprognostiziert es;create_metadata = falsefür riesige Kataloge.- Null-Fixed-Size-Listen brechen pyarrow < 26 Reader: mit NaN füllen oder variable-length Listen verwenden.
- Fortschrittsbalken in kopflosen Notebooks werden zu toten Widgets; der Notebook-Builder verwendet Textbalken.
- Parallele Shells teilen sich ein Arbeitsverzeichnis: absolute Pfade, PID-Dateien anstelle von
pgrep -f.
Ausgabe
Eine verifizierte HATS-Sammlung auf den Hosting-Zielen, eine bereitgestellte data.lsdb.io-Seite, ein Registry-Branch, NOTES.md, verify_results.csv, das ausgeführte Verifizierungs-Notebook und RUNLOG.md.