container_loaders
anomaly_match.data_io.container_loaders
¶
Decode functions for reading images from Zarr containers and Cutana caches.
These are shared between the training data sources and the prediction subprocess scripts. Centralising them avoids duplication and ensures consistent behaviour.
decode_zarr_image(image_data, cfg)
¶
Read and preprocess raw pixel data from an upstream Zarr store.
Runs the full fitsbolt pipeline (normalisation + resize) on the raw
array values, then applies channel_combination as post-processing.
The fitsbolt config carries channel_combination=None for non-FITS
sources (see :func:get_fitsbolt_config), so this post-hoc combine is
the single application — never a duplicate of a fitsbolt-side one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_data
|
ndarray
|
Raw pixel array from Zarr (CHW or HWC). |
required |
cfg
|
DotMap
|
Configuration with |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Preprocessed image as HWC numpy array with |
ndarray
|
|
Source code in anomaly_match/data_io/container_loaders.py
decode_zarr_gallery_images(raw_images, cfg)
¶
Decode raw Zarr pixels for gallery thumbnails the way the model saw them.
The gallery reads images straight from the store, so without this its
thumbnails ignored normalisation and channel_combination — a 1-output
matrix still showed colour images.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_images
|
dict[str, ndarray]
|
|
required |
cfg
|
DotMap
|
Session configuration; its |
required |
Returns:
| Type | Description |
|---|---|
dict[str, ndarray]
|
|
dict[str, ndarray]
|
and left out, so one bad entry does not blank the whole page. |
Source code in anomaly_match/data_io/container_loaders.py
apply_channel_combination_to_cutana_image(image_data, cfg)
¶
Combine Cutana per-band output to n_output_channels via fitsbolt.
Used on Cutana orchestrator output in the unlabeled training stream
and the prediction subprocess, where Cutana is configured with the
user's normalisation settings and returns per-band already
normalised data. The labeled cache read path uses
:func:decode_cutana_raw_images instead, because that path sees
unnormalised float32 and needs the full fitsbolt pipeline.
When no channel_combination is configured and the input has
exactly one band, the single channel is broadcast to
n_output_channels (the implicit "replicate VIS to RGB" intent for
single-extension sources). Otherwise the image passes through
unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_data
|
ndarray
|
HWC array from Cutana with |
required |
cfg
|
DotMap
|
Configuration holding |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
HWC numpy array with |
ndarray
|
as the input (which is already |
ndarray
|
because the orchestrator is built with matching |
Source code in anomaly_match/data_io/container_loaders.py
apply_channel_combination_to_cutana_batch(batch_data, cfg)
¶
Batched form of :func:apply_channel_combination_to_cutana_image.
Applies channel_combination to a whole (N, H, W, n_extensions)
stack in a single :func:batch_channel_combination matmul instead of a
per-image Python loop. On the prediction hot path this collapses the
dominant cost: a per-image loop over the channel combination was ~89% of
end-to-end wall time for multi-band (VIS+NIR) scoring (issue #458).
Output is identical to stacking the per-image results — the loop variant just paid Python-call and batch-axis-juggling overhead per cutout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch_data
|
ndarray
|
|
required |
cfg
|
DotMap
|
Configuration holding |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
|
ndarray
|
Contiguity is established by the consumer at the point it is needed |
ndarray
|
( |
ndarray
|
transpose, just before |
Source code in anomaly_match/data_io/container_loaders.py
decode_cutana_raw_images(images, cfg)
¶
Decode a batch of raw Cutana cache images in one fitsbolt pass.
Each image is expected to be an HWC ndarray with n_extensions
bands on the last axis — the layout the labeled cache stores after
Cutana extraction, so 3-band RGB, 4-band Euclid (VIS + NISP Y/J/H)
and any other per-band count work identically.
The labeled cache stores unnormalised float32 cutouts at a fixed
resolution (see
:data:anomaly_match.data_io.labeled_data_cache.LABELED_CACHE_RESOLUTION).
This function applies the user's current
normalisation_method/output_dtype/image_size/
channel_combination on the fly, so the cache stays valid across
all of those changes.
Versus decoding each item in its own call, three things are shared
across the batch: the fitsbolt_cfg save/restore dance happens once
(instead of N times), the per-cutout resize+normalise is fanned out
across the pod's cores (the resize anti-aliasing releases the GIL —
issue #500), and the final channel_combination matmul runs once on
a stacked (N,H,W,C) array via :func:batch_channel_combination —
a measurable win on 100+ preview thumbnails and a thousand-plus
labeled cutouts.
fitsbolt 0.3.x combines raw arrays too, so we pin
n_output_channels/n_expected_channels to the per-band count and
clear channel_combination on the fitsbolt config, then apply the
user's combination matrix post-hoc — mirroring :func:decode_zarr_image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
images
|
list[ndarray]
|
Raw HWC float arrays from the cache with |
required |
cfg
|
DotMap
|
Configuration with |
required |
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List of HWC numpy arrays at |
list[ndarray]
|
|
list[ndarray]
|
configured output dtype, one per input. Empty list if images |
list[ndarray]
|
is empty. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If images mix band counts (the batch must be homogeneous — see the single-pass channel-combination resolve). |
Source code in anomaly_match/data_io/container_loaders.py
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 | |