SimpleITK is a simplified interface to the Insight Toolkit (ITK) for image registration and segmentation
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Complete guide to error handling, exceptions, and validation in SimpleITK.
Primary exception type for SimpleITK errors.
import SimpleITK as sitk
try:
image = sitk.ReadImage('nonexistent.nii')
except RuntimeError as e:
print(f"SimpleITK error: {e}")File I/O Errors
Type Errors
Dimension Errors
Parameter Errors
Transform Errors
import SimpleITK as sitk
import os
def safe_read_image(file_path, default=None):
"""Safely read image with error handling."""
# Check file exists
if not os.path.exists(file_path):
print(f"File not found: {file_path}")
return default
try:
image = sitk.ReadImage(file_path)
return image
except RuntimeError as e:
error_msg = str(e).lower()
if "could not create" in error_msg:
print(f"Unsupported format: {file_path}")
elif "could not open" in error_msg:
print(f"Cannot open file: {file_path}")
elif "could not read" in error_msg:
print(f"Corrupted file: {file_path}")
else:
print(f"Read error: {e}")
return default
def safe_write_image(image, file_path):
"""Safely write image with error handling."""
try:
# Create directory if needed
os.makedirs(os.path.dirname(file_path) or '.', exist_ok=True)
sitk.WriteImage(image, file_path)
return True
except RuntimeError as e:
print(f"Write error: {e}")
return Falsedef validate_pixel_type(image, expected_types):
"""Validate image pixel type."""
pixel_type = image.GetPixelIDValue()
if pixel_type not in expected_types:
type_name = image.GetPixelIDTypeAsString()
raise ValueError(
f"Invalid pixel type: {type_name}. "
f"Expected one of: {expected_types}"
)
return True
# Usage
try:
validate_pixel_type(image, [sitk.sitkFloat32, sitk.sitkFloat64])
# Proceed with processing
except ValueError as e:
print(e)
# Convert to appropriate type
image = sitk.Cast(image, sitk.sitkFloat32)def validate_dimension(image, expected_dim):
"""Validate image dimension."""
actual_dim = image.GetDimension()
if actual_dim != expected_dim:
raise ValueError(
f"Invalid dimension: {actual_dim}. Expected: {expected_dim}"
)
return True
def validate_compatible_geometry(image1, image2):
"""Validate images have compatible geometry."""
if not image1.IsCongruentImageGeometry(image2):
print("Images have incompatible geometry:")
print(f" Image1 - Size: {image1.GetSize()}, Spacing: {image1.GetSpacing()}")
print(f" Image2 - Size: {image2.GetSize()}, Spacing: {image2.GetSpacing()}")
return False
return Truedef validate_parameters(sigma=None, radius=None, iterations=None):
"""Validate common filter parameters."""
errors = []
if sigma is not None:
if isinstance(sigma, (list, tuple)):
if any(s < 0 for s in sigma):
errors.append("Sigma must be non-negative")
elif sigma < 0:
errors.append("Sigma must be non-negative")
if radius is not None:
if isinstance(radius, (list, tuple)):
if any(r < 0 for r in radius):
errors.append("Radius must be non-negative")
elif radius < 0:
errors.append("Radius must be non-negative")
if iterations is not None:
if iterations < 1:
errors.append("Iterations must be positive")
if errors:
raise ValueError("; ".join(errors))
return Truedef validate_image(image, min_size=None, max_size=None, allowed_types=None):
"""Comprehensive image validation."""
# Check not empty
if image.GetSize() == ():
raise ValueError("Image is empty")
# Check size constraints
if min_size:
if any(s < min_size for s in image.GetSize()):
raise ValueError(f"Image too small. Minimum size: {min_size}")
if max_size:
if any(s > max_size for s in image.GetSize()):
raise ValueError(f"Image too large. Maximum size: {max_size}")
# Check pixel type
if allowed_types:
if image.GetPixelIDValue() not in allowed_types:
raise ValueError(
f"Invalid pixel type: {image.GetPixelIDTypeAsString()}"
)
# Check for invalid values (if float type)
if image.GetPixelIDValue() in [sitk.sitkFloat32, sitk.sitkFloat64]:
stats = sitk.StatisticsImageFilter()
stats.Execute(image)
import numpy as np
if np.isnan(stats.GetMean()) or np.isinf(stats.GetMean()):
raise ValueError("Image contains NaN or Inf values")
return Truedef validate_transform(transform, expected_dimension=None):
"""Validate transform."""
# Check dimension
if expected_dimension:
if transform.GetDimension() != expected_dimension:
raise ValueError(
f"Transform dimension {transform.GetDimension()} "
f"does not match expected {expected_dimension}"
)
# Check invertibility if needed
try:
inverse = transform.GetInverse()
except RuntimeError:
print("WARNING: Transform is not invertible")
return Truedef robust_filter_application(image, filter_func, required_type=sitk.sitkFloat32):
"""Apply filter with automatic type conversion."""
original_type = image.GetPixelIDValue()
# Convert if needed
if original_type != required_type:
print(f"Converting from {image.GetPixelIDTypeAsString()} to Float32")
image = sitk.Cast(image, required_type)
# Apply filter
result = filter_func(image)
# Convert back if needed
if original_type != required_type:
result = sitk.Cast(result, original_type)
return resultdef robust_binary_operation(image1, image2, operation):
"""Binary operation with automatic geometry matching."""
# Check if compatible
if not image1.IsCongruentImageGeometry(image2):
print("Resampling image2 to match image1 geometry")
image2 = sitk.Resample(
image2,
image1, # Use image1 as reference
sitk.Transform(),
sitk.sitkLinear,
0.0,
image2.GetPixelID()
)
# Now can operate
return operation(image1, image2)
# Usage
result = robust_binary_operation(img1, img2, sitk.Add)def robust_segmentation(image, seeds, lower, upper):
"""Segmentation with fallback strategies."""
try:
# Try confidence connected
result = sitk.ConfidenceConnected(
image,
seedList=seeds,
numberOfIterations=5,
multiplier=2.5
)
# Check if result is non-empty
stats = sitk.StatisticsImageFilter()
stats.Execute(result)
if stats.GetSum() == 0:
raise ValueError("Segmentation produced empty result")
return result
except (RuntimeError, ValueError) as e:
print(f"Confidence connected failed: {e}")
print("Falling back to simple threshold")
# Fallback to threshold
return sitk.BinaryThreshold(
image,
lowerThreshold=lower,
upperThreshold=upper
)# Global debug
sitk.ProcessObject.SetGlobalDefaultDebug(True)
# Per-filter debug
filter = sitk.DiscreteGaussianImageFilter()
filter.DebugOn()
result = filter.Execute(image)import SimpleITK as sitk
import traceback
def verbose_error_handling():
"""Detailed error reporting."""
try:
image = sitk.ReadImage('input.nii')
result = sitk.SomeFilter(image)
except RuntimeError as e:
print("=" * 60)
print("SimpleITK ERROR")
print("=" * 60)
print(f"Error message: {e}")
print(f"\nFull traceback:")
traceback.print_exc()
print("=" * 60)def preflight_check(image, operation_name):
"""Run pre-flight checks before expensive operation."""
checks = []
# Check 1: Image not empty
if image.GetSize() == ():
checks.append("Image is empty")
# Check 2: Reasonable size
num_pixels = image.GetNumberOfPixels()
if num_pixels > 1e9: # 1 billion pixels
checks.append(f"Image very large ({num_pixels} pixels)")
# Check 3: Valid pixel type
pixel_type = image.GetPixelIDValue()
if pixel_type == sitk.sitkUnknown:
checks.append("Unknown pixel type")
# Check 4: Valid spacing
spacing = image.GetSpacing()
if any(s <= 0 for s in spacing):
checks.append(f"Invalid spacing: {spacing}")
if checks:
print(f"Pre-flight warnings for {operation_name}:")
for check in checks:
print(f" ⚠️ {check}")
response = input("Continue anyway? (y/n): ")
return response.lower() == 'y'
return TrueCause: Unsupported file format Solution: Check file extension, try specifying ImageIO explicitly
Cause: Mismatched geometry (size, spacing, origin, direction) Solution: Resample to common geometry
Cause: Incompatible pixel types in operation Solution: Cast to common type
Cause: Accessing pixel outside image Solution: Validate indices before access
Cause: Singular matrix or non-invertible transform type Solution: Check transform parameters, use different transform type
Install with Tessl CLI
npx tessl i tessl/pypi-simpleitk@2.5.1