Habitat domain API
Imaging-side protocols, built-in operators, registries, and
SubjectPipeline. This is the embedding API: each protocol is
op(subject) or op(field) and returns a typed contract. Import
registries from the v2 capability packages (they are not top-level habit
exports).
Walkthrough (stop after any step, bring your own Subject):
Atomic operators. Concept:
Habitat analysis. Arrays in:
Load data.
For a whole-cohort study without hand-wiring each operator, use
fit_predict() with
stages (Python API guide (v2.0), beginner
path Quickstart: Python API). The mode-named aliases
(two_step_habitat(),
direct_pooling_habitat(),
one_step_habitat()) remain as thin validators.
A backend is optional. One subject is pipe(subject). Parallel /
checkpoints: Parallel execution and fault tolerance.
import the v2 capability packages # registers all built-ins
from habit.habitat_model import HabitatAssignerRegistry, HabitatModelFitterRegistry
from habit.habitat_features import HabitatFeatureExtractorRegistry
from habit.pipeline import SubjectPipeline
from habit.supervoxel import SupervoxelFeatureExtractorRegistry, SupervoxelizerRegistry
from habit.voxel_features import VoxelFeatureExtractorRegistry
Protocols
Protocol |
Call shape |
Level |
|---|---|---|
|
|
Subject |
|
|
Subject |
|
enriches supervoxel features |
Subject |
|
|
Cohort |
|
|
Subject |
|
|
Subject |
|
|
mixin |
|
|
Dataflow watershed |
Registry pattern (all domains)
from habit.supervoxel import SlicSupervoxelizer, SupervoxelizerRegistry
names = SupervoxelizerRegistry.available()
print(SupervoxelizerRegistry.constructor_signature("slic"))
op = SupervoxelizerRegistry.create("slic", n_supervoxels=50)
op = SlicSupervoxelizer(n_supervoxels=50)
Voxel feature extractors
Domain: voxel_feature_extractor
from habit.voxel_features import (
RawVoxelFeatures,
VoxelFeatureExtractorRegistry,
VoxelRadiomicsFeatures,
extract_voxel_texture,
)
voxel = VoxelFeatureExtractorRegistry.create(
"raw",
modalities=["T1", "T2"],
)
# Equivalent class form:
voxel = RawVoxelFeatures(modalities=["T1", "T2"])
field = voxel(subject)
texture = VoxelRadiomicsFeatures(modalities=["T2"], kernel_radius=3)
# Same extractor, one ImageVolume + mask (no Subject):
field = extract_voxel_texture(image, mask, kernel_radius=3, bin_width=12)
raw→RawVoxelFeatureslocal_entropy→LocalEntropyVoxelFeaturesvoxel_radiomics→VoxelRadiomicsFeatures(per-voxel texture)concat/expression/kinetic→ compose the families aboveextract_voxel_texture()— volume-levelvoxel_radiomics
Full names and knobs: Habitat Spec component catalog.
Supervoxelizers
Domain: supervoxelizer
from habit.supervoxel import SupervoxelizerRegistry
# All built-in supervoxelizers use n_supervoxels (not sklearn's
# n_clusters / n_components). Confirm with the constructor:
# SupervoxelizerRegistry.constructor_signature("kmeans")
slic = SupervoxelizerRegistry.create("slic", n_supervoxels=50)
km = SupervoxelizerRegistry.create("kmeans", n_supervoxels=40)
gmm = SupervoxelizerRegistry.create("gmm", n_supervoxels=40)
# All three are Seedable (default seed 0). Current skimage SLIC has no
# RNG; set_random_state still records the seed for API uniformity.
slic.set_random_state(42)
km.set_random_state(42)
unit = slic(field)
slic→SlicSupervoxelizer(Seedable; backend currently deterministic)kmeans→KMeansSupervoxelizer(Seedable)gmm→GmmSupervoxelizer(Seedable)
Supervoxel feature extractors
Domain: supervoxel_feature_extractor
from habit.supervoxel import SupervoxelFeatureExtractorRegistry
mean_fx = SupervoxelFeatureExtractorRegistry.create("mean_voxel_features")
rad_fx = SupervoxelFeatureExtractorRegistry.create("supervoxel_radiomics")
mean_voxel_features→MeanVoxelFeaturessupervoxel_radiomics→SupervoxelRadiomicsFeaturesmean/std/percentile→ per-supervoxel statistics (compose withconcat)
Step inspection (optional)
To observe every habitat pipeline boundary in memory, pass
inspect=StepRecorder(...) to a recipe. See
Feature preprocessing (“Inspect every step”) and
Atomic operators.
from habit.inspection import StepRecorder
import habit.recipes as recipes
rec = StepRecorder(steps=["supervoxels.described"], max_subjects=2)
result = recipes.Study(spec=spec).fit_predict(cohort, inspect=rec)
result.inspection.summary()
Habitat model fitters
Domain: habitat_model_fitter (cohort-level)
from habit.habitat_model import HabitatModelFitterRegistry
fitter = HabitatModelFitterRegistry.create(
"kmeans",
n_habitats=4,
n_init=10,
)
fitter.set_random_state(42)
model = fitter.fit(units, cohort=cohort)
gmm_fitter = HabitatModelFitterRegistry.create("gmm", n_habitats=4)
kmeans→KMeansHabitatModelFittergmm→GmmHabitatModelFitter
Omit n_habitats (or pass None) to select the count over
min_habitats..max_habitats via the fitter’s validation score. There is
no string "auto" value — that was a documentation error.
Habitat assigners
Domain: habitat_assigner
from habit.habitat_model import HabitatAssignerRegistry
# nearest_centroid requires the fitted HabitatModel (not a bare create()).
assigner = HabitatAssignerRegistry.create("nearest_centroid", model=model)
# Preferred after fit — same object, no registry call needed:
assigner = model.assigner()
habitat_map = assigner(unit)
nearest_centroid→NearestCentroidAssigner(constructor arg:model)
Habitat feature extractors
Domain: habitat_feature_extractor
from habit.habitat_features import HabitatFeatureExtractorRegistry
msi = HabitatFeatureExtractorRegistry.create("msi")
ith = HabitatFeatureExtractorRegistry.create("ith_score")
vol = HabitatFeatureExtractorRegistry.create("volume")
# Built-in graph topology family (not a private plugin).
graph = HabitatFeatureExtractorRegistry.create(
"graph",
edge_method="min_distance",
node_method="uniform_grid",
block_size=8,
)
non_rad = HabitatFeatureExtractorRegistry.create("non_radiomics")
trad = HabitatFeatureExtractorRegistry.create("traditional")
whole = HabitatFeatureExtractorRegistry.create("whole_habitat")
each = HabitatFeatureExtractorRegistry.create("each_habitat")
table = msi(subject, habitat_map)
graph_table = graph(subject, habitat_map)
msi→MsiHabitatFeaturesith_score→IthHabitatFeaturesvolume→HabitatVolumeFeaturesgraph→GraphHabitatFeatures(built-in; see Graph topology features)non_radiomics→NonRadiomicsHabitatFeaturestraditional→TraditionalRadiomicsHabitatFeatureswhole_habitat→WholeHabitatRadiomicsFeatureseach_habitat→EachHabitatRadiomicsFeatures
Compare features between habitats
After each_habitat (or any wide habitat_{id}_{feature} table),
to_habitat_feature_panel() / compare_habitat_features()
contrast habitats on the cohort (paired Cliff’s delta, BH-FDR) or on
one subject. Figures: plot_habitat_feature_heatmap(),
plot_habitat_feature_effect(),
plot_habitat_feature_components(),
plot_habitat_feature_violin(),
plot_habitat_feature_bars(). See
Whole / Each Habitat Radiomics. Gallery:
Habitat feature contrast.
For array-only callers, use the public kernel helpers
extract_graph_features() /
HabitatGraphFeatureOptions (same numeric definitions). Prefer
this domain / kernel path; the habit.compat.graph_plugin shim was removed
in v2.0.0.
SubjectPipeline
from habit.pipeline import SubjectPipeline
pipe = SubjectPipeline(
voxel_feature_extractor=voxel,
supervoxelizer=svx, # or None for direct clustering
habitat_assigner=model.assigner(),
supervoxel_feature_extractor=None, # optional
)
habitat_map = pipe(subject)
table = pipe.extract_features(subject, [msi, ith, vol])
maps = cohort.map(pipe)
Prefer build_habitat_components() when starting
from a HabitatSpec: attribute names on
HabitatComponents match Spec / pipeline fields
(voxel_feature_extractor, supervoxel_feature_extractor,
habitat_model_fitter, habitat_features, and the singular
*_feature_preprocessor chains). See Domain protocols and registries.
Direct (no-supervoxel) designs use voxel_units:
from habit.pipeline import voxel_units
units = [voxel_units(voxel(s)) for s in cohort]
model = fitter.fit(units, cohort=cohort)
pipe = SubjectPipeline(voxel, None, model.assigner())
Hand-assembled two-step chain
fields = [voxel(s) for s in cohort]
units = [svx(f) for f in fields]
model = fitter.fit(units, cohort=cohort)
maps = [model.assigner()(u) for u in units]
Image preprocessing domain
Domain: preprocessor (image-space steps). Discover names the same way;
parameters live on each component constructor.
from habit.plugins import list_plugins
from habit.image_preprocessing import PreprocessorRegistry
for info in list_plugins("preprocessor"):
print(info.name, PreprocessorRegistry.constructor_signature(info.name))
Registered names: resample, reorientation, registration,
n4_correction, zscore_normalization, histogram_standardization,
adaptive_histogram_equalization, dcm2nii, custom_preprocessor.