A Python library for extracting comprehensive morphological features from cell segmentation masks in microscopy time-series data. Allowing for morphokinetic analysis of cell and organelle shape dynamics.
Cellmorph processes segmented cell image masks (TIFF stacks) to compute 260+ morphological features per cell, including:
- Static features: Area, perimeter, circularity, eccentricity, Hu moments, convex hull properties
- Dynamic features: Centroid velocity, orientation changes, MSD-based diffusive/directed velocity
- Boundary features: Multi-scale curvature, spectral analysis, wavelet decomposition
- Protrusion detection: Peak detection with Fourier contour reconstruction
- Shape descriptors: Elliptical Fourier descriptors, deformation metrics
The pipeline includes Bayesian cell tracking to maintain cell identity across frames, allowing for processing of multi-cell time-lapse datasets.
# Clone the repository
git clone https://github.com/L-kuehl/cellmorph.git
cd cellmorph
# Install with uv (recommended)
uv sync
# Or with pip
pip install -r requirements.txtpython run_extraction.py /path/to/experiment /path/to/outputpython run_extraction.py /path/to/experiment /path/to/output --debugThis limits processing to 10 frames and 3 cells for quick testing.
cellmorph expects the following directory structure:
experiment_dir/
├── condition1/
│ ├── sample1_Cell.tif
│ ├── sample1_Nucleus.tif
│ └── sample2_Cell.tif
├── condition2/
│ └── sample3_Cell.tif
- TIFF files: 2D or 3D (time-series) segmentation masks
- Naming convention:
{sample_name}_{SegmentationType}.tif - Segmentation types:
Cell,Nucleus,Tissue,Granule
For each sample, cellmorph generates:
| File | Description |
|---|---|
{date}_{sample}_{segtype}_feature_df.pkl |
Pandas DataFrame with all features (long format) |
processed_masks/{sample}_{segtype}.tif |
Tracked and filtered segmentation mask |
import pandas as pd
# Load feature DataFrame
df = pd.read_pickle("output/condition1/20241229_sample1_Cell_feature_df.pkl")
# Each row = one cell in one frame
print(df.columns) # 260+ feature columns
print(df.head())cellmorph supports flexible configuration via environment variables and .env files.
# Copy the example configuration
cp .env.example .env
# Edit with your settings
nano .envSettings are resolved in this order (highest to lowest priority):
- Command line arguments
- Environment variables
.envfile in current directory- Default values
| Variable | Default | Description |
|---|---|---|
| Paths | ||
CELLMORPH_EXPERIMENT_DIR |
- | Input directory with experiment data |
CELLMORPH_SAVE_DIR |
- | Output directory for features |
| Processing | ||
CELLMORPH_SCALE_FACTOR_UM_PX |
0.1032 |
Pixel size in µm/pixel |
CELLMORPH_MIN_CELL_SIZE |
100 |
Min cell area in µm² |
CELLMORPH_MIN_TRACK_LENGTH |
50 |
Min track length in frames |
CELLMORPH_N_HARMONICS |
8 |
Fourier harmonics |
CELLMORPH_PROTRUSION_WINDOW |
20 |
Smoothing window size |
CELLMORPH_PROTRUSION_POLYORDER |
2 |
Smoothing polynomial order |
CELLMORPH_PROTRUSION_MIN_SIZE |
20 |
Min protrusion size (px) |
CELLMORPH_SEGMENTATION_KEYS |
Cell,Nucleus,Tissue,Granule |
Valid segmentation types |
| Runtime | ||
CELLMORPH_N_WORKERS |
auto | Parallel workers (default: all cores) |
CELLMORPH_DEBUG |
false |
Enable debug mode |
CELLMORPH_LOG_LEVEL |
INFO |
Logging level |
# Paths
CELLMORPH_EXPERIMENT_DIR=/data/microscopy/experiment1
CELLMORPH_SAVE_DIR=/data/features/experiment1
# Adjust for your microscope
CELLMORPH_SCALE_FACTOR_UM_PX=0.1032
# Filter settings
CELLMORPH_MIN_CELL_SIZE=100
CELLMORPH_MIN_TRACK_LENGTH=50
# Use 8 cores
CELLMORPH_N_WORKERS=8from src.config import get_config, CellmorphConfig
from src.extract_features import Processor
# Load from .env file
config = get_config(env_file="production.env")
# Or create programmatically
config = CellmorphConfig.default()
config.processing.scale_factor_um_px = 0.2
config.processing.min_cell_size = 150
# Use with Processor
processor = Processor(
experiment_dir="/path/to/data",
save_dir="/path/to/output",
config=config,
)src/
├── extract_features.py # Main pipeline orchestrator
├── feature_classes.py # Data structures (CellFeatures, SampleFeatures)
├── static_features.py # Per-frame morphological features
├── dynamic_features.py # Time-series derived features
├── boundary_features.py # Curvature and boundary analysis
├── protrusion_features.py# Protrusion detection and tracking
├── tracking.py # Cell tracking (btrack wrapper)
├── elliptical_fourier.py # Fourier shape descriptors
├── curvature.py # Gradient-based curvature
└── utils.py # Utility functions
- btrack: Bayesian cell tracking
- spatial-efd: Elliptical Fourier descriptors
- trackpy: Particle/protrusion tracking
- scikit-image: Image processing
- scipy: Signal processing, optimization
- pywavelets: Wavelet analysis
Usage: cellmorph [OPTIONS] [EXPERIMENT_DIR] [SAVE_DIR]
Extract morphological features from microscopy segmentation data.
Arguments:
EXPERIMENT_DIR Path to directory containing experiment data (optional if set in .env)
SAVE_DIR Path to directory where features will be saved (optional if set in .env)
Options:
-d, --debug / --no-debug Enable debug mode (10 frames, 3 cells)
-c, --create-dirs Create save directory if needed (default: True)
-n, --n-workers INTEGER Number of parallel workers (default: all cores)
-e, --env-file PATH Path to .env configuration file
-l, --log-level [DEBUG|INFO|WARNING|ERROR]
Logging level
--help Show this message and exit
Examples:
# Using command line arguments
$ cellmorph /path/to/experiment /path/to/output --debug
# Using .env file only (paths configured in .env)
$ cellmorph --env-file config.env
# Mix: CLI args override .env file settings
$ cellmorph /data/exp1 /data/output --env-file production.env --debug
MIT License - see LICENSE for details.
If you use cellmorph in your research, please cite:
@software{cellmorph,
author = {Kühl, Lucas},
title = {cellmorph: Comprehensive Cell Morphology Feature Extraction},
year = {2025},
url = {https://github.com/L-kuehl/cellmorph}
}Complete list of all extracted features organized by category.
Basic shape measurements computed from the binary mask in each frame.
| Feature | Description |
|---|---|
area |
Cell area in pixels, computed from regionprops |
convex_area |
Area of the convex hull enclosing the cell |
equivalent_disk_radius |
Radius of a disk with equal area: sqrt(area / π) |
perimeter_length |
Total boundary perimeter length |
length |
Major axis length of the fitted ellipse |
width |
Minor axis length of the fitted ellipse |
Shape Indices
| Feature | Description |
|---|---|
circularity |
How circular the shape is: 4π × area / perimeter² (1.0 = perfect circle) |
eccentricity |
Ellipse eccentricity from regionprops (0 = circle, 1 = line) |
elongation |
Ratio of major to minor axis: major_axis / minor_axis |
solidity |
Proportion of convex hull filled: area / convex_area |
rectangularity |
How well cell fills bounding box: area / bbox_area |
roughness |
Boundary irregularity: 1 - area / convex_area |
compactness |
Perimeter efficiency: perimeter² / area |
aspect_ratio |
Inverse elongation: minor_axis / major_axis |
roundness |
Alternative circularity: 4 × area / (π × major_axis²) |
fractal_dimension |
Boundary complexity estimate: 2 × log(perimeter) / log(area) |
Centroid and Position
| Feature | Description |
|---|---|
centroid_x |
X-coordinate of the geometric centroid |
centroid_y |
Y-coordinate of the geometric centroid |
medoid_x |
X-coordinate of the medoid (point in shape closest to centroid) |
medoid_y |
Y-coordinate of the medoid |
orientation |
Angle of major axis from horizontal (radians) |
eigenshape_orientation |
Orientation computed via PCA on contour points |
polarity |
Distance from bounding disk center to medoid, normalized by equivalent radius |
Bounding Geometry
| Feature | Description |
|---|---|
bbox |
Axis-aligned bounding box coordinates (min_row, min_col, max_row, max_col) |
bbox_area |
Area of the axis-aligned bounding box |
bounding_disk_center |
Center coordinates of minimum enclosing circle |
bounding_disk_radius |
Radius of minimum enclosing circle |
bounding_disk_coverage |
Area coverage: area / (π × bounding_disk_radius²) |
area_radius_coverage |
Same as bounding_disk_coverage |
minimal_bbox_area |
Area of the minimum rotated bounding rectangle |
minimal_bounding_disk_coverage |
1 - convex_area / area |
Convex Hull Properties
| Feature | Description |
|---|---|
convex_vertices |
Indices of convex hull vertices |
convex_perimeter_length |
Perimeter of the convex hull |
convex_perimeter_ratio |
Ratio of actual perimeter to convex hull perimeter |
convex_coverage |
1 - convex_hull_volume / mask_area |
Feret Diameters (Caliper Measurements)
| Feature | Description |
|---|---|
caliper_length |
Maximum Feret diameter (largest caliper distance) |
caliper_width |
Minimum Feret diameter (smallest caliper distance) |
mean_caliper_diameter |
Average of max and min Feret diameters |
caliper_elongation |
Feret-based elongation: 1 - (min_feret / max_feret) |
Radial Distance Statistics
| Feature | Description |
|---|---|
mean_centroid_distance |
Mean distance from centroid to all boundary points |
max_centroid_distance |
Maximum centroid-to-boundary distance |
min_centroid_distance |
Minimum centroid-to-boundary distance |
centroid_boundary_distance_variance |
Variance of centroid-to-boundary distances |
radial_variance_normalized |
Coefficient of variation: variance / mean of radial distances |
radius_skewness |
Skewness of the radial distance distribution |
radius_kurtosis |
Kurtosis of the radial distance distribution |
Hu Moments
| Feature | Description |
|---|---|
hu_moments |
Array of 7 Hu moment invariants (rotation, scale, and translation invariant) |
Temporal features computed from changes between consecutive frames.
Velocity Features
| Feature | Description |
|---|---|
centroid_velocity |
Frame-to-frame centroid displacement: sqrt(dx² + dy²) |
bounding_disk_velocity |
Frame-to-frame displacement of the bounding disk center |
orientation_velocity |
Frame-to-frame change in orientation angle |
eigenshape_orientation_velocity |
Frame-to-frame change in eigenshape orientation |
Rate of Change Features
| Feature | Description |
|---|---|
elongation_rate |
Temporal derivative of elongation: d(elongation)/dt |
circularity_rate |
Temporal derivative of circularity: d(circularity)/dt |
roughness_rate |
Temporal derivative of roughness: d(roughness)/dt |
MSD-Based Velocity Features
Computed by fitting MSD = d×t + v²×t² to centroid trajectories in sliding windows.
| Feature | Description |
|---|---|
diffusive_velocity |
Random motion component: sqrt(d) from MSD fit |
directed_velocity |
Persistent motion component: sqrt(v²) from MSD fit |
Boundary Dynamics
| Feature | Description |
|---|---|
dynamic_amplitude |
Mean peak-valley amplitude of boundary fluctuations across 8 angular quadrants, computed using rolling windows |
Features describing the shape and complexity of the cell boundary.
Basic Boundary Properties
| Feature | Description |
|---|---|
frequency |
Mean absolute gradient of the polar-transformed boundary distance signal |
amplitude |
Mean peak-to-valley amplitude in the boundary distance signal |
dcdistance |
Mean distance from centroid to boundary points |
ncdistance |
Nucleus-to-cell boundary distances (requires nucleus segmentation) |
Multi-Scale Curvature
Curvature computed at different smoothing scales (5, 10, 20 interpolation points).
| Feature | Description |
|---|---|
curvature_mean_scale_5 |
Mean curvature at fine scale (5 points) |
curvature_std_scale_5 |
Standard deviation of curvature at fine scale |
curvature_max_scale_5 |
Maximum curvature at fine scale |
curvature_mean_scale_10 |
Mean curvature at medium scale (10 points) |
curvature_std_scale_10 |
Standard deviation of curvature at medium scale |
curvature_max_scale_10 |
Maximum curvature at medium scale |
curvature_mean_scale_20 |
Mean curvature at coarse scale (20 points) |
curvature_std_scale_20 |
Standard deviation of curvature at coarse scale |
curvature_max_scale_20 |
Maximum curvature at coarse scale |
Curvature Statistics
| Feature | Description |
|---|---|
curvature_skewness |
Skewness of the curvature distribution (asymmetry) |
curvature_kurtosis |
Kurtosis of the curvature distribution (tail weight) |
Spectral Curvature Analysis
FFT-based analysis of the curvature signal.
| Feature | Description |
|---|---|
dominant_frequencies |
Top 5 frequencies from FFT of curvature signal |
dominant_amplitudes |
Amplitudes corresponding to dominant frequencies |
spectral_entropy |
Entropy of the curvature power spectrum (flatness measure) |
spectral_centroid |
Weighted mean frequency of the spectrum |
spectral_spread |
Standard deviation of spectrum around the centroid |
Curvature Zero-Crossings
| Feature | Description |
|---|---|
zero_crossing_count |
Number of times curvature changes sign along the boundary |
zero_crossing_density |
Zero crossings normalized by boundary length |
positive_negative_ratio |
Ratio of positive to negative curvature points |
Curvature Persistence
Analysis of continuous positive/negative curvature segments.
| Feature | Description |
|---|---|
avg_protrusion_length |
Average length of positive curvature segments (protrusions) |
avg_indentation_length |
Average length of negative curvature segments (indentations) |
max_protrusion_length |
Maximum positive curvature segment length |
max_indentation_length |
Maximum negative curvature segment length |
protrusion_indentation_ratio |
Ratio of average protrusion to indentation length |
Local Curvature Extrema
| Feature | Description |
|---|---|
local_maxima_count |
Number of local curvature maxima (peaks) |
local_minima_count |
Number of local curvature minima (valleys) |
avg_maxima_prominence |
Average prominence of curvature maxima |
avg_minima_prominence |
Average prominence of curvature minima |
avg_extrema_distance |
Average distance between adjacent extrema |
Scale-Space Curvature
| Feature | Description |
|---|---|
scale_space_stability |
Mean correlation of curvature between adjacent smoothing scales |
multiscale_curvature_entropy |
Mean entropy of curvature across all scales |
Autocorrelation Features
| Feature | Description |
|---|---|
autocorrelation_first_zero |
First lag where curvature autocorrelation crosses zero |
autocorrelation_decay_rate |
Exponential decay rate of autocorrelation |
periodicity_strength |
Height of first autocorrelation peak (periodic pattern strength) |
periodicity_lag |
Lag of the first autocorrelation peak |
Shape Index Classification
Boundary regions classified by normalized curvature values.
| Feature | Description |
|---|---|
cup_percentage |
Percentage of boundary with strong negative curvature (< -0.5) |
cap_percentage |
Percentage of boundary with strong positive curvature (> 0.5) |
saddle_percentage |
Percentage of curvature sign transitions |
flat_percentage |
Percentage of boundary with near-zero curvature ( |
shape_complexity |
Entropy of shape category distribution |
Multifractal Analysis
Wavelet-based multifractal analysis of curvature.
| Feature | Description |
|---|---|
singularity_spectrum_width |
Width of the multifractal singularity spectrum |
singularity_spectrum_peak |
Peak position of the singularity spectrum |
multifractal_spectrum |
Full multifractal spectrum dictionary |
Boundary Tortuosity and Anisotropy
| Feature | Description |
|---|---|
boundary_tortuosity |
Wiggliness: actual_perimeter / convex_hull_perimeter |
boundary_anisotropy |
Normalized std of centroid-to-boundary distances |
boundary_direction_entropy |
Entropy of boundary direction changes |
Wavelet Boundary Features
Wavelet decomposition of the centroid-to-boundary distance signal.
| Feature | Description |
|---|---|
wavelet_energy_level_1 |
Relative energy at detail level 1 (finest scale) |
wavelet_energy_level_2 |
Relative energy at detail level 2 |
wavelet_energy_level_3 |
Relative energy at detail level 3 |
wavelet_energy_level_4 |
Relative energy at detail level 4 (coarsest scale) |
wavelet_energy_ratio_high_low |
Ratio of high-frequency to low-frequency energy |
Local Boundary Variation
Rolling window analysis of boundary point positions.
| Feature | Description |
|---|---|
boundary_local_variation_mean |
Mean local variation in boundary positions |
boundary_local_variation_std |
Standard deviation of local variation |
boundary_local_variation_max |
Maximum local variation |
boundary_local_variation_min |
Minimum local variation |
Centroid Asymmetry
Asymmetry of boundary distances in different quadrants.
| Feature | Description |
|---|---|
boundary_centroid_horizontal_asymmetry |
Left-right asymmetry of boundary distances |
boundary_centroid_vertical_asymmetry |
Top-bottom asymmetry of boundary distances |
boundary_centroid_overall_asymmetry |
Maximum of horizontal and vertical asymmetry |
Features describing cell protrusions detected via Fourier contour reconstruction.
Per-Frame Protrusion Detection
| Feature | Description |
|---|---|
protrusion_counts |
Number of detected protrusions in the frame |
protrusion_positions |
Angular positions of protrusions along the boundary |
protrusion_coords |
(x, y) coordinates of protrusion peaks |
protrusion_heights |
Signed heights of protrusions (distance from Fourier reconstruction) |
protrusion_absolute_heights |
Absolute heights of protrusions |
protrusion_prominences |
Peak prominences from scipy.signal.find_peaks |
protrusion_widths |
Widths of protrusions at half-prominence |
protrusion_areas |
Integrated area under each protrusion peak |
protrusion_width_heights |
Height at which width is measured |
protrusion_left_bases |
Left base positions of protrusions |
protrusion_right_bases |
Right base positions of protrusions |
protrusion_left_ips |
Left interpolated positions at half-prominence |
protrusion_right_ips |
Right interpolated positions at half-prominence |
Aggregated Protrusion Statistics (per frame)
| Feature | Description |
|---|---|
mean_protrusion_height |
Mean height of all protrusions in the frame |
mean_protrusion_absolute_height |
Mean absolute height of protrusions |
mean_protrusion_width |
Mean width of protrusions |
mean_protrusion_area |
Mean area of protrusions |
mean_protrusion_width_heights |
Mean width height of protrusions |
Tracked Protrusion Dynamics
Features from tracking individual protrusions over time using trackpy.
| Feature | Description |
|---|---|
protrusion_speeds |
Frame-to-frame speeds of tracked protrusions |
protrusion_displacements |
Frame-to-frame displacements of tracked protrusions |
protrusion_accelerations |
Frame-to-frame acceleration of tracked protrusions |
protrusion_angle_changes |
Frame-to-frame direction changes of tracked protrusions |
mean_protrusion_speed |
Mean speed of all tracked protrusions per frame |
mean_protrusion_displacement |
Mean displacement per frame |
mean_protrusion_acceleration |
Mean acceleration per frame |
mean_protrusion_angle_change |
Mean angle change per frame |
Elliptical Fourier descriptor features using spatial_efd.
| Feature | Description |
|---|---|
fourier_coeffs |
Array of elliptical Fourier coefficients (n_harmonics × 4) |
fourier_coords |
Reconstructed contour coordinates from Fourier coefficients |
fr_norm_coords |
Normalized contour coordinates |
fourier_rotation |
Rotation angle used for coefficient normalization |
fourier_centroid |
Centroid used for contour normalization |
harmonic |
Number of harmonics used in the reconstruction |
deformation |
Shape deformation metric: D = |c_{2,0}| / c_{0,0} (ratio of second harmonic to base shape) |