Quick Start
This guide will get you up and running with Med-TDA in 5 minutes.
Installation
If you haven’t already, install Med-TDA:
pip install medtda
All dependencies (including SimpleITK for medical images) will be installed automatically.
Basic Usage: Single Image
Extract TDA features from a single medical image with a few lines of code:
from medtda import FeatureExtractor
# Initialize the feature extractor
extractor = FeatureExtractor(
normalize=True,
vectorization_method='PersStats'
)
# Extract features from image and mask
features = extractor.execute(
image='path/to/image.nii.gz',
mask='path/to/mask.nii.gz'
)
# features is a dictionary of TDA features
print(f"Extracted {len(features)} features")
print(list(features.keys())[:5]) # Show first 5 feature names
Expected Output:
Extracted 114 features
['PersStats_H0_mean', 'PersStats_H0_std',
'PersStats_H0_min', 'PersStats_H0_max',
'PersStats_H0_median']
Working with 2D Images
MedTDA also works with 2D images (PNG, JPG, TIFF):
from medtda import FeatureExtractor
import numpy as np
from PIL import Image
# Load 2D image
image = np.array(Image.open('image.png').convert('L'))
# Extract features
extractor = FeatureExtractor(
normalize=True,
vectorization_method='PersStats'
)
features = extractor.execute(image)
Without a Mask
You can extract features without a mask:
# Extract features from full image (no mask)
features = extractor.execute(image='image.nii.gz')
Using NumPy Arrays
Pass NumPy arrays directly instead of file paths:
import numpy as np
import SimpleITK as sitk
# Load image as NumPy array
image_sitk = sitk.ReadImage('image.nii.gz')
image_array = sitk.GetArrayFromImage(image_sitk)
# Extract features from array
features = extractor.execute(image=image_array)
Multiple Vectorization Methods
Extract features using multiple vectorization methods simultaneously:
extractor = FeatureExtractor(
normalize=True,
vectorization_method=[
'PersStats',
'BettiCurve',
'EntropySummary'
]
)
features = extractor.execute('image.nii.gz', 'mask.nii.gz')
print(f"Total features from all methods: {len(features)}")
This combines features from all specified methods into a single dictionary.
Preprocessing Options
Customize preprocessing with various options:
extractor = FeatureExtractor(
# Preprocessing
spacing=(1.0, 1.0, 1.0), # Resample to 1mm isotropic
window=(40, 400), # CT windowing (center, width)
normalize=True, # Normalize intensities
normalize_method='minmax', # Normalization method
crop_to_roi=True, # Crop to ROI for efficiency
roi_padding=2, # Padding around ROI
# Persistent Homology
filtration_type='sublevel', # Filtration type
construction='T', # Cubical complex construction
max_dimension=2, # Compute H0, H1, H2
# Vectorization
vectorization_method='PersStats'
)
features = extractor.execute('image.nii.gz', 'mask.nii.gz')
Getting Barcodes
Return persistence barcodes along with features:
extractor = FeatureExtractor(
normalize=True,
vectorization_method='PersStats',
return_barcodes=True # Return barcodes
)
# Now returns a tuple: (features, barcodes)
features, barcodes = extractor.execute('image.nii.gz', 'mask.nii.gz')
# barcodes is a dictionary: {'H0': array, 'H1': array, 'H2': array}
# where keys are homology dimension labels
print(f"H0 features: {barcodes['H0'].shape}") # (n_features, 2) birth-death pairs
print(f"H1 features: {barcodes['H1'].shape}")
Batch Processing (Python)
Process multiple images in a loop:
import pandas as pd
from medtda import FeatureExtractor
# List of images to process
cases = [
{'id': 'case001', 'image': 'scan1.nii.gz', 'mask': 'mask1.nii.gz'},
{'id': 'case002', 'image': 'scan2.nii.gz', 'mask': 'mask2.nii.gz'},
{'id': 'case003', 'image': 'scan3.nii.gz', 'mask': 'mask3.nii.gz'},
]
# Initialize extractor
extractor = FeatureExtractor(
normalize=True,
vectorization_method='PersStats'
)
# Extract features for all cases
results = []
for case in cases:
try:
features = extractor.execute(case['image'], case['mask'])
features['id'] = case['id']
results.append(features)
except Exception as e:
print(f"Error processing {case['id']}: {e}")
# Convert to DataFrame
df = pd.DataFrame(results)
print(df.head())
# Save to CSV
df.to_csv('tda_features.csv', index=False)
Command-Line Interface
MedTDA provides a powerful CLI for batch processing:
Single File
# Basic usage
medtda image.nii.gz --output-dir ./results
# With mask and preprocessing
medtda image.nii.gz --mask mask.nii.gz --output-dir ./results \
--normalize --spacing 1.0 1.0 1.0 \
--methods persistence_stats betti_curve
Batch Processing
Create a CSV file with your cases:
id,image_path,mask_path
case001,/data/scan1.nii.gz,/data/mask1.nii.gz
case002,/data/scan2.nii.gz,/data/mask2.nii.gz
case003,/data/scan3.nii.gz,/data/mask3.nii.gz
Process all cases:
# Sequential processing
medtda cases.csv --output-dir ./results --normalize --verbose
# Parallel processing with 4 workers
medtda cases.csv --output-dir ./results --workers 4 --verbose
# Use all CPU cores
medtda cases.csv --output-dir ./results --workers -1
Configuration Files
Use YAML configuration files for reproducibility:
# config.yaml
preprocessing:
normalize: true
normalize_method: minmax
spacing: [1.0, 1.0, 1.0]
crop_roi: true
persistent_homology:
filtration: sublevel
max_dimension: 2
vectorization:
methods:
- persistence_stats
- betti_curve
output:
output_dir: ./results
Then run:
medtda cases.csv --config config.yaml
Outputs
Single File Processing
When processing a single file, MedTDA creates:
image_name_features.csv- Feature vectors (one row)image_name_config.yaml- Configuration used (for reproducibility)image_name_barcodes.pkl- Persistence barcodes (if--save-barcodes)
Batch Processing
When processing multiple files, MedTDA creates:
batch_features.csv- All features combined (one row per case)config.yaml- Configuration usedcase_id_barcodes.pkl- Individual barcodes (if--save-barcodes)
Using Features in Machine Learning
The extracted features are ready for machine learning:
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# Load extracted features
features_df = pd.read_csv('batch_features.csv')
# Prepare data (assuming you have labels)
X = features_df.drop(['id', 'label'], axis=1)
y = features_df['label']
# Split data
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Train classifier
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)
# Evaluate
score = clf.score(X_test, y_test)
print(f"Accuracy: {score:.3f}")
Next Steps
Now that you know the basics:
Learn More: User Guide - Comprehensive guide to all features
CLI Reference: Command-Line Interface (CLI) - Complete command-line documentation
API Docs: API Reference - Detailed API reference
Theory: TDA Theory - Understanding TDA concepts
Examples: Examples - More practical examples
Common Next Questions
- How do I choose a vectorization method?
See Vectorization for guidance on selecting methods.
- What preprocessing should I use?
See Preprocessing for detailed preprocessing options.
- How does persistent homology work?
See Persistent Homology for TDA background.
- How can I visualize persistence diagrams?
See Basic Usage for visualization examples.
- My processing is slow, how can I speed it up?
See Frequently Asked Questions for performance optimization tips.