Bloch Simulation#

Sub-package containing Bloch simulation routines.

Include MR simulation routines for common sequences based on Extended Phase Graphs [1, 2]. Currently provided models include MPRAGE, Multiecho MPRAGE (ME-MPRAGE), Fast Spin Echo (FSE) and T1-T2 Shuffling and balanced / unbalanced MR Fingerprinting.

References

[1] Weigel, M. (2015), Extended phase graphs: Dephasing, RF pulses, and echoes - pure and simple. J. Magn. Reson. Imaging, 41: 266-295. https://doi.org/10.1002/jmri.24619

[2] Malik, S.J., Teixeira, R.P.A.G. and Hajnal, J.V. (2018), Extended phase graph formalism for systems with magnetization transfer and exchange. Magn. Reson. Med., 80: 767-779. https://doi.org/10.1002/mrm.27040

Numerical Models#

deepmr.bloch.mprage

Simulate a Magnetization Prepared (MP) Rapid Gradient Echo sequence.

deepmr.bloch.memprage

Simulate a Multi-Echo Magnetization Prepared (MP) Rapid Gradient Echo sequence.

deepmr.bloch.bssfpmrf

Simulate an inversion-prepared bSSFP sequence with variable flip angles.

deepmr.bloch.ssfpmrf

Simulate an inversion-prepared SSFP sequence with variable flip angles.

deepmr.bloch.fse

Simulate a Fast Spin Echo sequence.

deepmr.bloch.t1t2shuffling

Simulate a T1T2Shuffling Spin Echo sequence.

Custom signal models#

DeepMR also contains helper classes to define custom signal models. The main class for analytical and numerical models are deepmr.bloch.AnalyticalSimulator and deepmr.bloch.EPGSimulator, respectively.

Users can define a custom signal model by subclassing it and overloading sequence method. Base class already handle spin parameters (e.g., T1, T2, …) as well as simulation properties (e.g., computational device, maximum number of batches…) so the user has only to care about specific sequence arguments (e.g., flip angle, TR, … for GRE or flip angle, ETL, for FSE). In order to work properly, sequence method must be a staticmethod and the arguments must follow this order:

  1. sequence parameters (flip angle, TE, TR, nrepetitions, …)

  2. spin parameters (T1, T2, B1, …)

  3. (mandatory) buffer for output signal (analytical) or EPG states and output signal (numerical): signal / states, signal

from deepmr import bloch
from deepmr.bloch import ops

class SSFP(bloch.EPGSimulator):

    @staticmethod
    def signal(flip, TR, T1, T2, states, signal):

        # get device and sequence length
        device = flip.device
        npulses = flip.shape[-1]

        # define operators
        T = ops.RFPulse(device, alpha=flip) # RF pulse
        E = ops.Relaxation(device, TR, T1, T2) # relaxation until TR
        S = ops.Shift() # gradient spoil

        # apply sequence
        for n in range(npulses):
            states = T(states)
            signal[n] = ops.observe(states)
            states = E(states)
            states = S(states)

            # return output
            return signal

The resulting class can be used to perform simulation by instantiating an object (spin properties as input)and using the __call__ method (sequence properties as input):

ssfp = SSFP(device=device, T1=T1, T2=T2) # build simulator
signal = ssfp(flip=flip, TR=TR) # run simulation

For convenience, simulator instantiation and actual simulation can (and should) be wrapped in a wrapper function:

def simulate_ssfp(flip, TR, T1, T2, device="cpu"):
    mysim = SSFP(device=device, T1=T1, T2=T2)
    return ssfp(flip=flip, TR=TR)

The class also enable automatic forward differentiation wrt to input spin parameters via diff argument:

import numpy as np

def simulate_ssfp(flip, TR, T1, T2, diff=None, device="cpu"):
	ssfp = SSFP(device=device, T1=T1, T2=T2, diff=diff)
	return ssfp(flip=flip, TR=TR)

# this will return signal only (evolution towards steady state of unbalanced SSFP sequence)
signal = simulate_ssfp(flip=10.0*np.ones(1000, dtype=np.float32), TR=4.5, T1=500.0, T2=50.0)

# this will also return derivatives
signal, dsignal = simulate_ssfp(flip=10.0*np.ones(1000, dtype=np.float32), TR=8.5, T1=500.0, T2=50.0, diff=("T1", "T2"))

# dsignal[0] = dsignal / dT1 (derivative of signal wrt T1)
# dsignal[1] = dsignal / dT2 (derivative of signal wrt T2)

This is useful e.g. for nonlinear fitting and for calculating objective functions (CRLB) for sequence optimization.

To facilitate the development of signal models, we include basic sequence building blocks (e.g., Inversion Preparation, SSFP Propagator) and low-level Extended Phase Graphs operators:

Sequence Blocks#

deepmr.bloch.InversionPrep

Adiabatic inversion operator.

deepmr.bloch.T2Prep

T2 prep operator.

deepmr.bloch.ExcPulse

RF operator.

deepmr.bloch.bSSFPStep

(Balanced) SSFP propagator.

deepmr.bloch.SSFPFidStep

(Unbalanced) SSFP propagator.

deepmr.bloch.SSFPEchoStep

(Reverse) SSFP propagator.

deepmr.bloch.FSEStep

(Unbalanced) SSFP propagator.

Low-level Operators#

deepmr.bloch.EPGstates

EPG states matrix.

deepmr.bloch.RFPulse

Operator representing a RF pulse.

deepmr.bloch.AdiabaticPulse

Operator representing an adiabatic RF pulse.

deepmr.bloch.Relaxation

The "decay operator" applying relaxation and "regrowth" of the magnetization components.

deepmr.bloch.Shift

Perform shift operator corrsesponding to a 2npi dephasing of the magnetization.

deepmr.bloch.Spoil

Non-physical spoiling operator that zeros all transverse states.

deepmr.bloch.DiffusionDamping

Simulate diffusion effects by state dependent damping of the coefficients.

deepmr.bloch.FlowDephasing

Simulate state dependent phase accrual of the EPG coefficients due to flow.

deepmr.bloch.FlowWash

Simulate EPG states replacement due to flow.

deepmr.bloch.observe

Store observable magnetization.

deepmr.bloch.susceptibility

Apply static susceptibility effects (bulk decay and dephasing).

deepmr.bloch.t1sat

Apply t1 saturation effect.