Data Structures | |
struct | KSGRE_SEQUENCE |
Macros | |
#define | KSGRE_MINHNOVER 16 |
#define | KSGRE_DEFAULT_SSI_TIME 200 /* which may allow us to use the same SSI for other sequence modules too */ |
#define | KSGRE_DEFAULT_SSI_TIME_SSFP 100 |
#define | KSGRE_INIT_SEQUENCE {KS_INIT_SEQ_CONTROL, KS_INIT_READTRAP, KS_INIT_TRAP, KS_INIT_TRAP, KS_INIT_PHASER, KS_INIT_PHASER, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_TRAP, KS_INIT_TRAP, FALSE}; |
#define | KSGRE_PHASEENCODING_MEMORYPOOL_SIZE 105000 |
Variables | |
KS_SEQ_COLLECTION | seqcollection |
float | ksgre_excthickness = 0 |
float | ksgre_gscalerfexc = 0.9 |
int | ksgre_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",} |
float | ksgre_spoilerarea = 1500.0 with {0.0, 10000.0, 1500.0, VIS, "ksgre spoiler gradient area",} |
int | ksgre_sincrf = 0 with {0, 1, 0, VIS, "Use Sinc RF",} |
float | ksgre_sincrf_bw = 2500 with {0, 100000, 2500, VIS, "Sinc RF BW",} |
float | ksgre_sincrf_tbw = 2 with {2, 100, 2, VIS, "Sinc RF TBW",} |
int | ksgre_rfexc_choice = 0 with {0, 3, 0, VIS, "RF pulse 0(fast)-1-2(high FA) 3 (Hard non-sel)",} |
int | ksgre_kxnover = 32 with {KSGRE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",} |
int | ksgre_rampsampling = FALSE with {FALSE, TRUE, FALSE, VIS, "Rampsampling [0:OFF 1:ON]",} |
int | ksgre_extragap = 0 with {0, 100ms, 0, VIS, "extra gap between readouts [us]",} |
int | ksgre_minacslines = 16 with {0, 512, 16, VIS, "Minimum ACS lines for ARC",} |
int | ksgre_minzacslines = 16 with {0, 512, 16, VIS, "Minimum z ACS lines for ARC",} |
int | ksgre_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, VIS, "us from start until the first waveform begins",} |
int | ksgre_ssi_time = KSGRE_DEFAULT_SSI_TIME with {32, , KSGRE_DEFAULT_SSI_TIME, VIS, "time from eos to ssi in intern trig",} |
int | ksgre_dda = 2 with {0, 200, 2, VIS, "Number of dummy scans for steady state",} |
int | ksgre_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)",} |
int | ksgre_imsize = KS_IMSIZE_MIN256 with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_MIN256, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"} |
int | ksgre_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",} |
int | ksgre_ellipsekspace = TRUE with {FALSE, TRUE, TRUE, VIS, "ky-kz coverage 0:Rect 1:Elliptical",} |
KSGRE_SEQUENCE | ksgre = KSGRE_INIT_SEQUENCE |
KSSCAN_LOOP_CONTROL | ksgre_loopctrl = KSSCAN_INIT_LOOP_CONTROL |
KSINV_MODULE | ksgre_inv = KSINV_INIT_MODULE |
KS_PHASEENCODING_COORD | ksgre_phaseencoding_memorypool [KSGRE_PHASEENCODING_MEMORYPOOL_SIZE] = {KS_INIT_PHASEENCODING_COORD} |
int | ksgre_ssfp_endtime = 0 |
KS_KSPACE_ACQ | kacq = KS_INIT_KSPACE_ACQ |
int | sequence_iopts [] |
int | spgr_phase_counter |
MR-contrasts supported
Features
#define KSGRE_MINHNOVER 16 |
#define KSGRE_DEFAULT_SSI_TIME 200 /* which may allow us to use the same SSI for other sequence modules too */ |
#define KSGRE_DEFAULT_SSI_TIME_SSFP 100 |
#define KSGRE_INIT_SEQUENCE {KS_INIT_SEQ_CONTROL, KS_INIT_READTRAP, KS_INIT_TRAP, KS_INIT_TRAP, KS_INIT_PHASER, KS_INIT_PHASER, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_TRAP, KS_INIT_TRAP, FALSE}; |
#define KSGRE_PHASEENCODING_MEMORYPOOL_SIZE 105000 |
num elements allocated for unique phase encodes
STATUS cvinit | ( | void | ) |
STATUS cveval | ( | void | ) |
STATUS my_cveval | ( | void | ) |
STATUS cvcheck | ( | void | ) |
STATUS predownload | ( | void | ) |
STATUS pulsegen | ( | void | ) |
STATUS mps2 | ( | void | ) |
STATUS aps2 | ( | void | ) |
STATUS scan | ( | void | ) |
abstract | ( | "GRE " | [KSFoundation] | ) |
psdname | ( | "ksgre" | ) |
STATUS ksgre_pg | ( | int | start_time | ) |
This is the main pulse sequence in ksgre.e using the sequence objects in KSGRE_SEQUENCE with the sequence module name "ksgremain" (= ksgre.seqctrl.description)
STATUS | SUCCESS or FAILURE |
KS_CORESLICETIME ksgre_scan_coreslice | ( | const SCAN_INFO * | slice_pos, |
KS_DYNAMIC_STATE * | dynamic | ||
) |
ksgre
sequence module in real time during scanningThe main GRE sequence's play function
This function updates the waveforms, and plays out, the ksgre sequence module. The low-level function call startseq()
, which actually starts the realtime sequence playout is called from within ks_scan_playsequence(), which in addition also returns the time to play out that sequence module (see time += ...).
After each call to ks_scan_playsequence(), ks_plot_slicetime() is called to add slice-timing information for later HTML plotting of the sequence. As scanning is performed in real-time and may fail if interrupted, ks_plot_slicetime() will return quietly if it detects both IPG (TGT) and PSD_HW (on the MR scanner).
Common for all coreslice functions for any psd is the return of a KS_CORESLICETIME struct, which contains the time take to play out one slice (.duration
) and the time from the start of the coreslice to the (.referencetimepoint
) used to define the excitation location of the coreslice. Here this is simply ksgre.seqctrl.momentstart as there are no other embedded sequence modules played out inside this function. If any sequence module is added inside this function before/after ks_scan_playsequence(&ksgre.seqctrl), the KS_CORESLICETIME struct needs be updated accordingly.
[in] | slice_pos | Position of the slice to be played out (one element in the global ks_scan_info[] array) |
dynamic | Pointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions |
KS_CORESLICETIME ksgre_scan_coreslicegroup | ( | const SCAN_INFO * | slice_pos, |
KS_DYNAMIC_STATE * | dynamic | ||
) |
The main GRE sequence + potential other modules' play function
With the use of generic scan loops (ksscan.cc:ksscan_scanloop()) performing the actual scan in ksgre_scan_scanloop(), using
ksgre_loopctrl
)dynamic
)coreslice
)one needs to create the psd-specific function in this file to play out one slice of one or more sequence modules This is that function, which must take (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic) as the two input arguments, and return a KS_CORESLICETIME struct. This to match the various ksscan_****loop() functions in ksscan.cc, used to run the scan.
Unlike ksgre_scan_coreslice(), which only plays the main sequence (ksgre
), this function also plays other sequence modules. For now, this is only the kssat
sequence module, which is played out before the main sequence, if active.
[in] | slice_pos | Pointer to the SCAN_INFO struct corresponding to the current slice to be played out |
dynamic | Pointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions |
int ksgre_eval_ssitime | ( | ) |
int | SSI time in [us] |
STATUS ksgre_scan_seqstate | ( | SCAN_INFO | slice_pos, |
KS_PHASEENCODING_SHOTCOORDS | shot_coords | ||
) |
This function sets the current state of all ksgre sequence objects being part of KSFSE_SEQUENCE, incl. gradient amplitude changes, RF freq/phases and receive freq/phase based on current slice position and phase encoding indices for a given sequence playout in ksgre_scan_coreslice() during scan.
[in] | slice_pos | Position of the slice to be played out (one element in the ks_scan_info[] array) |
[in] | shot_coords | KS_PHASEENCODING_SHOTCOORDS with list of phase encoding indices for current shot |
STATUS | SUCCESS or FAILURE |
const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl | ( | ) |
void ksgre_init_imagingoptions | ( | void | ) |
STATUS ksgre_init_UI | ( | void | ) |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_UI | ( | ) |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_setupobjects | ( | ) |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_TErange | ( | ) |
N.B.: The minTE (avminte) and maxTE (avmaxte) ensures TE (opte) to be in the valid range for this pulse sequence to be set up in ksgre_pg(). If the pulse sequence design changes in ksgre_pg(), by adding/modifying/removing sequence objects in a way that affects the intended TE, this function needs to be updated too.
STATUS | SUCCESS or FAILURE |
void ksgre_set_kspace_design | ( | KS_KSPACE_DESIGN * | kdesign | ) |
This function sets up the k-space design for the GRE sequence based on UI CVs, including properties like FOV size, matrix size, parallel imaging factors, receiver bandwidth, and partial Fourier factors.
For acoustic noise reduction scans (opsilent), ramp sampling is enabled to reduce the TE.
It is used by ksgre_set_loop_control_design() and ksgre_eval_sat().
Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan
[out] | kdesign | KS_KSPACE_DESIGN |
void ksgre_set_slicetiming_design | ( | KS_SLICETIMING_DESIGN * | slicetiming_design | ) |
This function is called from ksgre_eval_loops()->ksgre_set_loop_control_design() to produce a KSSCAN_LOOP_CONTROL_DESIGN, which contains this KS_SLICETIMING_DESIGN struct steering how the final KS_SLICETIMING struct will be set up by ksscan_slicetiming_eval_design(), taking a KS_SLICETIMING_DESIGN as input
Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan
[out] | slicetiming_design | KS_SLICETIMING_DESIGN to be created |
STATUS ksgre_set_loop_control_design | ( | KSSCAN_LOOP_CONTROL_DESIGN * | loop_design | ) |
This function creates a KSSCAN_LOOP_CONTROL_DESIGN struct, with fields .dda: Number of dummy scans .naverages: Number of averages .nvols: Number of volumes .phaseenc_design: KS_PHASEENCODING_DESIGN (containing coordinates and other phase encoding info) .slicetiming_design: KS_SLICETIMING_DESIGN (containing slice timing info)
This function is called from ksgre_eval_loops() to produce a KSSCAN_LOOP_CONTROL_DESIGN, which is then used in part to create a KSSCAN_LOOP_CONTROL struct used in scan
Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan
[out] | loop_design | KSSCAN_LOOP_CONTROL_DESIGN to be created |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_inversion | ( | KS_SEQ_COLLECTION * | seqcollection | ) |
Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan. Here, the KSINV_DESIGN has local scope and is setup and used only by this function. What remains is the KSINV_MODULE ksgre_inv module, declaread in .
The KS_SEQ_COLLECTION is passed as a pointer to the function, to let the KSINV_MODULE to be registered in the collection for RF scaling, and heating calculations.
[in,out] | seqcollection | Pointer to the KS_SEQ_COLLECTION struct holding all sequence modules |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_sat | ( | KS_SEQ_COLLECTION * | seqcollection | ) |
As there can only be one global graphical saturation module that interacts with the UI, this function uses the global kssat
struct (KSSAT_MODULE) in kssat.e, which is at the top of ksgre.e
seqcollection
is passed as a pointer to the function, to register the KSSAT_MODULE in the collection for later RF scaling, and heating calculations.
Both design structs have local scope, and via ksgre_set_slicetiming_design(), the slice location info is used to control the location of the sat bands in kssat_setup_from_UI()
[in,out] | seqcollection | Pointer to the KS_SEQ_COLLECTION struct holding all sequence modules |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_gradheat_play | ( | const INT | max_encode_mode, |
int | nargs, | ||
void ** | args | ||
) |
This function
It should be noted that the content of this function is manual work and needs to be updated if the content of ksgre_pg() or used sequence modules are changed for the gradient heating to be accurate. So if, for example, major dynamic changes of gradient amplitudes or which sequence modules that are used, this function should be updated accordingly.
As ks_eval_getduration() and ks_eval_hwlimits() are common for all psds, this function has to have nargs and args as input arguments, but they are not used here. See ksgre_eval_loops() for more details.
[in] | max_encode_mode | The maximum encoding mode, which can be either AVERAGE_POWER or MAXIMUM_POWER. |
[in] | nargs | (not used) Number of extra input arguments (# elements of void pointer array **args) |
[in] | args | (not used) Void pointer array with nargs elements (may be NULL) |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_loops | ( | KS_SEQ_COLLECTION * | seqcollection | ) |
This function performs the following tasks:
newtime
ksgre.seqctrl.duration
) if the newtime > time using ks_eval_seqctrl_setduration()loopctrl_design
(for main sequence), which is used together with the coreslice function (ksgre_scan_coreslicegroup())ksgre_loopctrl
in ksscan_loop_control_eval_design() to control the scan loop for the main sequenceNote that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan. Here this applies to the local variable loopctrl_design
[in,out] | seqcollection | Pointer to the KS_SEQ_COLLECTION struct holding all sequence modules |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_eval_scantime | ( | KS_SEQ_COLLECTION * | seqcollection | ) |
pitscan
is the UI variable for the scan clock shown in the top right corner on the MR scanner. The call to GEReq_eval_checkTR_SAR_calcs() also sets up the UI SAR annotation.
STATUS | SUCCESS or FAILURE |
STATUS ksgre_update_UI | ( | ) |
STATUS | SUCCESS or FAILURE |
STATUS ksgre_predownload_plot | ( | KS_SEQ_COLLECTION * | seqcollection | ) |
If a file /usr/g/research/bin/ksdonotplot exists, this function will return SUCCESS without plotting. This is a system-wide way of quickly disabling plotting for all sequences.
Otherwise the function first prints out the textfile: <ks_psdname>_objects.txt, which contains the specs of most sequence components in the sequence.
The rest of the function is the plotting the main sequence diagram as HTML file, and lastly the sequence timing plot, showing slice location on the y-axis and time on the x-axis for all sequence modules at the same time.
The HTML plots will have a slider to show the dynamics of a psd. What is interesting to show dynamics for can vary between psds. In most cases only the shot index might be interesting, skipping non-relevant changes such as change in slice location. One can think of this as recording something in a video, where only the relevant parts are recorded.
"Recording" is first reset by ks_eval_seqcollection_resetninst(). The generic ksscan_plotloop_shots() is used to play a single slice for many shot indices.
Note that ksscan_plotloop_shots() internally copies the loop_control struct (arg 2) and overrides the number of slices in order to play a single slice.
Lastly, ks_plot_psd() is called to write out a JSON file, followed by a system call to the python script psdplot/psdplot.py to create the HTML plots. The HTML files can take 10-20 s to generate, so be patient.
For the slicetiming plot, the three functions ks_plot_slicetime_begin();ksgre_scan_scanloop();ks_plot_slicetime_end(); creates a corresponding JSON file, followed by a system call to the python script psdplot/psdplot_slicetime.py to create the HTML plot.
STATUS | SUCCESS or FAILURE |
STATUS ksgre_predownload_setrecon | ( | ) |
For most cases, the GEReq_predownload_*** functions in predownload() in ksgre.e set up the necessary rh*** variables for the reconstruction to work properly. However, if this sequence is customized, certain rh*** variables may need to be changed. Doing this here instead of in predownload() directly separates these changes from the standard behavior.
STATUS | SUCCESS or FAILURE |
float ksgre_scan_phase | ( | int | counter | ) |
This function is largely what makes the difference between the the types of gradient echo sequences by different phase increment policies. For SPGR, RF spoiling is wanted and one tries to not repeat the same RF phase in a series of consecutive excitation. For bSSFP, the flip angle should be 'negative' every other time, which is accomplished by setting the RF phase to 0 or 180 [deg]. In all other cases (values of oppseq), the RF phase is set to 0.
[in] | counter | Counter from the calling function that should increment by 1 outside this function |
phase | RF phase in [deg] to be passed to ks_scan_selrf_setfreqphase() and ks_scan_offsetfov() |
STATUS ksgre_scan_init | ( | void | ) |
STATUS | SUCCESS or FAILURE |
void ksgre_scan_prescanloop | ( | int | nloops, |
int | dda | ||
) |
STATUS | SUCCESS or FAILURE |
KS_SEQ_COLLECTION seqcollection |
float ksgre_excthickness = 0 |
float ksgre_gscalerfexc = 0.9 |
int ksgre_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",} |
float ksgre_spoilerarea = 1500.0 with {0.0, 10000.0, 1500.0, VIS, "ksgre spoiler gradient area",} |
int ksgre_sincrf = 0 with {0, 1, 0, VIS, "Use Sinc RF",} |
float ksgre_sincrf_bw = 2500 with {0, 100000, 2500, VIS, "Sinc RF BW",} |
float ksgre_sincrf_tbw = 2 with {2, 100, 2, VIS, "Sinc RF TBW",} |
int ksgre_rfexc_choice = 0 with {0, 3, 0, VIS, "RF pulse 0(fast)-1-2(high FA) 3 (Hard non-sel)",} |
int ksgre_kxnover = 32 with {KSGRE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",} |
int ksgre_rampsampling = FALSE with {FALSE, TRUE, FALSE, VIS, "Rampsampling [0:OFF 1:ON]",} |
int ksgre_extragap = 0 with {0, 100ms, 0, VIS, "extra gap between readouts [us]",} |
int ksgre_minacslines = 16 with {0, 512, 16, VIS, "Minimum ACS lines for ARC",} |
int ksgre_minzacslines = 16 with {0, 512, 16, VIS, "Minimum z ACS lines for ARC",} |
int ksgre_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, VIS, "us from start until the first waveform begins",} |
int ksgre_ssi_time = KSGRE_DEFAULT_SSI_TIME with {32, , KSGRE_DEFAULT_SSI_TIME, VIS, "time from eos to ssi in intern trig",} |
int ksgre_dda = 2 with {0, 200, 2, VIS, "Number of dummy scans for steady state",} |
int ksgre_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)",} |
int ksgre_imsize = KS_IMSIZE_MIN256 with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_MIN256, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"} |
int ksgre_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",} |
int ksgre_ellipsekspace = TRUE with {FALSE, TRUE, TRUE, VIS, "ky-kz coverage 0:Rect 1:Elliptical",} |
KSGRE_SEQUENCE ksgre = KSGRE_INIT_SEQUENCE |
KSSCAN_LOOP_CONTROL ksgre_loopctrl = KSSCAN_INIT_LOOP_CONTROL |
Scan loop control for the ksgre
sequence
KSINV_MODULE ksgre_inv = KSINV_INIT_MODULE |
Inversion module
KS_PHASEENCODING_COORD ksgre_phaseencoding_memorypool[KSGRE_PHASEENCODING_MEMORYPOOL_SIZE] = {KS_INIT_PHASEENCODING_COORD} |
int ksgre_ssfp_endtime = 0 |
KS_KSPACE_ACQ kacq = KS_INIT_KSPACE_ACQ |
int sequence_iopts[] |
int spgr_phase_counter |