KSFoundation  [October2024]
A platform for structured EPIC programming on GE MR systems
ksgre.e: GRE sequence

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
 

Functions

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)
 
KS_CORESLICETIME ksgre_scan_coreslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksgre_scan_coreslicegroup (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
int ksgre_eval_ssitime ()
 
STATUS ksgre_scan_seqstate (SCAN_INFO slice_pos, KS_PHASEENCODING_SHOTCOORDS shot_coords)
 
const KSSCAN_LOOP_CONTROLksgre_get_loop_ctrl ()
 
void ksgre_init_imagingoptions (void)
 
STATUS ksgre_init_UI (void)
 
STATUS ksgre_eval_UI ()
 
STATUS ksgre_eval_setupobjects ()
 
STATUS ksgre_eval_TErange ()
 
void ksgre_set_kspace_design (KS_KSPACE_DESIGN *kdesign)
 
void ksgre_set_slicetiming_design (KS_SLICETIMING_DESIGN *slicetiming_design)
 
STATUS ksgre_set_loop_control_design (KSSCAN_LOOP_CONTROL_DESIGN *loop_design)
 
STATUS ksgre_eval_inversion (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_eval_sat (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_gradheat_play (const INT max_encode_mode, int nargs, void **args)
 
STATUS ksgre_eval_loops (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_eval_scantime (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_update_UI ()
 
STATUS ksgre_predownload_plot (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_predownload_setrecon ()
 
float ksgre_scan_phase (int counter)
 
STATUS ksgre_scan_init (void)
 
void ksgre_scan_prescanloop (int nloops, int dda)
 

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
 

Detailed Description

MR-contrasts supported

Features

Macro Definition Documentation

◆ KSGRE_MINHNOVER

#define KSGRE_MINHNOVER   16

◆ KSGRE_DEFAULT_SSI_TIME

#define KSGRE_DEFAULT_SSI_TIME   200 /* which may allow us to use the same SSI for other sequence modules too */

◆ KSGRE_DEFAULT_SSI_TIME_SSFP

#define KSGRE_DEFAULT_SSI_TIME_SSFP   100

◆ KSGRE_INIT_SEQUENCE

◆ KSGRE_PHASEENCODING_MEMORYPOOL_SIZE

#define KSGRE_PHASEENCODING_MEMORYPOOL_SIZE   105000

num elements allocated for unique phase encodes

Function Documentation

◆ cvinit()

STATUS cvinit ( void  )
94  {
95  STATUS status;
96 
97  status = GEReq_cvinit();
98  KS_RAISE(status);
99 
100  /* reset debug file ./ks_debug.txt (SIM) or /usr/g/mrraw/ks_debug.txt (HW) */
101  ks_dbg_reset();
102 
103  /* Imaging Options buttons */
105 
106  /* Setup UI buttons */
107  status = ksgre_init_UI();
108  KS_RAISE(status);
109 
110  return SUCCESS;
111 
112 } /* cvinit() */
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksgre_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksgre_implementation.e:266
void ks_dbg_reset()
Clear debug file content
Definition: KSFoundation_common.c:140
STATUS GEReq_cvinit(void)
Helper function to be called at the beginning of cvinit()
Definition: GERequired.e:3194
void ksgre_init_imagingoptions(void)
Initial handling of imaging options buttons and top-level CVs at the PSD type-in page
Definition: ksgre_implementation.e:219

◆ cveval()

STATUS cveval ( void  )
121  {
122 
123  /*
124  cveval() is called 37+ times per UI button push on the MR system, while cvcheck() is only called once.
125  For a faster execution we have a my_cveval() function that is called in cvcheck() instead
126  */
127 
128  return SUCCESS;
129 
130 } /* cveval() */

◆ my_cveval()

STATUS my_cveval ( void  )
135  {
136  STATUS status;
137 
139 
140  /* Link the memory pool for the phase encoding plans */
143  KS_RAISE(status);
144 
145  status = GEReq_cveval();
146  KS_RAISE(status);
147 
148  /* User Interface updates & opuserCV sync */
149  status = ksgre_eval_UI();
150  KS_RAISE(status);
151 
152  /* Setup sequence objects */
153  status = ksgre_eval_setupobjects();
154  KS_RAISE(status);
155 
156  /* Calculate minimum (and maximum TE) */
157  status = ksgre_eval_TErange();
158  KS_RAISE(status);
159 
160  /* Run the sequence once (and only once after ksgre_eval_setupobjects()) in cveval() to
161  get the sequence duration and the number of object instances (for grad/rf limits in GEReq...limits()) */
162  status = ksgre_pg(ksgre_pos_start);
163  KS_RAISE(status);
164 
166  KS_RAISE(status);
167 
168  /* Add the passpacket seqctrl to the seqcollection */
170  KS_RAISE(status);
171 
172  /*--------- Begin: Additional sequence modules -----------*/
173 
174  /* Sat */
175  status = ksgre_eval_sat(&seqcollection);
176  KS_RAISE(status);
177 
178  /* Inversion (general & GRE specific). Must be the last sequence module added TODO */
180  KS_RAISE(status);
181 
182  /*--------- End: Additional sequence modules -----------*/
183 
184 
185  /* Min TR, #slices per TR, RF/gradient heating & SAR */
186  status = ksgre_eval_loops(&seqcollection);
187  KS_RAISE(status);
188 
189  /* RF scaling across sequence modules */
191  KS_RAISE(status);
192 
193  /* scan time */
195  KS_RAISE(status);
196 
197  return SUCCESS;
198 
199 } /* my_cveval() */
STATUS ksgre_eval_UI()
Gets the current UI and checks for valid inputs
Definition: ksgre_implementation.e:562
STATUS ksgre_eval_scantime(KS_SEQ_COLLECTION *seqcollection)
Sets the scan time and SAR values in the UI and checks that the sequence is within hardware limits...
Definition: ksgre_implementation.e:1272
STATUS ksgre_pg(int)
The ksgre (main) pulse sequence
Definition: ksgre_implementation.e:1520
KS_PHASEENCODING_COORD ksgre_phaseencoding_memorypool[KSGRE_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksgre_implementation.e:141
STATUS ksgre_eval_TErange()
Sets the min/max TE based on the durations of the sequence objects in KSGRE_SEQUENCE (ksgre)...
Definition: ksgre_implementation.e:789
STATUS ksgre_eval_loops(KS_SEQ_COLLECTION *seqcollection)
Setup of scan loop control struct after heating calculations
Definition: ksgre_implementation.e:1186
STATUS ksgre_eval_setupobjects()
Sets up all sequence objects for the main sequence module (KSGRE_SEQUENCE ksgre)
Definition: ksgre_implementation.e:597
STATUS ksgre_eval_sat(KS_SEQ_COLLECTION *seqcollection)
Set up of the KSSAT_MODULE kssat for graphical saturation in the UI
Definition: ksgre_implementation.e:1093
STATUS ks_eval_addtoseqcollection(KS_SEQ_COLLECTION *seqcollection, KS_SEQ_CONTROL *seqctrl) WARN_UNUSED_RESULT
Adds a sequence module (KS_SEQ_CONTROL) to the KS_SEQ_COLLECTION struct for later RF scaling and SAR ...
Definition: KSFoundation_host.c:207
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
STATUS ksgre_eval_inversion(KS_SEQ_COLLECTION *seqcollection)
Setup and evaluation of KSINV_DESIGN and the creation of a KSINV_MODULE module for inversion recovery...
Definition: ksgre_implementation.e:1050
void ks_init_seqcollection(KS_SEQ_COLLECTION *seqcollection)
Resets KS_SEQ_COLLECTION to its default value (KS_INIT_SEQ_COLLECTION)
Definition: KSFoundation_host.c:156
KS_SEQ_COLLECTION seqcollection
Definition: ksgre.e:88
#define KS_RAISE(status)
Definition: KSFoundation.h:190
#define KSGRE_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksgre_implementation.e:140
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
STATUS ks_phaseencoding_memorypool_init(KS_PHASEENCODING_COORD *entries, uint64_t size)
Internal use for correct migration of KS_PHASEENCODING_PLAN from HOST to TGT (IPG)
Definition: KSFoundation_common.c:580
int ksgre_pos_start
Definition: ksgre_implementation.e:109
STATUS GEReq_cveval(void)
Helper function to be called at the beginning of cveval()
Definition: GERequired.e:3346
STATUS GEReq_eval_rfscaling(KS_SEQ_COLLECTION *seqcollection)
Performs RF scaling of all RF pulses in the KS_SEQ_COLLECTION and Prescan
Definition: GERequired.e:808

◆ cvcheck()

STATUS cvcheck ( void  )
208  {
209  STATUS status;
210 
211  status = my_cveval();
212  KS_RAISE(status);
213 
214  status = GEReq_cvcheck();
215  KS_RAISE(status);
216 
217  status = ksgre_update_UI();
218  KS_RAISE(status);
219 
221 
222  return SUCCESS;
223 
224 } /* cvcheck() */
STATUS GEReq_cvcheck(void)
Helper function to be called at the beginning of cvcheck()
Definition: GERequired.e:3430
STATUS my_cveval(void)
Definition: ksgre.e:135
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int abort_on_kserror
Definition: KSFoundation_common.c:40
int ksgre_abort_on_kserror
Definition: ksgre_implementation.e:114
STATUS ksgre_update_UI()
Returns error of various parameter combinations that are not allowed for ksgre
Definition: ksgre_implementation.e:1311

◆ predownload()

STATUS predownload ( void  )
232  {
233  STATUS status;
234 
235  status = GEReq_predownload();
236  KS_RAISE(status);
237 
238  status = GEReq_predownload_prescan_options((RG_CAL_MODE_E) RG_CAL_MODE_LOW_FIXED);
239  KS_RAISE(status);
240 
241  /* Set filter slot # for SCAN, APS2, MPS2 */
243 
244  const KSSCAN_LOOP_CONTROL *loop_control = ksgre_get_loop_ctrl();
245 
246  /* slice ordering */
247  /* The following GE globals must be set appropriately:
248  data_acq_order[], rsp_info[], rsprot[], rsptrigger[]. This is a must for a main pulse sequence */
249  if (KS_3D_SELECTED) {
250  status = GEReq_predownload_store_sliceplan3D(opslquant, opvquant);
251  } else {
253  }
254  KS_RAISE(status);
255 
256  /* generic rh-vars setup */
258  ksgre_imsize, KS_GERECON * (rhrecon < 1000) /* online recon if rhrecon < 1000 */);
260  GEReq_predownload_setrecon_voldata(opfphases, loop_control->slicetiming.slice_plan); /* opfphases = number of volumes */
261 
262  /* further sequence specific recon settings that have not been set correctly at this point */
263  status = ksgre_predownload_setrecon();
264  KS_RAISE(status);
265 
266  /* plotting of sequence modules and slice timing to disk */
268 
269  return SUCCESS;
270 
271 } /* predownload() */
void GEReq_predownload_setrecon_readphase(const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser, int imsize_policy, int datadestination)
Sets required global rh*** variables for Cartsian imaging
Definition: GERequired.e:2633
STATUS GEReq_predownload_setfilter(FILTER_INFO *filt)
Definition: GERequired.e:1382
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
STATUS GEReq_predownload_store_sliceplan(KS_SLICE_PLAN slice_plan)
Sets mandatory global GE arrays for data acquisition
Definition: GERequired.e:1072
#define KS_GERECON
Definition: KSFoundation.h:241
int ksgre_imsize
Definition: ksgre_implementation.e:113
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
STATUS ksgre_predownload_setrecon()
Last-resort function to override certain recon variables not set up correctly already
Definition: ksgre_implementation.e:1471
const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl()
Definition: ksgre_implementation.e:1503
void GEReq_predownload_setrecon_voldata(int numvols, const KS_SLICE_PLAN slice_plan)
Sets rh*** variables related to multi-volume imaging
Definition: GERequired.e:2940
KS_SEQ_COLLECTION seqcollection
Definition: ksgre.e:88
int ksgre_extragap
Definition: ksgre_implementation.e:98
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_READTRAP read
Definition: ksgre_implementation.e:55
STATUS GEReq_predownload_prescan_options(RG_CAL_MODE_E rg_cal_mode)
Prescan options
Definition: GERequired.e:3124
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
STATUS GEReq_predownload_store_sliceplan3D(int slices_in_slab, int slabs)
Sets mandatory global GE arrays for data acquisition (3D imaging)
Definition: GERequired.e:1275
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1549
void GEReq_predownload_setrecon_annotations_readtrap(KS_READTRAP *readtrap, int echogap)
Sets ih*** variables for TE and rBW annotation based on a KS_READTRAP
Definition: GERequired.e:2865
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
STATUS GEReq_predownload(void)
Helper function to be called at the beginning of predownload()
Definition: GERequired.e:3473
STATUS ksgre_predownload_plot(KS_SEQ_COLLECTION *seqcollection)
Plotting of sequence modules and slice timing in HTML files
Definition: ksgre_implementation.e:1411
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59

◆ pulsegen()

STATUS pulsegen ( void  )
280  {
281 
283 
284  /* Link the memory pool for the phase encoding plans */
287 
288  /* Main Pulse Sequence */
290  KS_SEQLENGTH(seqcore, ksgre.seqctrl);
291 
292  /* Sat */
293  kssat_pg(&kssat);
294  if (kssat.seqctrl.duration > 0) {
295  KS_SEQLENGTH(seqsat, kssat.seqctrl);
296  }
297 
298  /* Inversion sequence modules */
300  if (ksgre_inv.seqctrl.duration > 0) {
301  KS_SEQLENGTH(seqinv, ksgre_inv.seqctrl);
302  }
303 
305 
306  buildinstr(); /* load the sequencer memory */
307 
308  return SUCCESS;
309 
310 } /* pulsegen() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
STATUS ksgre_pg(int)
The ksgre (main) pulse sequence
Definition: ksgre_implementation.e:1520
KS_PHASEENCODING_COORD ksgre_phaseencoding_memorypool[KSGRE_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksgre_implementation.e:141
KS_SEQLENGTH(seq_name, seq_struct)
Creates a hardware sequence for the current sequence module
Definition: GERequired.e:65
STATUS kssat_pg(KSSAT_MODULE *sat)
Place all waveforms for the saturation module
Definition: kssat.e:180
int duration
Definition: KSFoundation.h:1227
void GEReq_pulsegenEnd(void)
Helper function to be called at the end of pulsegen()
Definition: GERequired.e:3598
KSSAT_MODULE kssat
Definition: kssat.e:112
STATUS ksinv_pg(KSINV_MODULE *seq)
Generation of the waveforms for the waveform of the standard inversion module
Definition: ksinversion.cc:791
#define KSGRE_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksgre_implementation.e:140
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
STATUS ks_phaseencoding_memorypool_init(KS_PHASEENCODING_COORD *entries, uint64_t size)
Internal use for correct migration of KS_PHASEENCODING_PLAN from HOST to TGT (IPG)
Definition: KSFoundation_common.c:580
KSINV_MODULE ksgre_inv
Definition: ksgre_implementation.e:137
int ksgre_pos_start
Definition: ksgre_implementation.e:109
void GEReq_pulsegenBegin(void)
Helper function to be called at the beginning of pulsegen()
Definition: GERequired.e:3571
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73

◆ mps2()

STATUS mps2 ( void  )
333  {
334  rspent = L_MPS2;
335  strcpy(psdexitarg.text_arg, "mps2");
336 
337  if (ksgre_scan_init() == FAILURE)
338  return rspexit();
339 
341 
342  rspexit();
343 
344  return SUCCESS;
345 
346 } /* mps2() */
int ksgre_dda
Definition: ksgre_implementation.e:111
void ksgre_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksgre_implementation.e:2074
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:2045
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ aps2()

STATUS aps2 ( void  )
356  {
357 
358  rspent = L_APS2;
359  strcpy(psdexitarg.text_arg, "aps2");
360 
361  if (ksgre_scan_init() == FAILURE)
362  return rspexit();
363 
365 
366  rspexit();
367 
368  return SUCCESS;
369 
370 } /* aps2() */
int ksgre_dda
Definition: ksgre_implementation.e:111
void ksgre_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksgre_implementation.e:2074
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:2045
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ scan()

STATUS scan ( void  )
382  {
383 
384  rspent = L_SCAN;
385  strcpy(psdexitarg.text_arg, "scan");
386 
387  if (ksgre_scan_init() == FAILURE)
388  return rspexit();
389 
391 
392  GEReq_endofscan();
393 
394  rspexit();
395 
396  return SUCCESS;
397 
398 } /* scan() */
int GEReq_endofscan()
Sets SSP word in sequence off_GEpass() to tell system that scan is done
Definition: GERequired.e:3647
s64 ksgre_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksgre_implementation.e:2005
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:2045
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ abstract()

abstract ( "GRE "  [KSFoundation])

◆ psdname()

psdname ( "ksgre"  )

◆ ksgre_pg()

STATUS ksgre_pg ( int  start_time)

The ksgre (main) pulse sequence

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)

Return values
STATUSSUCCESS or FAILURE
1520  {
1521  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
1522  int readstart_pos, readend_pos;
1523  int i;
1524  int endposx = 0;
1525  int endposy = 0;
1526  int endposz = 0;
1527  STATUS status;
1528 
1529 #ifdef HOST_TGT
1530  if (opte < avminte) {
1531  /* we cannot proceed until TE is larger than the minimum TE (see ksgre_eval_TErange()).
1532  Return a long seq duration and pretend all is good */
1534  return SUCCESS;
1535  }
1536 #endif
1537 
1538  if (start_time < KS_RFSSP_PRETIME) {
1539  return ks_error("%s: 1st arg (pos start) must be at least %d us", __FUNCTION__, KS_RFSSP_PRETIME);
1540  }
1541 
1542  /*******************************************************************************************************
1543  * RF Excitation
1544  *******************************************************************************************************/
1545  tmploc.ampscale = 1.0;
1546  tmploc.pos = RUP_GRD(start_time);
1547  tmploc.board = ZGRAD;
1548 
1549  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksgre.selrfexc is an excitation pulse
1550  (ksgre.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksgre.seqctrl.momentstart
1551  to the absolute position in [us] of the isocenter of the RF excitation pulse */
1552  status = ks_pg_selrf(&ksgre.selrfexc, tmploc, &ksgre.seqctrl);
1553  KS_RAISE(status);
1554 
1555  /* forward to end of selrfexc.postgrad */
1557 
1558  /* Second flow comp gradient slice for slice excitation */
1559  status = ks_pg_trap(&ksgre.fcompslice, tmploc, &ksgre.seqctrl); /* N.B.: will return quietly if ksgre.fcompslice.duration = 0 (opfcomp = 0) */
1560  KS_RAISE(status);
1561 
1562  /*******************************************************************************************************
1563  * Readout timing
1564  *******************************************************************************************************/
1565 
1566  /* With ksgre.seqctrl.momentstart set by ks_pg_selrf(&ksgre.selrfexc, ...), the absolute readout position
1567  can be determined (for both full Fourier and partial Fourier readouts using ksgre.read.time2center) */
1568  readstart_pos = ksgre.seqctrl.momentstart + opte - ksgre.read.time2center;
1569 
1570 
1571  /*******************************************************************************************************
1572  * Pre-read: Dephasers
1573  *******************************************************************************************************/
1574 
1575  /******************** Z ********************/
1576  if (ksgre.zphaseenc.grad.duration > 0) {
1577  /* 3D: use .zphaseenc (with embedded slice rephaser via .areaoffset != 0) instead of .selrfexc.postgrad (not placed out since its .duration = 0) */
1578  tmploc.pos += ksgre.fcompslice.duration; /* fcompslice.duration = 0 unless opfcomp */
1579  status = ks_pg_phaser(&ksgre.zphaseenc, tmploc, &ksgre.seqctrl);
1580  KS_RAISE(status);
1581 
1583  }
1584 
1585  /******************** Y ********************/
1586  tmploc.pos = readstart_pos + RUP_GRD(ksgre.read.acqdelay) - ksgre.phaseenc.grad.duration;
1587  tmploc.board = YGRAD;
1588  status = ks_pg_phaser(&ksgre.phaseenc, tmploc, &ksgre.seqctrl);
1589  KS_RAISE(status);
1590 
1591  /* set phase encode amps to first ky view (for plotting & moment calcs in WTools) */
1592  ks_scan_phaser_toline(&ksgre.phaseenc, 0, 0); /* dephaser */
1593 
1594  /******************** X ********************/
1595  if (ksgre_slicecheck)
1596  tmploc.board = ZGRAD; /* move the readout to the Z-axis to view the slice thickness in the image */
1597  else
1598  tmploc.board = XGRAD;
1599  tmploc.pos = readstart_pos - ksgre.readdephaser.duration;
1600  status = ks_pg_trap(&ksgre.readdephaser, tmploc, &ksgre.seqctrl);
1601  KS_RAISE(status);
1602 
1603  tmploc.pos = readstart_pos - ksgre.readdephaser.duration - ksgre.fcompread.duration;
1604  status = ks_pg_trap(&ksgre.fcompread, tmploc, &ksgre.seqctrl); /* N.B.: will return quietly if ksgre.fcompread.duration = 0 */
1605  KS_RAISE(status);
1606 
1607 
1608  /*******************************************************************************************************
1609  * Readout(s)
1610  *******************************************************************************************************/
1611 
1612  if (ksgre_slicecheck)
1613  tmploc.board = ZGRAD;
1614  else
1615  tmploc.board = XGRAD;
1616 
1617  /* ksgre.read at TE = opte (1st echo) */
1618  tmploc.pos = readstart_pos;
1619  tmploc.ampscale = 1.0;
1620  for (i = 0; i < opnecho; i++) {
1621  status = ks_pg_readtrap(&ksgre.read, tmploc, &ksgre.seqctrl);
1622  KS_RAISE(status);
1623  tmploc.pos += ksgre.read.grad.duration + ksgre_extragap * ((i + 1) < opnecho); /* don't add extra gap after the last readout */
1624  tmploc.ampscale *= -1.0;
1625  }
1626  readend_pos = tmploc.pos; /* absolute time for end of last readout trapezoid */
1627  tmploc.ampscale = 1.0;
1628 
1629 
1630  /*******************************************************************************************************
1631  * Post-read: Rephasers & spoilers
1632  *******************************************************************************************************/
1633 
1634  /******************** X ********************/
1635  if (ksgre_slicecheck) {
1636  tmploc.board = ZGRAD; /* move the readout to the Z-axis to view the slice thickness in the image */
1637  } else {
1638  tmploc.board = XGRAD;
1639  }
1640  tmploc.pos = readend_pos;
1641  if (oppseq == PSD_SSFP) {
1642  status = ks_pg_trap(&ksgre.readrephaser_ssfp, tmploc, &ksgre.seqctrl); /* read rephaser */
1643  KS_RAISE(status);
1644  endposx = tmploc.pos + ksgre.readrephaser_ssfp.duration; /* absolute time for end of last waveform on X */
1645  } else {
1646  status = ks_pg_trap(&ksgre.spoiler, tmploc, &ksgre.seqctrl);
1647  KS_RAISE(status);
1648  endposx = tmploc.pos + ksgre.spoiler.duration; /* absolute time for end of last waveform on X */
1649  }
1650 
1651  /******************** Y ********************/
1652  /* phase encoding rephaser on Y (common for GRE, SPGR & SSFP) */
1653  tmploc.board = YGRAD;
1654  tmploc.pos = readend_pos - RDN_GRD(ksgre.read.acqdelay); /* Y rephaser can start at the end of the acqwin */
1655  status = ks_pg_phaser(&ksgre.phaseenc, tmploc, &ksgre.seqctrl);
1656  KS_RAISE(status);
1657  endposy = tmploc.pos + ksgre.phaseenc.grad.duration; /* absolute time for end of last waveform on Y */
1658 
1659  ks_scan_phaser_fromline(&ksgre.phaseenc, 1, 0); /* rephaser */
1660 
1661  /******************** Z ********************/
1662  tmploc.board = ZGRAD;
1663  tmploc.pos = readend_pos - RDN_GRD(ksgre.read.acqdelay); /* Z rephaser/spoiler can start at the end of the acqwin */
1664 
1665  if (oppseq == PSD_SSFP) {
1666 
1667  if (ksgre.zphaseenc.grad.duration > 0) { /* 3D */
1668  /* z phase encoding rephaser (if 3D SSFP) */
1669  status = ks_pg_phaser(&ksgre.zphaseenc, tmploc, &ksgre.seqctrl);
1670  KS_RAISE(status);
1671  endposz = tmploc.pos + ksgre.zphaseenc.grad.duration;
1672 
1674 
1675  } else { /* 2D SSFP */
1676  /* endtime - postgrad.duration = starting point for z postgrad trapezoid */
1677  tmploc.pos += IMax(3, \
1681 
1682  /* another instance of the slice rephaser, placed at the very end. Relies on isodelay = rfwave.duration / 2 */
1683  status = ks_pg_trap(&ksgre.selrfexc.postgrad, tmploc, &ksgre.seqctrl);
1684  KS_RAISE(status);
1685  endposz = tmploc.pos + ksgre.selrfexc.postgrad.duration;
1686  }
1687 
1688  } else { /* non-SSFP */
1689  if (ksgre_slicecheck) {
1690  tmploc.board = XGRAD;
1691  }
1692 
1693  status = ks_pg_trap(&ksgre.spoiler, tmploc, &ksgre.seqctrl);
1694  KS_RAISE(status);
1695  endposz = tmploc.pos + ksgre.spoiler.duration;
1696 
1697  }
1698 
1699  /*******************************************************************************************************
1700  * Set the minimal sequence duration (ksgre.seqctrl.min_duration) by calling
1701  * ks_eval_seqctrl_setminduration()
1702  *******************************************************************************************************/
1703 
1704  /* end position of all axes. Make sure we are divisible by GRAD_UPDATE_TIME (4us) */
1705  tmploc.pos = RUP_GRD(IMax(3, endposx, endposy, endposz));
1706 
1707 #ifdef HOST_TGT
1708  /* On HOST only: Sequence duration (ksgre.seqctrl.ssi_time must be > 0 and is added to ksgre.seqctrl.min_duration in ks_eval_seqctrl_setminduration() */
1710  ks_eval_seqctrl_setminduration(&ksgre.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
1711 #endif
1712 
1713  return SUCCESS;
1714 
1715 } /* ksgre_pg() */
KS_TRAP grad
Definition: KSFoundation.h:1463
KS_TRAP fcompread
Definition: ksgre_implementation.e:62
KS_TRAP grad
Definition: KSFoundation.h:1719
int ksgre_ssfp_endtime
Definition: ksgre_implementation.e:144
int ksgre_slicecheck
Definition: ksgre_implementation.e:86
int pos
Definition: KSFoundation.h:463
STATUS ks_pg_readtrap(KS_READTRAP *readtrap, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_READTRAP sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:2161
KS_TRAP fcompslice
Definition: ksgre_implementation.e:63
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
STATUS ks_pg_phaser(KS_PHASER *phaser, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_PHASER sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:2031
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
STATUS ks_pg_selrf(KS_SELRF *selrf, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_SELRF sequence object on a gradient (and RF) board at some position in the pulse sequence...
Definition: KSFoundation_common.c:2817
int momentstart
Definition: KSFoundation.h:1228
int board
Definition: KSFoundation.h:462
KS_TRAP grad
Definition: KSFoundation.h:1561
float ampscale
Definition: KSFoundation.h:464
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:57
KS_TRAP pregrad
Definition: KSFoundation.h:1462
STATUS ks_pg_trap(KS_TRAP *trap, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_TRAP sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:1802
int ksgre_extragap
Definition: ksgre_implementation.e:98
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP readdephaser
Definition: ksgre_implementation.e:56
KS_TRAP spoiler
Definition: ksgre_implementation.e:60
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:461
KS_READTRAP read
Definition: ksgre_implementation.e:55
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int ssi_time
Definition: KSFoundation.h:1226
void ks_scan_phaser_toline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from the k-space center to a desired k-s...
Definition: KSFoundation_tgt.c:460
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
STATUS ks_eval_seqctrl_setminduration(KS_SEQ_CONTROL *seqctrl, int mindur)
Sets the minimum duration and duration fields of a KS_SEQ_CONTROL struct based on some minimum time (...
Definition: KSFoundation_host.c:4921
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:287
int duration
Definition: KSFoundation.h:673
int time2center
Definition: KSFoundation.h:1560
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
int ksgre_eval_ssitime()
The SSI time for the sequence
Definition: ksgre_implementation.e:1230
int acqdelay
Definition: KSFoundation.h:1555
void ks_scan_phaser_fromline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from a k-space line to the k-space cente...
Definition: KSFoundation_tgt.c:472
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217

◆ ksgre_scan_coreslice()

KS_CORESLICETIME ksgre_scan_coreslice ( const SCAN_INFO *  slice_pos,
KS_DYNAMIC_STATE *  dynamic 
)

Plays out one slice for the ksgre sequence module in real time during scanning

The 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.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the global ks_scan_info[] array)
dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Returns
coreslicetime KS_CORESLICETIME containing the time taken in [us] to play out one slice and the moment start of the slice
1879  {
1880 
1881  float tloc = 0.0;
1882  SCAN_INFO slice_pos_updated;
1884 
1885  if (slice_pos != NULL) {
1886  /* modify sequence for next playout */
1887  /* uncomment to make transformations in the logical read-phase-slice coordinate system, using your own
1888  logic, here just rotating by 30 degrees in-plane
1889  float rotz = 30.0;
1890  ks_mat4_setgeometry(dynamic->Mlogical, 0, 0, 0, 0, 0, rotz);
1891  Mphysical is useful for prospective motion correction implementations as it operates in X-Y-Z coords
1892  but should be left as the identity matrix otherwise
1893  */
1894  ks_scan_update_slice_location(&slice_pos_updated, *slice_pos, dynamic->Mphysical, dynamic->Mlogical);
1895  tloc = slice_pos_updated.optloc;
1896 
1897  /* Set the module's state */
1898  ksgre_scan_seqstate(slice_pos_updated, dynamic->shot_coords);
1899  } else {
1900  ks_scan_rf_off(&ksgre.selrfexc.rf, INSTRALL); /* false slice, shut off RF pulses */
1901  }
1902 
1903  /* Data routing control */
1904  TYPDAB_PACKETS acqflag = slice_pos != NULL ? DABON : DABOFF;
1905  if ((dynamic->prescan || !dynamic->force_acq) && (dynamic->shot < 0 || dynamic->average < 0)) {
1906  acqflag = DABOFF;
1907  }
1908  const int dabop = (dynamic->average <= 0) ? DABSTORE : DABADD; /* replace or add to data */
1909 
1910  /* Same coord for all echoes */
1911  const KS_PHASEENCODING_COORD coord = dynamic->shot_coords.entries == NULL ?
1912  fake_coord : dynamic->shot_coords.entries[0];
1913 
1914  /* There is no compressed bam since DV26, however impact on product recon with SENSE is unclear */
1915  /* ASSET case triggered by R > 1 and no ACS lines */
1916  const int dabview_factor = (ksgre.phaseenc.R > 1 && ksgre.phaseenc.nacslines == 0) ?
1917  ksgre.phaseenc.R /* compressed BAM without empty non-acquired lines */ :
1918  1 /* normal */;
1919 
1920  const int dabview = coord.ky >= 0 ? coord.ky/dabview_factor : KS_NOTSET;
1921 
1922  int dabslice = dynamic->sltimeinpass;
1923  if (ksgre.zphaseenc.res > 1) {
1924  if (dynamic->slloc_offset) {
1925  dabslice = dynamic->slloc_offset - coord.kz;
1926  } else {
1927  dabslice = coord.kz;
1928  }
1929  }
1930 
1931  int echoindx = 0;
1932  for (; echoindx < ksgre.read.acq.base.ngenerated; echoindx++) {
1933 
1934  TYPDAB_PACKETS psc_acqflag = echoindx == 0 ? acqflag : DABOFF;
1935 
1936  loaddab(&ksgre.read.acq.echo[echoindx], dabslice, echoindx, dabop, dabview + 1,
1937  dynamic->prescan ? psc_acqflag : acqflag,
1938  PSD_LOAD_DAB_ALL); /* see epicfuns.h for alternatives to loaddab() */
1939  }
1940 
1944 
1945  ks_plot_slicetime(&ksgre.seqctrl, 1, &tloc, opslthick, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
1946 
1947  return slicetime;
1948 
1949 } /* ksgre_scan_coreslice() */
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:306
int R
Definition: KSFoundation.h:1723
WF_PULSE * echo
Definition: KSFoundation.h:846
int res
Definition: KSFoundation.h:1721
int nacslines
Definition: KSFoundation.h:1724
#define KS_NOTSET
Definition: KSFoundation.h:115
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
int momentstart
Definition: KSFoundation.h:1228
Duration and RF center (for excitation or inversion as applicable) of a coreslice/irslice function (h...
Definition: ksscan.h:72
s16 ky
Definition: KSFoundation.h:1750
void ks_scan_rf_off(KS_RF *rf, int instanceno)
Sets the amplitude of one or all instances of an RF pulse (KS_RF) to zero
Definition: KSFoundation_tgt.c:597
int duration
Definition: ksscan.h:73
KS_BASE base
Definition: KSFoundation.h:839
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1749
KS_RF rf
Definition: KSFoundation.h:1454
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
Definition: KSFoundation.h:404
Definition: KSFoundation.h:403
KS_READTRAP read
Definition: ksgre_implementation.e:55
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
s16 kz
Definition: KSFoundation.h:1751
void ks_scan_update_slice_location(SCAN_INFO *new_loc, const SCAN_INFO orig_loc, const KS_MAT4x4 M_physical, const KS_MAT4x4 M_logical)
Updates a SCAN_INFO struct using physical and logical 4x4 transformation matrices
Definition: KSFoundation_common.c:4015
void ks_plot_slicetime(const KS_SEQ_CONTROL *ctrl, int nslices, float *slicepos_mm, float slthick_mm, KS_PLOT_EXCITATION_MODE exctype)
ADDTITLEHERE
Definition: KSFoundation_common.c:4276
int ngenerated
Definition: KSFoundation.h:496
KS_READ acq
Definition: KSFoundation.h:1549
float opslthick
STATUS ksgre_scan_seqstate(SCAN_INFO slice_info, KS_PHASEENCODING_SHOTCOORDS shot_coords)
Sets the current state of all ksgre sequence objects at every ksgre playout in scan
Definition: ksgre_implementation.e:1782
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59

◆ ksgre_scan_coreslicegroup()

KS_CORESLICETIME ksgre_scan_coreslicegroup ( const SCAN_INFO *  slice_pos,
KS_DYNAMIC_STATE *  dynamic 
)

Function to run for scan to execute one slice of the ksgre sequence module with optional sat module

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

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.

Parameters
[in]slice_posPointer to the SCAN_INFO struct corresponding to the current slice to be played out
dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Returns
coreslicetime KS_CORESLICETIME containing the time taken in [us] to play out one slice and the moment start of the slice
1977  {
1978  KS_CORESLICETIME coreslicetime = KS_INIT_CORESLICETIME;
1979  int premainseq_duration = 0;
1980 
1981  /* Sat */
1982  premainseq_duration += kssat_scan(slice_pos, dynamic, &kssat);
1983 
1984  /* Main */
1985  coreslicetime = ksgre_scan_coreslice(slice_pos, dynamic);
1986 
1987  coreslicetime.duration += premainseq_duration;
1988  coreslicetime.referencetimepoint += premainseq_duration;
1989 
1990  return coreslicetime;
1991 
1992 } /* ksgre_scan_coreslicegroup() */
int kssat_scan(const SCAN_INFO *slice_info, KS_DYNAMIC_STATE *dynamic, KSSAT_MODULE *sat)
Change the dynamic state for a saturation module
Definition: kssat.e:239
Duration and RF center (for excitation or inversion as applicable) of a coreslice/irslice function (h...
Definition: ksscan.h:72
int duration
Definition: ksscan.h:73
KSSAT_MODULE kssat
Definition: kssat.e:112
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77
KS_CORESLICETIME ksgre_scan_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksgre sequence module in real time during scanning
Definition: ksgre_implementation.e:1879

◆ ksgre_eval_ssitime()

int ksgre_eval_ssitime ( )

The SSI time for the sequence

Return values
intSSI time in [us]
1230  {
1231 
1232  /* SSI time CV:
1233  Empirical finding on how much SSI time we need to update.
1234  But, use a longer SSI time when we write out data to file in scan() */
1235  if (KS_3D_SELECTED && (oppseq == PSD_SSFP))
1236  ksgre_ssi_time = RUP_GRD(IMax(2, KSGRE_DEFAULT_SSI_TIME_SSFP, _ksgre_ssi_time.minval));
1237  else
1238  ksgre_ssi_time = RUP_GRD(IMax(2, KSGRE_DEFAULT_SSI_TIME, _ksgre_ssi_time.minval));
1239 
1240  /* Copy SSI CV to seqctrl field used by setssitime() */
1241  ksgre.seqctrl.ssi_time = RUP_GRD(ksgre_ssi_time);
1242 
1243  /* SSI time one-sequence-off workaround:
1244  We set the hardware ssitime in ks_scan_playsequence(), but it acts on the next sequence module, hence
1245  we aren't doing this correctly when using multiple sequence modules (as KSChemSat etc).
1246  One option would be to add a short dummy sequence ks_scan_playsequence(), but need to investigate
1247  if there is a better way. For now, let's assume the the necessary update time is the longest for
1248  the main sequence (this function), and let the ssi time for all other sequence modules (KSChemSat etc)
1249  have the same ssi time as the main sequence. */
1251  /* TODO: for when we add inversion */
1252  /*
1253  ksinv_ssi_time = ksgre_ssi_time;
1254  ksinv_filltr_ssi_time = ksgre_ssi_time;
1255  */
1256  return ksgre_ssi_time;
1257 
1258 } /* ksgre_eval_ssitime() */
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
#define KSGRE_DEFAULT_SSI_TIME
Definition: ksgre_implementation.e:42
#define KSGRE_DEFAULT_SSI_TIME_SSFP
Definition: ksgre_implementation.e:43
int ssi_time
Definition: KSFoundation.h:1226
int ksgre_ssi_time
Definition: ksgre_implementation.e:110
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
int kssat_ssi_time
Definition: kssat.e:118

◆ ksgre_scan_seqstate()

STATUS ksgre_scan_seqstate ( SCAN_INFO  slice_pos,
KS_PHASEENCODING_SHOTCOORDS  shot_coords 
)

Sets the current state of all ksgre sequence objects at every ksgre playout in scan

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.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the ks_scan_info[] array)
[in]shot_coordsKS_PHASEENCODING_SHOTCOORDS with list of phase encoding indices for current shot
Return values
STATUSSUCCESS or FAILURE
1782  {
1783 
1785 
1786  ks_scan_rotate(slice_pos);
1787 
1788  /* RF frequency & phase */
1789  const float rfphase = ksgre_scan_phase(spgr_phase_counter++);
1790  if (ksgre.fiesta_firstplayout == TRUE) {
1791  /* half FA for the 1st RF played for current acquistion (= slice, since sequential mode) */
1792  ks_scan_rf_ampscale(&ksgre.selrfexc.rf, INSTRALL, 0.5);
1793  ksgre.fiesta_firstplayout = FALSE;
1794  } else {
1795  ks_scan_rf_on(&ksgre.selrfexc.rf, INSTRALL);
1796  }
1797  ks_scan_selrf_setfreqphase(&ksgre.selrfexc, 0 /* instance */, slice_pos, rfphase);
1798 
1799  /* ky, kz coordinate to play (for 2D: coord.kz = KS_NOTSET), same coord for all echoes */
1800  const KS_PHASEENCODING_COORD coord = shot_coords.entries == NULL ?
1801  fake_coord : shot_coords.entries[0];
1802 
1803  /* FOV offsets (by changing freq/phase of ksgre.read) */
1804  float ky_centred;
1805  if (coord.ky < 0) {
1806  ky_centred = 0.0f;
1807  } else {
1808  ky_centred = (float)coord.ky - (float)(ksgre.phaseenc.res - 1) / 2.0f;
1809  }
1810 
1811  if (KS_3D_SELECTED) {
1812  float zfovratio = (opslquant * opslthick) / opfov;
1813  float zchop_phase = 0.0;
1814  if (oparc && (coord.kz % 2)) {
1815  /* GEs ARC recon ignores RHF_ZCHOP bit in 'rhformat', but expects 3D data to be z-chopped for proper slice sorting.
1816  In GERequired.e:GEReq_predownload_setrecon_voldata(), RHF_ZCHOP is unset by default. In combination with
1817  that we do not do zchop for non-ARC scans (incl ASSET), this works well. But for ARC scans, we must zchop. That is,
1818  we add 180 phase to every odd kz encoded line, which is the same as a final z fftshift in the image domain */
1819  zchop_phase = 180.0;
1820  }
1821  float kz_centred;
1822  if (coord.kz < 0) {
1823  kz_centred = 0.0f;
1824  } else {
1825  kz_centred = (float)coord.kz - (float)(ksgre.zphaseenc.res - 1) / 2.0f;
1826  }
1827  ks_scan_offsetfov3D(&ksgre.read, INSTRALL, slice_pos, ky_centred, opphasefov, kz_centred, zfovratio, rfphase + zchop_phase);
1828  } else {
1829  ks_scan_offsetfov(&ksgre.read, INSTRALL, slice_pos, ky_centred, opphasefov, rfphase);
1830  }
1831 
1832  /* phase enc amps */
1833  ks_scan_phaser_toline(&ksgre.phaseenc, 0, coord.ky); /* dephaser. instance #0 of phaseenc */
1834  ks_scan_phaser_fromline(&ksgre.phaseenc, 1, coord.ky); /* rephaser. instance #1 of phaseenc */
1835 
1836  /* z phase enc amp */
1837  if (ksgre.zphaseenc.grad.duration > 0) { /* PSD_3D or PSD_3DM */
1838  /* dephaser (incl. slice rephaser in .areaoffset). instance #0 */
1840 
1841  if (ksgre.zphaseenc.grad.base.ngenerated == 2) {
1842  /* rephaser (incl. slice prephaser in .areaoffset for next excitation). instance #1 */
1844  }
1845  }
1846 
1847  return SUCCESS;
1848 
1849 } /* ksgre_scan_seqstate() */
void ks_scan_rf_on(KS_RF *rf, int instanceno)
Resets the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:566
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:306
int res
Definition: KSFoundation.h:1721
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_BASE base
Definition: KSFoundation.h:667
const KS_PHASEENCODING_COORD * entries
Definition: KSFoundation.h:1775
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
s16 ky
Definition: KSFoundation.h:1750
void ks_scan_offsetfov3D(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float kyview, float phasefovratio, float kzview, float zphasefovratio, float rcvphase)
Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift...
Definition: KSFoundation_tgt.c:1134
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1749
void ks_scan_selrf_setfreqphase(KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)...
Definition: KSFoundation_tgt.c:683
KS_RF rf
Definition: KSFoundation.h:1454
float opfov
KS_READTRAP read
Definition: ksgre_implementation.e:55
void ks_scan_phaser_toline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from the k-space center to a desired k-s...
Definition: KSFoundation_tgt.c:460
int fiesta_firstplayout
Definition: ksgre_implementation.e:64
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
void ks_scan_rotate(SCAN_INFO slice_pos)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:1179
float ksgre_scan_phase(int counter)
Returns a new RF phase based on an input counter and one of three GRE modes
Definition: ksgre_implementation.e:1746
void ks_scan_rf_ampscale(KS_RF *rf, int instanceno, float ampscale)
Changes the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:506
void ks_scan_offsetfov(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float view, float phasefovratio, float rcvphase)
Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift...
Definition: KSFoundation_tgt.c:1126
s16 kz
Definition: KSFoundation.h:1751
int spgr_phase_counter
Definition: ksgre_implementation.e:2027
int ngenerated
Definition: KSFoundation.h:496
int duration
Definition: KSFoundation.h:673
float opslthick
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
void ks_scan_phaser_fromline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from a k-space line to the k-space cente...
Definition: KSFoundation_tgt.c:472

◆ ksgre_get_loop_ctrl()

const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl ( )
1503  {
1504  return &ksgre_loopctrl;
1505 
1506 } /* ksgre_get_loop_ctrl() */
KSSCAN_LOOP_CONTROL ksgre_loopctrl
Definition: ksgre_implementation.e:134

◆ ksgre_init_imagingoptions()

void ksgre_init_imagingoptions ( void  )

Initial handling of imaging options buttons and top-level CVs at the PSD type-in page

Returns
void
219  {
220  int numopts = sizeof(sequence_iopts) / sizeof(int);
221 
222  psd_init_iopt_activity();
223  activate_iopt_list(numopts, sequence_iopts);
224  enable_iopt_list(numopts, sequence_iopts);
225 
226  /* Imaging option control functions (using PSD_IOPT_ZIP_512 as example):
227  - Make an option unchecked and not selectable: disable_ioption(PSD_IOPT_ZIP_512)
228  - Make an option checked and not selectable: set_required_disabled_option(PSD_IOPT_ZIP_512)
229  - Remove the imaging option: deactivate_ioption(PSD_IOPT_ZIP_512)
230  */
231 
232  cvset(opptsize, 2, 4, 4, ""); /* EDR */
233  set_required_disabled_option(PSD_IOPT_EDR); /* always use EDR, don't change */
234 
235  cvmax(opimode, PSD_3DM);
236 
237  if (oppseq == PSD_SSFP) {
238  /* Sequential forced on SSFP to keep TR minimal, i.e. one slice at a time */
239  set_required_disabled_option(PSD_IOPT_SEQUENTIAL);
240  set_disallowed_option(PSD_IOPT_CARD_GATE);
241  }
242 
243  /* This is likely good for PSD_3DM scans:
244  if (KS_3D_MULTISLAB_SELECTED) {
245  set_required_disabled_option(PSD_IOPT_SEQUENTIAL);
246  }
247  */
248 
249 #ifdef SIM
250  oppseq = PSD_GE;
251  setexist(oppseq, PSD_ON);
252  opirmode = PSD_OFF; /* default interleaved slices */
253  setexist(opirmode, PSD_ON);
254 #endif
255 
256 } /* ksgre_init_imagingoptions() */
int sequence_iopts[]
Definition: ksgre_implementation.e:193
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380

◆ ksgre_init_UI()

STATUS ksgre_init_UI ( void  )

Initial setup of user interface (UI) with default values for menus and fields

Return values
STATUSSUCCESS or FAILURE
266  {
267 
268  /* Gradient Echo Type of sequence */
269  acq_type = TYPGRAD; /* loadrheader.e rheaderinit: sets eeff = 1 */
270 
271  /* rampsampling on by default for SSFP scans to reduce TE & TR */
272  ksgre_rampsampling = (oppseq == PSD_SSFP) ? TRUE : FALSE;
273 
274  /* rBW */
275  if (oppseq == PSD_SSFP /* = 4 */) {
276  cvdef(oprbw, 125.0);
277  pircbval2 = 31.25;
278  pircbval3 = 41.67;
279  pircbval4 = 50.0;
280  pircbval5 = 62.50;
281  pircbval6 = 125.0;
282  } else {
283  cvdef(oprbw, 31.25);
284  pircbval2 = 13.89;
285  pircbval3 = 31.25;
286  pircbval4 = 41.67;
287  pircbval5 = 50.0;
288  pircbval6 = 62.50;
289  }
290  oprbw = _oprbw.defval;
291  cvmax(oprbw, 250);
292  pidefrbw = _oprbw.defval;
293  pircbnub = 31; /* number of variable bandwidth */
294  pircb2nub = 0; /* no second bandwidth option */
295 
296  /* NEX */
297  cvdef(opnex, 1);
298  opnex = _opnex.defval;
299  cvmin(opnex, 0.55);
300  pinexnub = 63;
301  pinexval2 = 0.55;
302  pinexval3 = 0.65;
303  pinexval4 = 0.75;
304  pinexval5 = 1;
305  pinexval6 = 2;
306 
307  /* FOV */
308  opfov = 240;
309  pifovnub = 5;
310  pifovval2 = 200;
311  pifovval3 = 220;
312  pifovval4 = 240;
313  pifovval5 = 260;
314  pifovval6 = 280;
315 
316  /* phase FOV fraction */
317  opphasefov = 1;
318  piphasfovnub2 = 63;
319  piphasfovval2 = 1.0;
320  piphasfovval3 = 0.9;
321  piphasfovval4 = 0.8;
322  piphasfovval5 = 0.7;
323  piphasfovval6 = 0.6;
324 
325  /* freq (x) resolution */
326  cvmin(opxres, 16);
327  cvdef(opxres, 128);
328  opxres = 128;
329  pixresnub = 63;
330  pixresval2 = 64;
331  pixresval3 = 128;
332  pixresval4 = 192;
333  pixresval5 = 256;
334  pixresval6 = 320;
335 
336  /* phase (y) resolution */
337  cvmin(opyres, 16);
338  cvdef(opyres, 128);
339  opyres = _opyres.defval;
340  piyresnub = 63;
341  piyresval2 = 64;
342  piyresval3 = 128;
343  piyresval4 = 192;
344  piyresval5 = 256;
345  piyresval6 = 320;
346 
347  /* Num echoes */
348  piechnub = 63;
349  cvdef(opnecho, 1);
350  cvmax(opnecho, 16);
351  opnecho = _opnecho.defval;
352  piechdefval = _opnecho.defval;
353  piechval2 = 1;
354  piechval3 = 2;
355  piechval4 = 4;
356  piechval5 = 8;
357  piechval6 = 16;
358 
359  /* TE */
360  avmaxte = 1s;
361  avminte = 0;
362  pitetype = PSD_LABEL_TE_NORM; /* alt. PSD_LABEL_TE_EFF */
363  cvdef(opte, 20ms);
364  opte = _opte.defval;
365  if (oppseq == PSD_SSFP) {
366  pite1nub = 4;
367  opautote = PSD_MINTEFULL;
368  } else {
369  pite1nub = 63;
370  }
371  pite1val2 = PSD_MINIMUMTE; /* opautote: PSD_MINTE = 2 */
372  pite1val3 = PSD_MINFULLTE; /* opautote: PSD_MINTEFULL = 1 */
373  pite1val4 = PSD_FWINPHASETE; /* opautote: PSD_FWINPHS = 3 */
374  pite1val5 = PSD_FWOUTPHASETE; /* opautote: PSD_FWOUTPHS = 4 */
375  if (cffield == 30000)
376  pite1val6 = 18ms; /* for T2*-w */
377  else
378  pite1val6 = 35ms; /* for T2*-w */
379 
380  /* TE2 */
381  pite2nub = 0;
382 
383  /* TR */
384  if (oppseq == PSD_SSFP || opfast == TRUE) {
385  pitrnub = 0; /* '0': shown but greyed out (but only if opautotr = 1, otherwise TR menu is hidden) */
386  cvoverride(opautotr, PSD_ON, PSD_FIX_OFF, PSD_EXIST_ON);
387  } else {
388  pitrnub = 6; /* '2': only one menu choice (Minimum = AutoTR) */
389  }
390  cvdef(optr, 100ms);
391  optr = _optr.defval;
392  pitrval2 = PSD_MINIMUMTR;
393  pitrval3 = 25ms;
394  pitrval4 = 35ms;
395  pitrval5 = 45ms;
396  pitrval6 = 100ms;
397 
398 
399  /* FA */
400  cvdef(opflip, 10);
401  opflip = _opflip.defval;
402 #if EPIC_RELEASE >= 24
403  pifamode = PSD_FLIP_ANGLE_MODE_EXCITE;
404 #endif
405  pifanub = 6;
406  if (KS_3D_SELECTED && (oppseq != PSD_SSFP)) {
407  pifaval2 = 10;
408  pifaval3 = 12;
409  pifaval4 = 15;
410  pifaval5 = 18;
411  pifaval6 = 20;
412  } else {
413  pifaval2 = 10;
414  pifaval3 = 20;
415  pifaval4 = 30;
416  if (oppseq == PSD_SSFP) {
417  pifaval5 = 40;
418  pifaval6 = 50;
419  } else {
420  pifaval5 = 60;
421  pifaval6 = 90;
422  }
423  }
424 
425  /* slice thickness */
426  pistnub = 5;
427  if (KS_3D_SELECTED) {
428  cvdef(opslthick, 1);
429  pistval2 = 0.8;
430  pistval3 = 0.9;
431  pistval4 = 1;
432  pistval5 = 1.5;
433  pistval6 = 2;
434  } else {
435  cvdef(opslthick, 4);
436  pistval2 = 2;
437  pistval3 = 3;
438  pistval4 = 4;
439  pistval5 = 5;
440  pistval6 = 10;
441  }
442  opslthick = _opslthick.defval;
443 
444  /* slice spacing */
445  cvdef(opslspace, 0);
446  opslspace = _opslspace.defval;
447  piisil = PSD_ON;
448  if (KS_3D_SELECTED) {
449  /* change these to do overlaps */
450  piisnub = 0;
451  piisval2 = 0;
452  } else {
453  piisnub = 4;
454  piisval2 = 0;
455  piisval3 = 0.5;
456  piisval4 = 1;
457  piisval5 = 4;
458  piisval6 = 20;
459  }
460 
461  /* default # of slices */
462  cvdef(opslquant, 30);
463 
464  /* 3D slice settings */
465  if (KS_3D_SELECTED) { /* PSD_3D (=2) or PSD_3DM (=6) */
466  pimultislab = 0; /* 0: forces only single slab, 1: allow multi-slab */
467  pilocnub = 4;
468  pilocval2 = 32;
469  pilocval3 = 64;
470  pilocval4 = 128;
471  /* opslquant = #slices in slab. opvquant = #slabs */
472  cvdef(opslquant, 32);
473  }
474 
475  opslquant = _opslquant.defval;
476 
477  /* Multi phase (i.e. multi volumes) */
478  if (opmph) {
479  pimphscrn = 1; /* display Multi-Phase Parameter screen */
480  pifphasenub = 6;
481  pifphaseval2 = 1;
482  pifphaseval3 = 2;
483  pifphaseval4 = 5;
484  pifphaseval5 = 10;
485  pifphaseval6 = 15;
486  pisldelnub = 0;
487  piacqnub = 0;
488  opacqo = 0;
489  setexist(opacqo, 1);
490  pihrepnub = 0; /* no XRR gating */
491  } else {
492  cvoverride(opfphases, 1, PSD_FIX_ON, PSD_EXIST_ON);
493  }
494 
495  /* opuser0: Recon number*/
496  cvmod(opuser0, 0, 9999, 0, "Recon number", 0, " ");
497  opuser0 = _opuser16.defval;
498  piuset |= use0;
499 
500 #ifdef REV
501  /* show GIT revision using REV variable from the Imakefile */
502  char userstr[100];
503  sprintf(userstr," Recon number [PSD's version: %s]", REV);
504  cvdesc(opuser0, userstr);
505 #endif
506 
507 
508  /* For 3D non-SSFP non-Sinc scans, let the user choose between fast scans and high FA */
509  cvmod(opuser1, _ksgre_rfexc_choice.minval, _ksgre_rfexc_choice.maxval, _ksgre_rfexc_choice.defval, _ksgre_rfexc_choice.descr, 0, " ");
510  opuser1 = _ksgre_rfexc_choice.defval;
511  ksgre_rfexc_choice = _ksgre_rfexc_choice.defval;
512  if (KS_3D_SELECTED && oppseq != PSD_SSFP && ksgre_sincrf == FALSE) /* PSD_3D or PSD_3DM */
513  piuset |= use1;
514  else
515  piuset &= ~use1;
516 
517  /* For 3D, choose between rectangular and elliptic k-space sampling (ky-kz plane) */
518  cvmod(opuser2, _ksgre_ellipsekspace.minval, _ksgre_ellipsekspace.maxval, _ksgre_ellipsekspace.defval, _ksgre_ellipsekspace.descr, 0, " ");
519  opuser2 = _ksgre_ellipsekspace.defval;
520  ksgre_ellipsekspace = _ksgre_ellipsekspace.defval;
521  if (KS_3D_SELECTED) /* PSD_3D or PSD_3DM */
522  piuset |= use2;
523  else
524  piuset &= ~use2;
525 
526  /*
527  Reserved opusers:
528  -----------------
529  GE reserves: opuser36-48 (epic.h)
530  */
531 
532  if (oparc) {
533  /* Acceleration menu as decimal numbers (max accel = 4) */
535  } else {
536  /* Acceleration menu as integers (max accel = 4)
537  Covers the non-accelerated and ASSET cases */
539  }
540 
541  return SUCCESS;
542 
543 } /* ksgre_init_UI() */
int piuset
Definition: KSFoundation.h:2337
int opxres
int opyres
int ksgre_sincrf
Definition: ksgre_implementation.e:88
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int ksgre_rfexc_choice
Definition: ksgre_implementation.e:91
Definition: KSFoundation.h:2337
float opfov
int ksgre_ellipsekspace
Definition: ksgre_implementation.e:115
STATUS GEReq_init_accelUI(int integeraccel, int maxaccel)
Sets up the menu for parallel imaging (ARC or ASSET) with max/min range
Definition: GERequired.e:468
int ksgre_rampsampling
Definition: ksgre_implementation.e:97
float opslthick
_cvint _optr

◆ ksgre_eval_UI()

STATUS ksgre_eval_UI ( )

Gets the current UI and checks for valid inputs

Return values
STATUSSUCCESS or FAILURE
562  {
563 
564  STATUS status;
565 
566  status = ksgre_init_UI();
567  KS_RAISE(status);
568 
569  if (opirprep) {
570  return KS_THROW("Inversion prep not implemented yet");
571  }
572 
573  ksgre_rfexc_choice = (int) opuser1;
574 
575  ksgre_ellipsekspace = (int) opuser2;
576 
577  rhrecon = (int) opuser16;
578 
579  /* Reserved opusers:
580  -----------------
581  ksgre_eval_inversion(): opuser26-29
582  GE reserves: opuser36-48 (epic.h)
583  */
584 
585  return SUCCESS;
586 
587 } /* ksgre_eval_UI() */
int ksgre_rfexc_choice
Definition: ksgre_implementation.e:91
int ksgre_ellipsekspace
Definition: ksgre_implementation.e:115
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksgre_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksgre_implementation.e:266
#define KS_THROW(format,...)
Definition: KSFoundation.h:181

◆ ksgre_eval_setupobjects()

STATUS ksgre_eval_setupobjects ( )

Sets up all sequence objects for the main sequence module (KSGRE_SEQUENCE ksgre)

Return values
STATUSSUCCESS or FAILURE
597  {
598  STATUS status;
599 
600  /* RF choices */
601  if (ksgre_sincrf) {
603  KS_RAISE(status);
605  } else {
606  if (oppseq == PSD_SSFP) {
607  if (KS_3D_SELECTED) {
608  ksgre.selrfexc.rf = ssfp_tbw3_01_001_pm_250; /* KSFoundation_GERF.h */
609  } else {
610  /* for now, use 4k BW sinc for 2D SSFP */
611  status = ks_eval_rf_sinc(&ksgre.selrfexc.rf, "", 4000, 2, opflip, KS_RF_SINCWIN_HAMMING);
612  KS_RAISE(status);
614  }
615  } else {
616  if (KS_3D_SELECTED) {
617  /* ksgre_rfexc_choice: Low values => shorter TE but lower max FA */
618  if (ksgre_rfexc_choice == 0)
619  ksgre.selrfexc.rf = exc_tbw8_01_001_150; /* KSFoundation_GERF.h */
620  else if (ksgre_rfexc_choice == 1)
621  ksgre.selrfexc.rf = exc_3d8min; /* KSFoundation_GERF.h */
622  else if (ksgre_rfexc_choice == 2)
623  ksgre.selrfexc.rf = exc_3d16min; /* KSFoundation_GERF.h */
624  else if (ksgre_rfexc_choice == 3)
625  ksgre.selrfexc.rf = excnonsel_fermi100; /* KSFoundation_GERF.h */
626  } else {
627  ksgre.selrfexc.rf = ssfp_tbw2_1_01; /* KSFoundation_GERF.h */
628  status = ks_eval_stretch_rf(&ksgre.selrfexc.rf, 4); /* stretch => reduce the BW to lower grad amp */
629  KS_RAISE(status);
630  }
631  }
632  }
633 
634  if (KS_3D_SELECTED) {
635  cvoverride(opvthick, exist(opslquant) * exist(opslthick), _opslquant.fixedflag, existcv(opslquant));
636  ksgre_excthickness = (exist(opslquant) - 2 * rhslblank) * exist(opslthick);
637  ksgre_gscalerfexc = 1.0;
638  } else {
640  }
641 
642  ksgre.selrfexc.rf.flip = opflip;
644 
645  /* selective RF excitation */
646  status = ks_eval_selrf1p(&ksgre.selrfexc, "rfexc");
647  KS_RAISE(status);
648 
649 
650  /* readout gradient and data acquisition */
651  ksgre.read.fov = opfov;
652  ksgre.read.res = RUP_FACTOR(opxres, 2); /* round up (RUP) to nearest multiple of 2 */
654  if (ksgre.read.rampsampling)
655  ksgre.read.acqdelay = 64; /* us on the ramp until acq should begin */
656  if (opautote == PSD_MINTE) { /* PSD_MINTE = 2 */
657  ksgre.read.nover = IMin(2,ksgre_kxnover,ksgre.read.res/2); /* Partial Fourier */
658  } else {
659  ksgre.read.nover = 0; /* Full Fourier */
660  }
661  ksgre.read.acq.rbw = oprbw;
662  status = ks_eval_readtrap(&ksgre.read, "read");
663  KS_RAISE(status);
664 
665  /* read dephaser */
667  status = ks_eval_trap(&ksgre.readdephaser, "readdephaser");
668  KS_RAISE(status);
669 
670  /* read rephaser (SSFP) */
671  if (oppseq == PSD_SSFP) {
673  status = ks_eval_trap(&ksgre.readrephaser_ssfp, "readrephaser_ssfp");
674  KS_RAISE(status);
675  } else {
677  }
678 
679  if (opfcomp == TRUE) {
680  /* X: Add second x dephaser */
682  status = ks_eval_trap(&ksgre.fcompread, "readdephaser1");
683  KS_RAISE(status);
684 
685  /* X: Now, make normal readdephaser twice as large */
686  ksgre.readdephaser.area *= 2;
687  status = ks_eval_trap(&ksgre.readdephaser, "readdephaser2");
688  KS_RAISE(status);
689 
690  /* Z: Add second z rephaser to complete 0th and 1st moment nulling of slice selection */
692  status = ks_eval_trap(&ksgre.fcompslice, "rfexc.reph2");
693  KS_RAISE(status);
694 
695  /* Z: Now, make normal z rephaser twice as large */
697  status = ks_eval_trap(&ksgre.selrfexc.postgrad, "rfexc.reph1");
698  KS_RAISE(status);
699 
700  } else {
703  }
704 
705  /* phase encoding gradient */
706  ksgre.phaseenc.fov = opfov * opphasefov;
707  ksgre.phaseenc.res = RUP_FACTOR((int) (opyres * opphasefov), 2); /* round up (RUP) to nearest multiple of 2 */
708  if (ksgre.read.nover == 0 && opnex < 1) {
709  int kynover;
710  kynover = ksgre.phaseenc.res * (opnex - 0.5);
711  kynover = ((kynover + 1) / 2) * 2; /* round to nearest even number */
712  if (kynover < KSGRE_MINHNOVER)
713  kynover = KSGRE_MINHNOVER; /* protect against too few overscans */
714  ksgre.phaseenc.nover = IMin(2, kynover, ksgre.phaseenc.res/2);
715  } else {
716  ksgre.phaseenc.nover = 0;
717  }
718 
719  /* set .R and .nacslines fields of ksgre.phaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
720  if (opasset) {
721  cvoverride(ksgre_minacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
722  } else if (oparc) {
723  ksgre_minacslines = _ksgre_minacslines.defval;
724  }
725  status = ks_eval_phaser_setaccel(&ksgre.phaseenc, ksgre_minacslines, opaccel_ph_stride);
726  KS_RAISE(status);
727 
728  status = ks_eval_phaser(&ksgre.phaseenc, "phaseenc");
729  KS_RAISE(status);
730 
731  /* z phase encoding gradient */
732  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
733 
734  if (opfcomp == TRUE) {
736  } else {
737  ksgre.selrfexc.postgrad.duration = 0; /* disable the slice rephaser gradient (.duration = 0), and put area necessary in zphaseenc.areaoffset */
738  ksgre.zphaseenc.areaoffset = ksgre.selrfexc.postgrad.area; /* copy the area info */
739  }
740  ksgre.zphaseenc.fov = opvthick;
741  ksgre.zphaseenc.res = IMax(2, 8, opslquant);
742  ksgre.zphaseenc.nover = 0;
743 
744  /* set .R and .nacslines fields of ksgre.zphaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
745  if (opasset) {
746  cvoverride(ksgre_minzacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
747  } else if (oparc) {
748  ksgre_minzacslines = _ksgre_minzacslines.defval;
749  }
750  status = ks_eval_phaser_setaccel(&ksgre.zphaseenc, ksgre_minzacslines, opaccel_sl_stride);
751  KS_RAISE(status);
752 
753  status = ks_eval_phaser(&ksgre.zphaseenc, "zphaseenc");
754  KS_RAISE(status);
755 
756  } else {
757 
759  }
760 
761  /* post-read spoiler */
762  ksgre.spoiler.area = (opnecho % 2 == 0) ? -1*ksgre_spoilerarea : ksgre_spoilerarea;
763  status = ks_eval_trap(&ksgre.spoiler, "spoiler");
764  KS_RAISE(status);
765 
766  /* init seqctrl */
768  strcpy(ksgre.seqctrl.description, "ksgremain");
770 
771  return SUCCESS;
772 
773 } /* ksgre_eval_setupobjects() */
STATUS ks_eval_selrf1p(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with physical gradient constraints (invariant to sli...
Definition: KSFoundation_host.c:3339
KS_TRAP fcompread
Definition: ksgre_implementation.e:62
#define KSGRE_MINHNOVER
Definition: ksgre_implementation.e:41
int res
Definition: KSFoundation.h:1721
int opxres
Definition: KSFoundation.h:2341
int opyres
STATUS ks_eval_phaser(KS_PHASER *phaser, const char *const desc) WARN_UNUSED_RESULT
Sets up an acquisition window with a trapezoid with preset gradient constraints
Definition: KSFoundation_host.c:1993
int role
Definition: KSFoundation.h:1027
int ksgre_minzacslines
Definition: ksgre_implementation.e:104
KS_TRAP fcompslice
Definition: ksgre_implementation.e:63
float fov
Definition: KSFoundation.h:1551
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
int ksgre_sincrf
Definition: ksgre_implementation.e:88
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int ksgre_rfexc_choice
Definition: ksgre_implementation.e:91
float areaoffset
Definition: KSFoundation.h:1726
float rbw
Definition: KSFoundation.h:842
float ksgre_excthickness
Definition: ksgre_implementation.e:84
KS_TRAP grad
Definition: KSFoundation.h:1561
DECL_TYPE KS_RF ssfp_tbw3_01_001_pm_250
Definition: KSFoundation_GERF.c:1177
Definition: KSFoundation.h:2340
float flip
Definition: KSFoundation.h:1028
DECL_TYPE KS_RF exc_3d8min
Definition: KSFoundation_GERF.c:735
DECL_TYPE KS_RF excnonsel_fermi100
Definition: KSFoundation_GERF.c:1325
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:57
int ksgre_kxnover
Definition: ksgre_implementation.e:96
STATUS ks_eval_phaser_setaccel(KS_PHASER *phaser, int min_acslines, float R) WARN_UNUSED_RESULT
Definition: KSFoundation_host.c:1911
float ksgre_spoilerarea
Definition: ksgre_implementation.e:87
void ks_init_seqcontrol(KS_SEQ_CONTROL *seqcontrol)
Resets KS_SEQ_CONTROL to its default value (KS_INIT_SEQ_CONTROL)
Definition: KSFoundation_host.c:148
KS_RF rf
Definition: KSFoundation.h:1454
void ks_init_trap(KS_TRAP *trap)
Resets a KS_TRAP sequence object to its default value (KS_INIT_TRAP)
Definition: KSFoundation_host.c:62
int res
Definition: KSFoundation.h:1552
float opfov
STATUS ks_eval_trap(KS_TRAP *trap, const char *const desc) WARN_UNUSED_RESULT
Sets up a trapezoid using a KS_TRAP sequence object with preset gradient constraints
Definition: KSFoundation_host.c:497
DECL_TYPE KS_RF ssfp_tbw2_1_01
Definition: KSFoundation_GERF.c:1031
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP readdephaser
Definition: ksgre_implementation.e:56
DECL_TYPE KS_RF exc_3d16min
Definition: KSFoundation_GERF.c:661
KS_TRAP spoiler
Definition: ksgre_implementation.e:60
float ksgre_gscalerfexc
Definition: ksgre_implementation.e:85
STATUS ks_eval_rf_sinc(KS_RF *rf, const char *const desc, double bw, double tbw, float flip, int wintype) WARN_UNUSED_RESULT
Sets up a KS_RF object with a Sinc pulse shape
Definition: KSFoundation_host.c:2176
KS_READTRAP read
Definition: ksgre_implementation.e:55
KS_TRAP postgrad
Definition: KSFoundation.h:1464
float ksgre_sincrf_tbw
Definition: ksgre_implementation.e:90
int nover
Definition: KSFoundation.h:1722
DECL_TYPE KS_RF exc_tbw8_01_001_150
Definition: KSFoundation_GERF.c:809
int ksgre_rampsampling
Definition: ksgre_implementation.e:97
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
STATUS ks_eval_readtrap(KS_READTRAP *readtrap, const char *const desc) WARN_UNUSED_RESULT
Sets up an acquisition window with a trapezoid with preset gradient constraints
Definition: KSFoundation_host.c:1230
float ksgre_sincrf_bw
Definition: ksgre_implementation.e:89
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
int nover
Definition: KSFoundation.h:1554
int rampsampling
Definition: KSFoundation.h:1553
KS_READ acq
Definition: KSFoundation.h:1549
int duration
Definition: KSFoundation.h:673
float opslthick
int ksgre_minacslines
Definition: ksgre_implementation.e:103
float area2center
Definition: KSFoundation.h:1559
float fov
Definition: KSFoundation.h:1720
STATUS ks_eval_stretch_rf(KS_RF *rf, float stretch_factor)
In-place stretching of a KS_RF object
Definition: KSFoundation_host.c:3928
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
int ksgre_eval_ssitime()
The SSI time for the sequence
Definition: ksgre_implementation.e:1230
int acqdelay
Definition: KSFoundation.h:1555
void ks_init_phaser(KS_PHASER *phaser)
Resets a KS_PHASER sequence object to its default value (KS_INIT_PHASER)
Definition: KSFoundation_host.c:118
float slthick
Definition: KSFoundation.h:1456

◆ ksgre_eval_TErange()

STATUS ksgre_eval_TErange ( )

Sets the min/max TE based on the durations of the sequence objects in KSGRE_SEQUENCE (ksgre)

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.

Return values
STATUSSUCCESS or FAILURE
789  {
790  float fieldscale = (float) B0_15000 / (float) cffield;
791  int fatwater_halflap = (fieldscale * 4.47ms) / 2; /* [us] */
792  int fatwater_numhalflaps;
793 
794  /* Minimum TE. Note that zphaseenc.grad.duration = 0 for 2D and ksgre.selrfexc.postgrad.duration = 0 for 3D */
795  avminte = ksgre.selrfexc.rf.iso2end;
796  if (ksgre_slicecheck) {
798  } else {
799  avminte += IMax(3, \
803  }
804  avminte += ksgre.read.time2center - ksgre.read.acqdelay; /* from start of acq win to k-space center */
805 
806  if (opautote == PSD_FWINPHS) {
807  /* fat-water in-phase */
808  avminte = CEIL_DIV(avminte, 2 * fatwater_halflap) * (2 * fatwater_halflap);
809  } else if (opautote == PSD_FWOUTPHS) {
810  /* fat-water out-of-phase */
811  fatwater_numhalflaps = CEIL_DIV(avminte, fatwater_halflap);
812  if ((fatwater_numhalflaps % 2) == 0)
813  fatwater_numhalflaps++; /* make sure it is odd */
814  avminte = fatwater_halflap * fatwater_numhalflaps;
815  }
816 
817  avminte += GRAD_UPDATE_TIME * 2; /* 8us extra margin */
818  avminte = RUP_FACTOR(avminte, 8); /* round up to make time divisible by 8us */
819 
820  /* bSSFP (FIESTA): TE = TR/2 */
821  if (oppseq == PSD_SSFP) {
822  int echocenter2momentstart;
823  echocenter2momentstart = ksgre.read.grad.duration - ksgre.read.time2center - ksgre.read.acqdelay; /* end of acqwin */
824 
825  echocenter2momentstart += IMax(3, \
828  KS_3D_SELECTED ? ksgre.zphaseenc.grad.duration : ksgre.selrfexc.postgrad.duration); /* end of spoiler/rephaser */
829 
830  echocenter2momentstart += ksgre.seqctrl.ssi_time; /* add SSI time. This is end of TR */
831  echocenter2momentstart += ksgre_pos_start + ksgre.selrfexc.grad.ramptime + ksgre.selrfexc.rf.start2iso; /* beginning of sequence to momentstart */
832  echocenter2momentstart = RUP_GRD(echocenter2momentstart);
833 
834  if (avminte <= echocenter2momentstart) {
835  avminte += echocenter2momentstart - avminte;
836  ksgre_ssfp_endtime = 0;
837  } else {
838  ksgre_ssfp_endtime = avminte - echocenter2momentstart;
839  }
840  }
841 
842  /* MaxTE. avmaxte = avminte if opautote != FALSE */
843  avmaxte = avminte;
844  if (opautote == FALSE) {
845  if (existcv(optr)) {
846  if (opautotr) {
847  /* TR = minTR, i.e. the current TE is also the maximum TE */
848  if (existcv(opte))
849  avmaxte = opte;
850  } else {
851  /* maximum TE dependent on the chosen TR */
852  avmaxte = optr - ksgre.seqctrl.ssi_time; /* maximum sequence duration for this TR (implies one slice per TR) */
853  avmaxte -= ksgre.spoiler.duration; /* subtract ksgre.spoiler time */
854  avmaxte -= (ksgre.read.grad.duration - ksgre.read.time2center); /* center of k-space to end of read decay ramp + extra gap */
855  if (opnecho > 1) {
856  avmaxte -= (opnecho - 1) * (ksgre.read.grad.duration + ksgre_extragap); /* for multi-echo */
857  }
858  }
859  } else {
860  avmaxte = 1s;
861  }
862  }
863 
864  if (opautote) {
865  setpopup(opte, PSD_OFF);
866  cvoverride(opte, avminte, PSD_FIX_ON, PSD_EXIST_ON); /* AutoTE: force TE to minimum */
867  } else {
868  setpopup(opte, PSD_ON);
869  if (opte < avminte)
870  opte = avminte;
871  }
872 
873  return SUCCESS;
874 
875 } /* ksgre_eval_TErange() */
KS_TRAP grad
Definition: KSFoundation.h:1463
KS_TRAP fcompread
Definition: ksgre_implementation.e:62
int start2iso
Definition: KSFoundation.h:1032
KS_TRAP grad
Definition: KSFoundation.h:1719
int ksgre_ssfp_endtime
Definition: ksgre_implementation.e:144
int ksgre_slicecheck
Definition: ksgre_implementation.e:86
KS_TRAP fcompslice
Definition: ksgre_implementation.e:63
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_TRAP grad
Definition: KSFoundation.h:1561
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:57
KS_RF rf
Definition: KSFoundation.h:1454
int ksgre_extragap
Definition: ksgre_implementation.e:98
KS_TRAP readdephaser
Definition: ksgre_implementation.e:56
KS_TRAP spoiler
Definition: ksgre_implementation.e:60
KS_READTRAP read
Definition: ksgre_implementation.e:55
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int iso2end
Definition: KSFoundation.h:1033
int ssi_time
Definition: KSFoundation.h:1226
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
int duration
Definition: KSFoundation.h:673
int ksgre_pos_start
Definition: ksgre_implementation.e:109
int time2center
Definition: KSFoundation.h:1560
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
int acqdelay
Definition: KSFoundation.h:1555
int ramptime
Definition: KSFoundation.h:671

◆ ksgre_set_kspace_design()

void ksgre_set_kspace_design ( KS_KSPACE_DESIGN kdesign)

Set the k-space design for use in ksgre_set_loop_control_design() and ksgre_eval_sat()

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

Parameters
[out]kdesignKS_KSPACE_DESIGN
Returns
void
896  {
897 
898  /* k-space design */
899  kdesign->fov[XGRAD] = opfov;
900  kdesign->fov[YGRAD] = opfov * opphasefov;
901  kdesign->res[XGRAD] = RUP_FACTOR(opxres, 2);
902  kdesign->res[YGRAD] = RUP_FACTOR((int) (opyres * opphasefov), 2);
903  kdesign->R[YGRAD] = (oparc || opasset) ? opaccel_ph_stride : 1;
904  kdesign->nacslines[YGRAD] = ksgre_minacslines;
905  kdesign->rbw = oprbw;
906  kdesign->override_R1 = 0; /* If non-zero, override the analog receive gain with this value */
907  if (opnex < 1) {
908  int kynover = kdesign->res[YGRAD] * (opnex - 0.5);
909  kynover += kynover % 2; /* round to nearest even number */
910  kdesign->nover[YGRAD] = IMax(2, kynover, KSGRE_MINHNOVER);
911  } else {
912  kdesign->nover[YGRAD] = 0;
913  }
914 
915  /* 3D */
916  kdesign->R[ZGRAD] = (oparc || opasset) ? opaccel_sl_stride : 1;
917  kdesign->nacslines[ZGRAD] = ksgre_minzacslines;
918  kdesign->nover[ZGRAD] = 0;
919  if (KS_3D_SELECTED) {
920  kdesign->fov[ZGRAD] = opvthick; /* + kissoff? */
921  kdesign->res[ZGRAD] = IMax(2, 8, opslquant);
922  } else {
923  kdesign->fov[ZGRAD] = KS_NOTSET;
924  kdesign->res[ZGRAD] = KS_NOTSET;
925  }
926 
927  /* rampsampling on for ART (opsilent) */
928  kdesign->rampsampling = (opsilent) ? TRUE : FALSE;
929 
930 } /* ksgre_set_kspace_design() */
int nacslines[3]
Definition: ksdesign.h:88
#define KSGRE_MINHNOVER
Definition: ksgre_implementation.e:41
int opxres
int R[3]
Definition: ksdesign.h:83
int opyres
int nover[3]
Definition: ksdesign.h:82
#define KS_NOTSET
Definition: KSFoundation.h:115
int ksgre_minzacslines
Definition: ksgre_implementation.e:104
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
float opfov
int override_R1
Definition: ksdesign.h:93
float rbw
Definition: ksdesign.h:91
int ksgre_minacslines
Definition: ksgre_implementation.e:103
int rampsampling
Definition: ksdesign.h:81
int res[3]
Definition: ksdesign.h:80
float fov[3]
Definition: ksdesign.h:79

◆ ksgre_set_slicetiming_design()

void ksgre_set_slicetiming_design ( KS_SLICETIMING_DESIGN slicetiming_design)

Set up the number of slices, TR range, and min num acquisitions in KS_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

Parameters
[out]slicetiming_designKS_SLICETIMING_DESIGN to be created
Returns
void
949  {
950 
951  /* interleaved slices in slice gap menu, force 2+ acqs */
952  int minacqs = (opileave) ? 2 : 1;
953 
954  if (opslspace < 0) { /* Because we use overlap (pi_neg_sp) */
955  minacqs = IMax(2, minacqs, ceil(opslthick / (opslthick - fabs(opslspace))));
956  }
957 
958  slicetiming_design->is3D = KS_3D_SELECTED;
959  slicetiming_design->nslices = opslquant;
960  ksscan_copy_slices(slicetiming_design, ks_scan_info);
961 
962  slicetiming_design->minacqs = minacqs;
963  if (opautotr) {
964  /* No limits */
965  slicetiming_design->minTR = 0;
966  slicetiming_design->maxTR = 0;
967  } else {
968  slicetiming_design->minTR = optr;
969  slicetiming_design->maxTR = optr;
970  }
971 
972 } /* ksgre_set_slicetiming_design() */
void ksscan_copy_slices(KS_SLICETIMING_DESIGN *slicetiming_design, const SCAN_INFO *scan_info)
Copying of the graphical slice prescription in the UI (scan_info[]) and opslquant to the KS_SLICETIMI...
Definition: ksscan.cc:372
int minacqs
Definition: ksscan.h:26
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int maxTR
Definition: ksscan.h:29
int nslices
Definition: ksscan.h:23
int is3D
Definition: ksscan.h:24
float opslthick
int minTR
Definition: ksscan.h:28
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:240

◆ ksgre_set_loop_control_design()

STATUS ksgre_set_loop_control_design ( KSSCAN_LOOP_CONTROL_DESIGN loop_design)

Setup of a KSSCAN_LOOP_CONTROL_DESIGN with desired k-space coordinates, averages, volumes, etc.

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

Parameters
[out]loop_designKSSCAN_LOOP_CONTROL_DESIGN to be created
Return values
STATUSSUCCESS or FAILURE
996  {
997 
998  /* number of dummy TRs to use to reach steady state */
999  if (oppseq == PSD_SSFP) {
1000  ksgre_dda = 20; /* since single-slice, it's quick anyway */
1001  } else {
1002  ksgre_dda = 4;
1003  }
1004 
1005  loop_design->dda = ksgre_dda;
1006  loop_design->naverages = ceil(opnex);
1007  loop_design->nvols = opfphases;
1008 
1009  /* Generate the k-space coordinate list */
1011  ksgre_set_kspace_design(&kdesign);
1012  STATUS s = ks_generate_3d_coords_simple(&kacq,
1013  kdesign.res[YGRAD], kdesign.res[ZGRAD],
1014  kdesign.nover[YGRAD], kdesign.nover[ZGRAD],
1015  kdesign.R[YGRAD], kdesign.R[ZGRAD],
1016  ks_cal_from_nacslines(kdesign.R[YGRAD], kdesign.nacslines[YGRAD]),
1017  ks_cal_from_nacslines(kdesign.R[ZGRAD], kdesign.nacslines[ZGRAD]),
1018  RECTANGULAR, /* calibration shape */
1019  ksgre_ellipsekspace ? ELLIPTICAL : RECTANGULAR /* kspace coverage */);
1020  KS_RAISE(s);
1021 
1022  /* Phase encoding */
1023  loop_design->phaseenc_design.encodes_per_shot = 1;
1024  loop_design->phaseenc_design.center_encode = 0;
1025  loop_design->phaseenc_design.kacq = kacq;
1026 
1028 
1029  return SUCCESS;
1030 
1031 } /* ksgre_set_loop_control_design() */
int encodes_per_shot
Definition: ksscan.h:140
int nacslines[3]
Definition: ksdesign.h:88
KS_KSPACE_ACQ kacq
Definition: ksscan.h:138
STATUS ks_generate_3d_coords_simple(KS_KSPACE_ACQ *kacq, int Ny, int Nz, int nover_y, int nover_z, int Ry, int Rz, int cal_y, int cal_z, KS_COVERAGE cal_coverage, KS_COVERAGE acq_coverage) WARN_UNUSED_RESULT
Generates Cartesian Coordinates.
Definition: KSFoundation_host.c:9972
int R[3]
Definition: ksdesign.h:83
int nover[3]
Definition: ksdesign.h:82
int naverages
Definition: ksscan.h:204
int ksgre_dda
Definition: ksgre_implementation.e:111
KS_PHASEENCODING_PLAN_DESIGN phaseenc_design
Definition: ksscan.h:207
int dda
Definition: ksscan.h:202
int nvols
Definition: ksscan.h:203
void ksgre_set_kspace_design(KS_KSPACE_DESIGN *kdesign)
Set the k-space design for use in ksgre_set_loop_control_design() and ksgre_eval_sat()
Definition: ksgre_implementation.e:896
#define KS_INIT_KSPACE_2D_DESIGN
Definition: ksdesign.h:99
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
int ksgre_ellipsekspace
Definition: ksgre_implementation.e:115
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Definition: KSFoundation.h:2094
Input design for how to set up data acquistion (FOV, matrix size, parallel imaging, rBW etc)This struct is used by e.g. ks_eval_design_readtrap(), ksepi_eval_kdesign2epitrain(), ksfse_eval_numlines2acq() and is a part of all sequence generator&#39;s design structs (KSEPI_MODULE->KSEPI_DESIGN, KSFSE_MODULE->KSFSE_DESIGN, KSGRE_MODULE->KSGRE_DESIGN)
Definition: ksdesign.h:76
int ks_cal_from_nacslines(int R, int nacslines)
ADDTITLEHERE
Definition: KSFoundation_host.c:9784
Definition: KSFoundation.h:2095
int center_encode
Definition: ksscan.h:141
void ksgre_set_slicetiming_design(KS_SLICETIMING_DESIGN *slicetiming_design)
Set up the number of slices, TR range, and min num acquisitions in KS_SLICETIMING_DESIGN
Definition: ksgre_implementation.e:949
KS_KSPACE_ACQ kacq
Definition: ksgre_implementation.e:171
int res[3]
Definition: ksdesign.h:80

◆ ksgre_eval_inversion()

STATUS ksgre_eval_inversion ( KS_SEQ_COLLECTION seqcollection)

Setup and evaluation of KSINV_DESIGN and the creation of a KSINV_MODULE module for inversion recovery

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.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1050  {
1051 
1052  STATUS status;
1053 
1054  KSINV_DESIGN inv_design = KSINV_INIT_DESIGN;
1055 
1056  ksinv_init_design(&inv_design, "inv"); /* e.g. STIR */
1057 
1058  inv_design.invdesign.slthick = KS_3D_SELECTED ? 0 /*non selective*/ : opslthick;
1059  inv_design.invdesign.flip = 180.0;
1060  inv_design.invdesign.rfpulse_choice = INV_ADIABATIC; /* TODO */
1061  inv_design.spoiler_area = ksgre_spoilerarea;
1062  inv_design.gscale_policy = KSINV_GSCALE_NONOVERLAP; /* TODO */
1063  inv_design.slice_gap = opslspace;
1064  inv_design.ssi_time = ksgre_ssi_time;
1065 
1066  const int minacqs = (opileave) ? 2 : 1;
1067  status = ksinv_eval_design(&ksgre_inv, &inv_design, minacqs, seqcollection);
1068  KS_RAISE(status);
1069 
1070  return SUCCESS;
1071 
1072 } /* ksgre_eval_inversion() */
void ksinv_init_design(KSINV_DESIGN *design, const char *desc)
Resets the design of the standard inversion module
Definition: ksinversion.cc:31
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
Definition: ksdesign.h:31
float spoiler_area
Definition: ksinversion.h:61
float flip
Definition: ksdesign.h:51
float ksgre_spoilerarea
Definition: ksgre_implementation.e:87
int ssi_time
Definition: ksinversion.h:64
int rfpulse_choice
Definition: ksdesign.h:58
#define KSINV_INIT_DESIGN
Definition: ksinversion.h:67
Definition: ksinversion.h:29
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Design for the standard inversion module
Definition: ksinversion.h:56
int slice_gap
Definition: ksinversion.h:59
int ksgre_ssi_time
Definition: ksgre_implementation.e:110
STATUS ksinv_eval_design(KSINV_MODULE *invseq, KSINV_DESIGN *invseq_design, int npasses, KS_SEQ_COLLECTION *seqcollection)
Standard setup function for KSINV_MODULE to be executed on HOST (cveval()) by the parent sequence (*...
Definition: ksinversion.cc:154
KS_SELRF_DESIGN invdesign
Definition: ksinversion.h:58
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
KSINV_MODULE ksgre_inv
Definition: ksgre_implementation.e:137
float opslthick
KSINV_GSCALE_POLICY gscale_policy
Definition: ksinversion.h:60
float slthick
Definition: ksdesign.h:50

◆ ksgre_eval_sat()

STATUS ksgre_eval_sat ( KS_SEQ_COLLECTION seqcollection)

Set up of the KSSAT_MODULE kssat for graphical saturation in the UI

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()

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1093  {
1094 
1095  STATUS status;
1096 
1098  ksgre_set_kspace_design(&kdesign);
1099 
1101  ksgre_set_slicetiming_design(&slicetiming_design);
1102 
1103  status = kssat_setup_from_UI(&kssat,
1104  &kdesign,
1105  &slicetiming_design,
1106  opslthick,
1107  seqcollection);
1108  KS_RAISE(status);
1109 
1110  return SUCCESS;
1111 
1112 } /* ksgre_eval_sat() */
STATUS kssat_setup_from_UI(KSSAT_MODULE *sat, KS_KSPACE_DESIGN *kspace_design, KS_SLICETIMING_DESIGN *slicetiming_design, float slthick, KS_SEQ_COLLECTION *seqcollection)
Setup the saturation module on the host from the scanner&#39;s UI
Definition: kssat.e:128
#define KS_INIT_SLICETIMING_DESIGN
Definition: ksscan.h:32
KSSAT_MODULE kssat
Definition: kssat.e:112
void ksgre_set_kspace_design(KS_KSPACE_DESIGN *kdesign)
Set the k-space design for use in ksgre_set_loop_control_design() and ksgre_eval_sat()
Definition: ksgre_implementation.e:896
#define KS_INIT_KSPACE_2D_DESIGN
Definition: ksdesign.h:99
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Input design for how to set up data acquistion (FOV, matrix size, parallel imaging, rBW etc)This struct is used by e.g. ks_eval_design_readtrap(), ksepi_eval_kdesign2epitrain(), ksfse_eval_numlines2acq() and is a part of all sequence generator&#39;s design structs (KSEPI_MODULE->KSEPI_DESIGN, KSFSE_MODULE->KSFSE_DESIGN, KSGRE_MODULE->KSGRE_DESIGN)
Definition: ksdesign.h:76
void ksgre_set_slicetiming_design(KS_SLICETIMING_DESIGN *slicetiming_design)
Set up the number of slices, TR range, and min num acquisitions in KS_SLICETIMING_DESIGN
Definition: ksgre_implementation.e:949
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
Struct for desired slice timing and slice location behavior. To be filled in by a parent sequence bef...
Definition: ksscan.h:21
float opslthick

◆ ksgre_gradheat_play()

STATUS ksgre_gradheat_play ( const INT  max_encode_mode,
int  nargs,
void **  args 
)

Play function of a test sequence used for gradient heating calculations

This function

  • plays a set of sequence modules that collectively makes a test sequence that attempts to be a good approximation of the average and maxmimum power dissipation of the gradient system. This function is not used for any data collection.
  • first plays the saturation sequence (if kssat.seqctrl.duration > 0), then the main sequence based on the max_encode_mode (AVERAGE_POWER or MAXIMUM_POWER)
  • is passed as an argument to ks_eval_getduration() to get the playout time and to ks_eval_hwlimits() to get the new minimum time due to hardware heating and SAR calculations.

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.

Parameters
[in]max_encode_modeThe 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)
Return values
STATUSSUCCESS or FAILURE
1146  {
1147  (void) nargs;
1148  (void) args;
1149 
1150  /* Sat */
1152 
1153  /* main */
1154  if (max_encode_mode == AVERAGE_POWER) {
1156  } else {
1157  ks_scan_phaser_max(&ksgre.phaseenc, INSTRALL);
1158  }
1159 
1161 
1162  return SUCCESS;
1163 
1164 } /* ksgre_gradheat_play() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
void ks_scan_phaser_max(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:497
KSSAT_MODULE kssat
Definition: kssat.e:112
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
void ks_scan_phaser_average(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:490

◆ ksgre_eval_loops()

STATUS ksgre_eval_loops ( KS_SEQ_COLLECTION seqcollection)

Setup of scan loop control struct after heating calculations

This function performs the following tasks:

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 this applies to the local variable loopctrl_design

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1186  {
1187  STATUS status;
1188 
1189  /* SAR and gradient heating */
1190  const int time = ks_eval_getduration(seqcollection, ksgre_gradheat_play, 0, NULL);
1191 
1192  int newtime = 0;
1193  status = ks_eval_hwlimits(&newtime, seqcollection, &loggrd, ksgre_gradheat_play, 0, NULL);
1194  KS_RAISE(status);
1195 
1196  if (newtime > time) {
1198  ks_dbg("hw limits active: %d -> %d", time, newtime);
1199  }
1200 
1201  /* Loop control evaluation */
1202 
1204  status = ksgre_set_loop_control_design(&loopctrl_design);
1205  KS_RAISE(status);
1206 
1208  &ksgre.seqctrl,
1210  &loopctrl_design);
1211  KS_RAISE(status);
1212 
1213  /* Fill in the 'tmin' and 'tmin_total'. tmin_total is only like GEs use of the variable when TR = minTR */
1214  tmin = ksgre.seqctrl.min_duration;
1215  tmin_total = ksgre.seqctrl.duration;
1216 
1217  return SUCCESS;
1218 
1219 } /* ksgre_eval_loops() */
Design parameters for generating a KSSCAN_LOOP_CONTROL
Definition: ksscan.h:201
int duration
Definition: KSFoundation.h:1227
STATUS ks_eval_hwlimits(int *newtime, KS_SEQ_COLLECTION *seqcollection, const LOG_GRAD *log_grad, STATUS(*play)(const INT max_encode_mode, int nargs, void **args), int nargs, void **args)
Definition: KSFoundation_host.c:5848
LOG_GRAD loggrd
int min_duration
Definition: KSFoundation.h:1224
STATUS ksscan_loop_control_eval_design(KSSCAN_LOOP_CONTROL *loop_control, KS_SEQ_CONTROL *sequence_to_inflate, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const KSSCAN_LOOP_CONTROL_DESIGN *design)
Generates a loop control
Definition: ksscan.cc:110
STATUS ks_eval_seqctrl_setduration(KS_SEQ_CONTROL *seqctrl, int dur)
Sets the .duration field of the sequence module (KS_SEQ_CONTROL), while checking that the input value...
Definition: KSFoundation_host.c:4952
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
STATUS ksgre_set_loop_control_design(KSSCAN_LOOP_CONTROL_DESIGN *loop_design)
Setup of a KSSCAN_LOOP_CONTROL_DESIGN with desired k-space coordinates, averages, volumes...
Definition: ksgre_implementation.e:996
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
KS_CORESLICETIME ksgre_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksgre sequence module with optional sat module...
Definition: ksgre_implementation.e:1977
STATUS STATUS ks_dbg(const char *format,...) __attribute__((format(printf
Common debug message function for HOST and TGT
STATUS ksgre_gradheat_play(const INT max_encode_mode, int nargs, void **args)
Play function of a test sequence used for gradient heating calculations
Definition: ksgre_implementation.e:1146
KSSCAN_LOOP_CONTROL ksgre_loopctrl
Definition: ksgre_implementation.e:134
s64 ks_eval_getduration(KS_SEQ_COLLECTION *seqcollection, STATUS(*play)(const INT max_encode_mode, int nargs, void **args), int nargs, void **args)
Definition: KSFoundation_host.c:5879
#define KSSCAN_INIT_LOOP_CONTROL_DESIGN
Definition: ksscan.h:211

◆ ksgre_eval_scantime()

STATUS ksgre_eval_scantime ( KS_SEQ_COLLECTION seqcollection)

Sets the scan time and SAR values in the UI and checks that the sequence is within hardware limits

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.

Return values
STATUSSUCCESS or FAILURE
1272  {
1273  STATUS status;
1274 
1275  /**** SAR Calcs: Check that we are within SAR/hardware limits ****/
1276 
1277  /* Step 1: set all `seqctrl.nseqinstances` to 0 */
1279 
1280  /* Step 2: run the scan loop to get total scan time */
1281  n64 scantime = ksgre_scan_scanloop();
1282 
1283  /* Step 3: Check that the entire sequence (across all sequence modules) is within SAR & hardware limits.
1284  Also sets up UI SAR annotation */
1285  status = GEReq_eval_checkTR_SAR_calcs(seqcollection, scantime);
1286  KS_RAISE(status);
1287 
1288  pitscan = (float) scantime; /* Scan time clock in UI */
1289 
1290  return SUCCESS;
1291 
1292 } /* ksgre_eval_scantime() */
s64 ksgre_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksgre_implementation.e:2005
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
void ks_eval_seqcollection_resetninst(KS_SEQ_COLLECTION *seqcollection)
Set the .nseqinstances field of each sequence module (KS_SEQ_CONTROL) equal to 0
Definition: KSFoundation_host.c:5929
STATUS GEReq_eval_checkTR_SAR_calcs(KS_SEQ_COLLECTION *seqcollection, s64 intended_time)
Checks that sequence modules sum up to TR, honoring SAR/heating limits
Definition: GERequired.e:902

◆ ksgre_update_UI()

STATUS ksgre_update_UI ( )

Returns error of various parameter combinations that are not allowed for ksgre

Return values
STATUSSUCCESS or FAILURE
1311  {
1312 
1313  /* Show resolution & BW per pixel in the UI */
1314  piinplaneres = 1;
1315  pirbwperpix = 1;
1316  ihinplanexres = ksgre.read.fov/ksgre.read.res;
1317  ihinplaneyres = ksgre.phaseenc.fov/ksgre.phaseenc.res;
1318  ihrbwperpix = (1000.0 * ksgre.read.acq.rbw * 2.0)/ksgre.read.res;
1319 
1320  const KSSCAN_LOOP_CONTROL *loopctrl = ksgre_get_loop_ctrl();
1321 
1322  _optr.minval = 0;
1323  _optr.maxval = 60s;
1324  if (opautotr) {
1325  avmintr = loopctrl->slicetiming.TR;
1326  avmaxtr = loopctrl->slicetiming.TR;
1327  } else {
1328  avmintr = _optr.minval;
1329  avmaxtr = _optr.maxval;
1330  }
1331  (optr) = loopctrl->slicetiming.TR; /* ()-parentheses avoids fixedflag expansion */
1332  act_tr = loopctrl->slicetiming.TR;
1333  ihtr = optr; /* image header TR */
1334 
1335  avmaxslquant = loopctrl->slicetiming.maxslices_per_TR;
1336  avmaxacqs = loopctrl->slicetiming.slice_plan.npasses;
1337 
1338  /* Force the user to select the Gradient Echo button. This error needs to be in cvcheck(), not in
1339  cvinit()/cveval() to avoid it to trigger also when Gradient Echo hass been selected */
1340  if (oppseq == PSD_SE || opepi == PSD_ON) {
1341  return ks_error("%s: Please first select the 'Gradient Echo' button", ks_psdname);
1342  }
1343 
1344  /* SSFP symmetric RF watchdog */
1345  if ((oppseq == PSD_SSFP) && (abs(ksgre.selrfexc.rf.rfwave.duration/2 - ksgre.selrfexc.rf.iso2end) > GRAD_UPDATE_TIME)) {
1346  return ks_error("ksgre_check: Symmetric RF pulses are required for SSFP scans");
1347  }
1348 
1349  /* SSFP duration watchdog (to assure TE = TR/2) */
1350  if (existcv(opte) && existcv(optr) && existcv(opflip) && (oppseq == PSD_SSFP) && (ksgre.seqctrl.duration > ksgre.seqctrl.min_duration)) {
1351  return ks_error("ksgre_check: SAR/heating penalty - reduce FA");
1352  }
1353 
1354  if (oparc && KS_3D_SELECTED && (ksgre.zphaseenc.R > ksgre.phaseenc.R)) {
1355  /* Unclear why, but zR > R leads to corrupted images for ARC and 3D.
1356  Probably a bug that can be fixed later. Limited experience (July 2018) */
1357  return ks_error("%s: Need Slice acceleration <= Phase accleration", __FUNCTION__);
1358  }
1359 
1360  return SUCCESS;
1361 
1362 } /* ksgre_update_UI() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float fov
Definition: KSFoundation.h:1551
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
float rbw
Definition: KSFoundation.h:842
int duration
Definition: KSFoundation.h:1227
char ks_psdname[256]
Definition: GERequired.e:245
int TR
Definition: ksscan.h:43
KS_RF rf
Definition: KSFoundation.h:1454
int res
Definition: KSFoundation.h:1552
int npasses
Definition: KSFoundation.h:1319
ifndef ACT_TR_EXISTS int act_tr
Definition: GERequired.e:235
const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl()
Definition: ksgre_implementation.e:1503
KS_WAVE rfwave
Definition: KSFoundation.h:1037
int min_duration
Definition: KSFoundation.h:1224
KS_READTRAP read
Definition: ksgre_implementation.e:55
int iso2end
Definition: KSFoundation.h:1033
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
KS_READ acq
Definition: KSFoundation.h:1549
int maxslices_per_TR
Definition: ksscan.h:44
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
_cvint _optr
float fov
Definition: KSFoundation.h:1720
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
int duration
Definition: KSFoundation.h:747

◆ ksgre_predownload_plot()

STATUS ksgre_predownload_plot ( KS_SEQ_COLLECTION seqcollection)

Plotting of sequence modules and slice timing in HTML files

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.

Return values
STATUSSUCCESS or FAILURE
1411  {
1412  char tmpstr[1000];
1413 
1414  /* System wide (psd independent) option to disable plotting, to e.g. speed up UX on a slow MR show system */
1415  if (existfile("/usr/g/research/bin/ksdonotplot")) {
1416  return SUCCESS;
1417  }
1418 
1419 #ifdef PSD_HW
1420  sprintf(tmpstr, "/usr/g/mrraw/%s_objects.txt", ks_psdname);
1421 #else
1422  sprintf(tmpstr, "./%s_objects.txt", ks_psdname);
1423 #endif
1424  FILE *fp = fopen(tmpstr, "w");
1425 
1426  /* Note: 'fp' can be replaced with 'stdout' or 'stderr' to get these
1427  values printed out in the WTools window in simulation. However,
1428  heavy printing may result in that the WTools window closes,
1429  why we here write to a file ksgre_objects.txt instead */
1437  fclose(fp);
1438 
1440 
1441  /* Main */
1444 
1445  /* Saturation */
1447 
1448  /* Sequence timing plot */
1452 
1453  return SUCCESS;
1454 
1455 } /* ksgre_predownload_plot() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
void ksscan_plotloop_shots(const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes a single-slice single-pass scan loop used for plotting all shots states
Definition: ksscan.cc:537
KS_SELRF selrfexc
Definition: ksgre_implementation.e:61
void ks_plot_host_seqctrl(const KS_SEQ_CONTROL *ctrl, const KS_PHASEENCODING_PLAN *plan)
ADDTITLEHERE
Definition: KSFoundation_host.c:7596
s64 ksgre_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksgre_implementation.e:2005
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:57
char ks_psdname[256]
Definition: GERequired.e:245
void ks_plot_slicetime_begin()
ADDTITLEHERE
Definition: KSFoundation_common.c:4266
const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl()
Definition: ksgre_implementation.e:1503
KSSAT_MODULE kssat
Definition: kssat.e:112
void ks_plot_slicetime_end()
ADDTITLEHERE
Definition: KSFoundation_common.c:4316
KS_TRAP readdephaser
Definition: ksgre_implementation.e:56
void ks_print_phaser(KS_PHASER phaser, FILE *fp)
Writes out the contents of a KS_PHASER sequence object for debugging
Definition: KSFoundation_host.c:6822
KS_TRAP spoiler
Definition: ksgre_implementation.e:60
KS_READTRAP read
Definition: ksgre_implementation.e:55
void ks_print_trap(KS_TRAP trap, FILE *fp)
Writes out the contents of a KS_TRAP sequence object for debugging
Definition: KSFoundation_host.c:6780
STATUS STATUS STATUS existfile(const char *fname)
ADDTITLEHERE
Definition: KSFoundation_common.c:203
KS_PHASER phaseenc
Definition: ksgre_implementation.e:58
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
void ks_plot_psd(const KS_SEQ_CONTROL *ctrl, const KSSCAN_LOOP_CONTROL *loopctrl)
Wrapper function for plotting a module/sequence entry
Definition: ksscan.cc:440
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
KS_CORESLICETIME ksgre_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksgre sequence module with optional sat module...
Definition: ksgre_implementation.e:1977
void ks_eval_seqcollection_resetninst(KS_SEQ_COLLECTION *seqcollection)
Set the .nseqinstances field of each sequence module (KS_SEQ_CONTROL) equal to 0
Definition: KSFoundation_host.c:5929
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:59
void ks_print_selrf(KS_SELRF selrf, FILE *fp)
Writes out the contents of a KS_SELRF sequence object for debugging
Definition: KSFoundation_host.c:6945
void ks_print_readtrap(KS_READTRAP readtrap, FILE *fp)
Writes out the contents of a KS_READTRAP sequence object for debugging
Definition: KSFoundation_host.c:6794

◆ ksgre_predownload_setrecon()

STATUS ksgre_predownload_setrecon ( )

Last-resort function to override certain recon variables not set up correctly already

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.

Return values
STATUSSUCCESS or FAILURE
1471  {
1472 
1473  KS_KACQ_RECONSHEDULE_ENTRY recon_table[16];
1474  int echo;
1475  for (echo = 0; echo < opnecho; echo++) {
1476  recon_table[echo].sampling_pattern_offset = 0;
1477  recon_table[echo].calibration_pattern_offset = KS_NOTSET;
1478  recon_table[echo].mask_pattern_offset = KS_NOTSET;
1479  recon_table[echo].echo_index = echo;
1480  }
1481  STATUS s = GEReq_writekacq(opnecho, recon_table, 1, &kacq);
1482  KS_RAISE(s);
1483 
1484  return SUCCESS;
1485 
1486 } /* ksgre_predownload_setrecon() */
int calibration_pattern_offset
Definition: KSFoundation.h:2298
#define KS_NOTSET
Definition: KSFoundation.h:115
int echo_index
Definition: KSFoundation.h:2296
An entry into the table that is written into the k_acq file when using GE&#39;s arc reconstruction
Definition: KSFoundation.h:2295
STATUS GEReq_writekacq(const int nrecon_schedule_entries, KS_KACQ_RECONSHEDULE_ENTRY *recon_schedule, const int num_patterns, const KS_KSPACE_ACQ *ks_kacq)
Definition: GERequired.e:2026
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_KSPACE_ACQ kacq
Definition: ksgre_implementation.e:171
int mask_pattern_offset
Definition: KSFoundation.h:2299
int sampling_pattern_offset
Definition: KSFoundation.h:2297

◆ ksgre_scan_phase()

float ksgre_scan_phase ( int  counter)

Returns a new RF phase based on an input counter and one of three GRE modes

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.

Parameters
[in]counterCounter from the calling function that should increment by 1 outside this function
Return values
phaseRF phase in [deg] to be passed to ks_scan_selrf_setfreqphase() and ks_scan_offsetfov()
1746  {
1747  float phase = 0;
1748 
1749  if (oppseq == PSD_SPGR /* = 5 */ ) {
1750  /* RF spoiling */
1751  phase = ks_scan_rf_phase_spoiling(counter);
1752  } else if (oppseq == PSD_SSFP /* = 4 */) {
1753  /* balanced SSFP */
1754  if (counter % 2)
1755  phase = 180;
1756  else
1757  phase = 0;
1758  } else {
1759  /* Gradient spoiling */
1760  phase = 0;
1761  }
1762 
1763  return phase;
1764 
1765 } /* ksgre_scan_phase() */
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:4827

◆ ksgre_scan_init()

STATUS ksgre_scan_init ( void  )

Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point

Return values
STATUSSUCCESS or FAILURE
2045  {
2046 
2047  GEReq_initRSP();
2048 
2049  /* Here goes code common for APS2, MPS2 and SCAN */
2050 
2051  ks_scan_switch_to_sequence(&ksgre.seqctrl); /* switch to main sequence */
2052  scopeon(&seqcore); /* Activate scope for core */
2053  syncon(&seqcore); /* Activate sync for core */
2054  setssitime(ksgre.seqctrl.ssi_time/HW_GRAD_UPDATE_TIME);
2055 
2056  /* can we make these independent on global rsptrigger and rsprot in orderslice? */
2057  settriggerarray( (short) ksgre_get_loop_ctrl()->slicetiming.slice_plan.nslices_per_pass, rsptrigger);
2058 
2059  spgr_phase_counter = 0;
2060  ksgre.fiesta_firstplayout = oppseq == PSD_SSFP ? TRUE : FALSE;
2061 
2062  return SUCCESS;
2063 
2064 } /* ksgre_scan_init() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1625
STATUS setssitime(long)
void GEReq_initRSP(void)
RSP Init. To be inserted in the psdinit() function (or scan()) in the main sequence
Definition: GERequired.e:3773
const KSSCAN_LOOP_CONTROL * ksgre_get_loop_ctrl()
Definition: ksgre_implementation.e:1503
int ssi_time
Definition: KSFoundation.h:1226
int fiesta_firstplayout
Definition: ksgre_implementation.e:64
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:54
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:133
int spgr_phase_counter
Definition: ksgre_implementation.e:2027

◆ ksgre_scan_prescanloop()

void ksgre_scan_prescanloop ( int  nloops,
int  dda 
)

Prescan loop called from both APS2 and MPS2 entry points

Return values
STATUSSUCCESS or FAILURE
2074  {
2075 
2077 
2078 } /* ksgre_scan_prescanloop() */
void ksscan_prescanloop(const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksscan.cc:603
KS_CORESLICETIME ksgre_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksgre sequence module with optional sat module...
Definition: ksgre_implementation.e:1977
KSSCAN_LOOP_CONTROL ksgre_loopctrl
Definition: ksgre_implementation.e:134

Variable Documentation

◆ seqcollection

KS_SEQ_COLLECTION seqcollection

◆ ksgre_excthickness

float ksgre_excthickness = 0

◆ ksgre_gscalerfexc

float ksgre_gscalerfexc = 0.9

◆ ksgre_slicecheck

int ksgre_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",}

◆ ksgre_spoilerarea

float ksgre_spoilerarea = 1500.0 with {0.0, 10000.0, 1500.0, VIS, "ksgre spoiler gradient area",}

◆ ksgre_sincrf

int ksgre_sincrf = 0 with {0, 1, 0, VIS, "Use Sinc RF",}

◆ ksgre_sincrf_bw

float ksgre_sincrf_bw = 2500 with {0, 100000, 2500, VIS, "Sinc RF BW",}

◆ ksgre_sincrf_tbw

float ksgre_sincrf_tbw = 2 with {2, 100, 2, VIS, "Sinc RF TBW",}

◆ ksgre_rfexc_choice

int ksgre_rfexc_choice = 0 with {0, 3, 0, VIS, "RF pulse 0(fast)-1-2(high FA) 3 (Hard non-sel)",}

◆ ksgre_kxnover

int ksgre_kxnover = 32 with {KSGRE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",}

◆ ksgre_rampsampling

int ksgre_rampsampling = FALSE with {FALSE, TRUE, FALSE, VIS, "Rampsampling [0:OFF 1:ON]",}

◆ ksgre_extragap

int ksgre_extragap = 0 with {0, 100ms, 0, VIS, "extra gap between readouts [us]",}

◆ ksgre_minacslines

int ksgre_minacslines = 16 with {0, 512, 16, VIS, "Minimum ACS lines for ARC",}

◆ ksgre_minzacslines

int ksgre_minzacslines = 16 with {0, 512, 16, VIS, "Minimum z ACS lines for ARC",}

◆ ksgre_pos_start

int ksgre_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, VIS, "us from start until the first waveform begins",}

◆ ksgre_ssi_time

int ksgre_ssi_time = KSGRE_DEFAULT_SSI_TIME with {32, , KSGRE_DEFAULT_SSI_TIME, VIS, "time from eos to ssi in intern trig",}

◆ ksgre_dda

int ksgre_dda = 2 with {0, 200, 2, VIS, "Number of dummy scans for steady state",}

◆ ksgre_debug

int ksgre_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)",}

◆ ksgre_imsize

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]"}

◆ ksgre_abort_on_kserror

int ksgre_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",}

◆ ksgre_ellipsekspace

int ksgre_ellipsekspace = TRUE with {FALSE, TRUE, TRUE, VIS, "ky-kz coverage 0:Rect 1:Elliptical",}

◆ ksgre

◆ ksgre_loopctrl

Scan loop control for the ksgre sequence

◆ ksgre_inv

Inversion module

◆ ksgre_phaseencoding_memorypool

◆ ksgre_ssfp_endtime

int ksgre_ssfp_endtime = 0

◆ kacq

◆ sequence_iopts

int sequence_iopts[]
Initial value:
= {
PSD_IOPT_ARC,
PSD_IOPT_ASSET,
PSD_IOPT_EDR,
PSD_IOPT_DYNPL,
PSD_IOPT_SEQUENTIAL,
PSD_IOPT_ZIP_512,
PSD_IOPT_IR_PREP,
PSD_IOPT_MILDNOTE,
PSD_IOPT_FLOW_COMP,
}

◆ spgr_phase_counter

int spgr_phase_counter