CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dipy

Comprehensive Python library for diffusion MRI analysis including tensor imaging, tractography, and visualization

Pending
Overview
Eval results
Files

simulations.mddocs/

Simulations and Phantoms

Signal simulation tools for generating synthetic diffusion MRI data, phantoms, and testing algorithms with known ground truth. DIPY provides comprehensive simulation capabilities for method validation and algorithm development.

Capabilities

Single Tensor Simulation

Generate diffusion signals from single tensor models with specified diffusion properties.

def single_tensor(gtab, S0=1, evals=None, evecs=None, snr=None):
    """
    Generate single tensor diffusion signal.
    
    Parameters:
        gtab (GradientTable): gradient table for simulation
        S0 (float): baseline signal intensity
        evals (array): tensor eigenvalues [lambda1, lambda2, lambda3]
        evecs (array): tensor eigenvectors (3x3 matrix)
        snr (float): signal-to-noise ratio (None for no noise)
        
    Returns:
        array: simulated diffusion signal
    """

def tensor(gtab, evals, evecs, S0=1, snr=None):
    """
    Simulate tensor signal with specified parameters.
    
    Parameters:
        gtab (GradientTable): diffusion gradient table
        evals (array): eigenvalues [AD, RD, RD] in mm²/s
        evecs (array): eigenvector matrix
        S0 (float): b=0 signal intensity
        snr (float): signal-to-noise ratio
        
    Returns:
        array: tensor-based signal
    """

def design_matrix(gtab):
    """
    Create design matrix for tensor fitting.
    
    Parameters:
        gtab (GradientTable): gradient table
        
    Returns:
        array: design matrix for linear fitting
    """

Multi-Tensor Simulation

Simulate complex tissue with multiple fiber populations and crossing configurations.

def multi_tensor(gtab, mevals, angles, fractions, S0=100, snr=None):
    """
    Multi-tensor signal simulation for crossing fibers.
    
    Parameters:
        gtab (GradientTable): gradient table
        mevals (list): eigenvalues for each tensor
        angles (list): fiber orientations [(theta1, phi1), (theta2, phi2), ...]
        fractions (list): volume fractions for each tensor (sum to 100)
        S0 (float): baseline signal
        snr (float): signal-to-noise ratio
        
    Returns:
        array: multi-tensor signal
    """

def two_tensor(gtab, evals1, evals2, angles, fractions, S0=100, snr=None):
    """
    Two-tensor crossing fiber simulation.
    
    Parameters:
        gtab (GradientTable): gradient information
        evals1 (array): first tensor eigenvalues
        evals2 (array): second tensor eigenvalues  
        angles (tuple): crossing angles (theta1, phi1, theta2, phi2)
        fractions (list): volume fractions [f1, f2]
        S0 (float): b=0 signal
        snr (float): noise level
        
    Returns:
        array: two-tensor signal
    """

def multi_tensor_odf(mevals, angles, fractions, sphere, tau=1/4*pi):
    """
    Generate multi-tensor ODF for visualization.
    
    Parameters:
        mevals (list): tensor eigenvalues
        angles (list): fiber angles
        fractions (list): volume fractions
        sphere (Sphere): sampling sphere
        tau (float): diffusion time parameter
        
    Returns:
        array: ODF values on sphere
    """

Sticks and Ball Model

Simplified model with stick-like fibers in isotropic background for fast simulation.

def sticks_and_ball(gtab, d=0.0015, S0=1, angles=[(0, 0)], fractions=[100], snr=None):
    """
    Sticks and ball model simulation.
    
    Parameters:
        gtab (GradientTable): gradient table
        d (float): stick diffusivity (mm²/s)
        S0 (float): baseline signal
        angles (list): stick orientations [(theta, phi), ...]
        fractions (list): volume fractions for each stick
        snr (float): signal-to-noise ratio
        
    Returns:
        tuple: (signal, sticks) simulated signal and stick parameters
    """

def ball_and_stick_signal(gtab, d=0.0015, f=0.5, S0=1, angles=[(0, 0)], snr=None):
    """
    Ball and stick model with isotropic and anisotropic components.
    
    Parameters:
        gtab (GradientTable): diffusion gradients
        d (float): stick diffusivity
        f (float): stick volume fraction (0-1)
        S0 (float): baseline signal
        angles (list): stick directions
        snr (float): noise level
        
    Returns:
        array: ball and stick signal
    """

Diffusion Kurtosis Simulation

Generate signals with non-Gaussian diffusion characteristics for DKI validation.

def kurtosis_signal(gtab, dt, kt, S0=1, snr=None):
    """
    Simulate diffusion kurtosis signal.
    
    Parameters:
        gtab (GradientTable): multi-shell gradient table
        dt (array): diffusion tensor (6-element vector)
        kt (array): kurtosis tensor (15-element vector)
        S0 (float): baseline signal
        snr (float): signal-to-noise ratio
        
    Returns:
        array: kurtosis-based signal
    """

def gaussian_signal(gtab, dt, S0=1, snr=None):
    """
    Generate Gaussian (tensor) signal for comparison.
    
    Parameters:
        gtab (GradientTable): gradient table
        dt (array): diffusion tensor
        S0 (float): b=0 signal
        snr (float): noise level
        
    Returns:
        array: Gaussian diffusion signal
    """

Phantom Generation

Create realistic phantom datasets with known ground truth for validation.

class SingleShellPhantom:
    """Single-shell diffusion phantom generator."""
    def __init__(self, gtab, snr=None):
        """
        Initialize phantom generator.
        
        Parameters:
            gtab (GradientTable): single-shell gradient table
            snr (float): signal-to-noise ratio
        """
    
    def create_voxel(self, tensor_params):
        """
        Create single voxel with specified parameters.
        
        Parameters:
            tensor_params (dict): tensor parameters
            
        Returns:
            array: simulated voxel signal
        """
    
    def create_volume(self, shape, tissue_map):
        """
        Create full volume phantom.
        
        Parameters:
            shape (tuple): volume dimensions
            tissue_map (array): tissue type labels
            
        Returns:
            array: 4D phantom volume
        """

class MultiShellPhantom:
    """Multi-shell phantom for advanced models."""
    def __init__(self, gtab, snr=None):
        """Initialize multi-shell phantom."""
    
    def add_crossing_region(self, center, radius, angles, fractions):
        """Add crossing fiber region to phantom."""
    
    def add_single_fiber_region(self, center, radius, tensor_params):
        """Add single fiber region."""
    
    def generate(self):
        """Generate complete phantom dataset."""

def spherical_phantom(gtab, sphere, angles, S0=100, snr=None):
    """
    Create spherical phantom with specified fiber orientations.
    
    Parameters:
        gtab (GradientTable): gradient table
        sphere (Sphere): sampling sphere
        angles (list): fiber directions
        S0 (float): baseline signal
        snr (float): noise level
        
    Returns:
        array: spherical phantom data
    """

Noise Models

Realistic noise models for diffusion MRI simulation including Rician and Gaussian noise.

def add_noise(signal, snr, S0=None, noise_type='rician'):
    """
    Add noise to simulated signal.
    
    Parameters:
        signal (array): clean signal
        snr (float): signal-to-noise ratio
        S0 (float): reference signal for SNR calculation
        noise_type (str): noise model ('rician', 'gaussian')
        
    Returns:
        array: noisy signal
    """

def rician_noise(signal, sigma):
    """
    Add Rician noise to magnitude signal.
    
    Parameters:
        signal (array): magnitude signal
        sigma (float): noise standard deviation
        
    Returns:
        array: Rician-distributed noisy signal
    """

def gaussian_noise(signal, sigma):
    """
    Add Gaussian noise to signal.
    
    Parameters:
        signal (array): input signal
        sigma (float): noise standard deviation
        
    Returns:
        array: Gaussian noisy signal
    """

def estimate_sigma(data, mask=None):
    """
    Estimate noise level from background regions.
    
    Parameters:
        data (array): diffusion data
        mask (array): brain mask
        
    Returns:
        float: estimated noise standard deviation
    """

Ground Truth Generation

Tools for creating datasets with known ground truth for algorithm validation.

class GroundTruthDataset:
    """Generate datasets with known ground truth."""
    def __init__(self, shape=(64, 64, 40), gtab=None):
        """
        Initialize ground truth generator.
        
        Parameters:
            shape (tuple): volume dimensions
            gtab (GradientTable): gradient table
        """
    
    def add_bundle(self, streamlines, tensor_params):
        """
        Add fiber bundle with known properties.
        
        Parameters:
            streamlines (list): bundle streamlines
            tensor_params (dict): diffusion parameters
        """
    
    def add_partial_volume(self, region_mask, tissue_fractions):
        """Add partial volume effects."""
    
    def generate_data(self, snr=30):
        """
        Generate complete dataset.
        
        Returns:
            tuple: (data, ground_truth_params)
        """

def create_qa_phantom(gtab, num_bundles=3, crossing_angle=60):
    """
    Create quality assurance phantom with crossing bundles.
    
    Parameters:
        gtab (GradientTable): gradient table
        num_bundles (int): number of fiber bundles
        crossing_angle (float): angle between crossing fibers
        
    Returns:
        tuple: (phantom_data, bundle_masks, tensor_params)
    """

Usage Examples

# Single tensor simulation
from dipy.sims.voxel import single_tensor, multi_tensor
from dipy.core.gradients import gradient_table
from dipy.core.sphere import get_sphere
import numpy as np

# Create gradient table
bvals = np.array([0, 1000, 1000, 2000, 2000])
bvecs = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0]])
bvecs = bvecs / np.linalg.norm(bvecs, axis=1, keepdims=True)
bvecs[0] = 0  # b=0 has no direction
gtab = gradient_table(bvals, bvecs)

# Simulate single tensor
evals = np.array([1.7e-3, 0.3e-3, 0.3e-3])  # AD, RD, RD
evecs = np.eye(3)  # aligned with x-axis
signal = single_tensor(gtab, S0=100, evals=evals, evecs=evecs, snr=30)

print(f"Simulated signal shape: {signal.shape}")
print(f"b=0 signal: {signal[0]:.1f}")
print(f"DW signal mean: {signal[1:].mean():.1f}")

# Multi-tensor crossing simulation
from dipy.sims.voxel import sticks_and_ball

# 90-degree crossing
angles = [(0, 0), (90, 0)]  # two perpendicular fibers
fractions = [50, 50]  # equal volume fractions
crossing_signal, sticks = sticks_and_ball(
    gtab, d=0.0015, S0=100, angles=angles, fractions=fractions, snr=25
)

# Create phantom volume
from dipy.sims.phantom import SingleShellPhantom

phantom = SingleShellPhantom(gtab, snr=30)

# Define tissue regions
shape = (32, 32, 20)
phantom_data = np.zeros(shape + (len(gtab.bvals),))

# Add single fiber region
center = (16, 16, 10)
for i in range(shape[0]):
    for j in range(shape[1]):
        for k in range(shape[2]):
            # Distance from center
            dist = np.sqrt((i-center[0])**2 + (j-center[1])**2 + (k-center[2])**2)
            if dist < 8:  # Within sphere
                if dist < 4:  # Inner core - single fiber
                    signal = single_tensor(gtab, S0=100, evals=evals, evecs=evecs, snr=30)
                else:  # Outer shell - partial volume
                    mixed_signal = 0.7 * single_tensor(gtab, S0=100, evals=evals, evecs=evecs) + \
                                  0.3 * single_tensor(gtab, S0=100, evals=[0.7e-3]*3, evecs=evecs)
                    mixed_signal = add_noise(mixed_signal, snr=30)
                phantom_data[i, j, k] = signal if dist < 4 else mixed_signal

print(f"Phantom shape: {phantom_data.shape}")

# Validation with known ground truth
from dipy.reconst.dti import TensorModel

# Fit tensor model to simulated data
tensor_model = TensorModel(gtab)
tensor_fit = tensor_model.fit(phantom_data)

# Compare with ground truth
estimated_fa = tensor_fit.fa
ground_truth_fa = 0.8  # Expected FA for our simulation

print(f"Ground truth FA: {ground_truth_fa:.3f}")
print(f"Estimated FA (center): {estimated_fa[16, 16, 10]:.3f}")
print(f"Estimation error: {abs(estimated_fa[16, 16, 10] - ground_truth_fa):.3f}")

# Noise analysis
from dipy.sims.voxel import add_noise, estimate_sigma

# Test different noise levels
snr_levels = [10, 20, 30, 50, 100]
clean_signal = single_tensor(gtab, S0=100, evals=evals, evecs=evecs)

for snr in snr_levels:
    noisy_signal = add_noise(clean_signal, snr, noise_type='rician')
    sigma_estimated = estimate_sigma(noisy_signal.reshape(1, 1, 1, -1))
    sigma_true = 100 / snr  # True noise level
    print(f"SNR {snr}: True σ={sigma_true:.2f}, Estimated σ={sigma_estimated:.2f}")

Install with Tessl CLI

npx tessl i tessl/pypi-dipy

docs

core-utilities.md

data-access.md

image-processing.md

index.md

neural-networks.md

registration.md

segmentation.md

signal-reconstruction.md

simulations.md

statistics.md

tractography.md

visualization.md

workflows.md

tile.json