Python API
This is the supported public API. Start with the
tutorial; see
capability and status for current limits. The API is
experimental and can change between 0.x releases.
| Need | Use |
|---|---|
| Run the finder | hebog.find_sources, hebog.SourceFinderRequest, hebog.SourceFinderConfig |
| Choose where work runs | hebog.executors |
| Read products | hebog.io.read_catalogue_fits_product, hebog.io.read_diagnostics_product |
| Handle failures | hebog.SourceFinderError and its subclasses; hebog.SourceFinderStagingWarning for what a killed run left |
Developers extending Hebog will also want the internal API.
Top-level package
hebog
A scalable source finder for radio continuum images.
InvalidSourceFinderInputError
Bases: SourceFinderError
The requested input cannot be read as a supported FITS image.
Source code in src/hebog/pipeline.py
44 45 | |
SourceFinderConfig
dataclass
Pipeline-neutral scientific thresholds for one image analysis.
Thresholds are explicit because a value appropriate for one survey,
image product, or pipeline stage is not a universal scientific default.
Island-size cuts are likewise explicit pixel counts; a compatibility
adapter may derive them from reviewed beam metadata before constructing
this scheduler-independent configuration.
background is estimated, Hebog's spatial background, or
zero, which subtracts nothing while the RMS is still estimated, as
PyBDSF's mean_map="zero" does; which one a workflow uses is that
workflow's adapter's choice, as are its filtering options. The residual
multiscale segmentation policy has its own explicit configuration because
its area and support rules use beam rather than pixel units.
continuum is the general source-association profile; compact is an
explicit component-level profile that is incomplete for extended emission.
A threshold or pixel count may be any real number or integer, a NumPy
scalar included, and is held as the Python float or int it
equals, so equal configurations serialize and hash alike.
SourceFinderConfig(5, 3, 7) SourceFinderConfig(detection_threshold_sigma=5.0, island_threshold_sigma=3.0, minimum_island_pixels=7, maximum_island_pixels=None, profile='continuum', background='estimated')
Source code in src/hebog/config.py
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
__post_init__()
Validate thresholds and pixel cuts, and hold plain values.
Source code in src/hebog/config.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
SourceFinderError
Bases: Exception
Base class for failures at the public source-finding boundary.
Source code in src/hebog/pipeline.py
36 37 | |
SourceFinderImageTooLargeError
Bases: SourceFinderError
An input exceeds the public finder's bounded image-size envelope.
Source code in src/hebog/pipeline.py
52 53 | |
SourceFinderOutputExistsError
Bases: SourceFinderError
The output destination exists without this request's products.
Source code in src/hebog/pipeline.py
40 41 | |
SourceFinderRequest
dataclass
Inputs for one independent source-finding analysis.
flat_noise_image_path names the primary-beam-uncorrected image of the
same sector, on the same pixel grid; when it is given, the run also
estimates that image's background and RMS and publishes its RMS map.
supplied_metadata applies to both images.
Source code in src/hebog/data_models/source_finding.py
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | |
__post_init__()
Reject unsupported schema versions and empty run identifiers.
Source code in src/hebog/data_models/source_finding.py
478 479 480 481 482 483 484 485 | |
SourceFinderResult
Bases: BaseModel
Versioned materialised products from one scientific image analysis.
Source code in src/hebog/data_models/source_finding.py
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | |
catalogue_path
property
Return the materialised catalogue path for workflow consumers.
diagnostics_path
property
Return the materialised diagnostics path.
mask_path
property
Return the materialised source-filtering mask path.
rms_path
property
Return the materialised RMS image path.
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/source_finding.py
617 618 619 620 621 622 623 624 625 626 | |
from_json_bytes(payload)
classmethod
Validate one serialized materialised result.
Source code in src/hebog/data_models/source_finding.py
628 629 630 631 632 633 634 | |
SourceFinderStagingWarning
Bases: UserWarning
An earlier run left a hidden staging directory beside the output.
A run that is killed cannot remove its staging directory. The next run to the same output removes one whose owner has provably stopped and leaves any other in place; it reports each with this warning.
Source code in src/hebog/pipeline.py
56 57 58 59 60 61 62 | |
SuppliedImageMetadata
dataclass
Physical metadata a caller supplies for keywords a FITS header omits.
Each value fills only a missing header keyword: frequency in Hz for
RESTFRQ or a frequency axis, restoring-beam full widths and position
angle in degrees for BMAJ, BMIN and BPA, and the pixel
brightness unit for BUNIT. Supplying a value the header already
provides is an input error, so supplied metadata never overrides an
image's own description.
SuppliedImageMetadata(reference_frequency_hz=144e6) SuppliedImageMetadata(reference_frequency_hz=144000000.0, beam_major_fwhm_degrees=None, beam_minor_fwhm_degrees=None, beam_position_angle_degrees=None, brightness_unit=None)
Source code in src/hebog/data_models/images.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
__post_init__()
Require at least one finite value with the header's own limits.
Source code in src/hebog/data_models/images.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
UnsupportedSourceFinderConfigurationError
Bases: SourceFinderError
The requested science cannot be executed by the public pipeline.
Source code in src/hebog/pipeline.py
48 49 | |
analysis_memory_bytes(image_shape_yx, *, expected_sources)
Return the memory one analysis holds in the process that runs it.
find_sources keeps Hebog's modules, the records each pass returns
for every source, and the products it publishes in the process that
calls it, so what it holds grows with the sources it finds, and with
the image through the background's noise grids. Its tasks are
not counted: each declares its own memory to the executor, which a
DaskExecutor attaches to the task under the caller's memory
resource. Reserve this amount for the task that calls
find_sources, for example under the same Dask resource. With a
SerialExecutor or ThreadExecutor the tasks run in the calling
process, so the memory they are admitted comes on top. A request with a
flat-noise image is covered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_shape_yx
|
tuple[int, int]
|
The input image's height and width in pixels. |
required |
expected_sources
|
int
|
An upper estimate of the sources the catalogue
will hold, such as :func: |
required |
Returns:
| Type | Description |
|---|---|
int
|
A fixed amount, an amount per expected source and two and a half |
int
|
bytes a pixel, with a quarter of headroom, in bytes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a dimension is not a positive integer or the source count is not a non-negative integer. |
Examples:
>>> analysis_memory_bytes(
... (3_000, 4_000), expected_sources=10
... ) == analysis_memory_bytes((4_000, 3_000), expected_sources=10)
True
Source code in src/hebog/pipeline.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
expected_source_count(image_path, *, detection_threshold_sigma, supplied_metadata=None)
Return an upper estimate of the sources find_sources publishes.
Pass it to :func:analysis_memory_bytes. A deconvolution model's
component list is no such estimate: it holds many components for each
source. A published source peaks at least the detection threshold times
the local noise above the background, so the estimate counts the pixels
that are the highest of their 3x3 neighbourhood and at least
detection_threshold_sigma times the noise above the median of their
512-pixel block. A block's noise is its valid pixels' 3-sigma-clipped
standard deviation, or the median of every block's if that is lower, so
neither the bright sources in a block nor a primary-beam correction's
noisier edges hide faint sources. A noise peak counts as a source would,
so the estimate errs high; on 21 development cases it bounded every
published source count, at 1.0 to 21 times it: 1.1 to 1.9 times on the
LOFAR and simulated SKA fields, and most where noise peaks sit on one
wide source. The image is read twice in bounded blocks, so no
image-sized array is held. An image find_sources refuses is
refused in the same way before any pixel is read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_path
|
Path
|
The FITS image |
required |
detection_threshold_sigma
|
float
|
The detection threshold the analysis
will use, |
required |
supplied_metadata
|
SuppliedImageMetadata | None
|
Values the header lacks, as the request gives them. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of such peaks; 0 for an image with no measurable noise. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the threshold is not finite and positive. |
InvalidSourceFinderInputError
|
If the image cannot be read as a FITS continuum image. |
UnsupportedSourceFinderConfigurationError
|
If |
SourceFinderImageTooLargeError
|
If the image exceeds the size
envelope |
Source code in src/hebog/pipeline.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
find_sources(request, config, executor)
Analyse one supported FITS image and atomically publish its products.
When the output already holds the products of a finished run of the
same request, with the same run ID, inputs, configuration and science,
they are returned without analysing the image again. A failed run
raises only once no task it submitted is still running, and removes
everything it staged. A killed run leaves a hidden staging directory,
which the next run to the same output removes once its owner has
provably stopped or reports with a SourceFinderStagingWarning.
The implementation is imported only when called so importing the public scheduler-independent API never loads a concrete I/O or scheduler layer.
Source code in src/hebog/pipeline.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
Request and result records
hebog.data_models
Small serializable scheduler-independent domain records.
BrightRegionCounts
Bases: BaseModel
How far one background estimate refined around bright candidates.
candidate_count counts the bright candidates the estimate found, at
or above its bright-candidate threshold. The estimate refines the noise
around each; candidates close enough to chain merge into one region,
which can span the image, and its fine cells are estimated in bounded
blocks. largest_read_pixels is the most pixels one of those tasks
read, zero when none read any.
Source code in src/hebog/data_models/source_finding.py
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | |
CatalogueSourceMembership
dataclass
Canonical exact partition of components assigned to one source.
Source code in src/hebog/data_models/source_association.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
__post_init__()
Require a non-empty canonical component membership.
Source code in src/hebog/data_models/source_association.py
114 115 116 117 118 119 120 121 122 123 124 | |
CelestialWcs
dataclass
Canonical FITS celestial-WCS cards and their coordinate-frame name.
Source code in src/hebog/data_models/images.py
89 90 91 92 93 94 95 96 97 98 99 100 101 | |
__post_init__()
Require enough metadata to reconstruct and interpret the WCS.
Source code in src/hebog/data_models/images.py
96 97 98 99 100 101 | |
ContinuumSourceFindingDiagnostics
Bases: BaseModel
Version-two diagnostics with per-extended-source provenance.
Source code in src/hebog/data_models/source_finding.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | |
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/source_finding.py
216 217 218 219 220 221 222 223 224 225 | |
from_json_bytes(payload)
classmethod
Validate one canonical serialized continuum diagnostic.
Source code in src/hebog/data_models/source_finding.py
227 228 229 230 231 232 233 234 235 | |
CrossScaleAssociation
Bases: _MultiscaleModel
Deterministic association of persistent scale detections.
Source code in src/hebog/data_models/multiscale.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
validate_association()
Bind the selected representation to retained provenance.
Source code in src/hebog/data_models/multiscale.py
108 109 110 111 112 113 114 115 116 117 118 119 120 | |
validate_identifiers(identifiers)
classmethod
Require stable association inputs.
Source code in src/hebog/data_models/multiscale.py
95 96 97 98 99 100 101 102 103 104 105 106 | |
DetectionComponentRecord
dataclass
Stable identity and pixel geometry for one immutable owner component.
Source code in src/hebog/data_models/source_association.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
__post_init__()
Require valid immutable geometry without promoting local labels.
Source code in src/hebog/data_models/source_association.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
FluxMeasurement
Bases: _CatalogueModel
Peak and integrated source flux plus local noise in canonical units.
Source code in src/hebog/data_models/catalogues.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
GaussianComponent
Bases: _MeasuredCatalogueObject
One fitted Gaussian with explicit source and support-island links.
Source code in src/hebog/data_models/catalogues.py
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | |
GaussianShape
Bases: _CatalogueModel
One fitted FWHM ellipse and optional one-sigma errors in degrees.
Source code in src/hebog/data_models/catalogues.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
ImageBounds
dataclass
Half-open global pixel bounds in NumPy (y, x) axis order.
Source code in src/hebog/data_models/partitioning.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
center_xy
property
Return the centre of the bounded pixels, in global (x, y).
Local geometry is derived here rather than at a corner, and every caller that derives it must agree, so the definition lives with the bounds instead of beside each use.
shape_yx
property
Return the bounded array shape in NumPy axis order.
__post_init__()
Require non-negative, non-empty half-open bounds.
Source code in src/hebog/data_models/partitioning.py
21 22 23 24 25 26 | |
contains(other)
Return whether another region lies completely within the bounds.
Source code in src/hebog/data_models/partitioning.py
56 57 58 59 60 61 62 63 | |
expanded(margin_pixels, image_shape_yx)
Return a uniformly expanded region clipped to the image plane.
Source code in src/hebog/data_models/partitioning.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
require_inside(shape_yx)
Reject bounds extending beyond one logical image plane.
Source code in src/hebog/data_models/partitioning.py
49 50 51 52 53 54 | |
ImageMetadata
dataclass
Scientific metadata required to interpret one logical image plane.
Source code in src/hebog/data_models/images.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
__post_init__()
Reject unsupported versions and incomplete physical metadata.
Source code in src/hebog/data_models/images.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
Island
Bases: _CatalogueModel
One connected detection region with signed original-pixel flux.
Source code in src/hebog/data_models/catalogues.py
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | |
MaterializedProduct
Bases: BaseModel
Closed restartable output file and its content identity.
Source code in src/hebog/data_models/source_finding.py
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | |
PartitionManifest
dataclass
Canonical tiling record with one owner per output pixel.
Source code in src/hebog/data_models/partitioning.py
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
__post_init__()
Reject unsupported versions and non-canonical ownership records.
Source code in src/hebog/data_models/partitioning.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
__reduce__()
Pickle as the geometry the tiles are planned from.
The tiles are the one canonical tiling of that geometry, which construction already requires, so they are rebuilt where the manifest is unpickled rather than shipped with it. Executor tasks carry manifests inside sinks and requests, and Dask serializes a task's payload with every task, so a payload that grew with the tile count made each task cost the driver time proportional to the image: about 280 ms for 14,641 128-pixel cells. Schema version 1 is the only one a manifest can have, so it is not carried; a second version must be added here.
Source code in src/hebog/data_models/partitioning.py
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | |
create(*, image_shape_yx, tile_core_shape_yx, halo_yx, partition_origin_yx=(0, 0))
classmethod
Validate geometry and construct its unique canonical manifest.
Source code in src/hebog/data_models/partitioning.py
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
owner_for_position_yx(position_yx)
Return the unique tile owning a source reference position.
Positions use zero-based continuous (y, x) pixel coordinates.
A position exactly on an internal boundary belongs to the core that
starts at that boundary. A source may overlap other cores and halos;
only its deterministic reference position selects catalogue ownership.
Source code in src/hebog/data_models/partitioning.py
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
tiles_meeting(bounds)
Return every tile whose core shares a pixel with bounds.
Cores form a grid, so the tiles are the index rectangle between the owners of the region's first and last pixels; no tile is scanned.
Examples:
>>> manifest = PartitionManifest.create(
... image_shape_yx=(10, 10),
... tile_core_shape_yx=(4, 4),
... halo_yx=(0, 0),
... )
>>> region = ImageBounds(3, 5, 7, 10)
>>> [
... (tile.tile_y_index, tile.tile_x_index)
... for tile in manifest.tiles_meeting(region)
... ]
[(0, 1), (0, 2), (1, 1), (1, 2)]
Source code in src/hebog/data_models/partitioning.py
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | |
ProductChunk
dataclass
Logical identity of one tile-owned chunk in a product array.
Source code in src/hebog/data_models/products.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
__post_init__()
Reject malformed chunk identities before storage access.
Source code in src/hebog/data_models/products.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
ProductGenerationManifest
Bases: BaseModel
Exact chunk set that makes one intermediate generation consumable.
Source code in src/hebog/data_models/generations.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/generations.py
127 128 129 130 131 132 133 134 135 | |
create(*, generation_id, partition_manifest, product_names, chunks)
classmethod
Canonicalize caller results before validating exact completion.
Source code in src/hebog/data_models/generations.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
from_json_bytes(payload)
classmethod
Validate one canonical serialized completion record.
Source code in src/hebog/data_models/generations.py
137 138 139 140 141 142 143 144 145 | |
PublicSourceFindingDiagnostics
Bases: BaseModel
Public-run diagnostics retain explicit measurement dispositions.
bright_regions describes the true-sky background estimate and
flat_noise_bright_regions the flat-noise image's, present exactly
when the run had one.
Source code in src/hebog/data_models/source_finding.py
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | |
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/source_finding.py
432 433 434 435 436 437 438 439 440 441 | |
from_json_bytes(payload)
classmethod
Validate one canonical serialized public diagnostic.
Source code in src/hebog/data_models/source_finding.py
443 444 445 446 447 448 449 450 451 | |
PublicSourceFindingProvenance
Bases: BaseModel
Exact input, configuration, and scientific-composition identity.
Source code in src/hebog/data_models/source_finding.py
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | |
RestoringBeam
dataclass
Elliptical restoring-beam full widths and position angle in degrees.
Source code in src/hebog/data_models/images.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
__post_init__()
Require finite positive ordered beam axes.
Source code in src/hebog/data_models/images.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
ScaleDetection
Bases: _MultiscaleModel
One bounded significant support region at one configured scale.
Source code in src/hebog/data_models/multiscale.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
validate_detection()
Validate global identity, bounds, and finite scale response.
Source code in src/hebog/data_models/multiscale.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
SkyPosition
Bases: _CatalogueModel
One ICRS sky position and optional one-sigma errors in degrees.
Source code in src/hebog/data_models/catalogues.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
SourceAssociationEdge
dataclass
One accepted pair supported by continuity and directional size.
Source code in src/hebog/data_models/source_association.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
__post_init__()
Require one canonical undirected accepted edge.
Source code in src/hebog/data_models/source_association.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
SourceAssociationResult
dataclass
Complete array-free association graph and source partition.
Source code in src/hebog/data_models/source_association.py
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | |
__post_init__()
Require unique evidence and an exact component partition.
Source code in src/hebog/data_models/source_association.py
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | |
SourceCandidate
Bases: _MeasuredCatalogueObject
One catalogue-level association of measured astrophysical emission.
Source code in src/hebog/data_models/catalogues.py
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | |
SourceCatalogue
Bases: _CatalogueModel
Canonical MFS catalogue with distinct islands, sources, and fits.
Source code in src/hebog/data_models/catalogues.py
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | |
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/catalogues.py
439 440 441 442 443 444 445 446 447 448 | |
create(*, catalogue_id, coordinate_frame, position_epoch, reference_frequency_hz, islands, sources, gaussian_components)
classmethod
Canonicalize reconciled records before schema validation.
Source code in src/hebog/data_models/catalogues.py
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | |
from_json_bytes(payload)
classmethod
Validate one serialized internal catalogue.
Source code in src/hebog/data_models/catalogues.py
450 451 452 453 454 455 456 | |
SourceFinderRequest
dataclass
Inputs for one independent source-finding analysis.
flat_noise_image_path names the primary-beam-uncorrected image of the
same sector, on the same pixel grid; when it is given, the run also
estimates that image's background and RMS and publishes its RMS map.
supplied_metadata applies to both images.
Source code in src/hebog/data_models/source_finding.py
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | |
__post_init__()
Reject unsupported schema versions and empty run identifiers.
Source code in src/hebog/data_models/source_finding.py
478 479 480 481 482 483 484 485 | |
SourceFinderResult
Bases: BaseModel
Versioned materialised products from one scientific image analysis.
Source code in src/hebog/data_models/source_finding.py
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | |
catalogue_path
property
Return the materialised catalogue path for workflow consumers.
diagnostics_path
property
Return the materialised diagnostics path.
mask_path
property
Return the materialised source-filtering mask path.
rms_path
property
Return the materialised RMS image path.
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/source_finding.py
617 618 619 620 621 622 623 624 625 626 | |
from_json_bytes(payload)
classmethod
Validate one serialized materialised result.
Source code in src/hebog/data_models/source_finding.py
628 629 630 631 632 633 634 | |
SourceFindingDiagnostics
Bases: BaseModel
Versioned scientific population summary for one completed run.
Source code in src/hebog/data_models/source_finding.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
canonical_json_bytes()
Return deterministic UTF-8 JSON with one final newline.
Source code in src/hebog/data_models/source_finding.py
81 82 83 84 85 86 87 88 89 90 | |
from_json_bytes(payload)
classmethod
Validate one canonical serialized diagnostics document.
Source code in src/hebog/data_models/source_finding.py
92 93 94 95 96 97 98 99 100 | |
SourceScaleProvenance
Bases: BaseModel
Auditable scale and support provenance for one extended source.
Source code in src/hebog/data_models/source_finding.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
SpectralModel
Bases: _CatalogueModel
Frequency convention for one reported source or component flux.
For log-polynomial, coefficient k multiplies
log(frequency / reference_frequency) ** (k + 1) in natural-log flux
space. An empty tuple explicitly means that no spectral fit was made.
Source code in src/hebog/data_models/catalogues.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | |
SuppliedImageMetadata
dataclass
Physical metadata a caller supplies for keywords a FITS header omits.
Each value fills only a missing header keyword: frequency in Hz for
RESTFRQ or a frequency axis, restoring-beam full widths and position
angle in degrees for BMAJ, BMIN and BPA, and the pixel
brightness unit for BUNIT. Supplying a value the header already
provides is an input error, so supplied metadata never overrides an
image's own description.
SuppliedImageMetadata(reference_frequency_hz=144e6) SuppliedImageMetadata(reference_frequency_hz=144000000.0, beam_major_fwhm_degrees=None, beam_minor_fwhm_degrees=None, beam_position_angle_degrees=None, brightness_unit=None)
Source code in src/hebog/data_models/images.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
__post_init__()
Require at least one finite value with the header's own limits.
Source code in src/hebog/data_models/images.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
TilePartition
dataclass
One non-overlapping output core and its clipped read-only halo.
Source code in src/hebog/data_models/partitioning.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | |
core_slices_yx
property
Locate the owned core inside an array read through its halo.
tile_id
property
Return a deterministic row-major identifier.
__post_init__()
Require valid indices and a read region containing the core.
Source code in src/hebog/data_models/partitioning.py
98 99 100 101 102 103 | |
WideObjectCounts
Bases: BaseModel
How many objects each round decided from its cores, not a window.
publication_owners, support_components, islands and
segments count objects whose window exceeded a task's read budget:
the cores that hold such an object decide it, and the driver then holds
its own pixels or seeds, the one term ADR-008 bounds by the object
rather than the tile. deferred_fit_parents answers to a different
bound: the fit stage defers a parent whose direct window exceeds the
reviewed compact admission bound, whatever the read budget, and gathers
its component records from the cores instead of reading it whole. Every
count is zero unless an object exceeded its bound, which no image within
the public envelope has been observed to hold.
Source code in src/hebog/data_models/source_finding.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | |
Executors
hebog.executors
Execution policies for coarse source-finding batches.
DaskExecutor
Submit coarse batches to an existing Dask client.
Hebog never creates, resizes or closes the client. Submission stays within the admitted in-flight bound and results are consumed in input order.
memory_resource and core_resource name Dask worker resources
the caller declared, for example with dask worker --resources
"memory=4e9,cores=4". Each named resource is attached to every task:
its declared memory in bytes and its threads, one when it declares
none. Dask then starts a task only on a worker with that much of each
still free, so tasks are not co-located past the memory a worker
declares. Named resources are also the admitted budget, because a
worker's thread count and memory limit include what other work holds.
Source code in src/hebog/executors/dask.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
capacity
property
Return the declared budget, or the cluster's current one.
client
property
Return the caller-owned client this executor submits to.
__init__(client, *, capacity=None, retry_limit=0, memory_resource=None, core_resource=None)
Bind one caller-owned client, budget, retry policy and resources.
Source code in src/hebog/executors/dask.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
map_batches(function, batches, *, requirement=None)
Submit batches and gather their results in input order.
No more tasks are in flight than the admitted bound, and the oldest is consumed before another is submitted.
Source code in src/hebog/executors/dask.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
Executor
Bases: Protocol
Execute coarse batches without exposing scheduler-specific objects.
Source code in src/hebog/executors/base.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
capacity
property
Return the execution budget admitted by the caller.
map_batches(function, batches, *, requirement=None)
Apply function to each batch and return ordered results.
Source code in src/hebog/executors/base.py
183 184 185 186 187 188 189 190 191 | |
ExecutorAdmissionError
Bases: ValueError
One task declared more resource than the caller admitted.
Source code in src/hebog/executors/base.py
23 24 | |
ExecutorCapacity
dataclass
The execution budget the caller admitted for one source finder.
memory_bytes_per_worker is the working set one task may hold. It is
None when the caller has declared no budget, in which case memory
admission is not enforced and a stage needing a budget must say so.
Source code in src/hebog/executors/base.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
__post_init__()
Require a positive, bounded and explicit execution budget.
Source code in src/hebog/executors/base.py
54 55 56 57 58 59 60 61 62 63 64 | |
admit(requirement)
Raise before submission when one task exceeds the budget.
Source code in src/hebog/executors/base.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
ExecutorPayloadError
Bases: ValueError
One task payload cannot cross a worker boundary.
Source code in src/hebog/executors/base.py
27 28 | |
SerialExecutor
Run batches serially for testing and scientific reference results.
This executor defines the behaviour every other policy must reproduce: input ordering, payload validation, retry of idempotent tasks and the first failing batch by index.
Source code in src/hebog/executors/serial.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
capacity
property
Return the execution budget admitted by the caller.
__init__(*, capacity=None, retry_limit=0)
Bind the caller's admitted budget and retry policy.
Source code in src/hebog/executors/serial.py
33 34 35 36 37 38 39 40 41 42 43 | |
map_batches(function, batches, *, requirement=None)
Apply function to each batch in input order.
Source code in src/hebog/executors/serial.py
63 64 65 66 67 68 69 70 71 | |
TaskRequirement
dataclass
One task's declared peak working set and thread requirement.
Source code in src/hebog/executors/base.py
83 84 85 86 87 88 89 90 91 92 93 | |
__post_init__()
Require a positive declared working set and thread count.
Source code in src/hebog/executors/base.py
90 91 92 93 | |
ThreadExecutor
Run bounded batches on one persistent caller-owned thread pool.
The pool exists for the lifetime of this executor, so tasks never create a nested pool and no stage starts threads of its own. Batches are submitted in input order within a bounded window and consumed in that same order, which keeps results and the propagated failure identical to the serial reference.
Source code in src/hebog/executors/threads.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
capacity
property
Return the execution budget admitted by the caller.
__enter__()
Return this executor for use inside a caller-owned scope.
Source code in src/hebog/executors/threads.py
97 98 99 | |
__exit__(exception_type, exception, traceback)
Release the pool the caller opened.
Source code in src/hebog/executors/threads.py
101 102 103 104 105 106 107 108 109 | |
__init__(thread_count, *, memory_bytes_per_worker=None, retry_limit=0)
Create one pool the caller owns for the whole run.
Source code in src/hebog/executors/threads.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
close()
Release the pool and abandon work that has not started.
Source code in src/hebog/executors/threads.py
111 112 113 | |
map_batches(function, batches, *, requirement=None)
Apply function to each batch and return ordered results.
Source code in src/hebog/executors/threads.py
158 159 160 161 162 163 164 165 166 | |
__getattr__(name)
Load the optional concrete Dask executor only when requested.
Source code in src/hebog/executors/__init__.py
30 31 32 33 34 35 36 37 38 | |
Reading products and images
hebog.io
Image and product input/output boundaries.
FitsImageSource
Read validated logical image planes through bounded FITS sections.
Optional supplied metadata fills keywords the header omits. It is part of the source, so every executor task that re-reads the header sees it.
Source code in src/hebog/io/fits.py
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | |
__getstate__()
Serialize the request to read a file, never what it once held.
A worker opens the file itself, so neither an open file nor validated metadata travels with the source: an open file cannot cross a process, and metadata could go stale in transit.
Source code in src/hebog/io/fits.py
603 604 605 606 607 608 609 610 611 612 613 | |
__init__(path, supplied_metadata=None)
Retain the path and supplied metadata; open files only on use.
Source code in src/hebog/io/fits.py
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | |
__setstate__(state)
Restore a source that has not yet read its file.
Source code in src/hebog/io/fits.py
615 616 617 618 619 | |
close()
Release every file this source holds open.
Worker threads each open the file, so one close frees them all. The source stays usable and opens the file again when it is next read.
Source code in src/hebog/io/fits.py
665 666 667 668 669 670 671 | |
header()
Return the primary header as the finder reads it.
Each float holds the number Astropy parsed, written so that wcslib
reads the same one. A WCS built from this header is therefore the
transform that :meth:metadata validates, which one built from the
file's own header text need not be. The header is the caller's own
copy.
Raises:
| Type | Description |
|---|---|
InvalidFitsImageError
|
If the file cannot be opened, or a numeric WCS card is not a number. |
Source code in src/hebog/io/fits.py
673 674 675 676 677 678 679 680 681 682 683 684 685 686 | |
metadata()
Return shape and unit without materialising the image plane.
A source validates one file once: tiled stages read hundreds of windows, and re-parsing the header and rebuilding both WCS objects for each of them costs more than reading the pixels.
Source code in src/hebog/io/fits.py
688 689 690 691 692 693 694 695 696 697 698 699 | |
read_window(bounds)
Read one half-open global window into owned read-only arrays.
Source code in src/hebog/io/fits.py
701 702 703 | |
read_windows(bounds_collection)
Read bounded windows through one validated FITS open.
A pixel is valid under the rule of :mod:hebog.io.pixel_validity:
finite, and in no 3x3 square of one repeated value. The rule looks
at the pixels up to two away, so each window is read two pixels
wider on every side inside the image, and only the window is kept.
Source code in src/hebog/io/fits.py
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | |
FitsProductImageSource
Read a checksum-verified RMS or mask product through bounded windows.
Source code in src/hebog/io/materialization.py
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 | |
__init__(product)
Require a supported image-product role without opening its file.
Source code in src/hebog/io/materialization.py
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 | |
metadata()
Return verified image metadata without materialising the plane.
Source code in src/hebog/io/materialization.py
1150 1151 1152 1153 1154 1155 1156 1157 1158 | |
read_window(bounds)
Read and validate one bounded product window.
A product pixel is valid where it is finite. The input image's block rule does not apply: a mask, or a constant noise estimate, is a product's value, not an unobserved region.
Source code in src/hebog/io/materialization.py
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 | |
scientific_status()
Return the verified scientific availability of this product.
Source code in src/hebog/io/materialization.py
1145 1146 1147 1148 | |
ImageBounds
dataclass
Half-open global pixel bounds in NumPy (y, x) axis order.
Source code in src/hebog/data_models/partitioning.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
center_xy
property
Return the centre of the bounded pixels, in global (x, y).
Local geometry is derived here rather than at a corner, and every caller that derives it must agree, so the definition lives with the bounds instead of beside each use.
shape_yx
property
Return the bounded array shape in NumPy axis order.
__post_init__()
Require non-negative, non-empty half-open bounds.
Source code in src/hebog/data_models/partitioning.py
21 22 23 24 25 26 | |
contains(other)
Return whether another region lies completely within the bounds.
Source code in src/hebog/data_models/partitioning.py
56 57 58 59 60 61 62 63 | |
expanded(margin_pixels, image_shape_yx)
Return a uniformly expanded region clipped to the image plane.
Source code in src/hebog/data_models/partitioning.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
require_inside(shape_yx)
Reject bounds extending beyond one logical image plane.
Source code in src/hebog/data_models/partitioning.py
49 50 51 52 53 54 | |
ImageMetadata
dataclass
Scientific metadata required to interpret one logical image plane.
Source code in src/hebog/data_models/images.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
__post_init__()
Reject unsupported versions and incomplete physical metadata.
Source code in src/hebog/data_models/images.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
ImageSource
Bases: Protocol
Narrow input seam implemented by window-readable image stores.
Source code in src/hebog/io/base.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
metadata()
Return logical image metadata without materialising the plane.
Source code in src/hebog/io/base.py
34 35 36 | |
read_window(bounds)
Read one bounded global window into worker-owned memory.
The window's valid_pixels must not depend on bounds: a source
whose rule looks at a pixel's neighbours, as the FITS source's block
rule (:mod:hebog.io.pixel_validity) does, reads a margin around the
window and keeps only the window, so any tiling decides the same
pixels.
Source code in src/hebog/io/base.py
38 39 40 41 42 43 44 45 46 47 | |
ImageWindow
dataclass
One owned, read-only bounded pixel window and its validity mask.
valid_pixels says which pixels the finder measures. A pixel's
validity belongs to the pixel, not to the window that holds it: the same
pixel must be valid in every window that contains it, however the image
is tiled.
Source code in src/hebog/io/base.py
16 17 18 19 20 21 22 23 24 25 26 27 28 | |
InvalidFitsImageError
Bases: ValueError
A FITS input is missing required structural or physical metadata.
Source code in src/hebog/io/fits.py
69 70 | |
InvalidMaterializedProductError
Bases: ProductMaterializationError
A product is corrupt, incomplete, or scientifically invalid.
Source code in src/hebog/io/materialization.py
150 151 | |
InvalidProductChunkError
Bases: ProductChunkError
A Zarr product chunk is missing, corrupt, or inconsistent.
Source code in src/hebog/io/zarr.py
77 78 | |
InvalidProductGenerationError
Bases: ProductGenerationError
A completion manifest or one of its chunks is invalid.
Source code in src/hebog/io/zarr.py
85 86 | |
MaterializedProductConflictError
Bases: ProductMaterializationError
A destination already contains different product bytes.
Source code in src/hebog/io/materialization.py
158 159 | |
ProductChunkConflictError
Bases: ProductChunkError
A completed Zarr chunk contains different values for one tile.
Source code in src/hebog/io/zarr.py
73 74 | |
ProductChunkError
Bases: ValueError
A Zarr product chunk cannot be safely published or consumed.
Source code in src/hebog/io/zarr.py
69 70 | |
ProductGenerationConflictError
Bases: ProductGenerationError
A different completion manifest already publishes this generation.
Source code in src/hebog/io/zarr.py
89 90 | |
ProductGenerationError
Bases: ProductChunkError
A Zarr generation cannot be safely published or consumed.
Source code in src/hebog/io/zarr.py
81 82 | |
ProductMaterializationError
Bases: ValueError
A restartable product could not be written or validated.
Source code in src/hebog/io/materialization.py
146 147 | |
UnsupportedFitsImageError
Bases: InvalidFitsImageError
A valid FITS input uses an image layout Hebog does not yet support.
Source code in src/hebog/io/fits.py
73 74 | |
UnsupportedMaterializedProductError
Bases: InvalidMaterializedProductError
A valid product uses an unsupported role or schema version.
Source code in src/hebog/io/materialization.py
154 155 | |
ZarrProductSink
Write complete canonical tile cores into one local Zarr v3 group.
Source code in src/hebog/io/zarr.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | |
generation_id
property
Return the immutable run identity stored with every chunk.
manifest
property
Return the immutable partition geometry used by this sink.
__getstate__()
Pickle the plain metadata only; open handles stay in this process.
A sink travels inside executor payloads, so a copy on a worker opens its own array handles and reads the completion marker once, and the pickled bytes never carry a store object. Both are immutable for a generation: an array's geometry and policy are fixed when it is created and the marker is published once, so a process validates them when it first opens them and trusts them for the sink's lifetime, while every chunk read is still checked against its record. A change to either on disk is not a supported operation; the next process or task to open the product rejects it.
Source code in src/hebog/io/zarr.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | |
__init__(root, manifest, *, generation_id)
Retain plain metadata without opening or creating a store.
Source code in src/hebog/io/zarr.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | |
initialize_product(*, product_name, dtype)
Create or validate one product array before worker submission.
Source code in src/hebog/io/zarr.py
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
iter_completed_row_blocks(product_name, *, max_block_bytes)
Yield validated full-width tile rows for final materialisation.
Every storage chunk is read and checksum-validated exactly once. A multi-tile row is assembled into one owned C-contiguous block. The caller must admit enough memory for one full tile row; this is bounded by image width times tile-core height rather than full image height. A one-tile image returns its already-owned chunk without an assembly copy.
Source code in src/hebog/io/zarr.py
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | |
publish_generation(*, product_names, chunks)
Conditionally publish one exact, fully validated generation.
Source code in src/hebog/io/zarr.py
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | |
read_chunk(record)
Validate one expected chunk and return an owned read-only array.
Source code in src/hebog/io/zarr.py
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | |
read_completed_window(product_name, bounds)
Read one checksum-validated bounded window from owned chunks.
Source code in src/hebog/io/zarr.py
664 665 666 667 668 669 670 | |
read_completed_windows(product_name, bounds_collection)
Read windows through a bounded cache of validated owned chunks.
Source code in src/hebog/io/zarr.py
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | |
read_generation()
Read and validate the published completion manifest.
The marker is parsed, required to be canonical and bound to this sink's run and partition. Its chunks are not re-read: every one was read and checksummed when the generation was published, and each is validated against its record again whenever it is read, so a consumer never pays for a whole generation it does not use.
Source code in src/hebog/io/zarr.py
653 654 655 656 657 658 659 660 661 662 | |
write_chunk(*, product_name, tile, values)
Write one aligned chunk or content-validate an existing retry.
Fresh LocalStore writes are atomic and use the required CRC32C codec. Their content SHA-256 is validated in the mandatory full-generation check before a completion marker can be published.
Source code in src/hebog/io/zarr.py
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | |
celestial_wcs_from_metadata(metadata)
Reconstruct an independent celestial WCS from serialized metadata.
Source code in src/hebog/algorithms/astrometry.py
57 58 59 60 61 62 63 | |
describe_published_product(path, *, role)
Validate one product a finished run published, and describe it.
Each product is read as its writer validated it before publishing it: a catalogue and diagnostics in full, an image by its header. The record is the one the writer returned, so a caller can resume from it.
Source code in src/hebog/io/materialization.py
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | |
read_catalogue_fits_product(product_or_path)
Read and strictly validate an internal catalogue FITS product.
Source code in src/hebog/io/materialization.py
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | |
read_diagnostics_product(product_or_path)
Read and strictly validate canonical diagnostics JSON.
Source code in src/hebog/io/materialization.py
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 | |
write_catalogue_fits_product(path, catalogue)
Write one validated, idempotent internal catalogue FITS product.
Source code in src/hebog/io/materialization.py
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | |
write_diagnostics_product(path, diagnostics)
Write one canonical, idempotent diagnostics JSON product.
Source code in src/hebog/io/materialization.py
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 | |
write_mask_fits_product(path, metadata, row_blocks)
Write one row-block-bounded binary source-filtering mask.
Source code in src/hebog/io/materialization.py
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 | |
write_rms_fits_product(path, metadata, row_blocks, *, dtype, scientific_status)
Write one row-block-bounded RMS FITS product without implicit casts.
Source code in src/hebog/io/materialization.py
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | |
Errors and entry point
hebog.pipeline
Scheduler-independent public source-finding API.
InvalidSourceFinderInputError
Bases: SourceFinderError
The requested input cannot be read as a supported FITS image.
Source code in src/hebog/pipeline.py
44 45 | |
SourceFinderError
Bases: Exception
Base class for failures at the public source-finding boundary.
Source code in src/hebog/pipeline.py
36 37 | |
SourceFinderImageTooLargeError
Bases: SourceFinderError
An input exceeds the public finder's bounded image-size envelope.
Source code in src/hebog/pipeline.py
52 53 | |
SourceFinderOutputExistsError
Bases: SourceFinderError
The output destination exists without this request's products.
Source code in src/hebog/pipeline.py
40 41 | |
SourceFinderStagingWarning
Bases: UserWarning
An earlier run left a hidden staging directory beside the output.
A run that is killed cannot remove its staging directory. The next run to the same output removes one whose owner has provably stopped and leaves any other in place; it reports each with this warning.
Source code in src/hebog/pipeline.py
56 57 58 59 60 61 62 | |
UnsupportedSourceFinderConfigurationError
Bases: SourceFinderError
The requested science cannot be executed by the public pipeline.
Source code in src/hebog/pipeline.py
48 49 | |
analysis_memory_bytes(image_shape_yx, *, expected_sources)
Return the memory one analysis holds in the process that runs it.
find_sources keeps Hebog's modules, the records each pass returns
for every source, and the products it publishes in the process that
calls it, so what it holds grows with the sources it finds, and with
the image through the background's noise grids. Its tasks are
not counted: each declares its own memory to the executor, which a
DaskExecutor attaches to the task under the caller's memory
resource. Reserve this amount for the task that calls
find_sources, for example under the same Dask resource. With a
SerialExecutor or ThreadExecutor the tasks run in the calling
process, so the memory they are admitted comes on top. A request with a
flat-noise image is covered.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_shape_yx
|
tuple[int, int]
|
The input image's height and width in pixels. |
required |
expected_sources
|
int
|
An upper estimate of the sources the catalogue
will hold, such as :func: |
required |
Returns:
| Type | Description |
|---|---|
int
|
A fixed amount, an amount per expected source and two and a half |
int
|
bytes a pixel, with a quarter of headroom, in bytes. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a dimension is not a positive integer or the source count is not a non-negative integer. |
Examples:
>>> analysis_memory_bytes(
... (3_000, 4_000), expected_sources=10
... ) == analysis_memory_bytes((4_000, 3_000), expected_sources=10)
True
Source code in src/hebog/pipeline.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
expected_source_count(image_path, *, detection_threshold_sigma, supplied_metadata=None)
Return an upper estimate of the sources find_sources publishes.
Pass it to :func:analysis_memory_bytes. A deconvolution model's
component list is no such estimate: it holds many components for each
source. A published source peaks at least the detection threshold times
the local noise above the background, so the estimate counts the pixels
that are the highest of their 3x3 neighbourhood and at least
detection_threshold_sigma times the noise above the median of their
512-pixel block. A block's noise is its valid pixels' 3-sigma-clipped
standard deviation, or the median of every block's if that is lower, so
neither the bright sources in a block nor a primary-beam correction's
noisier edges hide faint sources. A noise peak counts as a source would,
so the estimate errs high; on 21 development cases it bounded every
published source count, at 1.0 to 21 times it: 1.1 to 1.9 times on the
LOFAR and simulated SKA fields, and most where noise peaks sit on one
wide source. The image is read twice in bounded blocks, so no
image-sized array is held. An image find_sources refuses is
refused in the same way before any pixel is read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_path
|
Path
|
The FITS image |
required |
detection_threshold_sigma
|
float
|
The detection threshold the analysis
will use, |
required |
supplied_metadata
|
SuppliedImageMetadata | None
|
Values the header lacks, as the request gives them. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The number of such peaks; 0 for an image with no measurable noise. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the threshold is not finite and positive. |
InvalidSourceFinderInputError
|
If the image cannot be read as a FITS continuum image. |
UnsupportedSourceFinderConfigurationError
|
If |
SourceFinderImageTooLargeError
|
If the image exceeds the size
envelope |
Source code in src/hebog/pipeline.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | |
find_sources(request, config, executor)
Analyse one supported FITS image and atomically publish its products.
When the output already holds the products of a finished run of the
same request, with the same run ID, inputs, configuration and science,
they are returned without analysing the image again. A failed run
raises only once no task it submitted is still running, and removes
everything it staged. A killed run leaves a hidden staging directory,
which the next run to the same output removes once its owner has
provably stopped or reports with a SourceFinderStagingWarning.
The implementation is imported only when called so importing the public scheduler-independent API never loads a concrete I/O or scheduler layer.
Source code in src/hebog/pipeline.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |