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

Data Structures

struct  KSFSE_SEQUENCE
 

Macros

#define KSFSE_MINHNOVER   6
 
#define KSFSE_MIN_SSI_TIME   200
 
#define KSFSE_MAXTHICKFACT   3.0
 
#define KSFSE_INIT_SEQUENCE   {KS_INIT_SEQ_CONTROL, KS_INIT_READTRAP, KS_INIT_TRAP, KS_INIT_PHASER, KS_INIT_PHASER, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_SELRF};
 
#define KSFSE_PHASEENCODING_MEMORYPOOL_SIZE   25000
 

Enumerations

enum  { KSFSE_RECOVERY_OFF, KSFSE_RECOVERY_T1WOPT, KSFSE_RECOVERY_FAST }
 

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 ("FSE [KSFoundation]")
 
 psdname ("ksfse")
 
void ksfse_eval_TEmenu (int esp, int maxte, int etl, double optechono)
 
STATUS ksfse_calc_echo (double *bestecho, double *optecho, KS_PHASER *pe, int TE, int etl, int esp)
 
STATUS ksfse_pg (int start_time)
 
KS_CORESLICETIME ksfse_scan_coreslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksfse_scan_coreslicegroup (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksfse_scan_irslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
s64 ksfse_scan_scanloop ()
 
STATUS ksfse_scan_seqstate (SCAN_INFO slice_pos, KS_PHASEENCODING_SHOTCOORDS shot_coords)
 
const KSSCAN_LOOP_CONTROLksfse_get_loop_ctrl ()
 
void ksfse_init_imagingoptions (void)
 
STATUS ksfse_init_UI (void)
 
STATUS ksfse_eval_UI ()
 
int ksfse_eval_esp (int *min90_180, int *min180_echo, int slicecheck, KSFSE_SEQUENCE *seq)
 
int ksfse_eval_optimalkxnover (KSFSE_SEQUENCE *seq)
 
float ksfse_eval_rfstretchfactor (float patientweight, float flipangle, int tailoredrf_flag)
 
STATUS ksfse_eval_setuprfpulses_2D (KSFSE_SEQUENCE *seq, float crusher_dephasing)
 
STATUS ksfse_eval_setuprfpulses_3D (KSFSE_SEQUENCE *seq)
 
STATUS ksfse_eval_setuprfpulses_recovery (KSFSE_SEQUENCE *seq)
 
int ksfse_eval_ssitime ()
 
STATUS ksfse_eval_setupobjects ()
 
STATUS ksfse_eval_TErange ()
 
void ksfse_set_kspace_design (KS_KSPACE_DESIGN *kdesign)
 
void ksfse_set_slicetiming_design (KS_SLICETIMING_DESIGN *slicetiming_design)
 
STATUS ksfse_set_loop_control_design (KSSCAN_LOOP_CONTROL_DESIGN *loop_design)
 
STATUS ksfse_set_inversion_loop_control_design (KSINV_LOOP_CONTROL_DESIGN *invloopctrl_design)
 
STATUS ksfse_eval_inversion (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksfse_eval_sat (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksfse_gradheat_play (const INT max_encode_mode, int nargs, void **args)
 
STATUS ksfse_eval_loops (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksfse_eval_scantime (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksfse_update_UI ()
 
STATUS ksfse_predownload_plot (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksfse_predownload_setrecon ()
 
void ksfse_scan_rf_off ()
 
void ksfse_scan_rf_on ()
 
STATUS ksfse_scan_init (void)
 
void ksfse_scan_prescanloop (int nloops, int dda)
 

Variables

KS_SEQ_COLLECTION seqcollection
 
float ksfse_excthickness = 0
 
float ksfse_gscalerfexc = 0.9
 
float ksfse_flipexc = 90.0 with {0.0, 180.0, 90.0, VIS, "Excitation flip angle [deg]",}
 
float ksfse_spoilerarea = 2000.0 with {0.0, 20000.0, 5000.0, VIS, "ksfse spoiler gradient area",}
 
float rf_stretch_rfexc = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF excitation pulse if > 1.0",}
 
int ksfse_inflowsuppression = 0 with {0, 1, 0, VIS, "In-flow Suppression [0:OFF, 1:ON]",}
 
float ksfse_inflowsuppression_mm = 0.0 with {0.0, 100.0, 0.0, VIS, "In-flow suppression [mm]",}
 
int ksfse_vfa = 1 with {0, 1, 1, VIS, "Variable flip angles [0:OFF, 1:ON]",}
 
float ksfse_crusher_dephasing = 6.0 with {0.0, 100.0, 6.0, VIS, "scaling of crusher gradient area [cycles]",}
 
float ksfse_gscalerfref = 0.9
 
int ksfse_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",}
 
float rf_stretch_rfref = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF refocusing pulses if > 1.0",}
 
float rf_stretch_all = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch all RF pulses if > 1.0",}
 
int ksfse_recovery = KSFSE_RECOVERY_OFF with {KSFSE_RECOVERY_OFF, KSFSE_RECOVERY_FAST, KSFSE_RECOVERY_OFF, VIS, "Recovery. 0:off 1:T1wopt 2:T2fast", }
 
float rf_stretch_rfrecovery = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF recovery pulses if > 1.0",}
 
int ksfse_kxnover_min = KSFSE_MINHNOVER with {KSFSE_MINHNOVER, 512, KSFSE_MINHNOVER, VIS, "Min mum kx overscans for minTE",}
 
int ksfse_kxnover = 32 with {KSFSE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",}
 
int ksfse_rampsampling = 0 with {0, 1, 0, VIS, "Rampsampling [0:OFF 1:ON]",}
 
int ksfse_extragap = 0 with {0, 100ms, 0, VIS, "extra gap between readout [us]",}
 
int ksfse_etlte = 1 with {0, 1, 1, VIS, "ETL controls TE",}
 
float ksfse_xcrusherarea = 100.0 with {0.0, 1000.0, 100.0, VIS, "x crusher area for readout",}
 
int ksfse_esp = 0 with {0, 1000000, 0, VIS, "View-only: Echo spacing in [us]",}
 
int ksfse_noph = 0 with {0, 1, 0, VIS, "Turn OFF phase encoding [0:Disabled 1:Enabled]",}
 
int ksfse_minacslines = 12 with {0, 512, 12, VIS, "Minimum ACS lines for ARC",}
 
int ksfse_minzacslines = 12 with {0, 512, 12, VIS, "Minimum z ACS lines for ARC",}
 
int ksfse_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, VIS, "us from start until the first waveform begins",}
 
int ksfse_ssi_time = KSFSE_MIN_SSI_TIME with {50, , KSFSE_MIN_SSI_TIME, VIS, "time from eos to ssi in intern trig",}
 
int ksfse_dda = 2 with {0, 200, 2, VIS, "Number of dummy scans for steady state",}
 
int ksfse_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)",}
 
int ksfse_imsize = KS_IMSIZE_NATIVE with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_MIN256, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"}
 
int ksfse_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",}
 
int ksfse_mintr = 0 with {0, 20s, 0, VIS, "Min TR (ms) [0: Disabled]",}
 
int ksfse_maxtr = 0 with {0, 40s, 0, VIS, "Max TR (ms) [0: Disabled]",}
 
KSFSE_SEQUENCE ksfse = KSFSE_INIT_SEQUENCE
 
KSSCAN_LOOP_CONTROL ksfse_loopctrl = KSSCAN_INIT_LOOP_CONTROL
 
KSINV_MODULE ksfse_inv = KSINV_INIT_MODULE
 
KSINV_LOOP_CONTROL ksfse_inv_loopctrl = KSINV_INIT_LOOP_CONTROL
 
KS_PHASEENCODING_COORD ksfse_phaseencoding_memorypool [KSFSE_PHASEENCODING_MEMORYPOOL_SIZE] = {KS_INIT_PHASEENCODING_COORD}
 
KS_KSPACE_ACQ kacq = KS_INIT_KSPACE_ACQ
 
int sequence_iopts []
 

Detailed Description

MR-contrasts supported

Features

Macro Definition Documentation

◆ KSFSE_MINHNOVER

#define KSFSE_MINHNOVER   6

◆ KSFSE_MIN_SSI_TIME

#define KSFSE_MIN_SSI_TIME   200

◆ KSFSE_MAXTHICKFACT

#define KSFSE_MAXTHICKFACT   3.0

◆ KSFSE_INIT_SEQUENCE

◆ KSFSE_PHASEENCODING_MEMORYPOOL_SIZE

#define KSFSE_PHASEENCODING_MEMORYPOOL_SIZE   25000

num elements allocated for unique phase encodes

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
KSFSE_RECOVERY_OFF 
KSFSE_RECOVERY_T1WOPT 
KSFSE_RECOVERY_FAST 
Definition: ksfse_implementation.e:45
Definition: ksfse_implementation.e:45
Definition: ksfse_implementation.e:45

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 = ksfse_init_UI();
108  KS_RAISE(status);
109 
110  return SUCCESS;
111 
112 } /* cvinit() */
void ksfse_init_imagingoptions(void)
Initial handling of imaging options buttons and top-level CVs at the PSD type-in pages
Definition: ksfse_implementation.e:248
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksfse_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksfse_implementation.e:310
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

◆ cveval()

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

◆ my_cveval()

STATUS my_cveval ( void  )
134  {
135  STATUS status;
136 
138 
139  /* Link the memory pool for the phase encoding plans */
142  KS_RAISE(status);
143 
144  status = GEReq_cveval();
145  KS_RAISE(status);
146 
147  /* User Interface updates & opuserCV sync */
148  status = ksfse_eval_UI();
149  KS_RAISE(status);
150 
151  /* Setup sequence objects */
152  status = ksfse_eval_setupobjects();
153  KS_RAISE(status);
154 
155  /* Calculate minimum (and maximum TE), and sometimes ETL */
156  status = ksfse_eval_TErange();
157  KS_RAISE(status);
158 
159  /* Run the sequence once (and only once after ksfse_eval_setupobjects()) in cveval() to
160  get the sequence duration and the number of object instances (for grad/rf limits in GEReq...limits()) */
161  status = ksfse_pg(ksfse_pos_start);
162  KS_RAISE(status);
163 
165  KS_RAISE(status);
166 
167  /* Add the passpacket seqctrl to the seqcollection */
169  KS_RAISE(status);
170 
171 
172  /*--------- Begin: Additional sequence modules -----------*/
173 
174  /* Sat */
175  status = ksfse_eval_sat(&seqcollection);
176  KS_RAISE(status);
177 
178  /* Inversion */
180  KS_RAISE(status);
181 
182  /*--------- End: Additional sequence modules -----------*/
183 
184 
185  /* Min TR, #slices per TR, RF/gradient heating & SAR */
186  status = ksfse_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 ksfse_eval_sat(KS_SEQ_COLLECTION *seqcollection)
Set up of the KSSAT_MODULE kssat for graphical saturation in the UI
Definition: ksfse_implementation.e:1990
KS_SEQ_COLLECTION seqcollection
Definition: ksfse.e:88
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
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 ksfse_eval_TErange()
Sets the min/max TE and echo spacing for the FSE train based on rBW, res and ETL
Definition: ksfse_implementation.e:1583
STATUS ksfse_eval_UI()
Gets the current UI and checks for valid inputs
Definition: ksfse_implementation.e:735
STATUS ksfse_eval_loops(KS_SEQ_COLLECTION *seqcollection)
Setup of scan loop control structs after heating calculations
Definition: ksfse_implementation.e:2090
STATUS ksfse_eval_inversion(KS_SEQ_COLLECTION *seqcollection)
Setup and evaluation of KSINV_DESIGN and the creation of a KSINV_MODULE module for inversion recovery...
Definition: ksfse_implementation.e:1941
int ksfse_pos_start
Definition: ksfse_implementation.e:133
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_CONTROL seqctrl
Definition: ksfse_implementation.e:57
STATUS ksfse_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: ksfse_implementation.e:2149
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksfse_eval_setupobjects()
Sets up all sequence objects for the main sequence module (KSFSE_SEQUENCE ksfse)
Definition: ksfse_implementation.e:1415
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
#define KSFSE_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksfse_implementation.e:165
STATUS ksfse_pg(int)
The ksfse (main) pulse sequence
Definition: ksfse_implementation.e:2421
STATUS GEReq_cveval(void)
Helper function to be called at the beginning of cveval()
Definition: GERequired.e:3346
KS_PHASEENCODING_COORD ksfse_phaseencoding_memorypool[KSFSE_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksfse_implementation.e:166
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 = ksfse_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 ksfse_update_UI()
Update variables for the UI and checks for out of bounds values
Definition: ksfse_implementation.e:2192
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int abort_on_kserror
Definition: KSFoundation_common.c:40
int ksfse_abort_on_kserror
Definition: ksfse_implementation.e:138
STATUS my_cveval(void)
Definition: ksfse.e:134

◆ 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 = ksfse_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  ksfse_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 = ksfse_predownload_setrecon();
264  KS_RAISE(status);
265 
266  /* plotting of sequence modules and slice timing to disk */
268 
269 
270  return SUCCESS;
271 
272 } /* 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_PHASER phaseenc
Definition: ksfse_implementation.e:60
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
KS_SEQ_COLLECTION seqcollection
Definition: ksfse.e:88
STATUS ksfse_predownload_plot(KS_SEQ_COLLECTION *seqcollection)
Plotting of sequence modules and slice timing in HTML files
Definition: ksfse_implementation.e:2295
KS_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
#define KS_GERECON
Definition: KSFoundation.h:241
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_READTRAP read
Definition: ksfse_implementation.e:58
STATUS ksfse_predownload_setrecon()
Last-resort function to override certain recon variables not set up correctly already
Definition: ksfse_implementation.e:2360
int ksfse_imsize
Definition: ksfse_implementation.e:137
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
const KSSCAN_LOOP_CONTROL * ksfse_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksfse_implementation.e:2403
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int ksfse_extragap
Definition: ksfse_implementation.e:118
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
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

◆ pulsegen()

STATUS pulsegen ( void  )
281  {
282 
284 
285  /* Link the memory pool for the phase encoding plans */
288 
289  /* Main sequence */
291  KS_SEQLENGTH(seqcore, ksfse.seqctrl);
292 
293  /* Sat */
294  kssat_pg(&kssat);
295  if (kssat.seqctrl.duration > 0) {
296  KS_SEQLENGTH(seqsat, kssat.seqctrl);
297  }
298 
299  /* Inversion sequence modules */
300  if (ANYINVERSION) {
302  KS_SEQLENGTH(seqinv, ksfse_inv.seqctrl);
303  KS_SEQLENGTH(seqtrfill, ksfse_inv_loopctrl.seqctrl_filltr); /* FLAIR BLOCK requires 2 sequence modules */
304  }
305 
307 
308  buildinstr(); /* load the sequencer memory */
309 
310  return SUCCESS;
311 
312 } /* pulsegen() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
KS_SEQLENGTH(seq_name, seq_struct)
Creates a hardware sequence for the current sequence module
Definition: GERequired.e:65
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
STATUS kssat_pg(KSSAT_MODULE *sat)
Place all waveforms for the saturation module
Definition: kssat.e:180
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
int duration
Definition: KSFoundation.h:1227
void GEReq_pulsegenEnd(void)
Helper function to be called at the end of pulsegen()
Definition: GERequired.e:3598
int ksfse_pos_start
Definition: ksfse_implementation.e:133
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
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
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
#define KSFSE_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksfse_implementation.e:165
#define ANYINVERSION
Definition: KSFoundation.h:346
STATUS ksfse_pg(int)
The ksfse (main) pulse sequence
Definition: ksfse_implementation.e:2421
KS_SEQ_CONTROL seqctrl_filltr
Definition: ksinversion.h:111
void GEReq_pulsegenBegin(void)
Helper function to be called at the beginning of pulsegen()
Definition: GERequired.e:3571
KS_PHASEENCODING_COORD ksfse_phaseencoding_memorypool[KSFSE_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksfse_implementation.e:166
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73

◆ mps2()

STATUS mps2 ( void  )
335  {
336 
337  rspent = L_MPS2;
338  strcpy(psdexitarg.text_arg, "mps2");
339 
340  if (ksfse_scan_init() == FAILURE)
341  return rspexit();
342 
344 
345  rspexit();
346 
347  return SUCCESS;
348 
349 } /* mps2() */
STATUS ksfse_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksfse_implementation.e:2986
void ksfse_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksfse_implementation.e:3012
int ksfse_dda
Definition: ksfse_implementation.e:135
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ aps2()

STATUS aps2 ( void  )
359  {
360 
361  rspent = L_APS2;
362  strcpy(psdexitarg.text_arg, "aps2");
363 
364  if (ksfse_scan_init() == FAILURE)
365  return rspexit();
366 
368 
369  rspexit();
370 
371  return SUCCESS;
372 
373 } /* aps2() */
STATUS ksfse_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksfse_implementation.e:2986
void ksfse_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksfse_implementation.e:3012
int ksfse_dda
Definition: ksfse_implementation.e:135
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ scan()

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

◆ abstract()

abstract ( "FSE "  [KSFoundation])

◆ psdname()

psdname ( "ksfse"  )

◆ ksfse_eval_TEmenu()

void ksfse_eval_TEmenu ( int  esp,
int  maxte,
int  etl,
double  optechono 
)

Sets up the TE menu based on echo spacing, max TE, ETL and the optimal echo index

optechono is the echo index in range [0, ETL-1] that is in the center of the FSE train. If the TE corresponding to this index is chosen, optimal image quality is achieved with minimal FSE ghosting.

For ETLs > 6, this value is given first in the TE menu, meaning that if the user chooses the first field in the TE menu this will have the same effect as setting "ETL controls TE", and the remaining TE fields in the menu are the ones straddling the optimal TE.

For ETLs in range [2,6], MinFull is the first, followed by the optimal TE.

For ETL = 1, which corresponds to a conventional Spin-Echo, the user can choose only between MinTE (partial kx Fourier) and MinFullTE. Manual type-in is not allowed for ETL = 1.

Parameters
[in]espEcho Spacing in [us]
[in]maxteMaximum TE in [us]
[in]etlEcho Train Length
[in]optechonoOptimal echo index in range [0, ETL-1]
Returns
void
850  {
851  int allow_typein = 1;
852 
853  if (etl > 6) {
854  pite1val2 = optechono * esp; /* best TE for image quality (minimal T2-blurring, ghosting) */
855  pite1val3 = (optechono - 2) * esp;
856  pite1val4 = (optechono - 1) * esp;
857  pite1val5 = (optechono + 1) * esp;
858  pite1val6 = (optechono + 2) * esp;
859  } else if (etl > 1) {
860  pite1val2 = PSD_MINFULLTE;
861  pite1val3 = (optechono - 2) * esp;
862  pite1val4 = (optechono - 1) * esp;
863  pite1val5 = optechono * esp;
864  pite1val6 = (optechono + 1) * esp;
865  } else { /* etl = 1 */
866  allow_typein = 0;
867  pite1val2 = PSD_MINIMUMTE;
868  pite1val3 = PSD_MINFULLTE;
869  pite1val4 = 0;
870  pite1val5 = 0;
871  pite1val6 = 0;
872  }
873 
874  if (etl > 1) {
875  pite1nub = allow_typein + 2 +
876  4 * (pite1val3 >= esp && pite1val3 <= maxte) +
877  8 * (pite1val4 >= esp && pite1val4 <= maxte) +
878  16 * (pite1val5 >= esp && pite1val5 <= maxte) +
879  32 * (pite1val6 >= esp && pite1val6 <= maxte);
880  } else {
881  pite1nub = 6; /* only MinTE & MinFull */
882  }
883 
884 } /* ksfse_eval_TEmenu() */

◆ ksfse_calc_echo()

STATUS ksfse_calc_echo ( double *  bestecho,
double *  optecho,
KS_PHASER pe,
int  TE,
int  etl,
int  esp 
)

◆ ksfse_pg()

STATUS ksfse_pg ( int  start_time)

The ksfse (main) pulse sequence

This is the main pulse sequence in ksfse.e using the sequence objects in KSFSE_SEQUENCE with the sequence module name "ksfsemain" (= ksfse.seqctrl.description)

Return values
STATUSSUCCESS or FAILURE
2421  {
2422 
2423  STATUS status;
2424  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
2425  int readpos_start = KS_NOTSET;
2426  int spoiler_pos = KS_NOTSET;
2427  int i;
2428 
2429  if (start_time < KS_RFSSP_PRETIME) {
2430  return ks_error("%s: 1st arg (pos start) must be at least %d us", __FUNCTION__, KS_RFSSP_PRETIME);
2431  }
2432 
2433 
2434  /*******************************************************************************************************
2435  * RF Excitation
2436  *******************************************************************************************************/
2437  tmploc.ampscale = 1.0;
2438  tmploc.pos = RUP_GRD(start_time + KS_RFSSP_PRETIME);
2439  tmploc.board = ZGRAD;
2440 
2441  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksfse.selrfexc is an excitation pulse
2442  (ksfse.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksfse.seqctrl.momentstart
2443  to the absolute position in [us] of the isocenter of the RF excitation pulse */
2444  status = ks_pg_selrf(&ksfse.selrfexc, tmploc, &ksfse.seqctrl);
2445  KS_RAISE(status);
2446 
2447  /*******************************************************************************************************
2448  * X dephaser (between 90 and 1st 180)
2449  *******************************************************************************************************/
2450  if (ksfse_slicecheck) {
2452  tmploc.board = ZGRAD;
2453  } else {
2455  tmploc.board = XGRAD;
2456  }
2457  status = ks_pg_trap(&ksfse.readdephaser, tmploc, &ksfse.seqctrl);
2458  KS_RAISE(status);
2459 
2460  /*******************************************************************************************************
2461  * Generate the refocusing flip angles
2462  -------------------------------------------------------------------------------------------------------*/
2463  double flip_angles[512]; /* rad */
2464 
2465  if (ksfse_vfa) {
2466 
2467  STATUS status = ks_pg_fse_flip_angle_taperoff(flip_angles,
2468  opetl,
2470  80.0, /* degrees */
2471  opflair != OPFLAIR_INTERLEAVED);
2472  KS_RAISE(status);
2473  }
2474 
2475 
2476 
2477  /*******************************************************************************************************
2478  * FSE train: Begin
2479  -------------------------------------------------------------------------------------------------------*/
2480  for (i = 0; i < opetl; i++) {
2481 
2482  /* Selective RF Refocus with left (pregrad.) and right (postgrad.) crushers */
2483  tmploc.board = ZGRAD;
2484  if (i == 0) {
2485  /* special case for 1st pulse with at least a smaller left crusher */
2487 
2488  if (ksfse_vfa)
2489  tmploc.ampscale = flip_angles[i] / ksfse.selrfref1st.rf.flip;
2490 
2491  status = ks_pg_selrf(&ksfse.selrfref1st, tmploc, &ksfse.seqctrl);
2492  KS_RAISE(status);
2493  tmploc.ampscale = 1;
2494 
2495  } else if (i == 1) {
2497 
2498  if (ksfse_vfa)
2499  tmploc.ampscale = flip_angles[i] / ksfse.selrfref2nd.rf.flip;
2500 
2501  status = ks_pg_selrf(&ksfse.selrfref2nd, tmploc, &ksfse.seqctrl);
2502  KS_RAISE(status);
2503  tmploc.ampscale = 1;
2504 
2505  } else {
2507 
2508  if (ksfse_vfa)
2509  tmploc.ampscale = flip_angles[i] / ksfse.selrfref.rf.flip;
2510 
2511  status = ks_pg_selrf(&ksfse.selrfref, tmploc, &ksfse.seqctrl);
2512  KS_RAISE(status);
2513  tmploc.ampscale = 1;
2514 
2515  }
2516 
2517  /* ksfse_esp dependent time at beginning of readout ramp */
2518  readpos_start = ksfse.seqctrl.momentstart + (i + 1) * ksfse_esp - ksfse.read.time2center;
2519 
2520  /*******************************************************************************************************
2521  * Readouts
2522  *******************************************************************************************************/
2523  tmploc.pos = readpos_start;
2524  if (ksfse_slicecheck)
2525  tmploc.board = ZGRAD;
2526  else
2527  tmploc.board = XGRAD;
2528  status = ks_pg_readtrap(&ksfse.read, tmploc, &ksfse.seqctrl);
2529  KS_RAISE(status);
2530 
2531  /*******************************************************************************************************
2532  * Phase encoding dephasers & rephasers
2533  *******************************************************************************************************/
2534  tmploc.board = YGRAD;
2535  tmploc.pos = readpos_start + ksfse.read.acqdelay - ksfse.phaseenc.grad.duration;
2536  status = ks_pg_phaser(&ksfse.phaseenc, tmploc, &ksfse.seqctrl); /* instance 2*i */
2537  KS_RAISE(status);
2538  tmploc.pos = readpos_start + ksfse.read.grad.duration - ksfse.read.acqdelay;
2539  status = ks_pg_phaser(&ksfse.phaseenc, tmploc, &ksfse.seqctrl); /* instance 2*i + 1 */
2540  KS_RAISE(status);
2541 
2542  /*******************************************************************************************************
2543  * Z phase encoding dephasers & rephasers (3D)
2544  *******************************************************************************************************/
2545  if (ksfse.zphaseenc.grad.duration > 0) {
2546  tmploc.board = ZGRAD;
2547  tmploc.pos = readpos_start + ksfse.read.acqdelay - ksfse.zphaseenc.grad.duration;
2548  status = ks_pg_phaser(&ksfse.zphaseenc, tmploc, &ksfse.seqctrl); /* instance 2*i */
2549  KS_RAISE(status);
2550  tmploc.pos = readpos_start + ksfse.read.grad.duration - ksfse.read.acqdelay;
2551  status = ks_pg_phaser(&ksfse.zphaseenc, tmploc, &ksfse.seqctrl); /* instance 2*i + 1 */
2552  KS_RAISE(status);
2553  }
2554 
2555  } /* opetl */
2556 
2557  /*------------------------------------------------------------------------------------------------------
2558  * FSE train: End
2559  *******************************************************************************************************/
2560 
2561  /*******************************************************************************************************
2562  * Post-ETL forced recovery: T1-w Optimization / T2 fast Recovery
2563  *******************************************************************************************************/
2564  if (ksfse_recovery) {
2565 
2566  int lastReadoutCenter = ksfse.seqctrl.momentstart + opetl * ksfse_esp;
2567 
2568  /* Place extra refocusing pulse */
2569  tmploc.board = ZGRAD;
2570  tmploc.pos = lastReadoutCenter + ksfse_esp/2 - ksfse.selrfrecoverref.rf.start2iso - ksfse.selrfrecoverref.grad2rf_start;
2571  tmploc.ampscale = (ksfse_vfa) ? flip_angles[opetl-1] / ksfse.selrfrecoverref.rf.flip : 1;
2572 
2573  status = ks_pg_selrf(&ksfse.selrfrecoverref, tmploc, &ksfse.seqctrl);
2574  KS_RAISE(status);
2575 
2576  /* Place rewinder of previous readout in order to get back to the center of k-space */
2577  tmploc.pos = lastReadoutCenter + ksfse_esp - ksfse.selrfrecover.rf.start2iso - ksfse.readdephaser.duration;
2578  tmploc.ampscale = 1;
2579  if (ksfse_slicecheck) {
2580  tmploc.board = ZGRAD;
2581  tmploc.pos -= ksfse.selrfrecover.grad.ramptime;
2582  } else {
2583  tmploc.board = XGRAD;
2584  }
2585  status = ks_pg_trap(&ksfse.readdephaser, tmploc, &ksfse.seqctrl);
2586  KS_RAISE(status);
2587 
2588  /* Place excitation pulse */
2589  tmploc.board = ZGRAD;
2590  tmploc.pos = lastReadoutCenter + ksfse_esp - ksfse.selrfrecover.rf.start2iso - ksfse.selrfrecover.grad2rf_start;
2591 
2593  tmploc.ampscale = -1;
2594  } else { /* = KSFSE_RECOVERY_T1WOPT */
2595  tmploc.ampscale = 1;
2596  }
2597  status = ks_pg_selrf(&ksfse.selrfrecover, tmploc, &ksfse.seqctrl);
2598  KS_RAISE(status);
2599  tmploc.ampscale = 1;
2600 
2601  /* spoiler pos */
2603 
2604  } else {
2605 
2606  /* spoiler pos */
2608 
2609  } /* ksfse_recovery */
2610 
2611  /*******************************************************************************************************
2612  * Gradient spoiler on Y
2613  *******************************************************************************************************/
2614  tmploc.board = YGRAD;
2615  tmploc.pos = spoiler_pos;
2616  tmploc.ampscale = 1;
2617  status = ks_pg_trap(&ksfse.spoiler, tmploc, &ksfse.seqctrl);
2618  KS_RAISE(status);
2619  tmploc.pos += ksfse.spoiler.duration;
2620 
2621 
2622  /*******************************************************************************************************
2623  * Set the minimal sequence duration (ksfse.seqctrl.min_duration) by calling
2624  * ks_eval_seqctrl_setminduration()
2625  *******************************************************************************************************/
2626 
2627  /* make sure we are divisible by GRAD_UPDATE_TIME (4us) */
2628  tmploc.pos = RUP_GRD(tmploc.pos);
2629 
2630 #ifdef HOST_TGT
2631  /* On HOST only: Sequence duration (ksfse.seqctrl.ssi_time must be > 0 and is added to ksfse.seqctrl.min_duration in ks_eval_seqctrl_setminduration() */
2633  ks_eval_seqctrl_setminduration(&ksfse.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
2634 #endif
2635 
2636  return SUCCESS;
2637 
2638 } /* ksfse_pg() */
int ksfse_recovery
Definition: ksfse_implementation.e:109
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
KS_TRAP grad
Definition: KSFoundation.h:1463
int ksfse_eval_ssitime()
Set the SSI time for the sequence
Definition: ksfse_implementation.e:1376
int start2iso
Definition: KSFoundation.h:1032
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
KS_TRAP spoiler
Definition: ksfse_implementation.e:62
int pos
Definition: KSFoundation.h:463
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
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
#define KS_NOTSET
Definition: KSFoundation.h:115
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_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
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
KS_READTRAP read
Definition: ksfse_implementation.e:58
int board
Definition: KSFoundation.h:462
KS_TRAP grad
Definition: KSFoundation.h:1561
float ampscale
Definition: KSFoundation.h:464
float flip
Definition: KSFoundation.h:1028
int grad2rf_start
Definition: KSFoundation.h:1466
KS_TRAP readdephaser
Definition: ksfse_implementation.e:59
KS_RF rf
Definition: KSFoundation.h:1454
KS_WAVE rfwave
Definition: KSFoundation.h:1037
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
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
#define KS_RAISE(status)
Definition: KSFoundation.h:190
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:461
int iso2end
Definition: KSFoundation.h:1033
int ssi_time
Definition: KSFoundation.h:1226
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
int ksfse_esp
Definition: ksfse_implementation.e:121
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:287
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
Definition: ksfse_implementation.e:45
int time2center
Definition: KSFoundation.h:1560
int ksfse_vfa
Definition: ksfse_implementation.e:95
int acqdelay
Definition: KSFoundation.h:1555
int ramptime
Definition: KSFoundation.h:671
int duration
Definition: KSFoundation.h:747
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67
STATUS ks_pg_fse_flip_angle_taperoff(double *flip_angles, int etl, double flip1, double flip2, double flip3, double target_flip, int start_middle)
ADDTITLEHERE
Definition: KSFoundation_common.c:3430
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217
int ksfse_slicecheck
Definition: ksfse_implementation.e:102

◆ ksfse_scan_coreslice()

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

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

This function updates the waveforms, and plays out, the ksfse 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 ksfse.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(&ksfse.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
2807  {
2808  int i;
2809  float tloc = 0.0;
2811  SCAN_INFO slice_pos_updated;
2812 
2813  if (slice_pos != NULL) {
2814  /* uncomment to make transformations in the logical read-phase-slice coordinate system, using your own
2815  logic (e.g. radial or propeller applications), here just rotating by 30 degrees in-plane
2816  float rotz = 30.0;
2817  ks_mat4_setgeometry(dynamic->Mlogical, 0, 0, 0, 0, 0, rotz);
2818  Mphysical is useful for prospective motion correction implementations as it operates in X-Y-Z coords
2819  but should be left as the identity matrix otherwise
2820  */
2821  ks_scan_update_slice_location(&slice_pos_updated, *slice_pos, dynamic->Mphysical, dynamic->Mlogical);
2822  tloc = slice_pos_updated.optloc;
2823 
2824  ksfse_scan_rf_on();
2826  ksfse_scan_seqstate(slice_pos_updated, (ksfse_noph != PSD_ON) ? dynamic->shot_coords : dummy_shotcoords);
2827  } else {
2828  ksfse_scan_rf_off(); /* false slice, shut off RF pulses */
2829  }
2830 
2831  /* There is no compressed bam since DV26, however impact on product recon with SENSE is unclear */
2832  /* ASSET case triggered by R > 1 and no ACS lines */
2833  const int dabview_factor = (ksfse.phaseenc.R > 1 && ksfse.phaseenc.nacslines == 0) ?
2834  ksfse.phaseenc.R /* compressed BAM without empty non-acquired lines */ :
2835  1 /* normal */;
2836 
2837  /* data routing control */
2838  TYPDAB_PACKETS acqflag = slice_pos != NULL ? DABON : DABOFF;
2839  if ((dynamic->prescan || !dynamic->force_acq) && (dynamic->shot < 0 || dynamic->average < 0)) {
2840  acqflag = DABOFF;
2841  }
2842  const int dabop = (dynamic->average <= 0) ? DABSTORE : DABADD; /* replace or add to data */
2843  const int center_echo = opte / ksfse_esp - 1;
2844 
2845  for (i = 0; i < ksfse.read.acq.base.ngenerated; i++) {
2846  /* N.B.: Looping over ksfse.read.acq.base.ngenerated corresponds to:
2847  HOST: No looping since ksfse.read.acq.base.ngenerated is 0 on HOST
2848  TGT: ETL.
2849  This protects calls to loaddab() on HOST
2850  */
2851  KS_PHASEENCODING_COORD coord =
2852  dynamic->shot_coords.entries || i < dynamic->shot_coords.num_encodes ?
2853  dynamic->shot_coords.entries[i] : fake_coord;
2854 
2855  const int dabview = coord.ky >= 0 ?
2856  coord.ky/dabview_factor : KS_NOTSET;
2857 
2858  TYPDAB_PACKETS psc_acqflag = i == center_echo ? acqflag : DABOFF;
2859 
2860  loaddab(&ksfse.read.acq.echo[i], dynamic->sltimeinpass, 0, dabop, dabview + 1,
2861  dynamic->prescan ? psc_acqflag : acqflag,
2862  PSD_LOAD_DAB_ALL); /* see epicfuns.h for alternatives to loaddab() */
2863 
2864  } /* etl */
2865 
2867 
2869  slicetime.duration += ks_scan_playsequence(&ksfse.seqctrl);
2870 
2871  ks_plot_slicetime(&ksfse.seqctrl, 1, &tloc, opslthick, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
2872 
2873  return slicetime; /* in [us] */
2874 
2875 } /* ksfse_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 nacslines
Definition: KSFoundation.h:1724
ADDTITLEHERE
Definition: KSFoundation.h:1773
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
#define KS_NOTSET
Definition: KSFoundation.h:115
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
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
KS_READTRAP read
Definition: ksfse_implementation.e:58
STATUS ksfse_scan_seqstate(SCAN_INFO slice_info, KS_PHASEENCODING_SHOTCOORDS shot_coords)
Sets the current state of all ksfse sequence objects at every ksfse playout in scan
Definition: ksfse_implementation.e:2670
s16 ky
Definition: KSFoundation.h:1750
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
void ksfse_scan_rf_on()
Sets all RF pulse amplitudes on
Definition: ksfse_implementation.e:2769
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
Definition: KSFoundation.h:404
#define KS_INIT_PHASEENCODING_SHOTCOORDS
Definition: KSFoundation.h:1778
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
Definition: KSFoundation.h:403
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77
int ksfse_esp
Definition: ksfse_implementation.e:121
int ksfse_noph
Definition: ksfse_implementation.e:126
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
void ksfse_scan_rf_off()
Sets all RF pulse amplitudes to zero
Definition: ksfse_implementation.e:2750
int ngenerated
Definition: KSFoundation.h:496
KS_READ acq
Definition: KSFoundation.h:1549
float opslthick

◆ ksfse_scan_coreslicegroup()

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

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

With the use of generic scan loops (ksscan.cc:ksscan_scanloop()) performing the actual scan in ksfse_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 ksfse_scan_coreslice(), which only plays the main sequence (ksfse), 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
2912  {
2913  KS_CORESLICETIME coreslicetime = KS_INIT_CORESLICETIME;
2914  int premainseq_duration = 0;
2915 
2916  /* Sat */
2917  premainseq_duration += kssat_scan(slice_pos, dynamic, &kssat);
2918 
2919  /* Main */
2920  coreslicetime = ksfse_scan_coreslice(slice_pos, dynamic);
2921 
2922  coreslicetime.duration += premainseq_duration;
2923  coreslicetime.referencetimepoint += premainseq_duration;
2924 
2925  return coreslicetime;
2926 
2927 } /* ksfse_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
KS_CORESLICETIME ksfse_scan_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksfse sequence module in real time during scanning
Definition: ksfse_implementation.e:2807
KSSAT_MODULE kssat
Definition: kssat.e:112
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77

◆ ksfse_scan_irslice()

KS_CORESLICETIME ksfse_scan_irslice ( const SCAN_INFO *  slice_pos,
KS_DYNAMIC_STATE *  dynamic 
)
2880  {
2881 
2882  return ksinv_scan_irslice(&ksfse_inv, slice_pos, dynamic);
2883 
2884 } /* ksfse_scan_irslice() */
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
KS_CORESLICETIME ksinv_scan_irslice(KSINV_MODULE *seq, const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one inversion slice of the standard inversion module
Definition: ksinversion.cc:891

◆ ksfse_scan_scanloop()

s64 ksfse_scan_scanloop ( )

Plays out all volumes and passes of a single or multi-pass scan

This function is called from ksfse.e:scan(), which corresponds to the actual SCAN button press in the UI.

If inversion is used, the function calls ksinv_scan_scanloop(), where ksfse_inv_loopctrl is used to control the the scan looping. For non-inversion scans, ksscan_scanloop() is called, where ksfse_loopctrl is used to control the scan looping in both cases.

Returns
scantime Total scan time in [us]
2944  {
2945  s64 time = 0;
2946 
2947  if (!ANYINVERSION) {
2949  } else {
2951  }
2952 
2953  return time; /* in [us] */
2954 
2955 } /* ksfse_scan_scanloop() */
KS_CORESLICETIME ksfse_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksfse sequence module with optional sat module...
Definition: ksfse_implementation.e:2912
s64 ksinv_scan_scanloop(KSINV_LOOP_CONTROL *inv_loopctrl, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Plays the entire scan for an inversion loop control
Definition: ksinversion.cc:1224
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
KS_CORESLICETIME ksfse_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Definition: ksfse_implementation.e:2880
KSSCAN_LOOP_CONTROL ksfse_loopctrl
Definition: ksfse_implementation.e:159
s64 ksscan_scanloop(const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops according to the provided loop control
Definition: ksscan.cc:564
#define ANYINVERSION
Definition: KSFoundation.h:346

◆ ksfse_scan_seqstate()

STATUS ksfse_scan_seqstate ( SCAN_INFO  slice_pos,
KS_PHASEENCODING_SHOTCOORDS  shot_coords 
)

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

This function sets the current state of all ksfse 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 ksfse_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
2670  {
2671  (void) slice_pos;
2672  (void) shot_coords;
2673  int i;
2674  float rfphase = 0.0;
2676 
2677  ks_scan_rotate(slice_pos);
2678 
2679  ks_scan_selrf_setfreqphase(&ksfse.selrfexc, 0, slice_pos, rfphase /* [deg] */);
2680  ks_scan_selrf_setfreqphase(&ksfse.selrfref1st, INSTRALL, slice_pos, rfphase + 90 /* [deg] */);
2681  ks_scan_selrf_setfreqphase(&ksfse.selrfref2nd, INSTRALL, slice_pos, rfphase + 90 /* [deg] */);
2682  ks_scan_selrf_setfreqphase(&ksfse.selrfref, INSTRALL, slice_pos, rfphase + 90 /* [deg] */);
2683  if (ksfse_recovery) {
2684  ks_scan_selrf_setfreqphase(&ksfse.selrfrecoverref, INSTRALL, slice_pos, rfphase + 90 /* [deg] */);
2685  ks_scan_selrf_setfreqphase(&ksfse.selrfrecover, 0, slice_pos, rfphase /* [deg] */);
2686  }
2687 
2688  /* FOV offsets (by changing freq/phase of ksfse.read) */
2689  for (i = 0; i < opetl; i++) {
2690 
2691  KS_PHASEENCODING_COORD coord =
2692  shot_coords.entries || i < shot_coords.num_encodes ?
2693  shot_coords.entries[i] : fake_coord;
2694 
2695  ks_scan_phaser_toline(&ksfse.phaseenc, 0 + 2 * i, coord.ky); /* dephaser */
2696  ks_scan_phaser_fromline(&ksfse.phaseenc, 1 + 2 * i, coord.ky); /* rephaser */
2697 
2698  float ky_centred;
2699  if (coord.ky < 0) {
2700  ky_centred = 0.0f;
2701  } else {
2702  ky_centred = (float)coord.ky - (float)(ksfse.phaseenc.res - 1) / 2.0f;
2703  }
2704 
2705  if (KS_3D_SELECTED) {
2706  ks_scan_phaser_toline(&ksfse.zphaseenc, 0 + 2 * i, coord.kz); /* dephaser */
2707  ks_scan_phaser_fromline(&ksfse.zphaseenc, 1 + 2 * i, coord.kz); /* rephaser */
2708 
2709  float zfovratio = (opslquant * opslthick) / opfov;
2710  float zchop_phase = 0.0;
2711  float kz_centred;
2712  if (coord.kz < 0) {
2713  kz_centred = 0.0f;
2714  } else {
2715  kz_centred = (float)coord.kz - (float)(ksfse.zphaseenc.res - 1) / 2.0f;
2716  }
2717  if (oparc && (coord.kz % 2)) {
2718  /* GEs ARC recon ignores RHF_ZCHOP bit in 'rhformat', but expects 3D data to be z-chopped for proper slice sorting.
2719  In GERequired.e:GEReq_predownload_setrecon_voldata(), RHF_ZCHOP is unset by default. In combination with
2720  that we do not do zchop for non-ARC scans (incl ASSET), this works well. But for ARC scans, we must zchop. That is,
2721  we add 180 phase to every odd kz encoded line, which is the same as a final z fftshift in the image domain */
2722  zchop_phase = 180.0;
2723  }
2724  ks_scan_offsetfov3D(&ksfse.read, i, slice_pos, ky_centred, opphasefov, kz_centred, zfovratio, rfphase + zchop_phase);
2725  } else {
2726  ks_scan_offsetfov(&ksfse.read, i, slice_pos, ky_centred, opphasefov, rfphase);
2727  }
2728 
2729  } /* etl */
2730 
2731  /* Turn off T1-w opt. in DDAs */
2732  if ((ksfse_recovery) && (!shot_coords.entries)) {
2735  }
2736 
2737  return SUCCESS;
2738 
2739 } /* ksfse_scan_seqstate() */
int ksfse_recovery
Definition: ksfse_implementation.e:109
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:306
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
int res
Definition: KSFoundation.h:1721
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
const KS_PHASEENCODING_COORD * entries
Definition: KSFoundation.h:1775
KS_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_READTRAP read
Definition: ksfse_implementation.e:58
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
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
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
float opfov
int num_encodes
Definition: KSFoundation.h:1774
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
void ks_scan_rotate(SCAN_INFO slice_pos)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:1179
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
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
float opslthick
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
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67

◆ ksfse_get_loop_ctrl()

const KSSCAN_LOOP_CONTROL * ksfse_get_loop_ctrl ( )

Function to automatically switch between inverision and standard loop control

To save if statments in the code, this function returns the loop control in use depending on inversion is on or off.

Return values
STATUSSUCCESS or FAILURE
2403  {
2404  return ANYINVERSION ?
2406 
2407 } /* ksfse_get_loop_ctrl() */
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
KSSCAN_LOOP_CONTROL ksfse_loopctrl
Definition: ksfse_implementation.e:159
KSSCAN_LOOP_CONTROL loopctrl
Definition: ksinversion.h:110
#define ANYINVERSION
Definition: KSFoundation.h:346

◆ ksfse_init_imagingoptions()

void ksfse_init_imagingoptions ( void  )

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

Returns
void
248  {
249  int numopts = sizeof(sequence_iopts) / sizeof(int);
250 
251  psd_init_iopt_activity();
252  activate_iopt_list(numopts, sequence_iopts);
253  enable_iopt_list(numopts, sequence_iopts);
254 
255  /* Imaging option control functions (using PSD_IOPT_ZIP_512 as example):
256  - Make an option unchecked and not selectable: disable_ioption(PSD_IOPT_ZIP_512)
257  - Make an option checked and not selectable: set_required_disabled_option(PSD_IOPT_ZIP_512)
258  - Remove the imaging option: deactivate_ioption(PSD_IOPT_ZIP_512)
259  */
260 
261  cvset(opptsize, 2, 4, 4, ""); /* EDR */
262  set_required_disabled_option(PSD_IOPT_EDR); /* always use EDR, don't change */
263 
264  cvmax(opimode, PSD_3DM);
265 
266  /* Button accept control */
267  cvmax(opepi, PSD_OFF); /* don't allow EPI selection */
268  cvmax(opfast, PSD_ON);
269  cvmax(opssfse, PSD_ON);
270  cvmax(opflair, OPFLAIR_INTERLEAVED);
271  cvmax(optlrdrf, PSD_ON);
272  cvmax(opfr, PSD_ON);
273 
274  /* Exlude different inversion types */
275  set_incompatible(PSD_IOPT_T2FLAIR, PSD_IOPT_T1FLAIR);
276  set_incompatible(PSD_IOPT_IR_PREP, PSD_IOPT_T1FLAIR);
277  set_incompatible(PSD_IOPT_T2FLAIR, PSD_IOPT_IR_PREP);
278 
279  if (KS_3D_SELECTED) {
280  pidefexcitemode = NON_SELECTIVE;
281  piexcitemodenub = 1 + 2 /* + 4 FOCUS */;
282  cvmax(opexcitemode, NON_SELECTIVE);
283 
284  /* For now, 3D is not compatible with: */
285  deactivate_ioption(PSD_IOPT_T1FLAIR);
286  deactivate_ioption(PSD_IOPT_T2FLAIR);
287  deactivate_ioption(PSD_IOPT_IR_PREP);
288  deactivate_ioption(PSD_IOPT_TLRD_RF);
289  }
290 
291 #ifdef SIM
292  oppseq = PSD_SE;
293  setexist(oppseq, PSD_ON);
294  opfast = PSD_ON;
295  setexist(opfast, PSD_ON);
296  opirmode = PSD_OFF; /* default interleaved slices */
297  setexist(opirmode, PSD_ON);
298 #endif
299 
300 } /* ksfse_init_imagingoptions() */
int sequence_iopts[]
Definition: ksfse_implementation.e:218
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380

◆ ksfse_init_UI()

STATUS ksfse_init_UI ( void  )

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

Return values
STATUSSUCCESS or FAILURE
310  {
311 
312  /* IR always in interleaved mode */
313  if (oppseq == PSD_IR) {
314  cvoverride(opirmode, PSD_OFF, PSD_FIX_ON, PSD_EXIST_ON);
315  }
316 
317  acq_type = TYPSPIN; /* loadrheader.e rheaderinit: sets eeff = 1 */
318 
319  /* rBW */
320  cvmin(oprbw, 2);
321  cvmax(oprbw, 250.0);
322  pircbnub = 31; /* number of variable bandwidth */
323  if (opssfse == PSD_ON) {
324  pidefrbw = 62.50 * (cffield / 30000.0);
325  } else {
326  pidefrbw = 41.67 * (cffield / 30000.0);
327  }
328  pircbval2 = 31.25 * (cffield / 30000.0);
329  pircbval3 = 41.67 * (cffield / 30000.0);
330  pircbval4 = 50.00 * (cffield / 30000.0);
331  pircbval5 = 62.50 * (cffield / 30000.0);
332  pircbval6 = 83.33 * (cffield / 30000.0);
333  cvdef(oprbw, pidefrbw);
334  oprbw = _oprbw.defval;
335  pircb2nub = 0; /* no second bandwidth option */
336 
337  /* NEX */
338  pinexnub = 63;
339  if (opssfse == PSD_ON) {
340  cvdef(opnex, 0.6);
341  cvmin(opnex, 0.55);
342  cvmax(opnex, 100);
343  pinexval2 = 0.55;
344  pinexval3 = 0.575;
345  pinexval4 = 0.60;
346  pinexval5 = 0.625;
347  pinexval6 = 0.65;
348  } else {
349  cvdef(opnex, 1);
350  cvmin(opnex, 0.55);
351  cvmax(opnex, 100);
352  pinexval2 = 0.65;
353  pinexval3 = 0.75;
354  pinexval4 = 0.85;
355  pinexval5 = 1;
356  pinexval6 = 2;
357  }
358  opnex = _opnex.defval;
359 
360  /* FOV */
361  opfov = 240;
362  pifovnub = 4; /* show the first three + type-in */
363  pifovval2 = 180;
364  pifovval3 = 220;
365  pifovval4 = 240;
366  pifovval5 = 260;
367  pifovval6 = 280;
368 
369  /* phase FOV fraction */
370  opphasefov = 1;
371  piphasfovnub2 = 63;
372  piphasfovval2 = 1.0;
373  piphasfovval3 = 0.9;
374  piphasfovval4 = 0.8;
375  piphasfovval5 = 0.7;
376  piphasfovval6 = 0.6;
377 
378  /* freq (x) resolution */
379  cvmin(opxres, 16);
380  cvdef(opxres, 64);
381  opxres = _opxres.defval;
382  pixresnub = 63;
383  pixresval2 = 192;
384  pixresval3 = 224;
385  pixresval4 = 256;
386  pixresval5 = 320;
387  pixresval6 = 384;
388 
389  /* phase (y) resolution */
390  cvmin(opyres, 16);
391  piyresnub = 63;
392  if (opssfse == PSD_ON) {
393  piyresval2 = 64;
394  piyresval3 = 128;
395  piyresval4 = 160;
396  piyresval5 = 192;
397  piyresval6 = 256;
398  cvdef(opyres, 16); /* init low for SSFSE to avoid too long sequence length before proper values have been chosen */
399  } else {
400  piyresval2 = 192;
401  piyresval3 = 224;
402  piyresval4 = 256;
403  piyresval5 = 320;
404  piyresval6 = 384;
405  cvdef(opyres, 128);
406  }
407  opyres = _opyres.defval;
408 
409  /* Num echoes */
410  piechnub = 0;
411  cvdef(opnecho, 1);
412  cvmax(opnecho, 1);
413 
414  /* ETL */
415  avminetl = 1;
416  avmaxetl = 256;
417  if (opssfse == PSD_ON) {
418 
419  if (ksfse.phaseenc.numlinestoacq > 0)
420  cvdef(opetl, ksfse.phaseenc.numlinestoacq);
421  else
422  cvdef(opetl, _opyres.defval);
423  opetl = _opetl.defval;
424  pietlnub = 0;
425 
426  } else {
427 
428  if (!KS_3D_SELECTED) {
429  /* 2D */
430 
431  if (opflair == FALSE) {
432  if (optr < 1s) {
433  /* T1-w */
434  cvdef(opetl, 1);
435  opetl = _opetl.defval;
436  pietlnub = 63;
437  pietlval2 = 1;
438  pietlval3 = 2;
439  pietlval4 = 3;
440  pietlval5 = 4;
441  pietlval6 = 8;
442  } else {
443  /* T2-w */
444  cvdef(opetl, 16);
445  opetl = _opetl.defval;
446  pietlnub = 63;
447  pietlval2 = 8;
448  pietlval3 = 12;
449  pietlval4 = 16;
450  pietlval5 = 20;
451  pietlval6 = 24;
452  }
453  } else if (opflair == OPFLAIR_GROUP) { /* T2-FLAIR */
454  cvdef(opetl, 24);
455  opetl = _opetl.defval;
456  pietlnub = 63;
457  pietlval2 = 20;
458  pietlval3 = 24;
459  pietlval4 = 28;
460  pietlval5 = 32;
461  pietlval6 = 36;
462  } else if (opflair == OPFLAIR_INTERLEAVED) { /* T1-FLAIR */
463  cvdef(opetl, 8);
464  opetl = _opetl.defval;
465  pietlnub = 63;
466  pietlval2 = 4;
467  pietlval3 = 5;
468  pietlval4 = 6;
469  pietlval5 = 7;
470  pietlval6 = 8;
471  }
472 
473  } else {
474 
475  /* 3D */
476  cvdef(opetl, 32);
477  opetl = _opetl.defval;
478  pietlnub = 63;
479  pietlval2 = 32;
480  pietlval3 = 48;
481  pietlval4 = 64;
482  pietlval5 = 96;
483  pietlval6 = 128;
484  }
485 
486  } /* non-ssfse ETL menu */
487 
488 
489  /* TE */
490  pitetype = PSD_LABEL_TE_EFF; /* alt. PSD_LABEL_TE_EFF */
491  if (! existcv(opte)) {
492  avmaxte = 2s;
493  avminte = 0;
494  cvmin(opte, avminte);
495  cvmax(opte, avmaxte);
496  cvdef(opte, 100ms);
497  opte = _opte.defval;
498  ksfse_eval_TEmenu(10ms /* fake esp */, 200ms /* fake maxte */, opetl, opetl / 2.0);
499  }
500 
501  /* TE2 */
502  pite2nub = 0;
503 
504  /* TI */
505  cvset(opautoti, 0, 1, 1, "");
506  piautoti = 1; /* make 1st menu choice be AutoTI (opautoti = 1) */
507  if (opt1flair) {
508  pitinub = -1;
509  cvoverride(opautoti, 1, PSD_FIX_ON, PSD_EXIST_ON);
510  } else if (opt2flair) {
511  pitinub = 2;
512  } else if (opirprep) {
513  pitinub = 5;
514  pitival2 = 150ms;
515  pitival3 = 200ms;
516  pitival4 = 250ms;
517  pitival5 = 300ms;
518  } else {
519  pitinub = 0;
520  }
521  avminti = 0;
522  avmaxti = 100s;
523  cvset(opti, avminti, avmaxti, 1s, "Inversion time");
524 
525  /* TR */
526  cvdef(optr, 5s);
527  optr = _optr.defval;
528  /*
529  If you want values (pitrval) in the dropdown menu, change to pitrnub = 6;.
530  Remember that you can control the minimum and maximum TR-range
531  from the advanced tab using opuser18 & 19.
532  */
533  pitrnub = 2;
534  pitrval2 = PSD_MINIMUMTR;
535  pitrval3 = 500ms;
536  pitrval4 = 3000ms;
537  pitrval5 = 4000ms;
538  pitrval6 = 5000ms;
539 
540  /* FA of refocusing pulse */
541  cvmax(opflip, 360);
542  cvdef(opflip, 125); /* set it low to avoid init errors on sequence selection */
543  opflip = _opflip.defval;
544 #if EPIC_RELEASE >= 24
545  pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS;
546  pifanub = 5;
547  pifaval2 = 110;
548  pifaval3 = 125;
549  pifaval4 = 140;
550  pifaval5 = 160;
551 #else
552  pifanub = 0;
553 #endif
554 
555  /* slice thickness */
556  pistnub = 5;
557  if (KS_3D_SELECTED) {
558  cvdef(opslthick, 1);
559  pistval2 = 0.8;
560  pistval3 = 0.9;
561  pistval4 = 1;
562  pistval5 = 1.5;
563  pistval5 = 2;
564  } else {
565  cvdef(opslthick, 4);
566  pistval2 = 2;
567  pistval3 = 3;
568  pistval4 = 4;
569  pistval5 = 5;
570  pistval6 = 10;
571  }
572  opslthick = _opslthick.defval;
573 
574  /* slice spacing */
575  cvdef(opslspace, 0);
576  opslspace = _opslspace.defval;
577  piisil = PSD_ON;
578  if (KS_3D_SELECTED) {
579  /* change these to do overlaps */
580  piisnub = 0;
581  piisval2 = 0;
582  } else {
583  piisnub = 5;
584  piisval2 = 0;
585  piisval3 = 0.5;
586  piisval4 = 1;
587  piisval5 = 2;
588  piisval6 = 3;
589  }
590 
591  /* default # of slices */
592  cvdef(opslquant, 30);
593 
594  /* 3D slice settings */
595  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
596  pimultislab = 0; /* 0: forces only single slab, 1: allow multi-slab (won't work with non-selective refocusing pulses) */
597  pilocnub = 4;
598  pilocval2 = 28;
599  pilocval3 = 60;
600  pilocval4 = 124;
601  pilocval5 = 252;
602  /* opslquant = #slices in slab. opvquant = #slabs */
603  cvdef(opslquant, 32);
604  }
605 
606  opslquant = _opslquant.defval;
607 
608  /* Multi phase (i.e. multi volumes) (only active if PSD_IOPT_MPH, not PSD_IOPT_DYNPL) */
609  if (opmph) {
610  pimphscrn = 1; /* display Multi-Phase Parameter screen */
611  pifphasenub = 6;
612  pifphaseval2 = 1;
613  pifphaseval3 = 2;
614  pifphaseval4 = 5;
615  pifphaseval5 = 10;
616  pifphaseval6 = 15;
617  pisldelnub = 0;
618  piacqnub = 0;
619  setexist(opacqo, 1);
620  pihrepnub = 0; /* no XRR gating */
621  } else {
622  cvoverride(opfphases, 1, PSD_FIX_ON, PSD_EXIST_ON);
623  }
624 
625  /* opuser0: show GIT revision (GITSHA) using REV variable from the Imakefile */
626  char userstr[100];
627 #ifdef REV
628  sprintf(userstr, " %s PSD version: %s", _ksfse_flipexc.descr, REV);
629 #else
630  sprintf(userstr, "%s", _ksfse_flipexc.descr);
631 #endif
632  cvmod(opuser0, _ksfse_flipexc.minval, _ksfse_flipexc.maxval, _ksfse_flipexc.defval, userstr, 0, " ");
633  opuser0 = _opuser0.defval;
634  piuset |= use0;
635 
636  /* opuser1: TE based on ETL. */
637  cvmod(opuser1, _ksfse_etlte.minval, _ksfse_etlte.maxval, _ksfse_etlte.defval, _ksfse_etlte.descr, 0, " ");
638  opuser1 = _ksfse_etlte.defval;
639  ksfse_etlte = _ksfse_etlte.defval;
640 
641  if (opssfse) {
642  piuset &= ~use1; /* don't show for SSFSE */
643  } else {
644  piuset |= use1; /* show since not SSFSE */
645  }
646 
647  cvmod(opuser2, _ksfse_inflowsuppression.minval, _ksfse_inflowsuppression.maxval, _ksfse_inflowsuppression.defval, _ksfse_inflowsuppression.descr, 0, " ");
648  piuset |= use2;
649  opuser2 = _ksfse_inflowsuppression.defval;
650 
651 
652  if (opfr == FALSE && (oppseq != PSD_IR /* 3 */ && opirprep == FALSE && opflair == FALSE) && opssfse == FALSE && exist(opetl) > 1) {
653  /* if FSE-XL has been selected, allow T1-w optimization */
654  cvmod(opuser3, 0, 1, 0, "T1-w Optimization [0:OFF 1:ON]", 0, " ");
655  opuser3 = _opuser3.defval;
656  piuset |= use3;
657  } else {
658  opuser3 = 0;
659  piuset &= ~use3;
660  }
661 
662 
663  /* In-range TR support (but without using GE's opinrangetr, since we don't know
664  how to read the AutoTR field values on the Advanced tab. Instead, for now, add two opusers
665  for the range. If any of these are = 0, it is disabled */
666  cvmod(opuser4, _ksfse_mintr.minval/1000, _ksfse_mintr.maxval/1000, _ksfse_mintr.defval/1000, _ksfse_mintr.descr, 0, " "); /* minTR in [ms] */
667  opuser4 = _opuser4.defval;
668  piuset |= use4;
669  cvmod(opuser5, _ksfse_maxtr.minval/1000, _ksfse_maxtr.maxval/1000, _ksfse_maxtr.defval/1000, _ksfse_maxtr.descr, 0, " "); /* maxTR in [ms] */
670  opuser5 = _opuser5.defval;
671  if (opflair == OPFLAIR_GROUP) {
672  piuset &= ~use5; /* Don't show maxTR limit for T2FLAIR */
673  } else {
674  piuset |= use5;
675  }
676 
677  if (opflair != OPFLAIR_GROUP) {
678  _rf_stretch_all.defval = 1.5; /* Wider default (except for T2FLAIR which is less SAR heavy) to shorten the scan time (less SAR penalty) */
679  } else {
680  _rf_stretch_all.defval = 1.0;
681  }
682  cvmod(opuser6, 1.0, _rf_stretch_all.maxval, _rf_stretch_all.defval, _rf_stretch_all.descr, 0, " ");
683  opuser6 = _rf_stretch_all.defval;
684  piuset |= use6;
685 
686  /* T1-value */
687  float default_t1value;
688  if (opt1flair || opt2flair) {
689  default_t1value = (cffield >= 30000) ? T1_CSF_3T : T1_CSF_1_5T;
690  } else {
691  default_t1value = (cffield >= 30000) ? T1_FAT_3T : T1_FAT_1_5T;
692  }
693  cvset(opuser7, KS_NOTSET, 10000, default_t1value/1000, "T1-value to null [ms]");
694  if (ANYINVERSION && opautoti) {
695  piuset |= use7;
696  if (opuser7 <= 0) {
697  (opuser7) = default_t1value/1000;
698  }
699  } else {
700  piuset &= ~use7;
701  setfix(opuser7, FALSE);
702  }
703 
704  if (oparc) {
705  /* Acceleration menu as decimal numbers (max accel = 4) */
707  } else {
708  /* Acceleration menu as integers (max accel = 4)
709  Covers the non-accelerated and ASSET cases */
711  }
712 
713 
714  return SUCCESS;
715 
716 } /* ksfse_init_UI() */
int piuset
#define T1_FAT_3T
Definition: ksinversion.h:43
Definition: KSFoundation.h:2337
int opxres
int opyres
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
#define KS_NOTSET
Definition: KSFoundation.h:115
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
int numlinestoacq
Definition: KSFoundation.h:1727
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
Definition: KSFoundation.h:2337
#define T1_CSF_1_5T
Definition: ksinversion.h:38
float opfov
#define T1_CSF_3T
Definition: ksinversion.h:37
#define T1_FAT_1_5T
Definition: ksinversion.h:44
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380
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
#define ANYINVERSION
Definition: KSFoundation.h:346
float opslthick
void ksfse_eval_TEmenu(int esp, int maxte, int etl, double optechono)
Sets up the TE menu based on echo spacing, max TE, ETL and the optimal echo index
Definition: ksfse_implementation.e:850
_cvint _optr
int ksfse_etlte
Definition: ksfse_implementation.e:119

◆ ksfse_eval_UI()

STATUS ksfse_eval_UI ( )

Gets the current UI and checks for valid inputs

Return values
STATUSSUCCESS or FAILURE
735  {
736 
737  STATUS status;
738 
739  status = ksfse_init_UI();
740  KS_RAISE(status);
741 
742 
743 
744  /*** Copy UserCVs to human readable CVs ***/
745  ksfse_flipexc = opuser0;
746 
747  ksfse_etlte = (int) opuser1;
748  if (ksfse_etlte != PSD_OFF && ksfse_etlte != PSD_ON) {
749  return ks_error("'ETL controls TE' flag must be either [0:OFF, 1:ON]"); /* User error */
750  }
751 
752  if (existcv(opetl)) {
753  /* if ETL has been selected, adjust TR menu to either T1-w or T2-w mode */
754  if (exist(opetl) < 6) {
755  pitrval3 = 450ms;
756  pitrval4 = 500ms;
757  pitrval5 = 550ms;
758  pitrval6 = 600ms;
759  } else {
760  pitrval3 = 2500ms;
761  pitrval4 = 3000ms;
762  pitrval5 = 4000ms;
763  pitrval6 = 5000ms;
764  }
765  }
766 
767  /* Inflow suppression (only if spacing or multiple acqs) */
768  if (existcv(opslquant) && (opslspace > 0.0 || avmaxacqs > 1)) {
769  ksfse_inflowsuppression = opuser2;
770  } else {
771  cvoverride(ksfse_inflowsuppression, 0, PSD_FIX_OFF, PSD_EXIST_ON);
772  }
773  if (ksfse_inflowsuppression > 0) {
774  cvdesc(opuser2, "In-flow suppression 0:OFF [1:ON]"); /* Highlight ON */
775  } else {
776  cvdesc(opuser2, "In-flow suppression [0:OFF] 1:ON"); /* Highlight OFF */
777  }
778 
779  /* Fast recovery / T1w optimization */
780  if (opuser3 > 0) {
782  } else if (opfr) {
784  } else {
785  ksfse_recovery = 0;
786  }
787 
788  /* Min/Max TR */
789  {
790  (ksfse_mintr) = IMax(2, 0, RUP_GRD((int) opuser4 * 1000)); /* in [us] */
791  (ksfse_maxtr) = IMax(2, 0, RUP_GRD((int) opuser5 * 1000)); /* in [us] */
792 
793  char tmpstr[100];
794  sprintf(tmpstr, "Min TR (ms) [0: Auto]");
795  if (opflair == OPFLAIR_GROUP) {
796  /* T2FLAIR */
797  cvdesc(opuser4, tmpstr);
798  sprintf(tmpstr, "Min TR (ms) [0: Disabled]");
799  cvdesc(opuser5, tmpstr);
800  } else if (opflair == OPFLAIR_INTERLEAVED) {
801  /* T1FLAIR */
802  sprintf(tmpstr, "Min TR (ms) [0: Auto]");
803  cvdesc(opuser4, tmpstr);
804  } else {
805  sprintf(tmpstr, "Min TR (ms) [0: Disabled]");
806  cvdesc(opuser4, tmpstr);
807  cvdesc(opuser5, tmpstr);
808  }
809  }
810 
811  /* overall RF pulse stretching */
812  rf_stretch_all = opuser6;
813 
814 
815  /* Reserved opusers:
816  -----------------
817  ksfse_eval_inversion(): opuser26-29
818  GE reserves: opuser36-48 (epic.h)
819  */
820 
821  return SUCCESS;
822 
823 } /* ksfse_eval_UI() */
int ksfse_recovery
Definition: ksfse_implementation.e:109
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float rf_stretch_all
Definition: ksfse_implementation.e:104
int ksfse_inflowsuppression
Definition: ksfse_implementation.e:93
float ksfse_flipexc
Definition: ksfse_implementation.e:90
int ksfse_maxtr
Definition: ksfse_implementation.e:140
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksfse_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksfse_implementation.e:310
Definition: ksfse_implementation.e:45
int ksfse_mintr
Definition: ksfse_implementation.e:139
Definition: ksfse_implementation.e:45
int ksfse_etlte
Definition: ksfse_implementation.e:119

◆ ksfse_eval_esp()

int ksfse_eval_esp ( int *  min90_180,
int *  min180_echo,
int  slicecheck,
KSFSE_SEQUENCE seq 
)

Calculates echo spacing for the sequence

Parameters
[out]min90_180Pointer to the time between moment start of the excitation pulse to the center of the refocusing pulse in [us]
[out]min180_echoPointer to the time between center of the refocusing pulse to the center of the first echo in [us]
[in]slicecheck0: Normal mode 1: Slice check mode, where the readout is moved to the slice axis
[in]seqPointer to KSFSE_SEQUENCE
Return values
echospacingEcho Spacing in [us]
901  {
902  int echospacing;
903 
904  /*** minimum time needed between RF exc center to RF ref center ***/
905  /* latter portion of RF pulse incl ramptime of slice sel grad */
906  *min90_180 = seq->selrfexc.rf.iso2end;
907  if (slicecheck) {
908  /* need separate time for read dephaser */
909  *min90_180 += seq->selrfexc.rf2grad_end + seq->readdephaser.duration +
911  } else {
912  /* max of seq->readdephaser and time from end of rfexc grad plateau to beginning of plateau for rfrefocus */
913  *min90_180 += IMax(2,
914  seq->readdephaser.duration /* X */,
915  seq->selrfexc.rf2grad_end + seq->selrfref1st.grad2rf_start /* Z */);
916  }
917  *min90_180 += seq->selrfref1st.rf.start2iso; /* slice selection time until RF center */
918 
919  /*** minimum time needed between RF ref center and echo center ***/
920  KS_SELRF *selrf[3] = {&seq->selrfref1st, NULL, NULL};
921  if (opetl > 1) {
922  selrf[1] = &seq->selrfref2nd;
923  }
924  if (opetl > 2) {
925  selrf[2] = &seq->selrfref;
926  }
927 
928  int i = 0;
929  *min180_echo = 0;
930  for (; i<3; ++i) {
931 
932  if (!selrf[i]) {
933  continue;
934  }
935 
936  int _min180_echo = selrf[i]->rf.iso2end;
937  if (slicecheck) {
938  _min180_echo += IMax(2,
939  seq->phaseenc.grad.duration - seq->read.acqdelay + seq->read.time2center /* Y */,
940  selrf[i]->rf2grad_end + seq->zphaseenc.grad.duration + seq->read.time2center /* Z */);
941  } else {
942  _min180_echo += IMax(3,
943  seq->read.acqdelay /* X */,
944  seq->phaseenc.grad.duration /* Y */,
945  selrf[i]->rf2grad_end + seq->zphaseenc.grad.duration /* Z */);
946  }
947  _min180_echo += seq->read.time2center - seq->read.acqdelay; /* time from start of acquisition to k-space center */
948 
949  *min180_echo = IMax(2, *min180_echo, _min180_echo);
950  }
951 
952  echospacing = IMax(2, *min90_180, *min180_echo) * 2;
953  echospacing = RUP_FACTOR(echospacing, 16);
954 
955  return echospacing;
956 
957 } /* ksfse_eval_esp() */
int start2iso
Definition: KSFoundation.h:1032
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
Composite sequence object for slice-selective RF
Definition: KSFoundation.h:1453
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
KS_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
KS_READTRAP read
Definition: ksfse_implementation.e:58
int grad2rf_start
Definition: KSFoundation.h:1466
KS_TRAP readdephaser
Definition: ksfse_implementation.e:59
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
int iso2end
Definition: KSFoundation.h:1033
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
int time2center
Definition: KSFoundation.h:1560
int acqdelay
Definition: KSFoundation.h:1555

◆ ksfse_eval_optimalkxnover()

int ksfse_eval_optimalkxnover ( KSFSE_SEQUENCE seq)

Calculates the optimal number of k-space points for partial kx Fourier that does not increase TE

This function plays by the following rules:

  1. CV ksfse_kxnover_min is the lowest number of samples allowed
  2. ksfse.read.res/2 is the highest number of samples allowed
  3. Increase kxnover until an increase in TE results, while staying within above limits
Parameters
[in]seqPointer to the KSFSE_SEQUENCE struct holding all sequence objects
Return values
kxnoverOptimal number of k-space points beyond half k-space for partial kx Fourier scans.
974  {
975 
976  int min90_180 = 0; /* [us] */
977  int min180_echo = 0; /* [us] */
978  int kxnover = 0; /* samples */
979 
980  ksfse_eval_esp(&min90_180, &min180_echo, ksfse_slicecheck, seq);
981 
982  if (seq->read.nover) {
983  /* we are currently using partial Fourier, adjust kxnover to balance the time before and after
984  the refocusing pulse */
985  kxnover = seq->read.nover + ((min90_180 - min180_echo) / ks_calc_bw2tsp(seq->read.acq.rbw));
986  } else {
987  /* we are currently using full Fourier (read.nover = 0) */
988  if (min90_180 > min180_echo) {
989  /* more time needed before the 180 anyway, no need to do partial Fourier */
990  kxnover = seq->read.res / 2;
991  } else {
992  kxnover = seq->read.res / 2 - ((min180_echo - min90_180) / ks_calc_bw2tsp(seq->read.acq.rbw));
993  }
994  }
995 
996  /* keep in range */
997  if (kxnover < ksfse_kxnover_min) {
998  kxnover = ksfse_kxnover_min;
999  } else if (kxnover > seq->read.res / 2) {
1000  kxnover = seq->read.res / 2;
1001  }
1002 
1003  kxnover = RUP_GRD(kxnover);
1004 
1005  return kxnover;
1006 
1007 } /* ksfse_eval_optimalkxnover() */
int ksfse_eval_esp(int *min90_180, int *min180_echo, int slicecheck, KSFSE_SEQUENCE *seq)
Calculates echo spacing for the sequence
Definition: ksfse_implementation.e:901
KS_READTRAP read
Definition: ksfse_implementation.e:58
float rbw
Definition: KSFoundation.h:842
int ksfse_kxnover_min
Definition: ksfse_implementation.e:115
int res
Definition: KSFoundation.h:1552
int ks_calc_bw2tsp(float bw)
Convert receiver bandwidth to dwell time
Definition: KSFoundation_host.c:6197
int nover
Definition: KSFoundation.h:1554
KS_READ acq
Definition: KSFoundation.h:1549
int ksfse_slicecheck
Definition: ksfse_implementation.e:102

◆ ksfse_eval_rfstretchfactor()

float ksfse_eval_rfstretchfactor ( float  patientweight,
float  flipangle,
int  tailoredrf_flag 
)

Empricial RF stretch factor for the ksfse refocusing RF pulses based on patient weight and flip angle

This function returns a suitable scale factor for the duration of the RF refocusing pulse to keep the SAR within limits for different patient weights and flip angles.

The function is called from ksfse_eval_setuprfpulses_2D().

Parameters
[in]patientweightPatien weight [kg]
[in]flipangleFlip angle [degrees]
[in]tailoredrf_flagTailored RF flag
Return values
floatRF stretch factor
1027  {
1028  float rfstretchfactor = 1.0;
1029  float flipangle_factor = 1.0;
1030  float patientweight_factor = FMax(2, 1.0, patientweight * 0.0055 + 0.6); /* 1.0 at around 75 kg, never less than 0 */
1031 
1032  if (tailoredrf_flag) {
1033  /* Empirical 2D plane as a function of patient weight and flip angle (for RF pulse set ref_fse1601/2/n)
1034  Important to not let it below ~0.6 when flipangle or patient weight is too small */
1035  flipangle_factor = FMax(2, 0.6, 0.0035 * flipangle + 0.15);
1036  rfstretchfactor = flipangle_factor * patientweight_factor;
1037  } else {
1038  /* Empirical 2D plane as a function of patient weight and flip angle (for RF pulse set ref_se1b4)
1039  Important to not let it below ~0.6 when flipangle or patient weight is too small */
1040  flipangle_factor = FMax(2, 0.6, 0.0080 * flipangle - 0.10);
1041  rfstretchfactor = flipangle_factor * patientweight_factor;
1042  }
1043 
1044  if (rfstretchfactor < 0.6)
1045  rfstretchfactor = 0.6; /* extra level of safety */
1046 
1047  return rfstretchfactor;
1048 
1049 } /* ksfse_eval_rfstretchfactor() */

◆ ksfse_eval_setuprfpulses_2D()

STATUS ksfse_eval_setuprfpulses_2D ( KSFSE_SEQUENCE seq,
float  crusher_dephasing 
)

Sets up the RF objects for the ksfse sequence (2D)

This function attempts to mimick the RF scaling and flip angle varation performed in the product fsemaster.e psd, with and without the tailored RF (optlrdrf) option. It is called from ksfse_eval_setupobjects() to set up the RF pulses.

Parameters
[out]seqPointer to the KSFSE_SEQUENCE struct holding all sequence objects
[in]crusher_dephasingThe amount of crusher_dephasing in [cycles] for refocusing pulses
Return values
STATUSSUCCESS or FAILURE
1066  {
1067  STATUS status;
1068 
1069  /* Clear potential gradient waveforms in the KS_SELRF objects before we choose our RF pulses */
1074 
1075  /*******************************************************************************************************
1076  * RF Selections. Flip angle and slice thickness tweaks
1077  *******************************************************************************************************/
1078 
1080 
1081  if (optlrdrf == TRUE || opetl > 2) {
1082  seq->selrfexc.rf = exc_fse90; /* Excitation */
1083  seq->selrfref1st.rf = ref_fse1601; /* 1st Refocusing */
1084  seq->selrfref2nd.rf = ref_fse1602; /* 2nd Refocusing */
1085  seq->selrfref.rf = ref_fse160n; /* 3->ETL Refocusing */
1086  ksfse_gscalerfexc = 0.8;
1088  } else {
1089  seq->selrfexc.rf = exc_fl901mc;
1090  seq->selrfref1st.rf = ref_se1b4;
1091  seq->selrfref2nd.rf = ref_se1b4;
1092  seq->selrfref.rf = ref_se1b4;
1093  ksfse_gscalerfexc = 0.9;
1095  }
1096 
1097  /* Stretch factors for RF refocusing pulses */
1098  rf_stretch_rfref = ksfse_eval_rfstretchfactor(opweight, opflip, optlrdrf);
1100 
1101 #if EPIC_RELEASE >= 26
1102  if (opsarmode == 0) { /* normal mode */
1103  rf_stretch_all *= 1.6;
1104  } else if (opsarmode == 3) { /* low SAR mode */
1105  rf_stretch_all *= 3;
1106  }
1107 #endif
1108 
1109  /* Set flip angles */
1110  if (optlrdrf == TRUE && opetl > 2) {
1111  seq->selrfref1st.rf.flip = opflip + 0.6032 * (180.0 - opflip);
1112  seq->selrfref2nd.rf.flip = opflip + 0.1032 * (180.0 - opflip);
1113  seq->selrfref.rf.flip = opflip;
1114  } else {
1115  seq->selrfref1st.rf.flip = opflip;
1116  seq->selrfref2nd.rf.flip = opflip;
1117  seq->selrfref.rf.flip = opflip;
1118  }
1119 
1120 
1121  /*******************************************************************************************************
1122  * RF Excitation
1123  *******************************************************************************************************/
1125 
1126  /* Optional widening of the excitation pulse when we have slice gap or
1127  interleaved (opileave) slice mode where odd slices are completed and reconstructed
1128  before playing out the even slices */
1130  if (ksfse_inflowsuppression_mm <= 0) {
1131  /* ksfse_inflowsuppression_mm = 0 => auto thickness */
1132  int intleavefact = IMax(2, 1, avmaxacqs);
1133  float newthick = intleavefact * (ksfse_excthickness + opslspace);
1134  newthick = FMax(2, seq->selrfexc.slthick, newthick); /* to handle case where newthick is smaller */
1135  /* up to the case where newthick is three times the slice thickness */
1137  } else {
1138  /* ksfse_inflowsuppression_mm > 0: the user wants to specify how many mm extra the excitation
1139  thickness should be */
1141  }
1142  }
1143 
1144  seq->selrfexc.rf.flip = ksfse_flipexc; /* value from opuser0 */
1145 
1147  KS_RAISE(status);
1148 
1149  status = ks_eval_selrf(&seq->selrfexc, "rfexc");
1150  KS_RAISE(status);
1151 
1152  /*******************************************************************************************************
1153  * RF Refocusing (1st echo)
1154  *******************************************************************************************************/
1156 
1158  KS_RAISE(status);
1159 
1160  /* Left crusher: Merge excitation rephaser into left crusher */
1161  /* N.B.: Right crusher will be embedded in zphasenc in ksfse_eval_setupobjects() */
1162  seq->selrfref1st.pregrad_area_offset = seq->selrfexc.postgrad.area; /* note: postgrad.area is negative ! */
1163 
1164  /* disable the rephaser of the excitation */
1166  seq->selrfexc.postgrad.duration = 0;
1167 
1168  seq->selrfref1st.crusher_dephasing = crusher_dephasing;
1169  status = ks_eval_selrf(&seq->selrfref1st, "rfref1st");
1170  KS_RAISE(status);
1171 
1172  /*******************************************************************************************************
1173  * RF Refocusing (2nd echo)
1174  *******************************************************************************************************/
1176  seq->selrfref2nd.crusher_dephasing = crusher_dephasing;
1177 
1179  KS_RAISE(status);
1180 
1181  status = ks_eval_selrf(&seq->selrfref2nd, "rfref2nd");
1182  KS_RAISE(status);
1183 
1184  /*******************************************************************************************************
1185  * RF Refocusing (3rd-Nth echo)
1186  *******************************************************************************************************/
1188  seq->selrfref.crusher_dephasing = crusher_dephasing;
1189 
1191  KS_RAISE(status);
1192 
1193  status = ks_eval_selrf(&seq->selrfref, "rfref");
1194  KS_RAISE(status);
1195 
1196  return SUCCESS;
1197 
1198 } /* ksfse_eval_setuprfpulses_2D() */
float ksfse_inflowsuppression_mm
Definition: ksfse_implementation.e:94
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
float pregrad_area_offset
Definition: KSFoundation.h:1459
STATUS ks_eval_selrf(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with preset gradient constraints
Definition: KSFoundation_host.c:3312
float ksfse_excthickness
Definition: ksfse_implementation.e:88
KS_WAVE gradwave
Definition: KSFoundation.h:1465
float ksfse_gscalerfexc
Definition: ksfse_implementation.e:89
float crusher_dephasing
Definition: KSFoundation.h:1457
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
float rf_stretch_all
Definition: ksfse_implementation.e:104
float flip
Definition: KSFoundation.h:1028
int ksfse_inflowsuppression
Definition: ksfse_implementation.e:93
DECL_TYPE KS_RF ref_fse160n
Definition: KSFoundation_GERF.c:1621
float ksfse_flipexc
Definition: ksfse_implementation.e:90
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
float ksfse_gscalerfref
Definition: ksfse_implementation.e:101
DECL_TYPE KS_RF exc_fse90
Definition: KSFoundation_GERF.c:291
float area
Definition: KSFoundation.h:670
#define KSFSE_MAXTHICKFACT
Definition: ksfse_implementation.e:43
#define KS_RAISE(status)
Definition: KSFoundation.h:190
DECL_TYPE KS_RF ref_fse1602
Definition: KSFoundation_GERF.c:1547
KS_TRAP postgrad
Definition: KSFoundation.h:1464
float rf_stretch_rfexc
Definition: ksfse_implementation.e:92
float ksfse_eval_rfstretchfactor(float patientweight, float flipangle, int tailoredrf_flag)
Empricial RF stretch factor for the ksfse refocusing RF pulses based on patient weight and flip angle...
Definition: ksfse_implementation.e:1027
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
DECL_TYPE KS_RF ref_se1b4
Definition: KSFoundation_GERF.c:1399
DECL_TYPE KS_RF ref_fse1601
Definition: KSFoundation_GERF.c:1473
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
float opslthick
STATUS ks_eval_stretch_rf(KS_RF *rf, float stretch_factor)
In-place stretching of a KS_RF object
Definition: KSFoundation_host.c:3928
void ks_init_wave(KS_WAVE *wave)
Resets a KS_WAVE sequence object to its default value (KS_INIT_WAVE)
Definition: KSFoundation_host.c:78
float rf_stretch_rfref
Definition: ksfse_implementation.e:103
DECL_TYPE KS_RF exc_fl901mc
Definition: KSFoundation_GERF.c:217
float slthick
Definition: KSFoundation.h:1456

◆ ksfse_eval_setuprfpulses_3D()

STATUS ksfse_eval_setuprfpulses_3D ( KSFSE_SEQUENCE seq)

Sets up the RF objects for the ksfse sequence (3D)

Parameters
[in]seqPointer to the KSFSE_SEQUENCE struct holding all sequence objects
Return values
STATUSSUCCESS or FAILURE
1210  {
1211  STATUS status;
1212 
1213  /* GE defines (epic.h) for opexcitemode:
1214  SELECTIVE 0, NON_SELECTIVE 1, FOCUS 2 */
1215  const float hardpulse_duration = 1ms;
1216 
1217  /* Clear potential gradient waveforms in the KS_SELRF objects before we choose our RF pulses */
1222 
1223  cvoverride(opvthick, exist(opslquant) * exist(opslthick), _opslquant.fixedflag, existcv(opslquant));
1224  ksfse_excthickness = (exist(opslquant) - 2 * rhslblank) * exist(opslthick);
1225  ksfse_gscalerfexc = 1.0;
1226 
1227 
1228  /*******************************************************************************************************
1229  * RF Excitation
1230  *******************************************************************************************************/
1231  if (opexcitemode == NON_SELECTIVE) {
1232  /* Non-selective 90 hard excitaion */
1233  status = ks_eval_rf_hard(&seq->selrfexc.rf, "rfexc", hardpulse_duration, 90);
1234  KS_RAISE(status);
1235  seq->selrfexc.rf.role = KS_RF_ROLE_EXC;
1236  } else {
1237  /* Selective 90 using a sharp high-BW minimum phase excitation pulse */
1238  seq->selrfexc.rf = exc_3dfgre;
1239  seq->selrfexc.rf.flip = 90.0;
1240  }
1241 
1242  seq->selrfexc.slthick = ksfse_excthickness / ksfse_gscalerfexc * (opexcitemode != NON_SELECTIVE);
1243 
1245  KS_RAISE(status);
1246 
1247  status = ks_eval_selrf(&seq->selrfexc, "rfexc");
1248  KS_RAISE(status);
1249 
1250  /*******************************************************************************************************
1251  * RF Refocusing (1st echo)
1252  *******************************************************************************************************/
1253  status = ks_eval_rf_hard(&seq->selrfref1st.rf, "rfref1st", hardpulse_duration, opflip);
1254  KS_RAISE(status);
1256 
1257  seq->selrfref1st.slthick = 0; /* N.B.: sel gradient = 0 if .selrfref1st.slthick = 0 (ks_eval_selrf()) */
1258 
1260  KS_RAISE(status);
1261 
1263 
1264  /* Left crusher: Merge excitation rephaser into left crusher */
1265  /* N.B.: Right crusher will be embedded in zphasenc in ksfse_eval_setupobjects() */
1266  seq->selrfref1st.pregrad_area_offset += seq->selrfexc.postgrad.area; /* note: postgrad.area is negative ! */
1267 
1268  status = ks_eval_selrf(&seq->selrfref1st, "rfref1st");
1269  KS_RAISE(status);
1270 
1271  /* disable the rephaser of the excitation */
1272  seq->selrfexc.postgrad.duration = 0;
1274 
1275  /*******************************************************************************************************
1276  * RF Refocusing (2nd echo)
1277  *******************************************************************************************************/
1278  seq->selrfref2nd.rf = seq->selrfref1st.rf;
1279  seq->selrfref2nd.slthick = seq->selrfref1st.slthick;
1281  status = ks_eval_selrf(&seq->selrfref2nd, "rfref2nd");
1282  KS_RAISE(status);
1283 
1284  /*******************************************************************************************************
1285  * RF Refocusing (3rd-Nth echo)
1286  *******************************************************************************************************/
1287  seq->selrfref.rf = seq->selrfref1st.rf;
1288  seq->selrfref.slthick = seq->selrfref1st.slthick;
1290  status = ks_eval_selrf(&seq->selrfref, "rfref");
1291  KS_RAISE(status);
1292 
1293 
1294  /*******************************************************************************************************
1295  * Disable pre/postgrads by setting their duration to 0
1296  * The crusher area will be merged in zphaseenc
1297  *******************************************************************************************************/
1298  seq->selrfref1st.postgrad.duration = 0; /* right crusher only */
1299  seq->selrfref2nd.pregrad.duration = 0;
1300  seq->selrfref2nd.postgrad.duration = 0;
1301  seq->selrfref.pregrad.duration = 0;
1302  seq->selrfref.postgrad.duration = 0;
1303 
1304  return SUCCESS;
1305 
1306 } /* ksfse_eval_setuprfpulses_3D() */
float ksfse_crusher_dephasing
Definition: ksfse_implementation.e:100
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
float pregrad_area_offset
Definition: KSFoundation.h:1459
int role
Definition: KSFoundation.h:1027
STATUS ks_eval_selrf(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with preset gradient constraints
Definition: KSFoundation_host.c:3312
float ksfse_excthickness
Definition: ksfse_implementation.e:88
KS_WAVE gradwave
Definition: KSFoundation.h:1465
float ksfse_gscalerfexc
Definition: ksfse_implementation.e:89
float crusher_dephasing
Definition: KSFoundation.h:1457
Definition: KSFoundation.h:2340
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
Definition: KSFoundation.h:2340
float rf_stretch_all
Definition: ksfse_implementation.e:104
float flip
Definition: KSFoundation.h:1028
KS_TRAP pregrad
Definition: KSFoundation.h:1462
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
DECL_TYPE KS_RF exc_3dfgre
Definition: KSFoundation_GERF.c:587
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP postgrad
Definition: KSFoundation.h:1464
float rf_stretch_rfexc
Definition: ksfse_implementation.e:92
STATUS ks_eval_rf_hard(KS_RF *rf, const char *const desc, int duration, float flip) WARN_UNUSED_RESULT
Sets up a KS_RF object with a rectangular (hard) pulse of a given duration
Definition: KSFoundation_host.c:2361
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
float opslthick
STATUS ks_eval_stretch_rf(KS_RF *rf, float stretch_factor)
In-place stretching of a KS_RF object
Definition: KSFoundation_host.c:3928
void ks_init_wave(KS_WAVE *wave)
Resets a KS_WAVE sequence object to its default value (KS_INIT_WAVE)
Definition: KSFoundation_host.c:78
float rf_stretch_rfref
Definition: ksfse_implementation.e:103
float slthick
Definition: KSFoundation.h:1456

◆ ksfse_eval_setuprfpulses_recovery()

STATUS ksfse_eval_setuprfpulses_recovery ( KSFSE_SEQUENCE seq)

Sets up .selrfrecover and .selrfrecoverref for fast T1 recovery based on .selrfexc and .selrfref

Using ksfse.selrfexc and ksfse.selrfref as templates, this function sets up the RF pulses for fast recovery after the FSE train, which is controlled by the CV ksfse_recovery. The .selrfrecover pulse is a mirrored version of .selrfexc.

Parameters
[in,out]seqPointer to KSFSE_SEQUENCE
Return values
STATUSSUCCESS or FAILURE
1322  {
1323  STATUS status;
1324 
1327 
1328  /*******************************************************************************************************
1329  * Post-ETL forced recovery: T1-w Optimization / T2 fast Recovery
1330  *******************************************************************************************************/
1331 
1332  /* Recovery "negative" excitation (selrfrecover) */
1333  seq->selrfrecover.rf = seq->selrfexc.rf; /* already potentially RF-stretched */
1334  seq->selrfrecover.slthick = seq->selrfexc.slthick;
1335 
1336  status = ks_eval_selrf(&seq->selrfrecover, "rfrecover");
1337  if (status != SUCCESS ) return status;
1338 
1339  /* no postgrad by setting duration = 0 (or pregrad either since KS_RF_ROLE_EXC) */
1340  seq->selrfrecover.postgrad.duration = 0;
1341 
1342  /* Mirror RF wave using "-1" (negative stretch factor), will mirror the excitation RF pulse waveform */
1343  status = ks_eval_stretch_rf(&seq->selrfrecover.rf, -1);
1344  KS_RAISE(status);
1345 
1346 
1347  /* Recovery refocusing (selrfrecoverref). Use flip angle and design from 'selrfref.rf' but left crusher
1348  area from selrfref1st.pregrad.area */
1349  seq->selrfrecoverref.rf = seq->selrfref.rf;
1352  status = ks_eval_selrf(&seq->selrfrecoverref, "rfrecoverref");
1353  KS_RAISE(status);
1354 
1355  if (KS_3D_SELECTED) {
1356  seq->selrfrecoverref.pregrad.duration = 0; /* zphaseenc.areaoffset takes over */
1357  }
1358 
1361  KS_RAISE(status);
1362 
1363  return SUCCESS;
1364 
1365 } /* ksfse_eval_setuprfpulses_recovery() */
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
STATUS ks_eval_selrf(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with preset gradient constraints
Definition: KSFoundation_host.c:3312
KS_WAVE gradwave
Definition: KSFoundation.h:1465
float crusher_dephasing
Definition: KSFoundation.h:1457
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_TRAP pregrad
Definition: KSFoundation.h:1462
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
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
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP postgrad
Definition: KSFoundation.h:1464
KS_DESCRIPTION description
Definition: KSFoundation.h:668
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
int duration
Definition: KSFoundation.h:673
STATUS ks_eval_stretch_rf(KS_RF *rf, float stretch_factor)
In-place stretching of a KS_RF object
Definition: KSFoundation_host.c:3928
void ks_init_wave(KS_WAVE *wave)
Resets a KS_WAVE sequence object to its default value (KS_INIT_WAVE)
Definition: KSFoundation_host.c:78
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67
float slthick
Definition: KSFoundation.h:1456

◆ ksfse_eval_ssitime()

int ksfse_eval_ssitime ( )

Set the SSI time for the sequence

Return values
intSSI time in [us]
1376  {
1377 
1378  /* SSI time CV:
1379  Empirical finding as a function of etl on how much SSI time we need to update.
1380  But, use a longer SSI time when we write out data to file in scan() */
1381  ksfse_ssi_time = RUP_GRD(IMax(2, KSFSE_MIN_SSI_TIME + 13 * opetl, _ksfse_ssi_time.minval));
1382 
1383  /* Copy SSI CV to seqctrl field used by setssitime() */
1385 
1386  /* SSI time one-sequence-off workaround:
1387  We set the hardware ssitime in ks_scan_playsequence(), but it acts on the next sequence module, hence
1388  we aren't doing this correctly when using multiple sequence modules (as KSChemSat etc).
1389  One option would be to add a short dummy sequence ks_scan_playsequence(), but need to investigate
1390  if there is a better way. For now, let's assume the the necessary update time is the longest for
1391  the main sequence (this function), and let the ssi time for all other sequence modules (KSChemSat etc)
1392  have the same ssi time as the main sequence. */
1394 
1395  return ksfse_ssi_time;
1396 
1397 } /* ksfse_eval_ssitime() */
int ksfse_ssi_time
Definition: ksfse_implementation.e:134
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
#define KSFSE_MIN_SSI_TIME
Definition: ksfse_implementation.e:42
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
int ssi_time
Definition: KSFoundation.h:1226
int kssat_ssi_time
Definition: kssat.e:118

◆ ksfse_eval_setupobjects()

STATUS ksfse_eval_setupobjects ( )

Sets up all sequence objects for the main sequence module (KSFSE_SEQUENCE ksfse)

This function will set up all objects for the main sequence module (ksfse) via a mix of UI CVs and other CVs. This effectively sets the shape (amp, ramptimes & duration) of each trapezoid and waveform in the sequence for later placement in ksfse_pg().

For the RF pulse evaluation, this function calls either ksfse_eval_setuprfpulses_3D() or ksfse_eval_setuprfpulses_2D() depending on the 2D/3D mode.

Return values
STATUSSUCCESS or FAILURE
1415  {
1416  STATUS status;
1417 
1418  /* phase encoding gradient */
1419  ksfse.phaseenc.fov = opfov * opphasefov;
1420  ksfse.phaseenc.res = RUP_FACTOR((int) (opyres * opphasefov), 2); /* round up (RUP) to nearest multiple of 2 */
1421 
1422  if (opnex < 1) {
1423  int kynover;
1424  kynover = ksfse.phaseenc.res * (opnex - 0.5);
1425  kynover = ((kynover + 1) / 2) * 2; /* round to nearest even number */
1426  if (kynover < KSFSE_MINHNOVER)
1427  kynover = KSFSE_MINHNOVER; /* protect against too few overscans */
1428  ksfse.phaseenc.nover = IMin(2, kynover, ksfse.phaseenc.res / 2);
1429  } else {
1430  ksfse.phaseenc.nover = 0;
1431  }
1432 
1433  /* Readout gradient and data acquisition */
1434  ksfse.read.fov = opfov;
1435  ksfse.read.res = RUP_FACTOR(opxres, 2); /* Round UP to nearest multiple of 2 */
1436 
1438  if (ksfse.read.rampsampling) {
1439  ksfse.read.acqdelay = 16; /* us on the ramp until acq should begin */
1440  }
1441  if (opautote == PSD_MINTE && opnex >= 1) { /* PSD_MINTE = 2 */
1442  ksfse_kxnover = ksfse_eval_optimalkxnover(&ksfse); /* Partial Fourier */
1444  } else {
1445  ksfse.read.nover = 0; /* Full Fourier */
1446  }
1447  ksfse.read.acq.rbw = oprbw;
1449  status = ks_eval_readtrap(&ksfse.read, "read");
1450  KS_RAISE(status);
1451 
1452  /* read dephaser */
1454  status = ks_eval_trap(&ksfse.readdephaser, "readdephaser");
1455  KS_RAISE(status);
1456 
1457  /* set .R and .nacslines fields of ksfse.phaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
1458  if (opasset) {
1459  cvoverride(ksfse_minacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
1460  } else if (oparc) {
1461  ksfse_minacslines = _ksfse_minacslines.defval;
1462  }
1463  status = ks_eval_phaser_setaccel(&ksfse.phaseenc, ksfse_minacslines, opaccel_ph_stride);
1464  KS_RAISE(status);
1465 
1466  status = ks_eval_phaser(&ksfse.phaseenc, "phaseenc");
1467  KS_RAISE(status);
1468 
1469  /* setup RF pulses in FSE train */
1470  if (KS_3D_SELECTED) {
1472  KS_RAISE(status);
1473  } else {
1474  /* when quietness factor is used, find the crusher_dephasing that minimizes the echo spacing (esp) */
1475  if (ks_qfact > 1) {
1476  int dummy1, dummy2;
1477  float c;
1478  float optc = 2.0;
1479  int optesp = 1s;
1480  int my_esp = KS_NOTSET;
1481  for (c = 3.0; c < 10.0; c += 1.0) {
1482  status = ksfse_eval_setuprfpulses_2D(&ksfse, c);
1483  KS_RAISE(status);
1484  my_esp = ksfse_eval_esp(&dummy1, &dummy2, FALSE, &ksfse);
1485  if (my_esp <= optesp) {
1486  optesp = my_esp;
1487  optc = c;
1488  }
1489  }
1490  ksfse_crusher_dephasing = optc;
1491  }
1493  KS_RAISE(status);
1494  }
1495 
1496 
1497  /* z phase encoding gradient (N.B. 3D is not yet implemented in this sequence) */
1498  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
1499 
1500  /* Move crushers area from selrf.pregrad/postgrad to zphasenc.areaoffset */
1502  ksfse.zphaseenc.fov = opvthick;
1503  ksfse.zphaseenc.res = IMax(2, 1, opslquant);
1504  ksfse.zphaseenc.nover = 0;
1505 
1506  /* set .R and .nacslines fields of ksfse.zphaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
1507  if (opasset) {
1508  cvoverride(ksfse_minzacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
1509  } else if (oparc) {
1510  ksfse_minzacslines = _ksfse_minzacslines.defval;
1511  }
1512  status = ks_eval_phaser_setaccel(&ksfse.zphaseenc, ksfse_minzacslines, opaccel_sl_stride);
1513  KS_RAISE(status);
1514 
1515  /* another call done in ksfse_eval_setuprfpulses_3D() with .areaoffset > 0 */
1516  status = ks_eval_phaser(&ksfse.zphaseenc, "zphaseenc");
1517  KS_RAISE(status);
1518  } else {
1519 
1521 
1522  }
1523 
1524 
1525  /* Add recovery pulses after the main Echo Train, common for 2D and 3D */
1526  if (ksfse_recovery) {
1528  KS_RAISE(status);
1529  } else {
1532  }
1533 
1534  /* post-read spoiler */
1536  status = ks_eval_trap(&ksfse.spoiler, "spoiler");
1537  KS_RAISE(status);
1538 
1539  /* init seqctrl */
1541  strcpy(ksfse.seqctrl.description, "ksfsemain");
1543 
1544  return SUCCESS;
1545 
1546 } /* ksfse_eval_setupobjects() */
int ksfse_recovery
Definition: ksfse_implementation.e:109
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
int ksfse_eval_ssitime()
Set the SSI time for the sequence
Definition: ksfse_implementation.e:1376
int ksfse_eval_optimalkxnover(KSFSE_SEQUENCE *seq)
Calculates the optimal number of k-space points for partial kx Fourier that does not increase TE...
Definition: ksfse_implementation.e:974
int res
Definition: KSFoundation.h:1721
int opxres
float ksfse_crusher_dephasing
Definition: ksfse_implementation.e:100
int opyres
KS_TRAP spoiler
Definition: ksfse_implementation.e:62
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
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
int ksfse_kxnover
Definition: ksfse_implementation.e:116
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS ksfse_eval_setuprfpulses_2D(KSFSE_SEQUENCE *seq, float crusher_dephasing)
Sets up the RF objects for the ksfse sequence (2D)
Definition: ksfse_implementation.e:1066
float fov
Definition: KSFoundation.h:1551
STATUS ksfse_eval_setuprfpulses_recovery(KSFSE_SEQUENCE *seq)
Sets up .selrfrecover and .selrfrecoverref for fast T1 recovery based on .selrfexc and ...
Definition: ksfse_implementation.e:1322
KS_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
STATUS ksfse_eval_setuprfpulses_3D(KSFSE_SEQUENCE *seq)
Sets up the RF objects for the ksfse sequence (3D)
Definition: ksfse_implementation.e:1210
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int ksfse_eval_esp(int *min90_180, int *min180_echo, int slicecheck, KSFSE_SEQUENCE *seq)
Calculates echo spacing for the sequence
Definition: ksfse_implementation.e:901
KS_READTRAP read
Definition: ksfse_implementation.e:58
int ksfse_minzacslines
Definition: ksfse_implementation.e:128
float areaoffset
Definition: KSFoundation.h:1726
float rbw
Definition: KSFoundation.h:842
float paddingarea
Definition: KSFoundation.h:1556
STATUS ks_eval_phaser_setaccel(KS_PHASER *phaser, int min_acslines, float R) WARN_UNUSED_RESULT
Definition: KSFoundation_host.c:1911
float ks_qfact
Definition: GERequired.e:271
#define KSFSE_MINHNOVER
Definition: ksfse_implementation.e:41
KS_TRAP readdephaser
Definition: ksfse_implementation.e:59
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
int res
Definition: KSFoundation.h:1552
int ksfse_minacslines
Definition: ksfse_implementation.e:127
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
void ks_init_selrf(KS_SELRF *selrf)
Resets a KS_SELRF sequence object to its default value (KS_INIT_SELRF)
Definition: KSFoundation_host.c:102
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int nover
Definition: KSFoundation.h:1722
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
int ksfse_rampsampling
Definition: ksfse_implementation.e:117
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
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
float area2center
Definition: KSFoundation.h:1559
float fov
Definition: KSFoundation.h:1720
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 ksfse_spoilerarea
Definition: ksfse_implementation.e:91
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67
float ksfse_xcrusherarea
Definition: ksfse_implementation.e:120

◆ ksfse_eval_TErange()

STATUS ksfse_eval_TErange ( )

Sets the min/max TE and echo spacing for the FSE train based on rBW, res and ETL

Based on the duration of the sequence objects involved, this function first calculates the minimum echo spacing in the FSE train (ksfse_esp). Then, if the SSFSE flag is set (opssfse), the ETL (opetl) is forced to be equal to the number of phase encoding lines acquired (see ks_eval_phaseviewtable()), otherwise the chosen ETL is used to calculate how many TRs (or shots) is necessary to fill k-space (ksfse.phaseenc_plan.num_shots). This value is used later in scan.

Next, if the user has selected that the "ETL should set TE" (ksfse_etlte = TRUE), the echo time is forced to be equal to the most optimal one in the center of the echo train (optecho). The benefits of setting ksfse_etlte are

  • reduced T2-blurring due to faster k-space traversal, and
  • no FSE ghosting The drawback is that TE needs to be controlled via changing ETL in the UI, but image quality wise, it may still be worth it. If ksfse_etlte = FALSE, ksfse_calc_echo() will find the bestecho, which is the echo index in the FSE train closest to the desired TE. When bestecho ends up being equal to optecho (as enforced by ksfse_etlte), the image quality improves, however this it not possible, especially for long ETLs with a normal TE of 80-100 ms.

Last, this function calls ksfse_eval_TEmenu() to change the TE menu so the optimal TE is always at the top, followed by other TEs one or more echo spacings from the optimal TE.

N.B.: ksfse_esp is the shortest time allowed between the RF excitation and the first echo, which is also the same time needed between two consecutive echoes in the FSE train. ksfse_esp is used in ksfse_pg(). If the pulse sequence design changes in ksfse_pg() such that more/less time is needed to the first echo, or between consecutive echoes, ksfse_esp must here be updated to avoid gradient overlaps.

Return values
STATUSSUCCESS or FAILURE
1583  {
1584  int min90_180 = 0;
1585  int min180_echo = 0;
1586  double optecho, bestecho;
1587  int fixed_teflag = _opte.fixedflag;
1588  int exist_teflag = _opte.existflag;
1589  STATUS status;
1590 
1591 
1592  /* echo spacing (esp) */
1593  ksfse_esp = ksfse_eval_esp(&min90_180, &min180_echo, ksfse_slicecheck, &ksfse);
1594 
1595  /* ETL */
1596  if (opssfse == PSD_ON) {
1597  /* SSFSE case */
1598  cvoverride(opetl, ksfse.phaseenc.numlinestoacq, PSD_FIX_ON, PSD_EXIST_ON);
1599  } else {
1600  if (opetl < 1) {
1601  cvoverride(opetl, 1, PSD_FIX_ON, PSD_EXIST_ON);
1602  } else if (opetl > ksfse.phaseenc.numlinestoacq) {
1603  return ks_error("ksfse_eval_TErange: Please reduce ETL to %d", ksfse.phaseenc.numlinestoacq);
1604  }
1605  }
1606 
1607  /* if single shot (2D), ks_phaseencoding_generate_2Dfse() will not allow non-optimal TE, i.e. linear k-space sweep
1608  is required. Therefore, ETL must control TE via setting ksfse_etlte = TRUE */
1609  if (CEIL_DIV(ksfse.phaseenc.numlinestoacq, opetl) == 1) {
1610  cvoverride(ksfse_etlte, TRUE, PSD_FIX_ON, PSD_EXIST_ON);
1611  } else {
1612  _ksfse_etlte.fixedflag = FALSE;
1613  }
1614 
1615 
1616  /* calc spacing between RF pulses used for T1-w opt. */
1617  if (ksfse_recovery) {
1618 
1619  int recovery_min_read2ref = (ksfse.read.grad.duration - ksfse.read.time2center - ksfse.read.acqdelay) +
1622 
1623  int recovery_min_ref2exc = ksfse.selrfrecoverref.rf.iso2end +
1624  IMax(2, ksfse.readdephaser.duration,
1628 
1629  if (ksfse_slicecheck) {
1630  recovery_min_read2ref += ksfse.read.grad.ramptime;
1631  recovery_min_ref2exc = ksfse.selrfrecoverref.rf.iso2end +
1636  }
1637 
1638  int ksfse_recovery_spacing = IMax(2, recovery_min_read2ref, recovery_min_ref2exc) * 2;
1639 
1640  ksfse_esp = IMax(2, ksfse_esp, ksfse_recovery_spacing);
1641  }
1642 
1643  ksfse_esp += GRAD_UPDATE_TIME * 2; /* 8us extra margin */
1644  ksfse_esp = RUP_FACTOR(ksfse_esp, 8); /* make sure ksfse_esp is divisible by 8us (as we will need to use ksfse_esp/2 on 4us grid) */
1645 
1646 
1647  /* protect against too long sequence before we are having trouble in pg */
1648  if (ksfse_esp * opetl > 2s) {
1649  return ks_error("%s: Too long sequence duration (%.1f ms)", __FUNCTION__, (ksfse_esp * opetl) / 1000.0);
1650  }
1651 
1652  /* bestecho: opte rounded off. optecho: ignores 'opte' input */
1653  int dummy;
1654  status = ks_fse_calcecho(&bestecho, &optecho, &dummy, &ksfse.phaseenc, KS_PF_EARLY, opte, opetl, ksfse_esp);
1655  KS_RAISE(status);
1656 
1657  setpopup(opte, PSD_OFF);
1658 
1659 
1660  if (ksfse_etlte) {
1661  /* ETL is controlling the use of an optimal TE to ensure a linear k-space sweep */
1662  cvoverride(opte, (int) (ksfse_esp * optecho), PSD_FIX_ON, PSD_EXIST_ON);
1663  pite1nub = 0;
1664  _opte.defval = opte;
1665  pite1val2 = opte;
1666  avminte = opte;
1667  avmaxte = opte;
1668 
1669  /* must set opautote here so that the TE menu is shaded rather than removed */
1670  cvoverride(opautote, PSD_MINTEFULL, PSD_FIX_OFF, PSD_EXIST_ON);
1671 
1672  } else {
1673 
1674  /* minimum TE */
1675  avminte = ksfse_esp;
1676 
1677  if (opautote || (opte < avminte)) {
1678  cvoverride(opte, avminte, PSD_FIX_ON, PSD_EXIST_ON);
1679  } else {
1680  /* round opte to nearest valid value */
1681  cvoverride(opte, (int) (ksfse_esp * bestecho), fixed_teflag, exist_teflag);
1682  }
1683 
1684  /* maximum TE */
1685  avmaxte = ksfse_esp * opetl;
1686 
1687  /* Setup TE menu */
1688  ksfse_eval_TEmenu(ksfse_esp, avmaxte, opetl, optecho);
1689 
1690  }
1691 
1692 
1693  { /* Update opuser1 to show optimal TE and echo spacing) */
1694  char tmpstr[100];
1695  sprintf(tmpstr, "%s [opt=%.1f, esp=%d]", _ksfse_etlte.descr, (ksfse_esp * optecho) / 1000.0, ksfse_esp / 1000);
1696  cvdesc(opuser1, tmpstr);
1697  }
1698 
1699  return SUCCESS;
1700 
1701 } /* ksfse_eval_TErange() */
int ksfse_recovery
Definition: ksfse_implementation.e:109
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
KS_TRAP grad
Definition: KSFoundation.h:1463
int start2iso
Definition: KSFoundation.h:1032
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
int numlinestoacq
Definition: KSFoundation.h:1727
int ksfse_eval_esp(int *min90_180, int *min180_echo, int slicecheck, KSFSE_SEQUENCE *seq)
Calculates echo spacing for the sequence
Definition: ksfse_implementation.e:901
KS_READTRAP read
Definition: ksfse_implementation.e:58
Definition: KSFoundation.h:386
KS_TRAP grad
Definition: KSFoundation.h:1561
STATUS ks_fse_calcecho(double *bestecho, double *optecho, int *nacqlines_to_kspacecenter, const KS_PHASER *const pe, KS_PF_EARLYLATE pf_direction, int TE, int etl, int esp)
Calculates the ETL index corresponding the desired TE given a KS_PHASER object and echo spacing...
Definition: KSFoundation_common.c:804
int grad2rf_start
Definition: KSFoundation.h:1466
KS_TRAP readdephaser
Definition: ksfse_implementation.e:59
KS_RF rf
Definition: KSFoundation.h:1454
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int iso2end
Definition: KSFoundation.h:1033
int ksfse_esp
Definition: ksfse_implementation.e:121
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
void ksfse_eval_TEmenu(int esp, int maxte, int etl, double optechono)
Sets up the TE menu based on echo spacing, max TE, ETL and the optimal echo index
Definition: ksfse_implementation.e:850
int time2center
Definition: KSFoundation.h:1560
int ksfse_etlte
Definition: ksfse_implementation.e:119
int acqdelay
Definition: KSFoundation.h:1555
int ramptime
Definition: KSFoundation.h:671
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67
int ksfse_slicecheck
Definition: ksfse_implementation.e:102

◆ ksfse_set_kspace_design()

void ksfse_set_kspace_design ( KS_KSPACE_DESIGN kdesign)

Set the k-space design for use in ksfse_set_loop_control_design() and ksfse_eval_sat()

This function sets up the k-space design for the FSE 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 echo spacing.

It is used by ksfse_set_loop_control_design() and ksfse_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
1722  {
1723 
1724  /* k-space design */
1725  kdesign->fov[XGRAD] = opfov;
1726  kdesign->fov[YGRAD] = opfov * opphasefov;
1727  kdesign->res[XGRAD] = RUP_FACTOR(opxres, 2);
1728  kdesign->res[YGRAD] = RUP_FACTOR((int) (opyres * opphasefov), 2);
1729  kdesign->R[YGRAD] = (oparc || opasset) ? opaccel_ph_stride : 1;
1730  kdesign->R[ZGRAD] = ((oparc || opasset) && KS_3D_SELECTED) ? opaccel_sl_stride : 1;
1731  kdesign->nacslines[YGRAD] = ksfse_minacslines;
1732  kdesign->nacslines[ZGRAD] = ksfse_minzacslines;
1733  kdesign->rbw = oprbw;
1734  kdesign->override_R1 = 0; /* If non-zero, override the analog receive gain with this value */
1735  if (opnex < 1) {
1736  int kynover = kdesign->res[YGRAD] * (opnex - 0.5);
1737  kynover += kynover % 2; /* round to nearest even number */
1738  kdesign->nover[YGRAD] = IMax(2, kynover, KSFSE_MINHNOVER);
1739  } else {
1740  kdesign->nover[YGRAD] = 0;
1741  }
1742 
1743  /* rampsampling on for ART (opsilent) */
1744  kdesign->rampsampling = (opsilent) ? TRUE : FALSE;
1745 
1746 } /* ksfse_set_kspace_design() */
int nacslines[3]
Definition: ksdesign.h:88
int opxres
int R[3]
Definition: ksdesign.h:83
int opyres
int nover[3]
Definition: ksdesign.h:82
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int ksfse_minzacslines
Definition: ksfse_implementation.e:128
#define KSFSE_MINHNOVER
Definition: ksfse_implementation.e:41
int ksfse_minacslines
Definition: ksfse_implementation.e:127
float opfov
int override_R1
Definition: ksdesign.h:93
float rbw
Definition: ksdesign.h:91
int rampsampling
Definition: ksdesign.h:81
int res[3]
Definition: ksdesign.h:80
float fov[3]
Definition: ksdesign.h:79

◆ ksfse_set_slicetiming_design()

void ksfse_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 ksfse_eval_loops()->ksfse_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
1765  {
1766 
1767  /* interleaved slices in slice gap menu, force 2+ acqs */
1768  int minacqs = (opileave) ? 2 : 1;
1769 
1770  if (opslspace < 0) { /* Because we use overlap (pi_neg_sp) */
1771  minacqs = IMax(2, minacqs, ceil(opslthick / (opslthick - fabs(opslspace))));
1772  }
1773 
1774  slicetiming_design->is3D = KS_3D_SELECTED;
1775  slicetiming_design->nslices = opslquant;
1776  ksscan_copy_slices(slicetiming_design, ks_scan_info);
1777 
1778  slicetiming_design->minacqs = minacqs;
1779  if (opautotr) {
1780  slicetiming_design->minTR = ksfse_mintr;
1781  slicetiming_design->maxTR = ksfse_maxtr;
1782  } else {
1783  slicetiming_design->minTR = optr;
1784  slicetiming_design->maxTR = optr;
1785  }
1786 
1787 } /* ksfse_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 ksfse_maxtr
Definition: ksfse_implementation.e:140
int maxTR
Definition: ksscan.h:29
int nslices
Definition: ksscan.h:23
int ksfse_mintr
Definition: ksfse_implementation.e:139
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

◆ ksfse_set_loop_control_design()

STATUS ksfse_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 ksfse_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
1811  {
1812 
1813  if (optr > 6s || opssfse || opt2flair) {
1814  ksfse_dda = 0; /* For long TRs or single-shot FSE, don't use dummies */
1815  } else if (optr > 2s) {
1816  ksfse_dda = 1; /* For medium long TRs */
1817  } else {
1818  ksfse_dda = 2;
1819  }
1820 
1821  loop_design->dda = ksfse_dda;
1822  loop_design->naverages = ceil(opnex);
1823  loop_design->nvols = opfphases;
1824 
1825  /* Generate the k-space coordinate list */
1827  ksfse_set_kspace_design(&kdesign);
1828  STATUS s = ks_generate_3d_coords_caipi(&kacq,
1829  kdesign.res[YGRAD], kdesign.res[ZGRAD],
1830  kdesign.nover[YGRAD], kdesign.nover[ZGRAD],
1831  kdesign.R[YGRAD], kdesign.R[ZGRAD],
1832  ks_cal_from_nacslines(kdesign.R[YGRAD], kdesign.nacslines[YGRAD]),
1833  ks_cal_from_nacslines(kdesign.R[ZGRAD], kdesign.nacslines[ZGRAD]),
1834  RECTANGULAR, /* calibration shape */
1835  RECTANGULAR, /* kspace coverage, can be ELLIPTICAL as well */
1836  0, 0, 0, 0);
1837  KS_RAISE(s);
1838 
1839  /* Phase encoding */
1840  loop_design->phaseenc_design.encodes_per_shot = opetl;
1841  loop_design->phaseenc_design.center_encode = opte / ksfse_esp - 1;
1842  loop_design->phaseenc_design.kacq = kacq;
1843 
1845 
1846  return SUCCESS;
1847 
1848 } /* ksfse_set_loop_control_design() */
KS_KSPACE_ACQ kacq
Definition: ksfse_implementation.e:196
void ksfse_set_kspace_design(KS_KSPACE_DESIGN *kdesign)
Set the k-space design for use in ksfse_set_loop_control_design() and ksfse_eval_sat()
Definition: ksfse_implementation.e:1722
int encodes_per_shot
Definition: ksscan.h:140
int nacslines[3]
Definition: ksdesign.h:88
KS_KSPACE_ACQ kacq
Definition: ksscan.h:138
int R[3]
Definition: ksdesign.h:83
int nover[3]
Definition: ksdesign.h:82
int naverages
Definition: ksscan.h:204
STATUS ks_generate_3d_coords_caipi(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, int dy, int dz, int step_y, int step_z) WARN_UNUSED_RESULT
Generates Cartesian Coordinates with or without CAPIRINHA undersampling.
Definition: KSFoundation_host.c:9792
KS_PHASEENCODING_PLAN_DESIGN phaseenc_design
Definition: ksscan.h:207
int dda
Definition: ksscan.h:202
int nvols
Definition: ksscan.h:203
#define KS_INIT_KSPACE_2D_DESIGN
Definition: ksdesign.h:99
void ksfse_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: ksfse_implementation.e:1765
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
#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
int ks_cal_from_nacslines(int R, int nacslines)
ADDTITLEHERE
Definition: KSFoundation_host.c:9784
Definition: KSFoundation.h:2095
int ksfse_esp
Definition: ksfse_implementation.e:121
int center_encode
Definition: ksscan.h:141
int ksfse_dda
Definition: ksfse_implementation.e:135
int res[3]
Definition: ksdesign.h:80

◆ ksfse_set_inversion_loop_control_design()

STATUS ksfse_set_inversion_loop_control_design ( KSINV_LOOP_CONTROL_DESIGN invloopctrl_design)

Setup of a KSINV_LOOP_CONTROL_DESIGN with inversion related parameters

This function creates a KSSCAN_LOOP_CONTROL_DESIGN struct, which contains the same KSSCAN_LOOP_CONTROL_DESIGN struct as ksfse_set_loop_control_design() in its .loopctrl_design field. This by calling ksfse_set_loop_control_design(&invloopctrl_design->loopctrl_design) here.

In addition, inversion-recovery-related design info is set up in this function, including the type of inversion mode depending on the UI CVs opirprep, opt1flair, opt2flair.

The desired inversion timing is controlled by either the inversion time (TI) xor the T1 value of the tissue

  • .T1value = ksfse_t1value_to_null, if the UI CV opautoti is TRUE (makes the final TI change automatically with TR)
  • .TI = opti if the UI CV opautoti is FALSE (makes a fixed TI value set by the user)

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]invloopctrl_designKSINV_LOOP_CONTROL_DESIGN to be created
Return values
STATUSSUCCESS or FAILURE
1873  {
1874 
1875  if (!ANYINVERSION) {
1876  invloopctrl_design->irmode = KSINV_OFF;
1877  return SUCCESS;
1878  }
1879 
1880  if (exist(opautotr) == 0 && existcv(optr)) {
1881  return KS_THROW("MinimumTR (Auto) must be selected for FLAIR");
1882  }
1883 
1884  if ((opirprep + opt1flair + opt2flair) > 1) {
1885  return KS_THROW("Mutually exclusive opirprep/opt1flair/opt2flair");
1886  }
1887 
1888  STATUS s = ksfse_set_loop_control_design(&invloopctrl_design->loopctrl_design);
1889  KS_RAISE(s);
1890 
1891  invloopctrl_design->irmode = KSINV_OFF;
1892  if (opirprep) { /* IR prep */
1893  invloopctrl_design->dosliceahead = 1; /* TODO */
1894  invloopctrl_design->irmode = KSINV_ON_INTERLEAVED;
1895  }
1896  if (opt1flair) { /* interleaved IR */
1897  invloopctrl_design->dosliceahead = 1;
1898  invloopctrl_design->irmode = KSINV_ON_INTERLEAVED;
1899  invloopctrl_design->loopctrl_design.slicetiming_design.minTR =
1900  IMax(2, KSINV_MINTR_T1FLAIR, invloopctrl_design->loopctrl_design.slicetiming_design.minTR);
1901  invloopctrl_design->loopctrl_design.slicetiming_design.minTR =
1902  IMin(2, KSINV_MAXTR_T1FLAIR, invloopctrl_design->loopctrl_design.slicetiming_design.maxTR);
1903  }
1904  if (opt2flair) { /* FLAIR block */
1905  invloopctrl_design->irmode = KSINV_ON_FLAIR_BLOCK;
1906  invloopctrl_design->loopctrl_design.slicetiming_design.minTR =
1907  IMax(2, KSINV_MINTR_T2FLAIR, invloopctrl_design->loopctrl_design.slicetiming_design.minTR);
1908  }
1909 
1910  if (opautoti) { /* use either TI or T1value (XOR). must set the non-used one to KS_NOTSET */
1911  invloopctrl_design->TI = KS_NOTSET;
1912  invloopctrl_design->T1value = (int) opuser7 * 1000; /* ms -> us */;
1913  } else {
1914  invloopctrl_design->TI = opti;
1915  invloopctrl_design->T1value = KS_NOTSET;
1916  }
1917 
1918  invloopctrl_design->filltr_ssi_time = ksfse_ssi_time;
1919 
1920  return SUCCESS;
1921 
1922 } /* ksfse_set_inversion_loop_control_design() */
int ksfse_ssi_time
Definition: ksfse_implementation.e:134
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS ksfse_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: ksfse_implementation.e:1811
int T1value
Definition: ksinversion.h:91
int filltr_ssi_time
Definition: ksinversion.h:93
#define KSINV_MAXTR_T1FLAIR
Definition: ksinversion.h:35
Definition: ksinversion.h:27
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
int irmode
Definition: ksinversion.h:89
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Definition: ksinversion.h:27
Definition: ksinversion.h:27
int TI
Definition: ksinversion.h:90
#define KSINV_MINTR_T1FLAIR
Definition: ksinversion.h:34
#define KSINV_MINTR_T2FLAIR
Definition: ksinversion.h:33
int maxTR
Definition: ksscan.h:29
#define ANYINVERSION
Definition: KSFoundation.h:346
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int minTR
Definition: ksscan.h:28
KSSCAN_LOOP_CONTROL_DESIGN loopctrl_design
Definition: ksinversion.h:94
int dosliceahead
Definition: ksinversion.h:92

◆ ksfse_eval_inversion()

STATUS ksfse_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 ksfse_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
1941  {
1942 
1943  STATUS status;
1944 
1945  KSINV_DESIGN inv_design = KSINV_INIT_DESIGN;
1946 
1947  ksinv_init_design(&inv_design, "inv"); /* e.g. STIR */
1948  if (opt1flair) {
1949  ksinv_init_design(&inv_design, "t1flair");
1950  }
1951  if (opt2flair) {
1952  ksinv_init_design(&inv_design, "t2flair");
1953  }
1954 
1955  inv_design.invdesign.slthick = opslthick;
1956  inv_design.invdesign.flip = 180.0;
1957  inv_design.invdesign.rfpulse_choice = INV_ADIABATIC; /* TODO */
1958  inv_design.spoiler_area = ksfse_spoilerarea;
1959  inv_design.gscale_policy = KSINV_GSCALE_NONOVERLAP; /* TODO */
1960  inv_design.slice_gap = opslspace;
1961  inv_design.ssi_time = ksfse_ssi_time;
1962 
1963  const int minacqs = (opileave) ? 2 : 1;
1964  status = ksinv_eval_design(&ksfse_inv, &inv_design, minacqs, seqcollection);
1965  KS_RAISE(status);
1966 
1967  return SUCCESS;
1968 
1969 } /* ksfse_eval_inversion() */
int ksfse_ssi_time
Definition: ksfse_implementation.e:134
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
void ksinv_init_design(KSINV_DESIGN *design, const char *desc)
Resets the design of the standard inversion module
Definition: ksinversion.cc:31
Definition: ksdesign.h:31
float spoiler_area
Definition: ksinversion.h:61
float flip
Definition: ksdesign.h:51
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
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
float opslthick
KSINV_GSCALE_POLICY gscale_policy
Definition: ksinversion.h:60
float slthick
Definition: ksdesign.h:50
float ksfse_spoilerarea
Definition: ksfse_implementation.e:91

◆ ksfse_eval_sat()

STATUS ksfse_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 ksfse.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 ksfse_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
1990  {
1991 
1992  STATUS status;
1993 
1995  ksfse_set_kspace_design(&kdesign);
1996 
1998  ksfse_set_slicetiming_design(&slicetiming_design);
1999 
2000  status = kssat_setup_from_UI(&kssat,
2001  &kdesign,
2002  &slicetiming_design,
2003  opslthick,
2004  seqcollection);
2005  KS_RAISE(status);
2006 
2007  return SUCCESS;
2008 
2009 } /* ksfse_eval_sat() */
void ksfse_set_kspace_design(KS_KSPACE_DESIGN *kdesign)
Set the k-space design for use in ksfse_set_loop_control_design() and ksfse_eval_sat()
Definition: ksfse_implementation.e:1722
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
#define KS_INIT_KSPACE_2D_DESIGN
Definition: ksdesign.h:99
void ksfse_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: ksfse_implementation.e:1765
#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
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

◆ ksfse_gradheat_play()

STATUS ksfse_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.
  • is not used for any data collection.
  • first plays the saturation sequence (if kssat.seqctrl.duration > 0), then the inversion sequence (if any), 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 ksfse_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 ksfse_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
2044  {
2045  (void) nargs;
2046  (void) args;
2047 
2048  /* Sat */
2050 
2051  /* Inversion */
2052  if (ANYINVERSION) {
2054  }
2055 
2056  /* main */
2057  if (max_encode_mode == AVERAGE_POWER) {
2059  } else {
2060  ks_scan_phaser_max(&ksfse.phaseenc, INSTRALL);
2061  }
2063 
2064  return SUCCESS;
2065 
2066 } /* ksfse_gradheat_play() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
void ks_scan_phaser_max(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:497
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KSSAT_MODULE kssat
Definition: kssat.e:112
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
#define ANYINVERSION
Definition: KSFoundation.h:346
void ks_scan_phaser_average(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:490
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73

◆ ksfse_eval_loops()

STATUS ksfse_eval_loops ( KS_SEQ_COLLECTION seqcollection)

Setup of scan loop control structs after heating calculations

This function performs the following tasks:

  • Evaluates the SAR and gradient heating using ks_eval_hwlimits(...,ksfse_gradheat_play(),...) and returns newtime
  • Increases the main sequence duration (ksfse.seqctrl.duration) if the newtime > time using ks_eval_seqctrl_setduration()
  • Sets up
  • If inversion is used, inv_loopctrl_design is used to create ksfse_inv_loopctrl, which controls the scan loop instead of ksfse_loopctrl when inversion is on.

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 variables loopctrl_design and inv_loopctrl_design.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
2090  {
2091  STATUS status;
2092 
2093  /* SAR and gradient heating */
2094  const int time = ks_eval_getduration(seqcollection, ksfse_gradheat_play, 0, NULL);
2095 
2096  int newtime = 0;
2097  status = ks_eval_hwlimits(&newtime, seqcollection, &loggrd, ksfse_gradheat_play, 0, NULL);
2098  KS_RAISE(status);
2099 
2100  if (newtime > time) {
2102  ks_dbg("hw limits active: %d -> %d", time, newtime);
2103  }
2104 
2105  /* Loop control evaluation */
2106 
2107  if (!ANYINVERSION) {
2109  status = ksfse_set_loop_control_design(&loopctrl_design);
2110  KS_RAISE(status);
2111 
2113  &ksfse.seqctrl,
2115  &loopctrl_design);
2116  KS_RAISE(status);
2117  } else {
2119  ksfse_set_inversion_loop_control_design(&inv_loopctrl_design);
2120 
2124  &inv_loopctrl_design,
2125  seqcollection);
2126  KS_RAISE(status);
2127  }
2128 
2129  /* Fill in the 'tmin' and 'tmin_total'. tmin_total is only like GEs use of the variable when TR = minTR */
2130  tmin = ksfse.seqctrl.min_duration;
2131  tmin_total = ksfse.seqctrl.duration;
2132 
2133  return SUCCESS;
2134 
2135 } /* ksfse_eval_loops() */
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
KS_CORESLICETIME ksfse_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksfse sequence module with optional sat module...
Definition: ksfse_implementation.e:2912
Design parameters for generating a KSSCAN_LOOP_CONTROL
Definition: ksscan.h:201
#define KSINV_INIT_LOOP_CONTROL_DESIGN
Definition: ksinversion.h:97
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
STATUS ksfse_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: ksfse_implementation.e:1811
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
KS_CORESLICETIME ksfse_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Definition: ksfse_implementation.e:2880
int min_duration
Definition: KSFoundation.h:1224
STATUS ksfse_gradheat_play(const INT max_encode_mode, int nargs, void **args)
Play function of a test sequence used for gradient heating calculations
Definition: ksfse_implementation.e:2044
Design for KSINV_LOOP_CONTROL
Definition: ksinversion.h:88
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
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
KSSCAN_LOOP_CONTROL ksfse_loopctrl
Definition: ksfse_implementation.e:159
STATUS ksfse_set_inversion_loop_control_design(KSINV_LOOP_CONTROL_DESIGN *invloopctrl_design)
Setup of a KSINV_LOOP_CONTROL_DESIGN with inversion related parameters
Definition: ksfse_implementation.e:1873
STATUS ksinv_loop_control_eval_design(KSINV_LOOP_CONTROL *inv_loopctrl, KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_SEQ_CONTROL *invseq_seqctrl_ptr, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_SEQ_CONTROL *mainseq_seqctrl_ptr, const KSINV_LOOP_CONTROL_DESIGN *design, KS_SEQ_COLLECTION *seqcollection)
Generate an inversion loop control given both custom core acquisition and inversion
Definition: ksinversion.cc:202
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
STATUS STATUS ks_dbg(const char *format,...) __attribute__((format(printf
Common debug message function for HOST and TGT
#define ANYINVERSION
Definition: KSFoundation.h:346
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73
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

◆ ksfse_eval_scantime()

STATUS ksfse_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
2149  {
2150  STATUS status;
2151 
2152  /**** SAR Calcs: Check that we are within SAR/hardware limits ****/
2153 
2154  /* Step 1: set all `seqctrl.nseqinstances` to 0 */
2156 
2157  /* Step 2: run the scan loop to get total scan time */
2158  n64 scantime = ksfse_scan_scanloop();
2159 
2160  /* Step 3: Check that the entire sequence (across all sequence modules) is within SAR & hardware limits.
2161  Also sets up UI SAR annotation */
2162  status = GEReq_eval_checkTR_SAR_calcs(seqcollection, scantime);
2163  KS_RAISE(status);
2164 
2165  pitscan = (float) scantime; /* Scan time clock in UI */
2166 
2167  return SUCCESS;
2168 
2169 } /* ksfse_eval_scantime() */
s64 ksfse_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksfse_implementation.e:2944
#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

◆ ksfse_update_UI()

STATUS ksfse_update_UI ( )

Update variables for the UI and checks for out of bounds values

This function is called from cvcheck() to update the UI variables based largely on ksfse and ksfse_loopctrl after checks for some out-of-bounds values.

Return values
STATUSSUCCESS or FAILURE
2192  {
2193 
2194  /* Show resolution, BW per pixel & echo spacing in the UI */
2195  piinplaneres = 1;
2196  pirbwperpix = 1;
2197  piesp = 1;
2198  ihinplanexres = ksfse.read.fov/ksfse.read.res;
2199  ihinplaneyres = ksfse.phaseenc.fov/ksfse.phaseenc.res;
2200  ihrbwperpix = (1000.0 * ksfse.read.acq.rbw * 2.0)/ksfse.read.res;
2201  ihesp = ksfse_esp/1000.0;
2202 
2203  const KSSCAN_LOOP_CONTROL *loopctrl = ksfse_get_loop_ctrl();
2204 
2205  _optr.minval = 0;
2206  _optr.maxval = 60s;
2207  if (opautotr) {
2208  avmintr = loopctrl->slicetiming.TR;
2209  avmaxtr = loopctrl->slicetiming.TR;
2210  } else {
2211  avmintr = _optr.minval;
2212  avmaxtr = _optr.maxval;
2213  }
2214  (optr) = loopctrl->slicetiming.TR; /* ()-parentheses avoids fixedflag expansion */
2215  act_tr = loopctrl->slicetiming.TR;
2216  ihtr = optr; /* image header TR */
2217 
2218  avmaxslquant = loopctrl->slicetiming.maxslices_per_TR;
2219  avmaxacqs = loopctrl->slicetiming.slice_plan.npasses;
2220 
2221  if (ANYINVERSION) {
2222  cvoverride(opti, ksfse_inv_loopctrl.TI, PSD_FIX_ON, PSD_EXIST_ON);
2223  if (opautoti) {
2224  pitival2 = opti;
2225  }
2226  }
2227 
2228  /* Force the user to select the Fast Spin echo button. This error needs to be in cvcheck(), not in
2229  cvinit()/cveval() to avoid it to trigger also when Fast Spin Echo has been selected */
2230  if (!((oppseq == PSD_SE || oppseq == PSD_IR) && opfast == PSD_ON && existcv(opfast))) {
2231  return ks_error("%s: Please first select the 'Fast Spin Echo' button", ks_psdname);
2232  }
2233 
2234  if (KS_3D_SELECTED && opcube) {
2235  return ks_error("%s: Please select either FRFSE-XL or FSE", __FUNCTION__);
2236  }
2237 
2238  if (oparc && KS_3D_SELECTED && (ksfse.zphaseenc.R > ksfse.phaseenc.R)) {
2239  /* Unclear why, but zR > R leads to corrupted images for ARC and 3D.
2240  Probably a bug that can be fixed later. Limited experience (July 2018) */
2241  return ks_error("%s: Need Slice acceleration <= Phase accleration", __FUNCTION__);
2242  }
2243 
2244  return SUCCESS;
2245 
2246 } /* ksfse_update_UI() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
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_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_READTRAP read
Definition: ksfse_implementation.e:58
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
float rbw
Definition: KSFoundation.h:842
int TI
Definition: ksinversion.h:104
char ks_psdname[256]
Definition: GERequired.e:245
int TR
Definition: ksscan.h:43
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 * ksfse_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksfse_implementation.e:2403
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
int ksfse_esp
Definition: ksfse_implementation.e:121
#define ANYINVERSION
Definition: KSFoundation.h:346
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

◆ ksfse_predownload_plot()

STATUS ksfse_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();ksfse_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
2295  {
2296  char tmpstr[1000];
2297 
2298  /* System wide (psd independent) option to disable plotting, to e.g. speed up UX on a slow MR show system */
2299  if (existfile("/usr/g/research/bin/ksdonotplot")) {
2300  return SUCCESS;
2301  }
2302 
2303 #ifdef PSD_HW
2304  sprintf(tmpstr, "/usr/g/mrraw/%s_objects.txt", ks_psdname);
2305 #else
2306  sprintf(tmpstr, "./%s_objects.txt", ks_psdname);
2307 #endif
2308  FILE *fp = fopen(tmpstr, "w");
2309 
2310  /* Note: 'fp' can be replaced with 'stdout' or 'stderr' to get these
2311  values printed out in the WTools window in simulation. However,
2312  heavy printing may result in that the WTools window closes,
2313  why we here write to a file ksfse_objects.txt instead */
2323  if (ANYINVERSION) {
2325  }
2326  fclose(fp);
2327 
2329 
2330  /* Main */
2333 
2334  /* Saturation */
2336 
2337  /* Sequence timing plot: */
2341 
2342  return SUCCESS;
2343 
2344 } /* ksfse_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
s64 ksfse_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksfse_implementation.e:2944
KSINV_MODULE ksfse_inv
Definition: ksfse_implementation.e:162
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
KS_TRAP spoiler
Definition: ksfse_implementation.e:62
KS_PHASER phaseenc
Definition: ksfse_implementation.e:60
KS_CORESLICETIME ksfse_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksfse sequence module with optional sat module...
Definition: ksfse_implementation.e:2912
KS_SELRF selrfinv
Definition: ksinversion.h:74
KS_PHASER zphaseenc
Definition: ksfse_implementation.e:61
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
KS_READTRAP read
Definition: ksfse_implementation.e:58
void ks_plot_host_seqctrl(const KS_SEQ_CONTROL *ctrl, const KS_PHASEENCODING_PLAN *plan)
ADDTITLEHERE
Definition: KSFoundation_host.c:7596
char ks_psdname[256]
Definition: GERequired.e:245
KS_TRAP readdephaser
Definition: ksfse_implementation.e:59
void ks_plot_slicetime_begin()
ADDTITLEHERE
Definition: KSFoundation_common.c:4266
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
KSSAT_MODULE kssat
Definition: kssat.e:112
const KSSCAN_LOOP_CONTROL * ksfse_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksfse_implementation.e:2403
void ks_plot_slicetime_end()
ADDTITLEHERE
Definition: KSFoundation_common.c:4316
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
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
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
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_SELRF selrfref1st
Definition: ksfse_implementation.e:64
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
#define ANYINVERSION
Definition: KSFoundation.h:346
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

◆ ksfse_predownload_setrecon()

STATUS ksfse_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 ksfse.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
2360  {
2361 
2362  KS_KACQ_RECONSHEDULE_ENTRY recon_table[16];
2363  int echo;
2364  for (echo = 0; echo < opnecho; echo++) {
2365  recon_table[echo].sampling_pattern_offset = 0;
2366  recon_table[echo].calibration_pattern_offset = KS_NOTSET;
2367  recon_table[echo].mask_pattern_offset = KS_NOTSET;
2368  recon_table[echo].echo_index = echo;
2369  }
2370  STATUS s = GEReq_writekacq(opnecho, recon_table, 1, &kacq);
2371  KS_RAISE(s);
2372 
2373  return SUCCESS;
2374 
2375 } /* ksfse_predownload_setrecon() */
KS_KSPACE_ACQ kacq
Definition: ksfse_implementation.e:196
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
int mask_pattern_offset
Definition: KSFoundation.h:2299
int sampling_pattern_offset
Definition: KSFoundation.h:2297

◆ ksfse_scan_rf_off()

void ksfse_scan_rf_off ( )

Sets all RF pulse amplitudes to zero

Returns
void
2750  {
2751  ks_scan_rf_off(&ksfse.selrfexc.rf, INSTRALL);
2752  ks_scan_rf_off(&ksfse.selrfref1st.rf, INSTRALL);
2753  ks_scan_rf_off(&ksfse.selrfref2nd.rf, INSTRALL);
2754  ks_scan_rf_off(&ksfse.selrfref.rf, INSTRALL);
2755  ks_scan_rf_off(&ksfse.selrfrecover.rf, INSTRALL);
2756  ks_scan_rf_off(&ksfse.selrfrecoverref.rf, INSTRALL);
2757 
2758 } /* ksfse_scan_rf_off() */
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
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
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67

◆ ksfse_scan_rf_on()

void ksfse_scan_rf_on ( )

Sets all RF pulse amplitudes on

Returns
void
2769  {
2770  ks_scan_rf_on(&ksfse.selrfexc.rf, INSTRALL);
2771  ks_scan_rf_on(&ksfse.selrfref1st.rf, INSTRALL);
2772  ks_scan_rf_on(&ksfse.selrfref2nd.rf, INSTRALL);
2773  ks_scan_rf_on(&ksfse.selrfref.rf, INSTRALL);
2774  ks_scan_rf_on(&ksfse.selrfrecover.rf, INSTRALL);
2775  ks_scan_rf_on(&ksfse.selrfrecoverref.rf, INSTRALL);
2776 
2777 } /* ksfse_scan_rf_on() */
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
KS_SELRF selrfrecoverref
Definition: ksfse_implementation.e:68
KS_SELRF selrfexc
Definition: ksfse_implementation.e:63
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
KS_SELRF selrfref2nd
Definition: ksfse_implementation.e:65
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksfse_implementation.e:66
KS_SELRF selrfref1st
Definition: ksfse_implementation.e:64
KS_SELRF selrfrecover
Definition: ksfse_implementation.e:67

◆ ksfse_scan_init()

STATUS ksfse_scan_init ( void  )

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

Return values
STATUSSUCCESS or FAILURE
2986  {
2987 
2988  GEReq_initRSP();
2989 
2990  /* Here goes code common for APS2, MPS2 and SCAN */
2991 
2992  ks_scan_switch_to_sequence(&ksfse.seqctrl); /* switch to main sequence */
2993  scopeon(&seqcore); /* Activate scope for core */
2994  syncon(&seqcore); /* Activate sync for core */
2995  setssitime(ksfse.seqctrl.ssi_time / HW_GRAD_UPDATE_TIME);
2996 
2997  /* can we make these independent on global rsptrigger and rsprot in orderslice? */
2998  settriggerarray( (short) ksfse_get_loop_ctrl()->slicetiming.slice_plan.nslices_per_pass, rsptrigger);
2999 
3000  return SUCCESS;
3001 
3002 } /* ksfse_scan_init() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1625
STATUS setssitime(long)
KSFSE_SEQUENCE ksfse
Definition: ksfse_implementation.e:158
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 * ksfse_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksfse_implementation.e:2403
KS_SEQ_CONTROL seqctrl
Definition: ksfse_implementation.e:57
int ssi_time
Definition: KSFoundation.h:1226

◆ ksfse_scan_prescanloop()

void ksfse_scan_prescanloop ( int  nloops,
int  dda 
)

Prescan loop called from both APS2 and MPS2 entry points

Return values
STATUSSUCCESS or FAILURE
3012  {
3013 
3014  if (!ANYINVERSION) {
3016  } else {
3018  }
3019 
3020 } /* ksfse_scan_prescanloop() */
KS_CORESLICETIME ksfse_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksfse sequence module with optional sat module...
Definition: ksfse_implementation.e:2912
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
KSINV_LOOP_CONTROL ksfse_inv_loopctrl
Definition: ksfse_implementation.e:163
void ksinv_prescanloop(KSINV_LOOP_CONTROL *inv_loopctrl, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksinversion.cc:1285
KS_CORESLICETIME ksfse_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Definition: ksfse_implementation.e:2880
KSSCAN_LOOP_CONTROL ksfse_loopctrl
Definition: ksfse_implementation.e:159
#define ANYINVERSION
Definition: KSFoundation.h:346

Variable Documentation

◆ seqcollection

KS_SEQ_COLLECTION seqcollection

◆ ksfse_excthickness

float ksfse_excthickness = 0

◆ ksfse_gscalerfexc

float ksfse_gscalerfexc = 0.9

◆ ksfse_flipexc

float ksfse_flipexc = 90.0 with {0.0, 180.0, 90.0, VIS, "Excitation flip angle [deg]",}

◆ ksfse_spoilerarea

float ksfse_spoilerarea = 2000.0 with {0.0, 20000.0, 5000.0, VIS, "ksfse spoiler gradient area",}

◆ rf_stretch_rfexc

float rf_stretch_rfexc = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF excitation pulse if > 1.0",}

◆ ksfse_inflowsuppression

int ksfse_inflowsuppression = 0 with {0, 1, 0, VIS, "In-flow Suppression [0:OFF, 1:ON]",}

◆ ksfse_inflowsuppression_mm

float ksfse_inflowsuppression_mm = 0.0 with {0.0, 100.0, 0.0, VIS, "In-flow suppression [mm]",}

◆ ksfse_vfa

int ksfse_vfa = 1 with {0, 1, 1, VIS, "Variable flip angles [0:OFF, 1:ON]",}

◆ ksfse_crusher_dephasing

float ksfse_crusher_dephasing = 6.0 with {0.0, 100.0, 6.0, VIS, "scaling of crusher gradient area [cycles]",}

◆ ksfse_gscalerfref

float ksfse_gscalerfref = 0.9

◆ ksfse_slicecheck

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

◆ rf_stretch_rfref

float rf_stretch_rfref = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF refocusing pulses if > 1.0",}

◆ rf_stretch_all

float rf_stretch_all = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch all RF pulses if > 1.0",}

◆ ksfse_recovery

int ksfse_recovery = KSFSE_RECOVERY_OFF with {KSFSE_RECOVERY_OFF, KSFSE_RECOVERY_FAST, KSFSE_RECOVERY_OFF, VIS, "Recovery. 0:off 1:T1wopt 2:T2fast", }

◆ rf_stretch_rfrecovery

float rf_stretch_rfrecovery = 1.0 with {0.01, 100.0, 1.0, VIS, "Stretch RF recovery pulses if > 1.0",}

◆ ksfse_kxnover_min

int ksfse_kxnover_min = KSFSE_MINHNOVER with {KSFSE_MINHNOVER, 512, KSFSE_MINHNOVER, VIS, "Min mum kx overscans for minTE",}

◆ ksfse_kxnover

int ksfse_kxnover = 32 with {KSFSE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",}

◆ ksfse_rampsampling

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

◆ ksfse_extragap

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

◆ ksfse_etlte

int ksfse_etlte = 1 with {0, 1, 1, VIS, "ETL controls TE",}

◆ ksfse_xcrusherarea

float ksfse_xcrusherarea = 100.0 with {0.0, 1000.0, 100.0, VIS, "x crusher area for readout",}

◆ ksfse_esp

int ksfse_esp = 0 with {0, 1000000, 0, VIS, "View-only: Echo spacing in [us]",}

◆ ksfse_noph

int ksfse_noph = 0 with {0, 1, 0, VIS, "Turn OFF phase encoding [0:Disabled 1:Enabled]",}

◆ ksfse_minacslines

int ksfse_minacslines = 12 with {0, 512, 12, VIS, "Minimum ACS lines for ARC",}

◆ ksfse_minzacslines

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

◆ ksfse_pos_start

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

◆ ksfse_ssi_time

int ksfse_ssi_time = KSFSE_MIN_SSI_TIME with {50, , KSFSE_MIN_SSI_TIME, VIS, "time from eos to ssi in intern trig",}

◆ ksfse_dda

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

◆ ksfse_debug

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

◆ ksfse_imsize

int ksfse_imsize = KS_IMSIZE_NATIVE with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_MIN256, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"}

◆ ksfse_abort_on_kserror

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

◆ ksfse_mintr

int ksfse_mintr = 0 with {0, 20s, 0, VIS, "Min TR (ms) [0: Disabled]",}

◆ ksfse_maxtr

int ksfse_maxtr = 0 with {0, 40s, 0, VIS, "Max TR (ms) [0: Disabled]",}

◆ ksfse

Main FSE sequence

◆ ksfse_loopctrl

Scan loop control for the ksfse sequence (without inversion)

◆ ksfse_inv

Inversion module

◆ ksfse_inv_loopctrl

◆ ksfse_phaseencoding_memorypool

◆ kacq

◆ sequence_iopts

int sequence_iopts[]
Initial value:
= {
PSD_IOPT_ARC,
PSD_IOPT_ASSET,
PSD_IOPT_EDR,
PSD_IOPT_DYNPL,
PSD_IOPT_TLRD_RF,
PSD_IOPT_MILDNOTE,
PSD_IOPT_ZIP_512,
PSD_IOPT_FR,
PSD_IOPT_T1FLAIR,
PSD_IOPT_T2FLAIR,
PSD_IOPT_IR_PREP,
}