KSFoundation  [April-2021]
A platform for simpler EPIC programming on GE MR systems
ksgre: GRE sequence (2D/3D)

Data Structures

struct  KSGRE_SEQUENCE
 

Macros

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

Functions

STATUS cvinit (void)
 
STATUS cveval (void)
 
STATUS my_cveval (void)
 
STATUS cvcheck (void)
 
STATUS predownload (void)
 
STATUS pulsegen (void)
 
STATUS mps2 (void)
 
STATUS aps2 (void)
 
STATUS scan (void)
 
 abstract ("GRE [KSFoundation]")
 
 psdname ("ksgre")
 
STATUS ksgre_pg (int start_time)
 
int ksgre_scan_coreslice (const SCAN_INFO *slice_pos, int dabslice, int shot, int exc)
 
int ksgre_scan_coreslice_nargs (const SCAN_INFO *slice_pos, int dabslice, int nargs, void **args)
 
int ksgre_scan_sliceloop (int slperpass, int passindx, int shot, int exc)
 
int ksgre_eval_ssitime ()
 
void ksgre_init_imagingoptions (void)
 
STATUS ksgre_init_UI (void)
 
STATUS ksgre_eval_UI ()
 
STATUS ksgre_eval_setupobjects ()
 
STATUS ksgre_eval_TErange ()
 
STATUS ksgre_eval_inversion (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_eval_tr (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_eval_scantime ()
 
STATUS ksgre_check ()
 
STATUS ksgre_predownload_plot (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksgre_predownload_setrecon ()
 
float ksgre_scan_phase (int counter)
 
STATUS ksgre_scan_init (void)
 
STATUS ksgre_scan_prescanloop (int nloops, int dda)
 

Variables

KS_SEQ_COLLECTION seqcollection
 
float ksgre_excthickness = 0
 
float ksgre_gscalerfexc = 0.9
 
int ksgre_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",}
 
float ksgre_spoilerarea = 1500.0 with {0.0, 10000.0, 1500.0, VIS, "ksgre spoiler gradient area",}
 
int ksgre_sincrf = 0 with {0, 1, 0, VIS, "Use Sinc RF",}
 
float ksgre_sincrf_bw = 2500 with {0, 100000, 2500, VIS, "Sinc RF BW",}
 
float ksgre_sincrf_tbw = 2 with {2, 100, 2, VIS, "Sinc RF TBW",}
 
int ksgre_rfexc_choice = 0 with {0, 3, 0, VIS, "RF pulse 0(fast)-1-2(high FA) 3 (Hard non-sel)",}
 
int ksgre_kxnover = 32 with {KSGRE_MINHNOVER, 512, 32, VIS, "Num kx overscans for minTE",}
 
int ksgre_rampsampling = FALSE with {FALSE, TRUE, FALSE, VIS, "Rampsampling [0:OFF 1:ON]",}
 
int ksgre_extragap = 0 with {0, 100ms, 0, VIS, "extra gap between readouts [us]",}
 
int ksgre_minacslines = 8 with {0, 512, 8, VIS, "Minimum ACS lines for ARC",}
 
int ksgre_minzacslines = 8 with {0, 512, 8, VIS, "Minimum z ACS lines for ARC",}
 
int ksgre_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, VIS, "us from start until the first waveform begins",}
 
int ksgre_ssi_time = KSGRE_DEFAULT_SSI_TIME with {32, , KSGRE_DEFAULT_SSI_TIME, VIS, "time from eos to ssi in intern trig",}
 
int ksgre_dda = 2 with {0, 200, 2, VIS, "Number of dummy scans for steady state",}
 
int ksgre_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)",}
 
int ksgre_imsize = KS_IMSIZE_MIN256 with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_MIN256, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"}
 
int ksgre_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",}
 
int ksgre_ellipsekspace = TRUE with {FALSE, TRUE, TRUE, VIS, "ky-kz coverage 0:Rect 1:Elliptical",}
 
float ksgre_fattune = 0
 
KSGRE_SEQUENCE ksgre = KSGRE_INIT_SEQUENCE
 
int ksgre_ssfp_endtime = 0
 
int sequence_iopts []
 
int volindx
 
int passindx
 
int fiesta_firstplayout = 1
 
int spgr_phase_counter = 0
 

Detailed Description

MR-contrasts supported

Features

Macro Definition Documentation

◆ KSGRE_MINHNOVER

#define KSGRE_MINHNOVER   16

◆ KSGRE_DEFAULT_SSI_TIME

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

◆ KSGRE_DEFAULT_SSI_TIME_SSFP

#define KSGRE_DEFAULT_SSI_TIME_SSFP   100

◆ KSGRE_INIT_SEQUENCE

#define KSGRE_INIT_SEQUENCE
Value:
#define KS_INIT_PHASER
Definition: KSFoundation.h:218
#define KS_INIT_READTRAP
Definition: KSFoundation.h:215
#define KS_INIT_TRAP
Definition: KSFoundation.h:212
#define KS_INIT_SELRF
Definition: KSFoundation.h:240
#define KS_INIT_SEQ_CONTROL
Definition: KSFoundation.h:245
#define KS_INIT_PHASEENCODING_PLAN
Definition: KSFoundation.h:220

Function Documentation

◆ cvinit()

STATUS cvinit ( void  )
82  {
83  STATUS status;
84 
85  status = GEReq_cvinit();
86  if (status != SUCCESS) return status;
87 
88  /* reset debug file ./ks_debug.txt (SIM) or /usr/g/mrraw/ks_debug.txt (HW) */
89  ks_dbg_reset();
90 
91  /* Imaging Options buttons */
93 
94  /* Inversion UI init */
95  status = ksinv_init_UI();
96  if (status != SUCCESS) return status;
97 
98  /* Setup UI buttons */
99  status = ksgre_init_UI();
100  if (status != SUCCESS) return status;
101 
102  return SUCCESS;
103 
104 } /* cvinit() */
STATUS ksinv_init_UI()
Initializes inversion related UI
Definition: KSInversion.e:839
STATUS ksgre_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksgre_implementation.e:239
void ks_dbg_reset()
Clear debug file content
Definition: KSFoundation_common.c:119
STATUS GEReq_cvinit(void)
Helper function to be called at the beginning of cvinit()
Definition: GERequired.e:2220
void ksgre_init_imagingoptions(void)
Initial handling of imaging options buttons and top-level CVs at the PSD type-in page
Definition: ksgre_implementation.e:195

◆ cveval()

STATUS cveval ( void  )
112  {
113 
114  /*
115  cveval() is called 37+ times per UI button push on the MR system, while cvcheck() is only called once.
116  For a faster execution we have a my_cveval() function that is called in cvcheck() instead
117  */
118 
119  return SUCCESS;
120 }

◆ my_cveval()

STATUS my_cveval ( void  )
123  {
124  STATUS status;
125 
127 
128  status = GEReq_cveval();
129  if (status != SUCCESS) return status;
130 
131  /* User Interface updates & opuserCV sync */
132  status = ksgre_eval_UI();
133  if (status != SUCCESS) return status;
134 
135  /* Setup sequence objects */
136  status = ksgre_eval_setupobjects();
137  if (status != SUCCESS) return status;
138 
139  /* Calculate minimum (and maximum TE) */
140  status = ksgre_eval_TErange();
141  if (status != SUCCESS) return status;
142 
143  /* Run the sequence once (and only once after ksgre_eval_setupobjects()) in cveval() to
144  get the sequence duration and the number of object instances (for grad/rf limits in GEReq...limits()) */
145  status = ksgre_pg(ksgre_pos_start);
146  if (status != SUCCESS) return status;
147 
149  if (status != SUCCESS) return status;
150 
151 
152  /*--------- Begin: Additional sequence modules -----------*/
153 
154  /* Spatial Sat */
155  status = ksspsat_eval(&seqcollection);
156  if (status != SUCCESS) return status;
157 
158  /* ChemSat */
159  status = kschemsat_eval(&seqcollection);
160  if (status != SUCCESS) return status;
161 
162  /* Inversion (general & GRE specific). Must be the last sequence module added */
163  if (!KS_3D_SELECTED) {
165  if (status != SUCCESS) return status;
166  }
167 
168  /*--------- End: Additional sequence modules -----------*/
169 
170 
171  /* Min TR, #slices per TR, RF/gradient heating & SAR */
172  status = ksgre_eval_tr(&seqcollection);
173  if (status != SUCCESS) return status;
174 
175  /* RF scaling across sequence modules */
177  if (status != SUCCESS) return status;
178 
179  /* scan time */
180  status = ksgre_eval_scantime();
181  if (status != SUCCESS) return status;
182 
183  return SUCCESS;
184 
185 } /* my_cveval() */
STATUS ksgre_eval_UI()
Gets the current UI and checks for valid inputs
Definition: ksgre_implementation.e:535
STATUS ksgre_pg(int)
The ksgre (main) pulse sequence
Definition: ksgre_implementation.e:1254
STATUS ksgre_eval_TErange()
Sets the min/max TE based on the durations of the sequence objects in KSGRE_SEQUENCE (ksgre)...
Definition: ksgre_implementation.e:757
STATUS ksspsat_eval(KS_SEQ_COLLECTION *seqcollection)
Spatial Sat evaluation function, to be called from the cveval() function of the main sequence...
Definition: KSSpSat.e:633
STATUS ksgre_eval_setupobjects()
Sets up all sequence objects for the main sequence module (KSGRE_SEQUENCE ksgre)
Definition: ksgre_implementation.e:564
STATUS kschemsat_eval(KS_SEQ_COLLECTION *seqcollection)
Chemsat evaluation function, to be called from the cveval() function of the main sequence
Definition: KSChemSat.e:273
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
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:149
STATUS ksgre_eval_scantime()
Set the number of dummy scans for the sequence and calls ksgre_scan_scanloop() to determinethe length...
Definition: ksgre_implementation.e:1055
STATUS ksgre_eval_inversion(KS_SEQ_COLLECTION *seqcollection)
Wrapper function to KSInversion functions to add single and dual IR support to this sequence...
Definition: ksgre_implementation.e:874
void ks_init_seqcollection(KS_SEQ_COLLECTION *seqcollection)
Resets KS_SEQ_COLLECTION to its default value (KS_INIT_SEQ_COLLECTION)
Definition: KSFoundation_host.c:117
KS_SEQ_COLLECTION seqcollection
Definition: ksgre.e:76
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
int ksgre_pos_start
Definition: ksgre_implementation.e:99
STATUS ksgre_eval_tr(KS_SEQ_COLLECTION *seqcollection)
Evaluation of number of slices / TR, set up of slice plan, TR validation and SAR checks
Definition: ksgre_implementation.e:958
STATUS GEReq_cveval(void)
Helper function to be called at the beginning of cveval()
Definition: GERequired.e:2342
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:758

◆ cvcheck()

STATUS cvcheck ( void  )
192  {
193  STATUS status;
194 
195  status = my_cveval();
196  if (status != SUCCESS) return status;
197 
198  status = GEReq_cvcheck();
199  if (status != SUCCESS) return status;
200 
201  status = ksgre_check();
202  if (status != SUCCESS) return status;
203 
205 
206  return SUCCESS;
207 
208 } /* cvcheck() */
STATUS GEReq_cvcheck(void)
Helper function to be called at the beginning of cvcheck()
Definition: GERequired.e:2407
STATUS my_cveval(void)
Definition: ksgre.e:123
int abort_on_kserror
Definition: KSFoundation_common.c:40
int ksgre_abort_on_kserror
Definition: ksgre_implementation.e:104
STATUS ksgre_check()
Returns error of various parameter combinations that are not allowed for ksgre
Definition: ksgre_implementation.e:1088

◆ predownload()

STATUS predownload ( void  )
214  {
215  STATUS status;
216 
217  status = GEReq_predownload();
218  if (status != SUCCESS) return status;
219 
220  /* Set filter slot # for SCAN, APS2, MPS2 */
222 
223  /* slice ordering */
224  /* The following GE globals must be set appropriately:
225  data_acq_order[], rsp_info[], rsprot[], rsptrigger[]. This is a must for a main pulse sequence */
226  if (KS_3D_SELECTED) {
227  status = GEReq_predownload_store_sliceplan3D(opslquant, opvquant);
228  } else {
230  }
231  if (status != SUCCESS) return status;
232 
233  /* generic rh-vars setup */
235  ksgre_imsize, KS_SAVEPFILES * autolock + KS_GERECON * (rhrecon < 1000) /* online recon if rhrecon < 1000 */);
237  GEReq_predownload_setrecon_voldata(opfphases, ks_slice_plan); /* opfphases = number of volumes */
238 
239  /* KSInversion predownload */
240  status = ksinv_predownload_setrecon();
241  if (status != SUCCESS) return status;
242 
243  /* further sequence specific recon settings that have not been set correctly at this point */
244  status = ksgre_predownload_setrecon();
245  if (status != SUCCESS) return status;
246 
247  /* plotting of sequence modules and slice timing to disk */
249 
250  return SUCCESS;
251 
252 } /* 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:1685
STATUS GEReq_predownload_setfilter(FILTER_INFO *filt)
Assigns a global filter slot for a main sequence
Definition: GERequired.e:1149
STATUS GEReq_predownload_store_sliceplan(KS_SLICE_PLAN slice_plan)
Sets mandatory global GE arrays for data acquisition
Definition: GERequired.e:1001
#define KS_GERECON
Definition: KSFoundation.h:176
int ksgre_imsize
Definition: ksgre_implementation.e:103
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
STATUS ksinv_predownload_setrecon()
Sets IR-related recon variables in predownload
Definition: KSInversion.e:1898
STATUS ksgre_predownload_setrecon()
Last-resort function to override certain recon variables not set up correctly already
Definition: ksgre_implementation.e:1222
void GEReq_predownload_setrecon_voldata(int numvols, const KS_SLICE_PLAN slice_plan)
Sets rh*** variables related to multi-volume imaging
Definition: GERequired.e:1973
KS_SEQ_COLLECTION seqcollection
Definition: ksgre.e:76
int ksgre_extragap
Definition: ksgre_implementation.e:88
KS_READTRAP read
Definition: ksgre_implementation.e:46
#define KS_SAVEPFILES
Definition: KSFoundation.h:175
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
STATUS GEReq_predownload_store_sliceplan3D(int slices_in_slab, int slabs)
Sets mandatory global GE arrays for data acquisition (3D imaging)
Definition: GERequired.e:1123
FILTER_INFO filt
Definition: KSFoundation.h:735
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
KS_READ acq
Definition: KSFoundation.h:1574
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:1917
STATUS GEReq_predownload(void)
Helper function to be called at the beginning of predownload()
Definition: GERequired.e:2451
STATUS ksgre_predownload_plot(KS_SEQ_COLLECTION *seqcollection)
Plotting of sequence modules and slice timing to PNG/SVG/PDF files
Definition: ksgre_implementation.e:1155
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50

◆ pulsegen()

STATUS pulsegen ( void  )
259  {
260 
262 
263  /* Main Pulse Sequence */
265  KS_SEQLENGTH(seqcore, ksgre.seqctrl);
266 
267  /* Spatial Sat */
269 
270  /* ChemSat sequence module */
272  KS_SEQLENGTH(seqKSChemSat, kschemsat.seqctrl); /* does nothing if kschemsat.seqctrl.duration = 0 */
273 
274  /* Inversion sequence modules */
275  ksinv_pulsegen();
276 
278 
279  buildinstr(); /* load the sequencer memory */
280 
281  return SUCCESS;
282 
283 } /* pulsegen() */
KSCHEMSAT_SEQUENCE kschemsat
Definition: KSChemSat.e:89
int kschemsat_pg(KSCHEMSAT_SEQUENCE *chemsat)
The kschemsat (fatsat) pulse sequence module
Definition: KSChemSat.e:320
STATUS ksgre_pg(int)
The ksgre (main) pulse sequence
Definition: ksgre_implementation.e:1254
KS_SEQLENGTH(seq_name, seq_struct)
Creates a hardware sequence for the current sequence module
Definition: GERequired.e:65
void ksinv_pulsegen()
Generation of all inversion-related sequence modules
Definition: KSInversion.e:2077
void GEReq_pulsegenEnd(void)
Helper function to be called at the end of pulsegen()
Definition: GERequired.e:2551
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
STATUS ksspsat_pulsegen()
Definition: KSSpSat.e:754
KS_SEQ_CONTROL seqctrl
Definition: KSChemSat.e:71
int ksgre_pos_start
Definition: ksgre_implementation.e:99
void GEReq_pulsegenBegin(void)
Helper function to be called at the beginning of pulsegen()
Definition: GERequired.e:2527

◆ mps2()

STATUS mps2 ( void  )
302  {
303  rspent = L_MPS2;
304  strcpy(psdexitarg.text_arg, "mps2");
305 
306  if (ksgre_scan_init() == FAILURE)
307  return rspexit();
308 
309  if (ksgre_scan_prescanloop(30000, ksgre_dda) == FAILURE)
310  return rspexit();
311 
312  rspexit();
313 
314  return SUCCESS;
315 
316 } /* end mps2() */
int ksgre_dda
Definition: ksgre_implementation.e:101
STATUS ksgre_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksgre_implementation.e:2012
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:1984
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ aps2()

STATUS aps2 ( void  )
324  {
325 
326  rspent = L_APS2;
327  strcpy(psdexitarg.text_arg, "aps2");
328 
329  if (ksgre_scan_init() == FAILURE)
330  return rspexit();
331 
332  if (ksgre_scan_prescanloop(100, ksgre_dda) == FAILURE)
333  return rspexit();
334 
335  rspexit();
336 
337  return SUCCESS;
338 
339 } /* aps2() */
int ksgre_dda
Definition: ksgre_implementation.e:101
STATUS ksgre_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksgre_implementation.e:2012
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:1984
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ scan()

STATUS scan ( void  )
349  {
350 
351  rspent = L_SCAN;
352  strcpy(psdexitarg.text_arg, "scan");
353 
354  if (ksgre_scan_init() == FAILURE)
355  return rspexit();
356 
357  /* Scan hierarchy:
358 
359  Without inversion:
360  ksgre_scan_scanloop() - Data for the entire scan
361  ksgre_scan_acqloop() - All data for one set of slices that fit within one TR (one acquisition)
362  ksgre_scan_sliceloop() - One set of slices that fit within one TR played out for one shot
363  ksgre_scan_coreslice() - One slice playout, with optional other sequence modules
364 
365  With inversion:
366  ksgre_scan_scanloop() - Data for the entire scan
367  ksgre_scan_acqloop() - All data for one set of slices that fit within one TR (one acquisition)
368  ksinv_scan_sliceloop() - One set of slices that fit within one TR played out for one shot
369  using the sliceloop in KSInversion.e. Note that ksinv_scan_sliceloop()
370  takes over the TR timing from ksgre_scan_sliceloop() and uses a
371  function pointer to ksgre_scan_coreslice_nargs() to execute the
372  contents of ksgre_scan_coreslice().
373  */
375 
376  GEReq_endofscan();
377 
378  /* So we can see the sequence in plotter after scan completes */
380 
381  rspexit();
382 
383  return SUCCESS;
384 
385 } /* scan() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1356
int GEReq_endofscan()
Sets SSP word in sequence off_GEpass() to tell system that scan is done
Definition: GERequired.e:2590
float ksgre_scan_scanloop()
Plays out all passes of a single or multi-pass scan
Definition: ksgre_implementation.e:1925
STATUS ksgre_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksgre_implementation.e:1984
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ abstract()

abstract ( "GRE "  [KSFoundation])

◆ psdname()

psdname ( "ksgre"  )

◆ ksgre_pg()

STATUS ksgre_pg ( int  start_time)

The ksgre (main) pulse sequence

This is the main pulse sequence in ksgre.e using the sequence objects in KSGRE_SEQUENCE with the sequence module name "ksgremain" (= ksgre.seqctrl.description)

Return values
STATUSSUCCESS or FAILURE
1254  {
1255  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
1256  int readstart_pos, readend_pos;
1257  int i;
1258  int endposx = 0;
1259  int endposy = 0;
1260  int endposz = 0;
1261  STATUS status;
1262 
1263 #ifdef HOST_TGT
1264  if (opte < avminte) {
1265  /* we cannot proceed until TE is larger than the minimum TE (see ksgre_eval_TErange()).
1266  Return a long seq duration and pretend all is good */
1268  return SUCCESS;
1269  }
1270 #endif
1271 
1272  if (start_time < KS_RFSSP_PRETIME) {
1273  return ks_error("%s: 1st arg (pos start) must be at least %d us", __FUNCTION__, KS_RFSSP_PRETIME);
1274  }
1275 
1276  /*******************************************************************************************************
1277  * RF Excitation
1278  *******************************************************************************************************/
1279  tmploc.ampscale = 1.0;
1280  tmploc.pos = RUP_GRD(start_time);
1281  tmploc.board = ZGRAD;
1282 
1283  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksgre.selrfexc is an excitation pulse
1284  (ksgre.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksgre.seqctrl.momentstart
1285  to the absolute position in [us] of the isocenter of the RF excitation pulse */
1286  status = ks_pg_selrf(&ksgre.selrfexc, tmploc, &ksgre.seqctrl);
1287  if (status != SUCCESS) return status;
1288 
1289  /* forward to end of selrfexc.postgrad */
1291 
1292  /* Second flow comp gradient slice for slice excitation */
1293  if (ks_pg_trap(&ksgre.fcompslice, tmploc, &ksgre.seqctrl) == FAILURE) /* N.B.: will return quietly if ksgre.fcompslice.duration = 0 (opfcomp = 0) */
1294  return FAILURE;
1295 
1296  /*******************************************************************************************************
1297  * Readout timing
1298  *******************************************************************************************************/
1299 
1300  /* With ksgre.seqctrl.momentstart set by ks_pg_selrf(&ksgre.selrfexc, ...), the absolute readout position
1301  can be determined (for both full Fourier and partial Fourier readouts using ksgre.read.time2center) */
1302  readstart_pos = ksgre.seqctrl.momentstart + opte - ksgre.read.time2center;
1303 
1304 
1305  /*******************************************************************************************************
1306  * Pre-read: Dephasers
1307  *******************************************************************************************************/
1308 
1309  /******************** Z ********************/
1310  if (ksgre.zphaseenc.grad.duration > 0) {
1311  /* 3D: use .zphaseenc (with embedded slice rephaser via .areaoffset != 0) instead of .selrfexc.postgrad (not placed out since its .duration = 0) */
1312  tmploc.pos += ksgre.fcompslice.duration; /* fcompslice.duration = 0 unless opfcomp */
1313  if (ks_pg_phaser(&ksgre.zphaseenc, tmploc, &ksgre.seqctrl) == FAILURE)
1314  return FAILURE;
1315 
1317  }
1318 
1319  /******************** Y ********************/
1320  tmploc.pos = readstart_pos + RUP_GRD(ksgre.read.acqdelay) - ksgre.phaseenc.grad.duration;
1321  tmploc.board = YGRAD;
1322  if (ks_pg_phaser(&ksgre.phaseenc, tmploc, &ksgre.seqctrl) == FAILURE)
1323  return FAILURE;
1324 
1325  /* set phase encode amps to first ky view (for plotting & moment calcs in WTools) */
1326  ks_scan_phaser_toline(&ksgre.phaseenc, 0, 0); /* dephaser */
1327 
1328  /******************** X ********************/
1329  if (ksgre_slicecheck)
1330  tmploc.board = ZGRAD; /* move the readout to the Z-axis to view the slice thickness in the image */
1331  else
1332  tmploc.board = XGRAD;
1333  tmploc.pos = readstart_pos - ksgre.readdephaser.duration;
1334  if (ks_pg_trap(&ksgre.readdephaser, tmploc, &ksgre.seqctrl) == FAILURE)
1335  return FAILURE;
1336 
1337  tmploc.pos = readstart_pos - ksgre.readdephaser.duration - ksgre.fcompread.duration;
1338  if (ks_pg_trap(&ksgre.fcompread, tmploc, &ksgre.seqctrl) == FAILURE) /* N.B.: will return quietly if ksgre.fcompread.duration = 0 */
1339  return FAILURE;
1340 
1341 
1342  /*******************************************************************************************************
1343  * Readout(s)
1344  *******************************************************************************************************/
1345 
1346  if (ksgre_slicecheck)
1347  tmploc.board = ZGRAD;
1348  else
1349  tmploc.board = XGRAD;
1350 
1351  /* ksgre.read at TE = opte (1st echo) */
1352  tmploc.pos = readstart_pos;
1353  tmploc.ampscale = 1.0;
1354  for (i = 0; i < opnecho; i++) {
1355  if (ks_pg_readtrap(&ksgre.read, tmploc, &ksgre.seqctrl) == FAILURE)
1356  return FAILURE;
1357  tmploc.pos += ksgre.read.grad.duration + ksgre_extragap * ((i + 1) < opnecho); /* don't add extra gap after the last readout */
1358  tmploc.ampscale *= -1.0;
1359  }
1360  readend_pos = tmploc.pos; /* absolute time for end of last readout trapezoid */
1361  tmploc.ampscale = 1.0;
1362 
1363 
1364  /*******************************************************************************************************
1365  * Post-read: Rephasers & spoilers
1366  *******************************************************************************************************/
1367 
1368  /******************** X ********************/
1369  if (ksgre_slicecheck) {
1370  tmploc.board = ZGRAD; /* move the readout to the Z-axis to view the slice thickness in the image */
1371  } else {
1372  tmploc.board = XGRAD;
1373  }
1374  tmploc.pos = readend_pos;
1375  if (oppseq == PSD_SSFP) {
1376  if (ks_pg_trap(&ksgre.readrephaser_ssfp, tmploc, &ksgre.seqctrl) == FAILURE) /* read rephaser */
1377  return FAILURE;
1378  endposx = tmploc.pos + ksgre.readrephaser_ssfp.duration; /* absolute time for end of last waveform on X */
1379  } else {
1380  if (ks_pg_trap(&ksgre.spoiler, tmploc, &ksgre.seqctrl) == FAILURE)
1381  return FAILURE;
1382  endposx = tmploc.pos + ksgre.spoiler.duration; /* absolute time for end of last waveform on X */
1383  }
1384 
1385  /******************** Y ********************/
1386  /* phase encoding rephaser on Y (common for GRE, SPGR & SSFP) */
1387  tmploc.board = YGRAD;
1388  tmploc.pos = readend_pos - RDN_GRD(ksgre.read.acqdelay); /* Y rephaser can start at the end of the acqwin */
1389  if (ks_pg_phaser(&ksgre.phaseenc, tmploc, &ksgre.seqctrl) == FAILURE)
1390  return FAILURE;
1391  endposy = tmploc.pos + ksgre.phaseenc.grad.duration; /* absolute time for end of last waveform on Y */
1392 
1393  ks_scan_phaser_fromline(&ksgre.phaseenc, 1, 0); /* rephaser */
1394 
1395  /******************** Z ********************/
1396  tmploc.board = ZGRAD;
1397  tmploc.pos = readend_pos - RDN_GRD(ksgre.read.acqdelay); /* Z rephaser/spoiler can start at the end of the acqwin */
1398 
1399  if (oppseq == PSD_SSFP) {
1400 
1401  if (ksgre.zphaseenc.grad.duration > 0) { /* 3D */
1402  /* z phase encoding rephaser (if 3D SSFP) */
1403  if (ks_pg_phaser(&ksgre.zphaseenc, tmploc, &ksgre.seqctrl) == FAILURE)
1404  return FAILURE;
1405  endposz = tmploc.pos + ksgre.zphaseenc.grad.duration;
1406 
1408 
1409  } else { /* 2D SSFP */
1410  /* endtime - postgrad.duration = starting point for z postgrad trapezoid */
1411  tmploc.pos += IMax(3, \
1415 
1416  /* another instance of the slice rephaser, placed at the very end. Relies on isodelay = rfwave.duration / 2 */
1417  if (ks_pg_trap(&ksgre.selrfexc.postgrad, tmploc, &ksgre.seqctrl) == FAILURE)
1418  return FAILURE;
1419  endposz = tmploc.pos + ksgre.selrfexc.postgrad.duration;
1420  }
1421 
1422  } else { /* non-SSFP */
1423  if (ksgre_slicecheck) {
1424  tmploc.board = XGRAD;
1425  }
1426 
1427  if (ks_pg_trap(&ksgre.spoiler, tmploc, &ksgre.seqctrl) == FAILURE)
1428  return FAILURE;
1429  endposz = tmploc.pos + ksgre.spoiler.duration;
1430 
1431  }
1432 
1433  /*******************************************************************************************************
1434  * Setup phase encoding table for scan (2D + 3D)
1435  *******************************************************************************************************/
1436  if (ksgre_ellipsekspace && KS_3D_SELECTED) { /* 3D */
1438  } else {
1440  }
1441  if (status != SUCCESS) return status;
1443 
1444 
1445  /*******************************************************************************************************
1446  * Set the minimal sequence duration (ksgre.seqctrl.min_duration) by calling
1447  * ks_eval_seqctrl_setminduration()
1448  *******************************************************************************************************/
1449 
1450  /* end position of all axes. Make sure we are divisible by GRAD_UPDATE_TIME (4us) */
1451  tmploc.pos = RUP_GRD(IMax(3, endposx, endposy, endposz));
1452 
1453 #ifdef HOST_TGT
1454  /* On HOST only: Sequence duration (ksgre.seqctrl.ssi_time must be > 0 and is added to ksgre.seqctrl.min_duration in ks_eval_seqctrl_setminduration() */
1456  ks_eval_seqctrl_setminduration(&ksgre.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
1457 #endif
1458 
1459  return SUCCESS;
1460 
1461 } /* ksgre_pg() */
KS_TRAP grad
Definition: KSFoundation.h:1491
KS_TRAP fcompread
Definition: ksgre_implementation.e:53
KS_TRAP grad
Definition: KSFoundation.h:1676
int ksgre_ssfp_endtime
Definition: ksgre_implementation.e:124
int ksgre_slicecheck
Definition: ksgre_implementation.e:76
int pos
Definition: KSFoundation.h:389
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:1785
STATUS ks_phaseencoding_generate_simple(KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, const char *const desc, KS_PHASER *phaser, KS_PHASER *zphaser)
Generation of a KS_PHASEENCODING_PLAN for any sequence having only one echo (or same phasenc step for...
Definition: KSFoundation_common.c:481
KS_TRAP fcompslice
Definition: ksgre_implementation.e:54
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:1669
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int32_t i
Definition: KSFoundation_tgt.c:1389
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:2204
int momentstart
Definition: KSFoundation.h:1136
int board
Definition: KSFoundation.h:388
KS_TRAP grad
Definition: KSFoundation.h:1586
float ampscale
Definition: KSFoundation.h:390
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksgre_implementation.e:55
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:48
STATUS ks_phaseencoding_generate_simple_ellipse(KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, const char *const desc, KS_PHASER *phaser, KS_PHASER *zphaser)
Generation of a KS_PHASEENCODING_PLAN for any sequence having only one echo (or same phasenc step for...
Definition: KSFoundation_common.c:522
KS_TRAP pregrad
Definition: KSFoundation.h:1490
int ksgre_ellipsekspace
Definition: ksgre_implementation.e:105
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:1475
int ksgre_extragap
Definition: ksgre_implementation.e:88
KS_TRAP readdephaser
Definition: ksgre_implementation.e:47
KS_TRAP spoiler
Definition: ksgre_implementation.e:51
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:387
KS_READTRAP read
Definition: ksgre_implementation.e:46
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int ssi_time
Definition: KSFoundation.h:1134
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:340
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
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:4281
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
void ks_phaseencoding_print(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr)
Print out KS_PHASEENCODING_PLAN to a text file
Definition: KSFoundation_common.c:418
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:208
int duration
Definition: KSFoundation.h:585
int time2center
Definition: KSFoundation.h:1585
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50
int ksgre_eval_ssitime()
The SSI time for the sequence
Definition: ksgre_implementation.e:1012
int acqdelay
Definition: KSFoundation.h:1580
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:359
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:152

◆ ksgre_scan_coreslice()

int ksgre_scan_coreslice ( const SCAN_INFO *  slice_pos,
int  dabslice,
int  shot,
int  exc 
)

Plays out one slice in real time during scanning together with other active sequence modules

On TGT on the MR system (PSD_HW), this function sets up (ksgre_scan_seqstate()) and plays out the core ksgre sequence with optional sequence modules also called in this function. 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 += ...).

On HOST (in ksgre_eval_tr()) we call ksgre_scan_sliceloop_nargs(), which in turn calls this function that returns the total time in [us] taken to play out this core slice. These times are increasing in each parent function until ultimately ksgre_scan_scantime(), which returns the total time of the entire scan.

After each call to ks_scan_playsequence(), ks_plot_slicetime() is called to add slice-timing information on file for later PDF-generation 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). See predownload() for the PNG/PDF generation.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the global ks_scan_info[] array)
[in]dabslice0-based slice index for data storage
[in]shotshot index (over ky and kz)
[in]excExcitation index in range [0, NEX-1], where NEX = number of excitations (opnex)
Return values
coreslicetimeTime taken in [us] to play out one slice with potentially other sequence modules
1632  {
1633  int echoindx;
1634  int dabop, dabview;
1635  TYPDAB_PACKETS acqflag;
1636  int time = 0;
1637  float tloc = 0.0;
1638  KS_PHASEENCODING_COORD coord;
1639  int echo = 0; /* only one phase encode for all echoes for now */
1640 
1641  if (slice_pos != NULL)
1642  tloc = slice_pos->optloc;
1643 
1644 
1645  /*******************************************************************************************************
1646  * SpSat sequence module
1647  *******************************************************************************************************/
1649 
1650 
1651  /*******************************************************************************************************
1652  * Chemsat sequence module
1653  *******************************************************************************************************/
1656  ks_plot_slicetime(&kschemsat.seqctrl, 1, NULL, KS_NOTSET, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD); /* no slice location for fat sat */
1657 
1658  /*******************************************************************************************************
1659  * ksgre main sequence module
1660  *******************************************************************************************************/
1661  if (slice_pos != NULL) {
1662  /* modify sequence for next playout */
1663  ksgre_scan_seqstate(*slice_pos, shot);
1664  } else {
1665  /* false slice, shut off RF */
1666  ks_scan_rf_off(&ksgre.selrfexc.rf, INSTRALL);
1667  }
1668 
1669  coord = ks_phaseencoding_get(&ksgre.phaseenc_plan, echo, shot);
1670 
1671  /* data acquisition control */
1672  acqflag = (shot >= 0 && slice_pos != NULL && coord.ky >= 0 && slice_pos != NULL && dabslice >= 0) ? DABON : DABOFF; /* open or close data receiver */
1673  dabop = (exc <= 0) ? DABSTORE : DABADD; /* replace or add to data */
1674 
1675  if (KS_3D_SELECTED) {
1676  if (ks_scan_info[1].optloc > ks_scan_info[0].optloc)
1677  dabslice = (opslquant * opvquant - 1) - coord.kz;
1678  else
1679  dabslice = coord.kz;
1680  }
1681 
1682  dabview = (shot >= 0) ? coord.ky : KS_NOTSET;
1683 
1684  if (ksgre.phaseenc.R > 1 && ksgre.phaseenc.nacslines == 0 && dabview != KS_NOTSET) /* ASSET case triggered by R > 1 and no ACS lines */
1685  dabview /= ksgre.phaseenc.R; /* store in compressed BAM without empty non-acquired lines */
1686 
1687  for (echoindx = 0; echoindx < ksgre.read.acq.base.ngenerated; echoindx++) {
1688  ks_scan_loaddabwithindices_nex(&ksgre.read.acq.echo[echoindx], dabslice, echoindx, dabview + 1, /*acq*/ 0, /*vol*/ 0, dabop, acqflag);
1689  }
1690 
1692  ks_plot_slicetime(&ksgre.seqctrl, 1, &tloc, opslthick, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
1693 
1694  return time; /* in [us] */
1695 
1696 } /* ksgre_scan_coreslice() */
int ksspsat_scan_playsequences(int perform_slicetimeplot)
Definition: KSSpSat.e:819
KSCHEMSAT_SEQUENCE kschemsat
Definition: KSChemSat.e:89
int R
Definition: KSFoundation.h:1680
WF_PULSE * echo
Definition: KSFoundation.h:738
int nacslines
Definition: KSFoundation.h:1681
#define KS_NOTSET
Definition: KSFoundation.h:103
STATUS ks_scan_loaddabwithindices_nex(WF_PULSE_ADDR pulse, LONG slice, LONG echo, LONG view, uint8_t acq, uint8_t vol, LONG operation, TYPDAB_PACKETS acqon_flag)
loaddab() with extra arguments for current acquisition and image volume and current excitation (NEX)...
Definition: KSFoundation_tgt.c:1392
void kschemsat_scan_seqstate(KSCHEMSAT_SEQUENCE *kschemsat)
Sets the current state of all kschemsat sequence objects being part of KSCHEMSAT_SEQUENCE
Definition: KSChemSat.e:388
int ks_perform_slicetimeplot
Definition: GERequired.e:222
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int ky
Definition: KSFoundation.h:1705
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:469
int kz
Definition: KSFoundation.h:1706
KS_BASE base
Definition: KSFoundation.h:731
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksgre_implementation.e:55
STATUS ksgre_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksgre sequence objects being part of KSGRE_SEQUENCE
Definition: ksgre_implementation.e:1532
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1704
KS_PHASEENCODING_COORD ks_phaseencoding_get(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int echo, int shot)
Get [ky,kz] coordinate from KS_PHASEENCODING_PLAN for given echo and shot
Definition: KSFoundation_common.c:375
KS_RF rf
Definition: KSFoundation.h:1485
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368
Definition: KSFoundation.h:336
Definition: KSFoundation.h:335
KS_READTRAP read
Definition: ksgre_implementation.e:46
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
void ks_plot_slicetime(KS_SEQ_CONTROL *ctrl, int nslices, float *slicepos_mm, float slthick_mm, KS_PLOT_EXCITATION_MODE exctype)
Definition: KSFoundation_common.c:3404
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
int ngenerated
Definition: KSFoundation.h:410
KS_SEQ_CONTROL seqctrl
Definition: KSChemSat.e:71
KS_READ acq
Definition: KSFoundation.h:1574
float opslthick
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

◆ ksgre_scan_coreslice_nargs()

int ksgre_scan_coreslice_nargs ( const SCAN_INFO *  slice_pos,
int  dabslice,
int  nargs,
void **  args 
)

Wrapper function to ksgre_scan_coreslice() with standardized input arguments

KSInversion.e has functions (ksinv_eval_multislice(), ksinv_eval_checkTR_SAR() and ksinv_scan_sliceloop()) that expect a standardized function pointer to the coreslice function of a main sequence. When inversion mode is enabled for the sequence, ksinv_scan_sliceloop() is used instead of ksgre_scan_sliceloop() in ksgre_scan_acqloop(), and the generic ksinv_scan_sliceloop() function need a handle to the coreslice function of the main sequence.

In order for these ksinv_*** functions to work for any pulse sequence they need a standardized function pointer with a fixed set of input arguments. As different pulse sequences may need different number of input arguments (with different meaning) this ksgre_scan_coreslice_nargs() wrapper function provides the argument translation for ksgre_scan_coreslice().

The function pointer must have SCAN_INFO and slice storage index (dabslice) as the first two input args, while remaining input arguments (to ksgre_scan_coreslice()) are stored in the generic void pointer array with nargs elements, which is then unpacked before calling ksgre_scan_coreslice().

Parameters
[in]slice_posPointer to the SCAN_INFO struct corresponding to the current slice to be played out
[in]dabslice0-based slice index for data storage
[in]nargsNumber of extra input arguments to ksgre_scan_coreslice() in range [0,3]
[in]argsVoid pointer array pointing to the variables containing the actual values needed for ksgre_scan_coreslice()
Return values
coreslicetimeTime taken in [us] to play out one slice with potentially other sequence modules
1727  {
1728  int shot = 0;
1729  int exc = 0;
1730 
1731  if (nargs < 0 || nargs > 2) {
1732  ks_error("%s: 4th arg (void **) must contain up to 2 elements in the following order: shot, exc", __FUNCTION__);
1733  return -1;
1734  } else if (nargs > 0 && args == NULL) {
1735  ks_error("%s: 4th arg (void **) cannot be NULL if nargs (3rd arg) != 0", __FUNCTION__);
1736  return -1;
1737  }
1738 
1739  if (nargs >= 1 && args[0] != NULL) {
1740  shot = *((int *) args[0]);
1741  }
1742  if (nargs >= 2 && args[1] != NULL) {
1743  exc = *((int *) args[1]);
1744  }
1745 
1746  return ksgre_scan_coreslice(slice_pos, dabslice, /* psd specific: */ shot, exc); /* in [us] */
1747 
1748 } /* ksgre_scan_coreslice_nargs() */
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ksgre_scan_coreslice(const SCAN_INFO *slice_pos, int dabslice, int shot, int exc)
Plays out one slice in real time during scanning together with other active sequence modules...
Definition: ksgre_implementation.e:1632

◆ ksgre_scan_sliceloop()

int ksgre_scan_sliceloop ( int  slperpass,
int  passindx,
int  shot,
int  exc 
)

Plays out slperpass slices corresponding to one TR

This function gets a spatial slice location index based on the pass index and temporal position within current pass. It then calls ksgre_scan_coreslice() to play out one coreslice (i.e. the main ksgre main sequence + optional sequence modules, excluding inversion modules).

Parameters
[in]slperpassNumber of slices to play in the slice loop
[in]passindx0-based pass index in range [0, ks_slice_plan.npasses - 1]
[in]shotshot index in range [0, ksgre.phaseenc_plan.num_shots - 1]
[in]excExcitation index in range [0, NEX-1], where NEX = number of excitations (opnex)
Return values
slicelooptimeTime taken in [us] to play out slperpass slices
1767  {
1768  int time = 0;
1769  int slloc, sltimeinpass;
1770  SCAN_INFO centerposition = ks_scan_info[0]; /* first slice chosen here, need only rotation stuff */
1771 
1772  if (KS_3D_SELECTED) {
1773  int centerslice = opslquant/2;
1774  /* for future 3D multislab support, let passindx update centerposition */
1775  centerposition.optloc = (ks_scan_info[centerslice-1].optloc + ks_scan_info[centerslice].optloc)/2.0;
1776  }
1777 
1778  for (sltimeinpass = 0; sltimeinpass < slperpass; sltimeinpass++) {
1779 
1780  SCAN_INFO *current_slice = &centerposition;
1781 
1782  if (!KS_3D_SELECTED) { /* 2D */
1783  /* slice location from slice plan */
1784  slloc = ks_scan_getsliceloc(&ks_slice_plan, passindx, sltimeinpass);
1785 
1786  /* if slloc = KS_NOTSET, pass in NULL as first argument to indicate 'false slice' */
1787  current_slice = (slloc != KS_NOTSET) ? &ks_scan_info[slloc]: NULL;
1788  }
1789 
1790  time += ksgre_scan_coreslice(current_slice, sltimeinpass, shot, exc);
1791 
1792  }
1793 
1794  return time; /* in [us] */
1795 
1796 } /* ksgre_scan_sliceloop() */
#define KS_NOTSET
Definition: KSFoundation.h:103
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int passindx
Definition: ksgre_implementation.e:1963
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int ks_scan_getsliceloc(const KS_SLICE_PLAN *slice_plan, int passindx, int sltimeinpass)
Returns the spatially sorted slice index from a DATA_ACQ_ORDER struct array
Definition: KSFoundation_tgt.c:1023
int ksgre_scan_coreslice(const SCAN_INFO *slice_pos, int dabslice, int shot, int exc)
Plays out one slice in real time during scanning together with other active sequence modules...
Definition: ksgre_implementation.e:1632
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

◆ ksgre_eval_ssitime()

int ksgre_eval_ssitime ( )

The SSI time for the sequence

Return values
intSSI time in [us]
1012  {
1013 
1014  /* SSI time CV:
1015  Empirical finding on how much SSI time we need to update.
1016  But, use a longer SSI time when we write out data to file in scan() */
1017  if (KS_3D_SELECTED && (oppseq == PSD_SSFP))
1018  ksgre_ssi_time = RUP_GRD(IMax(2, KSGRE_DEFAULT_SSI_TIME_SSFP, _ksgre_ssi_time.minval));
1019  else
1020  ksgre_ssi_time = RUP_GRD(IMax(2, KSGRE_DEFAULT_SSI_TIME, _ksgre_ssi_time.minval));
1021 
1022  /* Copy SSI CV to seqctrl field used by setssitime() */
1023  ksgre.seqctrl.ssi_time = RUP_GRD(ksgre_ssi_time);
1024 
1025  /* SSI time one-sequence-off workaround:
1026  We set the hardware ssitime in ks_scan_playsequence(), but it acts on the next sequence module, hence
1027  we aren't doing this correctly when using multiple sequence modules (as KSChemSat etc).
1028  One option would be to add a short dummy sequence ks_scan_playsequence(), but need to investigate
1029  if there is a better way. For now, let's assume the the necessary update time is the longest for
1030  the main sequence (this function), and let the ssi time for all other sequence modules (KSChemSat etc)
1031  have the same ssi time as the main sequence. */
1036 
1037  return ksgre_ssi_time;
1038 
1039 } /* ksgre_eval_ssitime() */
int ksspsat_ssi_time
Definition: KSSpSat.e:135
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
#define KSGRE_DEFAULT_SSI_TIME
Definition: ksgre_implementation.e:35
int kschemsat_ssi_time
Definition: KSChemSat.e:106
int ksinv_filltr_ssi_time
Definition: KSInversion.e:158
#define KSGRE_DEFAULT_SSI_TIME_SSFP
Definition: ksgre_implementation.e:36
int ssi_time
Definition: KSFoundation.h:1134
int ksgre_ssi_time
Definition: ksgre_implementation.e:100
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
int ksinv_ssi_time
Definition: KSInversion.e:157

◆ ksgre_init_imagingoptions()

void ksgre_init_imagingoptions ( void  )

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

Returns
void
195  {
196  int numopts = sizeof(sequence_iopts) / sizeof(int);
197 
198  psd_init_iopt_activity();
199  activate_iopt_list(numopts, sequence_iopts);
200  enable_iopt_list(numopts, sequence_iopts);
201 
202  /* Imaging option control functions (using PSD_IOPT_ZIP_512 as example):
203  - Make an option unchecked and not selectable: disable_ioption(PSD_IOPT_ZIP_512)
204  - Make an option checked and not selectable: set_required_disabled_option(PSD_IOPT_ZIP_512)
205  - Remove the imaging option: deactivate_ioption(PSD_IOPT_ZIP_512)
206  */
207 
208  cvmax(opimode, PSD_3DM);
209 
210  if (oppseq == PSD_SSFP) {
211  /* Sequential forced on SSFP to keep TR minimal, i.e. one slice at a time */
212  set_required_disabled_option(PSD_IOPT_SEQUENTIAL);
213  set_disallowed_option(PSD_IOPT_CARD_GATE);
214  }
215 
216  /* This is likely good for PSD_3DM scans:
217  if (KS_3D_MULTISLAB_SELECTED) {
218  set_required_disabled_option(PSD_IOPT_SEQUENTIAL);
219  }
220  */
221 
222 #ifdef SIM
223  oppseq = PSD_GE;
224  setexist(oppseq, PSD_ON);
225  opirmode = PSD_OFF; /* default interleaved slices */
226  setexist(opirmode, PSD_ON);
227 #endif
228 
229 } /* ksgre_init_imagingoptions() */
int sequence_iopts[]
Definition: ksgre_implementation.e:169

◆ ksgre_init_UI()

STATUS ksgre_init_UI ( void  )

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

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

◆ ksgre_eval_UI()

STATUS ksgre_eval_UI ( )

Gets the current UI and checks for valid inputs

Return values
STATUSSUCCESS or FAILURE
535  {
536 
537  if (ksgre_init_UI() == FAILURE)
538  return FAILURE;
539 
540  ksgre_rfexc_choice = (int) opuser1;
541 
542  ksgre_ellipsekspace = (int) opuser2;
543 
544  rhrecon = (int) opuser16;
545 
546  /* Reserved opusers:
547  -----------------
548  ksgre_eval_inversion(): opuser26-29
549  GE reserves: opuser36-48 (epic.h)
550  */
551 
552  return SUCCESS;
553 
554 } /* ksgre_eval_UI() */
int ksgre_rfexc_choice
Definition: ksgre_implementation.e:81
int ksgre_ellipsekspace
Definition: ksgre_implementation.e:105
STATUS ksgre_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksgre_implementation.e:239

◆ ksgre_eval_setupobjects()

STATUS ksgre_eval_setupobjects ( )

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

Return values
STATUSSUCCESS or FAILURE
564  {
565  STATUS status;
566 
567  /* RF choices */
568  if (ksgre_sincrf) {
570  if (status != SUCCESS) return status;
572  } else {
573  if (oppseq == PSD_SSFP) {
574  if (KS_3D_SELECTED) {
575  ksgre.selrfexc.rf = ssfp_tbw3_01_001_pm_250; /* KSFoundation_GERF.h */
576  } else {
577  /* for now, use 4k BW sinc for 2D SSFP */
578  status = ks_eval_rf_sinc(&ksgre.selrfexc.rf, "", 4000, 2, opflip, KS_RF_SINCWIN_HAMMING);
579  if (status != SUCCESS) return status;
581  }
582  } else {
583  if (KS_3D_SELECTED) {
584  /* ksgre_rfexc_choice: Low values => shorter TE but lower max FA */
585  if (ksgre_rfexc_choice == 0)
586  ksgre.selrfexc.rf = exc_tbw8_01_001_150; /* KSFoundation_GERF.h */
587  else if (ksgre_rfexc_choice == 1)
588  ksgre.selrfexc.rf = exc_3d8min; /* KSFoundation_GERF.h */
589  else if (ksgre_rfexc_choice == 2)
590  ksgre.selrfexc.rf = exc_3d16min; /* KSFoundation_GERF.h */
591  else if (ksgre_rfexc_choice == 3)
592  ksgre.selrfexc.rf = excnonsel_fermi100; /* KSFoundation_GERF.h */
593  } else {
594  ksgre.selrfexc.rf = ssfp_tbw2_1_01; /* KSFoundation_GERF.h */
595  status = ks_eval_stretch_rf(&ksgre.selrfexc.rf, 4); /* stretch => reduce the BW to lower grad amp */
596  if (status != SUCCESS) return status;
597  }
598  }
599  }
600 
601  if (KS_3D_SELECTED) {
602  cvoverride(opvthick, exist(opslquant) * exist(opslthick), _opslquant.fixedflag, existcv(opslquant));
603  ksgre_excthickness = (exist(opslquant) - 2 * rhslblank) * exist(opslthick);
604  ksgre_gscalerfexc = 1.0;
605  } else {
607  }
608 
609  ksgre.selrfexc.rf.flip = opflip;
611 
612  /* selective RF excitation */
613  if (ks_eval_selrf1p(&ksgre.selrfexc, "rfexc") == FAILURE)
614  return FAILURE;
615 
616 
617  /* readout gradient and data acquisition */
618  ksgre.read.fov = opfov;
619  ksgre.read.res = RUP_FACTOR(opxres, 2); /* round up (RUP) to nearest multiple of 2 */
621  if (ksgre.read.rampsampling)
622  ksgre.read.acqdelay = 64; /* us on the ramp until acq should begin */
623  if (opautote == PSD_MINTE) { /* PSD_MINTE = 2 */
624  ksgre.read.nover = IMin(2,ksgre_kxnover,ksgre.read.res/2); /* Partial Fourier */
625  } else {
626  ksgre.read.nover = 0; /* Full Fourier */
627  }
628  ksgre.read.acq.rbw = oprbw;
629  if (ks_eval_readtrap(&ksgre.read, "read") == FAILURE)
630  return FAILURE;
631 
632  /* read dephaser */
634  if (ks_eval_trap(&ksgre.readdephaser, "readdephaser") == FAILURE)
635  return FAILURE;
636 
637  /* read rephaser (SSFP) */
638  if (oppseq == PSD_SSFP) {
640  if (ks_eval_trap(&ksgre.readrephaser_ssfp, "readrephaser_ssfp") == FAILURE)
641  return FAILURE;
642  } else {
644  }
645 
646  if (opfcomp == TRUE) {
647  /* X: Add second x dephaser */
649  if (ks_eval_trap(&ksgre.fcompread, "readdephaser1") == FAILURE)
650  return FAILURE;
651 
652  /* X: Now, make normal readdephaser twice as large */
653  ksgre.readdephaser.area *= 2;
654  if (ks_eval_trap(&ksgre.readdephaser, "readdephaser2") == FAILURE)
655  return FAILURE;
656 
657  /* Z: Add second z rephaser to complete 0th and 1st moment nulling of slice selection */
659  if (ks_eval_trap(&ksgre.fcompslice, "rfexc.reph2") == FAILURE)
660  return FAILURE;
661 
662  /* Z: Now, make normal z rephaser twice as large */
664  if (ks_eval_trap(&ksgre.selrfexc.postgrad, "rfexc.reph1") == FAILURE)
665  return FAILURE;
666 
667  } else {
670  }
671 
672  /* phase encoding gradient */
673  ksgre.phaseenc.fov = opfov * opphasefov;
674  ksgre.phaseenc.res = RUP_FACTOR((int) (opyres * opphasefov), 2); /* round up (RUP) to nearest multiple of 2 */
675  if (ksgre.read.nover == 0 && opnex < 1) {
676  int kynover;
677  kynover = ksgre.phaseenc.res * (opnex - 0.5);
678  kynover = ((kynover + 1) / 2) * 2; /* round to nearest even number */
679  if (kynover < KSGRE_MINHNOVER)
680  kynover = KSGRE_MINHNOVER; /* protect against too few overscans */
681  ksgre.phaseenc.nover = IMin(2, kynover, ksgre.phaseenc.res/2);
682  } else {
683  ksgre.phaseenc.nover = 0;
684  }
685 
686  /* set .R and .nacslines fields of ksgre.phaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
687  if (opasset) {
688  cvoverride(ksgre_minacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
689  } else if (oparc) {
690  ksgre_minacslines = _ksgre_minacslines.defval;
691  }
692  if (ks_eval_phaser_setaccel(&ksgre.phaseenc, ksgre_minacslines, opaccel_ph_stride) == FAILURE)
693  return FAILURE;
694 
695  if (ks_eval_phaser(&ksgre.phaseenc, "phaseenc") == FAILURE)
696  return FAILURE;
697 
698  /* z phase encoding gradient */
699  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
700 
701  if (opfcomp == TRUE) {
703  } else {
704  ksgre.selrfexc.postgrad.duration = 0; /* disable the slice rephaser gradient (.duration = 0), and put area necessary in zphaseenc.areaoffset */
705  ksgre.zphaseenc.areaoffset = ksgre.selrfexc.postgrad.area; /* copy the area info */
706  }
707  ksgre.zphaseenc.fov = opvthick;
708  ksgre.zphaseenc.res = IMax(2, 8, opslquant);
709  ksgre.zphaseenc.nover = 0;
710 
711  /* set .R and .nacslines fields of ksgre.zphaseenc using ks_eval_phaser_setaccel() before calling ks_eval_phaser() */
712  if (opasset) {
713  cvoverride(ksgre_minzacslines, 0, PSD_FIX_OFF, PSD_EXIST_ON);
714  } else if (oparc) {
715  ksgre_minzacslines = _ksgre_minzacslines.defval;
716  }
717  if (ks_eval_phaser_setaccel(&ksgre.zphaseenc, ksgre_minzacslines, opaccel_sl_stride) == FAILURE)
718  return FAILURE;
719 
720  if (ks_eval_phaser(&ksgre.zphaseenc, "zphaseenc") == FAILURE)
721  return FAILURE;
722 
723  } else {
724 
726 
727  }
728 
729  /* post-read spoiler */
730  ksgre.spoiler.area = (opnecho % 2 == 0) ? -1*ksgre_spoilerarea : ksgre_spoilerarea;
731  if (ks_eval_trap(&ksgre.spoiler, "spoiler") == FAILURE)
732  return FAILURE;
733 
734  /* init seqctrl */
736  strcpy(ksgre.seqctrl.description, "ksgremain");
738 
739  return SUCCESS;
740 
741 } /* ksgre_eval_setupobjects() */
STATUS ks_eval_selrf1p(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with physical gradient constraints (invariant to sli...
Definition: KSFoundation_host.c:3050
KS_TRAP fcompread
Definition: ksgre_implementation.e:53
#define KSGRE_MINHNOVER
Definition: ksgre_implementation.e:34
int res
Definition: KSFoundation.h:1678
int opxres
Definition: KSFoundation.h:1954
int opyres
STATUS ks_eval_phaser(KS_PHASER *phaser, const char *const desc) WARN_UNUSED_RESULT
Sets up an acquisition window with a trapezoid with preset gradient constraints
Definition: KSFoundation_host.c:2073
int role
Definition: KSFoundation.h:939
int ksgre_minzacslines
Definition: ksgre_implementation.e:94
KS_TRAP fcompslice
Definition: ksgre_implementation.e:54
float fov
Definition: KSFoundation.h:1576
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
int ksgre_sincrf
Definition: ksgre_implementation.e:78
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int ksgre_rfexc_choice
Definition: ksgre_implementation.e:81
float areaoffset
Definition: KSFoundation.h:1683
float rbw
Definition: KSFoundation.h:734
float ksgre_excthickness
Definition: ksgre_implementation.e:74
KS_TRAP grad
Definition: KSFoundation.h:1586
DECL_TYPE KS_RF ssfp_tbw3_01_001_pm_250
Definition: KSFoundation_GERF.c:95
Definition: KSFoundation.h:1953
float flip
Definition: KSFoundation.h:940
DECL_TYPE KS_RF exc_3d8min
Definition: KSFoundation_GERF.c:80
DECL_TYPE KS_RF excnonsel_fermi100
Definition: KSFoundation_GERF.c:101
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:48
int ksgre_kxnover
Definition: ksgre_implementation.e:86
STATUS ks_eval_phaser_setaccel(KS_PHASER *phaser, int min_acslines, float R) WARN_UNUSED_RESULT
Definition: KSFoundation_host.c:1995
float ksgre_spoilerarea
Definition: ksgre_implementation.e:77
void ks_init_seqcontrol(KS_SEQ_CONTROL *seqcontrol)
Resets KS_SEQ_CONTROL to its default value (KS_INIT_SEQ_CONTROL)
Definition: KSFoundation_host.c:112
KS_RF rf
Definition: KSFoundation.h:1485
void ks_init_trap(KS_TRAP *trap)
Resets a KS_TRAP sequence object to its default value (KS_INIT_TRAP)
Definition: KSFoundation_host.c:58
int res
Definition: KSFoundation.h:1577
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:434
DECL_TYPE KS_RF ssfp_tbw2_1_01
Definition: KSFoundation_GERF.c:92
float area
Definition: KSFoundation.h:582
KS_TRAP readdephaser
Definition: ksgre_implementation.e:47
DECL_TYPE KS_RF exc_3d16min
Definition: KSFoundation_GERF.c:77
KS_TRAP spoiler
Definition: ksgre_implementation.e:51
float ksgre_gscalerfexc
Definition: ksgre_implementation.e:75
STATUS ks_eval_rf_sinc(KS_RF *rf, const char *const desc, double bw, double tbw, float flip, int wintype) WARN_UNUSED_RESULT
Sets up a KS_RF object with a Sinc pulse shape
Definition: KSFoundation_host.c:2227
KS_READTRAP read
Definition: ksgre_implementation.e:46
KS_TRAP postgrad
Definition: KSFoundation.h:1492
float ksgre_sincrf_tbw
Definition: ksgre_implementation.e:80
int nover
Definition: KSFoundation.h:1679
DECL_TYPE KS_RF exc_tbw8_01_001_150
Definition: KSFoundation_GERF.c:83
int ksgre_rampsampling
Definition: ksgre_implementation.e:87
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
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:733
float ksgre_sincrf_bw
Definition: ksgre_implementation.e:79
KS_DESCRIPTION description
Definition: KSFoundation.h:1141
int nover
Definition: KSFoundation.h:1579
int rampsampling
Definition: KSFoundation.h:1578
KS_READ acq
Definition: KSFoundation.h:1574
int duration
Definition: KSFoundation.h:585
float opslthick
int ksgre_minacslines
Definition: ksgre_implementation.e:93
float area2center
Definition: KSFoundation.h:1584
float fov
Definition: KSFoundation.h:1677
STATUS ks_eval_stretch_rf(KS_RF *rf, float stretch_factor)
In-place stretching of a KS_RF object
Definition: KSFoundation_host.c:3500
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50
int ksgre_eval_ssitime()
The SSI time for the sequence
Definition: ksgre_implementation.e:1012
int acqdelay
Definition: KSFoundation.h:1580
void ks_init_phaser(KS_PHASER *phaser)
Resets a KS_PHASER sequence object to its default value (KS_INIT_PHASER)
Definition: KSFoundation_host.c:86
float slthick
Definition: KSFoundation.h:1487

◆ ksgre_eval_TErange()

STATUS ksgre_eval_TErange ( )

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

N.B.: The minTE (avminte) and maxTE (avmaxte) ensures TE (opte) to be in the valid range for this pulse sequence to be set up in ksgre_pg(). If the pulse sequence design changes in ksgre_pg(), by adding/modifying/removing sequence objects in a way that affects the intended TE, this function needs to be updated too.

Return values
STATUSSUCCESS or FAILURE
757  {
758  float fieldscale = (float) B0_15000 / (float) cffield;
759  int fatwater_halflap = (fieldscale * 4.47ms) / 2; /* [us] */
760  int fatwater_numhalflaps;
761 
762  /* Minimum TE. Note that zphaseenc.grad.duration = 0 for 2D and ksgre.selrfexc.postgrad.duration = 0 for 3D */
763  avminte = ksgre.selrfexc.rf.iso2end;
764  if (ksgre_slicecheck) {
766  } else {
767  avminte += IMax(3, \
771  }
772  avminte += ksgre.read.time2center - ksgre.read.acqdelay; /* from start of acq win to k-space center */
773 
774  if (opautote == PSD_FWINPHS) {
775  /* fat-water in-phase */
776  avminte = CEIL_DIV(avminte, 2 * fatwater_halflap) * (2 * fatwater_halflap);
777  } else if (opautote == PSD_FWOUTPHS) {
778  /* fat-water out-of-phase */
779  fatwater_numhalflaps = CEIL_DIV(avminte, fatwater_halflap);
780  if ((fatwater_numhalflaps % 2) == 0)
781  fatwater_numhalflaps++; /* make sure it is odd */
782  avminte = fatwater_halflap * fatwater_numhalflaps;
783  }
784 
785  avminte += GRAD_UPDATE_TIME * 2; /* 8us extra margin */
786  avminte = RUP_FACTOR(avminte, 8); /* round up to make time divisible by 8us */
787 
788  /* bSSFP (FIESTA): TE = TR/2 */
789  if (oppseq == PSD_SSFP) {
790  int echocenter2momentstart;
791  echocenter2momentstart = ksgre.read.grad.duration - ksgre.read.time2center - ksgre.read.acqdelay; /* end of acqwin */
792 
793  echocenter2momentstart += IMax(3, \
796  KS_3D_SELECTED ? ksgre.zphaseenc.grad.duration : ksgre.selrfexc.postgrad.duration); /* end of spoiler/rephaser */
797 
798  echocenter2momentstart += ksgre.seqctrl.ssi_time; /* add SSI time. This is end of TR */
799  echocenter2momentstart += ksgre_pos_start + ksgre.selrfexc.grad.ramptime + ksgre.selrfexc.rf.start2iso; /* beginning of sequence to momentstart */
800  echocenter2momentstart = RUP_GRD(echocenter2momentstart);
801 
802  if (avminte <= echocenter2momentstart) {
803  avminte += echocenter2momentstart - avminte;
804  ksgre_ssfp_endtime = 0;
805  } else {
806  ksgre_ssfp_endtime = avminte - echocenter2momentstart;
807  }
808  }
809 
810  /* MaxTE. avmaxte = avminte if opautote != FALSE */
811  avmaxte = avminte;
812  if (opautote == FALSE) {
813  if (existcv(optr)) {
814  if (opautotr) {
815  /* TR = minTR, i.e. the current TE is also the maximum TE */
816  if (existcv(opte))
817  avmaxte = opte;
818  } else {
819  /* maximum TE dependent on the chosen TR */
820  avmaxte = optr - ksgre.seqctrl.ssi_time; /* maximum sequence duration for this TR (implies one slice per TR) */
821  avmaxte -= ksgre.spoiler.duration; /* subtract ksgre.spoiler time */
822  avmaxte -= (ksgre.read.grad.duration - ksgre.read.time2center); /* center of k-space to end of read decay ramp + extra gap */
823  if (opnecho > 1) {
824  avmaxte -= (opnecho - 1) * (ksgre.read.grad.duration + ksgre_extragap); /* for multi-echo */
825  }
826  }
827  } else {
828  avmaxte = 1s;
829  }
830  }
831 
832  if (opautote) {
833  setpopup(opte, PSD_OFF);
834  cvoverride(opte, avminte, PSD_FIX_ON, PSD_EXIST_ON); /* AutoTE: force TE to minimum */
835  } else {
836  setpopup(opte, PSD_ON);
837  if (opte < avminte)
838  opte = avminte;
839  }
840 
841  return SUCCESS;
842 
843 } /* ksgre_eval_TErange() */
KS_TRAP grad
Definition: KSFoundation.h:1491
KS_TRAP fcompread
Definition: ksgre_implementation.e:53
int start2iso
Definition: KSFoundation.h:944
KS_TRAP grad
Definition: KSFoundation.h:1676
int ksgre_ssfp_endtime
Definition: ksgre_implementation.e:124
int ksgre_slicecheck
Definition: ksgre_implementation.e:76
KS_TRAP fcompslice
Definition: ksgre_implementation.e:54
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KS_TRAP grad
Definition: KSFoundation.h:1586
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:48
KS_RF rf
Definition: KSFoundation.h:1485
int ksgre_extragap
Definition: ksgre_implementation.e:88
KS_TRAP readdephaser
Definition: ksgre_implementation.e:47
KS_TRAP spoiler
Definition: ksgre_implementation.e:51
KS_READTRAP read
Definition: ksgre_implementation.e:46
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int iso2end
Definition: KSFoundation.h:945
int ssi_time
Definition: KSFoundation.h:1134
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
int duration
Definition: KSFoundation.h:585
int ksgre_pos_start
Definition: ksgre_implementation.e:99
int time2center
Definition: KSFoundation.h:1585
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50
int acqdelay
Definition: KSFoundation.h:1580
int ramptime
Definition: KSFoundation.h:583

◆ ksgre_eval_inversion()

STATUS ksgre_eval_inversion ( KS_SEQ_COLLECTION seqcollection)

Wrapper function to KSInversion functions to add single and dual IR support to this sequence

N.B.: For now, ksgre.e has the same inversion logic as ksfse.e and this function is similar to ksfse_eval_inversion(). This is not used in clinical practice for 3D GRE and should be viewed as a placeholder. Once 3D mode is supported with ksgre.e, this section should change to perform an MP-RAGE type or BRAVO type of preparation instead.

It is important that ksgre_eval_inversion() is called after other sequence modules have been set up and added to the KS_SEQ_COLLECTION struct in my_cveval(). Otherwise the TI and TR timing will be wrong.

Whether IR is on or off is determined by ksinv1_mode, which is set up in KSINV_EVAL()->ksinv_eval(). If it is off, this function will return quietly.

This function calls ksinv_eval_multislice() (KSInversion.e), which takes over the responsibility of TR timing that otherwise is determined in ksgre_eval_tr(). ksinv_eval_multislice() sets seqcollection.evaltrdone = TRUE, which indicates that TR timing has been done. ksgre_eval_tr() checks whether seqcollection.evaltrdone = TRUE to avoid that non-inversion TR timing overrides the TR timing set up in ksinv_eval_multislice().

At the end of this function, TR validation and heat/SAR checks are done.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
874  {
875  STATUS status;
876  int slperpass, npasses;
877  int approved_TR = FALSE;
878 
879  /* Set up up to four opusers for inversion control */
880  status = KSINV_EVAL(seqcollection, 26, 27, 28, 29); /* args 2-6: integer X corresponds to opuserX CV */
881  if (status != SUCCESS) return status;
882 
883  if (((int) *ksinv1_mode) == KSINV_OFF) {
884  /* If no IR1 flag on, return */
885  return SUCCESS;
886  }
887 
888  if (KS_3D_SELECTED) {
889  return ks_error("%s: This function is only for 2D scans", __FUNCTION__);
890  }
891 
892  /* interleaved slices in slice gap menu, force 2+ acqs */
893  if (opileave)
894  npasses = 2;
895  else
896  npasses = 1;
897 
898  while (approved_TR == FALSE) {
899 
900  /* Inversion (specific to 2D FSE/EPI type of PSDs). Must be done after all other sequence modules have been set up */
901  slperpass = CEIL_DIV((int) exist(opslquant), npasses);
902 
903  status = ks_calc_sliceplan(&ks_slice_plan, exist(opslquant), slperpass);
904  if (status != SUCCESS) return status;
905 
907  if (status != SUCCESS) return status;
908 
909  if (existcv(optr) && opflair == OPFLAIR_INTERLEAVED && optr > ksinv_maxtr_t1flair) {
910  /* T1-FLAIR */
911  if (npasses > exist(opslquant)) {
912  return ks_error("%s: T1-FLAIR: TR not met for single slice per TR", __FUNCTION__);
913  }
914  npasses++; /* increase #passes and call ksinv_eval_multislice() again with a new ks_slice_plan */
915  } else {
916  /* non-T1-FLAIR, or T1-FLAIR with approved TR value */
917  approved_TR = TRUE;
918  }
919 
920  } /* while (approved_TR == FALSE) */
921 
922 
923  /* Check TR timing and SAR limits */
925  if (status != SUCCESS) return status;
926 
927  return SUCCESS;
928 
929 } /* ksgre_eval_inversion() */
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
float * ksinv1_mode
Definition: KSInversion.e:140
STATUS ksinv_eval_checkTR_SAR(KS_SEQ_COLLECTION *seqcollection, KS_SLICE_PLAN *slice_plan, int(*play_coreslice)(const SCAN_INFO *, int, int, void **), int core_nargs, void **core_args)
Runs the inversion slice loop and validates TR and SAR/hardware limits
Definition: KSInversion.e:1853
int ksgre_scan_coreslice_nargs(const SCAN_INFO *slice_pos, int dabslice, int nargs, void **args)
Wrapper function to ksgre_scan_coreslice() with standardized input arguments
Definition: ksgre_implementation.e:1727
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
STATUS ks_calc_sliceplan(KS_SLICE_PLAN *slice_plan, int nslices, int slperpass)
Calculates the data acquisition order for a standard interleaved 2D scans using one or more passes...
Definition: KSFoundation_host.c:4866
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:80
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
#define KSINV_EVAL(sptr, o1, o2, o3, o4)
C-macro assigning four UserCV slots and then calling ksinv_eval()
Definition: KSInversion.e:1131
Definition: KSInversion.e:45
int ksinv_maxtr_t1flair
Definition: KSInversion.e:161
STATUS ksinv_eval_multislice(KS_SEQ_COLLECTION *seqcollection, KS_SLICE_PLAN *slice_plan, int(*play_coreslice)(const SCAN_INFO *, int, int, void **), int core_nargs, void **core_args, KS_SEQ_CONTROL *mainseqctrl)
Calculates the duration of inversion module(s) for various inversion modes
Definition: KSInversion.e:1516

◆ ksgre_eval_tr()

STATUS ksgre_eval_tr ( KS_SEQ_COLLECTION seqcollection)

Evaluation of number of slices / TR, set up of slice plan, TR validation and SAR checks

With the current sequence collection (see my_cveval()), and a function pointer to an argument-standardized wrapper function (ksgre_scan_sliceloop_nargs()) to the slice loop function (ksgre_scan_sliceloop(), this function calls GEReq_eval_TR(), where number of slices that can fit within one TR is determined by adding more slices as input argument to the slice loop function. For more details see GEReq_eval_TR().

With the number of slices/TR now known, a standard 2D slice plan is set up using ks_calc_sliceplan() and the duration of the main sequence is increased based on timetoadd_perTR, which was returned by GEReq_eval_TR(). timetoadd_perTR > 0 when optr > avmintr and when heat or SAR restrictions requires avmintr to be larger than the net sum of sequence modules in the slice loop.

This function first checks whether seqcollection.evaltrdone == TRUE. This is e.g. the case for inversion where the TR timing instead is controlled using ksgre_eval_inversion() (calling ksinv_eval_multislice()).

At the end of this function, TR validation and heat/SAR checks are done using GEReq_eval_checkTR_SAR().

Parameters
[in]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
958  {
959  int timetoadd_perTR;
960  STATUS status;
961  int slperpass, min_npasses;
962 
963  if (seqcollection->evaltrdone == TRUE) {
964  /* We cannot call GEReq_eval_TR() or GEReq_eval_checkTR_SAR(..., ksgre_scan_sliceloop_nargs, ...) if e.g. the inversion sequence module is used. This is because
965  ksinv_scan_sliceloop() is used instead of ksgre_scan_sliceloop(). When ksinv1.params.mode != 0 (i.e. inversion sequence module on), the TR timing is done in
966  ksinv_eval_multislice(), which is called from ksgre_eval_inversion().
967  In the future, other sequence modules may want to take over the responsibility of TR calculations and SAR checks, in which case they need to end their corresponding function
968  by setting evaltrdone = TRUE to avoid double processing here */
969  return SUCCESS;
970  }
971 
972  /* interleaved slices in slice gap menu, force 2+ acqs */
973  if (opileave)
974  min_npasses = 2;
975  else
976  min_npasses = 1;
977 
978  /* Calculate # slices per TR, # acquisitions and how much spare time we have within the current TR by running the slice loop, honoring heating and SAR limits */
979  status = GEReq_eval_TR(&slperpass, &timetoadd_perTR, min_npasses, seqcollection, ksgre_scan_sliceloop_nargs, 0, NULL);
980  if (status != SUCCESS) return status;
981 
982  /* Calculate the slice plan (ordering) and passes (acqs). ks_slice_plan is passed to GEReq_predownload_store_sliceplan() in predownload() */
983  if (KS_3D_SELECTED) {
984  ks_calc_sliceplan(&ks_slice_plan, exist(opvquant), 1 /* seq 3DMS */);
985  } else {
986  ks_calc_sliceplan(&ks_slice_plan, exist(opslquant), slperpass);
987  }
988  /* We spread the available timetoadd_perTR evenly, by increasing the .duration of each slice by timetoadd_perTR/slperpass */
989  ksgre.seqctrl.duration = RUP_GRD(ksgre.seqctrl.duration + CEIL_DIV(timetoadd_perTR, ks_slice_plan.nslices_per_pass));
990 
991  /* Update SAR values in the UI (error will occur if the sum of sequence durations differs from optr) */
993  if (status != SUCCESS) return status;
994 
995  /* Fill in the 'tmin' and 'tmin_total'. tmin_total is only like GEs use of the variable when TR = minTR */
996  tmin = ksgre.seqctrl.min_duration;
997  tmin_total = ksgre.seqctrl.duration;
998 
999  return SUCCESS;
1000 
1001 } /* ksgre_eval_tr() */
STATUS GEReq_eval_checkTR_SAR(KS_SEQ_COLLECTION *seqcollection, int nslices, int(*play_loop)(int, int, void **), int nargs, void **args)
Runs the slice loop and validates TR and SAR/hardware limits
Definition: GERequired.e:963
STATUS GEReq_eval_TR(int *slperpass, int *timetoadd_perTR, int requested_minacqs, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
Definition: GERequired.e:719
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int duration
Definition: KSFoundation.h:1135
int nslices_per_pass
Definition: KSFoundation.h:1353
int ksgre_scan_sliceloop_nargs(int slperpass, int nargs, void **args)
Wrapper function to ksgre_scan_sliceloop() with standardized input arguments
Definition: ksgre_implementation.e:1822
int min_duration
Definition: KSFoundation.h:1132
int evaltrdone
Definition: KSFoundation.h:1303
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
STATUS ks_calc_sliceplan(KS_SLICE_PLAN *slice_plan, int nslices, int slperpass)
Calculates the data acquisition order for a standard interleaved 2D scans using one or more passes...
Definition: KSFoundation_host.c:4866
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:80
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217

◆ ksgre_eval_scantime()

STATUS ksgre_eval_scantime ( )

Set the number of dummy scans for the sequence and calls ksgre_scan_scanloop() to determine

the length of the scan

After setting the number of dummy scans based on the current TR, the ksfse_scan_scanloop() is called to get the scan time. pitscan is the UI variable for the scan clock shown in the top right corner on the MR scanner.

Return values
STATUSSUCCESS or FAILURE
1055  {
1056 
1057  /* number of dummy TRs to use to reach steady state */
1058  if (oppseq == PSD_SSFP)
1059  ksgre_dda = 20; /* since single-slice, it's quick anyway */
1060  else
1061  ksgre_dda = 4;
1062 
1063  /* call the scan loop function to get the total scan time. pitscan is the countdown timer shown in
1064  the top-right corner on the MR scanner */
1065  pitscan = ksgre_scan_scanloop();
1066 
1067  return SUCCESS;
1068 }
int ksgre_dda
Definition: ksgre_implementation.e:101
float ksgre_scan_scanloop()
Plays out all passes of a single or multi-pass scan
Definition: ksgre_implementation.e:1925

◆ ksgre_check()

STATUS ksgre_check ( )

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

Return values
STATUSSUCCESS or FAILURE
1088  {
1089 
1090  /* Show resolution & BW per pixel in the UI */
1091 #if EPIC_RELEASE >= 26
1092  piinplaneres = 1;
1093  pirbwperpix = 1;
1094  ihinplanexres = ksgre.read.fov/ksgre.read.res;
1095  ihinplaneyres = ksgre.phaseenc.fov/ksgre.phaseenc.res;
1096  ihrbwperpix = (1000.0 * ksgre.read.acq.rbw * 2.0)/ksgre.read.res;
1097 #endif
1098 
1099  /* Force the user to select the Gradient Echo button. This error needs to be in cvcheck(), not in
1100  cvinit()/cveval() to avoid it to trigger also when Gradient Echo hass been selected */
1101  if (oppseq == PSD_SE || opepi == PSD_ON) {
1102  return ks_error("%s: Please first select the 'Gradient Echo' button", ks_psdname);
1103  }
1104 
1105  /* SSFP symmetric RF watchdog */
1106  if ((oppseq == PSD_SSFP) && (abs(ksgre.selrfexc.rf.rfwave.duration/2 - ksgre.selrfexc.rf.iso2end) > GRAD_UPDATE_TIME)) {
1107  return ks_error("ksgre_check: Symmetric RF pulses are required for SSFP scans");
1108  }
1109 
1110  /* SSFP duration watchdog (to assure TE = TR/2) */
1111  if (existcv(opte) && existcv(optr) && existcv(opflip) && (oppseq == PSD_SSFP) && (ksgre.seqctrl.duration > ksgre.seqctrl.min_duration)) {
1112  return ks_error("ksgre_check: SAR/heating penalty - reduce FA");
1113  }
1114 
1115  if (oparc && KS_3D_SELECTED && (ksgre.zphaseenc.R > ksgre.phaseenc.R)) {
1116  /* Unclear why, but zR > R leads to corrupted images for ARC and 3D.
1117  Probably a bug that can be fixed later. Limited experience (July 2018) */
1118  return ks_error("%s: Need Slice acceleration <= Phase accleration", __FUNCTION__);
1119  }
1120 
1121  return SUCCESS;
1122 
1123 } /* ksgre_check() */
int R
Definition: KSFoundation.h:1680
int res
Definition: KSFoundation.h:1678
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float fov
Definition: KSFoundation.h:1576
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
float rbw
Definition: KSFoundation.h:734
int duration
Definition: KSFoundation.h:1135
char ks_psdname[256]
Definition: GERequired.e:221
KS_RF rf
Definition: KSFoundation.h:1485
int res
Definition: KSFoundation.h:1577
KS_WAVE rfwave
Definition: KSFoundation.h:949
int min_duration
Definition: KSFoundation.h:1132
KS_READTRAP read
Definition: ksgre_implementation.e:46
int iso2end
Definition: KSFoundation.h:945
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
KS_READ acq
Definition: KSFoundation.h:1574
float fov
Definition: KSFoundation.h:1677
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50
int duration
Definition: KSFoundation.h:668

◆ ksgre_predownload_plot()

STATUS ksgre_predownload_plot ( KS_SEQ_COLLECTION seqcollection)

Plotting of sequence modules and slice timing to PNG/SVG/PDF files

The ks_plot_*** functions used in here will save plots to disk depending on the value of the CV ks_plot_filefmt (see KS_PLOT_FILEFORMATS). E.g. if ks_plot_filefmt = KS_PLOT_OFF, nothing will be written to disk. On the MR scanner, the output will be located in /usr/g/mrraw/plot/<ks_psdname>. In simulation, it will be placed in the current directory (./plot/).

Please see the documentation on how to install the required python version and links. Specifically, there must be a link /usr/local/bin/apython pointing to the Anaconda 2 python binary (v. 2.7).

In addition, the following text files are printed out

  • <ks_psdname>_objects.txt
  • <ks_psdname>_seqcollection.txt
1155  {
1156  char tmpstr[1000];
1157 
1158  /* System wide (psd independent) option to disable plotting, to e.g. speed up UX on a slow MR show system */
1159  if (existfile("/usr/g/research/bin/ksdonotplot")) {
1160  return SUCCESS;
1161  }
1162 
1163 #ifdef PSD_HW
1164  sprintf(tmpstr, "/usr/g/mrraw/%s_objects.txt", ks_psdname);
1165 #else
1166  sprintf(tmpstr, "./%s_objects.txt", ks_psdname);
1167 #endif
1168  FILE *fp = fopen(tmpstr, "w");
1169 
1170  /* Note: 'fp' can be replaced with 'stdout' or 'stderr' to get these
1171  values printed out in the WTools window in simulation. However,
1172  heavy printing may result in that the WTools window closes,
1173  why we here write to a file ksgre_objects.txt instead */
1181  fclose(fp);
1182 
1183 
1184  /* ks_plot_host():
1185  Plot each sequence module as a separate file (PNG/SVG/PDF depending on ks_plot_filefmt (GERequired.e))
1186  See KS_PLOT_FILEFORMATS in KSFoundation.h for options.
1187  Note that the phase encoding amplitudes corresponds to the first shot, as set by the call to ksgre_scan_seqstate below */
1190 
1191  /* Sequence timing plot */
1195 
1196  /* ks_plot_tgt_reset():
1197  Creates sub directories and clear old files for later use of ksfse_scan_acqloop()->ks_plot_tgt_addframe().
1198  ks_plot_tgt_addframe() will only write in MgdSim (WTools) to avoid timing issues on the MR scanner. Hence,
1199  unlike ks_plot_host() and the sequence timing plot, one has to open MgdSim and press RunEntry (and also
1200  press PlotPulse several times after pressing RunEntry).
1201  ks_plot_tgt_reset() will create a 'makegif_***.sh' file that should be run in a terminal afterwards
1202  to create the animiated GIF from the dat files */
1204 
1205 
1206  return SUCCESS;
1207 
1208 } /* ksgre_predownload_plot() */
KS_SELRF selrfexc
Definition: ksgre_implementation.e:52
void ks_plot_host(KS_SEQ_COLLECTION *seqcollection, KS_PHASEENCODING_PLAN *plan)
Definition: KSFoundation_host.c:5585
float ksgre_scan_scanloop()
Plays out all passes of a single or multi-pass scan
Definition: ksgre_implementation.e:1925
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksgre_implementation.e:55
KS_TRAP readrephaser_ssfp
Definition: ksgre_implementation.e:48
char ks_psdname[256]
Definition: GERequired.e:221
STATUS ksgre_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksgre sequence objects being part of KSGRE_SEQUENCE
Definition: ksgre_implementation.e:1532
void ks_plot_slicetime_begin()
Definition: KSFoundation_common.c:3396
void ks_plot_slicetime_end()
Definition: KSFoundation_common.c:3437
KS_TRAP readdephaser
Definition: ksgre_implementation.e:47
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:5198
KS_TRAP spoiler
Definition: ksgre_implementation.e:51
KS_READTRAP read
Definition: ksgre_implementation.e:46
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:5168
STATUS STATUS STATUS existfile(const char *fname)
Definition: KSFoundation_common.c:175
KS_PHASER phaseenc
Definition: ksgre_implementation.e:49
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
void ks_plot_tgt_reset(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_common.c:3445
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:80
KS_PHASER zphaseenc
Definition: ksgre_implementation.e:50
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:5316
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
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:5179

◆ ksgre_predownload_setrecon()

STATUS ksgre_predownload_setrecon ( )

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

For most cases, the GEReq_predownload_*** functions in predownload() in ksgre.e set up the necessary rh*** variables for the reconstruction to work properly. However, if this sequence is customized, certain rh*** variables may need to be changed. Doing this here instead of in predownload() directly separates these changes from the standard behavior.

Return values
STATUSSUCCESS or FAILURE
1222  {
1223 
1224  return SUCCESS;
1225 
1226 } /* ksgre_predownload_setrecon() */

◆ ksgre_scan_phase()

float ksgre_scan_phase ( int  counter)

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

This function is largely what makes the difference between the the types of gradient echo sequences by different phase increment policies. For SPGR, RF spoiling is wanted and one tries to not repeat the same RF phase in a series of consecutive excitation. For bSSFP, the flip angle should be 'negative' every other time, which is accomplished by setting the RF phase to 0 or 180 [deg]. In all other cases (values of oppseq), the RF phase is set to 0.

Parameters
[in]counterCounter from the calling function that should increment by 1 outside this function
Return values
phaseRF phase in [deg] to be passed to ks_scan_selrf_setfreqphase() and ks_scan_offsetfov()
1492  {
1493  float phase = 0;
1494 
1495  if (oppseq == PSD_SPGR /* = 5 */ ) {
1496  /* RF spoiling */
1497  phase = ks_scan_rf_phase_spoiling(counter);
1498  } else if (oppseq == PSD_SSFP /* = 4 */) {
1499  /* balanced SSFP */
1500  if (counter % 2)
1501  phase = 180;
1502  else
1503  phase = 0;
1504  } else {
1505  /* Gradient spoiling */
1506  phase = 0;
1507  }
1508 
1509  return phase;
1510 
1511 } /* ksgre_scan_phase() */
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:3883

◆ ksgre_scan_init()

STATUS ksgre_scan_init ( void  )

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

Return values
STATUSSUCCESS or FAILURE
1984  {
1985 
1986  GEReq_initRSP();
1987 
1988  /* Here goes code common for APS2, MPS2 and SCAN */
1989 
1990  ks_scan_switch_to_sequence(&ksgre.seqctrl); /* switch to main sequence */
1991  scopeon(&seqcore); /* Activate scope for core */
1992  syncon(&seqcore); /* Activate sync for core */
1993  setssitime(ksgre.seqctrl.ssi_time/HW_GRAD_UPDATE_TIME);
1994 
1995  /* can we make these independent on global rsptrigger and rsprot in orderslice? */
1996  settriggerarray( (short) ks_slice_plan.nslices_per_pass, rsptrigger);
1997 
1998  spgr_phase_counter = 0;
1999  fiesta_firstplayout = TRUE;
2000 
2001  return SUCCESS;
2002 
2003 } /* ksgre_scan_init() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1356
STATUS setssitime(long)
int fiesta_firstplayout
Definition: ksgre_implementation.e:1964
int nslices_per_pass
Definition: KSFoundation.h:1353
void GEReq_initRSP(void)
RSP Init. To be inserted in the psdinit() function (or scan()) in the main sequence
Definition: GERequired.e:2683
int ssi_time
Definition: KSFoundation.h:1134
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int spgr_phase_counter
Definition: ksgre_implementation.e:1965

◆ ksgre_scan_prescanloop()

STATUS ksgre_scan_prescanloop ( int  nloops,
int  dda 
)

Prescan loop called from both APS2 and MPS2 entry points

Return values
STATUSSUCCESS or FAILURE
2012  {
2013  int i, echoindx, sltimeinpass, slloc;
2014 
2015  /* turn off receivers for all echoes */
2016  for (echoindx = 0; echoindx < ksgre.read.acq.base.ngenerated; echoindx++) {
2017  loaddab(&ksgre.read.acq.echo[echoindx], 0, 0, DABSTORE, 0, DABOFF, PSD_LOAD_DAB_ALL);
2018  }
2019 
2020  /* play dummy scans to get into steady state */
2021  for (i = -dda; i < nloops; i++) {
2022 
2023  /* loop over slices */
2024  for (sltimeinpass = 0; sltimeinpass < ks_slice_plan.nslices_per_pass; sltimeinpass++) {
2025 
2026  /* slice location from slice plan (unless bSSFP, where we only play out center slice) */
2027  if (oppseq == PSD_SSFP)
2028  slloc = CEIL_DIV(opslquant, 2);
2029  else
2030  slloc = ks_scan_getsliceloc(&ks_slice_plan, 0, sltimeinpass);
2031 
2032  /* modify sequence for next playout */
2033  ksgre_scan_seqstate(ks_scan_info[slloc], KS_NOTSET); /* KS_NOTSET => no phase encodes */
2034 
2035  /* data routing control */
2036  if (i >= 0) {
2037  /* turn on receiver for 1st echo */
2038  if (ksgre.read.acq.base.ngenerated > 0)
2039  loaddab(&ksgre.read.acq.echo[0], 0, 0, DABSTORE, 0, DABON, PSD_LOAD_DAB_ALL);
2040  }
2041 
2043 
2044  } /* for slices */
2045 
2046  } /* for nloops */
2047 
2048  return SUCCESS;
2049 
2050 } /* ksgre_scan_prescanloop() */
WF_PULSE * echo
Definition: KSFoundation.h:738
#define KS_NOTSET
Definition: KSFoundation.h:103
int32_t i
Definition: KSFoundation_tgt.c:1389
KS_BASE base
Definition: KSFoundation.h:731
int nslices_per_pass
Definition: KSFoundation.h:1353
STATUS ksgre_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksgre sequence objects being part of KSGRE_SEQUENCE
Definition: ksgre_implementation.e:1532
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368
KS_READTRAP read
Definition: ksgre_implementation.e:46
KS_SEQ_CONTROL seqctrl
Definition: ksgre_implementation.e:45
KSGRE_SEQUENCE ksgre
Definition: ksgre_implementation.e:121
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int ks_scan_getsliceloc(const KS_SLICE_PLAN *slice_plan, int passindx, int sltimeinpass)
Returns the spatially sorted slice index from a DATA_ACQ_ORDER struct array
Definition: KSFoundation_tgt.c:1023
int ngenerated
Definition: KSFoundation.h:410
KS_READ acq
Definition: KSFoundation.h:1574
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

Variable Documentation

◆ seqcollection

KS_SEQ_COLLECTION seqcollection

◆ ksgre_excthickness

float ksgre_excthickness = 0

◆ ksgre_gscalerfexc

float ksgre_gscalerfexc = 0.9

◆ ksgre_slicecheck

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

◆ ksgre_spoilerarea

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

◆ ksgre_sincrf

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

◆ ksgre_sincrf_bw

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

◆ ksgre_sincrf_tbw

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

◆ ksgre_rfexc_choice

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

◆ ksgre_kxnover

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

◆ ksgre_rampsampling

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

◆ ksgre_extragap

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

◆ ksgre_minacslines

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

◆ ksgre_minzacslines

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

◆ ksgre_pos_start

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

◆ ksgre_ssi_time

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

◆ ksgre_dda

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

◆ ksgre_debug

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

◆ ksgre_imsize

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

◆ ksgre_abort_on_kserror

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

◆ ksgre_ellipsekspace

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

◆ ksgre_fattune

float ksgre_fattune = 0

◆ ksgre

◆ ksgre_ssfp_endtime

int ksgre_ssfp_endtime = 0

◆ sequence_iopts

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

◆ volindx

int volindx

◆ passindx

int passindx

◆ fiesta_firstplayout

int fiesta_firstplayout = 1

◆ spgr_phase_counter

int spgr_phase_counter = 0