MRIBuilder.jl internal API

Type diagram

AbstractBlock
├─ ContainerBlock
│  ├─ AbstractAlternativeBlocks
│  │  └─ AlternativeBlocks
│  ├─ BaseBuildingBlock
│  │  ├─ BuildingBlock
│  │  ├─ BaseTrapezoid
│  │  │  ├─ LineReadout
│  │  │  ├─ SliceSelect
│  │  │  └─ Trapezoid
│  │  │     ├─ Trapezoid1D
│  │  │     └─ Trapezoid3D
│  │  ├─ SpoiltSliceSelect
│  │  └─ Wait
│  └─ BaseSequence
│     ├─ EPIReadout
│     ├─ Repeat
│     ├─ Sequence
│     └─ SliceSelectRephase
├─ BaseComponent
│  ├─ EventComponent
│  │  ├─ InstantGradient
│  │  │  ├─ InstantGradient1D
│  │  │  └─ InstantGradient3D
│  │  ├─ RFPulseComponent
│  │  │  ├─ CompositePulse
│  │  │  ├─ ConstantPulse
│  │  │  ├─ GenericPulse
│  │  │  ├─ InstantPulse
│  │  │  └─ SincPulse
│  │  └─ ReadoutComponent
│  │     ├─ ADC
│  │     └─ SingleReadout
│  └─ GradientWaveform
│     ├─ ChangingGradient
│     │  ├─ ChangingGradient1D
│     │  └─ ChangingGradient3D
│     ├─ ConstantGradient
│     │  ├─ ConstantGradient1D
│     │  └─ ConstantGradient3D
│     └─ NoGradient
└─ Pathway

Sequence components

MRIBuilder.Components.AbstractTypes.edge_timesMethod
edge_times(container/component; tol=1e-6)

Returns all the edge times during a sequence in ms.

Edges are defined as any time, when:

  • the edge of a building block
  • the slope of the gradient profile changes suddenly
  • an RF pulse starts or ends

Edges that are within tol ms of each other are considered to be one edge (default: 1 ns).

source
MRIBuilder.Components.AbstractTypes.split_timestepMethod
split_timestep(component, precision)

Indicates the maximum timestep that a component can be linearised with and still achieve the required precision.

Typically, this will be determined by the maximum second derivative:

$\sqrt{\frac{2 \epsilon}{max(|d^2y/dx^2|)}}$

It should be infinite if the component is linear.

source
MRIBuilder.Components.GradientWaveformsModule

Module defining sub-types of the GradientWaveform.

There are only three types of [GradientBlock] objects:

  • ChangingGradient: any gradient changing linearly in strength.
  • ConstantGradient: any gradient staying constant in strength. These can overlap with a pulse (SliceSelectPulse).
  • NoGradient: any part of the gradient waveform when no gradient is active.

These parts are combined into a full gradient waveform in a BuildingBlock.

Each part of this gradient waveform can compute:

  • gradient_strength: maximum gradient strength in each dimension.
  • slew_rate: maximum slew rate in each dimension.
  • qval/qvec: area under curve
  • bmat_gradient: diffusion weighting (scalar in 1D or matrix in 3D).
source
MRIBuilder.Components.GradientWaveforms.ConstantGradientBlocks.ConstantGradientType
ConstantGradient(gradient_strength_vector, duration, group=nothing)
ConstantGradient(gradient_strength_scalar, orientation, duration, group=nothing)

Underlying type for any flat part in a 3D (first constructor) or 3D (second constructor) gradient waveform.

Usually, you do not want to create this object directly, use a BuildingBlock instead.

source
MRIBuilder.Components.GradientWaveforms.ChangingGradientBlocks.ChangingGradientType
ChangingGradient(grad1_scalar, slew_rate_scalar, orientation, duration, group=nothing)
ChangingGradient(grad1_vec, slew_rate_vec, duration, group=nothing)

Underlying type for any linearly changing part in a 1D (first constructor) or 3D (second constructor) gradient waveform.

Usually, you do not want to create this object directly, use a BuildingBlock instead.

source
MRIBuilder.Components.InstantGradients.InstantGradientType
InstantGradient(; orientation=nothing, group=nothing, variables...)

If the orientation is set an InstantGradient1D is returned, otherwise an InstantGradient3D.

Parameters

  • orientation sets the gradient orientation as a length-3 vector. If not set, the gradient can be in any direction.
  • group: name of the group to which this gradient belongs (used for scaling and rotating).

Variables

  • variables.qvec: Spatial frequency on which spins will be dephased due to this pulsed gradient in rad/um.
  • variables.spoiler: Length-scale on which spins will be dephased by exactly 2π in mm.
source
MRIBuilder.Components.Pulses.GenericPulses.GenericPulseType
GenericPulse(time, amplitude, phase, effective_time=<halfway>)
GenericPulse(time, amplitude; phase=0., frequency=0., effective_time=<halfway>)

Create a Pulse profile that has been fully defined by N control point.

All arguments should be arrays of the same length N defining these control points.

This pulse has no free variables.

  • time: time since the start of this BuildingBlock in ms.
  • amplitude: amplitude of the RF pulse at every timepoint in kHz.
  • phase: phase of the RF pulse at every timpoint in degrees. If not set explicitly it will be determined by the provided starting phase (degrees) and the frequency (kHz).
  • effective_time: the time that the RF pulse should be considered to have taken place when computing a Pathway (defaults: whenever half of the final flip angle has been achieved for on-resonance spins).
source
MRIBuilder.Components.Pulses.InstantPulses.InstantPulseType
InstantPulse(; flip_angle=nothing, phase=nothing, group=nothing)

Return an instant RF pulse that rotates all spins by flip_angle around an axis that has an angle of phase with the X-Y plane.

Parameters

  • group: name of the group to which this pulse belongs. This is used for scaling or adding phases/off-resonance frequencies.

Variables

source
MRIBuilder.Components.Pulses.ConstantPulses.ConstantPulseType
ConstantPulse(; variables...)

Represents an radio-frequency pulse with a constant amplitude and frequency (i.e., a rectangular function).

Parameters

  • group: name of the group to which this pulse belongs. This is used for scaling or adding phases/off-resonance frequencies.

Variables

source
MRIBuilder.Components.Pulses.SincPulses.SincPulseType
SincPulse(; Nzeros=3, apodise=true, variables...)

Represents a radio-frequency pulse with a sinc-like amplitude and constant frequency.

Parameters

  • Nzeros: Number of zero-crossings on each side of the sinc pulse. Can be set to a tuple with two values to have a different number of zero crossings on the left and the right of the sinc pulse.
  • apodise: if true (default) applies a Hanning apodising window to the sinc pulse.
  • group: name of the group to which this pulse belongs. This is used for scaling or adding phases/off-resonance frequencies.

Variables

source
MRIBuilder.Components.Pulses.CompositePulses.CompositePulseType
CompositePulse(; base_pulse, nweights, variables...)

A composite RF pulse formed by repeating a base RF pulse.

Parameters

  • base_pulse: The base RF pulse that will be repeated.
  • nweights: The number of repeated pulses. This will be ignored if a vector of weights is explicitly provided.

Variables

  • weights: The weight of each of the base RF pulses.
  • interpulse_delay: Time between the center of the RF pulses. If not otherwise constrained, it will be minimised.
  • scale_amplitude: How strongly one should scale the amplitude versus the duration to achieve the desired weights. If set to 1 only the RF pulse amplitude will be scaled. If set to 0 only the RF pulse duration will be scaled.
source
MRIBuilder.Components.Readouts.ADCs.ADCType
ADC(; center_halfway=true, oversample=1, variables...)

Adds a readout event.

Parameters

  • center_halfway: by default the time_to_center is assumed to be half of the duration. Set this to false to disable this assumption.
  • oversample: by how much the ADC should oversample (minimum of 1).

Variables

  • resolution: number of voxels in the readout direction. This can be a non-integer value during optimisation.
  • nsamples: number of samples in the readout. This can be a non-integer value during optimisation.
  • dwell_time: Time between each readout sample in ms.
  • duration: Total duration of the ADC event in ms.
  • time_to_center: time till the center of k-space from start of ADC in ms.
  • effective_time: same as time_to_center.
source

Containers for sequence components

MRIBuilder.Variables.get_gradientFunction
get_gradient(container, time)

Gets the gradient running at a particular time (in ms) during a sequence of building block.

This function will return a tuple with 2 elements:

  1. The GradientWaveform itself (which could be a NoGradient object).
  2. The time since the start of the gradient
source
MRIBuilder.Variables.get_pulseFunction
get_pulse(container, time)

Gets the pulse running at a particular time (in ms) during a sequence of building block.

If there is a RF pulse, this function will return a tuple with 2 elements:

  1. The RFPulseComponent itself
  2. The time since the start of the pulse

If there is no active RF pulse, nothing is returned.

source
MRIBuilder.Containers.BuildingBlocks.BaseBuildingBlockType

Basic BuildingBlock, which can consist of a gradient waveforms with any number of RF pulses/readouts overlaid

Main interface:

  • iteration will give the gradient waveforms interspersed by RF pulses/readouts.
    • Indiviual indices can be accessed using keys(building_block)
  • waveform_sequence returns just the gradient waveform as a sequence of GradientWaveform objects.
  • waveform returns just the gradient waveform as a sequence of (time, gradient_strength) tuples.
  • events returns the RF pulses and readouts.
  • variables.qvec returns area under curve for (part of) the gradient waveform.

Sub-types need to implement:

  • Base.keys: returns sequence of keys to all the components.
  • Base.getindex: returns the actual component for each key. For events (readout/pulses) this should return a tuple with (time delay till start, event).
source
MRIBuilder.Containers.BuildingBlocks.BuildingBlockType
BuildingBlock(waveform, events; duration=nothing, orientation=nothing, group)

Generic BaseBuildingBlock that can capture any overlapping gradients, RF pulses, and/or readouts. The gradients cannot contain any free variables.

Scanner constraints are automatically applied.

Arguments

  • waveform: Sequence of 2-element tuples with (time, (Gx, Gy, Gz)). If orientation is set then the tuple is expected to look like (time, G). This cannot contain any free variables.
  • events: Sequence of 2-element tuples with (time, pulse/readout). The time is the start time of the pulse/readout.
  • duration: duration of this BuildingBlock. If not set then it will be assumed to be the time of the last element in waveform.
  • orientation: orientation of the gradients in the waveform. If not set, then the full gradient vector should be given explicitly.
  • group: group of the gradient waveform
source
MRIBuilder.Containers.BuildingBlocks.waveform_sequenceMethod
waveform_sequence(building_block, first, last)

Gets the sequence of GradientWaveform from the event with key first till the event with key last.

Setting first to nothing indicates to start from the beginning of the building_block. Similarly, setting last to nothing indicates to continue till the end of the building_block.

source
MRIBuilder.Variables.variables.bmat_gradientFunction
bmat_gradient(overlapping, qstart[, first_event, last_event])

Computes the addition to the variables.bmat contributed by a specific building block or gradient.

qstart represents the variables.qvec at the start of this component.

If first_event is set to something else than nothing, only the gradient waveform after this RF pulse/Readout will be considered. Similarly, if last_event is set to something else than nothing, only the gradient waveform up to this RF pulse/Readout will be considered.

source
MRIBuilder.Variables.variables.qvecFunction
qvec(overlapping[, first_event, last_event])

Computes the area under the curve for the gradient waveform in BaseBuildingBlock.

If first_event is set to something else than nothing, only the gradient waveform after this RF pulse/Readout will be considered. Similarly, if last_event is set to something else than nothing, only the gradient waveform up to this RF pulse/Readout will be considered.

source
MRIBuilder.Containers.BaseSequences.BaseSequenceType

Super-type of any sequence of non-overlapping building blocks that should be played after each other.

It contains N ContainerBlock objects (e.g., building blocks or other sequences).

Main interface:

  • Acts as an iterable containing the blocks and sequences.
    • Indiviual blocks/sequences can be obtained using indexing.
    • If there is a finite number of repeats, the iteration will continue over all repeats.

Sub-types need to implement:

  • get_index_single_TR: return the index assuming it is between 1 and N
source
MRIBuilder.Containers.BaseSequences.SequenceType
Sequence(blocks; name=:Sequence, variables...)
Sequence(blocks...; name=:Sequence, variables...)

Defines an MRI sequence from a vector of building blocks.

Arguments

  • blocks: The actual building blocks that will be played in sequence. All the building blocks must be of type ContainerBlock, which means that they cannot only contain actual BaseBuildingBlock objects, but also other BaseSequence objects. Objects of a different type are converted into a ContainerBlock internally:
    • numbers/nothing/:min/:max : replaced with a Wait block with the appropriate constraint/objective added to its variables.duration.
    • RF pulse or readout: will be embedded within a BuildingBlock of the appropriate length

Specific named sequences might define additional variables.

source
MRIBuilder.Containers.Alternatives.AbstractAlternativeBlocksType

Parent type for all blocks that can take different MR sequence components between multiple repetitions of the sequence.

They can be extended into their individual components using adjust(<name>=:all).

Each subtype of AbstractAlternativeBlock needs to implement two methods:

source
MRIBuilder.Containers.Alternatives.AlternativeBlocksType
AlternativeBlocks(name, blocks)

Represents a part of the sequence where there are multiple possible alternatives.

Variables can be matched across these alternatives using match_blocks!.

The name is a symbol that is used to identify this AlternativeBlocks in the broader sequence (as in adjust).

source

Pre-defined sequence parts

There are helper functions available to actually add these to a sequence.

MRIBuilder.Parts.Trapezoids.LineReadoutType
LineReadout(adc; ramp_overlap=1., orientation=nothing, group=nothing, variables...)

Defines a trapezoidal gradient with an ADC readout overlaid.

Parameters and variables are identical as for Trapezoid with the addition of:

Parameters

  • adc: ADC object that describes the readout.
  • ramp_overlap: how much the gradient ramp should overlap with the ADC. 0 for no overlap, 1 for full overlap (default: 1). Can be set to nothing to become a free variable.

Variables

source
MRIBuilder.Parts.Trapezoids.SliceSelectType
SliceSelect(pulse; orientation=nothing, group=nothing, variables...)

Defines a trapezoidal gradient with a pulse played out during the flat time.

Parameters and variables are identical as for Trapezoid with the addition of:

Parameters

Variables

  • slice_thickness: thickness of the selected slice in mm
source
MRIBuilder.Parts.Trapezoids.TrapezoidType
Trapezoid(; orientation=nothing, group=nothing, variables...)

Defines a trapezoidal pulsed gradient

Parameters

  • orientation sets the gradient orientation (completely free by default). Can be set to a vector for a fixed orientation.
  • group: assign the trapezoidal gradient to a specific group. This group will be used to scale or rotate the gradients after optimisation.

Variables

Variables can be set during construction or afterwards as an attribute. If not set, they will be determined during the sequence optimisation.

Timing variables

  • variables.rise_time: Time of the gradient to reach from 0 to maximum in ms. If explicitly set to 0, the scanner slew rate will be ignored.
  • variables.flat_time: Time that the gradient stays at maximum strength in ms.
  • variables.δ: effective pulse duration (rise_time + flat_time) in ms.
  • variables.duration: total pulse duration (2 * rise_time + flat_time) in ms.

Gradient variables

  • variables.gradient_strength: Maximum gradient strength achieved during the pulse in kHz/um
  • variables.qvec: Spatial scale on which spins will be dephased due to this pulsed gradient in rad/um (given by δ * gradient_strength).

The bvalue can be constrained for multiple gradient pulses by creating a Pathway.

source
MRIBuilder.Variables.variables.ramp_overlapFunction
ramp_overlap(line_readout)

Return the fraction of the gradient ramp that overlaps with the ADC readout.

Set to 0 to ensure that the ADC is only active during the flat time of the readout.

source
MRIBuilder.Parts.SpoiltSliceSelects.SpoiltSliceSelectType
SpoiltSliceSelect(pulse; parameters..., variables...)

Adds slice selection to the pulse and surrounds it with spoiler gradients.

Parameters

  • orientation: vector with orientation of the slice selection and the spoilers (default: [0, 0, 1])
  • group: name of the group of the gradient. This will be used to scale and rotate the gradients after optimisation. Scaling is not recommended as this might ruin the spoiling.

Variables

  • duration: total duration of the block in ms.
  • slice_thickness: slice thickness in mm.
  • spoiler: length scale on which the spoilers achieve 2π dephasing in mm. This sets the minimum spoiling. If this spoiling level is not achieved by the slice-select gradient alone, then there will be additional gradients added.
source
MRIBuilder.Parts.EPIReadouts.EPIReadoutType
EPIReadout(; resolution, ky_lines=-resolution[2]:resolution[2], recenter=false, group=:FOV, variables...)

Defines an (accelerated) EPI readout.

Parameters

  • variables.resolution: Resolution of the final image in the frequency- and phase-encode directions.
  • recenter: if true, the signal will be recentred in k-space after the EPI readout.
  • group: name of the group used to rotate the readout gradients (default: :FOV).

Variables:

source

Sequence I/O

MRIBuilder.SequenceIO.PulseqIOModule

Stand-alone module that reads/writes Pulseq files.

The pulseq files are read into or written from a set of types that closely match the Pulseq file format. The translation of these types into MRIBuilder types is defined in "../pulseq.jl" (i.e., MRIBuilder.SequenceIO.Pulseq)

source
MRIBuilder.SequenceIO.PulseqIO.read_pulseqMethod
read_pulseq(IO)

Reads a sequence from a pulseq file (http://pulseq.github.io/). Pulseq files can be produced using matlab (http://pulseq.github.io/) or python (https://pypulseq.readthedocs.io/en/master/).

source
MRIBuilder.SequenceIO.PulseqIO.Types.PulseqBlockType
PulseqBlock(duration::Int, rf::PulseqRFPulse, gx::AnyPulseqGradient, gy::AnyPulseqGradient, gz::AnyPulseqGradient, adc::PulseqADC, ext)

Defines a Building Block with the Pulseq sequence (see specification).

The RF pulse, gradients, and ADC can be set to nothing.

The ext is a sequence of extension blocks that will be played out. Set this to a sequence of zero length to not have any extensions.

source
MRIBuilder.SequenceIO.PulseqIO.Components.add_components!Method
add_components(comp::PulseqComponents, search_vec::Vector, component)
add_components(comp::PulseqComponents, shape::PulseqShape)

Adds a component to the search_vec, which is assumed to be the appropriate vector within the comp.

It will check whether the component is already part of the search_vec before adding it. The integer ID of the position of the component in search_vec is returned.

0 is returned if component is nothing.

source

Plot

MRIBuilder.Plot.plot_sequenceFunction
plot_sequence(sequence; figure=(), axis=(), attributes...)
plot(sequence; attributes...)
plot!([scene,] sequence; attributes...)

Plot the sequence diagram.

Calling plot_sequence will result in a much cleaner sequence diagram (recommended). However, if you want to combine this diagram with other plots you will have to use plot or plot! instead.

If called as plot_sequence the user can also supply Makie.Figure (figure=(...)) and Makie.Axis (axis=(...)) keywords. If called using the plot or plot! interface, only the attributes listed below can be supplied

This function will only work if Makie is installed and imported.

Attributes

Line properties

  • linecolor sets the color of the lines. If you want to set the text color to the same value, you can also use color=....
  • linewidth=1.5 sets the width of the lines.
  • instant_width=3. sets the width of any instant gradients or pulses with respect to the linewidth.

Text properties

  • textcolor sets the color of the text. If you want to set the line color to the same value, you can also use color=....
  • font sets whether the rendered text is :regular, :bold, or :italic.
  • fontsize: set the size of each character.

Base.Docs.DocStr(svec("### Generic attributes\n\n- visible::Bool = true sets whether the plot will be rendered or not.\n- overdraw::Bool = false sets whether the plot will draw over other plots. This specifically means ignoring depth checks in GL backends.\n- transparency::Bool = false adjusts how the plot deals with transparency. In GLMakie transparency = true results in using Order Independent Transparency.\n- fxaa::Bool = true adjusts whether the plot is rendered with fxaa (anti-aliasing).\n- inspectable::Bool = true sets whether this plot should be seen by DataInspector.\n- depth_shift::Float32 = 0f0 adjusts the depth value of a plot after all other transformations, i.e. in clip space, where 0 <= depth <= 1. This only applies to GLMakie and WGLMakie and can be used to adjust render order (like a tunable overdraw).\n- model::Makie.Mat4f sets a model matrix for the plot. This replaces adjustments made with translate!, rotate! and scale!.\n- space::Symbol = :data sets the transformation space for box encompassing the volume plot. See Makie.spaces() for possible inputs.\n- clip_planes::Vector{Plane3f} = Plane3f[]: allows you to specify up to 8 planes behind which plot objects get clipped (i.e. become invisible). By default clip planes are inherited from the parent plot or scene.\n"), nothing, Dict{Symbol, Any}(:typesig => Tuple{Any}, :module => MakieCore, :linenumber => 4, :binding => MakieCore.genericplotattributes!, :path => "/root/.julia/packages/MakieCore/NeQjl/src/basic_plots.jl"))

source