konfai.data package#

Submodules#

konfai.data.augmentation module#

Data augmentation primitives applied by KonfAI datasets.

class konfai.data.augmentation.Prob(prob=1.0)[source]#

Bases: object

class konfai.data.augmentation.DataAugmentationsList(nb=10, data_augmentations={'default|Flip': <konfai.data.augmentation.Prob object>})[source]#

Bases: object

prepare(key)[source]#
Return type:

None

set_datasets(datasets)[source]#
Return type:

None

class konfai.data.augmentation.DataAugmentation(groups=None)[source]#

Bases: NeedDevice, ABC

load(prob)[source]#
set_datasets(datasets)[source]#
reset_state(index=None)[source]#

Drop the cached sampling for index so the next state_init re-samples.

Augmentation parameters are drawn once per case index and cached so that every patch of that case shares a consistent transform within an epoch (see state_init). They must, however, be re-drawn at the start of each epoch; otherwise a case keeps identical augmentation parameters for the whole run. DatasetManager.reset_augmentation calls this before state_init on every epoch reset. Subclass-specific caches (e.g. matrix/flip) are keyed by the same index and are overwritten by the subsequent _state_init; when the re-draw selects nothing they are left untouched but never read (__call__/inverse gate on who_index). Passing None clears every cached index.

Return type:

None

state_init(index, shapes, caches_attribute)[source]#
Return type:

list[list[int]]

patch_locality(index, a, cache_attribute)[source]#

Declare how the draw of copy a makes its output depend on its input, for patch streaming.

The same contract as konfai.data.transform.Transform.patch_locality() – read-only, no I/O, total, WHOLE_VOLUME by default – asked of one copy of one case, because that is the grain an augmentation is parameterised at: the halo of a geometric draw is the draw’s own, so two copies of the same case answer differently and the same copy answers differently next epoch. A copy the draw did not select is the identity, which the base answers for.

Return type:

PatchLocality

stream_region_source(index, a, target_slices, source_spatial_shape)[source]#

Map a target patch’s spatial slices to the source region copy a reads (region kinds).

Return type:

list[slice]

compute(name, index, a, tensor)[source]#

Apply the draw of copy a to one tensor – the forward counterpart of inverse().

Return type:

Tensor

inverse(index, a, tensor)[source]#
Return type:

Tensor

class konfai.data.augmentation.EulerTransform[source]#

Bases: DataAugmentation

class konfai.data.augmentation.Translate(t_min=-10, t_max=10, is_int=False)[source]#

Bases: EulerTransform

class konfai.data.augmentation.Rotate(a_min=0, a_max=360, is_quarter=False)[source]#

Bases: EulerTransform

Rotate a copy of the case about its centre.

A quarter draw is a signed permutation of the axes: an exact index remap (permute + flip), never an interpolation, and it transposes the extents it swaps, so the copy is cut on its own grid. A free angle displaces a voxel by 2 * R * sin(theta / 2) from the centre, which no constant halo bounds – it stays whole-volume.

class konfai.data.augmentation.Scale(s_std=0.2)[source]#

Bases: EulerTransform

class konfai.data.augmentation.Foreign(transform, classpath, groups=None)[source]#

Bases: DataAugmentation

Draw an augmentation from another framework.

classpath is module:Class and args are the arguments that class takes:

augmentations:
  Foreign:
    classpath: monai.transforms:RandGaussianNoise
    args: {prob: 1.0, std: 12.0}
    groups: [CT]

The class must be callable on one tensor, return the transformed tensor, and keep its shape – which is what torchvision’s transforms, TorchIO’s and MONAI’s array transforms all do.

A draw belongs to the case, and each group of the case is handed the same copy of it. The seed of the copy is drawn once and the global state is set from it before every group, so the class draws the same way for the label as for the image.

Name the ONE group a foreign draw belongs to. A single draw suits several groups only when the class consumes its random state identically whatever it is given and the draw does not SAMPLE: a rotation of the image is a rotation of the label, but a label interpolated between two ids is neither. Subclass DataAugmentation for a draw that must span groups – the draw is then a value this framework holds, rather than a random state two libraries agree about.

class konfai.data.augmentation.Flip(f_prob=[0.33, 0.33, 0.33], vector_field=False)[source]#

Bases: DataAugmentation

class konfai.data.augmentation.ColorTransform(groups=None)[source]#

Bases: DataAugmentation

class konfai.data.augmentation.Brightness(b_std, groups=None)[source]#

Bases: ColorTransform

class konfai.data.augmentation.Contrast(c_std, groups=None)[source]#

Bases: ColorTransform

class konfai.data.augmentation.LumaFlip(groups=None)[source]#

Bases: ColorTransform

class konfai.data.augmentation.HUE(hue_max, groups=None)[source]#

Bases: ColorTransform

class konfai.data.augmentation.Saturation(s_std, groups=None)[source]#

Bases: ColorTransform

class konfai.data.augmentation.Noise(n_std, noise_step=1000, beta_start=0.0001, beta_end=0.02, groups=None)[source]#

Bases: DataAugmentation

static enforce_zero_terminal_snr(betas)[source]#
load(prob)[source]#
class konfai.data.augmentation.CutOUT(c_prob, cutout_size, value, groups=None)[source]#

Bases: DataAugmentation

class konfai.data.augmentation.Elastix(grid_spacing=16, max_displacement=16)[source]#

Bases: DataAugmentation

class konfai.data.augmentation.Permute(prob_permute=[0.5, 0.5])[source]#

Bases: DataAugmentation

class konfai.data.augmentation.Mask(mask, value, groups=None)[source]#

Bases: DataAugmentation

konfai.data.data_manager module#

Dataset assembly, subset selection, and dataloader orchestration for KonfAI.

class konfai.data.data_manager.GroupTransform(transforms={'default|Normalize|Standardize|Unsqueeze|TensorCast|ResampleIsotropic|ResampleResize': <konfai.data.transform.TransformLoader object>}, patch_transforms={'default|Normalize|Standardize|Unsqueeze|TensorCast|ResampleIsotropic|ResampleResize': <konfai.data.transform.TransformLoader object>}, is_input=True)[source]#

Bases: object

Collection of transforms attached to one source-to-destination group path.

prepare(group_src, group_dest)[source]#
Return type:

None

set_datasets(datasets)[source]#
Return type:

None

to(device)[source]#
class konfai.data.data_manager.GroupTransformMetric(transforms={'default|Normalize|Standardize|Unsqueeze|TensorCast|ResampleIsotropic|ResampleResize': <konfai.data.transform.TransformLoader object>})[source]#

Bases: GroupTransform

Metric-specific group transform that omits patch-time transforms.

class konfai.data.data_manager.Group(groups_dest={'default|Labels': {'transforms': [], 'patch_transforms': []}})[source]#

Bases: dict[str, GroupTransform]

Mapping of destination group names to transform pipelines.

class konfai.data.data_manager.GroupMetric(groups_dest={'default|group_dest': {'transforms': [], 'patch_transforms': []}})[source]#

Bases: dict[str, GroupTransformMetric]

Metric-oriented variant of Group used during evaluation.

class konfai.data.data_manager.WindowedCaseSampler(mapping, shuffle, window, batch_size, num_workers)[source]#

Bases: Sampler[int]

Locality-aware training order: shuffle cases, window them, shuffle patches within each window.

DatasetIter loads each non-streamable case into a FIFO buffer, so a global patch shuffle reloads a volume repeatedly – once per patch that lands after an eviction. Keeping only window cases in play at a time — their patches shuffled together, emitted before advancing — reads each volume ~once. window is the decorrelation knob: 1 is perfect locality, and None (default) or >= n_cases is a single all-cases window, i.e. a plain global shuffle, byte for byte.

A map-style DataLoader sends batch j to worker j % num_workers and gives each worker its own buffer, so the cases are partitioned across workers (greedy least-loaded by patch count, see _partitions) and the per-worker windowed batches are round-robin interleaved: batch j then carries only worker j % num_workers’s cases, and every volume is read by exactly one worker.

class konfai.data.data_manager.DataItem(name, tensor, attribute, x, a, p, is_input)[source]#

Bases: object

Single tensor sample together with dataset metadata and patch indices.

name: str#
tensor: Tensor#
attribute: Attribute#
x: int#
a: int#
p: int#
is_input: bool#
class konfai.data.data_manager.BatchDataItem(name, tensor, attribute, x, a, p, is_input)[source]#

Bases: object

Batch-level representation of multiple DataItem objects.

name: list[str]#
tensor: Tensor#
attribute: list[Attribute]#
x: list[int]#
a: list[int]#
p: list[int]#
is_input: bool#
konfai.data.data_manager.collate_konfai(batch)[source]#

Collate KonfAI samples into the batch structure expected by the workflows.

Return type:

dict[str, BatchDataItem]

class konfai.data.data_manager.DatasetIter(rank, data, mapping, groups_src, inline_augmentations, data_augmentations_list, patch_size, overlap, buffer_size, apply_augmentations=True, use_cache=True)[source]#

Bases: Dataset

Torch dataset view over KonfAI dataset managers and patch mappings.

get_patch_config()[source]#
Return type:

tuple[list[int] | None, int | None]

to(device)[source]#
get_dataset_from_index(group_dest, index)[source]#
Return type:

DatasetManager

reset_augmentation(label)[source]#
load(label)[source]#
load_data(group_src, group_dest, index, augmentation_index=None)[source]#
Return type:

bool

unload_data(group_dest, index)[source]#
Return type:

None

class konfai.data.data_manager.Subset(subset=None, shuffle=True, shuffle_window=None)[source]#

Bases: object

requires_infos()[source]#

Return whether this subset implementation needs per-sample metadata.

Return type:

bool

class konfai.data.data_manager.TrainSubset(subset=None, shuffle=True, shuffle_window=None)[source]#

Bases: Subset

class konfai.data.data_manager.PredictionSubset(subset=None)[source]#

Bases: Subset

class konfai.data.data_manager.Data(dataset_filenames, groups_src, patch, use_cache, subset, batch_size, validation, validation_augmentations, inline_augmentations, data_augmentations_list, num_workers, pin_memory, prefetch_factor, persistent_workers, memory_budget)[source]#

Bases: ABC

Abstract base class shared by training, prediction, and evaluation datasets.

data: list[list[dict[str, list[DatasetManager]]]]#
mapping: list[list[list[tuple[int, int, int]]]]#
datasets: dict[str, Dataset]#
prepare()[source]#

Instantiate config-driven transforms and augmentations before runtime.

Return type:

None

get_groups_dest()[source]#
get_data(world_size)[source]#
Return type:

tuple[list[list[DataLoader]], list[str], list[str]]

class konfai.data.data_manager.DataTrain(dataset_filenames=['default|./Dataset:mha'], groups_src={'default|Labels': {'default|Labels': {'transforms': [], 'patch_transforms': []}}}, augmentations={'DataAugmentation_0': <konfai.data.augmentation.DataAugmentationsList object>}, inline_augmentations=False, patch=<konfai.data.patching.DatasetPatch object>, use_cache=True, memory_budget=None, subset=<konfai.data.data_manager.TrainSubset object>, batch_size=1, validation=0.2, validation_augmentations=True, num_workers=None, pin_memory=False, prefetch_factor=None, persistent_workers=None)[source]#

Bases: Data

Dataset configuration used by the training workflow.

class konfai.data.data_manager.DataPrediction(dataset_filenames=['default|./Dataset'], groups_src={'default': {'default|Labels': {'transforms': [], 'patch_transforms': []}}}, augmentations={'DataAugmentation_0': <konfai.data.augmentation.DataAugmentationsList object>}, patch=<konfai.data.patching.DatasetPatch object>, memory_budget=None, subset=<konfai.data.data_manager.PredictionSubset object>, batch_size=1, num_workers=None, pin_memory=False, prefetch_factor=None, persistent_workers=None)[source]#

Bases: Data

Dataset configuration used by the prediction workflow.

class konfai.data.data_manager.DataMetric(dataset_filenames=['default|./Dataset:mha'], groups_src={'default': {'default|group_dest': {'transforms': [], 'patch_transforms': []}}}, memory_budget=None, subset=<konfai.data.data_manager.PredictionSubset object>, validation=None, num_workers=None, pin_memory=False, prefetch_factor=None, persistent_workers=None)[source]#

Bases: Data

Dataset configuration used by the evaluation workflow.

konfai.data.patching module#

Patch extraction, accumulation, and patch-combination helpers for KonfAI.

class konfai.data.patching.Stage(*args, **kwargs)[source]#

Bases: Protocol

One step of what a case’s copy is made of, as the patch-streaming dispatcher sees it.

A copy is its group’s transforms followed by the augmentations drawn for it, and streaming asks the same three things of every step: what its output depends on, which source region a target patch needs, and to run on one tensor. A Transform answers them as itself. An augmentation is parameterised per case and per copy, so it answers them bound to one (see AugmentedStage).

patch_locality(cache_attribute)[source]#
Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#
Return type:

list[slice]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#
Return type:

None

class konfai.data.patching.AugmentedStage(augmentation, index, a)[source]#

Bases: object

One augmentation, bound to the case and the copy whose draw it carries.

An augmentation is parameterised per (case, copy); binding both makes it answer the Stage protocol like a plain transform.

augmentation: DataAugmentation#
index: int#
a: int#
patch_locality(cache_attribute)[source]#
Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#
Return type:

list[slice]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

An augmentation draws a copy of the case rather than restating its geometry: nothing to record.

Return type:

None

class konfai.data.patching.PatchReadPlan(data_slices, reflect_padding, constant_padding, concatenate_extend_slice)[source]#

Bases: object

Precomputed slicing and padding instructions for one patch request.

data_slices: tuple[slice, ...]#
reflect_padding: tuple[int, ...]#
constant_padding: tuple[int, ...]#
concatenate_extend_slice: bool#
class konfai.data.patching.PathCombine[source]#

Bases: ABC

Base class for overlap-aware weighting schemes applied during patch assembly.

data: Tensor#
overlap: int#
set_patch_config(patch_size, overlap)[source]#
Return type:

None

class konfai.data.patching.Mean[source]#

Bases: PathCombine

Uniform weighting: overlapping patches are plain-averaged by the assembly normalisation.

class konfai.data.patching.Cosinus[source]#

Bases: PathCombine

Raised-cosine (sin**2) taper: a smooth partition of unity across the patch overlap.

class konfai.data.patching.Gaussian(sigma_scale=0.125)[source]#

Bases: PathCombine

nnU-Net-style Gaussian importance weighting.

Favours patch centres — where the model sees the most surrounding context — and down-weights the borders, which suppresses seam artefacts. Not a partition of unity, but Accumulator.assemble normalises by the accumulated weight, so overlapping patches still form a correct weighted average.

class konfai.data.patching.Accumulator(patch_slices, patch_size, patch_combine=None, batch=True)[source]#

Bases: object

Accumulate patch predictions and reassemble them into a full tensor.

patch_slices: list[tuple[slice, ...]]#
add_layer(index, layer)[source]#
Return type:

None

is_empty()[source]#

True until the first patch has been blended in (no volume-sized buffer allocated yet).

Return type:

bool

is_full()[source]#
Return type:

bool

assemble()[source]#
Return type:

Tensor

class konfai.data.patching.Patch(patch_size, overlap, pad_value=0, extend_slice=0)[source]#

Bases: ABC

Abstract base class for dataset-level and model-level patch definitions.

load(shape, a=0)[source]#
Return type:

None

abstractmethod init(key)[source]#
get_patch_slices(a=0)[source]#
get_read_plan(data_shape, index, a, is_input)[source]#
Return type:

PatchReadPlan

apply_read_plan(data, plan)[source]#
Return type:

Tensor

get_data(data, index, a, is_input)[source]#
Return type:

list[Tensor]

get_size(a=0)[source]#
Return type:

int

class konfai.data.patching.DatasetPatch(patch_size=[128, 128, 128], overlap=None, pad_value=None, extend_slice=0)[source]#

Bases: Patch

Patch definition applied when sampling data from datasets.

init(key='')[source]#
class konfai.data.patching.ModelPatch(patch_size=[128, 128, 128], overlap=None, patch_combine=None, pad_value=None, extend_slice=0)[source]#

Bases: Patch

Patch definition applied inside model graphs during prediction or training.

patch_combine: PathCombine | None#
init(key)[source]#
disassemble(*data_list)[source]#
Return type:

Iterator[list[Tensor]]

class konfai.data.patching.DatasetManager(index, group_src, group_dest, name, dataset, patch, transforms, data_augmentations_list)[source]#

Bases: object

Cache-backed manager for one dataset case and one source/destination group.

cache_attributes: list[Attribute]#
data: list[Tensor]#
augmented_data: dict[int, Tensor]#
shapes: list[list[int]]#
reset_augmentation(reset_state=True)[source]#
load(pre_transform, data_augmentations_list, load_augmentations=True)[source]#
Return type:

None

can_stream_patch(a, apply_augmentations=True)[source]#
Return type:

bool

unload()[source]#
Return type:

None

unload_augmentation()[source]#
Return type:

None

get_data(index, a, patch_transforms, is_input, apply_augmentations=True)[source]#
Return type:

Tensor

get_size(a)[source]#
Return type:

int

konfai.data.transform module#

Tensor and image transforms used in KonfAI preprocessing and postprocessing.

class konfai.data.transform.LocalityKind(*values)[source]#

Bases: Enum

How a transform’s output at one voxel depends on its input (its patch-locality contract).

A transform DECLARES its contract via Transform.patch_locality(); the patch-streaming dispatcher (konfai.data.patching) reads the declaration and reads only the source region a target patch actually needs, instead of materialising the whole volume.

  • POINTWISE – output voxel depends only on the same voxel (and its channels): read the exact patch.

  • HALO – bounded neighbourhood: read the patch enlarged by halo per axis, crop after.

  • ORIENTATION – flip/permute: read the index-remapped source region.

  • CROP – the source region is the target region TRANSLATED: reading it IS the answer, so the stage is not re-applied to it. Unlike a reorientation this drops the voxels outside the box, so it is no bijection and the stored volume’s statistics are not its output’s.

  • GLOBAL_STAT – needs whole-volume stats (stat_keys subset of Min/Max/Mean/Std), obtained once from disk and cached: read the exact patch + the cached stat.

  • RESCALE – resample: source region via the scale mapping + interpolation halo.

  • WHOLE_VOLUME– genuinely needs the whole volume: the dispatcher falls back to a full load.

POINTWISE = 'pointwise'#
HALO = 'halo'#
ORIENTATION = 'orientation'#
CROP = 'crop'#
GLOBAL_STAT = 'global_stat'#
RESCALE = 'rescale'#
WHOLE_VOLUME = 'whole_volume'#
property preserves_statistics: bool#

Whether this kind leaves every whole-volume statistic of its input untouched.

Only a reorientation does: a flip or a permute is a bijection on the voxels, so the multiset of values – and therefore Min/Max/Mean/Std over it – is exactly the input’s. Every other kind may map values (POINTWISE, GLOBAL_STAT), mix neighbours (HALO) or interpolate (RESCALE). This is what decides whether the statistics of the STORED volume are still those of a later transform’s own input (see DatasetManager._plan_stream_region).

class konfai.data.transform.PatchLocality(kind, halo=(), stat_keys=<factory>, stat_channels=None, preserves_statistics=None)[source]#

Bases: object

A transform’s declared patch-locality contract (see LocalityKind).

halo is the per-spatial-axis neighbourhood radius in array order (Z, Y, X); a length-1 tuple broadcasts to every axis. stat_keys are the Attribute keys a GLOBAL_STAT transform reads before running (a subset of Min/Max/Mean/Std). stat_channels restricts the statistic to those channels (Normalize.channels).

kind: LocalityKind#
halo: tuple[int, ...] = ()#
stat_keys: frozenset[str]#
stat_channels: list[int] | None = None#
preserves_statistics: bool | None = None#
property statistics_preserving: bool#
class konfai.data.transform.Transform[source]#

Bases: NeedDevice, ABC

Base class for transforms operating on tensors and cached attributes.

supports_dataloader_workers = True#
datasets: list[Dataset]#
set_datasets(datasets)[source]#
transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#

Map a target-patch’s spatial slices to the source spatial region to read (region kinds).

Overridden by the kinds whose source region is an index remap of the target’s – ORIENTATION maps it and reorients what it reads, CROP maps it and is done. HALO and RESCALE are handled generically by the dispatcher, so the base raises for any transform that declares a region kind without providing the remap.

cache_attribute is the case’s SOURCE metadata, under the same rules as patch_locality(): a remap the image decides (a reorientation whose mirrored axes are the case’s own direction cosines) reads it here, and reads nothing else.

Return type:

list[slice]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the geometry a whole-volume __call__ would, given the FULL source shape.

Called once per case, on the persistent attribute, for the stage that owns a streamed region. A transform whose geometry rewrite depends on the volume’s EXTENT (a reorientation’s new origin is the corner it mirrors onto) cannot compute it from a patch, which is all its __call__ is handed while streaming: it writes the case-level answer here instead, and the patch-local one it wrote on the way is dropped rather than persisted. The base is a no-op – a transform that leaves geometry alone has nothing to record.

Return type:

None

class konfai.data.transform.TransformInverse(inverse)[source]#

Bases: Transform, ABC

Base class for transforms that can also invert their effect.

abstractmethod inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.TransformLoader[source]#

Bases: object

Resolve and instantiate transform classes from KonfAI configuration.

get_transform(classpath, konfai_args)[source]#
Return type:

Transform

class konfai.data.transform.Foreign(transform, classpath)[source]#

Bases: Transform

A transform from another framework, as the loader hands it over.

Name the class where a transform goes and its arguments under it:

transforms:
  monai.transforms:ScaleIntensity:
    minv: 0.0
    maxv: 1.0

The class must be callable on one tensor and return the transformed tensor, which is what torchvision’s transforms, TorchIO’s and MONAI’s array transforms all are. MONAI’s dictionary transforms (ScaleIntensityd) take a dictionary of keys instead: a KonfAI group is the key, so name the array class.

The class must be DETERMINISTIC: a transform runs on each group of a case in turn, so a random one would draw again for the label and misalign it from the image. Name it under the augmentations instead, where a draw is made once for the case and every group is handed it.

It reads the whole volume, which is what a class saying nothing about where its output comes from is owed. The shape is checked rather than assumed: the patch grid is planned on the shape a transform announces, and this one announces the shape it was given. Geometry is left as it stands, which a transform of the intensities alone leaves. A class that resamples, crops or reorients owns both, and a Transform subclass is what states them.

class konfai.data.transform.Clip(min_value=-1024, max_value=1024, save_clip_min=False, save_clip_max=False, mask=None)[source]#

Bases: Transform

Clip tensor intensities to a fixed or data-dependent value range.

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Normalize(lazy=False, channels=None, min_value=-1, max_value=1, inverse=True)[source]#

Bases: TransformInverse

Map intensities to a target min/max interval and optionally invert it.

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.UnNormalize(min_value=-1024, max_value=3071)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Standardize(lazy=False, mean=None, std=None, mask=None, inverse=True)[source]#

Bases: TransformInverse

Standardize tensors using cached or computed mean and standard deviation.

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.TensorCast(dtype='float32', inverse=True)[source]#

Bases: TransformInverse

dtype: dtype#
patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

static safe_dtype_cast(dtype_str)[source]#
Return type:

dtype

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Padding(padding=[0, 0, 0, 0, 0, 0], mode='constant', inverse=True)[source]#

Bases: TransformInverse

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Squeeze(dim, inverse=True)[source]#

Bases: TransformInverse

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Resample(inverse)[source]#

Bases: TransformInverse, ABC

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

abstractmethod transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

resample_source_region(target_slices, source_spatial_shape, cache_attribute, halo=1)[source]#

Map a TARGET-grid patch to the minimal SOURCE region to read.

Returns (source_slices, region_starts, scales, n_in, n_out) — all in array axis order (Z, Y, X). The halo is a pure safety margin (the formula’s +2 already captures the i1 neighbour); nearest needs none.

Return type:

tuple[list[slice], list[int], list[float], list[int], list[int]]

resample_region(sub_tensor, target_slices, region_starts, scales, n_in)[source]#

Interpolate a source sub-region to the target patch extent.

sub_tensor is [C, (z, y, x)] covering source_slices; region_starts are the global source indices of its first voxel per axis. Uses the same global coordinate formula as the whole-volume path, indexing the sub-region as sub[i - region_start].

Return type:

Tensor

abstractmethod write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the same ‘Spacing’/’Size’ stack a whole-volume __call__ would.

Called once per case on the persistent attribute so inverse() at prediction time pops exactly what the non-streamed path pushed. Uses the FULL source shape, never the halo’d sub-region.

Return type:

None

class konfai.data.transform.ResampleToResolution(spacing=[1.0, 1.0, 1.0], inverse=True)[source]#

Bases: Resample

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the same ‘Spacing’/’Size’ stack a whole-volume __call__ would.

Called once per case on the persistent attribute so inverse() at prediction time pops exactly what the non-streamed path pushed. Uses the FULL source shape, never the halo’d sub-region.

Return type:

None

class konfai.data.transform.ResampleToShape(shape=[100, 256, 256], inverse=True)[source]#

Bases: Resample

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the same ‘Spacing’/’Size’ stack a whole-volume __call__ would.

Called once per case on the persistent attribute so inverse() at prediction time pops exactly what the non-streamed path pushed. Uses the FULL source shape, never the halo’d sub-region.

Return type:

None

class konfai.data.transform.ResampleTransform(transforms, inverse=True)[source]#

Bases: TransformInverse

Resample a volume through stored transforms (a displacement field, an affine).

Whole-volume: nothing in the format bounds the stored displacement, so no halo can be declared from the header alone.

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Mask(path='./default.mha', value_outside=0)[source]#

Bases: Transform

Set everything outside a mask to a constant.

Whole-volume: __call__ does not know where its tensor sits, so it cannot read the matching region of the mask (Clip(mask=) and Standardize(mask=) load whole volumes for the same reason).

class konfai.data.transform.Dilate(dilate=1)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Sum(dim=0)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.MergeLabels[source]#

Bases: Transform

Merge the per-model argmax label maps of a combine: Concat ensemble into one global map.

Each model’s Argmax produces a LOCAL class index (0 = background). A model’s non-background labels are shifted past every earlier model’s foreground classes – by the CUMULATIVE sum of the earlier models’ foreground counts (nb_class - 1) – so the models’ disjoint label ranges tile a single global label space.

This is the label-space counterpart of InferenceStack (which averages same-class probability ensembles): use MergeLabels when the models segment DIFFERENT structures, e.g. the 5-task TotalSegmentator ensemble (organs / vertebrae / cardiac / muscles / ribs). Requires number_of_channels_per_model in the attribute (written by the Concat reduction).

Models are assumed to segment disjoint structures, but boundaries disagree in practice: a voxel claimed by several models takes the label of the LAST model in ensemble order (adding the global ids instead would fabricate a label belonging to neither model).

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Gradient(per_dim=False)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Argmax(dim=0)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Softmax(dim=0)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.FlatLabel(labels=None)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Save(dataset, group=None)[source]#

Bases: Transform

class konfai.data.transform.Flatten[source]#

Bases: Transform

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

class konfai.data.transform.Permute(dims='1|0|2', inverse=True)[source]#

Bases: TransformInverse

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#

Map a target-patch’s spatial slices to the source spatial region to read (region kinds).

Overridden by the kinds whose source region is an index remap of the target’s – ORIENTATION maps it and reorients what it reads, CROP maps it and is done. HALO and RESCALE are handled generically by the dispatcher, so the base raises for any transform that declares a region kind without providing the remap.

cache_attribute is the case’s SOURCE metadata, under the same rules as patch_locality(): a remap the image decides (a reorientation whose mirrored axes are the case’s own direction cosines) reads it here, and reads nothing else.

Return type:

list[slice]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Flip(dims='1|0|2', inverse=True)[source]#

Bases: TransformInverse

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#

Map a target-patch’s spatial slices to the source spatial region to read (region kinds).

Overridden by the kinds whose source region is an index remap of the target’s – ORIENTATION maps it and reorients what it reads, CROP maps it and is done. HALO and RESCALE are handled generically by the dispatcher, so the base raises for any transform that declares a region kind without providing the remap.

cache_attribute is the case’s SOURCE metadata, under the same rules as patch_locality(): a remap the image decides (a reorientation whose mirrored axes are the case’s own direction cosines) reads it here, and reads nothing else.

Return type:

list[slice]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.Canonical(inverse=True)[source]#

Bases: TransformInverse

Reorient a volume onto the canonical (LPS) direction cosines.

An orthogonal reorientation is a signed permutation of the axes: an exact index remap (values only change place, so whole-volume statistics survive); only an oblique direction is resampled. A remap that permutes axes transposes the extents it swaps, so transform_shape folds the patch grid onto the reoriented shape.

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#

Map a target-patch’s spatial slices to the source spatial region to read (region kinds).

Overridden by the kinds whose source region is an index remap of the target’s – ORIENTATION maps it and reorients what it reads, CROP maps it and is done. HALO and RESCALE are handled generically by the dispatcher, so the base raises for any transform that declares a region kind without providing the remap.

cache_attribute is the case’s SOURCE metadata, under the same rules as patch_locality(): a remap the image decides (a reorientation whose mirrored axes are the case’s own direction cosines) reads it here, and reads nothing else.

Return type:

list[slice]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the geometry a whole-volume __call__ would, given the FULL source shape.

Called once per case, on the persistent attribute, for the stage that owns a streamed region. A transform whose geometry rewrite depends on the volume’s EXTENT (a reorientation’s new origin is the corner it mirrors onto) cannot compute it from a patch, which is all its __call__ is handed while streaming: it writes the case-level answer here instead, and the patch-local one it wrote on the way is dropped rather than persisted. The base is a no-op – a transform that leaves geometry alone has nothing to record.

Return type:

None

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.HistogramMatching(reference_group)[source]#

Bases: Transform

Match a volume’s intensity distribution onto a reference group’s.

Whole-volume: the LUT is built from the volume’s 256-bin histogram, which is not a statistic GLOBAL_STAT names and cannot be read back out of the sitk filter.

class konfai.data.transform.SelectLabel(labels)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.OneHot(num_classes, inverse=True)[source]#

Bases: TransformInverse

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

class konfai.data.transform.KonfAIInference(repo_id='VBoussot/MRSegmentator-KonfAI', model_name='MRSegmentator', checkpoints_name=['fold_0'], number_of_tta=0, number_of_mc=0, per_channel=False)[source]#

Bases: Transform

supports_dataloader_workers = False#
infer_entry(dataset_path, output_path, gpu)[source]#
class konfai.data.transform.InferenceStack(dataset, name, mode='mean')[source]#

Bases: Transform

class konfai.data.transform.Norm[source]#

Bases: Transform

Vector magnitude over the trailing component axis.

Reduces a stacked vector field (e.g. a displacement-field ensemble [N, (D), H, W, C]) to per-sample magnitudes [N, (D), H, W], typically before Variance/StandardDeviation. The trailing tensor axis is the first geometry axis (numpy order is reversed), so that axis is dropped from Origin/Spacing/Direction.

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

class konfai.data.transform.Variance[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.SegmentationDisagreement(ignore_background=False)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Percentage(baseline)[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.StandardDeviation[source]#

Bases: Transform

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

class konfai.data.transform.Statistics[source]#

Bases: Transform

class konfai.data.transform.Crop(inverse=True)[source]#

Bases: TransformInverse

Crop a volume to the bounding box of its foreground.

The content-dependent box is computed once (transform_shape) and kept on the case as box margins; cropping is then the translation out[o] = volume[o + start], so a target patch reads its shifted source region. Dropped voxels mean the stored volume’s statistics are not the output’s (hence LocalityKind.CROP).

patch_locality(cache_attribute)[source]#

Declare how this transform’s output depends on its input, for patch streaming.

Answered from the transform’s own __init__ config and, where the honest answer depends on the image, from cache_attribute – the case’s SOURCE metadata, as the volume is stored. The dispatcher reads the header before any voxel, so a transform whose contract the image decides (a reorientation that is only a flip when the direction cosines are axis-aligned, a resample whose halo is the case’s own scale) can still declare it up front.

The default WHOLE_VOLUME is the safety net: any transform (including third-party custom ones) that does not override this falls to the whole-volume path, so nothing silently breaks.

An override is bound by three rules:

  • READ-ONLY. Never write to cache_attribute. A declaration is made once, for the whole case, and what it wrote would be one patch’s answer imposed on every other – the first-patch-wins bug the streamed paths are built to avoid. The dispatcher hands over a private copy, so a write cannot reach the case; it is simply lost.

  • NO I/O. Read the attribute already in hand, nothing else. Whether the outside world can honour the declaration (are the disk statistics readable, does a mask group exist) is the dispatcher’s call, and it already makes it.

  • TOTAL. Answer for ANY case. The metadata may be absent – the config-time checks probe with an empty Attribute, and a group carries only what its writer stored – so a missing key must return WHOLE_VOLUME, never raise.

Return type:

PatchLocality

stream_region_source(target_slices, source_spatial_shape, cache_attribute)[source]#

Map a target-patch’s spatial slices to the source spatial region to read (region kinds).

Overridden by the kinds whose source region is an index remap of the target’s – ORIENTATION maps it and reorients what it reads, CROP maps it and is done. HALO and RESCALE are handled generically by the dispatcher, so the base raises for any transform that declares a region kind without providing the remap.

cache_attribute is the case’s SOURCE metadata, under the same rules as patch_locality(): a remap the image decides (a reorientation whose mirrored axes are the case’s own direction cosines) reads it here, and reads nothing else.

Return type:

list[slice]

write_stream_cache_attribute(cache_attribute, source_spatial_shape)[source]#

Record the geometry a whole-volume __call__ would, given the FULL source shape.

Called once per case, on the persistent attribute, for the stage that owns a streamed region. A transform whose geometry rewrite depends on the volume’s EXTENT (a reorientation’s new origin is the corner it mirrors onto) cannot compute it from a patch, which is all its __call__ is handed while streaming: it writes the case-level answer here instead, and the patch-local one it wrote on the way is dropped rather than persisted. The base is a no-op – a transform that leaves geometry alone has nothing to record.

Return type:

None

transform_shape(group_src, name, shape, cache_attribute)[source]#
Return type:

list[int]

inverse(name, tensor, cache_attribute)[source]#
Return type:

Tensor

Module contents#

Data loading, patching, transform, and augmentation utilities for KonfAI.