Internal catalogue and result schemas
Hebog's internal schemas describe scientific concepts independently of PyBDSF, LSMTool, Rapthor, FITS column names or a scheduler. They are immutable Pydantic records that reject unknown fields and unsupported versions and serialize to canonical JSON. Round-trip and compatibility tests are the evidence for each one. A semantic change bumps the integer version and updates this page; stale development products are rejected and recreated, never migrated (ADR-006). The public meaning of every product column is in the output reference; this page holds the rules the records enforce.
Versions
| Record | Version | Module |
|---|---|---|
SourceCatalogue |
3 | hebog.data_models.catalogues |
Catalogue FITS encoding (HBGSCHE header card) |
4 | hebog.io.materialization |
SourceFinderResult, MaterializedProduct, SourceFinderRequest |
3, 1, 2 | hebog.data_models.source_finding |
PublicSourceFindingDiagnostics (the diagnostics product) |
13 | hebog.data_models.source_finding |
PublicSourceFindingProvenance, ContinuumSourceFindingDiagnostics, SourceFindingDiagnostics, SourceScaleProvenance |
4, 2, 1, 1 | hebog.data_models.source_finding |
ScaleDetection, CrossScaleAssociation |
1, 3 | hebog.data_models.multiscale |
ProductChunk, Zarr storage schema, generation marker |
2, 3, 1 | hebog.data_models.products, hebog.io.zarr, hebog.data_models.generations |
| Partition manifest | 1 | hebog.data_models.partitioning |
| Staging owner record | 1 | hebog.io.staging |
| Rapthor adapter records | 2 | hebog.adapters.rapthor |
| Rapthor dual-run comparison report | 1 | hebog.adapters.rapthor_comparison |
Source catalogue
SourceCatalogue is one MFS catalogue: a stable identity, the icrs frame
and position epoch, one reference frequency in hertz, and ordered
collections of islands, source candidates and fitted Gaussian components.
- The three identities are distinct. A
SourceCandidatehas a primaryIslandand zero or moreadditional_island_ids; aGaussianComponentbelongs to one source and a subset of its islands. References are validated and IDs are unique and in canonical order, so completion order cannot change the persisted bytes. - An island may have no accepted source, and a source may have no Gaussian.
A component whose fit is not admitted keeps its detected identity and the
source keeps its independent aperture measurement, with the reason
(
fit-model-inadequate,fit-linear-algebra-failure, …) in the diagnostics. No zero-valued fit is fabricated, and a source's member count need not equal its Gaussian rows. - Units are in field names: right ascension in
[0, 360)and declination in[-90, 90]degrees; FWHM axes in degrees with the angle in[0, 180); peak flux and local RMS in Jy/beam; integrated flux in Jy; frequency in Hz. - Unavailable uncertainties and unavailable or unresolved shapes are
None, never NaN or zero. A major-axis-only deconvolution stores one positive major FWHM, a null ellipse and themajor-axis-onlyflag. A fitted Gaussian always has a fitted shape; a source-level shape may be unavailable. GaussianComponent.fluxis the fitted model's infinite-plane integral.SourceCandidate.association_aperture_integrated_flux_jyis the source's signed aperture over its own footprint (ASSOCIATION_APERTURE_FLUX), to which no fit contributes and which thecompactprofile leaves unavailable. Estimator flags keep the two distinct.SpectralModeldistinguishes a reference-frequency-only MFS measurement from a log-polynomial fit whose coefficientkmultiplieslog(frequency / reference_frequency) ** (k + 1). Every row uses the catalogue's one reference frequency; per-channel catalogues are outside the contract.- An empty catalogue has no islands, sources or components and never a dummy row.
FITS encoding
The catalogue FITS file has exactly three binary tables, ISLANDS,
SOURCES and GAUSSIAN_COMPONENTS, with Hebog domain column names and
explicit units. At this boundary only, an unavailable float is NaN and reads
back as None; for a major-axis-only result DECONVOLVED_MAJOR is positive
while the minor axis and angle are NaN, and the reader rebuilds the one-axis
state from that pattern; the record requires the major-axis-only flag to
match it. Spectral coefficients are fixed-width float64
vectors padded with trailing NaN rather than variable-length heap columns, so
identical retries are byte-identical on every platform. Every HDU carries
CHECKSUM and DATASUM with a fixed provenance comment instead of Astropy's
wall-clock comment, and ADDITIONAL_ISLAND_IDS preserves multi-island links.
Result and diagnostics
SourceFinderResult holds the run ID, the source, Gaussian and island
counts, finite wall time and four MaterializedProduct records, plus a
fifth, flat_noise_rms, when the request named a flat-noise image. Each
record has a path, byte count, SHA-256, media type, content schema version
and scientific status:
| Role | Media type | Scientific status |
|---|---|---|
source-catalogue |
application/fits |
valid |
rms (the image's RMS, and the flat-noise image's) |
image/fits |
valid or unavailable |
source-filtering-mask |
image/fits |
valid |
diagnostics |
application/json |
valid |
Constructing the model does no I/O, and paths must be distinct.
unavailable RMS means a successful analysis had no usable noise estimate;
the file is a versioned all-NaN representation of that state, never copied
input pixels.
PublicSourceFindingDiagnostics is the diagnostics product. It records the
profile and its limitations, population counts, RMS status, exact provenance
(configuration SHA-256 and composition hash), the deblend-fallback and
wide-object round counts, and configuration_qualification:
development-unqualified for the 5σ/3σ, seven-pixel configuration without a
maximum island cut and custom-unqualified otherwise. Its canonical
measurement_dispositions list every detected component and source exactly
once with status measured, unavailable or deferred, the estimator or
failure reason, and whether a catalogue row was published; the per-kind
counts must match the catalogue. Fit attribution keeps the optimizer model,
sample count, noise estimator, bound and conditioning evidence and
covariance availability without arrays; association attribution keeps the
hierarchy, compact-model and morphology group IDs, the selected decision and
each source's association_evidence, stored once per source. A joint-fit
linear-algebra failure is recorded as fit-linear-algebra-failure for every
component of that fit, with no invented diagnostics. Successful publication
does not imply that every measurement or scientific gate passed.
Product materialisation
Astropy writes the final FITS products. RMS is a two-dimensional float32 or
float64 image whose dtype is chosen explicitly, non-negative where finite and
NaN where invalid; the mask is uint8 written from exact booleans. RMS and
mask writers take sequential full-width row blocks and validate each, so
peak memory is bounded by the block, not the plane; readers expose the same
products through bounded windows and verify the record's SHA-256 once per
reader. All four writers create and validate a same-directory temporary file
before publishing it. A retry with identical bytes returns the existing
record; one that would replace different bytes raises
MaterializedProductConflictError.
Intermediate Zarr generation
Intermediate planes are one immutable Zarr v3 generation per run (ADR-007). The rules the sink enforces:
- Every canonical tile owns and writes one complete chunk of each product.
The caller creates each product array (
initialize_product) before workers start, so workers never race metadata creation. ProductChunkis a small serializable identity: generation ID, core bounds, dtype, shape and logical SHA-256, with no open Zarr object or pixels. An identical retry reuses a completed chunk; a different value for the same product and tile fails closed.publish_generationrequires exactly one record for every product and tile, rejects missing, duplicate, conflicting, mixed-generation, wrong-owner and inconsistent-dtype records, checksums every chunk and only then conditionally creates the completion marker. Identical publications are idempotent, a different marker cannot replace the winner, and an interrupted run has no marker and resumes by writing its missing chunks.read_generationvalidates the marker without re-reading the chunks; each chunk is validated against its record whenever it is read. A sink caches its array handles and the parsed marker for its lifetime in one process, and a pickled copy starts empty.- Storage schema 3 stores numeric planes uncompressed with CRC32C and boolean masks with Zstandard level 1 plus CRC32C; every chunk also carries its logical SHA-256. Bounded consumers reuse at most four validated chunks while assembling windows, in a worker-local cache.
iter_completed_row_blocksstreams a product into FITS one full-width tile row at a time, validating each chunk once; a budget below one tile row fails before any bytes are written.
Normalized residuals and local label planes are worker temporaries; workers return component facts and boundary-label vectors, and reconciliation reduces them through a deterministic pairwise tree. Exact deblended-region labels are published as component label planes and read back by the fit tasks; no summary rectangle stands in for membership.
Multiscale and compact records
ScaleDetection describes one finite beam-normalized response with its
global bounds, valid-support fraction, normalized peak, significance and
scale. CrossScaleAssociation joins detections across adjacent scales and
records the selected detection explicitly. The moment and fit kernels return
frozen records (OwnedPixelPhotometry, GaussianMomentInitializer,
CelestialCompactGaussianFit) that keep owned-pixel flux distinct from
fitted flux and omit unavailable fields rather than encoding absence as
zero; the algorithm contracts describe them. None
of these records contains an image array, WCS object or scheduler state; WCS
objects are rebuilt transiently inside the astrometry boundary.
Compatibility
The internal catalogue defines no PyBDSF column names. The Rapthor catalogue view maps the internal records to the eight directly consumed fields, and the Rapthor source-finding contract says what an adapter must reproduce.