Sequence#

Import: cmrseq.Sequence

class Sequence(building_blocks, system_specs, snap_to_raster=False, copy=False)[source]#

Bases: object

This class serves as a container for MRI-sequence building blocks.

All blocks contained in a sequence are kept as mutable objects of type SequenceBaseBlock or rather its subclasses. This means if a contained block is changed/transformed outside the sequence scope, these changes are also reflected in the sequence.

Below, the functionality provided by a cmrseq.Sequence object is explained according to the groups:

  • Instantiation and composition

  • Get contained blocks

  • Gridding, Moments and K-space

Instantiation and composition

To instantiate a Sequence you need a list containing building blocks and a sytem-specification definition. On instantiation, all blocks are validated against the system limits. If any block violates the limits, an exception is raised.

Adding blocks: Blocks or even entire sequences can be added to an existing sequence object one the obe hand by using the :code:’add_block’, :code:’append’, :code:’extend’ methods (see documentation). And on the other hand, the Sequence class implements the addition operator, which combines two sequence objects into either a new object containing copies of all blocks contained in the other two or by in-place addition where no copies are made:

new_sequence_object = sequence1 + sequence2   # Combination with copy
sequence1 += sequence2                        # inplace combination of seq2 into seq1

Unique names: a sequence objects keeps a mapping of automatically created unique names to the actual blocks. Whenever blocks are added

Get contained blocks

There are multiple ways to query single or even multiple blocks at once from the sequence object. To get a complete list of unique block-names use the property seq.blocks.

Access by name: 1. Indexing by unique name: seq["trapezoidal_0"] 2. Get all blocks by partial string match: seq.get_block(partial_string_match=...) 3. Get all blocks by matching regular expression on unique names:

seq.get_block(regular_expression=...)

  1. Get a sequence object containing copies of all blocks matched as in (2. & 3.)

    seq.partial_sequence(...)

Assuming temporal order of start 1. Indexing by integer: seq[0] 2. Indexing by slice: seq[0:5] 3. Indexing by tuple of integers: seq[(0, 2, 5)] 4. Iterating over sequence: [block for block in seq] 5. Iterating over sequence with block-names

{name: block for (name, block) in seq.items()}

Gridding, Moments and K-space

Gradients, RF and ADCs represented on a dense temporal grid defined by the system raster times can be obtained by calling the methods: gradients_to_grid, rf_to_grid, and adc_to_grid.

Gradient moments of specified order can be integrated using the function

seq.calculate_moment.

To get a representation of the kspace-trajectory as well as timing and position of sampling events defined by contained ADC blocks can be obtained by the seq.calculate_kspace

function.

Parameters:
  • building_blocks (List[SequenceBaseBlock]) – List of building Blocks

  • system_specs (SystemSpec) – Instance of SystemSpec

  • snap_to_raster (bool) –

  • copy (bool) –

Methods:

adc_to_grid([force_raster])

Grids the ADC-Events of all blocks contained in the sequence as boolean 1D mask along with the resulting time-grid.

add_block(block[, copy])

Add the instance of block to the internal List of sequence blocks.

append(other[, copy, end_time])

If both system specifications match, copies all blocks from other, shifts them by the current end time of this sequence intance (plus an additional delay according to ADC/RF - dead times and RF-ring-down time) and adds the blocks to itself.

calculate_kspace()

Evaluates the k-space trajectory of the sequence.

calculate_moment([moment, center_time, ...])

Calculates gradient moments about a given center point

combined_adc()

Combines all ADC-type blocks contained in the sequence, on a joint time grid.

combined_gradients()

Combines the gradient definitions of all blocks contained in the sequence, into a joint single definition.

combined_rf()

Combines the rf-definitions of all blocks contained in the sequence, into a joint single definition.

copy()

Returns deepcopy of the sequence object

extend(other[, copy])

If both system specifications match, copies all blocks from other shifts them by own tmax and adds the blocks to own collection

get_block([block_name, ...])

Returns reference to the block whose member name matches the specified argument.

gradients_to_grid([start_time])

Grids gradient definitions of all blocks contained in the sequence, on a joint time grid from the minimal to maximal value in single time-points definitions with a step-length defined in system_specs.grad_raster_time.

items()

Returns a generator yielding (unique_block_name, block) tuples

partial_sequence(copy_blocks[, ...])

Returns a cmrseq.Sequence object containing references or deep-copies of all blocks matched either with partial-string-match or regular expressions specified as keyword argument.

register_omatrix(matrix[, gradients, rf_pulses])

Updates the mapping of orientation matrix objects for given Gradient blocks and rf_pulses associated with a slice-selection gradients

remove_block(block_name)

Removes block from internal lookup

rename_blocks(old_names, new_names)

Renames blocks and updates block lookup map

rf_to_grid()

Grids RF-definitions of all blocks contained in the sequence, on a joint time grid from the minimal to maximal value in single time-points definitions with a step-length defined in system_specs.rf_raster_time.

shift_in_time(shift)

Shifts all blocks contained in the sequence object by the specified time

time_reverse()

Reverses the sequence in time

validate()

Calls the validation function of each block with self._system_specs

Attributes:

adc_centers

Returns the centers of all adc_blocks in the sequence.

blocks

Returns a tuple containing the names of all blocks contained in the sequence object, where temporal ordering is assumed

duration

Time difference of earliest start and latest end of all blocks contained in the sequence

end_time

gradients

Returns the gradient definitions (t, wf) of all Gradient-type blocks that are contained in the sequence.

rf

Returns the rf definitions (t, amplitude) of RFPulse-type blocks that are contained in the sequence.

rf_events

Returns the rf events (rf-center, flip-angle) of RFPulse-type blocks that are contained in the sequence.

start_time

adc_to_grid(force_raster=False)[source]#

Grids the ADC-Events of all blocks contained in the sequence as boolean 1D mask along with the resulting time-grid. Additionally, the start and end points of the all adc-blocks are returned. The definition of start/end differ for force_gradient_raster True/False

Boolean mask explanation:

  • force_raster == False

    events that are not defined on the grid, are inserted into the time-raster resulting in a non-uniform time definition. The boolean values of the newly inserted points are set to 1.

  • force_raster == True

    for events that are not defined on the grid the boolean values of the interval borders on gradient raster time are set to 1. For events that are already on the grid, the corresponding single index is set 1.

Start/End - definition:

  • force_raster == False:

    the exact time of first/last event per block is returned.

  • force_raster == True:

    The returned start/end times correspond to the beginning and end of the plateau of a trapezoidal gradient played out during the adc-events (addition of dwell-time).

Parameters:

force_raster (bool) – bool - defaults to True

Return type:

Tuple[ndarray, ndarray, ndarray, ndarray]

Returns:

Tuple(np.array, np.array, np.array) - (t, ) containing time-values - (t, ) containing values of 0 or 1, indicating where the adc is active - (t, ) containing the adc_phase in radians - (#adc_blocks, 2) where (:, 0) contains the indices of the start time of

the adc-block and (:, 1) the end time correspondingly.

add_block(block, copy=True)[source]#

Add the instance of block to the internal List of sequence blocks.

Note: The internal definition of blocks is mutable, therefore if the new block is not copied, subsequent alterations can have unwanted side-effects inside the sequence.

Raises:
  • ValueError – If block.validate() fails to validate using the system specs of self

  • TypeError – If block is an instance of class SequenceBaseBlock

Parameters:
  • block (SequenceBaseBlock) – Sequence block to be added to the sequence

  • copy (bool) – Determines if the block is copied before adding it to the sequence

Return type:

None

append(other, copy=True, end_time=None)[source]#

If both system specifications match, copies all blocks from other, shifts them by the current end time of this sequence intance (plus an additional delay according to ADC/RF - dead times and RF-ring-down time) and adds the blocks to itself.

Raises:

ValueError – If other fails to validate using the system specs of self

Parameters:
  • other (Union[Sequence, SequenceBaseBlock]) – Sequence or block to be added to the sequence

  • copy (bool) – if true copies the other sequence object

  • end_time (Optional[Quantity]) –

Return type:

None

calculate_kspace()[source]#

Evaluates the k-space trajectory of the sequence.

Note: All RF-pulses with a smaller flip-angle other than 180° are assumed to be excitation pulses. 180° - Refocusing pulses result in a complex conjugation of the trajectory. Consecutive excitation pulses are handled by starting from k-space center again.

Return type:

Tuple[ndarray, ndarray, ndarray]

Returns:

Tuple of arrays containing:

  • k-space trajectory on gradient rasters (-1, 3) in 1/m

  • k-space points at adc events (-1, 3) in 1/m

  • time at adc events (-1 ) in ms

calculate_moment(moment=0, center_time=<Quantity(0.0, 'millisecond')>, end_time=None, start_time=None)[source]#

Calculates gradient moments about a given center point

Parameters:
  • moment (int) – int of desired moment number

  • center_time (Quantity) – Quantity of center time to calculate moment about

  • end_time (Optional[Quantity]) – Time to calculate moment up to, default is end of sequence

  • start_time (Optional[Quantity]) – Time to calculate moment from, default is start of sequence

Return type:

Quantity

Returns:

Quantity [Mx, My, Mz]

combined_adc()[source]#

Combines all ADC-type blocks contained in the sequence, on a joint time grid.

Note: The binary event channel of the returned array is technically not needed but adheres to the signature

of dense gridding

Return type:

Tuple[ndarray, ndarray]

Returns:

  • Array of shape (t, ) containing the time-points

  • Array of shape (t, 2) containing binary event and phase

combined_gradients()[source]#

Combines the gradient definitions of all blocks contained in the sequence, into a joint single definition. The joint time-points are defined by the set of unique time-points of all combined blocks. If gradients occur at the same time on the same channel, they are added.

Return type:

Tuple[ndarray, ndarray]

Returns:

(np.ndarray, np.ndarray) of shape (t, ) containing the time-points and (3 [gx, gy, gz], t) containing the waveform definition in ms and mT/m returns (None, None) if no gradients are contained in the sequence

combined_rf()[source]#

Combines the rf-definitions of all blocks contained in the sequence, into a joint single definition. The joint time-points are defined by the set of unique time-points of all combined blocks. If rf occur at the same time they are added.

Return type:

Tuple[ndarray, ndarray]

Returns:

(np.ndarray, np.ndarray) of shape (t, ) containing the time-points and (t, ) containing the complex RF-waveform definition in ms and uT

copy()[source]#

Returns deepcopy of the sequence object

extend(other, copy=True)[source]#

If both system specifications match, copies all blocks from other shifts them by own tmax and adds the blocks to own collection

Raises:

ValueError – If other fails to validate using the system specs of self

Parameters:
  • other (Sequence[Union[Sequence, SequenceBaseBlock]]) – ListSequence or block to be added to the sequence

  • copy (bool) – if true copies the other sequence object

Return type:

None

get_block(block_name=None, partial_string_match=None, regular_expression=None, typedef=None, invert_pattern=False, sort_by=None)[source]#

Returns reference to the block whose member name matches the specified argument. If no block with given name is present in the sequence, it returns None

Note

Checks which keyword argument to use from left to right as specified in the signature. If multiple are specified uses only the first one.

Raises:

ValueError if no keyword-argument is specified

Parameters:
  • block_name (Union[str, Iterable[str], None]) – String or iterable of strings exactly matching a set of blocks contained in the sequence

  • partial_string_match (Union[str, Iterable[str], None]) – str or iterable of strings that specify partial string matches. All blocks partially matching at least one are returned.

  • regular_expression (Union[str, Iterable[str], None]) – str or iterable of strings containing regular expressions that are matched against the block-names. All blocks, matching at least one of the given expressions are returned.

  • typedef – type defintion (e.g. cmrseq.bausteine.ADC)

  • invert_pattern (bool) – if True, all blocks except of the pattern-matched names are returned

  • sort_by (Optional[str]) – from [None, start, end] returns the list of blocks sorted according to their start or end time, is ignored if blocks are retrieved by name

Return type:

Union[SequenceBaseBlock, List[SequenceBaseBlock]]

Returns:

SequenceBaseBlock or List of SequenceBaseBlocks depending on the specified argument

gradients_to_grid(start_time=None)[source]#

Grids gradient definitions of all blocks contained in the sequence, on a joint time grid from the minimal to maximal value in single time-points definitions with a step-length defined in system_specs.grad_raster_time. If gradients occur at the same time on the same channel, they are added.

Return type:

Tuple[ndarray, ndarray]

Returns:

(np.ndarray, np.ndarray) of shape (t, ) containing the time-grid and (3 [gx, gy, gz], t) containing the waveform definition in ms and mT/m returns (None, None) if no gradients are contained in the sequence

Parameters:

start_time (Quantity | None) –

items()[source]#

Returns a generator yielding (unique_block_name, block) tuples

partial_sequence(copy_blocks, partial_string_match=None, regular_expression=None, invert_pattern=False, **kwargs)[source]#

Returns a cmrseq.Sequence object containing references or deep-copies of all blocks matched either with partial-string-match or regular expressions specified as keyword

argument.

Parameters:
  • copy_blocks (bool) – if True, creates deep-copies of matched blocks.

  • partial_string_match (Union[str, Iterable[str], None]) – str or iterable of strings that specify partial string matches. All blocks partially matching at least one are returned.

  • regular_expression (Union[str, Iterable[str], None]) – str or iterable of strings containing regular expressions that are matched against the block-names. All blocks, matching at least one of the given expressions are returned.

  • invert_pattern (bool) – if True, all blocks except of the pattern-matched names are returned

Return type:

Sequence

Returns:

Sequence object

register_omatrix(matrix, gradients=None, rf_pulses=None)[source]#

Updates the mapping of orientation matrix objects for given Gradient blocks and rf_pulses associated with a slice-selection gradients

Parameters:
  • matrix (OMatrix) – cmrseq.OMatrix object

  • gradients (Optional[list[Union[str, Gradient]]]) – List of unique block names or instances of type Gradient to be registered with the given o-matrix

  • rf_pulses (Optional[list[tuple[Union[str, RFPulse], Union[str, TrapezoidalGradient]]]]) – List of tuples containing block-names or instances of (RF-pulse, TrapezoidalGradients), to be registered with the orientation matrix

remove_block(block_name)[source]#

Removes block from internal lookup

Parameters:

block_name (str) –

rename_blocks(old_names, new_names)[source]#

Renames blocks and updates block lookup map

Parameters:
  • old_names (List[str]) –

  • new_names (List[str]) –

rf_to_grid()[source]#

Grids RF-definitions of all blocks contained in the sequence, on a joint time grid from the minimal to maximal value in single time-points definitions with a step-length defined in system_specs.rf_raster_time.

If RF-pulses occur at the same time on the same channel, they are added.

Return type:

Tuple[ndarray, ndarray]

Returns:

(np.ndarray, np.ndarray) of shape (1, t) containing the time-grid and (1, t) containing the complex RF amplitude

shift_in_time(shift)[source]#

Shifts all blocks contained in the sequence object by the specified time

Parameters:

shift (Quantity) – Quantity of dimesion time

Return type:

None

time_reverse()[source]#

Reverses the sequence in time

Return type:

None

validate()[source]#

Calls the validation function of each block with self._system_specs

Raises:
  • ValueError – If any contained block fails to validate with own system specs

  • ValueError – If any combination of contained acquisition blocks have temporal overlap.

  • ValueError – If all combined gradient definitions exceed system limits (max amplitude and slew-rate)

Return type:

None

property adc_centers: List[Quantity]#

Returns the centers of all adc_blocks in the sequence.

property blocks: List[str]#

Returns a tuple containing the names of all blocks contained in the sequence object, where temporal ordering is assumed

property duration: Quantity#

Time difference of earliest start and latest end of all blocks contained in the sequence

property end_time#
property gradients: List[Tuple[Quantity, Quantity]]#

Returns the gradient definitions (t, wf) of all Gradient-type blocks that are contained in the sequence. If an OMatrix is registered the gradient channels are rotated accordingly by applying the OMatrix object

property rf: List[Tuple[Quantity, Quantity]]#

Returns the rf definitions (t, amplitude) of RFPulse-type blocks that are contained in the sequence. If an OMatrix is registered the frequency offset is adjusted accordingly by applying the OMatrix object

property rf_events: List[Tuple[Quantity, Quantity]]#

Returns the rf events (rf-center, flip-angle) of RFPulse-type blocks that are contained in the sequence.

property start_time#