Skip to content

LucaNagel/bloch_sim_gui

Repository files navigation

Bloch Equation Simulator for Python

Live Demo

A high-performance Python implementation of the Bloch equation solver originally developed by Brian Hargreaves at Stanford University. This package provides a fast C-based core with Python bindings, parallel processing support, and an interactive GUI for MRI pulse sequence simulation.

Demo

Spin Echo Animation

Features

The Bloch Simulator can be accessed from 3 different directions:

Standalone GUI:

Download and install built package (.exe, .app) here. Features:

  • High performance GUI for nice visualization
  • Easily modify and live update simulation:
    • Sample Parameters: T1, T2, Polarization level (enables simulation of hyperpolarized magnetization), etc.
    • RF Pulses: Duration, Tip Angle, B1, Frequency, Phase, Pulse type such as sinc, Gaussian, Adiabatic Half Passage, etc.
    • Pulse Sequence: Blockpulse, Spin Echo, Slice Selection, SSFP, Inversion Recovery, etc.
  • Export:
    • Python compatible simulation results (.npy, .npz, .hdf5)
    • Automically generated IPython (.ipynb) notebooks for repeatility and modifications
    • Animations (.mp4, .gif) and figures (.svg, .png)

Python package blochsimulator

Install bloch simulator package from pypi.org via pip instal blochsimulator. Features:

  • Access simulation capabilites from IPython notebooks and python scripts
  • Highly customizable simulations

Online GUI

Access here online. Features:

  • No installation required
  • Simple UI, live simulation
  • Simulate RF Pulse Parameters and Slice Selection Parameters

Documentation

For detailed instructions on installation, GUI features, and Python API usage, please refer to the User Guide.

Installation

Method A: Direct Install (PyPI)

Recommended for most users. Package is availabe on pypi.org.

pip install blochsimulator

Method B: Python Package (From Source)

Recommended for researchers and developers.

To run from source, you need Python and a C Compiler installed.

👇 Click here for detailed setup instructions (Windows, macOS, Linux)

1. Install Python 3.9+

  • Windows:
    • Download the installer from python.org.
    • Important: During installation, check the box "Add Python to PATH".
  • macOS:
    • Download from python.org OR use Homebrew: brew install python.
  • Linux:
    • Usually pre-installed. If not: sudo apt install python3 python3-pip (Ubuntu/Debian) or sudo dnf install python3 (Fedora).

2. Install a C Compiler

Required to build the fast simulation core.

  • Windows:
    • Install Visual Studio Build Tools (free).
    • Download from visualstudio.microsoft.com.
    • In the installer, select "Desktop development with C++".
  • macOS:
    • Open Terminal and run: xcode-select --install.
    • (Optional but recommended for speed) Install OpenMP: brew install libomp.
  • Linux:
    • Install GCC: sudo apt install build-essential (Ubuntu/Debian) or sudo dnf groupinstall "Development Tools" (Fedora).

Steps:

  1. Navigate to the directory where you want to install the GUI in your terminal.
    cd /path/to/the/directory/
  2. Clone or download the repository.
    git clone git@github.com:LucaNagel/bloch_sim_gui.git
  3. Or if that fails:
    git clone https://github.com/LucaNagel/bloch_sim_gui.git
  4. Navigate to the cloned repository.
    cd bloch_sim_gui/
  5. Install in editable mode:
    pip install -e .

Verification (not necessary for the installation)

Test the installation:

from blochsimulator import BlochSimulator, TissueParameters

sim = BlochSimulator()
tissue = TissueParameters.gray_matter(3.0)
print(f"T1: {tissue.t1:.3f}s, T2: {tissue.t2:.3f}s")

Method C: Standalone App

No installation required. Recommended for non-technical users.

Download the most reason version for your OS in Releases

Activation (MacOS):

In case of the MacOS app, this requires you to manually remove the quarantine flag that macOS puts on the downloaded app. Only perform this step if you trust the distributor.

  1. Unzip the file and move BlochSimulator.app to your Applications folder.
  2. Launch BlochSimulator from your Applications folder and dimiss the warning.
  3. Go to System Settings > Privacy & Security, scroll down to the Security section, here you should see a message "BlochSimulator.app was blocked...". Click "Open Anyway".
  4. Launch BlochSimulator from your Applications folder.

Alternative Activation:

  1. Unzip the file and move BlochSimulator.app to your Applications folder.
  2. Crucial Step: Open Terminal and run this command to fix the "App is damaged" error:
    xattr -cr /Applications/BlochSimulator.app
  3. Launch BlochSimulator from your Applications folder.

Usage

🚀 Jupyter Notebook (Recommended)

You can launch the interactive GUI directly from a cell in your Jupyter Notebook.

# 0. Install from PyPI (run once) if not done before
!pip install blochsimulator

# 1. Launch GUI
!blochsimulator-gui

Note: This works if Jupyter is running on your local machine. It will not work on headless remote servers or Google Colab.

1. GUI Application

Once installed, you can launch the GUI from any terminal or shell:

blochsimulator-gui

Features:

  • Design RF pulses (rectangular, sinc, Gaussian)
  • Configure tissue parameters (T1, T2)
  • Select pulse sequences (spin echo, gradient echo, etc.)
  • Real-time 3D magnetization visualization
  • Signal analysis and frequency spectra

2. Python API

Basic Simulation

import numpy as np
from blochsimulator import BlochSimulator, TissueParameters

# Create simulator
sim = BlochSimulator(use_parallel=True, num_threads=4)

# Define tissue parameters
tissue = TissueParameters(
    name="Gray Matter",
    t1=1.33,  # seconds
    t2=0.083  # seconds
)

# Create a simple 90-degree pulse
ntime = 100
dt = 1e-5  # 10 microseconds
time = np.arange(ntime) * dt

b1 = np.zeros(ntime, dtype=complex)
b1[0] = 0.0235  # 90-degree hard pulse

gradients = np.zeros((ntime, 3))  # No gradients

# Run simulation
result = sim.simulate(
    sequence=(b1, gradients, time),
    tissue=tissue,
    mode=2  # Time-resolved output
)

# Plot results
sim.plot_magnetization()

Spin Echo Sequence

from blochsimulator import BlochSimulator, SpinEcho, TissueParameters

sim = BlochSimulator()

# Create spin echo sequence
sequence = SpinEcho(te=20e-3, tr=500e-3)  # 20ms TE, 500ms TR

# Simulate white matter
tissue = TissueParameters.white_matter(3.0)

# Run simulation with multiple frequencies (T2* effects)
frequencies = np.linspace(-50, 50, 11)  # Hz
result = sim.simulate(sequence, tissue, frequencies=frequencies)

# Access magnetization components
mx, my, mz = result['mx'], result['my'], result['mz']
signal = result['signal']

Custom Pulse Design

from blochsimulator import design_rf_pulse

# Design a sinc pulse
b1, time = design_rf_pulse(
    pulse_type='sinc',
    duration=2e-3,      # 2 ms
    flip_angle=180,     # degrees
    time_bw_product=4,  # Time-bandwidth product
    npoints=200
)

# Apply phase
phase = np.pi/4  # 45 degrees
b1_phased = b1 * np.exp(1j * phase)

Parallel Simulation

# Simulate multiple positions and frequencies in parallel
positions = np.random.randn(100, 3) * 0.01  # Random positions in 1cm cube
frequencies = np.linspace(-200, 200, 41)     # 41 frequencies

result = sim.simulate(
    sequence=sequence,
    tissue=tissue,
    positions=positions,
    frequencies=frequencies,
    mode=0  # Endpoint only (faster)
)

# Result shape: (100 positions, 41 frequencies)
print(f"Signal shape: {result['signal'].shape}")

3. Sequence Library

Pre-defined sequences are available:

from blochsimulator import SpinEcho, GradientEcho

# Spin Echo
se = SpinEcho(te=30e-3, tr=1.0)

# Gradient Echo
gre = GradientEcho(te=5e-3, tr=10e-3, flip_angle=30)

# Compile to waveforms
b1, gradients, time = se.compile(dt=1e-6)

4. Tissue Parameter Library

Common tissues at different field strengths:

from blochsimulator import TissueParameters

# 3T parameters
gm = TissueParameters.gray_matter(3.0)
wm = TissueParameters.white_matter(3.0)
csf = TissueParameters.csf(3.0)

# 7T parameters
gm_7t = TissueParameters.gray_matter(7.0)

# Custom tissue
liver = TissueParameters(
    name="Liver",
    t1=0.812,
    t2=0.042,
    t2_star=0.028,
    density=0.9
)

Desktop app build (PyInstaller)

For detailed packaging, release workflows, and CI/CD info, see the Developer Guide.

Note: Standalone applications for macOS, Windows, and Linux are automatically built and attached to GitHub Releases whenever a new version tag is pushed. The instructions below are for manual/local builds.

One build per OS is required (macOS build won’t run on Windows/Linux).

Prereqs

  • macOS: Xcode CLT; brew install libomp.
  • Windows: Python 3.8+ and MSVC Build Tools (for C extension).
  • Linux: gcc/g++; ensure libgomp available.

Quick build (any OS)

python -m pip install -r requirements.txt
python -m pip install pyinstaller
python setup.py build_ext --inplace
PYINSTALLER_CONFIG_DIR=.pyinstaller pyinstaller bloch_gui.spec --noconfirm

Artifact: dist/BlochSimulator (single binary; .exe on Windows).

One-liner helper

./scripts/build_pyinstaller.sh   # creates a venv, installs deps, builds, packages

Run the packaged app

  • macOS/Linux: ./dist/BlochSimulator
  • Windows: dist\\BlochSimulator.exe

Runtime data/exports

  • rfpulses/ is bundled automatically.
  • Exports default to per-user data dirs:
    • macOS: ~/Library/Application Support/BlochSimulator/exports
    • Windows: %APPDATA%\\BlochSimulator\\exports
    • Linux: ~/.local/share/BlochSimulator/exports
  • Override with BLOCH_APP_DIR or BLOCH_EXPORT_DIR if you need a custom location.

Theory

The simulator solves the Bloch equations:

$$ \frac{d\vec{M}}{dt} = \gamma (\vec{M} \times \vec{B}) - \begin{pmatrix} M_x / T_2 \ M_y / T_2 \ (M_z - M_0) / T_1 \end{pmatrix} $$

Using:

  • Rotation matrices for RF and gradient effects
  • Exponential decay for relaxation
  • Cayley-Klein parameters for efficient rotation calculation

Troubleshooting

Build Issues

  1. Missing compiler: Install gcc (Linux), Xcode (macOS), or Visual Studio (Windows)
  2. OpenMP not found: The code will still work but without parallelization
  3. Import error: Ensure the .so/.pyd file is in the same directory

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Submit a pull request

Citation

If you use this simulator in your research, please cite:

@software{blochsimulator_python,
  title={Python Bloch Equation Simulator GUI and API},
  author={Luca Nagel},
  year={2026},
  url={https://github.com/LucaNagel/bloch_sim_gui}
}

Acknowledgments

This project is based on code originally developed by Brian Hargreaves at Stanford University. Currently (01/2026) it is unfortunately not available. A python adaption of this code can be found here.

  • Original Bloch simulator by Brian Hargreaves, Stanford University
  • NumPy and SciPy communities
  • PyQt/PySide developers
  • OpenMP project
  • Built partially with codex, claude code and gemini cli

Contact

Luca Nagel

Appendix: File Structure

blochsimulator/
├── src/
│   └── blochsimulator/
│       ├── __init__.py
│       ├── simulator.py            # Core Python API
│       ├── gui.py                  # PyQt5 GUI
│       ├── bloch_core_modified.c   # C implementation
│       ├── bloch_core.h            # C header
│       ├── bloch_wrapper.pyx       # Cython wrapper
│       └── ...
├── tests/                          # Unit tests
├── docs/                           # Sphinx documentation
├── pyproject.toml                  # Modern build config
├── setup.py                        # C-extension build config
├── MANIFEST.in                     # Source dist manifest
└── README.md