KSFoundation  [October2024]
A platform for structured EPIC programming on GE MR systems
KS_TRAP Struct Reference

#include <KSFoundation.h>

Data Fields

KS_BASE base
 
KS_DESCRIPTION description
 
float amp
 
float area
 
int ramptime
 
int plateautime
 
int duration
 
int gradnum [3]
 
float heat_scaled_amp [3]
 
float heat_scaling_factor [3]
 
float fs_factor
 
KS_SEQLOClocs
 
WF_PULSE ** wfpulse
 
KS_WFINSTANCEwfi
 
KS_RT_SCALE_LOG rtscaling
 

Detailed Description

Core sequence object for making trapezoids on X,Y,Z, and OMEGA boards

KS_TRAP.png
KS_TRAP


When making trapezoids on X, Y, or Z boards, the amplitude units are [G/cm], while units are arbitrary on OMEGA.

First note that for RF slice selection, phase encoding, or readouts there are other sequence objects and functions that in use their own KS_TRAPs internally.

Direct use of KS_TRAP objects applies only to cases where a standalone gradient with a certain area is desired, usually acting as a gradient spoiler. To add a trapezoid to a pulse sequence as e.g. a gradient spoiler, first declare a KS_TRAP sequence object in the @ipgexport section (see example below). In cveval(), the desired area of the trapezoid (unit: [(G/cm) us]) is then set by assigning a value to the .area field in the KS_TRAP object. This serves as input information, from which the duration, ramptime, and amplitude is calculated by calling ks_eval_trap(). The second argument to ks_eval_trap(..., "name", ...) is the description that is inserted into the .description field of the KS_TRAP. On TGT, this name is also used in when naming the WF_PULSEs internally, with a '.#' suffix added at the end, where '#' is the first letter of the board it is placed on. Hence, for a description called "myspoiler", it will appear in TimeHist in MGD Sim/WTools as myspoiler.xa (ramp-up), myspoiler.x (plateau), and myspoiler.xd if it is placed on board XGRAD.

The general function for setting up a KS_TRAP is ks_eval_trap(), where slewrate and gradient amplitude are constrained by the default system limits to allow for simultaneous use on all 3 axis at the same time. The slewrate and gradient amplitude limits can be slacked if one can be sure that the KS_TRAP will be used on one or two axes at a time, by instead calling ks_eval_trap1() or ks_eval_trap2(). The difference is seen for (double) oblique slices, where strong slice angulation and the use of ks_eval_trap1() can produce up to 3x stronger gradient than ks_eval_trap(). These ks_eval_trap***() functions are all calling the one and same ks_eval_trap_constrained() function, where slewrate and gradient amplitude limits as well as minimum plateautime are explicitly given as input arguments. This function can also be called directly. In summary, call:

  • ks_eval_trap() - for generic use
  • ks_eval_trap1() - if this trapezoid will be placed on one board at a time, with no other gradients running on other boards simultaneously. This will increase the maximum amplitude for double oblique scans by up to 3 times.
  • ks_eval_trap2() - if this trapezoid will be placed on at most two boards at a time with no other gradients running on other boards simultaneously
  • ks_eval_trap_constrained() - if manual control of slewrate, gradient max and minimum plateau time is desired

Once a KS_TRAP object has been designed using ks_eval_trap(), the same KS_TRAP object can be freely placed on XGRAD, YGRAD and ZGRAD as many times as desired, by only changing the second argument each time (to avoid waveform overlaps). The second argument is a KS_SEQLOC struct with three fields:

  • .board: Choose between XGRAD, YGRAD, ZGRAD (or OMEGA)
  • .pos: Absolute time in [us] of the start of the attack ramp of the trapezoid
  • .ampscale: A factor that must be in range [-1.0,1.0] that is multiplied with .amp to yield a per-instance (i.e. per-placement) amplitude ([G/cm]). The simplest is to use 1.0, which makes the KS_TRAP object to be placed out on the board as initially designed using ks_eval_trap().

NOTE: Regardless of the order placed out in the @pg section, and on which boards (XGRAD, YGRAD, ZGRAD) the KS_TRAP object is placed, the instance number of the KS_TRAP is automatically sorted in time. If two instances of one KS_TRAP occur at the same time (.pos) on different boards, XGRAD comes before YGRAD, which comes before ZGRAD. These abstract, sorted, instance numbers are used by `ks_scan_***() functions in scan() to refer to a specific instance of a KS_TRAP object in the sequence.

When a trapezoid is placed on OMEGA, neither the designed amplitude (.amp field in KS_TRAP) nor the .ampscale (in KS_SEQLOC) has an effect on the final frequency modulation. Instead the run-time amplitude of a KS_TRAP object on the OMEGA board is controlled in scan() via a function called ks_scan_omegatrap_hz().

Advanced tip: After calling ks_eval_trap(), the field .duration will correspond to the total duration of the trapezoid. If one manually sets this field to 0 (after ks_eval_trap()), ks_pg_trap() will detect the zero duration and ignore placing this out in the @pg section without an error. This can sometimes be a convienient way of conditionally or temporarily disable a trapezoid. Moreover, sequence dependent timing functions also see this trapezoid having zero duration, making timing calculations to correspond well to the ignored placement of the trapezoid in the @pg section.

In scan() on TGT, the amplitude of each instance of the KS_TRAP object can be individually scaled in run-time using ks_scan_trap_ampscale(). The third argument to this function is another amplitude scaling factor that must be in range [-1.0,1.0]. The final amplitude of the trapezoid in [G/cm] becomes the product of the following:

It is a requirement that there is a (sequence generating) function in the @pg section (containing the ks_pg_trap() call(s)) that can be run on both HOST and TGT. This function should be called exactly once in cveval() (after ks_eval_trap() and other ks_eval_***() functions). ks_pg_trap() will throw an error on TGT if this has not been done. See KS_SEQ_CONTROL for an example

The .gradnum[] array is modified by ks_pg_trap() when run on HOST, to keep count of how many times the KS_TRAP will be placed in the @pg section. This information is used in ks_eval_hwlimits() together with the sequence module's common KS_SEQ_CONTROL object to calculate gradient heating limits for the sequence module.

Example

@ipgexport (HOST)
@host (HOST)
cveval() {
mytrap.area = 1000.0; // [(G/cm)*us]
ks_eval_trap(&mytrap, "myspoiler");
}
@pg
tmploc.board = XGRAD;
tmploc.pos = 10ms;
tmploc.ampscale = 1.0;
ks_pg_trap(&mytrap, tmploc, &seqctrl); // first instance (#0) of this trap in the sequence
tmploc.pos += mytrap.duration;
tmploc.ampscale = -1.0;
ks_pg_trap(&mytrap, tmploc, &seqctrl); // a second instance (#1) of this trap right after the 0th, with negative amplitude
@rsp (TGT)
scan() {
ks_scan_trap_ampscale(&mytrap, 0, 0.68); // will make the amplitude 0.68 times the original amp for the 0-th instance of this KS_TRAP
}

Field Documentation

◆ base

KS_BASE base

Internal use

◆ description

KS_DESCRIPTION description

Descriptive string for the KS_TRAP object with maximum KS_DESCRIPTION_LENGTH characters

◆ amp

float amp

Gradient amplitude in [G/cm]

◆ area

float area

Gradient area in [(G/cm)*us]

◆ ramptime

int ramptime

Duration of each ramp of the trapezoid in [us]

◆ plateautime

int plateautime

Duration of the plateau of the trapezoid in [us]

◆ duration

int duration

Duration of the entire trapezoid (plateautime + 2*ramptime) in [us]

◆ gradnum

int gradnum[3]

Internal use for gradient heating calculations

◆ heat_scaled_amp

float heat_scaled_amp[3]

scaling factor for gradient heating calculations, by default set to {1,1,1} in KS_INIT_TRAP (one scaling factor per logical axis), useful for example in diffusion imaging where the RMS average amplitude could be used instead of the maximum amplitude to reduce the TR. Keep time constants of the hardware in mind. "heat_scaled_amp" is used to create a GRAD_PULSE in ks_eval_makegradpulse which is used in minseq –> minseqgrad

◆ heat_scaling_factor

float heat_scaling_factor[3]

internal use populated in ks_eval_makegradpulse with amp*heat_scaled_amp[i], ks_eval_makegradpulse then creates a GRAD_PULSE which is used in minseq –> minseqgrad for heating calulations

◆ fs_factor

float fs_factor

At 1 the full dynamic range in integer waveform memory is used, at fs_factor = (wave.max / boardmax) full dynamic range of iamp is used >

◆ locs

KS_SEQLOC* locs

◆ wfpulse

WF_PULSE** wfpulse

Internal use

◆ wfi

Internal use

◆ rtscaling

KS_RT_SCALE_LOG rtscaling

Internal use


The documentation for this struct was generated from the following file: