Pulseq Sequence Interpreter#
The pulseq sequence interpreter consists of two sub-components. The SequenceProvider reads all the events from a pulseq sequence and calculates RF and gradient waveform. The unrolled pulse sequence is provided as UnrolledSequence which contains the unrolled waveforms and some additional data.
See also
User guide on the sequence calculation.
Sequence Provider#
Sequence provider class.
- class console.pulseq_interpreter.sequence_provider.SequenceProvider(gradient_efficiency: list[float], gpa_gain: list[float], high_impedance: list[bool], output_limits: list[int] | None = None, spcm_dwell_time: float = 5e-08, rf_to_mvolt: float = 1, system: ~pypulseq.opts.Opts = <pypulseq.opts.Opts object>)[source]#
Bases:
Sequence
Sequence provider class.
This object is inherited from pulseq sequence object, so that all methods of the pypulseq
Sequence
object can be accessed.The main functionality of the
SequenceProvider
is to unroll a given pulseq sequence. Usually the first step is to read a sequence file. The unrolling step can be achieved using theunroll_sequence()
function.Example
>>> seq = SequenceProvider() >>> seq.read("./seq_file.seq") >>> sqnc, gate, total_samples = seq.unroll_sequence()
- add_adc_gate(block: SimpleNamespace, gate: ndarray, clk_ref: ndarray) None [source]#
Add ADC gate signal and reference signal during gate inplace to gate and reference arrays.
- Parameters:
block – ADC event of sequence block.
gate – Gate array, predefined by zeros. If ADC event is present, the corresponding range is set to one.
clk_ref – Phase reference array, predefined by zeros. Digital signal during ADC which encodes the signal phase.
- calculate_gradient(block: SimpleNamespace, unroll_arr: ndarray, fov_scaling: float) None [source]#
Calculate spectrum-card sample points of a pypulseq gradient block event.
- Parameters:
block – Gradient block from pypulseq sequence, type must be grad or trap
unroll_arr – Section of numpy array which will contain the unrolled gradient event
fov_scaling – Scaling factor to adjust the FoV. Factor is applied to the whole gradient waveform, excepton the amplitude offset.
- Return type:
Array with sample points of RF waveform as int16 values
- Raises:
ValueError – Invalid block type (must be either
grad
ortrap
), gradient amplitude exceeds channel maximum output levelIndexError – Unrolled gradient waveform does not fit in unrolled array shape
- calculate_rf(block: SimpleNamespace, unroll_arr: ndarray, b1_scaling: float, unblanking: ndarray, num_samples_rf_start: int = 0) None [source]#
Calculate RF sample points to be played by TX card.
- Parameters:
block – Pulseq RF block
unroll_arr – Section of numpy array which will contain unrolled RF event
b1_scaling – Experiment dependent scaling factor of the RF amplitude
unblanking – Unblanking signal which is updated in-place for the calculated RF event
num_samples_rf_start – Number of samples until the first RF event in the sequence. This value is important to calculate the correct carrier wave phase offset.
- Return type:
Array with sample points of RF waveform as int16 values
- Raises:
ValueError – Invalid RF block
- from_pypulseq(seq: Sequence) None [source]#
Cast a pypulseq
Sequence
instance to thisSequenceProvider
.If argument is a valid
Sequence
instance, all the attributes ofSequence
are set in thisSequenceProvider
(inherits fromSequence
).- Parameters:
seq – Pypulseq
Sequence
instance- Raises:
ValueError – seq is not a valid pypulseq
Sequence
instanceAttributeError – Key of Sequence instance not
- plot_unrolled(time_range: tuple[float, float] = (0, -1)) tuple[Figure, ndarray] [source]#
Plot unrolled waveforms for replay.
- Parameters:
time_range – Specify the time range of the plot in seconds. If the second value is smaller then the first or -1, the whole sequence is plotted.
(0 (default =) – Specify the time range of the plot in seconds. If the second value is smaller then the first or -1, the whole sequence is plotted.
-1) – Specify the time range of the plot in seconds. If the second value is smaller then the first or -1, the whole sequence is plotted.
- Return type:
Matplotlib figure and axis
- unroll_sequence() UnrolledSequence [source]#
Unroll the pypulseq sequence description.
TODO: Update this docstring
- Parameters:
larmor_freq – (Larmor) frequency of the carrier RF waveform
b1_scaling – Factor for the RF waveform, which is to be calibrated per coil and phantom (load), by default 1.0
optional – Factor for the RF waveform, which is to be calibrated per coil and phantom (load), by default 1.0
fov_scaling – Per channel factor for the gradient waveforms to scale the field of fiew (FOV), by default Dimensions(1.0, 1.0, 1.0)
optional – Per channel factor for the gradient waveforms to scale the field of fiew (FOV), by default Dimensions(1.0, 1.0, 1.0)
- Returns:
Instance of an unrolled sequence object which contains a list of numpy arrays with the block-wise calculated sample points in correct spectrum card order (Fortran).
The list of unrolled sequence arrays is returned as uint16 values which contain a digital signal encoded by 15th bit. Only the RF channel does not contain a digital signal. In addition, the adc and unblanking signals are returned as list of numpy arrays in the unrolled sequence instance.
- Return type:
- Raises:
ValueError – Larmor frequency too large
ValueError – No block events defined
ValueError – Sequence timing check failed
ValueError – Amplitude limits not provided
Examples
For channels ch0, ch1, ch2, ch3, data values n = 0, 1, …, N are ordered the following way.
>>> data = [ch0_0, ch1_0, ch2_0, ch3_0, ch0_1, ch1_1, ..., ch0_n, ..., ch3_N]
Per channel data can be extracted by the following code.
>>> rf = seq[0::4] >>> gx = (seq[1::4] << 1).astype(np.int16) >>> gy = (seq[2::4] << 1).astype(np.int16) >>> gz = (seq[3::4] << 1).astype(np.int16)
All the gradient channels contain a digital signal encoded by the 15th bit. - gx: ADC gate signal - gy: Reference signal for phase correction - gz: RF unblanking signal The following example shows, how to extract the digital signals
>>> adc_gate = seq[1::4].astype(np.uint16) >> 15 >>> reference = seq[2::4].astype(np.uint16) >> 15 >>> unblanking = seq[3::4].astype(np.uint16) >> 15
As the 15th bit is not encoding the sign (as usual for int16), the values are casted to uint16 before shifting.
Unrolled Sequence#
Interface class for an unrolled sequence.
- class console.interfaces.unrolled_sequence.UnrolledSequence(seq: list, adc_gate: list, rf_unblanking: list, sample_count: int, gpa_gain: list[float], gradient_efficiency: list[float], rf_to_mvolt: float, dwell_time: float, larmor_frequency: float, duration: float, adc_count: int)[source]#
Bases:
object
Unrolled sequence interface.
This interface is used to share the unrolled sequence between the different components like TxEngine, SequenceProvider and AcquisitionControl. An unrolled sequence is generated by a SequenceProvider() instance using the unroll_sequence function.
- adc_count: int#
Number of adc events in the sequence.
- adc_gate: list#
ADC gate signal in binary logic where 0 corresponds to ADC gate off and 1 to ADC gate on.
- duration: float#
Total duration of the unrolled sequence in s.
- dwell_time: float#
Dwell time of the spectrum card replay data (unrolled sequence). Defines the distance in time between to sample points. Note that this dwell time does not correlate to the larmor frequecy. Due to the sampling theorem dwell_time < 1/(2*larmor_frequency) must be satisfied. Usually a higher factor is chosen.
- gpa_gain: list[float]#
The gradient waveforms in pulseq are defined in Hz/m. The translation to mV is calculated by 1e3 / (gyro * gpa_gain * grad_efficiency). The gpa gain is given in V/A and accounts for the voltage required to generate an output of 1A. The gyromagnetic ratio defined by 42.58e6 MHz/T.
- gradient_efficiency: list[float]#
The gradient waveforms in pulseq are defined in Hz/m. The translation to mV is calculated by 1e3 / (gyro * gpa_gain * grad_efficiency). The gradient efficiency is given in mT/m/A and accounts for the gradient field which is generated per 1A. The gyromagnetic ratio defined by 42.58e6 MHz/T.
- larmor_frequency: float#
Larmor frequency of the MR scanner which defines the frequency of the RF pulse carrier signal.
- rf_to_mvolt: float#
If sequence values are given as float values, they can be interpreted as output voltage [mV] directly. This conversion factor represents the scaling from original pulseq RF values [Hz] to card output voltage.
- rf_unblanking: list#
Unblanking signal for the RF power amplifier (RFPA) in binary logic. 0 corresponds to blanking state and 1 to unblanking state.
- sample_count: int#
Total number of samples per channel.
- seq: list#
Replay data as int16 values in a list of numpy arrays. The sequence data already contains the digital adc and unblanking signals in the channels gx and gy.