#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_SEQLOC * | locs |
WF_PULSE ** | wfpulse |
KS_WFINSTANCE * | wfi |
KS_RT_SCALE_LOG | rtscaling |
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:
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:
.amp
field of KS_TRAP (set by ks_eval_trap() in cveval()
).ampscale
field of KS_SEQLOC (2nd arg to ks_pg_trap() in the @pg
section that alters each instance)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.
KS_BASE base |
Internal use
KS_DESCRIPTION description |
Descriptive string for the KS_TRAP object with maximum KS_DESCRIPTION_LENGTH characters
float amp |
Gradient amplitude in [G/cm]
float area |
Gradient area in [(G/cm)*us]
int ramptime |
Duration of each ramp of the trapezoid in [us]
int plateautime |
Duration of the plateau of the trapezoid in [us]
int duration |
Duration of the entire trapezoid (plateautime + 2*ramptime) in [us]
int gradnum[3] |
Internal use for gradient heating calculations
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
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
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 >
KS_SEQLOC* locs |
WF_PULSE** wfpulse |
Internal use
KS_WFINSTANCE* wfi |
Internal use
KS_RT_SCALE_LOG rtscaling |
Internal use