Source code for habit.supervoxel.mean

# Copyright (c) 2024-2026 Li Chao, Dong Mengshi and HABIT Contributors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Mean voxel features: the default supervoxel description."""

from __future__ import annotations

from typing import Optional

from habit.contracts.habitat import Supervoxelization, VoxelFeatureField
from habit.contracts.subject import Subject
from habit.supervoxel.features_base import (
    aggregate_voxel_means,
    with_features,
)
from habit.supervoxel.features_registry import (
    SupervoxelFeatureExtractorRegistry,
)
from habit.spec.specs import Spec

__all__ = ["MeanVoxelFeatures"]
[docs] @SupervoxelFeatureExtractorRegistry.register("mean_voxel_features") class MeanVoxelFeatures: """ Describe each supervoxel by the mean of the voxel features within it. The v0.1 default (``supervoxel_level: {method: mean_voxel_features()}``) and the summary every built-in supervoxelizer already attaches. It exists as a registered component for two reasons: a study can state its choice explicitly instead of relying on a default, and a partition obtained from elsewhere (a saved label map, a third-party segmenter) can be described without re-running the supervoxelization. Voxel features are not recoverable from a :class:`~habit.contracts.habitat.Supervoxelization` alone, so the field that produced the partition must be supplied at construction time when calling this extractor standalone. Constructed without one, it returns the partition's existing features unchanged, which is the idempotent behaviour a pipeline needs when the user names the default explicitly. Args: field: Voxel features to aggregate. Optional; see above. """
[docs] def __init__(self, field: Optional[VoxelFeatureField] = None) -> None: self._field = field
@property def spec(self) -> Spec: """Return the algorithm specification.""" return Spec(name="mean_voxel_features", params={})
[docs] def __call__( self, subject: Subject, partition: Supervoxelization, ) -> Supervoxelization: """ Recompute per-supervoxel means over the partition's regions. Args: subject: Unused; means need no intensity access beyond the voxel features already computed. The parameter is part of the protocol so every extractor is interchangeable. partition: The subject's supervoxel partition. Returns: The partition with mean features attached. """ if self._field is None: return with_features(partition, partition.features, self.spec) features = aggregate_voxel_means(self._field, partition.label_array) return with_features(partition, features, self.spec)