Simulator#

class blochsim.Simulator[source]#

Bases: _SignalModel

Base class of a pulse sequence protocol and its signal model.

A subclass sets model, which says which tissue properties are exposed and how each kind of event is played, and implements layout(), which returns the events of one repetition from the protocol parameters. A closed-form signal implements evaluate() instead. simulate() returns the complex signal of the ADC events recorded, and jacobian() its derivative with respect to tissue properties.

Handlers#

A class attribute named after a kind of event binds the operator that plays it, both in layout() (as self.operators.<name>) and in a description or Pulseq file simulated with from_description() or from_pulseq():

  • excitation, refocusing, inversion, saturation, preparation, other: an RF event with that Pulseq RF use. A pulse with no use is played by excitation.

  • readout: an ADC event, with the gradients after it that its repetition plays (balanced, unbalanced or spoiled).

  • delay: a wait, with or without a gradient.

A handler is a callable returning an Operator: one of the built-in operators, or a function composing them with @. Handlers not named keep their defaults (Excitation for the last two RF uses).

The constructor fixes the keywords simulate() takes, as protocol parameters, tissue properties or run settings; a call overrides them. Subclasses document their own protocol parameters; the run settings below are common to all of them, and a subclass may change their class-level defaults.

param **protocol:

Protocol parameters (the arguments of layout()) and tissue properties to fix. Arrays may be NumPy, CuPy or torch; the signal is returned in the library they were given in.

type **protocol:

float or array-like

param states:

Configuration orders carried by the extended-phase-graph simulation. None sizes them from the dephasing in the sequence.

type states:

int, default=None

param repetitions:

Playings of the sequence; the last is recorded. None takes the class’s own (1 unless it declares otherwise); "auto" extrapolates the steady state from a few playings.

type repetitions:

int or “auto”, default=None

param record:

Which ADC events the signal holds: every one, those that acquire data, or those flagged as echoes.

type record:

{“all”, “acquired”, “echo”}, default=”all”

param execution:

"auto", "cpu" or CUDA device(s). "auto", which None stands for, runs a small problem where the tissue tensors are and cuts a larger one into chunks of voxels spread over every CUDA device; the signal comes back where the tissue tensors are. A call that carries a gradient runs where its tensors are unless a target is named.

type execution:

str, torch.device or sequence of device, default=None

param pulse:

RF waveform replacing the ideal hard pulse of definition 0, which the shipped operators play.

type pulse:

RfDefinition, default=None

param shims:

Transmit shims by shim_id. By default one channel drives every pulse alike.

type shims:

mapping, default=None

param across_slice:

Number of positions across the slice at which a shaped pulse is integrated, or an exact_slice_profile(). None uses the slice centre only.

type across_slice:

int or ExactSliceProfile, default=None

param resolve:

Reuse the packed event structure across calls that change only values. False rebuilds it every call.

type resolve:

bool, default=True

param crusher_dephasing_rad:

Dephasing of the unbalanced gradient across one voxel, in rad.

type crusher_dephasing_rad:

float, default=0.0

param voxel_size_m:

Voxel size along the unbalanced gradient, in m.

type voxel_size_m:

float, default=None

Tissue properties:
  • T1, T2 (float or array-like) – Longitudinal and transverse relaxation times, in ms.

  • M0 (float or array-like, default=1.0) – Equilibrium magnetization.

  • B1 (float or array-like, default=1.0) – Transmit field, as a fraction of the nominal flip angle.

  • B1phase (float or array-like, default=0.0) – Transmit phase, in rad.

  • B0 (float or array-like, default=0.0) – Off-resonance, in Hz.

  • T2prime (float or array-like, default=inf) – Reversible dephasing time, in ms.

  • inv_efficiency (float or array-like, default=1.0) – Fraction of a perfect inversion achieved by an inversion pulse.

  • D (float or array-like, default=0.0) – Apparent diffusion coefficient, in um^2/ms.

  • v (float or array-like, default=0.0) – Velocity along the unbalanced gradient, in m/s.

  • bound_fraction, bound_exchange, bound_T1 (float or array-like) – Semisolid pool for magnetization transfer: fraction, exchange rate in Hz and T1 in ms. A zero fraction leaves the pool out.

  • poolB_fraction, poolB_exchange, poolB_T1, poolB_T2, poolB_shift (float or array-like) – A second exchanging water pool: fraction, exchange rate in Hz, T1 and T2 in ms, chemical shift in Hz. Pools C to E take poolC_* to poolE_*.

protocol#

Protocol parameters fixed by the constructor, as torch tensors.

Type:

mapping

Methods

bind

Return a copy with further arguments fixed.

describe

Return the SequenceDescription of a protocol.

evaluate

Return the signal of one simulation of the protocol.

from_description

Return a simulator that plays an existing description.

from_pulseq

Return a simulator over one repetition of a Pulseq sequence.

jacobian

Return the signal and its derivative with respect to tissue properties.

layout

Return the operators of one repetition in playing order.

played

Return the protocol arguments of layout(), arrays as torch tensors.

repetition_s

Return the duration of one repetition in seconds.

simulate

Return the recorded signal.

bind()[source]#

Return a copy with further arguments fixed.

Parameters:

**values – Tissue properties, protocol arguments and run settings (those of the constructor, e.g. pulse and states), under the names simulate() takes. Fixed values replace earlier ones.

Returns:

The copy; self is unchanged.

Return type:

Simulator

property operators#

The EventOperators of model, read by layout().

property variables#

the protocol a call takes.

Type:

Names of the layout() parameters

to()[source]#

Return a copy with its protocol and fixed properties on device.

Parameters:

device (torch.device or str) – Target device.

Returns:

The copy; self is unchanged.

Return type:

Simulator

layout()[source]#

Return the operators of one repetition in playing order.

A bare operator starts where the previous one ended; an (offset_s, operator) pair starts offset_s seconds into the repetition. A subclass overrides this with the protocol parameters as keyword-only arguments, in ms and degrees, and documents them on the class.

Parameters:

**protocol – The arguments named by variables.

Returns:

Operators from operators.

Return type:

sequence of Operator or (float, Operator)

Raises:

NotImplementedError – If the subclass implements neither this nor describe().

repetition_s()[source]#

Return the duration of one repetition in seconds.

Defaults to played_s, the span the layout covers. Override when the repetition time exceeds it.

Parameters:
  • played_s (float or torch.Tensor) – Span covered by the layout, in seconds.

  • **protocol – The arguments of layout().

played()[source]#

Return the protocol arguments of layout(), arrays as torch tensors.

The constructor’s protocol overridden by sequence; run settings are dropped.

Parameters:

**sequence – Protocol arguments of this call.

property rf_raster_time_s#

RF raster time of the pulse shapes, in seconds.

describe()[source]#

Return the SequenceDescription of a protocol.

Parameters:

**protocol – Arguments of layout().

Returns:

The composed layout, or the stored description when the simulator was built by from_description() or from_pulseq().

Return type:

SequenceDescription

classmethod from_pulseq()[source]#

Return a simulator over one repetition of a Pulseq sequence.

The events are re-emitted through this class’s operators, as in from_description().

Parameters:
  • source (str, pathlib.Path or object) – A .seq file, or a pypulseq or pypulseqpp Sequence.

  • tr_index (int, default=None) – Repetition to read, counted from 0. Defaults to the TRRef definition, else the first repetition that acquires.

  • **settings – Run settings and tissue properties, as for the constructor.

Returns:

Simulator playing that repetition.

Return type:

Simulator

Raises:

ValueError – If the file declares no TRSize, tr_index is out of range, or the repetitions differ in their pulses and none was named.

classmethod from_description()[source]#

Return a simulator that plays an existing description.

The description carries RF pulses and ADC windows but no gradients, so its events are re-emitted through this class’s operators, which supply the dephasing (crushers, winding, spoiling). The class the method is called on therefore selects how the events are interpreted.

Parameters:
  • description (SequenceDescription) – Description decoded from an MRD stream or exported from a Pulseq design.

  • model (SpinPhysics, default=None) – Physics to read it with. Defaults to the class’s own.

  • **settings – Run settings and tissue properties, as for the constructor. repetitions defaults to the class’s own.

Returns:

Simulator playing the re-emitted description.

Return type:

Simulator

Raises:

ValueError – If called on Simulator itself, which names no handlers and so says nothing about how the stream is to be read.

evaluate()[source]#

Return the signal of one simulation of the protocol.

Parameters:
  • properties (mapping) – Tissue property values by public name, as torch tensors in public units (ms, degrees, Hz).

  • **sequence – Run settings (states, repetitions, record, device, execution, across_slice), each defaulting to the constructor’s, and protocol arguments overriding the constructor’s.

Returns:

Complex signal of the recorded ADC events, of shape (*voxel_shape, samples); with scalar properties there is no voxel axis.

Return type:

torch.Tensor