resampling_dataset
Batch resample all 3D volumes in a dataset folder to a uniform target size while preserving the field of view through automatic voxel spacing adjustment.
resampling_dataset(
nii_folder: str,
output_path: str,
desired_volume: tuple,
saving_mode: str = "case",
debug: bool = False
) -> None
Overview
This function processes all NIfTI volumes in a dataset folder by resampling them to a consistent target size. Unlike simple resizing, resampling automatically calculates new voxel spacing to maintain the original field of view, ensuring that anatomical dimensions are preserved in physical space.
The resampling process:
- Calculates new spacing: Adjusts voxel dimensions to match target size
- Applies B-spline interpolation: Smooth, high-quality resampling
- Preserves field of view: Maintains physical dimensions of anatomy
- Standardizes dimensions: Ensures all volumes have identical array sizes
This is essential for:
- Creating uniformly sized datasets for deep learning
- Standardizing input dimensions across different scanners
- Reducing computational requirements with smaller volumes
- Enabling batch processing with fixed-size inputs
- Preparing data for convolutional neural networks
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
nii_folder | str | required | Path to the directory containing input volumes in .nii.gz format. |
output_path | str | required | Root directory where resampled volumes will be saved. |
desired_volume | tuple | required | Target volume size as (X, Y, Z). Must contain exactly three integers. |
saving_mode | str | "case" | Organization mode: "case" (folder per volume) or "folder" (shared folder). |
debug | bool | False | If True, prints processing summary after completion. |
Returns
None – The function saves resampled volumes to disk.
Output Organization
Saving Modes
Case Mode (saving_mode="case")
Creates a separate folder for each volume:
output_path/
├── patient_001/
│ └── patient_001_resampled.nii.gz
├── patient_002/
│ └── patient_002_resampled.nii.gz
└── patient_003/
└── patient_003_resampled.nii.gz
Folder Mode (saving_mode="folder")
All resampled volumes in a single directory:
output_path/
├── patient_001_resampled.nii.gz
├── patient_002_resampled.nii.gz
└── patient_003_resampled.nii.gz
Filename Pattern
Each resampled volume is saved as:
<PREFIX>_resampled.nii.gz
Example: Input scan_042.nii.gz → Output scan_042_resampled.nii.gz
Resampling vs Resizing
Resampling (this function):
- Calculates new voxel spacing automatically
- Preserves physical dimensions (field of view)
- Maintains anatomical relationships
- Uses high-quality B-spline interpolation
Simple Resizing:
- Just changes array dimensions
- Distorts physical space if not careful
- May not preserve voxel spacing properly
Example:
Original: 512×512×300, spacing 0.5×0.5×1.0 mm → FOV: 256×256×300 mm
Resampled to 256×256×128 → spacing 1.0×1.0×2.34 mm → FOV: 256×256×300 mm (preserved!)
Target Volume Selection
Choose desired_volume based on your needs:
| Target Size | Use Case | Memory/Speed |
|---|---|---|
| (128, 128, 128) | Fast training, initial experiments | Low |
| (224, 224, 128) | Balanced quality and performance | Medium |
| (256, 256, 256) | High quality, detailed analysis | High |
| (512, 512, 256) | Maximum detail, clinical applications | Very High |
Considerations:
- Smaller volumes: Faster processing, less detail
- Larger volumes: More detail, higher computational cost
- Anisotropic sizes: Common for medical imaging (e.g., different Z resolution)
- Network requirements: Match input dimensions of your model
Exceptions
| Exception | Condition |
|---|---|
FileNotFoundError | The nii_folder does not exist or contains no .nii.gz files |
ValueError | desired_volume does not contain exactly 3 values |
ValueError | Invalid saving_mode parameter |
Usage Notes
- Input Format: Only
.nii.gzfiles are processed - 3D Volumes Required: Input must be 3D NIfTI images
- B-spline Interpolation: Provides smooth, high-quality results
- Field of View: Automatically preserved through spacing adjustment
- Sequential Processing: Volumes processed one at a time
- Progress Display: Shows progress bar during processing
- Output Directories: Automatically created if they don’t exist
Examples
Basic Usage
Resample dataset to standard size:
from nidataset.preprocessing import resampling_dataset
resampling_dataset(
nii_folder="dataset/original_scans/",
output_path="dataset/resampled/",
desired_volume=(224, 224, 128),
saving_mode="case"
)
# Creates: dataset/resampled/scan_001/scan_001_resampled.nii.gz, ...
Folder Mode Organization
All outputs in single directory:
resampling_dataset(
nii_folder="raw_data/",
output_path="preprocessed/uniform_size/",
desired_volume=(256, 256, 256),
saving_mode="folder",
debug=True
)
# Prints: Resampling completed for all files in 'raw_data/'
Small Size for Fast Training
Reduce volume size for rapid experimentation:
resampling_dataset(
nii_folder="training_data/full_res/",
output_path="training_data/low_res/",
desired_volume=(128, 128, 128),
saving_mode="case",
debug=True
)
# Smaller volumes for faster training iterations
High Resolution for Analysis
Maintain detail for clinical applications:
resampling_dataset(
nii_folder="clinical_scans/",
output_path="clinical_scans_processed/",
desired_volume=(512, 512, 256),
saving_mode="case",
debug=True
)
# High resolution preserved for diagnostic accuracy
Anisotropic Resampling
Different resolution in Z-axis (common in medical imaging):
resampling_dataset(
nii_folder="ct_scans/",
output_path="ct_resampled/",
desired_volume=(224, 224, 96), # Lower Z resolution
saving_mode="folder",
debug=True
)
# Matches typical slice thickness differences
Quality Control Verification
Resample and verify dimensions:
import nibabel as nib
from nidataset.preprocessing import resampling_dataset
target_size = (224, 224, 128)
# Resample dataset
resampling_dataset(
nii_folder="qa/originals/",
output_path="qa/resampled/",
desired_volume=target_size,
saving_mode="folder",
debug=True
)
# Verify results
for filename in os.listdir("qa/resampled/"):
if filename.endswith('_resampled.nii.gz'):
img = nib.load(f"qa/resampled/{filename}")
print(f"\n{filename}:")
print(f" Shape: {img.shape}")
print(f" Target: {target_size}")
print(f" Match: {img.shape == target_size}")
print(f" Voxel spacing: {img.header.get_zooms()[:3]}")
Comparing Before and After
Analyze resampling effects:
import nibabel as nib
import numpy as np
from nidataset.preprocessing import resampling_dataset
# Resample
resampling_dataset(
nii_folder="comparison/original/",
output_path="comparison/resampled/",
desired_volume=(256, 256, 128),
saving_mode="folder",
debug=True
)
# Compare a sample
original = nib.load("comparison/original/sample.nii.gz")
resampled = nib.load("comparison/resampled/sample_resampled.nii.gz")
orig_data = original.get_fdata()
resamp_data = resampled.get_fdata()
print("\nComparison:")
print(f" Original shape: {orig_data.shape}")
print(f" Original spacing: {original.header.get_zooms()[:3]}")
print(f" Original FOV: {np.array(orig_data.shape) * np.array(original.header.get_zooms()[:3])}")
print(f"\n Resampled shape: {resamp_data.shape}")
print(f" Resampled spacing: {resampled.header.get_zooms()[:3]}")
print(f" Resampled FOV: {np.array(resamp_data.shape) * np.array(resampled.header.get_zooms()[:3])}")
print(f"\n FOV preserved: Field of view should be approximately equal")
Multi-Resolution Processing
Create datasets at multiple resolutions:
from nidataset.preprocessing import resampling_dataset
resolutions = {
'low': (128, 128, 64),
'medium': (224, 224, 128),
'high': (256, 256, 256)
}
for res_name, target_size in resolutions.items():
print(f"\nCreating {res_name} resolution dataset...")
resampling_dataset(
nii_folder="source_data/",
output_path=f"multi_res/{res_name}/",
desired_volume=target_size,
saving_mode="folder",
debug=True
)
print("\nMulti-resolution datasets created")
Integration with Training Pipeline
Resample as preprocessing step:
from nidataset.preprocessing import resampling_dataset
from nidataset.slices import extract_slices_dataset
# Step 1: Resample to uniform size
print("Step 1: Resampling volumes...")
resampling_dataset(
nii_folder="training/raw_volumes/",
output_path="training/uniform_volumes/",
desired_volume=(224, 224, 128),
saving_mode="folder",
debug=True
)
# Step 2: Extract 2D slices from resampled volumes
print("\nStep 2: Extracting slices...")
extract_slices_dataset(
nii_folder="training/uniform_volumes/",
output_path="training/slices/",
view="axial",
saving_mode="case",
target_size=(224, 224),
save_stats=True
)
print("\nTraining data prepared")
Memory-Efficient Processing
Process large datasets by resolution reduction:
from nidataset.preprocessing import resampling_dataset
import nibabel as nib
# Calculate expected memory usage
def estimate_memory(shape, dtype='float32'):
bytes_per_voxel = np.dtype(dtype).itemsize
total_bytes = np.prod(shape) * bytes_per_voxel
return total_bytes / (1024**3) # GB
# Original sizes
print("Analyzing dataset...")
original_folder = "large_dataset/"
total_memory = 0
for filename in os.listdir(original_folder):
if filename.endswith('.nii.gz'):
img = nib.load(f"{original_folder}/{filename}")
memory = estimate_memory(img.shape)
total_memory += memory
print(f"Original dataset memory: {total_memory:.2f} GB")
# Resample to reduce size
target_size = (128, 128, 128)
reduced_memory = estimate_memory(target_size) * len(os.listdir(original_folder))
print(f"After resampling to {target_size}: {reduced_memory:.2f} GB")
print(f"Memory reduction: {(1 - reduced_memory/total_memory)*100:.1f}%")
# Perform resampling
resampling_dataset(
nii_folder=original_folder,
output_path="large_dataset_reduced/",
desired_volume=target_size,
saving_mode="folder",
debug=True
)
Batch Processing Different Datasets
Resample multiple datasets with different parameters:
from nidataset.preprocessing import resampling_dataset
datasets = {
'brain_mri': {'folder': 'data/brain/', 'size': (256, 256, 256)},
'chest_ct': {'folder': 'data/chest/', 'size': (224, 224, 128)},
'abdominal': {'folder': 'data/abdomen/', 'size': (224, 224, 128)}
}
for name, config in datasets.items():
print(f"\nProcessing {name}...")
resampling_dataset(
nii_folder=config['folder'],
output_path=f"resampled/{name}/",
desired_volume=config['size'],
saving_mode="case",
debug=True
)
print("\nAll datasets resampled")
Creating Test/Train Splits
Resample and organize for machine learning:
from nidataset.preprocessing import resampling_dataset
import shutil
import os
# Resample all data
resampling_dataset(
nii_folder="all_data/",
output_path="resampled_all/",
desired_volume=(224, 224, 128),
saving_mode="folder",
debug=True
)
# Split into train/val/test
splits = {
'train': ['scan_001', 'scan_002', 'scan_003'],
'val': ['scan_004'],
'test': ['scan_005']
}
for split_name, scan_ids in splits.items():
split_folder = f"dataset/{split_name}/"
os.makedirs(split_folder, exist_ok=True)
for scan_id in scan_ids:
src = f"resampled_all/{scan_id}_resampled.nii.gz"
dst = f"{split_folder}/{scan_id}_resampled.nii.gz"
if os.path.exists(src):
shutil.copy(src, dst)
print(f"{split_name}: {len(scan_ids)} scans")
Validating Resampling Quality
Check interpolation quality and artifacts:
import nibabel as nib
import numpy as np
from nidataset.preprocessing import resampling_dataset
# Resample
resampling_dataset(
nii_folder="validation/original/",
output_path="validation/resampled/",
desired_volume=(224, 224, 128),
saving_mode="folder",
debug=True
)
# Validate quality
original = nib.load("validation/original/sample.nii.gz")
resampled = nib.load("validation/resampled/sample_resampled.nii.gz")
orig_data = original.get_fdata()
resamp_data = resampled.get_fdata()
# Check for artifacts
print("\nQuality Validation:")
# 1. Intensity range preservation
print(f" Original range: [{orig_data.min():.1f}, {orig_data.max():.1f}]")
print(f" Resampled range: [{resamp_data.min():.1f}, {resamp_data.max():.1f}]")
# 2. Mean intensity (should be similar)
orig_mean = orig_data[orig_data > 0].mean()
resamp_mean = resamp_data[resamp_data > 0].mean()
print(f" Original mean: {orig_mean:.2f}")
print(f" Resampled mean: {resamp_mean:.2f}")
print(f" Difference: {abs(orig_mean - resamp_mean):.2f}")
# 3. Check for ringing artifacts (negative values in positive images)
if orig_data.min() >= 0 and resamp_data.min() < 0:
print(f" ⚠️ Warning: Negative values introduced (ringing artifact)")
else:
print(f" ✓ No negative values")
Typical Workflow
from nidataset.preprocessing import resampling_dataset
import nibabel as nib
# 1. Define input and output
source_folder = "dataset/variable_size_scans/"
output_folder = "dataset/uniform_size/"
target_dimensions = (224, 224, 128)
# 2. Resample all volumes to uniform size
resampling_dataset(
nii_folder=source_folder,
output_path=output_folder,
desired_volume=target_dimensions,
saving_mode="case",
debug=True
)
# 3. Verify a sample result
sample = nib.load(f"{output_folder}/sample/sample_resampled.nii.gz")
print(f"\nResampled volume shape: {sample.shape}")
print(f"Target shape: {target_dimensions}")
print(f"Match: {sample.shape == target_dimensions}")
# 4. Use resampled volumes for:
# - Training deep learning models with fixed input size
# - Batch processing without dimension mismatches
# - Consistent preprocessing across datasets
# - Efficient memory usage